input.c revision a1f3da82
1a1f3da82Smrg/* $XTermId: input.c,v 1.327 2011/02/09 10:15:07 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/* 4a1f3da82Smrg * Copyright 1999-2010,2011 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 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 34d522f475Smrg * 35d522f475Smrg * All Rights Reserved 36d522f475Smrg * 37d522f475Smrg * Permission to use, copy, modify, and distribute this software and its 38d522f475Smrg * documentation for any purpose and without fee is hereby granted, 39d522f475Smrg * provided that the above copyright notice appear in all copies and that 40d522f475Smrg * both that copyright notice and this permission notice appear in 41d522f475Smrg * supporting documentation, and that the name of Digital Equipment 42d522f475Smrg * Corporation not be used in advertising or publicity pertaining to 43d522f475Smrg * distribution of the software without specific, written prior permission. 44d522f475Smrg * 45d522f475Smrg * 46d522f475Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 47d522f475Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 48d522f475Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 49d522f475Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 50d522f475Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 51d522f475Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 52d522f475Smrg * SOFTWARE. 53d522f475Smrg */ 54d522f475Smrg 55d522f475Smrg/* input.c */ 56d522f475Smrg 57d522f475Smrg#include <xterm.h> 58d522f475Smrg 59d522f475Smrg#include <X11/keysym.h> 60d522f475Smrg 61d522f475Smrg#ifdef VMS 62d522f475Smrg#include <X11/keysymdef.h> 63d522f475Smrg#endif 64d522f475Smrg 65d522f475Smrg#if HAVE_X11_DECKEYSYM_H 66d522f475Smrg#include <X11/DECkeysym.h> 67d522f475Smrg#endif 68d522f475Smrg 69d522f475Smrg#if HAVE_X11_SUNKEYSYM_H 70d522f475Smrg#include <X11/Sunkeysym.h> 71d522f475Smrg#endif 72d522f475Smrg 73d522f475Smrg#if HAVE_X11_XF86KEYSYM_H 74d522f475Smrg#include <X11/XF86keysym.h> 75d522f475Smrg#endif 76d522f475Smrg 77d522f475Smrg#include <X11/Xutil.h> 78d522f475Smrg#include <stdio.h> 79d522f475Smrg#include <ctype.h> 80d522f475Smrg 81d522f475Smrg#include <xutf8.h> 82d522f475Smrg 83d522f475Smrg#include <data.h> 84d522f475Smrg#include <fontutils.h> 852eaa94a1Schristos#include <xstrings.h> 86d522f475Smrg#include <xtermcap.h> 87d522f475Smrg 88d522f475Smrg/* 89d522f475Smrg * Xutil.h has no macro to check for the complete set of function- and 90d522f475Smrg * modifier-keys that might be returned. Fake it. 91d522f475Smrg */ 92d522f475Smrg#ifdef XK_ISO_Lock 93d522f475Smrg#define IsPredefinedKey(n) ((n) >= XK_ISO_Lock && (n) <= XK_Delete) 94d522f475Smrg#else 95d522f475Smrg#define IsPredefinedKey(n) ((n) >= XK_BackSpace && (n) <= XK_Delete) 96d522f475Smrg#endif 97d522f475Smrg 98d522f475Smrg#ifdef XK_ISO_Left_Tab 99d522f475Smrg#define IsTabKey(n) ((n) == XK_Tab || (n) == XK_ISO_Left_Tab) 100d522f475Smrg#else 101d522f475Smrg#define IsTabKey(n) ((n) == XK_Tab) 102d522f475Smrg#endif 103d522f475Smrg 104d522f475Smrg#ifndef IsPrivateKeypadKey 105d522f475Smrg#define IsPrivateKeypadKey(k) (0) 106d522f475Smrg#endif 107d522f475Smrg 108d522f475Smrg#define IsBackarrowToggle(keyboard, keysym, state) \ 109d522f475Smrg ((((keyboard->flags & MODE_DECBKM) == 0) \ 110d522f475Smrg ^ ((state & ControlMask) != 0)) \ 111d522f475Smrg && (keysym == XK_BackSpace)) 112d522f475Smrg 113d522f475Smrg#define MAP(from, to) case from: result = to; break 114d522f475Smrg#define Masked(value,mask) ((value) & (unsigned) (~(mask))) 115d522f475Smrg 116d522f475Smrg#define KEYSYM_FMT "0x%04lX" /* simplify matching <X11/keysymdef.h> */ 117d522f475Smrg 11820d2c4d2Smrg#define TEK4014_GIN(tw) (tw != 0 && TekScreenOf(tw)->TekGIN) 119d522f475Smrg 120d522f475Smrgtypedef struct { 121d522f475Smrg KeySym keysym; 122d522f475Smrg Bool is_fkey; 123d522f475Smrg int nbytes; 124d522f475Smrg#define STRBUFSIZE 500 125d522f475Smrg char strbuf[STRBUFSIZE]; 126d522f475Smrg} KEY_DATA; 127d522f475Smrg 12820d2c4d2Smrgstatic 12920d2c4d2Smrgconst char *kypd_num = " XXXXXXXX\tXXX\rXXXxxxxXXXXXXXXXXXXXXXXXXXXX*+,-./0123456789XXX="; 13020d2c4d2Smrg/* 0123456789 abc def0123456789abcdef0123456789abcdef0123456789abcd */ 13120d2c4d2Smrgstatic 13220d2c4d2Smrgconst char *kypd_apl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ??????abcdefghijklmnopqrstuvwxyzXXX"; 13320d2c4d2Smrg/* 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd */ 13420d2c4d2Smrgstatic 13520d2c4d2Smrgconst char *curfinal = "HDACB FE"; 136d522f475Smrg 137d522f475Smrgstatic int decfuncvalue(KEY_DATA *); 138d522f475Smrgstatic void sunfuncvalue(ANSI *, KEY_DATA *); 139d522f475Smrgstatic void hpfuncvalue(ANSI *, KEY_DATA *); 140d522f475Smrgstatic void scofuncvalue(ANSI *, KEY_DATA *); 141d522f475Smrg 142d522f475Smrg#if OPT_TRACE 14320d2c4d2Smrgstatic const char * 144d522f475SmrgModifierName(unsigned modifier) 145d522f475Smrg{ 14620d2c4d2Smrg const char *s = ""; 147d522f475Smrg if (modifier & ShiftMask) 148d522f475Smrg s = " Shift"; 149d522f475Smrg else if (modifier & LockMask) 150d522f475Smrg s = " Lock"; 151d522f475Smrg else if (modifier & ControlMask) 152d522f475Smrg s = " Control"; 153d522f475Smrg else if (modifier & Mod1Mask) 154d522f475Smrg s = " Mod1"; 155d522f475Smrg else if (modifier & Mod2Mask) 156d522f475Smrg s = " Mod2"; 157d522f475Smrg else if (modifier & Mod3Mask) 158d522f475Smrg s = " Mod3"; 159d522f475Smrg else if (modifier & Mod4Mask) 160d522f475Smrg s = " Mod4"; 161d522f475Smrg else if (modifier & Mod5Mask) 162d522f475Smrg s = " Mod5"; 163d522f475Smrg return s; 164d522f475Smrg} 165d522f475Smrg 166d522f475Smrg#define FMT_MODIFIER_NAMES "%s%s%s%s%s%s%s%s" 167d522f475Smrg#define ARG_MODIFIER_NAMES(state) \ 168d522f475Smrg ModifierName(state & ShiftMask), \ 169d522f475Smrg ModifierName(state & LockMask), \ 170d522f475Smrg ModifierName(state & ControlMask), \ 171d522f475Smrg ModifierName(state & Mod1Mask), \ 172d522f475Smrg ModifierName(state & Mod2Mask), \ 173d522f475Smrg ModifierName(state & Mod3Mask), \ 174d522f475Smrg ModifierName(state & Mod4Mask), \ 175d522f475Smrg ModifierName(state & Mod5Mask) 176d522f475Smrg#endif 177d522f475Smrg 178d522f475Smrgstatic void 179d522f475SmrgAdjustAfterInput(XtermWidget xw) 180d522f475Smrg{ 18120d2c4d2Smrg TScreen *screen = TScreenOf(xw); 182d522f475Smrg 183d522f475Smrg if (screen->scrollkey && screen->topline != 0) 18420d2c4d2Smrg WindowScroll(xw, 0, False); 185d522f475Smrg if (screen->marginbell) { 186d522f475Smrg int col = screen->max_col - screen->nmarginbell; 18720d2c4d2Smrg if (screen->bellArmed >= 0) { 18820d2c4d2Smrg if (screen->bellArmed == screen->cur_row) { 189d522f475Smrg if (screen->cur_col >= col) { 19020d2c4d2Smrg Bell(xw, XkbBI_MarginBell, 0); 19120d2c4d2Smrg screen->bellArmed = -1; 192d522f475Smrg } 19320d2c4d2Smrg } else { 19420d2c4d2Smrg screen->bellArmed = 195d522f475Smrg screen->cur_col < col ? screen->cur_row : -1; 19620d2c4d2Smrg } 197d522f475Smrg } else if (screen->cur_col < col) 19820d2c4d2Smrg screen->bellArmed = screen->cur_row; 199d522f475Smrg } 200d522f475Smrg} 201d522f475Smrg 202d522f475Smrg/* 203d522f475Smrg * Return true if the key is on the editing keypad. This overlaps with 204d522f475Smrg * IsCursorKey() and IsKeypadKey() and must be tested before those macro to 205d522f475Smrg * distinguish it from them. 206d522f475Smrg */ 207d522f475Smrgstatic Bool 208d522f475SmrgIsEditFunctionKey(KeySym keysym) 209d522f475Smrg{ 210d522f475Smrg switch (keysym) { 211d522f475Smrg case XK_Prior: /* editing keypad */ 212d522f475Smrg case XK_Next: /* editing keypad */ 213d522f475Smrg case XK_Insert: /* editing keypad */ 214d522f475Smrg case XK_Find: /* editing keypad */ 215d522f475Smrg case XK_Select: /* editing keypad */ 216d522f475Smrg#ifdef DXK_Remove 217d522f475Smrg case DXK_Remove: /* editing keypad */ 218d522f475Smrg#endif 219d522f475Smrg#ifdef XK_KP_Delete 220d522f475Smrg case XK_KP_Delete: /* editing key on numeric keypad */ 221d522f475Smrg case XK_KP_Insert: /* editing key on numeric keypad */ 222d522f475Smrg#endif 223d522f475Smrg#ifdef XK_ISO_Left_Tab 224d522f475Smrg case XK_ISO_Left_Tab: 225d522f475Smrg#endif 226d522f475Smrg return True; 227d522f475Smrg default: 228d522f475Smrg return False; 229d522f475Smrg } 230d522f475Smrg} 231d522f475Smrg 232d522f475Smrg#if OPT_MOD_FKEYS 233d522f475Smrg#define IS_CTRL(n) ((n) < ANSI_SPA || ((n) >= 0x7f && (n) <= 0x9f)) 234d522f475Smrg 235d522f475Smrg/* 236d522f475Smrg * Return true if the keysym corresponds to one of the control characters, 237d522f475Smrg * or one of the common ASCII characters that is combined with control to 238d522f475Smrg * make a control character. 239d522f475Smrg */ 240d522f475Smrgstatic Bool 241d522f475SmrgIsControlInput(KEY_DATA * kd) 242d522f475Smrg{ 243d522f475Smrg return ((kd->keysym) >= 0x40 && (kd->keysym) <= 0x7f); 244d522f475Smrg} 245d522f475Smrg 246d522f475Smrgstatic Bool 247d522f475SmrgIsControlOutput(KEY_DATA * kd) 248d522f475Smrg{ 249d522f475Smrg return IS_CTRL(kd->keysym); 250d522f475Smrg} 251d522f475Smrg 252d522f475Smrg/* 253d522f475Smrg * X "normally" has some built-in translations, which the user may want to 254d522f475Smrg * suppress when processing the modifyOtherKeys resource. In particular, the 255d522f475Smrg * control modifier applied to some of the keyboard digits gives results for 256d522f475Smrg * control characters. 257d522f475Smrg * 258d522f475Smrg * control 2 0 NUL 259d522f475Smrg * control SPC 0 NUL 260d522f475Smrg * control @ 0 NUL 261d522f475Smrg * control ` 0 NUL 262d522f475Smrg * control 3 0x1b ESC 263d522f475Smrg * control 4 0x1c FS 264d522f475Smrg * control \ 0x1c FS 265d522f475Smrg * control 5 0x1d GS 266d522f475Smrg * control 6 0x1e RS 267d522f475Smrg * control ^ 0x1e RS 268d522f475Smrg * control ~ 0x1e RS 269d522f475Smrg * control 7 0x1f US 270d522f475Smrg * control / 0x1f US 271d522f475Smrg * control _ 0x1f US 272d522f475Smrg * control 8 0x7f DEL 273d522f475Smrg * 274d522f475Smrg * It is possible that some other keyboards do not work for these combinations, 275d522f475Smrg * but they do work with modifyOtherKeys=2 for the US keyboard: 276d522f475Smrg * 277d522f475Smrg * control ` 0 NUL 278d522f475Smrg * control [ 0x1b ESC 279d522f475Smrg * control \ 0x1c FS 280d522f475Smrg * control ] 0x1d GS 281d522f475Smrg * control ? 0x7f DEL 282d522f475Smrg */ 283d522f475Smrgstatic Bool 284d522f475SmrgIsControlAlias(KEY_DATA * kd) 285d522f475Smrg{ 286d522f475Smrg Bool result = False; 287d522f475Smrg 288d522f475Smrg if (kd->nbytes == 1) { 289d522f475Smrg result = IS_CTRL(CharOf(kd->strbuf[0])); 290d522f475Smrg } 291d522f475Smrg return result; 292d522f475Smrg} 293d522f475Smrg 294d522f475Smrg/* 295d522f475Smrg * If we are in the non-VT220/VT52 keyboard state, allow modifiers to add a 296d522f475Smrg * parameter to the function-key control sequences. 297d522f475Smrg * 298d522f475Smrg * Note that we generally cannot capture the Shift-modifier for the numeric 299d522f475Smrg * keypad since this is commonly used to act as a type of NumLock, e.g., 300d522f475Smrg * making the keypad send "7" (actually XK_KP_7) where the unshifted code 301d522f475Smrg * would be Home (XK_KP_Home). The other modifiers work, subject to the 302d522f475Smrg * usual window-manager assignments. 303d522f475Smrg */ 304d522f475Smrgstatic Bool 305d522f475SmrgallowModifierParm(XtermWidget xw, KEY_DATA * kd) 306d522f475Smrg{ 307d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 30820d2c4d2Smrg TScreen *screen = TScreenOf(xw); 309d522f475Smrg int keypad_mode = ((keyboard->flags & MODE_DECKPAM) != 0); 310d522f475Smrg 311d522f475Smrg Bool result = False; 312d522f475Smrg 313d522f475Smrg (void) screen; 314d522f475Smrg if (!(IsKeypadKey(kd->keysym) && keypad_mode) 315d522f475Smrg#if OPT_SUNPC_KBD 316d522f475Smrg && keyboard->type != keyboardIsVT220 317d522f475Smrg#endif 318d522f475Smrg#if OPT_VT52_MODE 319d522f475Smrg && screen->vtXX_level != 0 320d522f475Smrg#endif 321d522f475Smrg ) { 322d522f475Smrg result = True; 323d522f475Smrg } 324d522f475Smrg return result; 325d522f475Smrg} 326d522f475Smrg 327d522f475Smrg/* 328d522f475Smrg* Modifier codes: 329d522f475Smrg* None 1 330d522f475Smrg* Shift 2 = 1(None)+1(Shift) 331d522f475Smrg* Alt 3 = 1(None)+2(Alt) 332d522f475Smrg* Alt+Shift 4 = 1(None)+1(Shift)+2(Alt) 333d522f475Smrg* Ctrl 5 = 1(None)+4(Ctrl) 334d522f475Smrg* Ctrl+Shift 6 = 1(None)+1(Shift)+4(Ctrl) 335d522f475Smrg* Ctrl+Alt 7 = 1(None)+2(Alt)+4(Ctrl) 336d522f475Smrg* Ctrl+Alt+Shift 8 = 1(None)+1(Shift)+2(Alt)+4(Ctrl) 337d522f475Smrg* Meta 9 = 1(None)+8(Meta) 338d522f475Smrg* Meta+Shift 10 = 1(None)+8(Meta)+1(Shift) 339d522f475Smrg* Meta+Alt 11 = 1(None)+8(Meta)+2(Alt) 340d522f475Smrg* Meta+Alt+Shift 12 = 1(None)+8(Meta)+1(Shift)+2(Alt) 341d522f475Smrg* Meta+Ctrl 13 = 1(None)+8(Meta)+4(Ctrl) 342d522f475Smrg* Meta+Ctrl+Shift 14 = 1(None)+8(Meta)+1(Shift)+4(Ctrl) 343d522f475Smrg* Meta+Ctrl+Alt 15 = 1(None)+8(Meta)+2(Alt)+4(Ctrl) 344d522f475Smrg* Meta+Ctrl+Alt+Shift 16 = 1(None)+8(Meta)+1(Shift)+2(Alt)+4(Ctrl) 345d522f475Smrg*/ 346d522f475Smrg 347956cc18dSsnjunsigned 348d522f475SmrgxtermParamToState(XtermWidget xw, unsigned param) 349d522f475Smrg{ 350956cc18dSsnj unsigned result = 0; 351d522f475Smrg#if OPT_NUM_LOCK 352956cc18dSsnj if (param > MOD_NONE 353d522f475Smrg && ((ShiftMask 354d522f475Smrg | ControlMask 355d522f475Smrg | xw->misc.alt_mods 356d522f475Smrg | xw->misc.meta_mods) & xw->misc.other_mods) == 0) { 357956cc18dSsnj if ((param - MOD_NONE) & MOD_SHIFT) 35820d2c4d2Smrg UIntSet(result, ShiftMask); 359956cc18dSsnj if ((param - MOD_NONE) & MOD_CTRL) 36020d2c4d2Smrg UIntSet(result, ControlMask); 361956cc18dSsnj if ((param - MOD_NONE) & MOD_ALT) 36220d2c4d2Smrg UIntSet(result, xw->misc.alt_mods); 363956cc18dSsnj if ((param - MOD_NONE) & MOD_META) 36420d2c4d2Smrg UIntSet(result, xw->misc.meta_mods); 365d522f475Smrg } 366d522f475Smrg#else 367d522f475Smrg (void) xw; 368d522f475Smrg (void) param; 369d522f475Smrg#endif 370d522f475Smrg TRACE(("xtermParamToState(%d) %s%s%s%s -> %#x\n", param, 371956cc18dSsnj MODIFIER_NAME(param, MOD_SHIFT), 372956cc18dSsnj MODIFIER_NAME(param, MOD_ALT), 373956cc18dSsnj MODIFIER_NAME(param, MOD_CTRL), 374956cc18dSsnj MODIFIER_NAME(param, MOD_META), 375d522f475Smrg result)); 376d522f475Smrg return result; 377d522f475Smrg} 378d522f475Smrg 379956cc18dSsnjunsigned 380d522f475SmrgxtermStateToParam(XtermWidget xw, unsigned state) 381d522f475Smrg{ 382956cc18dSsnj unsigned modify_parm = MOD_NONE; 383d522f475Smrg 384956cc18dSsnj TRACE(("xtermStateToParam %#x\n", state)); 385d522f475Smrg#if OPT_NUM_LOCK 386d522f475Smrg if ((state & xw->misc.other_mods) == 0) { 387d522f475Smrg if (state & ShiftMask) { 388956cc18dSsnj modify_parm += MOD_SHIFT; 38920d2c4d2Smrg UIntClr(state, ShiftMask); 390d522f475Smrg } 391d522f475Smrg if (state & ControlMask) { 392956cc18dSsnj modify_parm += MOD_CTRL; 39320d2c4d2Smrg UIntClr(state, ControlMask); 394d522f475Smrg } 395d522f475Smrg if ((state & xw->misc.alt_mods) != 0) { 396956cc18dSsnj modify_parm += MOD_ALT; 39720d2c4d2Smrg UIntClr(state, xw->misc.alt_mods); 398d522f475Smrg } 399d522f475Smrg if ((state & xw->misc.meta_mods) != 0) { 400956cc18dSsnj modify_parm += MOD_META; 40120d2c4d2Smrg UIntClr(state, xw->misc.meta_mods); 402d522f475Smrg } 403d522f475Smrg } 404956cc18dSsnj if (modify_parm == MOD_NONE) 405956cc18dSsnj modify_parm = 0; 406d522f475Smrg#else 407d522f475Smrg (void) xw; 408d522f475Smrg (void) state; 409d522f475Smrg#endif 410d522f475Smrg TRACE(("...xtermStateToParam %d%s%s%s%s\n", modify_parm, 411956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_SHIFT), 412956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_ALT), 413956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_CTRL), 414956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_META))); 415d522f475Smrg return modify_parm; 416d522f475Smrg} 417d522f475Smrg 418d522f475Smrg#define computeMaskedModifier(xw, state, mask) \ 419d522f475Smrg xtermStateToParam(xw, Masked(state, mask)) 420d522f475Smrg 421d522f475Smrg#if OPT_NUM_LOCK 422d522f475Smrgstatic unsigned 423d522f475SmrgfilterAltMeta(unsigned result, unsigned mask, Bool enable, KEY_DATA * kd) 424d522f475Smrg{ 425d522f475Smrg if ((result & mask) != 0) { 426d522f475Smrg /* 427d522f475Smrg * metaSendsEscape makes the meta key independent of 428d522f475Smrg * modifyOtherKeys. 429d522f475Smrg */ 430d522f475Smrg if (enable) { 431d522f475Smrg result &= ~mask; 432d522f475Smrg } 433d522f475Smrg /* 434d522f475Smrg * A bare meta-modifier is independent of modifyOtherKeys. If it 435d522f475Smrg * is combined with other modifiers, make it depend. 436d522f475Smrg */ 437d522f475Smrg if ((result & ~(mask)) == 0) { 438d522f475Smrg result &= ~mask; 439d522f475Smrg } 440d522f475Smrg /* 441d522f475Smrg * Check for special cases of control+meta which are used by some 442d522f475Smrg * applications, e.g., emacs. 443d522f475Smrg */ 444d522f475Smrg if ((IsControlInput(kd) 445d522f475Smrg || IsControlOutput(kd)) 446d522f475Smrg && (result & ControlMask) != 0) { 447d522f475Smrg result &= ~(mask | ControlMask); 448d522f475Smrg } 449d522f475Smrg if (kd->keysym == XK_Return || kd->keysym == XK_Tab) { 450d522f475Smrg result &= ~(mask | ControlMask); 451d522f475Smrg } 452d522f475Smrg } 453d522f475Smrg return result; 454d522f475Smrg} 455d522f475Smrg#endif /* OPT_NUM_LOCK */ 456d522f475Smrg 457d522f475Smrg/* 458d522f475Smrg * Single characters (not function-keys) are allowed fewer modifiers when 459d522f475Smrg * interpreting modifyOtherKeys due to pre-existing associations with some 460d522f475Smrg * modifiers. 461d522f475Smrg */ 462d522f475Smrgstatic unsigned 463d522f475SmrgallowedCharModifiers(XtermWidget xw, unsigned state, KEY_DATA * kd) 464d522f475Smrg{ 465d522f475Smrg#if OPT_NUM_LOCK 466d522f475Smrg unsigned a_or_m = (state & (xw->misc.meta_mods | xw->misc.alt_mods)); 467d522f475Smrg#else 468d522f475Smrg unsigned a_or_m = 0; 469d522f475Smrg#endif 470d522f475Smrg /* 471d522f475Smrg * Start by limiting the result to the modifiers we might want to use. 472d522f475Smrg */ 473d522f475Smrg unsigned result = (state & (ControlMask 474d522f475Smrg | ShiftMask 475d522f475Smrg | a_or_m)); 476d522f475Smrg 477d522f475Smrg /* 478d522f475Smrg * If modifyOtherKeys is off or medium (0 or 1), moderate its effects by 479d522f475Smrg * excluding the common cases for modifiers. 480d522f475Smrg */ 481d522f475Smrg if (xw->keyboard.modify_now.other_keys <= 1) { 482d522f475Smrg if (IsControlInput(kd) 483d522f475Smrg && Masked(result, ControlMask) == 0) { 484d522f475Smrg /* These keys are already associated with the control-key */ 485d522f475Smrg if (xw->keyboard.modify_now.other_keys == 0) { 48620d2c4d2Smrg UIntClr(result, ControlMask); 487d522f475Smrg } 488d522f475Smrg } else if (kd->keysym == XK_Tab || kd->keysym == XK_Return) { 489a1f3da82Smrg /* EMPTY */ ; 490d522f475Smrg } else if (IsControlAlias(kd)) { 491d522f475Smrg /* Things like "^_" work here... */ 492d522f475Smrg if (Masked(result, (ControlMask | ShiftMask)) == 0) { 493d522f475Smrg result = 0; 494d522f475Smrg } 495d522f475Smrg } else if (!IsControlOutput(kd) && !IsPredefinedKey(kd->keysym)) { 496d522f475Smrg /* Printable keys are already associated with the shift-key */ 497d522f475Smrg if (!(result & ControlMask)) { 49820d2c4d2Smrg UIntClr(result, ShiftMask); 499d522f475Smrg } 500d522f475Smrg } 501d522f475Smrg#if OPT_NUM_LOCK 502d522f475Smrg result = filterAltMeta(result, 503d522f475Smrg xw->misc.meta_mods, 50420d2c4d2Smrg TScreenOf(xw)->meta_sends_esc, kd); 50520d2c4d2Smrg if (TScreenOf(xw)->alt_is_not_meta) { 506d522f475Smrg result = filterAltMeta(result, 507d522f475Smrg xw->misc.alt_mods, 50820d2c4d2Smrg TScreenOf(xw)->alt_sends_esc, kd); 509d522f475Smrg } 510d522f475Smrg#endif 511d522f475Smrg } 512d522f475Smrg TRACE(("...allowedCharModifiers(state=%u" FMT_MODIFIER_NAMES 513d522f475Smrg ", ch=" KEYSYM_FMT ") ->" 514d522f475Smrg "%u" FMT_MODIFIER_NAMES "\n", 515d522f475Smrg state, ARG_MODIFIER_NAMES(state), kd->keysym, 516d522f475Smrg result, ARG_MODIFIER_NAMES(result))); 517d522f475Smrg return result; 518d522f475Smrg} 519d522f475Smrg 520d522f475Smrg/* 521d522f475Smrg * Decide if we should generate a special escape sequence for "other" keys 522d522f475Smrg * than cursor-, function-keys, etc., as per the modifyOtherKeys resource. 523d522f475Smrg */ 524d522f475Smrgstatic Bool 525d522f475SmrgModifyOtherKeys(XtermWidget xw, 526d522f475Smrg unsigned state, 527d522f475Smrg KEY_DATA * kd, 528956cc18dSsnj unsigned modify_parm) 529d522f475Smrg{ 530d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 531d522f475Smrg Bool result = False; 532d522f475Smrg 533d522f475Smrg /* 534d522f475Smrg * Exclude the keys already covered by a modifier. 535d522f475Smrg */ 536d522f475Smrg if (kd->is_fkey 537d522f475Smrg || IsEditFunctionKey(kd->keysym) 538d522f475Smrg || IsKeypadKey(kd->keysym) 539d522f475Smrg || IsCursorKey(kd->keysym) 540d522f475Smrg || IsPFKey(kd->keysym) 541d522f475Smrg || IsMiscFunctionKey(kd->keysym) 542d522f475Smrg || IsPrivateKeypadKey(kd->keysym) 543d522f475Smrg#if OPT_NUM_LOCK 544d522f475Smrg || (state & xw->misc.other_mods) != 0 545d522f475Smrg#endif 546d522f475Smrg ) { 547d522f475Smrg result = False; 548d522f475Smrg } else if (modify_parm != 0) { 549d522f475Smrg if (IsBackarrowToggle(keyboard, kd->keysym, state)) { 550d522f475Smrg kd->keysym = XK_Delete; 55120d2c4d2Smrg UIntClr(state, ControlMask); 552d522f475Smrg } 553d522f475Smrg if (!IsPredefinedKey(kd->keysym)) { 554d522f475Smrg state = allowedCharModifiers(xw, state, kd); 555d522f475Smrg } 556d522f475Smrg if (state != 0) { 557d522f475Smrg switch (keyboard->modify_now.other_keys) { 558d522f475Smrg default: 559d522f475Smrg break; 560d522f475Smrg case 1: 561d522f475Smrg switch (kd->keysym) { 562d522f475Smrg case XK_BackSpace: 563d522f475Smrg case XK_Delete: 564d522f475Smrg result = False; 565d522f475Smrg break; 566d522f475Smrg#ifdef XK_ISO_Left_Tab 567d522f475Smrg case XK_ISO_Left_Tab: 568956cc18dSsnj if (computeMaskedModifier(xw, state, ShiftMask)) 569d522f475Smrg result = True; 570d522f475Smrg break; 571d522f475Smrg#endif 572d522f475Smrg case XK_Return: 573d522f475Smrg case XK_Tab: 574956cc18dSsnj result = (modify_parm != 0); 575d522f475Smrg break; 576d522f475Smrg default: 577d522f475Smrg if (IsControlInput(kd)) { 578d522f475Smrg if (state == ControlMask || state == ShiftMask) { 579d522f475Smrg result = False; 580d522f475Smrg } else { 581956cc18dSsnj result = (modify_parm != 0); 582d522f475Smrg } 583d522f475Smrg } else if (IsControlAlias(kd)) { 584d522f475Smrg if (state == ShiftMask) 585d522f475Smrg result = False; 586956cc18dSsnj else if (computeMaskedModifier(xw, state, ControlMask)) { 587d522f475Smrg result = True; 588d522f475Smrg } 589d522f475Smrg } else { 590d522f475Smrg result = True; 591d522f475Smrg } 592d522f475Smrg break; 593d522f475Smrg } 594d522f475Smrg break; 595d522f475Smrg case 2: 596d522f475Smrg switch (kd->keysym) { 597d522f475Smrg case XK_BackSpace: 598d522f475Smrg /* strip ControlMask as per IsBackarrowToggle() */ 599956cc18dSsnj if (computeMaskedModifier(xw, state, ControlMask)) 600d522f475Smrg result = True; 601d522f475Smrg break; 602d522f475Smrg case XK_Delete: 603956cc18dSsnj result = (xtermStateToParam(xw, state) != 0); 604d522f475Smrg break; 605d522f475Smrg#ifdef XK_ISO_Left_Tab 606d522f475Smrg case XK_ISO_Left_Tab: 607956cc18dSsnj if (computeMaskedModifier(xw, state, ShiftMask)) 608d522f475Smrg result = True; 609d522f475Smrg break; 610d522f475Smrg#endif 611d522f475Smrg case XK_Return: 612d522f475Smrg case XK_Tab: 613956cc18dSsnj result = (modify_parm != 0); 614d522f475Smrg break; 615d522f475Smrg default: 616d522f475Smrg if (IsControlInput(kd)) { 617d522f475Smrg result = True; 618d522f475Smrg } else if (state == ShiftMask) { 619d522f475Smrg result = (kd->keysym == ' ' || kd->keysym == XK_Return); 620956cc18dSsnj } else if (computeMaskedModifier(xw, state, ShiftMask)) { 621d522f475Smrg result = True; 622d522f475Smrg } 623d522f475Smrg break; 624d522f475Smrg } 625d522f475Smrg break; 626d522f475Smrg } 627d522f475Smrg } 628d522f475Smrg } 629d522f475Smrg TRACE(("...ModifyOtherKeys(%d,%d) %s\n", 630d522f475Smrg keyboard->modify_now.other_keys, 631d522f475Smrg modify_parm, 632d522f475Smrg BtoS(result))); 633d522f475Smrg return result; 634d522f475Smrg} 635d522f475Smrg 636d522f475Smrg#define APPEND_PARM(number) \ 637956cc18dSsnj reply->a_param[reply->a_nparam] = (ParmType) number; \ 638956cc18dSsnj reply->a_nparam++ 639d522f475Smrg 640d522f475Smrg/* 641d522f475Smrg * Function-key code 27 happens to not be used in the vt220-style encoding. 642d522f475Smrg * xterm uses this to represent modified non-function-keys such as control/+ in 643d522f475Smrg * the Sun/PC keyboard layout. See the modifyOtherKeys resource in the manpage 644d522f475Smrg * for more information. 645d522f475Smrg */ 646d522f475Smrgstatic Bool 647956cc18dSsnjmodifyOtherKey(ANSI * reply, int input_char, unsigned modify_parm, int format_keys) 648d522f475Smrg{ 649d522f475Smrg Bool result = False; 650d522f475Smrg 651d522f475Smrg if (input_char >= 0) { 652d522f475Smrg reply->a_type = ANSI_CSI; 653d522f475Smrg if (format_keys) { 654d522f475Smrg APPEND_PARM(input_char); 655d522f475Smrg APPEND_PARM(modify_parm); 656d522f475Smrg reply->a_final = 'u'; 657d522f475Smrg } else { 658d522f475Smrg APPEND_PARM(27); 659d522f475Smrg APPEND_PARM(modify_parm); 660d522f475Smrg APPEND_PARM(input_char); 661d522f475Smrg reply->a_final = '~'; 662d522f475Smrg } 663d522f475Smrg 664d522f475Smrg result = True; 665d522f475Smrg } 666d522f475Smrg return result; 667d522f475Smrg} 668d522f475Smrg 669d522f475Smrgstatic void 670956cc18dSsnjmodifyCursorKey(ANSI * reply, int modify, unsigned *modify_parm) 671d522f475Smrg{ 672956cc18dSsnj if (*modify_parm != 0) { 673d522f475Smrg if (modify < 0) { 674d522f475Smrg *modify_parm = 0; 675d522f475Smrg } 676d522f475Smrg if (modify > 0) { 677d522f475Smrg reply->a_type = ANSI_CSI; /* SS3 should not have params */ 678d522f475Smrg } 679d522f475Smrg if (modify > 1 && reply->a_nparam == 0) { 680d522f475Smrg APPEND_PARM(1); /* force modifier to 2nd param */ 681d522f475Smrg } 682d522f475Smrg if (modify > 2) { 683d522f475Smrg reply->a_pintro = '>'; /* mark this as "private" */ 684d522f475Smrg } 685d522f475Smrg } 686d522f475Smrg} 687d522f475Smrg#else 688d522f475Smrg#define modifyCursorKey(reply, modify, parm) /* nothing */ 689d522f475Smrg#endif /* OPT_MOD_FKEYS */ 690d522f475Smrg 691d522f475Smrg#if OPT_SUNPC_KBD 692d522f475Smrg/* 693d522f475Smrg * If we have told xterm that our keyboard is really a Sun/PC keyboard, this is 694d522f475Smrg * enough to make a reasonable approximation to DEC vt220 numeric and editing 695d522f475Smrg * keypads. 696d522f475Smrg */ 697d522f475Smrgstatic KeySym 698d522f475SmrgTranslateFromSUNPC(KeySym keysym) 699d522f475Smrg{ 700d522f475Smrg /* *INDENT-OFF* */ 701d522f475Smrg static struct { 702d522f475Smrg KeySym before, after; 703d522f475Smrg } table[] = { 704d522f475Smrg#ifdef DXK_Remove 705d522f475Smrg { XK_Delete, DXK_Remove }, 706d522f475Smrg#endif 707d522f475Smrg { XK_Home, XK_Find }, 708d522f475Smrg { XK_End, XK_Select }, 709d522f475Smrg#ifdef XK_KP_Home 710d522f475Smrg { XK_Delete, XK_KP_Decimal }, 711d522f475Smrg { XK_KP_Delete, XK_KP_Decimal }, 712d522f475Smrg { XK_KP_Insert, XK_KP_0 }, 713d522f475Smrg { XK_KP_End, XK_KP_1 }, 714d522f475Smrg { XK_KP_Down, XK_KP_2 }, 715d522f475Smrg { XK_KP_Next, XK_KP_3 }, 716d522f475Smrg { XK_KP_Left, XK_KP_4 }, 717d522f475Smrg { XK_KP_Begin, XK_KP_5 }, 718d522f475Smrg { XK_KP_Right, XK_KP_6 }, 719d522f475Smrg { XK_KP_Home, XK_KP_7 }, 720d522f475Smrg { XK_KP_Up, XK_KP_8 }, 721d522f475Smrg { XK_KP_Prior, XK_KP_9 }, 722d522f475Smrg#endif 723d522f475Smrg }; 724d522f475Smrg /* *INDENT-ON* */ 725d522f475Smrg 726d522f475Smrg unsigned n; 727d522f475Smrg 728d522f475Smrg for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) { 729d522f475Smrg if (table[n].before == keysym) { 730d522f475Smrg TRACE(("...Input keypad before was " KEYSYM_FMT "\n", keysym)); 731d522f475Smrg keysym = table[n].after; 732d522f475Smrg TRACE(("...Input keypad changed to " KEYSYM_FMT "\n", keysym)); 733d522f475Smrg break; 734d522f475Smrg } 735d522f475Smrg } 736d522f475Smrg return keysym; 737d522f475Smrg} 738d522f475Smrg#endif /* OPT_SUNPC_KBD */ 739d522f475Smrg 740d522f475Smrg#define VT52_KEYPAD \ 741d522f475Smrg if_OPT_VT52_MODE(screen,{ \ 742d522f475Smrg reply.a_type = ANSI_ESC; \ 743d522f475Smrg reply.a_pintro = '?'; \ 744d522f475Smrg }) 745d522f475Smrg 746d522f475Smrg#define VT52_CURSOR_KEYS \ 747d522f475Smrg if_OPT_VT52_MODE(screen,{ \ 748d522f475Smrg reply.a_type = ANSI_ESC; \ 749d522f475Smrg }) 750d522f475Smrg 751d522f475Smrg#undef APPEND_PARM 752d522f475Smrg#define APPEND_PARM(number) \ 753956cc18dSsnj reply.a_param[reply.a_nparam] = (ParmType) number, \ 754956cc18dSsnj reply.a_nparam++ 755d522f475Smrg 756d522f475Smrg#if OPT_MOD_FKEYS 757d522f475Smrg#define MODIFIER_PARM \ 758956cc18dSsnj if (modify_parm != 0) APPEND_PARM(modify_parm) 759d522f475Smrg#else 760d522f475Smrg#define MODIFIER_PARM /*nothing */ 761d522f475Smrg#endif 762d522f475Smrg 763d522f475Smrg/* 764d522f475Smrg * Determine if we use the \E[3~ sequence for Delete, or the legacy ^?. We 765d522f475Smrg * maintain the delete_is_del value as 3 states: unspecified(2), true and 766d522f475Smrg * false. If unspecified, it is handled differently according to whether the 767d522f475Smrg * legacy keyboard support is enabled, or if xterm emulates a VT220. 768d522f475Smrg * 769d522f475Smrg * Once the user (or application) has specified delete_is_del via resource 770d522f475Smrg * setting, popup menu or escape sequence, it overrides the keyboard type 771d522f475Smrg * rather than the reverse. 772d522f475Smrg */ 773d522f475SmrgBool 774d522f475SmrgxtermDeleteIsDEL(XtermWidget xw) 775d522f475Smrg{ 776d522f475Smrg Bool result = True; 777d522f475Smrg 778d522f475Smrg if (xw->keyboard.type == keyboardIsDefault 779d522f475Smrg || xw->keyboard.type == keyboardIsVT220) 78020d2c4d2Smrg result = (TScreenOf(xw)->delete_is_del == True); 781d522f475Smrg 782d522f475Smrg if (xw->keyboard.type == keyboardIsLegacy) 78320d2c4d2Smrg result = (TScreenOf(xw)->delete_is_del != False); 784d522f475Smrg 785d522f475Smrg TRACE(("xtermDeleteIsDEL(%d/%d) = %d\n", 786d522f475Smrg xw->keyboard.type, 78720d2c4d2Smrg TScreenOf(xw)->delete_is_del, 788d522f475Smrg result)); 789d522f475Smrg 790d522f475Smrg return result; 791d522f475Smrg} 792d522f475Smrg 793d522f475Smrgvoid 794d522f475SmrgInput(XtermWidget xw, 795d522f475Smrg XKeyEvent * event, 796d522f475Smrg Bool eightbit) 797d522f475Smrg{ 798d522f475Smrg Char *string; 799d522f475Smrg 800d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 80120d2c4d2Smrg TScreen *screen = TScreenOf(xw); 802d522f475Smrg 803d522f475Smrg int j; 804d522f475Smrg int key = False; 805d522f475Smrg ANSI reply; 806d522f475Smrg int dec_code; 807956cc18dSsnj unsigned modify_parm = 0; 808d522f475Smrg int keypad_mode = ((keyboard->flags & MODE_DECKPAM) != 0); 809d522f475Smrg unsigned evt_state = event->state; 810d522f475Smrg unsigned mod_state; 811d522f475Smrg KEY_DATA kd; 812d522f475Smrg 813d522f475Smrg /* Ignore characters typed at the keyboard */ 814d522f475Smrg if (keyboard->flags & MODE_KAM) 815d522f475Smrg return; 816d522f475Smrg 817d522f475Smrg kd.keysym = 0; 818d522f475Smrg kd.is_fkey = False; 819d522f475Smrg#if OPT_TCAP_QUERY 820d522f475Smrg if (screen->tc_query_code >= 0) { 8212eaa94a1Schristos kd.keysym = (KeySym) screen->tc_query_code; 822d522f475Smrg kd.is_fkey = screen->tc_query_fkey; 823d522f475Smrg if (kd.keysym != XK_BackSpace) { 824d522f475Smrg kd.nbytes = 0; 825d522f475Smrg kd.strbuf[0] = 0; 826d522f475Smrg } else { 827d522f475Smrg kd.nbytes = 1; 828d522f475Smrg kd.strbuf[0] = 8; 829d522f475Smrg } 830d522f475Smrg } else 831d522f475Smrg#endif 832d522f475Smrg { 833d522f475Smrg#if OPT_I18N_SUPPORT 834d522f475Smrg if (screen->xic) { 835d522f475Smrg Status status_return; 836d522f475Smrg#if OPT_WIDE_CHARS 837d522f475Smrg if (screen->utf8_mode) { 838d522f475Smrg kd.nbytes = Xutf8LookupString(screen->xic, event, 83920d2c4d2Smrg kd.strbuf, (int) sizeof(kd.strbuf), 840d522f475Smrg &kd.keysym, &status_return); 841d522f475Smrg } else 842d522f475Smrg#endif 843d522f475Smrg { 844d522f475Smrg kd.nbytes = XmbLookupString(screen->xic, event, 84520d2c4d2Smrg kd.strbuf, (int) sizeof(kd.strbuf), 846d522f475Smrg &kd.keysym, &status_return); 847d522f475Smrg } 848d522f475Smrg#if OPT_MOD_FKEYS 849d522f475Smrg /* 850d522f475Smrg * Fill-in some code useful with IsControlAlias(): 851d522f475Smrg */ 852d522f475Smrg if (status_return == XLookupBoth 853d522f475Smrg && kd.nbytes <= 1 854d522f475Smrg && !IsPredefinedKey(kd.keysym) 855d522f475Smrg && (keyboard->modify_now.other_keys > 1) 856d522f475Smrg && !IsControlInput(&kd)) { 857d522f475Smrg kd.nbytes = 1; 8582eaa94a1Schristos kd.strbuf[0] = (char) kd.keysym; 859d522f475Smrg } 860d522f475Smrg#endif /* OPT_MOD_FKEYS */ 861d522f475Smrg } else 862d522f475Smrg#endif /* OPT_I18N_SUPPORT */ 863d522f475Smrg { 864d522f475Smrg static XComposeStatus compose_status = 865d522f475Smrg {NULL, 0}; 86620d2c4d2Smrg kd.nbytes = XLookupString(event, kd.strbuf, (int) sizeof(kd.strbuf), 867d522f475Smrg &kd.keysym, &compose_status); 868d522f475Smrg } 869d522f475Smrg kd.is_fkey = IsFunctionKey(kd.keysym); 870d522f475Smrg } 871d522f475Smrg 872d522f475Smrg memset(&reply, 0, sizeof(reply)); 873d522f475Smrg 874d522f475Smrg TRACE(("Input keysym " 875d522f475Smrg KEYSYM_FMT 876d522f475Smrg ", %d:'%s'%s" FMT_MODIFIER_NAMES "%s%s%s%s%s%s\n", 877d522f475Smrg kd.keysym, 878d522f475Smrg kd.nbytes, 879956cc18dSsnj visibleChars((Char *) kd.strbuf, 880d522f475Smrg ((kd.nbytes > 0) 881d522f475Smrg ? (unsigned) kd.nbytes 882d522f475Smrg : 0)), 883d522f475Smrg ARG_MODIFIER_NAMES(evt_state), 884d522f475Smrg eightbit ? " 8bit" : " 7bit", 885d522f475Smrg IsKeypadKey(kd.keysym) ? " KeypadKey" : "", 886d522f475Smrg IsCursorKey(kd.keysym) ? " CursorKey" : "", 887d522f475Smrg IsPFKey(kd.keysym) ? " PFKey" : "", 888d522f475Smrg kd.is_fkey ? " FKey" : "", 889d522f475Smrg IsMiscFunctionKey(kd.keysym) ? " MiscFKey" : "", 890d522f475Smrg IsEditFunctionKey(kd.keysym) ? " EditFkey" : "")); 891d522f475Smrg 892d522f475Smrg#if OPT_SUNPC_KBD 893d522f475Smrg /* 894d522f475Smrg * DEC keyboards don't have keypad(+), but do have keypad(,) instead. 895d522f475Smrg * Other (Sun, PC) keyboards commonly have keypad(+), but no keypad(,) 896d522f475Smrg * - it's a pain for users to work around. 897d522f475Smrg */ 898d522f475Smrg if (keyboard->type == keyboardIsVT220 899d522f475Smrg && (evt_state & ShiftMask) == 0) { 900d522f475Smrg if (kd.keysym == XK_KP_Add) { 901d522f475Smrg kd.keysym = XK_KP_Separator; 90220d2c4d2Smrg UIntClr(evt_state, ShiftMask); 903d522f475Smrg TRACE(("...Input keypad(+), change keysym to " 904d522f475Smrg KEYSYM_FMT 905d522f475Smrg "\n", 906d522f475Smrg kd.keysym)); 907d522f475Smrg } 908d522f475Smrg if ((evt_state & ControlMask) != 0 909d522f475Smrg && kd.keysym == XK_KP_Separator) { 910d522f475Smrg kd.keysym = XK_KP_Subtract; 91120d2c4d2Smrg UIntClr(evt_state, ControlMask); 912d522f475Smrg TRACE(("...Input control/keypad(,), change keysym to " 913d522f475Smrg KEYSYM_FMT 914d522f475Smrg "\n", 915d522f475Smrg kd.keysym)); 916d522f475Smrg } 917d522f475Smrg } 918d522f475Smrg#endif 919d522f475Smrg 920d522f475Smrg /* 921d522f475Smrg * The keyboard tables may give us different keypad codes according to 922d522f475Smrg * whether NumLock is pressed. Use this check to simplify the process 923d522f475Smrg * of determining whether we generate an escape sequence for a keypad 924d522f475Smrg * key, or force it to the value kypd_num[]. There is no fixed 925d522f475Smrg * modifier for this feature, so we assume that it is the one assigned 926d522f475Smrg * to the NumLock key. 927d522f475Smrg * 928d522f475Smrg * This check used to try to return the contents of strbuf, but that 929d522f475Smrg * does not work properly when a control modifier is given (trash is 930d522f475Smrg * returned in the buffer in some cases -- perhaps an X bug). 931d522f475Smrg */ 932d522f475Smrg#if OPT_NUM_LOCK 933d522f475Smrg if (kd.nbytes == 1 934d522f475Smrg && IsKeypadKey(kd.keysym) 935d522f475Smrg && xw->misc.real_NumLock 936d522f475Smrg && (xw->misc.num_lock & evt_state) != 0) { 937d522f475Smrg keypad_mode = 0; 938d522f475Smrg TRACE(("...Input num_lock, force keypad_mode off\n")); 939d522f475Smrg } 940d522f475Smrg#endif 941d522f475Smrg 942d522f475Smrg#if OPT_MOD_FKEYS 943d522f475Smrg if (evt_state != 0 944d522f475Smrg && allowModifierParm(xw, &kd)) { 945d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 946d522f475Smrg } 947d522f475Smrg 948d522f475Smrg /* 949d522f475Smrg * Shift-tab is often mapped to XK_ISO_Left_Tab which is classified as 950d522f475Smrg * IsEditFunctionKey(), and the conversion does not produce any bytes. 951d522f475Smrg * Check for this special case so we have data when handling the 952d522f475Smrg * modifyOtherKeys resource. 953d522f475Smrg */ 954d522f475Smrg if (keyboard->modify_now.other_keys > 1) { 955d522f475Smrg if (IsTabKey(kd.keysym) && kd.nbytes == 0) { 956d522f475Smrg kd.nbytes = 1; 957d522f475Smrg kd.strbuf[0] = '\t'; 958d522f475Smrg } 959d522f475Smrg } 960d522f475Smrg#endif /* OPT_MOD_FKEYS */ 961d522f475Smrg 962d522f475Smrg /* VT300 & up: backarrow toggle */ 963d522f475Smrg if ((kd.nbytes == 1) 964d522f475Smrg && IsBackarrowToggle(keyboard, kd.keysym, evt_state)) { 965d522f475Smrg kd.strbuf[0] = ANSI_DEL; 966d522f475Smrg TRACE(("...Input backarrow changed to %d\n", kd.strbuf[0])); 967d522f475Smrg } 968d522f475Smrg#if OPT_SUNPC_KBD 969d522f475Smrg /* make an DEC editing-keypad from a Sun or PC editing-keypad */ 970d522f475Smrg if (keyboard->type == keyboardIsVT220 971d522f475Smrg && (kd.keysym != XK_Delete || !xtermDeleteIsDEL(xw))) 972d522f475Smrg kd.keysym = TranslateFromSUNPC(kd.keysym); 973d522f475Smrg else 974d522f475Smrg#endif 975d522f475Smrg { 976d522f475Smrg#ifdef XK_KP_Home 977d522f475Smrg if (kd.keysym >= XK_KP_Home && kd.keysym <= XK_KP_Begin) { 978d522f475Smrg TRACE(("...Input keypad before was " KEYSYM_FMT "\n", kd.keysym)); 9794e40088cSchristos kd.keysym += (KeySym) (XK_Home - XK_KP_Home); 980d522f475Smrg TRACE(("...Input keypad changed to " KEYSYM_FMT "\n", kd.keysym)); 981d522f475Smrg } 982d522f475Smrg#endif 983d522f475Smrg } 984d522f475Smrg 985d522f475Smrg /* 986d522f475Smrg * Map the Sun afterthought-keys in as F36 and F37. 987d522f475Smrg */ 988d522f475Smrg#ifdef SunXK_F36 989d522f475Smrg if (!kd.is_fkey) { 990d522f475Smrg if (kd.keysym == SunXK_F36) { 991d522f475Smrg kd.keysym = XK_Fn(36); 992d522f475Smrg kd.is_fkey = True; 993d522f475Smrg } 994d522f475Smrg if (kd.keysym == SunXK_F37) { 995d522f475Smrg kd.keysym = XK_Fn(37); 996d522f475Smrg kd.is_fkey = True; 997d522f475Smrg } 998d522f475Smrg } 999d522f475Smrg#endif 1000d522f475Smrg 1001d522f475Smrg /* 1002d522f475Smrg * Use the control- and shift-modifiers to obtain more function keys than 1003d522f475Smrg * the keyboard provides. We can do this if there is no conflicting use of 1004d522f475Smrg * those modifiers: 1005d522f475Smrg * 1006d522f475Smrg * a) for VT220 keyboard, we use only the control-modifier. The keyboard 1007d522f475Smrg * uses shift-modifier for UDK's. 1008d522f475Smrg * 1009d522f475Smrg * b) for non-VT220 keyboards, we only have to check if the 1010d522f475Smrg * modifyFunctionKeys resource is inactive. 1011d522f475Smrg * 1012d522f475Smrg * Thereafter, we note when we have a function-key and keep that 1013d522f475Smrg * distinction when testing for "function-key" values. 1014d522f475Smrg */ 1015d522f475Smrg if ((evt_state & (ControlMask | ShiftMask)) != 0 1016d522f475Smrg && kd.is_fkey) { 1017d522f475Smrg 1018d522f475Smrg /* VT220 keyboard uses shift for UDK */ 1019d522f475Smrg if (keyboard->type == keyboardIsVT220 1020d522f475Smrg || keyboard->type == keyboardIsLegacy) { 1021d522f475Smrg 1022d522f475Smrg TRACE(("...map XK_F%ld", kd.keysym - XK_Fn(1) + 1)); 1023d522f475Smrg if (evt_state & ControlMask) { 10242eaa94a1Schristos kd.keysym += (KeySym) xw->misc.ctrl_fkeys; 102520d2c4d2Smrg UIntClr(evt_state, ControlMask); 1026d522f475Smrg } 1027d522f475Smrg TRACE((" to XK_F%ld\n", kd.keysym - XK_Fn(1) + 1)); 1028d522f475Smrg 1029d522f475Smrg } 1030d522f475Smrg#if OPT_MOD_FKEYS 1031d522f475Smrg else if (keyboard->modify_now.function_keys < 0) { 1032d522f475Smrg 1033d522f475Smrg TRACE(("...map XK_F%ld", kd.keysym - XK_Fn(1) + 1)); 1034d522f475Smrg if (evt_state & ShiftMask) { 10352eaa94a1Schristos kd.keysym += (KeySym) (xw->misc.ctrl_fkeys * 1); 103620d2c4d2Smrg UIntClr(evt_state, ShiftMask); 1037d522f475Smrg } 1038d522f475Smrg if (evt_state & ControlMask) { 10392eaa94a1Schristos kd.keysym += (KeySym) (xw->misc.ctrl_fkeys * 2); 104020d2c4d2Smrg UIntClr(evt_state, ControlMask); 1041d522f475Smrg } 1042d522f475Smrg TRACE((" to XK_F%ld\n", kd.keysym - XK_Fn(1) + 1)); 1043d522f475Smrg 1044d522f475Smrg } 1045d522f475Smrg /* 1046d522f475Smrg * Reevaluate the modifier parameter, stripping off the modifiers 1047d522f475Smrg * that we just used. 1048d522f475Smrg */ 1049d522f475Smrg if (modify_parm) 1050d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 1051d522f475Smrg#endif /* OPT_MOD_FKEYS */ 1052d522f475Smrg } 1053d522f475Smrg 1054d522f475Smrg /* 1055d522f475Smrg * Test for one of the keyboard variants. 1056d522f475Smrg */ 1057d522f475Smrg switch (keyboard->type) { 1058d522f475Smrg case keyboardIsHP: 1059d522f475Smrg hpfuncvalue(&reply, &kd); 1060d522f475Smrg break; 1061d522f475Smrg case keyboardIsSCO: 1062d522f475Smrg scofuncvalue(&reply, &kd); 1063d522f475Smrg break; 1064d522f475Smrg case keyboardIsSun: 1065d522f475Smrg sunfuncvalue(&reply, &kd); 1066d522f475Smrg break; 1067d522f475Smrg case keyboardIsTermcap: 1068d522f475Smrg#if OPT_TCAP_FKEYS 1069d522f475Smrg if (xtermcapString(xw, (int) kd.keysym, evt_state)) 1070d522f475Smrg return; 1071d522f475Smrg#endif 1072d522f475Smrg break; 1073d522f475Smrg case keyboardIsDefault: 1074d522f475Smrg case keyboardIsLegacy: 1075d522f475Smrg case keyboardIsVT220: 1076d522f475Smrg break; 1077d522f475Smrg } 1078d522f475Smrg 1079d522f475Smrg if (reply.a_final) { 1080d522f475Smrg /* 1081d522f475Smrg * The key symbol matches one of the variants. Most of those are 1082d522f475Smrg * function-keys, though some cursor- and editing-keys are mixed in. 1083d522f475Smrg */ 1084d522f475Smrg modifyCursorKey(&reply, 1085d522f475Smrg ((kd.is_fkey 1086d522f475Smrg || IsMiscFunctionKey(kd.keysym) 1087d522f475Smrg || IsEditFunctionKey(kd.keysym)) 1088d522f475Smrg ? keyboard->modify_now.function_keys 1089d522f475Smrg : keyboard->modify_now.cursor_keys), 1090d522f475Smrg &modify_parm); 1091d522f475Smrg MODIFIER_PARM; 1092d522f475Smrg unparseseq(xw, &reply); 1093d522f475Smrg } else if (((kd.is_fkey 1094d522f475Smrg || IsMiscFunctionKey(kd.keysym) 1095d522f475Smrg || IsEditFunctionKey(kd.keysym)) 1096d522f475Smrg#if OPT_MOD_FKEYS 1097d522f475Smrg && !ModifyOtherKeys(xw, evt_state, &kd, modify_parm) 1098d522f475Smrg#endif 1099d522f475Smrg ) || (kd.keysym == XK_Delete 1100956cc18dSsnj && ((modify_parm != 0) 1101d522f475Smrg || !xtermDeleteIsDEL(xw)))) { 1102d522f475Smrg dec_code = decfuncvalue(&kd); 1103d522f475Smrg if ((evt_state & ShiftMask) 1104d522f475Smrg#if OPT_SUNPC_KBD 1105d522f475Smrg && keyboard->type == keyboardIsVT220 1106d522f475Smrg#endif 1107d522f475Smrg && ((string = (Char *) udk_lookup(dec_code, &kd.nbytes)) != 0)) { 110820d2c4d2Smrg UIntClr(evt_state, ShiftMask); 1109d522f475Smrg while (kd.nbytes-- > 0) 1110d522f475Smrg unparseputc(xw, CharOf(*string++)); 1111d522f475Smrg } 1112d522f475Smrg /* 1113d522f475Smrg * Interpret F1-F4 as PF1-PF4 for VT52, VT100 1114d522f475Smrg */ 1115d522f475Smrg else if (keyboard->type != keyboardIsLegacy 1116d522f475Smrg && (dec_code >= 11 && dec_code <= 14)) { 1117d522f475Smrg reply.a_type = ANSI_SS3; 1118d522f475Smrg VT52_CURSOR_KEYS; 11192eaa94a1Schristos reply.a_final = (Char) A2E(dec_code - 11 + E2A('P')); 1120d522f475Smrg modifyCursorKey(&reply, 1121d522f475Smrg keyboard->modify_now.function_keys, 1122d522f475Smrg &modify_parm); 1123d522f475Smrg MODIFIER_PARM; 1124d522f475Smrg unparseseq(xw, &reply); 1125956cc18dSsnj } else { 1126d522f475Smrg reply.a_type = ANSI_CSI; 1127d522f475Smrg reply.a_final = 0; 1128d522f475Smrg 1129d522f475Smrg#ifdef XK_ISO_Left_Tab 1130d522f475Smrg if (kd.keysym == XK_ISO_Left_Tab) { 1131d522f475Smrg reply.a_nparam = 0; 1132d522f475Smrg reply.a_final = 'Z'; 1133d522f475Smrg#if OPT_MOD_FKEYS 1134d522f475Smrg if (keyboard->modify_now.other_keys > 1 1135956cc18dSsnj && computeMaskedModifier(xw, evt_state, ShiftMask)) 1136d522f475Smrg modifyOtherKey(&reply, '\t', modify_parm, keyboard->format_keys); 1137d522f475Smrg#endif 1138d522f475Smrg } else 1139d522f475Smrg#endif /* XK_ISO_Left_Tab */ 1140d522f475Smrg { 1141d522f475Smrg reply.a_nparam = 1; 1142d522f475Smrg#if OPT_MOD_FKEYS 1143d522f475Smrg if (kd.is_fkey) { 1144d522f475Smrg modifyCursorKey(&reply, 1145d522f475Smrg keyboard->modify_now.function_keys, 1146d522f475Smrg &modify_parm); 1147d522f475Smrg } 1148d522f475Smrg MODIFIER_PARM; 1149d522f475Smrg#endif 1150956cc18dSsnj reply.a_param[0] = (ParmType) dec_code; 1151d522f475Smrg reply.a_final = '~'; 1152d522f475Smrg } 1153d522f475Smrg if (reply.a_final != 0 1154d522f475Smrg && (reply.a_nparam == 0 || reply.a_param[0] >= 0)) 1155d522f475Smrg unparseseq(xw, &reply); 1156d522f475Smrg } 1157d522f475Smrg key = True; 1158d522f475Smrg } else if (IsPFKey(kd.keysym)) { 1159d522f475Smrg reply.a_type = ANSI_SS3; 11602eaa94a1Schristos reply.a_final = (Char) ((kd.keysym - XK_KP_F1) + 'P'); 1161d522f475Smrg VT52_CURSOR_KEYS; 1162d522f475Smrg MODIFIER_PARM; 1163d522f475Smrg unparseseq(xw, &reply); 1164d522f475Smrg key = True; 1165d522f475Smrg } else if (IsKeypadKey(kd.keysym)) { 1166d522f475Smrg if (keypad_mode) { 1167d522f475Smrg reply.a_type = ANSI_SS3; 11682eaa94a1Schristos reply.a_final = (Char) (kypd_apl[kd.keysym - XK_KP_Space]); 1169d522f475Smrg VT52_KEYPAD; 1170d522f475Smrg MODIFIER_PARM; 1171d522f475Smrg unparseseq(xw, &reply); 1172d522f475Smrg } else { 1173d522f475Smrg unparseputc(xw, kypd_num[kd.keysym - XK_KP_Space]); 1174d522f475Smrg } 1175d522f475Smrg key = True; 1176d522f475Smrg } else if (IsCursorKey(kd.keysym)) { 1177d522f475Smrg if (keyboard->flags & MODE_DECCKM) { 1178d522f475Smrg reply.a_type = ANSI_SS3; 1179d522f475Smrg } else { 1180d522f475Smrg reply.a_type = ANSI_CSI; 1181d522f475Smrg } 1182d522f475Smrg modifyCursorKey(&reply, keyboard->modify_now.cursor_keys, &modify_parm); 11832eaa94a1Schristos reply.a_final = (Char) (curfinal[kd.keysym - XK_Home]); 1184d522f475Smrg VT52_CURSOR_KEYS; 1185d522f475Smrg MODIFIER_PARM; 1186d522f475Smrg unparseseq(xw, &reply); 1187d522f475Smrg key = True; 1188d522f475Smrg } else if (kd.nbytes > 0) { 1189d522f475Smrg int prefix = 0; 1190d522f475Smrg 1191d522f475Smrg#if OPT_TEK4014 1192d522f475Smrg if (TEK4014_GIN(tekWidget)) { 1193d522f475Smrg TekEnqMouse(tekWidget, kd.strbuf[0]); 1194d522f475Smrg TekGINoff(tekWidget); 1195d522f475Smrg kd.nbytes--; 1196d522f475Smrg for (j = 0; j < kd.nbytes; ++j) { 1197d522f475Smrg kd.strbuf[j] = kd.strbuf[j + 1]; 1198d522f475Smrg } 1199d522f475Smrg } 1200d522f475Smrg#endif 1201d522f475Smrg#if OPT_MOD_FKEYS 1202d522f475Smrg if ((keyboard->modify_now.other_keys > 0) 1203d522f475Smrg && ModifyOtherKeys(xw, evt_state, &kd, modify_parm) 1204d522f475Smrg && (mod_state = allowedCharModifiers(xw, evt_state, &kd)) != 0) { 1205d522f475Smrg int input_char; 1206d522f475Smrg 1207d522f475Smrg evt_state = mod_state; 1208d522f475Smrg 1209d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 1210d522f475Smrg 1211d522f475Smrg /* 1212d522f475Smrg * We want to show a keycode that corresponds to the 8-bit value 1213d522f475Smrg * of the key. If the keysym is less than 256, that is good 1214d522f475Smrg * enough. Special keys such as Tab may result in a value that 1215d522f475Smrg * is usable as well. For the latter (special cases), try to use 1216d522f475Smrg * the result from the X library lookup. 1217d522f475Smrg */ 1218d522f475Smrg input_char = ((kd.keysym < 256) 1219d522f475Smrg ? (int) kd.keysym 1220d522f475Smrg : ((kd.nbytes == 1) 1221d522f475Smrg ? CharOf(kd.strbuf[0]) 1222d522f475Smrg : -1)); 1223d522f475Smrg 1224d522f475Smrg TRACE(("...modifyOtherKeys %d;%d\n", modify_parm, input_char)); 1225d522f475Smrg if (modifyOtherKey(&reply, input_char, modify_parm, keyboard->format_keys)) { 1226d522f475Smrg unparseseq(xw, &reply); 1227d522f475Smrg } else { 122820d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 1229d522f475Smrg } 1230d522f475Smrg } else 1231d522f475Smrg#endif /* OPT_MOD_FKEYS */ 1232d522f475Smrg { 1233d522f475Smrg#if OPT_NUM_LOCK 1234d522f475Smrg /* 1235d522f475Smrg * Send ESC if we have a META modifier and metaSendsEcape is true. 1236d522f475Smrg * Like eightBitInput, except that it is not associated with 1237d522f475Smrg * terminal settings. 1238d522f475Smrg */ 1239d522f475Smrg if (kd.nbytes != 0) { 1240d522f475Smrg if (screen->meta_sends_esc 1241d522f475Smrg && (evt_state & xw->misc.meta_mods) != 0) { 1242d522f475Smrg TRACE(("...input-char is modified by META\n")); 124320d2c4d2Smrg UIntClr(evt_state, xw->misc.meta_mods); 1244d522f475Smrg eightbit = False; 1245d522f475Smrg prefix = ANSI_ESC; 1246d522f475Smrg } else if (eightbit) { 1247d522f475Smrg /* it might be overridden, but this helps for debugging */ 1248d522f475Smrg TRACE(("...input-char is shifted by META\n")); 1249d522f475Smrg } 1250d522f475Smrg if (screen->alt_is_not_meta 1251d522f475Smrg && (evt_state & xw->misc.alt_mods) != 0) { 125220d2c4d2Smrg UIntClr(evt_state, xw->misc.alt_mods); 1253d522f475Smrg if (screen->alt_sends_esc) { 1254d522f475Smrg TRACE(("...input-char is modified by ALT\n")); 12552eaa94a1Schristos eightbit = False; 1256d522f475Smrg prefix = ANSI_ESC; 1257d522f475Smrg } else if (!eightbit) { 1258d522f475Smrg TRACE(("...input-char is shifted by ALT\n")); 1259d522f475Smrg eightbit = True; 1260d522f475Smrg } 1261d522f475Smrg } 1262d522f475Smrg } 1263d522f475Smrg#endif 1264d522f475Smrg /* 1265d522f475Smrg * If metaSendsEscape is false, fall through to this chunk, which 1266d522f475Smrg * implements the eightBitInput resource. 1267d522f475Smrg * 1268d522f475Smrg * It is normally executed when the user presses Meta plus a 1269d522f475Smrg * printable key, e.g., Meta+space. The presence of the Meta 1270d522f475Smrg * modifier is not guaranteed since what really happens is the 1271d522f475Smrg * "insert-eight-bit" or "insert-seven-bit" action, which we 1272d522f475Smrg * distinguish by the eightbit parameter to this function. So the 1273d522f475Smrg * eightBitInput resource really means that we use this shifting 1274d522f475Smrg * logic in the "insert-eight-bit" action. 1275d522f475Smrg */ 1276d522f475Smrg if (eightbit && (kd.nbytes == 1) && screen->input_eight_bits) { 1277d522f475Smrg IChar ch = CharOf(kd.strbuf[0]); 1278d522f475Smrg if (ch < 128) { 12792eaa94a1Schristos kd.strbuf[0] |= (char) 0x80; 1280d522f475Smrg TRACE(("...input shift from %d to %d (%#x to %#x)\n", 1281d522f475Smrg ch, CharOf(kd.strbuf[0]), 1282d522f475Smrg ch, CharOf(kd.strbuf[0]))); 1283d522f475Smrg#if OPT_WIDE_CHARS 1284d522f475Smrg if (screen->utf8_mode) { 1285d522f475Smrg /* 1286d522f475Smrg * We could interpret the incoming code as "in the 1287d522f475Smrg * current locale", but it's simpler to treat it as 1288d522f475Smrg * a Unicode value to translate to UTF-8. 1289d522f475Smrg */ 1290d522f475Smrg ch = CharOf(kd.strbuf[0]); 1291d522f475Smrg kd.nbytes = 2; 12922eaa94a1Schristos kd.strbuf[0] = (char) (0xc0 | ((ch >> 6) & 0x3)); 12932eaa94a1Schristos kd.strbuf[1] = (char) (0x80 | (ch & 0x3f)); 1294d522f475Smrg TRACE(("...encoded %#x in UTF-8 as %#x,%#x\n", 1295d522f475Smrg ch, CharOf(kd.strbuf[0]), CharOf(kd.strbuf[1]))); 1296d522f475Smrg } 1297d522f475Smrg#endif 1298d522f475Smrg } 1299d522f475Smrg eightbit = False; 1300d522f475Smrg } 1301d522f475Smrg#if OPT_WIDE_CHARS 1302d522f475Smrg if (kd.nbytes == 1) /* cannot do NRC on UTF-8, for instance */ 1303d522f475Smrg#endif 1304d522f475Smrg { 1305d522f475Smrg /* VT220 & up: National Replacement Characters */ 1306d522f475Smrg if ((xw->flags & NATIONAL) != 0) { 13072eaa94a1Schristos unsigned cmp = xtermCharSetIn(CharOf(kd.strbuf[0]), 13082eaa94a1Schristos screen->keyboard_dialect[0]); 1309d522f475Smrg TRACE(("...input NRC %d, %s %d\n", 1310d522f475Smrg CharOf(kd.strbuf[0]), 1311d522f475Smrg (CharOf(kd.strbuf[0]) == cmp) 1312d522f475Smrg ? "unchanged" 1313d522f475Smrg : "changed to", 1314d522f475Smrg CharOf(cmp))); 13152eaa94a1Schristos kd.strbuf[0] = (char) cmp; 1316d522f475Smrg } else if (eightbit) { 1317d522f475Smrg prefix = ANSI_ESC; 1318d522f475Smrg } else if (kd.strbuf[0] == '?' 1319d522f475Smrg && (evt_state & ControlMask) != 0) { 1320d522f475Smrg kd.strbuf[0] = ANSI_DEL; 132120d2c4d2Smrg UIntClr(evt_state, ControlMask); 1322d522f475Smrg } 1323d522f475Smrg } 1324d522f475Smrg if (prefix != 0) 1325d522f475Smrg unparseputc(xw, prefix); /* escape */ 1326d522f475Smrg for (j = 0; j < kd.nbytes; ++j) 1327d522f475Smrg unparseputc(xw, CharOf(kd.strbuf[j])); 1328d522f475Smrg } 132920d2c4d2Smrg key = ((kd.keysym != ANSI_XOFF) && (kd.keysym != ANSI_XON)); 1330d522f475Smrg } 1331d522f475Smrg unparse_end(xw); 1332d522f475Smrg 1333d522f475Smrg if (key && !TEK4014_ACTIVE(xw)) 1334d522f475Smrg AdjustAfterInput(xw); 1335d522f475Smrg 1336d522f475Smrg xtermShowPointer(xw, False); 1337d522f475Smrg return; 1338d522f475Smrg} 1339d522f475Smrg 1340d522f475Smrgvoid 134120d2c4d2SmrgStringInput(XtermWidget xw, const Char * string, size_t nbytes) 1342d522f475Smrg{ 134320d2c4d2Smrg TRACE(("InputString (%s,%lu)\n", 134420d2c4d2Smrg visibleChars(string, (unsigned) nbytes), 134520d2c4d2Smrg (unsigned long) nbytes)); 1346d522f475Smrg#if OPT_TEK4014 1347d522f475Smrg if (nbytes && TEK4014_GIN(tekWidget)) { 1348d522f475Smrg TekEnqMouse(tekWidget, *string++); 1349d522f475Smrg TekGINoff(tekWidget); 1350d522f475Smrg nbytes--; 1351d522f475Smrg } 1352d522f475Smrg#endif 1353d522f475Smrg while (nbytes-- != 0) 1354d522f475Smrg unparseputc(xw, *string++); 1355d522f475Smrg if (!TEK4014_ACTIVE(xw)) 1356d522f475Smrg AdjustAfterInput(xw); 1357d522f475Smrg unparse_end(xw); 1358d522f475Smrg} 1359d522f475Smrg 1360d522f475Smrg/* These definitions are DEC-style (e.g., vt320) */ 1361d522f475Smrgstatic int 1362d522f475Smrgdecfuncvalue(KEY_DATA * kd) 1363d522f475Smrg{ 1364d522f475Smrg int result; 1365d522f475Smrg 1366d522f475Smrg if (kd->is_fkey) { 1367d522f475Smrg switch (kd->keysym) { 1368d522f475Smrg MAP(XK_Fn(1), 11); 1369d522f475Smrg MAP(XK_Fn(2), 12); 1370d522f475Smrg MAP(XK_Fn(3), 13); 1371d522f475Smrg MAP(XK_Fn(4), 14); 1372d522f475Smrg MAP(XK_Fn(5), 15); 1373d522f475Smrg MAP(XK_Fn(6), 17); 1374d522f475Smrg MAP(XK_Fn(7), 18); 1375d522f475Smrg MAP(XK_Fn(8), 19); 1376d522f475Smrg MAP(XK_Fn(9), 20); 1377d522f475Smrg MAP(XK_Fn(10), 21); 1378d522f475Smrg MAP(XK_Fn(11), 23); 1379d522f475Smrg MAP(XK_Fn(12), 24); 1380d522f475Smrg MAP(XK_Fn(13), 25); 1381d522f475Smrg MAP(XK_Fn(14), 26); 1382d522f475Smrg MAP(XK_Fn(15), 28); 1383d522f475Smrg MAP(XK_Fn(16), 29); 1384d522f475Smrg MAP(XK_Fn(17), 31); 1385d522f475Smrg MAP(XK_Fn(18), 32); 1386d522f475Smrg MAP(XK_Fn(19), 33); 1387d522f475Smrg MAP(XK_Fn(20), 34); 1388d522f475Smrg default: 1389d522f475Smrg /* after F20 the codes are made up and do not correspond to any 1390d522f475Smrg * real terminal. So they are simply numbered sequentially. 1391d522f475Smrg */ 13922eaa94a1Schristos result = 42 + (int) (kd->keysym - XK_Fn(21)); 1393d522f475Smrg break; 1394d522f475Smrg } 1395d522f475Smrg } else { 1396d522f475Smrg switch (kd->keysym) { 1397d522f475Smrg MAP(XK_Find, 1); 1398d522f475Smrg MAP(XK_Insert, 2); 1399d522f475Smrg MAP(XK_Delete, 3); 1400d522f475Smrg#ifdef XK_KP_Insert 1401d522f475Smrg MAP(XK_KP_Insert, 2); 1402d522f475Smrg MAP(XK_KP_Delete, 3); 1403d522f475Smrg#endif 1404d522f475Smrg#ifdef DXK_Remove 1405d522f475Smrg MAP(DXK_Remove, 3); 1406d522f475Smrg#endif 1407d522f475Smrg MAP(XK_Select, 4); 1408d522f475Smrg MAP(XK_Prior, 5); 1409d522f475Smrg MAP(XK_Next, 6); 1410d522f475Smrg#ifdef XK_ISO_Left_Tab 1411d522f475Smrg MAP(XK_ISO_Left_Tab, 'Z'); 1412d522f475Smrg#endif 1413d522f475Smrg MAP(XK_Help, 28); 1414d522f475Smrg MAP(XK_Menu, 29); 1415d522f475Smrg default: 1416d522f475Smrg result = -1; 1417d522f475Smrg break; 1418d522f475Smrg } 1419d522f475Smrg } 1420d522f475Smrg return result; 1421d522f475Smrg} 1422d522f475Smrg 1423d522f475Smrgstatic void 1424d522f475Smrghpfuncvalue(ANSI * reply, KEY_DATA * kd) 1425d522f475Smrg{ 1426d522f475Smrg#if OPT_HP_FUNC_KEYS 1427d522f475Smrg int result; 1428d522f475Smrg 1429d522f475Smrg if (kd->is_fkey) { 1430d522f475Smrg switch (kd->keysym) { 1431d522f475Smrg MAP(XK_Fn(1), 'p'); 1432d522f475Smrg MAP(XK_Fn(2), 'q'); 1433d522f475Smrg MAP(XK_Fn(3), 'r'); 1434d522f475Smrg MAP(XK_Fn(4), 's'); 1435d522f475Smrg MAP(XK_Fn(5), 't'); 1436d522f475Smrg MAP(XK_Fn(6), 'u'); 1437d522f475Smrg MAP(XK_Fn(7), 'v'); 1438d522f475Smrg MAP(XK_Fn(8), 'w'); 1439d522f475Smrg default: 1440d522f475Smrg result = -1; 1441d522f475Smrg break; 1442d522f475Smrg } 1443d522f475Smrg } else { 1444d522f475Smrg switch (kd->keysym) { 1445d522f475Smrg MAP(XK_Up, 'A'); 1446d522f475Smrg MAP(XK_Down, 'B'); 1447d522f475Smrg MAP(XK_Right, 'C'); 1448d522f475Smrg MAP(XK_Left, 'D'); 1449d522f475Smrg MAP(XK_End, 'F'); 1450d522f475Smrg MAP(XK_Clear, 'J'); 1451d522f475Smrg MAP(XK_Delete, 'P'); 1452d522f475Smrg MAP(XK_Insert, 'Q'); 1453d522f475Smrg MAP(XK_Next, 'S'); 1454d522f475Smrg MAP(XK_Prior, 'T'); 1455d522f475Smrg MAP(XK_Home, 'h'); 1456d522f475Smrg#ifdef XK_KP_Insert 1457d522f475Smrg MAP(XK_KP_Delete, 'P'); 1458d522f475Smrg MAP(XK_KP_Insert, 'Q'); 1459d522f475Smrg#endif 1460d522f475Smrg#ifdef DXK_Remove 1461d522f475Smrg MAP(DXK_Remove, 'P'); 1462d522f475Smrg#endif 1463d522f475Smrg MAP(XK_Select, 'F'); 1464d522f475Smrg MAP(XK_Find, 'h'); 1465d522f475Smrg default: 1466d522f475Smrg result = -1; 1467d522f475Smrg break; 1468d522f475Smrg } 1469d522f475Smrg } 1470d522f475Smrg if (result > 0) { 1471d522f475Smrg reply->a_type = ANSI_ESC; 14722eaa94a1Schristos reply->a_final = (Char) result; 1473d522f475Smrg } 1474d522f475Smrg#else 1475d522f475Smrg (void) reply; 1476d522f475Smrg (void) kd; 1477d522f475Smrg#endif /* OPT_HP_FUNC_KEYS */ 1478d522f475Smrg} 1479d522f475Smrg 1480d522f475Smrgstatic void 1481d522f475Smrgscofuncvalue(ANSI * reply, KEY_DATA * kd) 1482d522f475Smrg{ 1483d522f475Smrg#if OPT_SCO_FUNC_KEYS 1484d522f475Smrg int result; 1485d522f475Smrg 1486d522f475Smrg if (kd->is_fkey) { 1487d522f475Smrg switch (kd->keysym) { 1488d522f475Smrg MAP(XK_Fn(1), 'M'); 1489d522f475Smrg MAP(XK_Fn(2), 'N'); 1490d522f475Smrg MAP(XK_Fn(3), 'O'); 1491d522f475Smrg MAP(XK_Fn(4), 'P'); 1492d522f475Smrg MAP(XK_Fn(5), 'Q'); 1493d522f475Smrg MAP(XK_Fn(6), 'R'); 1494d522f475Smrg MAP(XK_Fn(7), 'S'); 1495d522f475Smrg MAP(XK_Fn(8), 'T'); 1496d522f475Smrg MAP(XK_Fn(9), 'U'); 1497d522f475Smrg MAP(XK_Fn(10), 'V'); 1498d522f475Smrg MAP(XK_Fn(11), 'W'); 1499d522f475Smrg MAP(XK_Fn(12), 'X'); 1500d522f475Smrg MAP(XK_Fn(13), 'Y'); 1501d522f475Smrg MAP(XK_Fn(14), 'Z'); 1502d522f475Smrg MAP(XK_Fn(15), 'a'); 1503d522f475Smrg MAP(XK_Fn(16), 'b'); 1504d522f475Smrg MAP(XK_Fn(17), 'c'); 1505d522f475Smrg MAP(XK_Fn(18), 'd'); 1506d522f475Smrg MAP(XK_Fn(19), 'e'); 1507d522f475Smrg MAP(XK_Fn(20), 'f'); 1508d522f475Smrg MAP(XK_Fn(21), 'g'); 1509d522f475Smrg MAP(XK_Fn(22), 'h'); 1510d522f475Smrg MAP(XK_Fn(23), 'i'); 1511d522f475Smrg MAP(XK_Fn(24), 'j'); 1512d522f475Smrg MAP(XK_Fn(25), 'k'); 1513d522f475Smrg MAP(XK_Fn(26), 'l'); 1514d522f475Smrg MAP(XK_Fn(27), 'm'); 1515d522f475Smrg MAP(XK_Fn(28), 'n'); 1516d522f475Smrg MAP(XK_Fn(29), 'o'); 1517d522f475Smrg MAP(XK_Fn(30), 'p'); 1518d522f475Smrg MAP(XK_Fn(31), 'q'); 1519d522f475Smrg MAP(XK_Fn(32), 'r'); 1520d522f475Smrg MAP(XK_Fn(33), 's'); 1521d522f475Smrg MAP(XK_Fn(34), 't'); 1522d522f475Smrg MAP(XK_Fn(35), 'u'); 1523d522f475Smrg MAP(XK_Fn(36), 'v'); 1524d522f475Smrg MAP(XK_Fn(37), 'w'); 1525d522f475Smrg MAP(XK_Fn(38), 'x'); 1526d522f475Smrg MAP(XK_Fn(39), 'y'); 1527d522f475Smrg MAP(XK_Fn(40), 'z'); 1528d522f475Smrg MAP(XK_Fn(41), '@'); 1529d522f475Smrg MAP(XK_Fn(42), '['); 1530d522f475Smrg MAP(XK_Fn(43), '\\'); 1531d522f475Smrg MAP(XK_Fn(44), ']'); 1532d522f475Smrg MAP(XK_Fn(45), '^'); 1533d522f475Smrg MAP(XK_Fn(46), '_'); 1534d522f475Smrg MAP(XK_Fn(47), '`'); 1535d522f475Smrg MAP(XK_Fn(48), '{'); /* no matching '}' */ 1536d522f475Smrg default: 1537d522f475Smrg result = -1; 1538d522f475Smrg break; 1539d522f475Smrg } 1540d522f475Smrg } else { 1541d522f475Smrg switch (kd->keysym) { 1542d522f475Smrg MAP(XK_Up, 'A'); 1543d522f475Smrg MAP(XK_Down, 'B'); 1544d522f475Smrg MAP(XK_Right, 'C'); 1545d522f475Smrg MAP(XK_Left, 'D'); 1546d522f475Smrg MAP(XK_Begin, 'E'); 1547d522f475Smrg MAP(XK_End, 'F'); 1548d522f475Smrg MAP(XK_Insert, 'L'); 1549d522f475Smrg MAP(XK_Next, 'G'); 1550d522f475Smrg MAP(XK_Prior, 'I'); 1551d522f475Smrg MAP(XK_Home, 'H'); 1552d522f475Smrg#ifdef XK_KP_Insert 1553d522f475Smrg MAP(XK_KP_Insert, 'L'); 1554d522f475Smrg#endif 1555d522f475Smrg default: 1556d522f475Smrg result = -1; 1557d522f475Smrg break; 1558d522f475Smrg } 1559d522f475Smrg } 1560d522f475Smrg if (result > 0) { 1561d522f475Smrg reply->a_type = ANSI_CSI; 15622eaa94a1Schristos reply->a_final = (Char) result; 1563d522f475Smrg } 1564d522f475Smrg#else 1565d522f475Smrg (void) reply; 1566d522f475Smrg (void) kd; 1567d522f475Smrg#endif /* OPT_SCO_FUNC_KEYS */ 1568d522f475Smrg} 1569d522f475Smrg 1570d522f475Smrgstatic void 1571d522f475Smrgsunfuncvalue(ANSI * reply, KEY_DATA * kd) 1572d522f475Smrg{ 1573d522f475Smrg#if OPT_SUN_FUNC_KEYS 1574956cc18dSsnj ParmType result; 1575d522f475Smrg 1576d522f475Smrg if (kd->is_fkey) { 1577d522f475Smrg switch (kd->keysym) { 1578d522f475Smrg /* kf1-kf20 are numbered sequentially */ 1579d522f475Smrg MAP(XK_Fn(1), 224); 1580d522f475Smrg MAP(XK_Fn(2), 225); 1581d522f475Smrg MAP(XK_Fn(3), 226); 1582d522f475Smrg MAP(XK_Fn(4), 227); 1583d522f475Smrg MAP(XK_Fn(5), 228); 1584d522f475Smrg MAP(XK_Fn(6), 229); 1585d522f475Smrg MAP(XK_Fn(7), 230); 1586d522f475Smrg MAP(XK_Fn(8), 231); 1587d522f475Smrg MAP(XK_Fn(9), 232); 1588d522f475Smrg MAP(XK_Fn(10), 233); 1589d522f475Smrg MAP(XK_Fn(11), 192); 1590d522f475Smrg MAP(XK_Fn(12), 193); 1591d522f475Smrg MAP(XK_Fn(13), 194); 1592d522f475Smrg MAP(XK_Fn(14), 195); /* kund */ 1593d522f475Smrg MAP(XK_Fn(15), 196); 1594d522f475Smrg MAP(XK_Fn(16), 197); /* kcpy */ 1595d522f475Smrg MAP(XK_Fn(17), 198); 1596d522f475Smrg MAP(XK_Fn(18), 199); 1597d522f475Smrg MAP(XK_Fn(19), 200); /* kfnd */ 1598d522f475Smrg MAP(XK_Fn(20), 201); 1599d522f475Smrg 1600d522f475Smrg /* kf31-kf36 are numbered sequentially */ 1601d522f475Smrg MAP(XK_Fn(21), 208); /* kf31 */ 1602d522f475Smrg MAP(XK_Fn(22), 209); 1603d522f475Smrg MAP(XK_Fn(23), 210); 1604d522f475Smrg MAP(XK_Fn(24), 211); 1605d522f475Smrg MAP(XK_Fn(25), 212); 1606d522f475Smrg MAP(XK_Fn(26), 213); /* kf36 */ 1607d522f475Smrg 1608d522f475Smrg /* kf37-kf47 are interspersed with keypad keys */ 1609d522f475Smrg MAP(XK_Fn(27), 214); /* khome */ 1610d522f475Smrg MAP(XK_Fn(28), 215); /* kf38 */ 1611d522f475Smrg MAP(XK_Fn(29), 216); /* kpp */ 1612d522f475Smrg MAP(XK_Fn(30), 217); /* kf40 */ 1613d522f475Smrg MAP(XK_Fn(31), 218); /* kb2 */ 1614d522f475Smrg MAP(XK_Fn(32), 219); /* kf42 */ 1615d522f475Smrg MAP(XK_Fn(33), 220); /* kend */ 1616d522f475Smrg MAP(XK_Fn(34), 221); /* kf44 */ 1617d522f475Smrg MAP(XK_Fn(35), 222); /* knp */ 1618d522f475Smrg MAP(XK_Fn(36), 234); /* kf46 */ 1619d522f475Smrg MAP(XK_Fn(37), 235); /* kf47 */ 1620d522f475Smrg default: 1621d522f475Smrg result = -1; 1622d522f475Smrg break; 1623d522f475Smrg } 1624d522f475Smrg } else { 1625d522f475Smrg switch (kd->keysym) { 1626d522f475Smrg MAP(XK_Help, 196); /* khlp */ 1627d522f475Smrg MAP(XK_Menu, 197); 1628d522f475Smrg 1629d522f475Smrg MAP(XK_Find, 1); 1630d522f475Smrg MAP(XK_Insert, 2); /* kich1 */ 1631d522f475Smrg MAP(XK_Delete, 3); 1632d522f475Smrg#ifdef XK_KP_Insert 1633d522f475Smrg MAP(XK_KP_Insert, 2); 1634d522f475Smrg MAP(XK_KP_Delete, 3); 1635d522f475Smrg#endif 1636d522f475Smrg#ifdef DXK_Remove 1637d522f475Smrg MAP(DXK_Remove, 3); 1638d522f475Smrg#endif 1639d522f475Smrg MAP(XK_Select, 4); 1640d522f475Smrg 1641d522f475Smrg MAP(XK_Prior, 216); 1642d522f475Smrg MAP(XK_Next, 222); 1643d522f475Smrg MAP(XK_Home, 214); 1644d522f475Smrg MAP(XK_End, 220); 1645d522f475Smrg MAP(XK_Begin, 218); /* kf41=kb2 */ 1646d522f475Smrg 1647d522f475Smrg default: 1648d522f475Smrg result = -1; 1649d522f475Smrg break; 1650d522f475Smrg } 1651d522f475Smrg } 1652d522f475Smrg if (result > 0) { 1653d522f475Smrg reply->a_type = ANSI_CSI; 1654d522f475Smrg reply->a_nparam = 1; 1655d522f475Smrg reply->a_param[0] = result; 1656d522f475Smrg reply->a_final = 'z'; 1657d522f475Smrg } else if (IsCursorKey(kd->keysym)) { 1658d522f475Smrg reply->a_type = ANSI_SS3; 16592eaa94a1Schristos reply->a_final = (Char) curfinal[kd->keysym - XK_Home]; 1660d522f475Smrg } 1661d522f475Smrg#else 1662d522f475Smrg (void) reply; 1663d522f475Smrg (void) kd; 1664d522f475Smrg#endif /* OPT_SUN_FUNC_KEYS */ 1665d522f475Smrg} 1666d522f475Smrg 1667d522f475Smrg#if OPT_NUM_LOCK 166820d2c4d2Smrg#define isName(c) ((c) == '_' || (c) == '-' || isalnum(CharOf(c))) 166920d2c4d2Smrg 167020d2c4d2Smrgstatic const char * 167120d2c4d2SmrgskipName(const char *s) 167220d2c4d2Smrg{ 167320d2c4d2Smrg while (*s != '\0' && isName(CharOf(*s))) 167420d2c4d2Smrg ++s; 167520d2c4d2Smrg return s; 167620d2c4d2Smrg} 167720d2c4d2Smrg 167820d2c4d2Smrg/* 167920d2c4d2Smrg * Found a ":" in a translation, check what is past it to see if it contains 168020d2c4d2Smrg * any of the insert-text action names. 168120d2c4d2Smrg */ 168220d2c4d2Smrgstatic Boolean 168320d2c4d2SmrgkeyCanInsert(const char *parse) 168420d2c4d2Smrg{ 168520d2c4d2Smrg Boolean result = False; 168620d2c4d2Smrg int ch; 168720d2c4d2Smrg Boolean escape = False; 168820d2c4d2Smrg Boolean quoted = False; 168920d2c4d2Smrg 169020d2c4d2Smrg static const char *table[] = 169120d2c4d2Smrg { 169220d2c4d2Smrg "insert", 169320d2c4d2Smrg "insert-seven-bit", 169420d2c4d2Smrg "insert-eight-bit", 169520d2c4d2Smrg "string", 169620d2c4d2Smrg }; 169720d2c4d2Smrg Cardinal n; 169820d2c4d2Smrg 169920d2c4d2Smrg while (*parse != '\0' && *parse != '\n') { 170020d2c4d2Smrg ch = CharOf(*parse++); 170120d2c4d2Smrg if (escape) { 170220d2c4d2Smrg escape = False; 170320d2c4d2Smrg } else if (ch == '\\') { 170420d2c4d2Smrg escape = True; 170520d2c4d2Smrg } else if (ch == '"') { 170620d2c4d2Smrg quoted = (Boolean) ! quoted; 170720d2c4d2Smrg } else if (!quoted && isName(ch)) { 170820d2c4d2Smrg const char *next = skipName(--parse); 170920d2c4d2Smrg size_t need = (size_t) (next - parse); 171020d2c4d2Smrg 171120d2c4d2Smrg for (n = 0; n < XtNumber(table); ++n) { 171220d2c4d2Smrg if (need == strlen(table[n]) 171320d2c4d2Smrg && !strncmp(parse, table[n], need)) { 171420d2c4d2Smrg result = True; 171520d2c4d2Smrg break; 171620d2c4d2Smrg } 171720d2c4d2Smrg } 171820d2c4d2Smrg parse = next; 171920d2c4d2Smrg } 172020d2c4d2Smrg 172120d2c4d2Smrg } 172220d2c4d2Smrg return result; 172320d2c4d2Smrg} 172420d2c4d2Smrg 172520d2c4d2Smrg/* 172620d2c4d2Smrg * Strip the entire action, to avoid matching it. 172720d2c4d2Smrg */ 172820d2c4d2Smrgstatic char * 172920d2c4d2SmrgstripAction(char *base, char *last) 173020d2c4d2Smrg{ 173120d2c4d2Smrg while (last != base) { 173220d2c4d2Smrg if (*--last == '\n') { 173320d2c4d2Smrg break; 173420d2c4d2Smrg } 173520d2c4d2Smrg } 173620d2c4d2Smrg return last; 173720d2c4d2Smrg} 173820d2c4d2Smrg 173920d2c4d2Smrgstatic char * 174020d2c4d2SmrgstripBlanks(char *base, char *last) 174120d2c4d2Smrg{ 174220d2c4d2Smrg while (last != base) { 174320d2c4d2Smrg int ch = CharOf(last[-1]); 174420d2c4d2Smrg if (ch != ' ' && ch != '\t') 174520d2c4d2Smrg break; 174620d2c4d2Smrg --last; 174720d2c4d2Smrg } 174820d2c4d2Smrg return last; 174920d2c4d2Smrg} 1750d522f475Smrg 1751d522f475Smrg/* 17522eaa94a1Schristos * Strip unneeded whitespace from a translations resource, mono-casing and 1753d522f475Smrg * returning a malloc'd copy of the result. 1754d522f475Smrg */ 1755d522f475Smrgstatic char * 175620d2c4d2SmrgstripTranslations(const char *s, Bool onlyInsert) 1757d522f475Smrg{ 1758d522f475Smrg char *dst = 0; 1759d522f475Smrg 1760d522f475Smrg if (s != 0) { 1761d522f475Smrg dst = TypeMallocN(char, strlen(s) + 1); 1762d522f475Smrg 1763d522f475Smrg if (dst != 0) { 1764d522f475Smrg int state = 0; 1765d522f475Smrg int ch = 0; 1766d522f475Smrg int prv = 0; 1767d522f475Smrg char *d = dst; 1768d522f475Smrg 1769d522f475Smrg TRACE(("stripping:\n%s\n", s)); 1770d522f475Smrg while (*s != '\0') { 1771d522f475Smrg ch = *s++; 1772d522f475Smrg if (ch == '\n') { 1773d522f475Smrg if (d != dst) 17742eaa94a1Schristos *d++ = (char) ch; 1775d522f475Smrg state = 0; 1776d522f475Smrg } else if (strchr(":!#", ch) != 0) { 177720d2c4d2Smrg d = stripBlanks(dst, d); 177820d2c4d2Smrg if (onlyInsert && (ch == ':') && !keyCanInsert(s)) { 177920d2c4d2Smrg d = stripAction(dst, d); 178020d2c4d2Smrg } 1781d522f475Smrg state = -1; 1782d522f475Smrg } else if (state >= 0) { 1783d522f475Smrg if (isspace(CharOf(ch))) { 1784d522f475Smrg if (state == 0 || strchr("<>~ \t", prv)) 1785d522f475Smrg continue; 1786d522f475Smrg } else if (strchr("<>~", ch)) { 178720d2c4d2Smrg d = stripBlanks(dst, d); 1788d522f475Smrg } 17892eaa94a1Schristos *d++ = x_toupper(ch); 1790d522f475Smrg ++state; 1791d522f475Smrg } 1792d522f475Smrg prv = ch; 1793d522f475Smrg } 1794d522f475Smrg *d = '\0'; 1795d522f475Smrg TRACE(("...result:\n%s\n", dst)); 1796d522f475Smrg } 1797d522f475Smrg } 1798d522f475Smrg return dst; 1799d522f475Smrg} 1800d522f475Smrg 1801d522f475Smrg/* 1802d522f475Smrg * Make a simple check to see if a given translations keyword appears in 1803d522f475Smrg * xterm's translations resource. It does not attempt to parse the strings, 1804d522f475Smrg * just makes a case-independent check and ensures that the ends of the match 1805d522f475Smrg * are on token-boundaries. 1806d522f475Smrg * 1807d522f475Smrg * That this can only retrieve translations that are given as resource values; 1808d522f475Smrg * the default translations in charproc.c for example are not retrievable by 1809d522f475Smrg * any interface to X. 1810d522f475Smrg * 1811d522f475Smrg * Also: We can retrieve only the most-specified translation resource. For 1812d522f475Smrg * example, if the resource file specifies both "*translations" and 1813d522f475Smrg * "XTerm*translations", we see only the latter. 1814d522f475Smrg */ 1815d522f475Smrgstatic Bool 181620d2c4d2SmrgTranslationsUseKeyword(Widget w, char **cache, const char *keyword, Bool onlyInsert) 1817d522f475Smrg{ 1818d522f475Smrg static String data; 1819d522f475Smrg static XtResource key_resources[] = 1820d522f475Smrg { 1821d522f475Smrg {XtNtranslations, XtCTranslations, XtRString, 1822d522f475Smrg sizeof(data), 0, XtRString, (XtPointer) NULL} 1823d522f475Smrg }; 1824d522f475Smrg Bool result = False; 1825d522f475Smrg char *copy; 1826d522f475Smrg char *test; 1827d522f475Smrg 182820d2c4d2Smrg if ((test = stripTranslations(keyword, onlyInsert)) != 0) { 1829d522f475Smrg if (*cache == 0) { 1830d522f475Smrg XtGetSubresources(w, 1831d522f475Smrg (XtPointer) &data, 1832d522f475Smrg "vt100", 1833d522f475Smrg "VT100", 1834d522f475Smrg key_resources, 1835d522f475Smrg XtNumber(key_resources), 1836d522f475Smrg NULL, 1837d522f475Smrg (Cardinal) 0); 183820d2c4d2Smrg if (data != 0 && (copy = stripTranslations(data, onlyInsert)) != 0) { 1839d522f475Smrg *cache = copy; 1840d522f475Smrg } 1841d522f475Smrg } 1842d522f475Smrg 1843d522f475Smrg if (*cache != 0) { 1844d522f475Smrg char *p = *cache; 1845d522f475Smrg int state = 0; 1846d522f475Smrg int now = ' ', prv; 1847d522f475Smrg 1848d522f475Smrg while (*p != 0) { 1849d522f475Smrg prv = now; 1850d522f475Smrg now = *p++; 1851d522f475Smrg if (now == ':' 1852d522f475Smrg || now == '!') { 1853d522f475Smrg state = -1; 1854d522f475Smrg } else if (now == '\n') { 1855d522f475Smrg state = 0; 1856d522f475Smrg } else if (state >= 0) { 1857d522f475Smrg if (now == test[state]) { 1858d522f475Smrg if ((state != 0 1859d522f475Smrg || !isName(prv)) 1860d522f475Smrg && ((test[++state] == 0) 1861d522f475Smrg && !isName(*p))) { 1862d522f475Smrg result = True; 1863d522f475Smrg break; 1864d522f475Smrg } 1865d522f475Smrg } else { 1866d522f475Smrg state = 0; 1867d522f475Smrg } 1868d522f475Smrg } 1869d522f475Smrg } 1870d522f475Smrg } 1871d522f475Smrg free(test); 1872d522f475Smrg } 187320d2c4d2Smrg TRACE(("TranslationsUseKeyword(%p, %s) = %d\n", 187420d2c4d2Smrg (void *) w, keyword, result)); 1875d522f475Smrg return result; 1876d522f475Smrg} 1877d522f475Smrg 1878d522f475Smrgstatic Bool 187920d2c4d2SmrgxtermHasTranslation(XtermWidget xw, const char *keyword, Bool onlyInsert) 1880d522f475Smrg{ 1881d522f475Smrg return (TranslationsUseKeyword(SHELL_OF(xw), 1882d522f475Smrg &(xw->keyboard.shell_translations), 188320d2c4d2Smrg keyword, 188420d2c4d2Smrg onlyInsert) 1885d522f475Smrg || TranslationsUseKeyword((Widget) xw, 1886d522f475Smrg &(xw->keyboard.xterm_translations), 188720d2c4d2Smrg keyword, 188820d2c4d2Smrg onlyInsert)); 1889d522f475Smrg} 1890d522f475Smrg 1891d522f475Smrg#if OPT_EXTRA_PASTE 1892d522f475Smrgstatic void 189320d2c4d2SmrgaddTranslation(XtermWidget xw, const char *fromString, const char *toString) 1894d522f475Smrg{ 189520d2c4d2Smrg size_t have = (xw->keyboard.extra_translations 189620d2c4d2Smrg ? strlen(xw->keyboard.extra_translations) 189720d2c4d2Smrg : 0); 189820d2c4d2Smrg size_t need = (((have != 0) ? (have + 4) : 0) 189920d2c4d2Smrg + strlen(fromString) 190020d2c4d2Smrg + strlen(toString) 190120d2c4d2Smrg + 6); 190220d2c4d2Smrg 190320d2c4d2Smrg if (!xtermHasTranslation(xw, fromString, False)) { 1904d522f475Smrg xw->keyboard.extra_translations 1905d522f475Smrg = TypeRealloc(char, need, xw->keyboard.extra_translations); 1906d522f475Smrg if ((xw->keyboard.extra_translations) != 0) { 1907d522f475Smrg TRACE(("adding %s: %s\n", fromString, toString)); 1908d522f475Smrg if (have) 1909d522f475Smrg strcat(xw->keyboard.extra_translations, " \\n\\"); 1910d522f475Smrg sprintf(xw->keyboard.extra_translations, "%s: %s", 1911d522f475Smrg fromString, toString); 1912d522f475Smrg TRACE(("...{%s}\n", xw->keyboard.extra_translations)); 1913d522f475Smrg } 1914d522f475Smrg } 1915d522f475Smrg} 1916d522f475Smrg#endif 1917d522f475Smrg 191820d2c4d2Smrg#define SaveMask(name) xw->misc.name |= (unsigned) mask;\ 191920d2c4d2Smrg TRACE(("SaveMask(%s) %#x (%#x is%s modifier)\n", \ 1920d522f475Smrg #name, \ 192120d2c4d2Smrg xw->misc.name, (unsigned) mask, \ 192220d2c4d2Smrg ModifierName((unsigned) mask))); 1923d522f475Smrg/* 1924d522f475Smrg * Determine which modifier mask (if any) applies to the Num_Lock keysym. 1925d522f475Smrg * 1926d522f475Smrg * Also, determine which modifiers are associated with the ALT keys, so we can 1927d522f475Smrg * send that information as a parameter for special keys in Sun/PC keyboard 1928d522f475Smrg * mode. However, if the ALT modifier is used in translations, we do not want 1929d522f475Smrg * to confuse things by sending the parameter. 1930d522f475Smrg */ 1931d522f475Smrgvoid 1932d522f475SmrgVTInitModifiers(XtermWidget xw) 1933d522f475Smrg{ 1934d522f475Smrg Display *dpy = XtDisplay(xw); 1935d522f475Smrg XModifierKeymap *keymap = XGetModifierMapping(dpy); 1936d522f475Smrg int i, j, k, l; 1937d522f475Smrg KeySym keysym; 1938d522f475Smrg unsigned long mask; 1939d522f475Smrg int min_keycode, max_keycode, keysyms_per_keycode = 0; 1940d522f475Smrg 1941d522f475Smrg if (keymap != 0) { 1942d522f475Smrg KeySym *theMap; 1943d522f475Smrg int keycode_count; 1944d522f475Smrg 1945d522f475Smrg TRACE(("VTInitModifiers\n")); 1946d522f475Smrg 1947d522f475Smrg XDisplayKeycodes(dpy, &min_keycode, &max_keycode); 1948d522f475Smrg keycode_count = (max_keycode - min_keycode + 1); 1949d522f475Smrg theMap = XGetKeyboardMapping(dpy, 1950956cc18dSsnj (KeyCode) min_keycode, 1951d522f475Smrg keycode_count, 1952d522f475Smrg &keysyms_per_keycode); 1953d522f475Smrg 1954d522f475Smrg if (theMap != 0) { 1955d522f475Smrg 1956d522f475Smrg#if OPT_EXTRA_PASTE 1957d522f475Smrg /* 1958d522f475Smrg * Assume that if we can find the paste keysym in the X keyboard 1959d522f475Smrg * mapping that the server allows the corresponding translations 1960d522f475Smrg * resource. 1961d522f475Smrg */ 1962d522f475Smrg int limit = (max_keycode - min_keycode) * keysyms_per_keycode; 1963d522f475Smrg for (i = 0; i < limit; ++i) { 1964d522f475Smrg#ifdef XF86XK_Paste 1965d522f475Smrg if (theMap[i] == XF86XK_Paste) { 1966d522f475Smrg TRACE(("keyboard has XF86XK_Paste\n")); 1967d522f475Smrg addTranslation(xw, 1968d522f475Smrg "<KeyPress> XF86Paste", 1969d522f475Smrg "insert-selection(SELECT, CUT_BUFFER0)"); 1970d522f475Smrg } 1971d522f475Smrg#endif 1972d522f475Smrg#ifdef SunXK_Paste 1973d522f475Smrg if (theMap[i] == SunXK_Paste) { 1974d522f475Smrg TRACE(("keyboard has SunXK_Paste\n")); 1975d522f475Smrg addTranslation(xw, 1976d522f475Smrg "<KeyPress> SunPaste", 1977d522f475Smrg "insert-selection(SELECT, CUT_BUFFER0)"); 1978d522f475Smrg } 1979d522f475Smrg#endif 1980d522f475Smrg } 1981d522f475Smrg#endif /* OPT_EXTRA_PASTE */ 1982d522f475Smrg 1983d522f475Smrg for (i = k = 0, mask = 1; i < 8; i++, mask <<= 1) { 1984d522f475Smrg for (j = 0; j < keymap->max_keypermod; j++) { 1985d522f475Smrg KeyCode code = keymap->modifiermap[k++]; 1986d522f475Smrg if (code == 0) 1987d522f475Smrg continue; 1988d522f475Smrg 1989d522f475Smrg for (l = 0; l < keysyms_per_keycode; ++l) { 1990d522f475Smrg keysym = XKeycodeToKeysym(dpy, code, l); 1991d522f475Smrg if (keysym == NoSymbol) { 1992a1f3da82Smrg /* EMPTY */ ; 1993d522f475Smrg } else if (keysym == XK_Num_Lock) { 1994d522f475Smrg SaveMask(num_lock); 1995d522f475Smrg } else if (keysym == XK_Alt_L || keysym == XK_Alt_R) { 1996d522f475Smrg SaveMask(alt_mods); 1997d522f475Smrg } else if (keysym == XK_Meta_L || keysym == XK_Meta_R) { 1998d522f475Smrg SaveMask(meta_mods); 1999d522f475Smrg } else if (mask == ShiftMask 2000d522f475Smrg && (keysym == XK_Shift_L 2001d522f475Smrg || keysym == XK_Shift_R)) { 2002a1f3da82Smrg /* EMPTY */ ; 2003d522f475Smrg } else if (mask == ControlMask 2004d522f475Smrg && (keysym == XK_Control_L 2005d522f475Smrg || keysym == XK_Control_R)) { 2006a1f3da82Smrg /* EMPTY */ ; 2007d522f475Smrg } else if (mask == LockMask 2008d522f475Smrg && (keysym == XK_Caps_Lock)) { 2009a1f3da82Smrg /* EMPTY */ ; 2010d522f475Smrg } else if (keysym == XK_Mode_switch 2011d522f475Smrg#ifdef XK_ISO_Level3_Shift 2012d522f475Smrg || keysym == XK_ISO_Level3_Shift 2013d522f475Smrg#endif 2014d522f475Smrg ) { 2015d522f475Smrg SaveMask(other_mods); 2016d522f475Smrg } 2017d522f475Smrg } 2018d522f475Smrg } 2019d522f475Smrg } 2020d522f475Smrg XFree(theMap); 2021d522f475Smrg } 2022d522f475Smrg 2023d522f475Smrg /* Don't disable any mods if "alwaysUseMods" is true. */ 2024d522f475Smrg if (!xw->misc.alwaysUseMods) { 202520d2c4d2Smrg 202620d2c4d2Smrg /* 202720d2c4d2Smrg * Force TranslationsUseKeyword() to reload. 202820d2c4d2Smrg */ 202920d2c4d2Smrg if (xw->keyboard.shell_translations) { 203020d2c4d2Smrg free(xw->keyboard.shell_translations); 203120d2c4d2Smrg xw->keyboard.shell_translations = 0; 203220d2c4d2Smrg } 203320d2c4d2Smrg if (xw->keyboard.xterm_translations) { 203420d2c4d2Smrg free(xw->keyboard.xterm_translations); 203520d2c4d2Smrg xw->keyboard.xterm_translations = 0; 203620d2c4d2Smrg } 203720d2c4d2Smrg 2038d522f475Smrg /* 2039d522f475Smrg * If the Alt modifier is used in translations, we would rather not 2040d522f475Smrg * use it to modify function-keys when NumLock is active. 2041d522f475Smrg */ 2042d522f475Smrg if ((xw->misc.alt_mods != 0) 204320d2c4d2Smrg && xtermHasTranslation(xw, "alt", True)) { 2044d522f475Smrg TRACE(("ALT is used as a modifier in translations (ignore mask)\n")); 2045d522f475Smrg xw->misc.alt_mods = 0; 2046d522f475Smrg } 2047d522f475Smrg 2048d522f475Smrg /* 2049d522f475Smrg * If the Meta modifier is used in translations, we would rather not 2050d522f475Smrg * use it to modify function-keys. 2051d522f475Smrg */ 2052d522f475Smrg if ((xw->misc.meta_mods != 0) 205320d2c4d2Smrg && xtermHasTranslation(xw, "meta", True)) { 2054d522f475Smrg TRACE(("META is used as a modifier in translations\n")); 2055d522f475Smrg xw->misc.meta_mods = 0; 2056d522f475Smrg } 2057d522f475Smrg } 2058d522f475Smrg 2059d522f475Smrg XFreeModifiermap(keymap); 2060d522f475Smrg } 2061d522f475Smrg} 2062d522f475Smrg#endif /* OPT_NUM_LOCK */ 2063