How curses preserves screen contents? - terminal

When you start the (n)curses program, it will remove the scroll bar from your terminal emulator, clear the screen, the scroll log (history) will also disappear. When you exit the program, the screen contents reappears, the scroll bar returns, and the scroll buffer returns.
How ncurses does it? I have studied all ANSI escape codes, I cannot see anything that can do such things. What is the technology behind this?

This is discussed at length in the xterm FAQ Why doesn't the screen clear when running vi?.
ncurses as such doesn't do it. This is done by the terminal, given the escape sequences provided in the terminal description.
The behavior is from the alternate screen buffer, which was introduced with xterm in X10R4 (the end of 1986). xterm maintains two buffers:
the normal screen buffer (what you see in the VT100 window) including the scrollback area, and
the alternate screen buffer (which does not include the scrollback area)
xterm (and programs which use this feature, such as rxvt) recognizes escape sequences for switching between the two buffers. Since conventional termcap had no feature for this, the developers used the termcap initialization sequences ti and te (which correspond to terminfo smcup and rmcup). Technically the names refer to cursor-addressing mode, but no one cares (much).
The original xterm's alternate screen feature could be suppressed by removing at runtime the termcap ti and te capabilities (from the TERMCAP environment variable), but that approach could not work with terminfo, which uses files. Since 1997, xterm has implemented a newer set of escape sequences which can be ignored by xterm. A few other programs allow the feature to be suppressed, but as a rule, those do not.

