Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmpdcurses/pdcurses/getch.c
3153 views
1
/* PDCurses */
2
3
#include <curspriv.h>
4
5
/*man-start**************************************************************
6
7
getch
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
96
static 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
120
static 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
137
static 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 *= 3;
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
190
static 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
230
static 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
323
int 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
469
int 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
479
int 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
489
int 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
501
int 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
517
unsigned 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
527
int 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
539
int 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
558
int get_wch(wint_t *wch)
559
{
560
PDC_LOG(("get_wch() - called\n"));
561
562
return wget_wch(stdscr, wch);
563
}
564
565
int 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
575
int 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
585
int unget_wch(const wchar_t wch)
586
{
587
return PDC_ungetch(wch);
588
}
589
#endif
590
591