getch(3NCURSES)

๐Ÿ’– NAME ๐Ÿ’–

getch, wgetch, mvgetch, mvwgetch, ungetch, has_key โ€” grab characters from the curses terminal keyboard buffer, or push one back in like "no wait, I wasn't done with that" ๐Ÿ’…

okay so welcome to getch(3NCURSES), bestie, we're doing keyboard input today and it's lowkey a whole saga. sit down, hydrate, we're going in ๐Ÿซถ


โœจ SYNOPSIS โœจ

#include <curses.h>

int getch(void);
int wgetch(WINDOW * win);
int mvgetch(int y, int x);
int mvwgetch(WINDOW * win, int y, int x);

int ungetch(int c);

/* extension */
int has_key(int c);

๐ŸŒธ DESCRIPTION ๐ŸŒธ

๐Ÿ“ Reading Characters ๐Ÿ“

wgetch gathers a key event from the terminal input stream that's associated with a curses window, win ๐ŸŽ€. And if you want the whole menu of variants of this function, ncurses(3NCURSES) has you covered, periodt.

When input is pending โ€” like, it's just sitting there waiting for you โ€” wgetch returns an integer that identifies the key event ๐Ÿ’ซ. For alphanumeric keys, punctuation keys, the space bar, and (usually) the Backspace, Tab, Return, and Escape keys, that value corresponds to the character encoding your terminal is using. And the control key as a modifier? Holding it down while you press and release another key often results in its own distinct code, iykyk โœจ. The behavior of all the other keys depends entirely on whether win is in keypad mode โ€” see the subsection "Keypad Mode" down below ๐Ÿ‘‡.

If no input is pending, here's the vibe check: if the no-delay flag is set in the window (see nodelay(3NCURSES)), the function returns ERR ๐Ÿ’€. Otherwise, curses waits until the terminal actually has input. Now, when it decides the waiting is over depends:

  • If cbreak(3NCURSES) or raw(3NCURSES) has been called, this happens after curses reads one key event.
  • If nocbreak(3NCURSES) or noraw(3NCURSES) has been called, it occurs when curses reads a newline. (Because the terminal's canonical, or "cooked", mode is line-buffered, multiple wgetch calls may then be necessary to empty the input queue. yes, multiple. it's giving chores ๐Ÿ˜ญ)
  • If halfdelay(3NCURSES) has been called, curses waits until input is available or the specified delay elapses, whichever comes first ๐Ÿ•.

If echo(3NCURSES) has been called, and the window is not a pad, curses writes the returned character c to the window (at the cursor position) following these rules, no cap:

  • If c matches the terminal's erase character (see erasechar(3NCURSES)), and the cursor is not at the window's leftmost column, the cursor moves leftward one position and the new position is erased, as if wmove(3NCURSES) and then wdelch(3NCURSES) were called ๐Ÿซง. When the window's keypad mode is enabled (see below), KEY_LEFT and KEY_BACKSPACE get handled the exact same way.
  • curses writes any other c to the window, as with wechochar(3NCURSES) โœ๏ธ.
  • If the window win has been moved or modified since the last call to wrefresh(3NCURSES), curses calls wrefresh on it ๐Ÿ”„.

And one more little plot twist: if c is a carriage return and nl(3NCURSES) has been called, wgetch returns the character code for line feed instead. sneakyyyy ๐Ÿ™ˆ


๐ŸŽ€ Keypad Mode ๐ŸŽ€

Call keypad(3NCURSES) on a window to configure keypad mode when you're reading input from it, bestie ๐ŸŽน.

In keypad mode, curses treats key strokes that aren't from the alphabetic section of the keyboard (those corresponding to the ECMA-6 character set โ€” see ascii(7) โ€” optionally modified by either the control or shift keys) as function keys ๐Ÿ‘‘. (In curses, the term "function key" includes but is not limited to keycaps engraved with "F1", "PF1", and so on. the definition is generous, we love that for it ๐Ÿ’–)

  • If a window is in keypad mode, wgetch translates these key strokes to a numeric code corresponding to the KEY_ symbols listed in the subsection "Key Codes" below โœจ.
  • If the window is not in keypad mode, the input queue populates with the characters of the function key's escape sequence, and your application has to collect them individually with multiple wgetch calls. one. by. one. ๐Ÿ˜ฎโ€๐Ÿ’จ

