diff options
Diffstat (limited to 'client/browser/qtermwidget/src/Screen.cpp')
-rw-r--r-- | client/browser/qtermwidget/src/Screen.cpp | 1567 |
1 files changed, 0 insertions, 1567 deletions
diff --git a/client/browser/qtermwidget/src/Screen.cpp b/client/browser/qtermwidget/src/Screen.cpp deleted file mode 100644 index ead0066a..00000000 --- a/client/browser/qtermwidget/src/Screen.cpp +++ /dev/null @@ -1,1567 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> - - Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008 - - 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. - - 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA. -*/ - -// Own -#include "Screen.h" - -// Standard -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <assert.h> -#include <string.h> -#include <ctype.h> - -// Qt -#include <QtCore/QTextStream> -#include <QtCore/QDate> - -// Konsole -#include "konsole_wcwidth.h" -#include "TerminalCharacterDecoder.h" - -using namespace Konsole; - -//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 - -//Macro to convert x,y position on screen to position within an image. -// -//Originally the image was stored as one large contiguous block of -//memory, so a position within the image could be represented as an -//offset from the beginning of the block. For efficiency reasons this -//is no longer the case. -//Many internal parts of this class still use this representation for parameters and so on, -//notably moveImage() and clearImage(). -//This macro converts from an X,Y position into an image offset. -#ifndef loc -#define loc(X,Y) ((Y)*columns+(X)) -#endif - - -Character Screen::defaultChar = Character(' ', - CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR), - CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR), - DEFAULT_RENDITION); - -//#define REVERSE_WRAPPED_LINES // for wrapped line debug - -Screen::Screen(int l, int c) - : lines(l), - columns(c), - screenLines(new ImageLine[lines+1] ), - _scrolledLines(0), - _droppedLines(0), - hist(new HistoryScrollNone()), - cuX(0), cuY(0), - cu_re(0), - tmargin(0), bmargin(0), - tabstops(0), - sel_begin(0), sel_TL(0), sel_BR(0), - sel_busy(false), - columnmode(false), - ef_fg(CharacterColor()), ef_bg(CharacterColor()), ef_re(0), - sa_cuX(0), sa_cuY(0), - sa_cu_re(0), - lastPos(-1) -{ - lineProperties.resize(lines+1); - for (int i=0;i<lines+1;i++) - lineProperties[i]=LINE_DEFAULT; - - initTabStops(); - clearSelection(); - reset(); -} - -/*! Destructor -*/ - -Screen::~Screen() -{ - delete[] screenLines; - delete[] tabstops; - delete hist; -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* 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 Screen::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 Screen::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 Screen::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 Screen::cursorRight(int n) -//=CUF -{ - if (n == 0) n = 1; // Default - cuX = qMin(columns-1,cuX+n); -} - -void Screen::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 ) ) - { qDebug()<<" setRegion("<<top<<","<<bot<<") : bad range."; - return; // Default error action: ignore - } - tmargin = top; - bmargin = bot; - cuX = 0; - cuY = getMode(MODE_Origin) ? top : 0; - -} - -int Screen::topMargin() const -{ - return tmargin; -} -int Screen::bottomMargin() const -{ - return bmargin; -} - -void Screen::index() -//=IND -{ - if (cuY == bmargin) - { - scrollUp(1); - } - else if (cuY < lines-1) - cuY += 1; -} - -void Screen::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 Screen::NextLine() -//=NEL -{ - Return(); index(); -} - -void Screen::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),' '); -} - -void Screen::deleteChars(int n) -{ - Q_ASSERT( n >= 0 ); - - // always delete at least one char - if (n == 0) - n = 1; - - // if cursor is beyond the end of the line there is nothing to do - if ( cuX >= screenLines[cuY].count() ) - return; - - if ( cuX+n >= screenLines[cuY].count() ) - n = screenLines[cuY].count() - 1 - cuX; - - Q_ASSERT( n >= 0 ); - Q_ASSERT( cuX+n < screenLines[cuY].count() ); - - screenLines[cuY].remove(cuX,n); -} - -void Screen::insertChars(int n) -{ - if (n == 0) n = 1; // Default - - if ( screenLines[cuY].size() < cuX ) - screenLines[cuY].resize(cuX); - - screenLines[cuY].insert(cuX,n,' '); - - if ( screenLines[cuY].count() > columns ) - screenLines[cuY].resize(columns); -} - -void Screen::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 Screen::insertLines(int n) -{ - if (n == 0) n = 1; // Default - scrollDown(cuY,n); -} - -// Mode Operations ----------------------------------------------------------- - -/*! Set a specific mode. */ - -void Screen::setMode(int m) -{ - currParm.mode[m] = true; - switch(m) - { - case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home - } -} - -/*! Reset a specific mode. */ - -void Screen::resetMode(int m) -{ - currParm.mode[m] = false; - switch(m) - { - case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home - } -} - -/*! Save a specific mode. */ - -void Screen::saveMode(int m) -{ - saveParm.mode[m] = currParm.mode[m]; -} - -/*! Restore a specific mode. */ - -void Screen::restoreMode(int m) -{ - currParm.mode[m] = saveParm.mode[m]; -} - -bool Screen::getMode(int m) const -{ - return currParm.mode[m]; -} - -void Screen::saveCursor() -{ - sa_cuX = cuX; - sa_cuY = cuY; - sa_cu_re = cu_re; - sa_cu_fg = cu_fg; - sa_cu_bg = cu_bg; -} - -void Screen::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 */ -/* */ -/* ------------------------------------------------------------------------- */ - -/*! Resize the screen image - - 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. - - If the new image is narrower than the old image then text on lines - which extends past the end of the new image is preserved so that it becomes - visible again if the screen is later resized to make it larger. -*/ - -void Screen::resizeImage(int new_lines, int new_columns) -{ - if ((new_lines==lines) && (new_columns==columns)) return; - - 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); - } - } - - // create new screen lines and copy from old to new - - ImageLine* newScreenLines = new ImageLine[new_lines+1]; - for (int i=0; i < qMin(lines-1,new_lines+1) ;i++) - newScreenLines[i]=screenLines[i]; - for (int i=lines;(i > 0) && (i<new_lines+1);i++) - newScreenLines[i].resize( new_columns ); - - lineProperties.resize(new_lines+1); - for (int i=lines;(i > 0) && (i<new_lines+1);i++) - lineProperties[i] = LINE_DEFAULT; - - clearSelection(); - - delete[] screenLines; - screenLines = newScreenLines; - - 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(); -} - -void Screen::setDefaultMargins() -{ - tmargin = 0; - bmargin = lines-1; -} - - -/* - Clarifying rendition here and in the display. - - currently, the display'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 TerminalDisplay'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 Screen::reverseRendition(Character& p) const -{ - CharacterColor f = p.foregroundColor; - CharacterColor b = p.backgroundColor; - - p.foregroundColor = b; - p.backgroundColor = f; //p->r &= ~RE_TRANSPARENT; -} - -void Screen::effectiveRendition() -// calculate rendition -{ - //copy "current rendition" straight into "effective rendition", which is then later copied directly - //into the image[] array which holds the characters and their appearance properties. - //- The old version below filtered out all attributes other than underline and blink at this stage, - //so that they would not be copied into the image[] array and hence would not be visible by TerminalDisplay - //which actually paints the screen using the information from the image[] array. - //I don't know why it did this, but I'm fairly sure it was the wrong thing to do. The net result - //was that bold text wasn't printed in bold by Konsole. - ef_re = cu_re; - - //OLD VERSION: - //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) - ef_fg.toggleIntensive(); -} - -/*! - 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. - -*/ - -void Screen::copyFromHistory(Character* dest, int startLine, int count) const -{ - Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= hist->getLines() ); - - for (int line = startLine; line < startLine + count; line++) - { - const int length = qMin(columns,hist->getLineLen(line)); - const int destLineOffset = (line-startLine)*columns; - - hist->getCells(line,0,length,dest + destLineOffset); - - for (int column = length; column < columns; column++) - dest[destLineOffset+column] = defaultChar; - - // invert selected text - if (sel_begin !=-1) - { - for (int column = 0; column < columns; column++) - { - if (isSelected(column,line)) - { - reverseRendition(dest[destLineOffset + column]); - } - } - } - } -} - -void Screen::copyFromScreen(Character* dest , int startLine , int count) const -{ - Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= lines ); - - for (int line = startLine; line < (startLine+count) ; line++) - { - int srcLineStartIndex = line*columns; - int destLineStartIndex = (line-startLine)*columns; - - for (int column = 0; column < columns; column++) - { - int srcIndex = srcLineStartIndex + column; - int destIndex = destLineStartIndex + column; - - dest[destIndex] = screenLines[srcIndex/columns].value(srcIndex%columns,defaultChar); - - // invert selected text - if (sel_begin != -1 && isSelected(column,line + hist->getLines())) - reverseRendition(dest[destIndex]); - } - - } -} - -void Screen::getImage( Character* dest, int size, int startLine, int endLine ) const -{ - Q_ASSERT( startLine >= 0 ); - Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines ); - - const int mergedLines = endLine - startLine + 1; - - Q_ASSERT( size >= mergedLines * columns ); - - const int linesInHistoryBuffer = qBound(0,hist->getLines()-startLine,mergedLines); - const int linesInScreenBuffer = mergedLines - linesInHistoryBuffer; - - // copy lines from history buffer - if (linesInHistoryBuffer > 0) { - copyFromHistory(dest,startLine,linesInHistoryBuffer); - } - - // copy lines from screen buffer - if (linesInScreenBuffer > 0) { - copyFromScreen(dest + linesInHistoryBuffer*columns, - startLine + linesInHistoryBuffer - hist->getLines(), - linesInScreenBuffer); - } - - // invert display when in screen mode - if (getMode(MODE_Screen)) - { - for (int i = 0; i < mergedLines*columns; i++) - reverseRendition(dest[i]); // for reverse display - } - - // mark the character at the current cursor position - int cursorIndex = loc(cuX, cuY + linesInHistoryBuffer); - if(getMode(MODE_Cursor) && cursorIndex < columns*mergedLines) - dest[cursorIndex].rendition |= RE_CURSOR; -} - -QVector<LineProperty> Screen::getLineProperties( int startLine , int endLine ) const -{ - Q_ASSERT( startLine >= 0 ); - Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines ); - - const int mergedLines = endLine-startLine+1; - const int linesInHistory = qBound(0,hist->getLines()-startLine,mergedLines); - const int linesInScreen = mergedLines - linesInHistory; - - QVector<LineProperty> result(mergedLines); - int index = 0; - - // copy properties for lines in history - for (int line = startLine; line < startLine + linesInHistory; line++) - { - //TODO Support for line properties other than wrapped lines - if (hist->isWrappedLine(line)) - { - result[index] = (LineProperty)(result[index] | LINE_WRAPPED); - } - index++; - } - - // copy properties for lines in screen buffer - const int firstScreenLine = startLine + linesInHistory - hist->getLines(); - for (int line = firstScreenLine; line < firstScreenLine+linesInScreen; line++) - { - result[index]=lineProperties[line]; - index++; - } - - return result; -} - -/*! -*/ - -void Screen::reset(bool clearScreen) -{ - 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(); - - if ( clearScreen ) - clear(); -} - -/*! Clear the entire screen and home the cursor. -*/ - -void Screen::clear() -{ - clearEntireScreen(); - home(); -} - -void Screen::BackSpace() -{ - cuX = qMin(columns-1,cuX); // nowrap! - cuX = qMax(0,cuX-1); - // if (BS_CLEARS) image[loc(cuX,cuY)].character = ' '; - - if (screenLines[cuY].size() < cuX+1) - screenLines[cuY].resize(cuX+1); - - if (BS_CLEARS) screenLines[cuY][cuX].character = ' '; -} - -void Screen::Tabulate(int n) -{ - // note that TAB is a format effector (does not write ' '); - if (n == 0) n = 1; - while((n > 0) && (cuX < columns-1)) - { - cursorRight(1); while((cuX < columns-1) && !tabstops[cuX]) cursorRight(1); - n--; - } -} - -void Screen::backTabulate(int n) -{ - // note that TAB is a format effector (does not write ' '); - if (n == 0) n = 1; - while((n > 0) && (cuX > 0)) - { - cursorLeft(1); while((cuX > 0) && !tabstops[cuX]) cursorLeft(1); - n--; - } -} - -void Screen::clearTabStops() -{ - for (int i = 0; i < columns; i++) tabstops[i] = false; -} - -void Screen::changeTabStop(bool set) -{ - if (cuX >= columns) return; - tabstops[cuX] = set; -} - -void Screen::initTabStops() -{ - 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 Screen::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 Screen::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 Screen::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. - - int w = konsole_wcwidth(c); - - if (w <= 0) - return; - - if (cuX+w > columns) { - if (getMode(MODE_Wrap)) { - lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | LINE_WRAPPED); - NextLine(); - } - else - cuX = columns-w; - } - - // ensure current line vector has enough elements - int size = screenLines[cuY].size(); - if (size == 0 && cuY > 0) - { - screenLines[cuY].resize( qMax(screenLines[cuY-1].size() , cuX+w) ); - } - else - { - if (size < cuX+w) - { - screenLines[cuY].resize(cuX+w); - } - } - - if (getMode(MODE_Insert)) insertChars(w); - - lastPos = loc(cuX,cuY); - - // check if selection is still valid. - checkSelection(cuX,cuY); - - Character& currentChar = screenLines[cuY][cuX]; - - currentChar.character = c; - currentChar.foregroundColor = ef_fg; - currentChar.backgroundColor = ef_bg; - currentChar.rendition = ef_re; - - int i = 0; - int newCursorX = cuX + w--; - while(w) - { - i++; - - if ( screenLines[cuY].size() < cuX + i + 1 ) - screenLines[cuY].resize(cuX+i+1); - - Character& ch = screenLines[cuY][cuX + i]; - ch.character = 0; - ch.foregroundColor = ef_fg; - ch.backgroundColor = ef_bg; - ch.rendition = ef_re; - - w--; - } - cuX = newCursorX; -} - -void Screen::compose(const QString& /*compose*/) -{ - Q_ASSERT( 0 /*Not implemented yet*/ ); - -/* if (lastPos == -1) - return; - - QChar c(image[lastPos].character); - compose.prepend(c); - //compose.compose(); ### FIXME! - image[lastPos].character = compose[0].unicode();*/ -} - -int Screen::scrolledLines() const -{ - return _scrolledLines; -} -int Screen::droppedLines() const -{ - return _droppedLines; -} -void Screen::resetDroppedLines() -{ - _droppedLines = 0; -} -void Screen::resetScrolledLines() -{ - //kDebug() << "scrolled lines reset"; - - _scrolledLines = 0; -} - -// Region commands ------------------------------------------------------------- - -void Screen::scrollUp(int n) -{ - if (n == 0) n = 1; // Default - if (tmargin == 0) addHistLine(); // hist.history - scrollUp(tmargin, n); -} - -/*! scroll up `n' lines within current region. - The `n' new lines are cleared. - \sa setRegion \sa scrollDown -*/ - -QRect Screen::lastScrolledRegion() const -{ - return _lastScrolledRegion; -} - -void Screen::scrollUp(int from, int n) -{ - if (n <= 0 || from + n > bmargin) return; - - _scrolledLines -= n; - _lastScrolledRegion = QRect(0,tmargin,columns-1,(bmargin-tmargin)); - - //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),' '); -} - -void Screen::scrollDown(int n) -{ - if (n == 0) n = 1; // Default - scrollDown(tmargin, n); -} - -/*! scroll down `n' lines within current region. - The `n' new lines are cleared. - \sa setRegion \sa scrollUp -*/ - -void Screen::scrollDown(int from, int n) -{ - - //kDebug() << "Screen::scrollDown( from: " << from << " , n: " << n << ")"; - - _scrolledLines += 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),' '); -} - -void Screen::setCursorYX(int y, int x) -{ - setCursorY(y); setCursorX(x); -} - -void Screen::setCursorX(int x) -{ - if (x == 0) x = 1; // Default - x -= 1; // Adjust - cuX = qMax(0,qMin(columns-1, x)); -} - -void Screen::setCursorY(int y) -{ - if (y == 0) y = 1; // Default - y -= 1; // Adjust - cuY = qMax(0,qMin(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) )); -} - -void Screen::home() -{ - cuX = 0; - cuY = 0; -} - -void Screen::Return() -{ - cuX = 0; -} - -int Screen::getCursorX() const -{ - return cuX; -} - -int Screen::getCursorY() const -{ - 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' (start) and `loce' (end) 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 Screen::clearImage(int loca, int loce, char c) -{ - 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(); - } - - int topLine = loca/columns; - int bottomLine = loce/columns; - - Character clearCh(c,cu_fg,cu_bg,DEFAULT_RENDITION); - - //if the character being used to clear the area is the same as the - //default character, the affected lines can simply be shrunk. - bool isDefaultCh = (clearCh == Character()); - - for (int y=topLine;y<=bottomLine;y++) - { - lineProperties[y] = 0; - - int endCol = ( y == bottomLine) ? loce%columns : columns-1; - int startCol = ( y == topLine ) ? loca%columns : 0; - - QVector<Character>& line = screenLines[y]; - - if ( isDefaultCh && endCol == columns-1 ) - { - line.resize(startCol); - } - else - { - if (line.size() < endCol + 1) - line.resize(endCol+1); - - Character* data = line.data(); - for (int i=startCol;i<=endCol;i++) - data[i]=clearCh; - } - } -} - -/*! move image between (including) `sourceBegin' and `sourceEnd' to 'dest'. - - The 'dest', 'sourceBegin' and 'sourceEnd' parameters can be generated using - the loc(column,line) macro. - -NOTE: moveImage() can only move whole lines. - - 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 Screen::moveImage(int dest, int sourceBegin, int sourceEnd) -{ - //kDebug() << "moving image from (" << (sourceBegin/columns) - // << "," << (sourceEnd/columns) << ") to " << - // (dest/columns); - - Q_ASSERT( sourceBegin <= sourceEnd ); - - int lines=(sourceEnd-sourceBegin)/columns; - - //move screen image and line properties: - //the source and destination areas of the image may overlap, - //so it matters that we do the copy in the right order - - //forwards if dest < sourceBegin or backwards otherwise. - //(search the web for 'memmove implementation' for details) - if (dest < sourceBegin) - { - for (int i=0;i<=lines;i++) - { - screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ]; - lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i]; - } - } - else - { - for (int i=lines;i>=0;i--) - { - screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ]; - lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i]; - } - } - - if (lastPos != -1) - { - int diff = dest - sourceBegin; // Scroll by this amount - lastPos += diff; - if ((lastPos < 0) || (lastPos >= (lines*columns))) - lastPos = -1; - } - - // Adjust selection to follow scroll. - if (sel_begin != -1) - { - bool beginIsTL = (sel_begin == sel_TL); - int diff = dest - sourceBegin; // Scroll by this amount - int scr_TL=loc(0,hist->getLines()); - int srca = sourceBegin+scr_TL; // Translate index from screen to global - int srce = sourceEnd+scr_TL; // Translate index from screen to global - int desta = srca+diff; - int deste = srce+diff; - - if ((sel_TL >= srca) && (sel_TL <= srce)) - sel_TL += diff; - else if ((sel_TL >= desta) && (sel_TL <= deste)) - sel_BR = -1; // Clear selection (see below) - - if ((sel_BR >= srca) && (sel_BR <= srce)) - sel_BR += diff; - else if ((sel_BR >= desta) && (sel_BR <= deste)) - sel_BR = -1; // Clear selection (see below) - - if (sel_BR < 0) - { - clearSelection(); - } - else - { - if (sel_TL < 0) - sel_TL = 0; - } - - if (beginIsTL) - sel_begin = sel_TL; - else - sel_begin = sel_BR; - } -} - -void Screen::clearToEndOfScreen() -{ - clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' '); -} - -void Screen::clearToBeginOfScreen() -{ - clearImage(loc(0,0),loc(cuX,cuY),' '); -} - -void Screen::clearEntireScreen() -{ - // Add entire screen to history - for (int i = 0; i < (lines-1); i++) - { - addHistLine(); scrollUp(0,1); - } - - clearImage(loc(0,0),loc(columns-1,lines-1),' '); -} - -/*! fill screen with 'E' - This is to aid screen alignment -*/ - -void Screen::helpAlign() -{ - clearImage(loc(0,0),loc(columns-1,lines-1),'E'); -} - -void Screen::clearToEndOfLine() -{ - clearImage(loc(cuX,cuY),loc(columns-1,cuY),' '); -} - -void Screen::clearToBeginOfLine() -{ - clearImage(loc(0,cuY),loc(cuX,cuY),' '); -} - -void Screen::clearEntireLine() -{ - clearImage(loc(0,cuY),loc(columns-1,cuY),' '); -} - -void Screen::setRendition(int re) -{ - cu_re |= re; - effectiveRendition(); -} - -void Screen::resetRendition(int re) -{ - cu_re &= ~re; - effectiveRendition(); -} - -void Screen::setDefaultRendition() -{ - setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR); - setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR); - cu_re = DEFAULT_RENDITION; - effectiveRendition(); -} - -void Screen::setForeColor(int space, int color) -{ - cu_fg = CharacterColor(space, color); - - if ( cu_fg.isValid() ) - effectiveRendition(); - else - setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR); -} - -void Screen::setBackColor(int space, int color) -{ - cu_bg = CharacterColor(space, color); - - if ( cu_bg.isValid() ) - effectiveRendition(); - else - setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR); -} - -/* ------------------------------------------------------------------------- */ -/* */ -/* Marking & Selection */ -/* */ -/* ------------------------------------------------------------------------- */ - -void Screen::clearSelection() -{ - sel_BR = -1; - sel_TL = -1; - sel_begin = -1; -} - -void Screen::getSelectionStart(int& column , int& line) -{ - if ( sel_TL != -1 ) - { - column = sel_TL % columns; - line = sel_TL / columns; - } - else - { - column = cuX + getHistLines(); - line = cuY + getHistLines(); - } -} -void Screen::getSelectionEnd(int& column , int& line) -{ - if ( sel_BR != -1 ) - { - column = sel_BR % columns; - line = sel_BR / columns; - } - else - { - column = cuX + getHistLines(); - line = cuY + getHistLines(); - } -} -void Screen::setSelectionStart(/*const ScreenCursor& viewCursor ,*/ const int x, const int y, const bool mode) -{ -// kDebug(1211) << "setSelBeginXY(" << x << "," << y << ")"; - sel_begin = loc(x,y); //+histCursor) ; - - /* FIXME, HACK to correct for x too far to the right... */ - if (x == columns) sel_begin--; - - sel_BR = sel_begin; - sel_TL = sel_begin; - columnmode = mode; -} - -void Screen::setSelectionEnd( const int x, const int y) -{ -// kDebug(1211) << "setSelExtentXY(" << x << "," << 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) l--; - - sel_TL = sel_begin; - sel_BR = l; - } -} - -bool Screen::isSelected( const int x,const int y) const -{ - if (columnmode) { - int sel_Left,sel_Right; - if ( sel_TL % columns < sel_BR % columns ) { - sel_Left = sel_TL; sel_Right = sel_BR; - } else { - sel_Left = sel_BR; sel_Right = sel_TL; - } - return ( x >= sel_Left % columns ) && ( x <= sel_Right % columns ) && - ( y >= sel_TL / columns ) && ( y <= sel_BR / columns ); - //( y+histCursor >= sel_TL / columns ) && ( y+histCursor <= sel_BR / columns ); - } - else { - //int pos = loc(x,y+histCursor); - int pos = loc(x,y); - return ( pos >= sel_TL && pos <= sel_BR ); - } -} - -QString Screen::selectedText(bool preserveLineBreaks) -{ - QString result; - QTextStream stream(&result, QIODevice::ReadWrite); - - PlainTextDecoder decoder; - decoder.begin(&stream); - writeSelectionToStream(&decoder , preserveLineBreaks); - decoder.end(); - - return result; -} - -bool Screen::isSelectionValid() const -{ - return ( sel_TL >= 0 && sel_BR >= 0 ); -} - -void Screen::writeSelectionToStream(TerminalCharacterDecoder* decoder , - bool preserveLineBreaks) -{ - // do nothing if selection is invalid - if ( !isSelectionValid() ) - return; - - int top = sel_TL / columns; - int left = sel_TL % columns; - - int bottom = sel_BR / columns; - int right = sel_BR % columns; - - Q_ASSERT( top >= 0 && left >= 0 && bottom >= 0 && right >= 0 ); - - //kDebug() << "sel_TL = " << sel_TL; - //kDebug() << "columns = " << columns; - - for (int y=top;y<=bottom;y++) - { - int start = 0; - if ( y == top || columnmode ) start = left; - - int count = -1; - if ( y == bottom || columnmode ) count = right - start + 1; - - const bool appendNewLine = ( y != bottom ); - copyLineToStream( y, - start, - count, - decoder, - appendNewLine, - preserveLineBreaks ); - } -} - - -void Screen::copyLineToStream(int line , - int start, - int count, - TerminalCharacterDecoder* decoder, - bool appendNewLine, - bool preserveLineBreaks) -{ - //buffer to hold characters for decoding - //the buffer is static to avoid initialising every - //element on each call to copyLineToStream - //(which is unnecessary since all elements will be overwritten anyway) - static const int MAX_CHARS = 1024; - static Character characterBuffer[MAX_CHARS]; - - assert( count < MAX_CHARS ); - - LineProperty currentLineProperties = 0; - - //determine if the line is in the history buffer or the screen image - if (line < hist->getLines()) - { - const int lineLength = hist->getLineLen(line); - - // ensure that start position is before end of line - start = qMin(start,qMax(0,lineLength-1)); - - //retrieve line from history buffer - if (count == -1) - { - count = lineLength-start; - } - else - { - count = qMin(start+count,lineLength)-start; - } - - // safety checks - assert( start >= 0 ); - assert( count >= 0 ); - assert( (start+count) <= hist->getLineLen(line) ); - - hist->getCells(line,start,count,characterBuffer); - - if ( hist->isWrappedLine(line) ) - currentLineProperties |= LINE_WRAPPED; - } - else - { - if ( count == -1 ) - count = columns - start; - - assert( count >= 0 ); - - const int screenLine = line-hist->getLines(); - - Character* data = screenLines[screenLine].data(); - int length = screenLines[screenLine].count(); - - //retrieve line from screen image - for (int i=start;i < qMin(start+count,length);i++) - { - characterBuffer[i-start] = data[i]; - } - - // count cannot be any greater than length - count = qBound(0,count,length-start); - - Q_ASSERT( screenLine < lineProperties.count() ); - currentLineProperties |= lineProperties[screenLine]; - } - - //do not decode trailing whitespace characters - for (int i=count-1 ; i >= 0; i--) - if (QChar(characterBuffer[i].character).isSpace()) - count--; - else - break; - - // add new line character at end - const bool omitLineBreak = (currentLineProperties & LINE_WRAPPED) || - !preserveLineBreaks; - - if ( !omitLineBreak && appendNewLine && (count+1 < MAX_CHARS) ) - { - characterBuffer[count] = '\n'; - count++; - } - - //decode line and write to text stream - decoder->decodeLine( (Character*) characterBuffer , - count, currentLineProperties ); -} - -// Method below has been removed because of its reliance on 'histCursor' -// and I want to restrict the methods which have knowledge of the scroll position -// to just those which deal with selection and supplying final screen images. -// -/*void Screen::writeToStream(QTextStream* stream , TerminalCharacterDecoder* decoder) { - sel_begin = 0; - sel_BR = sel_begin; - sel_TL = sel_begin; - setSelectionEnd(columns-1,lines-1+hist->getLines()-histCursor); - - writeSelectionToStream(stream,decoder); - - clearSelection(); -}*/ - -void Screen::writeToStream(TerminalCharacterDecoder* decoder, int from, int to) -{ - sel_begin = loc(0,from); - sel_TL = sel_begin; - sel_BR = loc(columns-1,to); - writeSelectionToStream(decoder); - clearSelection(); -} - -QString Screen::getHistoryLine(int no) -{ - sel_begin = loc(0,no); - sel_TL = sel_begin; - sel_BR = loc(columns-1,no); - return selectedText(false); -} - -void Screen::addHistLine() -{ - // add line to history buffer - // we have to take care about scrolling, too... - - if (hasScroll()) - { - int oldHistLines = hist->getLines(); - - hist->addCellsVector(screenLines[0]); - hist->addLine( lineProperties[0] & LINE_WRAPPED ); - - int newHistLines = hist->getLines(); - - bool beginIsTL = (sel_begin == sel_TL); - - // If the history is full, increment the count - // of dropped lines - if ( newHistLines == oldHistLines ) - _droppedLines++; - - // Adjust selection for the new point of reference - if (newHistLines > oldHistLines) - { - if (sel_begin != -1) - { - sel_TL += columns; - sel_BR += columns; - } - } - - if (sel_begin != -1) - { - // Scroll selection in history up - int top_BR = loc(0, 1+newHistLines); - - if (sel_TL < top_BR) - sel_TL -= columns; - - if (sel_BR < top_BR) - sel_BR -= columns; - - if (sel_BR < 0) - { - clearSelection(); - } - else - { - if (sel_TL < 0) - sel_TL = 0; - } - - if (beginIsTL) - sel_begin = sel_TL; - else - sel_begin = sel_BR; - } - } - -} - -int Screen::getHistLines() -{ - return hist->getLines(); -} - -void Screen::setScroll(const HistoryType& t , bool copyPreviousScroll) -{ - clearSelection(); - - if ( copyPreviousScroll ) - hist = t.scroll(hist); - else - { - HistoryScroll* oldScroll = hist; - hist = t.scroll(0); - delete oldScroll; - } -} - -bool Screen::hasScroll() -{ - return hist->hasScroll(); -} - -const HistoryType& Screen::getScroll() -{ - return hist->getType(); -} - -void Screen::setLineProperty(LineProperty property , bool enable) -{ - if ( enable ) - { - lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | property); - } - else - { - lineProperties[cuY] = (LineProperty)(lineProperties[cuY] & ~property); - } -} -void Screen::fillWithDefaultChar(Character* dest, int count) -{ - for (int i=0;i<count;i++) - dest[i] = defaultChar; -} |