4

Whilst I know that tput rmcup returns from the "alternate screen" (referred to as "cup mode" in man 5 terminfo) and restores the saved screen, it does have the side-effect of repositioning the cursor.

So if tput smcup was called, tput rmcup restores the screen and repositions the cursor, but if you then type a few more commands or press enter a few times and then use tput rmcup again, the cursor returns to the original saved position.

One use case is in a bash script that replays a terminal recording [using scriptreplay]: if the script ends prematurely without [the equivalent of] calling tput rmcup then I'd like to be able to detect that in my bash script and call tput rmcup automatically.

So in short, I'd like to be able to determine what the current screen state is; i.e., is it the "alternate screen" or is it the "normal screen"?

tel
  • 13,005
  • 2
  • 44
  • 62
IpsRich
  • 797
  • 10
  • 23

1 Answers1

3

If you're using xterm, then you can ask it what mode it's using. Although the alternate-screen feature is an xterm feature rather than "DEC", the setting is grouped with the DECSET modes described in XTerm Control Sequences:

CSI ? Pm h
          DEC Private Mode Set (DECSET).
...
            Ps = 1 0 4 7  -> Use Alternate Screen Buffer, xterm.  This
          may be disabled by the titeInhibit resource.
            Ps = 1 0 4 8  -> Save cursor as in DECSC, xterm.  This may
          be disabled by the titeInhibit resource.
            Ps = 1 0 4 9  -> Save cursor as in DECSC, xterm.  After sav-
          ing the cursor, switch to the Alternate Screen Buffer, clear-
          ing it first.  This may be disabled by the titeInhibit

The DECRQM control can be used to query the terminal:

CSI ? Ps$ p
          Request DEC private mode (DECRQM).  For VT300 and up, reply
          DECRPM is
            CSI ? Ps; Pm$ y
          where Ps is the mode number as in DECSET/DECSET, Pm is the
          mode value as in the ANSI DECRQM.

That is, your script could

printf '\033[?1049$p'

and read the result back, expecting something like \033[?1049;1$y

Here is a quick demo:

#!/bin/sh                                                                      

unexpected() {
        result=$(echo "$check"|sed -e 's/^@/\\033/')
        printf '? unexpected reply: %s\n' "$result"
        exit 1
}

exec </dev/tty
old=`stty -g`
stty raw -echo min 0  time 5
printf '\033[?1049$p'
read status
stty $old

if [ -n "$status" ]
then
        check=$(echo "$status" |tr '\033' '@')
        if [ "$check" != "$status" ]
        then
                case "$check" in
                '@[?1049;1$y')
                        echo "alternate screen"
                        ;;
                '@[?1049;2$y')
                        echo "normal screen"
                        ;;
                *)
                        unexpected
                        ;;
                esac
        else
                unexpected
        fi
else
        echo "? no reply from terminal"
fi

Of course, if you're not using xterm, your mileage may vary...

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • Thanks for the reply. That does sound like it will be useful to me, and indeed my `$TERM` environment variable is `xterm-256color` so this could be the right approach. However, I must confess, I didn't quite follow what I would need to do in order to make use of this. When I execute (in `bash`) the `printf` you suggested, that's exactly what I get back... Is that a surprise or am I using it wrongly? I'm not sure what to make of the `$` signs followed by spaces either: I don't know what that means in `bash`. – IpsRich Apr 19 '18 at 07:25
  • Thanks for the edit. I wasn't alerted that it had happened so didn't realise you're added the demo code. I've just tried it out on my `xterm-256color` terminal and I see the control codes on the screen followed less than a second later by the "? no reply from terminal" message. I guess that means my terminal's not compatible then? – IpsRich Nov 05 '18 at 14:10
  • sounds like it - there's a set of screens in vttest which can demonstrate that – Thomas Dickey Nov 05 '18 at 23:31
  • I've just tried the "Test of screen features" in `vttest` (v2.7) and whilst they mostly work, it's not 100%. The line that says "Origin mode test. This line should be at the bottom of the screen." is not at the bottom of the screen, for example. Oh well, thanks for your answer anyway - hopefully it'll help someone with a properly compatible xterm! – IpsRich Nov 06 '18 at 08:12
  • This particular feature can be seen in menu 11, 8, 2 ("Request Mode (DECRQM)/Report Mode (DECRPM)), though it only shows if the terminal recognizes the control, and what its response is - not whether the terminal does it properly by changing the response as the terminal switches between normal/alternate screens. – Thomas Dickey Nov 06 '18 at 09:11
  • I hadn't spotted that test. The output I get aligns with the output your little script above gave me: `Testing Request Mode (DECRQM)/Report Mode (DECRPM) [?1$p 1: DECCKM <13> failed[?2$p` (Sorry, I couldn't get the line breaks to work in a comment!) – IpsRich Nov 07 '18 at 08:04