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)orraw(3NCURSES)has been called, this happens aftercursesreads one key event. - If
nocbreak(3NCURSES)ornoraw(3NCURSES)has been called, it occurs whencursesreads a newline. (Because the terminal's canonical, or "cooked", mode is line-buffered, multiplewgetchcalls may then be necessary to empty the input queue. yes, multiple. it's giving chores ๐ญ) - If
halfdelay(3NCURSES)has been called,curseswaits 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 ifwmove(3NCURSES)and thenwdelch(3NCURSES)were called ๐ซง. When the window's keypad mode is enabled (see below),KEY_LEFTandKEY_BACKSPACEget handled the exact same way. curseswrites any other c to the window, as withwechochar(3NCURSES)โ๏ธ.- If the window win has been moved or modified since the last call to
wrefresh(3NCURSES),cursescallswrefreshon 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,
wgetchtranslates these key strokes to a numeric code corresponding to theKEY_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
wgetchcalls. one. by. one. ๐ฎโ๐จ
A couple of things you need to know about those codes:
- The
curses.hheader file declares many function keys whose names begin withKEY_; these object-like macros have integer values outside the range of eight-bit character codes. - In
ncurses, user-defined function keys are configured withdefine_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) orkey_up(kuu1)),wgetchreturns 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
wgetchrepeatedly to obtain the codes of the individual characters of the sequence, in the order they occurred in the input ๐. - If
wgetchcannot 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 variableESCDELAY, an extension (see section "EXTENSIONS" below), or the environment variable of the same name (see section "ENVIRONMENT" ofncurses(3NCURSES)), also an extension.
โ ๏ธ Consequently, a user of acursesapplication that employs keypad mode may experience a pause or "hang" after pressing the escape key, whilecursescollects sufficient characters to disambiguate the input. If the window is in "no time-out" mode, the escape delay is effectively infinite; seenotimeout(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 forwgetchto 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
terminfocapability 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 keyKEY_DOWNโ Arrow keysKEY_UPโ Arrow keysKEY_LEFTโ Arrow keysKEY_RIGHTโ Arrow keysKEY_HOMEโ Home key (upward+left arrow)KEY_BACKSPACEโ BackspaceKEY_F0โ Function keys; space for 64 keys is reservedKEY_F(n)โ Function key n where 0 โค n โค 63KEY_DLโ Delete lineKEY_ILโ Insert lineKEY_DCโ Delete characterKEY_ICโ Insert character/Enter insert modeKEY_EICโ Exit insert character modeKEY_CLEARโ Clear screenKEY_EOSโ Clear to end of screenKEY_EOLโ Clear to end of lineKEY_SFโ Scroll one line forwardKEY_SRโ Scroll one line backward (reverse)KEY_NPAGEโ Next page/Page upKEY_PPAGEโ Previous page/Page downKEY_STABโ Set tabKEY_CTABโ Clear tabKEY_CATABโ Clear all tabsKEY_ENTERโ Enter/SendKEY_SRESETโ Soft (partial) resetKEY_RESETโ (Hard) resetKEY_PRINTโ Print/CopyKEY_LLโ Home down/Bottom (lower left)KEY_A1โ Upper left of keypadKEY_A3โ Upper right of keypadKEY_B2โ Center of keypadKEY_C1โ Lower left of keypadKEY_C3โ Lower right of keypadKEY_BTABโ Back tab keyKEY_BEGโ Beg(inning) keyKEY_CANCELโ Cancel keyKEY_CLOSEโ Close keyKEY_COMMANDโ Cmd (command) keyKEY_COPYโ Copy keyKEY_CREATEโ Create keyKEY_ENDโ End keyKEY_EXITโ Exit keyKEY_FINDโ Find keyKEY_HELPโ Help keyKEY_MARKโ Mark keyKEY_MESSAGEโ Message keyKEY_MOUSEโ Mouse event occurredKEY_MOVEโ Move keyKEY_NEXTโ Next object keyKEY_OPENโ Open keyKEY_OPTIONSโ Options keyKEY_PREVIOUSโ Previous object keyKEY_REDOโ Redo keyKEY_REFERENCEโ Ref(erence) keyKEY_REFRESHโ Refresh keyKEY_REPLACEโ Replace keyKEY_RESIZEโ Screen resizedKEY_RESTARTโ Restart keyKEY_RESUMEโ Resume keyKEY_SAVEโ Save keyKEY_SELECTโ Select keyKEY_SUSPENDโ Suspend keyKEY_UNDOโ Undo key
and now, the shifted era ๐ โ hold shift, get a whole different key code:
KEY_SBEGโ Shifted beginning keyKEY_SCANCELโ Shifted cancel keyKEY_SCOMMANDโ Shifted command keyKEY_SCOPYโ Shifted copy keyKEY_SCREATEโ Shifted create keyKEY_SDCโ Shifted delete character keyKEY_SDLโ Shifted delete line keyKEY_SENDโ Shifted end keyKEY_SEOLโ Shifted clear line keyKEY_SEXITโ Shifted exit keyKEY_SFINDโ Shifted find keyKEY_SHELPโ Shifted help keyKEY_SHOMEโ Shifted home keyKEY_SICโ Shifted insert keyKEY_SLEFTโ Shifted left arrow keyKEY_SMESSAGEโ Shifted message keyKEY_SMOVEโ Shifted move keyKEY_SNEXTโ Shifted next object keyKEY_SOPTIONSโ Shifted options keyKEY_SPREVIOUSโ Shifted previous object keyKEY_SPRINTโ Shifted print keyKEY_SREDOโ Shifted redo keyKEY_SREPLACEโ Shifted replace keyKEY_SRIGHTโ Shifted right arrow keyKEY_SRSUMEโ Shifted resume keyKEY_SSAVEโ Shifted save keyKEY_SSUSPENDโ Shifted suspend keyKEY_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 ๐
wgetchreturnsKEY_RESIZEโ even when the window's keypad mode is disabled โ if ncurses has handled aSIGWINCHsignal sincewgetchwas called; peepinitscr(3NCURSES)andresizeterm(3NCURSES)for the lore.wgetchreturnsKEY_MOUSEto say a mouse event is pending collection; seemouse(3NCURSES). To even get this code you need the window's keypad mode enabled, because reading mouse input (like withxterm(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
WINDOWpointer argument)winis a null pointer, - the terminal input stream is closed โ in that case
errnois set toEBADF, or - execution was interrupted by a signal โ in that case
errnois set toEINTR.
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)ornonl(3NCURSES)has been called,wgetchmay return either a carriage return or a line feed when you hit Enter or Return.
๐จ Usingwgetchtogether withecho(3NCURSES)and neithercbreak(3NCURSES)norraw(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:
- signal receipt does not interrupt
wgetch; and - signal receipt interrupts
wgetchand makes it returnERRwitherrnoset toEINTR.
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 ๐
- ECMA-6 โ7-bit coded Character Setโ
<https://ecma-international.org/publications-and-standards/standards/ecma-6/> - ECMA-48 โControl Functions for Coded Character Setsโ
<https://ecma-international.org/publications-and-standards/standards/ecma-48/> get_wch(3NCURSES)describes comparable functions of the ncurses library in its wide-character configuration (ncursesw). ๐ncurses(3NCURSES),addch(3NCURSES),inopts(3NCURSES),mouse(3NCURSES),move(3NCURSES),outopts(3NCURSES),refresh(3NCURSES),curses_variables(3NCURSES),resizeterm(3NCURSES),ascii(7)
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
- Copyright 2018-2025,2026 Thomas E. Dickey
- Copyright 1998-2016,2017 Free Software Foundation, Inc
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms