1 /*
2 * Symbol table stuff.
3 * Symbol tables, and keymap setup.
4 * The terminal specific parts of building the
5 * keymap has been moved to a better place.
6 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include "def.h"
10
11 void keyadd ();
12 void keydup ();
13
14
15 extern char MSG_byte_shift[];
16 extern char MSG_back_char[];
17 extern char MSG_quit[];
18 extern char MSG_forw_del_char[];
19 extern char MSG_toggle_swap[];
20 extern char MSG_forw_char[];
21 extern char MSG_abort[];
22 extern char MSG_ins_self[];
23 extern char MSG_back_del_char[];
24 extern char MSG_refresh[];
25 extern char MSG_forw_line[];
26 extern char MSG_back_line[];
27 extern char MSG_quote[];
28 extern char MSG_recall[];
29 extern char MSG_twiddle[];
30 extern char MSG_forw_page[];
31 extern char MSG_kill_region[];
32 extern char MSG_yank[];
33 extern char MSG_down_window[];
34 extern char MSG_ins_toggle[];
35 extern char MSG_display_buffers[];
36 extern char MSG_quit[];
37 extern char MSG_exit_flush_all[];
38 extern char MSG_set_file_name[];
39 extern char MSG_file_insert[];
40 extern char MSG_buf_size_lock[];
41 extern char MSG_flush_all[];
42 extern char MSG_down_window[];
43 extern char MSG_up_window[];
44 extern char MSG_file_read[];
45 extern char MSG_file_save[];
46 extern char MSG_file_visit[];
47 extern char MSG_file_write[];
48 extern char MSG_swap_dot_and_mark[];
49 extern char MSG_shrink_window[];
50 extern char MSG_display_position[];
51 extern char MSG_start_macro[];
52 extern char MSG_end_macro[];
53 extern char MSG_help[];
54 extern char MSG_only_window[];
55 extern char MSG_del_window[];
56 extern char MSG_split_window[];
57 extern char MSG_use_buffer[];
58 extern char MSG_spawn_cli[];
59 extern char MSG_execute_macro[];
60 extern char MSG_goto_line[];
61 extern char MSG_ins_unit[];
62 extern char MSG_kill_buffer[];
63 extern char MSG_load_bindings[];
64 extern char MSG_forw_window[];
65 extern char MSG_back_window[];
66 extern char MSG_view_file[];
67 extern char MSG_enlarge_window[];
68 extern char MSG_ascii_mode[];
69 extern char MSG_binary_mode[];
70 extern char MSG_buffer_name[];
71 extern char MSG_decimal_mode[];
72 extern char MSG_ebcdic_mode[];
73 #if FLOAT_DISP
74 extern char MSG_float_mode[];
75 #endif
76 extern char MSG_hex_mode[];
77 extern char MSG_back_del_unit[];
78 extern char MSG_octal_mode[];
79 extern char MSG_display_version[];
80 extern char MSG_unit_size1[];
81 extern char MSG_unit_size2[];
82 extern char MSG_unit_size4[];
83 extern char MSG_unit_size8[];
84 extern char MSG_reposition_window[];
85 extern char MSG_set_mark[];
86 extern char MSG_goto_eob[];
87 extern char MSG_goto_bob[];
88 extern char MSG_next_buff[];
89 extern char MSG_prev_buff[];
90 extern char MSG_query_replace[];
91 extern char MSG_display_bindings[];
92 extern char MSG_auto_save[];
93 extern char MSG_back_unit[];
94 extern char MSG_compare[];
95 extern char MSG_forw_del_unit[];
96 extern char MSG_forw_unit[];
97 extern char MSG_link_windows[];
98 extern char MSG_print[];
99 extern char MSG_back_search[];
100 extern char MSG_forw_search[];
101 extern char MSG_back_page[];
102 extern char MSG_copy_region[];
103 extern char MSG_extended_command[];
104 extern char MSG_up_window[];
105 extern char MSG_search_again[];
106 extern char MSG_bind_to_key[];
107 extern char MSG_file_visit_split[];
108 extern char MSG_yank_buffer[];
109 extern char MSG_save_region[];
110 extern char MSG_use_buffer_split[];
111 extern char MSG_no_f_tb[];
112 extern char MSG_n_split[];
113 extern char MSG_n_combine[];
114 extern char MSG_show_save_buf[];
115 extern char MSG_scr_row[];
116
117 /*
118 * Defined by "main.c".
119 */
120 extern char ctrlg (); /* Abort out of things */
121 extern char quit (); /* Quit */
122 extern char ctlxlp (); /* Begin macro */
123 extern char ctlxrp (); /* End macro */
124 extern char ctlxe (); /* Execute macro */
125 extern char showversion (); /* Show version numbers, etc. */
126 extern char flushnquit (); /* Flush buffers & exit (fitz) */
127 extern char flush_all (); /* Flush buffers (jam) */
128 extern char autosave (); /* autosave function (jam) */
129
130 /*
131 * Defined by "search.c".
132 */
133 extern char forwsearch (); /* Search forward */
134 extern char backsearch (); /* Search backwards */
135 extern char searchagain (); /* Repeat last search command */
136 extern char queryrepl (); /* Query replace */
137 extern char compare (); /* Compare two windows */
138 extern char recall (); /* Recall last search string */
139
140 /*
141 * Defined by "basic.c".
142 */
143 extern char backchar (); /* Move backward by characters */
144 extern char forwchar (); /* Move forward by characters */
145 extern char gotobob (); /* Move to start of buffer */
146 extern char gotoeob (); /* Move to end of buffer */
147 extern char forwline (); /* Move forward by lines */
148 extern char backline (); /* Move backward by lines */
149 extern char forwpage (); /* Move forward by pages */
150 extern char backpage (); /* Move backward by pages */
151 extern char setmark (); /* Set mark */
152 extern char swapmark (); /* Swap "." and mark */
153 extern char gotoline (); /* Go to a specified line. */
154
155 /*
156 * Defined by "buffer.c".
157 */
158 extern char listbuffers (); /* Display list of buffers */
159 extern char showsavebuf (); /* Show the save buffer contents */
160 extern char usebuffer (); /* Switch a window to a buffer */
161 extern char use_buffer (); /* ditto, plus window split */
162 extern char killbuffer (); /* Make a buffer go away. */
163 extern char next_buf (); /* goto next buffer */
164 extern char prev_buf (); /* goto prev buffer */
165 extern char yank_buffer (); /* yank buffer by name */
166 extern char buffername (); /* change buffer name */
167 extern char bufsizlock (); /* lock buffer size */
168
169 /*
170 * Defined by "file."
171 */
172 extern char fileread (); /* Get a file, read only */
173 extern char filevisit (); /* Get a file, read write */
174 extern char file_visit (); /* ditto , plus window split */
175 extern char filewrite (); /* Write a file */
176 extern char filesave (); /* Save current file */
177 extern char filename (); /* Adjust file name */
178 extern char fileinsert (); /* insert file to cursor (jam ) */
179 extern char viewfile (); /* readonly file visit (jam) */
180
181 /*
182 * Defined by "random.c".
183 */
184
185 extern char dispshift (); /* Increment display shift */
186 extern char selfinsert (); /* Insert character */
187 extern char insert_toggle (); /* toggle insert mode (jam) */
188 extern char insertunit (); /* insert unit (pvr) */
189 extern char showcpos (); /* Show the cursor position */
190 extern char twiddle (); /* Twiddle units */
191 extern char forwdel (); /* Forward delete */
192 extern char backdel (); /* Backward delete */
193 extern char quote (); /* Insert literal */
194 extern char asciimode (); /* display ASCII data */
195 extern char ebcdicmode (); /* display EBCDIC data */
196 extern char decimalmode (); /* display DECIMAL data */
197 #if FLOAT_DISP
198 extern char floatmode (); /* display FLOATING POINT data */
199 #endif
200 extern char hexmode (); /* display HEX data */
201 extern char octalmode (); /* display OCTAL data */
202 extern char binarymode (); /* display BINARY data */
203 extern char dispsize1 (); /* display in BYTE format */
204 extern char dispsize2 (); /* display in WORD format */
205 extern char dispsize4 (); /* display in DWORD format*/
206 extern char dispsize8 (); /* display in DOUBLE format*/
207 extern char dispswapbyte (); /* Display swaped bytes pvr */
208 extern char yank (); /* Yank back from killbuffer. */
209 extern char linkwind (); /* Link all windows on one buffer. */
210 extern char n_way_split (); /* Split buffer into n buffers. */
211 extern char n_way_combine (); /* Combine n buffers into one. */
212
213 /*
214 * Defined by "region.c".
215 */
216 extern char killregion (); /* Kill region. */
217 extern char copyregion (); /* Copy region to kill buffer. */
218 extern char save_region (); /* Save region in named buffer. */
219
220 /*
221 * Defined by "spawn.c".
222 */
223 extern char spawncli (); /* Run CLI in a subjob. */
224 extern char clock (); /* display time in modeline */
225
226 /*
227 * Defined by "window.c".
228 */
229 extern char reposition (); /* Reposition window */
230 extern char refresh (); /* Refresh the screen */
231 extern char nextwind (); /* Move to the next window */
232 extern char prevwind (); /* Move to the previous window */
233 extern char mvdnwind (); /* Move window down */
234 extern char mvupwind (); /* Move window up */
235 extern char onlywind (); /* Make current window only one */
236 extern char delwind (); /* Delete current window */
237 extern char splitwind (); /* Split current window */
238 extern char enlargewind (); /* Enlarge display window. */
239 extern char shrinkwind (); /* Shrink window. */
240 extern char screen_rows (); /* Set the screen size */
241
242 /*
243 * Defined by "word.c".
244 */
245 extern char backunit (); /* Backup by units */
246 extern char forwunit (); /* Advance by units */
247 extern char delfunit (); /* Delete forward unit. */
248 extern char delbunit (); /* Delete backward unit. */
249
250 /*
251 * Defined by "extend.c".
252 */
253 extern char extend (); /* Extended commands. */
254 extern char help (); /* Help key. */
255 extern char bindtokey (); /* Modify key bindings. */
256 extern char wallchart (); /* Make wall chart. */
257 extern void check_extend (); /* load extended key file */
258 extern char load_extend (); /* load extended file by name */
259
260 /*
261 * Defined by "display.c
262 */
263 extern char print (); /* print window from mark to dot */
264
265 typedef struct
266 {
267 short k_key; /* Key to bind. */
268 char (*k_funcp) (); /* Function. */
269 char *k_name; /* Function name string. */
270 char k_modify; /* modify bit */
271 } KEY;
272
273 /*
274 * Default key binding table. This contains
275 * the function names, the symbol table name, and (possibly)
276 * a key binding for the builtin functions. There are no
277 * bindings for C-U or C-X. These are done with special
278 * code, but should be done normally.
279 */
280 KEY key[] =
281 {
282 { KCTRL | 'A', dispshift, MSG_byte_shift, 0 },
283 { KCTRL | 'B', backchar, MSG_back_char, SSRCH | SRPLC },
284 { KCTRL | 'C', quit, MSG_quit, 0 }, /* pvr */
285 { KCTRL | 'D', forwdel, MSG_forw_del_char, SMOD | SSIZE | SSRCH | SRPLC },
286 { KCTRL | 'E', dispswapbyte, MSG_toggle_swap, SSRCH | SRPLC }, /* pvr */
287 { KCTRL | 'F', forwchar, MSG_forw_char, SSRCH | SRPLC },
288 { KCTRL | 'G', ctrlg, MSG_abort, SSRCH | SRPLC },
289 { KCTRL | 'I', selfinsert, MSG_ins_self, SMOD | SSRCH | SRPLC },
290 { KCTRL | 'H', backdel, MSG_back_del_char, SMOD | SSIZE | SSRCH | SRPLC },
291 { KCTRL | 'L', refresh, MSG_refresh, SSRCH | SRPLC },
292 { KCTRL | 'N', forwline, MSG_forw_line, SSRCH | SRPLC },
293 { KCTRL | 'P', backline, MSG_back_line, SSRCH | SRPLC },
294 { KCTRL | 'Q', quote, MSG_quote, 0 },
295 { KCTRL | 'R', recall, MSG_recall, SSRCH | SRPLC },
296 { KCTRL | 'T', twiddle, MSG_twiddle, SMOD | SSRCH | SRPLC },
297 { KCTRL | 'V', forwpage, MSG_forw_page, SRPLC },
298 { KCTRL | 'W', killregion, MSG_kill_region, SMOD | SSIZE },
299 { KCTRL | 'Y', yank, MSG_yank, SMOD | SSIZE },
300 { KCTRL | 'Z', mvdnwind, MSG_down_window, 0 }, /* fitz */
301 { KCTLX | KCTRL | 'A', insert_toggle, MSG_ins_toggle, SSRCH | SRPLC },
302 { KCTLX | KCTRL | 'B', listbuffers, MSG_display_buffers, 0 },
303 { KCTLX | KCTRL | 'C', quit, MSG_quit, 0 },
304 { KCTLX | KCTRL | 'E', flushnquit, MSG_exit_flush_all, 0 }, /* fitz */
305 { KCTLX | KCTRL | 'F', filename, MSG_set_file_name, SMOD }, /* jam */
306 { KCTLX | KCTRL | 'I', fileinsert, MSG_file_insert, SMOD | SSIZE },
307 { KCTLX | KCTRL | 'L', bufsizlock, MSG_buf_size_lock, 0 },
308 { KCTLX | KCTRL | 'M', flush_all, MSG_flush_all, 0 },
309 { KCTLX | KCTRL | 'N', mvdnwind, MSG_down_window, 0 },
310 { KCTLX | KCTRL | 'P', mvupwind, MSG_up_window, 0 },
311 { KCTLX | KCTRL | 'R', fileread, MSG_file_read, 0 },
312 { KCTLX | KCTRL | 'S', filesave, MSG_file_save, 0 },
313 { KCTLX | KCTRL | 'V', filevisit, MSG_file_visit, 0 },
314 { KCTLX | KCTRL | 'W', filewrite, MSG_file_write, 0 },
315 { KCTLX | KCTRL | 'X', swapmark, MSG_swap_dot_and_mark, 0 },
316 { KCTLX | KCTRL | 'Z', shrinkwind, MSG_shrink_window, 0 },
317 { KCTLX | '=', showcpos, MSG_display_position, 0 },
318 { KCTLX | '(', ctlxlp, MSG_start_macro, 0 },
319 { KCTLX | ')', ctlxrp, MSG_end_macro, 0 },
320 { KCTLX | '?', help, MSG_help, 0 },
321 { KCTLX | '0', delwind, MSG_del_window, 0 },
322 { KCTLX | '1', onlywind, MSG_only_window, 0 },
323 { KCTLX | '2', splitwind, MSG_split_window, 0 },
324 { KCTLX | 'B', usebuffer, MSG_use_buffer, 0 },
325 { KCTLX | 'C', spawncli, MSG_spawn_cli, 0 }, /* fitz */
326 { KCTLX | 'E', ctlxe, MSG_execute_macro, 0 },
327 { KCTLX | 'G', gotoline, MSG_goto_line, 0 },
328 { KCTLX | 'I', insertunit, MSG_ins_unit, SMOD | SSIZE | SSRCH | SRPLC },
329 { KCTLX | 'K', killbuffer, MSG_kill_buffer, 0 },
330 { KCTLX | 'L', load_extend, MSG_load_bindings, 0 },
331 { KCTLX | 'N', nextwind, MSG_forw_window, 0 },
332 { KCTLX | 'P', prevwind, MSG_back_window, 0 },
333 { KCTLX | 'V', viewfile, MSG_view_file, 0 }, /* jam */
334 { KCTLX | 'Z', enlargewind, MSG_enlarge_window, 0 },
335 { KMETA | KCTRL | 'A', asciimode, MSG_ascii_mode, SSRCH | SRPLC }, /* pvr */
336 { KMETA | KCTRL | 'B', binarymode, MSG_binary_mode, SSRCH | SRPLC }, /* pvr */
337 { KMETA | KCTRL | 'D', decimalmode, MSG_decimal_mode, SSRCH | SRPLC }, /* pvr */
338 { KMETA | KCTRL | 'E', ebcdicmode, MSG_ebcdic_mode, SSRCH | SRPLC }, /* pvr */
339 #if FLOAT_DISP
340 { KMETA | KCTRL | 'F', floatmode, MSG_float_mode, SSRCH | SRPLC }, /* pvr */
341 #endif
342 { KMETA | KCTRL | 'H', hexmode, MSG_hex_mode, SSRCH | SRPLC }, /* pvr */
343 { KMETA | KCTRL | 'K', delbunit, MSG_back_del_unit, SMOD | SSIZE | SSRCH | SRPLC },
344 { KMETA | KCTRL | 'N', buffername, MSG_buffer_name, 0 },
345 { KMETA | KCTRL | 'O', octalmode, MSG_octal_mode, SSRCH | SRPLC }, /* pvr */
346 { KMETA | KCTRL | 'P', n_way_combine, MSG_n_combine, SSIZE | SMOD }, /* pvr */
347 { KMETA | KCTRL | 'R', screen_rows, MSG_scr_row, 0 }, /* pvr */
348 { KMETA | KCTRL | 'S', n_way_split, MSG_n_split, 0 }, /* pvr */
349 { KMETA | KCTRL | 'V', showversion, MSG_display_version, 0 },
350 { KMETA | KCTRL | 'W', showsavebuf, MSG_show_save_buf, 0 },
351 { KMETA | '1', dispsize1, MSG_unit_size1, SSRCH | SRPLC }, /* pvr */
352 { KMETA | '2', dispsize2, MSG_unit_size2, SSRCH | SRPLC }, /* pvr */
353 { KMETA | '4', dispsize4, MSG_unit_size4, SSRCH | SRPLC }, /* pvr */
354 { KMETA | '8', dispsize8, MSG_unit_size8, SSRCH | SRPLC }, /* pvr */
355 { KMETA | '!', reposition, MSG_reposition_window, 0 },
356 { KMETA | '.', setmark, MSG_set_mark, 0 },
357 { KMETA | '>', gotoeob, MSG_goto_eob, SSRCH | SRPLC },
358 { KMETA | '<', gotobob, MSG_goto_bob, SSRCH | SRPLC },
359 { KMETA | '+', next_buf, MSG_next_buff, 0 },
360 { KMETA | '-', prev_buf, MSG_prev_buff, 0 },
361 { KMETA | '%', queryrepl, MSG_query_replace, SMOD },
362 { KMETA | '?', wallchart, MSG_display_bindings, 0 },
363 { KMETA | 'A', autosave, MSG_auto_save, 0 },
364 { KMETA | 'B', backunit, MSG_back_unit, SSRCH | SRPLC },
365 { KMETA | 'C', compare, MSG_compare, 0 },
366 { KMETA | 'D', delfunit, MSG_forw_del_unit, SMOD | SSIZE | SSRCH | SRPLC },
367 { KMETA | 'F', forwunit, MSG_forw_unit, SSRCH | SRPLC },
368 { KMETA | 'G', use_buffer, MSG_use_buffer_split, 0 },
369 { KMETA | 'K', bindtokey, MSG_bind_to_key, 0 },
370 { KMETA | 'L', linkwind, MSG_link_windows, 0 },
371 { KMETA | 'O', save_region, MSG_save_region, 0 },
372 { KMETA | 'P', print, MSG_print, 0 },
373 { KMETA | 'R', backsearch, MSG_back_search, 0 },
374 { KMETA | 'S', forwsearch, MSG_forw_search, 0 },
375 { KMETA | 'T', searchagain, MSG_search_again, 0 },
376 { KMETA | 'U', file_visit, MSG_file_visit_split, 0 },
377 { KMETA | 'V', backpage, MSG_back_page, SRPLC },
378 { KMETA | 'W', copyregion, MSG_copy_region, 0 },
379 { KMETA | 'X', extend, MSG_extended_command, 0 },
380 { KMETA | 'Y', yank_buffer, MSG_yank_buffer, SMOD | SSIZE },
381 { KMETA | 'Z', mvupwind, MSG_up_window, 0 }
382 };
383
384 #define NKEY (sizeof(key) / sizeof(key[0]))
385
386 /*
387 * Symbol table lookup.
388 * Return a pointer to the SYMBOL node, or NULL if
389 * the symbol is not found.
390 */
391 SYMBOL *
symlookup(cp)392 symlookup (cp)
393 register char *cp;
394 {
395 register SYMBOL *sp;
396
397 sp = symbol[symhash (cp)];
398 while (sp != NULL)
399 {
400 if (strcmp (cp, sp->s_name) == 0)
401 return (sp);
402 sp = sp->s_symp;
403 }
404 return (NULL);
405 }
406
407 /*
408 * Take a string, and compute the symbol table
409 * bucket number. This is done by adding all of the characters
410 * together, and taking the sum mod NSHASH. The string probably
411 * should not contain any GR characters; if it does the "*cp"
412 * may get a nagative number on some machines, and the "%"
413 * will return a negative number!
414 */
415 int
symhash(cp)416 symhash (cp)
417 register char *cp;
418 {
419 register int c;
420 register int n;
421
422 n = 0;
423 while ((c = *cp++) != 0)
424 n += c;
425 return (n % NSHASH);
426 }
427
428 /*
429 * Build initial keymap. The funny keys
430 * (commands, odd control characters) are mapped using
431 * a big table and calls to "keyadd". The printing characters
432 * are done with some do-it-yourself handwaving. The terminal
433 * specific keymap initialization code is called at the
434 * very end to finish up. All errors are fatal.
435 */
436 void
keymapinit()437 keymapinit ()
438 {
439 register SYMBOL *sp;
440 register KEY *kp;
441 register int i;
442
443 for (i = 0; i < NKEYS; ++i)
444 binding[i] = NULL;
445 for (kp = &key[0]; kp < &key[NKEY]; ++kp)
446 keyadd (kp->k_key, kp->k_funcp, kp->k_name, kp->k_modify);
447 keydup (KCTLX | KCTRL | 'G', MSG_abort);
448 keydup (KMETA | KCTRL | 'G', MSG_abort);
449 keydup (0x7F, MSG_back_del_char);
450 keydup (KMETA | 'Q', MSG_quote);
451 keydup (KMETA | 0x7F, MSG_back_del_unit);
452 /*
453 * Should be bound by "tab" already.
454 */
455 if ((sp = symlookup (MSG_ins_self)) == NULL)
456 abort ();
457 for (i = 0x20; i < 0x7F; ++i)
458 {
459 if (binding[i] != NULL)
460 abort ();
461 binding[i] = sp;
462 ++sp->s_nkey;
463 }
464 ttykeymapinit ();
465 }
466
467 /*
468 * Create a new builtin function "name"
469 * with function "funcp". If the "new" is a real
470 * key, bind it as a side effect. All errors
471 * are fatal.
472 */
473 void
keyadd(new,funcp,name,modify)474 keyadd (new, funcp, name, modify)
475 short new;
476 #ifdef NOPROTO
477 bool (*funcp) ();
478 #else
479 bool (*funcp) (void);
480 #endif
481 char *name;
482 int modify;
483 {
484 register SYMBOL *sp;
485 register int hash;
486
487 if ((sp = (SYMBOL *) malloc (sizeof (SYMBOL))) == NULL)
488 abort ();
489 hash = symhash (name);
490 sp->s_symp = symbol[hash];
491 symbol[hash] = sp;
492 sp->s_nkey = 0;
493 sp->s_name = name;
494 sp->s_funcp = funcp;
495 sp->s_modify = modify;
496 if (new >= 0)
497 {
498 /* Bind this key. */
499 if (binding[new] != NULL)
500 abort ();
501 binding[new] = sp;
502 ++sp->s_nkey;
503 }
504 }
505
506 /*
507 * Bind key "new" to the existing
508 * routine "name". If the name cannot be found,
509 * or the key is already bound, abort.
510 */
511 void
keydup(new,name)512 keydup (new, name)
513 register int new;
514 char *name;
515 {
516 register SYMBOL *sp;
517
518 if (binding[new] != NULL || (sp = symlookup (name)) == NULL)
519 {
520 printf (MSG_no_f_tb, name);
521 abort ();
522 }
523 binding[new] = sp;
524 ++sp->s_nkey;
525 }
526