Annotation of src/usr.bin/vim/tables.c, Revision 1.1.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 */