lib_termcap.c revision 97052
1158115Sume/**************************************************************************** 2158115Sume * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc. * 3158115Sume * * 4158115Sume * Permission is hereby granted, free of charge, to any person obtaining a * 5158115Sume * copy of this software and associated documentation files (the * 6158115Sume * "Software"), to deal in the Software without restriction, including * 7158115Sume * without limitation the rights to use, copy, modify, merge, publish, * 8158115Sume * distribute, distribute with modifications, sublicense, and/or sell * 9158115Sume * copies of the Software, and to permit persons to whom the Software is * 10158115Sume * furnished to do so, subject to the following conditions: * 11158115Sume * * 12158115Sume * The above copyright notice and this permission notice shall be included * 13158115Sume * in all copies or substantial portions of the Software. * 14158115Sume * * 15158115Sume * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16158115Sume * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17158115Sume * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18158115Sume * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19158115Sume * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20158115Sume * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21158115Sume * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22158115Sume * * 23158115Sume * Except as contained in this notice, the name(s) of the above copyright * 24158115Sume * holders shall not be used in advertising or otherwise to promote the * 25158115Sume * sale, use or other dealings in this Software without prior written * 26158115Sume * authorization. * 27158115Sume ****************************************************************************/ 28158115Sume 29158115Sume/**************************************************************************** 30158115Sume * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31158115Sume * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32158115Sume * * 33158115Sume * some of the code in here was contributed by: * 34158115Sume * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) * 35158115Sume ****************************************************************************/ 36158115Sume 37158115Sume/* $FreeBSD: head/contrib/ncurses/ncurses/tinfo/lib_termcap.c 97052 2002-05-21 05:38:04Z peter $ */ 38158115Sume 39158115Sume#include <curses.priv.h> 40158115Sume 41158115Sume#include <termcap.h> 42158115Sume#include <tic.h> 43158115Sume#include <ctype.h> 44158115Sume 45158115Sume#define __INTERNAL_CAPS_VISIBLE 46158115Sume#include <term_entry.h> 47158115Sume 48158115SumeMODULE_ID("$Id: lib_termcap.c,v 1.42 2001/09/22 19:17:31 tom Exp $") 49158115Sume 50158115Sume#define CSI 233 51158115Sume#define ESC 033 /* ^[ */ 52158115Sume#define L_BRACK '[' 53158115Sume#define SHIFT_OUT 017 /* ^N */ 54158115Sume 55158115SumeNCURSES_EXPORT_VAR(char *) UP = 0; 56158115SumeNCURSES_EXPORT_VAR(char *) BC = 0; 57158115Sume 58158115Sume#ifdef FREEBSD_NATIVE 59158115Sume#undef GCC_UNUSED 60158115Sume#define GCC_UNUSED 61158115Sumeextern char _nc_termcap[]; /* buffer to copy out */ 62158115Sume#endif 63158115Sume 64158115Sumestatic char *fix_me = 0; 65158115Sume 66158115Sumestatic char * 67158115Sumeset_attribute_9(int flag) 68158115Sume{ 69158115Sume const char *result; 70158115Sume 71158115Sume if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0) 72158115Sume result = ""; 73158115Sume return strdup(result); 74158115Sume} 75158115Sume 76158115Sumestatic int 77158115Sumeis_csi(char *s) 78158115Sume{ 79158115Sume if (UChar(s[0]) == CSI) 80158115Sume return 1; 81158115Sume else if (s[0] == ESC && s[1] == L_BRACK) 82158115Sume return 2; 83158115Sume return 0; 84158115Sume} 85158115Sume 86158115Sumestatic char * 87158115Sumeskip_zero(char *s) 88158115Sume{ 89158115Sume if (s[0] == '0') { 90158115Sume if (s[1] == ';') 91158115Sume s += 2; 92158115Sume else if (isalpha(UChar(s[1]))) 93158115Sume s += 1; 94158115Sume } 95158115Sume return s; 96158115Sume} 97158115Sume 98158115Sumestatic bool 99158115Sumesimilar_sgr(char *a, char *b) 100158115Sume{ 101158115Sume int csi_a = is_csi(a); 102158115Sume int csi_b = is_csi(b); 103158115Sume 104158115Sume if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) { 105158115Sume a += csi_a; 106158115Sume b += csi_b; 107158115Sume if (*a != *b) { 108158115Sume a = skip_zero(a); 109158115Sume b = skip_zero(b); 110158115Sume } 111158115Sume } 112158115Sume return strcmp(a, b) == 0; 113158115Sume} 114158115Sume 115158115Sume/*************************************************************************** 116158115Sume * 117158115Sume * tgetent(bufp, term) 118158115Sume * 119158115Sume * In termcap, this function reads in the entry for terminal `term' into the 120158115Sume * buffer pointed to by bufp. It must be called before any of the functions 121158115Sume * below are called. 122158115Sume * In this terminfo emulation, tgetent() simply calls setupterm() (which 123158115Sume * does a bit more than tgetent() in termcap does), and returns its return 124158115Sume * value (1 if successful, 0 if no terminal with the given name could be 125158115Sume * found, or -1 if no terminal descriptions have been installed on the 126158115Sume * system). The bufp argument is ignored. 127158115Sume * 128158115Sume ***************************************************************************/ 129158115Sume 130158115SumeNCURSES_EXPORT(int) 131158115Sumetgetent(char *bufp GCC_UNUSED, const char *name) 132158115Sume{ 133158115Sume int errcode; 134158115Sume 135158115Sume T((T_CALLED("tgetent()"))); 136158115Sume 137158115Sume setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode); 138158115Sume 139158115Sume PC = 0; 140158115Sume UP = 0; 141158115Sume BC = 0; 142158115Sume fix_me = 0; 143158115Sume 144158115Sume if (errcode == 1) { 145158115Sume 146158115Sume if (cursor_left) 147158115Sume if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) 148158115Sume backspace_if_not_bs = cursor_left; 149158115Sume 150158115Sume /* we're required to export these */ 151158115Sume if (pad_char != NULL) 152158115Sume PC = pad_char[0]; 153158115Sume if (cursor_up != NULL) 154158257Sume UP = cursor_up; 155158115Sume if (backspace_if_not_bs != NULL) 156158115Sume BC = backspace_if_not_bs; 157158115Sume 158158257Sume /* 159158115Sume * While 'sgr0' is the "same" as termcap 'me', there is a compatibility 160158115Sume * issue. The sgr/sgr0 capabilities include setting/clearing alternate 161158115Sume * character set mode. A termcap application cannot use sgr, so sgr0 162158115Sume * strings that reset alternate character set mode will be 163158115Sume * misinterpreted. Here, we remove those from the more common 164158115Sume * ISO/ANSI/VT100 entries, which have sgr0 agreeing with sgr. 165158257Sume */ 166158257Sume if (exit_attribute_mode != 0 167158115Sume && set_attributes != 0) { 168158115Sume char *on = set_attribute_9(1); 169158115Sume char *off = set_attribute_9(0); 170158115Sume char *tmp; 171158115Sume size_t i, j, k; 172158115Sume 173158115Sume if (similar_sgr(off, exit_attribute_mode) 174158115Sume && !similar_sgr(off, on)) { 175158115Sume TR(TRACE_DATABASE, ("adjusting sgr0 : %s", _nc_visbuf(off))); 176158115Sume FreeIfNeeded(fix_me); 177158115Sume fix_me = off; 178158115Sume for (i = 0; off[i] != '\0'; ++i) { 179158115Sume if (on[i] != off[i]) { 180158115Sume j = strlen(off); 181158115Sume k = strlen(on); 182158115Sume while (j != 0 183158115Sume && k != 0 184158115Sume && off[j - 1] == on[k - 1]) { 185158115Sume --j, --k; 186158115Sume } 187158115Sume while (off[j] != '\0') { 188158115Sume off[i++] = off[j++]; 189158115Sume } 190158115Sume off[i] = '\0'; 191158115Sume break; 192158115Sume } 193158115Sume } 194158115Sume /* SGR 10 would reset to normal font */ 195158115Sume if ((i = is_csi(off)) != 0 196158115Sume && off[strlen(off) - 1] == 'm') { 197158115Sume tmp = skip_zero(off + i); 198158115Sume if (tmp[0] == '1' 199158115Sume && skip_zero(tmp + 1) != tmp + 1) { 200158115Sume i = tmp - off; 201158115Sume if (off[i - 1] == ';') 202158115Sume i--; 203158115Sume j = skip_zero(tmp + 1) - off; 204158115Sume while (off[j] != '\0') { 205158115Sume off[i++] = off[j++]; 206158115Sume } 207158115Sume off[i] = '\0'; 208158115Sume } 209158115Sume } 210158115Sume TR(TRACE_DATABASE, ("...adjusted me : %s", _nc_visbuf(fix_me))); 211158115Sume if (!strcmp(fix_me, exit_attribute_mode)) { 212158115Sume TR(TRACE_DATABASE, ("...same result, discard")); 213158115Sume free(fix_me); 214158115Sume fix_me = 0; 215158115Sume } 216158115Sume } 217158115Sume free(on); 218158115Sume } 219158115Sume 220158115Sume (void) baudrate(); /* sets ospeed as a side-effect */ 221158115Sume 222158115Sume/* LINT_PREPRO 223158115Sume#if 0*/ 224158115Sume#include <capdefaults.c> 225158115Sume/* LINT_PREPRO 226158115Sume#endif*/ 227158115Sume 228158115Sume } 229158115Sume 230158115Sume#ifdef FREEBSD_NATIVE 231158115Sume /* 232158115Sume * This is a REALLY UGLY hack. Basically, if we originate with 233158115Sume * a termcap source, try and copy it out. 234158115Sume */ 235158115Sume if (bufp && _nc_termcap[0]) 236158115Sume strncpy(bufp, _nc_termcap, 1024); 237158115Sume#endif 238158115Sume 239158115Sume returnCode(errcode); 240158115Sume} 241158115Sume 242158115Sume/*************************************************************************** 243158115Sume * 244158115Sume * tgetflag(str) 245158115Sume * 246158115Sume * Look up boolean termcap capability str and return its value (TRUE=1 if 247158115Sume * present, FALSE=0 if not). 248158115Sume * 249158115Sume ***************************************************************************/ 250158115Sume 251158115SumeNCURSES_EXPORT(int) 252158115Sumetgetflag(NCURSES_CONST char *id) 253158115Sume{ 254158115Sume int i; 255158115Sume 256158115Sume T((T_CALLED("tgetflag(%s)"), id)); 257158115Sume if (cur_term != 0) { 258158115Sume TERMTYPE *tp = &(cur_term->type); 259158115Sume for_each_boolean(i, tp) { 260158115Sume const char *capname = ExtBoolname(tp, i, boolcodes); 261158115Sume if (!strncmp(id, capname, 2)) { 262158115Sume /* setupterm forces invalid booleans to false */ 263158115Sume returnCode(tp->Booleans[i]); 264158115Sume } 265158115Sume } 266158115Sume } 267158115Sume returnCode(0); /* Solaris does this */ 268158115Sume} 269158115Sume 270158115Sume/*************************************************************************** 271158115Sume * 272158115Sume * tgetnum(str) 273158115Sume * 274158115Sume * Look up numeric termcap capability str and return its value, or -1 if 275158115Sume * not given. 276158115Sume * 277158115Sume ***************************************************************************/ 278158115Sume 279158115SumeNCURSES_EXPORT(int) 280158115Sumetgetnum(NCURSES_CONST char *id) 281158115Sume{ 282158115Sume int i; 283158115Sume 284158115Sume T((T_CALLED("tgetnum(%s)"), id)); 285158115Sume if (cur_term != 0) { 286158115Sume TERMTYPE *tp = &(cur_term->type); 287158115Sume for_each_number(i, tp) { 288158115Sume const char *capname = ExtNumname(tp, i, numcodes); 289158115Sume if (!strncmp(id, capname, 2)) { 290158115Sume if (!VALID_NUMERIC(tp->Numbers[i])) 291158115Sume returnCode(ABSENT_NUMERIC); 292158115Sume returnCode(tp->Numbers[i]); 293158115Sume } 294158115Sume } 295158115Sume } 296158115Sume returnCode(ABSENT_NUMERIC); 297158115Sume} 298158115Sume 299158115Sume/*************************************************************************** 300158115Sume * 301158115Sume * tgetstr(str, area) 302158115Sume * 303158115Sume * Look up string termcap capability str and return a pointer to its value, 304158115Sume * or NULL if not given. 305158115Sume * 306158115Sume ***************************************************************************/ 307158115Sume 308158115SumeNCURSES_EXPORT(char *) 309158115Sumetgetstr(NCURSES_CONST char *id, char **area) 310158115Sume{ 311158115Sume int i; 312158115Sume char *result = NULL; 313158115Sume 314158115Sume T((T_CALLED("tgetstr(%s,%p)"), id, area)); 315158115Sume if (cur_term != 0) { 316158115Sume TERMTYPE *tp = &(cur_term->type); 317158115Sume for_each_string(i, tp) { 318158115Sume const char *capname = ExtStrname(tp, i, strcodes); 319158115Sume if (!strncmp(id, capname, 2)) { 320158115Sume result = tp->Strings[i]; 321158115Sume TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); 322158115Sume /* setupterm forces canceled strings to null */ 323158115Sume if (VALID_STRING(result)) { 324158115Sume if (result == exit_attribute_mode 325158115Sume && fix_me != 0) { 326158115Sume result = fix_me; 327158115Sume TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); 328158115Sume } 329158115Sume if (area != 0 330158115Sume && *area != 0) { 331158115Sume (void) strcpy(*area, result); 332158115Sume *area += strlen(*area) + 1; 333158115Sume } 334158115Sume } 335158115Sume break; 336158115Sume } 337158115Sume } 338158115Sume } 339158115Sume returnPtr(result); 340158115Sume} 341158115Sume