1 /* 2 * Copyright 2013-2024, Haiku, Inc. All rights reserved. 3 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Ingo Weinhold, ingo_weinhold@gmx.de 8 * Siarzhuk Zharski, zharik@gmx.li 9 */ 10 #ifndef BASIC_TERMINAL_BUFFER_H 11 #define BASIC_TERMINAL_BUFFER_H 12 13 #include <limits.h> 14 #include <stack> 15 16 #include "HistoryBuffer.h" 17 #include "TermPos.h" 18 #include "UTF8Char.h" 19 20 21 class BString; 22 class TerminalCharClassifier; 23 struct TerminalLine; 24 25 26 struct TerminalBufferDirtyInfo { 27 int32 linesScrolled; // number of lines added to the history 28 int32 dirtyTop; // dirty line range 29 int32 dirtyBottom; // 30 bool invalidateAll; 31 bool messageSent; // listener has been notified 32 33 bool IsDirtyRegionValid() const 34 { 35 return dirtyTop <= dirtyBottom; 36 } 37 38 void ExtendDirtyRegion(int32 top, int32 bottom) 39 { 40 if (top < dirtyTop) 41 dirtyTop = top; 42 if (bottom > dirtyBottom) 43 dirtyBottom = bottom; 44 } 45 46 void Reset() 47 { 48 linesScrolled = 0; 49 dirtyTop = INT_MAX; 50 dirtyBottom = INT_MIN; 51 invalidateAll = false; 52 messageSent = false; 53 } 54 55 TerminalBufferDirtyInfo() 56 { 57 Reset(); 58 } 59 }; 60 61 62 class BasicTerminalBuffer { 63 public: 64 BasicTerminalBuffer(); 65 virtual ~BasicTerminalBuffer(); 66 67 status_t Init(int32 width, int32 height, 68 int32 historyCapacity); 69 70 int32 Width() const { return fWidth; } 71 int32 Height() const { return fHeight; } 72 inline int32 HistorySize() const; 73 inline int32 HistoryCapacity() const; 74 75 bool IsAlternateScreenActive() const 76 { return fAlternateScreenActive; } 77 78 TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; } 79 80 virtual status_t ResizeTo(int32 width, int32 height); 81 virtual status_t ResizeTo(int32 width, int32 height, 82 int32 historyCapacity); 83 status_t SetHistoryCapacity(int32 historyCapacity); 84 void Clear(bool resetCursor); 85 86 void SynchronizeWith( 87 const BasicTerminalBuffer* other, 88 int32 offset, int32 dirtyTop, 89 int32 dirtyBottom); 90 91 bool IsFullWidthChar(int32 row, int32 column) const; 92 int GetChar(int32 row, int32 column, 93 UTF8Char& character, 94 Attributes& attributes) const; 95 void GetCellAttributes(int32 row, int32 column, 96 Attributes& attributes, uint32& count) const; 97 int32 GetString(int32 row, int32 firstColumn, 98 int32 lastColumn, char* buffer, 99 Attributes& attributes) const; 100 void GetStringFromRegion(BString& string, 101 const TermPos& start, 102 const TermPos& end) const; 103 bool FindWord(const TermPos& pos, 104 TerminalCharClassifier* classifier, 105 bool findNonWords, TermPos& start, 106 TermPos& end) const; 107 int32 LineLength(int32 index) const; 108 void GetLineColor(int32 index, Attributes& attr) const; 109 110 bool PreviousLinePos(TermPos& pos) const; 111 bool NextLinePos(TermPos& pos, bool normalize) const; 112 // normalize specifies that the returned 113 // position must be a valid position, i.e. 114 // actually point to a character (as opposed 115 // to just pointing to the position after a 116 // character). 117 118 bool Find(const char* pattern, const TermPos& start, 119 bool forward, bool caseSensitive, 120 bool matchWord, TermPos& matchStart, 121 TermPos& matchEnd) const; 122 123 inline Attributes GetAttributes(); 124 inline void SetAttributes(const Attributes& attributes); 125 126 // snapshots and data capture for debugging 127 void MakeLinesSnapshots(time_t timeStamp, 128 const char* fileName); 129 void StartStopDebugCapture(); 130 void CaptureChar(char ch); 131 132 // insert chars/lines 133 void InsertChar(UTF8Char c); 134 void FillScreen(UTF8Char c, Attributes &attr); 135 136 void InsertCR(); 137 void InsertLF(); 138 void InsertRI(); 139 void InsertTab(); 140 void InsertCursorBackTab(int32 numTabs); 141 void SetInsertMode(int flag); 142 void InsertSpace(int32 num); 143 void InsertLines(int32 numLines); 144 void InsertLastChar(); 145 146 // delete chars/lines 147 inline void EraseChars(int32 numChars); 148 void EraseCharsFrom(int32 first, int32 numChars); 149 void EraseAbove(); 150 void EraseBelow(); 151 void EraseAll(); 152 void EraseScrollback(); 153 void DeleteChars(int32 numChars); 154 inline void DeleteColumns(); 155 void DeleteColumnsFrom(int32 first); 156 void DeleteLines(int32 numLines); 157 158 // get and set cursor position 159 inline void SetCursor(int32 x, int32 y); 160 inline void SetCursorX(int32 x); 161 inline void SetCursorY(int32 y); 162 inline TermPos Cursor() const { return fCursor; } 163 void SaveCursor(); 164 void RestoreCursor(); 165 166 // move cursor 167 inline void MoveCursorRight(int32 num); 168 inline void MoveCursorLeft(int32 num); 169 inline void MoveCursorUp(int32 num); 170 inline void MoveCursorDown(int32 num); 171 inline void NextLine(); 172 173 // scroll region 174 inline void ScrollBy(int32 numLines); 175 void SetScrollRegion(int32 top, int32 bottom); 176 void SetOriginMode(bool enabled); 177 void SaveOriginMode(); 178 void RestoreOriginMode(); 179 void SetTabStop(int32 x); 180 void ClearTabStop(int32 x); 181 void ClearAllTabStops(); 182 183 protected: 184 virtual void NotifyListener(); 185 186 inline int32 _LineIndex(int32 index) const; 187 inline TerminalLine* _LineAt(int32 index) const; 188 inline TerminalLine* _HistoryLineAt(int32 index, 189 TerminalLine* lineBuffer) const; 190 191 inline void _Invalidate(int32 top, int32 bottom); 192 inline void _CursorChanged(); 193 void _SetCursor(int32 x, int32 y, bool absolute); 194 void _InvalidateAll(); 195 196 static TerminalLine** _AllocateLines(int32 width, int32 count); 197 static void _FreeLines(TerminalLine** lines, int32 count); 198 void _ClearLines(int32 first, int32 last); 199 200 status_t _ResizeHistory(int32 width, 201 int32 historyCapacity); 202 status_t _ResizeSimple(int32 width, int32 height, 203 int32 historyCapacity); 204 status_t _ResizeRewrap(int32 width, int32 height, 205 int32 historyCapacity); 206 status_t _ResetTabStops(int32 width); 207 208 void _Scroll(int32 top, int32 bottom, 209 int32 numLines); 210 void _SoftBreakLine(); 211 void _PadLineToCursor(); 212 static void _TruncateLine(TerminalLine* line, int32 length); 213 void _InsertGap(int32 width); 214 TerminalLine* _GetPartialLineString(BString& string, 215 int32 row, int32 startColumn, 216 int32 endColumn) const; 217 bool _PreviousChar(TermPos& pos, UTF8Char& c) const; 218 bool _NextChar(TermPos& pos, UTF8Char& c) const; 219 220 bool _PreviousLinePos(TerminalLine* lineBuffer, 221 TerminalLine*& line, TermPos& pos) const; 222 bool _NormalizeLinePos(TerminalLine* lineBuffer, 223 TerminalLine*& line, TermPos& pos) const; 224 225 protected: 226 // screen width/height 227 int32 fWidth; 228 int32 fHeight; 229 230 // scroll region top/bottom 231 int32 fScrollTop; // first line to scroll 232 int32 fScrollBottom; // last line to scroll (incl.) 233 234 // line buffers for the history (ring buffer) 235 TerminalLine** fScreen; 236 int32 fScreenOffset; // index of screen line 0 237 HistoryBuffer* fHistory; 238 239 Attributes fAttributes; 240 241 // cursor position (origin: (0, 0)) 242 TermPos fCursor; 243 std::stack<TermPos> fSavedCursors; 244 bool fSoftWrappedCursor; 245 246 bool fOverwriteMode; // false for insert 247 bool fAlternateScreenActive; 248 bool fOriginMode; 249 bool fSavedOriginMode; 250 bool* fTabStops; 251 252 int fEncoding; 253 int fCaptureFile; 254 255 UTF8Char fLast; 256 257 // listener/dirty region management 258 TerminalBufferDirtyInfo fDirtyInfo; 259 }; 260 261 262 int32 263 BasicTerminalBuffer::HistorySize() const 264 { 265 return fHistory != NULL ? fHistory->Size() : 0; 266 } 267 268 269 int32 270 BasicTerminalBuffer::HistoryCapacity() const 271 { 272 return fHistory != NULL ? fHistory->Capacity() : 0; 273 } 274 275 276 Attributes 277 BasicTerminalBuffer::GetAttributes() 278 { 279 return fAttributes; 280 } 281 282 283 void 284 BasicTerminalBuffer::SetAttributes(const Attributes& attributes) 285 { 286 fAttributes = attributes; 287 } 288 289 290 void 291 BasicTerminalBuffer::EraseChars(int32 numChars) 292 { 293 EraseCharsFrom(fCursor.x, numChars); 294 } 295 296 297 void 298 BasicTerminalBuffer::DeleteColumns() 299 { 300 DeleteColumnsFrom(fCursor.x); 301 } 302 303 304 void 305 BasicTerminalBuffer::SetCursor(int32 x, int32 y) 306 { 307 _SetCursor(x, y, false); 308 } 309 310 311 void 312 BasicTerminalBuffer::SetCursorX(int32 x) 313 { 314 SetCursor(x, fCursor.y); 315 } 316 317 318 void 319 BasicTerminalBuffer::SetCursorY(int32 y) 320 { 321 SetCursor(fCursor.x, y); 322 } 323 324 325 void 326 BasicTerminalBuffer::MoveCursorRight(int32 num) 327 { 328 SetCursor(fCursor.x + num, fCursor.y); 329 } 330 331 332 void 333 BasicTerminalBuffer::MoveCursorLeft(int32 num) 334 { 335 SetCursor(fCursor.x - num, fCursor.y); 336 } 337 338 339 void 340 BasicTerminalBuffer::MoveCursorUp(int32 num) 341 { 342 SetCursor(fCursor.x, fCursor.y - num); 343 } 344 345 346 void 347 BasicTerminalBuffer::MoveCursorDown(int32 num) 348 { 349 SetCursor(fCursor.x, fCursor.y + num); 350 } 351 352 353 void 354 BasicTerminalBuffer::ScrollBy(int32 numLines) 355 { 356 _Scroll(fScrollTop, fScrollBottom, numLines); 357 } 358 359 360 void 361 BasicTerminalBuffer::NextLine() 362 { 363 SetCursor(0, fCursor.y + 1); 364 } 365 366 #endif // BASIC_TERMINAL_BUFFER_H 367