10e3d5408SPeter Wemm /**************************************************************************** 24454585cSRong-En Fan * Copyright (c) 1998-2006,2007 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> * 327d0e8efaSRong-En Fan * and: Thomas E. Dickey 1996-on * 33a17d2cb2SPeter Wemm * * 34a17d2cb2SPeter Wemm * some of the code in here was contributed by: * 35a17d2cb2SPeter Wemm * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) * 367d0e8efaSRong-En Fan * (but it has changed a lot) * 370e3d5408SPeter Wemm ****************************************************************************/ 380e3d5408SPeter Wemm 395bd21f8aSPeter Wemm /* $FreeBSD$ */ 405bd21f8aSPeter Wemm 41d91c14deSPeter Wemm #define __INTERNAL_CAPS_VISIBLE 420e3d5408SPeter Wemm #include <curses.priv.h> 430e3d5408SPeter Wemm 440e3d5408SPeter Wemm #include <termcap.h> 450e3d5408SPeter Wemm #include <tic.h> 46a17d2cb2SPeter Wemm #include <ctype.h> 470e3d5408SPeter Wemm 480e3d5408SPeter Wemm #include <term_entry.h> 490e3d5408SPeter Wemm 504454585cSRong-En Fan MODULE_ID("$Id: lib_termcap.c,v 1.61 2007/06/02 19:36:03 tom Exp $") 510e3d5408SPeter Wemm 52a17d2cb2SPeter Wemm NCURSES_EXPORT_VAR(char *) UP = 0; 53a17d2cb2SPeter Wemm NCURSES_EXPORT_VAR(char *) BC = 0; 540e3d5408SPeter Wemm 55c8b9c85eSPeter Wemm #ifdef FREEBSD_NATIVE 56c8b9c85eSPeter Wemm extern char _nc_termcap[]; /* buffer to copy out */ 57c8b9c85eSPeter Wemm #endif 58c8b9c85eSPeter Wemm 594454585cSRong-En Fan #define MyCache _nc_globals.tgetent_cache 604454585cSRong-En Fan #define CacheInx _nc_globals.tgetent_index 614454585cSRong-En Fan #define CacheSeq _nc_globals.tgetent_sequence 62a17d2cb2SPeter Wemm 634454585cSRong-En Fan #define FIX_SGR0 MyCache[CacheInx].fix_sgr0 644454585cSRong-En Fan #define LAST_TRM MyCache[CacheInx].last_term 654454585cSRong-En Fan #define LAST_BUF MyCache[CacheInx].last_bufp 664454585cSRong-En Fan #define LAST_USE MyCache[CacheInx].last_used 674454585cSRong-En Fan #define LAST_SEQ MyCache[CacheInx].sequence 68a17d2cb2SPeter Wemm 690e3d5408SPeter Wemm /*************************************************************************** 700e3d5408SPeter Wemm * 710e3d5408SPeter Wemm * tgetent(bufp, term) 720e3d5408SPeter Wemm * 730e3d5408SPeter Wemm * In termcap, this function reads in the entry for terminal `term' into the 740e3d5408SPeter Wemm * buffer pointed to by bufp. It must be called before any of the functions 750e3d5408SPeter Wemm * below are called. 760e3d5408SPeter Wemm * In this terminfo emulation, tgetent() simply calls setupterm() (which 770e3d5408SPeter Wemm * does a bit more than tgetent() in termcap does), and returns its return 780e3d5408SPeter Wemm * value (1 if successful, 0 if no terminal with the given name could be 790e3d5408SPeter Wemm * found, or -1 if no terminal descriptions have been installed on the 800e3d5408SPeter Wemm * system). The bufp argument is ignored. 810e3d5408SPeter Wemm * 820e3d5408SPeter Wemm ***************************************************************************/ 830e3d5408SPeter Wemm 84952abd2aSPeter Wemm NCURSES_EXPORT(int) 857d0e8efaSRong-En Fan tgetent(char *bufp, const char *name) 860e3d5408SPeter Wemm { 877d0e8efaSRong-En Fan int errcode; 887d0e8efaSRong-En Fan int n; 897d0e8efaSRong-En Fan bool found_cache = FALSE; 907d0e8efaSRong-En Fan 917d0e8efaSRong-En Fan START_TRACE(); 920e3d5408SPeter Wemm T((T_CALLED("tgetent()"))); 930e3d5408SPeter Wemm 947d0e8efaSRong-En Fan _nc_setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode, TRUE); 957d0e8efaSRong-En Fan 967d0e8efaSRong-En Fan /* 977d0e8efaSRong-En Fan * In general we cannot tell if the fixed sgr0 is still used by the 987d0e8efaSRong-En Fan * caller, but if tgetent() is called with the same buffer, that is 997d0e8efaSRong-En Fan * good enough, since the previous data would be invalidated by the 1007d0e8efaSRong-En Fan * current call. 1014454585cSRong-En Fan * 1024454585cSRong-En Fan * bufp may be a null pointer, e.g., GNU termcap. That allocates data, 1034454585cSRong-En Fan * which is good until the next tgetent() call. The conventional termcap 1044454585cSRong-En Fan * is inconvenient because of the fixed buffer size, but because it uses 1054454585cSRong-En Fan * caller-supplied buffers, can have multiple terminal descriptions in 1064454585cSRong-En Fan * use at a given time. 1077d0e8efaSRong-En Fan */ 1084454585cSRong-En Fan for (n = 0; n < TGETENT_MAX; ++n) { 1094454585cSRong-En Fan bool same_result = (MyCache[n].last_used && MyCache[n].last_bufp == bufp); 1107d0e8efaSRong-En Fan if (same_result) { 1114454585cSRong-En Fan CacheInx = n; 1127d0e8efaSRong-En Fan if (FIX_SGR0 != 0) { 1137d0e8efaSRong-En Fan FreeAndNull(FIX_SGR0); 1147d0e8efaSRong-En Fan } 1157d0e8efaSRong-En Fan /* 1167d0e8efaSRong-En Fan * Also free the terminfo data that we loaded (much bigger leak). 1177d0e8efaSRong-En Fan */ 1187d0e8efaSRong-En Fan if (LAST_TRM != 0 && LAST_TRM != cur_term) { 1197d0e8efaSRong-En Fan TERMINAL *trm = LAST_TRM; 1207d0e8efaSRong-En Fan del_curterm(LAST_TRM); 1214454585cSRong-En Fan for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) 1227d0e8efaSRong-En Fan if (LAST_TRM == trm) 1237d0e8efaSRong-En Fan LAST_TRM = 0; 1244454585cSRong-En Fan CacheInx = n; 1257d0e8efaSRong-En Fan } 1267d0e8efaSRong-En Fan found_cache = TRUE; 1277d0e8efaSRong-En Fan break; 1287d0e8efaSRong-En Fan } 1297d0e8efaSRong-En Fan } 1307d0e8efaSRong-En Fan if (!found_cache) { 1317d0e8efaSRong-En Fan int best = 0; 1327d0e8efaSRong-En Fan 1334454585cSRong-En Fan for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) { 1344454585cSRong-En Fan if (LAST_SEQ < MyCache[best].sequence) { 1354454585cSRong-En Fan best = CacheInx; 1367d0e8efaSRong-En Fan } 1377d0e8efaSRong-En Fan } 1384454585cSRong-En Fan CacheInx = best; 1397d0e8efaSRong-En Fan } 1407d0e8efaSRong-En Fan LAST_TRM = cur_term; 1414454585cSRong-En Fan LAST_SEQ = ++CacheSeq; 1420e3d5408SPeter Wemm 143a17d2cb2SPeter Wemm PC = 0; 144a17d2cb2SPeter Wemm UP = 0; 145a17d2cb2SPeter Wemm BC = 0; 1467d0e8efaSRong-En Fan FIX_SGR0 = 0; /* don't free it - application may still use */ 147a17d2cb2SPeter Wemm 1480e3d5408SPeter Wemm if (errcode == 1) { 1490e3d5408SPeter Wemm 1500e3d5408SPeter Wemm if (cursor_left) 1510e3d5408SPeter Wemm if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0) 1520e3d5408SPeter Wemm backspace_if_not_bs = cursor_left; 1530e3d5408SPeter Wemm 1540e3d5408SPeter Wemm /* we're required to export these */ 1550e3d5408SPeter Wemm if (pad_char != NULL) 1560e3d5408SPeter Wemm PC = pad_char[0]; 1570e3d5408SPeter Wemm if (cursor_up != NULL) 1580e3d5408SPeter Wemm UP = cursor_up; 1590e3d5408SPeter Wemm if (backspace_if_not_bs != NULL) 1600e3d5408SPeter Wemm BC = backspace_if_not_bs; 1610e3d5408SPeter Wemm 1627d0e8efaSRong-En Fan if ((FIX_SGR0 = _nc_trim_sgr0(&(cur_term->type))) != 0) { 1637d0e8efaSRong-En Fan if (!strcmp(FIX_SGR0, exit_attribute_mode)) { 1647d0e8efaSRong-En Fan if (FIX_SGR0 != exit_attribute_mode) { 1657d0e8efaSRong-En Fan free(FIX_SGR0); 166a17d2cb2SPeter Wemm } 1677d0e8efaSRong-En Fan FIX_SGR0 = 0; 168a17d2cb2SPeter Wemm } 169a17d2cb2SPeter Wemm } 1707d0e8efaSRong-En Fan LAST_BUF = bufp; 1714454585cSRong-En Fan LAST_USE = TRUE; 172a17d2cb2SPeter Wemm 1730e3d5408SPeter Wemm (void) baudrate(); /* sets ospeed as a side-effect */ 1740e3d5408SPeter Wemm 1750e3d5408SPeter Wemm /* LINT_PREPRO 1760e3d5408SPeter Wemm #if 0*/ 1770e3d5408SPeter Wemm #include <capdefaults.c> 1780e3d5408SPeter Wemm /* LINT_PREPRO 1790e3d5408SPeter Wemm #endif*/ 1800e3d5408SPeter Wemm 181b589b6f2SPeter Wemm } 182b589b6f2SPeter Wemm 183c8b9c85eSPeter Wemm #ifdef FREEBSD_NATIVE 184c8b9c85eSPeter Wemm /* 185c8b9c85eSPeter Wemm * This is a REALLY UGLY hack. Basically, if we originate with 186c8b9c85eSPeter Wemm * a termcap source, try and copy it out. 187c8b9c85eSPeter Wemm */ 188c8b9c85eSPeter Wemm if (bufp && _nc_termcap[0]) 189c8b9c85eSPeter Wemm strncpy(bufp, _nc_termcap, 1024); 190c8b9c85eSPeter Wemm #endif 191c8b9c85eSPeter Wemm 1920e3d5408SPeter Wemm returnCode(errcode); 1930e3d5408SPeter Wemm } 1940e3d5408SPeter Wemm 1950e3d5408SPeter Wemm /*************************************************************************** 1960e3d5408SPeter Wemm * 1970e3d5408SPeter Wemm * tgetflag(str) 1980e3d5408SPeter Wemm * 1990e3d5408SPeter Wemm * Look up boolean termcap capability str and return its value (TRUE=1 if 2000e3d5408SPeter Wemm * present, FALSE=0 if not). 2010e3d5408SPeter Wemm * 2020e3d5408SPeter Wemm ***************************************************************************/ 2030e3d5408SPeter Wemm 204952abd2aSPeter Wemm NCURSES_EXPORT(int) 205bd2a8869SPeter Wemm tgetflag(NCURSES_CONST char *id) 2060e3d5408SPeter Wemm { 2077d0e8efaSRong-En Fan unsigned i; 2080e3d5408SPeter Wemm 2090e3d5408SPeter Wemm T((T_CALLED("tgetflag(%s)"), id)); 2100e3d5408SPeter Wemm if (cur_term != 0) { 2110e3d5408SPeter Wemm TERMTYPE *tp = &(cur_term->type); 2120e3d5408SPeter Wemm for_each_boolean(i, tp) { 2130e3d5408SPeter Wemm const char *capname = ExtBoolname(tp, i, boolcodes); 2140e3d5408SPeter Wemm if (!strncmp(id, capname, 2)) { 2150e3d5408SPeter Wemm /* setupterm forces invalid booleans to false */ 2160e3d5408SPeter Wemm returnCode(tp->Booleans[i]); 2170e3d5408SPeter Wemm } 2180e3d5408SPeter Wemm } 2190e3d5408SPeter Wemm } 2200e3d5408SPeter Wemm returnCode(0); /* Solaris does this */ 2210e3d5408SPeter Wemm } 2220e3d5408SPeter Wemm 2230e3d5408SPeter Wemm /*************************************************************************** 2240e3d5408SPeter Wemm * 2250e3d5408SPeter Wemm * tgetnum(str) 2260e3d5408SPeter Wemm * 2270e3d5408SPeter Wemm * Look up numeric termcap capability str and return its value, or -1 if 2280e3d5408SPeter Wemm * not given. 2290e3d5408SPeter Wemm * 2300e3d5408SPeter Wemm ***************************************************************************/ 2310e3d5408SPeter Wemm 232952abd2aSPeter Wemm NCURSES_EXPORT(int) 233bd2a8869SPeter Wemm tgetnum(NCURSES_CONST char *id) 2340e3d5408SPeter Wemm { 2357d0e8efaSRong-En Fan unsigned i; 2360e3d5408SPeter Wemm 2370e3d5408SPeter Wemm T((T_CALLED("tgetnum(%s)"), id)); 2380e3d5408SPeter Wemm if (cur_term != 0) { 2390e3d5408SPeter Wemm TERMTYPE *tp = &(cur_term->type); 2400e3d5408SPeter Wemm for_each_number(i, tp) { 2410e3d5408SPeter Wemm const char *capname = ExtNumname(tp, i, numcodes); 2420e3d5408SPeter Wemm if (!strncmp(id, capname, 2)) { 2430e3d5408SPeter Wemm if (!VALID_NUMERIC(tp->Numbers[i])) 244bd2a8869SPeter Wemm returnCode(ABSENT_NUMERIC); 2450e3d5408SPeter Wemm returnCode(tp->Numbers[i]); 2460e3d5408SPeter Wemm } 2470e3d5408SPeter Wemm } 2480e3d5408SPeter Wemm } 249bd2a8869SPeter Wemm returnCode(ABSENT_NUMERIC); 2500e3d5408SPeter Wemm } 2510e3d5408SPeter Wemm 2520e3d5408SPeter Wemm /*************************************************************************** 2530e3d5408SPeter Wemm * 2540e3d5408SPeter Wemm * tgetstr(str, area) 2550e3d5408SPeter Wemm * 2560e3d5408SPeter Wemm * Look up string termcap capability str and return a pointer to its value, 2570e3d5408SPeter Wemm * or NULL if not given. 2580e3d5408SPeter Wemm * 2590e3d5408SPeter Wemm ***************************************************************************/ 2600e3d5408SPeter Wemm 261952abd2aSPeter Wemm NCURSES_EXPORT(char *) 262a17d2cb2SPeter Wemm tgetstr(NCURSES_CONST char *id, char **area) 2630e3d5408SPeter Wemm { 2647d0e8efaSRong-En Fan unsigned i; 265a17d2cb2SPeter Wemm char *result = NULL; 2660e3d5408SPeter Wemm 2670e3d5408SPeter Wemm T((T_CALLED("tgetstr(%s,%p)"), id, area)); 2680e3d5408SPeter Wemm if (cur_term != 0) { 2690e3d5408SPeter Wemm TERMTYPE *tp = &(cur_term->type); 2700e3d5408SPeter Wemm for_each_string(i, tp) { 2710e3d5408SPeter Wemm const char *capname = ExtStrname(tp, i, strcodes); 2720e3d5408SPeter Wemm if (!strncmp(id, capname, 2)) { 273a17d2cb2SPeter Wemm result = tp->Strings[i]; 274a17d2cb2SPeter Wemm TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); 275bd2a8869SPeter Wemm /* setupterm forces canceled strings to null */ 276a17d2cb2SPeter Wemm if (VALID_STRING(result)) { 277a17d2cb2SPeter Wemm if (result == exit_attribute_mode 2787d0e8efaSRong-En Fan && FIX_SGR0 != 0) { 2797d0e8efaSRong-En Fan result = FIX_SGR0; 280a17d2cb2SPeter Wemm TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); 281a17d2cb2SPeter Wemm } 2825bd21f8aSPeter Wemm if (area != 0 283a17d2cb2SPeter Wemm && *area != 0) { 284a17d2cb2SPeter Wemm (void) strcpy(*area, result); 2857d0e8efaSRong-En Fan result = *area; 2865bd21f8aSPeter Wemm *area += strlen(*area) + 1; 2872a043471SLuoqi Chen } 288a17d2cb2SPeter Wemm } 289a17d2cb2SPeter Wemm break; 2900e3d5408SPeter Wemm } 2910e3d5408SPeter Wemm } 2920e3d5408SPeter Wemm } 293a17d2cb2SPeter Wemm returnPtr(result); 2940e3d5408SPeter Wemm } 2957d0e8efaSRong-En Fan 2967d0e8efaSRong-En Fan #if NO_LEAKS 2977d0e8efaSRong-En Fan NCURSES_EXPORT(void) 2987d0e8efaSRong-En Fan _nc_tgetent_leaks(void) 2997d0e8efaSRong-En Fan { 3004454585cSRong-En Fan for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) { 3017d0e8efaSRong-En Fan FreeIfNeeded(FIX_SGR0); 3024454585cSRong-En Fan if (LAST_TRM != 0) 3037d0e8efaSRong-En Fan del_curterm(LAST_TRM); 3047d0e8efaSRong-En Fan } 3057d0e8efaSRong-En Fan } 3067d0e8efaSRong-En Fan #endif 307