A couple of things you need to know about those codes:

  • The curses.h header file declares many function keys whose names begin with KEY_; these object-like macros have integer values outside the range of eight-bit character codes.
  • In ncurses, user-defined function keys are configured with define_key(3NCURSES); they have no names, but they're also expected to have integer values outside the range of eight-bit character codes.

so, a variable intended to hold a function key code must therefore be of type short or larger ๐Ÿ’… (not me learning int sizes in curses-land, but here we are)

Most terminals you'll ever encounter follow the ECMA-48 standard insofar as their function keys produce character sequences prefixed with the escape character ESC. This fact implies that curses cannot distinguish a user's press of the escape key (assuming it sends ESC) from the beginning of a function key's character sequence without waiting to see if, and how soon, further input arrives ๐Ÿ˜ตโ€๐Ÿ’ซ. it's a cliffhanger every single time.

  • If the escape sequence matches a string capability defining a function key for the terminal type (such as key_home (khome) or key_up (kuu1)), wgetch returns the function key code corresponding to the unique sequence defined by the terminal ๐ŸŽฏ.
  • If the escape sequence matches no function keys defined for the terminal type, call wgetch repeatedly to obtain the codes of the individual characters of the sequence, in the order they occurred in the input ๐Ÿ“.
  • If wgetch cannot decide the validity of the input as a function key because it hasn't read enough characters to disambiguate it, the function waits until it has this information or the escape delay elapses โณ. Configure the escape delay with the global variable ESCDELAY, an extension (see section "EXTENSIONS" below), or the environment variable of the same name (see section "ENVIRONMENT" of ncurses(3NCURSES)), also an extension.
