aboutsummaryrefslogtreecommitdiff
path: root/scripts/kconfig/libcurses/getch.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kconfig/libcurses/getch.c')
-rw-r--r--scripts/kconfig/libcurses/getch.c589
1 files changed, 589 insertions, 0 deletions
diff --git a/scripts/kconfig/libcurses/getch.c b/scripts/kconfig/libcurses/getch.c
new file mode 100644
index 000000000..8719ca39c
--- /dev/null
+++ b/scripts/kconfig/libcurses/getch.c
@@ -0,0 +1,589 @@
1/* PDCurses */
2
3#include "curspriv.h"
4
5/*man-start**************************************************************
6
7getch
8-----
9
10### Synopsis
11
12 int getch(void);
13 int wgetch(WINDOW *win);
14 int mvgetch(int y, int x);
15 int mvwgetch(WINDOW *win, int y, int x);
16 int ungetch(int ch);
17 int flushinp(void);
18
19 int get_wch(wint_t *wch);
20 int wget_wch(WINDOW *win, wint_t *wch);
21 int mvget_wch(int y, int x, wint_t *wch);
22 int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch);
23 int unget_wch(const wchar_t wch);
24
25 unsigned long PDC_get_key_modifiers(void);
26 int PDC_return_key_modifiers(bool flag);
27
28### Description
29
30 With the getch(), wgetch(), mvgetch(), and mvwgetch() functions, a
31 character is read from the terminal associated with the window. In
32 nodelay mode, if there is no input waiting, the value ERR is
33 returned. In delay mode, the program will hang until the system
34 passes text through to the program. Depending on the setting of
35 cbreak(), this will be after one character or after the first
36 newline. Unless noecho() has been set, the character will also be
37 echoed into the designated window.
38
39 If keypad() is TRUE, and a function key is pressed, the token for
40 that function key will be returned instead of the raw characters.
41 Possible function keys are defined in "curses.h" with integers
42 beginning with 0401, whose names begin with KEY_.
43
44 If nodelay(win, TRUE) has been called on the window and no input is
45 waiting, the value ERR is returned.
46
47 ungetch() places ch back onto the input queue to be returned by the
48 next call to wgetch().
49
50 flushinp() throws away any type-ahead that has been typed by the user
51 and has not yet been read by the program.
52
53 wget_wch() is the wide-character version of wgetch(), available when
54 PDCurses is built with the PDC_WIDE option. It takes a pointer to a
55 wint_t rather than returning the key as an int, and instead returns
56 KEY_CODE_YES if the key is a function key. Otherwise, it returns OK
57 or ERR. It's important to check for KEY_CODE_YES, since regular wide
58 characters can have the same values as function key codes.
59
60 unget_wch() puts a wide character on the input queue.
61
62 PDC_get_key_modifiers() returns the keyboard modifiers (shift,
63 control, alt, numlock) effective at the time of the last getch()
64 call. Use the macros PDC_KEY_MODIFIER_* to determine which
65 modifier(s) were set. PDC_return_key_modifiers() tells getch() to
66 return modifier keys pressed alone as keystrokes (KEY_ALT_L, etc.).
67 These may not work on all platforms.
68
69 NOTE: getch() and ungetch() are implemented as macros, to avoid
70 conflict with many DOS compiler's runtime libraries.
71
72### Return Value
73
74 These functions return ERR or the value of the character, meta
75 character or function key token.
76
77### Portability
78 X/Open ncurses NetBSD
79 getch Y Y Y
80 wgetch Y Y Y
81 mvgetch Y Y Y
82 mvwgetch Y Y Y
83 ungetch Y Y Y
84 flushinp Y Y Y
85 get_wch Y Y Y
86 wget_wch Y Y Y
87 mvget_wch Y Y Y
88 mvwget_wch Y Y Y
89 unget_wch Y Y Y
90 PDC_get_key_modifiers - - -
91
92**man-end****************************************************************/
93
94#include <stdlib.h>
95
96static int _get_box(int *y_start, int *y_end, int *x_start, int *x_end)
97{
98 int start, end;
99
100 if (SP->sel_start < SP->sel_end)
101 {
102 start = SP->sel_start;
103 end = SP->sel_end;
104 }
105 else
106 {
107 start = SP->sel_end;
108 end = SP->sel_start;
109 }
110
111 *y_start = start / COLS;
112 *x_start = start % COLS;
113
114 *y_end = end / COLS;
115 *x_end = end % COLS;
116
117 return (end - start) + (*y_end - *y_start);
118}
119
120static void _highlight(void)
121{
122 int i, j, y_start, y_end, x_start, x_end;
123
124 if (-1 == SP->sel_start)
125 return;
126
127 _get_box(&y_start, &y_end, &x_start, &x_end);
128
129 for (j = y_start; j <= y_end; j++)
130 for (i = (j == y_start ? x_start : 0);
131 i < (j == y_end ? x_end : COLS); i++)
132 curscr->_y[j][i] ^= A_REVERSE;
133
134 wrefresh(curscr);
135}
136
137static void _copy(void)
138{
139#ifdef PDC_WIDE
140 wchar_t *wtmp;
141# define TMP wtmp
142# define MASK A_CHARTEXT
143#else
144# define TMP tmp
145# define MASK 0xff
146#endif
147 char *tmp;
148 long pos;
149 int i, j, y_start, y_end, x_start, x_end, len;
150
151 if (-1 == SP->sel_start)
152 return;
153
154 len = _get_box(&y_start, &y_end, &x_start, &x_end);
155
156 if (!len)
157 return;
158
159#ifdef PDC_WIDE
160 wtmp = malloc((len + 1) * sizeof(wchar_t));
161 len *= 4;
162#endif
163 tmp = malloc(len + 1);
164
165 for (j = y_start, pos = 0; j <= y_end; j++)
166 {
167 for (i = (j == y_start ? x_start : 0);
168 i < (j == y_end ? x_end : COLS); i++)
169 TMP[pos++] = curscr->_y[j][i] & MASK;
170
171 while (y_start != y_end && pos > 0 && TMP[pos - 1] == 32)
172 pos--;
173
174 if (j < y_end)
175 TMP[pos++] = 10;
176 }
177 TMP[pos] = 0;
178
179#ifdef PDC_WIDE
180 pos = PDC_wcstombs(tmp, wtmp, len);
181#endif
182
183 PDC_setclipboard(tmp, pos);
184 free(tmp);
185#ifdef PDC_WIDE
186 free(wtmp);
187#endif
188}
189
190static int _paste(void)
191{
192#ifdef PDC_WIDE
193 wchar_t *wpaste;
194# define PASTE wpaste
195#else
196# define PASTE paste
197#endif
198 char *paste;
199 long len, newmax;
200 int key;
201
202 key = PDC_getclipboard(&paste, &len);
203 if (PDC_CLIP_SUCCESS != key || !len)
204 return -1;
205
206#ifdef PDC_WIDE
207 wpaste = malloc(len * sizeof(wchar_t));
208 len = PDC_mbstowcs(wpaste, paste, len);
209#endif
210 newmax = len + SP->c_ungind;
211 if (newmax > SP->c_ungmax)
212 {
213 SP->c_ungch = realloc(SP->c_ungch, newmax * sizeof(int));
214 if (!SP->c_ungch)
215 return -1;
216 SP->c_ungmax = newmax;
217 }
218 while (len > 1)
219 PDC_ungetch(PASTE[--len]);
220 key = *PASTE;
221#ifdef PDC_WIDE
222 free(wpaste);
223#endif
224 PDC_freeclipboard(paste);
225 SP->key_modifiers = 0;
226
227 return key;
228}
229
230static int _mouse_key(void)
231{
232 int i, key = KEY_MOUSE, changes = SP->mouse_status.changes;
233 unsigned long mbe = SP->_trap_mbe;
234
235 /* Selection highlighting? */
236
237 if ((!mbe || SP->mouse_status.button[0] & BUTTON_SHIFT) && changes & 1)
238 {
239 i = SP->mouse_status.y * COLS + SP->mouse_status.x;
240 switch (SP->mouse_status.button[0] & BUTTON_ACTION_MASK)
241 {
242 case BUTTON_PRESSED:
243 _highlight();
244 SP->sel_start = SP->sel_end = i;
245 return -1;
246 case BUTTON_MOVED:
247 _highlight();
248 SP->sel_end = i;
249 _highlight();
250 return -1;
251 case BUTTON_RELEASED:
252 _copy();
253 return -1;
254 }
255 }
256 else if ((!mbe || SP->mouse_status.button[1] & BUTTON_SHIFT) &&
257 changes & 2 && (SP->mouse_status.button[1] &
258 BUTTON_ACTION_MASK) == BUTTON_CLICKED)
259 {
260 SP->key_code = FALSE;
261 return _paste();
262 }
263
264 /* Filter unwanted mouse events */
265
266 for (i = 0; i < 3; i++)
267 {
268 if (changes & (1 << i))
269 {
270 int shf = i * 5;
271 short button = SP->mouse_status.button[i] & BUTTON_ACTION_MASK;
272
273 if ( (!(mbe & (BUTTON1_PRESSED << shf)) &&
274 (button == BUTTON_PRESSED))
275
276 || (!(mbe & (BUTTON1_CLICKED << shf)) &&
277 (button == BUTTON_CLICKED))
278
279 || (!(mbe & (BUTTON1_DOUBLE_CLICKED << shf)) &&
280 (button == BUTTON_DOUBLE_CLICKED))
281
282 || (!(mbe & (BUTTON1_MOVED << shf)) &&
283 (button == BUTTON_MOVED))
284
285 || (!(mbe & (BUTTON1_RELEASED << shf)) &&
286 (button == BUTTON_RELEASED))
287 )
288 SP->mouse_status.changes ^= (1 << i);
289 }
290 }
291
292 if (changes & PDC_MOUSE_MOVED)
293 {
294 if (!(mbe & (BUTTON1_MOVED|BUTTON2_MOVED|BUTTON3_MOVED)))
295 SP->mouse_status.changes ^= PDC_MOUSE_MOVED;
296 }
297
298 if (changes & (PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN))
299 {
300 if (!(mbe & MOUSE_WHEEL_SCROLL))
301 SP->mouse_status.changes &=
302 ~(PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN);
303 }
304
305 if (!changes)
306 return -1;
307
308 /* Check for click in slk area */
309
310 i = PDC_mouse_in_slk(SP->mouse_status.y, SP->mouse_status.x);
311
312 if (i)
313 {
314 if (SP->mouse_status.button[0] & (BUTTON_PRESSED|BUTTON_CLICKED))
315 key = KEY_F(i);
316 else
317 key = -1;
318 }
319
320 return key;
321}
322
323int wgetch(WINDOW *win)
324{
325 int key, waitcount;
326
327 PDC_LOG(("wgetch() - called\n"));
328
329 if (!win || !SP)
330 return ERR;
331
332 waitcount = 0;
333
334 /* set the number of 1/20th second napms() calls */
335
336 if (SP->delaytenths)
337 waitcount = 2 * SP->delaytenths;
338 else
339 if (win->_delayms)
340 {
341 /* Can't really do millisecond intervals, so delay in
342 1/20ths of a second (50ms) */
343
344 waitcount = win->_delayms / 50;
345 if (!waitcount)
346 waitcount = 1;
347 }
348
349 /* refresh window when wgetch is called if there have been changes
350 to it and it is not a pad */
351
352 if (!(win->_flags & _PAD) && ((!win->_leaveit &&
353 (win->_begx + win->_curx != SP->curscol ||
354 win->_begy + win->_cury != SP->cursrow)) || is_wintouched(win)))
355 wrefresh(win);
356
357 /* if ungotten char exists, remove and return it */
358
359 if (SP->c_ungind)
360 return SP->c_ungch[--(SP->c_ungind)];
361
362 /* if normal and data in buffer */
363
364 if ((!SP->raw_inp && !SP->cbreak) && (SP->c_gindex < SP->c_pindex))
365 return SP->c_buffer[SP->c_gindex++];
366
367 /* prepare to buffer data */
368
369 SP->c_pindex = 0;
370 SP->c_gindex = 0;
371
372 /* to get here, no keys are buffered. go and get one. */
373
374 for (;;) /* loop for any buffering */
375 {
376 /* is there a keystroke ready? */
377
378 if (!PDC_check_key())
379 {
380 /* if not, handle timeout() and halfdelay() */
381
382 if (SP->delaytenths || win->_delayms)
383 {
384 if (!waitcount)
385 return ERR;
386
387 waitcount--;
388 }
389 else
390 if (win->_nodelay)
391 return ERR;
392
393 napms(50); /* sleep for 1/20th second */
394 continue; /* then check again */
395 }
396
397 /* if there is, fetch it */
398
399 key = PDC_get_key();
400
401 /* copy or paste? */
402
403 if (SP->key_modifiers & PDC_KEY_MODIFIER_SHIFT)
404 {
405 if (0x03 == key)
406 {
407 _copy();
408 continue;
409 }
410 else if (0x16 == key)
411 key = _paste();
412 }
413
414 /* filter mouse events; translate mouse clicks in the slk
415 area to function keys */
416
417 if (SP->key_code && key == KEY_MOUSE)
418 key = _mouse_key();
419
420 /* filter special keys if not in keypad mode */
421
422 if (SP->key_code && !win->_use_keypad)
423 key = -1;
424
425 /* unwanted key? loop back */
426
427 if (key == -1)
428 continue;
429
430 _highlight();
431 SP->sel_start = SP->sel_end = -1;
432
433 /* translate CR */
434
435 if (key == '\r' && SP->autocr && !SP->raw_inp)
436 key = '\n';
437
438 /* if echo is enabled */
439
440 if (SP->echo && !SP->key_code)
441 {
442 waddch(win, key);
443 wrefresh(win);
444 }
445
446 /* if no buffering */
447
448 if (SP->raw_inp || SP->cbreak)
449 return key;
450
451 /* if no overflow, put data in buffer */
452
453 if (key == '\b')
454 {
455 if (SP->c_pindex > SP->c_gindex)
456 SP->c_pindex--;
457 }
458 else
459 if (SP->c_pindex < _INBUFSIZ - 2)
460 SP->c_buffer[SP->c_pindex++] = key;
461
462 /* if we got a line */
463
464 if (key == '\n' || key == '\r')
465 return SP->c_buffer[SP->c_gindex++];
466 }
467}
468
469int mvgetch(int y, int x)
470{
471 PDC_LOG(("mvgetch() - called\n"));
472
473 if (move(y, x) == ERR)
474 return ERR;
475
476 return wgetch(stdscr);
477}
478
479int mvwgetch(WINDOW *win, int y, int x)
480{
481 PDC_LOG(("mvwgetch() - called\n"));
482
483 if (wmove(win, y, x) == ERR)
484 return ERR;
485
486 return wgetch(win);
487}
488
489int PDC_ungetch(int ch)
490{
491 PDC_LOG(("ungetch() - called\n"));
492
493 if (SP->c_ungind >= SP->c_ungmax) /* pushback stack full */
494 return ERR;
495
496 SP->c_ungch[SP->c_ungind++] = ch;
497
498 return OK;
499}
500
501int flushinp(void)
502{
503 PDC_LOG(("flushinp() - called\n"));
504
505 if (!SP)
506 return ERR;
507
508 PDC_flushinp();
509
510 SP->c_gindex = 1; /* set indices to kill buffer */
511 SP->c_pindex = 0;
512 SP->c_ungind = 0; /* clear SP->c_ungch array */
513
514 return OK;
515}
516
517unsigned long PDC_get_key_modifiers(void)
518{
519 PDC_LOG(("PDC_get_key_modifiers() - called\n"));
520
521 if (!SP)
522 return ERR;
523
524 return SP->key_modifiers;
525}
526
527int PDC_return_key_modifiers(bool flag)
528{
529 PDC_LOG(("PDC_return_key_modifiers() - called\n"));
530
531 if (!SP)
532 return ERR;
533
534 SP->return_key_modifiers = flag;
535 return PDC_modifiers_set();
536}
537
538#ifdef PDC_WIDE
539int wget_wch(WINDOW *win, wint_t *wch)
540{
541 int key;
542
543 PDC_LOG(("wget_wch() - called\n"));
544
545 if (!wch)
546 return ERR;
547
548 key = wgetch(win);
549
550 if (key == ERR)
551 return ERR;
552
553 *wch = key;
554
555 return SP->key_code ? KEY_CODE_YES : OK;
556}
557
558int get_wch(wint_t *wch)
559{
560 PDC_LOG(("get_wch() - called\n"));
561
562 return wget_wch(stdscr, wch);
563}
564
565int mvget_wch(int y, int x, wint_t *wch)
566{
567 PDC_LOG(("mvget_wch() - called\n"));
568
569 if (move(y, x) == ERR)
570 return ERR;
571
572 return wget_wch(stdscr, wch);
573}
574
575int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch)
576{
577 PDC_LOG(("mvwget_wch() - called\n"));
578
579 if (wmove(win, y, x) == ERR)
580 return ERR;
581
582 return wget_wch(win, wch);
583}
584
585int unget_wch(const wchar_t wch)
586{
587 return PDC_ungetch(wch);
588}
589#endif