1 /* $NetBSD: setterm.c,v 1.44 2009/02/22 20:05:48 christos Exp $ */
4 * Copyright (c) 1981, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)setterm.c 8.8 (Berkeley) 10/25/94";
37 __RCSID("$NetBSD: setterm.c,v 1.44 2009/02/22 20:05:48 christos Exp $");
41 #include <sys/ioctl.h> /* TIOCGWINSZ on old systems. */
49 #include "curses_private.h"
51 static int zap(SCREEN
*screen
);
53 static int does_esc_m(char *cap
);
54 static int does_ctrl_o(char *cap
);
56 static char *sflags
[] = {
58 &__tc_am
, &__tc_bs
, &__tc_cc
, &__tc_da
, &__tc_eo
,
60 &__tc_hc
, &__tc_hl
, &__tc_in
, &__tc_mi
, &__tc_ms
,
62 &__tc_nc
, &__tc_ns
, &__tc_os
, &__tc_ul
, &__tc_ut
,
64 &__tc_xb
, &__tc_xn
, &__tc_xt
, &__tc_xs
, &__tc_xx
67 static int *svals
[] = {
69 &__tc_pa
, &__tc_Co
, &__tc_NC
75 &__tc_AB
, &__tc_ac
, &__tc_ae
, &__tc_AF
, &__tc_AL
,
77 &__tc_al
, &__tc_as
, &__tc_bc
, &__tc_bl
, &__tc_bt
,
79 &__tc_cd
, &__tc_ce
, &__tc_cl
, &__tc_cm
, &__tc_cr
,
81 &__tc_cs
, &__tc_dc
, &__tc_DL
, &__tc_dl
, &__tc_dm
,
83 &__tc_DO
, &__tc_do
, &__tc_eA
, &__tc_ed
, &__tc_ei
,
85 &__tc_ho
, &__tc_Ic
, &__tc_ic
, &__tc_im
, &__tc_Ip
,
87 &__tc_ip
, &__tc_k0
, &__tc_k1
, &__tc_k2
, &__tc_k3
,
89 &__tc_k4
, &__tc_k5
, &__tc_k6
, &__tc_k7
, &__tc_k8
,
91 &__tc_k9
, &__tc_kd
, &__tc_ke
, &__tc_kh
, &__tc_kl
,
93 &__tc_kr
, &__tc_ks
, &__tc_ku
, &__tc_LE
, &__tc_ll
,
95 &__tc_ma
, &__tc_mb
, &__tc_md
, &__tc_me
, &__tc_mh
,
97 &__tc_mk
, &__tc_mm
, &__tc_mo
, &__tc_mp
, &__tc_mr
,
99 &__tc_nd
, &__tc_nl
, &__tc_oc
, &__tc_op
, &_PC
,
101 &__tc_rc
, &__tc_RI
, &__tc_Sb
, &__tc_sc
, &__tc_se
,
103 &__tc_SF
, &__tc_Sf
, &__tc_sf
, &__tc_so
, &__tc_sp
,
105 &__tc_SR
, &__tc_sr
, &__tc_ta
, &__tc_te
, &__tc_ti
,
107 &__tc_uc
, &__tc_ue
, &__tc_UP
, &__tc_up
, &__tc_us
,
110 &__tc_vb
, &__tc_ve
, &__tc_vi
, &__tc_vs
113 &__tc_vb
, &__tc_ve
, &__tc_vi
, &__tc_vs
, &__tc_Xh
,
115 &__tc_Xl
, &__tc_Xo
, &__tc_Xr
, &__tc_Xt
, &__tc_Xv
116 #endif /* HAVE_WCHAR */
119 attr_t __mask_op
, __mask_me
, __mask_ue
, __mask_se
;
124 return _cursesi_setterm(type
, _cursesi_screen
);
128 _cursesi_setterm(char *type
, SCREEN
*screen
)
138 if (t_getent(&screen
->cursesi_genbuf
, type
) != 1) {
142 __CTRACE(__CTRACE_INIT
, "setterm: tty = %s\n", type
);
145 /* Try TIOCGWINSZ, and, if it fails, the termcap entry. */
146 if (ioctl(fileno(screen
->outfd
), TIOCGWINSZ
, &win
) != -1 &&
147 win
.ws_row
!= 0 && win
.ws_col
!= 0) {
148 screen
->LINES
= win
.ws_row
;
149 screen
->COLS
= win
.ws_col
;
155 screen
->LINES
= t_getnum(screen
->cursesi_genbuf
, "li");
156 screen
->COLS
= t_getnum(screen
->cursesi_genbuf
, "co");
161 /* POSIX 1003.2 requires that the environment override. */
162 if ((p
= getenv("LINES")) != NULL
)
163 screen
->LINES
= (int) strtol(p
, NULL
, 0);
164 if ((p
= getenv("COLUMNS")) != NULL
)
165 screen
->COLS
= (int) strtol(p
, NULL
, 0);
166 if ((p
= getenv("ESCDELAY")) != NULL
)
167 ESCDELAY
= (int) strtol(p
, NULL
, 0);
171 * Want cols > 4, otherwise things will fail.
173 if (screen
->COLS
<= 4)
176 LINES
= screen
->LINES
;
180 __CTRACE(__CTRACE_INIT
, "setterm: LINES = %d, COLS = %d\n",
184 if (zap(screen
) == ERR
) /* Get terminal description.*/
188 /* If we can't tab, we can't backtab, either. */
190 screen
->tc_bt
= NULL
;
193 * Test for cursor motion capability.
196 if (t_goto(NULL
, screen
->tc_cm
, 0, 0, cm_buff
, sizeof(cm_buff
) - 1) < 0) {
203 * set the pad char, only take the first char of the pc capability
204 * as this is all we can use.
206 screen
->padchar
= screen
->tc_pc
? screen
->tc_pc
[0] : 0;
208 /* Get full name of terminal */
210 strcpy(screen
->ttytype
, "dumb");
214 if (t_getterm(screen
->cursesi_genbuf
, 0, &limit
))
216 if ((tcptr
= malloc(limit
+ 1)) == NULL
)
218 if (t_getterm(screen
->cursesi_genbuf
, &tcptr
, 0) < 0)
220 __longname(tcptr
, screen
->ttytype
);
224 /* If no scrolling commands, no quick change. */
226 (screen
->tc_cs
== NULL
|| screen
->tc_ho
== NULL
||
227 (screen
->tc_SF
== NULL
&& screen
->tc_sf
== NULL
) ||
228 (screen
->tc_SR
== NULL
&& screen
->tc_sr
== NULL
)) &&
229 ((screen
->tc_AL
== NULL
&& screen
->tc_al
== NULL
) ||
230 (screen
->tc_DL
== NULL
&& screen
->tc_dl
== NULL
));
233 * Precalculate conflict info for color/attribute end commands.
236 screen
->mask_op
= __ATTRIBUTES
& ~__COLOR
;
238 screen
->mask_op
= WA_ATTRIBUTES
& ~__COLOR
;
239 #endif /* HAVE_WCHAR */
240 if (screen
->tc_op
!= NULL
) {
241 if (does_esc_m(screen
->tc_op
))
243 ~(__STANDOUT
| __UNDERSCORE
| __TERMATTR
);
245 if (screen
->tc_se
!= NULL
&&
246 !strcmp(screen
->tc_op
, screen
->tc_se
))
247 screen
->mask_op
&= ~__STANDOUT
;
248 if (screen
->tc_ue
!= NULL
&&
249 !strcmp(screen
->tc_op
, screen
->tc_ue
))
250 screen
->mask_op
&= ~__UNDERSCORE
;
251 if (screen
->tc_me
!= NULL
&&
252 !strcmp(screen
->tc_op
, screen
->tc_me
))
253 screen
->mask_op
&= ~__TERMATTR
;
257 * Assume that "me" turns off all attributes apart from ACS.
258 * It might turn off ACS, so check for that.
260 if (screen
->tc_me
!= NULL
&& does_ctrl_o(screen
->tc_me
))
263 screen
->mask_me
= __ALTCHARSET
;
265 /* Check what turning off the attributes also turns off */
267 screen
->mask_ue
= __ATTRIBUTES
& ~__UNDERSCORE
;
269 screen
->mask_ue
= WA_ATTRIBUTES
& ~__UNDERSCORE
;
270 #endif /* HAVE_WCHAR */
271 if (screen
->tc_ue
!= NULL
) {
272 if (does_esc_m(screen
->tc_ue
))
274 ~(__STANDOUT
| __TERMATTR
| __COLOR
);
276 if (screen
->tc_se
!= NULL
&&
277 !strcmp(screen
->tc_ue
, screen
->tc_se
))
278 screen
->mask_ue
&= ~__STANDOUT
;
279 if (screen
->tc_me
!= NULL
&&
280 !strcmp(screen
->tc_ue
, screen
->tc_me
))
281 screen
->mask_ue
&= ~__TERMATTR
;
282 if (screen
->tc_op
!= NULL
&&
283 !strcmp(screen
->tc_ue
, screen
->tc_op
))
284 screen
->mask_ue
&= ~__COLOR
;
288 screen
->mask_se
= __ATTRIBUTES
& ~__STANDOUT
;
290 screen
->mask_se
= WA_ATTRIBUTES
& ~__STANDOUT
;
291 #endif /* HAVE_WCHAR */
292 if (screen
->tc_se
!= NULL
) {
293 if (does_esc_m(screen
->tc_se
))
295 ~(__UNDERSCORE
| __TERMATTR
| __COLOR
);
297 if (screen
->tc_ue
!= NULL
&&
298 !strcmp(screen
->tc_se
, screen
->tc_ue
))
299 screen
->mask_se
&= ~__UNDERSCORE
;
300 if (screen
->tc_me
!= NULL
&&
301 !strcmp(screen
->tc_se
, screen
->tc_me
))
302 screen
->mask_se
&= ~__TERMATTR
;
303 if (screen
->tc_op
!= NULL
&&
304 !strcmp(screen
->tc_se
, screen
->tc_op
))
305 screen
->mask_se
&= ~__COLOR
;
309 return (unknown
? ERR
: OK
);
313 * _cursesi_resetterm --
314 * Copy the terminal instance data for the given screen to the global
318 _cursesi_resetterm(SCREEN
*screen
)
320 char ***sp
, **scr_sp
;
321 int **vp
, *scr_vp
, i
;
324 LINES
= screen
->LINES
;
327 /* reset terminal capabilities */
329 scr_fp
= &screen
->tc_am
;
330 for (i
= 0; i
< screen
->flag_count
; i
++)
331 *(*fp
++) = *scr_fp
++;
334 scr_vp
= &screen
->tc_pa
;
335 for (i
= 0; i
< screen
->int_count
; i
++)
336 *(*vp
++) = *scr_vp
++;
339 scr_sp
= &screen
->tc_AB
;
340 for (i
= 0; i
< screen
->str_count
; i
++)
341 *(*sp
++) = *scr_sp
++;
346 PC
= screen
->padchar
;
348 __noqch
= screen
->noqch
;
349 __mask_op
= screen
->mask_op
;
350 __mask_me
= screen
->mask_me
;
351 __mask_ue
= screen
->mask_ue
;
352 __mask_se
= screen
->mask_se
;
357 * Gets all the terminal flags from the termcap database.
362 const char *nampstr
, *namp
;
372 namp
= "ambsccdaeohchlinmimsncnsosulutxbxnxtxsxx";
374 screen
->flag_count
= 0;
377 *(tmp
+ 1) = *(namp
+ 1);
378 *fp
++ = t_getflag(screen
->cursesi_genbuf
, tmp
);
380 __CTRACE(__CTRACE_INIT
, "%2.2s = %s\n", namp
,
381 fp
[-1] ? "TRUE" : "FALSE");
384 screen
->flag_count
++;
388 screen
->int_count
= 0;
391 *(tmp
+ 1) = *(namp
+ 1);
392 *vp
++ = t_getnum(screen
->cursesi_genbuf
, tmp
);
394 __CTRACE(__CTRACE_INIT
, "%2.2s = %d\n", namp
, vp
[-1]);
401 nampstr
= "ABacaeAFALalasbcblbtcdceclcmcrcsdcDLdldmDOdoeAedeihoIcicimIpipk0k1k2k3k4k5k6k7k8k9kdkekhklkrkskuLEllmambmdmemhmkmmmompmrndnlocoppcrcRISbscseSFSfsfsospSRsrtatetiucueUPupusvbvevivs";
403 nampstr
= "ABacaeAFALalasbcblbtcdceclcmcrcsdcDLdldmDOdoeAedeihoIcicimIpipk0k1k2k3k4k5k6k7k8k9kdkekhklkrkskuLEllmambmdmemhmkmmmompmrndnlocoppcrcRISbscseSFSfsfsospSRsrtatetiucueUPupusvbvevivsXhXlXoXrXtXv";
404 #endif /* HAVE_WCHAR */
408 screen
->str_count
= 0;
411 *(tmp
+ 1) = *(namp
+ 1);
412 *sp
++ = t_agetstr(screen
->cursesi_genbuf
, tmp
);
415 __CTRACE(__CTRACE_INIT
, "%2.2s = NULL\n", namp
);
417 __CTRACE(__CTRACE_INIT
, "%2.2s = \"", namp
);
418 for (cp
= sp
[-1]; *cp
; cp
++)
419 __CTRACE(__CTRACE_INIT
, "%s", unctrl(*cp
));
420 __CTRACE(__CTRACE_INIT
, "\"\n");
427 screen
->tc_so
= screen
->tc_se
= NULL
;
429 if (t_getnum(screen
->cursesi_genbuf
, "sg") > 0)
430 screen
->tc_so
= NULL
;
431 if (t_getnum(screen
->cursesi_genbuf
, "ug") > 0)
432 screen
->tc_us
= NULL
;
433 if (!screen
->tc_so
&& screen
->tc_us
) {
434 screen
->tc_so
= screen
->tc_us
;
435 screen
->tc_se
= screen
->tc_ue
;
444 * Return a capability from termcap.
449 return (t_agetstr(_cursesi_screen
->cursesi_genbuf
, name
));
454 * A hack for xterm-like terminals where "\E[m" or "\E[0m" will turn off
455 * other attributes, so we check for this in the capability passed to us.
456 * Note that we can't just do simple string comparison, as the capability
457 * may contain multiple, ';' separated sequence parts.
460 does_esc_m(char *cap
)
470 __CTRACE(__CTRACE_INIT
, "does_esc_m: Checking %s\n", cap
);
472 /* Is it just "\E[m" or "\E[0m"? */
473 if (!strcmp(cap
, "\x1b[m") || !strcmp(cap
, "\x1b[0m"))
476 /* Does it contain a "\E[...m" sequence? */
481 while (*capptr
!= 0) {
483 /* Start of sequence */
485 if (!strncmp(capptr
, "\x1b[", 2)) {
495 /* Looking for '0' */
499 else if (*capptr
> '0' && *capptr
<= '9')
501 else if (*capptr
!= ';')
504 /* Some other number */
508 else if (!(*capptr
>= '0' && *capptr
<= '9'))
515 else if (!((*capptr
>= '0' && *capptr
<= '9') ||
529 * A hack for vt100/xterm-like terminals where the "me" capability also
530 * unsets acs (i.e. it contains the character '\017').
533 does_ctrl_o(char *cap
)
538 __CTRACE(__CTRACE_INIT
, "does_ctrl_o: Looping on %s\n", capptr
);
540 while (*capptr
!= 0) {
541 if (*capptr
== '\x0f')