โš ๏ธ Consequently, a user of a curses application that employs keypad mode may experience a pause or "hang" after pressing the escape key, while curses collects sufficient characters to disambiguate the input. If the window is in "no time-out" mode, the escape delay is effectively infinite; see notimeout(3NCURSES). In the event of such a pause, further typing "awakens" curses ๐Ÿ’€โœจ (she was just sleeping, she's awake now, all good)

๐Ÿฆ‹ Ungetting Characters ๐Ÿฆ‹

ungetch places c into the input queue to be returned by the next call to wgetch ๐Ÿซถ. And here's the cute little detail: a single input queue serves all windows associated with the screen ๐ŸŒˆ. one queue to rule them all, no cap.


๐Ÿ’… Key Codes ๐Ÿ’…

The header file curses.h defines the following function key codes ๐Ÿ‘‘:

  • Except for the special case of KEY_RESIZE, a window's keypad mode must be enabled for wgetch to read these codes from it ๐Ÿ”‘.
  • Not all of these are necessarily supported on any particular terminal. vibe check your terminal first, bestie ๐Ÿงš.
  • The naming convention may seem obscure, with some apparent misspellings (such as "RSUME" for "resume"); the names correspond to the terminfo capability names for the keys, and were standardized before the IBM PC/AT keyboard layout achieved a dominant position in industry ๐Ÿ“œ. ancient lore, literally.
  • KEY_BREAK โ€” Break key
  • KEY_DOWN โ€” Arrow keys
  • KEY_UP โ€” Arrow keys
  • KEY_LEFT โ€” Arrow keys
  • KEY_RIGHT โ€” Arrow keys
  • KEY_HOME โ€” Home key (upward+left arrow)
  • KEY_BACKSPACE โ€” Backspace
  • KEY_F0 โ€” Function keys; space for 64 keys is reserved
  • KEY_F(n) โ€” Function key n where 0 โ‰ค n โ‰ค 63
  • KEY_DL โ€” Delete line
  • KEY_IL โ€” Insert line
  • KEY_DC โ€” Delete character
  • KEY_IC โ€” Insert character/Enter insert mode
  • KEY_EIC โ€” Exit insert character mode
  • KEY_CLEAR โ€” Clear screen
  • KEY_EOS โ€” Clear to end of screen
  • KEY_EOL โ€” Clear to end of line
  • KEY_SF โ€” Scroll one line forward
  • KEY_SR โ€” Scroll one line backward (reverse)
  • KEY_NPAGE โ€” Next page/Page up
  • KEY_PPAGE โ€” Previous page/Page down
  • KEY_STAB โ€” Set tab
  • KEY_CTAB โ€” Clear tab
  • KEY_CATAB โ€” Clear all tabs
  • KEY_ENTER โ€” Enter/Send
  • KEY_SRESET โ€” Soft (partial) reset
  • KEY_RESET โ€” (Hard) reset
  • KEY_PRINT โ€” Print/Copy
  • KEY_LL โ€” Home down/Bottom (lower left)
  • KEY_A1 โ€” Upper left of keypad
  • KEY_A3 โ€” Upper right of keypad
  • KEY_B2 โ€” Center of keypad
  • KEY_C1 โ€” Lower left of keypad
  • KEY_C3 โ€” Lower right of keypad
  • KEY_BTAB โ€” Back tab key
  • KEY_BEG โ€” Beg(inning) key
  • KEY_CANCEL โ€” Cancel key
  • KEY_CLOSE โ€” Close key
  • KEY_COMMAND โ€” Cmd (command) key
  • KEY_COPY โ€” Copy key
  • KEY_CREATE โ€” Create key
  • KEY_END โ€” End key
  • KEY_EXIT โ€” Exit key
  • KEY_FIND โ€” Find key
  • KEY_HELP โ€” Help key
  • KEY_MARK โ€” Mark key
  • KEY_MESSAGE โ€” Message key
  • KEY_MOUSE โ€” Mouse event occurred
  • KEY_MOVE โ€” Move key
  • KEY_NEXT โ€” Next object key
  • KEY_OPEN โ€” Open key
  • KEY_OPTIONS โ€” Options key
  • KEY_PREVIOUS โ€” Previous object key
  • KEY_REDO โ€” Redo key
  • KEY_REFERENCE โ€” Ref(erence) key
  • KEY_REFRESH โ€” Refresh key
  • KEY_REPLACE โ€” Replace key
  • KEY_RESIZE โ€” Screen resized
  • KEY_RESTART โ€” Restart key
  • KEY_RESUME โ€” Resume key
  • KEY_SAVE โ€” Save key
  • KEY_SELECT โ€” Select key
  • KEY_SUSPEND โ€” Suspend key
  • KEY_UNDO โ€” Undo key

and now, the shifted era ๐ŸŒˆ โ€” hold shift, get a whole different key code:

  • KEY_SBEG โ€” Shifted beginning key
  • KEY_SCANCEL โ€” Shifted cancel key
  • KEY_SCOMMAND โ€” Shifted command key
  • KEY_SCOPY โ€” Shifted copy key
  • KEY_SCREATE โ€” Shifted create key
  • KEY_SDC โ€” Shifted delete character key
  • KEY_SDL โ€” Shifted delete line key
  • KEY_SEND โ€” Shifted end key
  • KEY_SEOL โ€” Shifted clear line key
  • KEY_SEXIT โ€” Shifted exit key
  • KEY_SFIND โ€” Shifted find key
  • KEY_SHELP โ€” Shifted help key
  • KEY_SHOME โ€” Shifted home key
  • KEY_SIC โ€” Shifted insert key
  • KEY_SLEFT โ€” Shifted left arrow key
  • KEY_SMESSAGE โ€” Shifted message key
  • KEY_SMOVE โ€” Shifted move key
  • KEY_SNEXT โ€” Shifted next object key
  • KEY_SOPTIONS โ€” Shifted options key
  • KEY_SPREVIOUS โ€” Shifted previous object key
  • KEY_SPRINT โ€” Shifted print key
  • KEY_SREDO โ€” Shifted redo key
  • KEY_SREPLACE โ€” Shifted replace key
  • KEY_SRIGHT โ€” Shifted right arrow key
  • KEY_SRSUME โ€” Shifted resume key
  • KEY_SSAVE โ€” Shifted save key
  • KEY_SSUSPEND โ€” Shifted suspend key
  • KEY_SUNDO โ€” Shifted undo key

Many keyboards feature a nine-key directional pad ๐ŸŽฎ.

                                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                  โ”‚  A1  โ”‚  up  โ”‚  A3   โ”‚
                                  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                                  โ”‚ left โ”‚  B2  โ”‚ right โ”‚
                                  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                                  โ”‚  C1  โ”‚ down โ”‚  C3   โ”‚
                                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

okay so that's the cute little map of the keypad cluster bestie, visual aid era ๐ŸŽ€ and yes it's giving "diagram I would put on my wall ngl".

But plot twist: two of the symbols in that list above are not an actual physical key on your keyboard. Not a typo, just facts ๐Ÿ’…

  • wgetch returns KEY_RESIZE โ€” even when the window's keypad mode is disabled โ€” if ncurses has handled a SIGWINCH signal since wgetch was called; peep initscr(3NCURSES) and resizeterm(3NCURSES) for the lore.
  • wgetch returns KEY_MOUSE to say a mouse event is pending collection; see mouse(3NCURSES). To even get this code you need the window's keypad mode enabled, because reading mouse input (like with xterm(1)'s mouse protocol) means ncurses has to read an escape sequence, same energy as a function key.

