1 /* $NetBSD: termcap.c,v 1.10 2010/10/12 12:49:27 christos Exp $ */
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: termcap.c,v 1.10 2010/10/12 12:49:27 christos Exp $");
38 #include <term_private.h>
44 #include "termcap_map.c"
45 #include "termcap_hash.c"
52 tgetent(__unused
char *bp
, const char *name
)
55 static TERMINAL
*last
= NULL
;
57 _DIAGASSERT(name
!= NULL
);
59 /* Free the old term */
65 if (setupterm(name
, STDOUT_FILENO
, &errret
) != 0)
71 UP
= __UNCONST(cursor_up
);
72 BC
= __UNCONST(cursor_left
);
77 tgetflag(const char *id
)
83 _DIAGASSERT(id
!= NULL
);
88 ind
= _t_flaghash((const unsigned char *)id
, strlen(id
));
89 if (ind
<= __arraycount(_ti_cap_flagids
)) {
90 if (strcmp(id
, _ti_cap_flagids
[ind
].id
) == 0)
91 return cur_term
->flags
[_ti_cap_flagids
[ind
].ti
];
93 for (i
= 0; i
< cur_term
->_nuserdefs
; i
++) {
94 ud
= &cur_term
->_userdefs
[i
];
95 if (ud
->type
== 'f' && strcmp(ud
->id
, id
) == 0)
102 tgetnum(const char *id
)
109 _DIAGASSERT(id
!= NULL
);
111 if (cur_term
== NULL
)
114 ind
= _t_numhash((const unsigned char *)id
, strlen(id
));
115 if (ind
<= __arraycount(_ti_cap_numids
)) {
116 te
= &_ti_cap_numids
[ind
];
117 if (strcmp(id
, te
->id
) == 0) {
118 if (!VALID_NUMERIC(cur_term
->nums
[te
->ti
]))
119 return ABSENT_NUMERIC
;
120 return cur_term
->nums
[te
->ti
];
123 for (i
= 0; i
< cur_term
->_nuserdefs
; i
++) {
124 ud
= &cur_term
->_userdefs
[i
];
125 if (ud
->type
== 'n' && strcmp(ud
->id
, id
) == 0) {
126 if (!VALID_NUMERIC(ud
->num
))
127 return ABSENT_NUMERIC
;
135 tgetstr(const char *id
, char **area
)
142 _DIAGASSERT(id
!= NULL
);
144 if (cur_term
== NULL
)
148 ind
= _t_strhash((const unsigned char *)id
, strlen(id
));
149 if (ind
<= __arraycount(_ti_cap_strids
)) {
150 if (strcmp(id
, _ti_cap_strids
[ind
].id
) == 0) {
151 str
= cur_term
->strs
[_ti_cap_strids
[ind
].ti
];
157 for (i
= 0; i
< cur_term
->_nuserdefs
; i
++) {
158 ud
= &cur_term
->_userdefs
[i
];
159 if (ud
->type
== 's' && strcmp(ud
->id
, id
) == 0)
164 * We should fix sgr0(me) as it has a slightly different meaning
167 if (str
!= NULL
&& area
!= NULL
&& *area
!= NULL
) {
171 *area
+= strlen(*area
) + 1;
175 return __UNCONST(str
);
179 tgoto(const char *cm
, int destcol
, int destline
)
182 _DIAGASSERT(cm
!= NULL
);
183 return vtparm(cm
, destline
, destcol
);
187 flagname(const char *key
)
191 idx
= _t_flaghash((const unsigned char *)key
, strlen(key
));
192 if (idx
<= __arraycount(_ti_cap_flagids
) &&
193 strcmp(key
, _ti_cap_flagids
[idx
].id
) == 0)
194 return _ti_flagid(_ti_cap_flagids
[idx
].ti
);
199 numname(const char *key
)
203 idx
= _t_numhash((const unsigned char *)key
, strlen(key
));
204 if (idx
<= __arraycount(_ti_cap_numids
) &&
205 strcmp(key
, _ti_cap_numids
[idx
].id
) == 0)
206 return _ti_numid(_ti_cap_numids
[idx
].ti
);
211 strname(const char *key
)
215 idx
= _t_strhash((const unsigned char *)key
, strlen(key
));
216 if (idx
<= __arraycount(_ti_cap_strids
) &&
217 strcmp(key
, _ti_cap_strids
[idx
].id
) == 0)
218 return _ti_strid(_ti_cap_strids
[idx
].ti
);
220 if (strcmp(key
, "tc") == 0)
226 /* We don't currently map %> %B %D
227 * That means no conversion for regent100, hz1500, act4, act5, mime terms. */
229 strval(const char *val
)
236 len
= 1024; /* no single string should be bigger */
237 info
= ip
= malloc(len
);
244 /* Set ps and pe to point to the start and end of the padding */
245 if (isdigit((unsigned char)*val
)) {
247 isdigit((unsigned char)*val
) || *val
== '.';
259 for (; *val
!= '\0'; val
++) {
273 switch (c
= *(++val
)) {
288 /* Hope it matches a terminfo command. */
296 /* \E\ is valid termcap.
297 * We need to escape the final \ for terminfo. */
298 if (l
> 2 && info
[l
- 1] == '\\' &&
299 (info
[l
- 2] != '\\' && info
[l
- 2] != '^'))
306 /* Add our padding at the end. */
333 static DEF_INFO def_infos
[] = {
348 char *info
, *ip
, *token
, *val
, *p
, tok
[3];
350 size_t len
, lp
, nl
, vl
, rl
;
351 int defs
[__arraycount(def_infos
)], fv
;
353 _DIAGASSERT(cap
!= NULL
);
355 len
= strlen(cap
) * 2;
356 len
+= __arraycount(def_infos
) * (5 + 4 + 3); /* reserve for defs */
357 info
= ip
= malloc(len
);
361 memset(defs
, 0, sizeof(defs
));
364 for (token
= _ti_get_token(&cap
, ':');
366 token
= _ti_get_token(&cap
, ':'))
368 if (token
[0] == '\0')
373 if (token
[1] != '\0') {
377 if (token
[2] == '\0') {
378 name
= flagname(tok
);
380 } else if (token
[2] == '#') {
383 } else if (token
[2] == '=') {
385 val
= strval(token
+ 2);
390 /* If not matched we may need to convert padding still. */
392 p
= strchr(name
, '=');
400 /* See if this sets a default. */
401 for (nl
= 0; nl
< __arraycount(def_infos
); nl
++) {
402 if (strcmp(name
, def_infos
[nl
].name
) == 0) {
413 rl
= nl
+ vl
+ 3; /* , \0 */
420 p
= realloc(info
, len
);
441 /* Add any defaults not set above. */
442 for (nl
= 0; nl
< __arraycount(def_infos
); nl
++) {
446 strcpy(ip
, def_infos
[nl
].name
);
447 ip
+= strlen(def_infos
[nl
].name
);
449 strcpy(ip
, def_infos
[nl
].cap
);
450 ip
+= strlen(def_infos
[nl
].cap
);