aboutsummaryrefslogtreecommitdiff
path: root/scripts/kconfig/libcurses/getch.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--scripts/kconfig/libcurses/getch.c591
1 files changed, 591 insertions, 0 deletions
diff --git a/scripts/kconfig/libcurses/getch.c b/scripts/kconfig/libcurses/getch.c
new file mode 100644
index 000000000..9d771ec0e
--- /dev/null
+++ b/scripts/kconfig/libcurses/getch.c
@@ -0,0 +1,591 @@
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
79 Function | X/Open | ncurses | NetBSD
80 :---------------------|:------:|:-------:|:------:
81 getch | Y | Y | Y
82 wgetch | Y | Y | Y
83 mvgetch | Y | Y | Y
84 mvwgetch | Y | Y | Y
85 ungetch | Y | Y | Y
86 flushinp | Y | Y | Y
87 get_wch | Y | Y | Y
88 wget_wch | Y | Y | Y
89 mvget_wch | Y | Y | Y
90 mvwget_wch | Y | Y | Y
91 unget_wch | Y | Y | Y
92 PDC_get_key_modifiers | - | - | -
93
94**man-end****************************************************************/
95
96#include <stdlib.h>
97
98static int _get_box(int *y_start, int *y_end, int *x_start, int *x_end)
99{
100 int start, end;
101
102 if (SP->sel_start < SP->sel_end)
103 {
104 start = SP->sel_start;
105 end = SP->sel_end;
106 }
107 else
108 {
109 start = SP->sel_end;
110 end = SP->sel_start;
111 }
112
113 *y_start = start / COLS;
114 *x_start = start % COLS;
115
116 *y_end = end / COLS;
117 *x_end = end % COLS;
118
119 return (end - start) + (*y_end - *y_start);
120}
121
122static void _highlight(void)
123{
124 int i, j, y_start, y_end, x_start, x_end;
125
126 if (-1 == SP->sel_start)
127 return;
128
129 _get_box(&y_start, &y_end, &x_start, &x_end);
130
131 for (j = y_start; j <= y_end; j++)
132 for (i = (j == y_start ? x_start : 0);
133 i < (j == y_end ? x_end : COLS); i++)
134 curscr->_y[j][i] ^= A_REVERSE;
135
136 wrefresh(curscr);
137}
138
139static void _copy(void)
140{
141#ifdef PDC_WIDE
142 wchar_t *wtmp;
143# define TMP wtmp
144# define MASK A_CHARTEXT
145#else
146# define TMP tmp
147# define MASK 0xff
148#endif
149 char *tmp;
150 long pos;
151 int i, j, y_start, y_end, x_start, x_end, len;
152
153 if (-1 == SP->sel_start)
154 return;
155
156 len = _get_box(&y_start, &y_end, &x_start, &x_end);
157
158 if (!len)
159 return;
160
161#ifdef PDC_WIDE
162 wtmp = malloc((len + 1) * sizeof(wchar_t));
163 len *= 4;
164#endif
165 tmp = malloc(len + 1);
166
167 for (j = y_start, pos = 0; j <= y_end; j++)
168 {
169 for (i = (j == y_start ? x_start : 0);
170 i < (j == y_end ? x_end : COLS); i++)
171 TMP[pos++] = curscr->_y[j][i] & MASK;
172
173 while (y_start != y_end && pos > 0 && TMP[pos - 1] == 32)
174 pos--;
175
176 if (j < y_end)
177 TMP[pos++] = 10;
178 }
179 TMP[pos] = 0;
180
181#ifdef PDC_WIDE
182 pos = PDC_wcstombs(tmp, wtmp, len);
183#endif
184
185 PDC_setclipboard(tmp, pos);
186 free(tmp);
187#ifdef PDC_WIDE
188 free(wtmp);
189#endif
190}
191
192static int _paste(void)
193{
194#ifdef PDC_WIDE
195 wchar_t *wpaste;
196# define PASTE wpaste
197#else
198# define PASTE paste
199#endif
200 char *paste;
201 long len, newmax;
202 int key;
203
204 key = PDC_getclipboard(&paste, &len);
205 if (PDC_CLIP_SUCCESS != key || !len)
206 return -1;
207
208#ifdef PDC_WIDE
209 wpaste = malloc(len * sizeof(wchar_t));
210 len = PDC_mbstowcs(wpaste, paste, len);
211#endif
212 newmax = len + SP->c_ungind;
213 if (newmax > SP->c_ungmax)
214 {
215 SP->c_ungch = realloc(SP->c_ungch, newmax * sizeof(int));
216 if (!SP->c_ungch)
217 return -1;
218 SP->c_ungmax = newmax;
219 }
220 while (len > 1)
221 PDC_ungetch(PASTE[--len]);
222 key = *PASTE;
223#ifdef PDC_WIDE
224 free(wpaste);
225#endif
226 PDC_freeclipboard(paste);
227 SP->key_modifiers = 0;
228
229 return key;
230}
231
232static int _mouse_key(void)
233{
234 int i, key = KEY_MOUSE, changes = SP->mouse_status.changes;
235 unsigned long mbe = SP->_trap_mbe;
236
237 /* Selection highlighting? */
238
239 if ((!mbe || SP->mouse_status.button[0] & BUTTON_SHIFT) && changes & 1)
240 {
241 i = SP->mouse_status.y * COLS + SP->mouse_status.x;
242 switch (SP->mouse_status.button[0] & BUTTON_ACTION_MASK)
243 {
244 case BUTTON_PRESSED:
245 _highlight();
246 SP->sel_start = SP->sel_end = i;
247 return -1;
248 case BUTTON_MOVED:
249 _highlight();
250 SP->sel_end = i;
251 _highlight();
252 return -1;
253 case BUTTON_RELEASED:
254 _copy();
255 return -1;
256 }
257 }
258 else if ((!mbe || SP->mouse_status.button[1] & BUTTON_SHIFT) &&
259 changes & 2 && (SP->mouse_status.button[1] &
260 BUTTON_ACTION_MASK) == BUTTON_CLICKED)
261 {
262 SP->key_code = FALSE;
263 return _paste();
264 }
265
266 /* Filter unwanted mouse events */
267
268 for (i = 0; i < 3; i++)
269 {
270 if (changes & (1 << i))
271 {
272 int shf = i * 5;
273 short button = SP->mouse_status.button[i] & BUTTON_ACTION_MASK;
274
275 if ( (!(mbe & (BUTTON1_PRESSED << shf)) &&
276 (button == BUTTON_PRESSED))
277
278 || (!(mbe & (BUTTON1_CLICKED << shf)) &&
279 (button == BUTTON_CLICKED))
280
281 || (!(mbe & (BUTTON1_DOUBLE_CLICKED << shf)) &&
282 (button == BUTTON_DOUBLE_CLICKED))
283
284 || (!(mbe & (BUTTON1_MOVED << shf)) &&
285 (button == BUTTON_MOVED))
286
287 || (!(mbe & (BUTTON1_RELEASED << shf)) &&
288 (button == BUTTON_RELEASED))
289 )
290 SP->mouse_status.changes ^= (1 << i);
291 }
292 }
293
294 if (changes & PDC_MOUSE_MOVED)
295 {
296 if (!(mbe & (BUTTON1_MOVED|BUTTON2_MOVED|BUTTON3_MOVED)))
297 SP->mouse_status.changes ^= PDC_MOUSE_MOVED;
298 }
299
300 if (changes & (PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN))
301 {
302 if (!(mbe & MOUSE_WHEEL_SCROLL))
303 SP->mouse_status.changes &=
304 ~(PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN);
305 }
306
307 if (!changes)
308 return -1;
309
310 /* Check for click in slk area */
311
312 i = PDC_mouse_in_slk(SP->mouse_status.y, SP->mouse_status.x);
313
314 if (i)
315 {
316 if (SP->mouse_status.button[0] & (BUTTON_PRESSED|BUTTON_CLICKED))
317 key = KEY_F(i);
318 else
319 key = -1;
320 }
321
322 return key;
323}
324
325int wgetch(WINDOW *win)
326{
327 int key, waitcount;
328
329 PDC_LOG(("wgetch() - called\n"));
330
331 if (!win || !SP)
332 return ERR;
333
334 waitcount = 0;
335
336 /* set the number of 1/20th second napms() calls */
337
338 if (SP->delaytenths)
339 waitcount = 2 * SP->delaytenths;
340 else
341 if (win->_delayms)
342 {
343 /* Can't really do millisecond intervals, so delay in
344 1/20ths of a second (50ms) */
345
346 waitcount = win->_delayms / 50;
347 if (!waitcount)
348 waitcount = 1;
349 }
350
351 /* refresh window when wgetch is called if there have been changes
352 to it and it is not a pad */
353
354 if (!(win->_flags & _PAD) && ((!win->_leaveit &&
355 (win->_begx + win->_curx != SP->curscol ||
356 win->_begy + win->_cury != SP->cursrow)) || is_wintouched(win)))
357 wrefresh(win);
358
359 /* if ungotten char exists, remove and return it */
360
361 if (SP->c_ungind)
362 return SP->c_ungch[--(SP->c_ungind)];
363
364 /* if normal and data in buffer */
365
366 if ((!SP->raw_inp && !SP->cbreak) && (SP->c_gindex < SP->c_pindex))
367 return SP->c_buffer[SP->c_gindex++];
368
369 /* prepare to buffer data */
370
371 SP->c_pindex = 0;
372 SP->c_gindex = 0;
373
374 /* to get here, no keys are buffered. go and get one. */
375
376 for (;;) /* loop for any buffering */
377 {
378 /* is there a keystroke ready? */
379
380 if (!PDC_check_key())
381 {
382 /* if not, handle timeout() and halfdelay() */
383
384 if (SP->delaytenths || win->_delayms)
385 {
386 if (!waitcount)
387 return ERR;
388
389 waitcount--;
390 }
391 else
392 if (win->_nodelay)
393 return ERR;
394
395 napms(50); /* sleep for 1/20th second */
396 continue; /* then check again */
397 }
398
399 /* if there is, fetch it */
400
401 key = PDC_get_key();
402
403 /* copy or paste? */
404
405 if (SP->key_modifiers & PDC_KEY_MODIFIER_SHIFT)
406 {
407 if (0x03 == key)
408 {
409 _copy();
410 continue;
411 }
412 else if (0x16 == key)
413 key = _paste();
414 }
415
416 /* filter mouse events; translate mouse clicks in the slk
417 area to function keys */
418
419 if (SP->key_code && key == KEY_MOUSE)
420 key = _mouse_key();
421
422 /* filter special keys if not in keypad mode */
423
424 if (SP->key_code && !win->_use_keypad)
425 key = -1;
426
427 /* unwanted key? loop back */
428
429 if (key == -1)
430 continue;
431
432 _highlight();
433 SP->sel_start = SP->sel_end = -1;
434
435 /* translate CR */
436
437 if (key == '\r' && SP->autocr && !SP->raw_inp)
438 key = '\n';
439
440 /* if echo is enabled */
441
442 if (SP->echo && !SP->key_code)
443 {
444 waddch(win, key);
445 wrefresh(win);
446 }
447
448 /* if no buffering */
449
450 if (SP->raw_inp || SP->cbreak)
451 return key;
452
453 /* if no overflow, put data in buffer */
454
455 if (key == '\b')
456 {
457 if (SP->c_pindex > SP->c_gindex)
458 SP->c_pindex--;
459 }
460 else
461 if (SP->c_pindex < _INBUFSIZ - 2)
462 SP->c_buffer[SP->c_pindex++] = key;
463
464 /* if we got a line */
465
466 if (key == '\n' || key == '\r')
467 return SP->c_buffer[SP->c_gindex++];
468 }
469}
470
471int mvgetch(int y, int x)
472{
473 PDC_LOG(("mvgetch() - called\n"));
474
475 if (move(y, x) == ERR)
476 return ERR;
477
478 return wgetch(stdscr);
479}
480
481int mvwgetch(WINDOW *win, int y, int x)
482{
483 PDC_LOG(("mvwgetch() - called\n"));
484
485 if (wmove(win, y, x) == ERR)
486 return ERR;
487
488 return wgetch(win);
489}
490
491int PDC_ungetch(int ch)
492{
493 PDC_LOG(("ungetch() - called\n"));
494
495 if (SP->c_ungind >= SP->c_ungmax) /* pushback stack full */
496 return ERR;
497
498 SP->c_ungch[SP->c_ungind++] = ch;
499
500 return OK;
501}
502
503int flushinp(void)
504{
505 PDC_LOG(("flushinp() - called\n"));
506
507 if (!SP)
508 return ERR;
509
510 PDC_flushinp();
511
512 SP->c_gindex = 1; /* set indices to kill buffer */
513 SP->c_pindex = 0;
514 SP->c_ungind = 0; /* clear SP->c_ungch array */
515
516 return OK;
517}
518
519unsigned long PDC_get_key_modifiers(void)
520{
521 PDC_LOG(("PDC_get_key_modifiers() - called\n"));
522
523 if (!SP)
524 return ERR;
525
526 return SP->key_modifiers;
527}
528
529int PDC_return_key_modifiers(bool flag)
530{
531 PDC_LOG(("PDC_return_key_modifiers() - called\n"));
532
533 if (!SP)
534 return ERR;
535
536 SP->return_key_modifiers = flag;
537 return PDC_modifiers_set();
538}
539
540#ifdef PDC_WIDE
541int wget_wch(WINDOW *win, wint_t *wch)
542{
543 int key;
544
545 PDC_LOG(("wget_wch() - called\n"));
546
547 if (!wch)
548 return ERR;
549
550 key = wgetch(win);
551
552 if (key == ERR)
553 return ERR;
554
555 *wch = key;
556
557 return SP->key_code ? KEY_CODE_YES : OK;
558}
559
560int get_wch(wint_t *wch)
561{
562 PDC_LOG(("get_wch() - called\n"));
563
564 return wget_wch(stdscr, wch);
565}
566
567int mvget_wch(int y, int x, wint_t *wch)
568{
569 PDC_LOG(("mvget_wch() - called\n"));
570
571 if (move(y, x) == ERR)
572 return ERR;
573
574 return wget_wch(stdscr, wch);
575}
576
577int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch)
578{
579 PDC_LOG(("mvwget_wch() - called\n"));
580
581 if (wmove(win, y, x) == ERR)
582 return ERR;
583
584 return wget_wch(win, wch);
585}
586
587int unget_wch(const wchar_t wch)
588{
589 return PDC_ungetch(wch);
590}
591#endif