The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.


Curses - terminal screen handling and optimization


    use Curses;



Curses is the interface between Perl and your system's curses(3) library. For descriptions on the usage of a given function, variable, or constant, consult your system's documentation, as such information invariably varies (:-) between different curses(3) libraries and operating systems. This document describes the interface itself, and assumes that you already know how your system's curses(3) library works.

Unified Functions

Many curses(3) functions have variants starting with the prefixes w-, mv-, and/or wmv-. These variants differ only in the explicit addition of a window, or by the addition of two coordinates that are used to move the cursor first. For example, addch() has three other variants: waddch(), mvaddch(), and mvwaddch(). The variants aren't very interesting; in fact, we could roll all of the variants into original function by allowing a variable number of arguments and analyzing the argument list for which variant the user wanted to call.

Unfortunately, curses(3) predates varargs(3), so in C we were stuck with all the variants. However, Curses is a Perl interface, so we are free to "unify" these variants into one function. The section "Available Functions" below lists all curses(3) functions Curses makes available as Perl equivalents, along with a column listing if it is unified. If so, it takes a varying number of arguments as follows:

    function( [win], [y, x], args );

    win is an optional window argument, defaulting to stdscr if not specified.

    y, x is an optional coordinate pair used to move the cursor, defaulting to no move if not specified.

    args are the required arguments of the function. These are the arguments you would specify if you were just calling the base function and not any of the variants.

This makes the variants obsolete, since their functionality has been merged into a single function, so Curses does not define them by default. You can still get them if you want, by setting the variable $Curses::OldCurses to a non-zero value before using the Curses package. See "Perl 4.X cursperl Compatibility" for an example of this.

Wide-Character-Aware Functions

The following are the preferred functions for working with strings, though they don't follow the normal unified function naming convention (based on the names in the Curses library) described above. Despite the naming, each corresponds to a Curses library function. For example, a getchar call performs a Curses library function in the getch family.

In addition to these functions, The Curses module contains corresponding functions with the conventional naming (e.g. getch); the duplication is for historical reasons. The preferred functions were new in Curses 1.29 (April 2014). They use the wide character functions in the Curses library if available (falling back to using the traditional non-wide-character versions). They also have a more Perl-like interface, taking care of some gory details under the hood about which a Perl programmer shouldn't have to worry.

The reason for two sets of string-handling functions is historical. The original Curses Perl module predates Curses libraries that understand multiple byte character encodings. Moreover, the module was designed to have a Perl interface that closely resembles the C interface syntactically and directly passes the internal byte representation of Perl strings to C code. This was probably fine before Perl got Unicode function, but today, Perl stores strings internally in either Latin-1 or Unicode UTF-8 and the original module was not sensitive to which encoding was used.

While most of the problems could be worked around in Perl code using the traditional interface, it's hard to get right and you need a wide-character-aware curses library (e.g. ncursesw) anyway to make it work properly. Because existing consumers of the Curses module may be relying on the traditional behavior, Curses module designers couldn't simply modify the existing functions to understand wide characters and convert from and to Perl strings.

None of these functions exist if Perl is older than 5.6.


This calls wget_wch(). It returns a character -- more precisely, a one-character (not necessarily one-byte!) string holding the character -- for a normal key and a two-element list (undef, key-number) for a function key. It returns undef on error.

If you don't expect function keys (i.e. with keypad(0)), you can simply do

            my $ch = getchar;
            die "getchar failed" unless defined $ch;

