[prefix] Use garbage-collectable section names
[ipxe.git] / src / hci / mucurses / kb.c
1 #include <curses.h>
2 #include <stddef.h>
3 #include <unistd.h>
4 #include "mucurses.h"
5
6 /** @file
7 *
8 * MuCurses keyboard input handling functions
9 */
10
11 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
12
13 #define INPUT_DELAY 200 // half-blocking delay timer resolution (ms)
14 #define INPUT_DELAY_TIMEOUT 1000 // half-blocking delay timeout
15
16 int m_delay; /*
17 < 0 : blocking read
18 0 : non-blocking read
19 > 0 : timed blocking read
20 */
21 bool m_echo;
22 bool m_cbreak;
23
24 static int _wgetc ( WINDOW *win ) {
25 int timer, c;
26
27 if ( win == NULL )
28 return ERR;
29
30 timer = INPUT_DELAY_TIMEOUT;
31 while ( ! win->scr->peek( win->scr ) ) {
32 if ( m_delay == 0 ) // non-blocking read
33 return ERR;
34 if ( timer > 0 ) { // time-limited blocking read
35 if ( m_delay > 0 )
36 timer -= INPUT_DELAY;
37 mdelay( INPUT_DELAY );
38 } else { return ERR; } // non-blocking read
39 }
40
41 c = win->scr->getc( win->scr );
42
43 if ( m_echo && ( c >= 32 && c <= 126 ) ) // printable ASCII characters
44 _wputch( win, (chtype) ( c | win->attrs ), WRAP );
45
46 return c;
47 }
48
49 /**
50 * Pop a character from the FIFO into a window
51 *
52 * @v *win window in which to echo input
53 * @ret c char from input stream
54 */
55 int wgetch ( WINDOW *win ) {
56 int c;
57
58 c = _wgetc( win );
59
60 if ( m_echo ) {
61 if ( c >= KEY_MIN ) {
62 switch(c) {
63 case KEY_LEFT :
64 case KEY_BACKSPACE :
65 _wcursback( win );
66 wdelch( win );
67 break;
68 default :
69 beep();
70 break;
71 }
72 } else {
73 _wputch( win, (chtype)( c | win->attrs ), WRAP );
74 }
75 }
76
77 return c;
78 }
79
80 /**
81 * Read at most n characters from the FIFO into a window
82 *
83 * @v *win window in which to echo input
84 * @v *str pointer to string in which to store result
85 * @v n maximum number of characters to read into string (inc. NUL)
86 * @ret rc return status code
87 */
88 int wgetnstr ( WINDOW *win, char *str, int n ) {
89 char *_str;
90 int c;
91
92 if ( n == 0 ) {
93 *str = '\0';
94 return OK;
95 }
96
97 _str = str;
98
99 while ( ( c = _wgetc( win ) ) != ERR ) {
100 /* termination enforcement - don't let us go past the
101 end of the allocated buffer... */
102 if ( n == 0 && ( c >= 32 && c <= 126 ) ) {
103 _wcursback( win );
104 wdelch( win );
105 } else {
106 if ( c >= KEY_MIN ) {
107 switch(c) {
108 case KEY_LEFT :
109 case KEY_BACKSPACE :
110 _wcursback( win );
111 wdelch( win );
112 break;
113 case KEY_ENTER :
114 *_str = '\0';
115 return OK;
116 default :
117 beep();
118 break;
119 }
120 }
121 if ( c >= 32 && c <= 126 ) {
122 *(_str++) = c; n--;
123 }
124 }
125 }
126
127 return ERR;
128 }
129
130
131 /**
132 *
133 */
134 int echo ( void ) {
135 m_echo = TRUE;
136 return OK;
137 }
138
139 /**
140 *
141 */
142 int noecho ( void ) {
143 m_echo = FALSE;
144 return OK;
145 }