File indexing completed on 2025-01-19 04:23:29

0001 /*
0002     This file is part of Konsole, KDE's terminal.
0003 
0004     Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
0005     Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
0006 
0007     This program is free software; you can redistribute it and/or modify
0008     it under the terms of the GNU General Public License as published by
0009     the Free Software Foundation; either version 2 of the License, or
0010     (at your option) any later version.
0011 
0012     This program is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015     GNU General Public License for more details.
0016 
0017     You should have received a copy of the GNU General Public License
0018     along with this program; if not, write to the Free Software
0019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0020     02110-1301  USA.
0021 */
0022 
0023 #ifndef SCREEN_H
0024 #define SCREEN_H
0025 
0026 // Qt
0027 #include <QRect>
0028 #include <QTextStream>
0029 #include <QVarLengthArray>
0030 
0031 // Konsole
0032 #include "Character.h"
0033 #include "History.h"
0034 
0035 #define MODE_Origin    0
0036 #define MODE_Wrap      1
0037 #define MODE_Insert    2
0038 #define MODE_Screen    3
0039 #define MODE_Cursor    4
0040 #define MODE_NewLine   5
0041 #define MODES_SCREEN   6
0042 
0043 namespace Konsole
0044 {
0045 
0046 class TerminalCharacterDecoder;
0047 
0048 /**
0049     \brief An image of characters with associated attributes.
0050 
0051     The terminal emulation ( Emulation ) receives a serial stream of
0052     characters from the program currently running in the terminal.
0053     From this stream it creates an image of characters which is ultimately
0054     rendered by the display widget ( TerminalDisplay ).  Some types of emulation
0055     may have more than one screen image.
0056 
0057     getImage() is used to retrieve the currently visible image
0058     which is then used by the display widget to draw the output from the
0059     terminal.
0060 
0061     The number of lines of output history which are kept in addition to the current
0062     screen image depends on the history scroll being used to store the output.
0063     The scroll is specified using setScroll()
0064     The output history can be retrieved using writeToStream()
0065 
0066     The screen image has a selection associated with it, specified using
0067     setSelectionStart() and setSelectionEnd().  The selected text can be retrieved
0068     using selectedText().  When getImage() is used to retrieve the visible image,
0069     characters which are part of the selection have their colours inverted.
0070 */
0071 class Screen
0072 {
0073 public:
0074     /** Construct a new screen image of size @p lines by @p columns. */
0075     Screen(int lines, int columns);
0076     ~Screen();
0077 
0078     // VT100/2 Operations
0079     // Cursor Movement
0080 
0081     /**
0082      * Move the cursor up by @p n lines.  The cursor will stop at the
0083      * top margin.
0084      */
0085     void cursorUp(int n);
0086     /**
0087      * Move the cursor down by @p n lines.  The cursor will stop at the
0088      * bottom margin.
0089      */
0090     void cursorDown(int n);
0091     /**
0092      * Move the cursor to the left by @p n columns.
0093      * The cursor will stop at the first column.
0094      */
0095     void cursorLeft(int n);
0096     /**
0097      * Move the cursor to the right by @p n columns.
0098      * The cursor will stop at the right-most column.
0099      */
0100     void cursorRight(int n);
0101     /** Position the cursor on line @p y. */
0102     void setCursorY(int y);
0103     /** Position the cursor at column @p x. */
0104     void setCursorX(int x);
0105     /** Position the cursor at line @p y, column @p x. */
0106     void setCursorYX(int y, int x);
0107     /**
0108      * Sets the margins for scrolling the screen.
0109      *
0110      * @param topLine The top line of the new scrolling margin.
0111      * @param bottomLine The bottom line of the new scrolling margin.
0112      */
0113     void setMargins(int topLine , int bottomLine);
0114     /** Returns the top line of the scrolling region. */
0115     int topMargin() const;
0116     /** Returns the bottom line of the scrolling region. */
0117     int bottomMargin() const;
0118 
0119     /**
0120      * Resets the scrolling margins back to the top and bottom lines
0121      * of the screen.
0122      */
0123     void setDefaultMargins();
0124 
0125     /**
0126      * Moves the cursor down one line, if the MODE_NewLine mode
0127      * flag is enabled then the cursor is returned to the leftmost
0128      * column first.
0129      *
0130      * Equivalent to NextLine() if the MODE_NewLine flag is set
0131      * or index() otherwise.
0132      */
0133     void newLine();
0134     /**
0135      * Moves the cursor down one line and positions it at the beginning
0136      * of the line.  Equivalent to calling Return() followed by index()
0137      */
0138     void nextLine();
0139 
0140     /**
0141      * Move the cursor down one line.  If the cursor is on the bottom
0142      * line of the scrolling region (as returned by bottomMargin()) the
0143      * scrolling region is scrolled up by one line instead.
0144      */
0145     void index();
0146     /**
0147      * Move the cursor up one line.  If the cursor is on the top line
0148      * of the scrolling region (as returned by topMargin()) the scrolling
0149      * region is scrolled down by one line instead.
0150      */
0151     void reverseIndex();
0152 
0153     /**
0154      * Scroll the scrolling region of the screen up by @p n lines.
0155      * The scrolling region is initially the whole screen, but can be changed
0156      * using setMargins()
0157      */
0158     void scrollUp(int n);
0159     /**
0160      * Scroll the scrolling region of the screen down by @p n lines.
0161      * The scrolling region is initially the whole screen, but can be changed
0162      * using setMargins()
0163      */
0164     void scrollDown(int n);
0165     /**
0166      * Moves the cursor to the beginning of the current line.
0167      * Equivalent to setCursorX(0)
0168      */
0169     void toStartOfLine();
0170     /**
0171      * Moves the cursor one column to the left and erases the character
0172      * at the new cursor position.
0173      */
0174     void backspace();
0175     /** Moves the cursor @p n tab-stops to the right. */
0176     void tab(int n = 1);
0177     /** Moves the cursor @p n tab-stops to the left. */
0178     void backtab(int n);
0179 
0180     // Editing
0181 
0182     /**
0183      * Erase @p n characters beginning from the current cursor position.
0184      * This is equivalent to over-writing @p n characters starting with the current
0185      * cursor position with spaces.
0186      * If @p n is 0 then one character is erased.
0187      */
0188     void eraseChars(int n);
0189     /**
0190      * Delete @p n characters beginning from the current cursor position.
0191      * If @p n is 0 then one character is deleted.
0192      */
0193     void deleteChars(int n);
0194     /**
0195      * Insert @p n blank characters beginning from the current cursor position.
0196      * The position of the cursor is not altered.
0197      * If @p n is 0 then one character is inserted.
0198      */
0199     void insertChars(int n);
0200     /**
0201      * Repeat the preceeding graphic character @count times, including SPACE.
0202      * If @count is 0 then the character is repeated once.
0203      */
0204     void repeatChars(int count);
0205     /**
0206      * Removes @p n lines beginning from the current cursor position.
0207      * The position of the cursor is not altered.
0208      * If @p n is 0 then one line is removed.
0209      */
0210     void deleteLines(int n);
0211     /**
0212      * Inserts @p lines beginning from the current cursor position.
0213      * The position of the cursor is not altered.
0214      * If @p n is 0 then one line is inserted.
0215      */
0216     void insertLines(int n);
0217     /** Clears all the tab stops. */
0218     void clearTabStops();
0219     /**  Sets or removes a tab stop at the cursor's current column. */
0220     void changeTabStop(bool set);
0221 
0222     /** Resets (clears) the specified screen @p mode. */
0223     void resetMode(int mode);
0224     /** Sets (enables) the specified screen @p mode. */
0225     void setMode(int mode);
0226     /**
0227      * Saves the state of the specified screen @p mode.  It can be restored
0228      * using restoreMode()
0229      */
0230     void saveMode(int mode);
0231     /** Restores the state of a screen @p mode saved by calling saveMode() */
0232     void restoreMode(int mode);
0233     /** Returns whether the specified screen @p mode is enabled or not .*/
0234     bool getMode(int mode) const;
0235 
0236     /**
0237      * Saves the current position and appearance (text color and style) of the cursor.
0238      * It can be restored by calling restoreCursor()
0239      */
0240     void saveCursor();
0241     /** Restores the position and appearance of the cursor.  See saveCursor() */
0242     void restoreCursor();
0243 
0244     /** Clear the whole screen, moving the current screen contents into the history first. */
0245     void clearEntireScreen();
0246     /**
0247      * Clear the area of the screen from the current cursor position to the end of
0248      * the screen.
0249      */
0250     void clearToEndOfScreen();
0251     /**
0252      * Clear the area of the screen from the current cursor position to the start
0253      * of the screen.
0254      */
0255     void clearToBeginOfScreen();
0256     /** Clears the whole of the line on which the cursor is currently positioned. */
0257     void clearEntireLine();
0258     /** Clears from the current cursor position to the end of the line. */
0259     void clearToEndOfLine();
0260     /** Clears from the current cursor position to the beginning of the line. */
0261     void clearToBeginOfLine();
0262 
0263     /** Fills the entire screen with the letter 'E' */
0264     void helpAlign();
0265 
0266     /**
0267      * Enables the given @p rendition flag.  Rendition flags control the appearance
0268      * of characters on the screen.
0269      *
0270      * @see Character::rendition
0271      */
0272     void setRendition(int rendition);
0273     /**
0274      * Disables the given @p rendition flag.  Rendition flags control the appearance
0275      * of characters on the screen.
0276      *
0277      * @see Character::rendition
0278      */
0279     void resetRendition(int rendition);
0280 
0281     /**
0282      * Sets the cursor's foreground color.
0283      * @param space The color space used by the @p color argument
0284      * @param color The new foreground color.  The meaning of this depends on
0285      * the color @p space used.
0286      *
0287      * @see CharacterColor
0288      */
0289     void setForeColor(int space, int color);
0290     /**
0291      * Sets the cursor's background color.
0292      * @param space The color space used by the @p color argumnet.
0293      * @param color The new background color.  The meaning of this depends on
0294      * the color @p space used.
0295      *
0296      * @see CharacterColor
0297      */
0298     void setBackColor(int space, int color);
0299     /**
0300      * Resets the cursor's color back to the default and sets the
0301      * character's rendition flags back to the default settings.
0302      */
0303     void setDefaultRendition();
0304 
0305     /** Returns the column which the cursor is positioned at. */
0306     int  getCursorX() const;
0307     /** Returns the line which the cursor is positioned on. */
0308     int  getCursorY() const;
0309 
0310     /** Clear the entire screen and move the cursor to the home position.
0311      * Equivalent to calling clearEntireScreen() followed by home().
0312      */
0313     void clear();
0314     /**
0315      * Sets the position of the cursor to the 'home' position at the top-left
0316      * corner of the screen (0,0)
0317      */
0318     void home();
0319     /**
0320      * Resets the state of the screen.  This resets the various screen modes
0321      * back to their default states.  The cursor style and colors are reset
0322      * (as if setDefaultRendition() had been called)
0323      *
0324      * <ul>
0325      * <li>Line wrapping is enabled.</li>
0326      * <li>Origin mode is disabled.</li>
0327      * <li>Insert mode is disabled.</li>
0328      * <li>Cursor mode is enabled.  TODO Document me</li>
0329      * <li>Screen mode is disabled. TODO Document me</li>
0330      * <li>New line mode is disabled.  TODO Document me</li>
0331      * </ul>
0332      *
0333      * If @p clearScreen is true then the screen contents are erased entirely,
0334      * otherwise they are unaltered.
0335      */
0336     void reset(bool clearScreen = true);
0337 
0338     /**
0339      * Displays a new character at the current cursor position.
0340      *
0341      * If the cursor is currently positioned at the right-edge of the screen and
0342      * line wrapping is enabled then the character is added at the start of a new
0343      * line below the current one.
0344      *
0345      * If the MODE_Insert screen mode is currently enabled then the character
0346      * is inserted at the current cursor position, otherwise it will replace the
0347      * character already at the current cursor position.
0348      */
0349     void displayCharacter(wchar_t c);
0350 
0351     // Do composition with last shown character FIXME: Not implemented yet for KDE 4
0352     void compose(const QString& compose);
0353 
0354     /**
0355      * Resizes the image to a new fixed size of @p new_lines by @p new_columns.
0356      * In the case that @p new_columns is smaller than the current number of columns,
0357      * existing lines are not truncated.  This prevents characters from being lost
0358      * if the terminal display is resized smaller and then larger again.
0359      *
0360      * The top and bottom margins are reset to the top and bottom of the new
0361      * screen size.  Tab stops are also reset and the current selection is
0362      * cleared.
0363      */
0364     void resizeImage(int new_lines, int new_columns);
0365 
0366     /**
0367      * Returns the current screen image.
0368      * The result is an array of Characters of size [getLines()][getColumns()] which
0369      * must be freed by the caller after use.
0370      *
0371      * @param dest Buffer to copy the characters into
0372      * @param size Size of @p dest in Characters
0373      * @param startLine Index of first line to copy
0374      * @param endLine Index of last line to copy
0375      */
0376     void getImage( Character* dest , int size , int startLine , int endLine ) const;
0377 
0378     /**
0379      * Returns the additional attributes associated with lines in the image.
0380      * The most important attribute is LINE_WRAPPED which specifies that the
0381      * line is wrapped,
0382      * other attributes control the size of characters in the line.
0383      */
0384     QVector<LineProperty> getLineProperties( int startLine , int endLine ) const;
0385 
0386 
0387     /** Return the number of lines. */
0388     int getLines() const
0389     { return lines; }
0390     /** Return the number of columns. */
0391     int getColumns() const
0392     { return columns; }
0393     /** Return the number of lines in the history buffer. */
0394     int getHistLines() const;
0395     /**
0396      * Sets the type of storage used to keep lines in the history.
0397      * If @p copyPreviousScroll is true then the contents of the previous
0398      * history buffer are copied into the new scroll.
0399      */
0400     void setScroll(const HistoryType& , bool copyPreviousScroll = true);
0401     /** Returns the type of storage used to keep lines in the history. */
0402     const HistoryType& getScroll() const;
0403     /**
0404      * Returns true if this screen keeps lines that are scrolled off the screen
0405      * in a history buffer.
0406      */
0407     bool hasScroll() const;
0408 
0409     /**
0410      * Sets the start of the selection.
0411      *
0412      * @param column The column index of the first character in the selection.
0413      * @param line The line index of the first character in the selection.
0414      * @param blockSelectionMode True if the selection is in column mode.
0415      */
0416     void setSelectionStart(const int column, const int line, const bool blockSelectionMode);
0417 
0418     /**
0419      * Sets the end of the current selection.
0420      *
0421      * @param column The column index of the last character in the selection.
0422      * @param line The line index of the last character in the selection.
0423      */
0424     void setSelectionEnd(const int column, const int line);
0425 
0426     void selectAll();
0427 
0428     /**
0429      * Retrieves the start of the selection or the cursor position if there
0430      * is no selection.
0431      */
0432     void getSelectionStart(int& column , int& line) const;
0433 
0434     /**
0435      * Retrieves the end of the selection or the cursor position if there
0436      * is no selection.
0437      */
0438     void getSelectionEnd(int& column , int& line) const;
0439 
0440     /** Clears the current selection */
0441     void clearSelection();
0442 
0443     /**
0444       *  Returns true if the character at (@p column, @p line) is part of the
0445       *  current selection.
0446       */
0447     bool isSelected(const int column,const int line) const;
0448 
0449     /**
0450      * Convenience method.  Returns the currently selected text.
0451      * @param preserveLineBreaks Specifies whether new line characters should
0452      * be inserted into the returned text at the end of each terminal line.
0453      */
0454     QString selectedText(bool preserveLineBreaks) const;
0455 
0456     /**
0457      * Copies part of the output to a stream.
0458      *
0459      * @param decoder A decoder which converts terminal characters into text
0460      * @param fromLine The first line in the history to retrieve
0461      * @param toLine The last line in the history to retrieve
0462      */
0463     void writeLinesToStream(TerminalCharacterDecoder* decoder, int fromLine, int toLine) const;
0464 
0465     /**
0466      * Copies the selected characters, set using @see setSelBeginXY and @see setSelExtentXY
0467      * into a stream.
0468      *
0469      * @param decoder A decoder which converts terminal characters into text.
0470      * PlainTextDecoder is the most commonly used decoder which converts characters
0471      * into plain text with no formatting.
0472      * @param preserveLineBreaks Specifies whether new line characters should
0473      * be inserted into the returned text at the end of each terminal line.
0474      */
0475     void writeSelectionToStream(TerminalCharacterDecoder* decoder , bool
0476                                 preserveLineBreaks = true) const;
0477 
0478     /**
0479      * Checks if the text between from and to is inside the current
0480      * selection. If this is the case, the selection is cleared. The
0481      * from and to are coordinates in the current viewable window.
0482      * The loc(x,y) macro can be used to generate these values from a
0483      * column,line pair.
0484      *
0485      * @param from The start of the area to check.
0486      * @param to The end of the area to check
0487      */
0488     void checkSelection(int from, int to);
0489 
0490     /**
0491      * Sets or clears an attribute of the current line.
0492      *
0493      * @param property The attribute to set or clear
0494      * Possible properties are:
0495      * LINE_WRAPPED:     Specifies that the line is wrapped.
0496      * LINE_DOUBLEWIDTH: Specifies that the characters in the current line
0497      *                   should be double the normal width.
0498      * LINE_DOUBLEHEIGHT:Specifies that the characters in the current line
0499      *                   should be double the normal height.
0500      *                   Double-height lines are formed of two lines containing the same characters,
0501      *                   with both having the LINE_DOUBLEHEIGHT attribute.
0502      *                   This allows other parts of the code to work on the
0503      *                   assumption that all lines are the same height.
0504      *
0505      * @param enable true to apply the attribute to the current line or false to remove it
0506      */
0507     void setLineProperty(LineProperty property , bool enable);
0508 
0509     /**
0510      * Returns the number of lines that the image has been scrolled up or down by,
0511      * since the last call to resetScrolledLines().
0512      *
0513      * a positive return value indicates that the image has been scrolled up,
0514      * a negative return value indicates that the image has been scrolled down.
0515      */
0516     int scrolledLines() const;
0517 
0518     /**
0519      * Returns the region of the image which was last scrolled.
0520      *
0521      * This is the area of the image from the top margin to the
0522      * bottom margin when the last scroll occurred.
0523      */
0524     QRect lastScrolledRegion() const;
0525 
0526     /**
0527      * Resets the count of the number of lines that the image has been scrolled up or down by,
0528      * see scrolledLines()
0529      */
0530     void resetScrolledLines();
0531 
0532     /**
0533      * Returns the number of lines of output which have been
0534      * dropped from the history since the last call
0535      * to resetDroppedLines()
0536      *
0537      * If the history is not unlimited then it will drop
0538      * the oldest lines of output if new lines are added when
0539      * it is full.
0540      */
0541     int droppedLines() const;
0542 
0543     /**
0544      * Resets the count of the number of lines dropped from
0545      * the history.
0546      */
0547     void resetDroppedLines();
0548 
0549     /**
0550       * Fills the buffer @p dest with @p count instances of the default (ie. blank)
0551       * Character style.
0552       */
0553     static void fillWithDefaultChar(Character* dest, int count);
0554 
0555 private:
0556 
0557     //copies a line of text from the screen or history into a stream using a
0558     //specified character decoder.  Returns the number of lines actually copied,
0559     //which may be less than 'count' if (start+count) is more than the number of characters on
0560     //the line
0561     //
0562     //line - the line number to copy, from 0 (the earliest line in the history) up to
0563     //         history->getLines() + lines - 1
0564     //start - the first column on the line to copy
0565     //count - the number of characters on the line to copy
0566     //decoder - a decoder which converts terminal characters (an Character array) into text
0567     //appendNewLine - if true a new line character (\n) is appended to the end of the line
0568     int  copyLineToStream(int line,
0569                           int start,
0570                           int count,
0571                           TerminalCharacterDecoder* decoder,
0572                           bool appendNewLine,
0573                           bool preserveLineBreaks) const;
0574 
0575     //fills a section of the screen image with the character 'c'
0576     //the parameters are specified as offsets from the start of the screen image.
0577     //the loc(x,y) macro can be used to generate these values from a column,line pair.
0578     void clearImage(int loca, int loce, char c);
0579 
0580     //move screen image between 'sourceBegin' and 'sourceEnd' to 'dest'.
0581     //the parameters are specified as offsets from the start of the screen image.
0582     //the loc(x,y) macro can be used to generate these values from a column,line pair.
0583     //
0584     //NOTE: moveImage() can only move whole lines
0585     void moveImage(int dest, int sourceBegin, int sourceEnd);
0586     // scroll up 'i' lines in current region, clearing the bottom 'i' lines
0587     void scrollUp(int from, int i);
0588     // scroll down 'i' lines in current region, clearing the top 'i' lines
0589     void scrollDown(int from, int i);
0590 
0591     void addHistLine();
0592 
0593     void initTabStops();
0594 
0595     void updateEffectiveRendition();
0596     void reverseRendition(Character& p) const;
0597 
0598     bool isSelectionValid() const;
0599     // copies text from 'startIndex' to 'endIndex' to a stream
0600     // startIndex and endIndex are positions generated using the loc(x,y) macro
0601     void writeToStream(TerminalCharacterDecoder* decoder, int startIndex,
0602                        int endIndex, bool preserveLineBreaks = true) const;
0603     // copies 'count' lines from the screen buffer into 'dest',
0604     // starting from 'startLine', where 0 is the first line in the screen buffer
0605     void copyFromScreen(Character* dest, int startLine, int count) const;
0606     // copies 'count' lines from the history buffer into 'dest',
0607     // starting from 'startLine', where 0 is the first line in the history
0608     void copyFromHistory(Character* dest, int startLine, int count) const;
0609 
0610 
0611     // screen image ----------------
0612     int lines;
0613     int columns;
0614 
0615     typedef QVector<Character> ImageLine;      // [0..columns]
0616     ImageLine*          screenLines;    // [lines]
0617 
0618     int _scrolledLines;
0619     QRect _lastScrolledRegion;
0620 
0621     int _droppedLines;
0622 
0623     QVarLengthArray<LineProperty,64> lineProperties;
0624 
0625     // history buffer ---------------
0626     HistoryScroll* history;
0627 
0628     // cursor location
0629     int cuX;
0630     int cuY;
0631 
0632     // cursor color and rendition info
0633     CharacterColor currentForeground;
0634     CharacterColor currentBackground;
0635     quint8 currentRendition;
0636 
0637     // margins ----------------
0638     int _topMargin;
0639     int _bottomMargin;
0640 
0641     // states ----------------
0642     int currentModes[MODES_SCREEN];
0643     int savedModes[MODES_SCREEN];
0644 
0645     // ----------------------------
0646 
0647     QBitArray tabStops;
0648 
0649     // selection -------------------
0650     int selBegin; // The first location selected.
0651     int selTopLeft;    // TopLeft Location.
0652     int selBottomRight;    // Bottom Right Location.
0653     bool blockSelectionMode;  // Column selection mode
0654 
0655     // effective colors and rendition ------------
0656     CharacterColor effectiveForeground; // These are derived from
0657     CharacterColor effectiveBackground; // the cu_* variables above
0658     quint8 effectiveRendition;          // to speed up operation
0659 
0660     class SavedState
0661     {
0662     public:
0663         SavedState()
0664         : cursorColumn(0),cursorLine(0),rendition(0) {}
0665 
0666         int cursorColumn;
0667         int cursorLine;
0668         quint8 rendition;
0669         CharacterColor foreground;
0670         CharacterColor background;
0671     };
0672     SavedState savedState;
0673 
0674     // last position where we added a character
0675     int lastPos;
0676 
0677     // used in REP (repeating char)
0678     unsigned short lastDrawnChar;
0679 
0680     static Character defaultChar;
0681 };
0682 
0683 }
0684 
0685 #endif // SCREEN_H