Back to index

tetex-bin  3.0
lib_termcap.c
Go to the documentation of this file.
00001 /****************************************************************************
00002  * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc.              *
00003  *                                                                          *
00004  * Permission is hereby granted, free of charge, to any person obtaining a  *
00005  * copy of this software and associated documentation files (the            *
00006  * "Software"), to deal in the Software without restriction, including      *
00007  * without limitation the rights to use, copy, modify, merge, publish,      *
00008  * distribute, distribute with modifications, sublicense, and/or sell       *
00009  * copies of the Software, and to permit persons to whom the Software is    *
00010  * furnished to do so, subject to the following conditions:                 *
00011  *                                                                          *
00012  * The above copyright notice and this permission notice shall be included  *
00013  * in all copies or substantial portions of the Software.                   *
00014  *                                                                          *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
00016  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
00017  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
00018  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
00021  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
00022  *                                                                          *
00023  * Except as contained in this notice, the name(s) of the above copyright   *
00024  * holders shall not be used in advertising or otherwise to promote the     *
00025  * sale, use or other dealings in this Software without prior written       *
00026  * authorization.                                                           *
00027  ****************************************************************************/
00028 
00029 /****************************************************************************
00030  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
00031  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
00032  *     and: Thomas E. Dickey                        1996-on                 *
00033  *                                                                          *
00034  * some of the code in here was contributed by:                             *
00035  * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93)                      *
00036  ****************************************************************************/
00037 
00038 #define __INTERNAL_CAPS_VISIBLE
00039 #include <curses.priv.h>
00040 
00041 #include <termcap.h>
00042 #include <tic.h>
00043 #include <ctype.h>
00044 
00045 #include <term_entry.h>
00046 
00047 MODULE_ID("$Id: lib_termcap.c,v 1.46 2004/09/25 19:21:27 tom Exp $")
00048 
00049 #define CSI       233
00050 #define ESC       033              /* ^[ */
00051 #define L_BRACK   '['
00052 #define SHIFT_OUT 017              /* ^N */
00053 
00054 NCURSES_EXPORT_VAR(char *) UP = 0;
00055 NCURSES_EXPORT_VAR(char *) BC = 0;
00056 
00057 static char *fix_me = 0;
00058 
00059 static char *
00060 set_attribute_9(int flag)
00061 {
00062     const char *result;
00063 
00064     if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0)
00065        result = "";
00066     return strdup(result);
00067 }
00068 
00069 static int
00070 is_csi(char *s)
00071 {
00072     if (UChar(s[0]) == CSI)
00073        return 1;
00074     else if (s[0] == ESC && s[1] == L_BRACK)
00075        return 2;
00076     return 0;
00077 }
00078 
00079 static char *
00080 skip_zero(char *s)
00081 {
00082     if (s[0] == '0') {
00083        if (s[1] == ';')
00084            s += 2;
00085        else if (isalpha(UChar(s[1])))
00086            s += 1;
00087     }
00088     return s;
00089 }
00090 
00091 static bool
00092 similar_sgr(char *a, char *b)
00093 {
00094     bool result = FALSE;
00095     int csi_a = is_csi(a);
00096     int csi_b = is_csi(b);
00097     unsigned len_a;
00098     unsigned len_b;
00099 
00100     TR(TRACE_DATABASE, ("similar_sgr:\n\t%s\n\t%s",
00101                      _nc_visbuf2(1, a),
00102                      _nc_visbuf2(2, b)));
00103     if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) {
00104        a += csi_a;
00105        b += csi_b;
00106        if (*a != *b) {
00107            a = skip_zero(a);
00108            b = skip_zero(b);
00109        }
00110     }
00111     len_a = strlen(a);
00112     len_b = strlen(b);
00113     if (len_a && len_b) {
00114        if (len_a > len_b)
00115            result = (strncmp(a, b, len_b) == 0);
00116        else
00117            result = (strncmp(a, b, len_a) == 0);
00118     }
00119     TR(TRACE_DATABASE, ("...similar_sgr: %d\n\t%s\n\t%s", result,
00120                      _nc_visbuf2(1, a),
00121                      _nc_visbuf2(2, b)));
00122     return result;
00123 }
00124 
00125 static unsigned
00126 chop_out(char *string, unsigned i, unsigned j)
00127 {
00128     TR(TRACE_DATABASE, ("chop_out %d..%d from %s", i, j, _nc_visbuf(string)));
00129     while (string[j] != '\0') {
00130        string[i++] = string[j++];
00131     }
00132     string[i] = '\0';
00133     return i;
00134 }
00135 
00136 /***************************************************************************
00137  *
00138  * tgetent(bufp, term)
00139  *
00140  * In termcap, this function reads in the entry for terminal `term' into the
00141  * buffer pointed to by bufp. It must be called before any of the functions
00142  * below are called.
00143  * In this terminfo emulation, tgetent() simply calls setupterm() (which
00144  * does a bit more than tgetent() in termcap does), and returns its return
00145  * value (1 if successful, 0 if no terminal with the given name could be
00146  * found, or -1 if no terminal descriptions have been installed on the
00147  * system).  The bufp argument is ignored.
00148  *
00149  ***************************************************************************/
00150 
00151 NCURSES_EXPORT(int)
00152 tgetent(char *bufp GCC_UNUSED, const char *name)
00153 {
00154     int errcode;
00155 
00156     START_TRACE();
00157     T((T_CALLED("tgetent()")));
00158 
00159     setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode);
00160 
00161     PC = 0;
00162     UP = 0;
00163     BC = 0;
00164     fix_me = 0;
00165 
00166     if (errcode == 1) {
00167 
00168        if (cursor_left)
00169            if ((backspaces_with_bs = !strcmp(cursor_left, "\b")) == 0)
00170               backspace_if_not_bs = cursor_left;
00171 
00172        /* we're required to export these */
00173        if (pad_char != NULL)
00174            PC = pad_char[0];
00175        if (cursor_up != NULL)
00176            UP = cursor_up;
00177        if (backspace_if_not_bs != NULL)
00178            BC = backspace_if_not_bs;
00179 
00180        /*
00181         * While 'sgr0' is the "same" as termcap 'me', there is a compatibility
00182         * issue.  The sgr/sgr0 capabilities include setting/clearing alternate
00183         * character set mode.  A termcap application cannot use sgr, so sgr0
00184         * strings that reset alternate character set mode will be
00185         * misinterpreted.  Here, we remove those from the more common
00186         * ISO/ANSI/VT100 entries, which have sgr0 agreeing with sgr.
00187         */
00188        if (exit_attribute_mode != 0
00189            && set_attributes != 0) {
00190            bool found = FALSE;
00191            char *on = set_attribute_9(1);
00192            char *off = set_attribute_9(0);
00193            char *tmp;
00194            size_t i, j, k;
00195 
00196            TR(TRACE_DATABASE, ("checking if we can trim sgr0 based on sgr"));
00197            TR(TRACE_DATABASE, ("sgr0       %s", _nc_visbuf(exit_attribute_mode)));
00198            TR(TRACE_DATABASE, ("sgr(9:off) %s", _nc_visbuf(off)));
00199            TR(TRACE_DATABASE, ("sgr(9:on)  %s", _nc_visbuf(on)));
00200            if (similar_sgr(off, exit_attribute_mode)
00201               && !similar_sgr(off, on)) {
00202               TR(TRACE_DATABASE, ("adjusting sgr0 : %s", _nc_visbuf(off)));
00203               FreeIfNeeded(fix_me);
00204               fix_me = off;
00205               /*
00206                * If rmacs is a substring of sgr(0), remove that chunk.
00207                */
00208               if (exit_alt_charset_mode != 0) {
00209                   j = strlen(off);
00210                   k = strlen(exit_alt_charset_mode);
00211                   if (j > k) {
00212                      for (i = 0; i <= (j - k); ++i) {
00213                          if (!memcmp(exit_alt_charset_mode, off + i, k)) {
00214                             found = TRUE;
00215                             chop_out(off, i, i + k);
00216                             break;
00217                          }
00218                      }
00219                   }
00220               }
00221               /*
00222                * SGR 10 would reset to normal font.
00223                */
00224               if (!found) {
00225                   if ((i = is_csi(off)) != 0
00226                      && off[strlen(off) - 1] == 'm') {
00227                      TR(TRACE_DATABASE, ("looking for SGR 10 in %s",
00228                                        _nc_visbuf(off)));
00229                      tmp = skip_zero(off + i);
00230                      if (tmp[0] == '1'
00231                          && skip_zero(tmp + 1) != tmp + 1) {
00232                          i = tmp - off;
00233                          if (off[i - 1] == ';')
00234                             i--;
00235                          j = skip_zero(tmp + 1) - off;
00236                          i = chop_out(off, i, j);
00237                          found = TRUE;
00238                      }
00239                   }
00240               }
00241               if (!found
00242                   && (tmp = strstr(exit_attribute_mode, off)) != 0) {
00243                   i = tmp - exit_attribute_mode;
00244                   j = strlen(off);
00245                   tmp = strdup(exit_attribute_mode);
00246                   chop_out(tmp, i, j);
00247                   free(off);
00248                   fix_me = tmp;
00249               }
00250               TR(TRACE_DATABASE, ("...adjusted sgr0 : %s", _nc_visbuf(fix_me)));
00251               if (!strcmp(fix_me, exit_attribute_mode)) {
00252                   TR(TRACE_DATABASE, ("...same result, discard"));
00253                   free(fix_me);
00254                   fix_me = 0;
00255               }
00256            } else {
00257               /*
00258                * Either the sgr does not reference alternate character set,
00259                * or it is incorrect.  That's too hard to decide right now.
00260                */
00261               free(off);
00262            }
00263            free(on);
00264        } else {
00265            /*
00266             * Possibly some applications are confused if sgr0 contains rmacs,
00267             * but that would be a different bug report -TD
00268             */
00269        }
00270 
00271        (void) baudrate();   /* sets ospeed as a side-effect */
00272 
00273 /* LINT_PREPRO
00274 #if 0*/
00275 #include <capdefaults.c>
00276 /* LINT_PREPRO
00277 #endif*/
00278 
00279     }
00280     returnCode(errcode);
00281 }
00282 
00283 /***************************************************************************
00284  *
00285  * tgetflag(str)
00286  *
00287  * Look up boolean termcap capability str and return its value (TRUE=1 if
00288  * present, FALSE=0 if not).
00289  *
00290  ***************************************************************************/
00291 
00292 NCURSES_EXPORT(int)
00293 tgetflag(NCURSES_CONST char *id)
00294 {
00295     unsigned i;
00296 
00297     T((T_CALLED("tgetflag(%s)"), id));
00298     if (cur_term != 0) {
00299        TERMTYPE *tp = &(cur_term->type);
00300        for_each_boolean(i, tp) {
00301            const char *capname = ExtBoolname(tp, i, boolcodes);
00302            if (!strncmp(id, capname, 2)) {
00303               /* setupterm forces invalid booleans to false */
00304               returnCode(tp->Booleans[i]);
00305            }
00306        }
00307     }
00308     returnCode(0);          /* Solaris does this */
00309 }
00310 
00311 /***************************************************************************
00312  *
00313  * tgetnum(str)
00314  *
00315  * Look up numeric termcap capability str and return its value, or -1 if
00316  * not given.
00317  *
00318  ***************************************************************************/
00319 
00320 NCURSES_EXPORT(int)
00321 tgetnum(NCURSES_CONST char *id)
00322 {
00323     unsigned i;
00324 
00325     T((T_CALLED("tgetnum(%s)"), id));
00326     if (cur_term != 0) {
00327        TERMTYPE *tp = &(cur_term->type);
00328        for_each_number(i, tp) {
00329            const char *capname = ExtNumname(tp, i, numcodes);
00330            if (!strncmp(id, capname, 2)) {
00331               if (!VALID_NUMERIC(tp->Numbers[i]))
00332                   returnCode(ABSENT_NUMERIC);
00333               returnCode(tp->Numbers[i]);
00334            }
00335        }
00336     }
00337     returnCode(ABSENT_NUMERIC);
00338 }
00339 
00340 /***************************************************************************
00341  *
00342  * tgetstr(str, area)
00343  *
00344  * Look up string termcap capability str and return a pointer to its value,
00345  * or NULL if not given.
00346  *
00347  ***************************************************************************/
00348 
00349 NCURSES_EXPORT(char *)
00350 tgetstr(NCURSES_CONST char *id, char **area)
00351 {
00352     unsigned i;
00353     char *result = NULL;
00354 
00355     T((T_CALLED("tgetstr(%s,%p)"), id, area));
00356     if (cur_term != 0) {
00357        TERMTYPE *tp = &(cur_term->type);
00358        for_each_string(i, tp) {
00359            const char *capname = ExtStrname(tp, i, strcodes);
00360            if (!strncmp(id, capname, 2)) {
00361               result = tp->Strings[i];
00362               TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result)));
00363               /* setupterm forces canceled strings to null */
00364               if (VALID_STRING(result)) {
00365                   if (result == exit_attribute_mode
00366                      && fix_me != 0) {
00367                      result = fix_me;
00368                      TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result)));
00369                   }
00370                   if (area != 0
00371                      && *area != 0) {
00372                      (void) strcpy(*area, result);
00373                      *area += strlen(*area) + 1;
00374                   }
00375               }
00376               break;
00377            }
00378        }
00379     }
00380     returnPtr(result);
00381 }