The technology is called The Alternate Screen Buffer. Terminal emulator provides two modes: primary and alternate. Alternate screen buffer has no scroll back, when you switch between these buffers the contents in them is preserved. To switch between them use smcup and rmcup ANSI Escape Sequences. In binary form they are:
$ tput smcup|hexdump -C
00000000 1b 5b 3f 31 30 34 39 68 |.[?1049h|
$ tput rmcup|hexdump -C
00000000 1b 5b 3f 31 30 34 39 6c |.[?1049l|

Related

Obtain cursor color in terminal

Is there any way to determine what the color of the cursor is in a terminal running something like vim? I know that you can use tput cols and tput rows to determine the height and width of the terminal, are there similar tools for cursor color/obtaining the ansi standard foreground/background color of any character location in the current terminal?
The answer to your question is "No, there is no standard way to do that."
Consider that your terminal is modelled after ancient text terminals (like DEC VT100 and the like) which communicated with a server over a serial port or modem. And those terminals were in turn modelled after TeleTYpe (tty) devices which were connected to computers back in the 1960s.
Teletype machines ("dumb" terminals) provided no data back to the server that was not typed in to the keyboard. Devices like the VT100 ("smart" terminals) provided VERY LITTLE back to the server, but the list of what's available hasn't changed in many years.
Other resources:
The full list of reports available in VT220 emulation.
Another useful unofficial resource with slightly easier to follow wording.
Note that not all terminals are VT100/VT220, and your system may have locak extensions that provide what you need in a non-standard way.
For extra reading, have a look at man termcap and man terminfo. Check out the references in the "SEE ALSO" section of those pages.
Short answer: no
Long answer: the feature, if widely available would be another capability of tput, which allows you to retrieve any of the terminal capabilities for scripting. Those are documented in the terminfo manual page. None of those deal with cursor color, only with the (rather vague) cvvis (very visible), cnorm (normal) and civis (invisible) cursor attributes.
That is, most terminals do not
provide a way to set the cursor color or
provide a way to retrieve the cursor color
xterm is a rare exception, providing both. But the feature is not often supported in terminals imitating xterm. It is documented in XTerm Control Sequences as part of the dynamic colors feature:
OSC Ps ; Pt ST
OSC Ps ; Pt BEL
Set Text Parameters. For colors and font, if Pt is a "?", the
control sequence elicits a response which consists of the con-
trol sequence which would set the corresponding value. The
dtterm control sequences allow you to determine the icon name
and window title.
The 10 colors (below) which may be set or queried using 1 0
through 1 9 are denoted dynamic colors, since the correspond-
ing control sequences were the first means for setting xterm's
colors dynamically, i.e., after it was started. They are not
the same as the ANSI colors. These controls may be disabled
using the allowColorOps resource. At least one parameter is
expected for Pt. Each successive parameter changes the next
color in the list. The value of Ps tells the starting point
in the list. The colors are specified by name or RGB specifi-
cation as per XParseColor.
If a "?" is given rather than a name or RGB specification,
xterm replies with a control sequence of the same form which
can be used to set the corresponding dynamic color. Because
more than one pair of color number and specification can be
given in one control sequence, xterm can make more than one
reply.
Ps = 1 2 -> Change text cursor color to Pt.
The command-line program xtermcontrol uses these escape sequences to set and get the cursor color:
--cursor=COLOR
Set cursor color to COLOR.
--get-cursor
Report cursor color.
For example
$ xtermcontrol --get-cursor
rgb:0000/0000/0000
$ xtermcontrol --cursor limegreen
$ xtermcontrol --get-cursor
rgb:3232/cdcd/3232
For what it's worth, it is supported by VTE (e.g., gnome-terminal).

Keyboard characters in script record

I am using script to record a terminal session. However, inside my recorded text file, the text input and output is interlaced with strange characters that look like:
^M^[[K^[[A^[[C^ $vim session ^M
^[[?1049h^[[?1h^[=^[[1;21r^[[?12;25h^[[?12l^[[?25h^[[27m^[[m^[[H^[[2J^[[?25l^[[21;1H"session"
[noeol] 3L, 855C^
I think these correspond to return keys and other keyboard commands. Is there a way to not record these during a script session?
In the example given,
^M^[[K^[[A^[[C^ $vim session ^M
^[[?1049h^[[?1h^[=^[[1;21r^[[?12;25h^[[?12l^[[?25h^[[27m^[[m^[[H^[[2J^[[?25l^[[21;1H"session"
[noeol] 3L, 855C^
you have a mixture of cursor-movement and other escape-sequences. The ^[ is the escape character, and ^M is carriage return. As noted, script records everything sent to the terminal, and full-screen programs such as vim will always use these escape sequences. For instance, picking it apart
^[[K
clears the line,
^[[C
moves the cursor,
^[[?1049h
switches the terminal to the alternate screen,
^[[1;21r
sets scrolling margins
^[[?12;25h
sets modes (12 for blinking cursor, 25 to ensure the cursor is visible). Oddly, vim next stops blinking the cursor, resets video attributes with
^[[27m
^[[m
^[[H
before moving the cursor to the upper left
^[[J
and clearing the screen, and then hides the cursor again before
^[[21;1H"session"
[noeol] 3L, 855C
jumping to the lower left of the screen and printing a message (for reference, XTerm Control Sequences). So there is a lot going on, and it is not simply printing the screen left-to-right and top-to-bottom.
Since you are using script, it captures the output into a "typescript" file. If you want to filter those into readable form, a pager such as less using its -R option works passably well—but it misses things. The terminal emulator (with the same screensize) is the best way I know to filter the results, e.g, using a program which sends the characters to the terminal slowly. If you want plain text, select/paste from a replay (using ^S and ^Q to stop/resume) might be a way to go.
A UNIX terminal has two modes, canonical and non-canonical (also known as 'cooked' and 'raw').
The script program works by inserting itself into the message queue stack between the terminal driver and the shell (that's simplified).
The shell thinks it is talking to a terminal when it is talking with script. So what you see is what the shell sees, the raw terminal characters.
Try strings typescript

how to get current terminal color pair in bash

I would like to query and store the current terminal color pair in BASH e.g.:
#!/bin/bash
#some ANSI colour escape sequences
red="\033[0;31m"
grn="\033[0;32m"
blu="\033[0;34m"
def="\033[0;00m" # default
echo -e "Change to ${red} red to ${def} default to ${blu} blue."
# now store the current color (which happens to be blue) e.g.:
cur=????
echo -e "Change to ${grn} green and back to what I had before ${cur}"
echo -e "This would be in blue if variable cur contained e.g.: 0;34m."
echo -e "Back to default${def}"
exit 0
The answer that eludes me is how to capture the current color
cur=????
The question was about the current color, not the cursor position.
Both are "nonstandard" (though the latter, cursor position report is implemented by anything which has a valid claim to "VT100 emulator").
However, xterm implements a set of escape sequences referred to as dynamic colors, which predate the ANSI color functionality. Those set the working colors including text foreground and background. I modified this in 2002 to allow an application to send the sequence with a "?" rather than a color to tell xterm to return the color value, e.g.,
OSC 1 1 ? ST
using the notation given in XTerm Control Sequences
You can't; there is no standard control sequence to report the current cursor attributes.
What does exist, however, is a sequence to save and restore the current cursor position and attributes:
\e7 (DECSC) will save the cursor position and attributes.
\e8 (DECRC) will restore the saved cursor position and attributes.
There is no standard way to restore only the cursor attributes; however, as rici mentioned, you can get a report of the current position using \e[6n (DSR), then use the response to manually "un-restore" the cursor position after restoring its position and attributes.
Again, though, it's probably easier (and better) to just keep track of the colors in your application, rather than making the terminal responsible for that.
It's important to understand that the terminal state has nothing to do with bash. Bash doesn't care. It simply reads from stdin and writes to stdout and stderr. (See Note 1)
All terminal effects are implemented by the terminal emulator you happen to be using, of which there are many. In a graphical environment, you might be using, for example, xterm or konsole. You'll need to search the documentation for those emulators for specific terminal control codes which they interpret.
As far as I know, there is no standard code to get a report of the current terminal state, other than the cursor position (ESC[6n).
So your best bet is to remember the changes you made when you make them.
You can find a list of the standard codes implemented by the Linux console using man console_codes (although few people use the Linux console these days); most of those are also interpreted by xterm and other graphical consoles. There's an list of xterm sequences in Thomas Dickey's xterm site; it's a more or less de facto standard for terminal emulators but, as I said, you'll need to search in each emulator's documentation for idiosyncratic control sequences.
Notes
In interactive mode, bash uses a library called readline to help it handle some terminal effects. In particular, readline tries to maintain the current console cursor position, although it is easy to fool it. In PS1 you need to surround console control sequences with \[ and \] precisely because readline does not know that they are control sequences.
What I understood, is that u are asking to to get the default profile color of the user, of which u have change color of!
Eg: User is using 'Bright Green font color on Black background', you change it to 'Red font color on White background'. Now how to get/know the default colors and set them back to it!
You can use the sequence \033[0m in bash [also for command prompt (batch scripting) / powershell (ps scripting)]

Full screen terminal application with ruby (or other languages)

Have you ever used cli tools like vim or htop? All these will maximize inside the terminal and have no scrollback but when you exit, they disappear and you can see what you typed in before.
Example:
(terminal window with scrollback)
(maximized vim without scrollback)
(back in shell with scrollback and vim gone)
How can I do this in my own application, preferably ruby?
This is a mode supported by most terminals through the XTerm control sequence specifications.
The specific screen-switching mode that can be activated using those specs is called the alternate screen buffer.
When you send the correct XTerm control sequence to the terminal then the terminal will switch into an alternate screen buffer. Once whatever program exits, it usually sends the commands to switch back to the original screen buffer. This way you get the effect of the application restoring your original terminal display.
The sequence for activating the alternate buffer is CSI ? 47 h. CSI stands for Control Sequence Initiator, and it's usually ESC + [. So by sending ESC [ ? 47 h (without spaces) to the terminal it will switch to the alternate buffer.
You can test this by running the cat command in your shell, hitting ESC and typing [?47h and hitting enter. You should see the screen clear (or switch to the other buffer).
The sequence to switch back to the normal screen buffer is CSI ? 47 l, and you can test this the same way running the cat command and typing the keys ESC [ ? 47 l and hitting enter.
When programming complex terminal screen-based applications however, most people tend to use a library like curses or ncurses, which will take care of all the terminal handling stuff for you. See these for example:
Learning Ruby Curses
http://www.ruby-doc.org/stdlib-2.0.0/libdoc/curses/rdoc/Curses.html
I suspect a program like htop probably uses curses or ncurses too.

Unable to turn off automatic margins by termcap in Mac

I need to turn automatic margins off according the following statement from Screen's manual in my Mac
If your terminal is a "true"
auto-margin terminal (it doesn't allow
the last position on the screen
to be updated without scrolling the screen) consider using a version
of your terminal's termcap that
has automatic margins turned off.
How can you turn automatic margins off by your terminal's termcap?
Most terminal emulators, including the mac default terminal, are not "true auto-margin terminals" in the sense being discussed here - they emulate a vt100-series terminal, which had "smart" wraparound. You can check by running cat and typing to the end of the last line - after you type the last character, the cursor remains at the end of the line (highlighting the character you just typed) until you type another character.
The only consequence of a 'true auto-margin terminal' is that a character cannot be displayed in the lower right hand corner (though some programs are able to work around that by shifting a character into place with ich/ich1)
According to XTerm Control Sequences, this sequence should do what was asked:
CSI ? 7 l
That is,
printf '\033[?7l'
The 7 is documented as
Ps = 7 -> Wraparound Mode (DECAWM).
and the final character l (lowercase L) denotes this as a reset rather than a set control.
For whatever reason, the terminfo name for this is more obscure: "automatic margins". These terminfo capabilities deal with the feature (see terminfo(5)):
auto_right_margin am am terminal has auto‐
matic margins
enter_am_mode smam SA turn on automatic
margins
exit_am_mode rmam RA turn off automatic
margins
Interestingly, the vt100-nam terminal description in ncurses (which apparently no one uses) initializes the terminal to use automargins margins using this string:
rs2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h,
(the \E[?7h sets it), and asserts that the terminal does not use automatic margins by cancelling am. It also has the terminfo capabilities rmam and smam. So you could do this to prove that it works:
tput rmam
stty columns 999
ps -efwwwwwl
and (for the ordinary user) see the ps listing nicely truncated against the right margin of the terminal window.
The other variants vt220-nam and vt320-nam appear correct...
By the way, for Mac, you would use the terminfo names such as rmcup rather than the termcap RA, because OSX uses ncurses' tput (terminfo) rather than the BSD variant.
Further reading:
tput, reset - initialize a terminal or query terminfo
database
history section for tput
history section for tset
Occasionally someone asks about suppressing automargins because they suppose that terminals can pan/scroll left/right to show the information which was not wrapped to a new line. Terminals which do this are rare, and OSX Terminal is not one of those. It behaves like a subset of xterm, which itself emulates the series of DEC terminals vt52/vt100/vt220/etc. In this question, OP is concerned/confused about this paragraph from the screen manual:
If your terminal is a "true" auto-margin terminal (it doesn't allow the
last position on the screen to be updated without scrolling the screen)
consider using a version of your terminal's termcap that has automatic
margins turned off. This will ensure an accurate and optimal update of
the screen in all circumstances. Most terminals nowadays have "magic"
margins (automatic margins plus usable last column). This is the VT100
style type and perfectly suited for screen. If all you've got is a
"true" auto-margin terminal screen will be content to use it, but
updating a character put into the last position on the screen may not
be possible until the screen scrolls or the character is moved into a
safe position in some other way. This delay can be shortened by using a
terminal with insert-character capability.
That last position on the screen refers to the lower-right corner of the terminal. In the normal case, if your cursor is on the lower-right corner and you print a character, you would expect the display to scroll up by one line and show the character on the next line. Also (because terminals can be implemented in different ways), some could scroll up when you print a character in the last position. The VT100 does not do this. Not only does it not scroll up in that case, but it ignores non-printing characters while on the margin (see xterm FAQ That description of wrapping is odd, say more?). There is a terminfo flag xenl which is set to show when the terminal does this special behavior. About a third of the terminal descriptions in the terminal database have this flag. While most of those are for terminals which you likely will never encounter, keep in mind that the advice in the manual page was written back in an era when those other terminals were as likely to be found as a VT100-lookalike. The early change-history for screen is poor, but the text was in screen's second posting to Usenet in 1992. The initial posting in 1987 said something similar:
Screen
never writes in the last position of the screen, unless the boolean
capability LP is found in the termcap entry of the terminal.
Usually,
screen
cannot predict whether or not a particular terminal scrolls when
a character is written in the last column of the last line;
LP indicates that it is safe to write in this position.
Note that the LP capability is independent of am (automatic
margins); for certain terminals, such as the VT100, it is reasonable
to set am as well as LP in the corresponding termcap entry
(the VT100 does not move the cursor when a character is written in
the last column of each line).
The later wording reflects the fact that the terminfo system was prevalent, and the name LP was not termcap name chosen for corresponding with xenl (it is xn).
The point of all of this is that screen attempts to convert between programs writing to different terminal types and make them all appear like one type of terminal — which means that it tries to put text on the terminal's display in all of the locations. The lower-right corner is a problem because some terminals would scroll up, spoiling the attempt to write there. As a workaround, some terminals provided an alternative:
using a different mode (insert),
put the cursor on the next to last position of the display,
write characters to fill in, pushing a character into the last position, and
turn insert-mode off once it is done (otherwise a nuisance).
About two thirds of the descriptions in the terminal database have the capability to do this insert-mode (smir). That still was not perfect, but it certainly was worth mentioning in 1992. About a quarter implement a similar similar feature ich1. Some implement both (and vi could get confused by those, by trying to do both methods).
VT100-lookalikes provide a third way to write that last position; screen checks for and uses whatever is there.
If I understand you correctly you're looking to set the autowrap feature to NO using terminfo database. If so I believe you can use the -nam flag to turn it off - something like vt100-nam should do it. You can also check by looking at the man pages for terminfo.
If this solves your question, mark this up. (^_^) If not... well comment back and I'll check again for you. Cheers!
Update: There's also a shortcut that may apply to you to toggle the wrap off and on. Check out the shortcut sheet here. And additional information for Screen can be found here (search for wrap). You can also check here on how to use setterm (section 17.14 Changing the Terminal Settings). Also check here for examples of changing settings.
Good luck again. (^_^)

Resources