input.c revision e0a2b6df
1e0a2b6dfSmrg/* $XTermId: input.c,v 1.348 2013/11/26 00:12:10 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/* 4e0a2b6dfSmrg * Copyright 1999-2012,2013 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 770bd37d32Smrg#ifdef HAVE_XKBKEYCODETOKEYSYM 780bd37d32Smrg#include <X11/XKBlib.h> 790bd37d32Smrg#endif 800bd37d32Smrg 81d522f475Smrg#include <X11/Xutil.h> 82d522f475Smrg#include <stdio.h> 83d522f475Smrg#include <ctype.h> 84d522f475Smrg 85d522f475Smrg#include <xutf8.h> 86d522f475Smrg 87d522f475Smrg#include <data.h> 88d522f475Smrg#include <fontutils.h> 892eaa94a1Schristos#include <xstrings.h> 90d522f475Smrg#include <xtermcap.h> 91d522f475Smrg 92d522f475Smrg/* 93d522f475Smrg * Xutil.h has no macro to check for the complete set of function- and 94d522f475Smrg * modifier-keys that might be returned. Fake it. 95d522f475Smrg */ 96d522f475Smrg#ifdef XK_ISO_Lock 97d522f475Smrg#define IsPredefinedKey(n) ((n) >= XK_ISO_Lock && (n) <= XK_Delete) 98d522f475Smrg#else 99d522f475Smrg#define IsPredefinedKey(n) ((n) >= XK_BackSpace && (n) <= XK_Delete) 100d522f475Smrg#endif 101d522f475Smrg 102d522f475Smrg#ifdef XK_ISO_Left_Tab 103d522f475Smrg#define IsTabKey(n) ((n) == XK_Tab || (n) == XK_ISO_Left_Tab) 104d522f475Smrg#else 105d522f475Smrg#define IsTabKey(n) ((n) == XK_Tab) 106d522f475Smrg#endif 107d522f475Smrg 108d522f475Smrg#ifndef IsPrivateKeypadKey 109d522f475Smrg#define IsPrivateKeypadKey(k) (0) 110d522f475Smrg#endif 111d522f475Smrg 112d522f475Smrg#define IsBackarrowToggle(keyboard, keysym, state) \ 113d522f475Smrg ((((keyboard->flags & MODE_DECBKM) == 0) \ 114d522f475Smrg ^ ((state & ControlMask) != 0)) \ 115d522f475Smrg && (keysym == XK_BackSpace)) 116d522f475Smrg 117d522f475Smrg#define MAP(from, to) case from: result = to; break 118d522f475Smrg#define Masked(value,mask) ((value) & (unsigned) (~(mask))) 119d522f475Smrg 120d522f475Smrg#define KEYSYM_FMT "0x%04lX" /* simplify matching <X11/keysymdef.h> */ 121d522f475Smrg 12220d2c4d2Smrg#define TEK4014_GIN(tw) (tw != 0 && TekScreenOf(tw)->TekGIN) 123d522f475Smrg 124d522f475Smrgtypedef struct { 125d522f475Smrg KeySym keysym; 126d522f475Smrg Bool is_fkey; 127d522f475Smrg int nbytes; 128d522f475Smrg#define STRBUFSIZE 500 129d522f475Smrg char strbuf[STRBUFSIZE]; 130d522f475Smrg} KEY_DATA; 131d522f475Smrg 13220d2c4d2Smrgstatic 13320d2c4d2Smrgconst char *kypd_num = " XXXXXXXX\tXXX\rXXXxxxxXXXXXXXXXXXXXXXXXXXXX*+,-./0123456789XXX="; 13420d2c4d2Smrg/* 0123456789 abc def0123456789abcdef0123456789abcdef0123456789abcd */ 13520d2c4d2Smrgstatic 13620d2c4d2Smrgconst char *kypd_apl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ??????abcdefghijklmnopqrstuvwxyzXXX"; 13720d2c4d2Smrg/* 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd */ 13820d2c4d2Smrgstatic 13920d2c4d2Smrgconst char *curfinal = "HDACB FE"; 140d522f475Smrg 141d522f475Smrgstatic int decfuncvalue(KEY_DATA *); 142d522f475Smrgstatic void sunfuncvalue(ANSI *, KEY_DATA *); 143d522f475Smrgstatic void hpfuncvalue(ANSI *, KEY_DATA *); 144d522f475Smrgstatic void scofuncvalue(ANSI *, KEY_DATA *); 145d522f475Smrg 146d522f475Smrgstatic void 147d522f475SmrgAdjustAfterInput(XtermWidget xw) 148d522f475Smrg{ 14920d2c4d2Smrg TScreen *screen = TScreenOf(xw); 150d522f475Smrg 151d522f475Smrg if (screen->scrollkey && screen->topline != 0) 15220d2c4d2Smrg WindowScroll(xw, 0, False); 153d522f475Smrg if (screen->marginbell) { 154d522f475Smrg int col = screen->max_col - screen->nmarginbell; 15520d2c4d2Smrg if (screen->bellArmed >= 0) { 15620d2c4d2Smrg if (screen->bellArmed == screen->cur_row) { 157d522f475Smrg if (screen->cur_col >= col) { 15820d2c4d2Smrg Bell(xw, XkbBI_MarginBell, 0); 15920d2c4d2Smrg screen->bellArmed = -1; 160d522f475Smrg } 16120d2c4d2Smrg } else { 16220d2c4d2Smrg screen->bellArmed = 163d522f475Smrg screen->cur_col < col ? screen->cur_row : -1; 16420d2c4d2Smrg } 165d522f475Smrg } else if (screen->cur_col < col) 16620d2c4d2Smrg screen->bellArmed = screen->cur_row; 167d522f475Smrg } 168d522f475Smrg} 169d522f475Smrg 170d522f475Smrg/* 171d522f475Smrg * Return true if the key is on the editing keypad. This overlaps with 1720bd37d32Smrg * IsCursorKey() and IsKeypadKey() and must be tested before those macros to 173d522f475Smrg * distinguish it from them. 1740bd37d32Smrg * 1750bd37d32Smrg * VT220 emulation uses the VT100 numeric keypad as well as a 6-key 1760bd37d32Smrg * editing keypad. Here's a picture of the VT220 editing keypad: 1770bd37d32Smrg * +--------+--------+--------+ 1780bd37d32Smrg * | Find | Insert | Remove | 1790bd37d32Smrg * +--------+--------+--------+ 1800bd37d32Smrg * | Select | Prev | Next | 1810bd37d32Smrg * +--------+--------+--------+ 1820bd37d32Smrg * 1830bd37d32Smrg * and the similar Sun and PC keypads: 1840bd37d32Smrg * +--------+--------+--------+ 1850bd37d32Smrg * | Insert | Home | PageUp | 1860bd37d32Smrg * +--------+--------+--------+ 1870bd37d32Smrg * | Delete | End | PageDn | 1880bd37d32Smrg * +--------+--------+--------+ 189d522f475Smrg */ 190d522f475Smrgstatic Bool 1910bd37d32SmrgIsEditKeypad(XtermWidget xw, KeySym keysym) 192d522f475Smrg{ 1930bd37d32Smrg Bool result; 1940bd37d32Smrg 195d522f475Smrg switch (keysym) { 1960bd37d32Smrg case XK_Delete: 1970bd37d32Smrg result = !xtermDeleteIsDEL(xw); 1980bd37d32Smrg break; 1990bd37d32Smrg case XK_Prior: 2000bd37d32Smrg case XK_Next: 2010bd37d32Smrg case XK_Insert: 2020bd37d32Smrg case XK_Find: 2030bd37d32Smrg case XK_Select: 204d522f475Smrg#ifdef DXK_Remove 2050bd37d32Smrg case DXK_Remove: 206d522f475Smrg#endif 2070bd37d32Smrg result = True; 2080bd37d32Smrg break; 2090bd37d32Smrg default: 2100bd37d32Smrg result = False; 2110bd37d32Smrg break; 2120bd37d32Smrg } 2130bd37d32Smrg return result; 2140bd37d32Smrg} 2150bd37d32Smrg 2160bd37d32Smrg/* 2170bd37d32Smrg * Editing-keypad, plus other editing keys which are not included in the 2180bd37d32Smrg * other macros. 2190bd37d32Smrg */ 2200bd37d32Smrgstatic Bool 2210bd37d32SmrgIsEditFunctionKey(XtermWidget xw, KeySym keysym) 2220bd37d32Smrg{ 2230bd37d32Smrg Bool result; 2240bd37d32Smrg 2250bd37d32Smrg switch (keysym) { 226d522f475Smrg#ifdef XK_KP_Delete 227d522f475Smrg case XK_KP_Delete: /* editing key on numeric keypad */ 228d522f475Smrg case XK_KP_Insert: /* editing key on numeric keypad */ 229d522f475Smrg#endif 230d522f475Smrg#ifdef XK_ISO_Left_Tab 231d522f475Smrg case XK_ISO_Left_Tab: 232d522f475Smrg#endif 2330bd37d32Smrg result = True; 2340bd37d32Smrg break; 235d522f475Smrg default: 2360bd37d32Smrg result = IsEditKeypad(xw, keysym); 2370bd37d32Smrg break; 238d522f475Smrg } 2390bd37d32Smrg return result; 240d522f475Smrg} 241d522f475Smrg 242d522f475Smrg#if OPT_MOD_FKEYS 243d522f475Smrg#define IS_CTRL(n) ((n) < ANSI_SPA || ((n) >= 0x7f && (n) <= 0x9f)) 244d522f475Smrg 245d522f475Smrg/* 246d522f475Smrg * Return true if the keysym corresponds to one of the control characters, 247d522f475Smrg * or one of the common ASCII characters that is combined with control to 248d522f475Smrg * make a control character. 249d522f475Smrg */ 250d522f475Smrgstatic Bool 251d522f475SmrgIsControlInput(KEY_DATA * kd) 252d522f475Smrg{ 253d522f475Smrg return ((kd->keysym) >= 0x40 && (kd->keysym) <= 0x7f); 254d522f475Smrg} 255d522f475Smrg 256d522f475Smrgstatic Bool 257d522f475SmrgIsControlOutput(KEY_DATA * kd) 258d522f475Smrg{ 259d522f475Smrg return IS_CTRL(kd->keysym); 260d522f475Smrg} 261d522f475Smrg 262d522f475Smrg/* 263d522f475Smrg * X "normally" has some built-in translations, which the user may want to 264d522f475Smrg * suppress when processing the modifyOtherKeys resource. In particular, the 265d522f475Smrg * control modifier applied to some of the keyboard digits gives results for 266d522f475Smrg * control characters. 267d522f475Smrg * 268d522f475Smrg * control 2 0 NUL 269d522f475Smrg * control SPC 0 NUL 270d522f475Smrg * control @ 0 NUL 271d522f475Smrg * control ` 0 NUL 272d522f475Smrg * control 3 0x1b ESC 273d522f475Smrg * control 4 0x1c FS 274d522f475Smrg * control \ 0x1c FS 275d522f475Smrg * control 5 0x1d GS 276d522f475Smrg * control 6 0x1e RS 277d522f475Smrg * control ^ 0x1e RS 278d522f475Smrg * control ~ 0x1e RS 279d522f475Smrg * control 7 0x1f US 280d522f475Smrg * control / 0x1f US 281d522f475Smrg * control _ 0x1f US 282d522f475Smrg * control 8 0x7f DEL 283d522f475Smrg * 284d522f475Smrg * It is possible that some other keyboards do not work for these combinations, 285d522f475Smrg * but they do work with modifyOtherKeys=2 for the US keyboard: 286d522f475Smrg * 287d522f475Smrg * control ` 0 NUL 288d522f475Smrg * control [ 0x1b ESC 289d522f475Smrg * control \ 0x1c FS 290d522f475Smrg * control ] 0x1d GS 291d522f475Smrg * control ? 0x7f DEL 292d522f475Smrg */ 293d522f475Smrgstatic Bool 294d522f475SmrgIsControlAlias(KEY_DATA * kd) 295d522f475Smrg{ 296d522f475Smrg Bool result = False; 297d522f475Smrg 298d522f475Smrg if (kd->nbytes == 1) { 299d522f475Smrg result = IS_CTRL(CharOf(kd->strbuf[0])); 300d522f475Smrg } 301d522f475Smrg return result; 302d522f475Smrg} 303d522f475Smrg 304d522f475Smrg/* 305d522f475Smrg * If we are in the non-VT220/VT52 keyboard state, allow modifiers to add a 306d522f475Smrg * parameter to the function-key control sequences. 307d522f475Smrg * 308d522f475Smrg * Note that we generally cannot capture the Shift-modifier for the numeric 309d522f475Smrg * keypad since this is commonly used to act as a type of NumLock, e.g., 310d522f475Smrg * making the keypad send "7" (actually XK_KP_7) where the unshifted code 311d522f475Smrg * would be Home (XK_KP_Home). The other modifiers work, subject to the 312d522f475Smrg * usual window-manager assignments. 313d522f475Smrg */ 3140bd37d32Smrg#if OPT_SUNPC_KBD 3150bd37d32Smrg#define LegacyAllows(code) (!is_legacy || (code & xw->keyboard.modify_now.allow_keys) != 0) 3160bd37d32Smrg#else 3170bd37d32Smrg#define LegacyAllows(code) True 3180bd37d32Smrg#endif 3190bd37d32Smrg 320d522f475Smrgstatic Bool 321d522f475SmrgallowModifierParm(XtermWidget xw, KEY_DATA * kd) 322d522f475Smrg{ 323d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 3240bd37d32Smrg int is_legacy = (keyboard->type == keyboardIsLegacy); 325d522f475Smrg Bool result = False; 326d522f475Smrg 327d522f475Smrg#if OPT_SUNPC_KBD 3280bd37d32Smrg if (keyboard->type == keyboardIsVT220) 3290bd37d32Smrg is_legacy = True; 330d522f475Smrg#endif 3310bd37d32Smrg 332d522f475Smrg#if OPT_VT52_MODE 333e0a2b6dfSmrg if (TScreenOf(xw)->vtXX_level != 0) 334d522f475Smrg#endif 3350bd37d32Smrg { 3360bd37d32Smrg if (IsCursorKey(kd->keysym) || IsEditFunctionKey(xw, kd->keysym)) { 3370bd37d32Smrg result = LegacyAllows(2); 3380bd37d32Smrg } else if (IsKeypadKey(kd->keysym)) { 339e0a2b6dfSmrg result = LegacyAllows(1); 3400bd37d32Smrg } else if (IsFunctionKey(kd->keysym)) { 3410bd37d32Smrg result = LegacyAllows(4); 3420bd37d32Smrg } else if (IsMiscFunctionKey(kd->keysym)) { 3430bd37d32Smrg result = LegacyAllows(8); 3440bd37d32Smrg } 3450bd37d32Smrg } 3460bd37d32Smrg if (xw->keyboard.modify_now.other_keys != 0) { 347d522f475Smrg result = True; 348d522f475Smrg } 349d522f475Smrg return result; 350d522f475Smrg} 351d522f475Smrg 352d522f475Smrg/* 353d522f475Smrg* Modifier codes: 354d522f475Smrg* None 1 355d522f475Smrg* Shift 2 = 1(None)+1(Shift) 356d522f475Smrg* Alt 3 = 1(None)+2(Alt) 357d522f475Smrg* Alt+Shift 4 = 1(None)+1(Shift)+2(Alt) 358d522f475Smrg* Ctrl 5 = 1(None)+4(Ctrl) 359d522f475Smrg* Ctrl+Shift 6 = 1(None)+1(Shift)+4(Ctrl) 360d522f475Smrg* Ctrl+Alt 7 = 1(None)+2(Alt)+4(Ctrl) 361d522f475Smrg* Ctrl+Alt+Shift 8 = 1(None)+1(Shift)+2(Alt)+4(Ctrl) 362d522f475Smrg* Meta 9 = 1(None)+8(Meta) 363d522f475Smrg* Meta+Shift 10 = 1(None)+8(Meta)+1(Shift) 364d522f475Smrg* Meta+Alt 11 = 1(None)+8(Meta)+2(Alt) 365d522f475Smrg* Meta+Alt+Shift 12 = 1(None)+8(Meta)+1(Shift)+2(Alt) 366d522f475Smrg* Meta+Ctrl 13 = 1(None)+8(Meta)+4(Ctrl) 367d522f475Smrg* Meta+Ctrl+Shift 14 = 1(None)+8(Meta)+1(Shift)+4(Ctrl) 368d522f475Smrg* Meta+Ctrl+Alt 15 = 1(None)+8(Meta)+2(Alt)+4(Ctrl) 369d522f475Smrg* Meta+Ctrl+Alt+Shift 16 = 1(None)+8(Meta)+1(Shift)+2(Alt)+4(Ctrl) 370d522f475Smrg*/ 371d522f475Smrg 372956cc18dSsnjunsigned 373d522f475SmrgxtermParamToState(XtermWidget xw, unsigned param) 374d522f475Smrg{ 375956cc18dSsnj unsigned result = 0; 376d522f475Smrg#if OPT_NUM_LOCK 3770bd37d32Smrg if (param > MOD_NONE) { 378956cc18dSsnj if ((param - MOD_NONE) & MOD_SHIFT) 37920d2c4d2Smrg UIntSet(result, ShiftMask); 380956cc18dSsnj if ((param - MOD_NONE) & MOD_CTRL) 38120d2c4d2Smrg UIntSet(result, ControlMask); 382956cc18dSsnj if ((param - MOD_NONE) & MOD_ALT) 3830bd37d32Smrg UIntSet(result, xw->work.alt_mods); 384956cc18dSsnj if ((param - MOD_NONE) & MOD_META) 3850bd37d32Smrg UIntSet(result, xw->work.meta_mods); 386d522f475Smrg } 387d522f475Smrg#else 388d522f475Smrg (void) xw; 389d522f475Smrg (void) param; 390d522f475Smrg#endif 391d522f475Smrg TRACE(("xtermParamToState(%d) %s%s%s%s -> %#x\n", param, 392956cc18dSsnj MODIFIER_NAME(param, MOD_SHIFT), 393956cc18dSsnj MODIFIER_NAME(param, MOD_ALT), 394956cc18dSsnj MODIFIER_NAME(param, MOD_CTRL), 395956cc18dSsnj MODIFIER_NAME(param, MOD_META), 396d522f475Smrg result)); 397d522f475Smrg return result; 398d522f475Smrg} 399d522f475Smrg 400956cc18dSsnjunsigned 401d522f475SmrgxtermStateToParam(XtermWidget xw, unsigned state) 402d522f475Smrg{ 403956cc18dSsnj unsigned modify_parm = MOD_NONE; 404d522f475Smrg 405956cc18dSsnj TRACE(("xtermStateToParam %#x\n", state)); 406d522f475Smrg#if OPT_NUM_LOCK 4070bd37d32Smrg if (state & ShiftMask) { 4080bd37d32Smrg modify_parm += MOD_SHIFT; 4090bd37d32Smrg UIntClr(state, ShiftMask); 4100bd37d32Smrg } 4110bd37d32Smrg if (state & ControlMask) { 4120bd37d32Smrg modify_parm += MOD_CTRL; 4130bd37d32Smrg UIntClr(state, ControlMask); 4140bd37d32Smrg } 4150bd37d32Smrg if ((state & xw->work.alt_mods) != 0) { 4160bd37d32Smrg modify_parm += MOD_ALT; 4170bd37d32Smrg UIntClr(state, xw->work.alt_mods); 4180bd37d32Smrg } 4190bd37d32Smrg if ((state & xw->work.meta_mods) != 0) { 4200bd37d32Smrg modify_parm += MOD_META; 4210bd37d32Smrg UIntClr(state, xw->work.meta_mods); 422d522f475Smrg } 423956cc18dSsnj if (modify_parm == MOD_NONE) 424956cc18dSsnj modify_parm = 0; 425d522f475Smrg#else 426d522f475Smrg (void) xw; 427d522f475Smrg (void) state; 428d522f475Smrg#endif 429d522f475Smrg TRACE(("...xtermStateToParam %d%s%s%s%s\n", modify_parm, 430956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_SHIFT), 431956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_ALT), 432956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_CTRL), 433956cc18dSsnj MODIFIER_NAME(modify_parm, MOD_META))); 434d522f475Smrg return modify_parm; 435d522f475Smrg} 436d522f475Smrg 437d522f475Smrg#define computeMaskedModifier(xw, state, mask) \ 438d522f475Smrg xtermStateToParam(xw, Masked(state, mask)) 439d522f475Smrg 440d522f475Smrg#if OPT_NUM_LOCK 441d522f475Smrgstatic unsigned 442d522f475SmrgfilterAltMeta(unsigned result, unsigned mask, Bool enable, KEY_DATA * kd) 443d522f475Smrg{ 444d522f475Smrg if ((result & mask) != 0) { 445d522f475Smrg /* 446d522f475Smrg * metaSendsEscape makes the meta key independent of 447d522f475Smrg * modifyOtherKeys. 448d522f475Smrg */ 449d522f475Smrg if (enable) { 450d522f475Smrg result &= ~mask; 451d522f475Smrg } 452d522f475Smrg /* 453d522f475Smrg * A bare meta-modifier is independent of modifyOtherKeys. If it 454d522f475Smrg * is combined with other modifiers, make it depend. 455d522f475Smrg */ 456d522f475Smrg if ((result & ~(mask)) == 0) { 457d522f475Smrg result &= ~mask; 458d522f475Smrg } 459d522f475Smrg /* 460d522f475Smrg * Check for special cases of control+meta which are used by some 461d522f475Smrg * applications, e.g., emacs. 462d522f475Smrg */ 463d522f475Smrg if ((IsControlInput(kd) 464d522f475Smrg || IsControlOutput(kd)) 465d522f475Smrg && (result & ControlMask) != 0) { 466d522f475Smrg result &= ~(mask | ControlMask); 467d522f475Smrg } 468d522f475Smrg if (kd->keysym == XK_Return || kd->keysym == XK_Tab) { 469d522f475Smrg result &= ~(mask | ControlMask); 470d522f475Smrg } 471d522f475Smrg } 472d522f475Smrg return result; 473d522f475Smrg} 474d522f475Smrg#endif /* OPT_NUM_LOCK */ 475d522f475Smrg 476d522f475Smrg/* 477d522f475Smrg * Single characters (not function-keys) are allowed fewer modifiers when 478d522f475Smrg * interpreting modifyOtherKeys due to pre-existing associations with some 479d522f475Smrg * modifiers. 480d522f475Smrg */ 481d522f475Smrgstatic unsigned 482d522f475SmrgallowedCharModifiers(XtermWidget xw, unsigned state, KEY_DATA * kd) 483d522f475Smrg{ 484d522f475Smrg#if OPT_NUM_LOCK 4850bd37d32Smrg unsigned a_or_m = (state & (xw->work.meta_mods | xw->work.alt_mods)); 486d522f475Smrg#else 487d522f475Smrg unsigned a_or_m = 0; 488d522f475Smrg#endif 489d522f475Smrg /* 490d522f475Smrg * Start by limiting the result to the modifiers we might want to use. 491d522f475Smrg */ 492d522f475Smrg unsigned result = (state & (ControlMask 493d522f475Smrg | ShiftMask 494d522f475Smrg | a_or_m)); 495d522f475Smrg 496d522f475Smrg /* 497d522f475Smrg * If modifyOtherKeys is off or medium (0 or 1), moderate its effects by 498d522f475Smrg * excluding the common cases for modifiers. 499d522f475Smrg */ 500d522f475Smrg if (xw->keyboard.modify_now.other_keys <= 1) { 501d522f475Smrg if (IsControlInput(kd) 502d522f475Smrg && Masked(result, ControlMask) == 0) { 503d522f475Smrg /* These keys are already associated with the control-key */ 504d522f475Smrg if (xw->keyboard.modify_now.other_keys == 0) { 50520d2c4d2Smrg UIntClr(result, ControlMask); 506d522f475Smrg } 507d522f475Smrg } else if (kd->keysym == XK_Tab || kd->keysym == XK_Return) { 508a1f3da82Smrg /* EMPTY */ ; 509d522f475Smrg } else if (IsControlAlias(kd)) { 510d522f475Smrg /* Things like "^_" work here... */ 511d522f475Smrg if (Masked(result, (ControlMask | ShiftMask)) == 0) { 512d522f475Smrg result = 0; 513d522f475Smrg } 514d522f475Smrg } else if (!IsControlOutput(kd) && !IsPredefinedKey(kd->keysym)) { 515d522f475Smrg /* Printable keys are already associated with the shift-key */ 516d522f475Smrg if (!(result & ControlMask)) { 51720d2c4d2Smrg UIntClr(result, ShiftMask); 518d522f475Smrg } 519d522f475Smrg } 520d522f475Smrg#if OPT_NUM_LOCK 521d522f475Smrg result = filterAltMeta(result, 5220bd37d32Smrg xw->work.meta_mods, 52320d2c4d2Smrg TScreenOf(xw)->meta_sends_esc, kd); 52420d2c4d2Smrg if (TScreenOf(xw)->alt_is_not_meta) { 525d522f475Smrg result = filterAltMeta(result, 5260bd37d32Smrg xw->work.alt_mods, 52720d2c4d2Smrg TScreenOf(xw)->alt_sends_esc, kd); 528d522f475Smrg } 529d522f475Smrg#endif 530d522f475Smrg } 531d522f475Smrg TRACE(("...allowedCharModifiers(state=%u" FMT_MODIFIER_NAMES 532d522f475Smrg ", ch=" KEYSYM_FMT ") ->" 533d522f475Smrg "%u" FMT_MODIFIER_NAMES "\n", 534d522f475Smrg state, ARG_MODIFIER_NAMES(state), kd->keysym, 535d522f475Smrg result, ARG_MODIFIER_NAMES(result))); 536d522f475Smrg return result; 537d522f475Smrg} 538d522f475Smrg 539d522f475Smrg/* 540d522f475Smrg * Decide if we should generate a special escape sequence for "other" keys 541d522f475Smrg * than cursor-, function-keys, etc., as per the modifyOtherKeys resource. 542d522f475Smrg */ 543d522f475Smrgstatic Bool 544d522f475SmrgModifyOtherKeys(XtermWidget xw, 545d522f475Smrg unsigned state, 546d522f475Smrg KEY_DATA * kd, 547956cc18dSsnj unsigned modify_parm) 548d522f475Smrg{ 549d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 550d522f475Smrg Bool result = False; 551d522f475Smrg 552d522f475Smrg /* 553d522f475Smrg * Exclude the keys already covered by a modifier. 554d522f475Smrg */ 555d522f475Smrg if (kd->is_fkey 5560bd37d32Smrg || IsEditFunctionKey(xw, kd->keysym) 557d522f475Smrg || IsKeypadKey(kd->keysym) 558d522f475Smrg || IsCursorKey(kd->keysym) 559d522f475Smrg || IsPFKey(kd->keysym) 560d522f475Smrg || IsMiscFunctionKey(kd->keysym) 5610bd37d32Smrg || IsPrivateKeypadKey(kd->keysym)) { 562d522f475Smrg result = False; 563d522f475Smrg } else if (modify_parm != 0) { 564d522f475Smrg if (IsBackarrowToggle(keyboard, kd->keysym, state)) { 565d522f475Smrg kd->keysym = XK_Delete; 56620d2c4d2Smrg UIntClr(state, ControlMask); 567d522f475Smrg } 568d522f475Smrg if (!IsPredefinedKey(kd->keysym)) { 569d522f475Smrg state = allowedCharModifiers(xw, state, kd); 570d522f475Smrg } 571d522f475Smrg if (state != 0) { 572d522f475Smrg switch (keyboard->modify_now.other_keys) { 573d522f475Smrg default: 574d522f475Smrg break; 575d522f475Smrg case 1: 576d522f475Smrg switch (kd->keysym) { 577d522f475Smrg case XK_BackSpace: 578d522f475Smrg case XK_Delete: 579d522f475Smrg result = False; 580d522f475Smrg break; 581d522f475Smrg#ifdef XK_ISO_Left_Tab 582d522f475Smrg case XK_ISO_Left_Tab: 583956cc18dSsnj if (computeMaskedModifier(xw, state, ShiftMask)) 584d522f475Smrg result = True; 585d522f475Smrg break; 586d522f475Smrg#endif 587d522f475Smrg case XK_Return: 588d522f475Smrg case XK_Tab: 589956cc18dSsnj result = (modify_parm != 0); 590d522f475Smrg break; 591d522f475Smrg default: 592d522f475Smrg if (IsControlInput(kd)) { 593d522f475Smrg if (state == ControlMask || state == ShiftMask) { 594d522f475Smrg result = False; 595d522f475Smrg } else { 596956cc18dSsnj result = (modify_parm != 0); 597d522f475Smrg } 598d522f475Smrg } else if (IsControlAlias(kd)) { 599d522f475Smrg if (state == ShiftMask) 600d522f475Smrg result = False; 601956cc18dSsnj else if (computeMaskedModifier(xw, state, ControlMask)) { 602d522f475Smrg result = True; 603d522f475Smrg } 604d522f475Smrg } else { 605d522f475Smrg result = True; 606d522f475Smrg } 607d522f475Smrg break; 608d522f475Smrg } 609d522f475Smrg break; 610d522f475Smrg case 2: 611d522f475Smrg switch (kd->keysym) { 612d522f475Smrg case XK_BackSpace: 613d522f475Smrg /* strip ControlMask as per IsBackarrowToggle() */ 614956cc18dSsnj if (computeMaskedModifier(xw, state, ControlMask)) 615d522f475Smrg result = True; 616d522f475Smrg break; 617d522f475Smrg case XK_Delete: 618956cc18dSsnj result = (xtermStateToParam(xw, state) != 0); 619d522f475Smrg break; 620d522f475Smrg#ifdef XK_ISO_Left_Tab 621d522f475Smrg case XK_ISO_Left_Tab: 622956cc18dSsnj if (computeMaskedModifier(xw, state, ShiftMask)) 623d522f475Smrg result = True; 624d522f475Smrg break; 625d522f475Smrg#endif 626d522f475Smrg case XK_Return: 627d522f475Smrg case XK_Tab: 628956cc18dSsnj result = (modify_parm != 0); 629d522f475Smrg break; 630d522f475Smrg default: 631d522f475Smrg if (IsControlInput(kd)) { 632d522f475Smrg result = True; 633d522f475Smrg } else if (state == ShiftMask) { 634d522f475Smrg result = (kd->keysym == ' ' || kd->keysym == XK_Return); 635956cc18dSsnj } else if (computeMaskedModifier(xw, state, ShiftMask)) { 636d522f475Smrg result = True; 637d522f475Smrg } 638d522f475Smrg break; 639d522f475Smrg } 640d522f475Smrg break; 641d522f475Smrg } 642d522f475Smrg } 643d522f475Smrg } 644d522f475Smrg TRACE(("...ModifyOtherKeys(%d,%d) %s\n", 645d522f475Smrg keyboard->modify_now.other_keys, 646d522f475Smrg modify_parm, 647d522f475Smrg BtoS(result))); 648d522f475Smrg return result; 649d522f475Smrg} 650d522f475Smrg 651d522f475Smrg#define APPEND_PARM(number) \ 652956cc18dSsnj reply->a_param[reply->a_nparam] = (ParmType) number; \ 653956cc18dSsnj reply->a_nparam++ 654d522f475Smrg 655d522f475Smrg/* 656d522f475Smrg * Function-key code 27 happens to not be used in the vt220-style encoding. 657d522f475Smrg * xterm uses this to represent modified non-function-keys such as control/+ in 658d522f475Smrg * the Sun/PC keyboard layout. See the modifyOtherKeys resource in the manpage 659d522f475Smrg * for more information. 660d522f475Smrg */ 661d522f475Smrgstatic Bool 662e0a2b6dfSmrgmodifyOtherKey(ANSI *reply, int input_char, unsigned modify_parm, int format_keys) 663d522f475Smrg{ 664d522f475Smrg Bool result = False; 665d522f475Smrg 666d522f475Smrg if (input_char >= 0) { 667d522f475Smrg reply->a_type = ANSI_CSI; 668d522f475Smrg if (format_keys) { 669d522f475Smrg APPEND_PARM(input_char); 670d522f475Smrg APPEND_PARM(modify_parm); 671d522f475Smrg reply->a_final = 'u'; 672d522f475Smrg } else { 673d522f475Smrg APPEND_PARM(27); 674d522f475Smrg APPEND_PARM(modify_parm); 675d522f475Smrg APPEND_PARM(input_char); 676d522f475Smrg reply->a_final = '~'; 677d522f475Smrg } 678d522f475Smrg 679d522f475Smrg result = True; 680d522f475Smrg } 681d522f475Smrg return result; 682d522f475Smrg} 683d522f475Smrg 684d522f475Smrgstatic void 685e0a2b6dfSmrgmodifyCursorKey(ANSI *reply, int modify, unsigned *modify_parm) 686d522f475Smrg{ 687956cc18dSsnj if (*modify_parm != 0) { 688d522f475Smrg if (modify < 0) { 689d522f475Smrg *modify_parm = 0; 690d522f475Smrg } 691d522f475Smrg if (modify > 0) { 692d522f475Smrg reply->a_type = ANSI_CSI; /* SS3 should not have params */ 693d522f475Smrg } 694d522f475Smrg if (modify > 1 && reply->a_nparam == 0) { 695d522f475Smrg APPEND_PARM(1); /* force modifier to 2nd param */ 696d522f475Smrg } 697d522f475Smrg if (modify > 2) { 698d522f475Smrg reply->a_pintro = '>'; /* mark this as "private" */ 699d522f475Smrg } 700d522f475Smrg } 701d522f475Smrg} 702d522f475Smrg#else 703d522f475Smrg#define modifyCursorKey(reply, modify, parm) /* nothing */ 704d522f475Smrg#endif /* OPT_MOD_FKEYS */ 705d522f475Smrg 706d522f475Smrg#if OPT_SUNPC_KBD 707d522f475Smrg/* 708d522f475Smrg * If we have told xterm that our keyboard is really a Sun/PC keyboard, this is 709d522f475Smrg * enough to make a reasonable approximation to DEC vt220 numeric and editing 710d522f475Smrg * keypads. 711d522f475Smrg */ 712d522f475Smrgstatic KeySym 713d522f475SmrgTranslateFromSUNPC(KeySym keysym) 714d522f475Smrg{ 715d522f475Smrg /* *INDENT-OFF* */ 716d522f475Smrg static struct { 717d522f475Smrg KeySym before, after; 718d522f475Smrg } table[] = { 719d522f475Smrg#ifdef DXK_Remove 720d522f475Smrg { XK_Delete, DXK_Remove }, 721d522f475Smrg#endif 722d522f475Smrg { XK_Home, XK_Find }, 723d522f475Smrg { XK_End, XK_Select }, 724d522f475Smrg#ifdef XK_KP_Home 725d522f475Smrg { XK_Delete, XK_KP_Decimal }, 726d522f475Smrg { XK_KP_Delete, XK_KP_Decimal }, 727d522f475Smrg { XK_KP_Insert, XK_KP_0 }, 728d522f475Smrg { XK_KP_End, XK_KP_1 }, 729d522f475Smrg { XK_KP_Down, XK_KP_2 }, 730d522f475Smrg { XK_KP_Next, XK_KP_3 }, 731d522f475Smrg { XK_KP_Left, XK_KP_4 }, 732d522f475Smrg { XK_KP_Begin, XK_KP_5 }, 733d522f475Smrg { XK_KP_Right, XK_KP_6 }, 734d522f475Smrg { XK_KP_Home, XK_KP_7 }, 735d522f475Smrg { XK_KP_Up, XK_KP_8 }, 736d522f475Smrg { XK_KP_Prior, XK_KP_9 }, 737d522f475Smrg#endif 738d522f475Smrg }; 739d522f475Smrg /* *INDENT-ON* */ 740d522f475Smrg 741d522f475Smrg unsigned n; 742d522f475Smrg 743d522f475Smrg for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) { 744d522f475Smrg if (table[n].before == keysym) { 745d522f475Smrg TRACE(("...Input keypad before was " KEYSYM_FMT "\n", keysym)); 746d522f475Smrg keysym = table[n].after; 747d522f475Smrg TRACE(("...Input keypad changed to " KEYSYM_FMT "\n", keysym)); 748d522f475Smrg break; 749d522f475Smrg } 750d522f475Smrg } 751d522f475Smrg return keysym; 752d522f475Smrg} 753d522f475Smrg#endif /* OPT_SUNPC_KBD */ 754d522f475Smrg 755d522f475Smrg#define VT52_KEYPAD \ 756d522f475Smrg if_OPT_VT52_MODE(screen,{ \ 757d522f475Smrg reply.a_type = ANSI_ESC; \ 758d522f475Smrg reply.a_pintro = '?'; \ 759d522f475Smrg }) 760d522f475Smrg 761d522f475Smrg#define VT52_CURSOR_KEYS \ 762d522f475Smrg if_OPT_VT52_MODE(screen,{ \ 763d522f475Smrg reply.a_type = ANSI_ESC; \ 764d522f475Smrg }) 765d522f475Smrg 766d522f475Smrg#undef APPEND_PARM 767d522f475Smrg#define APPEND_PARM(number) \ 768956cc18dSsnj reply.a_param[reply.a_nparam] = (ParmType) number, \ 769956cc18dSsnj reply.a_nparam++ 770d522f475Smrg 771d522f475Smrg#if OPT_MOD_FKEYS 772d522f475Smrg#define MODIFIER_PARM \ 773956cc18dSsnj if (modify_parm != 0) APPEND_PARM(modify_parm) 774d522f475Smrg#else 775d522f475Smrg#define MODIFIER_PARM /*nothing */ 776d522f475Smrg#endif 777d522f475Smrg 778d522f475Smrg/* 779d522f475Smrg * Determine if we use the \E[3~ sequence for Delete, or the legacy ^?. We 780d522f475Smrg * maintain the delete_is_del value as 3 states: unspecified(2), true and 781d522f475Smrg * false. If unspecified, it is handled differently according to whether the 782d522f475Smrg * legacy keyboard support is enabled, or if xterm emulates a VT220. 783d522f475Smrg * 784d522f475Smrg * Once the user (or application) has specified delete_is_del via resource 785d522f475Smrg * setting, popup menu or escape sequence, it overrides the keyboard type 786d522f475Smrg * rather than the reverse. 787d522f475Smrg */ 788d522f475SmrgBool 789d522f475SmrgxtermDeleteIsDEL(XtermWidget xw) 790d522f475Smrg{ 791d522f475Smrg Bool result = True; 792d522f475Smrg 793d522f475Smrg if (xw->keyboard.type == keyboardIsDefault 794d522f475Smrg || xw->keyboard.type == keyboardIsVT220) 79520d2c4d2Smrg result = (TScreenOf(xw)->delete_is_del == True); 796d522f475Smrg 797d522f475Smrg if (xw->keyboard.type == keyboardIsLegacy) 79820d2c4d2Smrg result = (TScreenOf(xw)->delete_is_del != False); 799d522f475Smrg 800d522f475Smrg TRACE(("xtermDeleteIsDEL(%d/%d) = %d\n", 801d522f475Smrg xw->keyboard.type, 80220d2c4d2Smrg TScreenOf(xw)->delete_is_del, 803d522f475Smrg result)); 804d522f475Smrg 805d522f475Smrg return result; 806d522f475Smrg} 807d522f475Smrg 8080bd37d32Smrgstatic Boolean 8090bd37d32SmrglookupKeyData(KEY_DATA * kd, XtermWidget xw, XKeyEvent * event) 810d522f475Smrg{ 81120d2c4d2Smrg TScreen *screen = TScreenOf(xw); 8120bd37d32Smrg TKeyboard *keyboard = &(xw->keyboard); 8130bd37d32Smrg Boolean result = True; 814d522f475Smrg 8150bd37d32Smrg TRACE(("%s %#x\n", visibleEventType(event->type), event->keycode)); 816d522f475Smrg 8170bd37d32Smrg kd->keysym = 0; 8180bd37d32Smrg kd->is_fkey = False; 819d522f475Smrg#if OPT_TCAP_QUERY 820d522f475Smrg if (screen->tc_query_code >= 0) { 8210bd37d32Smrg kd->keysym = (KeySym) screen->tc_query_code; 8220bd37d32Smrg kd->is_fkey = screen->tc_query_fkey; 8230bd37d32Smrg if (kd->keysym != XK_BackSpace) { 8240bd37d32Smrg kd->nbytes = 0; 8250bd37d32Smrg kd->strbuf[0] = 0; 826d522f475Smrg } else { 8270bd37d32Smrg kd->nbytes = 1; 8280bd37d32Smrg kd->strbuf[0] = 8; 829d522f475Smrg } 830d522f475Smrg } else 831d522f475Smrg#endif 832d522f475Smrg { 8330bd37d32Smrg#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD 8340bd37d32Smrg TInput *input = lookupTInput(xw, (Widget) xw); 8350bd37d32Smrg if (input && input->xic) { 836d522f475Smrg Status status_return; 837d522f475Smrg#if OPT_WIDE_CHARS 838d522f475Smrg if (screen->utf8_mode) { 8390bd37d32Smrg kd->nbytes = Xutf8LookupString(input->xic, event, 8400bd37d32Smrg kd->strbuf, (int) sizeof(kd->strbuf), 8410bd37d32Smrg &(kd->keysym), &status_return); 842d522f475Smrg } else 843d522f475Smrg#endif 844d522f475Smrg { 8450bd37d32Smrg kd->nbytes = XmbLookupString(input->xic, event, 8460bd37d32Smrg kd->strbuf, (int) sizeof(kd->strbuf), 8470bd37d32Smrg &(kd->keysym), &status_return); 848d522f475Smrg } 849d522f475Smrg#if OPT_MOD_FKEYS 850d522f475Smrg /* 851d522f475Smrg * Fill-in some code useful with IsControlAlias(): 852d522f475Smrg */ 853d522f475Smrg if (status_return == XLookupBoth 8540bd37d32Smrg && kd->nbytes <= 1 8550bd37d32Smrg && !IsPredefinedKey(kd->keysym) 856d522f475Smrg && (keyboard->modify_now.other_keys > 1) 8570bd37d32Smrg && !IsControlInput(kd)) { 8580bd37d32Smrg kd->nbytes = 1; 8590bd37d32Smrg kd->strbuf[0] = (char) kd->keysym; 860d522f475Smrg } 861d522f475Smrg#endif /* OPT_MOD_FKEYS */ 862d522f475Smrg } else 863d522f475Smrg#endif /* OPT_I18N_SUPPORT */ 864d522f475Smrg { 865d522f475Smrg static XComposeStatus compose_status = 866d522f475Smrg {NULL, 0}; 8670bd37d32Smrg kd->nbytes = XLookupString(event, 8680bd37d32Smrg kd->strbuf, (int) sizeof(kd->strbuf), 8690bd37d32Smrg &(kd->keysym), &compose_status); 870d522f475Smrg } 8710bd37d32Smrg kd->is_fkey = IsFunctionKey(kd->keysym); 872d522f475Smrg } 8730bd37d32Smrg return result; 8740bd37d32Smrg} 8750bd37d32Smrg 8760bd37d32Smrgvoid 8770bd37d32SmrgInput(XtermWidget xw, 8780bd37d32Smrg XKeyEvent * event, 8790bd37d32Smrg Bool eightbit) 8800bd37d32Smrg{ 8810bd37d32Smrg Char *string; 8820bd37d32Smrg 8830bd37d32Smrg TKeyboard *keyboard = &(xw->keyboard); 8840bd37d32Smrg TScreen *screen = TScreenOf(xw); 8850bd37d32Smrg 8860bd37d32Smrg int j; 8870bd37d32Smrg int key = False; 8880bd37d32Smrg ANSI reply; 8890bd37d32Smrg int dec_code; 8900bd37d32Smrg unsigned modify_parm = 0; 8910bd37d32Smrg int keypad_mode = ((keyboard->flags & MODE_DECKPAM) != 0); 8920bd37d32Smrg unsigned evt_state = event->state; 8930bd37d32Smrg unsigned mod_state; 8940bd37d32Smrg KEY_DATA kd; 8950bd37d32Smrg 8960bd37d32Smrg /* Ignore characters typed at the keyboard */ 8970bd37d32Smrg if (keyboard->flags & MODE_KAM) 8980bd37d32Smrg return; 8990bd37d32Smrg 9000bd37d32Smrg lookupKeyData(&kd, xw, event); 901d522f475Smrg 902d522f475Smrg memset(&reply, 0, sizeof(reply)); 903d522f475Smrg 904d522f475Smrg TRACE(("Input keysym " 905d522f475Smrg KEYSYM_FMT 906d522f475Smrg ", %d:'%s'%s" FMT_MODIFIER_NAMES "%s%s%s%s%s%s\n", 907d522f475Smrg kd.keysym, 908d522f475Smrg kd.nbytes, 909956cc18dSsnj visibleChars((Char *) kd.strbuf, 910d522f475Smrg ((kd.nbytes > 0) 911d522f475Smrg ? (unsigned) kd.nbytes 912d522f475Smrg : 0)), 913d522f475Smrg ARG_MODIFIER_NAMES(evt_state), 914d522f475Smrg eightbit ? " 8bit" : " 7bit", 915d522f475Smrg IsKeypadKey(kd.keysym) ? " KeypadKey" : "", 916d522f475Smrg IsCursorKey(kd.keysym) ? " CursorKey" : "", 917d522f475Smrg IsPFKey(kd.keysym) ? " PFKey" : "", 918d522f475Smrg kd.is_fkey ? " FKey" : "", 919d522f475Smrg IsMiscFunctionKey(kd.keysym) ? " MiscFKey" : "", 9200bd37d32Smrg IsEditFunctionKey(xw, kd.keysym) ? " EditFkey" : "")); 921d522f475Smrg 922d522f475Smrg#if OPT_SUNPC_KBD 923d522f475Smrg /* 924d522f475Smrg * DEC keyboards don't have keypad(+), but do have keypad(,) instead. 925d522f475Smrg * Other (Sun, PC) keyboards commonly have keypad(+), but no keypad(,) 926d522f475Smrg * - it's a pain for users to work around. 927d522f475Smrg */ 928d522f475Smrg if (keyboard->type == keyboardIsVT220 929d522f475Smrg && (evt_state & ShiftMask) == 0) { 930d522f475Smrg if (kd.keysym == XK_KP_Add) { 931d522f475Smrg kd.keysym = XK_KP_Separator; 93220d2c4d2Smrg UIntClr(evt_state, ShiftMask); 933d522f475Smrg TRACE(("...Input keypad(+), change keysym to " 934d522f475Smrg KEYSYM_FMT 935d522f475Smrg "\n", 936d522f475Smrg kd.keysym)); 937d522f475Smrg } 938d522f475Smrg if ((evt_state & ControlMask) != 0 939d522f475Smrg && kd.keysym == XK_KP_Separator) { 940d522f475Smrg kd.keysym = XK_KP_Subtract; 94120d2c4d2Smrg UIntClr(evt_state, ControlMask); 942d522f475Smrg TRACE(("...Input control/keypad(,), change keysym to " 943d522f475Smrg KEYSYM_FMT 944d522f475Smrg "\n", 945d522f475Smrg kd.keysym)); 946d522f475Smrg } 947d522f475Smrg } 948d522f475Smrg#endif 949d522f475Smrg 950d522f475Smrg /* 951d522f475Smrg * The keyboard tables may give us different keypad codes according to 952d522f475Smrg * whether NumLock is pressed. Use this check to simplify the process 953d522f475Smrg * of determining whether we generate an escape sequence for a keypad 954d522f475Smrg * key, or force it to the value kypd_num[]. There is no fixed 955d522f475Smrg * modifier for this feature, so we assume that it is the one assigned 956d522f475Smrg * to the NumLock key. 957d522f475Smrg * 958d522f475Smrg * This check used to try to return the contents of strbuf, but that 959d522f475Smrg * does not work properly when a control modifier is given (trash is 960d522f475Smrg * returned in the buffer in some cases -- perhaps an X bug). 961d522f475Smrg */ 962d522f475Smrg#if OPT_NUM_LOCK 963d522f475Smrg if (kd.nbytes == 1 964d522f475Smrg && IsKeypadKey(kd.keysym) 965d522f475Smrg && xw->misc.real_NumLock 9660bd37d32Smrg && (xw->work.num_lock & evt_state) != 0) { 967d522f475Smrg keypad_mode = 0; 968d522f475Smrg TRACE(("...Input num_lock, force keypad_mode off\n")); 969d522f475Smrg } 970d522f475Smrg#endif 971d522f475Smrg 972d522f475Smrg#if OPT_MOD_FKEYS 973d522f475Smrg if (evt_state != 0 974d522f475Smrg && allowModifierParm(xw, &kd)) { 975d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 976d522f475Smrg } 977d522f475Smrg 978d522f475Smrg /* 979d522f475Smrg * Shift-tab is often mapped to XK_ISO_Left_Tab which is classified as 980d522f475Smrg * IsEditFunctionKey(), and the conversion does not produce any bytes. 981d522f475Smrg * Check for this special case so we have data when handling the 982d522f475Smrg * modifyOtherKeys resource. 983d522f475Smrg */ 984d522f475Smrg if (keyboard->modify_now.other_keys > 1) { 985d522f475Smrg if (IsTabKey(kd.keysym) && kd.nbytes == 0) { 986d522f475Smrg kd.nbytes = 1; 987d522f475Smrg kd.strbuf[0] = '\t'; 988d522f475Smrg } 989d522f475Smrg } 9900bd37d32Smrg#ifdef XK_ISO_Left_Tab 9910bd37d32Smrg else if (IsTabKey(kd.keysym) 9920bd37d32Smrg && kd.nbytes <= 1 9930bd37d32Smrg && modify_parm == (MOD_NONE + MOD_SHIFT)) { 9940bd37d32Smrg kd.keysym = XK_ISO_Left_Tab; 9950bd37d32Smrg } 9960bd37d32Smrg#endif 997d522f475Smrg#endif /* OPT_MOD_FKEYS */ 998d522f475Smrg 999d522f475Smrg /* VT300 & up: backarrow toggle */ 1000d522f475Smrg if ((kd.nbytes == 1) 1001d522f475Smrg && IsBackarrowToggle(keyboard, kd.keysym, evt_state)) { 1002d522f475Smrg kd.strbuf[0] = ANSI_DEL; 1003d522f475Smrg TRACE(("...Input backarrow changed to %d\n", kd.strbuf[0])); 1004d522f475Smrg } 1005d522f475Smrg#if OPT_SUNPC_KBD 1006d522f475Smrg /* make an DEC editing-keypad from a Sun or PC editing-keypad */ 1007d522f475Smrg if (keyboard->type == keyboardIsVT220 1008d522f475Smrg && (kd.keysym != XK_Delete || !xtermDeleteIsDEL(xw))) 1009d522f475Smrg kd.keysym = TranslateFromSUNPC(kd.keysym); 1010d522f475Smrg else 1011d522f475Smrg#endif 1012d522f475Smrg { 1013d522f475Smrg#ifdef XK_KP_Home 1014d522f475Smrg if (kd.keysym >= XK_KP_Home && kd.keysym <= XK_KP_Begin) { 1015d522f475Smrg TRACE(("...Input keypad before was " KEYSYM_FMT "\n", kd.keysym)); 10164e40088cSchristos kd.keysym += (KeySym) (XK_Home - XK_KP_Home); 1017d522f475Smrg TRACE(("...Input keypad changed to " KEYSYM_FMT "\n", kd.keysym)); 1018d522f475Smrg } 1019d522f475Smrg#endif 1020d522f475Smrg } 1021d522f475Smrg 1022d522f475Smrg /* 1023d522f475Smrg * Map the Sun afterthought-keys in as F36 and F37. 1024d522f475Smrg */ 1025d522f475Smrg#ifdef SunXK_F36 1026d522f475Smrg if (!kd.is_fkey) { 1027d522f475Smrg if (kd.keysym == SunXK_F36) { 1028d522f475Smrg kd.keysym = XK_Fn(36); 1029d522f475Smrg kd.is_fkey = True; 1030d522f475Smrg } 1031d522f475Smrg if (kd.keysym == SunXK_F37) { 1032d522f475Smrg kd.keysym = XK_Fn(37); 1033d522f475Smrg kd.is_fkey = True; 1034d522f475Smrg } 1035d522f475Smrg } 1036d522f475Smrg#endif 1037d522f475Smrg 1038d522f475Smrg /* 1039d522f475Smrg * Use the control- and shift-modifiers to obtain more function keys than 1040d522f475Smrg * the keyboard provides. We can do this if there is no conflicting use of 1041d522f475Smrg * those modifiers: 1042d522f475Smrg * 1043d522f475Smrg * a) for VT220 keyboard, we use only the control-modifier. The keyboard 1044d522f475Smrg * uses shift-modifier for UDK's. 1045d522f475Smrg * 1046d522f475Smrg * b) for non-VT220 keyboards, we only have to check if the 1047d522f475Smrg * modifyFunctionKeys resource is inactive. 1048d522f475Smrg * 1049d522f475Smrg * Thereafter, we note when we have a function-key and keep that 1050d522f475Smrg * distinction when testing for "function-key" values. 1051d522f475Smrg */ 1052d522f475Smrg if ((evt_state & (ControlMask | ShiftMask)) != 0 1053d522f475Smrg && kd.is_fkey) { 1054d522f475Smrg 1055d522f475Smrg /* VT220 keyboard uses shift for UDK */ 1056d522f475Smrg if (keyboard->type == keyboardIsVT220 1057d522f475Smrg || keyboard->type == keyboardIsLegacy) { 1058d522f475Smrg 1059d522f475Smrg TRACE(("...map XK_F%ld", kd.keysym - XK_Fn(1) + 1)); 1060d522f475Smrg if (evt_state & ControlMask) { 10612eaa94a1Schristos kd.keysym += (KeySym) xw->misc.ctrl_fkeys; 106220d2c4d2Smrg UIntClr(evt_state, ControlMask); 1063d522f475Smrg } 1064d522f475Smrg TRACE((" to XK_F%ld\n", kd.keysym - XK_Fn(1) + 1)); 1065d522f475Smrg 1066d522f475Smrg } 1067d522f475Smrg#if OPT_MOD_FKEYS 1068d522f475Smrg else if (keyboard->modify_now.function_keys < 0) { 1069d522f475Smrg 1070d522f475Smrg TRACE(("...map XK_F%ld", kd.keysym - XK_Fn(1) + 1)); 1071d522f475Smrg if (evt_state & ShiftMask) { 10722eaa94a1Schristos kd.keysym += (KeySym) (xw->misc.ctrl_fkeys * 1); 107320d2c4d2Smrg UIntClr(evt_state, ShiftMask); 1074d522f475Smrg } 1075d522f475Smrg if (evt_state & ControlMask) { 10762eaa94a1Schristos kd.keysym += (KeySym) (xw->misc.ctrl_fkeys * 2); 107720d2c4d2Smrg UIntClr(evt_state, ControlMask); 1078d522f475Smrg } 1079d522f475Smrg TRACE((" to XK_F%ld\n", kd.keysym - XK_Fn(1) + 1)); 1080d522f475Smrg 1081d522f475Smrg } 1082d522f475Smrg /* 1083d522f475Smrg * Reevaluate the modifier parameter, stripping off the modifiers 1084d522f475Smrg * that we just used. 1085d522f475Smrg */ 10860bd37d32Smrg if (modify_parm) { 1087d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 10880bd37d32Smrg } 1089d522f475Smrg#endif /* OPT_MOD_FKEYS */ 1090d522f475Smrg } 1091d522f475Smrg 1092d522f475Smrg /* 1093d522f475Smrg * Test for one of the keyboard variants. 1094d522f475Smrg */ 1095d522f475Smrg switch (keyboard->type) { 1096d522f475Smrg case keyboardIsHP: 1097d522f475Smrg hpfuncvalue(&reply, &kd); 1098d522f475Smrg break; 1099d522f475Smrg case keyboardIsSCO: 1100d522f475Smrg scofuncvalue(&reply, &kd); 1101d522f475Smrg break; 1102d522f475Smrg case keyboardIsSun: 1103d522f475Smrg sunfuncvalue(&reply, &kd); 1104d522f475Smrg break; 1105d522f475Smrg case keyboardIsTermcap: 1106d522f475Smrg#if OPT_TCAP_FKEYS 1107d522f475Smrg if (xtermcapString(xw, (int) kd.keysym, evt_state)) 1108d522f475Smrg return; 1109d522f475Smrg#endif 1110d522f475Smrg break; 1111d522f475Smrg case keyboardIsDefault: 1112d522f475Smrg case keyboardIsLegacy: 1113d522f475Smrg case keyboardIsVT220: 1114d522f475Smrg break; 1115d522f475Smrg } 1116d522f475Smrg 1117d522f475Smrg if (reply.a_final) { 1118d522f475Smrg /* 1119d522f475Smrg * The key symbol matches one of the variants. Most of those are 1120d522f475Smrg * function-keys, though some cursor- and editing-keys are mixed in. 1121d522f475Smrg */ 1122d522f475Smrg modifyCursorKey(&reply, 1123d522f475Smrg ((kd.is_fkey 1124d522f475Smrg || IsMiscFunctionKey(kd.keysym) 11250bd37d32Smrg || IsEditFunctionKey(xw, kd.keysym)) 1126d522f475Smrg ? keyboard->modify_now.function_keys 1127d522f475Smrg : keyboard->modify_now.cursor_keys), 1128d522f475Smrg &modify_parm); 1129d522f475Smrg MODIFIER_PARM; 1130d522f475Smrg unparseseq(xw, &reply); 1131d522f475Smrg } else if (((kd.is_fkey 1132d522f475Smrg || IsMiscFunctionKey(kd.keysym) 11330bd37d32Smrg || IsEditFunctionKey(xw, kd.keysym)) 1134d522f475Smrg#if OPT_MOD_FKEYS 1135d522f475Smrg && !ModifyOtherKeys(xw, evt_state, &kd, modify_parm) 1136d522f475Smrg#endif 1137d522f475Smrg ) || (kd.keysym == XK_Delete 1138956cc18dSsnj && ((modify_parm != 0) 1139d522f475Smrg || !xtermDeleteIsDEL(xw)))) { 1140d522f475Smrg dec_code = decfuncvalue(&kd); 1141d522f475Smrg if ((evt_state & ShiftMask) 1142d522f475Smrg#if OPT_SUNPC_KBD 1143d522f475Smrg && keyboard->type == keyboardIsVT220 1144d522f475Smrg#endif 1145d522f475Smrg && ((string = (Char *) udk_lookup(dec_code, &kd.nbytes)) != 0)) { 114620d2c4d2Smrg UIntClr(evt_state, ShiftMask); 1147d522f475Smrg while (kd.nbytes-- > 0) 1148d522f475Smrg unparseputc(xw, CharOf(*string++)); 1149d522f475Smrg } 1150d522f475Smrg /* 1151d522f475Smrg * Interpret F1-F4 as PF1-PF4 for VT52, VT100 1152d522f475Smrg */ 1153d522f475Smrg else if (keyboard->type != keyboardIsLegacy 1154d522f475Smrg && (dec_code >= 11 && dec_code <= 14)) { 1155d522f475Smrg reply.a_type = ANSI_SS3; 1156d522f475Smrg VT52_CURSOR_KEYS; 11572eaa94a1Schristos reply.a_final = (Char) A2E(dec_code - 11 + E2A('P')); 1158d522f475Smrg modifyCursorKey(&reply, 1159d522f475Smrg keyboard->modify_now.function_keys, 1160d522f475Smrg &modify_parm); 1161d522f475Smrg MODIFIER_PARM; 1162d522f475Smrg unparseseq(xw, &reply); 1163956cc18dSsnj } else { 1164d522f475Smrg reply.a_type = ANSI_CSI; 1165d522f475Smrg reply.a_final = 0; 1166d522f475Smrg 1167d522f475Smrg#ifdef XK_ISO_Left_Tab 1168d522f475Smrg if (kd.keysym == XK_ISO_Left_Tab) { 1169d522f475Smrg reply.a_nparam = 0; 1170d522f475Smrg reply.a_final = 'Z'; 1171d522f475Smrg#if OPT_MOD_FKEYS 1172d522f475Smrg if (keyboard->modify_now.other_keys > 1 1173956cc18dSsnj && computeMaskedModifier(xw, evt_state, ShiftMask)) 1174d522f475Smrg modifyOtherKey(&reply, '\t', modify_parm, keyboard->format_keys); 1175d522f475Smrg#endif 1176d522f475Smrg } else 1177d522f475Smrg#endif /* XK_ISO_Left_Tab */ 1178d522f475Smrg { 1179d522f475Smrg reply.a_nparam = 1; 1180d522f475Smrg#if OPT_MOD_FKEYS 1181d522f475Smrg if (kd.is_fkey) { 1182d522f475Smrg modifyCursorKey(&reply, 1183d522f475Smrg keyboard->modify_now.function_keys, 1184d522f475Smrg &modify_parm); 1185d522f475Smrg } 1186d522f475Smrg MODIFIER_PARM; 1187d522f475Smrg#endif 1188956cc18dSsnj reply.a_param[0] = (ParmType) dec_code; 1189d522f475Smrg reply.a_final = '~'; 1190d522f475Smrg } 1191d522f475Smrg if (reply.a_final != 0 1192d522f475Smrg && (reply.a_nparam == 0 || reply.a_param[0] >= 0)) 1193d522f475Smrg unparseseq(xw, &reply); 1194d522f475Smrg } 1195d522f475Smrg key = True; 1196d522f475Smrg } else if (IsPFKey(kd.keysym)) { 1197d522f475Smrg reply.a_type = ANSI_SS3; 11982eaa94a1Schristos reply.a_final = (Char) ((kd.keysym - XK_KP_F1) + 'P'); 1199d522f475Smrg VT52_CURSOR_KEYS; 1200d522f475Smrg MODIFIER_PARM; 1201d522f475Smrg unparseseq(xw, &reply); 1202d522f475Smrg key = True; 1203d522f475Smrg } else if (IsKeypadKey(kd.keysym)) { 1204d522f475Smrg if (keypad_mode) { 1205d522f475Smrg reply.a_type = ANSI_SS3; 12062eaa94a1Schristos reply.a_final = (Char) (kypd_apl[kd.keysym - XK_KP_Space]); 1207d522f475Smrg VT52_KEYPAD; 1208d522f475Smrg MODIFIER_PARM; 1209d522f475Smrg unparseseq(xw, &reply); 1210d522f475Smrg } else { 1211d522f475Smrg unparseputc(xw, kypd_num[kd.keysym - XK_KP_Space]); 1212d522f475Smrg } 1213d522f475Smrg key = True; 1214d522f475Smrg } else if (IsCursorKey(kd.keysym)) { 1215d522f475Smrg if (keyboard->flags & MODE_DECCKM) { 1216d522f475Smrg reply.a_type = ANSI_SS3; 1217d522f475Smrg } else { 1218d522f475Smrg reply.a_type = ANSI_CSI; 1219d522f475Smrg } 1220d522f475Smrg modifyCursorKey(&reply, keyboard->modify_now.cursor_keys, &modify_parm); 12212eaa94a1Schristos reply.a_final = (Char) (curfinal[kd.keysym - XK_Home]); 1222d522f475Smrg VT52_CURSOR_KEYS; 1223d522f475Smrg MODIFIER_PARM; 1224d522f475Smrg unparseseq(xw, &reply); 1225d522f475Smrg key = True; 1226d522f475Smrg } else if (kd.nbytes > 0) { 1227d522f475Smrg int prefix = 0; 1228d522f475Smrg 1229d522f475Smrg#if OPT_TEK4014 1230d522f475Smrg if (TEK4014_GIN(tekWidget)) { 1231d522f475Smrg TekEnqMouse(tekWidget, kd.strbuf[0]); 1232d522f475Smrg TekGINoff(tekWidget); 1233d522f475Smrg kd.nbytes--; 1234d522f475Smrg for (j = 0; j < kd.nbytes; ++j) { 1235d522f475Smrg kd.strbuf[j] = kd.strbuf[j + 1]; 1236d522f475Smrg } 1237d522f475Smrg } 1238d522f475Smrg#endif 1239d522f475Smrg#if OPT_MOD_FKEYS 1240d522f475Smrg if ((keyboard->modify_now.other_keys > 0) 1241d522f475Smrg && ModifyOtherKeys(xw, evt_state, &kd, modify_parm) 1242d522f475Smrg && (mod_state = allowedCharModifiers(xw, evt_state, &kd)) != 0) { 1243d522f475Smrg int input_char; 1244d522f475Smrg 1245d522f475Smrg evt_state = mod_state; 1246d522f475Smrg 1247d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 1248d522f475Smrg 1249d522f475Smrg /* 1250d522f475Smrg * We want to show a keycode that corresponds to the 8-bit value 1251d522f475Smrg * of the key. If the keysym is less than 256, that is good 1252d522f475Smrg * enough. Special keys such as Tab may result in a value that 1253d522f475Smrg * is usable as well. For the latter (special cases), try to use 1254d522f475Smrg * the result from the X library lookup. 1255d522f475Smrg */ 1256d522f475Smrg input_char = ((kd.keysym < 256) 1257d522f475Smrg ? (int) kd.keysym 1258d522f475Smrg : ((kd.nbytes == 1) 1259d522f475Smrg ? CharOf(kd.strbuf[0]) 1260d522f475Smrg : -1)); 1261d522f475Smrg 1262d522f475Smrg TRACE(("...modifyOtherKeys %d;%d\n", modify_parm, input_char)); 1263d522f475Smrg if (modifyOtherKey(&reply, input_char, modify_parm, keyboard->format_keys)) { 1264d522f475Smrg unparseseq(xw, &reply); 1265d522f475Smrg } else { 126620d2c4d2Smrg Bell(xw, XkbBI_MinorError, 0); 1267d522f475Smrg } 1268d522f475Smrg } else 1269d522f475Smrg#endif /* OPT_MOD_FKEYS */ 1270d522f475Smrg { 1271d522f475Smrg#if OPT_NUM_LOCK 1272d522f475Smrg /* 1273d522f475Smrg * Send ESC if we have a META modifier and metaSendsEcape is true. 1274d522f475Smrg * Like eightBitInput, except that it is not associated with 1275d522f475Smrg * terminal settings. 1276d522f475Smrg */ 1277d522f475Smrg if (kd.nbytes != 0) { 1278d522f475Smrg if (screen->meta_sends_esc 12790bd37d32Smrg && (evt_state & xw->work.meta_mods) != 0) { 1280d522f475Smrg TRACE(("...input-char is modified by META\n")); 12810bd37d32Smrg UIntClr(evt_state, xw->work.meta_mods); 1282d522f475Smrg eightbit = False; 1283d522f475Smrg prefix = ANSI_ESC; 1284d522f475Smrg } else if (eightbit) { 1285d522f475Smrg /* it might be overridden, but this helps for debugging */ 1286d522f475Smrg TRACE(("...input-char is shifted by META\n")); 1287d522f475Smrg } 1288d522f475Smrg if (screen->alt_is_not_meta 12890bd37d32Smrg && (evt_state & xw->work.alt_mods) != 0) { 12900bd37d32Smrg UIntClr(evt_state, xw->work.alt_mods); 1291d522f475Smrg if (screen->alt_sends_esc) { 1292d522f475Smrg TRACE(("...input-char is modified by ALT\n")); 12932eaa94a1Schristos eightbit = False; 1294d522f475Smrg prefix = ANSI_ESC; 1295d522f475Smrg } else if (!eightbit) { 1296d522f475Smrg TRACE(("...input-char is shifted by ALT\n")); 1297d522f475Smrg eightbit = True; 1298d522f475Smrg } 1299d522f475Smrg } 1300d522f475Smrg } 1301d522f475Smrg#endif 1302d522f475Smrg /* 1303d522f475Smrg * If metaSendsEscape is false, fall through to this chunk, which 1304d522f475Smrg * implements the eightBitInput resource. 1305d522f475Smrg * 1306d522f475Smrg * It is normally executed when the user presses Meta plus a 1307d522f475Smrg * printable key, e.g., Meta+space. The presence of the Meta 1308d522f475Smrg * modifier is not guaranteed since what really happens is the 1309d522f475Smrg * "insert-eight-bit" or "insert-seven-bit" action, which we 1310d522f475Smrg * distinguish by the eightbit parameter to this function. So the 1311d522f475Smrg * eightBitInput resource really means that we use this shifting 1312d522f475Smrg * logic in the "insert-eight-bit" action. 1313d522f475Smrg */ 1314d522f475Smrg if (eightbit && (kd.nbytes == 1) && screen->input_eight_bits) { 1315d522f475Smrg IChar ch = CharOf(kd.strbuf[0]); 13160bd37d32Smrg if ((ch < 128) && (screen->eight_bit_meta == ebTrue)) { 13172eaa94a1Schristos kd.strbuf[0] |= (char) 0x80; 1318d522f475Smrg TRACE(("...input shift from %d to %d (%#x to %#x)\n", 1319d522f475Smrg ch, CharOf(kd.strbuf[0]), 1320d522f475Smrg ch, CharOf(kd.strbuf[0]))); 1321d522f475Smrg#if OPT_WIDE_CHARS 1322d522f475Smrg if (screen->utf8_mode) { 1323d522f475Smrg /* 1324d522f475Smrg * We could interpret the incoming code as "in the 1325d522f475Smrg * current locale", but it's simpler to treat it as 1326d522f475Smrg * a Unicode value to translate to UTF-8. 1327d522f475Smrg */ 1328d522f475Smrg ch = CharOf(kd.strbuf[0]); 1329d522f475Smrg kd.nbytes = 2; 13302eaa94a1Schristos kd.strbuf[0] = (char) (0xc0 | ((ch >> 6) & 0x3)); 13312eaa94a1Schristos kd.strbuf[1] = (char) (0x80 | (ch & 0x3f)); 1332d522f475Smrg TRACE(("...encoded %#x in UTF-8 as %#x,%#x\n", 1333d522f475Smrg ch, CharOf(kd.strbuf[0]), CharOf(kd.strbuf[1]))); 1334d522f475Smrg } 1335d522f475Smrg#endif 1336d522f475Smrg } 1337d522f475Smrg eightbit = False; 1338d522f475Smrg } 1339d522f475Smrg#if OPT_WIDE_CHARS 1340d522f475Smrg if (kd.nbytes == 1) /* cannot do NRC on UTF-8, for instance */ 1341d522f475Smrg#endif 1342d522f475Smrg { 1343d522f475Smrg /* VT220 & up: National Replacement Characters */ 1344d522f475Smrg if ((xw->flags & NATIONAL) != 0) { 1345e0a2b6dfSmrg unsigned cmp = xtermCharSetIn(screen, 1346e0a2b6dfSmrg CharOf(kd.strbuf[0]), 13472eaa94a1Schristos screen->keyboard_dialect[0]); 1348d522f475Smrg TRACE(("...input NRC %d, %s %d\n", 1349d522f475Smrg CharOf(kd.strbuf[0]), 1350d522f475Smrg (CharOf(kd.strbuf[0]) == cmp) 1351d522f475Smrg ? "unchanged" 1352d522f475Smrg : "changed to", 1353d522f475Smrg CharOf(cmp))); 13542eaa94a1Schristos kd.strbuf[0] = (char) cmp; 1355d522f475Smrg } else if (eightbit) { 1356d522f475Smrg prefix = ANSI_ESC; 1357d522f475Smrg } else if (kd.strbuf[0] == '?' 1358d522f475Smrg && (evt_state & ControlMask) != 0) { 1359d522f475Smrg kd.strbuf[0] = ANSI_DEL; 136020d2c4d2Smrg UIntClr(evt_state, ControlMask); 1361d522f475Smrg } 1362d522f475Smrg } 1363d522f475Smrg if (prefix != 0) 1364d522f475Smrg unparseputc(xw, prefix); /* escape */ 1365d522f475Smrg for (j = 0; j < kd.nbytes; ++j) 1366d522f475Smrg unparseputc(xw, CharOf(kd.strbuf[j])); 1367d522f475Smrg } 136820d2c4d2Smrg key = ((kd.keysym != ANSI_XOFF) && (kd.keysym != ANSI_XON)); 1369d522f475Smrg } 1370d522f475Smrg unparse_end(xw); 1371d522f475Smrg 1372d522f475Smrg if (key && !TEK4014_ACTIVE(xw)) 1373d522f475Smrg AdjustAfterInput(xw); 1374d522f475Smrg 1375d522f475Smrg xtermShowPointer(xw, False); 1376d522f475Smrg return; 1377d522f475Smrg} 1378d522f475Smrg 1379d522f475Smrgvoid 1380e0a2b6dfSmrgStringInput(XtermWidget xw, const Char *string, size_t nbytes) 1381d522f475Smrg{ 138220d2c4d2Smrg TRACE(("InputString (%s,%lu)\n", 138320d2c4d2Smrg visibleChars(string, (unsigned) nbytes), 138420d2c4d2Smrg (unsigned long) nbytes)); 1385d522f475Smrg#if OPT_TEK4014 1386d522f475Smrg if (nbytes && TEK4014_GIN(tekWidget)) { 1387d522f475Smrg TekEnqMouse(tekWidget, *string++); 1388d522f475Smrg TekGINoff(tekWidget); 1389d522f475Smrg nbytes--; 1390d522f475Smrg } 1391d522f475Smrg#endif 1392d522f475Smrg while (nbytes-- != 0) 1393d522f475Smrg unparseputc(xw, *string++); 1394d522f475Smrg if (!TEK4014_ACTIVE(xw)) 1395d522f475Smrg AdjustAfterInput(xw); 1396d522f475Smrg unparse_end(xw); 1397d522f475Smrg} 1398d522f475Smrg 1399d522f475Smrg/* These definitions are DEC-style (e.g., vt320) */ 1400d522f475Smrgstatic int 1401d522f475Smrgdecfuncvalue(KEY_DATA * kd) 1402d522f475Smrg{ 1403d522f475Smrg int result; 1404d522f475Smrg 1405d522f475Smrg if (kd->is_fkey) { 1406d522f475Smrg switch (kd->keysym) { 1407d522f475Smrg MAP(XK_Fn(1), 11); 1408d522f475Smrg MAP(XK_Fn(2), 12); 1409d522f475Smrg MAP(XK_Fn(3), 13); 1410d522f475Smrg MAP(XK_Fn(4), 14); 1411d522f475Smrg MAP(XK_Fn(5), 15); 1412d522f475Smrg MAP(XK_Fn(6), 17); 1413d522f475Smrg MAP(XK_Fn(7), 18); 1414d522f475Smrg MAP(XK_Fn(8), 19); 1415d522f475Smrg MAP(XK_Fn(9), 20); 1416d522f475Smrg MAP(XK_Fn(10), 21); 1417d522f475Smrg MAP(XK_Fn(11), 23); 1418d522f475Smrg MAP(XK_Fn(12), 24); 1419d522f475Smrg MAP(XK_Fn(13), 25); 1420d522f475Smrg MAP(XK_Fn(14), 26); 1421d522f475Smrg MAP(XK_Fn(15), 28); 1422d522f475Smrg MAP(XK_Fn(16), 29); 1423d522f475Smrg MAP(XK_Fn(17), 31); 1424d522f475Smrg MAP(XK_Fn(18), 32); 1425d522f475Smrg MAP(XK_Fn(19), 33); 1426d522f475Smrg MAP(XK_Fn(20), 34); 1427d522f475Smrg default: 1428d522f475Smrg /* after F20 the codes are made up and do not correspond to any 1429d522f475Smrg * real terminal. So they are simply numbered sequentially. 1430d522f475Smrg */ 14312eaa94a1Schristos result = 42 + (int) (kd->keysym - XK_Fn(21)); 1432d522f475Smrg break; 1433d522f475Smrg } 1434d522f475Smrg } else { 1435d522f475Smrg switch (kd->keysym) { 1436d522f475Smrg MAP(XK_Find, 1); 1437d522f475Smrg MAP(XK_Insert, 2); 1438d522f475Smrg MAP(XK_Delete, 3); 1439d522f475Smrg#ifdef XK_KP_Insert 1440d522f475Smrg MAP(XK_KP_Insert, 2); 1441d522f475Smrg MAP(XK_KP_Delete, 3); 1442d522f475Smrg#endif 1443d522f475Smrg#ifdef DXK_Remove 1444d522f475Smrg MAP(DXK_Remove, 3); 1445d522f475Smrg#endif 1446d522f475Smrg MAP(XK_Select, 4); 1447d522f475Smrg MAP(XK_Prior, 5); 1448d522f475Smrg MAP(XK_Next, 6); 1449d522f475Smrg#ifdef XK_ISO_Left_Tab 1450d522f475Smrg MAP(XK_ISO_Left_Tab, 'Z'); 1451d522f475Smrg#endif 1452d522f475Smrg MAP(XK_Help, 28); 1453d522f475Smrg MAP(XK_Menu, 29); 1454d522f475Smrg default: 1455d522f475Smrg result = -1; 1456d522f475Smrg break; 1457d522f475Smrg } 1458d522f475Smrg } 1459d522f475Smrg return result; 1460d522f475Smrg} 1461d522f475Smrg 1462d522f475Smrgstatic void 1463e0a2b6dfSmrghpfuncvalue(ANSI *reply, KEY_DATA * kd) 1464d522f475Smrg{ 1465d522f475Smrg#if OPT_HP_FUNC_KEYS 1466d522f475Smrg int result; 1467d522f475Smrg 1468d522f475Smrg if (kd->is_fkey) { 1469d522f475Smrg switch (kd->keysym) { 1470d522f475Smrg MAP(XK_Fn(1), 'p'); 1471d522f475Smrg MAP(XK_Fn(2), 'q'); 1472d522f475Smrg MAP(XK_Fn(3), 'r'); 1473d522f475Smrg MAP(XK_Fn(4), 's'); 1474d522f475Smrg MAP(XK_Fn(5), 't'); 1475d522f475Smrg MAP(XK_Fn(6), 'u'); 1476d522f475Smrg MAP(XK_Fn(7), 'v'); 1477d522f475Smrg MAP(XK_Fn(8), 'w'); 1478d522f475Smrg default: 1479d522f475Smrg result = -1; 1480d522f475Smrg break; 1481d522f475Smrg } 1482d522f475Smrg } else { 1483d522f475Smrg switch (kd->keysym) { 1484d522f475Smrg MAP(XK_Up, 'A'); 1485d522f475Smrg MAP(XK_Down, 'B'); 1486d522f475Smrg MAP(XK_Right, 'C'); 1487d522f475Smrg MAP(XK_Left, 'D'); 1488d522f475Smrg MAP(XK_End, 'F'); 1489d522f475Smrg MAP(XK_Clear, 'J'); 1490d522f475Smrg MAP(XK_Delete, 'P'); 1491d522f475Smrg MAP(XK_Insert, 'Q'); 1492d522f475Smrg MAP(XK_Next, 'S'); 1493d522f475Smrg MAP(XK_Prior, 'T'); 1494d522f475Smrg MAP(XK_Home, 'h'); 1495d522f475Smrg#ifdef XK_KP_Insert 1496d522f475Smrg MAP(XK_KP_Delete, 'P'); 1497d522f475Smrg MAP(XK_KP_Insert, 'Q'); 1498d522f475Smrg#endif 1499d522f475Smrg#ifdef DXK_Remove 1500d522f475Smrg MAP(DXK_Remove, 'P'); 1501d522f475Smrg#endif 1502d522f475Smrg MAP(XK_Select, 'F'); 1503d522f475Smrg MAP(XK_Find, 'h'); 1504d522f475Smrg default: 1505d522f475Smrg result = -1; 1506d522f475Smrg break; 1507d522f475Smrg } 1508d522f475Smrg } 1509d522f475Smrg if (result > 0) { 1510d522f475Smrg reply->a_type = ANSI_ESC; 15112eaa94a1Schristos reply->a_final = (Char) result; 1512d522f475Smrg } 1513d522f475Smrg#else 1514d522f475Smrg (void) reply; 1515d522f475Smrg (void) kd; 1516d522f475Smrg#endif /* OPT_HP_FUNC_KEYS */ 1517d522f475Smrg} 1518d522f475Smrg 1519d522f475Smrgstatic void 1520e0a2b6dfSmrgscofuncvalue(ANSI *reply, KEY_DATA * kd) 1521d522f475Smrg{ 1522d522f475Smrg#if OPT_SCO_FUNC_KEYS 1523d522f475Smrg int result; 1524d522f475Smrg 1525d522f475Smrg if (kd->is_fkey) { 1526d522f475Smrg switch (kd->keysym) { 1527d522f475Smrg MAP(XK_Fn(1), 'M'); 1528d522f475Smrg MAP(XK_Fn(2), 'N'); 1529d522f475Smrg MAP(XK_Fn(3), 'O'); 1530d522f475Smrg MAP(XK_Fn(4), 'P'); 1531d522f475Smrg MAP(XK_Fn(5), 'Q'); 1532d522f475Smrg MAP(XK_Fn(6), 'R'); 1533d522f475Smrg MAP(XK_Fn(7), 'S'); 1534d522f475Smrg MAP(XK_Fn(8), 'T'); 1535d522f475Smrg MAP(XK_Fn(9), 'U'); 1536d522f475Smrg MAP(XK_Fn(10), 'V'); 1537d522f475Smrg MAP(XK_Fn(11), 'W'); 1538d522f475Smrg MAP(XK_Fn(12), 'X'); 1539d522f475Smrg MAP(XK_Fn(13), 'Y'); 1540d522f475Smrg MAP(XK_Fn(14), 'Z'); 1541d522f475Smrg MAP(XK_Fn(15), 'a'); 1542d522f475Smrg MAP(XK_Fn(16), 'b'); 1543d522f475Smrg MAP(XK_Fn(17), 'c'); 1544d522f475Smrg MAP(XK_Fn(18), 'd'); 1545d522f475Smrg MAP(XK_Fn(19), 'e'); 1546d522f475Smrg MAP(XK_Fn(20), 'f'); 1547d522f475Smrg MAP(XK_Fn(21), 'g'); 1548d522f475Smrg MAP(XK_Fn(22), 'h'); 1549d522f475Smrg MAP(XK_Fn(23), 'i'); 1550d522f475Smrg MAP(XK_Fn(24), 'j'); 1551d522f475Smrg MAP(XK_Fn(25), 'k'); 1552d522f475Smrg MAP(XK_Fn(26), 'l'); 1553d522f475Smrg MAP(XK_Fn(27), 'm'); 1554d522f475Smrg MAP(XK_Fn(28), 'n'); 1555d522f475Smrg MAP(XK_Fn(29), 'o'); 1556d522f475Smrg MAP(XK_Fn(30), 'p'); 1557d522f475Smrg MAP(XK_Fn(31), 'q'); 1558d522f475Smrg MAP(XK_Fn(32), 'r'); 1559d522f475Smrg MAP(XK_Fn(33), 's'); 1560d522f475Smrg MAP(XK_Fn(34), 't'); 1561d522f475Smrg MAP(XK_Fn(35), 'u'); 1562d522f475Smrg MAP(XK_Fn(36), 'v'); 1563d522f475Smrg MAP(XK_Fn(37), 'w'); 1564d522f475Smrg MAP(XK_Fn(38), 'x'); 1565d522f475Smrg MAP(XK_Fn(39), 'y'); 1566d522f475Smrg MAP(XK_Fn(40), 'z'); 1567d522f475Smrg MAP(XK_Fn(41), '@'); 1568d522f475Smrg MAP(XK_Fn(42), '['); 1569d522f475Smrg MAP(XK_Fn(43), '\\'); 1570d522f475Smrg MAP(XK_Fn(44), ']'); 1571d522f475Smrg MAP(XK_Fn(45), '^'); 1572d522f475Smrg MAP(XK_Fn(46), '_'); 1573d522f475Smrg MAP(XK_Fn(47), '`'); 1574d522f475Smrg MAP(XK_Fn(48), '{'); /* no matching '}' */ 1575d522f475Smrg default: 1576d522f475Smrg result = -1; 1577d522f475Smrg break; 1578d522f475Smrg } 1579d522f475Smrg } else { 1580d522f475Smrg switch (kd->keysym) { 1581d522f475Smrg MAP(XK_Up, 'A'); 1582d522f475Smrg MAP(XK_Down, 'B'); 1583d522f475Smrg MAP(XK_Right, 'C'); 1584d522f475Smrg MAP(XK_Left, 'D'); 1585d522f475Smrg MAP(XK_Begin, 'E'); 1586d522f475Smrg MAP(XK_End, 'F'); 1587d522f475Smrg MAP(XK_Insert, 'L'); 1588d522f475Smrg MAP(XK_Next, 'G'); 1589d522f475Smrg MAP(XK_Prior, 'I'); 1590d522f475Smrg MAP(XK_Home, 'H'); 1591d522f475Smrg#ifdef XK_KP_Insert 1592d522f475Smrg MAP(XK_KP_Insert, 'L'); 1593d522f475Smrg#endif 1594d522f475Smrg default: 1595d522f475Smrg result = -1; 1596d522f475Smrg break; 1597d522f475Smrg } 1598d522f475Smrg } 1599d522f475Smrg if (result > 0) { 1600d522f475Smrg reply->a_type = ANSI_CSI; 16012eaa94a1Schristos reply->a_final = (Char) result; 1602d522f475Smrg } 1603d522f475Smrg#else 1604d522f475Smrg (void) reply; 1605d522f475Smrg (void) kd; 1606d522f475Smrg#endif /* OPT_SCO_FUNC_KEYS */ 1607d522f475Smrg} 1608d522f475Smrg 1609d522f475Smrgstatic void 1610e0a2b6dfSmrgsunfuncvalue(ANSI *reply, KEY_DATA * kd) 1611d522f475Smrg{ 1612d522f475Smrg#if OPT_SUN_FUNC_KEYS 1613956cc18dSsnj ParmType result; 1614d522f475Smrg 1615d522f475Smrg if (kd->is_fkey) { 1616d522f475Smrg switch (kd->keysym) { 1617d522f475Smrg /* kf1-kf20 are numbered sequentially */ 1618d522f475Smrg MAP(XK_Fn(1), 224); 1619d522f475Smrg MAP(XK_Fn(2), 225); 1620d522f475Smrg MAP(XK_Fn(3), 226); 1621d522f475Smrg MAP(XK_Fn(4), 227); 1622d522f475Smrg MAP(XK_Fn(5), 228); 1623d522f475Smrg MAP(XK_Fn(6), 229); 1624d522f475Smrg MAP(XK_Fn(7), 230); 1625d522f475Smrg MAP(XK_Fn(8), 231); 1626d522f475Smrg MAP(XK_Fn(9), 232); 1627d522f475Smrg MAP(XK_Fn(10), 233); 1628d522f475Smrg MAP(XK_Fn(11), 192); 1629d522f475Smrg MAP(XK_Fn(12), 193); 1630d522f475Smrg MAP(XK_Fn(13), 194); 1631d522f475Smrg MAP(XK_Fn(14), 195); /* kund */ 1632d522f475Smrg MAP(XK_Fn(15), 196); 1633d522f475Smrg MAP(XK_Fn(16), 197); /* kcpy */ 1634d522f475Smrg MAP(XK_Fn(17), 198); 1635d522f475Smrg MAP(XK_Fn(18), 199); 1636d522f475Smrg MAP(XK_Fn(19), 200); /* kfnd */ 1637d522f475Smrg MAP(XK_Fn(20), 201); 1638d522f475Smrg 1639d522f475Smrg /* kf31-kf36 are numbered sequentially */ 1640d522f475Smrg MAP(XK_Fn(21), 208); /* kf31 */ 1641d522f475Smrg MAP(XK_Fn(22), 209); 1642d522f475Smrg MAP(XK_Fn(23), 210); 1643d522f475Smrg MAP(XK_Fn(24), 211); 1644d522f475Smrg MAP(XK_Fn(25), 212); 1645d522f475Smrg MAP(XK_Fn(26), 213); /* kf36 */ 1646d522f475Smrg 1647d522f475Smrg /* kf37-kf47 are interspersed with keypad keys */ 1648d522f475Smrg MAP(XK_Fn(27), 214); /* khome */ 1649d522f475Smrg MAP(XK_Fn(28), 215); /* kf38 */ 1650d522f475Smrg MAP(XK_Fn(29), 216); /* kpp */ 1651d522f475Smrg MAP(XK_Fn(30), 217); /* kf40 */ 1652d522f475Smrg MAP(XK_Fn(31), 218); /* kb2 */ 1653d522f475Smrg MAP(XK_Fn(32), 219); /* kf42 */ 1654d522f475Smrg MAP(XK_Fn(33), 220); /* kend */ 1655d522f475Smrg MAP(XK_Fn(34), 221); /* kf44 */ 1656d522f475Smrg MAP(XK_Fn(35), 222); /* knp */ 1657d522f475Smrg MAP(XK_Fn(36), 234); /* kf46 */ 1658d522f475Smrg MAP(XK_Fn(37), 235); /* kf47 */ 1659d522f475Smrg default: 1660d522f475Smrg result = -1; 1661d522f475Smrg break; 1662d522f475Smrg } 1663d522f475Smrg } else { 1664d522f475Smrg switch (kd->keysym) { 1665d522f475Smrg MAP(XK_Help, 196); /* khlp */ 1666d522f475Smrg MAP(XK_Menu, 197); 1667d522f475Smrg 1668d522f475Smrg MAP(XK_Find, 1); 1669d522f475Smrg MAP(XK_Insert, 2); /* kich1 */ 1670d522f475Smrg MAP(XK_Delete, 3); 1671d522f475Smrg#ifdef XK_KP_Insert 1672d522f475Smrg MAP(XK_KP_Insert, 2); 1673d522f475Smrg MAP(XK_KP_Delete, 3); 1674d522f475Smrg#endif 1675d522f475Smrg#ifdef DXK_Remove 1676d522f475Smrg MAP(DXK_Remove, 3); 1677d522f475Smrg#endif 1678d522f475Smrg MAP(XK_Select, 4); 1679d522f475Smrg 1680d522f475Smrg MAP(XK_Prior, 216); 1681d522f475Smrg MAP(XK_Next, 222); 1682d522f475Smrg MAP(XK_Home, 214); 1683d522f475Smrg MAP(XK_End, 220); 1684d522f475Smrg MAP(XK_Begin, 218); /* kf41=kb2 */ 1685d522f475Smrg 1686d522f475Smrg default: 1687d522f475Smrg result = -1; 1688d522f475Smrg break; 1689d522f475Smrg } 1690d522f475Smrg } 1691d522f475Smrg if (result > 0) { 1692d522f475Smrg reply->a_type = ANSI_CSI; 1693d522f475Smrg reply->a_nparam = 1; 1694d522f475Smrg reply->a_param[0] = result; 1695d522f475Smrg reply->a_final = 'z'; 1696d522f475Smrg } else if (IsCursorKey(kd->keysym)) { 1697d522f475Smrg reply->a_type = ANSI_SS3; 16982eaa94a1Schristos reply->a_final = (Char) curfinal[kd->keysym - XK_Home]; 1699d522f475Smrg } 1700d522f475Smrg#else 1701d522f475Smrg (void) reply; 1702d522f475Smrg (void) kd; 1703d522f475Smrg#endif /* OPT_SUN_FUNC_KEYS */ 1704d522f475Smrg} 1705d522f475Smrg 1706d522f475Smrg#if OPT_NUM_LOCK 170720d2c4d2Smrg#define isName(c) ((c) == '_' || (c) == '-' || isalnum(CharOf(c))) 170820d2c4d2Smrg 170920d2c4d2Smrgstatic const char * 171020d2c4d2SmrgskipName(const char *s) 171120d2c4d2Smrg{ 171220d2c4d2Smrg while (*s != '\0' && isName(CharOf(*s))) 171320d2c4d2Smrg ++s; 171420d2c4d2Smrg return s; 171520d2c4d2Smrg} 171620d2c4d2Smrg 171720d2c4d2Smrg/* 171820d2c4d2Smrg * Found a ":" in a translation, check what is past it to see if it contains 171920d2c4d2Smrg * any of the insert-text action names. 172020d2c4d2Smrg */ 172120d2c4d2Smrgstatic Boolean 172220d2c4d2SmrgkeyCanInsert(const char *parse) 172320d2c4d2Smrg{ 172420d2c4d2Smrg Boolean result = False; 172520d2c4d2Smrg int ch; 172620d2c4d2Smrg Boolean escape = False; 172720d2c4d2Smrg Boolean quoted = False; 172820d2c4d2Smrg 172920d2c4d2Smrg static const char *table[] = 173020d2c4d2Smrg { 173120d2c4d2Smrg "insert", 173220d2c4d2Smrg "insert-seven-bit", 173320d2c4d2Smrg "insert-eight-bit", 173420d2c4d2Smrg "string", 173520d2c4d2Smrg }; 173620d2c4d2Smrg Cardinal n; 173720d2c4d2Smrg 173820d2c4d2Smrg while (*parse != '\0' && *parse != '\n') { 173920d2c4d2Smrg ch = CharOf(*parse++); 174020d2c4d2Smrg if (escape) { 174120d2c4d2Smrg escape = False; 174220d2c4d2Smrg } else if (ch == '\\') { 174320d2c4d2Smrg escape = True; 174420d2c4d2Smrg } else if (ch == '"') { 1745e0a2b6dfSmrg quoted = (Boolean) !quoted; 174620d2c4d2Smrg } else if (!quoted && isName(ch)) { 174720d2c4d2Smrg const char *next = skipName(--parse); 174820d2c4d2Smrg size_t need = (size_t) (next - parse); 174920d2c4d2Smrg 175020d2c4d2Smrg for (n = 0; n < XtNumber(table); ++n) { 175120d2c4d2Smrg if (need == strlen(table[n]) 175220d2c4d2Smrg && !strncmp(parse, table[n], need)) { 175320d2c4d2Smrg result = True; 175420d2c4d2Smrg break; 175520d2c4d2Smrg } 175620d2c4d2Smrg } 175720d2c4d2Smrg parse = next; 175820d2c4d2Smrg } 175920d2c4d2Smrg 176020d2c4d2Smrg } 176120d2c4d2Smrg return result; 176220d2c4d2Smrg} 176320d2c4d2Smrg 176420d2c4d2Smrg/* 176520d2c4d2Smrg * Strip the entire action, to avoid matching it. 176620d2c4d2Smrg */ 176720d2c4d2Smrgstatic char * 176820d2c4d2SmrgstripAction(char *base, char *last) 176920d2c4d2Smrg{ 177020d2c4d2Smrg while (last != base) { 177120d2c4d2Smrg if (*--last == '\n') { 177220d2c4d2Smrg break; 177320d2c4d2Smrg } 177420d2c4d2Smrg } 177520d2c4d2Smrg return last; 177620d2c4d2Smrg} 177720d2c4d2Smrg 177820d2c4d2Smrgstatic char * 177920d2c4d2SmrgstripBlanks(char *base, char *last) 178020d2c4d2Smrg{ 178120d2c4d2Smrg while (last != base) { 178220d2c4d2Smrg int ch = CharOf(last[-1]); 178320d2c4d2Smrg if (ch != ' ' && ch != '\t') 178420d2c4d2Smrg break; 178520d2c4d2Smrg --last; 178620d2c4d2Smrg } 178720d2c4d2Smrg return last; 178820d2c4d2Smrg} 1789d522f475Smrg 1790d522f475Smrg/* 17912eaa94a1Schristos * Strip unneeded whitespace from a translations resource, mono-casing and 1792d522f475Smrg * returning a malloc'd copy of the result. 1793d522f475Smrg */ 1794d522f475Smrgstatic char * 179520d2c4d2SmrgstripTranslations(const char *s, Bool onlyInsert) 1796d522f475Smrg{ 1797d522f475Smrg char *dst = 0; 1798d522f475Smrg 1799d522f475Smrg if (s != 0) { 1800d522f475Smrg dst = TypeMallocN(char, strlen(s) + 1); 1801d522f475Smrg 1802d522f475Smrg if (dst != 0) { 1803d522f475Smrg int state = 0; 1804d522f475Smrg int ch = 0; 1805d522f475Smrg int prv = 0; 1806d522f475Smrg char *d = dst; 1807d522f475Smrg 1808d522f475Smrg TRACE(("stripping:\n%s\n", s)); 1809d522f475Smrg while (*s != '\0') { 1810d522f475Smrg ch = *s++; 1811d522f475Smrg if (ch == '\n') { 1812d522f475Smrg if (d != dst) 18132eaa94a1Schristos *d++ = (char) ch; 1814d522f475Smrg state = 0; 1815d522f475Smrg } else if (strchr(":!#", ch) != 0) { 181620d2c4d2Smrg d = stripBlanks(dst, d); 181720d2c4d2Smrg if (onlyInsert && (ch == ':') && !keyCanInsert(s)) { 181820d2c4d2Smrg d = stripAction(dst, d); 181920d2c4d2Smrg } 1820d522f475Smrg state = -1; 1821d522f475Smrg } else if (state >= 0) { 1822d522f475Smrg if (isspace(CharOf(ch))) { 1823d522f475Smrg if (state == 0 || strchr("<>~ \t", prv)) 1824d522f475Smrg continue; 1825d522f475Smrg } else if (strchr("<>~", ch)) { 182620d2c4d2Smrg d = stripBlanks(dst, d); 1827d522f475Smrg } 18282eaa94a1Schristos *d++ = x_toupper(ch); 1829d522f475Smrg ++state; 1830d522f475Smrg } 1831d522f475Smrg prv = ch; 1832d522f475Smrg } 1833d522f475Smrg *d = '\0'; 1834d522f475Smrg TRACE(("...result:\n%s\n", dst)); 1835d522f475Smrg } 1836d522f475Smrg } 1837d522f475Smrg return dst; 1838d522f475Smrg} 1839d522f475Smrg 1840d522f475Smrg/* 1841d522f475Smrg * Make a simple check to see if a given translations keyword appears in 1842d522f475Smrg * xterm's translations resource. It does not attempt to parse the strings, 1843d522f475Smrg * just makes a case-independent check and ensures that the ends of the match 1844d522f475Smrg * are on token-boundaries. 1845d522f475Smrg * 1846d522f475Smrg * That this can only retrieve translations that are given as resource values; 1847d522f475Smrg * the default translations in charproc.c for example are not retrievable by 1848d522f475Smrg * any interface to X. 1849d522f475Smrg * 1850d522f475Smrg * Also: We can retrieve only the most-specified translation resource. For 1851d522f475Smrg * example, if the resource file specifies both "*translations" and 1852d522f475Smrg * "XTerm*translations", we see only the latter. 1853d522f475Smrg */ 1854d522f475Smrgstatic Bool 185520d2c4d2SmrgTranslationsUseKeyword(Widget w, char **cache, const char *keyword, Bool onlyInsert) 1856d522f475Smrg{ 1857d522f475Smrg static String data; 1858d522f475Smrg static XtResource key_resources[] = 1859d522f475Smrg { 1860d522f475Smrg {XtNtranslations, XtCTranslations, XtRString, 1861d522f475Smrg sizeof(data), 0, XtRString, (XtPointer) NULL} 1862d522f475Smrg }; 1863d522f475Smrg Bool result = False; 1864d522f475Smrg char *copy; 1865d522f475Smrg char *test; 1866d522f475Smrg 186720d2c4d2Smrg if ((test = stripTranslations(keyword, onlyInsert)) != 0) { 1868d522f475Smrg if (*cache == 0) { 1869d522f475Smrg XtGetSubresources(w, 1870d522f475Smrg (XtPointer) &data, 1871d522f475Smrg "vt100", 1872d522f475Smrg "VT100", 1873d522f475Smrg key_resources, 1874d522f475Smrg XtNumber(key_resources), 1875d522f475Smrg NULL, 1876d522f475Smrg (Cardinal) 0); 187720d2c4d2Smrg if (data != 0 && (copy = stripTranslations(data, onlyInsert)) != 0) { 1878d522f475Smrg *cache = copy; 1879d522f475Smrg } 1880d522f475Smrg } 1881d522f475Smrg 1882d522f475Smrg if (*cache != 0) { 1883d522f475Smrg char *p = *cache; 1884d522f475Smrg int state = 0; 1885d522f475Smrg int now = ' ', prv; 1886d522f475Smrg 1887d522f475Smrg while (*p != 0) { 1888d522f475Smrg prv = now; 1889d522f475Smrg now = *p++; 1890d522f475Smrg if (now == ':' 1891d522f475Smrg || now == '!') { 1892d522f475Smrg state = -1; 1893d522f475Smrg } else if (now == '\n') { 1894d522f475Smrg state = 0; 1895d522f475Smrg } else if (state >= 0) { 1896d522f475Smrg if (now == test[state]) { 1897d522f475Smrg if ((state != 0 1898d522f475Smrg || !isName(prv)) 1899d522f475Smrg && ((test[++state] == 0) 1900d522f475Smrg && !isName(*p))) { 1901d522f475Smrg result = True; 1902d522f475Smrg break; 1903d522f475Smrg } 1904d522f475Smrg } else { 1905d522f475Smrg state = 0; 1906d522f475Smrg } 1907d522f475Smrg } 1908d522f475Smrg } 1909d522f475Smrg } 1910d522f475Smrg free(test); 1911d522f475Smrg } 191220d2c4d2Smrg TRACE(("TranslationsUseKeyword(%p, %s) = %d\n", 191320d2c4d2Smrg (void *) w, keyword, result)); 1914d522f475Smrg return result; 1915d522f475Smrg} 1916d522f475Smrg 1917d522f475Smrgstatic Bool 191820d2c4d2SmrgxtermHasTranslation(XtermWidget xw, const char *keyword, Bool onlyInsert) 1919d522f475Smrg{ 1920d522f475Smrg return (TranslationsUseKeyword(SHELL_OF(xw), 1921d522f475Smrg &(xw->keyboard.shell_translations), 192220d2c4d2Smrg keyword, 192320d2c4d2Smrg onlyInsert) 1924d522f475Smrg || TranslationsUseKeyword((Widget) xw, 1925d522f475Smrg &(xw->keyboard.xterm_translations), 192620d2c4d2Smrg keyword, 192720d2c4d2Smrg onlyInsert)); 1928d522f475Smrg} 1929d522f475Smrg 1930d522f475Smrg#if OPT_EXTRA_PASTE 1931d522f475Smrgstatic void 193220d2c4d2SmrgaddTranslation(XtermWidget xw, const char *fromString, const char *toString) 1933d522f475Smrg{ 193420d2c4d2Smrg size_t have = (xw->keyboard.extra_translations 193520d2c4d2Smrg ? strlen(xw->keyboard.extra_translations) 193620d2c4d2Smrg : 0); 193720d2c4d2Smrg size_t need = (((have != 0) ? (have + 4) : 0) 193820d2c4d2Smrg + strlen(fromString) 193920d2c4d2Smrg + strlen(toString) 194020d2c4d2Smrg + 6); 194120d2c4d2Smrg 194220d2c4d2Smrg if (!xtermHasTranslation(xw, fromString, False)) { 1943d522f475Smrg xw->keyboard.extra_translations 1944d522f475Smrg = TypeRealloc(char, need, xw->keyboard.extra_translations); 1945d522f475Smrg if ((xw->keyboard.extra_translations) != 0) { 1946d522f475Smrg TRACE(("adding %s: %s\n", fromString, toString)); 1947d522f475Smrg if (have) 1948d522f475Smrg strcat(xw->keyboard.extra_translations, " \\n\\"); 1949d522f475Smrg sprintf(xw->keyboard.extra_translations, "%s: %s", 1950d522f475Smrg fromString, toString); 1951d522f475Smrg TRACE(("...{%s}\n", xw->keyboard.extra_translations)); 1952d522f475Smrg } 1953d522f475Smrg } 1954d522f475Smrg} 1955d522f475Smrg#endif 1956d522f475Smrg 19570bd37d32Smrg#define SaveMask(name) xw->work.name |= (unsigned) mask;\ 19580bd37d32Smrg TRACE(("SaveMask(%#x -> %s) %#x (%#x is%s modifier)\n", \ 19590bd37d32Smrg (unsigned) keysym, #name, \ 19600bd37d32Smrg xw->work.name, (unsigned) mask, \ 196120d2c4d2Smrg ModifierName((unsigned) mask))); 1962d522f475Smrg/* 1963d522f475Smrg * Determine which modifier mask (if any) applies to the Num_Lock keysym. 1964d522f475Smrg * 1965d522f475Smrg * Also, determine which modifiers are associated with the ALT keys, so we can 1966d522f475Smrg * send that information as a parameter for special keys in Sun/PC keyboard 1967d522f475Smrg * mode. However, if the ALT modifier is used in translations, we do not want 1968d522f475Smrg * to confuse things by sending the parameter. 1969d522f475Smrg */ 1970d522f475Smrgvoid 1971d522f475SmrgVTInitModifiers(XtermWidget xw) 1972d522f475Smrg{ 1973d522f475Smrg Display *dpy = XtDisplay(xw); 1974d522f475Smrg XModifierKeymap *keymap = XGetModifierMapping(dpy); 1975d522f475Smrg int i, j, k, l; 1976d522f475Smrg KeySym keysym; 1977d522f475Smrg unsigned long mask; 1978d522f475Smrg int min_keycode, max_keycode, keysyms_per_keycode = 0; 1979d522f475Smrg 1980d522f475Smrg if (keymap != 0) { 1981d522f475Smrg KeySym *theMap; 1982d522f475Smrg int keycode_count; 1983d522f475Smrg 1984d522f475Smrg TRACE(("VTInitModifiers\n")); 1985d522f475Smrg 1986d522f475Smrg XDisplayKeycodes(dpy, &min_keycode, &max_keycode); 1987d522f475Smrg keycode_count = (max_keycode - min_keycode + 1); 1988d522f475Smrg theMap = XGetKeyboardMapping(dpy, 1989956cc18dSsnj (KeyCode) min_keycode, 1990d522f475Smrg keycode_count, 1991d522f475Smrg &keysyms_per_keycode); 1992d522f475Smrg 1993d522f475Smrg if (theMap != 0) { 1994d522f475Smrg 1995d522f475Smrg#if OPT_EXTRA_PASTE 1996d522f475Smrg /* 1997d522f475Smrg * Assume that if we can find the paste keysym in the X keyboard 1998d522f475Smrg * mapping that the server allows the corresponding translations 1999d522f475Smrg * resource. 2000d522f475Smrg */ 2001d522f475Smrg int limit = (max_keycode - min_keycode) * keysyms_per_keycode; 2002d522f475Smrg for (i = 0; i < limit; ++i) { 2003d522f475Smrg#ifdef XF86XK_Paste 2004d522f475Smrg if (theMap[i] == XF86XK_Paste) { 2005d522f475Smrg TRACE(("keyboard has XF86XK_Paste\n")); 2006d522f475Smrg addTranslation(xw, 2007d522f475Smrg "<KeyPress> XF86Paste", 2008d522f475Smrg "insert-selection(SELECT, CUT_BUFFER0)"); 2009d522f475Smrg } 2010d522f475Smrg#endif 2011d522f475Smrg#ifdef SunXK_Paste 2012d522f475Smrg if (theMap[i] == SunXK_Paste) { 2013d522f475Smrg TRACE(("keyboard has SunXK_Paste\n")); 2014d522f475Smrg addTranslation(xw, 2015d522f475Smrg "<KeyPress> SunPaste", 2016d522f475Smrg "insert-selection(SELECT, CUT_BUFFER0)"); 2017d522f475Smrg } 2018d522f475Smrg#endif 2019d522f475Smrg } 2020d522f475Smrg#endif /* OPT_EXTRA_PASTE */ 2021d522f475Smrg 2022d522f475Smrg for (i = k = 0, mask = 1; i < 8; i++, mask <<= 1) { 2023d522f475Smrg for (j = 0; j < keymap->max_keypermod; j++) { 2024d522f475Smrg KeyCode code = keymap->modifiermap[k++]; 2025d522f475Smrg if (code == 0) 2026d522f475Smrg continue; 2027d522f475Smrg 2028d522f475Smrg for (l = 0; l < keysyms_per_keycode; ++l) { 20290bd37d32Smrg#ifdef HAVE_XKBKEYCODETOKEYSYM 20300bd37d32Smrg keysym = XkbKeycodeToKeysym(dpy, code, 0, l); 20310bd37d32Smrg#else 2032d522f475Smrg keysym = XKeycodeToKeysym(dpy, code, l); 20330bd37d32Smrg#endif 2034d522f475Smrg if (keysym == NoSymbol) { 2035a1f3da82Smrg /* EMPTY */ ; 2036d522f475Smrg } else if (keysym == XK_Num_Lock) { 2037d522f475Smrg SaveMask(num_lock); 2038d522f475Smrg } else if (keysym == XK_Alt_L || keysym == XK_Alt_R) { 2039d522f475Smrg SaveMask(alt_mods); 2040d522f475Smrg } else if (keysym == XK_Meta_L || keysym == XK_Meta_R) { 2041d522f475Smrg SaveMask(meta_mods); 2042d522f475Smrg } 2043d522f475Smrg } 2044d522f475Smrg } 2045d522f475Smrg } 2046d522f475Smrg XFree(theMap); 2047d522f475Smrg } 2048d522f475Smrg 2049d522f475Smrg /* Don't disable any mods if "alwaysUseMods" is true. */ 2050d522f475Smrg if (!xw->misc.alwaysUseMods) { 205120d2c4d2Smrg 205220d2c4d2Smrg /* 205320d2c4d2Smrg * Force TranslationsUseKeyword() to reload. 205420d2c4d2Smrg */ 205520d2c4d2Smrg if (xw->keyboard.shell_translations) { 205620d2c4d2Smrg free(xw->keyboard.shell_translations); 205720d2c4d2Smrg xw->keyboard.shell_translations = 0; 205820d2c4d2Smrg } 205920d2c4d2Smrg if (xw->keyboard.xterm_translations) { 206020d2c4d2Smrg free(xw->keyboard.xterm_translations); 206120d2c4d2Smrg xw->keyboard.xterm_translations = 0; 206220d2c4d2Smrg } 206320d2c4d2Smrg 2064d522f475Smrg /* 2065d522f475Smrg * If the Alt modifier is used in translations, we would rather not 2066d522f475Smrg * use it to modify function-keys when NumLock is active. 2067d522f475Smrg */ 20680bd37d32Smrg if ((xw->work.alt_mods != 0) 206920d2c4d2Smrg && xtermHasTranslation(xw, "alt", True)) { 2070d522f475Smrg TRACE(("ALT is used as a modifier in translations (ignore mask)\n")); 20710bd37d32Smrg xw->work.alt_mods = 0; 2072d522f475Smrg } 2073d522f475Smrg 2074d522f475Smrg /* 2075d522f475Smrg * If the Meta modifier is used in translations, we would rather not 2076d522f475Smrg * use it to modify function-keys. 2077d522f475Smrg */ 20780bd37d32Smrg if ((xw->work.meta_mods != 0) 207920d2c4d2Smrg && xtermHasTranslation(xw, "meta", True)) { 2080d522f475Smrg TRACE(("META is used as a modifier in translations\n")); 20810bd37d32Smrg xw->work.meta_mods = 0; 2082d522f475Smrg } 2083d522f475Smrg } 2084d522f475Smrg 2085d522f475Smrg XFreeModifiermap(keymap); 2086d522f475Smrg } 2087d522f475Smrg} 2088d522f475Smrg#endif /* OPT_NUM_LOCK */ 2089