"Fossies" - the Fresh Open Source Software Archive

Member "xterm-379/xtermcap.c" (2 Jan 2023, 16030 Bytes) of package /linux/misc/xterm-379.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "xtermcap.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 377_vs_379.

    1 /* $XTermId: xtermcap.c,v 1.58 2023/01/02 18:19:19 tom Exp $ */
    2 
    3 /*
    4  * Copyright 2007-2020,2023 by Thomas E. Dickey
    5  *
    6  *                         All Rights Reserved
    7  *
    8  * Permission is hereby granted, free of charge, to any person obtaining a
    9  * copy of this software and associated documentation files (the
   10  * "Software"), to deal in the Software without restriction, including
   11  * without limitation the rights to use, copy, modify, merge, publish,
   12  * distribute, sublicense, and/or sell copies of the Software, and to
   13  * permit persons to whom the Software is furnished to do so, subject to
   14  * the following conditions:
   15  *
   16  * The above copyright notice and this permission notice shall be included
   17  * in all copies or substantial portions of the Software.
   18  *
   19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   22  * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
   23  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   26  *
   27  * Except as contained in this notice, the name(s) of the above copyright
   28  * holders shall not be used in advertising or otherwise to promote the
   29  * sale, use or other dealings in this Software without prior written
   30  * authorization.
   31  */
   32 
   33 #include <xtermcap.h>
   34 #include <data.h>
   35 
   36 #include <X11/keysym.h>
   37 #include <ctype.h>
   38 
   39 #ifdef VMS
   40 #include <X11/keysymdef.h>
   41 #endif
   42 
   43 #include <xstrings.h>
   44 
   45 #if USE_TERMINFO && defined(NCURSES_VERSION) && defined(HAVE_USE_EXTENDED_NAMES)
   46 #define USE_EXTENDED_NAMES 1
   47 #else
   48 #define USE_EXTENDED_NAMES 0
   49 #endif
   50 
   51 #if USE_TERMINFO
   52 #define TcapInit(buffer, name) (setupterm(name, fileno(stdout), &ignored) == OK)
   53 #define TcapFree()             (del_curterm(cur_term))
   54 #else
   55 #define TcapInit(buffer, name) (tgetent(buffer, name) == 1)
   56 #define TcapFree()      /*nothing */
   57 #endif
   58 
   59 #define NO_STRING (char *)(-1)
   60 
   61 #if OPT_TCAP_QUERY || OPT_TCAP_FKEYS
   62 
   63 #define SHIFT (MOD_NONE + MOD_SHIFT)
   64 
   65 typedef struct {
   66     const char *tc;
   67     const char *ti;
   68     int code;
   69     unsigned param;     /* see xtermStateToParam() */
   70 } TCAPINFO;
   71 /* *INDENT-OFF* */
   72 #define DATA(tc,ti,x,y) { tc, ti, x, y }
   73 static const TCAPINFO table[] = {
   74     /*  tcap    terminfo    code        state */
   75     DATA(   "%1",   "khlp",     XK_Help,    0   ),
   76     DATA(   "#1",   "kHLP",     XK_Help,    SHIFT   ),
   77     DATA(   "@0",   "kfnd",     XK_Find,    0   ),
   78     DATA(   "*0",   "kFND",     XK_Find,    SHIFT   ),
   79     DATA(   "*6",   "kslt",     XK_Select,  0   ),
   80     DATA(   "#6",   "kSLT",     XK_Select,  SHIFT   ),
   81 
   82     DATA(   "kh",   "khome",    XK_Home,    0   ),
   83     DATA(   "#2",   "kHOM",     XK_Home,    SHIFT   ),
   84     DATA(   "@7",   "kend",     XK_End,     0   ),
   85     DATA(   "*7",   "kEND",     XK_End,     SHIFT   ),
   86 
   87     DATA(   "kl",   "kcub1",    XK_Left,    0   ),
   88     DATA(   "kr",   "kcuf1",    XK_Right,   0   ),
   89     DATA(   "ku",   "kcuu1",    XK_Up,      0   ),
   90     DATA(   "kd",   "kcud1",    XK_Down,    0   ),
   91 
   92     DATA(   "#4",   "kLFT",     XK_Left,    SHIFT   ),
   93     DATA(   "%i",   "kRIT",     XK_Right,   SHIFT   ),
   94     DATA(   "kF",   "kind",     XK_Down,    SHIFT   ),
   95     DATA(   "kR",   "kri",      XK_Up,      SHIFT   ),
   96 
   97     DATA(   "k1",   "kf1",      XK_Fn(1),   0   ),
   98     DATA(   "k2",   "kf2",      XK_Fn(2),   0   ),
   99     DATA(   "k3",   "kf3",      XK_Fn(3),   0   ),
  100     DATA(   "k4",   "kf4",      XK_Fn(4),   0   ),
  101     DATA(   "k5",   "kf5",      XK_Fn(5),   0   ),
  102     DATA(   "k6",   "kf6",      XK_Fn(6),   0   ),
  103     DATA(   "k7",   "kf7",      XK_Fn(7),   0   ),
  104     DATA(   "k8",   "kf8",      XK_Fn(8),   0   ),
  105     DATA(   "k9",   "kf9",      XK_Fn(9),   0   ),
  106     DATA(   "k;",   "kf10",     XK_Fn(10),  0   ),
  107 
  108     DATA(   "F1",   "kf11",     XK_Fn(11),  0   ),
  109     DATA(   "F2",   "kf12",     XK_Fn(12),  0   ),
  110     DATA(   "F3",   "kf13",     XK_Fn(13),  0   ),
  111     DATA(   "F4",   "kf14",     XK_Fn(14),  0   ),
  112     DATA(   "F5",   "kf15",     XK_Fn(15),  0   ),
  113     DATA(   "F6",   "kf16",     XK_Fn(16),  0   ),
  114     DATA(   "F7",   "kf17",     XK_Fn(17),  0   ),
  115     DATA(   "F8",   "kf18",     XK_Fn(18),  0   ),
  116     DATA(   "F9",   "kf19",     XK_Fn(19),  0   ),
  117     DATA(   "FA",   "kf20",     XK_Fn(20),  0   ),
  118     DATA(   "FB",   "kf21",     XK_Fn(21),  0   ),
  119     DATA(   "FC",   "kf22",     XK_Fn(22),  0   ),
  120     DATA(   "FD",   "kf23",     XK_Fn(23),  0   ),
  121     DATA(   "FE",   "kf24",     XK_Fn(24),  0   ),
  122     DATA(   "FF",   "kf25",     XK_Fn(25),  0   ),
  123     DATA(   "FG",   "kf26",     XK_Fn(26),  0   ),
  124     DATA(   "FH",   "kf27",     XK_Fn(27),  0   ),
  125     DATA(   "FI",   "kf28",     XK_Fn(28),  0   ),
  126     DATA(   "FJ",   "kf29",     XK_Fn(29),  0   ),
  127     DATA(   "FK",   "kf30",     XK_Fn(30),  0   ),
  128     DATA(   "FL",   "kf31",     XK_Fn(31),  0   ),
  129     DATA(   "FM",   "kf32",     XK_Fn(32),  0   ),
  130     DATA(   "FN",   "kf33",     XK_Fn(33),  0   ),
  131     DATA(   "FO",   "kf34",     XK_Fn(34),  0   ),
  132     DATA(   "FP",   "kf35",     XK_Fn(35),  0   ),
  133 
  134     DATA(   "FQ",   "kf36",     -36,        0   ),
  135     DATA(   "FR",   "kf37",     -37,        0   ),
  136     DATA(   "FS",   "kf38",     -38,        0   ),
  137     DATA(   "FT",   "kf39",     -39,        0   ),
  138     DATA(   "FU",   "kf40",     -40,        0   ),
  139     DATA(   "FV",   "kf41",     -41,        0   ),
  140     DATA(   "FW",   "kf42",     -42,        0   ),
  141     DATA(   "FX",   "kf43",     -43,        0   ),
  142     DATA(   "FY",   "kf44",     -44,        0   ),
  143     DATA(   "FZ",   "kf45",     -45,        0   ),
  144     DATA(   "Fa",   "kf46",     -46,        0   ),
  145     DATA(   "Fb",   "kf47",     -47,        0   ),
  146     DATA(   "Fc",   "kf48",     -48,        0   ),
  147     DATA(   "Fd",   "kf49",     -49,        0   ),
  148     DATA(   "Fe",   "kf50",     -50,        0   ),
  149     DATA(   "Ff",   "kf51",     -51,        0   ),
  150     DATA(   "Fg",   "kf52",     -52,        0   ),
  151     DATA(   "Fh",   "kf53",     -53,        0   ),
  152     DATA(   "Fi",   "kf54",     -54,        0   ),
  153     DATA(   "Fj",   "kf55",     -55,        0   ),
  154     DATA(   "Fk",   "kf56",     -56,        0   ),
  155     DATA(   "Fl",   "kf57",     -57,        0   ),
  156     DATA(   "Fm",   "kf58",     -58,        0   ),
  157     DATA(   "Fn",   "kf59",     -59,        0   ),
  158     DATA(   "Fo",   "kf60",     -60,        0   ),
  159     DATA(   "Fp",   "kf61",     -61,        0   ),
  160     DATA(   "Fq",   "kf62",     -62,        0   ),
  161     DATA(   "Fr",   "kf63",     -63,        0   ),
  162 
  163     DATA(   "K1",   "ka1",      XK_KP_Home, 0   ),
  164     DATA(   "K4",   "kc1",      XK_KP_End,  0   ),
  165     DATA(   "K3",   "ka3",      XK_KP_Prior,    0   ),
  166     DATA(   "K5",   "kc3",      XK_KP_Next, 0   ),
  167 
  168 #ifdef XK_ISO_Left_Tab
  169     DATA(   "kB",   "kcbt",     XK_ISO_Left_Tab, 0  ),
  170 #endif
  171     DATA(   "kC",   "kclr",     XK_Clear,   0   ),
  172     DATA(   "kD",   "kdch1",    XK_Delete,  0   ),
  173     DATA(   "kI",   "kich1",    XK_Insert,  0   ),
  174 
  175     DATA(   "kN",   "knp",      XK_Next,    0   ),
  176     DATA(   "kP",   "kpp",      XK_Prior,   0   ),
  177     DATA(   "%c",   "kNXT",     XK_Next,    SHIFT   ),
  178     DATA(   "%e",   "kPRV",     XK_Prior,   SHIFT   ),
  179 
  180     DATA(   "&8",   "kund",     XK_Undo,    0   ),
  181     DATA(   "kb",   "kbs",      XK_BackSpace,   0   ),
  182 # if OPT_TCAP_QUERY && OPT_ISO_COLORS
  183     /* XK_COLORS is a fake code. */
  184     DATA(   "Co",   "colors",   XK_COLORS,  0   ),
  185 #  if OPT_DIRECT_COLOR
  186     /* note - termcap cannot support RGB */
  187     DATA(   "Co",   "RGB",      XK_RGB,     0   ),
  188 
  189 #  endif
  190 # endif
  191     DATA(   "TN",   "name",     XK_TCAPNAME,    0   ),
  192 #if USE_EXTENDED_NAMES
  193 #define DEXT(name, parm, code) DATA("", name, code, parm)
  194 #define D1ST(name, parm, code) DEXT("k" #name, parm, code)
  195 #define DMOD(name, parm, code) DEXT("k" #name #parm, parm, code)
  196 
  197 #define DGRP(name, code) \
  198     D1ST(name, 2, code), \
  199     DMOD(name, 3, code), \
  200     DMOD(name, 4, code), \
  201     DMOD(name, 5, code), \
  202     DMOD(name, 6, code), \
  203     DMOD(name, 7, code), \
  204     DMOD(name, 8, code)
  205 
  206     /* the terminfo codes here are ncurses extensions */
  207     /* ignore the termcap names, which are empty */
  208     DATA(   "", "kUP",      XK_Up,      SHIFT   ),
  209     DATA(   "", "kDN",      XK_Up,      SHIFT   ),
  210 
  211     DGRP(DN,   XK_Down),
  212     DGRP(LFT,  XK_Left),
  213     DGRP(RIT,  XK_Right),
  214     DGRP(UP,   XK_Up),
  215     DGRP(DC,   XK_Delete),
  216     DGRP(END,  XK_End),
  217     DGRP(HOM,  XK_Home),
  218     DGRP(IC,   XK_Insert),
  219     DGRP(NXT,  XK_Next),
  220     DGRP(PRV,  XK_Prior),
  221 #endif
  222 };
  223 #undef DATA
  224 /* *INDENT-ON* */
  225 
  226 #if OPT_TCAP_FKEYS
  227 static Boolean
  228 loadTermcapStrings(TScreen *screen)
  229 {
  230     Boolean result = True;
  231 
  232     if (screen->tcap_fkeys == 0) {
  233     Cardinal want = XtNumber(table);
  234     Cardinal have;
  235 #if !USE_TERMINFO
  236     char *area = screen->tcap_area;
  237 #endif
  238 
  239     TRACE(("loadTermcapStrings\n"));
  240     if ((screen->tcap_fkeys = TypeCallocN(char *, want)) != 0) {
  241 
  242         for (have = 0; have < want; ++have) {
  243         char name[80];
  244         char *fkey;
  245 
  246 #if USE_TERMINFO
  247         fkey = tigetstr(strcpy(name, table[have].ti));
  248 #else
  249         fkey = tgetstr(strcpy(name, table[have].tc), &area);
  250 #endif
  251         if (fkey != 0 && fkey != NO_STRING) {
  252             screen->tcap_fkeys[have] = x_strdup(fkey);
  253         } else {
  254             screen->tcap_fkeys[have] = NO_STRING;
  255         }
  256         }
  257     } else {
  258         result = False;
  259     }
  260     }
  261     return result;
  262 }
  263 #endif
  264 
  265 #if OPT_TCAP_QUERY
  266 static Boolean
  267 keyIsDistinct(XtermWidget xw, int which)
  268 {
  269     Boolean result = True;
  270 
  271     switch (xw->keyboard.type) {
  272     case keyboardIsTermcap:
  273 #if OPT_TCAP_FKEYS
  274     if (table[which].param == SHIFT) {
  275         TScreen *screen = TScreenOf(xw);
  276         Cardinal k;
  277 
  278         if (loadTermcapStrings(screen)
  279         && screen->tcap_fkeys[which] != NO_STRING) {
  280 
  281         for (k = 0; k < XtNumber(table); k++) {
  282 
  283             if (table[k].code == table[which].code
  284             && table[k].param == 0) {
  285             char *fkey;
  286 
  287             if ((fkey = screen->tcap_fkeys[k]) != NO_STRING
  288                 && !strcmp(fkey, screen->tcap_fkeys[which])) {
  289                 TRACE(("shifted/unshifted keys do not differ\n"));
  290                 result = False;
  291             }
  292             break;
  293             }
  294         }
  295         } else {
  296         /* there is no data for the shifted key */
  297         result = False;
  298         }
  299     }
  300 #endif
  301     break;
  302     /*
  303      * The vt220-keyboard will not return distinct key sequences for
  304      * shifted cursor-keys.  Just pretend they do not exist, since some
  305      * programs may be confused if we return the same data for
  306      * shifted/unshifted keys.
  307      */
  308     case keyboardIsVT220:
  309     if (table[which].param == SHIFT) {
  310         TRACE(("shifted/unshifted keys do not differ\n"));
  311         result = False;
  312     }
  313     break;
  314     case keyboardIsLegacy:
  315     case keyboardIsDefault:
  316     case keyboardIsHP:
  317     case keyboardIsSCO:
  318     case keyboardIsSun:
  319     break;
  320     }
  321 
  322     return result;
  323 }
  324 
  325 static int
  326 lookupTcapByName(const char *name)
  327 {
  328     int result = -2;
  329     Cardinal j;
  330 
  331     if (!IsEmpty(name)) {
  332     for (j = 0; j < XtNumber(table); j++) {
  333         if (!strcmp(table[j].ti, name) || !strcmp(table[j].tc, name)) {
  334         result = (int) j;
  335         break;
  336         }
  337     }
  338     }
  339 
  340     if (result >= 0) {
  341     TRACE(("lookupTcapByName(%s) tc=%s, ti=%s code %#x, param %#x\n",
  342            name,
  343            table[result].tc,
  344            table[result].ti,
  345            table[result].code,
  346            table[result].param));
  347     } else {
  348     TRACE(("lookupTcapByName(%s) FAIL\n", name));
  349     }
  350     return result;
  351 }
  352 
  353 /*
  354  * Parse the termcap/terminfo name from the string, returning a positive number
  355  * (the keysym) if found, otherwise -1.  Update the string pointer.
  356  * Returns the (shift, control) state in *state.
  357  *
  358  * This does not attempt to construct control/shift modifiers to construct
  359  * function-key values.  Instead, it sets the *fkey flag to pass to Input()
  360  * and bypass the lookup of keysym altogether.
  361  */
  362 int
  363 xtermcapKeycode(XtermWidget xw, const char **params, unsigned *state, Bool *fkey)
  364 {
  365     const TCAPINFO *data;
  366     int code = -1;
  367     char *name;
  368     const char *p;
  369 
  370     TRACE(("xtermcapKeycode(%s)\n", *params));
  371 
  372     /* Convert hex encoded name to ascii */
  373     name = x_decode_hex(*params, &p);
  374     *params = p;
  375 
  376     *state = 0;
  377     *fkey = False;
  378 
  379     if (!IsEmpty(name) && (*p == 0 || *p == ';')) {
  380     int which;
  381 
  382     if ((which = lookupTcapByName(name)) >= 0) {
  383         if (keyIsDistinct(xw, which)) {
  384         data = table + which;
  385         code = data->code;
  386         *state = xtermParamToState(xw, data->param);
  387         if (IsFunctionKey(code)) {
  388             *fkey = True;
  389         } else if (code < 0) {
  390             *fkey = True;
  391             code = XK_Fn((-code));
  392         }
  393 #if OPT_SUN_FUNC_KEYS
  394         if (*fkey && xw->keyboard.type == keyboardIsSun) {
  395             int num = code - XK_Fn(0);
  396 
  397             /* match function-key case in sunfuncvalue() */
  398             if (num > 20) {
  399             if (num <= 30 || num > 47) {
  400                 code = -1;
  401             } else {
  402                 code -= 10;
  403                 switch (num) {
  404                 case 37:    /* khome */
  405                 case 39:    /* kpp */
  406                 case 41:    /* kb2 */
  407                 case 43:    /* kend */
  408                 case 45:    /* knp */
  409                 code = -1;
  410                 break;
  411                 }
  412             }
  413             }
  414         }
  415 #endif
  416         } else {
  417         TRACE(("... name ok, data not ok\n"));
  418         code = -1;
  419         }
  420     } else {
  421         TRACE(("... name not ok\n"));
  422         code = -2;
  423     }
  424     } else {
  425     TRACE(("... name not ok\n"));
  426     code = -2;
  427     }
  428 
  429     TRACE(("... xtermcapKeycode(%s, %u, %d) -> %#06x\n",
  430        name, *state, *fkey, code));
  431     free(name);
  432     return code;
  433 }
  434 #endif /* OPT_TCAP_QUERY */
  435 
  436 #if OPT_TCAP_FKEYS
  437 static int
  438 nextTcapByCode(int code, unsigned param, int last)
  439 {
  440     int result = -1;
  441     int n;
  442 
  443     TRACE(("lookupTcapByCode %#x:%#x\n", code, param));
  444     for (n = last + 1; n < (int) XtNumber(table); n++) {
  445     if (table[n].code == code &&
  446         table[n].param == param) {
  447         TRACE(("->lookupTcapByCode %d:%s\n", n, table[n].ti));
  448         result = n;
  449         break;
  450     }
  451     }
  452     return result;
  453 }
  454 
  455 static int
  456 firstTcapByCode(int code, unsigned param)
  457 {
  458     return nextTcapByCode(code, param, -1);
  459 }
  460 
  461 int
  462 xtermcapString(XtermWidget xw, int keycode, unsigned mask)
  463 {
  464     int result = 0;
  465     unsigned param = xtermStateToParam(xw, mask);
  466     int which;
  467 
  468     if ((which = firstTcapByCode(keycode, param)) >= 0) {
  469     TScreen *screen = TScreenOf(xw);
  470 
  471     if (loadTermcapStrings(screen)) {
  472         do {
  473         char *fkey;
  474 
  475         if ((fkey = screen->tcap_fkeys[which]) != NO_STRING) {
  476             StringInput(xw, (Char *) fkey, strlen(fkey));
  477             result = 1;
  478             break;
  479         }
  480         } while ((which = nextTcapByCode(keycode, param, which)) >= 0);
  481     }
  482     }
  483 
  484     TRACE(("xtermcapString(keycode=%#x, mask=%#x) ->%d\n",
  485        keycode, mask, result));
  486 
  487     return result;
  488 }
  489 #endif /* OPT_TCAP_FKEYS */
  490 
  491 #endif /* OPT_TCAP_QUERY || OPT_TCAP_FKEYS */
  492 
  493 /*
  494  * If we're linked to terminfo, tgetent() will return an empty buffer.  We
  495  * cannot use that to adjust the $TERMCAP variable.
  496  */
  497 Bool
  498 get_termcap(XtermWidget xw, char *name)
  499 {
  500 #if USE_TERMINFO
  501     int ignored = 0;
  502 #endif
  503     char *buffer = get_tcap_buffer(xw);
  504 
  505     *buffer = 0;        /* initialize, in case we're using terminfo's tgetent */
  506 
  507 #if USE_EXTENDED_NAMES
  508     use_extended_names(TRUE);
  509 #endif
  510     if (!IsEmpty(name)) {
  511     if (TcapInit(buffer, name)) {
  512         TRACE(("get_termcap(%s) succeeded (%s)\n", name,
  513            (*buffer
  514             ? "ok:termcap, we can update $TERMCAP"
  515             : "assuming this is terminfo")));
  516         return True;
  517     } else {
  518         *buffer = 0;    /* just in case */
  519     }
  520     }
  521     return False;
  522 }
  523 
  524 /*
  525  * Retrieve the termcap-buffer.
  526  */
  527 char *
  528 get_tcap_buffer(XtermWidget xw)
  529 {
  530     TScreen *screen = TScreenOf(xw);
  531     char *buffer;
  532 
  533 #if OPT_TEK4014
  534     if (TEK4014_ACTIVE(xw)) {
  535     buffer = TekScreenOf(tekWidget)->tcapbuf;
  536     } else
  537 #endif
  538     {
  539     buffer = screen->tcapbuf;
  540     }
  541     return buffer;
  542 }
  543 
  544 /*
  545  * Retrieve the erase-key, for initialization in main program.
  546  */
  547 char *
  548 get_tcap_erase(XtermWidget xw)
  549 {
  550 #if !USE_TERMINFO
  551     char *area = TScreenOf(xw)->tcap_area;
  552 #endif
  553     char *fkey;
  554 
  555     (void) xw;
  556 #if USE_TERMINFO
  557     fkey = tigetstr("kbs");
  558 #else
  559     fkey = tgetstr("kb", &area);
  560 #endif
  561 
  562     if (fkey == NO_STRING)
  563     fkey = 0;
  564     if (fkey != 0)
  565     fkey = x_strdup(fkey);
  566     return fkey;
  567 }
  568 
  569 /*
  570  * A legal termcap (or terminfo) name consists solely of graphic characters,
  571  * excluding the punctuation used to delimit fields of the source description.
  572  */
  573 static Bool
  574 isLegalTcapName(const char *name)
  575 {
  576     Bool result = False;
  577 
  578     if (*name != '\0') {
  579     int length = 0;
  580     result = True;
  581     while (*name != '\0') {
  582         if (++length < 32 && isgraph(CharOf(*name))) {
  583         if (strchr("\\|,:'\"", *name) != 0) {
  584             result = False;
  585             break;
  586         }
  587         } else {
  588         result = False;
  589         break;
  590         }
  591         ++name;
  592     }
  593     }
  594 
  595     return result;
  596 }
  597 
  598 void
  599 set_termcap(XtermWidget xw, const char *name)
  600 {
  601     Boolean success = False;
  602 #if USE_TERMINFO
  603     int ignored = 0;
  604 #else
  605     TScreen *screen = TScreenOf(xw);
  606     char buffer[sizeof(screen->tcapbuf)];
  607 #endif
  608 
  609     TRACE(("set_termcap(%s)\n", NonNull(name)));
  610     if (IsEmpty(name)) {
  611     Bell(xw, XkbBI_MinorError, 0);
  612     } else {
  613     const char *temp;
  614     char *value;
  615 
  616     if ((value = x_decode_hex(name, &temp)) != 0) {
  617         if (*temp == '\0' && isLegalTcapName(value)) {
  618         if (TcapInit(buffer, value)) {
  619             TRACE(("...set_termcap(%s)\n", NonNull(value)));
  620 #if !USE_TERMINFO
  621             memcpy(screen->tcapbuf, buffer, sizeof(buffer));
  622 #endif
  623             free_termcap(xw);
  624             success = True;
  625         }
  626         }
  627         free(value);
  628     }
  629     }
  630     if (!success)
  631     Bell(xw, XkbBI_MinorError, 0);
  632 }
  633 
  634 void
  635 free_termcap(XtermWidget xw)
  636 {
  637 #if OPT_TCAP_FKEYS
  638     TScreen *screen = TScreenOf(xw);
  639 
  640     if (screen->tcap_fkeys != 0) {
  641     Cardinal want = XtNumber(table);
  642     Cardinal have;
  643 
  644     for (have = 0; have < want; ++have) {
  645         char *fkey = screen->tcap_fkeys[have];
  646         if (fkey != NO_STRING) {
  647         free(fkey);
  648         }
  649     }
  650     FreeAndNull(screen->tcap_fkeys);
  651     }
  652 #endif
  653     TcapFree();
  654 }