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.
7 * Ingo Weinhold, ingo_weinhold@gmx.de
8 * Siarzhuk Zharski, zharik@gmx.li
11 #include "TerminalBuffer.h"
19 #include "TermConst.h"
22 // #pragma mark - public methods
25 TerminalBuffer::TerminalBuffer()
27 BLocker("terminal buffer"),
29 fAlternateScreen(NULL
),
30 fAlternateHistory(NULL
),
31 fAlternateScreenOffset(0),
32 fAlternateAttributes(0),
39 TerminalBuffer::~TerminalBuffer()
41 delete fAlternateScreen
;
42 delete fAlternateHistory
;
43 delete[] fColorsPalette
;
48 TerminalBuffer::Init(int32 width
, int32 height
, int32 historySize
)
53 fAlternateScreen
= _AllocateLines(width
, height
);
54 if (fAlternateScreen
== NULL
)
57 for (int32 i
= 0; i
< height
; i
++)
58 fAlternateScreen
[i
]->Clear();
60 fColorsPalette
= new(std::nothrow
) rgb_color
[kTermColorCount
];
61 if (fColorsPalette
== NULL
)
64 memcpy(fColorsPalette
, TermApp::DefaultPalette(),
65 sizeof(rgb_color
) * kTermColorCount
);
67 return BasicTerminalBuffer::Init(width
, height
, historySize
);
72 TerminalBuffer::SetListener(BMessenger listener
)
75 fListenerValid
= true;
80 TerminalBuffer::UnsetListener()
82 fListenerValid
= false;
87 TerminalBuffer::Encoding() const
94 TerminalBuffer::ReportX10MouseEvent(bool reportX10MouseEvent
)
97 BMessage
message(MSG_REPORT_MOUSE_EVENT
);
98 message
.AddBool("reportX10MouseEvent", reportX10MouseEvent
);
99 fListener
.SendMessage(&message
);
105 TerminalBuffer::ReportNormalMouseEvent(bool reportNormalMouseEvent
)
107 if (fListenerValid
) {
108 BMessage
message(MSG_REPORT_MOUSE_EVENT
);
109 message
.AddBool("reportNormalMouseEvent", reportNormalMouseEvent
);
110 fListener
.SendMessage(&message
);
116 TerminalBuffer::ReportButtonMouseEvent(bool report
)
118 if (fListenerValid
) {
119 BMessage
message(MSG_REPORT_MOUSE_EVENT
);
120 message
.AddBool("reportButtonMouseEvent", report
);
121 fListener
.SendMessage(&message
);
127 TerminalBuffer::ReportAnyMouseEvent(bool reportAnyMouseEvent
)
129 if (fListenerValid
) {
130 BMessage
message(MSG_REPORT_MOUSE_EVENT
);
131 message
.AddBool("reportAnyMouseEvent", reportAnyMouseEvent
);
132 fListener
.SendMessage(&message
);
138 TerminalBuffer::SetEncoding(int encoding
)
140 fEncoding
= encoding
;
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
);
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
],
174 fListener
.SendMessage(&message
);
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
);
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
);
210 TerminalBuffer::SetCursorBlinking(bool blinking
)
212 if (fListenerValid
) {
213 BMessage
message(MSG_SET_CURSOR_STYLE
);
214 message
.AddBool("blinking", blinking
);
215 fListener
.SendMessage(&message
);
221 TerminalBuffer::SetCursorHidden(bool hidden
)
223 if (fListenerValid
) {
224 BMessage
message(MSG_SET_CURSOR_STYLE
);
225 message
.AddBool("hidden", hidden
);
226 fListener
.SendMessage(&message
);
232 TerminalBuffer::SetPaletteColor(uint8 index
, rgb_color color
)
234 if (index
< kTermColorCount
)
235 fColorsPalette
[index
] = 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;
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
);
263 return min_c(index
, int(kTermColorCount
- 1));
268 TerminalBuffer::NotifyQuit(int32 reason
)
270 if (fListenerValid
) {
271 BMessage
message(MSG_QUIT_TERMNAL
);
272 message
.AddInt32("reason", reason
);
273 fListener
.SendMessage(&message
);
279 TerminalBuffer::NotifyListener()
282 fListener
.SendMessage(MSG_TERMINAL_BUFFER_CHANGED
);
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
);
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
,
314 if (alternateScreenActive
)
315 _SwitchScreenBuffer();
319 // Switch to the alternate screen buffer and resize it.
320 if (fAlternateScreen
!= NULL
) {
321 TermPos cursor
= fCursor
;
326 _SwitchScreenBuffer();
328 error
= BasicTerminalBuffer::ResizeTo(width
, height
, 0);
335 if (!alternateScreenActive
)
336 _SwitchScreenBuffer();
339 // This sucks -- we can't do anything about it. Delete the
340 // alternate screen buffer.
341 _FreeLines(fAlternateScreen
, oldHeight
);
342 fAlternateScreen
= NULL
;
351 TerminalBuffer::UseAlternateScreenBuffer(bool clear
)
353 if (fAlternateScreenActive
|| fAlternateScreen
== NULL
)
356 _SwitchScreenBuffer();
366 TerminalBuffer::UseNormalScreenBuffer()
368 if (!fAlternateScreenActive
)
371 _SwitchScreenBuffer();
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
;