summaryrefslogtreecommitdiff
path: root/src/terminal/fqterm_buffer.h
blob: e3160324fd1c973c16d158aaad67d941ee62b7eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// SPDX-License-Identifier: GPL-2.0-or-later

#ifndef FQTERM_BUFFER_H
#define FQTERM_BUFFER_H

#include <QList>
#include <QObject>
#include <QPoint>

#include "fqterm_text_line.h"
class QString;
class QByteArray;
class QRect;

namespace FQTerm {

class FQTermTextLine;

/* Text buffer consists of characters in a matrix of cells.
 * 
 *                 Buffer
 *     +--------------------------------+
 *     ||---->                          |
 *     ||    x                          |
 *     ||                               |
 *     |V Y                             |
 *     |                                |
 *     .                                .
 *     .                                .
 *     .        histroical lines        .
 *     .                                .
 *     .                                .
 *     |                                |
 *     |                                |
 *     |                                |
 *     |                                |
 *     |+------------------------------+|
 *     |||---->                        ||
 *     |||    x                        ||
 *     |||          terminal           ||
 *     ||V Y                           ||
 *     ||                              ||
 *     ||                              ||
 *     ||         | (caret)            ||
 *     ||                              ||
 *     ||                              ||
 *     |+------------------------------+|
 *     +--------------------------------+
 *
 * Text buffer, to manage lines of characters with colors and
 * attributes, caret positions, terminal size/margins, selection
 * region, historical text lines, buffer write mode (insert or
 * replace), and etc.
 *
 * Note: There are two coordinates, relative to terminal or entire
 * buffer. When we use (column, row) it indicates terminal coordinate,
 * while when we use (column, line) it indicates buffer coordinate.
 * This rule applies both in variable names and function names.
 **/
class FQTermBuffer: public QObject {
  Q_OBJECT;
 public:
  enum TermMode {
    INSERT_MODE,     /* otherwise replace mode */
    ANSI_MODE,       /* otherwise VT52 mode */
    SMOOTH_MODE,     /* otherwse jump mode */
    NEWLINE_MODE,    /* otherwise line feed mode */
    CURSOR_MODE,     /* otherwise reset cursor mode */
    NUMERIC_MODE,    /* otherwise application mode */
    ORIGIN_MODE,     /* otherwise absolute mode */
    AUTOWRAP_MODE,   /* otherwise non-autowrap mode */
    AUTOREPEAT_MODE, /* otherwise non-autorepeat mode */
    LIGHTBG_MODE,    /* otherwise dark background mode */
  };

  enum VtCharSet {
    UNITED_KINGDOM_SET,
    ASCII_SET,
    SPECIAL_GRAPHICS,
    ALTERNATE_CHARACTER_ROM_STANDARD_CHARACTER_SET,
    ALTERNATE_CHARACTER_ROM_SPECIAL_GRAPHICS
  };
  
  FQTermBuffer(int column, int row, int max_hist_line, bool is_bbs);
  ~FQTermBuffer();

  // Get text lines.
  // Return null if the line_index is out of bound, return NULL.
  const FQTermTextLine *getTextLineInBuffer(int line_index) const;
  const FQTermTextLine *getTextLineInTerm(int line_index) const;

  // Get number of columns and rows of the term, or lines of the
  // entire buffer.
  int getNumColumns() const;
  int getNumRows() const;
  int getNumLines() const;
  
  // Set the size of the screen.
  void setTermSize(int col, int row);
  // set margins in term. (Generally speaking, most operations are
  // restrictied in [top_row_, bottom_row_] of terminal.)
  void setMargins(int top_row, int bottom_row);

  // reset terminal
  void termReset();
  
  // the caret's coordinate in term or buffer.
  int getCaretColumn() const;
  int getCaretRow() const;
  int getCaretLine() const;

  // Set current attribute.
  void setCurrentAttr(unsigned char color, unsigned char attr);

  // Below are a series of functions to modify the content of buffer.
  // These functions will work from the current caret position.
  // All the behaviours of these functions may be influenced by the
  // mode of this buffer (is_insert_mode_, is_newline_mode_, and
  // etc.).

  void writeText(const QString &cstr, int charstate = FQTermTextLine::NORMAL);

  void fillScreenWith(char c);

  void insertSpaces(int count);
  void insertLines(int count);

  void deleteText(int cell_count);
  void deleteLines(int line_count);

  void eraseText(int cell_count);

  void eraseToLineBegin();
  void eraseToLineEnd();
  void eraseEntireLine();

  void eraseToTermBegin();
  void eraseToTermEnd();
  void eraseEntireTerm();

  // Set a line of buffer to have been changed from start to end.
  void setLineChanged(int index, int cell_begin, int cell_end);
  void clearLineChanged(int index);
  void setLineAllChanged(int index);

  // Functions about caret.
  // If the caret is moved, the cells of the position of the last caret will
  // be marked as changed.
  void moveCaretOffset(int coloumn_offset, int row_offset,
                       bool scroll_if_necessary = false);
  void moveCaretTo(int column, int row, bool scroll_if_necessary = false);
  void changeCaretPosition(int column, int row);
  void saveCaret();
  void restoreCaret();

  void SelectVtCharacterSet(VtCharSet charset, bool G0);
  void invokeCharset(bool G0);

  // non-printing characters
  void tab();
  void carriageReturn();
  void lineFeed();

  void addTabStop();
  void clearTabStop(bool clear_all);
  
  // Select Mode (SM) and Reset Mode (RM) functions.
  // See ANSI X3.64 Mode-Changing Parameters.
  void setMode(TermMode);
  void resetMode(TermMode);

  bool isCursorMode() const { return is_cursor_mode_; }
  bool isAnsiMode() const { return is_ansi_mode_; }
  bool isNumericMode() const { return is_numeric_mode_; }
  bool isAutoRepeatMode() const { return is_autorepeat_mode_; }
  bool isLightBackgroundMode() const { return is_lightbg_mode_; }
  bool isNewLineMode() const {return is_newline_mode_;}
  
  // for test
  void startDecode();
  void endDecode();

  // Functions about selection in buffer.
  void setSelect(const QPoint &start_point, const QPoint &end_point);
  void clearSelect();
  bool isSelected(const QPoint &cell, bool isRectSel) const;
  bool isSelected(int line_index) const;

  QString getTextSelected(bool is_rect_sel, bool is_color_copy,
                          const QByteArray &escape) const;

  // Get the rectangle of selected text of a certain line in buffer.
  // Note: please ensure there exits any cell of the line line_index
  // is selected.
  QRect getSelectRect(int line_index, bool is_rect_sel) const;

  //Scroll line && adjust caret pos.
  //Scroll must occur at the line where caret is
  void scrollTerm(int numRows);
  
 signals:
  void bufferSizeChanged();
  void termSizeChanged(int column, int row);
  void onSetTermSize(int col, int row);
  void caretChangeRow();
 private:
  // Scroll lines between startRow and bottom_row_ (see setMargin()).
  // num > 0 scroll up.
  // num < 0 scroll down.
  void scrollLinesInTerm(int startRow, int numRows);

  // Replace a area of cells with spaces. 
  void clearArea(int startColumn, int startRow, 
                 int width, int height,
                 unsigned char color, unsigned char attr);

  // Append n empty lines to the buffer and make the first n lines of
  // term historical.
  void addHistoryLine(int n);

  int getTabStop(int column);

  struct Caret {
    int column_, row_;
    int color_, attr_;
    VtCharSet G0_, G1_;

    Caret();
  };

  // terminal size.
  int num_columns_, num_rows_;

  // term margins. (Generally speaking, most operations are
  // restrictied in [top_row_, bottom_row_] of terminal.)
  int top_row_, bottom_row_;

  // Historical data length and max length.
  int num_hist_lines_, max_num_hist_lines_;

  // All lines of text, including both historical lines and lines in
  // current terminal.
  //
  // Note: the number of historical lines, num_hist_lines, may
  // increase from 0 to max_num_hist_lines_.
  QList<FQTermTextLine *> text_lines_;

  void *tab_stops_;

  // The caret in terminal
  Caret caret_;
  Caret last_saved_caret_;

  bool is_g0_used_;  // is G0 or G1 charset used;

  bool is_insert_mode_;     // Is insert or replace mode.
  bool is_ansi_mode_;       // Is ansi or vt52 mode.
  bool is_smoothscroll_mode_; // Is smooth or jump scrolling mode.
  bool is_newline_mode_;    // Is newline or linefeed mode.
  bool is_cursor_mode_;     // Is cursor key mode.
  bool is_numeric_mode_;    // Is numeric or application mode.
  bool is_origin_mode_;     // Is origin or absolute mode.
  bool is_autowrap_mode_;   // Is auto-wrap mode enabled.
  bool is_autorepeat_mode_; // Is auto-repeat mode enabled.
  bool is_lightbg_mode_;    // Is light background or dark backgrond mode.

  // Selection in buffer. If section start and end are in the same
  // line, start.x should be equal to or less than end.x. Otherwise
  // start.y should be less than end.y.
  //
  // If selection_start_ = selection_start_ = (-1, -1), the selection
  // is empty.
  QPoint selection_start_;
  QPoint selection_end_;

  // whether this buffer is used for a bbs session.
  bool is_bbs_;
}; 

}  // namespace FQTerm

#endif // FQTERM_BUFFER_H