Looking at terminfo and Parameterized Strings.

Some examples from infocmp -1 xterm:

  • cud=\E[%p1%dB, given argument 13:

    • \E =><ESC>
    • [ => [
    • %p1 PUSH parameter 1 (13) onto stack
    • %d POP and print from stack as signed decimal => 13
      • Result: <ESC>[13B
  • csr=\E[%i%p1%d;%p2%dr, given arguments 13, 16:

    • \E =><ESC>
    • [ => [
    • %i Increment parameter 1 and 2: ++13, ++16 gives 14, 17
    • %p1 PUSH parameter 1 (14) onto stack.
    • %d POP and print from stack as signed decimal. => 14
    • ; => ;
    • %p2 PUSH parameter 2 (17) onto stack.
    • %d POP and print from stack as signed decimal. => 17
    • r => r
      • Result: <ESC>14;17r

But, ... how to read this one?

  • u6=\E[%i%d;%dR

After processing \E[%i we have <ESC>[ and incremented parameter 1 and 2 (if any). But stack is empty. Should not the two %d's pop and print two numbers from stack?

2 Answers 2


The absence of a %p marker is a quirk of ncurses: the terminfo compiler (tic) recognizes either terminfo (which uses %p1 to mark parameters) or termcap (which relies upon convention for the parameters). That would be a legal termcap expression. Since tic knows how to process a termcap expression, the string shown is "close enough" that there was no need to translate it further.

You can see what ncurses does using tput, e.g.,

tput u6 40 50

gives (note the reversal of parameters)


If the expression were given as


it would have the same result.

The u6-u9 capabilities are an early extension documented in ncurses's terminal database:

# The System V Release 4 and XPG4 terminfo format defines ten string
# capabilities for use by applications, <u0>...<u9>.   In this file, we use
# certain of these capabilities to describe functions which are not covered
# by terminfo.  The mapping is as follows:
#       u9      terminal enquire string (equiv. to ANSI/ECMA-48 DA)
#       u8      terminal answerback description
#       u7      cursor position request (equiv. to VT100/ANSI/ECMA-48 DSR 6)
#       u6      cursor position report (equiv. to ANSI/ECMA-48 CPR)
# The terminal enquire string <u9> should elicit an answerback response
# from the terminal.  Common values for <u9> will be ^E (on older ASCII
# terminals) or \E[c (on newer VT100/ANSI/ECMA-48-compatible terminals).
# The cursor position request (<u7>) string should elicit a cursor position
# report.  A typical value (for VT100 terminals) is \E[6n.
# The terminal answerback description (u8) must consist of an expected
# answerback string.  The string may contain the following scanf(3)-like
# escapes:
#       %c      Accept any character
#       %[...]  Accept any number of characters in the given set
# The cursor position report (<u6>) string must contain two scanf(3)-style
# %d format elements.  The first of these must correspond to the Y coordinate
# and the second to the %d.  If the string contains the sequence %i, it is
# taken as an instruction to decrement each value after reading it (this is
# the inverse sense from the cup string).  The typical CPR value is
# \E[%i%d;%dR (on VT100/ANSI/ECMA-48-compatible terminals).
# These capabilities are used by tack(1m), the terminfo action checker
# (distributed with ncurses 5.0).

Checking that last comment, tack exercises u8 and u9 but does nothing with u6 and u7.

The extension was added early in 1995:

# 9.3.4 (Wed Feb 22 19:27:34 EST 1995):
#       * Added correct acsc/smacs/rmacs strings for vt100 and xterm.
#       * Added u6/u7/u8/u9 capabilities.
#       * Added PCVT entry.

and while it is included in several entries for completeness (not many: there are 16 occurrences in 18,699 lines of terminfo.src), there are no well-known users of the feature. In fact, there is one place in ncurses where it could have been written to use it (some ifdef'd debugging code in the tty_update.c file), but that uses hard-coded escape sequences (marked as "ANSI compatible").

The reason for the absence of users would be:

  • inverting an arbitrary terminfo expression is harder than it may seem
  • xterm and similar terminals interpret these escape sequences

In ECMA-48, these are (u7) DSR (device status report) and (u6) CPR (active position report).

  • For what it's worth, the direct mode of Notcurses uses u7 extensively, including in ncdirect_cursor_yx(), and ncdirect_cursor_move_yx(). I wasn't aware of u6, though, and have been running a baroque algorithm to determine cursor report inversion and the need for decrement (see detect_cursor_inversion()); I will switch to u6, and hopefully eliminate this code.
    – nick black
    Commented Jun 14, 2021 at 0:04


It is a special entry in the database. It gives the respond format to u7.

The response is <ESC>[Y;XR as in Y=row and X=column.

If u6 has %i, one should decrement the responded values.


  • u6=\E[%i%d;%dR
  • u7=\E[6n

Send u7.

  • Response for example: \E[48;13R.
  • Result:
    • Y = 48 - 1 = 47
    • X = 13 - 1 = 12.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .