BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / terminal / TerminalBuffer.cpp
blob14362d1b11e6b9169f58f19e176efb15999187b8
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.
6 * Authors:
7 * Ingo Weinhold, ingo_weinhold@gmx.de
8 * Siarzhuk Zharski, zharik@gmx.li
9 */
11 #include "TerminalBuffer.h"
13 #include <algorithm>
15 #include <Message.h>
17 #include "Colors.h"
18 #include "TermApp.h"
19 #include "TermConst.h"
22 // #pragma mark - public methods
25 TerminalBuffer::TerminalBuffer()
27 BLocker("terminal buffer"),
28 fEncoding(M_UTF8),
29 fAlternateScreen(NULL),
30 fAlternateHistory(NULL),
31 fAlternateScreenOffset(0),
32 fAlternateAttributes(0),
33 fColorsPalette(NULL),
34 fListenerValid(false)
39 TerminalBuffer::~TerminalBuffer()
41 delete fAlternateScreen;
42 delete fAlternateHistory;
43 delete[] fColorsPalette;
47 status_t
48 TerminalBuffer::Init(int32 width, int32 height, int32 historySize)
50 if (Sem() < 0)
51 return Sem();
53 fAlternateScreen = _AllocateLines(width, height);
54 if (fAlternateScreen == NULL)
55 return B_NO_MEMORY;
57 for (int32 i = 0; i < height; i++)
58 fAlternateScreen[i]->Clear();
60 fColorsPalette = new(std::nothrow) rgb_color[kTermColorCount];
61 if (fColorsPalette == NULL)
62 return B_NO_MEMORY;
64 memcpy(fColorsPalette, TermApp::DefaultPalette(),
65 sizeof(rgb_color) * kTermColorCount);
67 return BasicTerminalBuffer::Init(width, height, historySize);
71 void
72 TerminalBuffer::SetListener(BMessenger listener)
74 fListener = listener;
75 fListenerValid = true;
79 void
80 TerminalBuffer::UnsetListener()
82 fListenerValid = false;
86 int
87 TerminalBuffer::Encoding() const
89 return fEncoding;
93 void
94 TerminalBuffer::ReportX10MouseEvent(bool reportX10MouseEvent)
96 if (fListenerValid) {
97 BMessage message(MSG_REPORT_MOUSE_EVENT);
98 message.AddBool("reportX10MouseEvent", reportX10MouseEvent);
99 fListener.SendMessage(&message);
104 void
105 TerminalBuffer::ReportNormalMouseEvent(bool reportNormalMouseEvent)
107 if (fListenerValid) {
108 BMessage message(MSG_REPORT_MOUSE_EVENT);
109 message.AddBool("reportNormalMouseEvent", reportNormalMouseEvent);
110 fListener.SendMessage(&message);
115 void
116 TerminalBuffer::ReportButtonMouseEvent(bool report)
118 if (fListenerValid) {
119 BMessage message(MSG_REPORT_MOUSE_EVENT);
120 message.AddBool("reportButtonMouseEvent", report);
121 fListener.SendMessage(&message);
126 void
127 TerminalBuffer::ReportAnyMouseEvent(bool reportAnyMouseEvent)
129 if (fListenerValid) {
130 BMessage message(MSG_REPORT_MOUSE_EVENT);
131 message.AddBool("reportAnyMouseEvent", reportAnyMouseEvent);
132 fListener.SendMessage(&message);
137 void
138 TerminalBuffer::SetEncoding(int encoding)
140 fEncoding = encoding;
144 void
145 TerminalBuffer::SetTitle(const char* title)
147 if (fListenerValid) {
148 BMessage message(MSG_SET_TERMINAL_TITLE);
149 message.AddString("title", title);
150 fListener.SendMessage(&message);
155 void
156 TerminalBuffer::SetColors(uint8* indexes, rgb_color* colors,
157 int32 count, bool dynamic)
159 if (fListenerValid) {
160 BMessage message(MSG_SET_TERMINAL_COLORS);
161 message.AddInt32("count", count);
162 message.AddBool("dynamic", dynamic);
163 message.AddData("index", B_UINT8_TYPE,
164 indexes, sizeof(uint8), true, count);
165 message.AddData("color", B_RGB_COLOR_TYPE,
166 colors, sizeof(rgb_color), true, count);
168 for (int i = 1; i < count; i++) {
169 message.AddData("index", B_UINT8_TYPE, &indexes[i], sizeof(uint8));
170 message.AddData("color", B_RGB_COLOR_TYPE, &colors[i],
171 sizeof(rgb_color));
174 fListener.SendMessage(&message);
179 void
180 TerminalBuffer::ResetColors(uint8* indexes, int32 count, bool dynamic)
182 if (fListenerValid) {
183 BMessage message(MSG_RESET_TERMINAL_COLORS);
184 message.AddInt32("count", count);
185 message.AddBool("dynamic", dynamic);
186 message.AddData("index", B_UINT8_TYPE,
187 indexes, sizeof(uint8), true, count);
189 for (int i = 1; i < count; i++)
190 message.AddData("index", B_UINT8_TYPE, &indexes[i], sizeof(uint8));
192 fListener.SendMessage(&message);
197 void
198 TerminalBuffer::SetCursorStyle(int32 style, bool blinking)
200 if (fListenerValid) {
201 BMessage message(MSG_SET_CURSOR_STYLE);
202 message.AddInt32("style", style);
203 message.AddBool("blinking", blinking);
204 fListener.SendMessage(&message);
209 void
210 TerminalBuffer::SetCursorBlinking(bool blinking)
212 if (fListenerValid) {
213 BMessage message(MSG_SET_CURSOR_STYLE);
214 message.AddBool("blinking", blinking);
215 fListener.SendMessage(&message);
220 void
221 TerminalBuffer::SetCursorHidden(bool hidden)
223 if (fListenerValid) {
224 BMessage message(MSG_SET_CURSOR_STYLE);
225 message.AddBool("hidden", hidden);
226 fListener.SendMessage(&message);
231 void
232 TerminalBuffer::SetPaletteColor(uint8 index, rgb_color color)
234 if (index < kTermColorCount)
235 fColorsPalette[index] = color;
239 rgb_color
240 TerminalBuffer::PaletteColor(uint8 index)
242 return fColorsPalette[min_c(index, kTermColorCount - 1)];
247 TerminalBuffer::GuessPaletteColor(int red, int green, int blue)
249 int distance = 255 * 100;
250 int index = -1;
251 for (uint32 i = 0; i < kTermColorCount && distance > 0; i++) {
252 rgb_color color = fColorsPalette[i];
253 int r = 30 * abs(color.red - red);
254 int g = 59 * abs(color.green - green);
255 int b = 11 * abs(color.blue - blue);
256 int d = r + g + b;
257 if (distance > d) {
258 index = i;
259 distance = d;
263 return min_c(index, int(kTermColorCount - 1));
267 void
268 TerminalBuffer::NotifyQuit(int32 reason)
270 if (fListenerValid) {
271 BMessage message(MSG_QUIT_TERMNAL);
272 message.AddInt32("reason", reason);
273 fListener.SendMessage(&message);
278 void
279 TerminalBuffer::NotifyListener()
281 if (fListenerValid)
282 fListener.SendMessage(MSG_TERMINAL_BUFFER_CHANGED);
286 status_t
287 TerminalBuffer::ResizeTo(int32 width, int32 height)
289 int32 historyCapacity = 0;
290 if (!fAlternateScreenActive)
291 historyCapacity = HistoryCapacity();
292 else if (fAlternateHistory != NULL)
293 historyCapacity = fAlternateHistory->Capacity();
295 return ResizeTo(width, height, historyCapacity);
299 status_t
300 TerminalBuffer::ResizeTo(int32 width, int32 height, int32 historyCapacity)
302 // switch to the normal screen buffer first
303 bool alternateScreenActive = fAlternateScreenActive;
304 if (alternateScreenActive)
305 _SwitchScreenBuffer();
307 int32 oldWidth = fWidth;
308 int32 oldHeight = fHeight;
310 // Resize the normal screen buffer/history.
311 status_t error = BasicTerminalBuffer::ResizeTo(width, height,
312 historyCapacity);
313 if (error != B_OK) {
314 if (alternateScreenActive)
315 _SwitchScreenBuffer();
316 return error;
319 // Switch to the alternate screen buffer and resize it.
320 if (fAlternateScreen != NULL) {
321 TermPos cursor = fCursor;
322 fCursor.SetTo(0, 0);
323 fWidth = oldWidth;
324 fHeight = oldHeight;
326 _SwitchScreenBuffer();
328 error = BasicTerminalBuffer::ResizeTo(width, height, 0);
330 fWidth = width;
331 fHeight = height;
332 fCursor = cursor;
334 // Switch back.
335 if (!alternateScreenActive)
336 _SwitchScreenBuffer();
338 if (error != B_OK) {
339 // This sucks -- we can't do anything about it. Delete the
340 // alternate screen buffer.
341 _FreeLines(fAlternateScreen, oldHeight);
342 fAlternateScreen = NULL;
346 return error;
350 void
351 TerminalBuffer::UseAlternateScreenBuffer(bool clear)
353 if (fAlternateScreenActive || fAlternateScreen == NULL)
354 return;
356 _SwitchScreenBuffer();
358 if (clear)
359 Clear(false);
361 _InvalidateAll();
365 void
366 TerminalBuffer::UseNormalScreenBuffer()
368 if (!fAlternateScreenActive)
369 return;
371 _SwitchScreenBuffer();
372 _InvalidateAll();
376 void
377 TerminalBuffer::_SwitchScreenBuffer()
379 std::swap(fScreen, fAlternateScreen);
380 std::swap(fHistory, fAlternateHistory);
381 std::swap(fScreenOffset, fAlternateScreenOffset);
382 std::swap(fAttributes, fAlternateAttributes);
383 fAlternateScreenActive = !fAlternateScreenActive;