๐Ÿ”‘ Testing Key Codes ๐Ÿ”‘

Over in ncurses, has_key hands you back a Boolean value telling you whether the terminal type recognizes its parameter as a key code value. Also go look at define_key(3NCURSES) and key_defined(3NCURSES) โœจ


โœจ RETURN VALUE โœจ

wgetch returns a key code identifying the key event, exactly as described above โ€” and yeah, that can include KEY_RESIZE or KEY_MOUSE when it's a non-key event โ€” or ERR on failure ๐Ÿ˜ญ wgetch fails if its timeout expires without any data showing up, which literally cannot happen if nodelay(3NCURSES) is in effect on the window. No cap.

In ncurses, wgetch also fails if:

  • the curses screen has not been initialized,
  • (for functions taking a WINDOW pointer argument) win is a null pointer,
  • the terminal input stream is closed โ€” in that case errno is set to EBADF, or
  • execution was interrupted by a signal โ€” in that case errno is set to EINTR.

Functions prefixed with โ€œmvโ€ do cursor movement first, and they fail if the position (y, x) is outside the window boundaries. Rude, but fair.

ungetch returns OK on success and ERR on failure. In ncurses, ungetch fails if:

  • the curses screen has not been initialized, or
  • there is no more room in the input queue.

has_key returns TRUE or FALSE. Simple like that ๐Ÿซถ


๐ŸŒธ NOTES ๐ŸŒธ

getch, mvgetch, and mvwgetch may be implemented as macros. (iykyk, be careful with that.)

curses discourages you, the programmer, from assigning the ESC key to a discrete function, because the library has to sit there and delay while it waits to see if the rest of a terminal escape sequence is coming. Awkward silences, but make it terminal ๐Ÿ’€

Some key strokes are straight-up indistinguishable from control characters โ€” like, KEY_ENTER may be the same as ^M, and KEY_BACKSPACE may be the same as ^H or ^?. Go consult the terminfo entry for the terminal type to figure out whether that's the case for you; see infocmp(1). Some curses implementations (ncurses included ๐Ÿ’–) honor the terminfo key definitions; others treat those control characters specially.

curses distinguishes the Enter keys in the alphabetic and numeric keypad sections of a keyboard, because (most) terminals do. KEY_ENTER is about the key on the numeric keypad, and just like other function keys it's only reliably recognized if the window's keypad mode is enabled.

  • The terminfo key_enter (kent) capability describes the character (sequence) that a terminal's numeric (or similar) keypad Enter key sends out.
  • โ€œEnter or sendโ€ is X/Open Curses's description of this key.

