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