1 /*======================================================================*\
2 |* Editor mined *|
3 |* keyboard input *|
4 \*======================================================================*/
5
6 #include "mined.h"
7 #include "charprop.h"
8 #include "io.h"
9 #include "termprop.h"
10
11 #define dont_debug_mouse
12
13
14 #if ! defined (__TURBOC__) && ! defined (VAXC)
15 #include <sys/time.h>
16 #endif
17
18 #ifdef vms
19 #undef CURSES
20 #endif
21
22 #ifdef CURSES
23 #include <curses.h>
24 #include <strings.h>
25 #endif
26
27
28 voidfunc keyproc = I; /* function addressed by entered function key */
29 unsigned char keyshift = 0; /* shift state of entered function key */
30 static unsigned char fkeyshift;
31 #define max_ansi_params 10
32 int ansi_params;
33 int ansi_param [max_ansi_params];
34 char ansi_ini;
35 char ansi_fini;
36
37 static
38 int keymap_delay = 0; /* wait to detect mapped key sequence */
39 static
40 int default_keymap_delay = 900; /* overridden by $MAPDELAY */
41
42 static
43 int escape_delay = 0; /* wait to detect escape sequence */
44 static
45 int default_escape_delay = 450; /* overridden by $ESCDELAY */
46
47 static
48 int dont_suppress_keymap = 1;
49
50 static
51 int report_winchg = 0;
52
53 /* The flag queue_mode_mapped indicates when the byte input queue
54 has been stuffed with keyboard mapped characters, always being
55 encoded in UTF-8, while otherwise the queue contents are in
56 terminal native encoding (which may also be UTF-8, or CJK, or Latin-1).
57 */
58 static
59 FLAG queue_mode_mapped = False; /* queue contains mapped character(s) */
60
61 /* In hp_shift_mode key shift indications like ESC 2p or ESC 5h
62 are considered to determine the keyshift state.
63 */
64 static
65 FLAG hp_shift_mode = False;
66
67 /* In sco_shift_mode key shift indications like ESC [2A or ESC [2M
68 are considered to determine the keyshift state.
69 */
70 static
71 FLAG sco_shift_mode = False;
72
73 /* mouse handling */
74 mousebutton_type mouse_button;
75 mousebutton_type mouse_prevbutton = movebutton;
76 int mouse_xpos, mouse_ypos, mouse_prevxpos, mouse_prevypos;
77 int mouse_shift = 0; /* modifier status */
78 FLAG report_release = False; /* selectively suppress release event */
79 FLAG window_focus = True; /* does the window have mouse/keyboard focus? */
80 int mouse_buttons_pressed = 0; /* count pressed buttons */
81
82
83 /*======================================================================*\
84 |* Local function declaration *|
85 \*======================================================================*/
86
87 static unsigned long _readchar _((void));
88
89
90 /*======================================================================*\
91 |* Function key tables *|
92 \*======================================================================*/
93
94 #define dont_debug_findkey
95
96
97 #ifndef msdos
98
99 #ifdef unix
100 #define TERMINFO
101 #endif
102
103 static
104 void
dummyfunc()105 dummyfunc ()
106 {
107 }
108
109 extern struct fkeyentry fkeymap [];
110 extern struct fkeyentry fkeymap_xterm [];
111 extern struct fkeyentry fkeymap_rxvt [];
112 extern struct fkeyentry fkeymap_linux [];
113 extern struct fkeyentry fkeymap_vt100 [];
114 extern struct fkeyentry fkeymap_vt52 [];
115 extern struct fkeyentry fkeymap_hp [];
116 extern struct fkeyentry fkeymap_siemens [];
117 extern struct fkeyentry fkeymap_scoansi [];
118 extern struct fkeyentry fkeymap_interix [];
119
120 static struct fkeyentry * fkeymap_spec = fkeymap_xterm;
121 #ifdef TERMINFO
122 extern struct fkeyentry fkeymap_terminfo [];
123 #endif
124
125 void
set_fkeymap(term)126 set_fkeymap (term)
127 char * term;
128 {
129 #ifdef debug_findkey
130 printf ("set_fkeymap %s\n", term);
131 #endif
132
133 if (term == NIL_PTR) {
134 fkeymap_spec = fkeymap;
135 } else if (* term == 'x') {
136 fkeymap_spec = fkeymap_xterm;
137 } else if (* term == 'r') {
138 fkeymap_spec = fkeymap_rxvt;
139 } else if (* term == 'l') {
140 fkeymap_spec = fkeymap_linux;
141 } else if (* term == 'h') {
142 fkeymap_spec = fkeymap_hp;
143 hp_shift_mode = True;
144 } else if (* term == 'v') {
145 fkeymap_spec = fkeymap_vt100;
146 } else if (* term == '5') {
147 fkeymap_spec = fkeymap_vt52;
148 } else if (* term == 'i') {
149 fkeymap_spec = fkeymap_interix;
150 } else if (* term == 's') {
151 fkeymap_spec = fkeymap_siemens;
152 use_mouse = False;
153 } else if (* term == 'o') {
154 fkeymap_spec = fkeymap_scoansi;
155 sco_shift_mode = True;
156 use_mouse = False;
157 }
158 }
159
160 #else
161
162 void
set_fkeymap(term)163 set_fkeymap (term)
164 char * term;
165 {
166 }
167
168 #endif
169
170
171 /*======================================================================*\
172 |* String input functions *|
173 \*======================================================================*/
174
175 /**
176 get_digits () reads in a number.
177 In contrast to get_number, it does no echoing, no messaging, reads
178 only decimal, and accepts zero length input.
179 The last character typed in is returned.
180 The resulting number is put into the integer the arguments points to.
181 It is for use within I/O routines (e.g. reading mouse escape sequences
182 or cursor position report) and thus calls read1byte / __readchar.
183 */
184 int
get_digits(result)185 get_digits (result)
186 int * result;
187 {
188 register int byte1;
189 register int value;
190
191 byte1 = read1byte ();
192 * result = -1;
193 /* Convert input to a decimal number */
194 value = 0;
195 while (byte1 >= '0' && byte1 <= '9') {
196 value *= 10;
197 value += byte1 - '0';
198 * result = value;
199 byte1 = read1byte ();
200 }
201
202 return byte1;
203 }
204
205
206 /**
207 get_string_nokeymap prompts a string like get_string
208 but doesn't apply international keyboard mapping
209 */
210 int
get_string_nokeymap(prompt,inbuf,statfl,term_input)211 get_string_nokeymap (prompt, inbuf, statfl, term_input)
212 char * prompt;
213 char * inbuf;
214 FLAG statfl;
215 char * term_input;
216 {
217 int ret;
218
219 dont_suppress_keymap = 0;
220 ret = get_string (prompt, inbuf, statfl, term_input);
221 dont_suppress_keymap = 1;
222
223 return ret;
224 }
225
226
227 /*======================================================================*\
228 |* Terminal input *|
229 \*======================================================================*/
230
231 #ifdef debug_keytrack
232
233 void
do_trace_keytrack(tag,c)234 do_trace_keytrack (tag, c)
235 char * tag;
236 unsigned long c;
237 {
238 printf ("[%s] ", tag);
239 if (command (c) == COMPOSE) {
240 printf ("COMPOSE");
241 } else if (c == FUNcmd) {
242 printf ("FUNcmd");
243 } else {
244 printf ("%02lX", c);
245 }
246 printf (" [keyshift %X]\n", keyshift);
247 }
248
249 #endif
250
251 #define dont_debug_mapped_keyboard
252
253 #define max_stamps 10
254 static long last_sec = 0;
255 static long last_msec = 0;
256 static int n_stamps = 0;
257 static int i_stamp = 0;
258 static long stamps [max_stamps];
259 static long total_deltas = 0;
260 long average_delta_readchar = 0;
261 long last_delta_readchar = 0;
262
263 static FLAG skip_1click = False;
264 static FLAG skip_1release = False;
265
266
267 static
268 void
timestamp_readchar()269 timestamp_readchar ()
270 {
271 #if ! defined (__TURBOC__) && ! defined (VAXC)
272 struct timeval now;
273 long sec;
274 long msec;
275
276 gettimeofday (& now, 0);
277 sec = now.tv_sec;
278 msec = now.tv_usec / 1000;
279 if (last_sec == 0) {
280 last_delta_readchar = 1000;
281 } else {
282 last_delta_readchar = (sec - last_sec) * 1000 + msec - last_msec;
283 }
284 last_sec = sec;
285 last_msec = msec;
286
287 if (n_stamps < max_stamps) {
288 n_stamps ++;
289 } else {
290 /* remove oldest stamp from statistics */
291 total_deltas -= stamps [i_stamp];
292 }
293 stamps [i_stamp] = last_delta_readchar;
294 /* add stamp to statistics */
295 total_deltas += last_delta_readchar;
296 i_stamp ++;
297 if (i_stamp == max_stamps) {
298 i_stamp = 0;
299 }
300
301 average_delta_readchar = total_deltas / n_stamps;
302 #endif
303 }
304
305 /*
306 * Readchar () reads one character from the terminal.
307 * There are problems due to interruption of the read operation by signals
308 * (QUIT, WINCH). The waitingforinput flag is only a partial solution.
309 * Unix doesn't provide sufficient facilities to handle these situations
310 * neatly and properly. Moreover, different Unix versions yield different
311 * surprising effects. However, the use of select () could still be
312 * an improvement.
313 */
314 static
315 unsigned long
readchar()316 readchar ()
317 {
318 unsigned long c;
319
320 #ifdef msdos
321 #define winchhere
322 #endif
323
324 #ifdef winchhere
325 FLAG waiting;
326
327 if (winchg && waitingforinput == False) {
328 /* In the Unix version, this is now done in __readchar () */
329 RDwinchg ();
330 }
331 /* must save waitingforinput flag since in the MSDOS version,
332 readchar can be called recursively */
333 waiting = waitingforinput;
334 #endif
335 waitingforinput = True;
336
337 c = _readchar ();
338 trace_keytrack ("readchar:_readchar", c);
339 /* check report_release to suppress subsequent release actions
340 (esp after menu item selection)
341 when multiple buttons are pressed simultaneously */
342 while (report_release == False &&
343 command (c) == MOUSEfunction && mouse_button == releasebutton)
344 {
345 last_mouse_event = releasebutton;
346 #ifdef debug_mouse
347 printf ("readchar: ignoring mouse release (report_release == False)\n");
348 #endif
349 c = _readchar ();
350 }
351 #ifdef debug_mouse
352 printf ("readchar: report_release = False\n");
353 #endif
354 report_release = False;
355
356 #ifdef winchhere
357 waitingforinput = waiting;
358 #else
359 waitingforinput = False;
360 #endif
361
362 /* the modification
363 if (quit) {
364 c = quit_char;
365 }
366 (now in __readchar) must not be placed after resetting the flag
367 waitingforinput = False;
368 Otherwise a QUIT signal coming in just between these two would
369 discard the last valid character just taken up.
370 */
371
372 timestamp_readchar ();
373
374 return c;
375 }
376
377 /*
378 readchar_nokeymap reads like readchar
379 but doesn't apply international keyboard mapping
380 */
381 static
382 unsigned long
readchar_nokeymap()383 readchar_nokeymap ()
384 {
385 unsigned long c;
386 int prev_dont_suppress_keymap = dont_suppress_keymap;
387
388 dont_suppress_keymap = 0;
389 c = readchar ();
390 dont_suppress_keymap = prev_dont_suppress_keymap;
391
392 return c;
393 }
394
395 /*
396 readcharacter_mapping () reads one character
397 either with or without keyboard mapping
398 */
399 static
400 unsigned long
readcharacter_mapping(map_keyboard,return_unicode)401 readcharacter_mapping (map_keyboard, return_unicode)
402 FLAG map_keyboard;
403 FLAG return_unicode;
404 {
405 int utfcount = 1;
406 unsigned long unichar;
407
408 if (map_keyboard) {
409 unichar = readchar ();
410 } else {
411 unichar = readchar_nokeymap ();
412 trace_keytrack ("readcharacter:readchar_nokeymap", unichar);
413 /* double check needed here because command ('\n') == SNL */
414 if (unichar == FUNcmd && command (unichar) == SNL) {
415 return '\r';
416 }
417 }
418
419 if (unichar == FUNcmd) {
420 /** housekeeping of some events to cover the cases:
421 focus-out mouse-click focus-in mouse-release (xterm 224)
422 focus-out mouse-click mouse-release focus-in
423 focus-out focus-in mouse-click mouse-release
424 and ignore the first mouse click/release in any case
425 */
426 FLAG skipmouse = False;
427
428 if (command (unichar) == FOCUSout) {
429 #ifdef debug_mouse
430 printf ("FOCUS out\n");
431 #endif
432 FOCUSout ();
433 skip_1click = True;
434 skip_1release = True;
435 skipmouse = True;
436 } else if (command (unichar) == FOCUSin) {
437 #ifdef debug_mouse
438 printf ("FOCUS in\n");
439 #endif
440 FOCUSin ();
441 skipmouse = True;
442 return FUNcmd;
443 } else if (command (unichar) == MOUSEfunction) {
444 if (mouse_button != releasebutton
445 && last_delta_readchar > 100 && skip_1click) {
446 /* skip click only immediately after focus in */
447 skip_1click = False;
448 skip_1release = False;
449 }
450
451 if (mouse_button == releasebutton && skip_1release) {
452 #ifdef debug_mouse
453 printf ("skipping 1 mouse release event\n");
454 #endif
455 skipmouse = True;
456 skip_1release = False;
457 } else if (mouse_button != releasebutton && skip_1click) {
458 #ifdef debug_mouse
459 printf ("skipping 1 mouse event\n");
460 #endif
461 skipmouse = True;
462 skip_1click = False;
463 skip_1release = False;
464 } else if (! window_focus) {
465 /* should not be needed anymore */
466 #ifdef debug_mouse
467 printf ("skipping mouse event while focus out\n");
468 #endif
469 skipmouse = True;
470 }
471 }
472
473 if (skipmouse) {
474 return readcharacter_mapping (map_keyboard, return_unicode);
475 } else {
476 /* WINCH exception isn't passing by here... */
477 #ifdef debug_mouse
478 if (command (unichar) == MOUSEfunction) {
479 if (mouse_button == releasebutton) {
480 printf ("passing mouse release event\n");
481 } else {
482 printf ("passing mouse event\n");
483 }
484 }
485 #endif
486 return FUNcmd;
487 }
488 }
489
490 if (utf8_input || queue_mode_mapped) {
491 if ((unichar & 0x80) == 0x00) {
492 utfcount = 1;
493 } else if ((unichar & 0xE0) == 0xC0) {
494 utfcount = 2;
495 unichar = unichar & 0x1F;
496 } else if ((unichar & 0xF0) == 0xE0) {
497 utfcount = 3;
498 unichar = unichar & 0x0F;
499 } else if ((unichar & 0xF8) == 0xF0) {
500 utfcount = 4;
501 unichar = unichar & 0x07;
502 } else if ((unichar & 0xFC) == 0xF8) {
503 utfcount = 5;
504 unichar = unichar & 0x03;
505 } else if ((unichar & 0xFE) == 0xFC) {
506 utfcount = 6;
507 unichar = unichar & 0x01;
508 } else /* illegal UTF-8 code */ {
509 return unichar;
510 }
511 while (utfcount > 1) {
512 unichar = (unichar << 6) | (readchar_nokeymap () & 0x3F);
513 utfcount --;
514 }
515 if (! return_unicode && (cjk_text || mapped_text)) {
516 return encodedchar (unichar);
517 } else {
518 return unichar;
519 }
520 } else if (cjk_term && multichar (unichar)) {
521 if (unichar == 0x8E && text_encoding_tag == 'C') {
522 unichar = (unichar << 24)
523 | (readchar_nokeymap () << 16)
524 | (readchar_nokeymap () << 8)
525 | readchar_nokeymap ();
526 } else if (unichar == 0x8F && (text_encoding_tag == 'J' || text_encoding_tag == 'X')) {
527 unichar = (unichar << 16)
528 | (readchar_nokeymap () << 8)
529 | readchar_nokeymap ();
530 } else {
531 int byte2 = readchar_nokeymap ();
532 if (text_encoding_tag == 'G' && '0' <= byte2 && byte2 <= '9') {
533 unichar = (unichar << 24)
534 | (byte2 << 16)
535 | (readchar_nokeymap () << 8)
536 | readchar_nokeymap ();
537 } else {
538 unichar = (unichar << 8) | byte2;
539 }
540 }
541 if (return_unicode || utf8_text) {
542 unichar = lookup_encodedchar (unichar);
543 }
544 return unichar;
545 } else {
546 if (mapped_term) {
547 if (! return_unicode && (cjk_text || mapped_text) && ! remapping_chars ()) {
548 #ifdef debug_mapped_keyboard
549 printf ("rc_m mapped (ret_u %d) -> %04X\n", return_unicode, unichar);
550 #endif
551 return unichar;
552 } else if (ascii_screen) {
553 /* skip validity check to allow Latin-1 input
554 if ASCII screen is set (reason may be just
555 missing display capability)
556 */
557 } else {
558 #ifdef debug_mapped_keyboard
559 printf ("rc_m mapped (ret_u %d) -> %04X -> %04X ...\n", return_unicode, unichar, lookup_mappedtermchar (unichar));
560 #endif
561 unichar = lookup_mappedtermchar (unichar);
562 if (no_unichar (unichar)) {
563 #ifdef debug_mapped_keyboard
564 printf ("rc_m mapped -> CHAR_INVALID\n");
565 #endif
566 return CHAR_INVALID;
567 }
568 }
569 }
570
571 if (! return_unicode && (cjk_text || mapped_text)) {
572 #ifdef debug_mapped_keyboard
573 printf ("rc_m -> %04X -> %04X\n", unichar, encodedchar (unichar));
574 #endif
575 return encodedchar (unichar);
576 } else {
577 #ifdef debug_mapped_keyboard
578 printf ("rc_m -> %04X\n", unichar);
579 #endif
580 return unichar;
581 }
582 }
583 }
584
585 /*
586 readcharacter () reads one character
587 keyboard mapping is suppressed
588 */
589 unsigned long
readcharacter()590 readcharacter ()
591 {
592 return readcharacter_mapping (False, False);
593 }
594
595 /*
596 readcharacter_mapped () reads one character
597 keyboard mapping is enabled
598 */
599 unsigned long
readcharacter_mapped()600 readcharacter_mapped ()
601 {
602 return readcharacter_mapping (True, False);
603 }
604
605 /*
606 readcharacter_unicode () reads one Unicode character
607 keyboard mapping is suppressed
608 */
609 unsigned long
readcharacter_unicode()610 readcharacter_unicode ()
611 {
612 return readcharacter_mapping (False, True);
613 }
614
615 /*
616 readcharacter_unicode_mapped () reads one Unicode character
617 keyboard mapping is enabled
618 */
619 unsigned long
readcharacter_unicode_mapped()620 readcharacter_unicode_mapped ()
621 {
622 return readcharacter_mapping (True, True);
623 }
624
625 /*
626 readcharacter_allbuttons always reports mouse button release
627 and also reports window size change as function RDwin
628 */
629 unsigned long
readcharacter_allbuttons(map_keyboard)630 readcharacter_allbuttons (map_keyboard)
631 FLAG map_keyboard;
632 {
633 unsigned long c;
634 int prev_report_winchg = report_winchg;
635
636 report_winchg = 1;
637
638 #ifdef debug_mouse
639 printf ("readchar_allbuttons: report_release = True\n");
640 #endif
641 report_release = True;
642
643 c = readcharacter_mapping (map_keyboard, True);
644
645 report_winchg = prev_report_winchg;
646
647 return c;
648 }
649
650
651 /*======================================================================*\
652 |* Mouse input *|
653 \*======================================================================*/
654
655 #ifdef debug_mouse
656
657 extern void do_trace_mouse _((char * tag));
658
659 void
do_trace_mouse(tag)660 do_trace_mouse (tag)
661 char * tag;
662 {
663 static char * button_name [] = {
664 "releasebutton",
665 "leftbutton",
666 "middlebutton",
667 "rightbutton",
668 "movebutton",
669 "wheelup",
670 "wheeldown"};
671
672 printf ("[%s] ", tag);
673 printf ("%X ", mouse_shift);
674 if (mouse_button != releasebutton) {
675 printf ("%s", button_name [mouse_button]);
676 } else {
677 printf ("release (%s)", button_name [mouse_prevbutton]);
678 }
679 printf (" @ %d:%d (%d:%d)\n", mouse_ypos, mouse_xpos, mouse_prevypos, mouse_prevxpos);
680 }
681
682 #endif
683
684 static
685 void
notice_previous_click()686 notice_previous_click ()
687 {
688 /* remember previous mouse click */
689 if (mouse_button == leftbutton || mouse_button == rightbutton || mouse_button == middlebutton) {
690 mouse_prevbutton = mouse_button;
691 mouse_prevxpos = mouse_xpos;
692 mouse_prevypos = mouse_ypos;
693 mouse_buttons_pressed ++;
694 }
695 }
696
697 static
698 void
fix_mouse_release_event()699 fix_mouse_release_event ()
700 {
701 /* workaround for incorrect mouse wheel escape sequences */
702 if (mouse_button == releasebutton) {
703 if (mouse_buttons_pressed > 0) {
704 mouse_buttons_pressed --;
705 } else {
706 /* fix the event report */
707 mouse_button = movebutton;
708 }
709 }
710 }
711
712 /*
713 * DIRECT...getxy () reads in the information part of a cursor escape sequence
714 */
715 static
716 int
DIRECTxtermgetbut()717 DIRECTxtermgetbut ()
718 {
719 int but = _readchar_nokeymap ();
720 if (but == quit_char) {
721 quit = True;
722 return 0;
723 }
724 if (use_mouse_extended) {
725 if ((but & 0xE0) == 0xC0) {
726 but &= 0x1F;
727 but = (but << 6) | (_readchar_nokeymap () & 0x3F);
728 }
729 }
730 return but;
731 }
732
733 static
734 int
DIRECTxtermgetpos()735 DIRECTxtermgetpos ()
736 {
737 int pos = _readchar_nokeymap ();
738 if (pos == quit_char) {
739 quit = True;
740 return 0;
741 }
742 if (use_mouse_extended) {
743 if ((pos & 0xE0) == 0xC0) {
744 pos &= 0x1F;
745 pos = (pos << 6) | (_readchar_nokeymap () & 0x3F);
746 }
747 if (pos == 0) {
748 pos = 0x800; /* out of range */
749 }
750 } else if (pos == 0) {
751 pos = 256; /* out of range */
752 }
753 return pos - 33;
754 }
755
756 static
757 void
get_mouse_button(button)758 get_mouse_button (button)
759 unsigned int button;
760 {
761 mouse_shift = button & 0x1C;
762 if (button & 32) {
763 mouse_button = movebutton;
764 } else if (button & 64) {
765 button &= 0x03;
766 if (button == 0x00) {
767 mouse_button = wheelup;
768 } else {
769 mouse_button = wheeldown;
770 }
771 } else {
772 button &= 0x03;
773 if (button == 0x00) {
774 mouse_button = leftbutton;
775 } else if (button == 0x01) {
776 mouse_button = middlebutton;
777 } else if (button == 0x02) {
778 mouse_button = rightbutton;
779 } else {
780 mouse_button = releasebutton;
781 }
782 }
783 }
784
785 static
786 void
DIRECTxtermgetxy(code)787 DIRECTxtermgetxy (code)
788 char code; /* 'M' for normal mouse report, 't'/'T' for tracking */
789 {
790 character button;
791
792 notice_previous_click ();
793
794 if (code == 't') {
795 mouse_button = releasebutton;
796 } else if (code == 'T') {
797 /* could be Siemens 97801/97808 page down ... !?! */
798 button = _readchar_nokeymap ();
799 button = _readchar_nokeymap ();
800 button = _readchar_nokeymap ();
801 button = _readchar_nokeymap ();
802 mouse_button = releasebutton;
803 } else { /* code == 'M' */
804 if (xterm_version >= 268) {
805 button = DIRECTxtermgetbut ();
806 } else {
807 button = _readchar_nokeymap ();
808 if (button == quit_char) {
809 quit = True;
810 }
811 }
812
813 if (bidi_screen && mintty_version == 0 && button == '$') {
814 /* fix mlterm quirk for mouse wheel scroll down */
815 button = 'a';
816 button = '#';
817 }
818 get_mouse_button (button - 32);
819 }
820
821 fix_mouse_release_event ();
822
823 mouse_xpos = DIRECTxtermgetpos ();
824 mouse_ypos = DIRECTxtermgetpos () - MENU;
825
826 #ifdef debug_mouse
827 printf ("mouse %c: ", code);
828 trace_mouse ("DIRECTxtermgetxy");
829 #endif
830
831 #if defined (unix) || defined (vms)
832 if (use_mouse_button_event_tracking && mouse_button == releasebutton) {
833 mouse_button_event_mode (False);
834 }
835 #endif
836 }
837
838 static
839 void
DIRECTsgrgetxy()840 DIRECTsgrgetxy ()
841 {
842 notice_previous_click ();
843
844 if (ansi_fini == 'm') {
845 ansi_param [0] |= 0x3; /* release button */
846 }
847 get_mouse_button (ansi_param [0]);
848
849 fix_mouse_release_event ();
850
851 mouse_ypos = ansi_param [2] - 1 - MENU;
852 mouse_xpos = ansi_param [1] - 1;
853 }
854
855 static
856 void
DIRECTurxvtgetxy()857 DIRECTurxvtgetxy ()
858 {
859 notice_previous_click ();
860
861 get_mouse_button (ansi_param [0] - 32);
862
863 fix_mouse_release_event ();
864
865 mouse_ypos = ansi_param [2] - 1 - MENU;
866 mouse_xpos = ansi_param [1] - 1;
867 }
868
869 static
870 void
DIRECTcrttoolgetxy()871 DIRECTcrttoolgetxy ()
872 {
873 character c;
874 int xpos;
875 int ypos;
876
877 /* fix crttool settings */
878 use_ascii_graphics = True;
879 menu_border_style = 'r';
880 use_mouse_release = False;
881
882 notice_previous_click ();
883
884 c = get_digits (& ypos); /* c should be ';' */
885 c = get_digits (& xpos);
886 if (c == 'l') {
887 mouse_button = leftbutton;
888 } else if (c == 'm') {
889 mouse_button = middlebutton;
890 } else if (c == 'r') {
891 mouse_button = rightbutton;
892 } else {
893 mouse_button = releasebutton;
894 }
895
896 fix_mouse_release_event ();
897
898 mouse_ypos = ypos - 1 - MENU;
899 mouse_xpos = xpos - 1;
900 }
901
902 static
903 void
DIRECTvtlocatorgetxy()904 DIRECTvtlocatorgetxy ()
905 {
906 notice_previous_click ();
907
908 if (ansi_param [0] == 2) {
909 mouse_button = leftbutton;
910 } else if (ansi_param [0] == 4) {
911 mouse_button = middlebutton;
912 } else if (ansi_param [0] == 6) {
913 mouse_button = rightbutton;
914 } else if (ansi_param [0] == 9) {
915 mouse_button = wheelup;
916 } else if (ansi_param [0] == 11) {
917 mouse_button = wheeldown;
918 } else {
919 mouse_button = releasebutton;
920 }
921
922 fix_mouse_release_event ();
923
924 mouse_ypos = ansi_param [2] - 1 - MENU;
925 mouse_xpos = ansi_param [3] - 1;
926 }
927
928 /*
929 * DIRECT... () reads in a direct cursor movement input sequence.
930 * Then it either performs a direct function (move/copy/paste) or
931 * invokes the menu functions.
932 * Is no longer called as this is already handled in _readchar ().
933 */
934 void
DIRECTxterm()935 DIRECTxterm ()
936 {
937 #ifdef debug_mouse
938 printf ("DIRECTxterm\n");
939 #endif
940 DIRECTxtermgetxy ('M');
941 MOUSEfunction ();
942 }
943
944 void
TRACKxterm()945 TRACKxterm ()
946 {
947 #ifdef debug_mouse
948 printf ("TRACKxterm\n");
949 #endif
950 DIRECTxtermgetxy ('t');
951 MOUSEfunction ();
952 }
953
954 void
TRACKxtermT()955 TRACKxtermT ()
956 {
957 #ifdef debug_mouse
958 printf ("TRACKxtermT\n");
959 #endif
960 DIRECTxtermgetxy ('T');
961 MOUSEfunction ();
962 }
963
964 void
DIRECTcrttool()965 DIRECTcrttool ()
966 {
967 DIRECTcrttoolgetxy ();
968 MOUSEfunction ();
969 }
970
971 void
DIRECTvtlocator()972 DIRECTvtlocator ()
973 {
974 DIRECTvtlocatorgetxy ();
975 MOUSEfunction ();
976 }
977
978
979 #ifdef CURSES
980 #ifdef KEY_MOUSE
981
982 #ifdef __PDCURSES__
983
984 /*
985 * CURSgetxy () reads in the information of a mouse event
986 */
987 static
988 void
CURSgetxy()989 CURSgetxy ()
990 {
991 # define mouse_state Mouse_status.changes
992 # define mouse_x MOUSE_X_POS
993 # define mouse_y MOUSE_Y_POS
994
995 int button = 0;
996
997 notice_previous_click ();
998
999 request_mouse_pos ();
1000
1001 if (BUTTON_CHANGED (1)) {
1002 button = 1;
1003 } else if (BUTTON_CHANGED (2)) {
1004 button = 2;
1005 } else if (BUTTON_CHANGED (3)) {
1006 button = 3;
1007 }
1008
1009 #ifdef BUTTON_SHIFT
1010 mouse_shift = (BUTTON_STATUS (button) & BUTTON_MODIFIER_MASK) == BUTTON_SHIFT;
1011 #else
1012 mouse_shift = 0;
1013 #endif
1014
1015 if ((BUTTON_STATUS (button) & BUTTON_ACTION_MASK) == BUTTON_PRESSED) {
1016 if (button == 1) {
1017 mouse_button = leftbutton;
1018 } else if (button == 2) {
1019 mouse_button = middlebutton;
1020 } else if (button == 3) {
1021 mouse_button = rightbutton;
1022 } else {
1023 mouse_button = releasebutton;
1024 }
1025 } else {
1026 mouse_button = releasebutton;
1027 }
1028
1029 fix_mouse_release_event ();
1030
1031 mouse_xpos = mouse_x;
1032 mouse_ypos = mouse_y - MENU;
1033 }
1034
1035 # else
1036
1037 static
1038 void
CURSgetxy()1039 CURSgetxy ()
1040 {
1041 #ifdef NCURSES_VERSION
1042 MEVENT mouse_info;
1043 # define mouse_state mouse_info.bstate
1044 # define mouse_x mouse_info.x
1045 # define mouse_y mouse_info.y
1046 #else
1047 unsigned long mouse_state;
1048 # define mouse_x Mouse_status.x
1049 # define mouse_y Mouse_status.y
1050 #endif
1051
1052 notice_previous_click ();
1053
1054 #ifdef NCURSES_VERSION
1055 getmouse (& mouse_info);
1056 #else
1057 mouse_state = getmouse ();
1058 #endif
1059
1060 #ifdef BUTTON_SHIFT
1061 mouse_shift = mouse_state & BUTTON_SHIFT;
1062 #else
1063 mouse_shift = 0;
1064 #endif
1065
1066 if (mouse_state & BUTTON1_CLICKED) {
1067 mouse_button = leftbutton;
1068 } else if (mouse_state & BUTTON2_CLICKED) {
1069 mouse_button = middlebutton;
1070 } else if (mouse_state & BUTTON3_CLICKED) {
1071 mouse_button = rightbutton;
1072 } else {
1073 mouse_button = releasebutton;
1074 }
1075
1076 fix_mouse_release_event ();
1077
1078 mouse_xpos = mouse_x - 1;
1079 mouse_ypos = mouse_y - 1 - MENU;
1080 }
1081
1082 #endif
1083
1084 #endif
1085 #endif
1086
1087
1088 /*======================================================================*\
1089 |* Character input *|
1090 \*======================================================================*/
1091
1092 /* max. length of function key sequence to be detected
1093 (depending on the fkeymap table, approx. 7),
1094 or of keyboard mapping sequence plus potential mapping rest
1095 */
1096 #define MAXCODELEN 33
1097
1098 /*
1099 * queue collects the keys of an Escape sequence typed in until the
1100 * sequence can be detected or rejected.
1101 * If the queue is not empty, queue [0] contains the character next
1102 * to be delivered by _readchar () (it's not a ring buffer).
1103 * The queue contents are always terminated by a '\0', so queue can also
1104 * be taken as a character string.
1105 */
1106 static character queue [MAXCODELEN + 1];
1107 static character * endp = queue;
1108 static character ctrl_queue [MAXCODELEN + 1];
1109 static character * endcp = ctrl_queue;
1110 static character raw_queue [MAXCODELEN + 1];
1111 static int rqi = 0;
1112
1113 static
1114 int
get1byte()1115 get1byte ()
1116 {
1117 int c = read1byte ();
1118 if (rqi < MAXCODELEN) {
1119 raw_queue [rqi ++] = c;
1120 raw_queue [rqi] = '\0';
1121 }
1122 return c;
1123 }
1124
1125 #ifdef not_used
1126 static
1127 int
q_empty()1128 q_empty ()
1129 {
1130 return endp == queue ? 1 : 0;
1131 }
1132 #endif
1133
1134 static
1135 int
q_notfull()1136 q_notfull ()
1137 {
1138 return endp - queue == MAXCODELEN ? 0 : 1;
1139 }
1140
1141 static
1142 void
raw_q_clear()1143 raw_q_clear ()
1144 {
1145 rqi = 0;
1146 }
1147
1148 static
1149 void
q_clear()1150 q_clear ()
1151 {
1152 endp = queue;
1153 endcp = ctrl_queue;
1154 rqi = 0;
1155 }
1156
1157 static
1158 int
q_len()1159 q_len ()
1160 {
1161 return endp - queue;
1162 }
1163
1164 static
1165 void
q_put(c)1166 q_put (c)
1167 character c;
1168 /* queue must not be full prior to this call! */
1169 {
1170 * endp = c;
1171 * ++ endp = '\0';
1172 if (c == '\0') {
1173 * endcp = '@';
1174 } else {
1175 * endcp = c;
1176 }
1177 * ++ endcp = '\0';
1178 }
1179
1180 /*
1181 static
1182 character
1183 q_unput ()
1184 {
1185 character c;
1186 if (q_len () == 0) {
1187 return '\0';
1188 } else {
1189 endp --;
1190 endcp --;
1191 c = * endp;
1192 * endp = '\0';
1193 * endcp = '\0';
1194 return c;
1195 }
1196 }
1197 */
1198
1199 static
1200 character
q_get()1201 q_get ()
1202 {
1203 character c;
1204 register character * pd;
1205 register character * ps;
1206
1207 c = * queue;
1208 pd = queue;
1209 ps = pd + 1;
1210 while (ps <= endp) {
1211 * pd ++ = * ps ++;
1212 }
1213 if (endp > queue) {
1214 endp --;
1215 endcp --;
1216 }
1217
1218 #define dont_debug_queue_delivery
1219 #ifdef debug_queue_delivery
1220 printf ("%02X\n", c);
1221 #endif
1222
1223 return c;
1224 }
1225
1226
1227 #ifndef msdos
1228
1229 /*
1230 * Look up key sequence in fkeymap table.
1231 * if matchmode == 0:
1232 * findkey (str) >= 0: escape sequence found
1233 * (str == fkeymap [findkey (str)].fk)
1234 * keyproc = fkeymap [i].fp (side effect)
1235 * == -1: escape sequence prefix recognised
1236 * (str is prefix of some entry in fkeymap)
1237 * == -2: escape sequence not found
1238 * (str is not contained in fkeymap)
1239 * * found == index of exact match if found
1240 * if matchmode == 1 (not used):
1241 * return -1 if any prefix detected (even if other exact match found)
1242 * if matchmode == 2 (not used):
1243 * don't return -1, only report exact or no match
1244 */
1245 static
1246 int
findkeyin(str,fkeymap,matchmode,found)1247 findkeyin (str, fkeymap, matchmode, found)
1248 char * str;
1249 struct fkeyentry * fkeymap;
1250 int matchmode;
1251 int * found;
1252 {
1253 int lastmatch = 0; /* last index with string matching prefix */
1254 register int i;
1255 int ret = -2;
1256
1257 * found = -1;
1258
1259 if (fkeymap [0].fk == NIL_PTR) {
1260 return ret;
1261 }
1262
1263 i = lastmatch;
1264 do {
1265 char * strpoi = str;
1266 char * mappoi = fkeymap [i].fk;
1267 do {
1268 /* compare str with map entry */
1269 if (* strpoi != * mappoi) {
1270 break;
1271 }
1272 if (* strpoi) {
1273 strpoi ++;
1274 mappoi ++;
1275 }
1276 } while (* strpoi);
1277
1278 /* if (strncmp (str, fkeymap [i].fk, strlen (str)) == 0) {*/
1279 if (* strpoi == '\0') {
1280 /* str is prefix of current entry */
1281 lastmatch = i;
1282 /* if (strlen (str) == strlen (fkeymap [i].fk)) {*/
1283 if (* mappoi == '\0') {
1284 /* str is equal to current entry */
1285 * found = i;
1286 keyproc = fkeymap [i].fp;
1287 if (! keyproc) {
1288 keyproc = I;
1289 }
1290 fkeyshift = fkeymap [i].fkeyshift;
1291 if (matchmode == 1) {
1292 /* return index unless other prefix
1293 was or will be found */
1294 if (ret == -2) {
1295 ret = i;
1296 }
1297 } else {
1298 return i;
1299 }
1300 } else {
1301 /* str is partial prefix of current entry */
1302 if (matchmode == 1) {
1303 /* return -1 but continue to search
1304 for exact match */
1305 ret = -1;
1306 } else if (matchmode != 2) {
1307 return -1;
1308 } else {
1309 }
1310 }
1311 }
1312 ++ i;
1313 if (fkeymap [i].fk == NIL_PTR) {
1314 i = 0;
1315 return ret;
1316 }
1317 } while (i != lastmatch);
1318
1319 return ret;
1320 }
1321
1322 static
1323 int
findkey(str)1324 findkey (str)
1325 char * str;
1326 {
1327 int dummy;
1328 int res;
1329
1330 res = findkeyin (str, fkeymap_spec, 0, & dummy);
1331 #ifdef debug_findkey
1332 printf ("<^[%s> _specific [%d]\n", str + 1, res);
1333 #endif
1334
1335 if (res != -2) {
1336 return res;
1337 }
1338
1339 res = findkeyin (str, fkeymap, 0, & dummy);
1340 #ifdef debug_findkey
1341 printf ("<^[%s> _deftable [%d]\n", str + 1, res);
1342 #endif
1343
1344 if (res != -2) {
1345 return res;
1346 }
1347
1348 #ifdef TERMINFO
1349 res = findkeyin (str, fkeymap_terminfo, 0, & dummy);
1350 # ifdef debug_findkey
1351 printf ("<^[%s> _terminfo [%d]\n", str + 1, res);
1352 # endif
1353 #endif
1354
1355 return res;
1356 }
1357
1358 #endif /* #ifndef msdos */
1359
1360
1361 #ifdef CURSES
1362 # ifdef vms
1363 typedef unsigned int chtype;
1364 # endif
1365
1366 chtype key;
1367
1368 extern int curs_readchar _((void));
1369
1370 static
1371 void
showfkey()1372 showfkey ()
1373 {
1374 build_string (text_buffer, "Curses function key entered: %03X / %04o", (int) key, (int) key);
1375 status_msg (text_buffer);
1376 }
1377
1378
1379 /*
1380 * Read a character, ignoring uninterpreted key strokes (SHIFT etc.)
1381 * also handles resize events
1382 */
1383 int
curs_readchar()1384 curs_readchar ()
1385 {
1386 unsigned long keycode;
1387 keycode = __readchar ();
1388 #ifdef vms
1389 if (keycode >= 0x100) {
1390 printf ("readchar: vms curses key %03X\n", keycode); sleep (1);
1391 }
1392 #else
1393 while (keycode >= KEY_MIN) {
1394 switch (keycode) {
1395 #ifdef KEY_RESIZE
1396 case KEY_RESIZE:
1397 printf ("curses resize key received \n"); sleep (1);
1398 keyproc = showfkey;
1399 return FUNcmd;
1400 #endif
1401 #ifdef KEY_SHIFT_L
1402 case KEY_SHIFT_L:
1403 case KEY_SHIFT_R:
1404 case KEY_CONTROL_L:
1405 case KEY_CONTROL_R:
1406 case KEY_ALT_L:
1407 case KEY_ALT_R:
1408 break;
1409 #endif
1410 default:
1411 return keycode;
1412 }
1413 keycode = __readchar ();
1414 }
1415 #endif
1416
1417 return keycode;
1418 }
1419
1420 /*
1421 * Mapping KEY_ code (curses) -> mined function
1422 */
1423 struct {
1424 chtype keycode;
1425 voidfunc func;
1426 unsigned char fkeyshift;
1427 } cursfunc [] = {
1428 #ifndef vms
1429 {KEY_F(1), F1},
1430 {KEY_F(2), F2},
1431 {KEY_F(3), F3},
1432 {KEY_F(4), F4},
1433 {KEY_F(5), F5},
1434 {KEY_F(6), F6},
1435 {KEY_F(7), F7},
1436 {KEY_F(8), F8},
1437 {KEY_F(9), F9},
1438 {KEY_F(10), F10},
1439 {KEY_F(11), F11},
1440 {KEY_F(12), F12},
1441 {KEY_IC, INSkey},
1442 {KEY_DC, DELkey},
1443 {KEY_HOME, HOMEkey},
1444 {KEY_END, ENDkey},
1445 {KEY_PPAGE, PGUPkey},
1446 {KEY_NPAGE, PGDNkey},
1447 {KEY_UP, UPkey},
1448 {KEY_DOWN, DNkey},
1449 {KEY_LEFT, LFkey},
1450 {KEY_RIGHT, RTkey},
1451 {KEY_B2, HOP},
1452 {KEY_A1, HOMEkey},
1453 {KEY_A3, PGUPkey},
1454 {KEY_C1, ENDkey},
1455 {KEY_C3, PGDNkey},
1456 #endif
1457 #ifdef KEY_A2
1458 {KEY_A2, UPkey},
1459 #endif
1460 #ifdef KEY_C2
1461 {KEY_C2, DNkey},
1462 #endif
1463 #ifdef KEY_B1
1464 {KEY_B1, LFkey},
1465 #endif
1466 #ifdef KEY_B3
1467 {KEY_B3, RTkey},
1468 #endif
1469 {0x1BF, BLINEORUP},
1470 {0x1C0, ELINEORDN},
1471
1472 #ifdef PAD0
1473 {PAD0, PASTE},
1474 #endif
1475 #ifdef __PDCURSES__
1476 {PADSLASH, I},
1477 {PADSTAR, I},
1478 {PADMINUS, I},
1479 {PADPLUS, I},
1480 {PADSTOP, CUT},
1481 {PADENTER, SNL},
1482 {ALT_F, FILEMENU},
1483 {ALT_E, EDITMENU},
1484 {ALT_S, SEARCHMENU},
1485 {ALT_P, PARAMENU},
1486 {ALT_O, OPTIONSMENU},
1487 #endif
1488
1489 {0}
1490 };
1491
1492 /*
1493 * Look up mined function by curses key code
1494 * lookup_curskey (str) >= 0: keycode == cursfunc [lookup_curskey (str)].fk
1495 * == -1: keycode is not contained in mapping table
1496 */
1497 static
1498 voidfunc
lookup_curskey(keycode)1499 lookup_curskey (keycode)
1500 chtype keycode;
1501 {
1502 register int i;
1503
1504 i = 0;
1505 while (cursfunc [i].keycode != 0 && cursfunc [i].keycode != keycode) {
1506 i ++;
1507 }
1508 if (cursfunc [i].keycode == 0) {
1509 return showfkey;
1510 } else {
1511 keyshift |= cursfunc [i].fkeyshift;
1512 return cursfunc [i].func;
1513 }
1514 }
1515
1516 #endif
1517
1518
1519 /*
1520 * Functions to read a character from terminal.
1521 If _readchar () detects a function key sequence (according to the
1522 table fkeymap), FUNcmd is returned, and the associated function is
1523 stored in the variable keyproc.
1524 Keyboard mapping is applied.
1525 */
1526
1527 unsigned long
_readchar_nokeymap()1528 _readchar_nokeymap ()
1529 {
1530 unsigned long c;
1531 int prev_dont_suppress_keymap = dont_suppress_keymap;
1532
1533 dont_suppress_keymap = 0;
1534 c = _readchar ();
1535 dont_suppress_keymap = prev_dont_suppress_keymap;
1536
1537 return c;
1538 }
1539
1540
1541 #define dont_debug_readbyte
1542
1543 #define dont_debug_terminal_response
1544 #ifdef debug_terminal_response
1545 #define trace_terminal_response(what) if (debug_tag) printf ("[%s (%d)] %s\n", debug_tag, msec, what);
1546 #else
1547 #define trace_terminal_response(what)
1548 #endif
1549
1550
1551 static int choose_char _((char *));
1552
1553 static character rest_queue [MAXCODELEN + 1];
1554 static FLAG have_rest_queue = False;
1555
1556 static
1557 void
putback_rest(rest)1558 putback_rest (rest)
1559 char * rest;
1560 {
1561 char old_rest_queue [MAXCODELEN + 1];
1562 #ifdef debug_readbyte
1563 printf ("putback_rest <%s>\n", rest);
1564 #endif
1565
1566 if (! streq (rest, " ")) {
1567 if (have_rest_queue) {
1568 /**
1569 overdraft characters to be mapped are
1570 put back into rest_queue
1571 to be considered for subsequent mapping
1572 -> Hiragana nihongo
1573 -> Hiragana nyi
1574 -> test abcde
1575 */
1576 strcpy (old_rest_queue, (char *) rest_queue);
1577 } else {
1578 old_rest_queue [0] = '\0';
1579 }
1580 strcpy ((char *) rest_queue, rest);
1581 strcat ((char *) rest_queue, old_rest_queue);
1582 have_rest_queue = True;
1583 }
1584 }
1585
1586 /* read 1 byte from queue; for curses, however, function
1587 key indications must be passed on which are longer than 8 bits
1588 */
1589 int
read1byte()1590 read1byte ()
1591 {
1592 if (have_rest_queue) {
1593 character * cr = rest_queue;
1594 character ch = * rest_queue;
1595 while (* (cr + 1) != '\0') {
1596 * cr = * (cr + 1);
1597 cr ++;
1598 }
1599 * cr = '\0';
1600 if (* rest_queue == '\0') {
1601 have_rest_queue = False;
1602 }
1603 #ifdef debug_readbyte
1604 printf ("read byte %02X from rest queue\n", ch);
1605 #endif
1606 return ch;
1607 } else {
1608 int ch;
1609 #ifdef CURSES
1610 ch = curs_readchar ();
1611 #else
1612 #ifdef debug_readbyte
1613 printf ("reading byte from io (report_winchg %d)\n", report_winchg);
1614 #endif
1615 if (report_winchg) {
1616 ch = __readchar_report_winchg ();
1617 } else {
1618 ch = __readchar ();
1619 }
1620 #endif
1621 #ifdef debug_readbyte
1622 printf ("read byte %02X from io\n", ch);
1623 #endif
1624 return ch;
1625 }
1626 }
1627
1628
1629 static
1630 int
bytereadyafter(msec,debug_tag)1631 bytereadyafter (msec, debug_tag)
1632 int msec;
1633 char * debug_tag;
1634 {
1635 if (have_rest_queue) {
1636 trace_terminal_response ("from rest queue");
1637 return 1;
1638 } else {
1639 if (inputreadyafter (msec) > 0) {
1640 trace_terminal_response ("response");
1641 return 1;
1642 } else {
1643 trace_terminal_response ("timeout");
1644 return 0;
1645 }
1646 }
1647 }
1648
1649 /*
1650 * Is a character available within a specified number of milliseconds ?
1651 */
1652 int
char_ready_within(msec,debug_tag)1653 char_ready_within (msec, debug_tag)
1654 int msec;
1655 char * debug_tag;
1656 {
1657 if (q_len () > 0) {
1658 trace_terminal_response ("from queue");
1659 return 1;
1660 } else {
1661 return bytereadyafter (msec, debug_tag);
1662 }
1663 }
1664
1665
1666 #ifndef msdos
1667 #define radical_stroke
1668 #endif
1669
1670
1671 #ifdef radical_stroke
1672 static menuitemtype radicalsmenu [] = {
1673 /* 1 stroke radicals */
1674 {"①.1:一 2:丨 3:丶 4:丿乀乁 5:乙乚乛 6:亅", dummyfunc, ""},
1675 /* 2 strokes radicals */
1676 {"②.7:二 8:亠 9:人亻 10:儿 11:入 12:八 13:冂 14:冖", dummyfunc, ""},
1677 {"②.15:冫 16:几 17:凵 18:刀刁刂 19:力 20:勹 21:匕", dummyfunc, ""},
1678 {"②.22:匚 23:匸 24:十 25:卜 26:卩 27:厂 28:厶 29:又", dummyfunc, ""},
1679 /* 3 strokes radicals */
1680 {"③.30:口 31:囗 32:土 33:士 34:夂 35:夊 36:夕 37:大夨 38:女 39:子孑孒孓", dummyfunc, ""},
1681 {"③.40:宀 41:寸 42:小 43:尢尣 44:尸 45:屮 46:山 47:巛巜川 48:工 49:己已巳", dummyfunc, ""},
1682 {"③.50:巾 51:干 52:乡幺 53:广 54:廴 55:廾 56:弋 57:弓 58:彐彑 59:彡 60:彳", dummyfunc, ""},
1683 /* 4 strokes radicals */
1684 {"④.61:心忄 62:戈 63:戶户戸 64:手扌才 65:支 66:攴攵 67:文 68:斗", dummyfunc, ""},
1685 {"④.69:斤 70:方 71:无 72:日 73:曰 74:月 75:木朩 76:欠 77:止 78:歹 79:殳", dummyfunc, ""},
1686 {"④.80:毋毌 81:比 82:毛 83:氏 84:气 85:水氵 86:火灬 87:爪爫 88:父 89:爻", dummyfunc, ""},
1687 {"④.90:丬爿 91:片 92:牙㸦 93:牛牜 94:犬犭", dummyfunc, ""},
1688 /* 5 strokes radicals */
1689 {"⑤.95:玄 96:玉王 97:瓜 98:瓦 99:甘 100:生 101:用甩 102:田由甲申甴电", dummyfunc, ""},
1690 {"⑤.103:疋 104:疒 105:癶 106:白 107:皮 108:皿 109:目", dummyfunc, ""},
1691 {"⑤.110:矛 111:矢 112:石 113:示礻 114:禸 115:禾 116:穴 117:立", dummyfunc, ""},
1692 /* 6 strokes radicals */
1693 {"⑥.118:竹 119:米 120:糸糹纟 121:缶 122:网罒罓䍏 123:羊 124:羽 125:老耂考", dummyfunc, ""},
1694 {"⑥.126:而 127:耒 128:耳 129:聿肀 130:肉 131:臣 132:自", dummyfunc, ""},
1695 {"⑥.133:至 134:臼 135:舌 136:舛 137:舟 138:艮 139:色 140:艸艹䒑", dummyfunc, ""},
1696 {"⑥.141:虍 142:虫 143:血 144:行 145:衣衤 146:襾西覀", dummyfunc, ""},
1697 /* 7 strokes radicals */
1698 {"⑦.147:見见 148:角 149:言訁讠 150:谷 151:豆 152:豕 153:豸", dummyfunc, ""},
1699 {"⑦.154:貝贝 155:赤 156:走赱 157:足 158:身 159:車车 160:辛", dummyfunc, ""},
1700 {"⑦.161:辰 162:辵辶 163:邑 164:酉 165:釆 166:里", dummyfunc, ""},
1701 /* 8 strokes radicals */
1702 {"⑧.167:金釒钅 168:長镸长 169:門门 170:阜阝", dummyfunc, ""},
1703 {"⑧.171:隶 172:隹 173:雨 174:靑青 175:非", dummyfunc, ""},
1704 /* 9 strokes radicals */
1705 {"⑨.176:面靣 177:革 178:韋韦 179:韭 180:音 181:頁页", dummyfunc, ""},
1706 {"⑨.182:風风 183:飛飞 184:食飠饣 185:首 186:香", dummyfunc, ""},
1707 /* 10 strokes radicals */
1708 {"⑩.187:馬马 188:骨 189:高髙 190:髟 191:鬥 192:鬯 193:鬲 194:鬼", dummyfunc, ""},
1709 /* 11 strokes radicals */
1710 {"⑪.195:魚鱼 196:鳥鸟 197:鹵 198:鹿 199:麥麦 200:麻", dummyfunc, ""},
1711 /* 12 strokes radicals */
1712 {"⑫.201:黃黄 202:黍 203:黑黒 204:黹", dummyfunc, ""},
1713 /* 13 strokes radicals */
1714 {"⑬.205:黽黾 206:鼎 207:鼓鼔 208:鼠鼡", dummyfunc, ""},
1715 /* 14 strokes radicals */
1716 {"⑭.209:鼻 210:齊齐", dummyfunc, ""},
1717 /* 15 strokes radicals */
1718 {"⑮.211:齒齿", dummyfunc, ""},
1719 /* 16 strokes radicals */
1720 {"⑯.212:龍龙 213:龜龟", dummyfunc, ""},
1721 /* 17 strokes radical */
1722 {"⑰.214:龠", dummyfunc, ""},
1723 };
1724 #endif
1725
1726
1727 #define dont_debug_kbesc
1728 #define dont_debug_kbansi
1729 #define dont_debug_kbmap
1730
1731 static
1732 unsigned long
_readchar()1733 _readchar ()
1734 {
1735 unsigned long ch;
1736 char * choice;
1737 int choice_index;
1738 /* queue handling */
1739 int res;
1740 char * found;
1741 char * mapped;
1742 char * prev_found = NIL_PTR;
1743
1744
1745 if (escape_delay == 0 || keymap_delay == 0) {
1746 char * env = envvar ("ESCDELAY");
1747 if (env) {
1748 (void) scan_int (env, & escape_delay);
1749 }
1750 if (escape_delay == 0) {
1751 escape_delay = default_escape_delay;
1752 }
1753 env = envvar ("MAPDELAY");
1754 if (env) {
1755 (void) scan_int (env, & keymap_delay);
1756 }
1757 if (keymap_delay == 0) {
1758 keymap_delay = default_keymap_delay;
1759 }
1760 }
1761
1762
1763 if (q_len () > 0) {
1764 return q_get ();
1765 }
1766 queue_mode_mapped = False;
1767 raw_q_clear ();
1768
1769 keyshift = 0;
1770 #ifdef msdos
1771 mouse_shift = 0;
1772 #endif
1773
1774
1775 #ifdef radical_stroke
1776 /* plug-in specific input methods */
1777 if (allow_keymap && dont_suppress_keymap
1778 && streq (keyboard_mapping, "rs")
1779 ) {
1780 int choice_col = x;
1781 int choice_line = y + 1;
1782 char radicalnumber [4];
1783
1784 choice_index = -1;
1785
1786 /* adjust menu position if too far down */
1787 if (choice_line + arrlen (radicalsmenu) + 2 > YMAX) {
1788 choice_line = y - arrlen (radicalsmenu) - 2;
1789 if (choice_line < 0) {
1790 choice_line = 0;
1791 }
1792 }
1793
1794 /* adjust menu position if on status line */
1795 if (input_active) {
1796 choice_line = YMAX - arrlen (radicalsmenu) - 2;
1797 if (choice_line < 0) {
1798 choice_line = 0;
1799 }
1800 choice_col = lpos;
1801 }
1802
1803 /* try to get radical, then character, from user */
1804 while (choice_index < 0) {
1805 int radical = popup_menu (radicalsmenu, arrlen (radicalsmenu),
1806 choice_col, choice_line,
1807 "Select radical", False, False, "1234567890x");
1808 if (radical < 0) {
1809 /* revert to previous mapping (or none) */
1810 toggleKEYMAP ();
1811 set_cursor_xy ();
1812 flush ();
1813 choice_index = 0; /* continue */
1814 } else {
1815 int radical_row = radical / 11;
1816 int radical_col = radical % 11;
1817 mapped = radicalsmenu [radical_row].itemname;
1818 while (* mapped != '\0' &&
1819 (* mapped < '0' || * mapped > '9'
1820 || radical_col > 0))
1821 {
1822 if (* mapped == ':') {
1823 radical_col --;
1824 }
1825 mapped ++;
1826 }
1827 found = radicalnumber;
1828 while (* mapped >= '0' && * mapped <= '9') {
1829 * found ++ = * mapped ++;
1830 }
1831 * found = '\0';
1832 res = map_key (radicalnumber, 2, & found, & mapped);
1833 if (res >= 0) {
1834 /* first goto in my life and then
1835 such an exceptionally ugly one -
1836 but it works well just this way */
1837 goto handle_mapped;
1838 } else {
1839 ring_bell ();
1840 }
1841 }
1842 }
1843 }
1844 #endif
1845
1846
1847 #ifdef CURSES
1848
1849 key = read1byte ();
1850 #ifdef vms
1851 if (key >= 0x100) {
1852 printf ("_readchar: vms curses key %03X\n", key); sleep (1);
1853 }
1854 #else
1855 if (key >= KEY_MIN) {
1856 #ifdef KEY_MOUSE
1857 if (key == KEY_MOUSE) {
1858 CURSgetxy ();
1859 keyproc = MOUSEfunction;
1860 return FUNcmd;
1861 }
1862 #endif
1863 keyproc = lookup_curskey (key);
1864 return FUNcmd;
1865 }
1866 #endif
1867 ch = key;
1868
1869 #else /* #ifdef CURSES */
1870
1871 #ifdef dosmouse
1872 {
1873 int ich = __readchar ();
1874 if (ich == FUNcmd) {
1875 DIRECTdosmousegetxy ();
1876 keyproc = MOUSEfunction;
1877 return FUNcmd;
1878 } else {
1879 ch = ich;
1880 }
1881 }
1882 #else
1883 ch = read1byte ();
1884 if (ch == FUNcmd) {
1885 /* pass back WINCH exception */
1886 return FUNcmd;
1887 }
1888 #endif
1889
1890 #endif /* #else CURSES */
1891
1892
1893 #ifdef msdos
1894
1895 if (ch > 0xFF) {
1896 keyproc = pc_xkey_map [ch - 0x100].fp;
1897 if (! keyproc) {
1898 keyproc = I;
1899 }
1900 keyshift |= pc_xkey_map [ch - 0x100].fkeyshift;
1901 return FUNcmd;
1902 }
1903
1904 if (ch == '\000') {
1905 # ifdef dosmouse
1906 ch = getch ();
1907 # else
1908 ch = read1byte ();
1909 # endif
1910 keyproc = pc_xkey_map [ch].fp;
1911 if (! keyproc) {
1912 keyproc = I;
1913 }
1914 keyshift |= pc_xkey_map [ch].fkeyshift;
1915 # ifdef debug_whatever
1916 /* VAXC needs the identity cast (voidfunc) */
1917 if ((voidfunc) keyproc == (voidfunc) I) {
1918 return ch;
1919 }
1920 # endif
1921 return FUNcmd;
1922 } else if (ch == ' ' && (keyshift & ctrl_mask)) {
1923 return 0; /* ctrl-Space -> NUL */
1924 } else {
1925 q_put (ch);
1926 }
1927
1928 #else /* #ifdef msdos */
1929
1930 trace_keytrack ("_readchar<033", ch);
1931 if (ch == '\033') {
1932 char second_esc_char = '\0';
1933 int esc_wait = 2 * escape_delay;
1934
1935 q_put (ch);
1936
1937 if (! bytereadyafter (esc_wait, NIL_PTR)) {
1938 return q_get ();
1939 }
1940
1941 while ((res = findkey (ctrl_queue)) == -1 /* prefix of table entry */
1942 && q_notfull ()
1943 #ifdef simple_escape_delay_handling
1944 && bytereadyafter (escape_delay, NIL_PTR)
1945 #endif
1946 )
1947 {
1948 char prev_ch = ch;
1949
1950 if (prev_ch != '\033' && ! input_active && ! bytereadyafter (escape_delay, NIL_PTR)) {
1951 status_uni ("...awaiting slow key code sequence...");
1952 }
1953
1954 ch = get1byte ();
1955 #ifdef debug_kbesc
1956 printf ("<^[%s> + [%dms] %02lX\n", ctrl_queue + 1, escape_delay, ch);
1957 #endif
1958
1959 /* accept ESC prefix as Alt modifier */
1960 if (detect_esc_alt && ch == '\033' && prev_ch == '\033') {
1961 if (bytereadyafter (escape_delay, NIL_PTR)) {
1962 ch = get1byte ();
1963 keyshift |= alt_mask;
1964 #ifdef debug_kbesc
1965 printf ("-> <^[%s> + ^[/%02lX\n", ctrl_queue + 1, ch);
1966 #endif
1967 }
1968 }
1969
1970 /* accept XTerm*modifyCursorKeys: 3 as well as
1971 device attributes reports (primary/secondary DA) */
1972 if (second_esc_char == '[' && prev_ch == '[' &&
1973 (ch == '>' || ch == '?')
1974 ) {
1975 if (ch == '?') {
1976 keyshift |= report_mask;
1977 }
1978 ch = get1byte ();
1979 #ifdef debug_kbesc
1980 printf ("-> <^[%s> + >?/%02lX\n", ctrl_queue + 1, ch);
1981 #endif
1982 }
1983
1984 check_ctrl_byte:
1985 /* handle generic shift state of ANSI sequences: */
1986 /* syntax of modifier indication varies with
1987 terminal type and mode; indications are as follows:
1988 ANSI 1 ANSI 2 keyshift
1989 plain - 9? 0x00
1990 Shift 2 10 0x01
1991 Alt 3 11 0x02
1992 Alt-Shift 4 12 0x03
1993 Control 5 13 0x04
1994 Control-Shift 6 14 0x05
1995 Alt-Control 7 15 0x06
1996 Alt-Control-Shift 8 16 0x07
1997 applkeypad_mask 0x08
1998 */
1999 if (ch == ';' && second_esc_char == '[') {
2000 ch = get1byte ();
2001 if (ch >= '2' && ch <= '9') {
2002 /* ESC [1;2A → ESC [1A + shift etc */
2003 /* special: map '9' to applkeypad_mask */
2004 keyshift |= (ch & ~'0') - 1;
2005 } else if (ch == '1') {
2006 ch = get1byte ();
2007 if (ch >= '0' && ch <= '6') {
2008 /* xterm with alwaysUseMods: */
2009 /* ESC [1;11A → ESC [1A + alt etc */
2010 keyshift |= applkeypad_mask | ((ch & ~'0') + 1);
2011 } else {
2012 q_put (';');
2013 q_put ('1');
2014 q_put (ch);
2015 }
2016 } else {
2017 q_put (';');
2018 q_put (ch);
2019 }
2020 ch = get1byte ();
2021 #ifdef debug_kbesc
2022 printf ("-> <^[%s> + 1-8/%02lX\n", ctrl_queue + 1, ch);
2023 #endif
2024 } else if (ch == ';' && second_esc_char == '1') {
2025 ch = get1byte ();
2026 if (ch >= '2' && ch <= '8') {
2027 /* xterm/VT52 mode: ESC 1;2A → ESC 1A + shift etc */
2028 keyshift |= (ch & ~'0') - 1;
2029 } else {
2030 q_put (';');
2031 q_put (ch);
2032 }
2033 ch = get1byte ();
2034 #ifdef debug_kbesc
2035 printf ("-> <^[%s> + ;/%02lX\n", ctrl_queue + 1, ch);
2036 #endif
2037 } else if (ch >= '0' && ch <= '9'
2038 && (second_esc_char == 'O' ||
2039 (hp_shift_mode && ! second_esc_char))) {
2040 if (ch >= '2' && ch <= '9') {
2041 /* ESC O2A → ESC OA + shift etc */
2042 /* HP: ESC 2p → ESC p + shift etc */
2043 /* special: map '9' to applkeypad_mask */
2044 keyshift |= (ch & ~'0') - 1;
2045 } else if (ch == '1' || (ch == '0' && mlterm_version)) {
2046 ch = get1byte ();
2047 if (ch >= '0' && ch <= '6') {
2048 /* ESC O11P → ESC OP + alt etc */
2049 /* HP: ESC 11p → ESC p + alt etc */
2050 keyshift |= applkeypad_mask | ((ch & ~'0') + 1);
2051 } else if (ch == ';') {
2052 /* mlterm: ESC O1;2A → ESC OA + shift etc */
2053 /* mlterm: ESC O0;3w → ESC O0w + alt etc */
2054 ch = get1byte ();
2055 keyshift |= ((ch & ~'0') - 1);
2056 } else {
2057 q_put ('1');
2058 q_put (ch);
2059 }
2060 } else {
2061 q_put (ch);
2062 }
2063 ch = get1byte ();
2064 #ifdef debug_kbesc
2065 printf ("-> <^[%s> + 0-9/%02lX\n", ctrl_queue + 1, ch);
2066 #endif
2067 } else if (sco_shift_mode && second_esc_char == '['
2068 && ch >= '0' && ch <= '9') {
2069 char newkeyshift;
2070 char newch = '\0';
2071 if (ch >= '2' && ch <= '9') {
2072 /* SCO: ESC [2M → ESC [M + shift etc */
2073 /* special: map '9' to applkeypad_mask */
2074 newkeyshift = (ch & ~'0') - 1;
2075 newch = get1byte ();
2076 #ifdef debug_kbesc
2077 printf ("-> <^[%s> + 2-8/%02X\n", ctrl_queue + 1, newch);
2078 #endif
2079 if (newch >= 'A' && newch <= 'Z') {
2080 keyshift |= newkeyshift;
2081 } else {
2082 q_put (ch);
2083 }
2084 } else if (ch == '1') {
2085 ch = get1byte ();
2086 #ifdef debug_kbesc
2087 printf ("-> <^[%s> + 1/%02lX\n", ctrl_queue + 1, ch);
2088 #endif
2089 if (ch >= '0' && ch <= '6') {
2090 /* SCO: ESC [11M → ESC [M + alt etc */
2091 newkeyshift = applkeypad_mask | ((ch & ~'0') + 1);
2092 newch = get1byte ();
2093 if (newch >= 'A' && newch <= 'Z') {
2094 keyshift |= newkeyshift;
2095 } else {
2096 q_put ('1');
2097 q_put (ch);
2098 }
2099 } else if (ch == ';') {
2100 /* xterm SCO: ESC [1;5R → ESC [R + alt etc */
2101 ch = get1byte ();
2102 keyshift |= (ch & ~'0') - 1;
2103 newch = get1byte ();
2104 } else {
2105 q_put ('1');
2106 q_put (ch);
2107 newch = get1byte ();
2108 }
2109 } else {
2110 #ifdef debug_kbesc
2111 printf ("-> <^[%s>\n", ctrl_queue + 1);
2112 #endif
2113 q_put (ch);
2114 newch = get1byte ();
2115 }
2116 ch = newch;
2117 if (ch == ';') {
2118 /* OK, so here is my second goto;
2119 this is really a very peculiar case,
2120 based on misconfiguration
2121 (mined assumes sco, terminal sends
2122 modified xterm sequences),
2123 which does not deserve any
2124 goto avoidance effort
2125 */
2126 #ifdef debug_kbesc
2127 printf ("goto check_ctrl_byte\n");
2128 #endif
2129 goto check_ctrl_byte;
2130 }
2131 } else if (prev_ch >= '0' && prev_ch <= '9') {
2132 if (ch == '^') {
2133 /* ESC [5^ → ESC [5~ + control (rxvt) */
2134 keyshift |= ctrl_mask;
2135 ch = '~';
2136 } else if (ch == '$') {
2137 /* ESC [5$ → ESC [5~ + shift (rxvt) */
2138 keyshift |= shift_mask;
2139 ch = '~';
2140 } else if (ch == '@') {
2141 /* ESC [5@ → ESC [5~ + control+shift (rxvt) */
2142 keyshift |= ctrlshift_mask;
2143 ch = '~';
2144 }
2145 } else if (ch >= 'a' && ch <= 'd') {
2146 if (prev_ch == 'O') {
2147 /* ESC Oa → ESC OA + control (rxvt) */
2148 keyshift |= ctrl_mask;
2149 ch -= 'a' - 'A';
2150 } else if (prev_ch == '[') {
2151 /* ESC [a → ESC [A + shift (rxvt) */
2152 keyshift |= shift_mask;
2153 ch -= 'a' - 'A';
2154 }
2155 }
2156
2157 q_put (ch);
2158 if (second_esc_char == '\0') {
2159 second_esc_char = ch;
2160 if (second_esc_char == 'O') {
2161 /* appl. cursor keys, appl. keypad */
2162 keyshift |= applkeypad_mask;
2163 }
2164 }
2165 }
2166 #ifdef debug_kbesc
2167 printf ("=> [%d] <^[%s> [keyshift %X]\n", res, ctrl_queue + 1, keyshift);
2168 #endif
2169 #ifdef debug_kbansi
2170 printf ("[%d] [keyshift %X]\n", res, keyshift);
2171 #endif
2172
2173 if (quit) {
2174 keyproc = I;
2175 return FUNcmd;
2176 } else if (res < 0) { /* key pattern not found in fkeymap table */
2177 if (second_esc_char == '[') {
2178 /* generic scanning for unknown ANSI sequence */
2179 #ifdef debug_kbansi
2180 character q1, q2;
2181 q1 = q_get (); /* swallow ESC */
2182 q2 = q_get (); /* swallow [ */
2183 printf ("swallowing %X %X\n", q1, q2);
2184 #else
2185 (void) q_get (); /* swallow ESC */
2186 (void) q_get (); /* swallow [ */
2187 #endif
2188 /* (Was putback_rest (ctrl_queue + 2);) */
2189 /* Use raw_queue to ignore previous modifier
2190 transformations like ESC [1;11A → ESC [1A + alt */
2191 if ((keyshift & alt_mask) && raw_queue [1] == '[') {
2192 /* consider double-ESC alt (rxvt) */
2193 putback_rest (raw_queue + 2);
2194 } else {
2195 putback_rest (raw_queue + 1);
2196 }
2197
2198 ansi_params = 0;
2199 ansi_ini = '\0';
2200 do {
2201 int i = -1;
2202 ansi_fini = get_digits (& i);
2203 if (ansi_params == 0 && i == -1 &&
2204 (ansi_fini == '>' || ansi_fini == '?' || ansi_fini == '<')
2205 ) {
2206 ansi_ini = ansi_fini;
2207 ansi_fini = ';';
2208 } else if (ansi_params < max_ansi_params) {
2209 ansi_param [ansi_params] = i;
2210 ansi_params ++;
2211 }
2212 } while (ansi_fini == ';');
2213 q_clear ();
2214 #ifdef debug_kbansi
2215 printf ("ansi %c (%d)", ansi_fini, ansi_params);
2216 {int i;
2217 for (i = 0; i < ansi_params; i ++) {
2218 printf (" %d", ansi_param [i]);
2219 }
2220 }
2221 printf ("\n");
2222 #endif
2223
2224 if ((ansi_fini == '~'
2225 && ansi_param [0] == 27
2226 && ansi_params >= 3
2227 )
2228 || (ansi_fini == 'u'
2229 && (ansi_params == 2
2230 || (ansi_params == 1 && keyshift > 0)
2231 )
2232 )
2233 ) {
2234 /* map xterm 235 mode formatOtherKeys: 1
2235 ^[[77;2u
2236 to xterm mode formatOtherKeys: 0
2237 ^[[27;2;77~
2238 */
2239 if (ansi_fini == 'u') {
2240 ansi_param [2] = ansi_param [0];
2241 }
2242
2243 if (ansi_params > 1) {
2244 /* handle generic escape sequence
2245 for modified key
2246 (xterm 214 resource modifyOtherKeys)
2247 */
2248 if (ansi_param [1] > 8) {
2249 ansi_param [1] -= 8;
2250 }
2251 keyshift |= ansi_param [1] - 1;
2252 }
2253
2254 /* enforce UTF-8 interpretation of input */
2255 queue_mode_mapped = True;
2256
2257 if (ansi_param [2] == ' ' && (keyshift & ctrlshift_mask) == ctrl_mask) {
2258 /* map ctrl-space to MARK,
2259 alt-ctrl-space to Hop MARK */
2260 q_put ('\0');
2261 } else if (ansi_param [2] == 0) {
2262 q_put ('\0');
2263 } else {
2264 char cbuf [7];
2265 char * cp = cbuf;
2266
2267 /* Shift-a/A -> A */
2268 if ((keyshift & altctrlshift_mask) == shift_mask
2269 && isLetter (ansi_param [2])
2270 ) {
2271 keyshift = 0;
2272 ansi_param [2] = case_convert (ansi_param [2], 1);
2273 }
2274
2275 /* Control-/ etc as accent prefix */
2276 if (keyshift & ctrl_mask) {
2277 struct prefixspec * ps;
2278 ps = lookup_prefix (COMPOSE, ansi_param [2]);
2279 if (ps && * ps->accentname) {
2280 keyshift = ansi_param [2];
2281 keyproc = COMPOSE;
2282 return FUNcmd;
2283 } else if (ps) {
2284 unsigned long unichar;
2285 int len;
2286 utf8_info (ps->pat1, & len, & unichar);
2287 ansi_param [2] = unichar;
2288 } else if ('?' <= ansi_param [2] && ansi_param [2] < '') {
2289 keyshift &= ~ ctrl_mask;
2290 return ansi_param [2] & 0x1F;
2291 }
2292 }
2293
2294 (void) utfencode (ansi_param [2], cbuf);
2295 while (* cp) {
2296 q_put (* cp ++);
2297 }
2298 }
2299
2300 /* Control/Alt/Control-Alt-0 -> ...key_0 */
2301 if (ansi_param [2] >= '0' && ansi_param [2] <= '9') {
2302 switch (ansi_param [2]) {
2303 case '0': keyproc = key_0; break;
2304 case '1': keyproc = key_1; break;
2305 case '2': keyproc = key_2; break;
2306 case '3': keyproc = key_3; break;
2307 case '4': keyproc = key_4; break;
2308 case '5': keyproc = key_5; break;
2309 case '6': keyproc = key_6; break;
2310 case '7': keyproc = key_7; break;
2311 case '8': keyproc = key_8; break;
2312 case '9': keyproc = key_9; break;
2313 }
2314 q_clear ();
2315 return FUNcmd;
2316 }
2317
2318 if (keyshift & alt_mask) {
2319 /* 2000.13 workaround for prompt */
2320 if ((keyshift & altctrl_mask) == alt_mask) {
2321 if (ansi_param [2] == 'k') {
2322 q_clear ();
2323 keyproc = toggleKEYMAP;
2324 return FUNcmd;
2325 }
2326 if (ansi_param [2] == 'K'
2327 || ansi_param [2] == 'I') {
2328 q_clear ();
2329 keyproc = setupKEYMAP;
2330 return FUNcmd;
2331 }
2332 }
2333
2334 return '\033';
2335 } else if (keyshift) {
2336 return q_get ();
2337 } else {
2338 /* fall through to keyboard mapping */
2339 }
2340 } else { /* not CSI 27 sequence */
2341 if (ansi_fini == '&') { /* DEC locator report */
2342 (void) read1byte (); /* swallow 'w' */
2343 if (ansi_params < 4) {
2344 ansi_param [3] = 1;
2345 if (ansi_params < 3) {
2346 ansi_param [2] = 1;
2347 }
2348 }
2349 DIRECTvtlocatorgetxy ();
2350 keyproc = MOUSEfunction;
2351 } else if (ansi_ini == '<') {
2352 DIRECTsgrgetxy ();
2353 keyproc = MOUSEfunction;
2354 } else if (! ansi_ini && ansi_fini == 'M') {
2355 DIRECTurxvtgetxy ();
2356 keyproc = MOUSEfunction;
2357 } else {
2358 keyproc = ANSIseq;
2359 }
2360 return FUNcmd;
2361 }
2362 } else if (keyshift & alt_mask) {
2363 /* restore the previously filtered ESCAPE */
2364 return '\033';
2365 } else {
2366 /* just deliver the typed characters */
2367 return q_get ();
2368 }
2369 } else { /* key pattern found in fkeymap table */
2370 q_clear ();
2371
2372 keyshift |= fkeyshift;
2373
2374 if (keyproc == ESCAPE) {
2375 /* mintty application escape key mode */
2376 return '\033';
2377 } else if (keyproc == DIRECTxterm) {
2378 #ifdef debug_mouse
2379 printf ("scanned xterm mouse escape\n");
2380 #endif
2381 DIRECTxtermgetxy ('M');
2382 keyproc = MOUSEfunction;
2383 } else if (keyproc == TRACKxterm) {
2384 #ifdef debug_mouse
2385 printf ("scanned xterm mouse tracking escape\n");
2386 #endif
2387 DIRECTxtermgetxy ('t');
2388 keyproc = MOUSEfunction;
2389 } else if (keyproc == TRACKxtermT) {
2390 #ifdef debug_mouse
2391 printf ("scanned xterm mouse tracking escape\n");
2392 #endif
2393 DIRECTxtermgetxy ('T');
2394 keyproc = MOUSEfunction;
2395 } else if (keyproc == DIRECTcrttool) {
2396 DIRECTcrttoolgetxy ();
2397 keyproc = MOUSEfunction;
2398 }
2399
2400 return FUNcmd;
2401 }
2402 } else {
2403 q_put (ch);
2404 }
2405
2406 #endif /* #else msdos */
2407
2408 if (allow_keymap && dont_suppress_keymap && keyboard_mapping_active ()) {
2409 disable_modify_keys (True);
2410 while ((res = map_key (ctrl_queue, 1, & found, & mapped)) == -1
2411 /* prefix of some table entry */
2412 && q_notfull ()
2413 && bytereadyafter (keymap_delay, NIL_PTR)
2414 )
2415 {
2416 #ifdef fix_modified_input
2417 /* avoid xterm modifyOtherKeys mode to interfere with
2418 input method handling: will have to use separate queue
2419 */
2420 q_put (_readchar_nokeymap ());
2421 plainly like this, we get an endless loop...
2422 now using disable_modify_keys workaround
2423 #else
2424 q_put (read1byte ());
2425 #endif
2426 /* exact match found? note for later consideration */
2427 if (found != NIL_PTR) {
2428 prev_found = found;
2429 }
2430 }
2431 disable_modify_keys (False);
2432 /* possible results:
2433 res >= 0: match found, no further prefix match
2434 res == -1, prev_found != NIL_PTR: prefix with previous match
2435 res == -1: prefix only, no further key typed
2436 res == -2: no match with previous match
2437 */
2438
2439 #ifdef debug_kbmap
2440 printf ("mapping %s, res %d, found %s -> ", ctrl_queue, res, found);
2441 #endif
2442 if (res < 0 && prev_found != NIL_PTR) {
2443 res = 1;
2444 if (found == NIL_PTR) {
2445 #ifdef debug_kbmap
2446 printf ("rest %s, ", ctrl_queue + strlen (prev_found));
2447 #endif
2448 putback_rest (ctrl_queue + strlen (prev_found));
2449 }
2450 } else if (res == -1) {
2451 res = map_key (ctrl_queue, 2, & found, & mapped);
2452 #ifdef debug_kbmap
2453 printf ("find again %s, found %s, ", ctrl_queue, found);
2454 #endif
2455 }
2456
2457 #ifdef debug_kbmap
2458 printf ("res %d\n", res);
2459 #endif
2460
2461 if (res >= 0) { /* key pattern detected in key mapping table */
2462
2463 handle_mapped:
2464 q_clear ();
2465
2466 /* check if mapping defines multiple choices */
2467 while (* mapped == ' ') {
2468 mapped ++;
2469 }
2470 choice = strchr (mapped, ' ');
2471 while (choice != NIL_PTR && * choice == ' ') {
2472 choice ++;
2473 }
2474 if (choice != NIL_PTR && * choice != '\0') {
2475 choice_index = choose_char (mapped);
2476 #ifdef debug_kbmap
2477 printf (" choose_char (%s) -> %d\n", mapped, choice_index);
2478 #endif
2479 if (choice_index < 0) {
2480 mapped = NIL_PTR;
2481 /* mapping cancelled */
2482 } else {
2483 while (choice_index > 0
2484 && mapped != NIL_PTR
2485 && * mapped != '\0')
2486 {
2487 mapped = strchr (mapped, ' ');
2488 if (mapped != NIL_PTR) {
2489 while (* mapped == ' ') {
2490 mapped ++;
2491 }
2492 }
2493 choice_index --;
2494 }
2495 }
2496 }
2497
2498 if (mapped != NIL_PTR) {
2499 queue_mode_mapped = True;
2500 while (* mapped != '\0' && * mapped != ' ') {
2501 q_put (* mapped);
2502 mapped ++;
2503 }
2504 }
2505 #ifdef debug_kbmap
2506 printf (" queued %s\n", ctrl_queue);
2507 #endif
2508 }
2509
2510 if (q_len () > 0) {
2511 return q_get () /* deliver the first mapped byte */;
2512 } else {
2513 ring_bell ();
2514 flush (); /* clear key mapping menu */
2515 #define return_after_esc
2516 #ifdef return_after_esc
2517 return CHAR_UNKNOWN; /* actually "CHAR_NONE" */
2518 #else
2519 if (is_menu_open () /* doesn't seem to work */) {
2520 return CHAR_UNKNOWN; /* actually "CHAR_NONE" */
2521 } else {
2522 /* read another character */
2523 /* prompt should have been redrawn;
2524 menu (file chooser) would stay blank...
2525 */
2526 return _readchar ();
2527 }
2528 #endif
2529 }
2530 } else { /* not keyboard mapped */
2531 return q_get ();
2532 }
2533
2534 }
2535
2536
2537 #define dont_debug_choose_char
2538
2539 static
2540 int
choose_char(choices)2541 choose_char (choices)
2542 char * choices;
2543 {
2544 int choice_count = 0;
2545 char * choicepoi = choices;
2546 int choice_col = x;
2547 int choice_line = y + 1;
2548
2549 char * thischoiceline;
2550 char * choicelines;
2551 menuitemtype * choicemenu;
2552
2553 int li, ci, lastcol, lastrow;
2554 char * choicelinepoi;
2555
2556 int selected;
2557
2558 #ifdef cut_picklist_to_screen
2559 FLAG reduced_menu = False;
2560 #endif
2561
2562 /* count choices */
2563 do {
2564 choice_count ++;
2565 choicepoi = strchr (choicepoi, ' ');
2566 while (choicepoi != NIL_PTR && * choicepoi == ' ') {
2567 choicepoi ++;
2568 }
2569 } while (choicepoi != NIL_PTR && * choicepoi != '\0');
2570 #ifdef debug_choose_char
2571 printf ("choices <%s>\n", choices);
2572 printf ("choice_count %d\n", choice_count);
2573 #endif
2574
2575 lastrow = (choice_count - 1) / 10;
2576 choicelines = alloc (strlen (choices) + 1 + choice_count * 2);
2577 choicemenu = alloc ((lastrow + 1) * sizeof (menuitemtype));
2578 if (choicelines == NIL_PTR || choicemenu == (menuitemtype *) NIL_PTR) {
2579 if (choicelines != NIL_PTR) {
2580 free_space (choicelines);
2581 }
2582 ring_bell ();
2583 flush ();
2584 return -1;
2585 }
2586
2587 /* adjust menu position if too far down */
2588 if (choice_line + lastrow + 3 > YMAX) {
2589 choice_line = y - lastrow - 3;
2590 if (choice_line < 0) {
2591 choice_line = 0;
2592 }
2593 }
2594
2595 /* adjust menu position if on status line */
2596 if (input_active) {
2597 choice_line = YMAX - lastrow - 3;
2598 if (choice_line < 0) {
2599 choice_line = 0;
2600 }
2601 choice_col = lpos;
2602 }
2603
2604 /* construct menu items */
2605 choicepoi = choices;
2606 while (* choicepoi == ' ') {
2607 choicepoi ++;
2608 }
2609 thischoiceline = choicelines;
2610 for (li = 0; li <= lastrow; li ++) {
2611 /* construct menu line */
2612 choicelinepoi = thischoiceline;
2613 if (li == lastrow) {
2614 lastcol = (choice_count - 1) % 10;
2615 if (lastcol < 0) {
2616 /* should not occur as choice_count > 0 */
2617 lastcol = 0;
2618 }
2619 } else {
2620 lastcol = 9;
2621 }
2622 for (ci = 0; ci <= lastcol; ci ++) {
2623 * choicelinepoi ++ = (ci + 1) % 10 + '0';
2624 * choicelinepoi ++ = ':';
2625 while (* choicepoi != ' ' && * choicepoi != '\0') {
2626 * choicelinepoi ++ = * choicepoi ++;
2627 }
2628 while (* choicepoi == ' ') {
2629 choicepoi ++;
2630 }
2631 if (ci < lastcol) {
2632 * choicelinepoi ++ = ' ';
2633 }
2634 }
2635 * choicelinepoi ++ = '\0';
2636 /* add menu line to menu */
2637 #ifdef debug_choose_char
2638 printf ("choiceline <%s>\n", thischoiceline);
2639 #endif
2640 /* fill menu item with collected data */
2641 fill_menuitem (& choicemenu [li], thischoiceline, NIL_PTR);
2642
2643 thischoiceline = choicelinepoi;
2644 }
2645 #ifdef debug_choose_char
2646 printf ("choicelines alloc %d length %d\n",
2647 strlen (choices) + 1 + choice_count * 2 + lastrow + 1,
2648 thischoiceline - choicelines);
2649 #endif
2650
2651 #ifdef cut_picklist_to_screen
2652 if (lastrow >= YMAX - 2) {
2653 lastrow = YMAX - 3;
2654 reduced_menu = True;
2655 if (! input_active) {
2656 status_msg ("Warning: full menu too large to display");
2657 }
2658 }
2659 #endif
2660 selected = popup_menu (choicemenu, lastrow + 1,
2661 choice_col, choice_line,
2662 "Choose character", False, False, "1234567890");
2663 if (input_active) {
2664 /* redraw_prompt () now checked and called in input () */
2665 #ifdef cut_picklist_to_screen
2666 } else if (reduced_menu) {
2667 clear_status ();
2668 #endif
2669 }
2670
2671 #ifdef debug_choose_char
2672 printf ("selected %d\n", selected);
2673 #endif
2674
2675 free_space (choicemenu);
2676 free_space (choicelines);
2677
2678 if (selected < choice_count) {
2679 return selected;
2680 } else {
2681 return -1;
2682 }
2683 }
2684
2685
2686 /*======================================================================*\
2687 |* End *|
2688 \*======================================================================*/
2689