author | erik <erik> | 2007-01-10 17:31:08 (UTC) |
---|---|---|
committer | erik <erik> | 2007-01-10 17:31:08 (UTC) |
commit | 6825f30b665952864dbe35fe8329a0e4c264d4b8 (patch) (side-by-side diff) | |
tree | 7c8d178f835d4a7d294b6ef65e0040c40579e84e | |
parent | d8e580a239ab84fbe063b2f3779d417598d5ca0a (diff) | |
download | opie-6825f30b665952864dbe35fe8329a0e4c264d4b8.zip opie-6825f30b665952864dbe35fe8329a0e4c264d4b8.tar.gz opie-6825f30b665952864dbe35fe8329a0e4c264d4b8.tar.bz2 |
All of the files included have instances where an array is new'ed but
the corresponding delete does not have the corresponding [] argument.
-rw-r--r-- | core/apps/embeddedkonsole/TEScreen.cpp | 4 | ||||
-rw-r--r-- | noncore/apps/checkbook/listedit.cpp | 2 | ||||
-rw-r--r-- | noncore/apps/opie-console/TEScreen.cpp | 4 | ||||
-rw-r--r-- | noncore/apps/opie-sheet/Excel.cpp | 2 | ||||
-rw-r--r-- | noncore/apps/tinykate/libkate/document/katedocument.cpp | 4 | ||||
-rw-r--r-- | noncore/comm/keypebble/krfbdecoder.cpp | 6 | ||||
-rw-r--r-- | noncore/games/sfcave/sfcave.cpp | 2 | ||||
-rw-r--r-- | noncore/settings/aqpkg/settingsimpl.cpp | 2 | ||||
-rw-r--r-- | noncore/settings/aqpkg/version.cpp | 2 |
9 files changed, 14 insertions, 14 deletions
diff --git a/core/apps/embeddedkonsole/TEScreen.cpp b/core/apps/embeddedkonsole/TEScreen.cpp index 8e69a88..1db34d2 100644 --- a/core/apps/embeddedkonsole/TEScreen.cpp +++ b/core/apps/embeddedkonsole/TEScreen.cpp @@ -1,1236 +1,1236 @@ /* -------------------------------------------------------------------------- */ /* */ /* [TEScreen.C] Screen Data Type */ /* */ /* -------------------------------------------------------------------------- */ /* */ /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ /* */ /* This file is part of Konsole - an X terminal for KDE */ /* */ /* -------------------------------------------------------------------------- */ /* */ /* Ported Konsole to Qt/Embedded */ /* */ /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ /* */ /* -------------------------------------------------------------------------- */ // enhancements added by L.J. Potter <ljp@llornkcor.com> /*! \file */ /*! \class TEScreen \brief The image manipulated by the emulation. This class implements the operations of the terminal emulation framework. It is a complete passive device, driven by the emulation decoder (TEmuVT102). By this it forms in fact an ADT, that defines operations on a rectangular image. It does neither know how to display its image nor about escape sequences. It is further independent of the underlying toolkit. By this, one can even use this module for an ordinary text surface. Since the operations are called by a specific emulation decoder, one may collect their different operations here. The state manipulated by the operations is mainly kept in `image', though it is a little more complex bejond this. See the header file of the class. \sa TEWidget \sa VT102Emulation */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> // #include <kdebug.h> #include <assert.h> #include <string.h> #include <ctype.h> #include <qpe/config.h> #include "TEScreen.h" #define HERE printf("%s(%d): here\n",__FILE__,__LINE__) //FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI. //FIXME: see if we can get this from terminfo. #define BS_CLEARS FALSE #define loc(X,Y) ((Y) * columns + (X)) /*! creates a `TEScreen' of `lines' lines and `columns' columns. */ TEScreen::TEScreen(int lines, int columns) { this->lines = lines; this->columns = columns; // odebug << "Columns " << columns << "" << oendl; image = (ca*) malloc(lines*columns*sizeof(ca)); tabstops = NULL; initTabStops(); histCursor = 0; horzCursor = 0; clearSelection(); reset(); } /*! Destructor */ TEScreen::~TEScreen() { free(image); if (tabstops) free(tabstops); } /* ------------------------------------------------------------------------- */ /* */ /* Normalized Screen Operations */ /* */ /* ------------------------------------------------------------------------- */ // Cursor Setting -------------------------------------------------------------- /*! \section Cursor The `cursor' is a location within the screen that is implicitely used in many operations. The operations within this section allow to manipulate the cursor explicitly and to obtain it's value. The position of the cursor is guarantied to be between (including) 0 and `columns-1' and `lines-1'. */ /*! Move the cursor up. The cursor will not be moved beyond the top margin. */ void TEScreen::cursorUp(int n) //=CUU { if (n == 0) n = 1; // Default int stop = cuY < tmargin ? 0 : tmargin; cuX = QMIN(columns-1,cuX); // nowrap! cuY = QMAX(stop,cuY-n); } /*! Move the cursor down. The cursor will not be moved beyond the bottom margin. */ void TEScreen::cursorDown(int n) //=CUD { if (n == 0) n = 1; // Default int stop = cuY > bmargin ? lines-1 : bmargin; cuX = QMIN(columns-1,cuX); // nowrap! cuY = QMIN(stop,cuY+n); } /*! Move the cursor left. The cursor will not move beyond the first column. */ void TEScreen::cursorLeft(int n) //=CUB { if (n == 0) n = 1; // Default cuX = QMIN(columns-1,cuX); // nowrap! cuX = QMAX(0,cuX-n); } /*! Move the cursor left. The cursor will not move beyond the rightmost column. */ void TEScreen::cursorRight(int n) //=CUF { if (n == 0) n = 1; // Default cuX = QMIN(columns-1,cuX+n); } /*! Set top and bottom margin. */ void TEScreen::setMargins(int top, int bot) //=STBM { if (top == 0) top = 1; // Default if (bot == 0) bot = lines; // Default top = top - 1; // Adjust to internal lineno bot = bot - 1; // Adjust to internal lineno if ( !( 0 <= top && top < bot && bot < lines ) ) { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n", __FILE__,__LINE__,top,bot); return; // Default error action: ignore } tmargin = top; bmargin = bot; cuX = 0; cuY = getMode(MODE_Origin) ? top : 0; } /*! Move the cursor down one line. If cursor is on bottom margin, the region between the actual top and bottom margin is scrolled up instead. */ void TEScreen::index() //=IND { if (cuY == bmargin) { if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history scrollUp(tmargin,1); } else if (cuY < lines-1) cuY += 1; } /*! Move the cursor up one line. If cursor is on the top margin, the region between the actual top and bottom margin is scrolled down instead. */ void TEScreen::reverseIndex() //=RI { if (cuY == tmargin) scrollDown(tmargin,1); else if (cuY > 0) cuY -= 1; } /*! Move the cursor to the begin of the next line. If cursor is on bottom margin, the region between the actual top and bottom margin is scrolled up. */ void TEScreen::NextLine() //=NEL { Return(); index(); } // Line Editing ---------------------------------------------------------------- /*! \section inserting / deleting characters */ /*! erase `n' characters starting from (including) the cursor position. The line is filled in from the right with spaces. */ void TEScreen::eraseChars(int n) { if (n == 0) n = 1; // Default int p = QMAX(0,QMIN(cuX+n-1,columns-1)); clearImage(loc(cuX,cuY),loc(p,cuY),' '); } /*! delete `n' characters starting from (including) the cursor position. The line is filled in from the right with spaces. */ void TEScreen::deleteChars(int n) { if (n == 0) n = 1; // Default int p = QMAX(0,QMIN(cuX+n,columns-1)); moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY)); clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' '); } /*! insert `n' spaces at the cursor position. The cursor is not moved by the operation. */ void TEScreen::insertChars(int n) { if (n == 0) n = 1; // Default int p = QMAX(0,QMIN(columns-1-n,columns-1)); int q = QMAX(0,QMIN(cuX+n,columns-1)); moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY)); clearImage(loc(cuX,cuY),loc(q-1,cuY),' '); } /*! delete `n' lines starting from (including) the cursor position. The cursor is not moved by the operation. */ void TEScreen::deleteLines(int n) { if (n == 0) n = 1; // Default scrollUp(cuY,n); } /*! insert `n' lines at the cursor position. The cursor is not moved by the operation. */ void TEScreen::insertLines(int n) { if (n == 0) n = 1; // Default scrollDown(cuY,n); } // Mode Operations ----------------------------------------------------------- /*! Set a specific mode. */ void TEScreen::setMode(int m) { currParm.mode[m] = TRUE; switch(m) { case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home } } /*! Reset a specific mode. */ void TEScreen::resetMode(int m) { currParm.mode[m] = FALSE; switch(m) { case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home } } /*! Save a specific mode. */ void TEScreen::saveMode(int m) { saveParm.mode[m] = currParm.mode[m]; } /*! Restore a specific mode. */ void TEScreen::restoreMode(int m) { currParm.mode[m] = saveParm.mode[m]; } //NOTE: this is a helper function /*! Return the setting a specific mode. */ BOOL TEScreen::getMode(int m) { return currParm.mode[m]; } /*! Save the cursor position and the rendition attribute settings. */ void TEScreen::saveCursor() { sa_cuX = cuX; sa_cuY = cuY; sa_cu_re = cu_re; sa_cu_fg = cu_fg; sa_cu_bg = cu_bg; } /*! Restore the cursor position and the rendition attribute settings. */ void TEScreen::restoreCursor() { cuX = QMIN(sa_cuX,columns-1); cuY = QMIN(sa_cuY,lines-1); cu_re = sa_cu_re; cu_fg = sa_cu_fg; cu_bg = sa_cu_bg; effectiveRendition(); } /* ------------------------------------------------------------------------- */ /* */ /* Screen Operations */ /* */ /* ------------------------------------------------------------------------- */ /*! Assing a new size to the screen. The topmost left position is maintained, while lower lines or right hand side columns might be removed or filled with spaces to fit the new size. The region setting is reset to the whole screen and the tab positions reinitialized. */ void TEScreen::resizeImage(int new_lines, int new_columns) { if (cuY > new_lines-1) { // attempt to preserve focus and lines bmargin = lines-1; //FIXME: margin lost for (int i = 0; i < cuY-(new_lines-1); i++) { addHistLine(); scrollUp(horzCursor,1); } } // make new image ca* newimg = (ca*)malloc( new_lines * new_columns * sizeof( ca)); clearSelection(); // clear new image for (int y = 0; y < new_lines; y++) for (int x = 0; x < new_columns; x++) { newimg[y*new_columns+x].c = ' '; newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR; newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR; newimg[y*new_columns+x].r = DEFAULT_RENDITION; } int cpy_lines = QMIN(new_lines, lines); int cpy_columns = QMIN(new_columns,columns); // copy to new image for (int y = 0; y < cpy_lines; y++) for (int x = 0; x < cpy_columns; x++) { newimg[y*new_columns+x].c = image[loc(x,y)].c; newimg[y*new_columns+x].f = image[loc(x,y)].f; newimg[y*new_columns+x].b = image[loc(x,y)].b; newimg[y*new_columns+x].r = image[loc(x,y)].r; } free(image); image = newimg; lines = new_lines; columns = new_columns; cuX = QMIN(cuX,columns-1); cuY = QMIN(cuY,lines-1); // FIXME: try to keep values, evtl. tmargin=0; bmargin=lines-1; initTabStops(); clearSelection(); } /* Clarifying rendition here and in TEWidget. currently, TEWidget's color table is 0 1 2 .. 9 10 .. 17 dft_fg, dft_bg, dim 0..7, intensive 0..7 cu_fg, cu_bg contain values 0..8; - 0 = default color - 1..8 = ansi specified color re_fg, re_bg contain values 0..17 due to the TEWidget's color table rendition attributes are attr widget screen -------------- ------ ------ RE_UNDERLINE XX XX affects foreground only RE_BLINK XX XX affects foreground only RE_BOLD XX XX affects foreground only RE_REVERSE -- XX RE_TRANSPARENT XX -- affects background only RE_INTENSIVE XX -- affects foreground only Note that RE_BOLD is used in both widget and screen rendition. Since xterm/vt102 is to poor to distinguish between bold (which is a font attribute) and intensive (which is a color attribute), we translate this and RE_BOLD in falls eventually appart into RE_BOLD and RE_INTENSIVE. */ void TEScreen::reverseRendition(ca* p) { UINT8 f = p->f; UINT8 b = p->b; p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT; } void TEScreen::effectiveRendition() // calculate rendition { ef_re = cu_re & (RE_UNDERLINE | RE_BLINK); if (cu_re & RE_REVERSE) { ef_fg = cu_bg; ef_bg = cu_fg; } else { ef_fg = cu_fg; ef_bg = cu_bg; } if (cu_re & RE_BOLD) { if (ef_fg < BASE_COLORS) ef_fg += BASE_COLORS; else ef_fg -= BASE_COLORS; } } /*! returns the image. Get the size of the image by \sa getLines and \sa getColumns. NOTE that the image returned by this function must later be freed. */ ca* TEScreen::getCookedImage() { int x,y; ca* merged = (ca*)malloc(lines*columns*sizeof(ca)); ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION); if (histCursor > hist.getLines()) { histCursor = hist.getLines(); } for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++) { int len = QMIN(columns,hist.getLineLen(y+histCursor)); int yp = y*columns; int yq = (y+histCursor)*columns; hist.getCells(y+histCursor,0,len,merged+yp); for (x = len; x < columns; x++) merged[yp+x] = dft; for (x = 0; x < columns; x++) { int p=x + yp; int q=x + yq; if ( ( q >= sel_TL ) && ( q <= sel_BR ) ) reverseRendition(&merged[p]); // for selection } } if (lines >= hist.getLines()-histCursor) { for (y = (hist.getLines()-histCursor); y < lines ; y++) { int yp = y*columns; int yq = (y+histCursor)*columns; int yr = (y-hist.getLines()+histCursor)*columns; for (x = 0; x < columns; x++) { int p = x + yp; int q = x + yq; int r = x + yr; merged[p] = image[r]; if ( q >= sel_TL && q <= sel_BR ) reverseRendition(&merged[p]); // for selection } } } // evtl. inverse display if (getMode(MODE_Screen)) { int i,n = lines*columns; for (i = 0; i < n; i++) reverseRendition(&merged[i]); // for reverse display } if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]); return merged; } /*! */ void TEScreen::reset() { Config cfg( "Konsole" ); cfg.setGroup("ScrollBar"); if( !cfg.readBoolEntry("HorzScroll",0) ) setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1] resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke setMode(MODE_Cursor); // cursor visible resetMode(MODE_Screen); // screen not inverse resetMode(MODE_NewLine); tmargin=0; bmargin=lines-1; setDefaultRendition(); saveCursor(); clear(); } /*! Clear the entire screen and home the cursor. */ void TEScreen::clear() { clearEntireScreen(); home(); } /*! Moves the cursor left one column. */ void TEScreen::BackSpace() { cuX = QMAX(0,cuX-1); if (BS_CLEARS) image[loc(cuX,cuY)].c = ' '; } /*! */ void TEScreen::Tabulate() { // note that TAB is a format effector (does not write ' '); cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1); } void TEScreen::clearTabStops() { for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE; } void TEScreen::changeTabStop(bool set) { if (cuX >= columns) return; tabstops[cuX] = set; } void TEScreen::initTabStops() { if (tabstops) free(tabstops); tabstops = (bool*)malloc(columns*sizeof(bool)); // Arrg! The 1st tabstop has to be one longer than the other. // i.e. the kids start counting from 0 instead of 1. // Other programs might behave correctly. Be aware. for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0); } /*! This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine) depending on the NewLine Mode (LNM). This mode also affects the key sequence returned for newline ([CR]LF). */ void TEScreen::NewLine() { if (getMode(MODE_NewLine)) Return(); index(); } /*! put `c' literally onto the screen at the current cursor position. VT100 uses the convention to produce an automatic newline (am) with the *first* character that would fall onto the next line (xenl). */ void TEScreen::checkSelection(int from, int to) { if (sel_begin == -1) return; int scr_TL = loc(0, hist.getLines()); //Clear entire selection if it overlaps region [from, to] if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) ) { clearSelection(); } } void TEScreen::ShowCharacter(unsigned short c) { // Note that VT100 does wrapping BEFORE putting the character. // This has impact on the assumption of valid cursor positions. // We indicate the fact that a newline has to be triggered by // putting the cursor one right to the last column of the screen. if (cuX >= columns) { if (getMode(MODE_Wrap)) NextLine(); else cuX = columns - 1; // comment out for no wrap } if (getMode(MODE_Insert)) insertChars(1); int i = loc( cuX, cuY); checkSelection(i, i); // check if selection is still valid. image[i].c = c; image[i].f = ef_fg; image[i].b = ef_bg; image[i].r = ef_re; cuX += 1; } // Region commands ------------------------------------------------------------- /*! scroll up `n' lines within current region. The `n' new lines are cleared. \sa setRegion \sa scrollDown */ void TEScreen::scrollUp(int from, int n) { if (n <= 0 || from + n > bmargin) return; //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds. moveImage( loc( 0, from), loc( 0, from + n), loc( columns - 1, bmargin)); clearImage( loc( 0, bmargin - n + 1), loc( columns - 1, bmargin), ' '); } /*! scroll down `n' lines within current region. The `n' new lines are cleared. \sa setRegion \sa scrollUp */ void TEScreen::scrollDown(int from, int n) { //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds. if (n <= 0) return; if (from > bmargin) return; if (from + n > bmargin) n = bmargin - from; moveImage( loc(0,from+n), loc(0,from), loc(columns-1,bmargin-n)); clearImage(loc(0,from),loc(columns-1,from+n-1),' '); } /*! position the cursor to a specific line and column. */ void TEScreen::setCursorYX(int y, int x) { setCursorY(y); setCursorX(x); } /*! Set the cursor to x-th line. */ void TEScreen::setCursorX(int x) { if (x == 0) x = 1; // Default x -= 1; // Adjust cuX = QMAX(0,QMIN(columns-1, x)); } /*! Set the cursor to y-th line. */ void TEScreen::setCursorY(int y) { if (y == 0) y = 1; // Default y -= 1; // Adjust cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) )); } /*! set cursor to the `left upper' corner of the screen (1,1). */ void TEScreen::home() { cuX = 0; cuY = 0; } /*! set cursor to the begin of the current line. */ void TEScreen::Return() { cuX = 0; } /*! returns the current cursor columns. */ int TEScreen::getCursorX() { return cuX; } /*! returns the current cursor line. */ int TEScreen::getCursorY() { return cuY; } // Erasing --------------------------------------------------------------------- /*! \section Erasing This group of operations erase parts of the screen contents by filling it with spaces colored due to the current rendition settings. Althought the cursor position is involved in most of these operations, it is never modified by them. */ /*! fill screen between (including) `loca' and `loce' with spaces. This is an internal helper functions. The parameter types are internal addresses of within the screen image and make use of the way how the screen matrix is mapped to the image vector. */ void TEScreen::clearImage(int loca, int loce, char c) { int i; int scr_TL=loc(0,hist.getLines()); //FIXME: check positions //Clear entire selection if it overlaps region to be moved... if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) ) { clearSelection(); } for (i = loca; i <= loce; i++) { image[i].c = c; image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here. } } /*! move image between (including) `loca' and `loce' to 'dst'. This is an internal helper functions. The parameter types are internal addresses of within the screen image and make use of the way how the screen matrix is mapped to the image vector. */ void TEScreen::moveImage(int dst, int loca, int loce) { //FIXME: check positions if (loce < loca) { // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl; return; } memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca)); } /*! clear from (including) current cursor position to end of screen. */ void TEScreen::clearToEndOfScreen() { clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' '); } /*! clear from begin of screen to (including) current cursor position. */ void TEScreen::clearToBeginOfScreen() { clearImage(loc(0,0),loc(cuX,cuY),' '); } /*! clear the entire screen. */ void TEScreen::clearEntireScreen() { clearImage(loc(0,0),loc(columns-1,lines-1),' '); } /*! fill screen with 'E' This is to aid screen alignment */ void TEScreen::helpAlign() { clearImage(loc(0,0),loc(columns-1,lines-1),'E'); } /*! clear from (including) current cursor position to end of current cursor line. */ void TEScreen::clearToEndOfLine() { clearImage(loc(cuX,cuY),loc(columns-1,cuY),' '); } /*! clear from begin of current cursor line to (including) current cursor position. */ void TEScreen::clearToBeginOfLine() { clearImage(loc(0,cuY),loc(cuX,cuY),' '); } /*! clears entire current cursor line */ void TEScreen::clearEntireLine() { clearImage( loc( 0, cuY),loc( columns - 1, cuY),' '); } // Rendition ------------------------------------------------------------------ /*! set rendition mode */ void TEScreen::setRendition(int re) { cu_re |= re; effectiveRendition(); } /*! reset rendition mode */ void TEScreen::resetRendition(int re) { cu_re &= ~re; effectiveRendition(); } /*! */ void TEScreen::setDefaultRendition() { setForeColorToDefault(); setBackColorToDefault(); cu_re = DEFAULT_RENDITION; effectiveRendition(); } /*! */ void TEScreen::setForeColor(int fgcolor) { cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2); effectiveRendition(); } /*! */ void TEScreen::setBackColor(int bgcolor) { cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2); effectiveRendition(); } /*! */ void TEScreen::setBackColorToDefault() { cu_bg = DEFAULT_BACK_COLOR; effectiveRendition(); } /*! */ void TEScreen::setForeColorToDefault() { cu_fg = DEFAULT_FORE_COLOR; effectiveRendition(); } /* ------------------------------------------------------------------------- */ /* */ /* Marking & Selection */ /* */ /* ------------------------------------------------------------------------- */ void TEScreen::clearSelection() { sel_BR = -1; sel_TL = -1; sel_begin = -1; } void TEScreen::setSelBeginXY(const int x, const int y) { if (histCursor > hist.getLines()) { histCursor = hist.getLines(); } sel_begin = loc(x,y+histCursor) ; sel_BR = sel_begin; sel_TL = sel_begin; } void TEScreen::setSelExtentXY(const int x, const int y) { if (sel_begin == -1) return; if (histCursor > hist.getLines()) { histCursor = hist.getLines(); } int l = loc(x,y + histCursor); if (l < sel_begin) { sel_TL = l; sel_BR = sel_begin; } else { /* FIXME, HACK to correct for x too far to the right... */ if (( x == columns )|| (x == 0)) l--; sel_TL = sel_begin; sel_BR = l; } } QString TEScreen::getSelText(const BOOL preserve_line_breaks) { if (sel_begin == -1) return QString::null; // Selection got clear while selecting. int *m; // buffer to fill. int s, d; // source index, dest. index. int hist_BR = loc(0, hist.getLines()); int hY = sel_TL / columns; int hX = sel_TL % columns; int eol; // end of line s = sel_TL; // tracks copy in source. // allocate buffer for maximum // possible size... d = (sel_BR - sel_TL) / columns + 1; m = new int[d * (columns + 1) + 2]; d = 0; while (s <= sel_BR) { if (s < hist_BR) { // get lines from hist.history // buffer. eol = hist.getLineLen(hY); if ((hY == (sel_BR / columns)) && (eol >= (sel_BR % columns))) { eol = sel_BR % columns + 1; } while (hX < eol) { m[d++] = hist.getCell(hY, hX++).c; s++; } if (s <= sel_BR) { // The line break handling // It's different from the screen // image case! if (eol % columns == 0) { // That's either a completely filled // line or an empty line if (eol == 0) { m[d++] = '\n'; } else { // We have a full line. // FIXME: How can we handle newlines // at this position?! } } else if ((eol + 1) % columns == 0) { // FIXME: We don't know if this was a // space at the last position or a // short line!! m[d++] = ' '; } else { // We have a short line here. Put a // newline or a space into the // buffer. m[d++] = preserve_line_breaks ? '\n' : ' '; } } hY++; hX = 0; s = hY * columns; } else { // or from screen image. eol = (s / columns + 1) * columns - 1; if (eol < sel_BR) { while ((eol > s) && isspace(image[eol - hist_BR].c)) { eol--; } } else { eol = sel_BR; } while (s <= eol) { m[d++] = image[s++ - hist_BR].c; } if (eol < sel_BR) { // eol processing see below ... if ((eol + 1) % columns == 0) { if (image[eol - hist_BR].c == ' ') { m[d++] = ' '; } } else { m[d++] = ((preserve_line_breaks || ((eol % columns) == 0)) ? '\n' : ' '); } } s = (eol / columns + 1) * columns; } } QChar* qc = new QChar[d]; for (int i = 0; i < d; i++) { qc[i] = m[i]; } QString res(qc, d); - delete m; - delete qc; + delete [] m; + delete [] qc; return res; } /* above ... end of line processing for selection -- psilva cases: 1) (eol+1)%columns == 0 --> the whole line is filled. If the last char is a space, insert (preserve) space. otherwise leave the text alone, so that words that are broken by linewrap are preserved. FIXME: * this suppresses \n for command output that is sized to the exact column width of the screen. 2) eol%columns == 0 --> blank line. insert a \n unconditionally. Do it either you would because you are in preserve_line_break mode, or because it's an ASCII paragraph delimiter, so even when not preserving line_breaks, you want to preserve paragraph breaks. 3) else --> partially filled line insert a \n in preserve line break mode, else a space The space prevents concatenation of the last word of one line with the first of the next. */ void TEScreen::addHistLine() { assert(hasScroll() || histCursor == 0); // add to hist buffer // we have to take care about scrolling, too... if (hasScroll()){ ca dft; int end = columns - 1; while (end >= 0 && image[end] == dft) end -= 1; hist.addCells( image, end + 1); hist.addLine(); // adjust history cursor histCursor += ( hist.getLines() - 1 == histCursor); } if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround } void TEScreen::setHistCursor(int cursor) { histCursor = cursor; //FIXME:rangecheck if (histCursor > hist.getLines()) { histCursor = hist.getLines(); } if (histCursor < 0) { histCursor = 0; } } void TEScreen::setHorzCursor(int cursor) { horzCursor = cursor; } int TEScreen::getHistCursor() { return histCursor; } int TEScreen::getHorzCursor() { return horzCursor; } int TEScreen::getHistLines() { return hist.getLines(); } void TEScreen::setScroll(bool on) { histCursor = 0; clearSelection(); hist.setScroll(on); } bool TEScreen::hasScroll() { return hist.hasScroll(); } diff --git a/noncore/apps/checkbook/listedit.cpp b/noncore/apps/checkbook/listedit.cpp index e40377b..b297d69 100644 --- a/noncore/apps/checkbook/listedit.cpp +++ b/noncore/apps/checkbook/listedit.cpp @@ -1,355 +1,355 @@ /* This file is part of the OPIE Project =. .=l. Copyright (c) 2002 Dan Williams <drw@handhelds.org> .>+-= _;:, .> :=|. This file is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This file is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU General ..}^=.= = ; Public License for more details. ++= -. .` .: : = ...= . :.=- You should have received a copy of the GNU -. .:....=;==+<; General Public License along with this file; -_. . . )=. = see the file COPYING. If not, write to the -- :-=` Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "listedit.h" /* OPIE */ #include <opie2/odebug.h> #include <opie2/oresource.h> #include <qpe/applnk.h> using namespace Opie::Core; /* QT */ #include <qlayout.h> #include <qlineedit.h> #include <qlistview.h> #include <qwidgetstack.h> #include <qcombobox.h> #include <qpushbutton.h> // --- ListEdit --------------------------------------------------------------- ListEdit::ListEdit( QWidget *parent, const char *sName ) : QWidget(parent, sName), TableDef(sName) { // get font height int fh = fontMetrics().height(); // create layout QGridLayout *layout=new QGridLayout(this); layout->setSpacing( 2 ); layout->setMargin( 4 ); // type table _typeTable = new QListView( this ); ColumnDef *def=first(); while( def ) { _typeTable->addColumn( def->getName() ); def=next(); } connect( _typeTable, SIGNAL( clicked(QListViewItem*,const QPoint&,int) ), this, SLOT( slotClick(QListViewItem*,const QPoint&,int) ) ); layout->addMultiCellWidget(_typeTable, 0,4,0,4); _currentItem=NULL; // edit field _stack=new QWidgetStack( this ); _stack->setMaximumHeight(fh+5); layout->addMultiCellWidget(_stack, 5,5,0,2); _typeEdit = new QLineEdit( _stack ); _stack->raiseWidget(_typeEdit ); connect( _typeEdit, SIGNAL( textChanged(const QString&) ), this, SLOT( slotEditChanged(const QString&) ) ); // combo box _box=new QComboBox( _stack ); connect( _box, SIGNAL( activated(const QString&) ), this, SLOT( slotActivated(const QString&) ) ); // add button QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ), tr( "Add" ), this ); btn->setFixedHeight( AppLnk::smallIconSize()+4 ); connect( btn, SIGNAL( clicked() ), this, SLOT( slotAdd() ) ); layout->addWidget( btn, 5, 3 ); // delete button btn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), tr( "Delete" ), this ); btn->setFixedHeight( AppLnk::smallIconSize()+4 ); connect( btn, SIGNAL( clicked() ), this, SLOT( slotDel() ) ); layout->addWidget( btn, 5, 4 ); } // --- ~ListEdit -------------------------------------------------------------- ListEdit::~ListEdit() { } // --- slotEditTypeChanged ---------------------------------------------------- void ListEdit::slotEditChanged(const QString &str) { if( !_currentItem || _currentColumn<0 ) return; _currentItem->setText(_currentColumn, str); } // --- slotAddType ------------------------------------------------------------ void ListEdit::slotAdd() { // construct new row QString args[8]; ColumnDef *pCol=this->first(); int i=0; while( pCol && i<8 ) { args[i++]=pCol->getNewValue(); pCol=this->next(); } _currentItem=new QListViewItem(_typeTable, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7] ); // fix uniques fixTypes(); // display col 0 of new value QPoint pnt; slotClick(_currentItem, pnt, 0); _typeTable->setSelected( _currentItem, true ); // make it selected _typeEdit->setCursorPosition(0); _typeEdit->setSelection(0, _typeEdit->text().length() ); } // --- slotDel ------------------------------------------------------------- void ListEdit::slotDel() { if( !_currentItem ) return; delete _currentItem; _currentItem=NULL; _typeEdit->setText(""); _stack->raiseWidget(_typeEdit); } // --- fixTypes ---------------------------------------------------------------- // Makes sure all entries have a unique name and empty entries are replaced // by a generic string. The first version performs the operation on a particular // column, whereas the 2nd does it for all unique columns. class ColMap { public: ColMap(QString sValue, QListViewItem *pEntry) { _sValue=sValue; _pEntry=pEntry; } QString &getValue() { return(_sValue); } QListViewItem *getItem() { return(_pEntry); } protected: QString _sValue; QListViewItem *_pEntry; }; class ColList : public QList<QString> { public: ColList() : QList<QString>() { } protected: int compareItems(QCollection::Item, QCollection::Item); }; int ColList::compareItems(QCollection::Item i1, QCollection::Item i2) { return( ((QString *)i1)->compare(*(QString *)i2) ); } void ListEdit::fixTypes(int iColumn) { // get column def ColumnDef *pDef=this->at(iColumn); // create map of entries if( !_typeTable->childCount() ) return; ColMap **colMap=new ColMap *[_typeTable->childCount()]; QListViewItem *cur=_typeTable->firstChild(); ColList lst; for(int i=0; i<_typeTable->childCount(); i++) { colMap[i]=new ColMap(cur->text(iColumn), cur); lst.append( &(colMap[i]->getValue()) ); cur=cur->nextSibling(); } // fix empty entries int i=0; for(QString *ptr=lst.first(); ptr; ptr=lst.next()) { *ptr=ptr->stripWhiteSpace(); if( ptr->isEmpty() ) { i++; if( i==1 ) *ptr=pDef->getNewValue(); else ptr->sprintf("%s %d", (const char *)pDef->getNewValue(), i); } } // fix dups lst.sort(); QString repl; for(uint iCur=0; iCur<lst.count()-1; iCur++) { QString *current=lst.at(iCur); for(uint iNext=iCur+1; iNext<lst.count(); iNext++ ) { if( *current!=*lst.at(iNext) ) continue; for(int i=2; ; i++) { repl.sprintf("%s %d", (const char *)*current, i); bool bDup=false; uint iChk=iNext+1; while( iChk<lst.count() ) { QString *chk=lst.at(iChk); if( !chk->startsWith(*current) ) break; if( *chk==repl ) { bDup=true; break; } iChk++; } if( !bDup ) { *lst.at(iNext)=repl; break; } } } } lst.sort(); // copy back clean up col map for(int i=0; i<_typeTable->childCount(); i++) { colMap[i]->getItem()->setText(iColumn, colMap[i]->getValue()); delete colMap[i]; } - delete colMap; + delete [] colMap; } void ListEdit::fixTypes() { int i; ColumnDef *pDef; for(pDef=this->first(), i=0; pDef; pDef=this->next(), i++) { if( pDef->hasFlag(ColumnDef::typeUnique) ) fixTypes(i); } _typeTable->sort(); } // --- storeInList ------------------------------------------------------------ void ListEdit::storeInList(QStringList &lst) { // delete old content lst.clear(); // add new one fixTypes(); QListViewItem *itm=_typeTable->firstChild(); while( itm ) { int i=0; QString sAdd; ColumnDef *pDef; for(pDef=this->first(), i=0; pDef; pDef=this->next(), i++) { if( i>=1 ) sAdd+=";"; sAdd += itm->text(i); } lst.append( sAdd ); itm=itm->nextSibling(); } } // --- slotClicked ------------------------------------------------------------ void ListEdit::slotClick(QListViewItem *itm, const QPoint &pnt, int col) { (void)pnt; // get rid of unused warning; // save values _currentItem=itm; _currentColumn=col; if( itm==NULL ) { _typeEdit->setText(""); _stack->raiseWidget(_typeEdit); return; } // display value if( _currentColumn<0 ) _currentColumn=0; ColumnDef *pDef=this->at(_currentColumn); if( pDef->isType(ColumnDef::typeString) ) { _typeEdit->setText( _currentItem->text(_currentColumn) ); _stack->raiseWidget(_typeEdit); } else if( pDef->isType(ColumnDef::typeList) ){ _box->clear(); _box->insertStringList( pDef->getValueList() ); QStringList::Iterator itr; int i=0; for(itr=pDef->getValueList().begin(); itr!=pDef->getValueList().end(); itr++) { if( (*itr)==_currentItem->text(_currentColumn) ) { _box->setCurrentItem(i); i=-1; break; } i++; } if( i>=0 ) { _box->insertItem( _currentItem->text(_currentColumn) ); _box->setCurrentItem(i); } _stack->raiseWidget(_box); } else { odebug << "Unsupported column type for column " << (const char *)pDef->getName() << "" << oendl; _typeEdit->setText(""); _stack->raiseWidget(_typeEdit); } } // --- addColumnDef ----------------------------------------------------------- void ListEdit::addColumnDef(ColumnDef *pDef) { _typeTable->addColumn( pDef->getName() ); _vColumns.append(pDef); } // --- addData ---------------------------------------------------------------- void ListEdit::addData(QStringList &lst) { // run through list QStringList::Iterator itr; for(itr=lst.begin(); itr!=lst.end(); itr++) { QStringList split=QStringList::split(";", *itr, true); QStringList::Iterator entry; QString args[8]; int i=0; for(entry=split.begin(); entry!=split.end() && i<8; entry++, i++) { args[i]= (*entry); } while(i<8) { args[i++]=""; } new QListViewItem(_typeTable, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); } } // --- slotActivated ---------------------------------------------------------- void ListEdit::slotActivated(const QString &str) { if( _currentItem==NULL || _currentColumn<0 ) return; _currentItem->setText(_currentColumn, str); } diff --git a/noncore/apps/opie-console/TEScreen.cpp b/noncore/apps/opie-console/TEScreen.cpp index 2675d31..8e91532 100644 --- a/noncore/apps/opie-console/TEScreen.cpp +++ b/noncore/apps/opie-console/TEScreen.cpp @@ -1,1208 +1,1208 @@ /* -------------------------------------------------------------------------- */ /* */ /* [TEScreen.C] Screen Data Type */ /* */ /* -------------------------------------------------------------------------- */ /* */ /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ /* */ /* This file is part of Konsole - an X terminal for KDE */ /* */ /* -------------------------------------------------------------------------- */ /* */ /* Ported Konsole to Qt/Embedded */ /* */ /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ /* */ /* -------------------------------------------------------------------------- */ /*! \file */ /*! \class TEScreen \brief The image manipulated by the emulation. This class implements the operations of the terminal emulation framework. It is a complete passive device, driven by the emulation decoder (TEmuVT102). By this it forms in fact an ADT, that defines operations on a rectangular image. It does neither know how to display its image nor about escape sequences. It is further independent of the underlying toolkit. By this, one can even use this module for an ordinary text surface. Since the operations are called by a specific emulation decoder, one may collect their different operations here. The state manipulated by the operations is mainly kept in `image', though it is a little more complex bejond this. See the header file of the class. \sa TEWidget \sa VT102Emulation */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> // #include <kdebug.h> #include <assert.h> #include <string.h> #include <ctype.h> #include "TEScreen.h" #define HERE printf("%s(%d): here\n",__FILE__,__LINE__) //FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI. //FIXME: see if we can get this from terminfo. #define BS_CLEARS FALSE #define loc(X,Y) ((Y)*columns+(X)) /*! creates a `TEScreen' of `lines' lines and `columns' columns. */ TEScreen::TEScreen(int lines, int columns) { this->lines = lines; this->columns = columns; image = (ca*) malloc(lines*columns*sizeof(ca)); tabstops = NULL; initTabStops(); histCursor = 0; clearSelection(); reset(); } /*! Destructor */ TEScreen::~TEScreen() { free(image); if (tabstops) free(tabstops); } /* ------------------------------------------------------------------------- */ /* */ /* Normalized Screen Operations */ /* */ /* ------------------------------------------------------------------------- */ // Cursor Setting -------------------------------------------------------------- /*! \section Cursor The `cursor' is a location within the screen that is implicitely used in many operations. The operations within this section allow to manipulate the cursor explicitly and to obtain it's value. The position of the cursor is guarantied to be between (including) 0 and `columns-1' and `lines-1'. */ /*! Move the cursor up. The cursor will not be moved beyond the top margin. */ void TEScreen::cursorUp(int n) //=CUU { if (n == 0) n = 1; // Default int stop = cuY < tmargin ? 0 : tmargin; cuX = QMIN(columns-1,cuX); // nowrap! cuY = QMAX(stop,cuY-n); } /*! Move the cursor down. The cursor will not be moved beyond the bottom margin. */ void TEScreen::cursorDown(int n) //=CUD { if (n == 0) n = 1; // Default int stop = cuY > bmargin ? lines-1 : bmargin; cuX = QMIN(columns-1,cuX); // nowrap! cuY = QMIN(stop,cuY+n); } /*! Move the cursor left. The cursor will not move beyond the first column. */ void TEScreen::cursorLeft(int n) //=CUB { if (n == 0) n = 1; // Default cuX = QMIN(columns-1,cuX); // nowrap! cuX = QMAX(0,cuX-n); } /*! Move the cursor left. The cursor will not move beyond the rightmost column. */ void TEScreen::cursorRight(int n) //=CUF { if (n == 0) n = 1; // Default cuX = QMIN(columns-1,cuX+n); } /*! Set top and bottom margin. */ void TEScreen::setMargins(int top, int bot) //=STBM { if (top == 0) top = 1; // Default if (bot == 0) bot = lines; // Default top = top - 1; // Adjust to internal lineno bot = bot - 1; // Adjust to internal lineno if ( !( 0 <= top && top < bot && bot < lines ) ) { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n", __FILE__,__LINE__,top,bot); return; // Default error action: ignore } tmargin = top; bmargin = bot; cuX = 0; cuY = getMode(MODE_Origin) ? top : 0; } /*! Move the cursor down one line. If cursor is on bottom margin, the region between the actual top and bottom margin is scrolled up instead. */ void TEScreen::index() //=IND { if (cuY == bmargin) { if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history scrollUp(tmargin,1); } else if (cuY < lines-1) cuY += 1; } /*! Move the cursor up one line. If cursor is on the top margin, the region between the actual top and bottom margin is scrolled down instead. */ void TEScreen::reverseIndex() //=RI { if (cuY == tmargin) scrollDown(tmargin,1); else if (cuY > 0) cuY -= 1; } /*! Move the cursor to the begin of the next line. If cursor is on bottom margin, the region between the actual top and bottom margin is scrolled up. */ void TEScreen::NextLine() //=NEL { Return(); index(); } // Line Editing ---------------------------------------------------------------- /*! \section inserting / deleting characters */ /*! erase `n' characters starting from (including) the cursor position. The line is filled in from the right with spaces. */ void TEScreen::eraseChars(int n) { if (n == 0) n = 1; // Default int p = QMAX(0,QMIN(cuX+n-1,columns-1)); clearImage(loc(cuX,cuY),loc(p,cuY),' '); } /*! delete `n' characters starting from (including) the cursor position. The line is filled in from the right with spaces. */ void TEScreen::deleteChars(int n) { if (n == 0) n = 1; // Default int p = QMAX(0,QMIN(cuX+n,columns-1)); moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY)); clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' '); } /*! insert `n' spaces at the cursor position. The cursor is not moved by the operation. */ void TEScreen::insertChars(int n) { if (n == 0) n = 1; // Default int p = QMAX(0,QMIN(columns-1-n,columns-1)); int q = QMAX(0,QMIN(cuX+n,columns-1)); moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY)); clearImage(loc(cuX,cuY),loc(q-1,cuY),' '); } /*! delete `n' lines starting from (including) the cursor position. The cursor is not moved by the operation. */ void TEScreen::deleteLines(int n) { if (n == 0) n = 1; // Default scrollUp(cuY,n); } /*! insert `n' lines at the cursor position. The cursor is not moved by the operation. */ void TEScreen::insertLines(int n) { if (n == 0) n = 1; // Default scrollDown(cuY,n); } // Mode Operations ----------------------------------------------------------- /*! Set a specific mode. */ void TEScreen::setMode(int m) { currParm.mode[m] = TRUE; switch(m) { case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home } } /*! Reset a specific mode. */ void TEScreen::resetMode(int m) { currParm.mode[m] = FALSE; switch(m) { case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home } } /*! Save a specific mode. */ void TEScreen::saveMode(int m) { saveParm.mode[m] = currParm.mode[m]; } /*! Restore a specific mode. */ void TEScreen::restoreMode(int m) { currParm.mode[m] = saveParm.mode[m]; } //NOTE: this is a helper function /*! Return the setting a specific mode. */ BOOL TEScreen::getMode(int m) { return currParm.mode[m]; } /*! Save the cursor position and the rendition attribute settings. */ void TEScreen::saveCursor() { sa_cuX = cuX; sa_cuY = cuY; sa_cu_re = cu_re; sa_cu_fg = cu_fg; sa_cu_bg = cu_bg; } /*! Restore the cursor position and the rendition attribute settings. */ void TEScreen::restoreCursor() { cuX = QMIN(sa_cuX,columns-1); cuY = QMIN(sa_cuY,lines-1); cu_re = sa_cu_re; cu_fg = sa_cu_fg; cu_bg = sa_cu_bg; effectiveRendition(); } /* ------------------------------------------------------------------------- */ /* */ /* Screen Operations */ /* */ /* ------------------------------------------------------------------------- */ /*! Assing a new size to the screen. The topmost left position is maintained, while lower lines or right hand side columns might be removed or filled with spaces to fit the new size. The region setting is reset to the whole screen and the tab positions reinitialized. */ void TEScreen::resizeImage(int new_lines, int new_columns) { if (cuY > new_lines-1) { // attempt to preserve focus and lines bmargin = lines-1; //FIXME: margin lost for (int i = 0; i < cuY-(new_lines-1); i++) { addHistLine(); scrollUp(0,1); } } // make new image ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca)); clearSelection(); // clear new image for (int y = 0; y < new_lines; y++) for (int x = 0; x < new_columns; x++) { newimg[y*new_columns+x].c = ' '; newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR; newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR; newimg[y*new_columns+x].r = DEFAULT_RENDITION; } int cpy_lines = QMIN(new_lines, lines); int cpy_columns = QMIN(new_columns,columns); // copy to new image for (int y = 0; y < cpy_lines; y++) for (int x = 0; x < cpy_columns; x++) { newimg[y*new_columns+x].c = image[loc(x,y)].c; newimg[y*new_columns+x].f = image[loc(x,y)].f; newimg[y*new_columns+x].b = image[loc(x,y)].b; newimg[y*new_columns+x].r = image[loc(x,y)].r; } free(image); image = newimg; lines = new_lines; columns = new_columns; cuX = QMIN(cuX,columns-1); cuY = QMIN(cuY,lines-1); // FIXME: try to keep values, evtl. tmargin=0; bmargin=lines-1; initTabStops(); clearSelection(); } /* Clarifying rendition here and in TEWidget. currently, TEWidget's color table is 0 1 2 .. 9 10 .. 17 dft_fg, dft_bg, dim 0..7, intensive 0..7 cu_fg, cu_bg contain values 0..8; - 0 = default color - 1..8 = ansi specified color re_fg, re_bg contain values 0..17 due to the TEWidget's color table rendition attributes are attr widget screen -------------- ------ ------ RE_UNDERLINE XX XX affects foreground only RE_BLINK XX XX affects foreground only RE_BOLD XX XX affects foreground only RE_REVERSE -- XX RE_TRANSPARENT XX -- affects background only RE_INTENSIVE XX -- affects foreground only Note that RE_BOLD is used in both widget and screen rendition. Since xterm/vt102 is to poor to distinguish between bold (which is a font attribute) and intensive (which is a color attribute), we translate this and RE_BOLD in falls eventually appart into RE_BOLD and RE_INTENSIVE. */ void TEScreen::reverseRendition(ca* p) { UINT8 f = p->f; UINT8 b = p->b; p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT; } void TEScreen::effectiveRendition() // calculate rendition { ef_re = cu_re & (RE_UNDERLINE | RE_BLINK); if (cu_re & RE_REVERSE) { ef_fg = cu_bg; ef_bg = cu_fg; } else { ef_fg = cu_fg; ef_bg = cu_bg; } if (cu_re & RE_BOLD) { if (ef_fg < BASE_COLORS) ef_fg += BASE_COLORS; else ef_fg -= BASE_COLORS; } } /*! returns the image. Get the size of the image by \sa getLines and \sa getColumns. NOTE that the image returned by this function must later be freed. */ ca* TEScreen::getCookedImage() { int x,y; ca* merged = (ca*)malloc(lines*columns*sizeof(ca)); ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION); for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++) { int len = QMIN(columns,hist.getLineLen(y+histCursor)); int yp = y*columns; int yq = (y+histCursor)*columns; hist.getCells(y+histCursor,0,len,merged+yp); for (x = len; x < columns; x++) merged[yp+x] = dft; for (x = 0; x < columns; x++) { int p=x + yp; int q=x + yq; if ( ( q >= sel_TL ) && ( q <= sel_BR ) ) reverseRendition(&merged[p]); // for selection } } if (lines >= hist.getLines()-histCursor) { for (y = (hist.getLines()-histCursor); y < lines ; y++) { int yp = y*columns; int yq = (y+histCursor)*columns; int yr = (y-hist.getLines()+histCursor)*columns; for (x = 0; x < columns; x++) { int p = x + yp; int q = x + yq; int r = x + yr; merged[p] = image[r]; if ( q >= sel_TL && q <= sel_BR ) reverseRendition(&merged[p]); // for selection } } } // evtl. inverse display if (getMode(MODE_Screen)) { int i,n = lines*columns; for (i = 0; i < n; i++) reverseRendition(&merged[i]); // for reverse display } if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]); return merged; } /*! */ void TEScreen::reset() { setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1] resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke setMode(MODE_Cursor); // cursor visible resetMode(MODE_Screen); // screen not inverse resetMode(MODE_NewLine); tmargin=0; bmargin=lines-1; setDefaultRendition(); saveCursor(); clear(); } /*! Clear the entire screen and home the cursor. */ void TEScreen::clear() { clearEntireScreen(); home(); } /*! Moves the cursor left one column. */ void TEScreen::BackSpace() { cuX = QMAX(0,cuX-1); if (BS_CLEARS) image[loc(cuX,cuY)].c = ' '; } /*! */ void TEScreen::Tabulate() { // note that TAB is a format effector (does not write ' '); cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1); } void TEScreen::clearTabStops() { for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE; } void TEScreen::changeTabStop(bool set) { if (cuX >= columns) return; tabstops[cuX] = set; } void TEScreen::initTabStops() { if (tabstops) free(tabstops); tabstops = (bool*)malloc(columns*sizeof(bool)); // Arrg! The 1st tabstop has to be one longer than the other. // i.e. the kids start counting from 0 instead of 1. // Other programs might behave correctly. Be aware. for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0); } /*! This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine) depending on the NewLine Mode (LNM). This mode also affects the key sequence returned for newline ([CR]LF). */ void TEScreen::NewLine() { if (getMode(MODE_NewLine)) Return(); index(); } /*! put `c' literally onto the screen at the current cursor position. VT100 uses the convention to produce an automatic newline (am) with the *first* character that would fall onto the next line (xenl). */ void TEScreen::checkSelection(int from, int to) { if (sel_begin == -1) return; int scr_TL = loc(0, hist.getLines()); //Clear entire selection if it overlaps region [from, to] if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) ) { clearSelection(); } } void TEScreen::ShowCharacter(unsigned short c) { // Note that VT100 does wrapping BEFORE putting the character. // This has impact on the assumption of valid cursor positions. // We indicate the fact that a newline has to be triggered by // putting the cursor one right to the last column of the screen. if (cuX >= columns) { if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1; } if (getMode(MODE_Insert)) insertChars(1); int i = loc(cuX,cuY); checkSelection(i, i); // check if selection is still valid. image[i].c = c; image[i].f = ef_fg; image[i].b = ef_bg; image[i].r = ef_re; cuX += 1; } // Region commands ------------------------------------------------------------- /*! scroll up `n' lines within current region. The `n' new lines are cleared. \sa setRegion \sa scrollDown */ void TEScreen::scrollUp(int from, int n) { if (n <= 0 || from + n > bmargin) return; //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds. moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin)); clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' '); } /*! scroll down `n' lines within current region. The `n' new lines are cleared. \sa setRegion \sa scrollUp */ void TEScreen::scrollDown(int from, int n) { //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds. if (n <= 0) return; if (from > bmargin) return; if (from + n > bmargin) n = bmargin - from; moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n)); clearImage(loc(0,from),loc(columns-1,from+n-1),' '); } /*! position the cursor to a specific line and column. */ void TEScreen::setCursorYX(int y, int x) { setCursorY(y); setCursorX(x); } /*! Set the cursor to x-th line. */ void TEScreen::setCursorX(int x) { if (x == 0) x = 1; // Default x -= 1; // Adjust cuX = QMAX(0,QMIN(columns-1, x)); } /*! Set the cursor to y-th line. */ void TEScreen::setCursorY(int y) { if (y == 0) y = 1; // Default y -= 1; // Adjust cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) )); } /*! set cursor to the `left upper' corner of the screen (1,1). */ void TEScreen::home() { cuX = 0; cuY = 0; } /*! set cursor to the begin of the current line. */ void TEScreen::Return() { cuX = 0; } /*! returns the current cursor columns. */ int TEScreen::getCursorX() { return cuX; } /*! returns the current cursor line. */ int TEScreen::getCursorY() { return cuY; } // Erasing --------------------------------------------------------------------- /*! \section Erasing This group of operations erase parts of the screen contents by filling it with spaces colored due to the current rendition settings. Althought the cursor position is involved in most of these operations, it is never modified by them. */ /*! fill screen between (including) `loca' and `loce' with spaces. This is an internal helper functions. The parameter types are internal addresses of within the screen image and make use of the way how the screen matrix is mapped to the image vector. */ void TEScreen::clearImage(int loca, int loce, char c) { int i; int scr_TL=loc(0,hist.getLines()); //FIXME: check positions //Clear entire selection if it overlaps region to be moved... if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) ) { clearSelection(); } for (i = loca; i <= loce; i++) { image[i].c = c; image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here. } } /*! move image between (including) `loca' and `loce' to 'dst'. This is an internal helper functions. The parameter types are internal addresses of within the screen image and make use of the way how the screen matrix is mapped to the image vector. */ void TEScreen::moveImage(int dst, int loca, int loce) { //FIXME: check positions if (loce < loca) { // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl; return; } memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca)); } /*! clear from (including) current cursor position to end of screen. */ void TEScreen::clearToEndOfScreen() { clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' '); } /*! clear from begin of screen to (including) current cursor position. */ void TEScreen::clearToBeginOfScreen() { clearImage(loc(0,0),loc(cuX,cuY),' '); } /*! clear the entire screen. */ void TEScreen::clearEntireScreen() { clearImage(loc(0,0),loc(columns-1,lines-1),' '); } /*! fill screen with 'E' This is to aid screen alignment */ void TEScreen::helpAlign() { clearImage(loc(0,0),loc(columns-1,lines-1),'E'); } /*! clear from (including) current cursor position to end of current cursor line. */ void TEScreen::clearToEndOfLine() { clearImage(loc(cuX,cuY),loc(columns-1,cuY),' '); } /*! clear from begin of current cursor line to (including) current cursor position. */ void TEScreen::clearToBeginOfLine() { clearImage(loc(0,cuY),loc(cuX,cuY),' '); } /*! clears entire current cursor line */ void TEScreen::clearEntireLine() { clearImage(loc(0,cuY),loc(columns-1,cuY),' '); } // Rendition ------------------------------------------------------------------ /*! set rendition mode */ void TEScreen::setRendition(int re) { cu_re |= re; effectiveRendition(); } /*! reset rendition mode */ void TEScreen::resetRendition(int re) { cu_re &= ~re; effectiveRendition(); } /*! */ void TEScreen::setDefaultRendition() { setForeColorToDefault(); setBackColorToDefault(); cu_re = DEFAULT_RENDITION; effectiveRendition(); } /*! */ void TEScreen::setForeColor(int fgcolor) { cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2); effectiveRendition(); } /*! */ void TEScreen::setBackColor(int bgcolor) { cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2); effectiveRendition(); } /*! */ void TEScreen::setBackColorToDefault() { cu_bg = DEFAULT_BACK_COLOR; effectiveRendition(); } /*! */ void TEScreen::setForeColorToDefault() { cu_fg = DEFAULT_FORE_COLOR; effectiveRendition(); } /* ------------------------------------------------------------------------- */ /* */ /* Marking & Selection */ /* */ /* ------------------------------------------------------------------------- */ void TEScreen::clearSelection() { sel_BR = -1; sel_TL = -1; sel_begin = -1; } void TEScreen::setSelBeginXY(const int x, const int y) { sel_begin = loc(x,y+histCursor) ; sel_BR = sel_begin; sel_TL = sel_begin; } void TEScreen::setSelExtentXY(const int x, const int y) { if (sel_begin == -1) return; int l = loc(x,y + histCursor); if (l < sel_begin) { sel_TL = l; sel_BR = sel_begin; } else { /* FIXME, HACK to correct for x too far to the right... */ if (( x == columns )|| (x == 0)) l--; sel_TL = sel_begin; sel_BR = l; } } QString TEScreen::getSelText(const BOOL preserve_line_breaks) { if (sel_begin == -1) return QString::null; // Selection got clear while selecting. int *m; // buffer to fill. int s, d; // source index, dest. index. int hist_BR = loc(0, hist.getLines()); int hY = sel_TL / columns; int hX = sel_TL % columns; int eol; // end of line s = sel_TL; // tracks copy in source. // allocate buffer for maximum // possible size... d = (sel_BR - sel_TL) / columns + 1; m = new int[d * (columns + 1) + 2]; d = 0; while (s <= sel_BR) { if (s < hist_BR) { // get lines from hist.history // buffer. eol = hist.getLineLen(hY); if ((hY == (sel_BR / columns)) && (eol >= (sel_BR % columns))) { eol = sel_BR % columns + 1; } while (hX < eol) { m[d++] = hist.getCell(hY, hX++).c; s++; } if (s <= sel_BR) { // The line break handling // It's different from the screen // image case! if (eol % columns == 0) { // That's either a completely filled // line or an empty line if (eol == 0) { m[d++] = '\n'; } else { // We have a full line. // FIXME: How can we handle newlines // at this position?! } } else if ((eol + 1) % columns == 0) { // FIXME: We don't know if this was a // space at the last position or a // short line!! m[d++] = ' '; } else { // We have a short line here. Put a // newline or a space into the // buffer. m[d++] = preserve_line_breaks ? '\n' : ' '; } } hY++; hX = 0; s = hY * columns; } else { // or from screen image. eol = (s / columns + 1) * columns - 1; if (eol < sel_BR) { while ((eol > s) && isspace(image[eol - hist_BR].c)) { eol--; } } else { eol = sel_BR; } while (s <= eol) { m[d++] = image[s++ - hist_BR].c; } if (eol < sel_BR) { // eol processing see below ... if ((eol + 1) % columns == 0) { if (image[eol - hist_BR].c == ' ') { m[d++] = ' '; } } else { m[d++] = ((preserve_line_breaks || ((eol % columns) == 0)) ? '\n' : ' '); } } s = (eol / columns + 1) * columns; } } QChar* qc = new QChar[d]; for (int i = 0; i < d; i++) { qc[i] = m[i]; } QString res(qc, d); - delete m; - delete qc; + delete [] m; + delete [] qc; return res; } QString TEScreen::getHistory() { sel_begin = 0; sel_BR = sel_begin; sel_TL = sel_begin; setSelExtentXY(columns-1,lines-1); QString tmp=getSelText(true); while (tmp.at(tmp.length()-2).unicode()==10 && tmp.at(tmp.length()-1).unicode()==10) tmp.truncate(tmp.length()-1); return tmp; } /* above ... end of line processing for selection -- psilva cases: 1) (eol+1)%columns == 0 --> the whole line is filled. If the last char is a space, insert (preserve) space. otherwise leave the text alone, so that words that are broken by linewrap are preserved. FIXME: * this suppresses \n for command output that is sized to the exact column width of the screen. 2) eol%columns == 0 --> blank line. insert a \n unconditionally. Do it either you would because you are in preserve_line_break mode, or because it's an ASCII paragraph delimiter, so even when not preserving line_breaks, you want to preserve paragraph breaks. 3) else --> partially filled line insert a \n in preserve line break mode, else a space The space prevents concatenation of the last word of one line with the first of the next. */ void TEScreen::addHistLine() { assert(hasScroll() || histCursor == 0); // add to hist buffer // we have to take care about scrolling, too... if (hasScroll()) { ca dft; int end = columns-1; while (end >= 0 && image[end] == dft) end -= 1; hist.addCells(image,end+1); hist.addLine(); // adjust history cursor histCursor += (hist.getLines()-1 == histCursor); } if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround } void TEScreen::setHistCursor(int cursor) { histCursor = cursor; //FIXME:rangecheck } int TEScreen::getHistCursor() { return histCursor; } int TEScreen::getHistLines() { return hist.getLines(); } void TEScreen::setScroll(bool on) { histCursor = 0; clearSelection(); hist.setScroll(on); } bool TEScreen::hasScroll() { return hist.hasScroll(); } diff --git a/noncore/apps/opie-sheet/Excel.cpp b/noncore/apps/opie-sheet/Excel.cpp index 338bc30..51fe707 100644 --- a/noncore/apps/opie-sheet/Excel.cpp +++ b/noncore/apps/opie-sheet/Excel.cpp @@ -1,1709 +1,1709 @@ /* =. This file is part of the Opie Project .=l. Copyright (C) 2004 Opie Developer Team <opie-devel@handhelds.org> .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Excel.h" /* STD */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <sys/types.h> #include <strings.h> static xfrecord formatter[] = { { 0xe , DATEFORMAT, "%m/%d/%y"}, { 0xf , DATEFORMAT, "%d-%b-%y"}, { 0x10, DATEFORMAT, "%d-%b"}, { 0x11, DATEFORMAT, "%b-%y"}, { 0x12, DATEFORMAT, "%I:%M %p"}, { 0x13, DATEFORMAT, "%I:%M:%S %p"}, { 0x14, DATEFORMAT, "%H:%M"}, { 0x15, DATEFORMAT, "%H:%M:%S"}, { 0x16, DATEFORMAT, "%m/%d/%y %H:%M"}, { 0x2d, DATEFORMAT, "%M:%S"}, { 0x2e, DATEFORMAT, "%H:%M:%S"}, { 0x2f, DATEFORMAT, "%M:%S"}, { 0xa5, DATEFORMAT, "%m/%d/%y %I:%M %p"}, { 0x1 , NUMBERFORMAT, "%.0f"}, { 0x2 , NUMBERFORMAT, "%.2f"}, { 0x3 , NUMBERFORMAT, "#,##%.0f"}, { 0x4 , NUMBERFORMAT, "#,##%.2f"}, { 0x5 , NUMBERFORMAT, "$#,##%.0f"}, { 0x6 , NUMBERFORMAT, "$#,##%.0f"}, { 0x7 , NUMBERFORMAT, "$#,##%.2f"}, { 0x8 , NUMBERFORMAT, "$#,##%.2f"}, { 0x9 , NUMBERFORMAT, "%.0f%%"}, { 0xa , NUMBERFORMAT, "%.2f%%"}, { 0xb , NUMBERFORMAT, "%e"}, { 0x25, NUMBERFORMAT, "#,##%.0f;(#,##0)"}, { 0x26, NUMBERFORMAT, "#,##%.0f;(#,##0)"}, { 0x27, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"}, { 0x28, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"}, { 0x29, NUMBERFORMAT, "#,##%.0f;(#,##0)"}, { 0x2a, NUMBERFORMAT, "$#,##%.0f;($#,##0)"}, { 0x2b, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"}, { 0x2c, NUMBERFORMAT, "$#,##%.2f;($#,##0.00)"}, { 0x30, NUMBERFORMAT, "##0.0E0"}, { 0, 0, ""} }; int ExcelBook::Integer2Byte(int b1, int b2) { int i1 = b1 & 0xff; int i2 = b2 & 0xff; int val = i2 << 8 | i1; return val; }; int ExcelBook::Integer4Byte(int b1,int b2,int b3,int b4) { int i1 = Integer2Byte(b1, b2); int i2 = Integer2Byte(b3, b4); int val = i2 << 16 | i1; return val; }; int ExcelBook::Integer2ByteFile(FILE *f) { int i1, i2; i1 = fgetc(f); i2 = fgetc(f); return Integer2Byte(i1,i2); }; float ExcelBook::Float4Byte(int b1, int b2, int b3, int b4) { int i; float f; unsigned char *ieee; ieee = (unsigned char *) &f; for (i = 0; i < 4; i++) ieee[i] = 0; ieee[0] = ((int)b4) & 0xff; ieee[1] = ((int)b3) & 0xff; ieee[2] = ((int)b2) & 0xff; ieee[3] = ((int)b1) & 0xff; return f; }; double ExcelBook::Double4Byte(int b1, int b2, int b3, int b4) { long int rk; double value; rk=Integer4Byte(b1,b2,b3,b4); //printf("Double4Bytes:%d,%d,%d,%d\r\n",b1,b2,b3,b4); if ( (rk & 0x02) != 0) { long int intval = rk >> 2; //drops the 2 bits printf("Double4Byte:intval=%d, rk=%d, rk>>2=%d\r\n",intval,rk,rk>>2); value = (double) intval; printf("Double4Byte: VALUEINT=%f\r\n",value); if ( (rk & 0x01) != 0) { value /= 100.0; }; return value; } else { union { double d; unsigned long int b[2]; } dbl_byte; unsigned long int valbits = (rk & 0xfffffffc); #if defined(__arm__) && !defined(__vfp__) dbl_byte.b[0]=valbits; dbl_byte.b[1]=0; #else dbl_byte.b[0]=0; dbl_byte.b[1]=valbits; #endif printf("dbl_byte.b[0]=%d,dbl_byte.b[1]=%d\r\n",dbl_byte.b[0],dbl_byte.b[1]); value=dbl_byte.d; printf("Double4Byte: VALUE=%f\r\n",value); if ( (rk & 0x01) != 0) { value /= 100.0; }; return value; }; }; void ExcelBook::DetectEndian(void) { int end; long i = 0x44332211; unsigned char* a = (unsigned char*) &i; end = (*a != 0x11); if (end == 1) { endian = BIG_ENDIAN; printf("BIGENDIAN!\r\n"); } else { endian = LITTLE_ENDIAN; printf("LITTLEENDIAN!\r\n"); } }; double ExcelBook::Double8Byte(int b1, int b2, int b3, int b4, int b5, int b6, int b7, int b8) { int i; double d; unsigned char *ieee; ieee = (unsigned char *)&d; for (i = 0; i < 8; i++) ieee[i] = 0; if (endian == BIG_ENDIAN) { ieee[0] = ((int)b8) & 0xff;ieee[1] = ((int)b7) & 0xff; ieee[2] = ((int)b6) & 0xff;ieee[3] = ((int)b5) & 0xff; ieee[4] = ((int)b4) & 0xff;ieee[5] = ((int)b3) & 0xff; ieee[6] = ((int)b2) & 0xff;ieee[7] = ((int)b1) & 0xff; } else { ieee[0] = ((int)b1) & 0xff;ieee[1] = ((int)b2) & 0xff; ieee[2] = ((int)b3) & 0xff;ieee[3] = ((int)b4) & 0xff; ieee[4] = ((int)b5) & 0xff;ieee[5] = ((int)b6) & 0xff; ieee[6] = ((int)b7) & 0xff;ieee[7] = ((int)b8) & 0xff; } return d; }; bool ExcelBook::OpenFile(char *Filename) { printf("Opening excel file!\r\n"); File= fopen(Filename, "r"); Position=0; // first byte index in file XFRecords.resize(0); SharedStrings.resize(0); Names.resize(0); Sheets.resize(0); if(File==NULL) return false; printf("Opened excel file!\r\n"); return true; }; bool ExcelBook::CloseFile(void) { int w1; for(w1=0;w1<(int)XFRecords.count();w1++) { if(XFRecords[w1]!=NULL) {delete XFRecords[w1];XFRecords[w1]=NULL;}; }; for(w1=0;w1<(int)SharedStrings.count();w1++) { if(SharedStrings[w1]!=NULL) {delete SharedStrings[w1];SharedStrings[w1]=NULL;}; }; for(w1=0;w1<(int)Names.count();w1++) { if(Names[w1]!=NULL) {delete Names[w1];Names[w1]=NULL;}; }; for(w1=0;w1<(int)Sheets.count();w1++) { if(Sheets[w1]!=NULL) {delete Sheets[w1];Sheets[w1]=NULL;}; }; XFRecords.resize(0); SharedStrings.resize(0); Names.resize(0); Sheets.resize(0); fclose(File); printf("closed excel file!\r\n"); if(File==NULL) return true; return false; }; void ExcelBook::SeekPosition(int pos) { if(!feof(File)) { Position=pos; //printf("SeekPosition:Pos:%d\r\n",Position); fseek(File,pos,SEEK_SET); }; }; void ExcelBook::SeekSkip(int pos) { if(!feof(File)) { Position=Position+pos; //printf("SeekSkip:Pos:%d\r\n",Position); fseek(File, Position, SEEK_SET); }; }; int ExcelBook::FileEOF(void) { if(File!=NULL) return(feof(File)); else return 0; //EOF is defined in stdlib as -1 }; int ExcelBook::Get2Bytes(void) { int i1,i2; i1=0; i2=0; if (!feof(File)) { i1=fgetc(File); Position++; }; if (!feof(File)) { i2=fgetc(File); Position++; }; return Integer2Byte(i1,i2); }; char* ExcelBook::Read(int pos, int length) { int i; char *data; data= new char[length]; SeekPosition(pos); for(i=0; i<length; i++) { if(!feof(File)) data[i]=fgetc(File); }; Position= Position+length; return data; }; QString ExcelBook::ReadUnicodeChar(int pos, int length) { int i; QString data; int i1=' ',i2=' ',ii; SeekPosition(pos); for(i=0; i<length; i++) { if(!feof(File)) i1=fgetc(File); if(!feof(File)) i2=fgetc(File); ii=Integer2Byte(i1,i2); data.append(ii); Position+=2; }; return data; }; QString* ExcelBook::GetString(int num) { if(num>=0 && num<(int)SharedStrings.count()) { return SharedStrings[num]; }; return new QString(""); }; int ExcelBook::SeekBOF(void) { int opcode,version,streamtype,length,ret=0; char *data; while(!feof(File)) { opcode=Get2Bytes(); if(opcode==XL_BOF) { length=Get2Bytes(); data=Read(Position,length); version=Integer2Byte(data[0], data[1]); streamtype=Integer2Byte(data[2], data[3]); printf("SEEKBOF:opcode=XLBOF, %d ,version %d\r\n",Position,version); - delete data; data=NULL; + delete [] data; data=NULL; if (version==BIFF8) ret=8; else if(version==BIFF7) ret=7; printf("SEEKBOF:versionBIFF%d\r\n",ret); if(streamtype==WBKGLOBAL) return ret *2; else if(streamtype==WRKSHEET) return ret *1; return 1; }; }; return 0; }; ExcelBREC* ExcelBook::GetBREC(void) { ExcelBREC* rec; rec= new ExcelBREC; if(FileEOF()) return NULL; rec->data=NULL; rec->code=Get2Bytes(); rec->length=Get2Bytes(); rec->position=Position; SeekSkip(rec->length); return rec; }; ExcelBREC* ExcelBook::PeekBREC(void) { int oldpos; ExcelBREC* NextRec; oldpos=Position; NextRec=GetBREC(); SeekPosition(oldpos); return NextRec; }; char* ExcelBook::GetDataOfBREC(ExcelBREC* record) { if(record->data==NULL) { ConvertCharToArray(record,Read(record->position,record->length),record->length); }; return record->data;//new? }; void ExcelBook::ConvertCharToArray(ExcelBREC* record, char* chars, int length) { record->data=new char[length]; for(int w1=0;w1<=length-1;w1++) record->data[w1]=chars[w1]; }; bool ExcelSheet::InitCells() { int r; Cells.resize(rows * cols + cols+1); if(Cells.count()==0) return false; for(r=0;r < Cells.count();r++) { Cells[r]=NULL; }; return true; }; void ExcelSheet::Set(int row, int col, ExcelCell* cell) { if(cell!=NULL&&(row*cols+col)<Cells.count()) { Cells[row*cols+col]=cell; }; }; ExcelCell* ExcelSheet::Get(int row, int col) { ExcelCell* cell; cell=Cells[row*cols+col]; if(cell==NULL) return NULL; return cell; }; int ExcelBook::SheetHandleRecord(ExcelSheet* sheet, ExcelBREC* record) { char* data=NULL; switch (record->code) { case XL_DIMENSION: data = GetDataOfBREC(record); if (record->length == 10) { sheet->rows = Integer2Byte(data[2], data[3]); sheet->cols = Integer2Byte(data[6], data[7]); } else { sheet->rows = Integer4Byte(data[4], data[5], data[6], data[7]); sheet->cols = Integer2Byte(data[10], data[11]); } sheet->InitCells(); break; case XL_LABELSST: HandleLabelSST(sheet, record); break; case XL_RK: case XL_RK2: HandleRK(sheet, record); break; case XL_MULRK: HandleMulrk(sheet, record); break; case XL_ROW: break; case XL_NUMBER: HandleNumber(sheet, record); break; case XL_BOOLERR: break; case XL_CONTINUE: break; case XL_FORMULA: case XL_FORMULA2: HandleFormula(sheet, record); break; case XL_LABEL: break; case XL_NAME: HandleName(sheet, record); break; case XL_BOF: break; case XL_EOF: return 0; default: break; }; return 1; }; int ExcelBook::ReadSheet(ExcelSheet* sheet) { ExcelBREC* record; int oldpos; oldpos = Position; SeekPosition(sheet->position); record = GetBREC(); while (record!=NULL) { if (!SheetHandleRecord(sheet, record)) break; record=GetBREC(); }; SeekPosition(oldpos); return 1; }; ExcelSheet* ExcelBook::GetSheet(void) { ExcelSheet* sh=NULL; int type; type=SeekBOF(); Version=type; sh=new ExcelSheet; if(type) { sh->type=type; sh->position=Position; sh->name=QString(""); }; if(type==8||type==7) { ReadSheet(sh); }; return sh; }; void ExcelBook::ParseSheets(void) { int BOFs; ExcelBREC* r; BOFs=1; r=GetBREC(); while(BOFs) { r=GetBREC(); switch(r->code) { case XL_SST: HandleSST(r); break; case XL_TXO: break; case XL_NAME: break; case XL_ROW: break; case XL_FORMAT: HandleFormat(r); break; case XL_XF: HandleXF(r); break; case XL_BOUNDSHEET: HandleBoundSheet(r); break; case XL_EXTSST: break; case XL_CONTINUE: break; case XL_EOF: BOFs--; break; default: break; }; }; }; void ExcelBook::GetSheets(void) { ExcelSheet* sheet; Sheets.resize(0); sheet=GetSheet(); while (sheet->Cells.count()!= 0 ) { Sheets.resize(Sheets.count()+1); Sheets[Sheets.count()-1]=sheet; sheet->name=*Names[Sheets.count()-1]; sheet=GetSheet(); }; }; bool ExcelBook::ParseBook(char *file) { dateformat=QString(""); DetectEndian(); if ( !OpenFile( file ) ) return false; SeekBOF(); ParseSheets(); GetSheets(); return true; }; QString ExcelBook::GetASCII(char* inbytes, int pos, int chars) { int i; QString outstr=""; for (i = 0; i < chars; i++) { outstr.append(inbytes[i+pos]); }; return outstr; }; QString ExcelBook::GetUnicode(char * inbytes, int pos, int chars) { QString outstr=""; int i; int rc; for (i=0; i<chars*2; i++) { rc=Integer2Byte(inbytes[i+pos],inbytes[i+pos+1]); outstr.append(QChar(rc)); i++; }; return outstr; }; void ExcelBook::HandleBoundSheet(ExcelBREC* rec) { char* data; int type; int visibility; int length; int pos; QString name; pos = 8; data = GetDataOfBREC(rec); type = data[4]; visibility = data[5]; length = data[6]; if(data[7]==0) { //ascii name=GetASCII(data,pos,length); } else { name=GetUnicode(data,pos,length); }; Names.resize(Names.count()+1); Names[Names.count()-1]=new QString(name); }; void ExcelBook::HandleName(ExcelSheet* sheet, ExcelBREC* rec) { char* data; QString name; int length; int pos; pos = 15; data = GetDataOfBREC(rec); length = data[3]; name = GetASCII(data,pos,length); }; ExcelFormat* ExcelBook::GetFormatting(int xf) { int i; ExcelFormat* rec; rec=new ExcelFormat(); for (i = 0; formatter[i].code != 0; i++) { if (xf == formatter[i].code) break; }; if (formatter[i].format ==NULL) return NULL; rec->code = xf; rec->type = formatter[i].type; rec->format = formatter[i].format; return rec; }; void ExcelBook::HandleSetOfSST(ExcelBREC* rec/*, SSTList* cont*/, char* bytes) { QString str=QString(""); char* data; int chars, pos, options, i; int richstring, fareaststring, runlength=0; int richruns=0,fareastsize=0; int totalstrings; int uniquestrings; data = GetDataOfBREC(rec); totalstrings = Integer4Byte(data[0], data[1], data[2], data[3]); uniquestrings = Integer4Byte(data[4], data[5], data[6], data[7]); pos = 8; for (i = 0; i < uniquestrings; i++) { richruns=0; fareastsize=0; chars = Integer2Byte(data[pos], data[pos+1]); pos += 2; options = data[pos]; pos++; fareaststring = ((options & 0x04) != 0); richstring = ((options & 0x08) != 0); if(richstring) { richruns= Integer2Byte(data[pos],data[pos+1]); pos+=2; }; if(fareaststring) { fareastsize=Integer4Byte(data[pos], data[pos+1], data[pos+2], data[pos+3]); pos+=4; }; if ((options & 0x01) == 0) //8 bit chars { /* ascii */ str = GetASCII(bytes,pos,chars); pos=pos+chars; if(str[0]=='=') str[0]=' '; }else //16 bit chars { /* unicode */ str = GetUnicode(bytes,pos,chars); pos=pos+chars*2; }; // HERE TO PUT richformat handling if (richstring) { pos += 4 * richruns; }; if (fareaststring) { pos += fareastsize; }; //printf("String=%s, length=%d first=0x%x\r\n",str.ascii(),str.length(),str[0].unicode()); SharedStrings.resize(SharedStrings.count()+1); SharedStrings[SharedStrings.count()-1]=new QString(str); } }; char* ExcelBook::MergeBytesFromSSTs(ExcelBREC* rec,SSTList* cont) { int i, pos; int length; char* data; char* bytes; length = rec->length; for (i = 0; i < (int) cont->rec.count(); i++) { length += cont->rec[i]->length; } bytes = GetDataOfBREC(rec); pos = rec->length; for (i = 0; i < (int) cont->rec.count(); i++) { data = GetDataOfBREC(cont->rec[i]); *bytes += pos; bytes = data; pos += cont->rec[i]->length; } return bytes; }; void ExcelBook::HandleSST(ExcelBREC* rec) { char* bytes; SSTList* cont; cont= new SSTList; ExcelBREC* nr; nr = PeekBREC(); while (nr->code == XL_CONTINUE) { cont->rec.resize(cont->rec.count()+1); cont->rec[cont->rec.count()-1]=GetBREC(); nr = PeekBREC(); } bytes = MergeBytesFromSSTs(rec,cont); HandleSetOfSST(rec, bytes); for(int w1=0;w1<(int)cont->rec.count();w1++) { if(cont->rec[w1]!=NULL) {delete cont->rec[w1];cont->rec[w1]=NULL;}; }; cont->rec.resize(0); }; void ExcelBook::HandleLabelSST(ExcelSheet* sheet, ExcelBREC* rec) { int index, row, col; char* data; data = GetDataOfBREC(rec); index = Integer4Byte(data[6], data[7], data[8], data[9]); row = Integer2Byte(data[0], data[1]); col = Integer2Byte(data[2], data[3]); sheet->Set(row,col, CellLabel(row, col, *GetString(index))); }; ExcelCell* ExcelBook::CellLabel(int row, int col, QString str) { ExcelCell* c; c= new ExcelCell; c->row = row; c->col = col; c->type = CELL_LABEL; c->valuec = str; return c; }; ExcelCell* ExcelBook::CellNumber(int row, int col, int index, double d) { ExcelCell* c; c=new ExcelCell; c->row = row; c->col = col; c->xfindex = index; c->type = CELL_NUMBER; c->valued = d; return c; }; QString* ExcelBook::CellDataString(ExcelSheet* sh, int row, int col) { time_t date; struct tm *tmptr; ExcelCell* c; char str[128]; QString format; int precision; int utcOffsetDays = 25569; int sInADay = 24 * 60 * 60; c = sh->Get(row,col); if (c == NULL) return new QString(""); switch (c->type) { case CELL_LABEL: return new QString(c->valuec); case CELL_NUMBER: if (XFRecords[c->xfindex]->type == DATEFORMAT) { format = XFRecords[c->xfindex]->format; date = (time_t) ((c->valued - utcOffsetDays) * sInADay); tmptr = gmtime(&date); if (dateformat) { strftime(str,1024,dateformat.ascii(),tmptr); } else { strftime(str,1024,format.ascii(),tmptr); }; } else if (XFRecords[c->xfindex]->type == NUMBERFORMAT) { format = XFRecords[c->xfindex]->format; //sprintf(str,format.ascii(),c->valued); // the real format is ignored... // because there is more work to be done in the field precision = CellGetPrecision(c->valued); sprintf(str,"%.*f",precision,c->valued); } else { precision = CellGetPrecision(c->valued); sprintf(str,"%.*f",precision,c->valued); }; break; case CELL_DATE: break; case CELL_BOOLEAN: break; case CELL_ERROR: break; } return new QString(str); }; int ExcelBook::CellGetPrecision(double d) { double t; int i,x; int count; if (d < 0) d *= -1; i = (int)d; t = d - (double)i; if (t <= 0) { return 0; }; count = 0; for (x = 6; x > 1; x--) { i = (int)d; t = d - (double)i; t *= pow(10,x - 2); i = (int)t; t = t - (double)i; t *= 10; i = (int)t; if (i > 0) break; count++; }; return (5 - count); }; void ExcelBook::CellSetDateFormat(char *d) { dateformat = QString(d); }; void ExcelBook::HandleMulrk(ExcelSheet* sheet, ExcelBREC* record) { struct mulrk mulrk; char* data; ExcelCell* cell; int len; int i; len = record->length; data = GetDataOfBREC(record); mulrk.row = Integer2Byte(data[0],data[1]); mulrk.first = Integer2Byte(data[2],data[3]); mulrk.last = Integer2Byte(data[len - 2],data[len - 1]); mulrk.numrks = mulrk.last - mulrk.first + 1; MulrkRead(&mulrk, data); for (i = 0; i < mulrk.numrks; i++) { cell = CellNumber(mulrk.row, mulrk.first + i, mulrk.xfindices[i], mulrk.rkdbls[i]); sheet->Set(mulrk.row,mulrk.first+ i, cell); //printf("handleMULRK:row=%d,col=%d,val=%f\r\n",mulrk.row,mulrk.first+i,mulrk.rkdbls[i]); } //delete(mulrk.xfindices); //delete(mulrk.rkdbls); }; void ExcelBook::MulrkRead(struct mulrk *mulrk, char* data) { double d; int i; int pos; pos = 4; mulrk->xfindices.resize(mulrk->numrks); mulrk->rkdbls.resize(mulrk->numrks); for (i = 0; i < mulrk->numrks; i++) { mulrk->xfindices[i] = Integer2Byte(data[pos], data[pos+1]); d=Double4Byte(data[pos+2], data[pos+3], data[pos+4], data[pos+5]); //printf("double:%f\r\n",d); mulrk->rkdbls[i] = d; pos += 6; } }; void ExcelBook::HandleNumber(ExcelSheet* sheet, ExcelBREC* record) { int xfindex, row, col; char* data; double d; data = GetDataOfBREC(record); row = Integer2Byte(data[0], data[1]); col = Integer2Byte(data[2], data[3]); xfindex = Integer2Byte(data[4], data[5]); #if defined(__arm__) && !defined(__vfp__) d=Double8Byte(data[10], data[11], data[12], data[13],data[6], data[7], data[8], data[9]); #else d=Double8Byte(data[6], data[7], data[8], data[9],data[10], data[11], data[12], data[13]); #endif //even if ARM is little endian... doubles are been placed as bigendian words. //thanks pb_ for that. :) sheet->Set(row,col, CellNumber(row,col,xfindex,d)); //printf("handleNumber:row=%d,col=%d,val=%f\r\n",row,col,d); }; ExcelFormat::ExcelFormat() { code=0;type=0;format=""; }; ExcelFormat::ExcelFormat(int c,int t, QString s) { code=c;type=t;format=s; }; void ExcelBook::HandleFormat(ExcelBREC* rec) { ExcelFormat* xfrec; char* data; int format; data = GetDataOfBREC(rec); format = Integer2Byte(data[2],data[3]); xfrec = GetFormatting(format); /*int idx; idx=XFRecords.count()-1; XFRecords[idx]->code=xfrec->code; XFRecords[idx]->type=xfrec->type; XFRecords[idx]->format="manos"; //XFRecords[XFRecords.count()-1]=xfrec; printf("6\r\n");*/ }; void ExcelBook::HandleXF(ExcelBREC* rec) { ExcelFormat* xfrec; char* data; int format; data = GetDataOfBREC(rec); format = Integer2Byte(data[2],data[3]); xfrec = GetFormatting(format); XFRecords.resize(XFRecords.count()+1); XFRecords[XFRecords.count()-1]=xfrec; }; void ExcelBook::HandleRK(ExcelSheet* sheet, ExcelBREC* record) { int xfindex, row, col; char* data; double d; data = GetDataOfBREC(record); row = Integer2Byte(data[0], data[1]); col = Integer2Byte(data[2], data[3]); xfindex = Integer2Byte(data[4], data[5]); d=Double4Byte(data[6], data[7], data[8], data[9]); sheet->Set(row,col,CellNumber(row,col,xfindex,d)); //printf("handleRK:row=%d,col=%d,val=%f\r\n",row,col,d); }; void ExcelBook::HandleFormula(ExcelSheet* sheet, ExcelBREC* record) { int xfindex, row, col; char* data; double d; data = GetDataOfBREC(record); row = Integer2Byte(data[0], data[1]); col = Integer2Byte(data[2], data[3]); if (data[6] == 0 && data[12] == -1 && data[13] == -1) { // string } else if (data[6] == 1 && data[12] == -1 && data[13] == -1) { // boolean } else if ( data[6] == 2 && data[12] == -1 && data[13] == -1) { // error } else { // number xfindex = Integer2Byte(data[4], data[5]); d=Double8Byte(data[6], data[7], data[8], data[9],data[10], data[11], data[12], data[13]); QString s1; int sz; sz=Integer2Byte(data[20],data[21]);// size of the formula char* formuladata; formuladata=new char[sz]; for(int w1=0;w1<sz;w1++) { formuladata[w1]=data[22+w1]; }; //22 is the first 0 idx of formula data s1="="+GetFormula(row,col,sheet,formuladata,sz); //printf("GetFormula:Formula=%s\r\n",s1.ascii()); sheet->Set(row,col,CellLabel(row,col,s1)); } }; QString ExcelBook::GetFormula(int row, int col, ExcelSheet* sheet, char* data, int sz) { int length=sz; printf("{FormulaParser}\r\n"); printf("row=%d, col=%d, length=%d\r\n",row,col,length); int idx=0; int w1,w2,w3,w4; double d1; int token; QString s1; QList <QString> operands; operands.setAutoDelete(TRUE); QString formula; operands.clear(); while( idx<length ) { token= data[idx]; idx++; switch(token) { case 0x1E: //prtInt w1=Integer2Byte(data[idx],data[idx+1]); idx=idx+2; operands.prepend(new QString(QString::number(w1))); printf(" token:ptgInt,num=%d\r\n",w1); break; case 0x1F: //ptgNumber #if defined(__arm__) && !defined(__vfp__) d1=Double8Byte(data[idx+4],data[idx+5],data[idx+6],data[idx+7] ,data[idx],data[idx+1],data[idx+2],data[idx+3]); #else d1=Double8Byte(data[idx],data[idx+1],data[idx+2],data[idx+3] ,data[idx+4],data[idx+5],data[idx+6],data[idx+7]); #endif idx=idx+8; operands.prepend(new QString(QString::number(d1))); printf(" token:ptgNumber,num=%f\r\n",d1); break; case 0x17: //ptgStr if(Version==8) { //unicode string //w1=Integer2Byte(data[idx],data[idx+1]);idx+=2; w1=data[idx];idx++; printf("len=%d\r\n",w1); int richruns=0; int fareastsize=0; int richstring,fareaststring; int options = data[idx];idx++; fareaststring = ((options & 0x04) != 0); richstring = ((options & 0x08) != 0); if(richstring) { //containts rich string formatting. printf("STRING:richstring\r\n"); richruns= Integer2Byte(data[idx],data[idx+1]); printf("richruns:%d\r\n",richruns); idx+=2; }; if(fareaststring) { //contains far east formatting printf("STRING:fareast!\r\n"); fareastsize=Integer4Byte(data[idx], data[idx+1], data[idx+2], data[idx+3]); printf("fareastsize=%d",fareastsize); idx+=4; }; if ((options & 0x01) == 0) //8 bit chars { /* ascii */ s1 = GetASCII(data,idx,w1); idx=idx+w1; printf("STRING:ASCII=%s\r\n",s1.ascii()); }else //16 bit chars { /* unicode */ s1 = GetUnicode(data,idx,w1); idx=idx+w1*2; printf("STRING:unicode=%s\r\n",s1.ascii()); }; // HERE TO PUT richformat handling if (richstring) { idx += 4 * richruns; }; if (fareaststring) { idx += fareastsize; }; s1=QString("""")+s1+QString(""""); operands.prepend(new QString(s1)); } else { w1=data[idx];idx++; s1=GetASCII(data,idx,w1); s1=QString("""")+s1+QString(""""); idx=idx+w1; operands.prepend(new QString(s1)); }; printf(" token:ptgStr,num=%d\r\n",w1); break; case 0x25: case 0x45: case 0x65: // ptgArea if(Version==8) { w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row1 w2=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row2 w3=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col1 w4=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col2 } else { w1=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row1 w2=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row2 w3=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col1 w4=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col2 }; //ignores relative or absolute refs s1=FindCellName(w1,w3)+":"+FindCellName(w2,w4); printf(" token:ptgArea,ref=%s\r\n",s1.ascii()); operands.prepend(new QString(s1)); break; case 0x24: case 0x44: case 0x64://ptgRef if(Version==8) { w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row w2=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col } else { w1=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row w2=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col }; s1=FindCellName(w1,w2); printf("token:ptgRef,ref=%s\r\n",s1.ascii()); operands.prepend(new QString(s1)); break; case 0x1D: // ptgBool w1=data[idx];idx++; printf("token:ptgBool,val=%d\r\n",w1); operands.prepend(new QString(QString::number(w1))); break; case 0x16://ptg MissArg printf("token:ptgMissArg, val=' '\r\n"); operands.prepend(new QString("0")); break; case 0x12://ptgUplus== printf("token:ptgUplus\r\n"); s1=QString("+")+operands.first()->ascii(); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x13://ptgUminus printf("token:ptgUminus\r\n"); s1=QString("-")+operands.first()->ascii(); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x03://ptgAdd printf("token:ptgAdd\r\n"); operands.first(); s1=operands.next()->ascii() +QString("+")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x04://ptgSub printf("token:ptgSub\r\n"); operands.first(); s1=operands.next()->ascii() +QString("-")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x05://ptgMul printf("token:ptgMul\r\n"); operands.first(); s1=operands.next()->ascii() +QString("*")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x06://ptgDiv printf("token:ptgDiv\r\n"); operands.first(); s1=operands.next()->ascii() +QString("/")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x07://ptgPOWER printf("token:ptgPow\r\n"); operands.first(); s1=QString("POWER(")+operands.next()->ascii() +QString(",")+operands.first()->ascii()+QString(")"); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x08://ptgConcat printf("token:ptgConcat\r\n"); operands.first(); s1=QString("CONCATENATE(")+operands.next()->ascii() +QString(",")+operands.first()->ascii()+QString(")"); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x15://ptgParenthesis printf("token:ptgParenthesis\r\n"); s1=QString("(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x14://ptgPercent printf("token:ptgPercent\r\n"); s1=operands.first()->ascii()+QString("*0.01"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x9://ptgLessThan printf("token:ptgLESS\r\n"); operands.first(); s1=operands.next()->ascii() +QString("<")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xa://ptgLessEqual printf("token:ptgLESS_EQUAL\r\n"); operands.first(); s1=operands.next()->ascii() +QString("<=")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xb://ptgEQUAL printf("token:ptgEQUAL\r\n"); operands.first(); s1=operands.next()->ascii() +QString("==")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xc://ptgGREATER_EQUAL printf("token:ptgGREAT_EQUAL\r\n"); operands.first(); s1=operands.next()->ascii() +QString(">=")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xd://ptgGREAT_THAN printf("token:ptgGREAT_THAN\r\n"); operands.first(); s1=operands.next()->ascii() +QString(">")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xe://ptgNOT_EQUAL printf("token:ptgNOTequal\r\n"); operands.first(); s1=operands.next()->ascii() +QString("!=")+operands.first()->ascii(); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x19://attribute can be Sum,If,Choose w3=Integer2Byte(data[idx],data[idx+1]);idx=idx+2; idx++; printf("token:ATTRIBUTE:0x%x\r\n",w3); for(w4=idx;w4<length;w4++) printf("0x%x, ",data[w4]); if(w3&0x01)//choose { printf("token:CHOOSE\r\n"); } else if(w3&0x02)//if { printf("token:IF\r\n"); } else if(w3&0x10)//sum { printf("token:SUM\r\n"); }; break; case 0x21: case 0x22: case 0x42: case 0x62: case 0x41: case 0x61://ptgFunction printf("token:ptgFunction\r\n"); if(token==0x22||token==0x42||token==0x62) { w2=(int)data[idx];idx++; w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2; } else { w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2; }; switch(w1) { case 0xf://SIN s1=QString("SIN(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x10://COS s1=QString("COS(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x11://tan s1=QString("TAN(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x62://asin s1=QString("ASIN(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x63://ACOS s1=QString("ACOS(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x12://ATAN s1=QString("ATAN(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xe5://SINH s1=QString("SINH(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xe6://COSH s1=QString("COSH(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xe7://TANH s1=QString("TANH(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xe8://ASINH s1=QString("ASINH(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xe9://ACOSH s1=QString("ACOSH(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xea://ATANH s1=QString("ATANH(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x13://pi s1="PI()"; operands.prepend(new QString(s1)); break; case 0x14://sqrt s1=QString("SQRT(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x15://exp s1=QString("EXP(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x16://LN s1=QString("LN(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x17://LOG10 s1=QString("LOG10(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x18://ABS s1=QString("ABS(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x19://int s1=QString("INT(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x1a://sign s1=QString("SIGN(")+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x1b://round operands.first(); s1=QString("ROUND(")+operands.next()->ascii() +QString(",")+operands.first()->ascii() +QString(")"); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x1d://index operands.first(); s1=QString("INDEX(")+operands.next()->ascii() +QString(",") +operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x1: // if ATTRIBUTE operands.first();operands.next(); s1=QString("IF(")+operands.next()->ascii()+QString(","); operands.first(); s1=s1+operands.next()->ascii()+QString(","); s1=s1+operands.first()->ascii()+QString(")"); operands.removeFirst(); operands.removeFirst(); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x81://isblank s1=QString("ISBLANK(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x80://isnumber s1=QString("ISNUMBER(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x120://ceiling operands.first(); s1=QString("CEILING(")+operands.next()->ascii() +QString(",")+operands.first()->ascii() +QString(")"); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x11d://floor operands.first(); s1=QString("FLOOR(")+operands.next()->ascii() +QString(",")+operands.first()->ascii() +QString(")"); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x157://degrees s1=QString("DEGREES(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x156://radians s1=QString("RADIANS(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xb8://fact s1=QString("FACT(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x27://MOD operands.first(); s1=QString("MOD(")+operands.next()->ascii() +QString(",")+operands.first()->ascii() +QString(")"); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x151://power operands.first(); s1=QString("POWER(")+operands.next()->ascii() +QString(",")+operands.first()->ascii() +QString(")"); operands.removeFirst();operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x3f://rand() s1="RAND()"; operands.prepend(new QString(s1)); break; case 0x4://sum for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("SUM(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x6://min for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("MIN(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x7://max for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("MAX(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x5://average for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("AVERAGE(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x2e://var for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("VAR(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xc2://varp for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("VARP(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xc://stdev for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("STDEV(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0xc1://stdevp for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("STDEVP(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x143://skew for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("SKEW(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x142://kurt for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("KURT(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; case 0x0://count for(w4=1;w4<w2;w4++) operands.removeFirst(); s1=QString("COUNT(")+operands.first()->ascii() +QString(")"); operands.removeFirst(); operands.prepend(new QString(s1)); break; default: printf("token:FUNCTION_UNKNOWN=0x%x\r\n",w1); return QString("FUNC_UNKNOWN"); break; }; break; default: printf("tokenUNKNOWN=0x%x\r\n",token); return QString("TOKEN_UKNOWN"); //it is dangerous to go to idx++ and not return // because the result is unexpected. // but there is a possibility the the parser will give the correct // answer, because there are some tokens in excel formulas that can be //ignored. idx++; break; }; }; printf("{////FormulaParser}\r\n"); printf("GetFormula:::::::r=%d,c=%d,,,%s\r\n",row,col,s1.ascii()); printf("\r\n"); s1=operands.first()->ascii(); operands.clear(); return QString(s1); }; QString ExcelBook::FindCellName(int row, int col) { row++;col++; QString s1=""; int i1=col % 26; int i2=col / 26; if (i2!=0) s1=(char)(i2+65); //65 =A s1=s1+(char)(i1+65-1); return (s1+QString::number(row)); }; diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp index 6dc4fd2..a70f3aa 100644 --- a/noncore/apps/tinykate/libkate/document/katedocument.cpp +++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp @@ -1,3175 +1,3175 @@ /*************************************************************************** katedocument.cpp - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "katedocument.h" #include "kmessagebox.h" #include "kglobal.h" //#include "kcharsets.h" #include "kdebug.h" //#include "kinstance.h" #include "kglobalsettings.h" //#include "kaction.h" //#include "kstdaction.h" #include "../view/kateview.h" #include "katebuffer.h" #include "katetextline.h" #include "katecmd.h" /* OPIE */ #include <opie2/odebug.h> #include <qpe/config.h> /* QT */ #include <qfileinfo.h> #include <qdatetime.h> #include <qstring.h> #include <qtimer.h> #include <qobject.h> #include <qapplication.h> #include <qclipboard.h> #include <qfont.h> #include <qpainter.h> #include <qfile.h> #include <qtextstream.h> #include <qtextcodec.h> /* STD */ #include <sys/time.h> #include <unistd.h> #include <stdio.h> KateAction::KateAction(Action a, PointStruc &cursor, int len, const QString &text) : action(a), cursor(cursor), len(len), text(text) { } KateActionGroup::KateActionGroup(PointStruc &aStart, int type) : start(aStart), action(0L), undoType(type) { } KateActionGroup::~KateActionGroup() { KateAction *current, *next; current = action; while (current) { next = current->next; delete current; current = next; } } void KateActionGroup::insertAction(KateAction *a) { a->next = action; action = a; } const char * KateActionGroup::typeName(int type) { // return a short text description of the given undo group type suitable for a menu // not the lack of i18n's, the caller is expected to handle translation switch (type) { case ugPaste : return "Paste Text"; case ugDelBlock : return "Selection Overwrite"; case ugIndent : return "Indent"; case ugUnindent : return "Unindent"; case ugComment : return "Comment"; case ugUncomment : return "Uncomment"; case ugReplace : return "Text Replace"; case ugSpell : return "Spell Check"; case ugInsChar : return "Typing"; case ugDelChar : return "Delete Text"; case ugInsLine : return "New Line"; case ugDelLine : return "Delete Line"; } return ""; } const int KateDocument::maxAttribs = 32; QStringList KateDocument::searchForList = QStringList(); QStringList KateDocument::replaceWithList = QStringList(); uint KateDocument::uniqueID = 0; QPtrDict<KateDocument::KateDocPrivate>* KateDocument::d_ptr = 0; KateDocument::KateDocument(bool bSingleViewMode, bool bBrowserView, QWidget *parentWidget, const char *widgetName, QObject *, const char *) : Kate::Document (), myFont(KGlobalSettings::generalFont()), myFontBold(KGlobalSettings::generalFont()), myFontItalic(KGlobalSettings::generalFont()), myFontBI(KGlobalSettings::generalFont()), myFontMetrics (myFont), myFontMetricsBold (myFontBold), myFontMetricsItalic (myFontItalic), myFontMetricsBI (myFontBI), hlManager(HlManager::self ()) { d(this)->hlSetByUser = false; PreHighlightedTill=0; RequestPreHighlightTill=0; m_bSingleViewMode=bSingleViewMode; m_bBrowserView = bBrowserView; m_url = QString::null; // NOTE: QFont::CharSet doesn't provide all the charsets KDE supports // (esp. it doesn't distinguish between UTF-8 and iso10646-1) myEncoding = QString::fromLatin1(QTextCodec::codecForLocale()->name()); maxLength = -1; setFont (KGlobalSettings::generalFont()); myDocID = uniqueID; uniqueID++; myDocName = QString (""); fileInfo = new QFileInfo (); myCmd = new KateCmd (this); connect(this,SIGNAL(modifiedChanged()),this,SLOT(slotModChanged())); buffer = new KWBuffer; connect(buffer, SIGNAL(linesChanged(int)), this, SLOT(slotBufferChanged())); // connect(buffer, SIGNAL(textChanged()), this, SIGNAL(textChanged())); connect(buffer, SIGNAL(needHighlight(long,long)),this,SLOT(slotBufferHighlight(long,long))); colors[0] = KGlobalSettings::baseColor(); colors[1] = KGlobalSettings::highlightColor(); m_attribs = new Attribute[maxAttribs]; m_highlight = 0L; tabChars = 8; m_singleSelection = false; newDocGeometry = false; readOnly = false; newDoc = false; modified = false; undoList.setAutoDelete(true); undoState = 0; undoSteps = 50; pseudoModal = 0L; clear(); setHighlight(0); //calls updateFontData() // if the user changes the highlight with the dialog, notify the doc connect(hlManager,SIGNAL(changed()),SLOT(hlChanged())); newDocGeometry = false; readConfig(); setReadOnly(false); } void KateDocument::setDontChangeHlOnSave() { d(this)->hlSetByUser = true; } void KateDocument::setFont (QFont font) { kdDebug()<<"Kate:: setFont"<<endl; int oldwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 myFont = font; myFontBold = QFont (font); myFontBold.setBold (true); myFontItalic = QFont (font); myFontItalic.setItalic (true); myFontBI = QFont (font); myFontBI.setBold (true); myFontBI.setItalic (true); myFontMetrics = CachedFontMetrics (myFont); myFontMetricsBold = CachedFontMetrics (myFontBold); myFontMetricsItalic = CachedFontMetrics (myFontItalic); myFontMetricsBI = CachedFontMetrics (myFontBI); int newwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 maxLength=maxLength*(float)newwidth/(float)oldwidth; //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 updateFontData(); updateViews(); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 } long KateDocument::needPreHighlight(long till) { int max=numLines()-1; if (till>max) { till=max; } if (PreHighlightedTill>=till) return -1; long tmp=RequestPreHighlightTill; if (RequestPreHighlightTill<till) { RequestPreHighlightTill=till; if (tmp<=PreHighlightedTill) QTimer::singleShot(10,this,SLOT(doPreHighlight())); } return RequestPreHighlightTill; } void KateDocument::doPreHighlight() { int from = PreHighlightedTill; int till = PreHighlightedTill+200; int max = numLines()-1; if (till > max) { till = max; } PreHighlightedTill = till; updateLines(from,till); emit preHighlightChanged(PreHighlightedTill); if (PreHighlightedTill<RequestPreHighlightTill) QTimer::singleShot(10,this,SLOT(doPreHighlight())); } KateDocument::~KateDocument() { m_highlight->release(); writeConfig(); if ( !m_bSingleViewMode ) { m_views.setAutoDelete( true ); m_views.clear(); m_views.setAutoDelete( false ); } delete_d(this); } void KateDocument::openURL(const QString &filename) { m_file=filename; fileInfo->setFile (m_file); setMTime(); if (!fileInfo->exists() || !fileInfo->isReadable()) { odebug << "File doesn't exit or couldn't be read" << oendl; return ; } buffer->clear(); #warning fixme // buffer->insertFile(0, m_file, KGlobal::charsets()->codecForName(myEncoding)); odebug << "Telling buffer to open file" << oendl; buffer->insertFile(0, m_file, QTextCodec::codecForLocale()); setMTime(); if (myWordWrap) wrapText (myWordWrapAt); int hl = hlManager->wildcardFind( m_file ); setHighlight(hl); updateLines(); updateViews(); emit fileNameChanged(); return ; } bool KateDocument::saveFile() { QFile f( m_file ); if ( !f.open( IO_WriteOnly ) ) return false; // Error QTextStream stream(&f); stream.setEncoding(QTextStream::RawUnicode); // disable Unicode headers #warning fixme // stream.setCodec(KGlobal::charsets()->codecForName(myEncoding)); stream.setCodec(QTextCodec::codecForLocale()); // this line sets the mapper to the correct codec int maxLine = numLines(); int line = 0; while(true) { stream << getTextLine(line)->getString(); line++; if (line >= maxLine) break; if (eolMode == KateDocument::eolUnix) stream << "\n"; else if (eolMode == KateDocument::eolDos) stream << "\r\n"; else if (eolMode == KateDocument::eolMacintosh) stream << '\r'; }; f.close(); fileInfo->setFile (m_file); setMTime(); if (!(d(this)->hlSetByUser)) { int hl = hlManager->wildcardFind( m_file ); setHighlight(hl); } emit fileNameChanged (); return (f.status() == IO_Ok); } KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name ) { return new KateView( this, parent, name); } QString KateDocument::textLine( int line ) const { TextLine::Ptr l = getTextLine( line ); if ( !l ) return QString(); return l->getString(); } void KateDocument::replaceLine(const QString& s,int line) { remove_Line(line,false); insert_Line(s,line,true); } void KateDocument::insertLine( const QString &str, int l ) { insert_Line(str,l,true); } void KateDocument::insert_Line(const QString& s,int line, bool update) { kdDebug(13020)<<"KateDocument::insertLine "<<s<<QString(" %1").arg(line)<<endl; TextLine::Ptr TL=new TextLine(); TL->append(s.unicode(),s.length()); buffer->insertLine(line,TL); if (update) { newDocGeometry=true; updateLines(line); updateViews(); } } void KateDocument::insertAt( const QString &s, int line, int col, bool ) { VConfig c; c.view = 0; // ### FIXME c.cursor.x = col; c.cursor.y = line; c.cXPos = 0; // ### FIXME c.flags = 0; // ### FIXME insert( c, s ); } void KateDocument::removeLine( int line ) { remove_Line(line,true); } void KateDocument::remove_Line(int line,bool update) { kdDebug(13020)<<"KateDocument::removeLine "<<QString("%1").arg(line)<<endl; buffer->removeLine(line); // newDocGeometry=true; // if line==0) if (update) { updateLines(line); updateViews(); } } int KateDocument::length() const { return text().length(); } void KateDocument::setSelection( int , int , int , int ) { } bool KateDocument::hasSelection() const { return (selectEnd >= selectStart); } QString KateDocument::selection() const { uint flags = 0; TextLine::Ptr textLine; int len, z, start, end, i; len = 1; if (!(flags & KateView::cfVerticalSelect)) { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected(); if (textLine->isSelected()) len++; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); if (textLine->isSelected()) { s[len] = '\n'; len++; } } // s[len] = '\0'; return s; } else { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected() + 1; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); s[len] = '\n'; len++; } // s[len] = '\0'; // the final \0 is not counted in length() return s; } } int KateDocument::numLines() const { return buffer->count(); } TextLine::Ptr KateDocument::getTextLine(int line) const { // This is a hack to get this stuff working. return buffer->line(line); } int KateDocument::textLength(int line) { TextLine::Ptr textLine = getTextLine(line); if (!textLine) return 0; return textLine->length(); } void KateDocument::setTabWidth(int chars) { if (tabChars == chars) return; if (chars < 1) chars = 1; if (chars > 16) chars = 16; tabChars = chars; updateFontData(); maxLength = -1; for (int i=0; i < buffer->count(); i++) { TextLine::Ptr textLine = buffer->line(i); int len = textWidth(textLine,textLine->length()); if (len > maxLength) { maxLength = len; longestLine = textLine; } } } void KateDocument::setReadOnly(bool m) { KTextEditor::View *view; if (m != readOnly) { readOnly = m; // if (readOnly) recordReset(); for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newStatus(); } } } bool KateDocument::isReadOnly() const { return readOnly; } void KateDocument::setNewDoc( bool m ) { // KTextEditor::View *view; if ( m != newDoc ) { newDoc = m; //// if (readOnly) recordReset(); // for (view = m_views.first(); view != 0L; view = m_views.next() ) { // emit static_cast<KateView *>( view )->newStatus(); // } } } bool KateDocument::isNewDoc() const { return newDoc; } void KateDocument::setModified(bool m) { KTextEditor::View *view; if (m != modified) { modified = m; for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newStatus(); } emit modifiedChanged (); } } bool KateDocument::isModified() const { return modified; } void KateDocument::readConfig() { KateConfig *config = KGlobal::config(); config->setGroup("Kate Document"); myWordWrap = config->readBoolEntry("Word Wrap On", false); myWordWrapAt = config->readNumEntry("Word Wrap At", 80); if (myWordWrap) wrapText (myWordWrapAt); setTabWidth(config->readNumEntry("TabWidth", 8)); setUndoSteps(config->readNumEntry("UndoSteps", 50)); m_singleSelection = config->readBoolEntry("SingleSelection", false); myEncoding = config->readEntry("Encoding", QString::fromLatin1(QTextCodec::codecForLocale()->name())); setFont (config->readFontEntry("Font", myFont)); colors[0] = config->readColorEntry("Color Background", colors[0]); colors[1] = config->readColorEntry("Color Selected", colors[1]); // config->sync(); } void KateDocument::writeConfig() { KateConfig *config = KGlobal::config(); config->setGroup("Kate Document"); config->writeEntry("Word Wrap On", myWordWrap); config->writeEntry("Word Wrap At", myWordWrapAt); config->writeEntry("TabWidth", tabChars); config->writeEntry("UndoSteps", undoSteps); config->writeEntry("SingleSelection", m_singleSelection); config->writeEntry("Encoding", myEncoding); config->writeEntry("Font", myFont); config->writeEntry("Color Background", colors[0]); config->writeEntry("Color Selected", colors[1]); // config->sync(); } void KateDocument::readSessionConfig(KateConfig *config) { m_url = config->readEntry("URL"); // ### doesn't this break the encoding? (Simon) setHighlight(hlManager->nameFind(config->readEntry("Highlight"))); // anders: restore bookmarks if possible QValueList<int> l = config->readIntListEntry("Bookmarks"); if ( l.count() ) { for (uint i=0; i < l.count(); i++) { if ( numLines() < l[i] ) break; getTextLine( l[i] )->addMark( Bookmark ); } } } void KateDocument::writeSessionConfig(KateConfig *config) { #if 0 config->writeEntry("URL", m_url); // ### encoding?? (Simon) config->writeEntry("Highlight", m_highlight->name()); // anders: save bookmarks QList<Kate::Mark> l = marks(); QValueList<int> ml; for (uint i=0; i < l.count(); i++) { if ( l.at(i)->type == 1) // only save bookmarks ml << l.at(i)->line; } if ( ml.count() ) config->writeEntry("Bookmarks", ml); #endif } void KateDocument::setHighlight(int n) { Highlight *h; // hlNumber = n; h = hlManager->getHl(n); if (h == m_highlight) { updateLines(); } else { if (m_highlight != 0L) m_highlight->release(); h->use(); m_highlight = h; makeAttribs(); } PreHighlightedTill=0; RequestPreHighlightTill=0; emit(highlightChanged()); } void KateDocument::makeAttribs() { odebug << "KateDocument::makeAttribs()" << oendl; m_numAttribs = hlManager->makeAttribs(m_highlight, m_attribs, maxAttribs); updateFontData(); updateLines(); } void KateDocument::updateFontData() { int maxAscent, maxDescent; int tabWidth; KateView *view; maxAscent = myFontMetrics.ascent(); maxDescent = myFontMetrics.descent(); tabWidth = myFontMetrics.width(' '); fontHeight = maxAscent + maxDescent + 1; fontAscent = maxAscent; m_tabWidth = tabChars*tabWidth; for (view = views.first(); view != 0L; view = views.next() ) { view->myViewInternal->drawBuffer->resize(view->width(),fontHeight); view->tagAll(); view->updateCursor(); } } void KateDocument::hlChanged() { //slot makeAttribs(); updateViews(); } void KateDocument::addView(KTextEditor::View *view) { views.append( static_cast<KateView *>( view ) ); KTextEditor::Document::addView( view ); connect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); } void KateDocument::removeView(KTextEditor::View *view) { // if (undoView == view) recordReset(); disconnect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); views.removeRef( static_cast<KateView *>( view ) ); KTextEditor::Document::removeView( view ); } void KateDocument::slotViewDestroyed() { views.removeRef( static_cast<const KateView *>( sender() ) ); } bool KateDocument::ownedView(KateView *view) { // do we own the given view? return (views.containsRef(view) > 0); } bool KateDocument::isLastView(int numViews) { return ((int) views.count() == numViews); } int KateDocument::textWidth(const TextLine::Ptr &textLine, int cursorX) { int x; int z; QChar ch; Attribute *a; x = 0; for (z = 0; z < cursorX; z++) { ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } return x; } int KateDocument::textWidth(PointStruc &cursor) { if (cursor.x < 0) cursor.x = 0; if (cursor.y < 0) cursor.y = 0; if (cursor.y >= numLines()) cursor.y = lastLine(); return textWidth(getTextLine(cursor.y),cursor.x); } int KateDocument::textWidth(bool wrapCursor, PointStruc &cursor, int xPos) { int len; int x, oldX; int z; QChar ch; Attribute *a; if (cursor.y < 0) cursor.y = 0; if (cursor.y > lastLine()) cursor.y = lastLine(); TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); x = oldX = z = 0; while (x < xPos && (!wrapCursor || z < len)) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } if (xPos - oldX < x - xPos && z > 0) { z--; x = oldX; } cursor.x = z; return x; } int KateDocument::textPos(const TextLine::Ptr &textLine, int xPos) { int x, oldX; int z; QChar ch; Attribute *a; x = oldX = z = 0; while (x < xPos) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } if (xPos - oldX < x - xPos && z > 0) { z--; // newXPos = oldX; }// else newXPos = x; return z; } int KateDocument::textWidth() { return int(maxLength + 8); } int KateDocument::textHeight() { return numLines()*fontHeight; } void KateDocument::insert(VConfig &c, const QString &s) { int pos; QChar ch; QString buf; if (s.isEmpty()) return; recordStart(c, KateActionGroup::ugPaste); pos = 0; if (!(c.flags & KateView::cfVerticalSelect)) { do { ch = s[pos]; if (ch.isPrint() || ch == '\t') { buf += ch; // append char to buffer } else if (ch == '\n') { recordAction(KateAction::newLine, c.cursor); // wrap contents behind cursor to new line recordInsert(c, buf); // append to old line // c.cursor.x += buf.length(); buf.truncate(0); // clear buffer c.cursor.y++; c.cursor.x = 0; } pos++; } while (pos < (int) s.length()); } else { int xPos; xPos = textWidth(c.cursor); do { ch = s[pos]; if (ch.isPrint() || ch == '\t') { buf += ch; } else if (ch == '\n') { recordInsert(c, buf); c.cursor.x += buf.length(); buf.truncate(0); c.cursor.y++; if (c.cursor.y >= numLines()) recordAction(KateAction::insLine, c.cursor); c.cursor.x = textPos(getTextLine(c.cursor.y), xPos); } pos++; } while (pos < (int) s.length()); } recordInsert(c, buf); c.cursor.x += buf.length(); recordEnd(c); } void KateDocument::insertFile(VConfig &c, QIODevice &dev) { recordStart(c, KateActionGroup::ugPaste); QString buf; QChar ch, last; QTextStream stream( &dev ); while ( !stream.atEnd() ) { stream >> ch; if (ch.isPrint() || ch == '\t') { buf += ch; } else if (ch == '\n' || ch == '\r') { if (last != '\r' || ch != '\n') { recordAction(KateAction::newLine, c.cursor); recordInsert(c, buf); buf.truncate(0); c.cursor.y++; c.cursor.x = 0; } last = ch; } } recordInsert(c, buf); recordEnd(c); } int KateDocument::currentColumn(PointStruc &cursor) { return getTextLine(cursor.y)->cursorX(cursor.x,tabChars); } bool KateDocument::insertChars(VConfig &c, const QString &chars) { int z, pos, l; bool onlySpaces; QChar ch; QString buf; TextLine::Ptr textLine = getTextLine(c.cursor.y); pos = 0; onlySpaces = true; for (z = 0; z < (int) chars.length(); z++) { ch = chars[z]; if (ch == '\t' && c.flags & KateView::cfReplaceTabs) { l = tabChars - (textLine->cursorX(c.cursor.x, tabChars) % tabChars); while (l > 0) { buf.insert(pos, ' '); pos++; l--; } } else if (ch.isPrint() || ch == '\t') { buf.insert(pos, ch); pos++; if (ch != ' ') onlySpaces = false; if (c.flags & KateView::cfAutoBrackets) { if (ch == '(') buf.insert(pos, ')'); if (ch == '[') buf.insert(pos, ']'); if (ch == '{') buf.insert(pos, '}'); } } } //pos = cursor increment //return false if nothing has to be inserted if (buf.isEmpty()) return false; //auto deletion of the marked text occurs not very often and can therefore // be recorded separately if (c.flags &KateView:: cfDelOnInput) delMarkedText(c); recordStart(c, KateActionGroup::ugInsChar); recordReplace(c/*.cursor*/, (c.flags & KateView::cfOvr) ? buf.length() : 0, buf); c.cursor.x += pos; if (myWordWrap && myWordWrapAt > 0) { int line; const QChar *s; // int pos; PointStruc actionCursor; line = c.cursor.y; do { textLine = getTextLine(line); s = textLine->getText(); l = textLine->length(); for (z = myWordWrapAt; z < l; z++) if (!s[z].isSpace()) break; //search for text to wrap if (z >= l) break; // nothing more to wrap pos = myWordWrapAt; for (; z >= 0; z--) { //find wrap position if (s[z].isSpace()) { pos = z + 1; break; } } //pos = wrap position if (line == c.cursor.y && pos <= c.cursor.x) { //wrap cursor c.cursor.y++; c.cursor.x -= pos; } if (line == lastLine() || (getTextLine(line+1)->length() == 0) ) { //at end of doc: create new line actionCursor.x = pos; actionCursor.y = line; recordAction(KateAction::newLine,actionCursor); } else { //wrap actionCursor.y = line + 1; if (!s[l - 1].isSpace()) { //add space in next line if necessary actionCursor.x = 0; recordInsert(actionCursor, " "); } actionCursor.x = textLine->length() - pos; recordAction(KateAction::wordWrap, actionCursor); } line++; } while (true); } recordEnd(c); return true; } QString tabString(int pos, int tabChars) { QString s; while (pos >= tabChars) { s += '\t'; pos -= tabChars; } while (pos > 0) { s += ' '; pos--; } return s; } void KateDocument::newLine(VConfig &c) { //auto deletion of marked text is done by the view to have a more // "low level" KateDocument::newLine method recordStart(c, KateActionGroup::ugInsLine); if (!(c.flags & KateView::cfAutoIndent)) { recordAction(KateAction::newLine,c.cursor); c.cursor.y++; c.cursor.x = 0; } else { TextLine::Ptr textLine = getTextLine(c.cursor.y); int pos = textLine->firstChar(); if (c.cursor.x < pos) c.cursor.x = pos; // place cursor on first char if before int y = c.cursor.y; while ((y > 0) && (pos < 0)) { // search a not empty text line textLine = getTextLine(--y); pos = textLine->firstChar(); } recordAction(KateAction::newLine, c.cursor); c.cursor.y++; c.cursor.x = 0; if (pos > 0) { pos = textLine->cursorX(pos, tabChars); // if (getTextLine(c.cursor.y)->length() > 0) { QString s = tabString(pos, (c.flags & KateView::cfSpaceIndent) ? 0xffffff : tabChars); recordInsert(c.cursor, s); pos = s.length(); // } // recordInsert(c.cursor, QString(textLine->getText(), pos)); c.cursor.x = pos; } } recordEnd(c); } void KateDocument::killLine(VConfig &c) { recordStart(c, KateActionGroup::ugDelLine); c.cursor.x = 0; recordDelete(c.cursor, 0xffffff); if (c.cursor.y < lastLine()) { recordAction(KateAction::killLine, c.cursor); } recordEnd(c); } void KateDocument::backspace(VConfig &c) { if (c.cursor.x <= 0 && c.cursor.y <= 0) return; if (c.cursor.x > 0) { recordStart(c, KateActionGroup::ugDelChar); if (!(c.flags & KateView::cfBackspaceIndents)) { // ordinary backspace c.cursor.x--; recordDelete(c.cursor, 1); } else { // backspace indents: erase to next indent position int l = 1; // del one char TextLine::Ptr textLine = getTextLine(c.cursor.y); int pos = textLine->firstChar(); if (pos < 0 || pos >= c.cursor.x) { // only spaces on left side of cursor // search a line with less spaces int y = c.cursor.y; while (y > 0) { textLine = getTextLine(--y); pos = textLine->firstChar(); if (pos >= 0 && pos < c.cursor.x) { l = c.cursor.x - pos; // del more chars break; } } } // break effectively jumps here c.cursor.x -= l; recordDelete(c.cursor, l); } } else { // c.cursor.x == 0: wrap to previous line recordStart(c, KateActionGroup::ugDelLine); c.cursor.y--; c.cursor.x = getTextLine(c.cursor.y)->length(); recordAction(KateAction::delLine,c.cursor); } recordEnd(c); } void KateDocument::del(VConfig &c) { TextLine::Ptr textLine = getTextLine(c.cursor.y); int len = (c.flags & KateView::cfRemoveSpaces) ? textLine->lastChar() : textLine->length(); if (c.cursor.x < len/*getTextLine(c.cursor.y)->length()*/) { // delete one character recordStart(c, KateActionGroup::ugDelChar); recordDelete(c.cursor, 1); recordEnd(c); } else { if (c.cursor.y < lastLine()) { // wrap next line to this line textLine->truncate(c.cursor.x); // truncate spaces recordStart(c, KateActionGroup::ugDelLine); recordAction(KateAction::delLine,c.cursor); recordEnd(c); } } } void KateDocument::clear() { PointStruc cursor; KateView *view; setPseudoModal(0L); cursor.x = cursor.y = 0; for (view = views.first(); view != 0L; view = views.next() ) { view->updateCursor(cursor); view->tagAll(); } eolMode = KateDocument::eolUnix; buffer->clear(); longestLine = buffer->line(0); maxLength = 0; select.x = -1; selectStart = 0xffffff; selectEnd = 0; oldMarkState = false; setModified(false); undoList.clear(); currentUndo = 0; newUndo(); } void KateDocument::cut(VConfig &c) { if (selectEnd < selectStart) return; copy(c.flags); delMarkedText(c); } void KateDocument::copy(int flags) { if (selectEnd < selectStart) return; QString s = markedText(flags); if (!s.isEmpty()) { //#if defined(_WS_X11_) if (m_singleSelection) disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, 0); //#endif QApplication::clipboard()->setText(s); //#if defined(_WS_X11_) if (m_singleSelection) { connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged())); } //#endif } } void KateDocument::paste(VConfig &c) { QString s = QApplication::clipboard()->text(); if (!s.isEmpty()) { insert(c, s); } } void KateDocument::toggleRect(int start, int end, int x1, int x2) { int z, line; bool t; if (x1 > x2) { z = x1; x1 = x2; x2 = z; } if (start > end) { z = start; start = end; end = z; } t = false; for (line = start; line < end; line++) { int x, oldX, s, e, newX1, newX2; QChar ch; Attribute *a; TextLine::Ptr textLine = getTextLine(line); //--- speed optimization //s = textPos(textLine, x1, newX1); x = oldX = z = 0; while (x < x1) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } s = z; if (x1 - oldX < x - x1 && z > 0) { s--; newX1 = oldX; } else newX1 = x; //e = textPos(textLine, x2, newX2); while (x < x2) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } e = z; if (x2 - oldX < x - x2 && z > 0) { e--; newX2 = oldX; } else newX2 = x; //--- if (e > s) { textLine->toggleSelect(s, e); tagLineRange(line, newX1, newX2); t = true; } } if (t) { end--; // tagLines(start, end); if (start < selectStart) selectStart = start; if (end > selectEnd) selectEnd = end; emit selectionChanged(); } } void KateDocument::selectTo(VConfig &c, PointStruc &cursor, int cXPos) { //c.cursor = old cursor position //cursor = new cursor position if (c.cursor.x != select.x || c.cursor.y != select.y) { //new selection if (!(c.flags & KateView::cfKeepSelection)) deselectAll(); // else recordReset(); anchor = c.cursor; aXPos = c.cXPos; } if (!(c.flags & KateView::cfVerticalSelect)) { //horizontal selections int x, y, sXPos; int ex, ey, eXPos; bool sel; if (cursor.y > c.cursor.y || (cursor.y == c.cursor.y && cursor.x > c.cursor.x)) { x = c.cursor.x; y = c.cursor.y; sXPos = c.cXPos; ex = cursor.x; ey = cursor.y; eXPos = cXPos; sel = true; } else { x = cursor.x; y = cursor.y; sXPos = cXPos; ex = c.cursor.x; ey = c.cursor.y; eXPos = c.cXPos; sel = false; } // tagLines(y, ye); if (y < ey) { //tagLineRange(y, sXPos, 0xffffff); tagLines(y, ey -1); tagLineRange(ey, 0, eXPos); } else tagLineRange(y, sXPos, eXPos); if (y < selectStart) selectStart = y; if (ey > selectEnd) selectEnd = ey; TextLine::Ptr textLine = getTextLine(y); if (c.flags & KateView::cfXorSelect) { //xor selection with old selection while (y < ey) { textLine->toggleSelectEol(x); x = 0; y++; textLine = getTextLine(y); } textLine->toggleSelect(x, ex); } else { //set selection over old selection if (anchor.y > y || (anchor.y == y && anchor.x > x)) { if (anchor.y < ey || (anchor.y == ey && anchor.x < ex)) { sel = !sel; while (y < anchor.y) { textLine->selectEol(sel, x); x = 0; y++; textLine = getTextLine(y); } textLine->select(sel, x, anchor.x); x = anchor.x; } sel = !sel; } while (y < ey) { textLine->selectEol(sel, x); x = 0; y++; textLine = getTextLine(y); } textLine->select(sel, x, ex); } } else { //vertical (block) selections // int ax, sx, ex; // ax = textWidth(anchor); // sx = textWidth(start); // ex = textWidth(end); toggleRect(c.cursor.y + 1, cursor.y + 1, aXPos, c.cXPos); toggleRect(anchor.y, cursor.y + 1, c.cXPos, cXPos); } select = cursor; optimizeSelection(); emit selectionChanged(); } void KateDocument::selectAll() { int z; TextLine::Ptr textLine; select.x = -1; // if (selectStart != 0 || selectEnd != lastLine()) recordReset(); selectStart = 0; selectEnd = lastLine(); tagLines(selectStart,selectEnd); for (z = selectStart; z < selectEnd; z++) { textLine = getTextLine(z); textLine->selectEol(true,0); } textLine = getTextLine(z); textLine->select(true,0,textLine->length()); emit selectionChanged(); } void KateDocument::deselectAll() { select.x = -1; if (selectEnd < selectStart) return; // recordReset(); tagLines(selectStart,selectEnd); for (int z = selectStart; z <= selectEnd; z++) { TextLine::Ptr textLine = getTextLine(z); textLine->selectEol(false,0); } selectStart = 0xffffff; selectEnd = 0; emit selectionChanged(); } void KateDocument::invertSelection() { TextLine::Ptr textLine; select.x = -1; // if (selectStart != 0 || selectEnd != lastLine()) recordReset(); selectStart = 0; selectEnd = lastLine(); tagLines(selectStart,selectEnd); for (int z = selectStart; z < selectEnd; z++) { textLine = getTextLine(z); textLine->toggleSelectEol(0); } textLine = getTextLine(selectEnd); textLine->toggleSelect(0,textLine->length()); optimizeSelection(); emit selectionChanged(); } void KateDocument::selectWord(PointStruc &cursor, int flags) { int start, end, len; TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); start = end = cursor.x; while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; if (end <= start) return; if (!(flags & KateView::cfKeepSelection)) deselectAll(); // else recordReset(); textLine->select(true, start, end); anchor.x = start; select.x = end; anchor.y = select.y = cursor.y; tagLines(cursor.y, cursor.y); if (cursor.y < selectStart) selectStart = cursor.y; if (cursor.y > selectEnd) selectEnd = cursor.y; emit selectionChanged(); } void KateDocument::selectLength(PointStruc &cursor, int length, int flags) { int start, end; TextLine::Ptr textLine = getTextLine(cursor.y); start = cursor.x; end = start + length; if (end <= start) return; if (!(flags & KateView::cfKeepSelection)) deselectAll(); textLine->select(true, start, end); anchor.x = start; select.x = end; anchor.y = select.y = cursor.y; tagLines(cursor.y, cursor.y); if (cursor.y < selectStart) selectStart = cursor.y; if (cursor.y > selectEnd) selectEnd = cursor.y; emit selectionChanged(); } void KateDocument::doIndent(VConfig &c, int change) { c.cursor.x = 0; recordStart(c, (change < 0) ? KateActionGroup::ugUnindent : KateActionGroup::ugIndent); if (selectEnd < selectStart) { // single line optimizeLeadingSpace(c.cursor.y, c.flags, change); } else { // entire selection TextLine::Ptr textLine; int line, z; QChar ch; if (c.flags & KateView::cfKeepIndentProfile && change < 0) { // unindent so that the existing indent profile doesn´t get screwed // if any line we may unindent is already full left, don't do anything for (line = selectStart; line <= selectEnd; line++) { textLine = getTextLine(line); if (textLine->isSelected() || textLine->numSelected()) { for (z = 0; z < tabChars; z++) { ch = textLine->getChar(z); if (ch == '\t') break; if (ch != ' ') { change = 0; goto jumpOut; } } } } jumpOut:; } for (line = selectStart; line <= selectEnd; line++) { textLine = getTextLine(line); if (textLine->isSelected() || textLine->numSelected()) { optimizeLeadingSpace(line, c.flags, change); } } } // recordEnd now removes empty undo records recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); } /* Optimize the leading whitespace for a single line. If change is > 0, it adds indentation units (tabChars) if change is == 0, it only optimizes If change is < 0, it removes indentation units This will be used to indent, unindent, and optimal-fill a line. If excess space is removed depends on the flag cfKeepExtraSpaces which has to be set by the user */ void KateDocument::optimizeLeadingSpace(int line, int flags, int change) { int len; int chars, space, okLen; QChar ch; int extra; QString s; PointStruc cursor; TextLine::Ptr textLine = getTextLine(line); len = textLine->length(); space = 0; // length of space at the beginning of the textline okLen = 0; // length of space which does not have to be replaced for (chars = 0; chars < len; chars++) { ch = textLine->getChar(chars); if (ch == ' ') { space++; if (flags & KateView::cfSpaceIndent && okLen == chars) okLen++; } else if (ch == '\t') { space += tabChars - space % tabChars; if (!(flags & KateView::cfSpaceIndent) && okLen == chars) okLen++; } else break; } space += change*tabChars; // modify space width // if line contains only spaces it will be cleared if (space < 0 || chars == len) space = 0; extra = space % tabChars; // extra spaces which don´t fit the indentation pattern if (flags & KateView::cfKeepExtraSpaces) chars -= extra; if (flags & KateView::cfSpaceIndent) { space -= extra; ch = ' '; } else { space /= tabChars; ch = '\t'; } // don´t replace chars which are already ok cursor.x = QMIN(okLen, QMIN(chars, space)); chars -= cursor.x; space -= cursor.x; if (chars == 0 && space == 0) return; //nothing to do s.fill(ch, space); //printf("chars %d insert %d cursor.x %d\n", chars, insert, cursor.x); cursor.y = line; recordReplace(cursor, chars, s); } void KateDocument::doComment(VConfig &c, int change) { c.flags |=KateView:: cfPersistent; recordStart(c, (change < 0) ? KateActionGroup::ugUncomment : KateActionGroup::ugComment); QString startComment = m_highlight->getCommentStart(); QString startLineComment = m_highlight->getCommentSingleLineStart(); QString endComment = m_highlight->getCommentEnd(); int startCommentLen = startComment.length(); int startLineCommentLen = startLineComment.length(); int endCommentLen = endComment.length(); if (change > 0) { if ( !hasMarkedText() ) { if (startLineComment != "") { // Add a start comment mark c.cursor.x = 0; recordReplace(c.cursor, 0, startLineComment); } else if ((startComment != "") && (endComment != "")) { // Add a start comment mark c.cursor.x = 0; recordReplace(c.cursor, 0, startComment); // Add an end comment mark TextLine* textline = getTextLine(c.cursor.y); c.cursor.x = textline->length(); recordReplace(c.cursor, 0, endComment); c.cursor.x = 0; } } else if ((startComment != "") && (endComment != "")) { QString marked (c.view->markedText ()); int preDeleteLine = -1, preDeleteCol = -1; c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); if (marked.length() > 0) c.view->keyDelete (); int line = -1, col = -1; c.view->getCursorPosition (&line, &col); c.view->insertText (startComment + marked + endComment); } } else { if ( !hasMarkedText() ) { TextLine* textline = getTextLine(c.cursor.y); if(textline->startingWith(startLineComment)) { // Remove start comment mark c.cursor.x = 0; recordReplace(c.cursor, startLineCommentLen, ""); } else if (textline->startingWith(startComment) && textline->endingWith(endComment)) { // Remove start comment mark c.cursor.x = 0; recordReplace(c.cursor, startCommentLen, ""); // Remove end comment mark if(endComment != "") { c.cursor.x = textline->length() - endCommentLen; recordReplace(c.cursor, endCommentLen, ""); c.cursor.x = 0; } } } else { QString marked (c.view->markedText ()); int preDeleteLine = -1, preDeleteCol = -1; c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); int start = marked.find (startComment); int end = marked.findRev (endComment); if ((start > -1) && (end > -1)) { marked.remove (start, startCommentLen); marked.remove (end-startCommentLen, endCommentLen); c.view->keyDelete (); int line = -1, col = -1; c.view->getCursorPosition (&line, &col); c.view->insertText (marked); } } } recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); } QString KateDocument::text() const { QString s; for (int i=0; i < buffer->count(); i++) { TextLine::Ptr textLine = buffer->line(i); s.insert(s.length(), textLine->getText(), textLine->length()); if ( (i < (buffer->count()-1)) ) s.append('\n'); } return s; } QString KateDocument::getWord(PointStruc &cursor) { int start, end, len; TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); start = end = cursor.x; while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; len = end - start; return QString(&textLine->getText()[start], len); } void KateDocument::setText(const QString &s) { int pos; QChar ch; clear(); int line=1; TextLine::Ptr textLine = buffer->line(0); for (pos = 0; pos <= (int) s.length(); pos++) { ch = s[pos]; if (ch.isPrint() || ch == '\t') { textLine->append(&ch, 1); } else if (ch == '\n') { textLine = new TextLine(); buffer->insertLine (line, textLine); line++; } } updateLines(); } QString KateDocument::markedText(int flags) { TextLine::Ptr textLine; int len, z, start, end, i; len = 1; if (!(flags & KateView::cfVerticalSelect)) { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected(); if (textLine->isSelected()) len++; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); if (textLine->isSelected()) { s[len] = '\n'; len++; } } // s[len] = '\0'; return s; } else { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected() + 1; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); s[len] = '\n'; len++; } // s[len] = '\0'; // the final \0 is not counted in length() return s; } } void KateDocument::delMarkedText(VConfig &c/*, bool undo*/) { int end = 0; if (selectEnd < selectStart) return; // the caller may have already started an undo record for the current action // if (undo) //auto deletion of the marked text occurs not very often and can therefore // be recorded separately recordStart(c, KateActionGroup::ugDelBlock); for (c.cursor.y = selectEnd; c.cursor.y >= selectStart; c.cursor.y--) { TextLine::Ptr textLine = getTextLine(c.cursor.y); c.cursor.x = textLine->length(); do { end = textLine->findRevUnselected(c.cursor.x); if (end == 0) break; c.cursor.x = textLine->findRevSelected(end); recordDelete(c.cursor, end - c.cursor.x); } while (true); end = c.cursor.x; c.cursor.x = textLine->length(); if (textLine->isSelected()) recordAction(KateAction::delLine,c.cursor); } c.cursor.y++; /*if (end < c.cursor.x)*/ c.cursor.x = end; selectEnd = -1; select.x = -1; /*if (undo)*/ recordEnd(c); } void KateDocument::tagLineRange(int line, int x1, int x2) { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagLines(line, line, x1, x2); } } void KateDocument::tagLines(int start, int end) { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagLines(start, end, 0, 0xffffff); } } void KateDocument::tagAll() { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagAll(); } } void KateDocument::updateLines(int startLine, int endLine, int flags, int cursorY) { TextLine::Ptr textLine; int line, last_line; int ctxNum, endCtx; // kdDebug(13020)<<"******************KateDocument::updateLines Checkpoint 1"<<endl; if (buffer->line(startLine)==0) {kdDebug(13020)<<"********************No buffer for line " << startLine << " found**************"<<endl; return;}; // kdDebug(13020)<<"KateDocument::updateLines Checkpoint 2"<<endl; last_line = lastLine(); // if (endLine >= last_line) endLine = last_line; line = startLine; ctxNum = 0; if (line > 0) ctxNum = getTextLine(line - 1)->getContext(); do { // kdDebug(13020)<<QString("**************Working on line: %1").arg(line)<<endl; textLine = getTextLine(line); if (textLine==0) kdDebug(13020)<<"****updateLines()>> error textLine==0"<<endl; if (line <= endLine && line != cursorY) { if (flags & KateView::cfRemoveSpaces) textLine->removeSpaces(); updateMaxLength(textLine); } endCtx = textLine->getContext(); // odebug << "DOHIGHLIGHT" << oendl; ctxNum = m_highlight->doHighlight(ctxNum,textLine); textLine->setContext(ctxNum); line++; } while ((buffer->line(line)!=0) && (line <= endLine || endCtx != ctxNum)); // kdDebug(13020)<<"updateLines :: while loop left"<<endl; tagLines(startLine, line - 1); } void KateDocument::updateMaxLength(TextLine::Ptr &textLine) { int len; len = textWidth(textLine,textLine->length()); if (len > maxLength) { longestLine = textLine; maxLength = len; newDocGeometry = true; } else { if (!longestLine || (textLine == longestLine && len <= maxLength*3/4)) { maxLength = -1; for (int i = 0; i < numLines();i++) { textLine = getTextLine(i); len = textWidth(textLine,textLine->length()); if (len > maxLength) { maxLength = len; longestLine = textLine; } } newDocGeometry = true; } } } void KateDocument::slotBufferChanged() { newDocGeometry = true; //updateLines();//JW updateViews(); } void KateDocument::slotBufferHighlight(long start,long stop) { kdDebug(13020)<<"KateDocument::slotBufferHighlight"<<QString("%1-%2").arg(start).arg(stop)<<endl; updateLines(start,stop); // buffer->startLoadTimer(); } void KateDocument::updateViews(KateView *exclude) { KateView *view; int flags; bool markState = hasMarkedText(); flags = (newDocGeometry) ? KateView::ufDocGeometry : 0; for (view = views.first(); view != 0L; view = views.next() ) { if (view != exclude) view->updateView(flags); // notify every view about the changed mark state.... if (oldMarkState != markState) emit view->newMarkStatus(); } oldMarkState = markState; newDocGeometry = false; } QColor &KateDocument::cursorCol(int x, int y) { int attr; Attribute *a; TextLine::Ptr textLine = getTextLine(y); attr = textLine->getRawAttr(x); a = &m_attribs[attr & taAttrMask]; if (attr & taSelected) return a->selCol; else return a->col; } void KateDocument::paintTextLine(QPainter &paint, int line, int xStart, int xEnd, bool showTabs) { paintTextLine (paint, line, 0, xStart, xEnd, showTabs); } void KateDocument::paintTextLine(QPainter &paint, int line, int y, int xStart, int xEnd, bool showTabs) { TextLine::Ptr textLine; int len; const QChar *s; int z, x; QChar ch; Attribute *a = 0L; int attr, nextAttr; int xs; int xc, zc; if (line > lastLine()) { paint.fillRect(0, y, xEnd - xStart,fontHeight, colors[0]); return; } textLine = getTextLine(line); len = textLine->length(); s = textLine->getText(); // skip to first visible character x = 0; z = 0; do { xc = x; zc = z; if (z == len) break; ch = s[z];//textLine->getChar(z); if (ch == '\t') { x += m_tabWidth - (x % m_tabWidth); } else { a = &m_attribs[textLine->getAttr(z)]; if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } z++; } while (x <= xStart); // draw background xs = xStart; attr = textLine->getRawAttr(zc); while (x < xEnd) { nextAttr = textLine->getRawAttr(z); if ((nextAttr ^ attr) & taSelected) { if (attr & taSelected) paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[1]); else paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[0]); xs = x; attr = nextAttr; } if (z == len) break; ch = s[z];//textLine->getChar(z); if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else { a = &m_attribs[textLine->getAttr(z)]; if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } z++; } if (attr & taSelected) paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[1]); else paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[0]); len = z; //reduce length to visible length // draw text x = xc; z = zc; y += fontAscent;// -1; attr = -1; while (z < len) { ch = s[z];//textLine->getChar(z); if (ch == '\t') { if (z > zc) { //this should cause no copy at all QConstString str((QChar *) &s[zc], z - zc /*+1*/); QString s = str.string(); paint.drawText(x - xStart, y, s); if (a->bold && a->italic) x += myFontMetricsBI.width(s); else if (a->bold) x += myFontMetricsBold.width(s); else if (a->italic) x += myFontMetricsItalic.width(s); else x += myFontMetrics.width(s); } zc = z +1; if (showTabs) { nextAttr = textLine->getRawAttr(z); if (nextAttr != attr) { attr = nextAttr; a = &m_attribs[attr & taAttrMask]; if (attr & taSelected) paint.setPen(a->selCol); else paint.setPen(a->col); if (a->bold && a->italic) paint.setFont(myFontBI); else if (a->bold) paint.setFont(myFontBold); else if (a->italic) paint.setFont(myFontItalic); else paint.setFont(myFont); } // paint.drawLine(x - xStart, y -2, x - xStart, y); // paint.drawLine(x - xStart, y, x - xStart + 2, y); paint.drawPoint(x - xStart, y); paint.drawPoint(x - xStart +1, y); paint.drawPoint(x - xStart, y -1); } x += m_tabWidth - (x % m_tabWidth); } else { nextAttr = textLine->getRawAttr(z); if (nextAttr != attr) { if (z > zc) { QConstString str((QChar *) &s[zc], z - zc /*+1*/); QString s = str.string(); paint.drawText(x - xStart, y, s); if (a->bold && a->italic) x += myFontMetricsBI.width(s); else if (a->bold) x += myFontMetricsBold.width(s); else if (a->italic) x += myFontMetricsItalic.width(s); else x += myFontMetrics.width(s); zc = z; } attr = nextAttr; a = &m_attribs[attr & taAttrMask]; if (attr & taSelected) paint.setPen(a->selCol); else paint.setPen(a->col); if (a->bold && a->italic) paint.setFont(myFontBI); else if (a->bold) paint.setFont(myFontBold); else if (a->italic) paint.setFont(myFontItalic); else paint.setFont(myFont); } } z++; } if (z > zc) { QConstString str((QChar *) &s[zc], z - zc /*+1*/); paint.drawText(x - xStart, y, str.string()); } } // Applies the search context, and returns whether a match was found. If one is, // the length of the string matched is also returned. bool KateDocument::doSearch(SConfig &sc, const QString &searchFor) { int line, col; int searchEnd; int bufLen, tlen; QChar *t; TextLine::Ptr textLine; int pos, newPos; if (searchFor.isEmpty()) return false; bufLen = 0; t = 0L; line = sc.cursor.y; col = sc.cursor.x; if (!(sc.flags & KateView::sfBackward)) { //forward search if (sc.flags & KateView::sfSelected) { if (line < selectStart) { line = selectStart; col = 0; } searchEnd = selectEnd; } else searchEnd = lastLine(); while (line <= searchEnd) { textLine = getTextLine(line); tlen = textLine->length(); if (tlen > bufLen) { - delete t; + delete [] t; bufLen = (tlen + 255) & (~255); t = new QChar[bufLen]; } memcpy(t, textLine->getText(), tlen*sizeof(QChar)); if (sc.flags & KateView::sfSelected) { pos = 0; do { pos = textLine->findSelected(pos); newPos = textLine->findUnselected(pos); memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); pos = newPos; } while (pos < tlen); } QString text(t, tlen); if (sc.flags & KateView::sfWholeWords) { // Until the end of the line... while (col < tlen) { // ...find the next match. col = sc.search(text, col); if (col != -1) { // Is the match delimited correctly? if (((col == 0) || (!m_highlight->isInWord(t[col]))) && ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { goto found; } else { // Start again from the next character. col++; } } else { // No match. break; } } } else { // Non-whole-word search. col = sc.search(text, col); if (col != -1) goto found; } col = 0; line++; } } else { // backward search if (sc.flags & KateView::sfSelected) { if (line > selectEnd) { line = selectEnd; col = -1; } searchEnd = selectStart; } else searchEnd = 0; while (line >= searchEnd) { textLine = getTextLine(line); tlen = textLine->length(); if (tlen > bufLen) { - delete t; + delete [] t; bufLen = (tlen + 255) & (~255); t = new QChar[bufLen]; } memcpy(t, textLine->getText(), tlen*sizeof(QChar)); if (sc.flags & KateView::sfSelected) { pos = 0; do { pos = textLine->findSelected(pos); newPos = textLine->findUnselected(pos); memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); pos = newPos; } while (pos < tlen); } if (col < 0 || col > tlen) col = tlen; QString text(t, tlen); if (sc.flags & KateView::sfWholeWords) { // Until the beginning of the line... while (col >= 0) { // ...find the next match. col = sc.search(text, col); if (col != -1) { // Is the match delimited correctly? if (((col == 0) || (!m_highlight->isInWord(t[col]))) && ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { goto found; } else { // Start again from the previous character. col--; } } else { // No match. break; } } } else { // Non-whole-word search. col = sc.search(text, col); if (col != -1) goto found; } col = -1; line--; } } sc.flags |= KateView::sfWrapped; return false; found: if (sc.flags & KateView::sfWrapped) { if ((line > sc.startCursor.y || (line == sc.startCursor.y && col >= sc.startCursor.x)) ^ ((sc.flags & KateView::sfBackward) != 0)) return false; } sc.cursor.x = col; sc.cursor.y = line; return true; } void KateDocument::tagLine(int line) { if (tagStart > line) tagStart = line; if (tagEnd < line) tagEnd = line; } void KateDocument::insLine(int line) { KateView *view; if (selectStart >= line) selectStart++; if (selectEnd >= line) selectEnd++; if (tagStart >= line) tagStart++; if (tagEnd >= line) tagEnd++; newDocGeometry = true; for (view = views.first(); view != 0L; view = views.next() ) { view->insLine(line); } } void KateDocument::delLine(int line) { KateView *view; if (selectStart >= line && selectStart > 0) selectStart--; if (selectEnd >= line) selectEnd--; if (tagStart >= line && tagStart > 0) tagStart--; if (tagEnd >= line) tagEnd--; newDocGeometry = true; for (view = views.first(); view != 0L; view = views.next() ) { view->delLine(line); } } void KateDocument::optimizeSelection() { TextLine::Ptr textLine; while (selectStart <= selectEnd) { textLine = getTextLine(selectStart); if (textLine->isSelected() || textLine->numSelected() > 0) break; selectStart++; } while (selectEnd >= selectStart) { textLine = getTextLine(selectEnd); if (textLine->isSelected() || textLine->numSelected() > 0) break; selectEnd--; } if (selectStart > selectEnd) { selectStart = 0xffffff; selectEnd = 0; } } void KateDocument::doAction(KateAction *a) { switch (a->action) { case KateAction::replace: doReplace(a); break; case KateAction::wordWrap: doWordWrap(a); break; case KateAction::wordUnWrap: doWordUnWrap(a); break; case KateAction::newLine: doNewLine(a); break; case KateAction::delLine: doDelLine(a); break; case KateAction::insLine: doInsLine(a); break; case KateAction::killLine: doKillLine(a); break; /* case KateAction::doubleLine: break; case KateAction::removeLine: break;*/ } } void KateDocument::doReplace(KateAction *a) { TextLine::Ptr textLine; int l; //exchange current text with stored text in KateAction *a textLine = getTextLine(a->cursor.y); l = textLine->length() - a->cursor.x; if (l > a->len) l = a->len; QString oldText(&textLine->getText()[a->cursor.x], (l < 0) ? 0 : l); textLine->replace(a->cursor.x, a->len, a->text.unicode(), a->text.length()); a->len = a->text.length(); a->text = oldText; buffer->changeLine(a->cursor.y); tagLine(a->cursor.y); } void KateDocument::doWordWrap(KateAction *a) { TextLine::Ptr textLine; textLine = getTextLine(a->cursor.y - 1); a->len = textLine->length() - a->cursor.x; textLine->wrap(getTextLine(a->cursor.y),a->len); buffer->changeLine(a->cursor.y - 1); buffer->changeLine(a->cursor.y); tagLine(a->cursor.y - 1); tagLine(a->cursor.y); if (selectEnd == a->cursor.y - 1) selectEnd++; a->action = KateAction::wordUnWrap; } void KateDocument::doWordUnWrap(KateAction *a) { TextLine::Ptr textLine; textLine = getTextLine(a->cursor.y - 1); // textLine->setLength(a->len); textLine->unWrap(a->len, getTextLine(a->cursor.y),a->cursor.x); buffer->changeLine(a->cursor.y - 1); buffer->changeLine(a->cursor.y); tagLine(a->cursor.y - 1); tagLine(a->cursor.y); a->action = KateAction::wordWrap; } void KateDocument::doNewLine(KateAction *a) { TextLine::Ptr textLine, newLine; textLine = getTextLine(a->cursor.y); newLine = new TextLine(textLine->getRawAttr(), textLine->getContext()); textLine->wrap(newLine,a->cursor.x); buffer->insertLine(a->cursor.y + 1, newLine); buffer->changeLine(a->cursor.y); insLine(a->cursor.y + 1); tagLine(a->cursor.y); tagLine(a->cursor.y + 1); if (selectEnd == a->cursor.y) selectEnd++;//addSelection(a->cursor.y + 1); a->action = KateAction::delLine; } void KateDocument::doDelLine(KateAction *a) { TextLine::Ptr textLine, nextLine; textLine = getTextLine(a->cursor.y); nextLine = getTextLine(a->cursor.y+1); // textLine->setLength(a->cursor.x); textLine->unWrap(a->cursor.x, nextLine,nextLine->length()); textLine->setContext(nextLine->getContext()); if (longestLine == nextLine) longestLine = 0L; buffer->changeLine(a->cursor.y); buffer->removeLine(a->cursor.y+1); tagLine(a->cursor.y); delLine(a->cursor.y + 1); a->action = KateAction::newLine; } void KateDocument::doInsLine(KateAction *a) { buffer->insertLine(a->cursor.y, new TextLine()); insLine(a->cursor.y); a->action = KateAction::killLine; } void KateDocument::doKillLine(KateAction *a) { TextLine::Ptr textLine = getTextLine(a->cursor.y); if (longestLine == textLine) longestLine = 0L; buffer->removeLine(a->cursor.y); delLine(a->cursor.y); tagLine(a->cursor.y); a->action = KateAction::insLine; } void KateDocument::newUndo() { KTextEditor::View *view; int state; state = 0; if (currentUndo > 0) state |= 1; if (currentUndo < (int) undoList.count()) state |= 2; undoState = state; for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newUndo(); } } void KateDocument::recordStart(VConfig &c, int newUndoType) { recordStart(c.view, c.cursor, c.flags, newUndoType); } void KateDocument::recordStart(KateView *, PointStruc &cursor, int flags, int newUndoType, bool keepModal, bool mergeUndo) { KateActionGroup *g; // if (newUndoType == KateActionGroup::ugNone) { // only a bug would cause this //why should someone do this? we can't prevent all programming errors :) (jochen whilhelmy) // debug("KateDocument::recordStart() called with no undo group type!"); // return; // } if (!keepModal) setPseudoModal(0L); //i optimized the group undo stuff a bit (jochen wilhelmy) // recordReset() is not needed any more g = undoList.getLast(); if (g != 0L && ((undoCount < 1024 && flags & KateView::cfGroupUndo && g->end.x == cursor.x && g->end.y == cursor.y) || mergeUndo)) { //undo grouping : same actions are put into one undo step //precondition : new action starts where old stops or mergeUndo flag if (g->undoType == newUndoType || (g->undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) || (g->undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine)) { undoCount++; if (g->undoType != newUndoType) undoCount = 0xffffff; return; } } undoCount = 0; /* if (undoView != view) { // always kill the current undo group if the editing view changes recordReset(); undoType = newUndoType; } else if (newUndoType == undoType) { printf("bla!!!\n"); // same as current type, keep using it return; } else if ( (undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) || (undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine) ) { // some type combinations can run together... undoType += 1000; return; } else { recordReset(); undoType = newUndoType; } undoView = view; */ while ((int) undoList.count() > currentUndo) undoList.removeLast(); while ((int) undoList.count() > undoSteps) { undoList.removeFirst(); currentUndo--; } g = new KateActionGroup(cursor, newUndoType); undoList.append(g); // currentUndo++; tagEnd = 0; tagStart = 0xffffff; } void KateDocument::recordAction(KateAction::Action action, PointStruc &cursor) { KateAction *a; a = new KateAction(action, cursor); doAction(a); undoList.getLast()->insertAction(a); } void KateDocument::recordInsert(VConfig &c, const QString &text) { recordReplace(c, 0, text); } void KateDocument::recordReplace(VConfig &c, int len, const QString &text) { if (c.cursor.x > 0 && !(c.flags & KateView::cfSpaceIndent)) { TextLine::Ptr textLine = getTextLine(c.cursor.y); if (textLine->length() == 0) { QString s = tabString(c.cursor.x, tabChars); int len = s.length(); s += text; c.cursor.x = 0; recordReplace(c.cursor, len, s); c.cursor.x = len; return; } } recordReplace(c.cursor, len, text); } void KateDocument::recordInsert(PointStruc &cursor, const QString &text) { recordReplace(cursor, 0, text); } void KateDocument::recordDelete(PointStruc &cursor, int len) { recordReplace(cursor, len, QString::null); } void KateDocument::recordReplace(PointStruc &cursor, int len, const QString &text) { KateAction *a; TextLine::Ptr textLine; int l; if (len == 0 && text.isEmpty()) return; //try to append to last replace action a = undoList.getLast()->action; if (a == 0L || a->action != KateAction::replace || a->cursor.x + a->len != cursor.x || a->cursor.y != cursor.y) { //if (a != 0L) printf("new %d %d\n", a->cursor.x + a->len, cursor.x); a = new KateAction(KateAction::replace, cursor); undoList.getLast()->insertAction(a); } //replace textLine = getTextLine(cursor.y); l = textLine->length() - cursor.x; if (l > len) l = len; a->text.insert(a->text.length(), &textLine->getText()[cursor.x], (l < 0) ? 0 : l); textLine->replace(cursor.x, len, text.unicode(), text.length()); a->len += text.length(); buffer->changeLine(a->cursor.y); updateMaxLength(textLine); tagLine(a->cursor.y); } void KateDocument::recordEnd(VConfig &c) { recordEnd(c.view, c.cursor, c.flags); } void KateDocument::recordEnd(KateView *view, PointStruc &cursor, int flags) { KateActionGroup *g; // clear selection if option "persistent selections" is off // if (!(flags & cfPersistent)) deselectAll(); g = undoList.getLast(); if (g->action == 0L) { // no action has been done: remove empty undo record undoList.removeLast(); return; } // store end cursor position for redo g->end = cursor; currentUndo = undoList.count(); if (tagStart <= tagEnd) { optimizeSelection(); updateLines(tagStart, tagEnd, flags, cursor.y); setModified(true); } view->updateCursor(cursor, flags); // newUndo(); /* undoCount++; // we limit the number of individual undo operations for sanity - is 1K reasonable? // this is also where we handle non-group undo preference // if the undo type is singlular, we always finish it now if ( undoType == KateActionGroup::ugPaste || undoType == KateActionGroup::ugDelBlock || undoType > 1000 || undoCount > 1024 || !(flags & cfGroupUndo) ) { printf("recordend %d %d\n", undoType, undoCount); recordReset(); } */ // this should keep the flood of signals down a little... if (undoCount == 0) newUndo(); emit textChanged(); } /* void KateDocument::recordReset() { if (pseudoModal) return; // forces the next call of recordStart() to begin a new undo group // not used in normal editing, but used by markFound(), etc. undoType = KateActionGroup::ugNone; undoCount = 0; undoView = NULL; undoReported = false; printf("recordreset\n"); } */ /* void KateDocument::recordDel(PointStruc &cursor, TextLine::Ptr &textLine, int l) { int len; len = textLine->length() - cursor.x; if (len > l) len = l; if (len > 0) { insertUndo(new KateAction(KateAction::replace,cursor,&textLine->getText()[cursor.x],len)); } } */ void KateDocument::doActionGroup(KateActionGroup *g, int flags, bool undo) { KateAction *a, *next; setPseudoModal(0L); if (!(flags & KateView::cfPersistent)) deselectAll(); tagEnd = 0; tagStart = 0xffffff; a = g->action; g->action = 0L; while (a) { doAction(a); next = a->next; g->insertAction(a); a = next; } optimizeSelection(); if (tagStart <= tagEnd) updateLines(tagStart, tagEnd, flags); // the undo/redo functions set undo to true, all others should leave it // alone (default) if (!undo) { setModified(true); newUndo(); } } int KateDocument::nextUndoType() { KateActionGroup *g; if (currentUndo <= 0) return KateActionGroup::ugNone; g = undoList.at(currentUndo - 1); return g->undoType; } int KateDocument::nextRedoType() { KateActionGroup *g; if (currentUndo >= (int) undoList.count()) return KateActionGroup::ugNone; g = undoList.at(currentUndo); // if (!g) return KateActionGroup::ugNone; return g->undoType; } void KateDocument::undoTypeList(QValueList<int> &lst) { lst.clear(); for (int i = currentUndo-1; i>=0 ;i--) lst.append(undoList.at(i)->undoType); } void KateDocument::redoTypeList(QValueList<int> &lst) { lst.clear(); for (int i = currentUndo+1; i<(int)undoList.count(); i++) lst.append(undoList.at(i)->undoType); } void KateDocument::undo(VConfig &c, int count) { KateActionGroup *g = 0L; int num; bool needUpdate = false; // don't update the cursor until completely done if (count <= 0) return; for (num = 0 ; num < count ; num++) { if (currentUndo <= 0) break; currentUndo--; g = undoList.at(currentUndo); doActionGroup(g, c.flags, true); // do not setModified() or newUndo() needUpdate = true; // if (num == 0) recordReset(); } if (needUpdate) { // since we told doActionGroup() not to do this stuff, we need to do it now c.view->updateCursor(g->start); setModified(true); newUndo(); } } void KateDocument::redo(VConfig &c, int count) { KateActionGroup *g = 0L; int num; bool needUpdate = false; // don't update the cursor until completely done if (count <= 0) return; for (num = 0 ; num < count ; num++) { if (currentUndo+1 > (int)undoList.count()) break; g = undoList.at(currentUndo); currentUndo++; doActionGroup(g, c.flags, true); // do not setModified() or newUndo() needUpdate = true; // if (num == 0) recordReset(); } if (needUpdate) { // since we told doActionGroup() not to do this stuff, we need to do it now c.view->updateCursor(g->end); setModified(true); newUndo(); } } void KateDocument::clearRedo() { // disable redos // this was added as an assist to the spell checker bool deleted = false; while ((int) undoList.count() > currentUndo) { deleted = true; undoList.removeLast(); } if (deleted) newUndo(); } void KateDocument::setUndoSteps(int steps) { if (steps < 5) steps = 5; undoSteps = steps; } void KateDocument::setPseudoModal(QWidget *w) { // QWidget *old = pseudoModal; // (glenebob) // this is a temporary hack to make the spell checker work a little // better - as kspell progresses, this sort of thing should become // obsolete or worked around more cleanly // this is relied upon *only* by the spell-check code if (pseudoModal && pseudoModal != (QWidget*)1L) delete pseudoModal; // pseudoModal = 0L; // if (old || w) recordReset(); pseudoModal = w; } void KateDocument::newBracketMark(PointStruc &cursor, BracketMark &bm) { TextLine::Ptr textLine; int x, line, count, attr; QChar bracket, opposite, ch; Attribute *a; bm.eXPos = -1; //mark bracked mark as invalid x = cursor.x -1; // -1 to look at left side of cursor if (x < 0) return; line = cursor.y; //current line count = 0; //bracket counter for nested brackets textLine = getTextLine(line); if (!textLine) return; bracket = textLine->getChar(x); attr = textLine->getAttr(x); if (bracket == '(' || bracket == '[' || bracket == '{') { //get opposite bracket opposite = ')'; if (bracket == '[') opposite = ']'; if (bracket == '{') opposite = '}'; //get attribute of bracket (opposite bracket must have the same attribute) x++; while (line - cursor.y < 40) { //go to next line on end of line while (x >= (int) textLine->length()) { line++; if (line > lastLine()) return; textLine = getTextLine(line); x = 0; } if (textLine->getAttr(x) == attr) { //try to find opposite bracked ch = textLine->getChar(x); if (ch == bracket) count++; //same bracket : increase counter if (ch == opposite) { count--; if (count < 0) goto found; } } x++; } } else if (bracket == ')' || bracket == ']' || bracket == '}') { opposite = '('; if (bracket == ']') opposite = '['; if (bracket == '}') opposite = '{'; x--; while (cursor.y - line < 20) { while (x < 0) { line--; if (line < 0) return; textLine = getTextLine(line); x = textLine->length() -1; } if (textLine->getAttr(x) == attr) { ch = textLine->getChar(x); if (ch == bracket) count++; if (ch == opposite) { count--; if (count < 0) goto found; } } x--; } } return; found: //cursor position of opposite bracket bm.cursor.x = x; bm.cursor.y = line; //x position (start and end) of related bracket bm.sXPos = textWidth(textLine, x); a = &m_attribs[attr]; if (a->bold && a->italic) bm.eXPos = bm.sXPos + myFontMetricsBI.width(bracket); else if (a->bold) bm.eXPos = bm.sXPos + myFontMetricsBold.width(bracket); else if (a->italic) bm.eXPos = bm.sXPos + myFontMetricsItalic.width(bracket); else bm.eXPos = bm.sXPos + myFontMetrics.width(bracket); } void KateDocument::clipboardChanged() { //slot //#if defined(_WS_X11_) if (m_singleSelection) { disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged())); deselectAll(); updateViews(); } //#endif } #if 0 void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev ) { KParts::ReadWritePart::guiActivateEvent( ev ); if ( ev->activated() ) emit selectionChanged(); } #endif void KateDocument::setDocName (QString docName) { myDocName = docName; emit nameChanged (this); } void KateDocument::setDocFile (QString docFile) { m_file = docFile; emit fileNameChanged (); } void KateDocument::setMTime() { if (fileInfo && !fileInfo->fileName().isEmpty()) { fileInfo->refresh(); mTime = fileInfo->lastModified(); } } void KateDocument::isModOnHD(bool forceReload) { if (fileInfo && !fileInfo->fileName().isEmpty()) { fileInfo->refresh(); if (fileInfo->lastModified() > mTime) { if ( forceReload || (KMessageBox::warningContinueCancel(0, (i18n("The file %1 has changed on disk.\nDo you want to reload it?\n\nIf you cancel you will lose these changes next time you save this file")).arg(m_url), i18n("File has changed on Disk"), i18n("Yes") ) == KMessageBox::Continue) ) reloadFile(); else setMTime(); } } } void KateDocument::reloadFile() { #warning fixme #if 0 if (fileInfo && !fileInfo->fileName().isEmpty()) { KateDocument::openFile(); setMTime(); } #endif } void KateDocument::slotModChanged() { emit modStateChanged (this); } QList<Kate::Mark> KateDocument::marks () { QList<Kate::Mark> list; TextLine::Ptr line; for (int i=0; i < numLines(); i++) { line = getTextLine(i); if (line->mark() != 0) { Kate::Mark *mark=new Kate::Mark; mark->line = i; mark->type = line->mark(); list.append (mark); } } return list; } void KateDocument::flush () { if (isReadOnly()) return; m_url = QString::null; fileInfo->setFile (QString()); setMTime(); clear(); updateViews(); emit fileNameChanged (); } void KateDocument::open (const QString &name) { openURL (name); } void KateDocument::wrapText (uint col) { int line = 0; int z = 0; while(true) { TextLine::Ptr l = getTextLine(line); if (l->length() > col) { TextLine::Ptr tl = new TextLine(); buffer->insertLine(line+1,tl); const QChar *text = l->getText(); for (z=col; z>0; z--) { if (z < 1) break; if (text[z].isSpace()) break; } if (z < 1) z=col; l->wrap (tl, z); } line++; if (line >= numLines()) break; }; newDocGeometry=true; updateLines(); updateViews(); } void KateDocument::setWordWrap (bool on) { if (on != myWordWrap && on) wrapText (myWordWrapAt); myWordWrap = on; } void KateDocument::setWordWrapAt (uint col) { if (myWordWrapAt != col && myWordWrap) wrapText (myWordWrapAt); myWordWrapAt = col; } void KateDocument::applyWordWrap () { wrapText (myWordWrapAt); } diff --git a/noncore/comm/keypebble/krfbdecoder.cpp b/noncore/comm/keypebble/krfbdecoder.cpp index 837fcc5..27ae101 100644 --- a/noncore/comm/keypebble/krfbdecoder.cpp +++ b/noncore/comm/keypebble/krfbdecoder.cpp @@ -1,831 +1,831 @@ #include "krfbconnection.h" #include "krfbserverinfo.h" #include "krfbdecoder.h" #include "krfbbuffer.h" /* OPIE */ #include <opie2/odebug.h> using namespace Opie::Core; /* QT */ #include <qpixmap.h> /* STD */ #include <assert.h> // // Endian stuff // //#ifndef OPIE_NO_DEBUG const int endianTest = 1; //#endif #define Swap16IfLE(s) \ (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) #define Swap32IfLE(l) \ (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \ (((l) & 0x00ff0000) >> 8) | \ (((l) & 0x0000ff00) << 8) | \ (((l) & 0x000000ff) << 24)) : (l)) // // The lengths of the messages we need to wait for // const int ServerInitLength = 24; const int UpdateHeaderLength = 4; const int RectHeaderLength = 12; const int RectChunkSize = 4; const int CopyRectPosLength = 4; const int ServerCutLenLength = 7; // // Client -> Server Message Identifiers // static CARD8 SetPixelFormatId = 0; //static CARD8 FixColourMapEntriesId = 1; // Not used static CARD8 SetEncodingsId = 2; static CARD8 UpdateRequestId = 3; static CARD8 KeyEventId = 4; static CARD8 PointerEventId = 5; static CARD8 ClientCutTextId = 6; // // Server -> Client Message Identifiers // static CARD8 UpdateId = 0; static CARD8 BellId = 2; static CARD8 ServerCutId = 3; // // Encoding identifiers // static CARD32 RawEncoding = Swap32IfLE( 0 ); static CARD32 CopyRectEncoding = Swap32IfLE(1 ); static CARD32 RreEncoding = Swap32IfLE( 2 ); static CARD32 CorreEncoding = Swap32IfLE( 4 ); static CARD32 HexTileEncoding = Swap32IfLE( 5 ); static struct { int keysym; int keycode; } keyMap[] = { { 0xff08, Qt::Key_Backspace }, { 0xff09, Qt::Key_Tab }, { 0xff0d, Qt::Key_Return }, { 0xff1b, Qt::Key_Escape }, { 0xff63, Qt::Key_Insert }, { 0xffff, Qt::Key_Delete }, { 0xff50, Qt::Key_Home }, { 0xff57, Qt::Key_End }, { 0xff55, Qt::Key_Prior }, { 0xff56, Qt::Key_Next }, { 0xff51, Qt::Key_Left }, { 0xff52, Qt::Key_Up }, { 0xff53, Qt::Key_Right }, { 0xff54, Qt::Key_Down }, { 0xffbe, Qt::Key_F1 }, { 0xffbf, Qt::Key_F2 }, { 0xffc0, Qt::Key_F3 }, { 0xffc1, Qt::Key_F4 }, { 0xffc2, Qt::Key_F5 }, { 0xffc3, Qt::Key_F6 }, { 0xffc4, Qt::Key_F7 }, { 0xffc5, Qt::Key_F8 }, { 0xffc6, Qt::Key_F9 }, { 0xffc7, Qt::Key_F10 }, { 0xffc8, Qt::Key_F11 }, { 0xffc9, Qt::Key_F12 }, { 0xffe1, Qt::Key_Shift }, { 0xffe2, Qt::Key_Shift }, { 0xffe3, Qt::Key_Control }, { 0xffe4, Qt::Key_Control }, { 0xffe7, Qt::Key_Meta }, { 0xffe8, Qt::Key_Meta }, { 0xffe9, Qt::Key_Alt }, { 0xffea, Qt::Key_Alt }, { 0, 0 } }; KRFBDecoder::KRFBDecoder( KRFBConnection *con ) : QObject( con, "RFB Decoder" ) { assert( con ); assert( con->state() == KRFBConnection::Connected ); this->con = con; this->buf = 0; this->info = 0; this->format = 0; this->buttonMask = 0; currentState = Idle; } KRFBDecoder::~KRFBDecoder() { if ( info ) delete info; if ( format ) delete format; } void KRFBDecoder::start() { sendClientInit(); } void KRFBDecoder::sendClientInit() { con->write( &( con->options()->shared ), 1 ); // Wait for server init owarn << "Waiting for server init" << oendl; static QString statusMsg = tr( "Waiting for server initialization..." ); emit status( statusMsg ); currentState = AwaitingServerInit; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerInit() ) ); con->waitForData( ServerInitLength ); } void KRFBDecoder::gotServerInit() { owarn << "Got server init" << oendl; disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerInit() ) ); if ( info ) delete info; info = new KRFBServerInfo; CHECK_PTR( info ); con->read( &(info->width), 2 ); info->width = Swap16IfLE( info->width ); con->read( &info->height, 2 ); info->height = Swap16IfLE( info->height ); con->read( &(info->bpp), 1 ); con->read( &(info->depth), 1 ); con->read( &(info->bigEndian), 1 ); con->read( &(info->trueColor), 1 ); con->read( &(info->redMax), 2 ); info->redMax = Swap16IfLE( info->redMax ); con->read( &(info->greenMax), 2 ); info->greenMax = Swap16IfLE( info->greenMax ); con->read( &(info->blueMax), 2 ); info->blueMax = Swap16IfLE( info->blueMax ); con->read( &(info->redShift), 1 ); con->read( &(info->greenShift), 1 ); con->read( &(info->blueShift), 1 ); con->read( info->padding, 3 ); con->read( &(info->nameLength), 4 ); info->nameLength = Swap32IfLE( info->nameLength ); owarn << "Width = " << info->width << ", Height = " << info->height << "" << oendl; owarn << "Bpp = " << info->bpp << ", Depth = " << info->depth << ", Big = " << info->bigEndian << ", True = " << info->trueColor << oendl; owarn << "RedMax = " << info->redMax << ", GreenMax = " << info->greenMax << ", BlueMax = " << info->blueMax << oendl; owarn << "RedShift = " << info->redShift << ", GreenShift = " << info->greenShift << ", BlueShift = " << info-> blueShift << oendl; buf->resize( info->width/con->options()->scaleFactor, info->height /con->options()->scaleFactor); // Wait for desktop name owarn << "Waiting for desktop name" << oendl; static QString statusMsg = tr( "Waiting for desktop name..." ); emit status( statusMsg ); currentState = AwaitingDesktopName; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotDesktopName() ) ); con->waitForData( info->nameLength ); } void KRFBDecoder::gotDesktopName() { assert( info ); assert( currentState == AwaitingDesktopName ); owarn << "Got desktop name" << oendl; disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotDesktopName() ) ); char *buf = new char[ info->nameLength + 1 ]; CHECK_PTR( buf ); con->read( buf, info->nameLength ); buf[ info->nameLength ] = '\0'; info->name = buf; owarn << "Desktop: " << info->name.latin1() << "" << oendl; - delete buf; + delete [] buf; // Get the format we'll really use and tell the server decidePixelFormat(); sendPixelFormat(); sendAllowedEncodings(); currentState = Idle; QString msg; msg = tr( "Connected to %1" ); msg = msg.arg( info->name ); emit status( msg ); sendUpdateRequest( false ); } void KRFBDecoder::decidePixelFormat() { assert( info ); if ( format ) delete format; format = new KRFBPixelFormat; CHECK_PTR( format ); // What depth do we want? // // We'll use the minimum of the remote and local depths, UNLESS an // eight bit session has been specifically requested by the user. int screenDepth = QPixmap::defaultDepth(); int bestDepth = ( screenDepth > info->depth ) ? info->depth : screenDepth; int chosenDepth; if ( con->options()->colors256 ) chosenDepth = 8; else chosenDepth = bestDepth; owarn << "Screen depth=" << screenDepth << ", server depth=" << info->depth << ", best depth=" << bestDepth << "eight bit " << con->options()->colors256 << ", chosenDepth=" << chosenDepth << oendl; format->depth = chosenDepth; // If we're using the servers native depth if ( chosenDepth == info->depth ) { // Use the servers native format format->bpp = info->bpp; // format->bigEndian = info->bigEndian; format->bigEndian = true; format->trueColor = info->trueColor; format->redMax = info->redMax; format->greenMax = info->greenMax; format->blueMax = info->blueMax; format->redShift = info->redShift; format->greenShift = info->greenShift; format->blueShift = info->blueShift; } else { if ( chosenDepth == 8 ) { format->bpp = 8; format->bigEndian = true; format->trueColor = true; format->redMax = 7; format->greenMax = 7; format->blueMax = 3; format->redShift = 0; format->greenShift = 3; format->blueShift = 6; } } format->redMax = Swap16IfLE( format->redMax ); format->greenMax = Swap16IfLE( format->greenMax ); format->blueMax = Swap16IfLE( format->blueMax ); } void KRFBDecoder::sendPixelFormat() { static char padding[3]; con->write( &SetPixelFormatId, 1 ); con->write( padding, 3 ); con->write( &(format->bpp), 1 ); con->write( &(format->depth), 1 ); con->write( &(format->bigEndian), 1 ); con->write( &(format->trueColor), 1 ); con->write( &(format->redMax), 2 ); con->write( &(format->greenMax), 2 ); con->write( &(format->blueMax), 2 ); con->write( &(format->redShift), 1 ); con->write( &(format->greenShift), 1 ); con->write( &(format->blueShift), 1 ); con->write( format->padding, 3 ); // Padding } void KRFBDecoder::sendAllowedEncodings() { static CARD8 padding[1]; con->write( &SetEncodingsId, 1 ); con->write( padding, 1 ); CARD16 noEncodings = con->options()->encodings(); noEncodings = Swap16IfLE( noEncodings ); con->write( &noEncodings, 2 ); if ( con->options()->corre ) con->write( &CorreEncoding, 4 ); if ( con->options()->hexTile ) con->write( &HexTileEncoding, 4 ); if ( con->options()->rre ) con->write( &RreEncoding, 4 ); if ( con->options()->copyrect ) con->write( &CopyRectEncoding, 4 ); // We always support this con->write( &RawEncoding, 4 ); } void KRFBDecoder::sendUpdateRequest( bool incremental ) { if ( currentState != Idle ) return; con->write( &UpdateRequestId, 1 ); con->write( &incremental, 1 ); static CARD16 x = 0, y = 0; static CARD16 w = Swap16IfLE( info->width ); static CARD16 h = Swap16IfLE( info->height ); con->write( &x, 2 ); con->write( &y, 2 ); con->write( &w, 2 ); con->write( &h, 2 ); // Now wait for the update currentState = AwaitingUpdate; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); con->waitForData( UpdateHeaderLength ); } void KRFBDecoder::gotUpdateHeader() { assert( currentState == AwaitingUpdate ); // owarn << "Got update header" << oendl; disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotUpdateHeader() ) ); CARD8 msgType; con->read( &msgType, 1 ); if ( msgType != UpdateId ) { // We might have a bell or server cut if ( msgType == ServerCutId ) { oldState = currentState; gotServerCut(); } else if ( msgType == BellId ) { oldState = currentState; gotBell(); } else { int msg = msgType; QString protocolError = tr( "Protocol Error: Message Id %1 was " "found when expecting an update " "message." ).arg( msg ); currentState = Error; emit error( protocolError ); } return; } CARD8 padding; con->read( &padding, 1 ); con->read( &noRects, 2 ); noRects = Swap16IfLE( noRects ); // owarn << "Expecting " << noRects << " rects" << oendl; // Now wait for the data currentState = AwaitingRectHeader; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); con->waitForData( RectHeaderLength ); } void KRFBDecoder::gotRectHeader() { assert( currentState == AwaitingRectHeader ); // owarn << "Got rect header" << oendl; disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotRectHeader() ) ); con->read( &x, 2 ); x = Swap16IfLE( x ); con->read( &y, 2 ); y = Swap16IfLE( y ); con->read( &w, 2 ); w = Swap16IfLE( w ); con->read( &h, 2 ); h = Swap16IfLE( h ); con->read( &encoding, 4 ); // CARD32 encodingLocal = Swap32IfLE( encoding ); // owarn << "Rect: x=" << x << ", y= " << y << ", w=" << w << ", h=" << h // << ", encoding= " << encodingLocal << oendl; // // Each encoding needs to be handled differently. Some require // waiting for more data, but others like a copyrect do not. // Our constants have already been byte swapped, so we use // the remote value as is. // if ( encoding == RawEncoding ) { // owarn << "Raw encoding" << oendl; handleRawRect(); } else if ( encoding == CopyRectEncoding ) { // owarn << "CopyRect encoding" << oendl; handleCopyRect(); } else if ( encoding == RreEncoding ) { owarn << "RRE encoding" << oendl; handleRRERect(); } else if ( encoding == CorreEncoding ) { owarn << "CoRRE encoding" << oendl; handleCoRRERect(); } else if ( encoding == HexTileEncoding ) { owarn << "HexTile encoding" << oendl; handleHexTileRect(); } else { int msg = Swap32IfLE( encoding ); QString protocolError = tr( "Protocol Error: An unknown encoding was " "used by the server %1" ).arg( msg ); currentState = Error; owarn << "Unknown encoding, " << msg << "" << oendl; emit error( protocolError ); return; } } // // Raw Encoding // void KRFBDecoder::handleRawRect() { // We need something a bit cleverer here to handle large // rectanges nicely. The chunking should be based on the // overall size (but has to be in complete lines). // owarn << "Handling a raw rect chunk" << oendl; // CARD32 lineCount = w * format->bpp / 8; if ( h > RectChunkSize ) { // if ( con->sock->size() / lineCount ) { // getRawRectChunk( con->sock->size() / lineCount ); // } // else { getRawRectChunk( RectChunkSize ); // } } else { getRawRectChunk( h ); } } void KRFBDecoder::getRawRectChunk( int lines ) { this->lines = lines; CARD32 count = lines * w * format->bpp / 8; // Wait for server init // owarn << "Waiting for raw rect chunk, " << count << "" << oendl; currentState = AwaitingRawRectChunk; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRawRectChunk() ) ); con->waitForData( count ); } void KRFBDecoder::gotRawRectChunk() { assert( currentState == AwaitingRawRectChunk ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotRawRectChunk() ) ); // owarn << "Got raw rect chunk" << oendl; // // Read the rect data and copy it to the buffer. // // TODO: Replace this! int count = lines * w * format->bpp / 8; char *hack = new char[ count ]; con->read( hack, count ); buf->drawRawRectChunk( hack, x, y, w, lines ); - delete hack; + delete [] hack; // /TODO: h = h - lines; y = y + lines; if ( h > 0 ) { handleRawRect(); } else { noRects--; // owarn << "There are " << noRects << " rects left" << oendl; if ( noRects ) { currentState = AwaitingRectHeader; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); con->waitForData( RectHeaderLength ); } else { // we are now ready for the next update - no need to wait for the timer currentState = Idle; sendUpdateRequest (1); } } } // // Copy Rectangle Encoding // void KRFBDecoder::handleCopyRect() { currentState = AwaitingCopyRectPos; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotCopyRectPos() ) ); con->waitForData( CopyRectPosLength ); } void KRFBDecoder::gotCopyRectPos() { disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotCopyRectPos() ) ); CARD16 srcX; CARD16 srcY; con->read( &srcX, 2 ); con->read( &srcY, 2 ); srcX = Swap16IfLE( srcX ); srcY = Swap16IfLE( srcY ); buf->copyRect( srcX, srcY, x, y, w, h ); noRects--; // owarn << "There are " << noRects << " rects left" << oendl; if ( noRects ) { currentState = AwaitingRectHeader; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotRectHeader() ) ); con->waitForData( RectHeaderLength ); } else currentState = Idle; } void KRFBDecoder::handleRRERect() { owarn << "RRE not implemented" << oendl; } void KRFBDecoder::handleCoRRERect() { owarn << "CoRRE not implemented" << oendl; } void KRFBDecoder::handleHexTileRect() { owarn << "HexTile not implemented" << oendl; } void KRFBDecoder::sendMouseEvent( QMouseEvent *e ) { // Deal with the buttons if ( e->type() != QEvent::MouseMove ) { buttonMask = 0; if ( e->type() == QEvent::MouseButtonPress ) { if ( e->button() & LeftButton ) buttonMask |= 0x01; if ( e->button() & MidButton ) buttonMask |= 0x04; if ( e->button() & RightButton ) buttonMask |= 0x02; } else if ( e->type() == QEvent::MouseButtonRelease ) { if ( e->button() & LeftButton ) buttonMask &= 0x06; if ( e->button() & MidButton ) buttonMask |= 0x03; if ( e->button() & RightButton ) buttonMask |= 0x05; } } // HACK: Scaling CARD16 x = Swap16IfLE( e->x() * con->options()->scaleFactor ); CARD16 y = Swap16IfLE( e->y() * con->options()->scaleFactor ); con->write( &PointerEventId, 1 ); con->write( &buttonMask, 1 ); con->write( &x, 2 ); con->write( &y, 2 ); } void KRFBDecoder::sendCutEvent( const QString &unicode ) { // // Warning: There is a bug in the RFB protocol because there is no way to find // out the codepage in use on the remote machine. This could be fixed by requiring // the remote server to use utf8 etc. but for now we have to assume they're the // same. I've reported this problem to the ORL guys, but they apparantly have no // immediate plans to fix the issue. :-( (rich) // CARD8 padding[3]; QCString text = unicode.local8Bit(); CARD32 length = text.length(); length = Swap32IfLE( length ); con->write( &ClientCutTextId, 1 ); con->write( &padding, 3 ); con->write( &length, 4 ); con->write( text.data(), length ); } void KRFBDecoder::gotServerCut() { owarn << "Got server cut" << oendl; currentState = AwaitingServerCutLength; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutLength() ) ); con->waitForData( ServerCutLenLength ); } void KRFBDecoder::gotServerCutLength() { assert( currentState = AwaitingServerCutLength ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerCutLength() ) ); CARD8 padding[3]; con->read( padding, 3 ); con->read( &serverCutTextLen, 4 ); serverCutTextLen = Swap32IfLE( serverCutTextLen ); currentState = AwaitingServerCutText; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerCutText() ) ); con->waitForData( serverCutTextLen ); } void KRFBDecoder::gotServerCutText() { assert( currentState = AwaitingServerCutText ); disconnect( con, SIGNAL( gotEnoughData() ), this, SLOT( gotServerCutText() ) ); // // Warning: There is a bug in the RFB protocol because there is no way to find // out the codepage in use on the remote machine. This could be fixed by requiring // the remote server to use utf8 etc. but for now we have to assume they're the // same. I've reported this problem to the ORL guys, but they apparantly have no // immediate plans to fix the issue. :-( (rich) // char *cutbuf = new char[ serverCutTextLen + 1 ]; CHECK_PTR( cutbuf ); con->read( cutbuf, serverCutTextLen ); cutbuf[ serverCutTextLen ] = '\0'; /* For some reason QApplication::clipboard()->setText() segfaults when called * from within keypebble's mass of signals and slots owarn << "Server cut: " << cutbuf << "" << oendl; QString cutText( cutbuf ); // DANGER!! qApp->clipboard()->setText( cutText ); */ - delete cutbuf; + delete [] cutbuf; // Now wait for the update (again) if ( oldState == AwaitingUpdate ) { currentState = AwaitingUpdate; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); con->waitForData( UpdateHeaderLength ); } else if ( oldState == Idle ) { currentState = Idle; } else { owarn << "Async handled in weird state" << oendl; currentState = oldState; }; } void KRFBDecoder::gotBell() { owarn << "Got server bell" << oendl; buf->soundBell(); // Now wait for the update (again) if ( oldState == AwaitingUpdate ) { currentState = AwaitingUpdate; connect( con, SIGNAL( gotEnoughData() ), SLOT( gotUpdateHeader() ) ); con->waitForData( UpdateHeaderLength ); } else if ( oldState == Idle ) { currentState = Idle; } else { owarn << "Async handled in weird state" << oendl; currentState = oldState; }; } void KRFBDecoder::sendKeyPressEvent( QKeyEvent *event ) { int key; key = toKeySym( event ); if ( key ) { key = Swap32IfLE( key ); CARD8 mask = true; CARD16 padding = 0; con->write( &KeyEventId, 1 ); con->write( &mask, 1 ); con->write( &padding, 2 ); con->write( &key, 4 ); } } void KRFBDecoder::sendKeyReleaseEvent( QKeyEvent *event ) { int key; key = toKeySym( event ); if ( key ) { key = Swap32IfLE( key ); CARD8 mask = false; CARD16 padding = 0; con->write( &KeyEventId, 1 ); con->write( &mask, 1 ); con->write( &padding, 2 ); con->write( &key, 4 ); } } // // The RFB protocol spec says 'For most ordinary keys, the 'keysym' // is the same as the corresponding ASCII value.', but doesn't // elaborate what the most ordinary keys are. The spec also lists // a set (possibly subset, it's unspecified) of mappings for // "other common keys" (backspace, tab, return, escape, etc). // int KRFBDecoder::toKeySym( QKeyEvent *k ) { // // Try and map these "other common keys" first. // if ((k->key() >= Qt::Key_Escape) && (k->key() <= Qt::Key_F12)) { for(int i = 0; keyMap[i].keycode != 0; i++) { if (k->key() == keyMap[i].keycode) { return keyMap[i].keysym; } } } // // If these keys aren't matched, return the ascii code and let the // server figure it out. We don't return k->key(), as the data in // key differs between input methods, and we don't want special cases. // return k->ascii(); } diff --git a/noncore/games/sfcave/sfcave.cpp b/noncore/games/sfcave/sfcave.cpp index a6c92a0..516dc93 100644 --- a/noncore/games/sfcave/sfcave.cpp +++ b/noncore/games/sfcave/sfcave.cpp @@ -1,1211 +1,1211 @@ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <opie2/oapplicationfactory.h> #include <qpe/qpeapplication.h> #include <qpe/config.h> #include <qpe/global.h> #include <qdir.h> #include "helpwindow.h" #include "sfcave.h" #define CAPTION "SFCave 1.13 by AndyQ" #define UP_THRUST 0.6 #define NO_THRUST 0.8 #define MAX_DOWN_THRUST 4.0 #define MAX_UP_THRUST -3.5 // States #define STATE_BOSS 0 #define STATE_RUNNING 1 #define STATE_CRASHING 2 #define STATE_CRASHED 3 #define STATE_NEWGAME 4 #define STATE_MENU 5 #define STATE_REPLAY 6 // Menus #define MENU_MAIN_MENU 0 #define MENU_OPTIONS_MENU 1 #define MENU_REPLAY_MENU 2 // Main Menu Options #define MENU_START_GAME 0 #define MENU_REPLAY 1 #define MENU_OPTIONS 2 #define MENU_HELP 3 #define MENU_QUIT 4 // Option Menu Options #define MENU_GAME_TYPE 0 #define MENU_GAME_DIFFICULTY 1 #define MENU_CLEAR_HIGHSCORES 2 #define MENU_BACK 3 // Replay Menu Options #define MENU_REPLAY_START 0 #define MENU_REPLAY_LOAD 1 #define MENU_REPLAY_SAVE 2 #define MENU_REPLAY_BACK 3 #define NR_GAME_DIFFICULTIES 3 #define NR_GAME_TYPES 3 #define DIFICULTY_EASY 0 #define DIFICULTY_NORMAL 1 #define DIFICULTY_HARD 2 #define EASY "Easy" #define NORMAL "Normal" #define HARD "Hard" #define SFCAVE_GAME_TYPE 0 #define GATES_GAME_TYPE 1 #define FLY_GAME_TYPE 2 #define SFCAVE_GAME "SFCave" #define GATES_GAME "Gates" #define FLY_GAME "Fly" #define CURRENT_GAME_TYPE gameTypes[currentGameType] #define CURRENT_GAME_DIFFICULTY difficultyOption[currentGameDifficulty]; QString SFCave::dificultyOption[] = { EASY, NORMAL, HARD }; QString SFCave::gameTypes[] = { SFCAVE_GAME, GATES_GAME, FLY_GAME }; QString SFCave::menuOptions[NR_MENUS][MAX_MENU_OPTIONS] = { { "Start Game", "Replays", "Options", "Help", "Quit", "", "", "" }, { "Game Type - %s", "Game Difficulty - %s", "Clear High Scores for this game", "Back", "", "", "", "" }, { "Play Reply", "Load Replay", "Save Replay", "Back", "", "", "", "" } }; int SFCave::nrMenuOptions[NR_MENUS] = { 5, 4, 4 }; int SFCave ::currentMenuOption[NR_MENUS] = { 0, 0, 0 }; #define UP_THRUST 0.6 #define NO_THRUST 0.8 #define MAX_DOWN_THRUST 4.0 #define MAX_UP_THRUST -3.5 double SFCave::UpThrustVals[3][3] = {{ 0.6, 0.6, 0.6 }, // SFCave { 0.6, 0.6, 0.8 }, // Gates { 0.4, 0.7, 1.0 } }; // Fly double SFCave::DownThrustVals[3][3] = {{ 0.8, 0.8, 0.8 }, // SFCave { 0.8, 0.8, 1.0 }, // Gates { 0.4, 0.7, 1.0 } }; // Fly double SFCave::MaxUpThrustVals[3][3] = {{ -3.5, -3.5, -3.5 }, // SFCave { -3.5, -4.0, -5.0 }, // Gates { -3.5, -4.0, -5.0 } }; // Fly double SFCave::MaxDownThrustVals[3][3] = {{ 4.0, 4.0, 4.0 }, // SFCave { 4.0, 5.0, 5.5 }, // Gates { 3.5, 4.0, 5.0 } }; // Fly int SFCave::flyEasyScores[7][3] = { { 0, 10, 5 }, { 10, 20, 3 }, { 20, 30, 2 }, { 30, 40, 1 }, { 50, 70, -2 }, { 70, 300, -5 }, { -1, -1, -1 } }; int SFCave::flyNormalScores[7][3] = { { 0, 10, 5 }, { 10, 20, 3 }, { 20, 30, 2 }, { 30, 40, 1 }, { 50, 70, -2 }, { 70, 300, -5 }, { -1, -1, -1 } }; int SFCave::flyHardScores[7][3] = { { 0, 20, 5 }, { 20, 40, 3 }, { 40, 100, 1 }, { 100, 150, -2 }, { 150, 300, -5 }, { -1, -1, -1 } }; int SFCave::initialGateGaps[] = { 75, 50, 25 }; #define FLYSCORES( x, y ) (*(flyScores + ((x)*3) + y)) bool movel; OPIE_EXPORT_APP( Opie::Core::OApplicationFactory<SFCave> ) SFCave :: SFCave( QWidget *w, const char *name, WFlags fl ) : QMainWindow( w, name, fl ) { showMaximized(); movel = true; int spd = 3; replayIt = 0; replayFile = Global::applicationFileName("sfcave", "replay"); sWidth = width(); sHeight = height(); segSize = sWidth/(MAPSIZE-1)+1; currentMenuNr = 0; currentGameType = 0; currentGameDifficulty = 0; setCaption( CAPTION ); showScoreZones = false; #ifdef QWS Config cfg( "sfcave" ); cfg.setGroup( "settings" ); QString key = "highScore_"; for ( int i = 0 ; i < 3 ; ++i ) { for ( int j = 0 ; j < 3 ; ++j ) highestScore[i][j] = cfg.readNumEntry( key + gameTypes[i] + "_" + dificultyOption[j], 0 ); } currentGameType = cfg.readNumEntry( "gameType", 0 ); currentGameDifficulty = cfg.readNumEntry( "difficulty", 0 ); #endif speed = spd; // Change to 2 for PC press = false; showEyeCandy = false; offscreen = new QPixmap( sWidth, sHeight ); offscreen->fill( Qt::black ); // setUp(); crashLineLength = -1; state = STATE_MENU; prevState = STATE_MENU; gameTimer = new QTimer( this, "game timer" ); connect( gameTimer, SIGNAL( timeout() ), this, SLOT( run() ) ); QTimer::singleShot(0, this, SLOT(start())); } SFCave :: ~SFCave() { } void SFCave :: start() { gameTimer->start( 10 ); } void SFCave :: setSeed( int seed ) { if ( seed == -1 ) currentSeed = ((unsigned long) time((time_t *) NULL)); else currentSeed = seed; PutSeed( currentSeed ); } int SFCave :: nextInt( int range ) { int val = (int)(Random( ) * range); return val; } void SFCave :: setUp() { score = 0; offset = 0; nrFrames = 0; dir = 1; thrust = 0; startScoring = false; press = false; if ( CURRENT_GAME_TYPE == SFCAVE_GAME ) { thrustUp = UpThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];; noThrust = DownThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];; maxUpThrust = MaxUpThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];; maxDownThrust = MaxDownThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];; if ( currentGameDifficulty == DIFICULTY_EASY ) gateDistance = 100; else if ( currentGameDifficulty == DIFICULTY_NORMAL ) gateDistance = 60; else gateDistance = 40; } else if ( CURRENT_GAME_TYPE == GATES_GAME ) { thrustUp = UpThrustVals[GATES_GAME_TYPE][currentGameDifficulty];; noThrust = DownThrustVals[GATES_GAME_TYPE][currentGameDifficulty];; maxUpThrust = MaxUpThrustVals[GATES_GAME_TYPE][currentGameDifficulty];; maxDownThrust = MaxDownThrustVals[GATES_GAME_TYPE][currentGameDifficulty];; gateDistance = 75; nextGate = nextInt( 50 ) + gateDistance; } else { thrustUp = UpThrustVals[FLY_GAME_TYPE][currentGameDifficulty]; noThrust = DownThrustVals[FLY_GAME_TYPE][currentGameDifficulty]; maxUpThrust = MaxUpThrustVals[FLY_GAME_TYPE][currentGameDifficulty]; maxDownThrust = MaxDownThrustVals[FLY_GAME_TYPE][currentGameDifficulty]; if ( currentGameDifficulty == DIFICULTY_EASY ) flyScores = (int*)flyEasyScores; else if ( currentGameDifficulty == DIFICULTY_NORMAL ) flyScores = (int*)flyNormalScores; else flyScores = (int*)flyHardScores; } crashLineLength = 0; lastGateBottomY = 0; user.setRect( 50, sWidth/2, 4, 4 ); blockWidth = 20; blockHeight = 70; gapHeight = initialGateGaps[currentGameDifficulty]; for ( int i = 0 ; i < TRAILSIZE ; ++i ) { trail[i].setX( -1 ); trail[i].setY( 0 ); } if ( CURRENT_GAME_TYPE != FLY_GAME ) { maxHeight = 50; mapTop[0] = (int)(nextInt(50)) + 5; mapBottom[0] = (int)(nextInt(50)) + 5; for ( int i = 1 ; i < MAPSIZE ; ++i ) setPoint( i ); } else { maxHeight = 100; for ( int i = 0 ; i < MAPSIZE ; ++i ) mapBottom[i] = sHeight - 10; } for ( int i = 0 ; i < BLOCKSIZE ; ++i ) blocks[i].setY( -1 ); } void SFCave :: run() { switch ( state ) { case STATE_MENU: displayMenu(); break; case STATE_NEWGAME: setSeed( -1 ); setUp(); draw(); state = STATE_RUNNING; replay = false; replayList.clear(); break; case STATE_REPLAY: setSeed( currentSeed ); setUp(); draw(); state = STATE_RUNNING; replay = true; if ( replayIt ) delete replayIt; replayIt = new QListIterator<int>( replayList ); break; case STATE_BOSS: drawBoss(); break; case STATE_CRASHING: case STATE_CRASHED: press = false; draw(); break; case STATE_RUNNING: { if ( nrFrames % 2 == 0 ) handleKeys(); // Apply Game rules nrFrames ++; if ( replay ) { while( replayIt->current() && *(replayIt->current()) == nrFrames ) { press = !press; ++(*replayIt); } } if ( CURRENT_GAME_TYPE == SFCAVE_GAME ) handleGameSFCave(); else if ( CURRENT_GAME_TYPE == GATES_GAME ) handleGameGates(); else if ( CURRENT_GAME_TYPE == FLY_GAME ) handleGameFly(); draw(); break; } } } void SFCave :: handleGameSFCave() { // Update score if ( nrFrames % 5 == 0 ) score ++; if ( nrFrames % 500 == 0 ) { if ( maxHeight < sHeight - 100 ) { maxHeight += 10; // Reduce block height if ( maxHeight > sHeight - 150 ) blockHeight -= 5; } } if ( nrFrames % gateDistance == 0 ) addBlock(); if ( checkCollision() ) { if ( score > highestScore[currentGameType][currentGameDifficulty] ) { highestScore[currentGameType][currentGameDifficulty] = score; saveScore(); } state = STATE_CRASHING; } else { moveLandscape(); } } void SFCave :: handleGameGates() { // Update score if ( nrFrames % 5 == 0 ) score ++; // Slightly random gap distance if ( nrFrames >= nextGate ) { nextGate = nrFrames + nextInt( 50 ) + gateDistance; addGate(); } if ( nrFrames % 500 == 0 ) { if ( gapHeight > 75 ) gapHeight -= 5; } if ( checkCollision() ) { if ( score > highestScore[currentGameType][currentGameDifficulty] ) { highestScore[currentGameType][currentGameDifficulty] = score; saveScore(); } state = STATE_CRASHING; } else { moveLandscape(); } } void SFCave :: handleGameFly() { int diff = mapBottom[10] - user.y(); if ( nrFrames % 4 == 0 ) { if ( !startScoring ) { if ( diff < 40 ) startScoring = true; } if ( startScoring ) { // Update score // get distance between landscape and ship // the closer the difference is to 0 means more points for ( int i = 0 ; i < 10 && FLYSCORES( i, 0 ) != -1 ; ++i ) { if ( FLYSCORES( i, 0 ) <= diff && FLYSCORES(i, 1 ) > diff ) { score += FLYSCORES( i, 2 ); break; } } } } if ( checkFlyGameCollision() ) { if ( score > highestScore[currentGameType][currentGameDifficulty] ) { highestScore[currentGameType][currentGameDifficulty] = score; saveScore(); } state = STATE_CRASHING; } else { moveFlyGameLandscape(); } } bool SFCave :: checkFlyGameCollision() { if ( (user.y() + user.width()) >= mapBottom[11] ) return true; return false; } void SFCave :: moveFlyGameLandscape() { offset++; if ( offset >= segSize ) { offset = 0; for ( int i = 0 ; i < MAPSIZE-speed ; ++i ) mapBottom[i] = mapBottom[i+speed]; for ( int i = speed ; i > 0 ; --i ) setFlyPoint( MAPSIZE-i ); } } void SFCave :: setFlyPoint( int point ) { static int fly_difficulty_levels[] = { 5, 10, 15 }; if ( nextInt(100) >= 75 ) dir *= -1; int prevPoint = mapBottom[point-1]; int nextPoint = prevPoint + (dir * nextInt( fly_difficulty_levels[currentGameDifficulty] ) ); if ( nextPoint > sHeight ) { nextPoint = sHeight; dir *= -1; } else if ( nextPoint < maxHeight ) { nextPoint = maxHeight; dir *= 1; } mapBottom[point] = nextPoint; } bool SFCave :: checkCollision() { if ( (user.y() + user.width()) >= mapBottom[11] || user.y() <= mapTop[11] ) return true; for ( int i = 0 ; i < BLOCKSIZE ; ++i ) { if ( blocks[i].y() != -1 ) { if ( blocks[i].intersects( user ) ) return true; } } return false; } void SFCave :: moveLandscape() { offset++; if ( offset >= segSize ) { offset = 0; for ( int i = 0 ; i < MAPSIZE-speed ; ++i ) { mapTop[i] = mapTop[i+speed]; mapBottom[i] = mapBottom[i+speed]; } for ( int i = speed ; i > 0 ; --i ) setPoint( MAPSIZE-i ); } for ( int i = 0 ; i < BLOCKSIZE ; ++i ) { if ( blocks[i].y() != -1 ) { blocks[i].moveBy( -speed, 0 ); if ( blocks[i].x() + blocks[i].width() < 0 ) blocks[i].setY( -1 ); } } } void SFCave :: addBlock() { for ( int i = 0 ; i < BLOCKSIZE ; ++i ) { if ( blocks[i].y() == -1 ) { int x = sWidth; int y = mapTop[50] + (int)(nextInt(mapBottom[50] - mapTop[50] - blockHeight)); blocks[i].setRect( x, y, blockWidth, blockHeight ); break; } } } void SFCave :: addGate() { for ( int i = 0 ; i < BLOCKSIZE ; ++i ) { if ( blocks[i].y() == -1 ) { int x1 = sWidth; int y1 = mapTop[50]; int b1Height = nextInt(mapBottom[50] - mapTop[50] - gapHeight); // See if height between last gate and this one is too big if ( b1Height - 100 > lastGateBottomY ) b1Height -= 25; else if ( b1Height + 100 < lastGateBottomY ) b1Height += 25; lastGateBottomY = b1Height; int x2 = sWidth; int y2 = y1 + b1Height + gapHeight; int b2Height = mapBottom[50] - y2; blocks[i].setRect( x1, y1, blockWidth, b1Height ); blocks[i+1].setRect( x2, y2, blockWidth, b2Height ); break; } } } void SFCave :: setPoint( int point ) { if ( nextInt(100) >= 80 ) dir *= -1; mapTop[point] = mapTop[point-1] + (dir * nextInt( 5 ) ); if ( mapTop[point] < 0 ) { mapTop[point] = 0; dir *= -1; } else if ( mapTop[point] >= maxHeight ) { mapTop[point] = maxHeight; dir *= -1; } // mapBottom[point] = sHeight - (maxHeight - mapBottom[point]); mapBottom[point] = sHeight - (maxHeight - mapTop[point]); } void SFCave :: drawBoss() { offscreen->fill( Qt::black ); bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true ); } void SFCave :: draw() { //printf( "Paint\n" ); offscreen->fill( Qt::black ); QPainter p( offscreen ); QFontMetrics fm = p.fontMetrics(); p.setPen( Qt::white ); for ( int i = 0 ; i < MAPSIZE -3; ++i ) { // Only display top landscape if not running FLY_GAME if ( CURRENT_GAME_TYPE != FLY_GAME ) p.drawLine( (i*segSize) - (offset*speed), mapTop[i], ((i+1)*segSize)-(offset*speed), mapTop[i+1] ); p.drawLine( (i*segSize) - (offset*speed), mapBottom[i], ((i+1)*segSize)-(offset*speed), mapBottom[i+1] ); if ( CURRENT_GAME_TYPE == FLY_GAME && showScoreZones ) { p.setPen( Qt::blue ); for ( int j = 1 ; j < 10 && FLYSCORES( j, 0 ) != -1 ; ++j ) { if ( FLYSCORES( j, 2 ) < 0 ) p.setPen( Qt::red ); p.drawLine( (i*segSize) - (offset*speed), mapBottom[i]-FLYSCORES( j, 0 ), ((i+1)*segSize)-(offset*speed), mapBottom[i+1]-FLYSCORES( j, 0 ) ); } p.setPen( Qt::white ); } } // Uncomment this to show user segment (usful for checking collision boundary with landscape // p.setPen( Qt::red ); // p.drawLine( (11*segSize) - (offset*speed), 0, ((11)*segSize)-(offset*speed), sHeight ); // p.setPen( Qt::white ); // Draw user p.drawRect( user ); // Draw trails for ( int i = 0 ; i < TRAILSIZE ; ++i ) if ( trail[i].x() >= 0 ) { if ( showEyeCandy ) p.setPen( Qt::white.light((int)(100.0-3*(user.x()/100.0)* (user.x()-trail[i].x())) ) ); p.drawRect( trail[i].x(), trail[i].y(), 2, 2 ); } p.setPen( Qt::white ); // Draw blocks for ( int i = 0 ; i < BLOCKSIZE ; ++i ) if ( blocks[i].y() != -1 ) { p.fillRect( blocks[i], Qt::black ); p.drawRect( blocks[i] ); } // draw score QString s; s.sprintf( "score %06d high score %06d", score, highestScore[currentGameType][currentGameDifficulty] ); p.drawText( 5, 10, s ); if ( state == STATE_CRASHING || state == STATE_CRASHED ) { // add next crash line if ( crashLineLength != -1 ) { for ( int i = 0 ; i < 36 ; ++i ) { int x = (int)(user.x() + (crashLineLength+nextInt(10)) * cos( (M_PI/180) * (10.0 * i) ) ); int y = (int)(user.y() + (crashLineLength+nextInt(10)) * sin( (M_PI/180) * (10.0 * i) ) ); p.drawLine( user.x(), user.y(), x, y ); } } if ( state == STATE_CRASHING && crashLineLength >= 15 ) //|| crashLineLength == -1) ) state = STATE_CRASHED; if ( state == STATE_CRASHED ) { QString text = "Press up or down to start"; p.drawText( (sWidth/2) - (fm.width( text )/2), 120, text ); text = "Press OK for menu"; p.drawText( (sWidth/2) - (fm.width( text )/2), 135, text ); /* text = "Press r to replay"; p.drawText( (sWidth/2) - (fm.width( text )/2), 150, text ); text = "Press s to save the replay"; p.drawText( (sWidth/2) - (fm.width( text )/2), 165, text ); text = "Press r to load a saved replay"; p.drawText( (sWidth/2) - (fm.width( text )/2), 180, text ); */ } else crashLineLength ++; } p.end(); bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true ); //printf( "endpaint\n" ); } void SFCave :: handleKeys() { // Find enpty trail and move others bool done = false; for ( int i = 0 ; i < TRAILSIZE ; ++i ) { if ( trail[i].x() < 0 ) { if ( !done ) { trail[i].setX( user.x() - 5 ); trail[i].setY( user.y() ); done = true; } } else { trail[i].setX( trail[i].x() - (2) ); } } if ( speed <= 3 ) { if ( press ) thrust -= thrustUp; else thrust += noThrust; if ( thrust > maxDownThrust ) thrust = maxDownThrust; else if ( thrust < maxUpThrust ) thrust = maxUpThrust; } else { if ( press ) thrust -= 0.5; else thrust += 0.8; if ( thrust > 5.0 ) thrust = 5.0; else if ( thrust < -3.5 ) thrust = -3.5; } user.moveBy( 0, (int)thrust ); } void SFCave :: keyPressEvent( QKeyEvent *e ) { if ( state == STATE_MENU ) handleMenuKeys( e ); else { switch( e->key() ) { case Qt::Key_Up: case Qt::Key_F9: case Qt::Key_Space: if ( state == STATE_RUNNING ) { if ( !replay && !press ) { press = true; replayList.append( new int( nrFrames ) ); } } else if ( state == STATE_CRASHED ) { if ( e->key() == Key_Up ) state = STATE_NEWGAME; } break; case Qt::Key_M: case Qt::Key_Return: case Qt::Key_Enter: if ( state == STATE_CRASHED ) { state = STATE_MENU; currentMenuNr = 0; currentMenuOption[currentMenuNr] = 0; } break; case Qt::Key_Z: showScoreZones = !showScoreZones; break; default: e->ignore(); break; } } } void SFCave :: keyReleaseEvent( QKeyEvent *e ) { if ( state == STATE_MENU ) { } else { switch( e->key() ) { case Qt::Key_F9: case Qt::Key_Space: case Qt::Key_Up: if ( state == STATE_RUNNING ) { if ( !replay && press ) { press = false; replayList.append( new int( nrFrames ) ); } } break; case Qt::Key_E: showEyeCandy = !showEyeCandy; break; case Qt::Key_R: if ( state == STATE_CRASHED ) state = STATE_REPLAY; break; case Qt::Key_Down: if ( state == STATE_CRASHED ) state = STATE_NEWGAME; break; case Qt::Key_S: if ( state == STATE_CRASHED ) saveReplay(); break; case Qt::Key_L: if ( state == STATE_CRASHED ) loadReplay(); break; default: e->ignore(); break; } } } void SFCave :: saveScore() { #ifdef QWS Config cfg( "sfcave" ); cfg.setGroup( "settings" ); QString key = "highScore_"; cfg.writeEntry( key + gameTypes[currentGameType] + "_" + dificultyOption[currentGameDifficulty], highestScore[currentGameType][currentGameDifficulty] ); key += CURRENT_GAME_TYPE; cfg.writeEntry( key, highestScore[currentGameType] ); #endif } void SFCave :: saveReplay() { FILE *out; out = fopen( QFile::encodeName(replayFile).data(), "w" ); if ( !out ) { printf( "Couldn't write to %s\n", QFile::encodeName(replayFile).data() ); return; } // Build up string of values // Format is:: <landscape seed> <game type> <difficulty> <framenr> <framenr>....... QString val; val.sprintf( "%d %d %d ", currentSeed, currentGameType, currentGameDifficulty ); QListIterator<int> it( replayList ); while( it.current() ) { QString tmp; tmp.sprintf( "%d ", (*it.current()) ); val += tmp; ++it; } val += "\n"; QString line; line.sprintf( "%d\n", val.length() ); fwrite( (const char *)line, 1, line.length(), out ); fwrite( (const char *)val, 1, val.length(), out ); fclose( out ); printf( "Replay saved to %s\n", QFile::encodeName(replayFile).data() ); } void SFCave :: loadReplay() { FILE *in = fopen( QFile::encodeName(replayFile).data() , "r" ); if ( in == 0 ) { printf( "Couldn't load replay file!\n" ); return; } // Read next line - contains the size of the options char line[10+1]; fgets( line, 10, in ); int length = -1; sscanf( line, "%d", &length ); char *data = new char[length+1]; fread( data, 1, length, in ); // printf( "data - %s", data ); QString sep = " "; QStringList list = QStringList::split( sep, QString( data ) ); // print it out QStringList::Iterator it = list.begin(); currentSeed = (*it).toInt(); ++it; currentGameType = (*it).toInt(); ++it; currentGameDifficulty = (*it).toInt(); ++it; replayList.clear(); for ( ; it != list.end(); ++it ) { int v = (*it).toInt(); replayList.append( new int( v ) ); } - delete data; + delete [] data; fclose( in ); printf( "Replay loaded from %s\n", QFile::encodeName(replayFile).data() ); } //--------------- MENU CODE --------------------- void SFCave :: handleMenuKeys( QKeyEvent *e ) { switch( e->key() ) { case Qt::Key_Down: currentMenuOption[currentMenuNr] ++; if ( menuOptions[currentMenuNr][currentMenuOption[currentMenuNr]] == "" ) currentMenuOption[currentMenuNr] = 0; break; case Qt::Key_Up: currentMenuOption[currentMenuNr] --; if ( currentMenuOption[currentMenuNr] < 0 ) currentMenuOption[currentMenuNr] = nrMenuOptions[currentMenuNr]-1; break; case Qt::Key_Left: if ( currentMenuNr == MENU_OPTIONS_MENU ) { if ( currentMenuOption[currentMenuNr] == MENU_GAME_TYPE ) { currentGameType --; if ( currentGameType < 0 ) currentGameType = NR_GAME_TYPES - 1; } else if ( currentMenuOption[currentMenuNr] == MENU_GAME_DIFFICULTY ) { currentGameDifficulty --; if ( currentGameDifficulty < 0 ) currentGameDifficulty = NR_GAME_DIFFICULTIES - 1; } } break; case Qt::Key_Right: if ( currentMenuNr == MENU_OPTIONS_MENU ) { if ( currentMenuOption[currentMenuNr] == MENU_GAME_TYPE ) { currentGameType ++; if ( currentGameType == NR_GAME_TYPES ) currentGameType = 0; } else if ( currentMenuOption[currentMenuNr] == MENU_GAME_DIFFICULTY ) { currentGameDifficulty ++; if ( currentGameDifficulty == NR_GAME_DIFFICULTIES ) currentGameDifficulty = 0; } } break; case Qt::Key_Space: case Qt::Key_Return: case Qt::Key_Enter: dealWithMenuSelection(); break; } } void SFCave :: displayMenu() { offscreen->fill( Qt::black ); QPainter p( offscreen ); p.setPen( Qt::white ); QFont f( "Helvetica", 16 ); p.setFont( f ); QFontMetrics fm = p.fontMetrics(); QString text = "SFCave"; p.drawText( (sWidth/2) - (fm.width( text )/2), 60, text ); text = "Written by Andy Qua"; p.drawText( (sWidth/2) - (fm.width( text )/2), 85, text ); // Draw options int pos = 140; for ( int i = 0 ; menuOptions[currentMenuNr][i] != "" ; ++i, pos += 25 ) { if ( currentMenuOption[currentMenuNr] == i ) p.setPen( Qt::yellow ); else p.setPen( Qt::white ); QString text; if ( menuOptions[currentMenuNr][i].find( "%s" ) != -1 ) { QString val; if ( i == MENU_GAME_TYPE ) val = gameTypes[currentGameType]; else val = dificultyOption[currentGameDifficulty]; text.sprintf( (const char *)menuOptions[currentMenuNr][i], (const char *)val ); } else text = menuOptions[currentMenuNr][i]; p.drawText( (sWidth/2) - (fm.width( text )/2), pos, text ); } p.end(); bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true ); } void SFCave :: dealWithMenuSelection() { switch( currentMenuNr ) { case MENU_MAIN_MENU: { switch( currentMenuOption[currentMenuNr] ) { case MENU_START_GAME: state = STATE_NEWGAME; break; case MENU_REPLAY: currentMenuNr = MENU_REPLAY_MENU; currentMenuOption[currentMenuNr] = 0; break; case MENU_OPTIONS: currentMenuNr = MENU_OPTIONS_MENU; currentMenuOption[currentMenuNr] = 0; break; case MENU_HELP: { // Display Help Menu HelpWindow *win = new HelpWindow( ); QPEApplication::showWidget( win ); break; } case MENU_QUIT: QApplication::exit(); break; } break; } case MENU_OPTIONS_MENU: { switch( currentMenuOption[currentMenuNr] ) { case MENU_GAME_TYPE: break; case MENU_GAME_DIFFICULTY: break; case MENU_CLEAR_HIGHSCORES: for ( int i = 0 ; i < 3 ; ++i ) highestScore[currentGameType][i] = 0; break; case MENU_BACK: currentMenuNr = MENU_MAIN_MENU; #ifdef QWS Config cfg( "sfcave" ); cfg.setGroup( "settings" ); cfg.writeEntry( "difficulty", currentGameDifficulty ); cfg.writeEntry( "gameType", currentGameType ); #endif break; } break; } case MENU_REPLAY_MENU: { switch( currentMenuOption[currentMenuNr] ) { case MENU_REPLAY_START: if ( currentSeed != 0 ) state = STATE_REPLAY; // Display No Replay break; case MENU_REPLAY_LOAD: loadReplay(); break; case MENU_REPLAY_SAVE: saveReplay(); break; case MENU_REPLAY_BACK: currentMenuNr = MENU_MAIN_MENU; break; } } } } diff --git a/noncore/settings/aqpkg/settingsimpl.cpp b/noncore/settings/aqpkg/settingsimpl.cpp index 7ffa1d6..0886e69 100644 --- a/noncore/settings/aqpkg/settingsimpl.cpp +++ b/noncore/settings/aqpkg/settingsimpl.cpp @@ -1,490 +1,490 @@ /* This file is part of the OPIE Project =. Copyright (c) 2002 Andy Qua <andy.qua@blueyonder.co.uk> .=l. Dan Williams <drw@handhelds.org> .>+-= _;:, .> :=|. This file is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This file is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU General ..}^=.= = ; Public License for more details. ++= -. .` .: : = ...= . :.=- You should have received a copy of the GNU -. .:....=;==+<; General Public License along with this file; -_. . . )=. = see the file COPYING. If not, write to the -- :-=` Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "settingsimpl.h" #include "global.h" /* OPIE */ #include <opie2/otabwidget.h> #include <opie2/oresource.h> #include <qpe/config.h> #include <qpe/qpeapplication.h> /* QT */ #include <qcheckbox.h> #include <qgroupbox.h> #include <qlabel.h> #include <qlayout.h> #include <qlineedit.h> #include <qlistbox.h> #include <qpushbutton.h> using namespace Opie::Ui; using namespace Opie::Ui; SettingsImpl :: SettingsImpl( DataManager *dataManager, QWidget * parent, const char* name, bool modal, WFlags fl ) : QDialog( parent, name, modal, fl ) { setCaption( tr( "Configuration" ) ); // Setup layout to make everything pretty QVBoxLayout *layout = new QVBoxLayout( this ); layout->setMargin( 2 ); layout->setSpacing( 4 ); // Setup tabs for all info OTabWidget *tabwidget = new OTabWidget( this ); layout->addWidget( tabwidget ); tabwidget->addTab( initServerTab(), "aqpkg/servertab", tr( "Servers" ) ); tabwidget->addTab( initDestinationTab(), "aqpkg/desttab", tr( "Destinations" ) ); tabwidget->addTab( initProxyTab(), "aqpkg/proxytab", tr( "Proxies" ) ); tabwidget->setCurrentTab( tr( "Servers" ) ); dataMgr = dataManager; setupData(); changed = false; newserver = false; newdestination = false; } SettingsImpl :: ~SettingsImpl() { } bool SettingsImpl :: showDlg() { QPEApplication::execDialog( this ); if ( changed ) dataMgr->writeOutIpkgConf(); return changed; } QWidget *SettingsImpl :: initServerTab() { QWidget *control = new QWidget( this ); QVBoxLayout *vb = new QVBoxLayout( control ); QScrollView *sv = new QScrollView( control ); vb->addWidget( sv, 0, 0 ); sv->setResizePolicy( QScrollView::AutoOneFit ); sv->setFrameStyle( QFrame::NoFrame ); QWidget *container = new QWidget( sv->viewport() ); sv->addChild( container ); QGridLayout *layout = new QGridLayout( container ); layout->setSpacing( 2 ); layout->setMargin( 4 ); servers = new QListBox( container ); servers->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) ); connect( servers, SIGNAL( highlighted(int) ), this, SLOT( editServer(int) ) ); layout->addMultiCellWidget( servers, 0, 0, 0, 1 ); QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ), tr( "New" ), container ); connect( btn, SIGNAL( clicked() ), this, SLOT( newServer() ) ); layout->addWidget( btn, 1, 0 ); btn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), tr( "Delete" ), container ); connect( btn, SIGNAL( clicked() ), this, SLOT( removeServer() ) ); layout->addWidget( btn, 1, 1 ); QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "Server" ), container ); grpbox->layout()->setSpacing( 2 ); grpbox->layout()->setMargin( 4 ); layout->addMultiCellWidget( grpbox, 2, 2, 0, 1 ); QGridLayout *grplayout = new QGridLayout( grpbox->layout() ); QLabel *label = new QLabel( tr( "Name:" ), grpbox ); grplayout->addWidget( label, 0, 0 ); servername = new QLineEdit( grpbox ); grplayout->addWidget( servername, 0, 1 ); label = new QLabel( tr( "Address:" ), grpbox ); grplayout->addWidget( label, 1, 0 ); serverurl = new QLineEdit( grpbox ); grplayout->addWidget( serverurl, 1, 1 ); active = new QCheckBox( tr( "Active Server" ), grpbox ); grplayout->addMultiCellWidget( active, 2, 2, 0, 1 ); btn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), tr( "Update" ), grpbox ); connect( btn, SIGNAL( clicked() ), this, SLOT( changeServerDetails() ) ); grplayout->addMultiCellWidget( btn, 3, 3, 0, 1 ); return control; } QWidget *SettingsImpl :: initDestinationTab() { QWidget *control = new QWidget( this ); QVBoxLayout *vb = new QVBoxLayout( control ); QScrollView *sv = new QScrollView( control ); vb->addWidget( sv, 0, 0 ); sv->setResizePolicy( QScrollView::AutoOneFit ); sv->setFrameStyle( QFrame::NoFrame ); QWidget *container = new QWidget( sv->viewport() ); sv->addChild( container ); QGridLayout *layout = new QGridLayout( container ); layout->setSpacing( 2 ); layout->setMargin( 4 ); destinations = new QListBox( container ); destinations->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) ); connect( destinations, SIGNAL( highlighted(int) ), this, SLOT( editDestination(int) ) ); layout->addMultiCellWidget( destinations, 0, 0, 0, 1 ); QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "new", Opie::Core::OResource::SmallIcon ), tr( "New" ), container ); connect( btn, SIGNAL( clicked() ), this, SLOT( newDestination() ) ); layout->addWidget( btn, 1, 0 ); btn = new QPushButton( Opie::Core::OResource::loadPixmap( "trash", Opie::Core::OResource::SmallIcon ), tr( "Delete" ), container ); connect( btn, SIGNAL( clicked() ), this, SLOT( removeDestination() ) ); layout->addWidget( btn, 1, 1 ); QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "Destination" ), container ); grpbox->layout()->setSpacing( 2 ); grpbox->layout()->setMargin( 4 ); layout->addMultiCellWidget( grpbox, 2, 2, 0, 1 ); QGridLayout *grplayout = new QGridLayout( grpbox->layout() ); QLabel *label = new QLabel( tr( "Name:" ), grpbox ); grplayout->addWidget( label, 0, 0 ); destinationname = new QLineEdit( grpbox ); grplayout->addWidget( destinationname, 0, 1 ); label = new QLabel( tr( "Location:" ), grpbox ); grplayout->addWidget( label, 1, 0 ); destinationurl = new QLineEdit( grpbox ); grplayout->addWidget( destinationurl, 1, 1 ); linkToRoot = new QCheckBox( tr( "Link to root" ), grpbox ); grplayout->addMultiCellWidget( linkToRoot, 2, 2, 0, 1 ); btn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), tr( "Update" ), grpbox ); connect( btn, SIGNAL( clicked() ), this, SLOT( changeDestinationDetails() ) ); grplayout->addMultiCellWidget( btn, 3, 3, 0, 1 ); return control; } QWidget *SettingsImpl :: initProxyTab() { QWidget *control = new QWidget( this ); QVBoxLayout *vb = new QVBoxLayout( control ); QScrollView *sv = new QScrollView( control ); vb->addWidget( sv, 0, 0 ); sv->setResizePolicy( QScrollView::AutoOneFit ); sv->setFrameStyle( QFrame::NoFrame ); QWidget *container = new QWidget( sv->viewport() ); sv->addChild( container ); QGridLayout *layout = new QGridLayout( container ); layout->setSpacing( 2 ); layout->setMargin( 4 ); QGroupBox *grpbox = new QGroupBox( 0, Qt::Vertical, tr( "HTTP Proxy" ), container ); grpbox->layout()->setSpacing( 2 ); grpbox->layout()->setMargin( 4 ); layout->addMultiCellWidget( grpbox, 0, 0, 0, 1 ); QVBoxLayout *grplayout = new QVBoxLayout( grpbox->layout() ); txtHttpProxy = new QLineEdit( grpbox ); grplayout->addWidget( txtHttpProxy ); chkHttpProxyEnabled = new QCheckBox( tr( "Enabled" ), grpbox ); grplayout->addWidget( chkHttpProxyEnabled ); grpbox = new QGroupBox( 0, Qt::Vertical, tr( "FTP Proxy" ), container ); grpbox->layout()->setSpacing( 2 ); grpbox->layout()->setMargin( 4 ); layout->addMultiCellWidget( grpbox, 1, 1, 0, 1 ); grplayout = new QVBoxLayout( grpbox->layout() ); txtFtpProxy = new QLineEdit( grpbox ); grplayout->addWidget( txtFtpProxy ); chkFtpProxyEnabled = new QCheckBox( tr( "Enabled" ), grpbox ); grplayout->addWidget( chkFtpProxyEnabled ); QLabel *label = new QLabel( tr( "Username:" ), container ); layout->addWidget( label, 2, 0 ); txtUsername = new QLineEdit( container ); layout->addWidget( txtUsername, 2, 1 ); label = new QLabel( tr( "Password:" ), container ); layout->addWidget( label, 3, 0 ); txtPassword = new QLineEdit( container ); layout->addWidget( txtPassword, 3, 1 ); QPushButton *btn = new QPushButton( Opie::Core::OResource::loadPixmap( "edit", Opie::Core::OResource::SmallIcon ), tr( "Update" ), container ); connect( btn, SIGNAL( clicked() ), this, SLOT( proxyApplyChanges() ) ); layout->addMultiCellWidget( btn, 4, 4, 0, 1 ); return control; } void SettingsImpl :: setupData() { // add servers QString serverName; QListIterator<Server> it( dataMgr->getServerList() ); for ( ; it.current(); ++it ) { serverName = it.current()->getServerName(); if ( serverName == LOCAL_SERVER || serverName == LOCAL_IPKGS ) continue; servers->insertItem( serverName ); } // add destinations QListIterator<Destination> it2( dataMgr->getDestinationList() ); for ( ; it2.current(); ++it2 ) destinations->insertItem( it2.current()->getDestinationName() ); // setup proxy tab txtHttpProxy->setText( dataMgr->getHttpProxy() ); txtFtpProxy->setText( dataMgr->getFtpProxy() ); txtUsername->setText( dataMgr->getProxyUsername() ); txtPassword->setText( dataMgr->getProxyPassword() ); chkHttpProxyEnabled->setChecked( dataMgr->getHttpProxyEnabled() ); chkFtpProxyEnabled->setChecked( dataMgr->getFtpProxyEnabled() ); } //------------------ Servers tab ---------------------- void SettingsImpl :: editServer( int sel ) { currentSelectedServer = sel; Server *s = dataMgr->getServer( servers->currentText() ); if ( s ) { serverName = s->getServerName(); servername->setText( s->getServerName() ); serverurl->setText( s->getServerUrl() ); active->setChecked( s->isServerActive() ); } else { serverName = ""; servername->setText( "" ); serverurl->setText( "" ); active->setChecked( false ); } } void SettingsImpl :: newServer() { newserver = true; servername->setText( "" ); serverurl->setText( "" ); servername->setFocus(); active->setChecked( true ); } void SettingsImpl :: removeServer() { changed = true; Server *s = dataMgr->getServer( servers->currentText() ); if ( s ) { dataMgr->getServerList().removeRef( s ); servers->removeItem( currentSelectedServer ); } } void SettingsImpl :: changeServerDetails() { changed = true; QString newName = servername->text(); // Convert any spaces to underscores char *tmpStr = new char[newName.length() + 1]; for ( unsigned int i = 0 ; i < newName.length() ; ++i ) { if ( newName[i] == ' ' ) tmpStr[i] = '_'; else tmpStr[i] = newName[i].latin1(); } tmpStr[newName.length()] = '\0'; newName = tmpStr; - delete tmpStr; + delete [] tmpStr; if ( !newserver ) { Server *s = dataMgr->getServer( servers->currentText() ); if ( s ) { // Update url s->setServerUrl( serverurl->text() ); s->setActive( active->isChecked() ); // Check if server name has changed, if it has then we need to replace the key in the map if ( serverName != newName ) { // Update server name s->setServerName( newName ); } // Update list box servers->changeItem( newName, currentSelectedServer ); } } else { Server s( newName, serverurl->text() ); dataMgr->getServerList().append( new Server( newName, serverurl->text() ) ); dataMgr->getServerList().last()->setActive( active->isChecked() ); servers->insertItem( newName ); servers->setCurrentItem( servers->count() ); newserver = false; } } //------------------ Destinations tab ---------------------- void SettingsImpl :: editDestination( int sel ) { currentSelectedDestination = sel; Destination *d = dataMgr->getDestination( destinations->currentText() ); if ( d ) { destinationName = d->getDestinationName(); destinationname->setText( d->getDestinationName() ); destinationurl->setText( d->getDestinationPath() ); linkToRoot->setChecked( d->linkToRoot() ); } else { destinationName = ""; destinationname->setText( "" ); destinationurl->setText( "" ); linkToRoot->setChecked( false ); } } void SettingsImpl :: newDestination() { newdestination = true; destinationname->setText( "" ); destinationurl->setText( "" ); destinationname->setFocus(); linkToRoot->setChecked( true ); } void SettingsImpl :: removeDestination() { changed = true; Destination *d = dataMgr->getDestination( destinations->currentText() ); if ( d ) { dataMgr->getDestinationList().removeRef( d ); destinations->removeItem( currentSelectedDestination ); } } void SettingsImpl :: changeDestinationDetails() { changed = true; #ifdef QWS Config cfg( "aqpkg" ); cfg.setGroup( "destinations" ); #endif QString newName = destinationname->text(); if ( !newdestination ) { Destination *d = dataMgr->getDestination( destinations->currentText() ); if ( d ) { // Update url d->setDestinationPath( destinationurl->text() ); d->linkToRoot( linkToRoot->isChecked() ); // Check if server name has changed, if it has then we need to replace the key in the map if ( destinationName != newName ) { // Update server name d->setDestinationName( newName ); // Update list box destinations->changeItem( newName, currentSelectedDestination ); } #ifdef QWS QString key = newName; key += "_linkToRoot"; int val = d->linkToRoot(); cfg.writeEntry( key, val ); #endif } } else { dataMgr->getDestinationList().append( new Destination( newName, destinationurl->text() ) ); destinations->insertItem( newName ); destinations->setCurrentItem( destinations->count() ); newdestination = false; #ifdef QWS QString key = newName; key += "_linkToRoot"; cfg.writeEntry( key, true ); #endif } } //------------------ Proxy tab ---------------------- void SettingsImpl :: proxyApplyChanges() { changed = true; dataMgr->setHttpProxy( txtHttpProxy->text() ); dataMgr->setFtpProxy( txtFtpProxy->text() ); dataMgr->setProxyUsername( txtUsername->text() ); dataMgr->setProxyPassword( txtPassword->text() ); dataMgr->setHttpProxyEnabled( chkHttpProxyEnabled->isChecked() ); dataMgr->setFtpProxyEnabled( chkFtpProxyEnabled->isChecked() ); } diff --git a/noncore/settings/aqpkg/version.cpp b/noncore/settings/aqpkg/version.cpp index 59e6f3f..ce2de7b 100644 --- a/noncore/settings/aqpkg/version.cpp +++ b/noncore/settings/aqpkg/version.cpp @@ -1,219 +1,219 @@ /* * libdpkg - Debian packaging suite library routines * vercmp.c - comparison of version numbers * * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk> * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with dpkg; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <qobject.h> //# define _(Text) Text class versionrevision { public: versionrevision() { version = 0; } ~versionrevision() { if ( version ) - delete version; + delete [] version; } void setVersion( const char *str ) { version = new char[(strlen(str)+1)]; strcpy( version, str ); } unsigned long epoch; char *version; const char *revision; const char *familiar_revision; }; static int verrevcmp(const char *val, const char *ref) { int vc, rc; long vl, rl; const char *vp, *rp; if (!val) val= ""; if (!ref) ref= ""; for (;;) { vp= val; while (*vp && !isdigit(*vp)) vp++; rp= ref; while (*rp && !isdigit(*rp)) rp++; for (;;) { vc= val == vp ? 0 : *val++; rc= ref == rp ? 0 : *ref++; if (!rc && !vc) break; if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */ if (rc && !isalpha(rc)) rc += 256; if (vc != rc) return vc - rc; } val= vp; ref= rp; vl=0; if (isdigit(*vp)) vl= strtol(val,(char**)&val,10); rl=0; if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10); if (vl != rl) return vl - rl; if (!*val && !*ref) return 0; if (!*val) return -1; if (!*ref) return +1; } } int versioncompare(const struct versionrevision *version, const struct versionrevision *refversion) { int r; if (version->epoch > refversion->epoch) return 1; if (version->epoch < refversion->epoch) return -1; r= verrevcmp(version->version,refversion->version); if (r) return r; r= verrevcmp(version->revision,refversion->revision); if (r) return r; return verrevcmp(version->familiar_revision,refversion->familiar_revision); } int versionsatisfied3(const struct versionrevision *it, const struct versionrevision *ref, const char *op) { int r; r= versioncompare(it,ref); if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) return r <= 0; if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) return r >= 0; if (strcmp(op, "<<") == 0) return r < 0; if (strcmp(op, ">>") == 0) return r > 0; if (strcmp(op, "=") == 0) return r == 0; // fprintf(stderr, "unknown operator: %s", op); exit(1); } const char *parseversion(struct versionrevision *rversion, const char *string) { char *hyphen, *colon, *eepochcolon; unsigned long epoch; if ( !*string ) return QObject::tr( "Version string is empty." ); colon= strchr(string,':'); if (colon) { epoch= strtoul(string,&eepochcolon,10); if ( colon != eepochcolon ) return QObject::tr( "Epoch in version is not number." ); if ( !*++colon ) return QObject::tr( "Nothing after colon in version number." ); string= colon; rversion->epoch= epoch; } else { rversion->epoch= 0; } rversion->revision = ""; rversion->familiar_revision = ""; rversion->setVersion( string ); hyphen= strrchr(rversion->version,'-'); if (hyphen) { *hyphen++= 0; if (strncmp("fam", hyphen, 3) == 0) { rversion->familiar_revision=hyphen+3; hyphen= strrchr(rversion->version,'-'); if (hyphen) { *hyphen++= 0; rversion->revision = hyphen; } } else { rversion->revision = hyphen; } } /* fprintf(stderr,"Parsed version: %lu, %s, %s, %s\n", rversion->epoch, rversion->version, rversion->revision, rversion->familiar_revision); */ return 0; } int compareVersions( const char *v1, const char *v2 ) { const char *err; versionrevision ver, ref; err = parseversion(&ref, v1); if (err) { // fprintf(stderr, "Invalid version `%s': %s\n", v2, err); return -2; } err = parseversion(&ver, v2); if (err) { // fprintf(stderr, "Invalid version `%s': %s\n", v1, err); return -2; } if ( versionsatisfied3( &ver, &ref, "=" ) ) return 0; else if ( versionsatisfied3( &ver, &ref, "<" ) ) return -1; else return 1; } /* int main(int argc, char *argv[]) { const char *err; versionrevision ver, ref; if (argc < 4) { fprintf(stderr, "usage: %s: version op refversion\n", argv[0]); return 2; } err = parseversion(&ver, argv[1]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err); return 2; } err = parseversion(&ref, argv[3]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err); return 2; } printf( "Result: %d\n", versionsatisfied3(&ver, &ref, argv[2]) ); } */ |