1 /*======================================================================*\
2 |* Editor mined *|
3 |* Function key dispatcher *|
4 \*======================================================================*/
5
6 #include "mined.h"
7 #include "charprop.h"
8 #include "io.h"
9
10
11 /*======================================================================*\
12 |* Debug function dispatching *|
13 \*======================================================================*/
14
15 #define dont_debug_dispatch
16
17 #ifdef debug_dispatch
18 #define trace_dispatch(func) do_debug_dispatch (func)
19 #else
20 #define trace_dispatch(func)
21 #endif
22
23 #ifdef debug_dispatch
24 static
25 void
do_debug_dispatch(func)26 do_debug_dispatch (func)
27 char * func;
28 {
29 if (keyshift & applkeypad_mask) {
30 printf ("appl-keypad ");
31 }
32 if (keyshift & ctrl_mask) {
33 printf ("ctrl-");
34 }
35 if (keyshift & alt_mask) {
36 printf ("alt-");
37 }
38 if (keyshift & shift_mask) {
39 printf ("shift-");
40 }
41 printf ("%s\n", func);
42 }
43 #endif
44
45
46 /*======================================================================*\
47 |* Dispatch function keys and some keypad keys to mined functions *|
48 \*======================================================================*/
49
50 /**
51 HOMEkey () is invoked by a Home key on the right (application) keypad;
52 function configurable
53 */
54 void
HOMEkey()55 HOMEkey ()
56 {
57 trace_dispatch ("Home");
58
59 if (! (keyshift & altctrlshift_mask) && home_selection) {
60 MARK ();
61 return;
62 }
63
64 if (shift_selection) {
65 if (keyshift & alt_mask) {
66 keyshift &= ~ alt_mask;
67 } else if (apply_shift_selection) {
68 trigger_highlight_selection ();
69
70 if (keyshift & ctrl_mask) {
71 keyshift = 0;
72 BFILE ();
73 } else {
74 BLINEORUP ();
75 }
76 return;
77 }
78 }
79
80 #ifdef weird_stuff_disabling_alt_in_xterm
81 if ((keyshift & (alt_mask | applkeypad_mask)) == alt_mask) {
82 smallHOMEkey ();
83 return;
84 }
85 #endif
86
87 if (keyshift & shift_mask) {
88 keyshift = 0;
89 MARK ();
90 } else if (keyshift & ctrl_mask) {
91 keyshift = 0;
92 BLINEORUP ();
93 } else {
94 if (mined_keypad == ! (keyshift & alt_mask)) {
95 MARK ();
96 } else {
97 BLINEORUP ();
98 }
99 }
100 }
101
102 /**
103 smallHOMEkey () is invoked by a Home key on the small keypad;
104 function configurable
105 */
106 void
smallHOMEkey()107 smallHOMEkey ()
108 {
109 trace_dispatch ("smallHome");
110
111 if (! (keyshift & altctrlshift_mask) &&
112 (small_home_selection || (shift_selection && ! mined_keypad))) {
113 MARK ();
114 return;
115 }
116
117 if (shift_selection) {
118 if (keyshift & alt_mask) {
119 keyshift &= ~ alt_mask;
120 } else if (apply_shift_selection) {
121 trigger_highlight_selection ();
122
123 if (keyshift & ctrl_mask) {
124 keyshift = 0;
125 BFILE ();
126 } else {
127 BLINEORUP ();
128 }
129 return;
130 }
131 }
132
133 if (keyshift & shift_mask) {
134 keyshift = 0;
135 MARK ();
136 } else if (keyshift & ctrl_mask) {
137 keyshift = 0;
138 MOVLBEG ();
139 } else {
140 if (mined_keypad == ! (keyshift & alt_mask)) {
141 BLINEORUP ();
142 } else {
143 MARK ();
144 }
145 }
146 }
147
148 /**
149 ENDkey () is invoked by an End key on the right (application) keypad;
150 function configurable
151 */
152 void
ENDkey()153 ENDkey ()
154 {
155 trace_dispatch ("End");
156
157 if (! (keyshift & altctrlshift_mask) && home_selection) {
158 COPY ();
159 return;
160 }
161
162 if (shift_selection) {
163 if (keyshift & alt_mask) {
164 keyshift &= ~ alt_mask;
165 } else if (apply_shift_selection) {
166 trigger_highlight_selection ();
167
168 if (keyshift & ctrl_mask) {
169 keyshift = 0;
170 EFILE ();
171 } else {
172 ELINEORDN ();
173 }
174 return;
175 }
176 }
177
178 #ifdef weird_stuff_disabling_alt_in_xterm
179 if ((keyshift & (alt_mask | applkeypad_mask)) == alt_mask) {
180 smallENDkey ();
181 return;
182 }
183 #endif
184
185 if (keyshift & shift_mask) {
186 keyshift = 0;
187 COPY ();
188 } else if (keyshift & ctrl_mask) {
189 keyshift = 0;
190 ELINEORDN ();
191 } else {
192 if (mined_keypad == ! (keyshift & alt_mask)) {
193 COPY ();
194 } else {
195 ELINEORDN ();
196 }
197 }
198 }
199
200 /**
201 smallENDkey () is invoked by an End key on the small keypad;
202 function configurable
203 */
204 void
smallENDkey()205 smallENDkey ()
206 {
207 trace_dispatch ("smallEnd");
208
209 if (! (keyshift & altctrlshift_mask) &&
210 (small_home_selection || (shift_selection && ! mined_keypad))) {
211 COPY ();
212 return;
213 }
214
215 if (shift_selection) {
216 if (keyshift & alt_mask) {
217 keyshift &= ~ alt_mask;
218 } else if (apply_shift_selection) {
219 trigger_highlight_selection ();
220
221 if (keyshift & ctrl_mask) {
222 keyshift = 0;
223 EFILE ();
224 } else {
225 ELINEORDN ();
226 }
227 return;
228 }
229 }
230
231 if (keyshift & shift_mask) {
232 keyshift = 0;
233 COPY ();
234 } else if (keyshift & ctrl_mask) {
235 keyshift = 0;
236 MOVLEND ();
237 } else {
238 if (mined_keypad == ! (keyshift & alt_mask)) {
239 ELINEORDN ();
240 } else {
241 COPY ();
242 }
243 }
244 }
245
246
247 #define not_alt_del_always_deletes_char
248 #define alt_alt_may_delete_char
249
250 #ifdef alt_del_always_deletes_char
251 #define cut_cond (mined_keypad && ! (keyshift & (alt_mask | applkeypad_mask)))
252 #else
253 #ifdef alt_alt_may_delete_char
254 #define cut_cond (mined_keypad == ! (keyshift & alt_mask))
255 #else
256 #define cut_cond (mined_keypad == ! ((keyshift & (alt_mask | applkeypad_mask)) == (alt_mask | applkeypad_mask)))
257 #endif
258 #endif
259
260 /**
261 DELkey () is invoked by a Delete function key,
262 often KP_Delete on right keypad;
263 function configurable
264 */
265 void
DELkey()266 DELkey ()
267 {
268 trace_dispatch ("Delete");
269
270 if ((keyshift & ctrl_mask) && ! (keyshift & alt_mask)) {
271 /*keyshift = 0;*/
272 DCC ();
273 } else if ((keyshift & shift_mask) && ! (keyshift & alt_mask)) {
274 keyshift = 0;
275 CUT ();
276 } else {
277 #ifdef oldstyle_DELkey
278 /*
279 mined_keypad alt_mask applkeypad_mask alt-KP alt-DEL alt-ALT
280 1 0 0 cut ! cut cut
281 1 0 1 * * *
282 1 1 0 cut del del
283 1 1 1 del del del
284 0 0 0 del ! del del
285 0 0 1 * * *
286 0 1 0 del del cut
287 0 1 1 cut del cut
288 */
289 if (cut_cond) {
290 CUT ();
291 } else {
292 DCC ();
293 }
294 #else
295 if (has_active_selection ()) {
296 if (keyshift & alt_mask) {
297 DCC ();
298 } else {
299 CUT ();
300 }
301 } else {
302 if (keyshift & alt_mask) {
303 CUT ();
304 } else {
305 DCC ();
306 }
307 }
308 #endif
309 }
310 }
311
312 /**
313 smallDELkey () is invoked by the small keypad ("extended") Delete key
314 */
315 void
smallDELkey()316 smallDELkey ()
317 {
318 trace_dispatch ("smallDelete");
319
320 keyshift |= ctrl_mask;
321 DELkey ();
322 }
323
324 /**
325 DELchar () is invoked by a DEL character unless reconfigured to
326 map to DPC;
327 the key may be a Delete function key (on small keypad, if so configured),
328 or the Backarrow key (unless configured to emit the BackSpace character)
329 */
330 void
DELchar()331 DELchar ()
332 {
333 trace_dispatch ("DEL");
334
335 if (keyshift & shift_mask) {
336 keyshift = 0;
337 CUT ();
338 } else if (keyshift & ctrl_mask) {
339 DCC ();
340 } else {
341 if (hop_flag > 0 || keyshift & alt_mask) {
342 hop_flag = 0;
343 CUT ();
344 } else {
345 DCC ();
346 }
347 }
348 }
349
350 void
INSkey()351 INSkey ()
352 {
353 trace_dispatch ("Insert");
354
355 if (! hop_flag && (keyshift & alt_mask)) {
356 keyshift = 0;
357 YANKRING ();
358 } else if (keyshift & ctrl_mask) {
359 PASTEstay ();
360 } else {
361 PASTE ();
362 }
363 }
364
365 /**
366 smallINSkey () is invoked by the small keypad ("extended") Insert key
367 */
368 void
smallINSkey()369 smallINSkey ()
370 {
371 trace_dispatch ("smallInsert");
372
373 keyshift |= ctrl_mask;
374 INSkey ();
375 }
376
377
378 /**
379 Keypad keys with special functions
380 */
381 void
KP_plus()382 KP_plus ()
383 {
384 if (keyshift & (ctrl_mask | shift_mask)) {
385 if ((keyshift & altctrlshift_mask) == altctrlshift_mask) {
386 screenmorecols ();
387 } else if ((keyshift & altctrlshift_mask) == ctrlshift_mask) {
388 screenmorelines ();
389 } else {
390 fontbigger ();
391 }
392 } else {
393 SD ();
394 }
395 }
396
397 void
KP_minus()398 KP_minus ()
399 {
400 if (keyshift & (ctrl_mask | shift_mask)) {
401 if ((keyshift & altctrlshift_mask) == altctrlshift_mask) {
402 screenlesscols ();
403 } else if ((keyshift & altctrlshift_mask) == ctrlshift_mask) {
404 screenlesslines ();
405 } else {
406 fontsmaller ();
407 }
408 } else {
409 SU ();
410 }
411 }
412
413 /**
414 Display function key help lines
415 */
416 static voidfunc fhelp_func = F1;
417 static char fhelp_keyshift = 0;
418
419 void
display_FHELP()420 display_FHELP ()
421 {
422 /* use the following screen attributes:
423 unicode indicator (cyan background)
424 highlight (red background)
425 reverse
426 plain (normal)
427 */
428 if (fhelp_func == COMPOSE) {
429 status_uni ("ctrl- , ¸/ͺ . ˙/῾ :/\" ¨ ; ˛ ' ´tonos ´ oxia - ¯ < ̌/᾿ ( ˘ ) ̑ & hook ^ ~ ` / °");
430 } else if (fhelp_func == key_1) {
431 if (fhelp_keyshift == altctrl_mask) {
432 status_uni ("alt-ctrl- 1 ˘/ ̛ + ´ 2 ˘/ ̛ + ` 3 ˘/ ̛ + ̉ 4 ˘/ ̛ + ~ 5 ˘/ ̛ + ̣ 6 ῞ 7 ῝ 8 ῟ 9 0 ");
433 } else if (fhelp_keyshift == ctrl_mask) {
434 status_uni ("ctrl- 1 ´ 2 ` 3 ̉ 4 ~ 5 ̣ 6 ^ 7 ˘ 8 ̛ 9 / 0 °");
435 } else {
436 status_uni ("alt- 1 ^ + ´ 2 ^ + ` 3 ^ + ̉ 4 ^ + ~ 5 ^ + ̣ 6 ῎ 7 ῍ 8 ῏ 9 0 ");
437 }
438 } else {
439 if ((fhelp_keyshift & altctrlshift_mask) == altshift_mask) {
440 status_uni ("alt-shift- F4 Kill window! F5 ˘ F6 ˙");
441 } else if ((fhelp_keyshift & altctrlshift_mask) == ctrlshift_mask) {
442 status_uni ("ctrl-shift- F5 ˛ F6 ¯ F8 LineRepl F9 FindChar");
443 } else if (fhelp_keyshift & alt_mask) {
444 status_uni ("alt- F2 SaveAs F4 Kill window! F8 SearchBack F9 NextBack F10 FlagMenu");
445 } else if (fhelp_keyshift & ctrl_mask) {
446 status_uni ("ctrl- F2 SaveTo F4 PastePrev F5 °/¸ F6 ^ F8 Subst/Confirm F10 InfoMenu");
447 } else if (fhelp_keyshift & shift_mask) {
448 status_uni ("shift- F2 Save! F3 CaseTog F4 WrtBuf F5 ~ F6 ` F8 Subst F9 FindIdf F10 Menu");
449 } else {
450 status_uni (" F2 Save F3 Edit F4 InsFile F5 \" F6 ´ F8 Search F9 Next F10 Filemenu");
451 }
452 }
453 }
454
455 void
toggle_FHELP()456 toggle_FHELP ()
457 {
458 always_disp_help = ! always_disp_help;
459 }
460
461 void
FHELP(func)462 FHELP (func)
463 voidfunc func;
464 {
465 fhelp_func = func;
466 fhelp_keyshift = keyshift;
467 if (hop_flag > 0) {
468 hop_flag = 0;
469 always_disp_help = ! always_disp_help;
470 } else {
471 display_FHELP ();
472 }
473 }
474
475
476 void
F1()477 F1 ()
478 {
479 trace_dispatch ("F1");
480
481 if (keyshift & altctrlshift_mask) {
482 FHELP (F1);
483 } else {
484 HELP ();
485 }
486 }
487
488 void
F2()489 F2 ()
490 {
491 trace_dispatch ("F2");
492
493 if (keyshift & ctrl_mask) {
494 /* enforce creation of file info file */
495 hop_flag = 1;
496 }
497
498 if (keyshift & alt_mask) {
499 keyshift = 0;
500 SAVEAS ();
501 } else if (keyshift & shift_mask) {
502 keyshift = 0;
503 WTU ();
504 } else if (keyshift & ctrl_mask) {
505 keyshift = 0;
506 EXED ();
507 } else {
508 WT ();
509 }
510 }
511
512 void
F3()513 F3 ()
514 {
515 trace_dispatch ("F3");
516
517 if (keyshift & alt_mask) {
518 keyshift = 0;
519 SELECTFILE ();
520 } else if (keyshift & ctrl_mask) {
521 keyshift = 0;
522 VIEW ();
523 } else if (keyshift & shift_mask) {
524 keyshift = 0;
525 LOWCAPWORD ();
526 } else {
527 EDIT ();
528 }
529 }
530
531 void
F4()532 F4 ()
533 {
534 trace_dispatch ("F4");
535
536 if (keyshift & shift_mask) {
537 keyshift = 0;
538 WB ();
539 } else if (keyshift & ctrl_mask) {
540 keyshift = 0;
541 YANKRING ();
542 } else {
543 INSFILE ();
544 }
545 }
546
547 #ifdef dispatch_accents
548 /* accent prefix keys are now handled generically in edit.c:
549 insert_prefix (F5);
550 insert_prefix (F6);
551 */
552 void
F5()553 F5 ()
554 {
555 trace_dispatch ("F5");
556
557 /* standard function key assignment:
558 F5 F6
559 " ´
560 shift ~ `
561 ctrl ° ^
562 */
563 if (keyshift & ctrl_mask) {
564 keyshift = 0;
565 insert_angstrom ();
566 } else if (keyshift & shift_mask) {
567 keyshift = 0;
568 insert_tilde ();
569 } else {
570 insert_diaeresis ();
571 }
572 }
573
574 void
F6()575 F6 ()
576 {
577 trace_dispatch ("F6");
578
579 /* standard function key assignment:
580 F5 F6
581 " ´
582 shift ~ `
583 ctrl ° ^
584 */
585 if (keyshift & ctrl_mask) {
586 keyshift = 0;
587 insert_circumflex ();
588 } else if (keyshift & shift_mask) {
589 keyshift = 0;
590 insert_grave ();
591 } else {
592 insert_acute ();
593 }
594 }
595 #endif
596
597 void
FIND()598 FIND ()
599 {
600 if ((keyshift & ctrlshift_mask) == ctrlshift_mask) {
601 keyshift = 0;
602 if (hop_flag > 0) {
603 Stag ();
604 } else {
605 LR ();
606 }
607 } else if ((keyshift & altctrl_mask) == altctrl_mask) {
608 keyshift = 0;
609 if (hop_flag > 0) {
610 hop_flag = 0;
611 SCURCHAR (REVERSE);
612 } else {
613 REPL ();
614 }
615 } else if (keyshift & ctrl_mask) {
616 keyshift = 0;
617 if (hop_flag > 0) {
618 hop_flag = 0;
619 SCURCHAR (FORWARD);
620 } else {
621 REPL ();
622 }
623 } else if (keyshift & shift_mask) {
624 keyshift = 0;
625 if (hop_flag > 0) {
626 hop_flag = 0;
627 Stag ();
628 } else {
629 GR ();
630 }
631 } else if (keyshift & alt_mask) {
632 keyshift = 0;
633 SRV ();
634 } else {
635 SFW ();
636 }
637 }
638
639 void
AGAIN()640 AGAIN ()
641 {
642 if ((keyshift & altctrlshift_mask) == altctrlshift_mask) {
643 keyshift = 0;
644 SCURCHAR (REVERSE);
645 } else if ((keyshift & ctrlshift_mask) == ctrlshift_mask) {
646 keyshift = 0;
647 SCURCHAR (FORWARD);
648 } else if ((keyshift & altshift_mask) == altshift_mask) {
649 keyshift = 0;
650 SIDF (REVERSE);
651 } else if (keyshift & shift_mask) {
652 keyshift = 0;
653 SIDFW ();
654 } else if (keyshift & alt_mask) {
655 RESreverse ();
656 } else {
657 RES ();
658 }
659 }
660
661 void
F7()662 F7 ()
663 {
664 trace_dispatch ("F7");
665
666 FIND ();
667 }
668
669 void
F8()670 F8 ()
671 {
672 trace_dispatch ("F8");
673
674 FIND ();
675 }
676
677 void
F9()678 F9 ()
679 {
680 trace_dispatch ("F9");
681
682 AGAIN ();
683 }
684
685 void
F10()686 F10 ()
687 {
688 trace_dispatch ("F10");
689
690 if (keyshift & alt_mask) {
691 keyshift = 0;
692 handleFlagmenus ();
693 } else if (keyshift & shift_mask) {
694 keyshift = 0;
695 QUICKMENU ();
696 } else if (keyshift & ctrl_mask) {
697 keyshift = 0;
698 handleFlagmenus ();
699 } else {
700 FILEMENU ();
701 }
702 }
703
704 void
F11()705 F11 ()
706 {
707 trace_dispatch ("F11");
708
709 if (keyshift & alt_mask) {
710 if (keyshift & shift_mask) {
711 hop_flag = 1;
712 }
713 search_wrong_enc ();
714 } else if ((keyshift & ctrlshift_mask) == ctrlshift_mask) {
715 hop_flag = 1;
716 changeuni ();
717 } else if (keyshift & shift_mask) {
718 keyshift = 0;
719 hop_flag = 1;
720 LOWCAP ();
721 } else if (keyshift & ctrl_mask) {
722 UML (' ');
723 } else {
724 LOWCAP ();
725 }
726 }
727
728 void
F12()729 F12 ()
730 {
731 trace_dispatch ("F12");
732
733 if (keyshift & alt_mask) {
734 if (keyshift & ctrl_mask) {
735 toggleKEYMAP ();
736 } else {
737 switchAltScreen ();
738 }
739 } else if ((keyshift & ctrlshift_mask) == ctrlshift_mask) {
740 SAVPOS ();
741 } else if (keyshift & ctrl_mask) {
742 setupKEYMAP ();
743 } else if (keyshift & shift_mask) {
744 KEYREC ();
745 } else {
746 KEYREC ();
747 }
748 }
749
750
751 /*======================================================================*\
752 |* Generic command processing functions *|
753 \*======================================================================*/
754
755 /*
756 * return the mined command associated with the key value
757 */
758 voidfunc
command(c)759 command (c)
760 unsigned long c;
761 {
762 if (c == FUNcmd) {
763 return keyproc;
764 } else if (/* c >= 0 && */ c < arrlen (key_map)) {
765 return key_map [c];
766 } else {
767 return Scharacter;
768 }
769 }
770
771
772 /**
773 Invoke function associated with the key.
774 */
775 void
invoke_key_function(key)776 invoke_key_function (key)
777 unsigned long key;
778 {
779 (command (key)) (key);
780 }
781
782
783 /*
784 * BAD complains about unknown command characters.
785 */
786 static
787 void
BAD(c,tag)788 BAD (c, tag)
789 unsigned long c;
790 char * tag;
791 {
792 char cmdbuf [34];
793 char * cbuf = cmdbuf;
794
795 strcpy (cmdbuf, "Unknown command: ");
796 if (tag) {
797 strcat (cmdbuf, tag);
798 }
799 while (* cbuf) {
800 cbuf ++;
801 }
802
803 if (no_char (c)) {
804 strcpy (cbuf, "<unknown character>");
805 } else if (c < ' ') {
806 cbuf [0] = '^';
807 cbuf [1] = c + '@';
808 cbuf [2] = '\0';
809 } else {
810 (void) utfencode (c, cbuf);
811 }
812
813 ring_bell ();
814 status_uni (cmdbuf);
815 }
816
817 void
BADch(c)818 BADch (c)
819 unsigned long c;
820 {
821 BAD (c, "");
822 }
823
824 /*
825 * Ignore this keystroke.
826 */
827 void
I()828 I ()
829 {
830 }
831
832 /*
833 * 'HOP' key function expander.
834 */
835 void
HOP()836 HOP ()
837 {
838 if (shift_selection && (keyshift & shift_mask)) {
839 keyshift &= ~ shift_mask;
840 COPY ();
841 return;
842 }
843
844 hop_flag = 2;
845 if (MENU) {
846 displayflags ();
847 set_cursor_xy ();
848 flush ();
849 }
850 if (! char_ready_within (500, NIL_PTR)) {
851 status_uni ("HOP: type command (to amplify/expand) ...");
852 }
853 }
854
855 /*
856 * Cancel prefix function.
857 */
858 void
CANCEL()859 CANCEL ()
860 {
861 hop_flag = 0;
862 clear_status ();
863 }
864
865
866 /**
867 Read ANSI escape sequence that has been started with ESC [
868 (but too slowly to be recognised on keyboard input level);
869 swallow [, ? or > (for reports), 0-9, and ; characters
870 plus final letter, @ or ~
871 */
872 static
873 void
CSI()874 CSI ()
875 {
876 character c;
877 FLAG msg_shown = False;
878
879 if (stat_visible) {
880 ring_bell ();
881 } else {
882 status_uni ("... absorbing delayed terminal escape sequence ... - Press Enter to abort");
883 msg_shown = True;
884 }
885 flush ();
886
887 while ((c = read1byte ()) == '[' || c == '?' || c == '>' || c == ';'
888 || (c >= '0' && c <= '9')) {
889 }
890
891 if (msg_shown) {
892 error ("(Discarded slow escape sequence) - Re-enter function key");
893 }
894 }
895
896 /**
897 Read escape sequence that has been started with ESC O
898 (but too slowly to be recognised on keyboard input level);
899 swallow 0-9, and ; characters plus final character
900 */
901 static
902 void
ESCO()903 ESCO ()
904 {
905 character c;
906 FLAG msg_shown = False;
907
908 if (stat_visible) {
909 ring_bell ();
910 } else {
911 status_uni ("... Absorbing delayed terminal escape sequence ... - Press Enter to abort");
912 msg_shown = True;
913 }
914 flush ();
915
916 while ((c = read1byte ()) == ';' || (c >= '0' && c <= '9')) {
917 }
918
919 if (msg_shown) {
920 error ("(Discarded slow escape sequence) - Re-enter function key");
921 }
922 }
923
924 /**
925 Read terminal report string which has been started with ESC ]
926 */
927 void
OSC()928 OSC ()
929 {
930 character c;
931 FLAG msg_shown = False;
932
933 if (stat_visible) {
934 ring_bell ();
935 } else {
936 status_uni ("... Absorbing delayed terminal report string ... - Press Enter to abort");
937 msg_shown = True;
938 }
939 flush ();
940
941 while ((c = read1byte ()) >= ' ') {
942 }
943 if (c == '\033') {
944 read1byte (); /* '\\' */
945 }
946
947 if (msg_shown) {
948 clear_status ();
949 }
950 }
951
952
953 #define cmd_char(c) (c < '\040' ? c + '\100' : (c >= '\140' ? c - '\040' : c))
954
955 /*
956 * Interpret control-Q commands. Most can be implemented with the Hop function.
957 */
958 void
ctrlQ()959 ctrlQ ()
960 {
961 unsigned long c;
962 voidfunc func;
963
964 if (! char_ready_within (500, NIL_PTR)) {
965 status_uni ("^Q: blockBegin Find replAce goto<n>mark HOP...");
966 }
967 if (quit) {
968 return;
969 }
970
971 c = readcharacter_unicode ();
972 if (quit) {
973 return;
974 }
975
976 clear_status ();
977 if ('0' <= c && c <= '9') {
978 GOMAn ((int) c - (int) '0');
979 return;
980 }
981 if (c == '\033' || c == quit_char) {
982 CANCEL ();
983 return;
984 }
985 switch (cmd_char (c)) {
986 case 'B' : {GOMA () ; return;}
987 case 'K' : { ; return;} /* not exactly WS function */
988 case 'P' : { ; return;} /* not exactly WS function */
989 case 'V' : { ; return;} /* not exactly WS function */
990 case 'W' : /* not exactly WS function */
991 case 'Z' : /* not exactly WS function */
992 case 'Y' :
993 case '\177' : {
994 func = command (c);
995 hop_flag = 1;
996 (* func) (c);
997 return;
998 }
999 case 'F' : {if (hop_flag > 0) {
1000 SRV ();
1001 } else {
1002 SFW ();
1003 }
1004 return;
1005 }
1006 case 'A' : {if (hop_flag > 0) {
1007 REPL ();
1008 } else {
1009 GR ();
1010 }
1011 return;
1012 }
1013 case 'Q' : {REPT (' '); return;} /* not exactly WS function */
1014 case 'L' : /* not exactly WS function */
1015 /*
1016 ^Q: B/K top/bottom block
1017 P last position
1018 W/Z continuous scroll
1019 V last find or block
1020 Y/DEL delete line right/left
1021 0-9 marker
1022 F find
1023 A replace
1024 Q repeat next key/command
1025 L find misspelling
1026 */
1027 default : {
1028 func = command (c);
1029 if (func != Scharacter) {
1030 hop_flag = 1;
1031 keyshift |= alt_mask;
1032 (* func) (c);
1033 } else {
1034 BAD (c, "^Q ");
1035 }
1036 return;
1037 }
1038 }
1039 }
1040
1041 /*
1042 * Interpret control-K commands.
1043 */
1044 void
ctrlK()1045 ctrlK ()
1046 {
1047 unsigned long c;
1048
1049 if (! char_ready_within (500, NIL_PTR)) {
1050 status_msg ("^K: Save Done eXit Quit Read Log <n>mark / block: B/K mark Cop Ydel moV Wr...");
1051 }
1052 if (quit) {
1053 return;
1054 }
1055
1056 c = readcharacter_unicode ();
1057 if (quit) {
1058 return;
1059 }
1060
1061 clear_status ();
1062 if ('0' <= c && c <= '9') {
1063 MARKn ((int) c - (int) '0');
1064 return;
1065 }
1066 if (c == '\033' || c == quit_char) {
1067 CANCEL ();
1068 return;
1069 }
1070 switch (cmd_char (c)) {
1071 case 'S' : {WTU (); return;}
1072 case 'D' : {EXFILE (); return;}
1073 case 'X' : {EXMINED (); return;}
1074 case 'Q' : {QUED (); return;}
1075 case 'B' : {setMARK (True) ; return;}
1076 case 'K' : {COPY () ; return;} /* not exactly WS function */
1077 case 'H' : { ; return;} /* not exactly WS function */
1078 case 'C' : {PASTE () ; return;} /* not exactly WS function */
1079 case 'Y' : {CUT () ; return;} /* not exactly WS function */
1080 case 'V' : {PASTE (); return;} /* not exactly WS function */
1081 case 'W' : {WB (); return;} /* not exactly WS function */
1082 case 'N' : { ; return;} /* not exactly WS function */
1083 case 'R' : {INSFILE (); return;}
1084 case 'L' : {CHDI (); return;}
1085 /*
1086 ^K 0-9 set/hide marker
1087 B/K block begin/end
1088 H block hide
1089 C/Y/V/W block copy/delete/move/write
1090 N column block
1091 */
1092 default : {
1093 BAD (c, "^K ");
1094 return;
1095 }
1096 }
1097 }
1098
1099 /*
1100 * Interpret control-O commands.
1101 */
1102 void
ctrlO()1103 ctrlO ()
1104 {
1105 unsigned long c;
1106
1107 if (! char_ready_within (500, NIL_PTR)) {
1108 status_msg ("^O: L/R left/right margins...");
1109 }
1110 if (quit) {
1111 return;
1112 }
1113
1114 c = readcharacter_unicode ();
1115 if (quit) {
1116 return;
1117 }
1118
1119 clear_status ();
1120 if ('0' <= c && c <= '9') {
1121 return;
1122 }
1123 if (c == '\033' || c == quit_char) {
1124 CANCEL ();
1125 return;
1126 }
1127 switch (cmd_char (c)) {
1128 case 'L' : {ADJLM (); return;}
1129 case 'R' : {ADJRM (); return;}
1130 case 'G' : {ADJFLM () /* actually paragraph tab */; return;}
1131 /*
1132 ^O L/R/M set left/right margin /release
1133 I/N set/clear tab
1134 F ruler from line
1135 C center line
1136 S set line spacing
1137 W toggle word wrap
1138 T toggle ruler line
1139 J toggle justify
1140 V vari-tabs
1141 H hyph-help
1142 E soft hyph
1143 D print display
1144 P page break
1145 */
1146 default : {
1147 BAD (c, "^O ");
1148 return;
1149 }
1150 }
1151 }
1152
1153 /*
1154 * Set marker / go to marker.
1155 */
1156 void
MARKER()1157 MARKER ()
1158 {
1159 unsigned long c;
1160
1161 status_msg ("0..9: set marker / , or blank: default marker");
1162 c = readcharacter_unicode ();
1163 if (quit) {
1164 return;
1165 }
1166
1167 clear_status ();
1168 if (c == '\033' || c == quit_char) {
1169 CANCEL ();
1170 } else if ('0' <= c && c <= '9') {
1171 MARKn ((int) c - (int) '0');
1172 } else if ('a' <= c && c <= 'f') {
1173 MARKn ((int) c - (int) 'a' + 10);
1174 } else if (c == ',' || c == '\'' || c == ' ' || c == ']' || c == '\035') {
1175 setMARK (True);
1176 } else {
1177 BAD (c, "mark ");
1178 }
1179 }
1180
1181 void
GOMARKER()1182 GOMARKER ()
1183 {
1184 unsigned long c;
1185
1186 status_msg ("0..9: go marker / blank: default marker");
1187 c = readcharacter_unicode ();
1188 if (quit) {
1189 return;
1190 }
1191
1192 clear_status ();
1193 if (c == '\033' || c == quit_char) {
1194 CANCEL ();
1195 } else if ('0' <= c && c <= '9') {
1196 GOMAn ((int) c - (int) '0');
1197 } else if ('a' <= c && c <= 'f') {
1198 GOMAn ((int) c - (int) 'a' + 10);
1199 } else if (c == ',' || c == '.' || c == 'g' || c == 'G' || c == '\'' ||
1200 c == ' ' || c == ']' || c == '\035') {
1201 GOMA ();
1202 } else {
1203 BAD (c, "go mark ");
1204 }
1205 }
1206
1207
1208 /*
1209 Toggle TAB width.
1210 */
1211 void
toggle_tabsize()1212 toggle_tabsize ()
1213 {
1214 static int prev_tabsize = 2;
1215
1216 if (hop_flag > 0) {
1217 toggle_tab_expansion ();
1218 return;
1219 }
1220
1221 if (tabsize == 2 || tabsize == 8) {
1222 prev_tabsize = tabsize;
1223 tabsize = 4;
1224 } else if (prev_tabsize == 8) {
1225 tabsize = 2;
1226 } else {
1227 tabsize = 8;
1228 }
1229 RDwin ();
1230 }
1231
1232 /*
1233 * Interpret Escape commands.
1234 */
1235 void
ESCAPE()1236 ESCAPE ()
1237 {
1238 unsigned long c;
1239 voidfunc func;
1240 FLAG quick_alt = False;
1241
1242 if (char_ready_within (50, NIL_PTR)) {
1243 /* try to distinguish Alt- from explicit ESC */
1244 quick_alt = True;
1245 }
1246 if (! char_ready_within (450, NIL_PTR)) {
1247 status_uni ("ESCexit SPACEmenu quit /search \\backw (match replace goto justify =rept help ...");
1248 }
1249 if (quit) {
1250 return;
1251 }
1252
1253 c = readcharacter_unicode ();
1254 if (quit) {
1255 return;
1256 }
1257
1258 clear_status ();
1259
1260 if ('0' <= c && c <= '9') {
1261 REPT (c);
1262 return;
1263 }
1264
1265 trace_keytrack ("ESCAPE", c);
1266 switch (c) {
1267 case '[' : {CSI (); return;}
1268 case 'O' : {ESCO (); return;}
1269 case ']' : {OSC (); return;}
1270 case '\'' :
1271 {
1272 if (quick_alt) { /* detect Alt-' vs. ESC ' */
1273 break;
1274 }
1275 if (keyshift & alt_mask) {
1276 break;
1277 } else {
1278 GOMARKER (); return;
1279 }
1280 }
1281 case '\033' : {EXED (); return;}
1282 case '\r' :
1283 case '\n' :
1284 if (keyshift & ctrlshift_mask) {
1285 break;
1286 } else {
1287 Popmark ();
1288 return;
1289 }
1290 case '.' :
1291 {
1292 show_vt100_graph = False;
1293 if (hop_flag > 0) {
1294 RDcenter ();
1295 } else {
1296 RDwin ();
1297 }
1298 return;
1299 }
1300 case 'q' : {QUED (); return;}
1301 case '/' : {SFW (); return;}
1302 case '\\' : {SRV (); return;}
1303 case 'R' : {LR (); return;}
1304 case 'r' : {REPL (); return;}
1305 case 'w' : {WT (); return;}
1306 case 'W' : {WTU (); return;}
1307 case 'v' : {VIEW (); return;}
1308 case 'V' : {toggle_VIEWmode (); return;}
1309 case 'g' : {GOTO (); return;}
1310 case 'h' : {HELP (); return;}
1311 case '?' : {FS (); return;}
1312 case 'm' : {MARKER (); return;}
1313 case 'i' : {INSFILE (); return;}
1314 case 'b' : {WB (); return;}
1315 case '=' : {REPT (' '); return;}
1316 case 'z' : {SUSP (); return;}
1317 case 'd' : {CHDI (); return;}
1318 case '!' : {SH (); return;}
1319 case '@' :
1320 case '^' : {setMARK (True); return;}
1321 case 'n' : {NN (); return;}
1322 case 'c' : {CMD (); return;}
1323 case 'u' : {display_code (); return;}
1324 case 'U' : {changeuni (); return;}
1325 case 'X' : {changehex (); return;}
1326 case 'A' : {changeoct (); return;}
1327 case 'D' : {changedec (); return;}
1328 case '+' : {NXTFILE (); return;}
1329 case '-' : {PRVFILE (); return;}
1330 case '#' : {SELECTFILE (); return;}
1331 case '%' : {screensmaller (); return;}
1332 case '&' : {screenbigger (); return;}
1333 case 'l' : {screenlesslines (); return;}
1334 case 'L' : {screenmorelines (); return;}
1335 case 'J' : {JUS (); return;}
1336 case 'j' : {JUSclever (); return;}
1337 case '<' : {ADJLM (); return;}
1338 case ';' : {ADJFLM (); return;}
1339 case ':' : {ADJNLM (); return;}
1340 case '>' : {ADJRM (); return;}
1341 case 'P' : {ADJPAGELEN (); return;}
1342 case 'T' : {toggle_tabsize (); return;}
1343 case 'H' : {HTML (); return;}
1344 case 'x' : {AltX (); return;}
1345 case (character) '�' : /* ä German */
1346 case (character) '�' : /* ö German */
1347 case (character) '�' : /* ü German */
1348 case (character) '�' : /* ß German */
1349 {UML ('g'); return;}
1350 case (character) '�' : /* é French */
1351 case (character) '�' : /* è French */
1352 case (character) '�' : /* à French */
1353 case (character) '�' : /* ù French */
1354 case (character) '�' : /* ç French */
1355 case (character) '�' : /* ² French */
1356 {UML ('f'); return;}
1357 case (character) '�' : /* æ Scandinavian */
1358 case (character) '�' : /* å Scandinavian */
1359 case (character) '�' : /* ø Scandinavian */
1360 {UML ('d'); return;}
1361 case (character) '�' : /* ì Italian */
1362 case (character) '�' : /* ò Italian */
1363 {UML ('i'); return;}
1364 case 0x0142 : /* ł Polish/Baltic */
1365 case 0x0144 : /* ń Polish/Baltic */
1366 case 0x017A : /* ź Polish/Baltic */
1367 case 0x0107 : /* ć Polish/Baltic/Croatian/Slovenian */
1368 {UML ('e'); return;}
1369 case 0x016F : /* ů Slovak */
1370 case 0x0151 : /* ő Hungarian */
1371 case 0x0171 : /* ű Hungarian */
1372 case 0x010D : /* č Croatian/Slovenian */
1373 case 0x017E : /* ž Croatian/Slovenian */
1374 case 0x0161 : /* š Croatian/Slovenian */
1375 case 0x0111 : /* đ Croatian/Slovenian/Vietnamese */
1376 case 0x01A1 : /* ơ Vietnamese */
1377 case 0x01B0 : /* ư Vietnamese */
1378 {UML ('e'); return;}
1379 case '_' : /* generic */
1380 case (character) '�' : /* ° Norwegian */
1381 case (character) '�' : /* ª Portuguese */
1382 case (character) '�' : /* º Portuguese */
1383 case (character) '�' : /* « Portuguese */
1384 case (character) '�' : /* ñ Spanish */
1385 case 0x011F : /* ğ Turkish */
1386 case 0x015F : /* ş Turkish */
1387 case 0x0131 : /* ı Turkish */
1388 {UML (language_tag); return;}
1389 case 'C' : {LOWCAP (); return;}
1390 case '(' :
1391 case '{' : {SCORR (REVERSE); return;}
1392 case ')' :
1393 case '}' : {SCORR (FORWARD); return;}
1394 case 't' : {Stag (); return;}
1395 case 'a' : {toggle_append (); return;}
1396 case 'k' : {toggleKEYMAP (); return;}
1397 case 'I' :
1398 case 'K' : {setupKEYMAP (); return;}
1399 case 'Q' : if (smart_quotes) {
1400 handleQuotemenu ();
1401 displayflags ();
1402 } else {
1403 error ("Smart quotes not enabled");
1404 }
1405 return;
1406 case 'E' : if (hop_flag > 0) {
1407 toggle_encoding ();
1408 } else {
1409 handleEncodingmenu ();
1410 }
1411 return;
1412 case ' ' : {QUICKMENU (); return;}
1413 case 'f' : {FILEMENU (); return;}
1414 case 'e' : {EDITMENU (); return;}
1415 case 's' : {SEARCHMENU (); return;}
1416 case 'p' : {PARAMENU (); return;}
1417 case 'o' : {OPTIONSMENU (); return;}
1418 case ',' : {GR (); return;}
1419 /*
1420 case 'e' : {EDIT (); return;}
1421 case 's' : {GR (); return;}
1422 case 'p' : {PRINT (); return;}
1423 */
1424 }
1425
1426 /* fallback */
1427 if (c == quit_char) {
1428 CANCEL ();
1429 return;
1430 }
1431 func = command (c);
1432 if (func != Scharacter) {
1433 hop_flag = 1;
1434 keyshift |= alt_mask;
1435 (* func) (c);
1436 } else {
1437 BAD (c, "ESC/Alt-");
1438 }
1439 return;
1440 }
1441
1442 /*
1443 * Interpret emacs meta commands.
1444 */
1445 void
META()1446 META ()
1447 {
1448 unsigned long c;
1449 voidfunc func;
1450
1451 if (! char_ready_within (500, NIL_PTR)) {
1452 status_uni ("Meta ESC(exit) TAB,space(menu) /,\\(search) (match ...");
1453 }
1454 if (quit) {
1455 return;
1456 }
1457
1458 c = readcharacter_unicode ();
1459 if (quit) {
1460 return;
1461 }
1462
1463 clear_status ();
1464
1465 if ('0' <= c && c <= '9') {
1466 REPT (c);
1467 return;
1468 }
1469
1470 switch (c) {
1471 /* emacs meta commands */
1472 case 'v' : {MOVPU (); return;}
1473 case 'f' : {MNW (); return;}
1474 case 'b' : {MPW (); return;}
1475 case 'a' : {BSEN (); return;}
1476 case 'e' : {ESEN (); return;}
1477 case '<' : {BFILE (); return;}
1478 case '>' : {EFILE (); return;}
1479 case 'd' : {DNW (); return;}
1480 case 'k' : {setMARK (True); ESEN (); CUT (); return;}
1481 case 'w' : {COPY (); return;}
1482 case 'y' : {YANKRING (); return;}
1483 case 'z' : {SUSP (); return;}
1484 case '%' : {REPL (); return;}
1485 case 'u' : {hop_flag = 1; UPPER (); return;}
1486 case 'l' : {hop_flag = 1; LOWER (); return;}
1487 case 'c' : {CAPWORD (); return;}
1488 case '.' : {Stag (); return;}
1489
1490 case 'x' : {ESCAPE (); return;}
1491 case '\033' : {ESCAPE (); return;}
1492
1493 default : {
1494 if (c == quit_char) {
1495 CANCEL ();
1496 return;
1497 }
1498 func = command (c);
1499 if (func != Scharacter) {
1500 hop_flag = 1;
1501 keyshift |= alt_mask;
1502 (* func) (c);
1503 } else {
1504 BAD (c, "Meta-");
1505 }
1506 return;
1507 }
1508 }
1509 }
1510
1511 /*
1512 * Interpret emacs ^X commands.
1513 */
1514 void
EMAX()1515 EMAX ()
1516 {
1517 unsigned long c;
1518
1519 if (! char_ready_within (500, NIL_PTR)) {
1520 status_msg ("^X ...");
1521 }
1522 if (quit) {
1523 return;
1524 }
1525
1526 c = readcharacter_unicode ();
1527 if (quit) {
1528 return;
1529 }
1530
1531 clear_status ();
1532
1533 if (command (c) == MARK) {
1534 Popmark ();
1535 return;
1536 }
1537 switch (c) {
1538 case 'u' : {UNDO (); return;}
1539 case '' : {QUED (); return;}
1540 case '' : {WT (); return;}
1541 case '' : {SAVEAS (); return;}
1542 case '' : {PRVFILE (); return;}
1543 case '' : {EDIT (); return;}
1544 case '\032' : {SUSP (); return;}
1545 case '\033' : {REPT (' '); return;}
1546 case 'i' : {INSFILE (); return;}
1547 case 's' : {WT (); return;}
1548 case 'k' : {EDIT (); return;}
1549 case '=' : {FS (); return;}
1550 case '[' : {MOVPU (); return;}
1551 case ']' : {MOVPD (); return;}
1552 default : {
1553 if (c == quit_char) {
1554 CANCEL ();
1555 return;
1556 }
1557 BAD (c, "^X ");
1558 }
1559 }
1560 }
1561
1562
1563 /*
1564 * REPT () prompts for a count and wants a command after that. It repeats the
1565 * command count times. If a ^\ is given during repeating, stop looping and
1566 * return to main loop.
1567 */
1568 void
REPT(firstdigit)1569 REPT (firstdigit)
1570 char firstdigit;
1571 {
1572 int count;
1573 voidfunc func;
1574 long val;
1575 unsigned long cmd;
1576 int number;
1577
1578 hop_flag = 0;
1579 if (firstdigit >= '0' && firstdigit <= '9') {
1580 val = get_number ("Please continue repeat count...", firstdigit, & number);
1581 if (firstdigit != '0' && number < 10) {
1582 error ("Invalid repeat count after ESC <digit>");
1583 return;
1584 }
1585 } else {
1586 val = get_number ("Please enter repeat count...", '\0', & number);
1587 }
1588 if (val == ERRORS) {
1589 return;
1590 }
1591 cmd = val;
1592
1593 func = command (cmd);
1594 if (func == I) { /* no function assigned? */
1595 clear_status ();
1596 return;
1597 } else if (func == CTRLINS
1598 || func == COMPOSE
1599 || func == F5
1600 || func == F6
1601 || func == key_1
1602 || func == key_2
1603 || func == key_3
1604 || func == key_4
1605 || func == key_5
1606 || func == key_6
1607 || func == key_7
1608 || func == key_8
1609 || func == key_9
1610 || func == key_0
1611 ) {
1612 /* handle ^V/compose input here to not only repeat the prefix */
1613 if (func == CTRLINS) {
1614 cmd = CTRLGET (False);
1615 } else {
1616 cmd = CTRLGET (True);
1617 }
1618 for (count = 0; count < number; count ++) {
1619 Scharacter (cmd);
1620 }
1621 return;
1622 }
1623
1624 count = number;
1625 while (count -- > 0 && quit == False) {
1626 char save_keyshift = keyshift;
1627 if (stat_visible) {
1628 clear_status ();
1629 }
1630 reset_smart_replacement ();
1631 (* func) (cmd);
1632 keyshift = save_keyshift;
1633 display_flush ();
1634 flush ();
1635 }
1636 reset_smart_replacement ();
1637
1638 if (quit) { /* Abort has been given */
1639 error ("Repeat aborted");
1640 } else {
1641 clear_status ();
1642 }
1643 }
1644
1645
1646 /*
1647 Toggle TAB expansion.
1648 */
1649 void
toggle_tab_expansion()1650 toggle_tab_expansion ()
1651 {
1652 expand_tabs = ! expand_tabs;
1653 }
1654
1655 /*
1656 * Toggle insert/overwrite mode.
1657 */
1658 void
TOGINS()1659 TOGINS ()
1660 {
1661 if (insert_mode) {
1662 insert_mode = False;
1663 } else {
1664 insert_mode = True;
1665 }
1666 }
1667
1668 void
UNDO()1669 UNDO ()
1670 {
1671 error ("Undo not implemented");
1672 }
1673
1674 void
SPELL()1675 SPELL ()
1676 {
1677 error ("Spell checking not implemented");
1678 }
1679
1680
1681 /*======================================================================*\
1682 |* End *|
1683 \*======================================================================*/
1684