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