Annotation of src/usr.bin/vim/tables.c, Revision 1.1
1.1 ! downsj 1: /* $OpenBSD$ */
! 2: /* vi:set ts=4 sw=4:
! 3: *
! 4: * VIM - Vi IMproved by Bram Moolenaar
! 5: * This file by Robert Webb
! 6: *
! 7: * Do ":help uganda" in Vim to read copying and usage conditions.
! 8: * Do ":help credits" in Vim to see a list of people who contributed.
! 9: */
! 10:
! 11: /*
! 12: * tables.c: functions that use lookup tables for various things, generally to
! 13: * do with special key codes.
! 14: */
! 15:
! 16: #include "vim.h"
! 17: #include "globals.h"
! 18: #include "proto.h"
! 19: #include "option.h"
! 20:
! 21: /*
! 22: * Some useful tables.
! 23: */
! 24:
! 25: static struct
! 26: {
! 27: int mod_mask; /* Bit-mask for particular key modifier */
! 28: char_u name; /* Single letter name of modifier */
! 29: } mod_mask_table[] =
! 30: {
! 31: {MOD_MASK_ALT, (char_u)'M'},
! 32: {MOD_MASK_CTRL, (char_u)'C'},
! 33: {MOD_MASK_SHIFT, (char_u)'S'},
! 34: {MOD_MASK_2CLICK, (char_u)'2'},
! 35: {MOD_MASK_3CLICK, (char_u)'3'},
! 36: {MOD_MASK_4CLICK, (char_u)'4'},
! 37: {0x0, NUL}
! 38: };
! 39:
! 40: /*
! 41: * Shifted key terminal codes and their unshifted equivalent.
! 42: * Don't add mouse codes here, they are handled seperately!
! 43: */
! 44: static char_u shifted_keys_table[] =
! 45: {
! 46: /* shifted unshifted */
! 47: '&', '9', '@', '1', /* begin */
! 48: '&', '0', '@', '2', /* cancel */
! 49: '*', '1', '@', '4', /* command */
! 50: '*', '2', '@', '5', /* copy */
! 51: '*', '3', '@', '6', /* create */
! 52: '*', '4', 'k', 'D', /* delete char */
! 53: '*', '5', 'k', 'L', /* delete line */
! 54: '*', '7', '@', '7', /* end */
! 55: '*', '9', '@', '9', /* exit */
! 56: '*', '0', '@', '0', /* find */
! 57: '#', '1', '%', '1', /* help */
! 58: '#', '2', 'k', 'h', /* home */
! 59: '#', '3', 'k', 'I', /* insert */
! 60: '#', '4', 'k', 'l', /* left arrow */
! 61: '%', 'a', '%', '3', /* message */
! 62: '%', 'b', '%', '4', /* move */
! 63: '%', 'c', '%', '5', /* next */
! 64: '%', 'd', '%', '7', /* options */
! 65: '%', 'e', '%', '8', /* previous */
! 66: '%', 'f', '%', '9', /* print */
! 67: '%', 'g', '%', '0', /* redo */
! 68: '%', 'h', '&', '3', /* replace */
! 69: '%', 'i', 'k', 'r', /* right arrow */
! 70: '%', 'j', '&', '5', /* resume */
! 71: '!', '1', '&', '6', /* save */
! 72: '!', '2', '&', '7', /* suspend */
! 73: '!', '3', '&', '8', /* undo */
! 74: KS_EXTRA, KE_S_UP, 'k', 'u', /* up arrow */
! 75: KS_EXTRA, KE_S_DOWN, 'k', 'd', /* down arrow */
! 76:
! 77: KS_EXTRA, KE_S_F1, 'k', '1', /* F1 */
! 78: KS_EXTRA, KE_S_F2, 'k', '2',
! 79: KS_EXTRA, KE_S_F3, 'k', '3',
! 80: KS_EXTRA, KE_S_F4, 'k', '4',
! 81: KS_EXTRA, KE_S_F5, 'k', '5',
! 82: KS_EXTRA, KE_S_F6, 'k', '6',
! 83: KS_EXTRA, KE_S_F7, 'k', '7',
! 84: KS_EXTRA, KE_S_F8, 'k', '8',
! 85: KS_EXTRA, KE_S_F9, 'k', '9',
! 86: KS_EXTRA, KE_S_F10, 'k', ';', /* F10 */
! 87:
! 88: KS_EXTRA, KE_S_F11, 'F', '1',
! 89: KS_EXTRA, KE_S_F12, 'F', '2',
! 90: KS_EXTRA, KE_S_F13, 'F', '3',
! 91: KS_EXTRA, KE_S_F14, 'F', '4',
! 92: KS_EXTRA, KE_S_F15, 'F', '5',
! 93: KS_EXTRA, KE_S_F16, 'F', '6',
! 94: KS_EXTRA, KE_S_F17, 'F', '7',
! 95: KS_EXTRA, KE_S_F18, 'F', '8',
! 96: KS_EXTRA, KE_S_F19, 'F', '9',
! 97: KS_EXTRA, KE_S_F20, 'F', 'A',
! 98:
! 99: KS_EXTRA, KE_S_F21, 'F', 'B',
! 100: KS_EXTRA, KE_S_F22, 'F', 'C',
! 101: KS_EXTRA, KE_S_F23, 'F', 'D',
! 102: KS_EXTRA, KE_S_F24, 'F', 'E',
! 103: KS_EXTRA, KE_S_F25, 'F', 'F',
! 104: KS_EXTRA, KE_S_F26, 'F', 'G',
! 105: KS_EXTRA, KE_S_F27, 'F', 'H',
! 106: KS_EXTRA, KE_S_F28, 'F', 'I',
! 107: KS_EXTRA, KE_S_F29, 'F', 'J',
! 108: KS_EXTRA, KE_S_F30, 'F', 'K',
! 109:
! 110: KS_EXTRA, KE_S_F31, 'F', 'L',
! 111: KS_EXTRA, KE_S_F32, 'F', 'M',
! 112: KS_EXTRA, KE_S_F33, 'F', 'N',
! 113: KS_EXTRA, KE_S_F34, 'F', 'O',
! 114: KS_EXTRA, KE_S_F35, 'F', 'P',
! 115:
! 116: KS_EXTRA, KE_S_TAB, KS_EXTRA, KE_TAB, /* TAB */
! 117: NUL
! 118: };
! 119:
! 120: static struct key_name_entry
! 121: {
! 122: int key; /* Special key code or ascii value */
! 123: char_u *name; /* Name of key */
! 124: } key_names_table[] =
! 125: {
! 126: {' ', (char_u *)"Space"},
! 127: {TAB, (char_u *)"Tab"},
! 128: {K_TAB, (char_u *)"Tab"},
! 129: {NL, (char_u *)"NL"},
! 130: {NL, (char_u *)"NewLine"}, /* Alternative name */
! 131: {NL, (char_u *)"LineFeed"}, /* Alternative name */
! 132: {NL, (char_u *)"LF"}, /* Alternative name */
! 133: {CR, (char_u *)"CR"},
! 134: {CR, (char_u *)"Return"}, /* Alternative name */
! 135: {ESC, (char_u *)"Esc"},
! 136: {K_UP, (char_u *)"Up"},
! 137: {K_DOWN, (char_u *)"Down"},
! 138: {K_LEFT, (char_u *)"Left"},
! 139: {K_RIGHT, (char_u *)"Right"},
! 140:
! 141: {K_F1, (char_u *)"F1"},
! 142: {K_F2, (char_u *)"F2"},
! 143: {K_F3, (char_u *)"F3"},
! 144: {K_F4, (char_u *)"F4"},
! 145: {K_F5, (char_u *)"F5"},
! 146: {K_F6, (char_u *)"F6"},
! 147: {K_F7, (char_u *)"F7"},
! 148: {K_F8, (char_u *)"F8"},
! 149: {K_F9, (char_u *)"F9"},
! 150: {K_F10, (char_u *)"F10"},
! 151:
! 152: {K_F11, (char_u *)"F11"},
! 153: {K_F12, (char_u *)"F12"},
! 154: {K_F13, (char_u *)"F13"},
! 155: {K_F14, (char_u *)"F14"},
! 156: {K_F15, (char_u *)"F15"},
! 157: {K_F16, (char_u *)"F16"},
! 158: {K_F17, (char_u *)"F17"},
! 159: {K_F18, (char_u *)"F18"},
! 160: {K_F19, (char_u *)"F19"},
! 161: {K_F20, (char_u *)"F20"},
! 162:
! 163: {K_F21, (char_u *)"F21"},
! 164: {K_F22, (char_u *)"F22"},
! 165: {K_F23, (char_u *)"F23"},
! 166: {K_F24, (char_u *)"F24"},
! 167: {K_F25, (char_u *)"F25"},
! 168: {K_F26, (char_u *)"F26"},
! 169: {K_F27, (char_u *)"F27"},
! 170: {K_F28, (char_u *)"F28"},
! 171: {K_F29, (char_u *)"F29"},
! 172: {K_F30, (char_u *)"F30"},
! 173:
! 174: {K_F31, (char_u *)"F31"},
! 175: {K_F32, (char_u *)"F32"},
! 176: {K_F33, (char_u *)"F33"},
! 177: {K_F34, (char_u *)"F34"},
! 178: {K_F35, (char_u *)"F35"},
! 179:
! 180: {K_HELP, (char_u *)"Help"},
! 181: {K_UNDO, (char_u *)"Undo"},
! 182: {K_BS, (char_u *)"BS"},
! 183: {K_BS, (char_u *)"BackSpace"}, /* Alternative name */
! 184: {K_INS, (char_u *)"Insert"},
! 185: {K_INS, (char_u *)"Ins"}, /* Alternative name */
! 186: {K_DEL, (char_u *)"Del"},
! 187: {K_DEL, (char_u *)"Delete"}, /* Alternative name */
! 188: {K_HOME, (char_u *)"Home"},
! 189: {K_END, (char_u *)"End"},
! 190: {K_PAGEUP, (char_u *)"PageUp"},
! 191: {K_PAGEDOWN, (char_u *)"PageDown"},
! 192: {K_MOUSE, (char_u *)"Mouse"},
! 193: {K_LEFTMOUSE, (char_u *)"LeftMouse"},
! 194: {K_LEFTDRAG, (char_u *)"LeftDrag"},
! 195: {K_LEFTRELEASE, (char_u *)"LeftRelease"},
! 196: {K_MIDDLEMOUSE, (char_u *)"MiddleMouse"},
! 197: {K_MIDDLEDRAG, (char_u *)"MiddleDrag"},
! 198: {K_MIDDLERELEASE, (char_u *)"MiddleRelease"},
! 199: {K_RIGHTMOUSE, (char_u *)"RightMouse"},
! 200: {K_RIGHTDRAG, (char_u *)"RightDrag"},
! 201: {K_RIGHTRELEASE, (char_u *)"RightRelease"},
! 202: {K_ZERO, (char_u *)"Nul"},
! 203: {0, NULL}
! 204: };
! 205:
! 206: #define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry))
! 207:
! 208: #ifdef USE_MOUSE
! 209: static struct
! 210: {
! 211: int pseudo_code; /* Code for pseudo mouse event */
! 212: int button; /* Which mouse button is it? */
! 213: int is_click; /* Is it a mouse button click event? */
! 214: int is_drag; /* Is it a mouse drag event? */
! 215: } mouse_table[] =
! 216: {
! 217: {KE_LEFTMOUSE, MOUSE_LEFT, TRUE, FALSE},
! 218: {KE_LEFTDRAG, MOUSE_LEFT, FALSE, TRUE},
! 219: {KE_LEFTRELEASE, MOUSE_LEFT, FALSE, FALSE},
! 220: {KE_MIDDLEMOUSE, MOUSE_MIDDLE, TRUE, FALSE},
! 221: {KE_MIDDLEDRAG, MOUSE_MIDDLE, FALSE, TRUE},
! 222: {KE_MIDDLERELEASE, MOUSE_MIDDLE, FALSE, FALSE},
! 223: {KE_RIGHTMOUSE, MOUSE_RIGHT, TRUE, FALSE},
! 224: {KE_RIGHTDRAG, MOUSE_RIGHT, FALSE, TRUE},
! 225: {KE_RIGHTRELEASE, MOUSE_RIGHT, FALSE, FALSE},
! 226: {KE_IGNORE, MOUSE_RELEASE, FALSE, TRUE}, /* DRAG without CLICK */
! 227: {KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE}, /* RELEASE without CLICK */
! 228: {0, 0, 0, 0},
! 229: };
! 230: #endif /* USE_MOUSE */
! 231:
! 232: /*
! 233: * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
! 234: * modifier name ('S' for Shift, 'C' for Ctrl etc).
! 235: */
! 236: int
! 237: name_to_mod_mask(c)
! 238: int c;
! 239: {
! 240: int i;
! 241:
! 242: for (i = 0; mod_mask_table[i].mod_mask; i++)
! 243: if (TO_LOWER(c) == TO_LOWER(mod_mask_table[i].name))
! 244: return mod_mask_table[i].mod_mask;
! 245: return 0x0;
! 246: }
! 247:
! 248: /*
! 249: * Decide whether the given key code (K_*) is a shifted special
! 250: * key (by looking at mod_mask). If it is, then return the appropriate shifted
! 251: * key code, otherwise just return the character as is.
! 252: */
! 253: int
! 254: check_shifted_spec_key(c)
! 255: int c;
! 256: {
! 257: int i;
! 258: int key0;
! 259: int key1;
! 260:
! 261: if (mod_mask & MOD_MASK_SHIFT)
! 262: {
! 263: if (c == TAB) /* TAB is not in the table, K_TAB is */
! 264: return K_S_TAB;
! 265: key0 = KEY2TERMCAP0(c);
! 266: key1 = KEY2TERMCAP1(c);
! 267: for (i = 0; shifted_keys_table[i] != NUL; i += 4)
! 268: if (key0 == shifted_keys_table[i + 2] &&
! 269: key1 == shifted_keys_table[i + 3])
! 270: return TERMCAP2KEY(shifted_keys_table[i],
! 271: shifted_keys_table[i + 1]);
! 272: }
! 273: return c;
! 274: }
! 275:
! 276: /*
! 277: * Decide whether the given special key is shifted or not. If it is we
! 278: * return OK and change it to the equivalent unshifted special key code,
! 279: * otherwise we leave it as is and return FAIL.
! 280: */
! 281: int
! 282: unshift_special_key(p)
! 283: char_u *p;
! 284: {
! 285: int i;
! 286:
! 287: for (i = 0; shifted_keys_table[i]; i += 4)
! 288: if (p[0] == shifted_keys_table[i] && p[1] == shifted_keys_table[i + 1])
! 289: {
! 290: p[0] = shifted_keys_table[i + 2];
! 291: p[1] = shifted_keys_table[i + 3];
! 292: return OK;
! 293: }
! 294: return FAIL;
! 295: }
! 296:
! 297: /*
! 298: * Return a string which contains the name of the given key when the given
! 299: * modifiers are down.
! 300: */
! 301: char_u *
! 302: get_special_key_name(c, modifiers)
! 303: int c;
! 304: int modifiers;
! 305: {
! 306: static char_u string[MAX_KEY_NAME_LEN + 1];
! 307:
! 308: int i, idx;
! 309: char_u *s;
! 310: char_u name[2];
! 311:
! 312: string[0] = '<';
! 313: idx = 1;
! 314:
! 315: /* translate shifted keys into unshifted keys and set modifier */
! 316: if (IS_SPECIAL(c))
! 317: {
! 318: name[0] = KEY2TERMCAP0(c);
! 319: name[1] = KEY2TERMCAP1(c);
! 320: if (unshift_special_key(&name[0]))
! 321: modifiers |= MOD_MASK_SHIFT;
! 322: c = TERMCAP2KEY(name[0], name[1]);
! 323: }
! 324:
! 325: /* translate the modifier into a string */
! 326: for (i = 0; mod_mask_table[i].mod_mask; i++)
! 327: if (modifiers & mod_mask_table[i].mod_mask)
! 328: {
! 329: string[idx++] = mod_mask_table[i].name;
! 330: string[idx++] = (char_u)'-';
! 331: }
! 332:
! 333: /* try to find the key in the special key table */
! 334: i = find_special_key_in_table(c);
! 335: if (i < 0) /* unknown special key, output t_xx */
! 336: {
! 337: if (IS_SPECIAL(c))
! 338: {
! 339: string[idx++] = 't';
! 340: string[idx++] = '_';
! 341: string[idx++] = KEY2TERMCAP0(c);
! 342: string[idx++] = KEY2TERMCAP1(c);
! 343: }
! 344: /* Not a special key, only modifiers, output directly */
! 345: else
! 346: {
! 347: if (isprintchar(c))
! 348: string[idx++] = c;
! 349: else
! 350: {
! 351: s = transchar(c);
! 352: while (*s)
! 353: string[idx++] = *s++;
! 354: }
! 355: }
! 356: }
! 357: else /* use name of special key */
! 358: {
! 359: STRCPY(string + idx, key_names_table[i].name);
! 360: idx = STRLEN(string);
! 361: }
! 362: string[idx++] = '>';
! 363: string[idx] = NUL;
! 364: return string;
! 365: }
! 366:
! 367: /*
! 368: * Try to find key "c" in the special key table.
! 369: * Return the index when found, -1 when not found.
! 370: */
! 371: int
! 372: find_special_key_in_table(c)
! 373: int c;
! 374: {
! 375: int i;
! 376:
! 377: for (i = 0; key_names_table[i].name != NULL; i++)
! 378: if (c == key_names_table[i].key)
! 379: break;
! 380: if (key_names_table[i].name == NULL)
! 381: i = -1;
! 382: return i;
! 383: }
! 384:
! 385: /*
! 386: * Find the special key with the given name (the given string does not have to
! 387: * end with NUL, the name is assumed to end before the first non-idchar).
! 388: * If the name starts with "t_" the next two characters are interpreted as a
! 389: * termcap name.
! 390: * Return the key code, or 0 if not found.
! 391: */
! 392: int
! 393: get_special_key_code(name)
! 394: char_u *name;
! 395: {
! 396: char_u *table_name;
! 397: char_u string[3];
! 398: int i, j;
! 399:
! 400: /*
! 401: * If it's <t_xx> we get the code for xx from the termcap
! 402: */
! 403: if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
! 404: {
! 405: string[0] = name[2];
! 406: string[1] = name[3];
! 407: string[2] = NUL;
! 408: if (add_termcap_entry(string, FALSE) == OK)
! 409: return TERMCAP2KEY(name[2], name[3]);
! 410: }
! 411: else
! 412: for (i = 0; key_names_table[i].name != NULL; i++)
! 413: {
! 414: table_name = key_names_table[i].name;
! 415: for (j = 0; isidchar(name[j]) && table_name[j] != NUL; j++)
! 416: if (TO_LOWER(table_name[j]) != TO_LOWER(name[j]))
! 417: break;
! 418: if (!isidchar(name[j]) && table_name[j] == NUL)
! 419: return key_names_table[i].key;
! 420: }
! 421: return 0;
! 422: }
! 423:
! 424: char_u *
! 425: get_key_name(i)
! 426: int i;
! 427: {
! 428: if (i >= KEY_NAMES_TABLE_LEN)
! 429: return NULL;
! 430: return key_names_table[i].name;
! 431: }
! 432:
! 433: #ifdef USE_MOUSE
! 434: /*
! 435: * Look up the given mouse code to return the relevant information in the other
! 436: * arguments. Return which button is down or was released.
! 437: */
! 438: int
! 439: get_mouse_button(code, is_click, is_drag)
! 440: int code;
! 441: int *is_click;
! 442: int *is_drag;
! 443: {
! 444: int i;
! 445:
! 446: for (i = 0; mouse_table[i].pseudo_code; i++)
! 447: if (code == mouse_table[i].pseudo_code)
! 448: {
! 449: *is_click = mouse_table[i].is_click;
! 450: *is_drag = mouse_table[i].is_drag;
! 451: return mouse_table[i].button;
! 452: }
! 453: return 0; /* Shouldn't get here */
! 454: }
! 455:
! 456: /*
! 457: * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
! 458: * the given information about which mouse button is down, and whether the
! 459: * mouse was clicked, dragged or released.
! 460: */
! 461: int
! 462: get_pseudo_mouse_code(button, is_click, is_drag)
! 463: int button; /* eg MOUSE_LEFT */
! 464: int is_click;
! 465: int is_drag;
! 466: {
! 467: int i;
! 468:
! 469: for (i = 0; mouse_table[i].pseudo_code; i++)
! 470: if (button == mouse_table[i].button
! 471: && is_click == mouse_table[i].is_click
! 472: && is_drag == mouse_table[i].is_drag)
! 473: {
! 474: return mouse_table[i].pseudo_code;
! 475: }
! 476: return KE_IGNORE; /* not recongnized, ignore it */
! 477: }
! 478: #endif /* USE_MOUSE */