author | erik <erik> | 2007-01-19 01:12:38 (UTC) |
---|---|---|
committer | erik <erik> | 2007-01-19 01:12:38 (UTC) |
commit | 1ab92f1d2b346de7da8ca5c3aaa6bc75b43981e7 (patch) (side-by-side diff) | |
tree | af4a12bc46e25853386dc53868b869e1bf05d863 /core | |
parent | 2b45dc71e79a3eb7d4e8553273c9bc4f4282d50a (diff) | |
download | opie-1ab92f1d2b346de7da8ca5c3aaa6bc75b43981e7.zip opie-1ab92f1d2b346de7da8ca5c3aaa6bc75b43981e7.tar.gz opie-1ab92f1d2b346de7da8ca5c3aaa6bc75b43981e7.tar.bz2 |
Every single file in this commit had a memory leak where a resource is
allocated in the constructor but not de-allocated in the destructor.
This commit fixes that.
-rw-r--r-- | core/apps/embeddedkonsole/TEScreen.cpp | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/core/apps/embeddedkonsole/TEScreen.cpp b/core/apps/embeddedkonsole/TEScreen.cpp index 1db34d2..30ff49d 100644 --- a/core/apps/embeddedkonsole/TEScreen.cpp +++ b/core/apps/embeddedkonsole/TEScreen.cpp @@ -1,186 +1,186 @@ /* -------------------------------------------------------------------------- */ /* */ /* [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) +TEScreen::TEScreen(int _lines, int _columns) : + lines(_lines), + columns(_columns), + tabstops(0), + histCursor(0), + horzCursor(0) { - this->lines = lines; - this->columns = columns; // odebug << "Columns " << columns << "" << oendl; - image = (ca*) malloc(lines*columns*sizeof(ca)); - tabstops = NULL; initTabStops(); - - histCursor = 0; - horzCursor = 0; + image = new ca[lines*columns]; + initTabStops(); clearSelection(); reset(); } /*! Destructor */ TEScreen::~TEScreen() { - free(image); - if (tabstops) free(tabstops); + delete [] image; + delete [] 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; @@ -303,421 +303,423 @@ void TEScreen::insertLines(int 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)); + ca* newimg = new ca[new_lines * new_columns]; 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); + delete [] 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* merged = new ca[lines*columns]; 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)); + if (tabstops) + delete [] tabstops; + + tabstops = new bool[columns]; // 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),' '); } |