1 #include <stdio.h>
2 #include <curses.h>
3 #include <ipxe/ansicol.h>
4 #include <ipxe/console.h>
5
6 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
7
8 static void ansiscr_reset(struct _curses_screen *scr) __nonnull;
9 static void ansiscr_movetoyx(struct _curses_screen *scr,
10 unsigned int y, unsigned int x) __nonnull;
11 static void ansiscr_putc(struct _curses_screen *scr, chtype c) __nonnull;
12
13 static unsigned int saved_usage;
14
ansiscr_attrs(struct _curses_screen * scr,attr_t attrs)15 static void ansiscr_attrs ( struct _curses_screen *scr, attr_t attrs ) {
16 int bold = ( attrs & A_BOLD );
17 attr_t cpair = PAIR_NUMBER ( attrs );
18
19 if ( scr->attrs != attrs ) {
20 scr->attrs = attrs;
21 /* Reset attributes and set/clear bold as appropriate */
22 printf ( "\033[0;%dm", ( bold ? 1 : 22 ) );
23 /* Set foreground and background colours */
24 ansicol_set_pair ( cpair );
25 }
26 }
27
ansiscr_reset(struct _curses_screen * scr)28 static void ansiscr_reset ( struct _curses_screen *scr ) {
29 /* Reset terminal attributes and clear screen */
30 scr->attrs = 0;
31 scr->curs_x = 0;
32 scr->curs_y = 0;
33 printf ( "\0330m" );
34 ansicol_set_pair ( CPAIR_DEFAULT );
35 printf ( "\033[2J" );
36 }
37
ansiscr_init(struct _curses_screen * scr)38 static void ansiscr_init ( struct _curses_screen *scr ) {
39 saved_usage = console_set_usage ( CONSOLE_USAGE_TUI );
40 ansiscr_reset ( scr );
41 }
42
ansiscr_exit(struct _curses_screen * scr)43 static void ansiscr_exit ( struct _curses_screen *scr ) {
44 ansiscr_reset ( scr );
45 console_set_usage ( saved_usage );
46 }
47
ansiscr_erase(struct _curses_screen * scr,attr_t attrs)48 static void ansiscr_erase ( struct _curses_screen *scr, attr_t attrs ) {
49 ansiscr_attrs ( scr, attrs );
50 printf ( "\033[2J" );
51 }
52
ansiscr_movetoyx(struct _curses_screen * scr,unsigned int y,unsigned int x)53 static void ansiscr_movetoyx ( struct _curses_screen *scr,
54 unsigned int y, unsigned int x ) {
55 if ( ( x != scr->curs_x ) || ( y != scr->curs_y ) ) {
56 /* ANSI escape sequence to update cursor position */
57 printf ( "\033[%d;%dH", ( y + 1 ), ( x + 1 ) );
58 scr->curs_x = x;
59 scr->curs_y = y;
60 }
61 }
62
ansiscr_putc(struct _curses_screen * scr,chtype c)63 static void ansiscr_putc ( struct _curses_screen *scr, chtype c ) {
64 unsigned int character = ( c & A_CHARTEXT );
65 attr_t attrs = ( c & ( A_ATTRIBUTES | A_COLOR ) );
66
67 /* Update attributes if changed */
68 ansiscr_attrs ( scr, attrs );
69
70 /* Print the actual character */
71 putchar ( character );
72
73 /* Update expected cursor position */
74 if ( ++(scr->curs_x) == COLS ) {
75 scr->curs_x = 0;
76 ++scr->curs_y;
77 }
78 }
79
ansiscr_getc(struct _curses_screen * scr __unused)80 static int ansiscr_getc ( struct _curses_screen *scr __unused ) {
81 return getchar();
82 }
83
ansiscr_peek(struct _curses_screen * scr __unused)84 static bool ansiscr_peek ( struct _curses_screen *scr __unused ) {
85 return iskey();
86 }
87
ansiscr_cursor(struct _curses_screen * scr __unused,int visibility)88 static void ansiscr_cursor ( struct _curses_screen *scr __unused,
89 int visibility ) {
90 printf ( "\033[?25%c", ( visibility ? 'h' : 'l' ) );
91 }
92
93 SCREEN _ansi_screen = {
94 .init = ansiscr_init,
95 .exit = ansiscr_exit,
96 .erase = ansiscr_erase,
97 .movetoyx = ansiscr_movetoyx,
98 .putc = ansiscr_putc,
99 .getc = ansiscr_getc,
100 .peek = ansiscr_peek,
101 .cursor = ansiscr_cursor,
102 };
103