1210284Sjmallett/* 2232812Sjmallett * Copyright 2013, Haiku, Inc. All rights reserved. 3215990Sjmallett * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 4210284Sjmallett * Distributed under the terms of the MIT License. 5210284Sjmallett * 6215990Sjmallett * Authors: 7215990Sjmallett * Ingo Weinhold, ingo_weinhold@gmx.de 8215990Sjmallett * Siarzhuk Zharski, zharik@gmx.li 9210284Sjmallett */ 10215990Sjmallett#ifndef BASIC_TERMINAL_BUFFER_H 11215990Sjmallett#define BASIC_TERMINAL_BUFFER_H 12210284Sjmallett 13215990Sjmallett#include <limits.h> 14215990Sjmallett#include <stack> 15215990Sjmallett 16215990Sjmallett#include "HistoryBuffer.h" 17215990Sjmallett#include "TermPos.h" 18232812Sjmallett#include "UTF8Char.h" 19215990Sjmallett 20215990Sjmallett 21215990Sjmallettclass BString; 22215990Sjmallettclass TerminalCharClassifier; 23215990Sjmallettstruct TerminalLine; 24215990Sjmallett 25215990Sjmallett 26215990Sjmallettstruct TerminalBufferDirtyInfo { 27215990Sjmallett int32 linesScrolled; // number of lines added to the history 28215990Sjmallett int32 dirtyTop; // dirty line range 29232812Sjmallett int32 dirtyBottom; // 30215990Sjmallett bool invalidateAll; 31215990Sjmallett bool messageSent; // listener has been notified 32215990Sjmallett 33215990Sjmallett bool IsDirtyRegionValid() const 34215990Sjmallett { 35215990Sjmallett return dirtyTop <= dirtyBottom; 36215990Sjmallett } 37215990Sjmallett 38210284Sjmallett void ExtendDirtyRegion(int32 top, int32 bottom) 39210284Sjmallett { 40210284Sjmallett if (top < dirtyTop) 41210284Sjmallett dirtyTop = top; 42210284Sjmallett if (bottom > dirtyBottom) 43210284Sjmallett dirtyBottom = bottom; 44210284Sjmallett } 45215990Sjmallett 46210284Sjmallett void Reset() 47210284Sjmallett { 48210284Sjmallett linesScrolled = 0; 49210284Sjmallett dirtyTop = INT_MAX; 50210284Sjmallett dirtyBottom = INT_MIN; 51232812Sjmallett invalidateAll = false; 52210284Sjmallett messageSent = false; 53210284Sjmallett } 54210284Sjmallett 55210284Sjmallett TerminalBufferDirtyInfo() 56210284Sjmallett { 57210284Sjmallett Reset(); 58210284Sjmallett } 59210284Sjmallett}; 60210284Sjmallett 61210284Sjmallett 62210284Sjmallettclass BasicTerminalBuffer { 63210284Sjmallettpublic: 64210284Sjmallett BasicTerminalBuffer(); 65210284Sjmallett virtual ~BasicTerminalBuffer(); 66215990Sjmallett 67210284Sjmallett status_t Init(int32 width, int32 height, 68215990Sjmallett int32 historyCapacity); 69215990Sjmallett 70215990Sjmallett int32 Width() const { return fWidth; } 71215990Sjmallett int32 Height() const { return fHeight; } 72215990Sjmallett inline int32 HistorySize() const; 73215990Sjmallett inline int32 HistoryCapacity() const; 74210284Sjmallett 75210284Sjmallett bool IsAlternateScreenActive() const 76210284Sjmallett { return fAlternateScreenActive; } 77210284Sjmallett 78215990Sjmallett TerminalBufferDirtyInfo& DirtyInfo() { return fDirtyInfo; } 79215990Sjmallett 80215990Sjmallett virtual status_t ResizeTo(int32 width, int32 height); 81215990Sjmallett virtual status_t ResizeTo(int32 width, int32 height, 82215990Sjmallett int32 historyCapacity); 83215990Sjmallett status_t SetHistoryCapacity(int32 historyCapacity); 84215990Sjmallett void Clear(bool resetCursor); 85215990Sjmallett 86215990Sjmallett void SynchronizeWith( 87215990Sjmallett const BasicTerminalBuffer* other, 88215990Sjmallett int32 offset, int32 dirtyTop, 89215990Sjmallett int32 dirtyBottom); 90215990Sjmallett 91215990Sjmallett bool IsFullWidthChar(int32 row, int32 column) const; 92215990Sjmallett int GetChar(int32 row, int32 column, 93215990Sjmallett UTF8Char& character, 94215990Sjmallett Attributes& attributes) const; 95215990Sjmallett void GetCellAttributes(int32 row, int32 column, 96215990Sjmallett Attributes& attributes, uint32& count) const; 97215990Sjmallett int32 GetString(int32 row, int32 firstColumn, 98215990Sjmallett int32 lastColumn, char* buffer, 99215990Sjmallett Attributes& attributes) const; 100215990Sjmallett void GetStringFromRegion(BString& string, 101215990Sjmallett const TermPos& start, 102215990Sjmallett const TermPos& end) const; 103215990Sjmallett bool FindWord(const TermPos& pos, 104215990Sjmallett TerminalCharClassifier* classifier, 105215990Sjmallett bool findNonWords, TermPos& start, 106215990Sjmallett TermPos& end) const; 107215990Sjmallett int32 LineLength(int32 index) const; 108215990Sjmallett void GetLineColor(int32 index, Attributes& attr) const; 109215990Sjmallett 110215990Sjmallett bool PreviousLinePos(TermPos& pos) const; 111215990Sjmallett bool NextLinePos(TermPos& pos, bool normalize) const; 112215990Sjmallett // normalize specifies that the returned 113215990Sjmallett // position must be a valid position, i.e. 114215990Sjmallett // actually point to a character (as opposed 115215990Sjmallett // to just pointing to the position after a 116215990Sjmallett // character). 117215990Sjmallett 118215990Sjmallett bool Find(const char* pattern, const TermPos& start, 119215990Sjmallett bool forward, bool caseSensitive, 120215990Sjmallett bool matchWord, TermPos& matchStart, 121215990Sjmallett TermPos& matchEnd) const; 122215990Sjmallett 123215990Sjmallett inline Attributes GetAttributes(); 124215990Sjmallett inline void SetAttributes(const Attributes& attributes); 125215990Sjmallett 126215990Sjmallett // snapshots and data capture for debugging 127215990Sjmallett void MakeLinesSnapshots(time_t timeStamp, 128215990Sjmallett const char* fileName); 129215990Sjmallett void StartStopDebugCapture(); 130215990Sjmallett void CaptureChar(char ch); 131215990Sjmallett 132215990Sjmallett // insert chars/lines 133215990Sjmallett void InsertChar(UTF8Char c); 134215990Sjmallett void FillScreen(UTF8Char c, Attributes &attr); 135215990Sjmallett 136215990Sjmallett void InsertCR(); 137215990Sjmallett void InsertLF(); 138215990Sjmallett void InsertRI(); 139215990Sjmallett void InsertTab(); 140215990Sjmallett void InsertCursorBackTab(int32 numTabs); 141215990Sjmallett void SetInsertMode(int flag); 142215990Sjmallett void InsertSpace(int32 num); 143215990Sjmallett void InsertLines(int32 numLines); 144215990Sjmallett void InsertLastChar(); 145215990Sjmallett 146215990Sjmallett // delete chars/lines 147215990Sjmallett inline void EraseChars(int32 numChars); 148215990Sjmallett void EraseCharsFrom(int32 first, int32 numChars); 149215990Sjmallett void EraseAbove(); 150215990Sjmallett void EraseBelow(); 151215990Sjmallett void EraseAll(); 152215990Sjmallett void DeleteChars(int32 numChars); 153215990Sjmallett inline void DeleteColumns(); 154215990Sjmallett void DeleteColumnsFrom(int32 first); 155215990Sjmallett void DeleteLines(int32 numLines); 156215990Sjmallett 157215990Sjmallett // get and set cursor position 158215990Sjmallett inline void SetCursor(int32 x, int32 y); 159215990Sjmallett inline void SetCursorX(int32 x); 160215990Sjmallett inline void SetCursorY(int32 y); 161215990Sjmallett inline TermPos Cursor() const { return fCursor; } 162215990Sjmallett void SaveCursor(); 163215990Sjmallett void RestoreCursor(); 164215990Sjmallett 165210284Sjmallett // move cursor 166210284Sjmallett inline void MoveCursorRight(int32 num); 167210284Sjmallett inline void MoveCursorLeft(int32 num); 168210284Sjmallett inline void MoveCursorUp(int32 num); 169210284Sjmallett 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 182protected: 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 224protected: 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 261int32 262BasicTerminalBuffer::HistorySize() const 263{ 264 return fHistory != NULL ? fHistory->Size() : 0; 265} 266 267 268int32 269BasicTerminalBuffer::HistoryCapacity() const 270{ 271 return fHistory != NULL ? fHistory->Capacity() : 0; 272} 273 274 275Attributes 276BasicTerminalBuffer::GetAttributes() 277{ 278 return fAttributes; 279} 280 281 282void 283BasicTerminalBuffer::SetAttributes(const Attributes& attributes) 284{ 285 fAttributes = attributes; 286} 287 288 289void 290BasicTerminalBuffer::EraseChars(int32 numChars) 291{ 292 EraseCharsFrom(fCursor.x, numChars); 293} 294 295 296void 297BasicTerminalBuffer::DeleteColumns() 298{ 299 DeleteColumnsFrom(fCursor.x); 300} 301 302 303void 304BasicTerminalBuffer::SetCursor(int32 x, int32 y) 305{ 306 _SetCursor(x, y, false); 307} 308 309 310void 311BasicTerminalBuffer::SetCursorX(int32 x) 312{ 313 SetCursor(x, fCursor.y); 314} 315 316 317void 318BasicTerminalBuffer::SetCursorY(int32 y) 319{ 320 SetCursor(fCursor.x, y); 321} 322 323 324void 325BasicTerminalBuffer::MoveCursorRight(int32 num) 326{ 327 SetCursor(fCursor.x + num, fCursor.y); 328} 329 330 331void 332BasicTerminalBuffer::MoveCursorLeft(int32 num) 333{ 334 SetCursor(fCursor.x - num, fCursor.y); 335} 336 337 338void 339BasicTerminalBuffer::MoveCursorUp(int32 num) 340{ 341 SetCursor(fCursor.x, fCursor.y - num); 342} 343 344 345void 346BasicTerminalBuffer::MoveCursorDown(int32 num) 347{ 348 SetCursor(fCursor.x, fCursor.y + num); 349} 350 351 352void 353BasicTerminalBuffer::ScrollBy(int32 numLines) 354{ 355 _Scroll(fScrollTop, fScrollBottom, numLines); 356} 357 358 359void 360BasicTerminalBuffer::NextLine() 361{ 362 SetCursor(0, fCursor.y + 1); 363} 364 365#endif // BASIC_TERMINAL_BUFFER_H 366