2 * termcap.c - termcap manipulation through curses
4 * This file is part of zsh, the Z shell.
6 * Copyright (c) 1992-1997 Paul Falstad
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
15 * In no event shall Paul Falstad or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Paul Falstad and the Zsh Development Group have been advised of
19 * the possibility of such damage.
21 * Paul Falstad and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose. The software
24 * provided hereunder is on an "as is" basis, and Paul Falstad and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
31 * We need to include the zsh headers later to avoid clashes with
32 * the definitions on some systems, however we need the configuration
33 * file to decide whether we should avoid curses.h, which clashes
34 * with several zsh constants on some systems (e.g. SunOS 4).
36 #include "../../config.h"
39 # if defined(ZSH_HAVE_CURSES_H) && defined(ZSH_HAVE_TERM_H)
40 # define USES_TERM_H 1
42 # ifdef HAVE_TERMCAP_H
43 # define USES_TERMCAP_H 1
48 #include "termcap.mdh"
49 #include "termcap.pro"
57 # ifdef ZSH_HAVE_CURSES_H
58 # include "../zshcurses.h"
60 # include "../zshterm.h"
62 # ifdef USES_TERMCAP_H
67 #ifndef HAVE_BOOLCODES
68 static char *boolcodes
[] = {
69 "bw", "am", "ut", "cc", "xs", "YA", "YF", "YB", "xt", "xn", "eo",
70 "gn", "hc", "HC", "km", "YC", "hs", "hl", "in", "YG", "da", "db",
71 "mi", "ms", "nx", "xb", "NP", "ND", "NR", "os", "5i", "YD", "YE",
72 "es", "hz", "ul", "xo", NULL
};
81 /* ncurses can tell if an existing boolean capability is *
82 * off, but other curses variants can't, so we fudge it. *
83 * This feature of ncurses appears to have gone away as *
84 * of NCURSES_MAJOR_VERSION == 5, so don't rely on it. */
85 switch (tgetflag(s
)) {
89 for (b
= (char **)boolcodes
; *b
; ++b
)
90 if (s
[0] == (*b
)[0] && s
[1] == (*b
)[1])
99 /* echotc: output a termcap */
103 bin_echotc(char *name
, char **argv
, UNUSED(Options ops
), UNUSED(int func
))
105 char *s
, buf
[2048], *t
, *u
;
109 if (termflags
& TERM_BAD
)
111 if ((termflags
& TERM_UNKNOWN
) && (isset(INTERACTIVE
) || !init_term()))
113 /* if the specified termcap has a numeric value, display it */
114 if ((num
= tgetnum(s
)) != -1) {
118 /* if the specified termcap is boolean, and set, say so */
119 switch (ztgetflag(s
)) {
129 /* get a string-type capability */
132 if (t
== (char *)-1 || !t
|| !*t
) {
133 /* capability doesn't exist, or (if boolean) is off */
134 zwarnnam(name
, "no such capability: %s", s
);
137 /* count the number of arguments required */
138 for (argct
= 0, u
= t
; *u
; u
++)
140 if (u
++, (*u
== 'd' || *u
== '2' || *u
== '3' || *u
== '.' ||
144 /* check that the number of arguments provided is correct */
145 if (arrlen(argv
) != argct
) {
146 zwarnnam(name
, (arrlen(argv
) < argct
) ? "not enough arguments" :
147 "too many arguments");
150 /* output string, through the proper termcap functions */
154 /* This assumes arguments of <lines> <columns> for cap 'cm' */
155 num
= (argv
[1]) ? atoi(argv
[1]) : atoi(*argv
);
156 tputs(tgoto(t
, num
, atoi(*argv
)), 1, putraw
);
161 static struct builtin bintab
[] = {
162 BUILTIN("echotc", 0, bin_echotc
, 1, -1, 0, NULL
, NULL
),
167 gettermcap(UNUSED(HashTable ht
), const char *name
)
170 char *tcstr
, buf
[2048], *u
, *nameu
;
173 /* This depends on the termcap stuff in init.c */
174 if (termflags
& TERM_BAD
)
176 if ((termflags
& TERM_UNKNOWN
) && (isset(INTERACTIVE
) || !init_term()))
180 nameu
= dupstring(name
);
181 unmetafy(nameu
, &len
);
183 pm
= (Param
) hcalloc(sizeof(struct param
));
184 pm
->node
.nam
= nameu
;
185 pm
->node
.flags
= PM_READONLY
;
188 /* logic in the following cascade copied from echotc, above */
190 if ((num
= tgetnum(nameu
)) != -1) {
191 pm
->gsu
.i
= &nullsetinteger_gsu
;
193 pm
->node
.flags
|= PM_INTEGER
;
197 pm
->gsu
.s
= &nullsetscalar_gsu
;
198 switch (ztgetflag(nameu
)) {
202 pm
->u
.str
= dupstring("no");
203 pm
->node
.flags
|= PM_SCALAR
;
206 pm
->u
.str
= dupstring("yes");
207 pm
->node
.flags
|= PM_SCALAR
;
210 if ((tcstr
= tgetstr(nameu
, &u
)) != NULL
&& tcstr
!= (char *)-1) {
211 pm
->u
.str
= dupstring(tcstr
);
212 pm
->node
.flags
|= PM_SCALAR
;
214 /* zwarn("no such capability: %s", name); */
215 pm
->u
.str
= dupstring("");
216 pm
->node
.flags
|= PM_UNSET
;
223 scantermcap(UNUSED(HashTable ht
), ScanFunc func
, int flags
)
227 char **capcode
, *tcstr
, buf
[2048], *u
;
229 #ifndef HAVE_NUMCODES
230 static char *numcodes
[] = {
231 "co", "it", "lh", "lw", "li", "lm", "sg", "ma", "Co", "pa", "MW",
232 "NC", "Nl", "pb", "vt", "ws", "Yo", "Yp", "Ya", "BT", "Yc", "Yb",
233 "Yd", "Ye", "Yf", "Yg", "Yh", "Yi", "Yk", "Yj", "Yl", "Ym", "Yn",
237 #ifndef HAVE_STRCODES
238 static char *zstrcodes
[] = {
239 "ac", "bt", "bl", "cr", "ZA", "ZB", "ZC", "ZD", "cs", "rP", "ct",
240 "MC", "cl", "cb", "ce", "cd", "ch", "CC", "CW", "cm", "do", "ho",
241 "vi", "le", "CM", "ve", "nd", "ll", "up", "vs", "ZE", "dc", "dl",
242 "DI", "ds", "DK", "hd", "eA", "as", "SA", "mb", "md", "ti", "dm",
243 "mh", "ZF", "ZG", "im", "ZH", "ZI", "ZJ", "ZK", "ZL", "mp", "mr",
244 "mk", "ZM", "so", "ZN", "ZO", "us", "ZP", "SX", "ec", "ae", "RA",
245 "me", "te", "ed", "ZQ", "ei", "ZR", "ZS", "ZT", "ZU", "se", "ZV",
246 "ZW", "ue", "ZX", "RX", "PA", "fh", "vb", "ff", "fs", "WG", "HU",
247 "i1", "is", "i3", "if", "iP", "Ic", "Ip", "ic", "al", "ip", "K1",
248 "K3", "K2", "kb", "@1", "kB", "K4", "K5", "@2", "ka", "kC", "@3",
249 "@4", "@5", "@6", "kt", "kD", "kL", "kd", "kM", "@7", "@8", "kE",
250 "kS", "@9", "k0", "k1", "k;", "F1", "F2", "F3", "F4", "F5", "F6",
251 "F7", "F8", "F9", "k2", "FA", "FB", "FC", "FD", "FE", "FF", "FG",
252 "FH", "FI", "FJ", "k3", "FK", "FL", "FM", "FN", "FO", "FP", "FQ",
253 "FR", "FS", "FT", "k4", "FU", "FV", "FW", "FX", "FY", "FZ", "Fa",
254 "Fb", "Fc", "Fd", "k5", "Fe", "Ff", "Fg", "Fh", "Fi", "Fj", "Fk",
255 "Fl", "Fm", "Fn", "k6", "Fo", "Fp", "Fq", "Fr", "k7", "k8", "k9",
256 "@0", "%1", "kh", "kI", "kA", "kl", "kH", "%2", "%3", "%4", "%5",
257 "kN", "%6", "%7", "kP", "%8", "%9", "%0", "&1", "&2", "&3", "&4",
258 "&5", "kr", "&6", "&9", "&0", "*1", "*2", "*3", "*4", "*5", "*6",
259 "*7", "*8", "*9", "kF", "*0", "#1", "#2", "#3", "#4", "%a", "%b",
260 "%c", "%d", "%e", "%f", "kR", "%g", "%h", "%i", "%j", "!1", "!2",
261 "kT", "!3", "&7", "&8", "ku", "ke", "ks", "l0", "l1", "la", "l2",
262 "l3", "l4", "l5", "l6", "l7", "l8", "l9", "Lf", "LF", "LO", "mo",
263 "mm", "ZY", "ZZ", "Za", "Zb", "Zc", "Zd", "nw", "Ze", "oc", "op",
264 "pc", "DC", "DL", "DO", "Zf", "IC", "SF", "AL", "LE", "Zg", "RI",
265 "Zh", "SR", "UP", "Zi", "pk", "pl", "px", "pn", "ps", "pO", "pf",
266 "po", "PU", "QD", "RC", "rp", "RF", "r1", "r2", "r3", "rf", "rc",
267 "cv", "sc", "sf", "sr", "Zj", "sa", "Sb", "Zk", "Zl", "SC", "sp",
268 "Sf", "ML", "Zm", "MR", "Zn", "st", "Zo", "Zp", "wi", "Zq", "Zr",
269 "Zs", "Zt", "Zu", "Zv", "ta", "Zw", "ts", "TO", "uc", "hu", "u0",
270 "u1", "u2", "u3", "u4", "u5", "u6", "u7", "u8", "u9", "WA", "XF",
271 "XN", "Zx", "S8", "Yv", "Zz", "Xy", "Zy", "ci", "Yw", "Yx", "dv",
272 "S1", "Yy", "S2", "S4", "S3", "S5", "Gm", "Km", "Mi", "S6", "xl",
273 "RQ", "S7", "s0", "s1", "s2", "s3", "AB", "AF", "Yz", "ML", "YZ",
274 "MT", "Xh", "Xl", "Xo", "Xr", "Xt", "Xv", "sA", "sL", NULL
};
277 pm
= (Param
) hcalloc(sizeof(struct param
));
280 pm
->node
.flags
= PM_READONLY
| PM_SCALAR
;
281 pm
->gsu
.s
= &nullsetscalar_gsu
;
283 for (capcode
= (char **)boolcodes
; *capcode
; capcode
++) {
284 if ((num
= ztgetflag(*capcode
)) != -1) {
285 pm
->u
.str
= num
? dupstring("yes") : dupstring("no");
286 pm
->node
.nam
= dupstring(*capcode
);
287 func(&pm
->node
, flags
);
291 pm
->node
.flags
= PM_READONLY
| PM_INTEGER
;
292 pm
->gsu
.i
= &nullsetinteger_gsu
;
294 for (capcode
= (char **)numcodes
; *capcode
; capcode
++) {
295 if ((num
= tgetnum(*capcode
)) != -1) {
297 pm
->node
.nam
= dupstring(*capcode
);
298 func(&pm
->node
, flags
);
302 pm
->node
.flags
= PM_READONLY
| PM_SCALAR
;
303 pm
->gsu
.s
= &nullsetscalar_gsu
;
305 for (capcode
= (char **)
311 ; *capcode
; capcode
++) {
312 if ((tcstr
= (char *)tgetstr(*capcode
,&u
)) != NULL
&&
313 tcstr
!= (char *)-1) {
314 pm
->u
.str
= dupstring(tcstr
);
315 pm
->node
.nam
= dupstring(*capcode
);
316 func(&pm
->node
, flags
);
321 struct paramdef partab
[] = {
322 SPECIALPMDEF("termcap", PM_READONLY
, NULL
, gettermcap
, scantermcap
)
326 #endif /* HAVE_TGETENT */
328 static struct features module_features
= {
330 bintab
, sizeof(bintab
)/sizeof(*bintab
),
337 partab
, sizeof(partab
)/sizeof(*partab
),
346 setup_(UNUSED(Module m
))
353 features_(Module m
, char ***features
)
355 *features
= featuresarray(m
, &module_features
);
361 enables_(Module m
, int **enables
)
363 return handlefeatures(m
, &module_features
, enables
);
371 # ifdef HAVE_SETUPTERM
372 setupterm((char *)0, 1, (int *)0);
382 return setfeatureenables(m
, &module_features
, NULL
);
387 finish_(UNUSED(Module m
))