1 /* Public Domain Curses */
5 RCSID("$Id: getch.c,v 1.72 2008/07/13 16:08:18 wmcbrine Exp $")
7 /*man-start**************************************************************
13 int wgetch(WINDOW *win);
14 int mvgetch(int y, int x);
15 int mvwgetch(WINDOW *win, int y, int x);
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);
25 unsigned long PDC_get_key_modifiers(void);
26 int PDC_save_key_modifiers(bool flag);
27 int PDC_return_key_modifiers(bool flag);
30 With the getch(), wgetch(), mvgetch(), and mvwgetch() functions,
31 a character is read from the terminal associated with the window.
32 In 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
37 be echoed into the designated window.
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_.
44 If nodelay(win, TRUE) has been called on the window and no input
45 is waiting, the value ERR is returned.
47 ungetch() places ch back onto the input queue to be returned by
48 the next call to wgetch().
50 flushinp() throws away any type-ahead that has been typed by the
51 user and has not yet been read by the program.
53 PDC_get_key_modifiers() returns the keyboard modifiers (shift,
54 control, alt, numlock) effective at the time of the last getch()
55 call, if PDC_save_key_modifiers(TRUE) has been called before the
56 getch(). Use the macros PDC_KEY_MODIFIER_* to determine which
57 modifier(s) were set. PDC_return_key_modifiers() tells getch()
58 to return modifier keys pressed alone as keystrokes (KEY_ALT_L,
59 etc.). These may not work on all platforms.
61 NOTE: getch() and ungetch() are implemented as macros, to avoid
62 conflict with many DOS compiler's runtime libraries.
65 These functions return ERR or the value of the character, meta
66 character or function key token.
68 Portability X/Open BSD SYS V
80 PDC_get_key_modifiers - - -
82 **man-end****************************************************************/
84 #define _INBUFSIZ 512 /* size of terminal input buffer */
85 #define NUNGETCH 256 /* max # chars to ungetch() */
87 static int c_pindex
= 0; /* putter index */
88 static int c_gindex
= 1; /* getter index */
89 static int c_ungind
= 0; /* ungetch() push index */
90 static int c_ungch
[NUNGETCH
]; /* array of ungotten chars */
92 static int _mouse_key(WINDOW
*win
)
94 int i
, key
= KEY_MOUSE
;
95 unsigned long mbe
= SP
->_trap_mbe
;
97 /* Filter unwanted mouse events */
99 for (i
= 0; i
< 3; i
++)
101 if (pdc_mouse_status
.changes
& (1 << i
))
104 short button
= pdc_mouse_status
.button
[i
] & BUTTON_ACTION_MASK
;
106 if ( (!(mbe
& (BUTTON1_PRESSED
<< shf
)) &&
107 (button
== BUTTON_PRESSED
))
109 || (!(mbe
& (BUTTON1_CLICKED
<< shf
)) &&
110 (button
== BUTTON_CLICKED
))
112 || (!(mbe
& (BUTTON1_DOUBLE_CLICKED
<< shf
)) &&
113 (button
== BUTTON_DOUBLE_CLICKED
))
115 || (!(mbe
& (BUTTON1_MOVED
<< shf
)) &&
116 (button
== BUTTON_MOVED
))
118 || (!(mbe
& (BUTTON1_RELEASED
<< shf
)) &&
119 (button
== BUTTON_RELEASED
))
121 pdc_mouse_status
.changes
^= (1 << i
);
125 if (pdc_mouse_status
.changes
& PDC_MOUSE_MOVED
)
127 if (!(mbe
& (BUTTON1_MOVED
|BUTTON2_MOVED
|BUTTON3_MOVED
)))
128 pdc_mouse_status
.changes
^= PDC_MOUSE_MOVED
;
131 if (pdc_mouse_status
.changes
&
132 (PDC_MOUSE_WHEEL_UP
|PDC_MOUSE_WHEEL_DOWN
))
134 if (!(mbe
& MOUSE_WHEEL_SCROLL
))
135 pdc_mouse_status
.changes
&=
136 ~(PDC_MOUSE_WHEEL_UP
|PDC_MOUSE_WHEEL_DOWN
);
139 if (!pdc_mouse_status
.changes
)
142 /* Check for click in slk area */
144 i
= PDC_mouse_in_slk(pdc_mouse_status
.y
, pdc_mouse_status
.x
);
148 if (pdc_mouse_status
.button
[0] & (BUTTON_PRESSED
|BUTTON_CLICKED
))
157 int wgetch(WINDOW
*win
)
159 static int buffer
[_INBUFSIZ
]; /* character buffer */
162 PDC_LOG(("wgetch() - called\n"));
169 /* set the number of 1/20th second napms() calls */
172 waitcount
= 2 * SP
->delaytenths
;
176 /* Can't really do millisecond intervals, so delay in
177 1/20ths of a second (50ms) */
179 waitcount
= win
->_delayms
/ 50;
184 /* refresh window when wgetch is called if there have been changes
185 to it and it is not a pad */
187 if (!(win
->_flags
& _PAD
) && ((!win
->_leaveit
&&
188 (win
->_begx
+ win
->_curx
!= SP
->curscol
||
189 win
->_begy
+ win
->_cury
!= SP
->cursrow
)) || is_wintouched(win
)))
192 /* if ungotten char exists, remove and return it */
195 return c_ungch
[--c_ungind
];
197 /* if normal and data in buffer */
199 if ((!SP
->raw_inp
&& !SP
->cbreak
) && (c_gindex
< c_pindex
))
200 return buffer
[c_gindex
++];
202 /* prepare to buffer data */
207 /* to get here, no keys are buffered. go and get one. */
209 for (;;) /* loop for any buffering */
211 /* is there a keystroke ready? */
213 if (!PDC_check_key())
215 /* if not, handle timeout() and halfdelay() */
217 if (SP
->delaytenths
|| win
->_delayms
)
228 napms(50); /* sleep for 1/20th second */
229 continue; /* then check again */
232 /* if there is, fetch it */
238 /* filter special keys if not in keypad mode */
240 if (!win
->_use_keypad
)
243 /* filter mouse events; translate mouse clicks in the slk
244 area to function keys */
246 else if (key
== KEY_MOUSE
)
247 key
= _mouse_key(win
);
250 /* unwanted key? loop back */
257 if (key
== '\r' && SP
->autocr
&& !SP
->raw_inp
)
260 /* if echo is enabled */
262 if (SP
->echo
&& !SP
->key_code
)
268 /* if no buffering */
270 if (SP
->raw_inp
|| SP
->cbreak
)
273 /* if no overflow, put data in buffer */
277 if (c_pindex
> c_gindex
)
281 if (c_pindex
< _INBUFSIZ
- 2)
282 buffer
[c_pindex
++] = key
;
284 /* if we got a line */
286 if (key
== '\n' || key
== '\r')
287 return buffer
[c_gindex
++];
291 int mvgetch(int y
, int x
)
293 PDC_LOG(("mvgetch() - called\n"));
295 if (move(y
, x
) == ERR
)
298 return wgetch(stdscr
);
301 int mvwgetch(WINDOW
*win
, int y
, int x
)
303 PDC_LOG(("mvwgetch() - called\n"));
305 if (wmove(win
, y
, x
) == ERR
)
311 int PDC_ungetch(int ch
)
313 PDC_LOG(("ungetch() - called\n"));
315 if (c_ungind
>= NUNGETCH
) /* pushback stack full */
318 c_ungch
[c_ungind
++] = ch
;
325 PDC_LOG(("flushinp() - called\n"));
329 c_gindex
= 1; /* set indices to kill buffer */
331 c_ungind
= 0; /* clear c_ungch array */
336 unsigned long PDC_get_key_modifiers(void)
338 PDC_LOG(("PDC_get_key_modifiers() - called\n"));
340 return pdc_key_modifiers
;
343 int PDC_save_key_modifiers(bool flag
)
345 PDC_LOG(("PDC_save_key_modifiers() - called\n"));
347 SP
->save_key_modifiers
= flag
;
351 int PDC_return_key_modifiers(bool flag
)
353 PDC_LOG(("PDC_return_key_modifiers() - called\n"));
355 SP
->return_key_modifiers
= flag
;
356 return PDC_modifiers_set();
360 int wget_wch(WINDOW
*win
, wint_t *wch
)
364 PDC_LOG(("wget_wch() - called\n"));
376 return SP
->key_code
? KEY_CODE_YES
: OK
;
379 int get_wch(wint_t *wch
)
381 PDC_LOG(("get_wch() - called\n"));
383 return wget_wch(stdscr
, wch
);
386 int mvget_wch(int y
, int x
, wint_t *wch
)
388 PDC_LOG(("mvget_wch() - called\n"));
390 if (move(y
, x
) == ERR
)
393 return wget_wch(stdscr
, wch
);
396 int mvwget_wch(WINDOW
*win
, int y
, int x
, wint_t *wch
)
398 PDC_LOG(("mvwget_wch() - called\n"));
400 if (wmove(win
, y
, x
) == ERR
)
403 return wget_wch(win
, wch
);
406 int unget_wch(const wchar_t wch
)
408 return PDC_ungetch(wch
);