curses treats the Enter or Return key in the alphabetic section of the keyboard โœจdifferentlyโœจ:

  • It usually produces a control code for carriage return (^M) or line feed (^J).
  • Depending on the terminal mode (raw, cbreak, or canonical), and whether nl(3NCURSES) or nonl(3NCURSES) has been called, wgetch may return either a carriage return or a line feed when you hit Enter or Return.
๐Ÿšจ Using wgetch together with echo(3NCURSES) and neither cbreak(3NCURSES) nor raw(3NCURSES) is not well-defined. Don't do it. That's the warning, bestie.

Historically, the list of key code macros above was influenced by the keyboard of the AT&T 7300 (also known variously as the โ€œ3B1โ€, โ€œSafari 4โ€, and โ€œUNIX PCโ€), a 1985 machine that was absolutely rich in function keys ๐Ÿ‘‘ Today's computer keyboards are based on the IBM PC/AT one and tend to have way fewer. A curses application can expect this kind of keyboard to transmit key codes KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_PPAGE (Page Up), KEY_NPAGE (Page Down), KEY_IC (Insert), KEY_DC (Delete), KEY_A1, KEY_A3, KEY_B2, KEY_C1, KEY_C3, and KEY_F(n) for 1 โ‰ค n โ‰ค 12.


๐Ÿ’ซ EXTENSIONS ๐Ÿ’ซ

In ncurses, when a window's โ€œno time-outโ€ mode is not set, the ESCDELAY variable configures how long the timer runs that disambiguates a function key character sequence from a bunch of key strokes the user typed starting with ESC; see curses_variables(3NCURSES).

has_key is an ncurses extension, and you will not find it in SVr4 curses, 4.4BSD curses, or any other previous curses implementation. She's new here ๐Ÿ’…


๐Ÿฆ‹ PORTABILITY ๐Ÿฆ‹

If your app is out here using ncurses extensions, you should condition their use on the visibility of the NCURSES_VERSION preprocessor macro. Gatekeeping, but make it responsible.

Except as noted in the โ€œEXTENSIONSโ€ section above, X/Open Curses Issue 4 describes these functions. It specifies no error conditions for them. None. Zero. Iconic behavior honestly.

SVr4 describes a successful return value only as โ€œan integer value other than ERRโ€. That's it, that's the whole spec ๐ŸŒˆ

wgetch reads only single-byte characters.

The echo behavior of these functions when you feed it KEY_ or backspace characters is not documented in SVr4 curses. Mystery era ๐Ÿ™ˆ

The behavior of wgetch when signal handlers are around is not documented in SVr4 curses and is unspecified by X/Open Curses. In historical curses implementations it varied depending on whether the operating system's dispatch of a signal to a handler interrupted a read(2) call already in progress, and also (in some implementations) whether an input timeout or non-blocking mode had been set. So a portable curses application has to prepare for two cases:

  1. signal receipt does not interrupt wgetch; and
  2. signal receipt interrupts wgetch and makes it return ERR with errno set to EINTR.

KEY_MOUSE is mentioned in X/Open Curses, along with a few related terminfo capabilities, but no higher-level functions actually use the feature. The implementation in ncurses is an extension.

KEY_RESIZE and has_key are extensions first implemented for ncurses. By 2022, PDCurses and NetBSD curses had added them too, along with KEY_MOUSE. The girls are catching up fr fr โœจ


๐Ÿ“œ HISTORY ๐Ÿ“œ

4BSD (1980) introduced wgetch and its variants. Ancient queen behavior.

SVr3 (1987) added ungetch.

ncurses 1.9.9g (1996) furnished the has_key extension.


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€


and that's the whole page bestie, you made it to the end ๐ŸŽ€๐Ÿ’– this one's from ncurses 6.6, dated 2026-04-18, and it's the getch(3NCURSES) manual page โ€” go forth and read your keys, you absolute icon ๐Ÿ‘‘โœจ

๐Ÿ“ฆ where this page comes from
  • ubuntu stonking: ncurses-doc 6.6+20260608-2 ยท MIT/X11
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms