2 * Console.cpp - Mimicing the console driver
3 * Based on the console driver.
5 * Copyright 2005 Michael Lotz. All rights reserved.
6 * Distributed under the Haiku License.
8 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
9 * Distributed under the terms of the MIT License.
11 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
12 * Distributed under the terms of the NewOS License.
16 #include "ViewBuffer.h"
19 Console::Console(ViewBuffer
*output
)
20 : fState(CONSOLE_STATE_NORMAL
),
23 fOutput
->GetSize(&fColumns
, &fLines
);
24 fOutput
->SetResizeCallback(&ResizeCallback
, this);
38 Console::ResetConsole()
42 fScrollBottom
= fLines
- 1;
49 Console::ResizeCallback(int32 width
, int32 height
, void *data
)
51 Console
*console
= (Console
*)data
;
53 console
->fColumns
= width
;
54 console
->fLines
= height
;
55 console
->SetScrollRegion(console
->fScrollTop
, height
- 1);
60 Console::SetScrollRegion(int top
, int bottom
)
70 fScrollBottom
= bottom
;
77 // see if cursor is outside of scroll region
78 if (fY
< fScrollTop
|| fY
> fScrollBottom
)
81 if (fY
- fScrollTop
> 1) {
82 // move the screen up one
83 fOutput
->Blit(0, fScrollTop
+ 1, fColumns
, fY
- fScrollTop
, 0, fScrollTop
);
86 // clear the bottom line
87 fOutput
->FillGlyph(0, fY
, fColumns
, 1, ' ', fAttr
);
94 // see if cursor is outside of scroll region
95 if (fY
< fScrollTop
|| fY
> fScrollBottom
)
98 if (fScrollBottom
- fY
> 1) {
99 // move the screen down one
100 fOutput
->Blit(0, fY
, fColumns
, fScrollBottom
- fY
, 0, fY
+ 1);
103 // clear the top line
104 fOutput
->FillGlyph(0, fY
, fColumns
, 1, ' ', fAttr
);
111 if (fY
== fScrollBottom
) {
112 // we hit the bottom of our scroll region
114 } else if (fY
< fScrollBottom
) {
123 if (fY
== fScrollTop
) {
124 // we hit the top of our scroll region
126 } else if (fY
> fScrollTop
) {
133 Console::CariageReturn()
154 fOutput
->PutGlyph(fX
, fY
, ' ', fAttr
);
161 fX
= (fX
+ TAB_SIZE
) & ~TAB_MASK
;
162 if (fX
>= fColumns
) {
170 Console::EraseLine(erase_line_mode mode
)
173 case LINE_ERASE_WHOLE
:
174 fOutput
->FillGlyph(0, fY
, fColumns
, 1, ' ', fAttr
);
176 case LINE_ERASE_LEFT
:
177 fOutput
->FillGlyph(0, fY
, fX
+ 1, 1, ' ', fAttr
);
179 case LINE_ERASE_RIGHT
:
180 fOutput
->FillGlyph(fX
, fY
, fColumns
- fX
, 1, ' ', fAttr
);
189 Console::EraseScreen(erase_screen_mode mode
)
192 case SCREEN_ERASE_WHOLE
:
193 fOutput
->Clear(fAttr
);
195 case SCREEN_ERASE_UP
:
196 fOutput
->FillGlyph(0, 0, fColumns
, fY
+ 1, ' ', fAttr
);
198 case SCREEN_ERASE_DOWN
:
199 fOutput
->FillGlyph(fY
, 0, fColumns
, fLines
- fY
, ' ', fAttr
);
208 Console::SaveCursor(bool save_attrs
)
219 Console::RestoreCursor(bool restore_attrs
)
230 Console::UpdateCursor(int x
, int y
)
232 fOutput
->MoveCursor(x
, y
);
237 Console::GotoXY(int new_x
, int new_y
)
239 if (new_x
>= fColumns
)
240 new_x
= fColumns
- 1;
254 Console::PutChar(const char c
)
256 fOutput
->PutGlyph(fX
, fY
, c
, fAttr
);
257 if (++fX
>= fColumns
) {
265 Console::SetVT100Attributes(int32
*args
, int32 argCount
)
268 // that's the default (attributes off)
273 for (int32 i
= 0; i
< argCount
; i
++) {
278 fReverseAttr
= false;
282 fAttr
|= 0x08; // set the bright bit
286 fAttr
&= ~0x08; // unset the bright bit
288 case 4: // underscore we can't do
291 fAttr
|= 0x80; // set the blink bit
295 fAttr
= ((fAttr
& BMASK
) >> 4) | ((fAttr
& FMASK
) << 4);
302 /* foreground colors */
303 case 30: fAttr
= (fAttr
& ~FMASK
) | 0 | (fBrightAttr
? 0x08 : 0); break; // black
304 case 31: fAttr
= (fAttr
& ~FMASK
) | 4 | (fBrightAttr
? 0x08 : 0); break; // red
305 case 32: fAttr
= (fAttr
& ~FMASK
) | 2 | (fBrightAttr
? 0x08 : 0); break; // green
306 case 33: fAttr
= (fAttr
& ~FMASK
) | 6 | (fBrightAttr
? 0x08 : 0); break; // yellow
307 case 34: fAttr
= (fAttr
& ~FMASK
) | 1 | (fBrightAttr
? 0x08 : 0); break; // blue
308 case 35: fAttr
= (fAttr
& ~FMASK
) | 5 | (fBrightAttr
? 0x08 : 0); break; // magenta
309 case 36: fAttr
= (fAttr
& ~FMASK
) | 3 | (fBrightAttr
? 0x08 : 0); break; // cyan
310 case 37: fAttr
= (fAttr
& ~FMASK
) | 7 | (fBrightAttr
? 0x08 : 0); break; // white
312 /* background colors */
313 case 40: fAttr
= (fAttr
& ~BMASK
) | (0 << 4); break; // black
314 case 41: fAttr
= (fAttr
& ~BMASK
) | (4 << 4); break; // red
315 case 42: fAttr
= (fAttr
& ~BMASK
) | (2 << 4); break; // green
316 case 43: fAttr
= (fAttr
& ~BMASK
) | (6 << 4); break; // yellow
317 case 44: fAttr
= (fAttr
& ~BMASK
) | (1 << 4); break; // blue
318 case 45: fAttr
= (fAttr
& ~BMASK
) | (5 << 4); break; // magenta
319 case 46: fAttr
= (fAttr
& ~BMASK
) | (3 << 4); break; // cyan
320 case 47: fAttr
= (fAttr
& ~BMASK
) | (7 << 4); break; // white
327 Console::ProcessVT100Command(const char c
, bool seen_bracket
, int32
*args
, int32 argCount
)
333 case 'H': /* set cursor position */
335 int32 row
= argCount
> 0 ? args
[0] : 1;
336 int32 col
= argCount
> 1 ? args
[1] : 1;
344 case 'A': { /* move up */
345 int32 deltay
= argCount
> 0 ? -args
[0] : -1;
348 GotoXY(fX
, fY
+ deltay
);
352 case 'B': { /* move down */
353 int32 deltay
= argCount
> 0 ? args
[0] : 1;
356 GotoXY(fX
, fY
+ deltay
);
359 case 'D': { /* move left */
360 int32 deltax
= argCount
> 0 ? -args
[0] : -1;
363 GotoXY(fX
+ deltax
, fY
);
367 case 'C': { /* move right */
368 int32 deltax
= argCount
> 0 ? args
[0] : 1;
371 GotoXY(fX
+ deltax
, fY
);
375 case 'G': { /* set X position */
376 int32 newx
= argCount
> 0 ? args
[0] : 1;
382 case 'd': { /* set y position */
383 int32 newy
= argCount
> 0 ? args
[0] : 1;
389 case 's': /* save current cursor */
392 case 'u': /* restore cursor */
393 RestoreCursor(false);
395 case 'r': { /* set scroll region */
396 int32 low
= argCount
> 0 ? args
[0] : 1;
397 int32 high
= argCount
> 1 ? args
[1] : fLines
;
399 SetScrollRegion(low
- 1, high
- 1);
402 case 'L': { /* scroll virtual down at cursor */
403 int32 lines
= argCount
> 0 ? args
[0] : 1;
410 case 'M': { /* scroll virtual up at cursor */
411 int32 lines
= argCount
> 0 ? args
[0] : 1;
419 if (argCount
== 0 || args
[0] == 0) {
420 // erase to end of line
421 EraseLine(LINE_ERASE_RIGHT
);
422 } else if (argCount
> 0) {
424 EraseLine(LINE_ERASE_LEFT
);
425 else if (args
[0] == 2)
426 EraseLine(LINE_ERASE_WHOLE
);
430 if (argCount
== 0 || args
[0] == 0) {
431 // erase to end of screen
432 EraseScreen(SCREEN_ERASE_DOWN
);
433 } else if (argCount
> 0) {
435 EraseScreen(SCREEN_ERASE_UP
);
436 else if (args
[0] == 2)
437 EraseScreen(SCREEN_ERASE_WHOLE
);
442 SetVT100Attributes(args
, argCount
);
474 Console::Write(const void *buf
, size_t len
)
476 UpdateCursor(-1, -1); // hide the cursor
482 c
= &((const char *)buf
)[pos
++];
485 case CONSOLE_STATE_NORMAL
:
486 // just output the stuff
494 case 0x8: // backspace
502 //printf("<BEEP>\n");
509 fState
= CONSOLE_STATE_GOT_ESCAPE
;
515 case CONSOLE_STATE_GOT_ESCAPE
:
516 // look for either commands with no argument, or the '[' character
519 fState
= CONSOLE_STATE_SEEN_BRACKET
;
522 fArgs
[fArgCount
] = 0;
523 ProcessVT100Command(*c
, false, fArgs
, fArgCount
+ 1);
524 fState
= CONSOLE_STATE_NORMAL
;
527 case CONSOLE_STATE_SEEN_BRACKET
:
531 fArgs
[fArgCount
] = *c
- '0';
532 fState
= CONSOLE_STATE_PARSING_ARG
;
535 // private DEC mode parameter follows - we ignore those anyway
536 // ToDo: check if it was really used in combination with a mode command
539 ProcessVT100Command(*c
, true, fArgs
, fArgCount
+ 1);
540 fState
= CONSOLE_STATE_NORMAL
;
543 case CONSOLE_STATE_NEW_ARG
:
547 if (fArgCount
== MAX_ARGS
) {
548 fState
= CONSOLE_STATE_NORMAL
;
551 fArgs
[fArgCount
] = *c
- '0';
552 fState
= CONSOLE_STATE_PARSING_ARG
;
555 ProcessVT100Command(*c
, true, fArgs
, fArgCount
+ 1);
556 fState
= CONSOLE_STATE_NORMAL
;
559 case CONSOLE_STATE_PARSING_ARG
:
563 fArgs
[fArgCount
] *= 10;
564 fArgs
[fArgCount
] += *c
- '0';
567 fState
= CONSOLE_STATE_NEW_ARG
;
570 ProcessVT100Command(*c
, true, fArgs
, fArgCount
+ 1);
571 fState
= CONSOLE_STATE_NORMAL
;
576 UpdateCursor(fX
, fY
); // show it again