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