1 /**************************************************************************** 2 * Copyright (c) 1998-2001,2002 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29 /**************************************************************************** 30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32 * * 33 * some of the code in here was contributed by: * 34 * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) * 35 ****************************************************************************/ 36 37 /* $FreeBSD$ */ 38 39 #define __INTERNAL_CAPS_VISIBLE 40 #include <curses.priv.h> 41 42 #include <termcap.h> 43 #include <tic.h> 44 #include <ctype.h> 45 46 #include <term_entry.h> 47 48 MODULE_ID("$Id: lib_termcap.c,v 1.43 2002/05/25 12:24:13 tom Exp $") 49 50 #define CSI 233 51 #define ESC 033 /* ^[ */ 52 #define L_BRACK '[' 53 #define SHIFT_OUT 017 /* ^N */ 54 55 NCURSES_EXPORT_VAR(char *) UP = 0; 56 NCURSES_EXPORT_VAR(char *) BC = 0; 57 58 #ifdef FREEBSD_NATIVE 59 #undef GCC_UNUSED 60 #define GCC_UNUSED 61 extern char _nc_termcap[]; /* buffer to copy out */ 62 #endif 63 64 static char *fix_me = 0; 65 66 static char * 67 set_attribute_9(int flag) 68 { 69 const char *result; 70 71 if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0) 72 result = ""; 73 return strdup(result); 74 } 75 76 static int 77 is_csi(char *s) 78 { 79 if (UChar(s[0]) == CSI) 80 return 1; 81 else if (s[0] == ESC && s[1] == L_BRACK) 82 return 2; 83 return 0; 84 } 85 86 static char * 87 skip_zero(char *s) 88 { 89 if (s[0] == '0') { 90 if (s[1] == ';') 91 s += 2; 92 else if (isalpha(UChar(s[1]))) 93 s += 1; 94 } 95 return s; 96 } 97 98 static bool 99 similar_sgr(char *a, char *b) 100 { 101 int csi_a = is_csi(a); 102 int csi_b = is_csi(b); 103 104 if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) { 105 a += csi_a; 106 b += csi_b; 107 if (*a != *b) { 108 a = skip_zero(a); 109 b = skip_zero(b); 110 } 111 } 112 return strcmp(a, b) == 0; 113 } 114 115 /*************************************************************************** 116 * 117 * tgetent(bufp, term) 118 * 119 * In termcap, this function reads in the entry for terminal `term' into the 120 * buffer pointed to by bufp. It must be called before any of the functions 121 * below are called. 122 * In this terminfo emulation, tgetent() simply calls setupterm() (which 123 * does a bit more than tgetent() in termcap does), and returns its return 124 * value (1 if successful, 0 if no terminal with the given name could be 125 * found, or -1 if no terminal descriptions have been installed on the 126 * system). The bufp argument is ignored. 127 * 128 ***************************************************************************/ 129 130 NCURSES_EXPORT(int) 131 tgetent(char *bufp GCC_UNUSED, const char *name) 132 { 133 int errcode; 134 135 T((T_CALLED("tgetent()"))); 136 137 setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode); 138 139 PC = 0; 140 UP = 0; 141 BC = 0; 142 fix_me = 0; 143 144 if (errcode == 1) { 145 146 if (cursor_left) 147 if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) 148 backspace_if_not_bs = cursor_left; 149 150 /* we're required to export these */ 151 if (pad_char != NULL) 152 PC = pad_char[0]; 153 if (cursor_up != NULL) 154 UP = cursor_up; 155 if (backspace_if_not_bs != NULL) 156 BC = backspace_if_not_bs; 157 158 /* 159 * While 'sgr0' is the "same" as termcap 'me', there is a compatibility 160 * issue. The sgr/sgr0 capabilities include setting/clearing alternate 161 * character set mode. A termcap application cannot use sgr, so sgr0 162 * strings that reset alternate character set mode will be 163 * misinterpreted. Here, we remove those from the more common 164 * ISO/ANSI/VT100 entries, which have sgr0 agreeing with sgr. 165 */ 166 if (exit_attribute_mode != 0 167 && set_attributes != 0) { 168 char *on = set_attribute_9(1); 169 char *off = set_attribute_9(0); 170 char *tmp; 171 size_t i, j, k; 172 173 if (similar_sgr(off, exit_attribute_mode) 174 && !similar_sgr(off, on)) { 175 TR(TRACE_DATABASE, ("adjusting sgr0 : %s", _nc_visbuf(off))); 176 FreeIfNeeded(fix_me); 177 fix_me = off; 178 for (i = 0; off[i] != '\0'; ++i) { 179 if (on[i] != off[i]) { 180 j = strlen(off); 181 k = strlen(on); 182 while (j != 0 183 && k != 0 184 && off[j - 1] == on[k - 1]) { 185 --j, --k; 186 } 187 while (off[j] != '\0') { 188 off[i++] = off[j++]; 189 } 190 off[i] = '\0'; 191 break; 192 } 193 } 194 /* SGR 10 would reset to normal font */ 195 if ((i = is_csi(off)) != 0 196 && off[strlen(off) - 1] == 'm') { 197 tmp = skip_zero(off + i); 198 if (tmp[0] == '1' 199 && skip_zero(tmp + 1) != tmp + 1) { 200 i = tmp - off; 201 if (off[i - 1] == ';') 202 i--; 203 j = skip_zero(tmp + 1) - off; 204 while (off[j] != '\0') { 205 off[i++] = off[j++]; 206 } 207 off[i] = '\0'; 208 } 209 } 210 TR(TRACE_DATABASE, ("...adjusted me : %s", _nc_visbuf(fix_me))); 211 if (!strcmp(fix_me, exit_attribute_mode)) { 212 TR(TRACE_DATABASE, ("...same result, discard")); 213 free(fix_me); 214 fix_me = 0; 215 } 216 } 217 free(on); 218 } 219 220 (void) baudrate(); /* sets ospeed as a side-effect */ 221 222 /* LINT_PREPRO 223 #if 0*/ 224 #include <capdefaults.c> 225 /* LINT_PREPRO 226 #endif*/ 227 228 } 229 230 #ifdef FREEBSD_NATIVE 231 /* 232 * This is a REALLY UGLY hack. Basically, if we originate with 233 * a termcap source, try and copy it out. 234 */ 235 if (bufp && _nc_termcap[0]) 236 strncpy(bufp, _nc_termcap, 1024); 237 #endif 238 239 returnCode(errcode); 240 } 241 242 /*************************************************************************** 243 * 244 * tgetflag(str) 245 * 246 * Look up boolean termcap capability str and return its value (TRUE=1 if 247 * present, FALSE=0 if not). 248 * 249 ***************************************************************************/ 250 251 NCURSES_EXPORT(int) 252 tgetflag(NCURSES_CONST char *id) 253 { 254 int i; 255 256 T((T_CALLED("tgetflag(%s)"), id)); 257 if (cur_term != 0) { 258 TERMTYPE *tp = &(cur_term->type); 259 for_each_boolean(i, tp) { 260 const char *capname = ExtBoolname(tp, i, boolcodes); 261 if (!strncmp(id, capname, 2)) { 262 /* setupterm forces invalid booleans to false */ 263 returnCode(tp->Booleans[i]); 264 } 265 } 266 } 267 returnCode(0); /* Solaris does this */ 268 } 269 270 /*************************************************************************** 271 * 272 * tgetnum(str) 273 * 274 * Look up numeric termcap capability str and return its value, or -1 if 275 * not given. 276 * 277 ***************************************************************************/ 278 279 NCURSES_EXPORT(int) 280 tgetnum(NCURSES_CONST char *id) 281 { 282 int i; 283 284 T((T_CALLED("tgetnum(%s)"), id)); 285 if (cur_term != 0) { 286 TERMTYPE *tp = &(cur_term->type); 287 for_each_number(i, tp) { 288 const char *capname = ExtNumname(tp, i, numcodes); 289 if (!strncmp(id, capname, 2)) { 290 if (!VALID_NUMERIC(tp->Numbers[i])) 291 returnCode(ABSENT_NUMERIC); 292 returnCode(tp->Numbers[i]); 293 } 294 } 295 } 296 returnCode(ABSENT_NUMERIC); 297 } 298 299 /*************************************************************************** 300 * 301 * tgetstr(str, area) 302 * 303 * Look up string termcap capability str and return a pointer to its value, 304 * or NULL if not given. 305 * 306 ***************************************************************************/ 307 308 NCURSES_EXPORT(char *) 309 tgetstr(NCURSES_CONST char *id, char **area) 310 { 311 int i; 312 char *result = NULL; 313 314 T((T_CALLED("tgetstr(%s,%p)"), id, area)); 315 if (cur_term != 0) { 316 TERMTYPE *tp = &(cur_term->type); 317 for_each_string(i, tp) { 318 const char *capname = ExtStrname(tp, i, strcodes); 319 if (!strncmp(id, capname, 2)) { 320 result = tp->Strings[i]; 321 TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); 322 /* setupterm forces canceled strings to null */ 323 if (VALID_STRING(result)) { 324 if (result == exit_attribute_mode 325 && fix_me != 0) { 326 result = fix_me; 327 TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); 328 } 329 if (area != 0 330 && *area != 0) { 331 (void) strcpy(*area, result); 332 *area += strlen(*area) + 1; 333 } 334 } 335 break; 336 } 337 } 338 } 339 returnPtr(result); 340 } 341