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
21class BString;
22class TerminalCharClassifier;
23struct TerminalLine;
24
25
26struct 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
62class BasicTerminalBuffer {
63public:
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
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