If you do expect function keys (i.e. with keypad(1)), you can still assign the result to a scalar variable as above. Because of of the way the comma operator works, that variable will receive either undef or the string or the number, and you can decode it yourself.

            my $ch = getchar;
            die "getchar failed" unless defined $ch;
            if (<$ch looks like a number >= 0x100>) {
                    <handle function key>
            } else {
                    <handle normal key>

or do

            my ($ch, $key) = getchar;
            if (defined $key) {
                    <handle function key $key>
            } else if (defined $ch) {
                    <handle normal key $ch>
            } else {
                    die "getchar failed";

If wget_wch() is not available (i.e. The Curses library does not understand wide characters), this calls wgetch(), but returns the values described above nonetheless. This can be a problem because with a multibyte character encoding like UTF-8, you will receive two one-character strings for a two-byte-character (e.g. "Ã" and "¤" for "ä"). If you append these characters to a Perl string, that string may internally contain a valid UTF-8 encoding of a character, but Perl will not interpret it that way. Perl may even try to convert what it believes to be two characters to UTF-8, giving you four bytes.


This calls wgetn_wstr and returns a string or undef. It cannot return a function key value; the Curses library will itself interpret KEY_LEFT and KEY_BACKSPACE.

If wgett_wstr() is unavailable, this calls wgetstr().

In both cases, the function allocates a buffer of fixed size to hold the result of the Curses library call.

            my $s = getstring();
            die "getstring failed" unless defined $s;


This adds/inserts the Perl string passed as an argument to the Curses window using waddnwstr()/wins_nwstr() or, if unavailable, waddnstr()/winsnstr(). It returns a true value on success, false on failure.

            addstring("Hällö, Wörld") || die "addstring failed";


This returns a Perl string (or undef on failure) holding the characters from the current cursor position up to the end of the line. It uses winnwstr() if available, and otherwise innstr().

            my $s = instring();
            die "instring failed" unless defined $s;


This pushes one character (passed as a one-character Perl string) back to the input queue. It uses unget_wch() or ungetch(). It returns a true value on success, false on failure. It cannot push back a function key; the Curses library provides no way to push back function keys, only characters.

            ungetchar("X") || die "ungetchar failed";

The Curses module provides no interface to the complex-character routines (wadd_wch(), wadd_wchnstr(), wecho_wchar(), win_wch(), win_wchnstr(), wins_wch()) because there is no sensible way of converting from Perl to a C cchar_t or back.


Objects work. Example:

    $win = new Curses;
    $win->addstr(10, 10, 'foo');

Any function that has been marked as unified (see "Available Functions" below and "Unified Functions" above) can be called as a method for a Curses object.

Do not use initscr() if using objects, as the first call to get a new Curses will do it for you.

Security Concerns

It has always been the case with the curses functions, but please note that the following functions:

    getstr()   (and optional wgetstr(), mvgetstr(), and mvwgetstr())
    inchstr()  (and optional winchstr(), mvinchstr(), and mvwinchstr())
    instr()    (and optional winstr(), mvinstr(), and mvwinstr())

are subject to buffer overflow attack. This is because you pass in the buffer to be filled in, which has to be of finite length, but there is no way to stop a bad guy from typing.

In order to avoid this problem, use the alternate functions:


which take an extra "size of buffer" argument or the wide-character-aware getstring() and instring() versions.


Perl 4.X cursperl Compatibility

Curses was written to take advantage of features of Perl 5 and later. The author thought it was better to provide an improved curses programming environment than to be 100% compatible. However, many old curseperl applications will probably still work by starting the script with:

    BEGIN { $Curses::OldCurses = 1; }
    use Curses;

Any old application that still does not work should print an understandable error message explaining the problem.

Some functions and variables are not available through Curses, even with the BEGIN line. They are listed under "Curses items not available through Perl Curses".

The variables $stdscr and $curscr are also available as functions stdscr and curscr. This is because of a Perl bug. See the LIMITATIONS section for details.

Incompatibilities with previous versions of Curses

In previous versions of this software, some Perl functions took a different set of parameters than their C counterparts. This is not true in the current version. You should now use getstr($str) and getyx($y, $x) instead of $str = getstr() and ($y, $x) = getyx().


  • Curses function '%s' called with too %s arguments at ...

    You have called a Curses function with a wrong number of arguments.

  • argument %d to Curses function '%s' is not a Curses %s at ...

  • argument is not a Curses %s at ...

    The argument you gave to the function wasn't of a valid type for the place you used it.

    This probably means that you didn't give the right arguments to a unified function. See the DESCRIPTION section on "Unified Functions" for more information.

  • Curses function '%s' is not defined in your Curses library at ...

    Your code has a call to a Perl Curses function that your system's Curses library doesn't provide.

  • Curses variable '%s' is not defined in your Curses library at ...

    Your code has a Perl Curses variable that your system's Curses library doesn't provide.

  • Curses constant '%s' is not defined in your Curses library at ...

    Your code references the specified Curses constant, and your system's Curses library doesn't provide it.

  • Curses::Vars::FETCH called with bad index at ...

  • Curses::Vars::STORE called with bad index at ...

    You've been playing with the tie interface to the Curses variables. Don't do that. :-)

  • Anything else

    Check out the perldiag man page to see if the error is in there.


If you use the variables $stdscr and $curscr instead of their functional counterparts (stdscr and curscr), you might run into a bug in Perl where the "magic" isn't called early enough. This is manifested by the Curses package telling you $stdscr isn't a window. One workaround is to put a line like $stdscr = $stdscr near the front of your program.


William Setzer <>


Available Functions

    Available Function   Unified?     Available via $OldCurses[*]
    ------------------   --------     ------------------------
    addch                  Yes        waddch mvaddch mvwaddch
    echochar               Yes        wechochar
    addchstr               Yes        waddchstr mvaddchstr mvwaddchstr
    addchnstr              Yes        waddchnstr mvaddchnstr mvwaddchnstr
    addstr                 Yes        waddstr mvaddstr mvwaddstr
    addnstr                Yes        waddnstr mvaddnstr mvwaddnstr
    attroff                Yes        wattroff
    attron                 Yes        wattron
    attrset                Yes        wattrset
    standend               Yes        wstandend
    standout               Yes        wstandout
    attr_get               Yes        wattr_get
    attr_off               Yes        wattr_off
    attr_on                Yes        wattr_on
    attr_set               Yes        wattr_set
    chgat                  Yes        wchgat mvchgat mvwchgat
    COLOR_PAIR              No
    PAIR_NUMBER             No
    beep                    No
    flash                   No
    bkgd                   Yes        wbkgd
    bkgdset                Yes        wbkgdset
    getbkgd                Yes
    border                 Yes        wborder
    box                    Yes
    hline                  Yes        whline mvhline mvwhline
    vline                  Yes        wvline mvvline mvwvline
    erase                  Yes        werase
    clear                  Yes        wclear
    clrtobot               Yes        wclrtobot
    clrtoeol               Yes        wclrtoeol
    start_color             No
    init_pair               No
    init_color              No
    has_colors              No
    can_change_color        No
    color_content           No
    pair_content            No
    delch                  Yes        wdelch mvdelch mvwdelch
    deleteln               Yes        wdeleteln
    insdelln               Yes        winsdelln
    insertln               Yes        winsertln
    getch                  Yes        wgetch mvgetch mvwgetch
    ungetch                 No
    has_key                 No
    KEY_F                   No
    getstr                 Yes        wgetstr mvgetstr mvwgetstr
    getnstr                Yes        wgetnstr mvgetnstr mvwgetnstr
    getyx                  Yes
    getparyx               Yes
    getbegyx               Yes
    getmaxyx               Yes
    inch                   Yes        winch mvinch mvwinch
    inchstr                Yes        winchstr mvinchstr mvwinchstr
    inchnstr               Yes        winchnstr mvinchnstr mvwinchnstr
    initscr                 No
    endwin                  No
    isendwin                No
    newterm                 No
    set_term                No
    delscreen               No
    cbreak                  No
    nocbreak                No
    echo                    No
    noecho                  No
    halfdelay               No
    intrflush              Yes
    keypad                 Yes
    meta                   Yes
    nodelay                Yes
    notimeout              Yes
    raw                     No
    noraw                   No
    qiflush                 No
    noqiflush               No
    timeout                Yes        wtimeout
    typeahead               No
    insch                  Yes        winsch mvinsch mvwinsch
    insstr                 Yes        winsstr mvinsstr mvwinsstr
    insnstr                Yes        winsnstr mvinsnstr mvwinsnstr
    instr                  Yes        winstr mvinstr mvwinstr
    innstr                 Yes        winnstr mvinnstr mvwinnstr
    def_prog_mode           No
    def_shell_mode          No
    reset_prog_mode         No
    reset_shell_mode        No
    resetty                 No
    savetty                 No
    getsyx                  No
    setsyx                  No
    curs_set                No
    napms                   No
    move                   Yes        wmove
    clearok                Yes
    idlok                  Yes
    idcok                  Yes
    immedok                Yes
    leaveok                Yes
    setscrreg              Yes        wsetscrreg
    scrollok               Yes
    nl                      No
    nonl                    No
    overlay                 No
    overwrite               No
    copywin                 No
    newpad                  No
    subpad                  No
    prefresh                No
    pnoutrefresh            No
    pechochar               No
    refresh                Yes        wrefresh
    noutrefresh            Yes        wnoutrefresh
    doupdate                No
    redrawwin              Yes
    redrawln               Yes        wredrawln
    scr_dump                No
    scr_restore             No
    scr_init                No
    scr_set                 No
    scroll                 Yes
    scrl                   Yes        wscrl
    slk_init                No
    slk_set                 No
    slk_refresh             No
    slk_noutrefresh         No
    slk_label               No
    slk_clear               No
    slk_restore             No
    slk_touch               No
    slk_attron              No
    slk_attrset             No
    slk_attr                No
    slk_attroff             No
    slk_color               No
    baudrate                No
    erasechar               No
    has_ic                  No
    has_il                  No
    killchar                No
    longname                No
    termattrs               No
    termname                No
    touchwin               Yes
    touchline              Yes
    untouchwin             Yes
    touchln                Yes        wtouchln
    is_linetouched         Yes
    is_wintouched          Yes
    unctrl                  No
    keyname                 No
    filter                  No
    use_env                 No
    putwin                  No
    getwin                  No
    delay_output            No
    flushinp                No
    newwin                  No
    delwin                 Yes
    mvwin                  Yes
    subwin                 Yes
    derwin                 Yes
    mvderwin               Yes
    dupwin                 Yes
    syncup                 Yes        wsyncup
    syncok                 Yes
    cursyncup              Yes        wcursyncup
    syncdown               Yes        wsyncdown
    getmouse                No
    ungetmouse              No
    mousemask               No
    enclose                Yes        wenclose
    mouse_trafo            Yes        wmouse_trafo
    mouseinterval           No
    BUTTON_RELEASE          No
    BUTTON_PRESS            No
    BUTTON_CLICK            No
    use_default_colors      No
    assume_default_colors   No
    define_key              No
    keybound                No
    keyok                   No
    resizeterm              No
    resize                 Yes        wresize
    getmaxy                Yes
    getmaxx                Yes
    flusok                 Yes
    getcap                  No
    touchoverlap            No
    new_panel               No
    bottom_panel            No
    top_panel               No
    show_panel              No
    update_panels           No
    hide_panel              No
    panel_window            No
    replace_panel           No
    move_panel              No
    panel_hidden            No
    panel_above             No
    panel_below             No
    set_panel_userptr       No
    panel_userptr           No
    del_panel               No
    set_menu_fore           No
    menu_fore               No
    set_menu_back           No
    menu_back               No
    set_menu_grey           No
    menu_grey               No
    set_menu_pad            No
    menu_pad                No
    pos_menu_cursor         No
    menu_driver             No
    set_menu_format         No
    menu_format             No
    set_menu_items          No
    menu_items              No
    item_count              No
    set_menu_mark           No
    menu_mark               No
    new_menu                No
    free_menu               No
    menu_opts               No
    set_menu_opts           No
    menu_opts_on            No
    menu_opts_off           No
    set_menu_pattern        No
    menu_pattern            No
    post_menu               No
    unpost_menu             No
    set_menu_userptr        No
    menu_userptr            No
    set_menu_win            No
    menu_win                No
    set_menu_sub            No
    menu_sub                No
    scale_menu              No
    set_current_item        No
    current_item            No
    set_top_row             No
    top_row                 No
    item_index              No
    item_name               No
    item_description        No
    new_item                No
    free_item               No
    set_item_opts           No
    item_opts_on            No
    item_opts_off           No
    item_opts               No
    item_userptr            No
    set_item_userptr        No
    set_item_value          No
    item_value              No
    item_visible            No
    menu_request_name       No
    menu_request_by_name    No
    set_menu_spacing        No
    menu_spacing            No
    pos_form_cursor         No
    data_ahead              No
    data_behind             No
    form_driver             No
    set_form_fields         No
    form_fields             No
    field_count             No
    move_field              No
    new_form                No
    free_form               No
    set_new_page            No
    new_page                No
    set_form_opts           No
    form_opts_on            No
    form_opts_off           No
    form_opts               No
    set_current_field       No
    current_field           No
    set_form_page           No
    form_page               No
    field_index             No
    post_form               No
    unpost_form             No
    set_form_userptr        No
    form_userptr            No
    set_form_win            No
    form_win                No
    set_form_sub            No
    form_sub                No
    scale_form              No
    set_field_fore          No
    field_fore              No
    set_field_back          No
    field_back              No
    set_field_pad           No
    field_pad               No
    set_field_buffer        No
    field_buffer            No
    set_field_status        No
    field_status            No
    set_max_field           No
    field_info              No
    dynamic_field_info      No
    set_field_just          No
    field_just              No
    new_field               No
    dup_field               No
    link_field              No
    free_field              No
    set_field_opts          No
    field_opts_on           No
    field_opts_off          No
    field_opts              No
    set_field_userptr       No
    field_userptr           No
    field_arg               No
    form_request_name       No
    form_request_by_name    No

[*] To use any functions in this column, the program must set the variable $Curses::OldCurses variable to a non-zero value before using the Curses package. See "Perl 4.X cursperl Compatibility" for an example of this.

Available Wide-Character-Aware Functions

    Function    Uses wide-character call  Reverts to legacy call
    --------    ------------------------  ----------------------
    getchar     wget_wch                  wgetch
    getstring   wgetn_wstr                wgetnstr
    ungetchar   unget_wch                 ungetch
    instring    winnwtr                   winnstr
    addstring   waddnwstr                 waddnstr
    insstring   wins_nwstr                winsnstr

Available Variables

    LINES                   COLS                    stdscr
    curscr                  COLORS                  COLOR_PAIRS

Available Constants

    ERR                     OK                      ACS_BLOCK
    ACS_BOARD               ACS_BTEE                ACS_BULLET
    ACS_CKBOARD             ACS_DARROW              ACS_DEGREE
    ACS_DIAMOND             ACS_HLINE               ACS_LANTERN
    ACS_LARROW              ACS_LLCORNER            ACS_LRCORNER
    ACS_LTEE                ACS_PLMINUS             ACS_PLUS
    ACS_RARROW              ACS_RTEE                ACS_S1
    ACS_S9                  ACS_TTEE                ACS_UARROW
    ACS_ULCORNER            ACS_URCORNER            ACS_VLINE
    A_ALTCHARSET            A_ATTRIBUTES            A_BLINK
    A_BOLD                  A_CHARTEXT              A_COLOR
    A_DIM                   A_INVIS                 A_NORMAL
    A_PROTECT               A_REVERSE               A_STANDOUT
    A_UNDERLINE             COLOR_BLACK             COLOR_BLUE
    COLOR_CYAN              COLOR_GREEN             COLOR_MAGENTA
    COLOR_RED               COLOR_WHITE             COLOR_YELLOW
    KEY_A1                  KEY_A3                  KEY_B2
    KEY_BACKSPACE           KEY_BEG                 KEY_BREAK
    KEY_BTAB                KEY_C1                  KEY_C3
    KEY_CANCEL              KEY_CATAB               KEY_CLEAR
    KEY_CLOSE               KEY_COMMAND             KEY_COPY
    KEY_CREATE              KEY_CTAB                KEY_DC
    KEY_DL                  KEY_DOWN                KEY_EIC
    KEY_END                 KEY_ENTER               KEY_EOL
    KEY_EOS                 KEY_EVENT               KEY_EXIT
    KEY_FIND                KEY_HELP                KEY_HOME
    KEY_IC                  KEY_IL                  KEY_LEFT
    KEY_LL                  KEY_MARK                KEY_MAX
    KEY_MESSAGE             KEY_MIN                 KEY_MOVE
    KEY_NEXT                KEY_NPAGE               KEY_OPEN
    KEY_OPTIONS             KEY_PPAGE               KEY_PREVIOUS
    KEY_PRINT               KEY_REDO                KEY_REFERENCE
    KEY_REFRESH             KEY_REPLACE             KEY_RESET
    KEY_RESIZE              KEY_RESTART             KEY_RESUME
    KEY_SAVE                KEY_SBEG                KEY_SCANCEL
    KEY_SCOMMAND            KEY_SCOPY               KEY_SCREATE
    KEY_SDC                 KEY_SDL                 KEY_SELECT
    KEY_SEND                KEY_SEOL                KEY_SEXIT
    KEY_SF                  KEY_SFIND               KEY_SHELP
    KEY_SHOME               KEY_SIC                 KEY_SLEFT
    KEY_SMESSAGE            KEY_SMOVE               KEY_SNEXT
    KEY_SR                  KEY_SREDO               KEY_SREPLACE
    KEY_SRESET              KEY_SRIGHT              KEY_SRSUME
    KEY_SSAVE               KEY_SSUSPEND            KEY_STAB
    KEY_SUNDO               KEY_SUSPEND             KEY_UNDO
    KEY_UP                  KEY_MOUSE               BUTTON1_RELEASED
    BUTTON_SHIFT            BUTTON_ALT              ALL_MOUSE_EVENTS
    E_CONNECTED             E_BAD_STATE             E_NO_ROOM
    E_INVALID_FIELD         E_CURRENT               REQ_LEFT_ITEM
    REQ_RIGHT_ITEM          REQ_UP_ITEM             REQ_DOWN_ITEM
    O_ONEVALUE              O_SHOWDESC              O_ROWMAJOR
    O_IGNORECASE            O_SHOWMATCH             O_NONCYCLIC
    REQ_END_FIELD           REQ_BEG_LINE            REQ_END_LINE
    REQ_DOWN_CHAR           REQ_NEW_LINE            REQ_INS_CHAR
    REQ_INS_LINE            REQ_DEL_CHAR            REQ_DEL_PREV
    REQ_DEL_LINE            REQ_DEL_WORD            REQ_CLR_EOL
    REQ_CLR_EOF             REQ_CLR_FIELD           REQ_OVL_MODE
    REQ_INS_MODE            REQ_SCR_FLINE           REQ_SCR_BLINE
    JUSTIFY_RIGHT           O_VISIBLE               O_ACTIVE
    O_PUBLIC                O_EDIT                  O_WRAP
    O_BLANK                 O_AUTOSKIP              O_NULLOK
    O_PASSOK                O_STATIC                O_NL_OVERLOAD

Curses functions not available through Perl Curses

    tstp _putchar fullname scanw wscanw mvscanw mvwscanw ripoffline
    setupterm setterm set_curterm del_curterm restartterm tparm tputs
    putp vidputs vidattr mvcur tigetflag tigetnum tigetstr tgetent
    tgetflag tgetnum tgetstr tgoto tputs

Curses menu functions not available through Perl Curses

    set_item_init item_init set_item_term item_term set_menu_init
    menu_init set_menu_term menu_term

Curses form functions not available through Perl Curses

    new_fieldtype free_fieldtype set_fieldtype_arg
    set_fieldtype_choice link_fieldtype set_form_init form_init
    set_form_term form_term set_field_init field_init set_field_term
    field_term set_field_type field_type