summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/hci/mucurses/kb.c
blob: 8face14d89593c873295dc11ccfe5dc579371d3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <curses.h>
#include <stddef.h>
#include <unistd.h>
#include "mucurses.h"

/** @file
 *
 * MuCurses keyboard input handling functions
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#define INPUT_DELAY 		200 // half-blocking delay timer resolution (ms)
#define INPUT_DELAY_TIMEOUT 	1000 // half-blocking delay timeout

int m_delay; /* 
		< 0 : blocking read
		0   : non-blocking read
		> 0 : timed blocking read
	     */
bool m_echo;
bool m_cbreak;

static int _wgetc ( WINDOW *win ) {
	int timer, c;

	if ( win == NULL )
		return ERR;

	timer = INPUT_DELAY_TIMEOUT;
	while ( ! win->scr->peek( win->scr ) ) {
		if ( m_delay == 0 ) // non-blocking read
			return ERR;
		if ( timer > 0 ) {  // time-limited blocking read
			if ( m_delay > 0 )
				timer -= INPUT_DELAY;
			mdelay( INPUT_DELAY );
		} else { return ERR; } // non-blocking read
	}

	c = win->scr->getc( win->scr );

	if ( m_echo && ( c >= 32 && c <= 126 ) ) // printable ASCII characters
		_wputch( win, (chtype) ( c | win->attrs ), WRAP );

	return c;
}

/**
 * Pop a character from the FIFO into a window
 *
 * @v *win	window in which to echo input
 * @ret c	char from input stream
 */
int wgetch ( WINDOW *win ) {
	int c;

	c = _wgetc( win );

	if ( m_echo ) {
		if ( c >= KEY_MIN ) {
			switch(c) {
			case KEY_LEFT :
			case KEY_BACKSPACE :
				_wcursback( win );
				wdelch( win );
				break;
			default :
				beep();
				break;
			}
		} else {
			_wputch( win, (chtype)( c | win->attrs ), WRAP );
		}
	}

	return c;
}

/**
 * Read at most n characters from the FIFO into a window
 *
 * @v *win	window in which to echo input
 * @v *str	pointer to string in which to store result
 * @v n		maximum number of characters to read into string (inc. NUL)
 * @ret rc	return status code
 */
int wgetnstr ( WINDOW *win, char *str, int n ) {
	char *_str;
	int c;

	if ( n == 0 ) {
		*str = '\0';
		return OK;
	}

	_str = str;

	while ( ( c = _wgetc( win ) ) != ERR ) {
		/* termination enforcement - don't let us go past the
		   end of the allocated buffer... */
		if ( n == 0 && ( c >= 32 && c <= 126 ) ) {
			_wcursback( win );
			wdelch( win );
		} else {
			if ( c >= KEY_MIN ) {
				switch(c) {
				case KEY_LEFT :
				case KEY_BACKSPACE :
					_wcursback( win );
					wdelch( win );
					break;
				case KEY_ENTER :
					*_str = '\0';
					return OK;
				default :
					beep();
					break;
				}
			}
			if ( c >= 32 && c <= 126 ) {
				*(_str++) = c; n--;
			}
		}
	}

	return ERR;
}


/**
 *
 */
int echo ( void ) {
	m_echo = TRUE;
	return OK;
}

/**
 *
 */
int noecho ( void ) {
	m_echo = FALSE;
	return OK;
}