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