15104ee6eSmrg/* $XTermId: xtermcap.c,v 1.63 2024/12/01 20:17:29 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/* 45104ee6eSmrg * Copyright 2007-2023,2024 by Thomas E. Dickey 5d522f475Smrg * 6d522f475Smrg * All Rights Reserved 7d522f475Smrg * 8d522f475Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9d522f475Smrg * copy of this software and associated documentation files (the 10d522f475Smrg * "Software"), to deal in the Software without restriction, including 11d522f475Smrg * without limitation the rights to use, copy, modify, merge, publish, 12d522f475Smrg * distribute, sublicense, and/or sell copies of the Software, and to 13d522f475Smrg * permit persons to whom the Software is furnished to do so, subject to 14d522f475Smrg * the following conditions: 15d522f475Smrg * 16d522f475Smrg * The above copyright notice and this permission notice shall be included 17d522f475Smrg * in all copies or substantial portions of the Software. 18d522f475Smrg * 19d522f475Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20d522f475Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21d522f475Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22d522f475Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23d522f475Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24d522f475Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25d522f475Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26d522f475Smrg * 27d522f475Smrg * Except as contained in this notice, the name(s) of the above copyright 28d522f475Smrg * holders shall not be used in advertising or otherwise to promote the 29d522f475Smrg * sale, use or other dealings in this Software without prior written 30d522f475Smrg * authorization. 31d522f475Smrg */ 32d522f475Smrg 33d522f475Smrg#include <xtermcap.h> 3420d2c4d2Smrg#include <data.h> 35d522f475Smrg 36d522f475Smrg#include <X11/keysym.h> 3720d2c4d2Smrg#include <ctype.h> 38d522f475Smrg 39d522f475Smrg#include <xstrings.h> 40d522f475Smrg 412eaa94a1Schristos#if USE_TERMINFO && defined(NCURSES_VERSION) && defined(HAVE_USE_EXTENDED_NAMES) 422eaa94a1Schristos#define USE_EXTENDED_NAMES 1 432eaa94a1Schristos#else 442eaa94a1Schristos#define USE_EXTENDED_NAMES 0 452eaa94a1Schristos#endif 462eaa94a1Schristos 4720d2c4d2Smrg#if USE_TERMINFO 4820d2c4d2Smrg#define TcapInit(buffer, name) (setupterm(name, fileno(stdout), &ignored) == OK) 49f2e35a3aSmrg#define TcapFree() (del_curterm(cur_term)) 5020d2c4d2Smrg#else 5120d2c4d2Smrg#define TcapInit(buffer, name) (tgetent(buffer, name) == 1) 52f2e35a3aSmrg#define TcapFree() /*nothing */ 5320d2c4d2Smrg#endif 5420d2c4d2Smrg 5520d2c4d2Smrg#define NO_STRING (char *)(-1) 5620d2c4d2Smrg 57d522f475Smrg#if OPT_TCAP_QUERY || OPT_TCAP_FKEYS 58d522f475Smrg 59956cc18dSsnj#define SHIFT (MOD_NONE + MOD_SHIFT) 60956cc18dSsnj 61d522f475Smrgtypedef struct { 6220d2c4d2Smrg const char *tc; 6320d2c4d2Smrg const char *ti; 64d522f475Smrg int code; 65956cc18dSsnj unsigned param; /* see xtermStateToParam() */ 66d522f475Smrg} TCAPINFO; 67d522f475Smrg/* *INDENT-OFF* */ 68d522f475Smrg#define DATA(tc,ti,x,y) { tc, ti, x, y } 69e39b573cSmrgstatic const TCAPINFO table[] = { 70956cc18dSsnj /* tcap terminfo code state */ 71d522f475Smrg DATA( "%1", "khlp", XK_Help, 0 ), 72956cc18dSsnj DATA( "#1", "kHLP", XK_Help, SHIFT ), 73d522f475Smrg DATA( "@0", "kfnd", XK_Find, 0 ), 74956cc18dSsnj DATA( "*0", "kFND", XK_Find, SHIFT ), 75d522f475Smrg DATA( "*6", "kslt", XK_Select, 0 ), 76956cc18dSsnj DATA( "#6", "kSLT", XK_Select, SHIFT ), 77d522f475Smrg 78d522f475Smrg DATA( "kh", "khome", XK_Home, 0 ), 79956cc18dSsnj DATA( "#2", "kHOM", XK_Home, SHIFT ), 80d522f475Smrg DATA( "@7", "kend", XK_End, 0 ), 81956cc18dSsnj DATA( "*7", "kEND", XK_End, SHIFT ), 82d522f475Smrg 83d522f475Smrg DATA( "kl", "kcub1", XK_Left, 0 ), 84d522f475Smrg DATA( "kr", "kcuf1", XK_Right, 0 ), 85d522f475Smrg DATA( "ku", "kcuu1", XK_Up, 0 ), 86d522f475Smrg DATA( "kd", "kcud1", XK_Down, 0 ), 87d522f475Smrg 88956cc18dSsnj DATA( "#4", "kLFT", XK_Left, SHIFT ), 89956cc18dSsnj DATA( "%i", "kRIT", XK_Right, SHIFT ), 90e39b573cSmrg DATA( "kF", "kind", XK_Down, SHIFT ), 91e39b573cSmrg DATA( "kR", "kri", XK_Up, SHIFT ), 92d522f475Smrg 93d522f475Smrg DATA( "k1", "kf1", XK_Fn(1), 0 ), 94d522f475Smrg DATA( "k2", "kf2", XK_Fn(2), 0 ), 95d522f475Smrg DATA( "k3", "kf3", XK_Fn(3), 0 ), 96d522f475Smrg DATA( "k4", "kf4", XK_Fn(4), 0 ), 97d522f475Smrg DATA( "k5", "kf5", XK_Fn(5), 0 ), 98d522f475Smrg DATA( "k6", "kf6", XK_Fn(6), 0 ), 99d522f475Smrg DATA( "k7", "kf7", XK_Fn(7), 0 ), 100d522f475Smrg DATA( "k8", "kf8", XK_Fn(8), 0 ), 101d522f475Smrg DATA( "k9", "kf9", XK_Fn(9), 0 ), 102d522f475Smrg DATA( "k;", "kf10", XK_Fn(10), 0 ), 103d522f475Smrg 104d522f475Smrg DATA( "F1", "kf11", XK_Fn(11), 0 ), 105d522f475Smrg DATA( "F2", "kf12", XK_Fn(12), 0 ), 106d522f475Smrg DATA( "F3", "kf13", XK_Fn(13), 0 ), 107d522f475Smrg DATA( "F4", "kf14", XK_Fn(14), 0 ), 108d522f475Smrg DATA( "F5", "kf15", XK_Fn(15), 0 ), 109d522f475Smrg DATA( "F6", "kf16", XK_Fn(16), 0 ), 110d522f475Smrg DATA( "F7", "kf17", XK_Fn(17), 0 ), 111d522f475Smrg DATA( "F8", "kf18", XK_Fn(18), 0 ), 112d522f475Smrg DATA( "F9", "kf19", XK_Fn(19), 0 ), 113d522f475Smrg DATA( "FA", "kf20", XK_Fn(20), 0 ), 114d522f475Smrg DATA( "FB", "kf21", XK_Fn(21), 0 ), 115d522f475Smrg DATA( "FC", "kf22", XK_Fn(22), 0 ), 116d522f475Smrg DATA( "FD", "kf23", XK_Fn(23), 0 ), 117d522f475Smrg DATA( "FE", "kf24", XK_Fn(24), 0 ), 118d522f475Smrg DATA( "FF", "kf25", XK_Fn(25), 0 ), 119d522f475Smrg DATA( "FG", "kf26", XK_Fn(26), 0 ), 120d522f475Smrg DATA( "FH", "kf27", XK_Fn(27), 0 ), 121d522f475Smrg DATA( "FI", "kf28", XK_Fn(28), 0 ), 122d522f475Smrg DATA( "FJ", "kf29", XK_Fn(29), 0 ), 123d522f475Smrg DATA( "FK", "kf30", XK_Fn(30), 0 ), 124d522f475Smrg DATA( "FL", "kf31", XK_Fn(31), 0 ), 125d522f475Smrg DATA( "FM", "kf32", XK_Fn(32), 0 ), 126d522f475Smrg DATA( "FN", "kf33", XK_Fn(33), 0 ), 127d522f475Smrg DATA( "FO", "kf34", XK_Fn(34), 0 ), 128d522f475Smrg DATA( "FP", "kf35", XK_Fn(35), 0 ), 129d522f475Smrg 130d522f475Smrg DATA( "FQ", "kf36", -36, 0 ), 131d522f475Smrg DATA( "FR", "kf37", -37, 0 ), 132d522f475Smrg DATA( "FS", "kf38", -38, 0 ), 133d522f475Smrg DATA( "FT", "kf39", -39, 0 ), 134d522f475Smrg DATA( "FU", "kf40", -40, 0 ), 135d522f475Smrg DATA( "FV", "kf41", -41, 0 ), 136d522f475Smrg DATA( "FW", "kf42", -42, 0 ), 137d522f475Smrg DATA( "FX", "kf43", -43, 0 ), 138d522f475Smrg DATA( "FY", "kf44", -44, 0 ), 139d522f475Smrg DATA( "FZ", "kf45", -45, 0 ), 140d522f475Smrg DATA( "Fa", "kf46", -46, 0 ), 141d522f475Smrg DATA( "Fb", "kf47", -47, 0 ), 142d522f475Smrg DATA( "Fc", "kf48", -48, 0 ), 143d522f475Smrg DATA( "Fd", "kf49", -49, 0 ), 144d522f475Smrg DATA( "Fe", "kf50", -50, 0 ), 145d522f475Smrg DATA( "Ff", "kf51", -51, 0 ), 146d522f475Smrg DATA( "Fg", "kf52", -52, 0 ), 147d522f475Smrg DATA( "Fh", "kf53", -53, 0 ), 148d522f475Smrg DATA( "Fi", "kf54", -54, 0 ), 149d522f475Smrg DATA( "Fj", "kf55", -55, 0 ), 150d522f475Smrg DATA( "Fk", "kf56", -56, 0 ), 151d522f475Smrg DATA( "Fl", "kf57", -57, 0 ), 152d522f475Smrg DATA( "Fm", "kf58", -58, 0 ), 153d522f475Smrg DATA( "Fn", "kf59", -59, 0 ), 154d522f475Smrg DATA( "Fo", "kf60", -60, 0 ), 155d522f475Smrg DATA( "Fp", "kf61", -61, 0 ), 156d522f475Smrg DATA( "Fq", "kf62", -62, 0 ), 157d522f475Smrg DATA( "Fr", "kf63", -63, 0 ), 158d522f475Smrg 159d522f475Smrg DATA( "K1", "ka1", XK_KP_Home, 0 ), 160d522f475Smrg DATA( "K4", "kc1", XK_KP_End, 0 ), 1612eaa94a1Schristos DATA( "K3", "ka3", XK_KP_Prior, 0 ), 1622eaa94a1Schristos DATA( "K5", "kc3", XK_KP_Next, 0 ), 163d522f475Smrg 164d522f475Smrg#ifdef XK_ISO_Left_Tab 165d522f475Smrg DATA( "kB", "kcbt", XK_ISO_Left_Tab, 0 ), 166d522f475Smrg#endif 167d522f475Smrg DATA( "kC", "kclr", XK_Clear, 0 ), 168d522f475Smrg DATA( "kD", "kdch1", XK_Delete, 0 ), 169d522f475Smrg DATA( "kI", "kich1", XK_Insert, 0 ), 17020d2c4d2Smrg 171d522f475Smrg DATA( "kN", "knp", XK_Next, 0 ), 172d522f475Smrg DATA( "kP", "kpp", XK_Prior, 0 ), 17320d2c4d2Smrg DATA( "%c", "kNXT", XK_Next, SHIFT ), 17420d2c4d2Smrg DATA( "%e", "kPRV", XK_Prior, SHIFT ), 17520d2c4d2Smrg 1762eaa94a1Schristos DATA( "&8", "kund", XK_Undo, 0 ), 177d522f475Smrg DATA( "kb", "kbs", XK_BackSpace, 0 ), 178d522f475Smrg# if OPT_TCAP_QUERY && OPT_ISO_COLORS 179d522f475Smrg /* XK_COLORS is a fake code. */ 180d522f475Smrg DATA( "Co", "colors", XK_COLORS, 0 ), 181f2e35a3aSmrg# if OPT_DIRECT_COLOR 182f2e35a3aSmrg /* note - termcap cannot support RGB */ 183f2e35a3aSmrg DATA( "Co", "RGB", XK_RGB, 0 ), 184f2e35a3aSmrg 185f2e35a3aSmrg# endif 186d522f475Smrg# endif 18720d2c4d2Smrg DATA( "TN", "name", XK_TCAPNAME, 0 ), 1882eaa94a1Schristos#if USE_EXTENDED_NAMES 189d522f475Smrg#define DEXT(name, parm, code) DATA("", name, code, parm) 190d522f475Smrg#define D1ST(name, parm, code) DEXT("k" #name, parm, code) 191d522f475Smrg#define DMOD(name, parm, code) DEXT("k" #name #parm, parm, code) 192d522f475Smrg 193d522f475Smrg#define DGRP(name, code) \ 194d522f475Smrg D1ST(name, 2, code), \ 195d522f475Smrg DMOD(name, 3, code), \ 196d522f475Smrg DMOD(name, 4, code), \ 197d522f475Smrg DMOD(name, 5, code), \ 198d522f475Smrg DMOD(name, 6, code), \ 199d522f475Smrg DMOD(name, 7, code), \ 200d522f475Smrg DMOD(name, 8, code) 201d522f475Smrg 20220d2c4d2Smrg /* the terminfo codes here are ncurses extensions */ 20320d2c4d2Smrg /* ignore the termcap names, which are empty */ 20420d2c4d2Smrg DATA( "", "kUP", XK_Up, SHIFT ), 20520d2c4d2Smrg DATA( "", "kDN", XK_Up, SHIFT ), 20620d2c4d2Smrg 207d522f475Smrg DGRP(DN, XK_Down), 208d522f475Smrg DGRP(LFT, XK_Left), 209d522f475Smrg DGRP(RIT, XK_Right), 210d522f475Smrg DGRP(UP, XK_Up), 211d522f475Smrg DGRP(DC, XK_Delete), 212d522f475Smrg DGRP(END, XK_End), 213d522f475Smrg DGRP(HOM, XK_Home), 214d522f475Smrg DGRP(IC, XK_Insert), 215d522f475Smrg DGRP(NXT, XK_Next), 216d522f475Smrg DGRP(PRV, XK_Prior), 217d522f475Smrg#endif 218d522f475Smrg}; 219d522f475Smrg#undef DATA 220d522f475Smrg/* *INDENT-ON* */ 221d522f475Smrg 222956cc18dSsnj#if OPT_TCAP_FKEYS 223894e0ac8Smrgstatic Boolean 224894e0ac8SmrgloadTermcapStrings(TScreen *screen) 225956cc18dSsnj{ 226894e0ac8Smrg Boolean result = True; 227894e0ac8Smrg 2285104ee6eSmrg if (screen->tcap_fkeys == NULL) { 229956cc18dSsnj Cardinal want = XtNumber(table); 230956cc18dSsnj Cardinal have; 231f2e35a3aSmrg#if !USE_TERMINFO 232956cc18dSsnj char *area = screen->tcap_area; 233956cc18dSsnj#endif 234956cc18dSsnj 23520d2c4d2Smrg TRACE(("loadTermcapStrings\n")); 2365104ee6eSmrg if ((screen->tcap_fkeys = TypeCallocN(char *, want)) != NULL) { 2372e4f8982Smrg 238956cc18dSsnj for (have = 0; have < want; ++have) { 2392e4f8982Smrg char name[80]; 2402e4f8982Smrg char *fkey; 2412e4f8982Smrg 242f2e35a3aSmrg#if USE_TERMINFO 24320d2c4d2Smrg fkey = tigetstr(strcpy(name, table[have].ti)); 244956cc18dSsnj#else 24520d2c4d2Smrg fkey = tgetstr(strcpy(name, table[have].tc), &area); 246956cc18dSsnj#endif 2475104ee6eSmrg if (fkey != NULL && fkey != NO_STRING) { 248956cc18dSsnj screen->tcap_fkeys[have] = x_strdup(fkey); 249956cc18dSsnj } else { 250956cc18dSsnj screen->tcap_fkeys[have] = NO_STRING; 251956cc18dSsnj } 252956cc18dSsnj } 253894e0ac8Smrg } else { 254894e0ac8Smrg result = False; 255956cc18dSsnj } 256956cc18dSsnj } 257894e0ac8Smrg return result; 258956cc18dSsnj} 259956cc18dSsnj#endif 260956cc18dSsnj 261d522f475Smrg#if OPT_TCAP_QUERY 262956cc18dSsnjstatic Boolean 263956cc18dSsnjkeyIsDistinct(XtermWidget xw, int which) 264d522f475Smrg{ 265956cc18dSsnj Boolean result = True; 266d522f475Smrg 267956cc18dSsnj switch (xw->keyboard.type) { 268956cc18dSsnj case keyboardIsTermcap: 269956cc18dSsnj#if OPT_TCAP_FKEYS 270956cc18dSsnj if (table[which].param == SHIFT) { 271956cc18dSsnj TScreen *screen = TScreenOf(xw); 272956cc18dSsnj Cardinal k; 273956cc18dSsnj 274894e0ac8Smrg if (loadTermcapStrings(screen) 275894e0ac8Smrg && screen->tcap_fkeys[which] != NO_STRING) { 2762e4f8982Smrg 277956cc18dSsnj for (k = 0; k < XtNumber(table); k++) { 2782e4f8982Smrg 279956cc18dSsnj if (table[k].code == table[which].code 280956cc18dSsnj && table[k].param == 0) { 2812e4f8982Smrg char *fkey; 2822e4f8982Smrg 283956cc18dSsnj if ((fkey = screen->tcap_fkeys[k]) != NO_STRING 284956cc18dSsnj && !strcmp(fkey, screen->tcap_fkeys[which])) { 285956cc18dSsnj TRACE(("shifted/unshifted keys do not differ\n")); 286956cc18dSsnj result = False; 287956cc18dSsnj } 288956cc18dSsnj break; 289956cc18dSsnj } 290956cc18dSsnj } 291956cc18dSsnj } else { 292956cc18dSsnj /* there is no data for the shifted key */ 293f2e35a3aSmrg result = False; 294d522f475Smrg } 295d522f475Smrg } 296956cc18dSsnj#endif 297956cc18dSsnj break; 298956cc18dSsnj /* 299956cc18dSsnj * The vt220-keyboard will not return distinct key sequences for 300956cc18dSsnj * shifted cursor-keys. Just pretend they do not exist, since some 301956cc18dSsnj * programs may be confused if we return the same data for 302956cc18dSsnj * shifted/unshifted keys. 303956cc18dSsnj */ 304956cc18dSsnj case keyboardIsVT220: 305956cc18dSsnj if (table[which].param == SHIFT) { 306956cc18dSsnj TRACE(("shifted/unshifted keys do not differ\n")); 307956cc18dSsnj result = False; 308956cc18dSsnj } 309956cc18dSsnj break; 310956cc18dSsnj case keyboardIsLegacy: 311956cc18dSsnj case keyboardIsDefault: 312956cc18dSsnj case keyboardIsHP: 313956cc18dSsnj case keyboardIsSCO: 314956cc18dSsnj case keyboardIsSun: 315956cc18dSsnj break; 316d522f475Smrg } 3172eaa94a1Schristos 318956cc18dSsnj return result; 319956cc18dSsnj} 320956cc18dSsnj 321956cc18dSsnjstatic int 322956cc18dSsnjlookupTcapByName(const char *name) 323956cc18dSsnj{ 324956cc18dSsnj int result = -2; 325956cc18dSsnj Cardinal j; 326956cc18dSsnj 32720d2c4d2Smrg if (!IsEmpty(name)) { 328956cc18dSsnj for (j = 0; j < XtNumber(table); j++) { 329956cc18dSsnj if (!strcmp(table[j].ti, name) || !strcmp(table[j].tc, name)) { 330956cc18dSsnj result = (int) j; 331956cc18dSsnj break; 332956cc18dSsnj } 333956cc18dSsnj } 3342eaa94a1Schristos } 3352eaa94a1Schristos 336956cc18dSsnj if (result >= 0) { 337956cc18dSsnj TRACE(("lookupTcapByName(%s) tc=%s, ti=%s code %#x, param %#x\n", 338956cc18dSsnj name, 339956cc18dSsnj table[result].tc, 340956cc18dSsnj table[result].ti, 341956cc18dSsnj table[result].code, 342956cc18dSsnj table[result].param)); 3432eaa94a1Schristos } else { 3442eaa94a1Schristos TRACE(("lookupTcapByName(%s) FAIL\n", name)); 3452eaa94a1Schristos } 346d522f475Smrg return result; 347d522f475Smrg} 348d522f475Smrg 349d522f475Smrg/* 350d522f475Smrg * Parse the termcap/terminfo name from the string, returning a positive number 351d522f475Smrg * (the keysym) if found, otherwise -1. Update the string pointer. 352d522f475Smrg * Returns the (shift, control) state in *state. 353d522f475Smrg * 354d522f475Smrg * This does not attempt to construct control/shift modifiers to construct 355d522f475Smrg * function-key values. Instead, it sets the *fkey flag to pass to Input() 356d522f475Smrg * and bypass the lookup of keysym altogether. 357d522f475Smrg */ 358d522f475Smrgint 359894e0ac8SmrgxtermcapKeycode(XtermWidget xw, const char **params, unsigned *state, Bool *fkey) 360d522f475Smrg{ 361e39b573cSmrg const TCAPINFO *data; 362d522f475Smrg int code = -1; 36320d2c4d2Smrg char *name; 36420d2c4d2Smrg const char *p; 365d522f475Smrg 366d522f475Smrg TRACE(("xtermcapKeycode(%s)\n", *params)); 367d522f475Smrg 368d522f475Smrg /* Convert hex encoded name to ascii */ 36920d2c4d2Smrg name = x_decode_hex(*params, &p); 370d522f475Smrg *params = p; 371d522f475Smrg 372d522f475Smrg *state = 0; 373d522f475Smrg *fkey = False; 374d522f475Smrg 37520d2c4d2Smrg if (!IsEmpty(name) && (*p == 0 || *p == ';')) { 3762e4f8982Smrg int which; 3772e4f8982Smrg 378956cc18dSsnj if ((which = lookupTcapByName(name)) >= 0) { 379956cc18dSsnj if (keyIsDistinct(xw, which)) { 380956cc18dSsnj data = table + which; 381956cc18dSsnj code = data->code; 382956cc18dSsnj *state = xtermParamToState(xw, data->param); 383956cc18dSsnj if (IsFunctionKey(code)) { 384956cc18dSsnj *fkey = True; 385956cc18dSsnj } else if (code < 0) { 386956cc18dSsnj *fkey = True; 387956cc18dSsnj code = XK_Fn((-code)); 388956cc18dSsnj } 389d522f475Smrg#if OPT_SUN_FUNC_KEYS 390956cc18dSsnj if (*fkey && xw->keyboard.type == keyboardIsSun) { 391956cc18dSsnj int num = code - XK_Fn(0); 392956cc18dSsnj 393956cc18dSsnj /* match function-key case in sunfuncvalue() */ 394956cc18dSsnj if (num > 20) { 395956cc18dSsnj if (num <= 30 || num > 47) { 396d522f475Smrg code = -1; 397956cc18dSsnj } else { 398956cc18dSsnj code -= 10; 399956cc18dSsnj switch (num) { 400956cc18dSsnj case 37: /* khome */ 401956cc18dSsnj case 39: /* kpp */ 402956cc18dSsnj case 41: /* kb2 */ 403956cc18dSsnj case 43: /* kend */ 404956cc18dSsnj case 45: /* knp */ 405956cc18dSsnj code = -1; 406956cc18dSsnj break; 407956cc18dSsnj } 408d522f475Smrg } 409d522f475Smrg } 410d522f475Smrg } 411d522f475Smrg#endif 412956cc18dSsnj } else { 413956cc18dSsnj TRACE(("... name ok, data not ok\n")); 414956cc18dSsnj code = -1; 415956cc18dSsnj } 416956cc18dSsnj } else { 417956cc18dSsnj TRACE(("... name not ok\n")); 418956cc18dSsnj code = -2; 419d522f475Smrg } 420956cc18dSsnj } else { 421956cc18dSsnj TRACE(("... name not ok\n")); 422956cc18dSsnj code = -2; 423d522f475Smrg } 424d522f475Smrg 425d522f475Smrg TRACE(("... xtermcapKeycode(%s, %u, %d) -> %#06x\n", 426d522f475Smrg name, *state, *fkey, code)); 42720d2c4d2Smrg free(name); 428d522f475Smrg return code; 429d522f475Smrg} 430d522f475Smrg#endif /* OPT_TCAP_QUERY */ 431d522f475Smrg 432d522f475Smrg#if OPT_TCAP_FKEYS 43320d2c4d2Smrgstatic int 43420d2c4d2SmrgnextTcapByCode(int code, unsigned param, int last) 435d522f475Smrg{ 43620d2c4d2Smrg int result = -1; 43720d2c4d2Smrg int n; 438d522f475Smrg 439956cc18dSsnj TRACE(("lookupTcapByCode %#x:%#x\n", code, param)); 44020d2c4d2Smrg for (n = last + 1; n < (int) XtNumber(table); n++) { 441d522f475Smrg if (table[n].code == code && 442956cc18dSsnj table[n].param == param) { 443956cc18dSsnj TRACE(("->lookupTcapByCode %d:%s\n", n, table[n].ti)); 44420d2c4d2Smrg result = n; 445d522f475Smrg break; 446d522f475Smrg } 447d522f475Smrg } 448d522f475Smrg return result; 449d522f475Smrg} 450d522f475Smrg 45120d2c4d2Smrgstatic int 45220d2c4d2SmrgfirstTcapByCode(int code, unsigned param) 45320d2c4d2Smrg{ 45420d2c4d2Smrg return nextTcapByCode(code, param, -1); 45520d2c4d2Smrg} 45620d2c4d2Smrg 457d522f475Smrgint 458d522f475SmrgxtermcapString(XtermWidget xw, int keycode, unsigned mask) 459d522f475Smrg{ 460d522f475Smrg int result = 0; 461d522f475Smrg unsigned param = xtermStateToParam(xw, mask); 46220d2c4d2Smrg int which; 463d522f475Smrg 46420d2c4d2Smrg if ((which = firstTcapByCode(keycode, param)) >= 0) { 465d522f475Smrg TScreen *screen = TScreenOf(xw); 466d522f475Smrg 467894e0ac8Smrg if (loadTermcapStrings(screen)) { 46820d2c4d2Smrg do { 4692e4f8982Smrg char *fkey; 4702e4f8982Smrg 47120d2c4d2Smrg if ((fkey = screen->tcap_fkeys[which]) != NO_STRING) { 47220d2c4d2Smrg StringInput(xw, (Char *) fkey, strlen(fkey)); 47320d2c4d2Smrg result = 1; 47420d2c4d2Smrg break; 47520d2c4d2Smrg } 47620d2c4d2Smrg } while ((which = nextTcapByCode(keycode, param, which)) >= 0); 477d522f475Smrg } 478d522f475Smrg } 479d522f475Smrg 480d522f475Smrg TRACE(("xtermcapString(keycode=%#x, mask=%#x) ->%d\n", 481d522f475Smrg keycode, mask, result)); 482d522f475Smrg 483d522f475Smrg return result; 484d522f475Smrg} 485d522f475Smrg#endif /* OPT_TCAP_FKEYS */ 486d522f475Smrg 487d522f475Smrg#endif /* OPT_TCAP_QUERY || OPT_TCAP_FKEYS */ 48820d2c4d2Smrg 489d522f475Smrg/* 490d522f475Smrg * If we're linked to terminfo, tgetent() will return an empty buffer. We 491d522f475Smrg * cannot use that to adjust the $TERMCAP variable. 492d522f475Smrg */ 493d522f475SmrgBool 49420d2c4d2Smrgget_termcap(XtermWidget xw, char *name) 495d522f475Smrg{ 49620d2c4d2Smrg#if USE_TERMINFO 49720d2c4d2Smrg int ignored = 0; 49820d2c4d2Smrg#endif 49920d2c4d2Smrg char *buffer = get_tcap_buffer(xw); 50020d2c4d2Smrg 501d522f475Smrg *buffer = 0; /* initialize, in case we're using terminfo's tgetent */ 502d522f475Smrg 5032eaa94a1Schristos#if USE_EXTENDED_NAMES 504d522f475Smrg use_extended_names(TRUE); 505d522f475Smrg#endif 50620d2c4d2Smrg if (!IsEmpty(name)) { 50720d2c4d2Smrg if (TcapInit(buffer, name)) { 508d522f475Smrg TRACE(("get_termcap(%s) succeeded (%s)\n", name, 509d522f475Smrg (*buffer 510d522f475Smrg ? "ok:termcap, we can update $TERMCAP" 511d522f475Smrg : "assuming this is terminfo"))); 512d522f475Smrg return True; 513d522f475Smrg } else { 514d522f475Smrg *buffer = 0; /* just in case */ 515d522f475Smrg } 516d522f475Smrg } 517d522f475Smrg return False; 518d522f475Smrg} 51920d2c4d2Smrg 52020d2c4d2Smrg/* 52120d2c4d2Smrg * Retrieve the termcap-buffer. 52220d2c4d2Smrg */ 52320d2c4d2Smrgchar * 52420d2c4d2Smrgget_tcap_buffer(XtermWidget xw) 52520d2c4d2Smrg{ 52620d2c4d2Smrg TScreen *screen = TScreenOf(xw); 52720d2c4d2Smrg char *buffer; 52820d2c4d2Smrg 52920d2c4d2Smrg#if OPT_TEK4014 53020d2c4d2Smrg if (TEK4014_ACTIVE(xw)) { 53120d2c4d2Smrg buffer = TekScreenOf(tekWidget)->tcapbuf; 53220d2c4d2Smrg } else 53320d2c4d2Smrg#endif 53420d2c4d2Smrg { 53520d2c4d2Smrg buffer = screen->tcapbuf; 53620d2c4d2Smrg } 53720d2c4d2Smrg return buffer; 53820d2c4d2Smrg} 53920d2c4d2Smrg 54020d2c4d2Smrg/* 54120d2c4d2Smrg * Retrieve the erase-key, for initialization in main program. 54220d2c4d2Smrg */ 5435104ee6eSmrg#if OPT_INITIAL_ERASE 54420d2c4d2Smrgchar * 545f2e35a3aSmrgget_tcap_erase(XtermWidget xw) 54620d2c4d2Smrg{ 547f2e35a3aSmrg#if !USE_TERMINFO 54820d2c4d2Smrg char *area = TScreenOf(xw)->tcap_area; 54920d2c4d2Smrg#endif 55020d2c4d2Smrg char *fkey; 55120d2c4d2Smrg 552f2e35a3aSmrg (void) xw; 553f2e35a3aSmrg#if USE_TERMINFO 55420d2c4d2Smrg fkey = tigetstr("kbs"); 55520d2c4d2Smrg#else 55620d2c4d2Smrg fkey = tgetstr("kb", &area); 55720d2c4d2Smrg#endif 55820d2c4d2Smrg 55920d2c4d2Smrg if (fkey == NO_STRING) 5605104ee6eSmrg fkey = NULL; 5615104ee6eSmrg if (fkey != NULL) 56220d2c4d2Smrg fkey = x_strdup(fkey); 56320d2c4d2Smrg return fkey; 56420d2c4d2Smrg} 5655104ee6eSmrg#endif /* OPT_INITIAL_ERASE */ 56620d2c4d2Smrg 56720d2c4d2Smrg/* 56820d2c4d2Smrg * A legal termcap (or terminfo) name consists solely of graphic characters, 56920d2c4d2Smrg * excluding the punctuation used to delimit fields of the source description. 57020d2c4d2Smrg */ 57120d2c4d2Smrgstatic Bool 57220d2c4d2SmrgisLegalTcapName(const char *name) 57320d2c4d2Smrg{ 57420d2c4d2Smrg Bool result = False; 57520d2c4d2Smrg 57620d2c4d2Smrg if (*name != '\0') { 5775307cd1aSmrg int length = 0; 57820d2c4d2Smrg result = True; 57920d2c4d2Smrg while (*name != '\0') { 5805307cd1aSmrg if (++length < 32 && isgraph(CharOf(*name))) { 5815104ee6eSmrg if (strchr("\\|,:'\"", *name) != NULL) { 58220d2c4d2Smrg result = False; 58320d2c4d2Smrg break; 58420d2c4d2Smrg } 58520d2c4d2Smrg } else { 58620d2c4d2Smrg result = False; 58720d2c4d2Smrg break; 58820d2c4d2Smrg } 58920d2c4d2Smrg ++name; 59020d2c4d2Smrg } 59120d2c4d2Smrg } 59220d2c4d2Smrg 59320d2c4d2Smrg return result; 59420d2c4d2Smrg} 59520d2c4d2Smrg 59620d2c4d2Smrgvoid 59720d2c4d2Smrgset_termcap(XtermWidget xw, const char *name) 59820d2c4d2Smrg{ 59920d2c4d2Smrg Boolean success = False; 60020d2c4d2Smrg#if USE_TERMINFO 60120d2c4d2Smrg int ignored = 0; 60220d2c4d2Smrg#else 60320d2c4d2Smrg TScreen *screen = TScreenOf(xw); 60420d2c4d2Smrg char buffer[sizeof(screen->tcapbuf)]; 60520d2c4d2Smrg#endif 60620d2c4d2Smrg 60720d2c4d2Smrg TRACE(("set_termcap(%s)\n", NonNull(name))); 60820d2c4d2Smrg if (IsEmpty(name)) { 60920d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 61020d2c4d2Smrg } else { 61120d2c4d2Smrg const char *temp; 61220d2c4d2Smrg char *value; 61320d2c4d2Smrg 6145104ee6eSmrg if ((value = x_decode_hex(name, &temp)) != NULL) { 61520d2c4d2Smrg if (*temp == '\0' && isLegalTcapName(value)) { 61620d2c4d2Smrg if (TcapInit(buffer, value)) { 6175307cd1aSmrg TRACE(("...set_termcap(%s)\n", NonNull(value))); 61820d2c4d2Smrg#if !USE_TERMINFO 61920d2c4d2Smrg memcpy(screen->tcapbuf, buffer, sizeof(buffer)); 62020d2c4d2Smrg#endif 62120d2c4d2Smrg free_termcap(xw); 62220d2c4d2Smrg success = True; 62320d2c4d2Smrg } 62420d2c4d2Smrg } 62520d2c4d2Smrg free(value); 62620d2c4d2Smrg } 62720d2c4d2Smrg } 62820d2c4d2Smrg if (!success) 62920d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 63020d2c4d2Smrg} 63120d2c4d2Smrg 63220d2c4d2Smrgvoid 63320d2c4d2Smrgfree_termcap(XtermWidget xw) 63420d2c4d2Smrg{ 635a1f3da82Smrg#if OPT_TCAP_FKEYS 63620d2c4d2Smrg TScreen *screen = TScreenOf(xw); 63720d2c4d2Smrg 6385104ee6eSmrg if (screen->tcap_fkeys != NULL) { 63920d2c4d2Smrg Cardinal want = XtNumber(table); 64020d2c4d2Smrg Cardinal have; 64120d2c4d2Smrg 64220d2c4d2Smrg for (have = 0; have < want; ++have) { 6432e4f8982Smrg char *fkey = screen->tcap_fkeys[have]; 644f2e35a3aSmrg if (fkey != NO_STRING) { 64520d2c4d2Smrg free(fkey); 64620d2c4d2Smrg } 64720d2c4d2Smrg } 648f2e35a3aSmrg FreeAndNull(screen->tcap_fkeys); 64920d2c4d2Smrg } 65004b94745Smrg#else 65104b94745Smrg (void) xw; 652a1f3da82Smrg#endif 653f2e35a3aSmrg TcapFree(); 65420d2c4d2Smrg} 655