Ncurses: Difference between revisions
add note about ESCDELAY and notimeout |
No edit summary |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
Quality character cell graphics since [https://invisible-island.net/ncurses/ncurses.faq.html 1982]. NCURSES is an implementation and extension of [[Single UNIX Specification|SUS4-2018]]'s X/Open Curses API, and is installed on pretty much every Linux machine in existence. | |||
==Tracing== | |||
By either defining the symbol TRACE during compilation or linking against <tt>libncurses_g</tt>, tracing functionality becomes available to an Ncurses application (see <tt>trace(3NCURSES)</tt>). Either calling the <tt>trace()</tt> function or defining the <tt>NCURSES_TRACE</tt> environment variable is sufficient to initiate tracing, which will be logged to the file <tt>trace</tt> in the current directory (this file must not already exist). | |||
==Escape== | ==Escape== | ||
You can get Escape with no delay by using <tt>notimeout(3ncurses)</tt>, but this eliminates use of the function and arrow keys on terminals where those sequences are composed with Escape. You probably don't want that. You can use the ESCDELAY environment variable (see <tt>ncurses(3ncurses)</tt>) to change this (ncurses also provides a global of the same name). [[Vim]] uses a 25ms default. The ncurses default appears to be 1s (1000ms), which makes one's application feel kinda seasick when running on any reasonable connection (not to mention locally). This seems difficult to manipulate programaticly, though. :/ | You can get Escape with no delay by using <tt>notimeout(3ncurses)</tt>, but this eliminates use of the function and arrow keys on terminals where those sequences are composed with Escape. You probably don't want that. You can use the ESCDELAY environment variable (see <tt>ncurses(3ncurses)</tt>) to change this (ncurses also provides a global of the same name). In a threaded environment, <tt>set_escdelay()</tt> ought be preferred. [[Vim]] uses a 25ms default. The ncurses default appears to be 1s (1000ms), which makes one's application feel kinda seasick when running on any reasonable connection (not to mention locally). This seems difficult to manipulate programaticly, though. :/ | ||
===Escape codes=== | |||
The primary means of communicating with terminals is via escape sequences. The terminfo library, shipped with ncurses, allows these sequences to be looked up based off the terminal type (usually encoded in the environment variable <tt>TERM</tt>). The <tt>infocmp</tt> program dumps terminfo entries. Many terminals and terminal emulators support only some escape sequences, and they are not effectively standardized across terminals. Embedding hard-coded escape sequences into your program is a recipe for pain. | |||
The "termcap" library is obsolete, superseded entirely by terminfo, and ought not be used in new programs. | |||
==Colors== | ==Colors== | ||
| Line 28: | Line 38: | ||
| ncurses-term | | ncurses-term | ||
|} | |} | ||
===Color attributes=== | |||
Using color pairs beyond 256 requires a 16-bit attribute. By default, only 8 bits are provided (see <tt>A_COLOR</tt>). Thus for instance <tt>wattron(w, COLOR_PAIR(260))</tt> is equivalent to <tt>wattron(w, COLOR_PAIR(4))</tt>. In order to use pairs above 256, drop <tt>COLOR_PAIR</tt>, and always refer to the pair via pointer using the <tt>void* opts</tt> parameter to functions like <tt>wattron</tt>. What, there is not such parameter? Ahhh, of course; you need to use <tt>wattr_on</tt>. Note the underscore, and hate life. | |||
As of 2019-11, here are the relevant definitions from my installation of ncurses: | |||
<pre> | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#define NCURSES_CAST(type,value) static_cast<type>(value) | |||
#else | |||
#define NCURSES_CAST(type,value) (type)(value) | |||
#endif | |||
#define NCURSES_ATTR_SHIFT 8 | |||
#define NCURSES_BITS(mask,shift) (NCURSES_CAST(chtype,(mask)) << ((shift) + NCURSES_ATTR_SHIFT)) | |||
#define A_COLOR NCURSES_BITS(((1U) << 8) - 1U,0) | |||
#define COLOR_PAIR(n) (NCURSES_BITS((n), 0) & A_COLOR) | |||
#define PAIR_NUMBER(a) (NCURSES_CAST(int,((NCURSES_CAST(unsigned long,(a)) & A_COLOR) >> NCURSES_ATTR_SHIFT))) | |||
</pre> | |||
The default colors built into ncurses can be dumped with <tt>color_content -p</tt>. | |||
===True Color=== | |||
Test for terminal support (courtesy [https://gist.github.com/XVilka/8346728 XVilka]: | |||
<pre>awk 'BEGIN{ | |||
s="/\\/\\/\\/\\/\\"; s=s s s s s s s s; | |||
for (colnum = 0; colnum<77; colnum++) { | |||
r = 255-(colnum*255/76); | |||
g = (colnum*510/76); | |||
b = (colnum*255/76); | |||
if (g>255) g = 510-g; | |||
printf "\033[48;2;%d;%d;%dm", r,g,b; | |||
printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b; | |||
printf "%s\033[0m", substr(s,colnum+1,1); | |||
} | |||
printf "\n"; | |||
}'</pre> | |||
==[[Unicode]]== | ==[[Unicode]]== | ||
| Line 34: | Line 80: | ||
* setlocale() needs have been called prior to calling any ncurses functions | * setlocale() needs have been called prior to calling any ncurses functions | ||
** ncurses assumes that the locale does not change once started | ** ncurses assumes that the locale does not change once started | ||
[[CATEGORY: Terminals]] | |||