10e3d5408SPeter Wemm /**************************************************************************** 2a17d2cb2SPeter Wemm * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc. * 30e3d5408SPeter Wemm * * 40e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a * 50e3d5408SPeter Wemm * copy of this software and associated documentation files (the * 60e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including * 70e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, * 80e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell * 90e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is * 100e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: * 110e3d5408SPeter Wemm * * 120e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included * 130e3d5408SPeter Wemm * in all copies or substantial portions of the Software. * 140e3d5408SPeter Wemm * * 150e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 160e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 170e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 180e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 190e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 200e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 210e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 220e3d5408SPeter Wemm * * 230e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright * 240e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the * 250e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written * 260e3d5408SPeter Wemm * authorization. * 270e3d5408SPeter Wemm ****************************************************************************/ 280e3d5408SPeter Wemm 290e3d5408SPeter Wemm /**************************************************************************** 300e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 310e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32a17d2cb2SPeter Wemm * * 33a17d2cb2SPeter Wemm * some of the code in here was contributed by: * 34a17d2cb2SPeter Wemm * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) * 350e3d5408SPeter Wemm ****************************************************************************/ 360e3d5408SPeter Wemm 375bd21f8aSPeter Wemm /* $FreeBSD$ */ 385bd21f8aSPeter Wemm 390e3d5408SPeter Wemm #include <curses.priv.h> 400e3d5408SPeter Wemm 410e3d5408SPeter Wemm #include <termcap.h> 420e3d5408SPeter Wemm #include <tic.h> 43a17d2cb2SPeter Wemm #include <ctype.h> 440e3d5408SPeter Wemm 450e3d5408SPeter Wemm #define __INTERNAL_CAPS_VISIBLE 460e3d5408SPeter Wemm #include <term_entry.h> 470e3d5408SPeter Wemm 48a17d2cb2SPeter Wemm MODULE_ID("$Id: lib_termcap.c,v 1.42 2001/09/22 19:17:31 tom Exp $") 490e3d5408SPeter Wemm 50a17d2cb2SPeter Wemm #define CSI 233 51a17d2cb2SPeter Wemm #define ESC 033 /* ^[ */ 52a17d2cb2SPeter Wemm #define L_BRACK '[' 53a17d2cb2SPeter Wemm #define SHIFT_OUT 017 /* ^N */ 540e3d5408SPeter Wemm 55a17d2cb2SPeter Wemm NCURSES_EXPORT_VAR(char *) UP = 0; 56a17d2cb2SPeter Wemm NCURSES_EXPORT_VAR(char *) BC = 0; 570e3d5408SPeter Wemm 58c8b9c85eSPeter Wemm #ifdef FREEBSD_NATIVE 5977b3485bSLuoqi Chen #undef GCC_UNUSED 6077b3485bSLuoqi Chen #define GCC_UNUSED 61c8b9c85eSPeter Wemm extern char _nc_termcap[]; /* buffer to copy out */ 62c8b9c85eSPeter Wemm #endif 63c8b9c85eSPeter Wemm 64a17d2cb2SPeter Wemm static char *fix_me = 0; 65a17d2cb2SPeter Wemm 66a17d2cb2SPeter Wemm static char * 67a17d2cb2SPeter Wemm set_attribute_9(int flag) 68a17d2cb2SPeter Wemm { 69a17d2cb2SPeter Wemm const char *result; 70a17d2cb2SPeter Wemm 71a17d2cb2SPeter Wemm if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0) 72a17d2cb2SPeter Wemm result = ""; 73a17d2cb2SPeter Wemm return strdup(result); 74a17d2cb2SPeter Wemm } 75a17d2cb2SPeter Wemm 76a17d2cb2SPeter Wemm static int 77a17d2cb2SPeter Wemm is_csi(char *s) 78a17d2cb2SPeter Wemm { 79a17d2cb2SPeter Wemm if (UChar(s[0]) == CSI) 80a17d2cb2SPeter Wemm return 1; 81a17d2cb2SPeter Wemm else if (s[0] == ESC && s[1] == L_BRACK) 82a17d2cb2SPeter Wemm return 2; 83a17d2cb2SPeter Wemm return 0; 84a17d2cb2SPeter Wemm } 85a17d2cb2SPeter Wemm 86a17d2cb2SPeter Wemm static char * 87a17d2cb2SPeter Wemm skip_zero(char *s) 88a17d2cb2SPeter Wemm { 89a17d2cb2SPeter Wemm if (s[0] == '0') { 90a17d2cb2SPeter Wemm if (s[1] == ';') 91a17d2cb2SPeter Wemm s += 2; 92a17d2cb2SPeter Wemm else if (isalpha(UChar(s[1]))) 93a17d2cb2SPeter Wemm s += 1; 94a17d2cb2SPeter Wemm } 95a17d2cb2SPeter Wemm return s; 96a17d2cb2SPeter Wemm } 97a17d2cb2SPeter Wemm 98a17d2cb2SPeter Wemm static bool 99a17d2cb2SPeter Wemm similar_sgr(char *a, char *b) 100a17d2cb2SPeter Wemm { 101a17d2cb2SPeter Wemm int csi_a = is_csi(a); 102a17d2cb2SPeter Wemm int csi_b = is_csi(b); 103a17d2cb2SPeter Wemm 104a17d2cb2SPeter Wemm if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) { 105a17d2cb2SPeter Wemm a += csi_a; 106a17d2cb2SPeter Wemm b += csi_b; 107a17d2cb2SPeter Wemm if (*a != *b) { 108a17d2cb2SPeter Wemm a = skip_zero(a); 109a17d2cb2SPeter Wemm b = skip_zero(b); 110a17d2cb2SPeter Wemm } 111a17d2cb2SPeter Wemm } 112a17d2cb2SPeter Wemm return strcmp(a, b) == 0; 113a17d2cb2SPeter Wemm } 114a17d2cb2SPeter Wemm 1150e3d5408SPeter Wemm /*************************************************************************** 1160e3d5408SPeter Wemm * 1170e3d5408SPeter Wemm * tgetent(bufp, term) 1180e3d5408SPeter Wemm * 1190e3d5408SPeter Wemm * In termcap, this function reads in the entry for terminal `term' into the 1200e3d5408SPeter Wemm * buffer pointed to by bufp. It must be called before any of the functions 1210e3d5408SPeter Wemm * below are called. 1220e3d5408SPeter Wemm * In this terminfo emulation, tgetent() simply calls setupterm() (which 1230e3d5408SPeter Wemm * does a bit more than tgetent() in termcap does), and returns its return 1240e3d5408SPeter Wemm * value (1 if successful, 0 if no terminal with the given name could be 1250e3d5408SPeter Wemm * found, or -1 if no terminal descriptions have been installed on the 1260e3d5408SPeter Wemm * system). The bufp argument is ignored. 1270e3d5408SPeter Wemm * 1280e3d5408SPeter Wemm ***************************************************************************/ 1290e3d5408SPeter Wemm 130952abd2aSPeter Wemm NCURSES_EXPORT(int) 131a17d2cb2SPeter Wemm tgetent(char *bufp GCC_UNUSED, const char *name) 1320e3d5408SPeter Wemm { 1330e3d5408SPeter Wemm int errcode; 1340e3d5408SPeter Wemm 1350e3d5408SPeter Wemm T((T_CALLED("tgetent()"))); 1360e3d5408SPeter Wemm 1370e3d5408SPeter Wemm setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode); 1380e3d5408SPeter Wemm 139a17d2cb2SPeter Wemm PC = 0; 140a17d2cb2SPeter Wemm UP = 0; 141a17d2cb2SPeter Wemm BC = 0; 142a17d2cb2SPeter Wemm fix_me = 0; 143a17d2cb2SPeter Wemm 1440e3d5408SPeter Wemm if (errcode == 1) { 1450e3d5408SPeter Wemm 1460e3d5408SPeter Wemm if (cursor_left) 1470e3d5408SPeter Wemm if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) 1480e3d5408SPeter Wemm backspace_if_not_bs = cursor_left; 1490e3d5408SPeter Wemm 1500e3d5408SPeter Wemm /* we're required to export these */ 1510e3d5408SPeter Wemm if (pad_char != NULL) 1520e3d5408SPeter Wemm PC = pad_char[0]; 1530e3d5408SPeter Wemm if (cursor_up != NULL) 1540e3d5408SPeter Wemm UP = cursor_up; 1550e3d5408SPeter Wemm if (backspace_if_not_bs != NULL) 1560e3d5408SPeter Wemm BC = backspace_if_not_bs; 1570e3d5408SPeter Wemm 158a17d2cb2SPeter Wemm /* 159a17d2cb2SPeter Wemm * While 'sgr0' is the "same" as termcap 'me', there is a compatibility 160a17d2cb2SPeter Wemm * issue. The sgr/sgr0 capabilities include setting/clearing alternate 161a17d2cb2SPeter Wemm * character set mode. A termcap application cannot use sgr, so sgr0 162a17d2cb2SPeter Wemm * strings that reset alternate character set mode will be 163a17d2cb2SPeter Wemm * misinterpreted. Here, we remove those from the more common 164a17d2cb2SPeter Wemm * ISO/ANSI/VT100 entries, which have sgr0 agreeing with sgr. 165a17d2cb2SPeter Wemm */ 166a17d2cb2SPeter Wemm if (exit_attribute_mode != 0 167a17d2cb2SPeter Wemm && set_attributes != 0) { 168a17d2cb2SPeter Wemm char *on = set_attribute_9(1); 169a17d2cb2SPeter Wemm char *off = set_attribute_9(0); 170a17d2cb2SPeter Wemm char *tmp; 171a17d2cb2SPeter Wemm size_t i, j, k; 172a17d2cb2SPeter Wemm 173a17d2cb2SPeter Wemm if (similar_sgr(off, exit_attribute_mode) 174a17d2cb2SPeter Wemm && !similar_sgr(off, on)) { 175a17d2cb2SPeter Wemm TR(TRACE_DATABASE, ("adjusting sgr0 : %s", _nc_visbuf(off))); 176a17d2cb2SPeter Wemm FreeIfNeeded(fix_me); 177a17d2cb2SPeter Wemm fix_me = off; 178a17d2cb2SPeter Wemm for (i = 0; off[i] != '\0'; ++i) { 179a17d2cb2SPeter Wemm if (on[i] != off[i]) { 180a17d2cb2SPeter Wemm j = strlen(off); 181a17d2cb2SPeter Wemm k = strlen(on); 182a17d2cb2SPeter Wemm while (j != 0 183a17d2cb2SPeter Wemm && k != 0 184a17d2cb2SPeter Wemm && off[j - 1] == on[k - 1]) { 185a17d2cb2SPeter Wemm --j, --k; 186a17d2cb2SPeter Wemm } 187a17d2cb2SPeter Wemm while (off[j] != '\0') { 188a17d2cb2SPeter Wemm off[i++] = off[j++]; 189a17d2cb2SPeter Wemm } 190a17d2cb2SPeter Wemm off[i] = '\0'; 191a17d2cb2SPeter Wemm break; 192a17d2cb2SPeter Wemm } 193a17d2cb2SPeter Wemm } 194a17d2cb2SPeter Wemm /* SGR 10 would reset to normal font */ 195a17d2cb2SPeter Wemm if ((i = is_csi(off)) != 0 196a17d2cb2SPeter Wemm && off[strlen(off) - 1] == 'm') { 197a17d2cb2SPeter Wemm tmp = skip_zero(off + i); 198a17d2cb2SPeter Wemm if (tmp[0] == '1' 199a17d2cb2SPeter Wemm && skip_zero(tmp + 1) != tmp + 1) { 200a17d2cb2SPeter Wemm i = tmp - off; 201a17d2cb2SPeter Wemm if (off[i - 1] == ';') 202a17d2cb2SPeter Wemm i--; 203a17d2cb2SPeter Wemm j = skip_zero(tmp + 1) - off; 204a17d2cb2SPeter Wemm while (off[j] != '\0') { 205a17d2cb2SPeter Wemm off[i++] = off[j++]; 206a17d2cb2SPeter Wemm } 207a17d2cb2SPeter Wemm off[i] = '\0'; 208a17d2cb2SPeter Wemm } 209a17d2cb2SPeter Wemm } 210a17d2cb2SPeter Wemm TR(TRACE_DATABASE, ("...adjusted me : %s", _nc_visbuf(fix_me))); 211a17d2cb2SPeter Wemm if (!strcmp(fix_me, exit_attribute_mode)) { 212a17d2cb2SPeter Wemm TR(TRACE_DATABASE, ("...same result, discard")); 213a17d2cb2SPeter Wemm free(fix_me); 214a17d2cb2SPeter Wemm fix_me = 0; 215a17d2cb2SPeter Wemm } 216a17d2cb2SPeter Wemm } 217a17d2cb2SPeter Wemm free(on); 218a17d2cb2SPeter Wemm } 219a17d2cb2SPeter Wemm 2200e3d5408SPeter Wemm (void) baudrate(); /* sets ospeed as a side-effect */ 2210e3d5408SPeter Wemm 2220e3d5408SPeter Wemm /* LINT_PREPRO 2230e3d5408SPeter Wemm #if 0*/ 2240e3d5408SPeter Wemm #include <capdefaults.c> 2250e3d5408SPeter Wemm /* LINT_PREPRO 2260e3d5408SPeter Wemm #endif*/ 2270e3d5408SPeter Wemm 228b589b6f2SPeter Wemm } 229b589b6f2SPeter Wemm 230c8b9c85eSPeter Wemm #ifdef FREEBSD_NATIVE 231c8b9c85eSPeter Wemm /* 232c8b9c85eSPeter Wemm * This is a REALLY UGLY hack. Basically, if we originate with 233c8b9c85eSPeter Wemm * a termcap source, try and copy it out. 234c8b9c85eSPeter Wemm */ 235c8b9c85eSPeter Wemm if (bufp && _nc_termcap[0]) 236c8b9c85eSPeter Wemm strncpy(bufp, _nc_termcap, 1024); 237c8b9c85eSPeter Wemm #endif 238c8b9c85eSPeter Wemm 2390e3d5408SPeter Wemm returnCode(errcode); 2400e3d5408SPeter Wemm } 2410e3d5408SPeter Wemm 2420e3d5408SPeter Wemm /*************************************************************************** 2430e3d5408SPeter Wemm * 2440e3d5408SPeter Wemm * tgetflag(str) 2450e3d5408SPeter Wemm * 2460e3d5408SPeter Wemm * Look up boolean termcap capability str and return its value (TRUE=1 if 2470e3d5408SPeter Wemm * present, FALSE=0 if not). 2480e3d5408SPeter Wemm * 2490e3d5408SPeter Wemm ***************************************************************************/ 2500e3d5408SPeter Wemm 251952abd2aSPeter Wemm NCURSES_EXPORT(int) 252bd2a8869SPeter Wemm tgetflag(NCURSES_CONST char *id) 2530e3d5408SPeter Wemm { 2540e3d5408SPeter Wemm int i; 2550e3d5408SPeter Wemm 2560e3d5408SPeter Wemm T((T_CALLED("tgetflag(%s)"), id)); 2570e3d5408SPeter Wemm if (cur_term != 0) { 2580e3d5408SPeter Wemm TERMTYPE *tp = &(cur_term->type); 2590e3d5408SPeter Wemm for_each_boolean(i, tp) { 2600e3d5408SPeter Wemm const char *capname = ExtBoolname(tp, i, boolcodes); 2610e3d5408SPeter Wemm if (!strncmp(id, capname, 2)) { 2620e3d5408SPeter Wemm /* setupterm forces invalid booleans to false */ 2630e3d5408SPeter Wemm returnCode(tp->Booleans[i]); 2640e3d5408SPeter Wemm } 2650e3d5408SPeter Wemm } 2660e3d5408SPeter Wemm } 2670e3d5408SPeter Wemm returnCode(0); /* Solaris does this */ 2680e3d5408SPeter Wemm } 2690e3d5408SPeter Wemm 2700e3d5408SPeter Wemm /*************************************************************************** 2710e3d5408SPeter Wemm * 2720e3d5408SPeter Wemm * tgetnum(str) 2730e3d5408SPeter Wemm * 2740e3d5408SPeter Wemm * Look up numeric termcap capability str and return its value, or -1 if 2750e3d5408SPeter Wemm * not given. 2760e3d5408SPeter Wemm * 2770e3d5408SPeter Wemm ***************************************************************************/ 2780e3d5408SPeter Wemm 279952abd2aSPeter Wemm NCURSES_EXPORT(int) 280bd2a8869SPeter Wemm tgetnum(NCURSES_CONST char *id) 2810e3d5408SPeter Wemm { 2820e3d5408SPeter Wemm int i; 2830e3d5408SPeter Wemm 2840e3d5408SPeter Wemm T((T_CALLED("tgetnum(%s)"), id)); 2850e3d5408SPeter Wemm if (cur_term != 0) { 2860e3d5408SPeter Wemm TERMTYPE *tp = &(cur_term->type); 2870e3d5408SPeter Wemm for_each_number(i, tp) { 2880e3d5408SPeter Wemm const char *capname = ExtNumname(tp, i, numcodes); 2890e3d5408SPeter Wemm if (!strncmp(id, capname, 2)) { 2900e3d5408SPeter Wemm if (!VALID_NUMERIC(tp->Numbers[i])) 291bd2a8869SPeter Wemm returnCode(ABSENT_NUMERIC); 2920e3d5408SPeter Wemm returnCode(tp->Numbers[i]); 2930e3d5408SPeter Wemm } 2940e3d5408SPeter Wemm } 2950e3d5408SPeter Wemm } 296bd2a8869SPeter Wemm returnCode(ABSENT_NUMERIC); 2970e3d5408SPeter Wemm } 2980e3d5408SPeter Wemm 2990e3d5408SPeter Wemm /*************************************************************************** 3000e3d5408SPeter Wemm * 3010e3d5408SPeter Wemm * tgetstr(str, area) 3020e3d5408SPeter Wemm * 3030e3d5408SPeter Wemm * Look up string termcap capability str and return a pointer to its value, 3040e3d5408SPeter Wemm * or NULL if not given. 3050e3d5408SPeter Wemm * 3060e3d5408SPeter Wemm ***************************************************************************/ 3070e3d5408SPeter Wemm 308952abd2aSPeter Wemm NCURSES_EXPORT(char *) 309a17d2cb2SPeter Wemm tgetstr(NCURSES_CONST char *id, char **area) 3100e3d5408SPeter Wemm { 3110e3d5408SPeter Wemm int i; 312a17d2cb2SPeter Wemm char *result = NULL; 3130e3d5408SPeter Wemm 3140e3d5408SPeter Wemm T((T_CALLED("tgetstr(%s,%p)"), id, area)); 3150e3d5408SPeter Wemm if (cur_term != 0) { 3160e3d5408SPeter Wemm TERMTYPE *tp = &(cur_term->type); 3170e3d5408SPeter Wemm for_each_string(i, tp) { 3180e3d5408SPeter Wemm const char *capname = ExtStrname(tp, i, strcodes); 3190e3d5408SPeter Wemm if (!strncmp(id, capname, 2)) { 320a17d2cb2SPeter Wemm result = tp->Strings[i]; 321a17d2cb2SPeter Wemm TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); 322bd2a8869SPeter Wemm /* setupterm forces canceled strings to null */ 323a17d2cb2SPeter Wemm if (VALID_STRING(result)) { 324a17d2cb2SPeter Wemm if (result == exit_attribute_mode 325a17d2cb2SPeter Wemm && fix_me != 0) { 326a17d2cb2SPeter Wemm result = fix_me; 327a17d2cb2SPeter Wemm TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); 328a17d2cb2SPeter Wemm } 3295bd21f8aSPeter Wemm if (area != 0 330a17d2cb2SPeter Wemm && *area != 0) { 331a17d2cb2SPeter Wemm (void) strcpy(*area, result); 3325bd21f8aSPeter Wemm *area += strlen(*area) + 1; 3332a043471SLuoqi Chen } 334a17d2cb2SPeter Wemm } 335a17d2cb2SPeter Wemm break; 3360e3d5408SPeter Wemm } 3370e3d5408SPeter Wemm } 3380e3d5408SPeter Wemm } 339a17d2cb2SPeter Wemm returnPtr(result); 3400e3d5408SPeter Wemm } 341