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 TERMINAL_LINE_H
11#define TERMINAL_LINE_H
12
13#include <GraphicsDefs.h>
14#include <SupportDefs.h>
15
16#include "TermConst.h"
17
18#include "UTF8Char.h"
19
20
21struct Attributes {
22	uint32 state;
23	uint32 foreground;
24	uint32 background;
25	uint32 underline;
26	int underlineStyle;
27
28	Attributes() : state(0), foreground(0), background(0), underline(0), underlineStyle(0) {}
29
30	inline void Reset()
31	{
32		state = 0;
33		foreground = 0;
34		background = 0;
35		underline = 0;
36		underlineStyle = 0;
37	}
38
39	inline bool IsWidth() const { return (state & A_WIDTH) == A_WIDTH; }
40	inline bool IsBold() const { return (state & BOLD) == BOLD; }
41	inline bool IsUnder() const { return (state & UNDERLINE) == UNDERLINE; }
42	inline bool IsInverse() const { return (state & INVERSE) == INVERSE; }
43	inline bool IsMouse() const { return (state & MOUSE) == MOUSE; }
44	inline bool IsForeSet() const { return (state & FORESET) == FORESET; }
45	inline bool IsBackSet() const { return (state & BACKSET) == BACKSET; }
46	inline bool IsUnderSet() const { return (state & UNDERSET) == UNDERSET; }
47	inline bool IsFont() const { return (state & FONT) == FONT; }
48	inline bool IsCR() const { return (state & DUMPCR) == DUMPCR; }
49
50	inline void SetDirectForeground(uint8 red, uint8 green, uint8 blue)
51	{
52		foreground = 0x80000000 | (red << 16) | (green << 8) | blue;
53		state &= ~FORECOLOR;
54		state |= FORESET;
55	}
56
57	inline void SetDirectBackground(uint8 red, uint8 green, uint8 blue)
58	{
59		background = 0x80000000 | (red << 16) | (green << 8) | blue;
60		state &= ~BACKCOLOR;
61		state |= BACKSET;
62	}
63
64	inline void SetDirectUnderline(uint8 red, uint8 green, uint8 blue)
65	{
66		underline = 0x80000000 | (red << 16) | (green << 8) | blue;
67		state |= UNDERSET;
68	}
69
70	inline void SetIndexedForeground(uint32 index)
71	{
72		state &= ~FORECOLOR;
73		state |= FORESET;
74		state |= FORECOLORED(index);
75		foreground = 0;
76	}
77
78	inline void SetIndexedBackground(uint32 index)
79	{
80		state &= ~BACKCOLOR;
81		state |= BACKSET;
82		state |= BACKCOLORED(index);
83		background = 0;
84	}
85
86	inline void SetIndexedUnderline(uint32 index)
87	{
88		state |= UNDERSET;
89		underline = index;
90	}
91
92	inline void SetUnder(int style)
93	{
94		underlineStyle = style;
95		state |= UNDERLINE;
96	}
97
98	inline void UnsetForeground()
99	{
100		state &= ~FORESET;
101		foreground = 0;
102	}
103
104	inline void UnsetBackground()
105	{
106		state &= ~BACKSET;
107		background = 0;
108	}
109
110	inline void UnsetUnderline()
111	{
112		state &= ~UNDERSET;
113		underline = 0;
114	}
115
116	inline void UnsetUnder()
117	{
118		underlineStyle = 0;
119		state &= ~UNDERLINE;
120	}
121
122	inline rgb_color
123	ForegroundColor(const rgb_color* indexedColors) const
124	{
125		if ((foreground & 0x80000000) != 0)
126			return make_color((foreground >> 16) & 0xFF,
127				(foreground >> 8) & 0xFF,
128				foreground & 0xFF);
129		else
130			return indexedColors[(state & FORECOLOR) >> 16];
131	}
132
133	inline rgb_color
134	BackgroundColor(const rgb_color* indexedColors) const
135	{
136		if ((background & 0x80000000) != 0)
137			return make_color((background >> 16) & 0xFF,
138				(background >> 8) & 0xFF,
139				background & 0xFF);
140		else
141			return indexedColors[(state & BACKCOLOR) >> 24];
142	}
143
144	inline rgb_color
145	UnderlineColor(const rgb_color* indexedColors) const
146	{
147		if ((underline & 0x80000000) != 0)
148			return make_color((underline >> 16) & 0xFF,
149				(underline >> 8) & 0xFF,
150				underline & 0xFF);
151		else
152			return indexedColors[underline];
153	}
154
155	inline int
156	UnderlineStyle() const
157	{
158		return underlineStyle;
159	}
160
161	inline Attributes&
162	operator&=(uint32 value) { state &= value; return *this; }
163
164	inline Attributes&
165	operator|=(uint32 value) { state |= value; return *this; }
166
167	inline uint32
168	operator|(uint32 value) { return state | value; }
169
170	inline uint32
171	operator&(uint32 value) { return state & value; }
172
173	inline bool
174	operator==(const Attributes& other) const
175	{
176		return state == other.state
177			&& foreground == other.foreground
178			&& background == other.background
179			&& underline == other.underline
180			&& underlineStyle == other.underlineStyle;
181	}
182
183	inline bool
184	operator!=(const Attributes& other) const
185	{
186		return state != other.state
187			|| foreground != other.foreground
188			|| background != other.background
189			|| underline != other.underline
190			|| underlineStyle != other.underlineStyle;
191	}
192};
193
194
195struct TerminalCell {
196	UTF8Char			character;
197	Attributes			attributes;
198
199	inline bool
200	operator!=(const Attributes& other) const
201	{
202		return (attributes.state & CHAR_ATTRIBUTES)
203				!= (other.state & CHAR_ATTRIBUTES)
204			|| attributes.foreground != other.foreground
205			|| attributes.background != other.background;
206	}
207};
208
209
210struct TerminalLine {
211	uint16			length;
212	bool			softBreak;	// soft line break
213	Attributes		attributes;
214	TerminalCell	cells[1];
215
216	inline void Clear()
217	{
218		Clear(Attributes());
219	}
220
221	inline void Clear(size_t count)
222	{
223		Clear(Attributes(), count);
224	}
225
226	inline void Clear(Attributes attr, size_t count = 0)
227	{
228		length = 0;
229		attributes = attr;
230		softBreak = false;
231		for (size_t i = 0; i < count; i++)
232			cells[i].attributes = attr;
233	}
234};
235
236
237struct AttributesRun {
238	Attributes	attributes;
239	uint16	offset;			// character offset
240	uint16	length;			// length of the run in characters
241};
242
243
244struct HistoryLine {
245	AttributesRun*	attributesRuns;
246	uint16			attributesRunCount;	// number of attribute runs
247	uint16			byteLength : 15;	// number of bytes in the line
248	bool			softBreak : 1;		// soft line break;
249	Attributes		attributes;
250
251	AttributesRun* AttributesRuns() const
252	{
253		return attributesRuns;
254	}
255
256	char* Chars() const
257	{
258		return (char*)(attributesRuns + attributesRunCount);
259	}
260
261	int32 BufferSize() const
262	{
263		return attributesRunCount * sizeof(AttributesRun) + byteLength;
264	}
265};
266
267
268#endif	// TERMINAL_LINE_H
269