xref: /haiku/src/apps/terminal/BasicTerminalBuffer.h (revision 344ded80d400028c8f561b4b876257b94c12db4a)
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