1 /* 2 * Copyright 2013, 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 DeleteChars(int32 numChars); 153 inline void DeleteColumns(); 154 void DeleteColumnsFrom(int32 first); 155 void DeleteLines(int32 numLines); 156 157 // get and set cursor position 158 inline void SetCursor(int32 x, int32 y); 159 inline void SetCursorX(int32 x); 160 inline void SetCursorY(int32 y); 161 inline TermPos Cursor() const { return fCursor; } 162 void SaveCursor(); 163 void RestoreCursor(); 164 165 // move cursor 166 inline void MoveCursorRight(int32 num); 167 inline void MoveCursorLeft(int32 num); 168 inline void MoveCursorUp(int32 num); 169 inline void MoveCursorDown(int32 num); 170 inline void NextLine(); 171 172 // scroll region 173 inline void ScrollBy(int32 numLines); 174 void SetScrollRegion(int32 top, int32 bottom); 175 void SetOriginMode(bool enabled); 176 void SaveOriginMode(); 177 void RestoreOriginMode(); 178 void SetTabStop(int32 x); 179 void ClearTabStop(int32 x); 180 void ClearAllTabStops(); 181 182 protected: 183 virtual void NotifyListener(); 184 185 inline int32 _LineIndex(int32 index) const; 186 inline TerminalLine* _LineAt(int32 index) const; 187 inline TerminalLine* _HistoryLineAt(int32 index, 188 TerminalLine* lineBuffer) const; 189 190 inline void _Invalidate(int32 top, int32 bottom); 191 inline void _CursorChanged(); 192 void _SetCursor(int32 x, int32 y, bool absolute); 193 void _InvalidateAll(); 194 195 static TerminalLine** _AllocateLines(int32 width, int32 count); 196 static void _FreeLines(TerminalLine** lines, int32 count); 197 void _ClearLines(int32 first, int32 last); 198 199 status_t _ResizeHistory(int32 width, 200 int32 historyCapacity); 201 status_t _ResizeSimple(int32 width, int32 height, 202 int32 historyCapacity); 203 status_t _ResizeRewrap(int32 width, int32 height, 204 int32 historyCapacity); 205 status_t _ResetTabStops(int32 width); 206 207 void _Scroll(int32 top, int32 bottom, 208 int32 numLines); 209 void _SoftBreakLine(); 210 void _PadLineToCursor(); 211 static void _TruncateLine(TerminalLine* line, int32 length); 212 void _InsertGap(int32 width); 213 TerminalLine* _GetPartialLineString(BString& string, 214 int32 row, int32 startColumn, 215 int32 endColumn) const; 216 bool _PreviousChar(TermPos& pos, UTF8Char& c) const; 217 bool _NextChar(TermPos& pos, UTF8Char& c) const; 218 219 bool _PreviousLinePos(TerminalLine* lineBuffer, 220 TerminalLine*& line, TermPos& pos) const; 221 bool _NormalizeLinePos(TerminalLine* lineBuffer, 222 TerminalLine*& line, TermPos& pos) const; 223 224 protected: 225 // screen width/height 226 int32 fWidth; 227 int32 fHeight; 228 229 // scroll region top/bottom 230 int32 fScrollTop; // first line to scroll 231 int32 fScrollBottom; // last line to scroll (incl.) 232 233 // line buffers for the history (ring buffer) 234 TerminalLine** fScreen; 235 int32 fScreenOffset; // index of screen line 0 236 HistoryBuffer* fHistory; 237 238 Attributes fAttributes; 239 240 // cursor position (origin: (0, 0)) 241 TermPos fCursor; 242 std::stack<TermPos> fSavedCursors; 243 bool fSoftWrappedCursor; 244 245 bool fOverwriteMode; // false for insert 246 bool fAlternateScreenActive; 247 bool fOriginMode; 248 bool fSavedOriginMode; 249 bool* fTabStops; 250 251 int fEncoding; 252 int fCaptureFile; 253 254 UTF8Char fLast; 255 256 // listener/dirty region management 257 TerminalBufferDirtyInfo fDirtyInfo; 258 }; 259 260 261 int32 262 BasicTerminalBuffer::HistorySize() const 263 { 264 return fHistory != NULL ? fHistory->Size() : 0; 265 } 266 267 268 int32 269 BasicTerminalBuffer::HistoryCapacity() const 270 { 271 return fHistory != NULL ? fHistory->Capacity() : 0; 272 } 273 274 275 Attributes 276 BasicTerminalBuffer::GetAttributes() 277 { 278 return fAttributes; 279 } 280 281 282 void 283 BasicTerminalBuffer::SetAttributes(const Attributes& attributes) 284 { 285 fAttributes = attributes; 286 } 287 288 289 void 290 BasicTerminalBuffer::EraseChars(int32 numChars) 291 { 292 EraseCharsFrom(fCursor.x, numChars); 293 } 294 295 296 void 297 BasicTerminalBuffer::DeleteColumns() 298 { 299 DeleteColumnsFrom(fCursor.x); 300 } 301 302 303 void 304 BasicTerminalBuffer::SetCursor(int32 x, int32 y) 305 { 306 _SetCursor(x, y, false); 307 } 308 309 310 void 311 BasicTerminalBuffer::SetCursorX(int32 x) 312 { 313 SetCursor(x, fCursor.y); 314 } 315 316 317 void 318 BasicTerminalBuffer::SetCursorY(int32 y) 319 { 320 SetCursor(fCursor.x, y); 321 } 322 323 324 void 325 BasicTerminalBuffer::MoveCursorRight(int32 num) 326 { 327 SetCursor(fCursor.x + num, fCursor.y); 328 } 329 330 331 void 332 BasicTerminalBuffer::MoveCursorLeft(int32 num) 333 { 334 SetCursor(fCursor.x - num, fCursor.y); 335 } 336 337 338 void 339 BasicTerminalBuffer::MoveCursorUp(int32 num) 340 { 341 SetCursor(fCursor.x, fCursor.y - num); 342 } 343 344 345 void 346 BasicTerminalBuffer::MoveCursorDown(int32 num) 347 { 348 SetCursor(fCursor.x, fCursor.y + num); 349 } 350 351 352 void 353 BasicTerminalBuffer::ScrollBy(int32 numLines) 354 { 355 _Scroll(fScrollTop, fScrollBottom, numLines); 356 } 357 358 359 void 360 BasicTerminalBuffer::NextLine() 361 { 362 SetCursor(0, fCursor.y + 1); 363 } 364 365 #endif // BASIC_TERMINAL_BUFFER_H 366