input.c revision 2eaa94a1
12eaa94a1Schristos/* $XTermId: input.c,v 1.302 2008/12/30 17:20:39 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/* 4d522f475Smrg * Copyright 1999-2007,2008 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 118d522f475Smrg#define TEK4014_GIN(tw) (tw != 0 && tw->screen.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 128d522f475Smrg/* 0123456789 abc def0123456789abcdef0123456789abcdef0123456789abcd */ 129d522f475Smrgstatic char *kypd_num = " XXXXXXXX\tXXX\rXXXxxxxXXXXXXXXXXXXXXXXXXXXX*+,-./0123456789XXX="; 130d522f475Smrg 131d522f475Smrg/* 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd */ 132d522f475Smrgstatic char *kypd_apl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ??????abcdefghijklmnopqrstuvwxyzXXX"; 133d522f475Smrg 134d522f475Smrgstatic char *curfinal = "HDACB FE"; 135d522f475Smrg 136d522f475Smrgstatic int decfuncvalue(KEY_DATA *); 137d522f475Smrgstatic void sunfuncvalue(ANSI *, KEY_DATA *); 138d522f475Smrgstatic void hpfuncvalue(ANSI *, KEY_DATA *); 139d522f475Smrgstatic void scofuncvalue(ANSI *, KEY_DATA *); 140d522f475Smrg 141d522f475Smrg#if OPT_TRACE 142d522f475Smrgstatic char * 143d522f475SmrgModifierName(unsigned modifier) 144d522f475Smrg{ 145d522f475Smrg char *s = ""; 146d522f475Smrg if (modifier & ShiftMask) 147d522f475Smrg s = " Shift"; 148d522f475Smrg else if (modifier & LockMask) 149d522f475Smrg s = " Lock"; 150d522f475Smrg else if (modifier & ControlMask) 151d522f475Smrg s = " Control"; 152d522f475Smrg else if (modifier & Mod1Mask) 153d522f475Smrg s = " Mod1"; 154d522f475Smrg else if (modifier & Mod2Mask) 155d522f475Smrg s = " Mod2"; 156d522f475Smrg else if (modifier & Mod3Mask) 157d522f475Smrg s = " Mod3"; 158d522f475Smrg else if (modifier & Mod4Mask) 159d522f475Smrg s = " Mod4"; 160d522f475Smrg else if (modifier & Mod5Mask) 161d522f475Smrg s = " Mod5"; 162d522f475Smrg return s; 163d522f475Smrg} 164d522f475Smrg 165d522f475Smrg#define FMT_MODIFIER_NAMES "%s%s%s%s%s%s%s%s" 166d522f475Smrg#define ARG_MODIFIER_NAMES(state) \ 167d522f475Smrg ModifierName(state & ShiftMask), \ 168d522f475Smrg ModifierName(state & LockMask), \ 169d522f475Smrg ModifierName(state & ControlMask), \ 170d522f475Smrg ModifierName(state & Mod1Mask), \ 171d522f475Smrg ModifierName(state & Mod2Mask), \ 172d522f475Smrg ModifierName(state & Mod3Mask), \ 173d522f475Smrg ModifierName(state & Mod4Mask), \ 174d522f475Smrg ModifierName(state & Mod5Mask) 175d522f475Smrg#endif 176d522f475Smrg 177d522f475Smrgstatic void 178d522f475SmrgAdjustAfterInput(XtermWidget xw) 179d522f475Smrg{ 180d522f475Smrg TScreen *screen = &(xw->screen); 181d522f475Smrg 182d522f475Smrg if (screen->scrollkey && screen->topline != 0) 183d522f475Smrg WindowScroll(xw, 0); 184d522f475Smrg if (screen->marginbell) { 185d522f475Smrg int col = screen->max_col - screen->nmarginbell; 186d522f475Smrg if (screen->bellarmed >= 0) { 187d522f475Smrg if (screen->bellarmed == screen->cur_row) { 188d522f475Smrg if (screen->cur_col >= col) { 189d522f475Smrg Bell(XkbBI_MarginBell, 0); 190d522f475Smrg screen->bellarmed = -1; 191d522f475Smrg } 192d522f475Smrg } else 193d522f475Smrg screen->bellarmed = 194d522f475Smrg screen->cur_col < col ? screen->cur_row : -1; 195d522f475Smrg } else if (screen->cur_col < col) 196d522f475Smrg screen->bellarmed = screen->cur_row; 197d522f475Smrg } 198d522f475Smrg} 199d522f475Smrg 200d522f475Smrg/* 201d522f475Smrg * Return true if the key is on the editing keypad. This overlaps with 202d522f475Smrg * IsCursorKey() and IsKeypadKey() and must be tested before those macro to 203d522f475Smrg * distinguish it from them. 204d522f475Smrg */ 205d522f475Smrgstatic Bool 206d522f475SmrgIsEditFunctionKey(KeySym keysym) 207d522f475Smrg{ 208d522f475Smrg switch (keysym) { 209d522f475Smrg case XK_Prior: /* editing keypad */ 210d522f475Smrg case XK_Next: /* editing keypad */ 211d522f475Smrg case XK_Insert: /* editing keypad */ 212d522f475Smrg case XK_Find: /* editing keypad */ 213d522f475Smrg case XK_Select: /* editing keypad */ 214d522f475Smrg#ifdef DXK_Remove 215d522f475Smrg case DXK_Remove: /* editing keypad */ 216d522f475Smrg#endif 217d522f475Smrg#ifdef XK_KP_Delete 218d522f475Smrg case XK_KP_Delete: /* editing key on numeric keypad */ 219d522f475Smrg case XK_KP_Insert: /* editing key on numeric keypad */ 220d522f475Smrg#endif 221d522f475Smrg#ifdef XK_ISO_Left_Tab 222d522f475Smrg case XK_ISO_Left_Tab: 223d522f475Smrg#endif 224d522f475Smrg return True; 225d522f475Smrg default: 226d522f475Smrg return False; 227d522f475Smrg } 228d522f475Smrg} 229d522f475Smrg 230d522f475Smrg#if OPT_MOD_FKEYS 231d522f475Smrg#define IS_CTRL(n) ((n) < ANSI_SPA || ((n) >= 0x7f && (n) <= 0x9f)) 232d522f475Smrg 233d522f475Smrg/* 234d522f475Smrg * Return true if the keysym corresponds to one of the control characters, 235d522f475Smrg * or one of the common ASCII characters that is combined with control to 236d522f475Smrg * make a control character. 237d522f475Smrg */ 238d522f475Smrgstatic Bool 239d522f475SmrgIsControlInput(KEY_DATA * kd) 240d522f475Smrg{ 241d522f475Smrg return ((kd->keysym) >= 0x40 && (kd->keysym) <= 0x7f); 242d522f475Smrg} 243d522f475Smrg 244d522f475Smrgstatic Bool 245d522f475SmrgIsControlOutput(KEY_DATA * kd) 246d522f475Smrg{ 247d522f475Smrg return IS_CTRL(kd->keysym); 248d522f475Smrg} 249d522f475Smrg 250d522f475Smrg/* 251d522f475Smrg * X "normally" has some built-in translations, which the user may want to 252d522f475Smrg * suppress when processing the modifyOtherKeys resource. In particular, the 253d522f475Smrg * control modifier applied to some of the keyboard digits gives results for 254d522f475Smrg * control characters. 255d522f475Smrg * 256d522f475Smrg * control 2 0 NUL 257d522f475Smrg * control SPC 0 NUL 258d522f475Smrg * control @ 0 NUL 259d522f475Smrg * control ` 0 NUL 260d522f475Smrg * control 3 0x1b ESC 261d522f475Smrg * control 4 0x1c FS 262d522f475Smrg * control \ 0x1c FS 263d522f475Smrg * control 5 0x1d GS 264d522f475Smrg * control 6 0x1e RS 265d522f475Smrg * control ^ 0x1e RS 266d522f475Smrg * control ~ 0x1e RS 267d522f475Smrg * control 7 0x1f US 268d522f475Smrg * control / 0x1f US 269d522f475Smrg * control _ 0x1f US 270d522f475Smrg * control 8 0x7f DEL 271d522f475Smrg * 272d522f475Smrg * It is possible that some other keyboards do not work for these combinations, 273d522f475Smrg * but they do work with modifyOtherKeys=2 for the US keyboard: 274d522f475Smrg * 275d522f475Smrg * control ` 0 NUL 276d522f475Smrg * control [ 0x1b ESC 277d522f475Smrg * control \ 0x1c FS 278d522f475Smrg * control ] 0x1d GS 279d522f475Smrg * control ? 0x7f DEL 280d522f475Smrg */ 281d522f475Smrgstatic Bool 282d522f475SmrgIsControlAlias(KEY_DATA * kd) 283d522f475Smrg{ 284d522f475Smrg Bool result = False; 285d522f475Smrg 286d522f475Smrg if (kd->nbytes == 1) { 287d522f475Smrg result = IS_CTRL(CharOf(kd->strbuf[0])); 288d522f475Smrg } 289d522f475Smrg return result; 290d522f475Smrg} 291d522f475Smrg 292d522f475Smrg/* 293d522f475Smrg * If we are in the non-VT220/VT52 keyboard state, allow modifiers to add a 294d522f475Smrg * parameter to the function-key control sequences. 295d522f475Smrg * 296d522f475Smrg * Note that we generally cannot capture the Shift-modifier for the numeric 297d522f475Smrg * keypad since this is commonly used to act as a type of NumLock, e.g., 298d522f475Smrg * making the keypad send "7" (actually XK_KP_7) where the unshifted code 299d522f475Smrg * would be Home (XK_KP_Home). The other modifiers work, subject to the 300d522f475Smrg * usual window-manager assignments. 301d522f475Smrg */ 302d522f475Smrgstatic Bool 303d522f475SmrgallowModifierParm(XtermWidget xw, KEY_DATA * kd) 304d522f475Smrg{ 305d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 306d522f475Smrg TScreen *screen = &(xw->screen); 307d522f475Smrg int keypad_mode = ((keyboard->flags & MODE_DECKPAM) != 0); 308d522f475Smrg 309d522f475Smrg Bool result = False; 310d522f475Smrg 311d522f475Smrg (void) screen; 312d522f475Smrg if (!(IsKeypadKey(kd->keysym) && keypad_mode) 313d522f475Smrg#if OPT_SUNPC_KBD 314d522f475Smrg && keyboard->type != keyboardIsVT220 315d522f475Smrg#endif 316d522f475Smrg#if OPT_VT52_MODE 317d522f475Smrg && screen->vtXX_level != 0 318d522f475Smrg#endif 319d522f475Smrg ) { 320d522f475Smrg result = True; 321d522f475Smrg } 322d522f475Smrg return result; 323d522f475Smrg} 324d522f475Smrg 325d522f475Smrg/* 326d522f475Smrg* Modifier codes: 327d522f475Smrg* None 1 328d522f475Smrg* Shift 2 = 1(None)+1(Shift) 329d522f475Smrg* Alt 3 = 1(None)+2(Alt) 330d522f475Smrg* Alt+Shift 4 = 1(None)+1(Shift)+2(Alt) 331d522f475Smrg* Ctrl 5 = 1(None)+4(Ctrl) 332d522f475Smrg* Ctrl+Shift 6 = 1(None)+1(Shift)+4(Ctrl) 333d522f475Smrg* Ctrl+Alt 7 = 1(None)+2(Alt)+4(Ctrl) 334d522f475Smrg* Ctrl+Alt+Shift 8 = 1(None)+1(Shift)+2(Alt)+4(Ctrl) 335d522f475Smrg* Meta 9 = 1(None)+8(Meta) 336d522f475Smrg* Meta+Shift 10 = 1(None)+8(Meta)+1(Shift) 337d522f475Smrg* Meta+Alt 11 = 1(None)+8(Meta)+2(Alt) 338d522f475Smrg* Meta+Alt+Shift 12 = 1(None)+8(Meta)+1(Shift)+2(Alt) 339d522f475Smrg* Meta+Ctrl 13 = 1(None)+8(Meta)+4(Ctrl) 340d522f475Smrg* Meta+Ctrl+Shift 14 = 1(None)+8(Meta)+1(Shift)+4(Ctrl) 341d522f475Smrg* Meta+Ctrl+Alt 15 = 1(None)+8(Meta)+2(Alt)+4(Ctrl) 342d522f475Smrg* Meta+Ctrl+Alt+Shift 16 = 1(None)+8(Meta)+1(Shift)+2(Alt)+4(Ctrl) 343d522f475Smrg*/ 344d522f475Smrg 345d522f475Smrg#undef CTRL 346d522f475Smrg 347d522f475Smrg/* FIXME - make these used in xtermcap.c */ 348d522f475Smrg#define UNMOD 1 349d522f475Smrg#define SHIFT 1 350d522f475Smrg#define ALT 2 351d522f475Smrg#define CTRL 4 352d522f475Smrg#define META 8 353d522f475Smrg 354d522f475Smrg#define MODIFIER_NAME(parm, name) \ 355d522f475Smrg (((parm > UNMOD) && ((parm - UNMOD) & name)) ? " "#name : "") 356d522f475Smrg 357d522f475Smrgint 358d522f475SmrgxtermParamToState(XtermWidget xw, unsigned param) 359d522f475Smrg{ 360d522f475Smrg int result = 0; 361d522f475Smrg#if OPT_NUM_LOCK 362d522f475Smrg if (param > UNMOD 363d522f475Smrg && ((ShiftMask 364d522f475Smrg | ControlMask 365d522f475Smrg | xw->misc.alt_mods 366d522f475Smrg | xw->misc.meta_mods) & xw->misc.other_mods) == 0) { 367d522f475Smrg if ((param - UNMOD) & SHIFT) 368d522f475Smrg result |= ShiftMask; 369d522f475Smrg if ((param - UNMOD) & CTRL) 370d522f475Smrg result |= ControlMask; 371d522f475Smrg if ((param - UNMOD) & ALT) 372d522f475Smrg result |= xw->misc.alt_mods; 373d522f475Smrg if ((param - UNMOD) & META) 374d522f475Smrg result |= xw->misc.meta_mods; 375d522f475Smrg } 376d522f475Smrg#else 377d522f475Smrg (void) xw; 378d522f475Smrg (void) param; 379d522f475Smrg#endif 380d522f475Smrg TRACE(("xtermParamToState(%d) %s%s%s%s -> %#x\n", param, 381d522f475Smrg MODIFIER_NAME(param, SHIFT), 382d522f475Smrg MODIFIER_NAME(param, ALT), 383d522f475Smrg MODIFIER_NAME(param, CTRL), 384d522f475Smrg MODIFIER_NAME(param, META), 385d522f475Smrg result)); 386d522f475Smrg return result; 387d522f475Smrg} 388d522f475Smrg 389d522f475Smrgint 390d522f475SmrgxtermStateToParam(XtermWidget xw, unsigned state) 391d522f475Smrg{ 392d522f475Smrg int modify_parm = UNMOD; 393d522f475Smrg 394d522f475Smrg#if OPT_NUM_LOCK 395d522f475Smrg if ((state & xw->misc.other_mods) == 0) { 396d522f475Smrg if (state & ShiftMask) { 397d522f475Smrg modify_parm += SHIFT; 398d522f475Smrg state &= ~ShiftMask; 399d522f475Smrg } 400d522f475Smrg if (state & ControlMask) { 401d522f475Smrg modify_parm += CTRL; 402d522f475Smrg state &= ~ControlMask; 403d522f475Smrg } 404d522f475Smrg if ((state & xw->misc.alt_mods) != 0) { 405d522f475Smrg modify_parm += ALT; 406d522f475Smrg state &= ~xw->misc.alt_mods; 407d522f475Smrg } 408d522f475Smrg if ((state & xw->misc.meta_mods) != 0) { 409d522f475Smrg modify_parm += META; 410d522f475Smrg state &= ~xw->misc.meta_mods; 411d522f475Smrg } 412d522f475Smrg } 413d522f475Smrg#else 414d522f475Smrg (void) xw; 415d522f475Smrg (void) state; 416d522f475Smrg#endif 417d522f475Smrg TRACE(("...xtermStateToParam %d%s%s%s%s\n", modify_parm, 418d522f475Smrg MODIFIER_NAME(modify_parm, SHIFT), 419d522f475Smrg MODIFIER_NAME(modify_parm, ALT), 420d522f475Smrg MODIFIER_NAME(modify_parm, CTRL), 421d522f475Smrg MODIFIER_NAME(modify_parm, META))); 422d522f475Smrg return modify_parm; 423d522f475Smrg} 424d522f475Smrg 425d522f475Smrg#define computeMaskedModifier(xw, state, mask) \ 426d522f475Smrg xtermStateToParam(xw, Masked(state, mask)) 427d522f475Smrg 428d522f475Smrg#if OPT_NUM_LOCK 429d522f475Smrgstatic unsigned 430d522f475SmrgfilterAltMeta(unsigned result, unsigned mask, Bool enable, KEY_DATA * kd) 431d522f475Smrg{ 432d522f475Smrg if ((result & mask) != 0) { 433d522f475Smrg /* 434d522f475Smrg * metaSendsEscape makes the meta key independent of 435d522f475Smrg * modifyOtherKeys. 436d522f475Smrg */ 437d522f475Smrg if (enable) { 438d522f475Smrg result &= ~mask; 439d522f475Smrg } 440d522f475Smrg /* 441d522f475Smrg * A bare meta-modifier is independent of modifyOtherKeys. If it 442d522f475Smrg * is combined with other modifiers, make it depend. 443d522f475Smrg */ 444d522f475Smrg if ((result & ~(mask)) == 0) { 445d522f475Smrg result &= ~mask; 446d522f475Smrg } 447d522f475Smrg /* 448d522f475Smrg * Check for special cases of control+meta which are used by some 449d522f475Smrg * applications, e.g., emacs. 450d522f475Smrg */ 451d522f475Smrg if ((IsControlInput(kd) 452d522f475Smrg || IsControlOutput(kd)) 453d522f475Smrg && (result & ControlMask) != 0) { 454d522f475Smrg result &= ~(mask | ControlMask); 455d522f475Smrg } 456d522f475Smrg if (kd->keysym == XK_Return || kd->keysym == XK_Tab) { 457d522f475Smrg result &= ~(mask | ControlMask); 458d522f475Smrg } 459d522f475Smrg } 460d522f475Smrg return result; 461d522f475Smrg} 462d522f475Smrg#endif /* OPT_NUM_LOCK */ 463d522f475Smrg 464d522f475Smrg/* 465d522f475Smrg * Single characters (not function-keys) are allowed fewer modifiers when 466d522f475Smrg * interpreting modifyOtherKeys due to pre-existing associations with some 467d522f475Smrg * modifiers. 468d522f475Smrg */ 469d522f475Smrgstatic unsigned 470d522f475SmrgallowedCharModifiers(XtermWidget xw, unsigned state, KEY_DATA * kd) 471d522f475Smrg{ 472d522f475Smrg#if OPT_NUM_LOCK 473d522f475Smrg unsigned a_or_m = (state & (xw->misc.meta_mods | xw->misc.alt_mods)); 474d522f475Smrg#else 475d522f475Smrg unsigned a_or_m = 0; 476d522f475Smrg#endif 477d522f475Smrg /* 478d522f475Smrg * Start by limiting the result to the modifiers we might want to use. 479d522f475Smrg */ 480d522f475Smrg unsigned result = (state & (ControlMask 481d522f475Smrg | ShiftMask 482d522f475Smrg | a_or_m)); 483d522f475Smrg 484d522f475Smrg /* 485d522f475Smrg * If modifyOtherKeys is off or medium (0 or 1), moderate its effects by 486d522f475Smrg * excluding the common cases for modifiers. 487d522f475Smrg */ 488d522f475Smrg if (xw->keyboard.modify_now.other_keys <= 1) { 489d522f475Smrg if (IsControlInput(kd) 490d522f475Smrg && Masked(result, ControlMask) == 0) { 491d522f475Smrg /* These keys are already associated with the control-key */ 492d522f475Smrg if (xw->keyboard.modify_now.other_keys == 0) { 493d522f475Smrg result &= ~ControlMask; 494d522f475Smrg } 495d522f475Smrg } else if (kd->keysym == XK_Tab || kd->keysym == XK_Return) { 496d522f475Smrg ; 497d522f475Smrg } else if (IsControlAlias(kd)) { 498d522f475Smrg /* Things like "^_" work here... */ 499d522f475Smrg if (Masked(result, (ControlMask | ShiftMask)) == 0) { 500d522f475Smrg result = 0; 501d522f475Smrg } 502d522f475Smrg } else if (!IsControlOutput(kd) && !IsPredefinedKey(kd->keysym)) { 503d522f475Smrg /* Printable keys are already associated with the shift-key */ 504d522f475Smrg if (!(result & ControlMask)) { 505d522f475Smrg result &= ~ShiftMask; 506d522f475Smrg } 507d522f475Smrg } 508d522f475Smrg#if OPT_NUM_LOCK 509d522f475Smrg result = filterAltMeta(result, 510d522f475Smrg xw->misc.meta_mods, 511d522f475Smrg xw->screen.meta_sends_esc, kd); 512d522f475Smrg if (xw->screen.alt_is_not_meta) { 513d522f475Smrg result = filterAltMeta(result, 514d522f475Smrg xw->misc.alt_mods, 515d522f475Smrg xw->screen.alt_sends_esc, kd); 516d522f475Smrg } 517d522f475Smrg#endif 518d522f475Smrg } 519d522f475Smrg TRACE(("...allowedCharModifiers(state=%u" FMT_MODIFIER_NAMES 520d522f475Smrg ", ch=" KEYSYM_FMT ") ->" 521d522f475Smrg "%u" FMT_MODIFIER_NAMES "\n", 522d522f475Smrg state, ARG_MODIFIER_NAMES(state), kd->keysym, 523d522f475Smrg result, ARG_MODIFIER_NAMES(result))); 524d522f475Smrg return result; 525d522f475Smrg} 526d522f475Smrg 527d522f475Smrg/* 528d522f475Smrg * Decide if we should generate a special escape sequence for "other" keys 529d522f475Smrg * than cursor-, function-keys, etc., as per the modifyOtherKeys resource. 530d522f475Smrg */ 531d522f475Smrgstatic Bool 532d522f475SmrgModifyOtherKeys(XtermWidget xw, 533d522f475Smrg unsigned state, 534d522f475Smrg KEY_DATA * kd, 535d522f475Smrg int modify_parm) 536d522f475Smrg{ 537d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 538d522f475Smrg Bool result = False; 539d522f475Smrg 540d522f475Smrg /* 541d522f475Smrg * Exclude the keys already covered by a modifier. 542d522f475Smrg */ 543d522f475Smrg if (kd->is_fkey 544d522f475Smrg || IsEditFunctionKey(kd->keysym) 545d522f475Smrg || IsKeypadKey(kd->keysym) 546d522f475Smrg || IsCursorKey(kd->keysym) 547d522f475Smrg || IsPFKey(kd->keysym) 548d522f475Smrg || IsMiscFunctionKey(kd->keysym) 549d522f475Smrg || IsPrivateKeypadKey(kd->keysym) 550d522f475Smrg#if OPT_NUM_LOCK 551d522f475Smrg || (state & xw->misc.other_mods) != 0 552d522f475Smrg#endif 553d522f475Smrg ) { 554d522f475Smrg result = False; 555d522f475Smrg } else if (modify_parm != 0) { 556d522f475Smrg if (IsBackarrowToggle(keyboard, kd->keysym, state)) { 557d522f475Smrg kd->keysym = XK_Delete; 558d522f475Smrg state &= ~ControlMask; 559d522f475Smrg } 560d522f475Smrg if (!IsPredefinedKey(kd->keysym)) { 561d522f475Smrg state = allowedCharModifiers(xw, state, kd); 562d522f475Smrg } 563d522f475Smrg if (state != 0) { 564d522f475Smrg switch (keyboard->modify_now.other_keys) { 565d522f475Smrg default: 566d522f475Smrg break; 567d522f475Smrg case 1: 568d522f475Smrg switch (kd->keysym) { 569d522f475Smrg case XK_BackSpace: 570d522f475Smrg case XK_Delete: 571d522f475Smrg result = False; 572d522f475Smrg break; 573d522f475Smrg#ifdef XK_ISO_Left_Tab 574d522f475Smrg case XK_ISO_Left_Tab: 575d522f475Smrg if (computeMaskedModifier(xw, state, ShiftMask) > 1) 576d522f475Smrg result = True; 577d522f475Smrg break; 578d522f475Smrg#endif 579d522f475Smrg case XK_Return: 580d522f475Smrg case XK_Tab: 581d522f475Smrg result = (modify_parm > 1); 582d522f475Smrg break; 583d522f475Smrg default: 584d522f475Smrg if (IsControlInput(kd)) { 585d522f475Smrg if (state == ControlMask || state == ShiftMask) { 586d522f475Smrg result = False; 587d522f475Smrg } else { 588d522f475Smrg result = (modify_parm > 1); 589d522f475Smrg } 590d522f475Smrg } else if (IsControlAlias(kd)) { 591d522f475Smrg if (state == ShiftMask) 592d522f475Smrg result = False; 593d522f475Smrg else if (computeMaskedModifier(xw, state, ControlMask) 594d522f475Smrg > 1) { 595d522f475Smrg result = True; 596d522f475Smrg } 597d522f475Smrg } else { 598d522f475Smrg result = True; 599d522f475Smrg } 600d522f475Smrg break; 601d522f475Smrg } 602d522f475Smrg break; 603d522f475Smrg case 2: 604d522f475Smrg switch (kd->keysym) { 605d522f475Smrg case XK_BackSpace: 606d522f475Smrg /* strip ControlMask as per IsBackarrowToggle() */ 607d522f475Smrg if (computeMaskedModifier(xw, state, ControlMask) > 1) 608d522f475Smrg result = True; 609d522f475Smrg break; 610d522f475Smrg case XK_Delete: 611d522f475Smrg result = (xtermStateToParam(xw, state) > 1); 612d522f475Smrg break; 613d522f475Smrg#ifdef XK_ISO_Left_Tab 614d522f475Smrg case XK_ISO_Left_Tab: 615d522f475Smrg if (computeMaskedModifier(xw, state, ShiftMask) > 1) 616d522f475Smrg result = True; 617d522f475Smrg break; 618d522f475Smrg#endif 619d522f475Smrg case XK_Return: 620d522f475Smrg case XK_Tab: 621d522f475Smrg result = (modify_parm > 1); 622d522f475Smrg break; 623d522f475Smrg default: 624d522f475Smrg if (IsControlInput(kd)) { 625d522f475Smrg result = True; 626d522f475Smrg } else if (state == ShiftMask) { 627d522f475Smrg result = (kd->keysym == ' ' || kd->keysym == XK_Return); 628d522f475Smrg } else if (computeMaskedModifier(xw, state, ShiftMask) > 1) { 629d522f475Smrg result = True; 630d522f475Smrg } 631d522f475Smrg break; 632d522f475Smrg } 633d522f475Smrg break; 634d522f475Smrg } 635d522f475Smrg } 636d522f475Smrg } 637d522f475Smrg TRACE(("...ModifyOtherKeys(%d,%d) %s\n", 638d522f475Smrg keyboard->modify_now.other_keys, 639d522f475Smrg modify_parm, 640d522f475Smrg BtoS(result))); 641d522f475Smrg return result; 642d522f475Smrg} 643d522f475Smrg 644d522f475Smrg#define APPEND_PARM(number) \ 645d522f475Smrg reply->a_param[(int) reply->a_nparam] = number, \ 646d522f475Smrg reply->a_nparam += 1 647d522f475Smrg 648d522f475Smrg/* 649d522f475Smrg * Function-key code 27 happens to not be used in the vt220-style encoding. 650d522f475Smrg * xterm uses this to represent modified non-function-keys such as control/+ in 651d522f475Smrg * the Sun/PC keyboard layout. See the modifyOtherKeys resource in the manpage 652d522f475Smrg * for more information. 653d522f475Smrg */ 654d522f475Smrgstatic Bool 655d522f475SmrgmodifyOtherKey(ANSI * reply, int input_char, int modify_parm, int format_keys) 656d522f475Smrg{ 657d522f475Smrg Bool result = False; 658d522f475Smrg 659d522f475Smrg if (input_char >= 0) { 660d522f475Smrg reply->a_type = ANSI_CSI; 661d522f475Smrg if (format_keys) { 662d522f475Smrg APPEND_PARM(input_char); 663d522f475Smrg APPEND_PARM(modify_parm); 664d522f475Smrg reply->a_final = 'u'; 665d522f475Smrg } else { 666d522f475Smrg APPEND_PARM(27); 667d522f475Smrg APPEND_PARM(modify_parm); 668d522f475Smrg APPEND_PARM(input_char); 669d522f475Smrg reply->a_final = '~'; 670d522f475Smrg } 671d522f475Smrg 672d522f475Smrg result = True; 673d522f475Smrg } 674d522f475Smrg return result; 675d522f475Smrg} 676d522f475Smrg 677d522f475Smrgstatic void 678d522f475SmrgmodifyCursorKey(ANSI * reply, int modify, int *modify_parm) 679d522f475Smrg{ 680d522f475Smrg if (*modify_parm > 1) { 681d522f475Smrg if (modify < 0) { 682d522f475Smrg *modify_parm = 0; 683d522f475Smrg } 684d522f475Smrg if (modify > 0) { 685d522f475Smrg reply->a_type = ANSI_CSI; /* SS3 should not have params */ 686d522f475Smrg } 687d522f475Smrg if (modify > 1 && reply->a_nparam == 0) { 688d522f475Smrg APPEND_PARM(1); /* force modifier to 2nd param */ 689d522f475Smrg } 690d522f475Smrg if (modify > 2) { 691d522f475Smrg reply->a_pintro = '>'; /* mark this as "private" */ 692d522f475Smrg } 693d522f475Smrg } 694d522f475Smrg} 695d522f475Smrg#else 696d522f475Smrg#define modifyCursorKey(reply, modify, parm) /* nothing */ 697d522f475Smrg#endif /* OPT_MOD_FKEYS */ 698d522f475Smrg 699d522f475Smrg#if OPT_SUNPC_KBD 700d522f475Smrg/* 701d522f475Smrg * If we have told xterm that our keyboard is really a Sun/PC keyboard, this is 702d522f475Smrg * enough to make a reasonable approximation to DEC vt220 numeric and editing 703d522f475Smrg * keypads. 704d522f475Smrg */ 705d522f475Smrgstatic KeySym 706d522f475SmrgTranslateFromSUNPC(KeySym keysym) 707d522f475Smrg{ 708d522f475Smrg /* *INDENT-OFF* */ 709d522f475Smrg static struct { 710d522f475Smrg KeySym before, after; 711d522f475Smrg } table[] = { 712d522f475Smrg#ifdef DXK_Remove 713d522f475Smrg { XK_Delete, DXK_Remove }, 714d522f475Smrg#endif 715d522f475Smrg { XK_Home, XK_Find }, 716d522f475Smrg { XK_End, XK_Select }, 717d522f475Smrg#ifdef XK_KP_Home 718d522f475Smrg { XK_Delete, XK_KP_Decimal }, 719d522f475Smrg { XK_KP_Delete, XK_KP_Decimal }, 720d522f475Smrg { XK_KP_Insert, XK_KP_0 }, 721d522f475Smrg { XK_KP_End, XK_KP_1 }, 722d522f475Smrg { XK_KP_Down, XK_KP_2 }, 723d522f475Smrg { XK_KP_Next, XK_KP_3 }, 724d522f475Smrg { XK_KP_Left, XK_KP_4 }, 725d522f475Smrg { XK_KP_Begin, XK_KP_5 }, 726d522f475Smrg { XK_KP_Right, XK_KP_6 }, 727d522f475Smrg { XK_KP_Home, XK_KP_7 }, 728d522f475Smrg { XK_KP_Up, XK_KP_8 }, 729d522f475Smrg { XK_KP_Prior, XK_KP_9 }, 730d522f475Smrg#endif 731d522f475Smrg }; 732d522f475Smrg /* *INDENT-ON* */ 733d522f475Smrg 734d522f475Smrg unsigned n; 735d522f475Smrg 736d522f475Smrg for (n = 0; n < sizeof(table) / sizeof(table[0]); n++) { 737d522f475Smrg if (table[n].before == keysym) { 738d522f475Smrg TRACE(("...Input keypad before was " KEYSYM_FMT "\n", keysym)); 739d522f475Smrg keysym = table[n].after; 740d522f475Smrg TRACE(("...Input keypad changed to " KEYSYM_FMT "\n", keysym)); 741d522f475Smrg break; 742d522f475Smrg } 743d522f475Smrg } 744d522f475Smrg return keysym; 745d522f475Smrg} 746d522f475Smrg#endif /* OPT_SUNPC_KBD */ 747d522f475Smrg 748d522f475Smrg#define VT52_KEYPAD \ 749d522f475Smrg if_OPT_VT52_MODE(screen,{ \ 750d522f475Smrg reply.a_type = ANSI_ESC; \ 751d522f475Smrg reply.a_pintro = '?'; \ 752d522f475Smrg }) 753d522f475Smrg 754d522f475Smrg#define VT52_CURSOR_KEYS \ 755d522f475Smrg if_OPT_VT52_MODE(screen,{ \ 756d522f475Smrg reply.a_type = ANSI_ESC; \ 757d522f475Smrg }) 758d522f475Smrg 759d522f475Smrg#undef APPEND_PARM 760d522f475Smrg#define APPEND_PARM(number) \ 761d522f475Smrg reply.a_param[(int) reply.a_nparam] = number, \ 762d522f475Smrg reply.a_nparam += 1 763d522f475Smrg 764d522f475Smrg#if OPT_MOD_FKEYS 765d522f475Smrg#define MODIFIER_PARM \ 766d522f475Smrg if (modify_parm > 1) APPEND_PARM(modify_parm) 767d522f475Smrg#else 768d522f475Smrg#define MODIFIER_PARM /*nothing */ 769d522f475Smrg#endif 770d522f475Smrg 771d522f475Smrg/* 772d522f475Smrg * Determine if we use the \E[3~ sequence for Delete, or the legacy ^?. We 773d522f475Smrg * maintain the delete_is_del value as 3 states: unspecified(2), true and 774d522f475Smrg * false. If unspecified, it is handled differently according to whether the 775d522f475Smrg * legacy keyboard support is enabled, or if xterm emulates a VT220. 776d522f475Smrg * 777d522f475Smrg * Once the user (or application) has specified delete_is_del via resource 778d522f475Smrg * setting, popup menu or escape sequence, it overrides the keyboard type 779d522f475Smrg * rather than the reverse. 780d522f475Smrg */ 781d522f475SmrgBool 782d522f475SmrgxtermDeleteIsDEL(XtermWidget xw) 783d522f475Smrg{ 784d522f475Smrg Bool result = True; 785d522f475Smrg 786d522f475Smrg if (xw->keyboard.type == keyboardIsDefault 787d522f475Smrg || xw->keyboard.type == keyboardIsVT220) 788d522f475Smrg result = (xw->screen.delete_is_del == True); 789d522f475Smrg 790d522f475Smrg if (xw->keyboard.type == keyboardIsLegacy) 791d522f475Smrg result = (xw->screen.delete_is_del != False); 792d522f475Smrg 793d522f475Smrg TRACE(("xtermDeleteIsDEL(%d/%d) = %d\n", 794d522f475Smrg xw->keyboard.type, 795d522f475Smrg xw->screen.delete_is_del, 796d522f475Smrg result)); 797d522f475Smrg 798d522f475Smrg return result; 799d522f475Smrg} 800d522f475Smrg 801d522f475Smrgvoid 802d522f475SmrgInput(XtermWidget xw, 803d522f475Smrg XKeyEvent * event, 804d522f475Smrg Bool eightbit) 805d522f475Smrg{ 806d522f475Smrg Char *string; 807d522f475Smrg 808d522f475Smrg TKeyboard *keyboard = &(xw->keyboard); 809d522f475Smrg TScreen *screen = &(xw->screen); 810d522f475Smrg 811d522f475Smrg int j; 812d522f475Smrg int key = False; 813d522f475Smrg ANSI reply; 814d522f475Smrg int dec_code; 815d522f475Smrg int modify_parm = 0; 816d522f475Smrg int keypad_mode = ((keyboard->flags & MODE_DECKPAM) != 0); 817d522f475Smrg unsigned evt_state = event->state; 818d522f475Smrg unsigned mod_state; 819d522f475Smrg KEY_DATA kd; 820d522f475Smrg 821d522f475Smrg /* Ignore characters typed at the keyboard */ 822d522f475Smrg if (keyboard->flags & MODE_KAM) 823d522f475Smrg return; 824d522f475Smrg 825d522f475Smrg kd.keysym = 0; 826d522f475Smrg kd.is_fkey = False; 827d522f475Smrg#if OPT_TCAP_QUERY 828d522f475Smrg if (screen->tc_query_code >= 0) { 8292eaa94a1Schristos kd.keysym = (KeySym) screen->tc_query_code; 830d522f475Smrg kd.is_fkey = screen->tc_query_fkey; 831d522f475Smrg if (kd.keysym != XK_BackSpace) { 832d522f475Smrg kd.nbytes = 0; 833d522f475Smrg kd.strbuf[0] = 0; 834d522f475Smrg } else { 835d522f475Smrg kd.nbytes = 1; 836d522f475Smrg kd.strbuf[0] = 8; 837d522f475Smrg } 838d522f475Smrg } else 839d522f475Smrg#endif 840d522f475Smrg { 841d522f475Smrg#if OPT_I18N_SUPPORT 842d522f475Smrg if (screen->xic) { 843d522f475Smrg Status status_return; 844d522f475Smrg#if OPT_WIDE_CHARS 845d522f475Smrg if (screen->utf8_mode) { 846d522f475Smrg kd.nbytes = Xutf8LookupString(screen->xic, event, 847d522f475Smrg kd.strbuf, sizeof(kd.strbuf), 848d522f475Smrg &kd.keysym, &status_return); 849d522f475Smrg } else 850d522f475Smrg#endif 851d522f475Smrg { 852d522f475Smrg kd.nbytes = XmbLookupString(screen->xic, event, 853d522f475Smrg kd.strbuf, sizeof(kd.strbuf), 854d522f475Smrg &kd.keysym, &status_return); 855d522f475Smrg } 856d522f475Smrg#if OPT_MOD_FKEYS 857d522f475Smrg /* 858d522f475Smrg * Fill-in some code useful with IsControlAlias(): 859d522f475Smrg */ 860d522f475Smrg if (status_return == XLookupBoth 861d522f475Smrg && kd.nbytes <= 1 862d522f475Smrg && !IsPredefinedKey(kd.keysym) 863d522f475Smrg && (keyboard->modify_now.other_keys > 1) 864d522f475Smrg && !IsControlInput(&kd)) { 865d522f475Smrg kd.nbytes = 1; 8662eaa94a1Schristos kd.strbuf[0] = (char) kd.keysym; 867d522f475Smrg } 868d522f475Smrg#endif /* OPT_MOD_FKEYS */ 869d522f475Smrg } else 870d522f475Smrg#endif /* OPT_I18N_SUPPORT */ 871d522f475Smrg { 872d522f475Smrg static XComposeStatus compose_status = 873d522f475Smrg {NULL, 0}; 874d522f475Smrg kd.nbytes = XLookupString(event, kd.strbuf, sizeof(kd.strbuf), 875d522f475Smrg &kd.keysym, &compose_status); 876d522f475Smrg } 877d522f475Smrg kd.is_fkey = IsFunctionKey(kd.keysym); 878d522f475Smrg } 879d522f475Smrg 880d522f475Smrg memset(&reply, 0, sizeof(reply)); 881d522f475Smrg 882d522f475Smrg TRACE(("Input keysym " 883d522f475Smrg KEYSYM_FMT 884d522f475Smrg ", %d:'%s'%s" FMT_MODIFIER_NAMES "%s%s%s%s%s%s\n", 885d522f475Smrg kd.keysym, 886d522f475Smrg kd.nbytes, 887d522f475Smrg visibleChars(PAIRED_CHARS((Char *) kd.strbuf, 0), 888d522f475Smrg ((kd.nbytes > 0) 889d522f475Smrg ? (unsigned) kd.nbytes 890d522f475Smrg : 0)), 891d522f475Smrg ARG_MODIFIER_NAMES(evt_state), 892d522f475Smrg eightbit ? " 8bit" : " 7bit", 893d522f475Smrg IsKeypadKey(kd.keysym) ? " KeypadKey" : "", 894d522f475Smrg IsCursorKey(kd.keysym) ? " CursorKey" : "", 895d522f475Smrg IsPFKey(kd.keysym) ? " PFKey" : "", 896d522f475Smrg kd.is_fkey ? " FKey" : "", 897d522f475Smrg IsMiscFunctionKey(kd.keysym) ? " MiscFKey" : "", 898d522f475Smrg IsEditFunctionKey(kd.keysym) ? " EditFkey" : "")); 899d522f475Smrg 900d522f475Smrg#if OPT_SUNPC_KBD 901d522f475Smrg /* 902d522f475Smrg * DEC keyboards don't have keypad(+), but do have keypad(,) instead. 903d522f475Smrg * Other (Sun, PC) keyboards commonly have keypad(+), but no keypad(,) 904d522f475Smrg * - it's a pain for users to work around. 905d522f475Smrg */ 906d522f475Smrg if (keyboard->type == keyboardIsVT220 907d522f475Smrg && (evt_state & ShiftMask) == 0) { 908d522f475Smrg if (kd.keysym == XK_KP_Add) { 909d522f475Smrg kd.keysym = XK_KP_Separator; 910d522f475Smrg evt_state &= ~ShiftMask; 911d522f475Smrg TRACE(("...Input keypad(+), change keysym to " 912d522f475Smrg KEYSYM_FMT 913d522f475Smrg "\n", 914d522f475Smrg kd.keysym)); 915d522f475Smrg } 916d522f475Smrg if ((evt_state & ControlMask) != 0 917d522f475Smrg && kd.keysym == XK_KP_Separator) { 918d522f475Smrg kd.keysym = XK_KP_Subtract; 919d522f475Smrg evt_state &= ~ControlMask; 920d522f475Smrg TRACE(("...Input control/keypad(,), change keysym to " 921d522f475Smrg KEYSYM_FMT 922d522f475Smrg "\n", 923d522f475Smrg kd.keysym)); 924d522f475Smrg } 925d522f475Smrg } 926d522f475Smrg#endif 927d522f475Smrg 928d522f475Smrg /* 929d522f475Smrg * The keyboard tables may give us different keypad codes according to 930d522f475Smrg * whether NumLock is pressed. Use this check to simplify the process 931d522f475Smrg * of determining whether we generate an escape sequence for a keypad 932d522f475Smrg * key, or force it to the value kypd_num[]. There is no fixed 933d522f475Smrg * modifier for this feature, so we assume that it is the one assigned 934d522f475Smrg * to the NumLock key. 935d522f475Smrg * 936d522f475Smrg * This check used to try to return the contents of strbuf, but that 937d522f475Smrg * does not work properly when a control modifier is given (trash is 938d522f475Smrg * returned in the buffer in some cases -- perhaps an X bug). 939d522f475Smrg */ 940d522f475Smrg#if OPT_NUM_LOCK 941d522f475Smrg if (kd.nbytes == 1 942d522f475Smrg && IsKeypadKey(kd.keysym) 943d522f475Smrg && xw->misc.real_NumLock 944d522f475Smrg && (xw->misc.num_lock & evt_state) != 0) { 945d522f475Smrg keypad_mode = 0; 946d522f475Smrg TRACE(("...Input num_lock, force keypad_mode off\n")); 947d522f475Smrg } 948d522f475Smrg#endif 949d522f475Smrg 950d522f475Smrg#if OPT_MOD_FKEYS 951d522f475Smrg if (evt_state != 0 952d522f475Smrg && allowModifierParm(xw, &kd)) { 953d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 954d522f475Smrg } 955d522f475Smrg 956d522f475Smrg /* 957d522f475Smrg * Shift-tab is often mapped to XK_ISO_Left_Tab which is classified as 958d522f475Smrg * IsEditFunctionKey(), and the conversion does not produce any bytes. 959d522f475Smrg * Check for this special case so we have data when handling the 960d522f475Smrg * modifyOtherKeys resource. 961d522f475Smrg */ 962d522f475Smrg if (keyboard->modify_now.other_keys > 1) { 963d522f475Smrg if (IsTabKey(kd.keysym) && kd.nbytes == 0) { 964d522f475Smrg kd.nbytes = 1; 965d522f475Smrg kd.strbuf[0] = '\t'; 966d522f475Smrg } 967d522f475Smrg } 968d522f475Smrg#endif /* OPT_MOD_FKEYS */ 969d522f475Smrg 970d522f475Smrg /* VT300 & up: backarrow toggle */ 971d522f475Smrg if ((kd.nbytes == 1) 972d522f475Smrg && IsBackarrowToggle(keyboard, kd.keysym, evt_state)) { 973d522f475Smrg kd.strbuf[0] = ANSI_DEL; 974d522f475Smrg TRACE(("...Input backarrow changed to %d\n", kd.strbuf[0])); 975d522f475Smrg } 976d522f475Smrg#if OPT_SUNPC_KBD 977d522f475Smrg /* make an DEC editing-keypad from a Sun or PC editing-keypad */ 978d522f475Smrg if (keyboard->type == keyboardIsVT220 979d522f475Smrg && (kd.keysym != XK_Delete || !xtermDeleteIsDEL(xw))) 980d522f475Smrg kd.keysym = TranslateFromSUNPC(kd.keysym); 981d522f475Smrg else 982d522f475Smrg#endif 983d522f475Smrg { 984d522f475Smrg#ifdef XK_KP_Home 985d522f475Smrg if (kd.keysym >= XK_KP_Home && kd.keysym <= XK_KP_Begin) { 986d522f475Smrg TRACE(("...Input keypad before was " KEYSYM_FMT "\n", kd.keysym)); 9872eaa94a1Schristos kd.keysym += (unsigned) (XK_Home - XK_KP_Home); 988d522f475Smrg TRACE(("...Input keypad changed to " KEYSYM_FMT "\n", kd.keysym)); 989d522f475Smrg } 990d522f475Smrg#endif 991d522f475Smrg } 992d522f475Smrg 993d522f475Smrg /* 994d522f475Smrg * Map the Sun afterthought-keys in as F36 and F37. 995d522f475Smrg */ 996d522f475Smrg#ifdef SunXK_F36 997d522f475Smrg if (!kd.is_fkey) { 998d522f475Smrg if (kd.keysym == SunXK_F36) { 999d522f475Smrg kd.keysym = XK_Fn(36); 1000d522f475Smrg kd.is_fkey = True; 1001d522f475Smrg } 1002d522f475Smrg if (kd.keysym == SunXK_F37) { 1003d522f475Smrg kd.keysym = XK_Fn(37); 1004d522f475Smrg kd.is_fkey = True; 1005d522f475Smrg } 1006d522f475Smrg } 1007d522f475Smrg#endif 1008d522f475Smrg 1009d522f475Smrg /* 1010d522f475Smrg * Use the control- and shift-modifiers to obtain more function keys than 1011d522f475Smrg * the keyboard provides. We can do this if there is no conflicting use of 1012d522f475Smrg * those modifiers: 1013d522f475Smrg * 1014d522f475Smrg * a) for VT220 keyboard, we use only the control-modifier. The keyboard 1015d522f475Smrg * uses shift-modifier for UDK's. 1016d522f475Smrg * 1017d522f475Smrg * b) for non-VT220 keyboards, we only have to check if the 1018d522f475Smrg * modifyFunctionKeys resource is inactive. 1019d522f475Smrg * 1020d522f475Smrg * Thereafter, we note when we have a function-key and keep that 1021d522f475Smrg * distinction when testing for "function-key" values. 1022d522f475Smrg */ 1023d522f475Smrg if ((evt_state & (ControlMask | ShiftMask)) != 0 1024d522f475Smrg && kd.is_fkey) { 1025d522f475Smrg 1026d522f475Smrg /* VT220 keyboard uses shift for UDK */ 1027d522f475Smrg if (keyboard->type == keyboardIsVT220 1028d522f475Smrg || keyboard->type == keyboardIsLegacy) { 1029d522f475Smrg 1030d522f475Smrg TRACE(("...map XK_F%ld", kd.keysym - XK_Fn(1) + 1)); 1031d522f475Smrg if (evt_state & ControlMask) { 10322eaa94a1Schristos kd.keysym += (KeySym) xw->misc.ctrl_fkeys; 1033d522f475Smrg evt_state &= ~ControlMask; 1034d522f475Smrg } 1035d522f475Smrg TRACE((" to XK_F%ld\n", kd.keysym - XK_Fn(1) + 1)); 1036d522f475Smrg 1037d522f475Smrg } 1038d522f475Smrg#if OPT_MOD_FKEYS 1039d522f475Smrg else if (keyboard->modify_now.function_keys < 0) { 1040d522f475Smrg 1041d522f475Smrg TRACE(("...map XK_F%ld", kd.keysym - XK_Fn(1) + 1)); 1042d522f475Smrg if (evt_state & ShiftMask) { 10432eaa94a1Schristos kd.keysym += (KeySym) (xw->misc.ctrl_fkeys * 1); 1044d522f475Smrg evt_state &= ~ShiftMask; 1045d522f475Smrg } 1046d522f475Smrg if (evt_state & ControlMask) { 10472eaa94a1Schristos kd.keysym += (KeySym) (xw->misc.ctrl_fkeys * 2); 1048d522f475Smrg evt_state &= ~ControlMask; 1049d522f475Smrg } 1050d522f475Smrg TRACE((" to XK_F%ld\n", kd.keysym - XK_Fn(1) + 1)); 1051d522f475Smrg 1052d522f475Smrg } 1053d522f475Smrg /* 1054d522f475Smrg * Reevaluate the modifier parameter, stripping off the modifiers 1055d522f475Smrg * that we just used. 1056d522f475Smrg */ 1057d522f475Smrg if (modify_parm) 1058d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 1059d522f475Smrg#endif /* OPT_MOD_FKEYS */ 1060d522f475Smrg } 1061d522f475Smrg 1062d522f475Smrg /* 1063d522f475Smrg * Test for one of the keyboard variants. 1064d522f475Smrg */ 1065d522f475Smrg switch (keyboard->type) { 1066d522f475Smrg case keyboardIsHP: 1067d522f475Smrg hpfuncvalue(&reply, &kd); 1068d522f475Smrg break; 1069d522f475Smrg case keyboardIsSCO: 1070d522f475Smrg scofuncvalue(&reply, &kd); 1071d522f475Smrg break; 1072d522f475Smrg case keyboardIsSun: 1073d522f475Smrg sunfuncvalue(&reply, &kd); 1074d522f475Smrg break; 1075d522f475Smrg case keyboardIsTermcap: 1076d522f475Smrg#if OPT_TCAP_FKEYS 1077d522f475Smrg if (xtermcapString(xw, (int) kd.keysym, evt_state)) 1078d522f475Smrg return; 1079d522f475Smrg#endif 1080d522f475Smrg break; 1081d522f475Smrg case keyboardIsDefault: 1082d522f475Smrg case keyboardIsLegacy: 1083d522f475Smrg case keyboardIsVT220: 1084d522f475Smrg break; 1085d522f475Smrg } 1086d522f475Smrg 1087d522f475Smrg if (reply.a_final) { 1088d522f475Smrg /* 1089d522f475Smrg * The key symbol matches one of the variants. Most of those are 1090d522f475Smrg * function-keys, though some cursor- and editing-keys are mixed in. 1091d522f475Smrg */ 1092d522f475Smrg modifyCursorKey(&reply, 1093d522f475Smrg ((kd.is_fkey 1094d522f475Smrg || IsMiscFunctionKey(kd.keysym) 1095d522f475Smrg || IsEditFunctionKey(kd.keysym)) 1096d522f475Smrg ? keyboard->modify_now.function_keys 1097d522f475Smrg : keyboard->modify_now.cursor_keys), 1098d522f475Smrg &modify_parm); 1099d522f475Smrg MODIFIER_PARM; 1100d522f475Smrg unparseseq(xw, &reply); 1101d522f475Smrg } else if (((kd.is_fkey 1102d522f475Smrg || IsMiscFunctionKey(kd.keysym) 1103d522f475Smrg || IsEditFunctionKey(kd.keysym)) 1104d522f475Smrg#if OPT_MOD_FKEYS 1105d522f475Smrg && !ModifyOtherKeys(xw, evt_state, &kd, modify_parm) 1106d522f475Smrg#endif 1107d522f475Smrg ) || (kd.keysym == XK_Delete 1108d522f475Smrg && ((modify_parm > 1) 1109d522f475Smrg || !xtermDeleteIsDEL(xw)))) { 1110d522f475Smrg dec_code = decfuncvalue(&kd); 1111d522f475Smrg if ((evt_state & ShiftMask) 1112d522f475Smrg#if OPT_SUNPC_KBD 1113d522f475Smrg && keyboard->type == keyboardIsVT220 1114d522f475Smrg#endif 1115d522f475Smrg && ((string = (Char *) udk_lookup(dec_code, &kd.nbytes)) != 0)) { 1116d522f475Smrg evt_state &= ~ShiftMask; 1117d522f475Smrg while (kd.nbytes-- > 0) 1118d522f475Smrg unparseputc(xw, CharOf(*string++)); 1119d522f475Smrg } 1120d522f475Smrg#if OPT_VT52_MODE 1121d522f475Smrg /* 1122d522f475Smrg * Interpret F1-F4 as PF1-PF4 for VT52, VT100 1123d522f475Smrg */ 1124d522f475Smrg else if (keyboard->type != keyboardIsLegacy 1125d522f475Smrg && (dec_code >= 11 && dec_code <= 14)) { 1126d522f475Smrg reply.a_type = ANSI_SS3; 1127d522f475Smrg VT52_CURSOR_KEYS; 11282eaa94a1Schristos reply.a_final = (Char) A2E(dec_code - 11 + E2A('P')); 1129d522f475Smrg modifyCursorKey(&reply, 1130d522f475Smrg keyboard->modify_now.function_keys, 1131d522f475Smrg &modify_parm); 1132d522f475Smrg MODIFIER_PARM; 1133d522f475Smrg unparseseq(xw, &reply); 1134d522f475Smrg } 1135d522f475Smrg#endif 1136d522f475Smrg else { 1137d522f475Smrg reply.a_type = ANSI_CSI; 1138d522f475Smrg reply.a_final = 0; 1139d522f475Smrg 1140d522f475Smrg#ifdef XK_ISO_Left_Tab 1141d522f475Smrg if (kd.keysym == XK_ISO_Left_Tab) { 1142d522f475Smrg reply.a_nparam = 0; 1143d522f475Smrg reply.a_final = 'Z'; 1144d522f475Smrg#if OPT_MOD_FKEYS 1145d522f475Smrg if (keyboard->modify_now.other_keys > 1 1146d522f475Smrg && computeMaskedModifier(xw, evt_state, ShiftMask) > 1) 1147d522f475Smrg modifyOtherKey(&reply, '\t', modify_parm, keyboard->format_keys); 1148d522f475Smrg#endif 1149d522f475Smrg } else 1150d522f475Smrg#endif /* XK_ISO_Left_Tab */ 1151d522f475Smrg { 1152d522f475Smrg reply.a_nparam = 1; 1153d522f475Smrg#if OPT_MOD_FKEYS 1154d522f475Smrg if (kd.is_fkey) { 1155d522f475Smrg modifyCursorKey(&reply, 1156d522f475Smrg keyboard->modify_now.function_keys, 1157d522f475Smrg &modify_parm); 1158d522f475Smrg } 1159d522f475Smrg MODIFIER_PARM; 1160d522f475Smrg#endif 1161d522f475Smrg reply.a_param[0] = dec_code; 1162d522f475Smrg reply.a_final = '~'; 1163d522f475Smrg } 1164d522f475Smrg if (reply.a_final != 0 1165d522f475Smrg && (reply.a_nparam == 0 || reply.a_param[0] >= 0)) 1166d522f475Smrg unparseseq(xw, &reply); 1167d522f475Smrg } 1168d522f475Smrg key = True; 1169d522f475Smrg } else if (IsPFKey(kd.keysym)) { 1170d522f475Smrg reply.a_type = ANSI_SS3; 11712eaa94a1Schristos reply.a_final = (Char) ((kd.keysym - XK_KP_F1) + 'P'); 1172d522f475Smrg VT52_CURSOR_KEYS; 1173d522f475Smrg MODIFIER_PARM; 1174d522f475Smrg unparseseq(xw, &reply); 1175d522f475Smrg key = True; 1176d522f475Smrg } else if (IsKeypadKey(kd.keysym)) { 1177d522f475Smrg if (keypad_mode) { 1178d522f475Smrg reply.a_type = ANSI_SS3; 11792eaa94a1Schristos reply.a_final = (Char) (kypd_apl[kd.keysym - XK_KP_Space]); 1180d522f475Smrg VT52_KEYPAD; 1181d522f475Smrg MODIFIER_PARM; 1182d522f475Smrg unparseseq(xw, &reply); 1183d522f475Smrg } else { 1184d522f475Smrg unparseputc(xw, kypd_num[kd.keysym - XK_KP_Space]); 1185d522f475Smrg } 1186d522f475Smrg key = True; 1187d522f475Smrg } else if (IsCursorKey(kd.keysym)) { 1188d522f475Smrg if (keyboard->flags & MODE_DECCKM) { 1189d522f475Smrg reply.a_type = ANSI_SS3; 1190d522f475Smrg } else { 1191d522f475Smrg reply.a_type = ANSI_CSI; 1192d522f475Smrg } 1193d522f475Smrg modifyCursorKey(&reply, keyboard->modify_now.cursor_keys, &modify_parm); 11942eaa94a1Schristos reply.a_final = (Char) (curfinal[kd.keysym - XK_Home]); 1195d522f475Smrg VT52_CURSOR_KEYS; 1196d522f475Smrg MODIFIER_PARM; 1197d522f475Smrg unparseseq(xw, &reply); 1198d522f475Smrg key = True; 1199d522f475Smrg } else if (kd.nbytes > 0) { 1200d522f475Smrg int prefix = 0; 1201d522f475Smrg 1202d522f475Smrg#if OPT_TEK4014 1203d522f475Smrg if (TEK4014_GIN(tekWidget)) { 1204d522f475Smrg TekEnqMouse(tekWidget, kd.strbuf[0]); 1205d522f475Smrg TekGINoff(tekWidget); 1206d522f475Smrg kd.nbytes--; 1207d522f475Smrg for (j = 0; j < kd.nbytes; ++j) { 1208d522f475Smrg kd.strbuf[j] = kd.strbuf[j + 1]; 1209d522f475Smrg } 1210d522f475Smrg } 1211d522f475Smrg#endif 1212d522f475Smrg#if OPT_MOD_FKEYS 1213d522f475Smrg if ((keyboard->modify_now.other_keys > 0) 1214d522f475Smrg && ModifyOtherKeys(xw, evt_state, &kd, modify_parm) 1215d522f475Smrg && (mod_state = allowedCharModifiers(xw, evt_state, &kd)) != 0) { 1216d522f475Smrg int input_char; 1217d522f475Smrg 1218d522f475Smrg evt_state = mod_state; 1219d522f475Smrg 1220d522f475Smrg modify_parm = xtermStateToParam(xw, evt_state); 1221d522f475Smrg 1222d522f475Smrg /* 1223d522f475Smrg * We want to show a keycode that corresponds to the 8-bit value 1224d522f475Smrg * of the key. If the keysym is less than 256, that is good 1225d522f475Smrg * enough. Special keys such as Tab may result in a value that 1226d522f475Smrg * is usable as well. For the latter (special cases), try to use 1227d522f475Smrg * the result from the X library lookup. 1228d522f475Smrg */ 1229d522f475Smrg input_char = ((kd.keysym < 256) 1230d522f475Smrg ? (int) kd.keysym 1231d522f475Smrg : ((kd.nbytes == 1) 1232d522f475Smrg ? CharOf(kd.strbuf[0]) 1233d522f475Smrg : -1)); 1234d522f475Smrg 1235d522f475Smrg TRACE(("...modifyOtherKeys %d;%d\n", modify_parm, input_char)); 1236d522f475Smrg if (modifyOtherKey(&reply, input_char, modify_parm, keyboard->format_keys)) { 1237d522f475Smrg unparseseq(xw, &reply); 1238d522f475Smrg } else { 1239d522f475Smrg Bell(XkbBI_MinorError, 0); 1240d522f475Smrg } 1241d522f475Smrg } else 1242d522f475Smrg#endif /* OPT_MOD_FKEYS */ 1243d522f475Smrg { 1244d522f475Smrg#if OPT_NUM_LOCK 1245d522f475Smrg /* 1246d522f475Smrg * Send ESC if we have a META modifier and metaSendsEcape is true. 1247d522f475Smrg * Like eightBitInput, except that it is not associated with 1248d522f475Smrg * terminal settings. 1249d522f475Smrg */ 1250d522f475Smrg if (kd.nbytes != 0) { 1251d522f475Smrg if (screen->meta_sends_esc 1252d522f475Smrg && (evt_state & xw->misc.meta_mods) != 0) { 1253d522f475Smrg TRACE(("...input-char is modified by META\n")); 1254d522f475Smrg evt_state &= ~xw->misc.meta_mods; 1255d522f475Smrg eightbit = False; 1256d522f475Smrg prefix = ANSI_ESC; 1257d522f475Smrg } else if (eightbit) { 1258d522f475Smrg /* it might be overridden, but this helps for debugging */ 1259d522f475Smrg TRACE(("...input-char is shifted by META\n")); 1260d522f475Smrg } 1261d522f475Smrg if (screen->alt_is_not_meta 1262d522f475Smrg && (evt_state & xw->misc.alt_mods) != 0) { 1263d522f475Smrg evt_state &= ~xw->misc.alt_mods; 1264d522f475Smrg if (screen->alt_sends_esc) { 1265d522f475Smrg TRACE(("...input-char is modified by ALT\n")); 12662eaa94a1Schristos eightbit = False; 1267d522f475Smrg prefix = ANSI_ESC; 1268d522f475Smrg } else if (!eightbit) { 1269d522f475Smrg TRACE(("...input-char is shifted by ALT\n")); 1270d522f475Smrg eightbit = True; 1271d522f475Smrg } 1272d522f475Smrg } 1273d522f475Smrg } 1274d522f475Smrg#endif 1275d522f475Smrg /* 1276d522f475Smrg * If metaSendsEscape is false, fall through to this chunk, which 1277d522f475Smrg * implements the eightBitInput resource. 1278d522f475Smrg * 1279d522f475Smrg * It is normally executed when the user presses Meta plus a 1280d522f475Smrg * printable key, e.g., Meta+space. The presence of the Meta 1281d522f475Smrg * modifier is not guaranteed since what really happens is the 1282d522f475Smrg * "insert-eight-bit" or "insert-seven-bit" action, which we 1283d522f475Smrg * distinguish by the eightbit parameter to this function. So the 1284d522f475Smrg * eightBitInput resource really means that we use this shifting 1285d522f475Smrg * logic in the "insert-eight-bit" action. 1286d522f475Smrg */ 1287d522f475Smrg if (eightbit && (kd.nbytes == 1) && screen->input_eight_bits) { 1288d522f475Smrg IChar ch = CharOf(kd.strbuf[0]); 1289d522f475Smrg if (ch < 128) { 12902eaa94a1Schristos kd.strbuf[0] |= (char) 0x80; 1291d522f475Smrg TRACE(("...input shift from %d to %d (%#x to %#x)\n", 1292d522f475Smrg ch, CharOf(kd.strbuf[0]), 1293d522f475Smrg ch, CharOf(kd.strbuf[0]))); 1294d522f475Smrg#if OPT_WIDE_CHARS 1295d522f475Smrg if (screen->utf8_mode) { 1296d522f475Smrg /* 1297d522f475Smrg * We could interpret the incoming code as "in the 1298d522f475Smrg * current locale", but it's simpler to treat it as 1299d522f475Smrg * a Unicode value to translate to UTF-8. 1300d522f475Smrg */ 1301d522f475Smrg ch = CharOf(kd.strbuf[0]); 1302d522f475Smrg kd.nbytes = 2; 13032eaa94a1Schristos kd.strbuf[0] = (char) (0xc0 | ((ch >> 6) & 0x3)); 13042eaa94a1Schristos kd.strbuf[1] = (char) (0x80 | (ch & 0x3f)); 1305d522f475Smrg TRACE(("...encoded %#x in UTF-8 as %#x,%#x\n", 1306d522f475Smrg ch, CharOf(kd.strbuf[0]), CharOf(kd.strbuf[1]))); 1307d522f475Smrg } 1308d522f475Smrg#endif 1309d522f475Smrg } 1310d522f475Smrg eightbit = False; 1311d522f475Smrg } 1312d522f475Smrg#if OPT_WIDE_CHARS 1313d522f475Smrg if (kd.nbytes == 1) /* cannot do NRC on UTF-8, for instance */ 1314d522f475Smrg#endif 1315d522f475Smrg { 1316d522f475Smrg /* VT220 & up: National Replacement Characters */ 1317d522f475Smrg if ((xw->flags & NATIONAL) != 0) { 13182eaa94a1Schristos unsigned cmp = xtermCharSetIn(CharOf(kd.strbuf[0]), 13192eaa94a1Schristos screen->keyboard_dialect[0]); 1320d522f475Smrg TRACE(("...input NRC %d, %s %d\n", 1321d522f475Smrg CharOf(kd.strbuf[0]), 1322d522f475Smrg (CharOf(kd.strbuf[0]) == cmp) 1323d522f475Smrg ? "unchanged" 1324d522f475Smrg : "changed to", 1325d522f475Smrg CharOf(cmp))); 13262eaa94a1Schristos kd.strbuf[0] = (char) cmp; 1327d522f475Smrg } else if (eightbit) { 1328d522f475Smrg prefix = ANSI_ESC; 1329d522f475Smrg } else if (kd.strbuf[0] == '?' 1330d522f475Smrg && (evt_state & ControlMask) != 0) { 1331d522f475Smrg kd.strbuf[0] = ANSI_DEL; 1332d522f475Smrg evt_state &= ~ControlMask; 1333d522f475Smrg } 1334d522f475Smrg } 1335d522f475Smrg if (prefix != 0) 1336d522f475Smrg unparseputc(xw, prefix); /* escape */ 1337d522f475Smrg for (j = 0; j < kd.nbytes; ++j) 1338d522f475Smrg unparseputc(xw, CharOf(kd.strbuf[j])); 1339d522f475Smrg } 1340d522f475Smrg key = True; 1341d522f475Smrg } 1342d522f475Smrg unparse_end(xw); 1343d522f475Smrg 1344d522f475Smrg if (key && !TEK4014_ACTIVE(xw)) 1345d522f475Smrg AdjustAfterInput(xw); 1346d522f475Smrg 1347d522f475Smrg xtermShowPointer(xw, False); 1348d522f475Smrg return; 1349d522f475Smrg} 1350d522f475Smrg 1351d522f475Smrgvoid 1352d522f475SmrgStringInput(XtermWidget xw, Char * string, size_t nbytes) 1353d522f475Smrg{ 1354d522f475Smrg TRACE(("InputString (%s,%d)\n", 1355d522f475Smrg visibleChars(PAIRED_CHARS(string, 0), nbytes), 1356d522f475Smrg nbytes)); 1357d522f475Smrg#if OPT_TEK4014 1358d522f475Smrg if (nbytes && TEK4014_GIN(tekWidget)) { 1359d522f475Smrg TekEnqMouse(tekWidget, *string++); 1360d522f475Smrg TekGINoff(tekWidget); 1361d522f475Smrg nbytes--; 1362d522f475Smrg } 1363d522f475Smrg#endif 1364d522f475Smrg while (nbytes-- != 0) 1365d522f475Smrg unparseputc(xw, *string++); 1366d522f475Smrg if (!TEK4014_ACTIVE(xw)) 1367d522f475Smrg AdjustAfterInput(xw); 1368d522f475Smrg unparse_end(xw); 1369d522f475Smrg} 1370d522f475Smrg 1371d522f475Smrg/* These definitions are DEC-style (e.g., vt320) */ 1372d522f475Smrgstatic int 1373d522f475Smrgdecfuncvalue(KEY_DATA * kd) 1374d522f475Smrg{ 1375d522f475Smrg int result; 1376d522f475Smrg 1377d522f475Smrg if (kd->is_fkey) { 1378d522f475Smrg switch (kd->keysym) { 1379d522f475Smrg MAP(XK_Fn(1), 11); 1380d522f475Smrg MAP(XK_Fn(2), 12); 1381d522f475Smrg MAP(XK_Fn(3), 13); 1382d522f475Smrg MAP(XK_Fn(4), 14); 1383d522f475Smrg MAP(XK_Fn(5), 15); 1384d522f475Smrg MAP(XK_Fn(6), 17); 1385d522f475Smrg MAP(XK_Fn(7), 18); 1386d522f475Smrg MAP(XK_Fn(8), 19); 1387d522f475Smrg MAP(XK_Fn(9), 20); 1388d522f475Smrg MAP(XK_Fn(10), 21); 1389d522f475Smrg MAP(XK_Fn(11), 23); 1390d522f475Smrg MAP(XK_Fn(12), 24); 1391d522f475Smrg MAP(XK_Fn(13), 25); 1392d522f475Smrg MAP(XK_Fn(14), 26); 1393d522f475Smrg MAP(XK_Fn(15), 28); 1394d522f475Smrg MAP(XK_Fn(16), 29); 1395d522f475Smrg MAP(XK_Fn(17), 31); 1396d522f475Smrg MAP(XK_Fn(18), 32); 1397d522f475Smrg MAP(XK_Fn(19), 33); 1398d522f475Smrg MAP(XK_Fn(20), 34); 1399d522f475Smrg default: 1400d522f475Smrg /* after F20 the codes are made up and do not correspond to any 1401d522f475Smrg * real terminal. So they are simply numbered sequentially. 1402d522f475Smrg */ 14032eaa94a1Schristos result = 42 + (int) (kd->keysym - XK_Fn(21)); 1404d522f475Smrg break; 1405d522f475Smrg } 1406d522f475Smrg } else { 1407d522f475Smrg switch (kd->keysym) { 1408d522f475Smrg MAP(XK_Find, 1); 1409d522f475Smrg MAP(XK_Insert, 2); 1410d522f475Smrg MAP(XK_Delete, 3); 1411d522f475Smrg#ifdef XK_KP_Insert 1412d522f475Smrg MAP(XK_KP_Insert, 2); 1413d522f475Smrg MAP(XK_KP_Delete, 3); 1414d522f475Smrg#endif 1415d522f475Smrg#ifdef DXK_Remove 1416d522f475Smrg MAP(DXK_Remove, 3); 1417d522f475Smrg#endif 1418d522f475Smrg MAP(XK_Select, 4); 1419d522f475Smrg MAP(XK_Prior, 5); 1420d522f475Smrg MAP(XK_Next, 6); 1421d522f475Smrg#ifdef XK_ISO_Left_Tab 1422d522f475Smrg MAP(XK_ISO_Left_Tab, 'Z'); 1423d522f475Smrg#endif 1424d522f475Smrg MAP(XK_Help, 28); 1425d522f475Smrg MAP(XK_Menu, 29); 1426d522f475Smrg default: 1427d522f475Smrg result = -1; 1428d522f475Smrg break; 1429d522f475Smrg } 1430d522f475Smrg } 1431d522f475Smrg return result; 1432d522f475Smrg} 1433d522f475Smrg 1434d522f475Smrgstatic void 1435d522f475Smrghpfuncvalue(ANSI * reply, KEY_DATA * kd) 1436d522f475Smrg{ 1437d522f475Smrg#if OPT_HP_FUNC_KEYS 1438d522f475Smrg int result; 1439d522f475Smrg 1440d522f475Smrg if (kd->is_fkey) { 1441d522f475Smrg switch (kd->keysym) { 1442d522f475Smrg MAP(XK_Fn(1), 'p'); 1443d522f475Smrg MAP(XK_Fn(2), 'q'); 1444d522f475Smrg MAP(XK_Fn(3), 'r'); 1445d522f475Smrg MAP(XK_Fn(4), 's'); 1446d522f475Smrg MAP(XK_Fn(5), 't'); 1447d522f475Smrg MAP(XK_Fn(6), 'u'); 1448d522f475Smrg MAP(XK_Fn(7), 'v'); 1449d522f475Smrg MAP(XK_Fn(8), 'w'); 1450d522f475Smrg default: 1451d522f475Smrg result = -1; 1452d522f475Smrg break; 1453d522f475Smrg } 1454d522f475Smrg } else { 1455d522f475Smrg switch (kd->keysym) { 1456d522f475Smrg MAP(XK_Up, 'A'); 1457d522f475Smrg MAP(XK_Down, 'B'); 1458d522f475Smrg MAP(XK_Right, 'C'); 1459d522f475Smrg MAP(XK_Left, 'D'); 1460d522f475Smrg MAP(XK_End, 'F'); 1461d522f475Smrg MAP(XK_Clear, 'J'); 1462d522f475Smrg MAP(XK_Delete, 'P'); 1463d522f475Smrg MAP(XK_Insert, 'Q'); 1464d522f475Smrg MAP(XK_Next, 'S'); 1465d522f475Smrg MAP(XK_Prior, 'T'); 1466d522f475Smrg MAP(XK_Home, 'h'); 1467d522f475Smrg#ifdef XK_KP_Insert 1468d522f475Smrg MAP(XK_KP_Delete, 'P'); 1469d522f475Smrg MAP(XK_KP_Insert, 'Q'); 1470d522f475Smrg#endif 1471d522f475Smrg#ifdef DXK_Remove 1472d522f475Smrg MAP(DXK_Remove, 'P'); 1473d522f475Smrg#endif 1474d522f475Smrg MAP(XK_Select, 'F'); 1475d522f475Smrg MAP(XK_Find, 'h'); 1476d522f475Smrg default: 1477d522f475Smrg result = -1; 1478d522f475Smrg break; 1479d522f475Smrg } 1480d522f475Smrg } 1481d522f475Smrg if (result > 0) { 1482d522f475Smrg reply->a_type = ANSI_ESC; 14832eaa94a1Schristos reply->a_final = (Char) result; 1484d522f475Smrg } 1485d522f475Smrg#else 1486d522f475Smrg (void) reply; 1487d522f475Smrg (void) kd; 1488d522f475Smrg#endif /* OPT_HP_FUNC_KEYS */ 1489d522f475Smrg} 1490d522f475Smrg 1491d522f475Smrgstatic void 1492d522f475Smrgscofuncvalue(ANSI * reply, KEY_DATA * kd) 1493d522f475Smrg{ 1494d522f475Smrg#if OPT_SCO_FUNC_KEYS 1495d522f475Smrg int result; 1496d522f475Smrg 1497d522f475Smrg if (kd->is_fkey) { 1498d522f475Smrg switch (kd->keysym) { 1499d522f475Smrg MAP(XK_Fn(1), 'M'); 1500d522f475Smrg MAP(XK_Fn(2), 'N'); 1501d522f475Smrg MAP(XK_Fn(3), 'O'); 1502d522f475Smrg MAP(XK_Fn(4), 'P'); 1503d522f475Smrg MAP(XK_Fn(5), 'Q'); 1504d522f475Smrg MAP(XK_Fn(6), 'R'); 1505d522f475Smrg MAP(XK_Fn(7), 'S'); 1506d522f475Smrg MAP(XK_Fn(8), 'T'); 1507d522f475Smrg MAP(XK_Fn(9), 'U'); 1508d522f475Smrg MAP(XK_Fn(10), 'V'); 1509d522f475Smrg MAP(XK_Fn(11), 'W'); 1510d522f475Smrg MAP(XK_Fn(12), 'X'); 1511d522f475Smrg MAP(XK_Fn(13), 'Y'); 1512d522f475Smrg MAP(XK_Fn(14), 'Z'); 1513d522f475Smrg MAP(XK_Fn(15), 'a'); 1514d522f475Smrg MAP(XK_Fn(16), 'b'); 1515d522f475Smrg MAP(XK_Fn(17), 'c'); 1516d522f475Smrg MAP(XK_Fn(18), 'd'); 1517d522f475Smrg MAP(XK_Fn(19), 'e'); 1518d522f475Smrg MAP(XK_Fn(20), 'f'); 1519d522f475Smrg MAP(XK_Fn(21), 'g'); 1520d522f475Smrg MAP(XK_Fn(22), 'h'); 1521d522f475Smrg MAP(XK_Fn(23), 'i'); 1522d522f475Smrg MAP(XK_Fn(24), 'j'); 1523d522f475Smrg MAP(XK_Fn(25), 'k'); 1524d522f475Smrg MAP(XK_Fn(26), 'l'); 1525d522f475Smrg MAP(XK_Fn(27), 'm'); 1526d522f475Smrg MAP(XK_Fn(28), 'n'); 1527d522f475Smrg MAP(XK_Fn(29), 'o'); 1528d522f475Smrg MAP(XK_Fn(30), 'p'); 1529d522f475Smrg MAP(XK_Fn(31), 'q'); 1530d522f475Smrg MAP(XK_Fn(32), 'r'); 1531d522f475Smrg MAP(XK_Fn(33), 's'); 1532d522f475Smrg MAP(XK_Fn(34), 't'); 1533d522f475Smrg MAP(XK_Fn(35), 'u'); 1534d522f475Smrg MAP(XK_Fn(36), 'v'); 1535d522f475Smrg MAP(XK_Fn(37), 'w'); 1536d522f475Smrg MAP(XK_Fn(38), 'x'); 1537d522f475Smrg MAP(XK_Fn(39), 'y'); 1538d522f475Smrg MAP(XK_Fn(40), 'z'); 1539d522f475Smrg MAP(XK_Fn(41), '@'); 1540d522f475Smrg MAP(XK_Fn(42), '['); 1541d522f475Smrg MAP(XK_Fn(43), '\\'); 1542d522f475Smrg MAP(XK_Fn(44), ']'); 1543d522f475Smrg MAP(XK_Fn(45), '^'); 1544d522f475Smrg MAP(XK_Fn(46), '_'); 1545d522f475Smrg MAP(XK_Fn(47), '`'); 1546d522f475Smrg MAP(XK_Fn(48), '{'); /* no matching '}' */ 1547d522f475Smrg default: 1548d522f475Smrg result = -1; 1549d522f475Smrg break; 1550d522f475Smrg } 1551d522f475Smrg } else { 1552d522f475Smrg switch (kd->keysym) { 1553d522f475Smrg MAP(XK_Up, 'A'); 1554d522f475Smrg MAP(XK_Down, 'B'); 1555d522f475Smrg MAP(XK_Right, 'C'); 1556d522f475Smrg MAP(XK_Left, 'D'); 1557d522f475Smrg MAP(XK_Begin, 'E'); 1558d522f475Smrg MAP(XK_End, 'F'); 1559d522f475Smrg MAP(XK_Insert, 'L'); 1560d522f475Smrg MAP(XK_Next, 'G'); 1561d522f475Smrg MAP(XK_Prior, 'I'); 1562d522f475Smrg MAP(XK_Home, 'H'); 1563d522f475Smrg#ifdef XK_KP_Insert 1564d522f475Smrg MAP(XK_KP_Insert, 'L'); 1565d522f475Smrg#endif 1566d522f475Smrg default: 1567d522f475Smrg result = -1; 1568d522f475Smrg break; 1569d522f475Smrg } 1570d522f475Smrg } 1571d522f475Smrg if (result > 0) { 1572d522f475Smrg reply->a_type = ANSI_CSI; 15732eaa94a1Schristos reply->a_final = (Char) result; 1574d522f475Smrg } 1575d522f475Smrg#else 1576d522f475Smrg (void) reply; 1577d522f475Smrg (void) kd; 1578d522f475Smrg#endif /* OPT_SCO_FUNC_KEYS */ 1579d522f475Smrg} 1580d522f475Smrg 1581d522f475Smrgstatic void 1582d522f475Smrgsunfuncvalue(ANSI * reply, KEY_DATA * kd) 1583d522f475Smrg{ 1584d522f475Smrg#if OPT_SUN_FUNC_KEYS 1585d522f475Smrg int result; 1586d522f475Smrg 1587d522f475Smrg if (kd->is_fkey) { 1588d522f475Smrg switch (kd->keysym) { 1589d522f475Smrg /* kf1-kf20 are numbered sequentially */ 1590d522f475Smrg MAP(XK_Fn(1), 224); 1591d522f475Smrg MAP(XK_Fn(2), 225); 1592d522f475Smrg MAP(XK_Fn(3), 226); 1593d522f475Smrg MAP(XK_Fn(4), 227); 1594d522f475Smrg MAP(XK_Fn(5), 228); 1595d522f475Smrg MAP(XK_Fn(6), 229); 1596d522f475Smrg MAP(XK_Fn(7), 230); 1597d522f475Smrg MAP(XK_Fn(8), 231); 1598d522f475Smrg MAP(XK_Fn(9), 232); 1599d522f475Smrg MAP(XK_Fn(10), 233); 1600d522f475Smrg MAP(XK_Fn(11), 192); 1601d522f475Smrg MAP(XK_Fn(12), 193); 1602d522f475Smrg MAP(XK_Fn(13), 194); 1603d522f475Smrg MAP(XK_Fn(14), 195); /* kund */ 1604d522f475Smrg MAP(XK_Fn(15), 196); 1605d522f475Smrg MAP(XK_Fn(16), 197); /* kcpy */ 1606d522f475Smrg MAP(XK_Fn(17), 198); 1607d522f475Smrg MAP(XK_Fn(18), 199); 1608d522f475Smrg MAP(XK_Fn(19), 200); /* kfnd */ 1609d522f475Smrg MAP(XK_Fn(20), 201); 1610d522f475Smrg 1611d522f475Smrg /* kf31-kf36 are numbered sequentially */ 1612d522f475Smrg MAP(XK_Fn(21), 208); /* kf31 */ 1613d522f475Smrg MAP(XK_Fn(22), 209); 1614d522f475Smrg MAP(XK_Fn(23), 210); 1615d522f475Smrg MAP(XK_Fn(24), 211); 1616d522f475Smrg MAP(XK_Fn(25), 212); 1617d522f475Smrg MAP(XK_Fn(26), 213); /* kf36 */ 1618d522f475Smrg 1619d522f475Smrg /* kf37-kf47 are interspersed with keypad keys */ 1620d522f475Smrg MAP(XK_Fn(27), 214); /* khome */ 1621d522f475Smrg MAP(XK_Fn(28), 215); /* kf38 */ 1622d522f475Smrg MAP(XK_Fn(29), 216); /* kpp */ 1623d522f475Smrg MAP(XK_Fn(30), 217); /* kf40 */ 1624d522f475Smrg MAP(XK_Fn(31), 218); /* kb2 */ 1625d522f475Smrg MAP(XK_Fn(32), 219); /* kf42 */ 1626d522f475Smrg MAP(XK_Fn(33), 220); /* kend */ 1627d522f475Smrg MAP(XK_Fn(34), 221); /* kf44 */ 1628d522f475Smrg MAP(XK_Fn(35), 222); /* knp */ 1629d522f475Smrg MAP(XK_Fn(36), 234); /* kf46 */ 1630d522f475Smrg MAP(XK_Fn(37), 235); /* kf47 */ 1631d522f475Smrg default: 1632d522f475Smrg result = -1; 1633d522f475Smrg break; 1634d522f475Smrg } 1635d522f475Smrg } else { 1636d522f475Smrg switch (kd->keysym) { 1637d522f475Smrg MAP(XK_Help, 196); /* khlp */ 1638d522f475Smrg MAP(XK_Menu, 197); 1639d522f475Smrg 1640d522f475Smrg MAP(XK_Find, 1); 1641d522f475Smrg MAP(XK_Insert, 2); /* kich1 */ 1642d522f475Smrg MAP(XK_Delete, 3); 1643d522f475Smrg#ifdef XK_KP_Insert 1644d522f475Smrg MAP(XK_KP_Insert, 2); 1645d522f475Smrg MAP(XK_KP_Delete, 3); 1646d522f475Smrg#endif 1647d522f475Smrg#ifdef DXK_Remove 1648d522f475Smrg MAP(DXK_Remove, 3); 1649d522f475Smrg#endif 1650d522f475Smrg MAP(XK_Select, 4); 1651d522f475Smrg 1652d522f475Smrg MAP(XK_Prior, 216); 1653d522f475Smrg MAP(XK_Next, 222); 1654d522f475Smrg MAP(XK_Home, 214); 1655d522f475Smrg MAP(XK_End, 220); 1656d522f475Smrg MAP(XK_Begin, 218); /* kf41=kb2 */ 1657d522f475Smrg 1658d522f475Smrg default: 1659d522f475Smrg result = -1; 1660d522f475Smrg break; 1661d522f475Smrg } 1662d522f475Smrg } 1663d522f475Smrg if (result > 0) { 1664d522f475Smrg reply->a_type = ANSI_CSI; 1665d522f475Smrg reply->a_nparam = 1; 1666d522f475Smrg reply->a_param[0] = result; 1667d522f475Smrg reply->a_final = 'z'; 1668d522f475Smrg } else if (IsCursorKey(kd->keysym)) { 1669d522f475Smrg reply->a_type = ANSI_SS3; 16702eaa94a1Schristos reply->a_final = (Char) curfinal[kd->keysym - XK_Home]; 1671d522f475Smrg } 1672d522f475Smrg#else 1673d522f475Smrg (void) reply; 1674d522f475Smrg (void) kd; 1675d522f475Smrg#endif /* OPT_SUN_FUNC_KEYS */ 1676d522f475Smrg} 1677d522f475Smrg 1678d522f475Smrg#if OPT_NUM_LOCK 1679d522f475Smrg#define isName(c) ((c) == '_' || isalnum(CharOf(c))) 1680d522f475Smrg 1681d522f475Smrg/* 16822eaa94a1Schristos * Strip unneeded whitespace from a translations resource, mono-casing and 1683d522f475Smrg * returning a malloc'd copy of the result. 1684d522f475Smrg */ 1685d522f475Smrgstatic char * 1686d522f475SmrgstripTranslations(const char *s) 1687d522f475Smrg{ 1688d522f475Smrg char *dst = 0; 1689d522f475Smrg 1690d522f475Smrg if (s != 0) { 1691d522f475Smrg dst = TypeMallocN(char, strlen(s) + 1); 1692d522f475Smrg 1693d522f475Smrg if (dst != 0) { 1694d522f475Smrg int state = 0; 1695d522f475Smrg int ch = 0; 1696d522f475Smrg int prv = 0; 1697d522f475Smrg char *d = dst; 1698d522f475Smrg 1699d522f475Smrg TRACE(("stripping:\n%s\n", s)); 1700d522f475Smrg while (*s != '\0') { 1701d522f475Smrg ch = *s++; 1702d522f475Smrg if (ch == '\n') { 1703d522f475Smrg if (d != dst) 17042eaa94a1Schristos *d++ = (char) ch; 1705d522f475Smrg state = 0; 1706d522f475Smrg } else if (strchr(":!#", ch) != 0) { 1707d522f475Smrg while (d != dst && isspace(CharOf(d[-1]))) 1708d522f475Smrg --d; 1709d522f475Smrg state = -1; 1710d522f475Smrg } else if (state >= 0) { 1711d522f475Smrg if (isspace(CharOf(ch))) { 1712d522f475Smrg if (state == 0 || strchr("<>~ \t", prv)) 1713d522f475Smrg continue; 1714d522f475Smrg } else if (strchr("<>~", ch)) { 1715d522f475Smrg while (d != dst && isspace(CharOf(d[-1]))) 1716d522f475Smrg --d; 1717d522f475Smrg } 17182eaa94a1Schristos *d++ = x_toupper(ch); 1719d522f475Smrg ++state; 1720d522f475Smrg } 1721d522f475Smrg prv = ch; 1722d522f475Smrg } 1723d522f475Smrg *d = '\0'; 1724d522f475Smrg TRACE(("...result:\n%s\n", dst)); 1725d522f475Smrg } 1726d522f475Smrg } 1727d522f475Smrg return dst; 1728d522f475Smrg} 1729d522f475Smrg 1730d522f475Smrg/* 1731d522f475Smrg * Make a simple check to see if a given translations keyword appears in 1732d522f475Smrg * xterm's translations resource. It does not attempt to parse the strings, 1733d522f475Smrg * just makes a case-independent check and ensures that the ends of the match 1734d522f475Smrg * are on token-boundaries. 1735d522f475Smrg * 1736d522f475Smrg * That this can only retrieve translations that are given as resource values; 1737d522f475Smrg * the default translations in charproc.c for example are not retrievable by 1738d522f475Smrg * any interface to X. 1739d522f475Smrg * 1740d522f475Smrg * Also: We can retrieve only the most-specified translation resource. For 1741d522f475Smrg * example, if the resource file specifies both "*translations" and 1742d522f475Smrg * "XTerm*translations", we see only the latter. 1743d522f475Smrg */ 1744d522f475Smrgstatic Bool 1745d522f475SmrgTranslationsUseKeyword(Widget w, char **cache, const char *keyword) 1746d522f475Smrg{ 1747d522f475Smrg static String data; 1748d522f475Smrg static XtResource key_resources[] = 1749d522f475Smrg { 1750d522f475Smrg {XtNtranslations, XtCTranslations, XtRString, 1751d522f475Smrg sizeof(data), 0, XtRString, (XtPointer) NULL} 1752d522f475Smrg }; 1753d522f475Smrg Bool result = False; 1754d522f475Smrg char *copy; 1755d522f475Smrg char *test; 1756d522f475Smrg 1757d522f475Smrg if ((test = stripTranslations(keyword)) != 0) { 1758d522f475Smrg if (*cache == 0) { 1759d522f475Smrg XtGetSubresources(w, 1760d522f475Smrg (XtPointer) &data, 1761d522f475Smrg "vt100", 1762d522f475Smrg "VT100", 1763d522f475Smrg key_resources, 1764d522f475Smrg XtNumber(key_resources), 1765d522f475Smrg NULL, 1766d522f475Smrg (Cardinal) 0); 1767d522f475Smrg if (data != 0 && (copy = stripTranslations(data)) != 0) { 1768d522f475Smrg *cache = copy; 1769d522f475Smrg } 1770d522f475Smrg } 1771d522f475Smrg 1772d522f475Smrg if (*cache != 0) { 1773d522f475Smrg char *p = *cache; 1774d522f475Smrg int state = 0; 1775d522f475Smrg int now = ' ', prv; 1776d522f475Smrg 1777d522f475Smrg while (*p != 0) { 1778d522f475Smrg prv = now; 1779d522f475Smrg now = *p++; 1780d522f475Smrg if (now == ':' 1781d522f475Smrg || now == '!') { 1782d522f475Smrg state = -1; 1783d522f475Smrg } else if (now == '\n') { 1784d522f475Smrg state = 0; 1785d522f475Smrg } else if (state >= 0) { 1786d522f475Smrg if (now == test[state]) { 1787d522f475Smrg if ((state != 0 1788d522f475Smrg || !isName(prv)) 1789d522f475Smrg && ((test[++state] == 0) 1790d522f475Smrg && !isName(*p))) { 1791d522f475Smrg result = True; 1792d522f475Smrg break; 1793d522f475Smrg } 1794d522f475Smrg } else { 1795d522f475Smrg state = 0; 1796d522f475Smrg } 1797d522f475Smrg } 1798d522f475Smrg } 1799d522f475Smrg } 1800d522f475Smrg free(test); 1801d522f475Smrg } 1802d522f475Smrg TRACE(("TranslationsUseKeyword(%p, %s) = %d\n", w, keyword, result)); 1803d522f475Smrg return result; 1804d522f475Smrg} 1805d522f475Smrg 1806d522f475Smrgstatic Bool 1807d522f475SmrgxtermHasTranslation(XtermWidget xw, const char *keyword) 1808d522f475Smrg{ 1809d522f475Smrg return (TranslationsUseKeyword(SHELL_OF(xw), 1810d522f475Smrg &(xw->keyboard.shell_translations), 1811d522f475Smrg keyword) 1812d522f475Smrg || TranslationsUseKeyword((Widget) xw, 1813d522f475Smrg &(xw->keyboard.xterm_translations), 1814d522f475Smrg keyword)); 1815d522f475Smrg} 1816d522f475Smrg 1817d522f475Smrg#if OPT_EXTRA_PASTE 1818d522f475Smrgstatic void 1819d522f475SmrgaddTranslation(XtermWidget xw, char *fromString, char *toString) 1820d522f475Smrg{ 1821d522f475Smrg unsigned have = (xw->keyboard.extra_translations 1822d522f475Smrg ? strlen(xw->keyboard.extra_translations) 1823d522f475Smrg : 0); 1824d522f475Smrg unsigned need = (((have != 0) ? (have + 4) : 0) 1825d522f475Smrg + strlen(fromString) 1826d522f475Smrg + strlen(toString) 1827d522f475Smrg + 6); 1828d522f475Smrg 1829d522f475Smrg if (!xtermHasTranslation(xw, fromString)) { 1830d522f475Smrg xw->keyboard.extra_translations 1831d522f475Smrg = TypeRealloc(char, need, xw->keyboard.extra_translations); 1832d522f475Smrg if ((xw->keyboard.extra_translations) != 0) { 1833d522f475Smrg TRACE(("adding %s: %s\n", fromString, toString)); 1834d522f475Smrg if (have) 1835d522f475Smrg strcat(xw->keyboard.extra_translations, " \\n\\"); 1836d522f475Smrg sprintf(xw->keyboard.extra_translations, "%s: %s", 1837d522f475Smrg fromString, toString); 1838d522f475Smrg TRACE(("...{%s}\n", xw->keyboard.extra_translations)); 1839d522f475Smrg } 1840d522f475Smrg } 1841d522f475Smrg} 1842d522f475Smrg#endif 1843d522f475Smrg 1844d522f475Smrg#define SaveMask(name) xw->misc.name |= mask;\ 1845d522f475Smrg TRACE(("SaveMask(%s) %#lx (%#lx is%s modifier)\n", \ 1846d522f475Smrg #name, \ 1847d522f475Smrg xw->misc.name, mask, \ 1848d522f475Smrg ModifierName(mask))); 1849d522f475Smrg/* 1850d522f475Smrg * Determine which modifier mask (if any) applies to the Num_Lock keysym. 1851d522f475Smrg * 1852d522f475Smrg * Also, determine which modifiers are associated with the ALT keys, so we can 1853d522f475Smrg * send that information as a parameter for special keys in Sun/PC keyboard 1854d522f475Smrg * mode. However, if the ALT modifier is used in translations, we do not want 1855d522f475Smrg * to confuse things by sending the parameter. 1856d522f475Smrg */ 1857d522f475Smrgvoid 1858d522f475SmrgVTInitModifiers(XtermWidget xw) 1859d522f475Smrg{ 1860d522f475Smrg Display *dpy = XtDisplay(xw); 1861d522f475Smrg XModifierKeymap *keymap = XGetModifierMapping(dpy); 1862d522f475Smrg int i, j, k, l; 1863d522f475Smrg KeySym keysym; 1864d522f475Smrg unsigned long mask; 1865d522f475Smrg int min_keycode, max_keycode, keysyms_per_keycode = 0; 1866d522f475Smrg 1867d522f475Smrg if (keymap != 0) { 1868d522f475Smrg KeySym *theMap; 1869d522f475Smrg int keycode_count; 1870d522f475Smrg 1871d522f475Smrg TRACE(("VTInitModifiers\n")); 1872d522f475Smrg 1873d522f475Smrg XDisplayKeycodes(dpy, &min_keycode, &max_keycode); 1874d522f475Smrg keycode_count = (max_keycode - min_keycode + 1); 1875d522f475Smrg theMap = XGetKeyboardMapping(dpy, 1876d522f475Smrg min_keycode, 1877d522f475Smrg keycode_count, 1878d522f475Smrg &keysyms_per_keycode); 1879d522f475Smrg 1880d522f475Smrg if (theMap != 0) { 1881d522f475Smrg 1882d522f475Smrg#if OPT_EXTRA_PASTE 1883d522f475Smrg /* 1884d522f475Smrg * Assume that if we can find the paste keysym in the X keyboard 1885d522f475Smrg * mapping that the server allows the corresponding translations 1886d522f475Smrg * resource. 1887d522f475Smrg */ 1888d522f475Smrg int limit = (max_keycode - min_keycode) * keysyms_per_keycode; 1889d522f475Smrg for (i = 0; i < limit; ++i) { 1890d522f475Smrg#ifdef XF86XK_Paste 1891d522f475Smrg if (theMap[i] == XF86XK_Paste) { 1892d522f475Smrg TRACE(("keyboard has XF86XK_Paste\n")); 1893d522f475Smrg addTranslation(xw, 1894d522f475Smrg "<KeyPress> XF86Paste", 1895d522f475Smrg "insert-selection(SELECT, CUT_BUFFER0)"); 1896d522f475Smrg } 1897d522f475Smrg#endif 1898d522f475Smrg#ifdef SunXK_Paste 1899d522f475Smrg if (theMap[i] == SunXK_Paste) { 1900d522f475Smrg TRACE(("keyboard has SunXK_Paste\n")); 1901d522f475Smrg addTranslation(xw, 1902d522f475Smrg "<KeyPress> SunPaste", 1903d522f475Smrg "insert-selection(SELECT, CUT_BUFFER0)"); 1904d522f475Smrg } 1905d522f475Smrg#endif 1906d522f475Smrg } 1907d522f475Smrg#endif /* OPT_EXTRA_PASTE */ 1908d522f475Smrg 1909d522f475Smrg for (i = k = 0, mask = 1; i < 8; i++, mask <<= 1) { 1910d522f475Smrg for (j = 0; j < keymap->max_keypermod; j++) { 1911d522f475Smrg KeyCode code = keymap->modifiermap[k++]; 1912d522f475Smrg if (code == 0) 1913d522f475Smrg continue; 1914d522f475Smrg 1915d522f475Smrg for (l = 0; l < keysyms_per_keycode; ++l) { 1916d522f475Smrg keysym = XKeycodeToKeysym(dpy, code, l); 1917d522f475Smrg if (keysym == NoSymbol) { 1918d522f475Smrg ; 1919d522f475Smrg } else if (keysym == XK_Num_Lock) { 1920d522f475Smrg SaveMask(num_lock); 1921d522f475Smrg } else if (keysym == XK_Alt_L || keysym == XK_Alt_R) { 1922d522f475Smrg SaveMask(alt_mods); 1923d522f475Smrg } else if (keysym == XK_Meta_L || keysym == XK_Meta_R) { 1924d522f475Smrg SaveMask(meta_mods); 1925d522f475Smrg } else if (mask == ShiftMask 1926d522f475Smrg && (keysym == XK_Shift_L 1927d522f475Smrg || keysym == XK_Shift_R)) { 1928d522f475Smrg ; /* ignore */ 1929d522f475Smrg } else if (mask == ControlMask 1930d522f475Smrg && (keysym == XK_Control_L 1931d522f475Smrg || keysym == XK_Control_R)) { 1932d522f475Smrg ; /* ignore */ 1933d522f475Smrg } else if (mask == LockMask 1934d522f475Smrg && (keysym == XK_Caps_Lock)) { 1935d522f475Smrg ; /* ignore */ 1936d522f475Smrg } else if (keysym == XK_Mode_switch 1937d522f475Smrg#ifdef XK_ISO_Level3_Shift 1938d522f475Smrg || keysym == XK_ISO_Level3_Shift 1939d522f475Smrg#endif 1940d522f475Smrg ) { 1941d522f475Smrg SaveMask(other_mods); 1942d522f475Smrg } 1943d522f475Smrg } 1944d522f475Smrg } 1945d522f475Smrg } 1946d522f475Smrg XFree(theMap); 1947d522f475Smrg } 1948d522f475Smrg 1949d522f475Smrg /* Don't disable any mods if "alwaysUseMods" is true. */ 1950d522f475Smrg if (!xw->misc.alwaysUseMods) { 1951d522f475Smrg /* 1952d522f475Smrg * If the Alt modifier is used in translations, we would rather not 1953d522f475Smrg * use it to modify function-keys when NumLock is active. 1954d522f475Smrg */ 1955d522f475Smrg if ((xw->misc.alt_mods != 0) 1956d522f475Smrg && xtermHasTranslation(xw, "alt")) { 1957d522f475Smrg TRACE(("ALT is used as a modifier in translations (ignore mask)\n")); 1958d522f475Smrg xw->misc.alt_mods = 0; 1959d522f475Smrg } 1960d522f475Smrg 1961d522f475Smrg /* 1962d522f475Smrg * If the Meta modifier is used in translations, we would rather not 1963d522f475Smrg * use it to modify function-keys. 1964d522f475Smrg */ 1965d522f475Smrg if ((xw->misc.meta_mods != 0) 1966d522f475Smrg && xtermHasTranslation(xw, "meta")) { 1967d522f475Smrg TRACE(("META is used as a modifier in translations\n")); 1968d522f475Smrg xw->misc.meta_mods = 0; 1969d522f475Smrg } 1970d522f475Smrg } 1971d522f475Smrg 1972d522f475Smrg XFreeModifiermap(keymap); 1973d522f475Smrg } 1974d522f475Smrg} 1975d522f475Smrg#endif /* OPT_NUM_LOCK */ 1976