1 /*======================================================================*\
2 |*		Editor mined						*|
3 |*		operating system dependent I/O				*|
4 \*======================================================================*/
5 
6 #ifdef _AIX
7 #define _ALL_SOURCE	/* get struct winsize defined */
8 #endif
9 
10 
11 #include "mined.h"
12 #include "io.h"
13 #include "termprop.h"
14 
15 
16 #ifdef vms
17 
18 #define __BSD44_CURSES
19 
20 #undef CURSES
21 #define ANSI
22 
23 #include "vmsio.c"
24 
25 #endif
26 
27 
28 #ifdef ANSI
29 #undef conio
30 #endif
31 
32 #ifdef msdos
33 
34 #ifndef __TURBOC__
35 #undef unix
36 /* don't #define ANSI */
37 #endif
38 
39 #ifndef conio
40 #define ANSI
41 #endif
42 
43 #endif
44 
45 
46 #include <errno.h>
47 #include <signal.h>
48 #ifndef __TURBOC__
49 extern int kill _((pid_t, int));
50 #endif
51 
52 /* include configuration for SIGWINCH information retrieval */
53 #ifdef SGTTY
54 #undef TERMIO
55 #define include_SGTTY
56 #endif
57 #ifdef TERMIO
58 #define include_TERMIO
59 #endif
60 
61 
62 /* terminal handling selection */
63 #ifdef CURSES
64 #define _SGTTYB_	/* avoid duplicate definitions on SunOS */
65 #include <curses.h>
66 # undef FALSE
67 # undef TRUE
68 
69 # ifdef SETLOCALE
70 # include <locale.h>
71 # endif
72 
73 /* ensure window size detection capability */
74 # ifndef SGTTY
75 # define include_TERMIO
76 # endif
77 
78 # ifdef vms
79 # undef include_TERMIO
80 # endif
81 
82 # undef TERMIO	/* \ must be  */
83 # undef SGTTY	/* / disabled */
84 #endif
85 
86 
87 #ifdef include_TERMIO
88 # ifdef questionable_but_recommended_by_some_SuSe_Guru_doesnt_work_on_HP
89 #  if defined (__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1))
90 #	include <termios.h>		/* define POSIX.1 termios */
91 #	include <sys/ioctl.h>		/* declare ioctl() for winsize */
92 #	undef   TCGETS		/* Use POSIX.1 instead */
93 #  else
94 /* Compatible <termio.h> for old 'struct termio' ioctl interface. */
95 #	include <termio.h>
96 #  endif
97 # else
98 #	include <termios.h>		/* define POSIX.1 termios */
99 #	include <sys/ioctl.h>		/* declare ioctl() for winsize */
100 # endif
101 #endif
102 
103 #ifdef include_SGTTY
104 #define BSD_COMP /* let SunOS #include <sys/ttold.h> in <sys/ioctl.h> */
105 #include <sys/ioctl.h>
106 #include <sgtty.h> /* after <sys/ttold.h> */
107 /*extern int ioctl ();*/
108 #endif
109 
110 
111 #ifdef __CYGWIN__
112 #include <sys/ioctl.h>
113 #endif
114 
115 #ifdef SIGPHONE		/* this trick was taken from less' screen.c */
116 #include <sys/window.h>	/* for window size detection */
117 #endif
118 
119 #ifdef msdos
120 #define _getch_
121 #define getch dosgetch
122 #endif
123 
124 #ifdef msdos
125 /* make REGS "x." branch work with djgpp */
126 #define _NAIVE_DOS_REGS
127 #include <dos.h>
128 #ifndef __TURBOC__
129 #include <dpmi.h>
130 #include <go32.h> /* define transfer buffer __tb and function dosmemget */
131 #endif
132 #endif
133 
134 
135 #ifdef unix
136 # undef _POSIX_SOURCE
137 # undef _XOPEN_SOURCE
138 #ifndef __MINGW32__
139 /* use select () for peek/read? */
140 #define selectpeek
141 #define selectread
142 #endif
143 #endif
144 
145 #ifdef __CYGWIN__
146 #include <cygwin/version.h>	/* check CYGWIN_VERSION_DLL_* */
147 #if CYGWIN_VERSION_DLL_MAJOR == 1007 && CYGWIN_VERSION_DLL_MINOR <= 17
148 /* should in theory be checked dynamically, by calling uname(2) within #ifdef __CYGWIN__ ... */
149 /* support immediate response to WINCH */
150 #undef selectread
151 #endif
152 #endif
153 
154 #define dont_debug_timeout_read
155 #ifdef debug_timeout_read
156 #undef selectread
157 #endif
158 
159 #ifdef __EMX__
160 #undef selectpeek
161 #undef selectread
162 # ifdef CURSES
163 # define _getch_
164 # endif
165 #endif
166 
167 #ifdef vms
168 # include <socket.h>	/* for select () and struct timeval */
169 # ifdef CURSES
170 # define _getch_
171 # endif
172 #endif
173 
174 #ifdef CURSES_INPUT	/* currently not defined */
175 #define _getch_	/* not necessarily needed for Unix, but might be better
176 		   with new curs_readchar loop in inputreadyafter () */
177 #endif
178 
179 #ifdef _getch_
180 #ifndef CURSES
181 extern int getch ();
182 #endif
183 #endif
184 
185 
186 #ifndef __TURBOC__
187 #include <sys/time.h>	/* for struct timeval (for select in inputreadyafter) */
188 #endif
189 
190 
191 /*======================================================================*\
192 |*			Mode indication					*|
193 \*======================================================================*/
194 
195 /* terminal capabilites and feature usage */
196 FLAG can_scroll_reverse = True;
197 FLAG can_add_line = True;
198 FLAG can_delete_line = True;
199 FLAG can_clear_eol = True;
200 FLAG can_clear_eos = True;
201 FLAG can_erase_chars = True;
202 FLAG can_reverse_mode = True;
203 FLAG can_hide_cursor = False;
204 FLAG can_dim = False;
205 FLAG can_alt_cset = True;
206 FLAG use_mouse_button_event_tracking = True;
207 FLAG colours_256 = False;
208 FLAG colours_88 = False;
209 FLAG ansi_esc = True;
210 FLAG standout_glitch = False;
211 FLAG use_appl_cursor = True;
212 FLAG use_appl_keypad = False;
213 
214 /* menu border style */
215 FLAG use_ascii_graphics = False;	/* use ASCII graphics for borders */
216 FLAG use_vga_block_graphics = False;	/* charset is VGA with block graphics */
217 FLAG use_pc_block_graphics = False;	/* alternate charset is VGA with block graphics */
218 FLAG use_vt100_block_graphics = False;
219 FLAG full_menu_bg = False;		/* full coloured background */
220 char menu_border_style = 's';
221 int menumargin = 0;
222 FLAG explicit_border_style = False;
223 FLAG explicit_scrollbar_style = False;
224 FLAG explicit_keymap = False;
225 FLAG use_stylish_menu_selection = True;
226 FLAG bold_border = True;
227 #define use_normalchars_boxdrawing ((utf8_screen || use_ascii_graphics) && ! use_vt100_block_graphics && ! use_vga_block_graphics)
228 
229 int
use_unicode_menubar()230 use_unicode_menubar ()
231 {
232   if (use_stylish_menu_selection
233       && use_normalchars_boxdrawing
234       && ! use_ascii_graphics
235       && menu_border_style != 'P'
236       && menu_border_style != '@') {
237 	return 1 + (menu_border_style == 'd');
238   } else {
239 	return 0;
240   }
241 }
242 
243 /* feature usage options */
244 FLAG use_script_colour = True;
245 FLAG use_mouse = True;
246 FLAG use_mouse_release = True;
247 FLAG use_mouse_anymove_inmenu = True;
248 FLAG use_mouse_anymove_always = False;
249 FLAG use_mouse_extended = False;	/* UTF-8 encoding of mouse coordinates */
250 FLAG use_mouse_1015 = False;		/* numeric encoding of mouse coordinates */
251 FLAG use_bold = True;
252 FLAG use_bgcolor = True;
253 FLAG avoid_reverse_colour = False;
254 FLAG use_modifyOtherKeys = False;
255 int cursor_style = 0;
256 
257 /* state */
258 static FLAG in_menu_mouse_mode = False; /* used in dosmouse.c */
259 FLAG in_menu_border = False;
260 /*int current_cursor_y = 0;*/
261 static FLAG is_mouse_button_event_mode_enabled = False;
262 
263 /* screen attributes: ANSI sequences */
264 char * markansi = 0;		/* line indicator marking (dim/red) */
265 char * emphansi = 0;		/* status line emphasis mode (red bg) */
266 char * borderansi = 0;		/* menu border colour (red) */
267 char * selansi = 0;		/* menu selection */
268 char * selfgansi = 0;		/* menu selection background */
269 char * ctrlansi = 0;		/* Control character display */
270 char * uniansi = 0;		/* Unicode character display */
271 char * specialansi = 0;		/* Unicode (lineend) marker display */
272 char * combiningansi = 0;	/* combining character display */
273 char * menuansi = 0;		/* menu line */
274 char * HTMLansi = 0;		/* HTML display */
275 char * XMLattribansi = 0;	/* HTML/XML attribute display */
276 char * XMLvalueansi = 0;	/* HTML/XML value display */
277 char * diagansi = 0;		/* dialog (bottom status) line */
278 char * scrollfgansi = 0;	/* scrollbar foreground */
279 char * scrollbgansi = 0;	/* scrollbar background */
280 
281 #define nonempty(ansi)	(ansi && * ansi)
282 
283 static int colour_token = -1;
284 
285 void
set_colour_token(token)286 set_colour_token (token)
287   int token;
288 {
289 	colour_token = token;
290 }
291 
292 
293 /*======================================================================*\
294 |*			I/O channels					*|
295 \*======================================================================*/
296 
297 /* tty file handles */
298 int input_fd = STD_IN;
299 #ifdef __EMX__
300 int output_fd = STD_OUT;
301 #else
302 int output_fd = STD_ERR;
303 #endif
304 
305 #define tty_fd	output_fd
306 
307 
308 /*======================================================================*\
309 |*			Interrupt signal handling			*|
310 \*======================================================================*/
311 
312 #define dont_debug_winchg
313 
314 #ifdef debug_winchg
315 #define trace_winchg(params)	printf params
316 #else
317 #define trace_winchg(params)
318 #endif
319 
320 
321 /* interrupt control */
322 FLAG tty_closed = False;
323 FLAG hup = False;	/* set when SIGHUP is caught */
324 /* don't use 'static' for variables used in signal handler */
325 FLAG intr_char = False;	/* set when SIGINT is caught */
326 int sigcaught = 0;	/* set to signal caught */
327 FLAG continued = False;	/* set when SIGCONT is receive */
328 
329 
330 /**
331    Signal handler for system
332  */
333 static
334 void
catch_interrupt(signum)335 catch_interrupt (signum)
336   int signum;
337 {
338   sigcaught = signum;
339   /*catch_signals ();*/
340   signal (signum, catch_interrupt);
341 
342   /* To converge towards BSD signal() semantics:
343      don't handle_interrupt here; postpone (setting sigcaught flag)
344      and handle after select(), maybe after read(), elsewhere?
345    */
346   handle_interrupt (signum);
347 }
348 
349 static
350 void
catch_crash(signum)351 catch_crash (signum)
352   int signum;
353 {
354   sigcaught = signum;
355   /*catch_signals ();*/
356   signal (signum, catch_crash);
357 
358   /* To converge towards BSD signal() semantics:
359      don't handle_interrupt here; postpone (setting sigcaught flag)
360      and handle after select(), maybe after read(), elsewhere?
361    */
362   handle_interrupt (signum);
363 /*kill (getpid (), SIGABRT); trying to enforce core dump - not working */
364 }
365 
366 void
catch_signals()367 catch_signals ()
368 {
369 #if defined (SIGRTMIN) && defined (SIGRTMAX)
370   int i;
371   for (i = SIGRTMIN; i <= SIGRTMAX; i ++) {
372 	signal (i, catch_interrupt);
373   }
374 #endif
375 
376 #ifdef SIGABRT
377   signal (SIGABRT, catch_crash);
378 #endif
379 #ifdef SIGSEGV
380   signal (SIGSEGV, catch_crash);
381 #endif
382 #ifdef SIGBUS
383   signal (SIGBUS, catch_crash);
384 #endif
385 #ifdef SIGFPE
386   signal (SIGFPE, catch_crash);
387 #endif
388 #ifdef SIGILL
389   signal (SIGILL, catch_crash);
390 #endif
391 
392 #ifdef SIGHUP
393   signal (SIGHUP, catch_interrupt);
394 #endif
395 #ifdef SIGTRAP
396   signal (SIGTRAP, catch_interrupt);
397 #endif
398 #ifdef SIGEMT
399   signal (SIGEMT, catch_interrupt);
400 #endif
401 #ifdef SIGSYS
402   signal (SIGSYS, catch_interrupt);
403 #endif
404 #ifdef SIGPIPE
405   signal (SIGPIPE, catch_interrupt);
406 #endif
407 #ifdef SIGALRM
408   signal (SIGALRM, catch_interrupt);
409 #endif
410 #ifdef SIGTERM
411   signal (SIGTERM, catch_interrupt);
412 #endif
413 #ifdef SIGXCPU
414   signal (SIGXCPU, catch_interrupt);
415 #endif
416 #ifdef SIGXFSZ
417   signal (SIGXFSZ, catch_interrupt);
418 #endif
419 #ifdef SIGVTALRM
420   signal (SIGVTALRM, catch_interrupt);
421 #endif
422 #ifdef SIGPROF
423   signal (SIGPROF, catch_interrupt);
424 #endif
425 #ifdef SIGPWR
426   signal (SIGPWR, catch_interrupt);
427 #endif
428 
429 #ifdef SIGIO
430   /* or should this rather be ignored? */
431   signal (SIGIO, catch_interrupt);
432 #else
433 #ifdef SIGPOLL
434   signal (SIGPOLL, catch_interrupt);
435 #endif
436 #endif
437 #ifdef SIGLOST
438   /* linux man 7 signal says "SIGIO and SIGLOST have the same value."
439      but on cygwin, they have different values
440    */
441   signal (SIGLOST, catch_interrupt);
442 #endif
443 
444 #ifdef SIGUSR1
445   signal (SIGUSR1, catch_interrupt);
446 #endif
447 #ifdef SIGUSR2
448   signal (SIGUSR2, catch_interrupt);
449 #endif
450 #ifdef SIGUSR3
451   signal (SIGUSR3, catch_interrupt);
452 #endif
453 }
454 
455 #ifdef SIGWINCH
456 /*
457  * Catch the SIGWINCH signal sent to mined.
458  */
459 static
460 void
catchwinch(dummy)461 catchwinch (dummy)
462   int dummy;
463 {
464   winchg = True;
465   interrupted = True;
466   trace_winchg (("catching winchg\n"));
467 
468   /* workaround for interference of WINCH and FOCUSin handling */
469   window_focus = True;
470 
471 /* This is now performed in __readchar () to prevent display garbage
472    in case this interrupts occurs during display output operations which
473    get screen size related values changed while relying on them.
474   if (waitingforinput) {
475 	RDwinchg ();
476   }
477 */
478 
479   signal (SIGWINCH, catchwinch); /* reinstall the signal */
480   kill (getppid (), SIGWINCH);	/* propagate to parent (e.g. shell) */
481 }
482 #endif
483 
484 #ifdef SIGQUIT
485 /*
486  * Catch the SIGQUIT signal (^\) sent to mined. It turns on the quitflag.
487  */
488 static
489 void
catchquit(dummy)490 catchquit (dummy)
491   int dummy;
492 {
493 #ifdef UNUSED /* Should not be needed with new __readchar () */
494 /* Was previously needed on Sun but showed bad effects on Iris. */
495   static char quitchar = '\0';
496   if (waitingforinput) {
497 	/* simulate input to enable immediate break also during input */
498 	(void) ioctl (input_fd, TIOCSTI, & quitchar);
499   }
500 #endif
501   quit = True;
502   signal (SIGQUIT, catchquit); /* reinstall the signal */
503 }
504 #endif
505 
506 #ifdef SIGBREAK
507 /*
508  * Catch the SIGBREAK signal (control-Break) and turn on the quitflag.
509  */
510 static
511 void
catchbreak(dummy)512 catchbreak (dummy)
513   int dummy;
514 {
515   quit = True;
516   signal (SIGBREAK, catchbreak); /* do we need this ? */
517 }
518 #else
519 # ifdef msdos
520 static
521 int
controlbreak()522 controlbreak ()
523 {
524   quit = True;
525   return 1; /* continue program execution */
526 }
527 # endif
528 #endif
529 
530 #ifdef SIGINT
531 /*
532  * Catch the SIGINT signal (^C) sent if it cannot be ignored by tty driver
533  */
534 static
535 void
catchint(dummy)536 catchint (dummy)
537   int dummy;
538 {
539   intr_char = True;
540   signal (SIGINT, catchint); /* reinstall the signal */
541 }
542 #endif
543 
544 #ifdef SIGTSTP
545 /**
546    Catch external TSTP signal to try to reset terminal modes
547  */
548 static
549 void
catchtstp(dummy)550 catchtstp (dummy)
551   int dummy;
552 {
553   interrupted = True;
554   /* for now, do nothing, effectively ignoring the external signal */
555   signal (SIGTSTP, catchtstp); /* reinstall the signal */
556 }
557 #endif
558 
559 #ifdef SIGCONT
560 /**
561    Catch CONT signal to refresh screen
562  */
563 static
564 void
catchcont(dummy)565 catchcont (dummy)
566   int dummy;
567 {
568   /* trigger screen refresh */
569   winchg = True;
570   interrupted = True;
571   continued = True;
572   signal (SIGCONT, catchcont); /* reinstall the signal */
573 }
574 #endif
575 
576 
577 #ifdef SIGTSTP
578 #ifdef __ANDROID__
579 FLAG cansuspendmyself = False;
580 #else
581 FLAG cansuspendmyself = True;
582 #endif
583 #else
584 FLAG cansuspendmyself = False;
585 #endif
586 
587 void
suspendmyself()588 suspendmyself ()
589 {
590 #ifdef SIGTSTP
591   signal (SIGTSTP, SIG_DFL); /* uninstall catch of external TSTP */
592   kill (getpid (), SIGTSTP);
593   signal (SIGTSTP, catchtstp); /* reinstall the signal */
594 #endif
595 }
596 
597 
598 /*======================================================================*\
599 |*			Unix terminal capabilities			*|
600 \*======================================================================*/
601 
602 #if defined (unix) || defined (ANSI) || defined (vms)
603 
604 #ifndef CURSES
605 
606 static FLAG avoid_tputs = False;
607 
608 #ifdef __CYGWIN__avoiding_tputs
609 /* workaround: tputs not working anymore if terminfo not installed,
610    esp. when running stand-alone (without cygwin environment) */
611 #warning deprecated workaround replaced by dynamic alternative
612 #define termputstr(str, aff)	putstring (str)
613 #else
614 #ifdef vms
615 #define termputstr(str, aff)	putescape (str)
616 #else
617 #ifdef ANSI
618 #define termputstr(str, aff)	putstring (str)
619 #else
620 
621 extern int tputs _((char *, int, intfunc));
622 /*#define termputstr(str, aff)	(void) tputs (str, aff, (intfunc) __putchar)*/
623 static
624 void
termputstr(str,aff)625 termputstr (str, aff)
626   char * str;
627   int aff;
628 {
629   if (avoid_tputs) {
630 	putstring (str);
631   } else {
632 	(void) tputs (str, aff, (intfunc) __putchar);
633   }
634 }
635 
636 #endif
637 #endif
638 #endif
639 
640 static char
641      * cCL, * cCE, * cCD, * cEC, * cSR, * cAL, * cDL, * cCS, * cSC, * cRC,
642      * cCM, * cSO, * cSE, * cVS, * cVE, * cVI,
643      * cTI, * cTE, * cKS, * cKE,
644      * cAS, * cAE, * cEA, * cdisableEA, * cAC, * cS2, * cS3,
645      * cME, * cMR, * cMH, * cMD, * cUL, * cBL, * cAF, * cAB;
646 
647 #endif
648 
649 static char * cMouseEventAnyOn = "\033[?1003h";
650 static char * cMouseEventAnyOff = "\033[?1003l";
651 static char * cMouseEventBtnOn = "\033[?1002h";
652 #ifndef CURSES
653 static char * cMouseEventBtnOff = "\033[?1002l";
654 static char * cMouseButtonOn = "\033[?1000h";
655 static char * cMouseButtonOff = "\033[?1000l";
656 static char * cMouseX10On = "\033[?9h";
657 static char * cMouseX10Off = "\033[?9l";
658 
659 static char * cMouseExtendedOn = "\033[?1005h";
660 static char * cMouseExtendedOff = "\033[?1005l";
661 static char * cMouse1015On = "\033[?1015h";
662 static char * cMouse1015Off = "\033[?1015l";
663 
664 static char * cMouseFocusOn = "\033[?1004h";
665 static char * cMouseFocusOff = "\033[?1004l";
666 static char * cAmbigOn = "\033[?7700h";
667 static char * cAmbigOff = "\033[?7700l";
668 #endif
669 
670 #endif	/* defined (unix) || defined (vms) */
671 
672 
673 #ifdef unix
674 
675 /**
676    termcap/termlib API and storage
677  */
678 #if ! defined (ANSI) && ! defined (CURSES)
679 #define TERMAPI
680 #define TERMCAP	/* disable to use termlib/terminfo API */
681 #endif
682 
683 #ifdef CURSES
684 #define TERMAPI
685 #undef TERMCAP
686 #endif
687 
688 #ifdef __EMX__
689 #define TERMCAP
690 #endif
691 
692 
693 #ifdef __CYGWIN__avoiding_tputs
694 #warning deprecated workaround replaced by dynamic alternative
695 /* strip "$<2>" delay suffixes if not using tputs */
tstrfix(tc,tstr)696 static char * tstrfix (tc, tstr)
697   char * tc;
698   char * tstr;
699 {
700   if (tstr) {
701 	char * junk = strchr (tstr, '$');
702 	if (junk && * (junk + 1) == '<') {
703 		char * fixtstr = malloc (junk - tstr + 1);
704 		* fixtstr = '\0';
705 		strncat (fixtstr, tstr, junk - tstr);
706 		return fixtstr;
707 	}
708   }
709   return tstr;
710 }
711 #else
712 #define tstrfix(tc, tstr)	tstr
713 #endif
714 
715 #ifdef TERMAPI
716 #ifdef TERMCAP
717 /* termcap API */
718 #define term_setup(TERM)	(tgetent (term_rawbuf, TERM) == 1)
719 #define term_getstr(tc, ti)	tstrfix (tc, tgetstr (tc, & term_capbufpoi))
720 #define term_getnum(tc, ti)	tgetnum (tc)
721 #define term_getflag(tc, ti)	tgetflag (tc)
722 
723 #else	/* #ifdef TERMCAP */
724 /* terminfo API */
725 #define term_setup(TERM)	(setterm (TERM) == 0)
726 #define term_getstr(tc, ti)	tstrfix (tc, tigetstr (ti))
727 #define term_getnum(tc, ti)	tigetnum (ti)
728 #define term_getflag(tc, ti)	tigetflag (ti)
729 
730 #endif	/* #else TERMCAP */
731 #endif
732 
733 
734 #ifndef CURSES
735 
736 #ifdef TERMCAP
737 
738 extern int tgetent _((char * rawbuf, char * TERM));
739 extern char * tgetstr _((char *, char * * capbufpoi));
740 extern int tgetnum _((char *));
741 extern int tgetflag _((char *));
742 
743 #define term_capbuflen 1024
744 static char term_capbuf [term_capbuflen];
745 static char * term_capbufpoi = term_capbuf;
746 
747 #else	/* #ifdef TERMCAP */
748 
749 #ifdef BSD
750 extern int setterm _((char * TERM));
751 #else
752 extern int setupterm _((char * TERM, int , int *));
753 #define setterm(TERM)	setupterm (TERM, 1, 0)
754 #endif
755 extern char * tigetstr _((char *));
756 extern int tigetnum _((char *));
757 extern int tigetflag _((char *));
758 
759 #endif	/* #else TERMCAP */
760 
761 
762 extern char * tgoto _((char *, int, int));
763 
764 #define aff1 0
765 #define affmax YMAX
766 
767 #endif	/* #ifndef CURSES */
768 
769 
770 #define dont_debug_terminfo
771 
772 #ifndef ANSI
773 
774 #define fkeymap_terminfo_len 155
775 struct fkeyentry fkeymap_terminfo [fkeymap_terminfo_len + 1] = {
776 	{NIL_PTR}
777 };
778 static int fkeymap_terminfo_i = 0;
779 
780 static
781 void
add_keymap_entry(cap,f,shift_state)782 add_keymap_entry (cap, f, shift_state)
783   char * cap;
784   voidfunc f;
785   unsigned char shift_state;
786 {
787   if (fkeymap_terminfo_i < fkeymap_terminfo_len) {
788 	fkeymap_terminfo [fkeymap_terminfo_i].fk = cap;
789 	fkeymap_terminfo [fkeymap_terminfo_i].fp = f;
790 	fkeymap_terminfo [fkeymap_terminfo_i].fkeyshift = shift_state;
791 	fkeymap_terminfo_i ++;
792 	fkeymap_terminfo [fkeymap_terminfo_i].fk = NIL_PTR;
793   }
794 }
795 
796 
797 static
798 char *
add_terminfo_entry(tc,ti,f,shift_state)799 add_terminfo_entry (tc, ti, f, shift_state)
800   char * tc;
801   char * ti;
802   voidfunc f;
803   unsigned char shift_state;
804 {
805   if (f) {
806 	char * cap = term_getstr (tc, ti);
807 	if (cap) {
808 		add_keymap_entry (cap, f, shift_state);
809 #ifdef debug_terminfo
810 		printf ("termcap %s / terminfo %s : <^[%s> [shift %X]\n", tc, ti, cap + 1, shift_state);
811 #endif
812 		return cap;
813 	}
814   }
815   return 0;
816 }
817 
818 static
819 void
add_terminfo_entries()820 add_terminfo_entries ()
821 {
822   char * caphome;
823   char * capend;
824   caphome = add_terminfo_entry ("K1", "ka1",	HOMEkey, 0);	/* upper left of keypad */
825   (void) add_terminfo_entry ("K3", "ka3",	PGUPkey, 0);	/* upper right of keypad */
826   (void) add_terminfo_entry ("K2", "kb2",	HOP, 0);	/* center of keypad */
827   capend = add_terminfo_entry ("K4", "kc1",	ENDkey, 0);	/* lower left of keypad */
828   (void) add_terminfo_entry ("K5", "kc3",	PGDNkey, 0);	/* lower right of keypad */
829 
830   if (caphome && capend) {
831     /* if keypad keys are explicitly defined, use them to assign HOME/END;
832        if home/begin/home_down/end key definitions refer to different keys,
833        map "small" keypad functions to them;
834        if they happen to refer to the same keys, the first setting
835        will have precedence
836      */
837     (void) add_terminfo_entry ("kh", "khome",	smallHOMEkey, 0);	/* home key */
838     (void) add_terminfo_entry ("kH", "kll",	smallENDkey, 0);	/* lower-left key (home down) */
839     (void) add_terminfo_entry ("@1", "kbeg",	smallHOMEkey, 0);	/* begin key */
840     (void) add_terminfo_entry ("@7", "kend",	smallENDkey, 0);	/* end key */
841     (void) add_terminfo_entry ("#2", "kHOM",	HOMEkey, shift_mask);	/* shifted home key */
842     (void) add_terminfo_entry ("&9", "kBEG",	HOMEkey, shift_mask);	/* shifted begin key */
843     (void) add_terminfo_entry ("*7", "kEND",	ENDkey, shift_mask);	/* shifted end key */
844   } else {
845     /* if keypad keys are not explicitly defined,
846        assign HOME/END to home/begin and home_down/end keys
847      */
848     (void) add_terminfo_entry ("kh", "khome",	HOMEkey, 0);	/* home key */
849     (void) add_terminfo_entry ("kH", "kll",	ENDkey, 0);	/* lower-left key (home down) */
850     (void) add_terminfo_entry ("@1", "kbeg",	HOMEkey, 0);	/* begin key */
851     (void) add_terminfo_entry ("@7", "kend",	ENDkey, 0);	/* end key */
852     (void) add_terminfo_entry ("#2", "kHOM",	smallHOMEkey, shift_mask);	/* shifted home key */
853     (void) add_terminfo_entry ("&9", "kBEG",	smallHOMEkey, shift_mask);	/* shifted begin key */
854     (void) add_terminfo_entry ("*7", "kEND",	smallENDkey, shift_mask);	/* shifted end key */
855   }
856 
857   (void) add_terminfo_entry ("kb", "kbs",	DPC, 0);	/* backspace key */
858   (void) add_terminfo_entry ("kB", "kcbt",	MPW, 0);	/* back-tab key */
859   (void) add_terminfo_entry ("@2", "kcan",	0, 0);	/* cancel key */
860   (void) add_terminfo_entry ("ka", "ktbc",	0, 0);	/* clear-all-tabs key */
861   (void) add_terminfo_entry ("kC", "kclr",	0, 0);	/* clear-screen or erase key */
862   (void) add_terminfo_entry ("@3", "kclo",	0, 0);	/* close key */
863   (void) add_terminfo_entry ("@4", "kcmd",	HOP, 0);	/* command key */
864   (void) add_terminfo_entry ("@5", "kcpy",	COPY, 0);	/* copy key */
865   (void) add_terminfo_entry ("@6", "kcrt",	0, 0);	/* create key */
866   (void) add_terminfo_entry ("kt", "kctab",	0, 0);	/* clear-tab key */
867   (void) add_terminfo_entry ("kD", "kdch1",	DELkey, 0);	/* delete-character key */
868   (void) add_terminfo_entry ("kL", "kdl1",	0, 0);	/* delete-line key */
869   (void) add_terminfo_entry ("kd", "kcud1",	DNkey, 0);	/* down-arrow key */
870   (void) add_terminfo_entry ("kM", "krmir",	0, 0);	/* sent by rmir or smir in insert mode */
871   (void) add_terminfo_entry ("@8", "kent",	SNL, 0);	/* enter/send key */
872   (void) add_terminfo_entry ("kE", "kel",	0, 0);	/* clear-to-end-of-line key */
873   (void) add_terminfo_entry ("kS", "ked",	0, 0);	/* clear-to-end-of-screen key */
874   (void) add_terminfo_entry ("@9", "kext",	0, 0);	/* exit key */
875 
876   (void) add_terminfo_entry ("k0", "kf0",	F10, 0);	/* F0 function key */
877   (void) add_terminfo_entry ("k1", "kf1",	F1, 0);	/* F1 function key */
878   (void) add_terminfo_entry ("k2", "kf2",	F2, 0);	/* F2 function key */
879   (void) add_terminfo_entry ("k3", "kf3",	F3, 0);	/* F3 function key */
880   (void) add_terminfo_entry ("k4", "kf4",	F4, 0);	/* F4 function key */
881   (void) add_terminfo_entry ("k5", "kf5",	F5, 0);	/* F5 function key */
882   (void) add_terminfo_entry ("k6", "kf6",	F6, 0);	/* F6 function key */
883   (void) add_terminfo_entry ("k7", "kf7",	F7, 0);	/* F7 function key */
884   (void) add_terminfo_entry ("k8", "kf8",	F8, 0);	/* F8 function key */
885   (void) add_terminfo_entry ("k9", "kf9",	F9, 0);	/* F9 function key */
886   (void) add_terminfo_entry ("k;", "kf10",	F10, 0);	/* F10 function key */
887 
888 #ifdef shift_f_keys
889 	there is no uniform mapping of actual shifted function keys
890 	to terminfo F11..F63 names, so better leave these entries out
891   (void) add_terminfo_entry ("F1", "kf11",	F11, 0);	/* F11 function key */
892   (void) add_terminfo_entry ("F2", "kf12",	F12, 0);	/* F12 function key */
893   (void) add_terminfo_entry ("F3", "kf13",	F1, shift_mask);	/* F13 function key */
894   (void) add_terminfo_entry ("F4", "kf14",	F2, shift_mask);	/* F14 function key */
895   (void) add_terminfo_entry ("F5", "kf15",	F3, shift_mask);	/* F15 function key */
896   (void) add_terminfo_entry ("F6", "kf16",	F4, shift_mask);	/* F16 function key */
897   (void) add_terminfo_entry ("F7", "kf17",	F5, shift_mask);	/* F17 function key */
898   (void) add_terminfo_entry ("F8", "kf18",	F6, shift_mask);	/* F18 function key */
899   (void) add_terminfo_entry ("F9", "kf19",	F7, shift_mask);	/* F19 function key */
900   (void) add_terminfo_entry ("FA", "kf20",	F8, shift_mask);	/* F20 function key */
901   (void) add_terminfo_entry ("FB", "kf21",	F9, shift_mask);	/* F21 function key */
902   (void) add_terminfo_entry ("FC", "kf22",	F10, shift_mask);	/* F22 function key */
903   (void) add_terminfo_entry ("FD", "kf23",	F11, shift_mask);	/* F23 function key */
904   (void) add_terminfo_entry ("FE", "kf24",	F12, shift_mask);	/* F24 function key */
905   (void) add_terminfo_entry ("FF", "kf25",	F1, ctrl_mask);	/* F25 function key */
906   (void) add_terminfo_entry ("FG", "kf26",	F2, ctrl_mask);	/* F26 function key */
907   (void) add_terminfo_entry ("FH", "kf27",	F3, ctrl_mask);	/* F27 function key */
908   (void) add_terminfo_entry ("FI", "kf28",	F4, ctrl_mask);	/* F28 function key */
909   (void) add_terminfo_entry ("FJ", "kf29",	F5, ctrl_mask);	/* F29 function key */
910   (void) add_terminfo_entry ("FK", "kf30",	F6, ctrl_mask);	/* F30 function key */
911   (void) add_terminfo_entry ("FL", "kf31",	F7, ctrl_mask);	/* F31 function key */
912   (void) add_terminfo_entry ("FM", "kf32",	F8, ctrl_mask);	/* F32 function key */
913   (void) add_terminfo_entry ("FN", "kf33",	F9, ctrl_mask);	/* F33 function key */
914   (void) add_terminfo_entry ("FO", "kf34",	F10, ctrl_mask);	/* F34 function key */
915   (void) add_terminfo_entry ("FP", "kf35",	F11, ctrl_mask);	/* F35 function key */
916   (void) add_terminfo_entry ("FQ", "kf36",	F12, ctrl_mask);	/* F36 function key */
917   (void) add_terminfo_entry ("FR", "kf37",	F1, ctrlshift_mask);	/* F37 function key */
918   (void) add_terminfo_entry ("FS", "kf38",	F2, ctrlshift_mask);	/* F38 function key */
919   (void) add_terminfo_entry ("FT", "kf39",	F3, ctrlshift_mask);	/* F39 function key */
920   (void) add_terminfo_entry ("FU", "kf40",	F4, ctrlshift_mask);	/* F40 function key */
921   (void) add_terminfo_entry ("FV", "kf41",	F5, ctrlshift_mask);	/* F41 function key */
922   (void) add_terminfo_entry ("FW", "kf42",	F6, ctrlshift_mask);	/* F42 function key */
923   (void) add_terminfo_entry ("FX", "kf43",	F7, ctrlshift_mask);	/* F43 function key */
924   (void) add_terminfo_entry ("FY", "kf44",	F8, ctrlshift_mask);	/* F44 function key */
925   (void) add_terminfo_entry ("FZ", "kf45",	F9, ctrlshift_mask);	/* F45 function key */
926   (void) add_terminfo_entry ("Fa", "kf46",	F10, ctrlshift_mask);	/* F46 function key */
927   (void) add_terminfo_entry ("Fb", "kf47",	F11, ctrlshift_mask);	/* F47 function key */
928   (void) add_terminfo_entry ("Fc", "kf48",	F12, ctrlshift_mask);	/* F48 function key */
929   (void) add_terminfo_entry ("Fd", "kf49",	F1, alt_mask);	/* F49 function key */
930   (void) add_terminfo_entry ("Fe", "kf50",	F2, alt_mask);	/* F50 function key */
931   (void) add_terminfo_entry ("Ff", "kf51",	F3, alt_mask);	/* F51 function key */
932   (void) add_terminfo_entry ("Fg", "kf52",	F4, alt_mask);	/* F52 function key */
933   (void) add_terminfo_entry ("Fh", "kf53",	F5, alt_mask);	/* F53 function key */
934   (void) add_terminfo_entry ("Fi", "kf54",	F6, alt_mask);	/* F54 function key */
935   (void) add_terminfo_entry ("Fj", "kf55",	F7, alt_mask);	/* F55 function key */
936   (void) add_terminfo_entry ("Fk", "kf56",	F8, alt_mask);	/* F56 function key */
937   (void) add_terminfo_entry ("Fl", "kf57",	F9, alt_mask);	/* F57 function key */
938   (void) add_terminfo_entry ("Fm", "kf58",	F10, alt_mask);	/* F58 function key */
939   (void) add_terminfo_entry ("Fn", "kf59",	F11, alt_mask);	/* F59 function key */
940   (void) add_terminfo_entry ("Fo", "kf60",	F12, alt_mask);	/* F60 function key */
941   (void) add_terminfo_entry ("Fp", "kf61",	F1, altshift_mask);	/* F61 function key */
942   (void) add_terminfo_entry ("Fq", "kf62",	F2, altshift_mask);	/* F62 function key */
943   (void) add_terminfo_entry ("Fr", "kf63",	F3, altshift_mask);	/* F63 function key */
944 #endif
945 
946   (void) add_terminfo_entry ("@0", "kfnd",	FIND, 0);	/* find key */
947   (void) add_terminfo_entry ("%1", "khlp",	HELP, 0);	/* help key */
948   (void) add_terminfo_entry ("kI", "kich1",	INSkey, 0);	/* insert-character key */
949   (void) add_terminfo_entry ("kA", "kil1",	0, 0);	/* insert-line key */
950   (void) add_terminfo_entry ("kl", "kcub1",	LFkey, 0);	/* left-arrow key */
951   (void) add_terminfo_entry ("%2", "kmrk",	MARK, 0);	/* mark key */
952   (void) add_terminfo_entry ("%3", "kmsg",	0, 0);	/* message key */
953   (void) add_terminfo_entry ("%4", "kmov",	0, 0);	/* move key */
954   (void) add_terminfo_entry ("%5", "knxt",	0, 0);	/* next key */
955   (void) add_terminfo_entry ("kN", "knp",	PGDNkey, 0);	/* next-page key */
956   (void) add_terminfo_entry ("%6", "kopn",	EDIT, 0);	/* open key */
957   (void) add_terminfo_entry ("%7", "kopt",	QUICKMENU, 0);	/* options key */
958   (void) add_terminfo_entry ("kP", "kpp",	PGUPkey, 0);	/* previous-page key */
959   (void) add_terminfo_entry ("%8", "kprv",	0, 0);	/* previous key */
960   (void) add_terminfo_entry ("%9", "kprt",	PRINT, 0);	/* print key */
961   (void) add_terminfo_entry ("%0", "krdo",	COPY, 0);	/* redo key */
962   (void) add_terminfo_entry ("&1", "kref",	0, 0);	/* reference key */
963   (void) add_terminfo_entry ("&2", "krfr",	0, 0);	/* refresh key */
964   (void) add_terminfo_entry ("&3", "krpl",	GR, 0);	/* replace key */
965   (void) add_terminfo_entry ("&4", "krst",	0, 0);	/* restart key */
966   (void) add_terminfo_entry ("&5", "kres",	AGAIN, 0);	/* resume key */
967   (void) add_terminfo_entry ("kr", "kcuf1",	RTkey, 0);	/* right-arrow key */
968   (void) add_terminfo_entry ("&6", "ksav",	WT, 0);	/* save key */
969   (void) add_terminfo_entry ("&0", "kCAN",	0, shift_mask);	/* shifted cancel key */
970   (void) add_terminfo_entry ("*1", "kCMD",	HOP, shift_mask);	/* shifted command key */
971   (void) add_terminfo_entry ("*2", "kCPY",	COPY, shift_mask);	/* shifted copy key */
972   (void) add_terminfo_entry ("*3", "kCRT",	0, shift_mask);	/* shifted create key */
973   (void) add_terminfo_entry ("*4", "kDC",	DELkey, shift_mask);	/* shifted delete-character key */
974   (void) add_terminfo_entry ("*5", "kDL",	0, shift_mask);	/* shifted delete-line key */
975   (void) add_terminfo_entry ("*6", "kslt",	MARK, 0);	/* select key */
976   (void) add_terminfo_entry ("*8", "kEOL",	0, shift_mask);	/* shifted clear-to-end-of-line key */
977   (void) add_terminfo_entry ("*9", "kEXT",	0, shift_mask);	/* shifted exit key */
978   (void) add_terminfo_entry ("kF", "kind",	SD, 0);	/* scroll-forward key */
979   (void) add_terminfo_entry ("*0", "kFND",	FIND, shift_mask);	/* shifted find key */
980   (void) add_terminfo_entry ("#1", "kHLP",	HELP, shift_mask);	/* shifted help key */
981   (void) add_terminfo_entry ("#3", "kIC",	INSkey, shift_mask);	/* shifted insert-character key */
982   (void) add_terminfo_entry ("#4", "kLFT",	LFkey, shift_mask);	/* shifted left-arrow key */
983   (void) add_terminfo_entry ("%a", "kMSG",	0, shift_mask);	/* shifted message key */
984   (void) add_terminfo_entry ("%b", "kMOV",	0, shift_mask);	/* shifted move key */
985   (void) add_terminfo_entry ("%c", "kNXT",	PGDNkey, shift_mask);	/* shifted next key */
986   (void) add_terminfo_entry ("%d", "kOPT",	handleFlagmenus, shift_mask);	/* shifted options key */
987   (void) add_terminfo_entry ("%e", "kPRV",	PGUPkey, shift_mask);	/* shifted previous key */
988   (void) add_terminfo_entry ("%f", "kPRT",	PRINT, shift_mask);	/* shifted print key */
989   (void) add_terminfo_entry ("kR", "kri",	SU, 0);	/* scroll-backward key */
990   (void) add_terminfo_entry ("%g", "kRDO",	COPY, shift_mask);	/* shifted redo key */
991   (void) add_terminfo_entry ("%h", "kRPL",	REPL, shift_mask);	/* shifted replace key */
992   (void) add_terminfo_entry ("%i", "kRIT",	RTkey, shift_mask);	/* shifted right-arrow key */
993   (void) add_terminfo_entry ("%j", "kRES",	AGAIN, shift_mask);	/* shifted resume key */
994   (void) add_terminfo_entry ("!1", "kSAV",	WTU, shift_mask);	/* shifted save key */
995   (void) add_terminfo_entry ("!2", "kSPD",	SUSP, shift_mask);	/* shifted suspend key */
996   (void) add_terminfo_entry ("kT", "khts",	0, 0);	/* set-tab key */
997   (void) add_terminfo_entry ("!3", "kUND",	UNDO, shift_mask);	/* shifted undo key */
998   (void) add_terminfo_entry ("&7", "kspd",	SUSP, 0);	/* suspend key */
999   (void) add_terminfo_entry ("&8", "kund",	UNDO, 0);	/* undo key */
1000   (void) add_terminfo_entry ("ku", "kcuu1",	UPkey, 0);	/* up-arrow key */
1001   (void) add_terminfo_entry ("Km", "kmous",	DIRECTxterm, 0);	/* Mouse event has occurred */
1002 }
1003 
1004 #endif	/* #else ANSI */
1005 
1006 #endif	/* #ifdef unix */
1007 
1008 
1009 #ifdef ANSI
1010 struct fkeyentry fkeymap_terminfo [1] = {
1011 	{NIL_PTR}
1012 };
1013 #endif
1014 
1015 
1016 /*======================================================================*\
1017 |*			TTY and terminal mode switcher			*|
1018 \*======================================================================*/
1019 
1020 static void start_screen_mode _((int kb));
1021 static void end_screen_mode _((void));
1022 static void setup_terminal _((void));
1023 static void reset_terminal _((void));
1024 
1025 
1026 #ifdef CURSES
1027 
1028 #define use_newterm	/* otherwise, redirection to stdout doesn't work */
1029 
1030 #ifdef __EMX__		/* __PDCURSES__ ? */
1031 #undef use_newterm
1032 #endif
1033 #ifdef msdos
1034 #undef use_newterm
1035 #endif
1036 #ifdef vms
1037 #undef use_newterm
1038 #endif
1039 
1040 static FLAG screen_acquired = False;
1041 static void configure_screen _((void));
1042 # ifdef use_newterm
1043 static SCREEN * myscreen;
1044 extern FILE * fdopen ();
1045 # endif
1046 
1047 #endif
1048 
1049 
1050 #ifdef TERMIO
1051 static FLAG old_termprops_not_saved = True;
1052 #endif
1053 #ifdef SGTTY
1054 static FLAG old_termprops_not_saved = True;
1055 #endif
1056 
1057 static FLAG init_done = False;
1058 
1059 /* the termios ISIG flag suppresses signal generation on
1060    tty input of INTR, QUIT, SUSP, or DSUSP associated keys */
1061 #define dont_use_ISIG
1062 
1063 #ifdef TERMIO
1064 #ifdef debug_termios
1065 static
1066 void
dump_termios(tios)1067 dump_termios (tios)
1068   struct termios * tios;
1069 {
1070 	int i;
1071 	printf ("iflag %04X\n", tios->c_iflag);
1072 	printf ("oflag %04X\n", tios->c_oflag);
1073 	printf ("cflag %04X\n", tios->c_cflag);
1074 	printf ("lflag %04X\n", tios->c_lflag);
1075 	printf ("line  %02X\n", tios->c_line);
1076 	for (i = 0; i < NCCS; i ++) {
1077 		printf ("cc[%d] %02X\n", i, tios->c_cc [i]);
1078 	}
1079 }
1080 #endif
1081 #endif
1082 
1083 /*
1084  * Set (True) or Restore (False) tty raw mode.
1085  * Also set signal characters (except for ^\) to UNDEF. ^\ is caught.
1086  */
1087 void
raw_mode(to_raw_state)1088 raw_mode (to_raw_state)
1089   FLAG to_raw_state;
1090 {
1091 #ifdef TERMIO
1092   static struct termios old_termio;
1093 	 struct termios new_termio;
1094 #ifdef TCGETS
1095 # define gettermio(fd, iopoi)	ioctl (fd, TCGETS, iopoi)
1096 # ifdef TCSETSW
1097 # define settermio(fd, iopoi)	ioctl (fd, TCSETSW, iopoi)
1098 # else
1099 # define settermio(fd, iopoi)	ioctl (fd, TCSETS, iopoi)
1100 # endif
1101 #else
1102 # define gettermio(fd, iopoi)	tcgetattr (fd, iopoi)
1103 # ifdef TCSADRAIN
1104 # define settermio(fd, iopoi)	tcsetattr (fd, TCSADRAIN, iopoi)
1105 # else
1106 # define settermio(fd, iopoi)	tcsetattr (fd, TCSANOW, iopoi)
1107 # endif
1108 #endif
1109 #endif /* TERMIO */
1110 
1111 #ifdef SGTTY
1112   static struct sgttyb old_tty;
1113 	 struct sgttyb new_tty;
1114   static int oldlmode;
1115 	 int lmode;
1116   static struct tchars old_tchars;
1117   static struct ltchars old_ltchars;
1118 
1119 /* correspondence between the tchars/ltchars characters of the sgtty
1120    interface and the c_cc characters of the termios interface (codes vary):
1121 	sgtty		termio		sgtty		termio
1122 	struct tchars			struct ltchars
1123 	t_intrc		VINTR		t_suspc		VSUSP
1124 	t_quitc		VQUIT		t_dsuspc	VDSUSP
1125 	t_startc	VSTART		t_rprntc	VREPRINT
1126 	t_stopc		VSTOP		t_flushc	VDISCARD
1127 	t_eofc		VEOF (VMIN)	t_werasc	VWERASE
1128 	t_brkc		VEOL (VTIME)	t_lnextc	VLNEXT
1129 */
1130 #define NDEF '\377'
1131   static struct tchars new_tchars = {NDEF, 0, NDEF, NDEF, NDEF, NDEF};
1132   static struct tchars new_QStchars = {NDEF, 0, '\021', '\023', NDEF, NDEF};
1133   static struct ltchars new_ltchars = {NDEF, NDEF, NDEF, NDEF, NDEF, NDEF};
1134 
1135   new_tchars.t_quitc = quit_char;
1136   new_QStchars.t_quitc = quit_char;
1137 #endif /* SGTTY */
1138 
1139 
1140   if (to_raw_state == False) {
1141 	isscreenmode = False;
1142 
1143 /* Reset screen */
1144 
1145 	reset_terminal ();
1146 	end_screen_mode ();
1147 
1148 #ifndef CURSES
1149 	flush ();
1150 #endif
1151 
1152 
1153 /* Reset tty */
1154 #ifdef CURSES
1155 	savetty ();
1156 	endwin ();
1157 # ifdef vms
1158 	(void) system ("set terminal /ttsync /nopasthru");
1159 # endif
1160 #else
1161 #ifdef vms
1162 	ttclose ();
1163 #endif
1164 #endif
1165 
1166 #ifdef TERMIO
1167 	if (settermio (tty_fd, & old_termio) < 0) {
1168 /*printf ("settermio failed: %s\n", serror ());*/
1169 	}
1170 /*	one byte of output swallowed here on SunOS	*/
1171 #endif
1172 #ifdef SGTTY
1173 	(void) ioctl (tty_fd, TIOCSETP, & old_tty);
1174 	(void) ioctl (tty_fd, TIOCSETC, & old_tchars);
1175 /*	one byte of output swallowed here on SunOS	*/
1176 	(void) ioctl (tty_fd, TIOCSLTC, & old_ltchars);
1177 	(void) ioctl (tty_fd, TIOCLSET, & oldlmode);
1178 #endif
1179 
1180 /*	output a byte that SunOS may swallow:	*/
1181 	(void) write (output_fd, " \r", 2);
1182 
1183 #if defined (TIOCEXCL) && defined (TIOCNXCL)
1184 	/* release tty lock */
1185 	(void) ioctl (tty_fd, TIOCNXCL);
1186 #endif
1187 
1188 	return;
1189   }
1190 
1191 
1192   else /* (to_raw_state == True) */ {
1193 	if (isscreenmode) {
1194 		/* first terminal mode initialization is delayed
1195 		   and de-coupled from tty configuration */
1196 		start_screen_mode (1);
1197 		setup_terminal ();
1198 		init_done = True;
1199 		return;
1200 	}
1201 
1202 	/* first call: don't rely on checkwinsize() yet! */
1203 
1204 	isscreenmode = True;
1205 
1206 /* Init tty */
1207 #ifdef CURSES
1208 # ifdef vms
1209 	(void) system ("set terminal /pasthru /nottsync");
1210 # endif
1211 
1212 	if (screen_acquired == False) {
1213 # ifdef use_newterm
1214 		FILE * ttyin = fdopen (input_fd, "r");
1215 		FILE * ttyout = fdopen (output_fd, "w");
1216 		myscreen = newterm (NIL_PTR, ttyout, ttyin);
1217 		if (! myscreen) {
1218 			printf ("Cannot open terminal: %s\n", envvar ("TERM"));
1219 			exit (-1);
1220 		}
1221 # else
1222 		initscr ();
1223 # endif
1224 
1225 		add_terminfo_entries ();
1226 
1227 		screen_acquired = True;
1228 		configure_screen ();
1229 	} else {
1230 		resetty ();
1231 	}
1232 
1233 	getwinsize ();
1234 #else
1235 #ifdef vms
1236 	ttopen ();
1237 #endif
1238 #endif
1239 
1240 #ifdef TERMIO
1241 # ifdef ioctl_twice
1242 	if (old_termprops_not_saved) {
1243 		/* Save old tty settings */
1244 		if (gettermio (tty_fd, & old_termio) < 0) {
1245 /*printf ("gettermio failed: %s\n", serror ());*/
1246 		}
1247 
1248 		/* Determine configured erase character */
1249 		erase_char = old_termio.c_cc [VERASE];
1250 		/*kill_char = old_termio.c_cc [VKILL];*/
1251 
1252 		old_termprops_not_saved = False;
1253 	}
1254 # endif
1255 
1256 	if (gettermio (tty_fd, & new_termio) < 0) {
1257 /*printf ("gettermio failed: %s\n", serror ());*/
1258 	}
1259 
1260 # ifndef ioctl_twice
1261 	if (old_termprops_not_saved) {
1262 		/* Save old tty settings */
1263 		memcpy (& old_termio, & new_termio, sizeof (struct termios));
1264 
1265 		/* Determine configured erase character */
1266 		erase_char = old_termio.c_cc [VERASE];
1267 		/*kill_char = old_termio.c_cc [VKILL];*/
1268 
1269 		old_termprops_not_saved = False;
1270 	}
1271 # endif
1272 
1273 	if (controlQS == False) {
1274 		new_termio.c_iflag &= ~(ISTRIP|IXON|IXOFF);
1275 	} else {
1276 		new_termio.c_iflag &= ~(ISTRIP);
1277 	}
1278 	new_termio.c_oflag &= ~OPOST;
1279 	new_termio.c_cflag &= ~(PARENB|CSIZE);
1280 	new_termio.c_cflag |= CS8;
1281 	new_termio.c_lflag &= ~(ICANON|ECHO
1282 #ifdef use_ISIG
1283 #ifdef ISIG
1284 		|ISIG
1285 #endif
1286 #endif
1287 		);
1288 	new_termio.c_iflag &= ~ICRNL;	/* pass through ^M */
1289 #define NDEF '\000'
1290 	new_termio.c_cc [VMIN] = 1;
1291 #ifdef selectread
1292 	new_termio.c_cc [VTIME] = 0;
1293 #else
1294 	/* let read loop monitor WINCH */
1295 	new_termio.c_cc [VTIME] = 3;	/* 3 is good trade-off */
1296 #endif
1297 	new_termio.c_cc [VQUIT] = quit_char;	/* don't use ISIG! */
1298 	new_termio.c_cc [VINTR] = NDEF;
1299 	new_termio.c_cc [VSUSP] = NDEF;
1300 #ifdef VSTOP
1301 	new_termio.c_cc [VSTOP] = NDEF;	/* or/also use IXOFF? */
1302 #endif
1303 #ifdef VDISCARD
1304 	new_termio.c_cc [VDISCARD] = NDEF;
1305 #endif
1306 #ifdef VDSUSP
1307 	new_termio.c_cc [VDSUSP] = NDEF;
1308 #endif
1309 #ifdef VLNEXT
1310 	new_termio.c_cc [VLNEXT] = NDEF;
1311 #endif
1312 	if (settermio (tty_fd, & new_termio) < 0) {
1313 /*printf ("settermio failed: %s\n", serror ());*/
1314 	}
1315 #endif /* TERMIO */
1316 #ifdef SGTTY
1317 	if (old_termprops_not_saved) {
1318 		/* Save old tty settings */
1319 		(void) ioctl (tty_fd, TIOCGETP, & old_tty);
1320 		(void) ioctl (tty_fd, TIOCGETC, & old_tchars);
1321 		(void) ioctl (tty_fd, TIOCGLTC, & old_ltchars);
1322 		(void) ioctl (tty_fd, TIOCLGET, & oldlmode);
1323 
1324 		/* Determine configured erase character */
1325 		erase_char = old_tty.sg_erase;
1326 		/*kill_char = old_tty.sg_kill;*/
1327 
1328 		old_termprops_not_saved = False;
1329 	}
1330 
1331 	/* Set line mode */
1332 	/* If this feature should not be available on some system,
1333 	   RAW must be used instead of CBREAK below to enable 8 bit output */
1334 	lmode = oldlmode;
1335 	lmode |= LPASS8; /* enable 8 bit characters on input in CBREAK mode */
1336 	lmode |= LLITOUT; /* enable 8 bit characters on output in CBREAK mode;
1337 	    this may not be necessary in newer Unixes, e.g. SunOS 4;
1338 	    output handling is slightly complicated by LITOUT */
1339 	(void) ioctl (tty_fd, TIOCLSET, & lmode);
1340 	/* Set tty to CBREAK (or RAW) mode */
1341 	new_tty = old_tty;
1342 	new_tty.sg_flags &= ~ECHO;
1343 	new_tty.sg_flags |= CBREAK;
1344 	(void) ioctl (tty_fd, TIOCSETP, & new_tty);
1345 	/* Unset signal chars */
1346 	if (controlQS == False) {
1347 		/* leave quit_char */
1348 		(void) ioctl (tty_fd, TIOCSETC, & new_tchars);
1349 	} else {
1350 		/* leave quit_char, ^Q, ^S */
1351 		(void) ioctl (tty_fd, TIOCSETC, & new_QStchars);
1352 	}
1353 	(void) ioctl (tty_fd, TIOCSLTC, & new_ltchars); /* Leaves nothing */
1354 #endif /* SGTTY */
1355 
1356 #if defined (TIOCEXCL) && defined (TIOCNXCL)
1357 	/* prevent from other processes spoiling the editing screen;
1358 	   acquire tty lock
1359 		- does not lock against root processes writing to tty
1360 		- does not work on cygwin (as of 1.7.30)
1361 	 */
1362 	(void) ioctl (tty_fd, TIOCEXCL);
1363 #endif
1364 
1365 
1366 /* Init screen */
1367 	if (init_done) { /* postpone on first invocation of raw_mode */
1368 		/* keyboard modes */
1369 		start_screen_mode (1);
1370 		/* specific terminal modes */
1371 		setup_terminal ();
1372 	}
1373 	/* do not postpone actual screen mode */
1374 	start_screen_mode (0);
1375 
1376 #ifdef CURSES
1377 	refresh ();
1378 	/* Determine configured erase character */
1379 	erase_char = erasechar ();
1380 	/*kill_char = killchar ();*/
1381 #else
1382 	flush ();
1383 #endif
1384 
1385 /* Setup specific signal handlers */
1386 #ifdef SIGQUIT
1387 	signal (SIGQUIT, catchquit);	/* Catch quit_char */
1388 #endif
1389 #ifdef SIGBREAK
1390 	signal (SIGBREAK, catchbreak);	/* control-Break (e.g. OS/2) */
1391 #else
1392 # ifdef msdos_suppressbreak
1393 	ctrlbrk (controlbreak);	/* completely useless, stupid Turbo-C! */
1394 # endif
1395 #endif
1396 #ifdef SIGINT
1397 	signal (SIGINT, catchint);	/* Catch INTR char (^C) */
1398 #endif
1399 #ifdef SIGWINCH
1400 	signal (SIGWINCH, catchwinch);	/* Catch window size changes */
1401 #endif
1402 #ifdef SIGTSTP
1403 	signal (SIGTSTP, catchtstp);
1404 #endif
1405 #ifdef SIGCONT
1406 	signal (SIGCONT, catchcont);
1407 #endif
1408   }
1409 }
1410 
1411 
1412 /*======================================================================*\
1413 |*			Terminal mode setup				*|
1414 \*======================================================================*/
1415 
1416 /**
1417    temporarily disable modifyOtherKeys for shifted letters
1418  */
1419 void
disable_modify_keys(dis)1420 disable_modify_keys (dis)
1421   FLAG dis;
1422 {
1423 #ifdef unix
1424   if (use_modifyOtherKeys && xterm_version > 0) {
1425 	if (dis) {
1426 		putescape ("\033[>4m");
1427 	} else {
1428 		putescape ("\033[>4;2m");
1429 	}
1430 	flush ();
1431   }
1432 #endif
1433 }
1434 
1435 
1436 FLAG redefined_ansi2 = False;
1437 
1438 #if defined (unix) || defined (ANSI) || defined (vms)
1439 
1440 FLAG redefined_ansi3 = False;
1441 FLAG redefined_ansi7 = False;
1442 FLAG redefined_curscolr = False;
1443 
1444 char set_ansi2 [27];
1445 char restore_ansi2 [27];
1446 char set_ansi3 [27];
1447 char restore_ansi3 [27];
1448 char set_ansi7 [27];
1449 char restore_ansi7 [27];
1450 char set_curscolr [27];
1451 char restore_curscolr [27];
1452 
1453 static void
setup_terminal()1454 setup_terminal ()
1455 {
1456   /* set redefined ANSI colors */
1457   if (redefined_ansi7) {
1458 	putescape (set_ansi7);
1459   }
1460   if (redefined_ansi2) {
1461 	putescape (set_ansi2);
1462   }
1463   if (redefined_ansi3) {
1464 	putescape (set_ansi3);
1465   }
1466   if (redefined_curscolr) {
1467 	putescape (set_curscolr);
1468   }
1469 
1470   /* set special keyboard modes */
1471   if (use_modifyOtherKeys) {
1472 	putescape ("\033[>4;2m");
1473   }
1474 
1475   /* screen style */
1476   if (cursor_style) {
1477 	static char cs [15];
1478 	build_string (cs, "\033[%d q", cursor_style);
1479 	putescape (cs);
1480   }
1481 
1482   /* specific terminal configuration */
1483   if (configure_xterm_keyboard && xterm_version > 0) {
1484 	putescape ("\033[?1037s"); /* save DEC mode value */
1485 	/* send DEL from the editing‐keypad Delete key */
1486 	putescape ("\033[?1037h");
1487 	if (xterm_version < 122) {
1488 		putescape ("\033[?1034s"); /* save DEC mode value */
1489 		/* send ESC when Meta modifies a key (eightBitInput: false) */
1490 		putescape ("\033[?1034l");
1491 	} else {
1492 		putescape ("\033[?1036s"); /* save DEC mode value */
1493 		/* send ESC when Meta modifies a key (metaSendsEscape: true) */
1494 		putescape ("\033[?1036h");
1495 	}
1496   }
1497 #ifdef mintty_scrollbar_workaround
1498   if (mintty_version > 0) {
1499 	putescape ("\033[?30l"); /* disable scrollbar to facilitate mouse wheel */
1500 # ifdef debug_terminal_resize
1501 	printf ("disabling scrollbar\n");
1502 # endif
1503   }
1504 #endif
1505   if (mintty_version >= 403) {
1506 	/* this mode interferes with fkeymap_rxvt
1507 	   if inappropriately TERM=rxvt in mintty (workaround in mined1.c) */
1508 	putescape ("\033[?7727h"); /* application escape key mode: ESC sends ^[O[ */
1509   }
1510   if (mintty_version >= 501) {
1511 	putescape ("\033[?7783h"); /* shortcut override on */
1512   }
1513 }
1514 
1515 static void
reset_terminal()1516 reset_terminal ()
1517 {
1518   /* restore redefined ANSI colors */
1519   if (redefined_ansi7) {
1520 	putescape (restore_ansi7);
1521   }
1522   if (redefined_ansi2) {
1523 	putescape (restore_ansi2);
1524   }
1525   if (redefined_ansi3) {
1526 	putescape (restore_ansi3);
1527   }
1528   if (redefined_curscolr) {
1529 	putescape (restore_curscolr);
1530   }
1531 
1532   /* reset special keyboard modes */
1533   if (use_modifyOtherKeys) {
1534 #ifdef reset_modifyOtherKeys
1535 	if (mintty_version == 400) {
1536 		putescape ("\033[>4;0m");
1537 	} else {
1538 		putescape ("\033[>4m");
1539 	}
1540 #else
1541 	putescape ("\033[>4m");
1542 #endif
1543   }
1544 
1545 /* screen style */
1546   if (cursor_style) {
1547 	putescape ("\033[0 q");
1548   }
1549 
1550   /* restore specific terminal modes */
1551   if (configure_xterm_keyboard && xterm_version > 0) {
1552 	putescape ("\033[?1037r"); /* restore DEC mode value */
1553 	if (xterm_version < 122) {
1554 		putescape ("\033[?1034r"); /* restore DEC mode value */
1555 	} else {
1556 		putescape ("\033[?1036r"); /* restore DEC mode value */
1557 	}
1558   }
1559 #ifdef mintty_scrollbar_workaround
1560   if (mintty_version > 0) {
1561 	putescape ("\033[?30h"); /* enable scrollbar if it was enabled */
1562 # ifdef debug_terminal_resize
1563 	printf ("enabling scrollbar\n");
1564 # endif
1565   }
1566 #endif
1567   if (mintty_version >= 403) {
1568 	putescape ("\033[?7727l"); /* reset application escape key mode */
1569   }
1570   if (mintty_version >= 501) {
1571 	putescape ("\033[?7783l"); /* shortcut override off */
1572   }
1573 }
1574 
1575 #else
1576 
1577 static void
setup_terminal()1578 setup_terminal ()
1579 {
1580 }
1581 
1582 static void
reset_terminal()1583 reset_terminal ()
1584 {
1585 }
1586 
1587 #endif
1588 
1589 
1590 /*======================================================================*\
1591 |*			Escape code I/O routine				*|
1592 \*======================================================================*/
1593 
1594 #ifdef CURSES
1595 void
_putescape(s)1596 _putescape (s)
1597   char * s;
1598 {
1599 	/* synchronize with buffered screen output */
1600 	flush ();
1601 	/* bypass curses for escape sequence */
1602 	if (write (output_fd, s, strlen (s)) <= 0) {
1603 		/* terminal write error; cannot do anything */
1604 	}
1605 }
1606 #else
1607 #define _putescape(s)	putstring (s)
1608 #endif
1609 
1610 void
putescape(s)1611 putescape (s)
1612   char * s;
1613 {
1614   if (screen_version > 0) {
1615 	/* pass through transparently to host terminal: */
1616 	_putescape ("\033P");
1617 	_putescape (s);
1618 	_putescape ("\033\\");
1619   } else {
1620 	_putescape (s);
1621   }
1622 }
1623 
1624 
1625 /*======================================================================*\
1626 |*			Menu borders					*|
1627 \*======================================================================*/
1628 
1629 /*	block graphics mapping
1630 	note: VGA (PC) encoding also used on Linux console!
1631 VT100	VGA	curses
1632 j	D9	ACS_LRCORNER
1633 k	BF	ACS_URCORNER
1634 l	DA	ACS_ULCORNER
1635 m	C0	ACS_LLCORNER
1636 n		ACS_PLUS
1637 o		ACS_S1
1638 p		ACS_S3
1639 q	C4	ACS_HLINE
1640 r		ACS_S7
1641 s		ACS_S9
1642 t	C3	ACS_LTEE
1643 u	B4	ACS_RTEE
1644 v	C1	ACS_BTEE
1645 w	C2	ACS_TTEE
1646 x	B3	ACS_VLINE
1647 */
1648 
1649 /**
1650    ASCII block graphics mapping
1651    +-+-+
1652    +-+-+
1653    | | |
1654    +-+-+
1655  */
1656 static
1657 char *
asciiblockchar(c)1658 asciiblockchar (c)
1659   character c;
1660 {
1661     if (menu_border_style == 'r') {
1662 	switch (c) {
1663 		case 'j':	return "/";	/* LR */
1664 		case 'k':	return "\\";	/* UR */
1665 		case 'l':	return "/";	/* UL */
1666 		case 'm':	return "\\";	/* LL */
1667 		case 'n':	return "+";	/* crossing (not used) */
1668 		case 'q':	if (cjk_width_data_version) {
1669 					return "--";	/* hor. line */
1670 				} else {
1671 					return "-";	/* hor. line */
1672 				}
1673 		case 't':	return "+";	/* left tee */
1674 		case 'u':	return "+";	/* right tee */
1675 		case 'v':	return "+";	/* bottom tee */
1676 		case 'w':	return "+";	/* top tee */
1677 		case 'x':	return "|";	/* vert. line */
1678 		case 'f':
1679 		case 'g':	/* scrolling indication */
1680 				if (utf8_screen) {
1681 					return "¦";
1682 				} else if (cjk_term || mapped_term) {
1683 					return "|";
1684 				} else {
1685 					return "�";
1686 				}
1687 		default: return "";
1688 	}
1689     } else {
1690 	switch (c) {
1691 		case 'j':	return "+";	/* LR */
1692 		case 'k':	return "+";	/* UR */
1693 		case 'l':	return "+";	/* UL */
1694 		case 'm':	return "+";	/* LL */
1695 		case 'n':	return "+";	/* crossing (not used) */
1696 		case 'q':	if (cjk_width_data_version) {
1697 					return "--";	/* hor. line */
1698 				} else {
1699 					return "-";	/* hor. line */
1700 				}
1701 		case 't':	return "+";	/* left tee */
1702 		case 'u':	return "+";	/* right tee */
1703 		case 'v':	return "+";	/* bottom tee */
1704 		case 'w':	return "+";	/* top tee */
1705 		case 'x':	return "|";	/* vert. line */
1706 		case 'f':
1707 		case 'g':	/* scrolling indication */
1708 				if (utf8_screen) {
1709 					return "¦";
1710 				} else if (cjk_term || mapped_term) {
1711 					return "|";
1712 				} else {
1713 					return "�";
1714 				}
1715 		default: return "";
1716 	}
1717     }
1718 }
1719 
1720 #ifndef CURSES
1721 
1722 /**
1723    VGA (PC/DOS) block graphics mapping
1724  */
1725 static
1726 character
vgablockchar(c)1727 vgablockchar (c)
1728   character c;
1729 {
1730     if (menu_border_style == 'd') {
1731 	switch (c) {
1732 		case 'j':	return 0xBC;	/* LR */
1733 		case 'k':	return 0xBB;	/* UR */
1734 		case 'l':	return 0xC9;	/* UL */
1735 		case 'm':	return 0xC8;	/* LL */
1736 		case 'n':	return 0xCE;	/* crossing (not used) */
1737 		case 'q':	return 0xCD;	/* hor. line */
1738 		case 't':	return 0xCC;	/* left tee */
1739 		case 'u':	return 0xB9;	/* right tee */
1740 		case 'v':	return 0xCA;	/* bottom tee */
1741 		case 'w':	return 0xCB;	/* top tee */
1742 		case 'x':	return 0xBA;	/* vert. line */
1743 		case 'f':	/* scrolling indication up */
1744 		case 'g':	/* scrolling indication down */
1745 				return '';
1746 #ifdef choose_scrolling_indicators
1747 				return '';	/* diamond */
1748 				return 0xBA;	/* double line */
1749 				return '';	/* arrow up */
1750 				return '';	/* arrow down */
1751 				return 0xB2;	/* box */
1752 #endif
1753 		default:	return c;
1754 	}
1755     } else {
1756 	switch (c) {
1757 		case 'j':	return 0xD9;	/* LR */
1758 		case 'k':	return 0xBF;	/* UR */
1759 		case 'l':	return 0xDA;	/* UL */
1760 		case 'm':	return 0xC0;	/* LL */
1761 		case 'n':	return 0xC5;	/* crossing (not used) */
1762 		case 'q':	return 0xC4;	/* hor. line */
1763 		case 't':	return 0xC3;	/* left tee */
1764 		case 'u':	return 0xB4;	/* right tee */
1765 		case 'v':	return 0xC1;	/* bottom tee */
1766 		case 'w':	return 0xC2;	/* top tee */
1767 		case 'x':	return 0xB3;	/* vert. line */
1768 		case 'f':	/* scrolling indication up */
1769 				return '';	/* arrow up */
1770 		case 'g':	/* scrolling indication down */
1771 				return '';	/* arrow down */
1772 #ifdef choose_scrolling_indicators
1773 				return '';	/* arrow up */
1774 				return '';	/* arrow down */
1775 				return '';	/* diamond */
1776 				return 0xBA;	/* double line */
1777 				return 0xB2;	/* box */
1778 #endif
1779 		default:	return c;
1780 	}
1781     }
1782 }
1783 
1784 #if defined (unix) || defined (vms)
1785 
1786 /**
1787    block graphics mapping using termcap "ac" / terminfo "acsc" capability,
1788    or VT100 block graphics by default
1789  */
1790 static
1791 char *
acblockchar(c)1792 acblockchar (c)
1793   character c;
1794 {
1795   character cout = '\0';
1796   static char sout [3];
1797   char * spoi = sout;
1798 
1799   if (c == 'f' || c == 'g') {
1800 	c = '`';	/* choose one of '`' 'a' '|' 'f' */
1801   }
1802 
1803   if (* cAC) {
1804 	int i;
1805 	for (i = 0; i < strlen (cAC); i += 2) {
1806 		if (cAC [i] == c) {
1807 			cout = cAC [i + 1];
1808 			break;
1809 		}
1810 	}
1811 	if (cout == '\0') {
1812 		/*don't return asciiblockchar (c) while in graphics mode*/
1813 		/*don't skip wide handling below anyway*/
1814 		cout = c;
1815 	}
1816   } else {
1817 	cout = c;
1818   }
1819 
1820   * spoi ++ = cout;
1821   if (c == 'q' && cjk_width_data_version && cjk_term) {
1822 	* spoi ++ = cout;
1823   }
1824   * spoi = '\0';
1825   return sout;
1826 }
1827 
1828 #endif
1829 
1830 #endif
1831 
1832 /**
1833    Unicode block graphics mapping
1834    ┌─┬─┐  ╭─┬─╮
1835    ├─┼─┤  ├─┼─┤
1836    │ │ │  │ │ │
1837    └─┴─┘  ╰─┴─╯
1838    ┏━┳━┓  ╔═╦═╗
1839    ┣━╋━┫  ╠═╬═╣
1840    ┃ ┃ ┃  ║ ║ ║
1841    ┗━┻━┛  ╚═╩═╝
1842  */
1843 static
1844 char *
unicodeblockchar(c)1845 unicodeblockchar (c)
1846   character c;
1847 {
1848   if (use_ascii_graphics) {
1849 	return asciiblockchar (c);
1850   } else {
1851     if (menu_border_style == 'f') {
1852 	switch (c) {
1853 		case 'j':	return "┛";	/* LR */
1854 		case 'k':	return "┓";	/* UR */
1855 		case 'l':	return "┏";	/* UL */
1856 		case 'm':	return "┗";	/* LL */
1857 		case 'n':	return "╋";	/* crossing (not used) */
1858 		case 'q':	return "━";	/* hor. line */
1859 		case 't':	return "┣";	/* left tee */
1860 		case 'u':	return "┫";	/* right tee */
1861 		case 'v':	return "┻";	/* bottom tee */
1862 		case 'w':	return "┳";	/* top tee */
1863 		case 'x':	return "┃";	/* vert. line */
1864 		case 'f':	/* scroll indication up */
1865 		case 'g':	/* scroll indication down */
1866 				return menu_cont_fatmarker;
1867 #ifdef choose_scrolling_indicators
1868 				return "⬆";
1869 				return "⬇";
1870 #endif
1871 		default: return "";
1872 	}
1873     } else if (menu_border_style == 'd') {
1874 	switch (c) {
1875 		case 'j':	return "╝";	/* LR */
1876 		case 'k':	return "╗";	/* UR */
1877 		case 'l':	return "╔";	/* UL */
1878 		case 'm':	return "╚";	/* LL */
1879 		case 'n':	return "╬";	/* crossing (not used) */
1880 		case 'q':	return "═";	/* hor. line */
1881 		case 't':	return "╠";	/* left tee */
1882 		case 'u':	return "╣";	/* right tee */
1883 		case 'v':	return "╩";	/* bottom tee */
1884 		case 'w':	return "╦";	/* top tee */
1885 		case 'x':	return "║";	/* vert. line */
1886 		case 'f':	/* scroll indication up */
1887 		case 'g':	/* scroll indication down */
1888 				return "║";	/* scrolling indication */
1889 #ifdef choose_scrolling_indicators
1890 				return "⇑";
1891 				return "⇓";
1892 #endif
1893 		default: return "";
1894 	}
1895     } else if (menu_border_style == 'r') {
1896 	switch (c) {
1897 		case 'j':	return "╯";	/* LR */
1898 		case 'k':	return "╮";	/* UR */
1899 		case 'l':	return "╭";	/* UL */
1900 		case 'm':	return "╰";	/* LL */
1901 		case 'n':	return "┼";	/* crossing (not used) */
1902 		case 'q':	return "─";	/* hor. line */
1903 		case 't':	return "├";	/* left tee */
1904 		case 'u':	return "┤";	/* right tee */
1905 		case 'v':	return "┴";	/* bottom tee */
1906 		case 'w':	return "┬";	/* top tee */
1907 		case 'x':	return "│";	/* vert. line */
1908 		case 'f':	/* scroll indication up */
1909 		case 'g':	/* scroll indication down */
1910 				return menu_cont_marker; /* scroll indication */
1911 #ifdef choose_scrolling_indicators
1912 				return "↑";
1913 				return "↓";
1914 				return "⇡";
1915 				return "⇣";
1916 #endif
1917 		default: return "";
1918 	}
1919     } else {
1920 	switch (c) {
1921 		case 'j':	return "┘";	/* LR */
1922 		case 'k':	return "┐";	/* UR */
1923 		case 'l':	return "┌";	/* UL */
1924 		case 'm':	return "└";	/* LL */
1925 		case 'n':	return "┼";	/* crossing (not used) */
1926 		case 'q':	return "─";	/* hor. line */
1927 		case 't':	return "├";	/* left tee */
1928 		case 'u':	return "┤";	/* right tee */
1929 		case 'v':	return "┴";	/* bottom tee */
1930 		case 'w':	return "┬";	/* top tee */
1931 		case 'x':	return "│";	/* vert. line */
1932 		case 'f':	/* scroll indication up */
1933 		case 'g':	/* scroll indication down */
1934 				return menu_cont_marker; /* scroll indication */
1935 #ifdef choose_scrolling_indicators
1936 				return "↑";
1937 				return "↓";
1938 				return "⇡";
1939 				return "⇣";
1940 #endif
1941 		default: return "";
1942 	}
1943     }
1944   }
1945 }
1946 
1947 
1948 /*======================================================================*\
1949 |*			Mouse mode control				*|
1950 \*======================================================================*/
1951 
1952 #if defined (unix) || defined (ANSI) || defined (vms)
1953 
1954 /**
1955    Adapt mouse mode to menu state (menu opened?)
1956    While a menu is open, mouse movement should be reported separately.
1957  */
1958 void
menu_mouse_mode(menu)1959 menu_mouse_mode (menu)
1960   FLAG menu;
1961 {
1962   if (! use_mouse) {
1963 	return;
1964   }
1965 
1966 #ifdef debug_mouse
1967   printf ("menu_mouse_mode %d\n", menu);
1968 #endif
1969 
1970   if (menu) {
1971 	if (in_menu_mouse_mode == False) {
1972 #ifndef CURSES_mouse
1973 		if (use_mouse_button_event_tracking) {
1974 			/* activate button-event tracking */
1975 			putescape (cMouseEventBtnOn);
1976 			if (use_mouse_anymove_inmenu) {
1977 				/* activate any-event tracking */
1978 				putescape (cMouseEventAnyOn);
1979 			}
1980 		}
1981 #endif
1982 		/* hide cursor for menu display if reverse mode available
1983 		   for menu item marking
1984 		 */
1985 		if (can_reverse_mode) {
1986 			disp_cursor (False);
1987 		}
1988 	}
1989   } else {
1990 	if (in_menu_mouse_mode) {
1991 #ifndef CURSES_mouse
1992 		if (use_mouse_button_event_tracking) {
1993 			if (use_mouse_anymove_inmenu && ! use_mouse_anymove_always) {
1994 				/* deactivate any-event tracking */
1995 				putescape (cMouseEventAnyOff);
1996 			}
1997 			/* reactivate button-event tracking */
1998 			putescape (cMouseEventBtnOn);
1999 			if (use_mouse_anymove_always) {
2000 				/* upgrade to any-event tracking */
2001 				putescape (cMouseEventAnyOn);
2002 			}
2003 		}
2004 #endif
2005 		/* turn cursor visible again;
2006 		   (was turned invisible only if reverse mode available)
2007 		 */
2008 		if (can_reverse_mode) {
2009 			disp_cursor (True);
2010 		}
2011 	}
2012   }
2013   in_menu_mouse_mode = menu;
2014 }
2015 
2016 /**
2017    Enable/disable xterm button event reporting mode.
2018  */
2019 void
mouse_button_event_mode(report)2020 mouse_button_event_mode (report)
2021   FLAG report;
2022 {
2023   if (! use_mouse_button_event_tracking) {
2024 	return;
2025   }
2026 
2027 #ifdef debug_mouse
2028   printf ("mouse_button_event_mode %d\n", report);
2029 #endif
2030 
2031 #ifndef CURSES_mouse
2032   if (report) {
2033 	/* activate button-event tracking */
2034 	putescape (cMouseEventBtnOn);
2035 	is_mouse_button_event_mode_enabled = True;
2036   } else if (is_mouse_button_event_mode_enabled) {
2037 #ifdef switch_button_event_tracking
2038 	putescape (cMouseEventBtnOff);
2039 	flush ();
2040 #endif
2041 	is_mouse_button_event_mode_enabled = False;
2042   }
2043 #endif
2044 }
2045 
2046 /**
2047    Switch normal/alternate screen buffer.
2048  */
2049 void
screen_buffer(alt)2050 screen_buffer (alt)
2051   FLAG alt;
2052 {
2053 #ifdef CURSES
2054   if (alt) {
2055 	putescape ("[?47h");
2056   } else {
2057 	putescape ("[?47l");
2058   }
2059   flush ();
2060 #else
2061   if (alt) {
2062 	termputstr (cTI, aff1);
2063   } else {
2064 	termputstr (cTE, aff1);
2065   }
2066 #endif
2067 }
2068 
2069 #endif
2070 
2071 #ifdef CURSES
2072 
2073 /*======================================================================*\
2074 |*			Curses						*|
2075 \*======================================================================*/
2076 
2077 
2078 #define TRUE (char) 1
2079 #define FALSE (char) 0
2080 extern int curs_readchar _((void));
2081 
2082 
2083 /* colour definitions from curses.h
2084 // #define COLOR_BLACK     0
2085 // #define COLOR_RED       1
2086 // #define COLOR_GREEN     2
2087 // #define COLOR_YELLOW    3
2088 // #define COLOR_BLUE      4
2089 // #define COLOR_MAGENTA   5
2090 // #define COLOR_CYAN      6
2091 // #define COLOR_WHITE     7
2092 */
2093 /* colour pair index definitions */
2094 #define ctrlcolor 0
2095 #define menucolor 0
2096 #define diagcolor 0
2097 
2098 #define markcolor 1
2099 #define emphcolor markcolor
2100 #define menuborder markcolor
2101 #define menuheader markcolor
2102 #define scrollfgcolor 2
2103 #define specialcolor 3
2104 #define selcolor 4
2105 #define menuitem 5
2106 #define HTMLcolor 6
2107 #define HTMLcomment 7
2108 #define HTMLjsp 8
2109 #define XMLattrib 9
2110 #define XMLvalue 10
2111 #define colour8_base 11
2112 
2113 #if NCURSES_VERSION_MAJOR >= 5
2114 #define use_default_colour
2115 #endif
2116 #if NCURSES_VERSION_MAJOR == 4
2117 # if NCURSES_VERSION_MINOR >= 2
2118 #define use_default_colour
2119 # endif
2120 #endif
2121 
2122 #ifdef use_default_colour
2123 #define COLOR_fg -1
2124 #define COLOR_bg -1
2125 #else
2126 #define COLOR_fg COLOR_WHITE
2127 #define COLOR_bg COLOR_BLACK
2128 #endif
2129 
2130 static
2131 void
init_colours()2132 init_colours ()
2133 {
2134   start_color ();
2135 #ifdef use_default_colour
2136   use_default_colors ();
2137 #endif
2138   if (! has_colors ()) {
2139 	bw_term = True;
2140   }
2141 
2142 /* This produces silly warnings if compiled with gcc option -Wconversion
2143    ("passing arg ... with different width due to prototype")
2144    although all parameters are short.
2145 */
2146 #ifndef vms
2147   init_pair (markcolor, COLOR_RED, COLOR_bg);
2148   init_pair (scrollfgcolor, COLOR_CYAN, COLOR_BLUE);
2149   init_pair (specialcolor, COLOR_CYAN, COLOR_bg);
2150   init_pair (selcolor, COLOR_BLUE, COLOR_bg);
2151 
2152   init_pair (menuitem, COLOR_BLACK, COLOR_YELLOW);
2153   init_pair (HTMLcomment, COLOR_BLUE, COLOR_YELLOW);
2154   init_pair (HTMLcolor, COLOR_CYAN, COLOR_bg);
2155   init_pair (HTMLjsp, COLOR_BLUE, COLOR_bg);
2156   init_pair (XMLattrib, COLOR_RED, COLOR_bg);
2157   init_pair (XMLvalue, COLOR_MAGENTA, COLOR_bg);
2158 
2159   init_pair (colour8_base + 0, COLOR_BLACK, COLOR_bg);
2160   init_pair (colour8_base + 1, COLOR_RED, COLOR_bg);
2161   init_pair (colour8_base + 2, COLOR_GREEN, COLOR_bg);
2162   init_pair (colour8_base + 3, COLOR_YELLOW, COLOR_bg);
2163   init_pair (colour8_base + 4, COLOR_BLUE, COLOR_bg);
2164   init_pair (colour8_base + 5, COLOR_MAGENTA, COLOR_bg);
2165   init_pair (colour8_base + 6, COLOR_CYAN, COLOR_bg);
2166   init_pair (colour8_base + 7, COLOR_WHITE, COLOR_bg);
2167 #endif
2168 }
2169 
2170 
2171 void
__putchar(c)2172 __putchar (c)
2173   register character c;
2174 {
2175   addch (c);
2176 }
2177 
2178 void
putblockchar(c)2179 putblockchar (c)
2180   register character c;
2181 {
2182   if (menu_border_style == 'P' && c != 'q') {
2183 	return;
2184   } else if (menu_border_style == 'p' && c != 'q') {
2185 	putstring (" ");
2186 	return;
2187   }
2188 
2189   if (use_normalchars_boxdrawing) {
2190 	addstr (unicodeblockchar (c));
2191   } else {
2192 #ifdef vms
2193 	addstr (asciiblockchar (c));
2194 #else
2195 	switch (c) {
2196 		case 'j':	addch (ACS_LRCORNER);	break;
2197 		case 'k':	addch (ACS_URCORNER);	break;
2198 		case 'l':	addch (ACS_ULCORNER);	break;
2199 		case 'm':	addch (ACS_LLCORNER);	break;
2200 		case 'n':	addch (ACS_PLUS);	break;
2201 		case 'q':	addch (ACS_HLINE);	break;
2202 		case 't':	addch (ACS_LTEE);	break;
2203 		case 'u':	addch (ACS_RTEE);	break;
2204 		case 'v':	addch (ACS_BTEE);	break;
2205 		case 'w':	addch (ACS_TTEE);	break;
2206 		case 'x':	addch (ACS_VLINE);	break;
2207 		case 'f':
2208 		case 'g':	addch (ACS_DIAMOND);	break;
2209 		default:	addch (' ');
2210 	}
2211 #endif
2212   }
2213 }
2214 
2215 void
ring_bell()2216 ring_bell ()
2217 {
2218   beep ();
2219 }
2220 
2221 void
putstring(str)2222 putstring (str)
2223   register char * str;
2224 {
2225   addstr (str);
2226 }
2227 
2228 void
flush()2229 flush ()
2230 {
2231   refresh ();
2232 }
2233 
2234 void
clear_screen()2235 clear_screen ()
2236 {
2237   clear ();
2238 }
2239 
2240 void
clear_eol()2241 clear_eol ()
2242 {
2243   clrtoeol ();
2244 }
2245 
2246 void
erase_chars(n)2247 erase_chars (n)
2248   register int n;
2249 {
2250   while (n -- > 0) {
2251 	__putchar (' ');
2252   }
2253 }
2254 
2255 void
scroll_forward()2256 scroll_forward ()
2257 {
2258   scroll (stdscr);
2259 }
2260 
2261 void
scroll_reverse()2262 scroll_reverse ()
2263 { /* only to be called if can_add_line or cursor is at top of screen */
2264   insertln ();
2265 }
2266 
2267 void
add_line(y)2268 add_line (y)
2269   register int y;
2270 { /* only to be called if can_add_line == True */
2271   move (y + MENU, 0);
2272   insertln ();
2273 }
2274 
2275 void
delete_line(y)2276 delete_line (y)
2277   register int y;
2278 {
2279   move (y + MENU, 0);
2280   deleteln ();
2281 }
2282 
2283 void
set_cursor(x,y)2284 set_cursor (x, y)
2285   register int x;
2286   register int y;
2287 {
2288   /*current_cursor_y = y;*/
2289   move (y + MENU, x);
2290 }
2291 
2292 void
reverse_on()2293 reverse_on ()
2294 {
2295   standout ();
2296 }
2297 
2298 void
reverse_off()2299 reverse_off ()
2300 {
2301   standend ();
2302 }
2303 
2304 
2305 static
2306 void
configure_screen()2307 configure_screen ()
2308 {
2309 #ifdef __PDCURSES__
2310   keypad (stdscr, TRUE);
2311 #endif
2312 
2313 #ifdef KEY_MOUSE
2314 
2315 # ifdef __PDCURSES__
2316   (void) mouse_set (ALL_MOUSE_EVENTS);
2317 # else
2318 #  ifdef NCURSES_VERSION
2319   (void) mousemask (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED
2320 #   ifdef BUTTON_SHIFT
2321 		    | BUTTON_SHIFT
2322 #   endif
2323 #   ifdef ALL_MOUSE_EVENTS
2324 		    | ALL_MOUSE_EVENTS
2325 #   endif
2326 #   ifdef REPORT_MOUSE_POSITION
2327 		    | REPORT_MOUSE_POSITION
2328 #   endif
2329 	, /*(mmask_t)*/ (unsigned long) 0);
2330 #  endif
2331 # endif
2332 #endif
2333 
2334   init_colours ();
2335 
2336 #define use_cbreak
2337 
2338 #ifdef vms
2339   crmode ();
2340 #else
2341 # ifdef use_cbreak
2342   /* not sufficient to suppress ^S processing on Unix in pipe ?! */
2343   /* but now also VSTOP is explicitly removed */
2344   cbreak ();
2345 # else
2346   raw ();
2347 # endif
2348   nonl ();
2349 #endif
2350 
2351   meta (stdscr, TRUE);	/* should force 8-bit-cleanness but doesn't work */
2352   noecho ();
2353   scrollok (stdscr, FALSE);
2354 
2355 #if defined (unix) && ! defined (ultrix)
2356 # ifndef __EMX__
2357   idlok (stdscr, TRUE);
2358 # endif
2359 # ifndef sun
2360   typeahead (input_fd);
2361 # endif
2362 #endif
2363 }
2364 
2365 static
2366 void
start_screen_mode(kb)2367 start_screen_mode (kb)
2368   int kb;
2369 {
2370   /* for curses, see configure_screen () above */
2371 }
2372 
2373 static
2374 void
end_screen_mode()2375 end_screen_mode ()
2376 {
2377 }
2378 
2379 
2380 static
2381 void
get_term_cap(TERMname)2382 get_term_cap (TERMname)
2383   char * TERMname;
2384 {
2385 #ifdef SETLOCALE
2386   setlocale (LC_ALL, "");
2387 #endif
2388 
2389   YMAX = LINES - 1 - MENU;	/* # of lines */
2390   XMAX = COLS - 1;	/* # of columns */
2391 /*  getwinsize (); */
2392 }
2393 
2394 void
altcset_on()2395 altcset_on ()
2396 {
2397 	attron (A_ALTCHARSET);
2398 }
2399 
2400 void
altcset_off()2401 altcset_off ()
2402 {
2403 	attroff (A_ALTCHARSET);
2404 }
2405 
2406 void
disp_cursor(visible)2407 disp_cursor (visible)
2408   FLAG visible;
2409 {
2410 	if (visible) {
2411 		curs_set (1);
2412 	} else {
2413 		curs_set (0);
2414 	}
2415 }
2416 
2417 void
set_screen_mode(m)2418 set_screen_mode (m)
2419   int m;
2420 {}
2421 
2422 void
maximize_restore_screen()2423 maximize_restore_screen ()
2424 {
2425 }
2426 
2427 void
switch_textmode_height(cycle)2428 switch_textmode_height (cycle)
2429   FLAG cycle;
2430 {}
2431 
2432 void
resize_font(inc)2433 resize_font (inc)
2434   int inc;
2435 {
2436   if (mintty_version >= 503) {
2437 	if (inc > 0) {		/* increase font size */
2438 		putescape ("]7770;+1");
2439 	} else if (inc < 0) {	/* decrease font size */
2440 		putescape ("]7770;-1");
2441 	} else {		/* reset to default */
2442 		putescape ("]7770;");
2443 	}
2444   } else if (xterm_version >= 203 /* best guess */) {
2445 	if (inc > 0) {		/* increase font size */
2446 		putescape ("]50;#+1");
2447 	} else if (inc < 0) {	/* decrease font size */
2448 		putescape ("]50;#-1");
2449 	} else {		/* reset to default */
2450 		putescape ("]50;#");
2451 	}
2452   }
2453 }
2454 
2455 static
2456 void
resize_screen(l,c)2457 resize_screen (l, c)
2458   int l;
2459   int c;
2460 {
2461   static char s [22];
2462   build_string (s, "\033[8;%d;%dt", l, c);
2463   putescape (s);
2464 }
2465 
2466 static
2467 void
resize_vt(sb,keep_columns)2468 resize_vt (sb, keep_columns)
2469   FLAG sb;
2470   FLAG keep_columns;
2471 {
2472   if (keep_columns == True) {
2473 	/* change number of lines (VT420) */
2474 	int lines = YMAX + 1 + MENU;
2475 	static int vtlines [] = {24, 36, 48, 72, 144};
2476 	int i;
2477 	static char s [15];
2478 	if (sb == SMALLER) {
2479 		for (i = arrlen (vtlines) - 1; i >= 0; i --) {
2480 			if (lines > vtlines [i]) {
2481 				build_string (s, "\033[%dt", vtlines [i]);
2482 				putescape (s);
2483 				YMAX = vtlines [i] - 1 - MENU;
2484 				return;
2485 			}
2486 		}
2487 	} else {
2488 		for (i = 0; i < arrlen (vtlines); i ++) {
2489 			if (lines < vtlines [i]) {
2490 				build_string (s, "\033[%dt", vtlines [i]);
2491 				putescape (s);
2492 				YMAX = vtlines [i] - 1 - MENU;
2493 				return;
2494 			}
2495 		}
2496 	}
2497   } else {
2498 	/* switch 80/132 columns */
2499 	if (sb == SMALLER) {
2500 		putescape ("\033[?40h\033[?3l");
2501 		XMAX = 79;
2502 	} else {
2503 		putescape ("\033[?40h\033[?3h");
2504 		XMAX = 131;
2505 	}
2506   }
2507 }
2508 
2509 void
resize_the_screen(sb,keep_columns)2510 resize_the_screen (sb, keep_columns)
2511   FLAG sb;
2512   FLAG keep_columns;
2513 {
2514   if (decterm_version > 0) {
2515 	resize_vt (sb, keep_columns);
2516   } else {
2517 	int ldif = 6;
2518 	int coldif = 13;
2519 	if (sb == SMALLER) {
2520 		ldif = - ldif;
2521 		coldif = - coldif;
2522 	}
2523 	if (keep_columns == True) {
2524 		coldif = 0;
2525 	} else if (keep_columns == NOT_VALID) {
2526 		ldif = 0;
2527 	}
2528 
2529 	resize_screen (YMAX + 1 + MENU + ldif, XMAX + 1 + coldif);
2530   }
2531 }
2532 
2533 #else	/* #ifdef CURSES */
2534 
2535 
2536 /*======================================================================*\
2537 			non-curses
2538 \*======================================================================*/
2539 
2540 
2541 #ifndef msdos
2542 void
ring_bell()2543 ring_bell ()
2544 {
2545   putchar ('\07');
2546 }
2547 #endif
2548 
2549 
2550 /*======================================================================*\
2551 |*			Basic buffered screen output			*|
2552 \*======================================================================*/
2553 
2554 /* screen buffer length should be sufficient to keep one full window;
2555    not essential, though, on very large screen
2556  */
2557 #define screenbuflen	22222
2558 
2559 static char screenbuf [screenbuflen + 1];
2560 static unsigned int screenbuf_count = 0;
2561 
2562 #define dont_debug_write
2563 
2564 #ifdef debug_write
2565 static
print_buf(s,len)2566 void print_buf (s, len)
2567   char * s;
2568   int len;
2569 {
2570   while (len > 0) {
2571 	if ((* s & 0xE0) == 0) {
2572 		printf ("^%c", * s + 0x40);
2573 	} else {
2574 		printf ("%c", * s);
2575 	}
2576 	s ++;
2577 	len --;
2578   }
2579 }
2580 #endif
2581 
2582 /*
2583  * Flush the screen buffer
2584  */
2585 static
2586 int
flush_screenbuf()2587 flush_screenbuf ()
2588 {
2589   if (screenbuf_count == 0) {		/* There is nothing to flush */
2590 	return FINE;
2591   }
2592 
2593 #ifdef conio
2594   cputs (screenbuf);
2595 #else
2596 #ifdef BorlandC
2597   screenbuf [screenbuf_count] = '\0';
2598 /* don't ask me why that crazy compiler doesn't work with write () below */
2599   printf ("%s", screenbuf);
2600 #else
2601   {
2602 	char * writepoi = screenbuf;
2603 	int written = 0;
2604 	int none_count = 0;
2605 /*	int less_count = 0;	*/
2606 
2607 #ifdef debug_write
2608 	printf ("writing %d: ", screenbuf_count);
2609 	print_buf (writepoi, screenbuf_count);
2610 	printf ("\n");
2611 	if (tty_closed) {
2612 		printf ("(tty closed) - not written\n");
2613 		sleep (1);
2614 	}
2615 #endif
2616 
2617 	if (tty_closed) {
2618 		screenbuf_count = 0;
2619 		return ERRORS;
2620 	}
2621 
2622 	while (screenbuf_count > 0) {
2623 #ifdef vms_async_output
2624 		/* no noticeable speed improvement */
2625 		written = ttputs (writepoi, screenbuf_count);
2626 #else
2627 		written = write (output_fd, writepoi, screenbuf_count);
2628 #endif
2629 #ifdef debug_write
2630 		printf ("written %d (errno %d: %s)\n", written, geterrno (), serror ());
2631 #endif
2632 		if (written == -1) {
2633 			if (geterrno () == EINTR && winchg) {
2634 				/* try again */
2635 			} else {
2636 				tty_closed = True;
2637 				panicio ("Terminal write error", serror ());
2638 				screenbuf_count = 0;
2639 				return ERRORS;
2640 			}
2641 		} else if (written == 0) {
2642 			none_count ++;
2643 			if (none_count > 20) {
2644 				panicio ("Terminal write error", serror ());
2645 				screenbuf_count = 0;
2646 				return ERRORS;
2647 			}
2648 		} else {
2649 			screenbuf_count -= written;
2650 			writepoi += written;
2651 		}
2652 	}
2653   }
2654 #endif
2655 #endif
2656 
2657   screenbuf_count = 0;
2658   return FINE;
2659 }
2660 
2661 void
flush()2662 flush ()
2663 {
2664   (void) flush_screenbuf ();
2665 }
2666 
2667 /*
2668  * putoutchar does a buffered output to screen.
2669  */
2670 static
2671 int
putoutchar(c)2672 putoutchar (c)
2673   character c;
2674 {
2675   if (c == '\n') {
2676 	if (putoutchar ('\r') == ERRORS) {
2677 		return ERRORS;
2678 	}
2679   }
2680   if (translate_output) {
2681 	if ((c & '\200') != '\0') {
2682 		char clow = (c & '\177');
2683 		altcset_on ();
2684 		if ((int) clow < translen) {
2685 			putoutchar (transout [(int) clow]);
2686 		} else {
2687 			putoutchar (clow);
2688 		}
2689 		altcset_off ();
2690 		return FINE;
2691 	}
2692   }
2693   if (screen_version > 0 && screen_version < 400 && c >= 0x80 && c < 0xA0) {
2694 	/* embed C1 control characters (workaround for 'screen' bug) */
2695 	putoutchar ('\033');
2696 	putoutchar ('P');
2697 	screenbuf [screenbuf_count ++] = c;
2698 	if (screenbuf_count == screenbuflen) {
2699 		(void) flush_screenbuf ();
2700 	}
2701 	putoutchar ('\033');
2702 	putoutchar ('\\');
2703 	return FINE;
2704   }
2705   screenbuf [screenbuf_count ++] = c;
2706   if (screenbuf_count == screenbuflen) {
2707 	return flush_screenbuf ();
2708   }
2709 
2710 #define dont_debug_all_output
2711 #ifdef debug_all_output
2712   if (c == '\033') {
2713 	printf ("^[");
2714   } else {
2715 	printf ("%c", c);
2716   }
2717 #endif
2718 #ifdef debug_flush_output
2719   flush ();
2720 #endif
2721 
2722   return FINE;
2723 }
2724 
2725 /*
2726  * Putoutstring writes the given string out to the terminal.
2727  * (buffered via misused screen buffer!)
2728 putstring (str) does putoutstring (str) unless with curses or conio
2729  */
2730 static
2731 void
putoutstring(text)2732 putoutstring (text)
2733   register char * text;
2734 {
2735   while (* text != '\0') {
2736 	(void) putoutchar (* text ++);
2737   }
2738 }
2739 
2740 void
__putchar(c)2741 __putchar (c)
2742   register character c;
2743 {
2744 #ifdef conio
2745   putch (c);
2746 #else
2747   putoutchar (c);
2748 #endif
2749 }
2750 
2751 void
putstring(str)2752 putstring (str)
2753   register char * str;
2754 {
2755 #ifdef conio
2756   cputs (str);
2757 #else
2758   putoutstring (str);
2759 #endif
2760 }
2761 
2762 /**
2763    Output a menu border character. Decide which style to use,
2764    block graphics (VT100 or VGA), Unicode graphics, ASCII graphics.
2765    This and it's setup is a mess and could do with some revision.
2766  */
2767 void
putblockchar(c)2768 putblockchar (c)
2769   register character c;
2770 {
2771   if (menu_border_style == 'P' && c != 'q') {
2772 	return;
2773   } else if (menu_border_style == 'p' && c != 'q') {
2774 	putstring (" ");
2775 	return;
2776   }
2777 
2778 #ifdef conio
2779   if (use_ascii_graphics) {
2780 	putstring (asciiblockchar (c));
2781   } else {
2782 	putchar (vgablockchar (c));
2783   }
2784 #else
2785   if (use_ascii_graphics) {
2786 	putoutstring (asciiblockchar (c));
2787   } else if (use_vga_block_graphics) {
2788 	putoutchar (vgablockchar (c));
2789   } else if (use_normalchars_boxdrawing) {
2790 	putoutstring (unicodeblockchar (c));
2791   } else if (use_pc_block_graphics) {
2792 	putoutchar (vgablockchar (c));
2793   } else {
2794 # if defined (unix) || defined (vms)
2795 	putoutstring (acblockchar (c));
2796 # else
2797 	putoutstring (asciiblockchar (c));
2798 # endif
2799   }
2800 #endif
2801 }
2802 
2803 
2804 /*======================================================================*\
2805 |*			Screen control functions			*|
2806 \*======================================================================*/
2807 
2808 #if defined (unix) || defined (ANSI)
2809 
2810 void
clear_screen()2811 clear_screen ()
2812 {
2813   termputstr (cCL, affmax);
2814 }
2815 
2816 void
clear_eol()2817 clear_eol ()
2818 {
2819   if (can_clear_eol) {
2820 	termputstr (cCE, aff1);
2821   }
2822 }
2823 
2824 void
erase_chars(n)2825 erase_chars (n)
2826   register int n;
2827 {
2828 #ifdef ANSI
2829   static char s [15];
2830   build_string (s, "\033[%dX", n);
2831   termputstr (s, aff1);
2832 #else
2833   termputstr (tgoto (cEC, 0, n), aff1);
2834 #endif
2835 }
2836 
2837 void
scroll_forward()2838 scroll_forward ()
2839 {
2840   set_cursor (0, YMAX);
2841   termputstr ("\n", affmax);
2842 }
2843 
2844 void
scroll_reverse()2845 scroll_reverse ()
2846 { /* only to be called if can_add_line or cursor is at top of screen */
2847   if (can_add_line) {
2848 	add_line (0);
2849   } else {
2850 	termputstr (cSR, affmax);
2851   }
2852 }
2853 
2854 static
2855 void
scrolling_region(yb,ye)2856 scrolling_region (yb, ye)
2857   register int yb;
2858   register int ye;
2859 {
2860 #ifdef ANSI
2861   static char s [22];
2862   build_string (s, "\033[%d;%dr", yb + 1, ye + 1);
2863   termputstr (s, aff1);
2864 #else
2865   termputstr (tgoto (cCS, ye, yb), aff1);
2866 #endif
2867 }
2868 
2869 void
add_line(y)2870 add_line (y)
2871   register int y;
2872 { /* only to be called if can_add_line == True */
2873   if (cAL) {
2874 	set_cursor (0, y);
2875 	termputstr (cAL, affmax);
2876   } else {
2877 	set_cursor (0, y);
2878 	termputstr (cSC, aff1);
2879 	scrolling_region (MENU + y, MENU + YMAX);
2880 	termputstr (cRC, aff1);
2881 	termputstr (cSR, affmax);
2882 	scrolling_region (0, MENU + YMAX);
2883 	termputstr (cRC, aff1);
2884   }
2885 }
2886 
2887 void
delete_line(y)2888 delete_line (y)
2889   register int y;
2890 {
2891   if (cDL) {
2892 	set_cursor (0, y);
2893 	termputstr (cDL, affmax);
2894   } else {
2895 	set_cursor (0, y);
2896 	termputstr (cSC, aff1);
2897 	scrolling_region (MENU + y, MENU + YMAX);
2898 	set_cursor (0, YMAX);
2899 	termputstr ("\n", affmax);
2900 	scrolling_region (0, MENU + YMAX);
2901 	termputstr (cRC, aff1);
2902   }
2903 }
2904 
2905 void
set_cursor(x,y)2906 set_cursor (x, y)
2907   register int x;
2908   register int y;
2909 {
2910 #ifdef ANSI
2911   static char s [22];
2912 #endif
2913 
2914   if (screen_version > 0) {
2915 	/* flush cursor position (workaround for 'screen' bug) */
2916 #ifdef ANSI
2917 	termputstr ("\033[1;1H", aff1);
2918 #else
2919 	termputstr (tgoto (cCM, 0, 0), aff1);
2920 #endif
2921   }
2922 
2923   /*current_cursor_y = y;*/
2924 #ifdef ANSI
2925   build_string (s, "\033[%d;%dH", y + 1 + MENU, x + 1);
2926   termputstr (s, aff1);
2927 #else
2928   termputstr (tgoto (cCM, x, y + MENU), aff1);
2929 #endif
2930 }
2931 
2932 #define dont_use_standout /* might add underline, e.g. within 'screen' */
2933 
2934 void
reverse_on()2935 reverse_on ()
2936 {
2937 #ifdef use_standout
2938   termputstr (cSO, aff1);
2939 #else
2940   termputstr (cMR, aff1);
2941 #endif
2942 }
2943 
2944 void
reverse_off()2945 reverse_off ()
2946 {
2947 #ifdef use_standout
2948   termputstr (cSE, aff1);
2949 #else
2950   termputstr (cME, aff1);
2951 #endif
2952 }
2953 
2954 void
altcset_on()2955 altcset_on ()
2956 {
2957   if (use_pc_block_graphics) {
2958 	termputstr (cS2, aff1);
2959   } else {
2960 	termputstr (cAS, aff1);
2961   }
2962 }
2963 
2964 void
altcset_off()2965 altcset_off ()
2966 {
2967   if (use_pc_block_graphics) {
2968 	termputstr (cS3, aff1);
2969   } else {
2970 	termputstr (cAE, aff1);
2971   }
2972 }
2973 
2974 #endif	/* #if defined (unix) || defined (ANSI) */
2975 
2976 #if defined (unix) && ! defined (ANSI)
2977 
2978 static
2979 void
get_terminfo(TERMname)2980 get_terminfo (TERMname)
2981   char * TERMname;
2982 {
2983 	/* get screen size */
2984 	YMAX = term_getnum ("li", "lines") - 1 - MENU;	/* # of lines */
2985 	XMAX = term_getnum ("co", "cols") - 1;	/* # of columns */
2986 	getwinsize ();
2987 
2988 	/* get screen control escape sequences */
2989 	cCL = term_getstr ("cl", "clear");	/* clear screen */
2990 	cCE = term_getstr ("ce", "el");		/* clear to end of line */
2991 	cCD = term_getstr ("cd", "ed");		/* clear to end of screen */
2992 	cCM = term_getstr ("cm", "cup");	/* move cursor */
2993 
2994 	cEC = term_getstr ("ec", "ech");	/* erase characters */
2995 	cSR = term_getstr ("sr", "ri");		/* scroll down */
2996 	cAL = term_getstr ("al", "il1");	/* add line */
2997 	cDL = term_getstr ("dl", "dl1");	/* delete line */
2998 	cCS = term_getstr ("cs", "csr");	/* change scrolling region */
2999 	cSC = term_getstr ("sc", "sc");	/* save cursor    \ needed with VT100   */
3000 	cRC = term_getstr ("rc", "rc");	/* restore cursor / for add/delete line */
3001 
3002 	cME = term_getstr ("me", "sgr0");	/* turn off all attributes */
3003 	cMR = term_getstr ("mr", "rev");	/* reverse */
3004 	cMD = term_getstr ("md", "bold");	/* bold / extra bright */
3005 	cMH = term_getstr ("mh", "dim");	/* dim / half-bright */
3006 	cUL = term_getstr ("us", "smul");	/* underline */
3007 	cBL = term_getstr ("mb", "blink");	/* blink */
3008 	cSO = term_getstr ("so", "smso");	/* standout mode */
3009 	cSE = term_getstr ("se", "rmso");	/* end standout mode */
3010 
3011 	cVS = term_getstr ("vs", "cvvis");	/* visual cursor */
3012 	cVE = term_getstr ("ve", "cnorm");	/* normal cursor */
3013 	cVI = term_getstr ("vi", "civis");	/* invisible cursor */
3014 	cTI = term_getstr ("ti", "smcup");	/* positioning mode */
3015 	cTE = term_getstr ("te", "rmcup");	/* end " */
3016 	cKS = term_getstr ("ks", "smkx");	/* keypad mode */
3017 	cKE = term_getstr ("ke", "rmkx");	/* end " */
3018 	cAS = term_getstr ("as", "smacs");	/* alternate character set */
3019 	cAE = term_getstr ("ae", "rmacs");	/* end " */
3020 	cEA = term_getstr ("eA", "enacs");	/* enable " */
3021 	cAC = term_getstr ("ac", "acsc");	/* block graphics code mapping */
3022 	cS2 = term_getstr ("S2", "smpch");	/* PC character set */
3023 	cS3 = term_getstr ("S3", "rmpch");	/* end " */
3024 
3025 	cAF = term_getstr ("AF", "setaf");	/* select foreground colour */
3026 	cAB = term_getstr ("AB", "setab");	/* select background colour */
3027 	if (term_getnum ("Co", "colors") == 0 && ! cAF) {
3028 		bw_term = True;
3029 	}
3030 	standout_glitch = term_getflag ("xs", "xhp");	/* standout glitch */
3031 
3032 	/* add function key escape sequences */
3033 	add_terminfo_entries ();
3034 }
3035 
3036 #endif	/* #if defined (unix) || defined (ANSI) */
3037 
3038 
3039 #if defined (vms) || defined (ANSI)
3040 
3041 static
3042 FLAG
term_setup(TERMname)3043 term_setup (TERMname)
3044   char * TERMname;
3045 {
3046   return False;
3047 }
3048 
3049 static
3050 void
get_terminfo(TERMname)3051 get_terminfo (TERMname)
3052   char * TERMname;
3053 {
3054 }
3055 
3056 #endif
3057 
3058 
3059 #if defined (unix) || defined (ANSI) || defined (vms)
3060 
3061 void
disp_cursor(visible)3062 disp_cursor (visible)
3063   FLAG visible;
3064 {
3065 	if (visible) {
3066 		/* first turn it "normal" in case "very visible" does
3067 		   not work, then try "very visible"
3068 		 */
3069 		termputstr (cVE, affmax);
3070 		termputstr (cVS, affmax);
3071 	} else {
3072 		termputstr (cVI, affmax);
3073 	}
3074 }
3075 
3076 static
3077 void
set_term_defaults(TERMname)3078 set_term_defaults (TERMname)
3079   char * TERMname;
3080 {
3081 	/* set common ANSI sequences */
3082 	cCL = "";		/* clear screen */
3083 	cCE = "";		/* clear to end of line */
3084 	cCD = "";		/* clear to end of screen */
3085 	cCM = "[%i%p1%d;%p2%dH";	/* move cursor */
3086 	cCS = NIL_PTR;		/* change scrolling region */
3087 	cEC = NIL_PTR;		/* erase characters */
3088 	cSR = NIL_PTR;		/* scroll down */
3089 	cAL = NIL_PTR;		/* add line */
3090 	cDL = NIL_PTR;		/* delete line */
3091 	cSC = NIL_PTR;		/* save cursor position */
3092 	cRC = NIL_PTR;		/* restore cursor position */
3093 
3094 	cVS = NIL_PTR;		/* visual cursor */
3095 	cVE = NIL_PTR;		/* normal cursor */
3096 	cVI = NIL_PTR;		/* invisible cursor */
3097 	cTI = NIL_PTR;		/* positioning mode */
3098 	cTE = NIL_PTR;		/* end " */
3099 	cKS = NIL_PTR;		/* keypad mode */
3100 	cKE = NIL_PTR;		/* end " */
3101 
3102 	cME = "";		/* turn off all attributes */
3103 	cMR = "";		/* reverse */
3104 	cMD = "";		/* bold */
3105 	cMH = NIL_PTR;		/* dim */
3106 	cUL = "";		/* underline */
3107 	cBL = "";		/* blink */
3108 	cSO = "";		/* standout mode */
3109 	cSE = "";;		/* end standout */
3110 	cAF = NIL_PTR;		/* set foreground colour */
3111 	cAB = NIL_PTR;		/* set background colour */
3112 	cAS = NIL_PTR;		/* alternate character set */
3113 	cAE = NIL_PTR;		/* end " */
3114 	cEA = NIL_PTR;		/* enable " */
3115 	cAC = NIL_PTR;		/* block graphics code mapping */
3116 	cS2 = NIL_PTR;		/* PC character set */
3117 	cS3 = NIL_PTR;		/* end " */
3118 #ifdef __CYGWIN__
3119 	if (strisprefix ("interix", TERMname)) {
3120 		/* running cygwin version in interix terminal,
3121 		   cygwin console terminal emulation is applicable
3122 		 */
3123 		TERMname = "cygwin";
3124 	}
3125 #endif
3126 	if (streq (TERMname, "cygwin")) {
3127 		cEC = "[%dX";		/* erase characters */
3128 		cSR = "M";		/* scroll down */
3129 		cAL = "";		/* add line */
3130 		cDL = "";		/* delete line */
3131 		cSC = "7";		/* save cursor position */
3132 		cRC = "8";		/* restore cursor position */
3133 
3134 		cTI = "7[?47h";	/* positioning mode */
3135 		cTE = "[?47l8";	/* end " */
3136 
3137 		cSE = "";		/* end standout */
3138 		cS2 = "";		/* PC character set */
3139 		cS3 = "";		/* end " */
3140 	} else if (strisprefix ("xterm", TERMname)) {
3141 		cCS = "[%i%p1%d;%p2%dr";	/* change scrolling region */
3142 		cEC = "[%dX";		/* erase characters */
3143 		cSR = "M";		/* scroll down */
3144 		cAL = "";		/* add line */
3145 		cDL = "";		/* delete line */
3146 		cSC = "7";		/* save cursor position */
3147 		cRC = "8";		/* restore cursor position */
3148 
3149 		cVS = "[?12;25h";	/* visual cursor */
3150 		cVE = "[?12l[?25h";	/* normal cursor */
3151 		cVI = "[?25l";		/* invisible cursor */
3152 #ifdef newer_xterm_may_use
3153 		/* xterm_version >= 90, not detected yet at this time */
3154 		cTI = "[?1049h";	/* positioning mode */
3155 		cTE = "[?1049l";	/* end " */
3156 #else
3157 		cTI = "7[?47h";	/* positioning mode */
3158 		cTE = "[?47l8";	/* end " */
3159 #endif
3160 		cKS = "[?1h=";	/* keypad mode */
3161 		cKE = "[?1l>";	/* end " */
3162 
3163 		cSE = "";		/* end standout */
3164 		cAS = "(0";		/* alternate character set */
3165 		cAE = "(B";		/* end " */
3166 	} else if (strisprefix ("rxvt", TERMname)) {
3167 		cCS = "[%i%p1%d;%p2%dr";	/* change scrolling region */
3168 		cSR = "M";		/* scroll down */
3169 		cAL = "";		/* add line */
3170 		cDL = "";		/* delete line */
3171 		cSC = "7";		/* save cursor position */
3172 		cRC = "8";		/* restore cursor position */
3173 
3174 		cVE = "[?25h";		/* normal cursor */
3175 		cVI = "[?25l";		/* invisible cursor */
3176 		cTI = "7[?47h";	/* positioning mode */
3177 		cTE = "[?47l8";	/* end " */
3178 		cKS = "=";		/* keypad mode */
3179 		cKE = ">";		/* end " */
3180 
3181 		cSE = "";		/* end standout */
3182 		cAS = "";		/* alternate character set */
3183 		cAE = "";		/* end " */
3184 		cEA = "(B)0";		/* enable " */
3185 	} else if (strisprefix ("vt", TERMname)
3186 		   && ! streq ("vt52", TERMname)
3187 		   && ! strisprefix ("vt50", TERMname)
3188 		) {
3189 		cCS = "[%i%p1%d;%p2%dr";	/* change scrolling region */
3190 		cSR = "M";		/* scroll down */
3191 		cSC = "7";		/* save cursor position */
3192 		cRC = "8";		/* restore cursor position */
3193 		if (TERMname [2] > '1' || strisprefix ("vt102", TERMname)) {
3194 			cAL = "";		/* add line */
3195 			cDL = "";		/* delete line */
3196 		}
3197 
3198 		cKS = "[?1h=";	/* keypad mode */
3199 		cKE = "[?1l>";	/* end " */
3200 
3201 		cSE = "";		/* end standout */
3202 		cAS = "";		/* alternate character set */
3203 		cAE = "";		/* end " */
3204 		cEA = "(B)0";		/* enable " */
3205 	} else if (strisprefix ("linux", TERMname)) {
3206 		cCS = "[%i%p1%d;%p2%dr";	/* change scrolling region */
3207 		cEC = "[%dX";		/* erase characters */
3208 		cSR = "M";		/* scroll down */
3209 		cAL = "";		/* add line */
3210 		cDL = "";		/* delete line */
3211 		cSC = "7";		/* save cursor position */
3212 		cRC = "8";		/* restore cursor position */
3213 
3214 		cVS = "[?25h[?8c";	/* visual cursor */
3215 		cVE = "[?25h[?0c";	/* normal cursor */
3216 		cVI = "[?25l[?1c";	/* invisible cursor */
3217 
3218 		cSE = "";		/* end standout */
3219 		cS2 = "";		/* PC character set */
3220 		cS3 = "";		/* end " */
3221 	} else if (strisprefix ("screen", TERMname)) {
3222 		cCS = "[%i%p1%d;%p2%dr";	/* change scrolling region */
3223 		cSR = "M";		/* scroll down */
3224 		cAL = "";		/* add line */
3225 		cDL = "";		/* delete line */
3226 		cSC = "7";		/* save cursor position */
3227 		cRC = "8";		/* restore cursor position */
3228 
3229 		cVS = "";		/* visual cursor */
3230 		cVE = "[?25h";	/* normal cursor */
3231 		cVI = "[?25l";		/* invisible cursor */
3232 		cTI = "[?1049h";	/* positioning mode */
3233 		cTE = "[?1049l";	/* end " */
3234 		cKS = "[?1h=";	/* keypad mode */
3235 		cKE = "[?1l>";	/* end " */
3236 
3237 		cSO = "";		/* standout */
3238 		cSE = "";		/* end standout */
3239 		cAS = "";		/* alternate character set */
3240 		cAE = "";		/* end " */
3241 	} else if (strisprefix ("interix", TERMname)) {
3242 		cSR = "";		/* scroll down */
3243 		cAL = "";		/* add line */
3244 		cDL = "";		/* delete line */
3245 		cSC = "";		/* save cursor position */
3246 		cRC = "";		/* restore cursor position */
3247 
3248 		cTI = "";	/* positioning mode */
3249 		cTE = "\r";	/* end " */
3250 
3251 		cSE = "";		/* end standout */
3252 	} else {
3253 		errprintf ("Unknown terminal %s - trying minimal ANSI terminal settings\n", TERMname);
3254 #ifndef ANSI
3255 		sleep (1);
3256 #endif
3257 	}
3258 }
3259 
3260 
3261 #define dont_debug_termcap
3262 
3263 #ifdef debug_termcap
3264 /**
3265    Debug termcap control strings.
3266  */
3267 static
3268 void
print_termcapstr(s,namecap,nameinfo)3269 print_termcapstr (s, namecap, nameinfo)
3270   char * s;
3271   char * namecap;
3272   char * nameinfo;
3273 {
3274   printf ("%s (%s): ", namecap, nameinfo);
3275   if (s) {
3276     while (* s) {
3277 	if ((* s & 0xE0) == 0) {
3278 		printf ("^%c", * s + 0x40);
3279 	} else {
3280 		printf ("%c", * s);
3281 	}
3282 	s ++;
3283     }
3284   } else {
3285     printf ("(NULL)");
3286   }
3287   printf ("\n");
3288 }
3289 #endif
3290 
3291 static
3292 void
get_term_cap(TERMname)3293 get_term_cap (TERMname)
3294   char * TERMname;
3295 {
3296 #ifdef TERMCAP
3297   char term_rawbuf [2048];
3298 #endif
3299 
3300   char * check;
3301 
3302   if (! term_setup (TERMname)) {
3303 	avoid_tputs = True;
3304 	/* support some terminals even without termcap/terminfo available,
3305 	   especially for cygwin stand-alone version;
3306 	   first set minimal set of ANSI sequences
3307 	 */
3308 	YMAX = 23 - MENU;
3309 	XMAX = 79;
3310 	getwinsize ();
3311 	set_term_defaults (TERMname);
3312   } else {
3313 	get_terminfo (TERMname);
3314   }
3315 #ifdef debug_termcap
3316   print_termcapstr (cCL, "cl", "clear");	/* clear screen */
3317   print_termcapstr (cCE, "ce", "el");	/* clear to end of line */
3318   print_termcapstr (cCD, "cd", "ed");	/* clear to end of screen */
3319   print_termcapstr (cCM, "cm", "cup");	/* move cursor */
3320 
3321   print_termcapstr (cEC, "ec", "ech");	/* erase characters */
3322   print_termcapstr (cSR, "sr", "ri");	/* scroll down */
3323   print_termcapstr (cAL, "al", "il1");	/* add line */
3324   print_termcapstr (cDL, "dl", "dl1");	/* delete line */
3325   print_termcapstr (cCS, "cs", "csr");	/* change scrolling region */
3326   print_termcapstr (cSC, "sc", "sc");	/* save cursor    \ needed with VT100   */
3327   print_termcapstr (cRC, "rc", "rc");	/* restore cursor / for add/delete line */
3328 
3329   print_termcapstr (cME, "me", "sgr0");	/* turn off all attributes */
3330   print_termcapstr (cMR, "mr", "rev");	/* reverse */
3331   print_termcapstr (cMD, "md", "bold");	/* bold / extra bright */
3332   print_termcapstr (cMH, "mh", "dim");	/* dim / half-bright */
3333   print_termcapstr (cUL, "us", "smul");	/* underline */
3334   print_termcapstr (cBL, "mb", "blink");	/* blink */
3335   print_termcapstr (cSO, "so", "smso");	/* standout mode */
3336   print_termcapstr (cSE, "se", "rmso");	/* end standout mode */
3337 
3338   print_termcapstr (cVS, "vs", "cvvis");	/* visual cursor */
3339   print_termcapstr (cVE, "ve", "cnorm");	/* normal cursor */
3340   print_termcapstr (cVI, "vi", "civis");	/* invisible cursor */
3341   print_termcapstr (cTI, "ti", "smcup");	/* positioning mode */
3342   print_termcapstr (cTE, "te", "rmcup");	/* end " */
3343   print_termcapstr (cKS, "ks", "smkx");	/* keypad mode */
3344   print_termcapstr (cKE, "ke", "rmkx");	/* end " */
3345   print_termcapstr (cAS, "as", "smacs");	/* alternate character set */
3346   print_termcapstr (cAE, "ae", "rmacs");	/* end " */
3347   print_termcapstr (cEA, "eA", "enacs");	/* enable " */
3348   print_termcapstr (cAC, "ac", "acsc");	/* block graphics code mapping */
3349   print_termcapstr (cS2, "S2", "smpch");	/* PC character set */
3350   print_termcapstr (cS3, "S3", "rmpch");	/* end " */
3351 
3352   print_termcapstr (cAF, "AF", "setaf");	/* select foreground colour */
3353   print_termcapstr (cAB, "AB", "setab");	/* select background colour */
3354 #endif
3355 
3356 #ifdef TERMCAP
3357   if (term_capbufpoi > term_capbuf + term_capbuflen) {
3358 	panic ("Terminal control strings don't fit", NIL_PTR);
3359   }
3360 #endif
3361 
3362   /* derive and fix properties */
3363   if (!cSR) {
3364 	cSR = cAL;
3365   }
3366 
3367   if (cAL || (cSR && cCS)) {
3368 	can_add_line = True;
3369   } else {
3370 	can_add_line = False;
3371   }
3372   if (cSR) {
3373 	can_scroll_reverse = True;
3374   } else {
3375 	can_scroll_reverse = False;
3376   }
3377   if (cDL || cCS) {
3378 	can_delete_line = True;
3379   } else {
3380 	can_delete_line = False;
3381   }
3382   if (cCE) {
3383 	can_clear_eol = True;
3384   } else {
3385 	can_clear_eol = False;
3386   }
3387   if (cCD) {
3388 	can_clear_eos = True;
3389   } else {
3390 	can_clear_eos = False;
3391   }
3392   if (cEC) {
3393 	can_erase_chars = True;
3394   } else {
3395 	can_erase_chars = False;
3396   }
3397   if (cVI) {
3398 	can_hide_cursor = True;
3399   }
3400   if (cMH) {
3401 	can_dim = True;
3402   }
3403 
3404 #define denull(c)	if (c == NIL_PTR) c = ""
3405 
3406   denull (cSO);
3407   denull (cSE);
3408   denull (cTI);
3409   denull (cTE);
3410   denull (cVS);
3411   denull (cVE);
3412   denull (cVI);
3413   denull (cAS);
3414   denull (cAE);
3415   denull (cEA);
3416   denull (cAC);
3417   denull (cS2);
3418   denull (cS3);
3419   denull (cKS);
3420   denull (cKE);
3421   denull (cME);
3422   denull (cMR);
3423   denull (cMH);
3424   denull (cUL);
3425   denull (cBL);
3426   denull (cMD);
3427   denull (cAF);
3428   denull (cAB);
3429 
3430   /* if the terminal has no explicit "reverse" control, use standout instead */
3431   if (* cMR == '\0') {
3432 	cMR = cSO;
3433 	cME = cSE;
3434   }
3435   if (* cMR == '\0') {
3436 	can_reverse_mode = False;
3437   }
3438 
3439   /* verify minimal feature set */
3440   if (!cCL || !cCM /* || !cSO || !cSE */ ) {
3441 	panic ("Sorry, terminal features are insufficient for mined", NIL_PTR);
3442   }
3443 
3444   /* check if terminal accepts ANSI control sequence patterns */
3445   check = cME;
3446   if (* check == '\0') {
3447 	check = cSE;
3448   }
3449   if (strcontains (check, "\033[") && strchr (check, 'm') != NIL_PTR) {
3450 	ansi_esc = True;
3451   } else {
3452 	ansi_esc = False;
3453   }
3454 
3455   /* set mouse mode controls */
3456   if (! ansi_esc) {
3457 	/* disable xterm mouse escape sequences */
3458 	cMouseX10On = "";
3459 	cMouseX10Off = "";
3460 	cMouseButtonOn = "";
3461 	cMouseButtonOff = "";
3462 	cMouseEventBtnOn = "";
3463 	cMouseEventBtnOff = "";
3464 	cMouseEventAnyOn = "";
3465 	cMouseEventAnyOff = "";
3466 	cMouseExtendedOn = "";
3467 	cMouseExtendedOff = "";
3468 	cMouseFocusOn = "";
3469 	cMouseFocusOff = "";
3470 	cAmbigOn = "";
3471 	cAmbigOff = "";
3472   }
3473 
3474   if (* cAS == '\0') {
3475 	if (use_vt100_block_graphics) {
3476 		cAS = "";
3477 		cAE = "";
3478 	}
3479   }
3480   if (strcontains (TERMname, "linux") && use_vt100_block_graphics) {
3481 	cAS = "";
3482 	cAE = "";
3483   }
3484 #ifdef terminal_already_detected
3485   /* which is not the case... */
3486   if (mintty_version >= 400) {
3487 	cS2 = "";
3488 	cS3 = "";
3489   }
3490 #endif
3491   if (* cAS == '\0') {
3492 	can_alt_cset = False;
3493   }
3494   if (* cEA == '\0' && * cAS == ''
3495       && (strisprefix ("xterm", TERMname)
3496        || strisprefix ("rxvt", TERMname)
3497        || strisprefix ("konsole", TERMname)
3498        || strisprefix ("screen", TERMname)
3499      )) {
3500 	/* workaround for missing eA capability in terminfo / /etc/termcap */
3501 	cEA = "\033(B\033)0";
3502   }
3503   if (strcontains (cEA, "\033)0")) {
3504 	/* workaround for missing disable alternate charset capability */
3505 	/* restore normal G1 character set on exit */
3506 	cdisableEA = "\033)B";
3507   } else {
3508 	cdisableEA = "";
3509   }
3510   if (* cS2 != '\0' && * cS3 != '\0') {
3511 	use_pc_block_graphics = True;
3512   }
3513 
3514   if ((* cTI == '\0'
3515       || * (cTI + 1) == '@'	/* workaround for bug in Solaris terminfo */
3516       ) && strisprefix ("xterm", TERMname)
3517      ) {
3518 	cTI = "7[?47h";	/* positioning mode */
3519 	cTE = "[?47l8";	/* end " */
3520   }
3521 
3522   if (* cKS == '\0' && ansi_esc) {
3523 	/* escape sequence to enable application keypad;
3524 	   include ESC= / ESC> for terminals that don't understand
3525 	   ESC[?66;1h (e.g. linux console)
3526 	 */
3527 	if (strcontains (TERMname, "linux")) {
3528 		cKS = "\033=";
3529 		cKE = "\033>";
3530 	} else {
3531 		cKS = "\033=\033[?66;1h";
3532 		cKE = "\033>\033[?66;1l";
3533 	}
3534   }
3535 
3536   if (* cAF == '\0' && ansi_esc) {
3537 	cAF = "\033[3%dm";
3538 	cAB = "\033[4%dm";
3539   }
3540 
3541   if (* cVI == '\0' && ansi_esc) {
3542 	cVI = "\033[?25l";
3543 	if (* cVE == '\0') {
3544 		cVE = "\033[?25h";
3545 	}
3546   }
3547 }
3548 
3549 
3550 /**
3551    the two invocation modes (kb or not) and their usage are a mess
3552    (also setup_terminal is used in addition)
3553    - but never touch a running system...
3554  */
3555 static
3556 void
start_screen_mode(kb)3557 start_screen_mode (kb)
3558   int kb;
3559 {
3560   if (decterm_version > 0) {	/* setup DEC locator reports */
3561 	cMouseX10On = "";
3562 	cMouseX10Off = "";
3563 	cMouseButtonOn = "\033[1'z\033[1'{\033[3'{";
3564 	cMouseButtonOff = "\033[0'z";
3565 	cMouseEventBtnOn = "";
3566 	cMouseEventBtnOff = "";
3567 	cMouseEventAnyOn = "";
3568 	cMouseEventAnyOff = "";
3569 	cMouseExtendedOn = "";
3570 	cMouseExtendedOff = "";
3571   }
3572 
3573   if (kb) {
3574 	/* adjust control sequences */
3575 	if (! init_done) {
3576 		/* if termcap/terminfo defines combined control sequences that
3577 		   set/reset both application cursor keys and application
3578 		   keypad mode, reduce them to application cursor keys only in
3579 		   order to maintain distinguishable control-keypad-keys
3580 		 */
3581 		if (! use_appl_keypad) {
3582 			if (strncmp (cKS, "\033[?1h", 5) == 0) {
3583 				cKS = "\033[?1h";
3584 			}
3585 			if (strncmp (cKE, "\033[?1l", 5) == 0) {
3586 				cKE = "\033[?1l";
3587 			}
3588 		}
3589 		if (! use_appl_cursor) {
3590 			if (strncmp (cKS, "\033[?1h", 5) == 0) {
3591 				cKS += 5;
3592 			}
3593 			if (strncmp (cKE, "\033[?1l", 5) == 0) {
3594 				cKE += 5;
3595 			}
3596 		}
3597 	}
3598 
3599 	/* set keyboard modes */
3600 	termputstr (cKS, affmax);
3601 
3602 	if (xterm_version >= 280) {
3603 		/* enable modifyKeyboard resource */
3604 		putescape ("\033[>0;15m");
3605 		/* and then enable VT220 Keyboard with Application Keypad mode */
3606 		putescape ("\033[?1061h\033[?66h");
3607 	}
3608 
3609 	/* set mouse modes */
3610 	if (use_mouse) {
3611 #ifdef debug_mouse
3612 		printf ("starting mouse mode\n");
3613 #endif
3614 		putescape (cMouseX10On);	/* activate mouse reporting */
3615 		putescape (cMouseButtonOn);
3616 		putescape (cMouseEventBtnOn);
3617 		if (use_mouse_anymove_always) {
3618 			putescape (cMouseEventAnyOn);
3619 		}
3620 		if (use_mouse_1015) {
3621 			/* numeric encoding of mouse coordinates */
3622 			putescape (cMouse1015On);
3623 		} else if (use_mouse_extended) {
3624 			/* UTF-8 encoding of mouse coordinates */
3625 			putescape (cMouseExtendedOn);
3626 		}
3627 		putescape (cMouseFocusOn);	/* activate focus reports */
3628 		putescape (cAmbigOn);	/* activate ambiguous width change reports */
3629 	}
3630   } else {
3631 	/* set screen modes */
3632 	termputstr (cTI, affmax);
3633 	termputstr (cVS, affmax);
3634 
3635 	/* Reset scrolling region in case terminal is bigger than assumed;
3636 	   terminal misconfiguration effect was observed after
3637 	   * window size changes of Sun windows
3638 	   * remote login to VMS
3639 	   * explicit misconfiguration with stty
3640 	 */
3641 	if (cCS) {
3642 		/* YMAX as derived from tty may not yet been adjusted
3643 		   to actual terminal size (in case of inconsistence);
3644 		   checkwinsize() would have to have been called before!
3645 		   Possibly a reason to move this into the section above
3646 		   for start_screen_mode (1) but then we're getting other
3647 		   effects due to the cursor movement...
3648 		 */
3649 		/*scrolling_region (0, MENU + YMAX);*/
3650 		scrolling_region (-1, -1);
3651 	}
3652 
3653 #ifndef CURSES
3654 	/* enable alternate character set */
3655 	termputstr (cEA, aff1);
3656 #endif
3657   }
3658 }
3659 
3660 static
3661 void
end_screen_mode()3662 end_screen_mode ()
3663 {
3664   /* reset mouse modes */
3665   if (use_mouse) {
3666 	putescape (cMouseFocusOff);
3667 	putescape (cAmbigOff);
3668 	if (use_mouse_1015) {
3669 		putescape (cMouse1015Off);
3670 	} else if (use_mouse_extended) {
3671 		putescape (cMouseExtendedOff);
3672 	}
3673 	putescape (cMouseEventBtnOff);
3674 	putescape (cMouseButtonOff);
3675 	putescape (cMouseX10Off);
3676 #ifdef debug_mouse
3677 	printf ("ended mouse mode\n");
3678 #endif
3679   }
3680   /* if mouse was released quickly after, e.g., QUIT command,
3681      swallow mouse release report already sent */
3682 #ifndef vms_slow_lookahead
3683   if (char_ready_within (50, NIL_PTR)) {
3684 	(void) _readchar_nokeymap ();
3685   }
3686 #endif
3687 
3688   /* reset keyboard modes */
3689   termputstr (cKE, affmax);
3690 
3691   if (xterm_version >= 280) {
3692 	/* reset modifyKeyboard resource */
3693 	putescape ("\033[>0m");
3694 	/* and then disable VT220 Keyboard with Application Keypad mode */
3695 	putescape ("\033[?1061l\033[?66l");
3696   }
3697 
3698   /* reset screen modes */
3699   termputstr (cVE, affmax);
3700   termputstr (cTE, affmax);
3701 
3702 #ifndef CURSES
3703 /* disable alternate character set */
3704   termputstr (cdisableEA, aff1);
3705 #endif
3706 
3707   flush ();
3708 }
3709 
3710 #endif	/* defined (unix) || defined (vms) */
3711 
3712 
3713 #ifdef vms
3714 
3715 void
add_terminfo_entries()3716 add_terminfo_entries ()
3717 {
3718 }
3719 
3720 #endif
3721 
3722 
3723 #ifdef msdos
3724 
3725 #ifdef __TURBOC__
3726 #define peekbyte peekb
3727 #define peekword peek
3728 #endif
3729 #ifdef __DJGPP__
3730 #define peekbyte _farpeekb
3731 #define peekword _farpeekw
3732 #include <sys/farptr.h>
3733 #endif
3734 
3735 #ifdef conio
3736 #include <conio.h>
3737 
3738 static struct text_info scrinfo;
3739 
3740 #ifdef __TURBOC__
3741 static FLAG use_peek = NOT_VALID;	/* determine on first demand */
3742 #else
3743 static FLAG use_peek = False;	/* peek doesn't seem to work with djgpp */
3744 #endif
3745 
3746 /**
3747    Retrieve screen size from BIOS
3748 	BIOS data:
3749 	40:4A	word	video columns
3750 	can also be determined with INT10h, function 0Fh
3751 	40:84	byte	video lines - 1			(EGA/VGA required)
3752 	40:85	word	character height (pixels)	(EGA/VGA required)
3753 	can also be determined with INT10h, function 11h/30h
3754  */
3755 void
getwinsize()3756 getwinsize ()
3757 {
3758   int bioslines;
3759   int bioscols;
3760   if (use_peek == NOT_VALID) {
3761 	gettextinfo (& scrinfo);
3762 	/* check whether this is reliable (EGA or VGA only): */
3763 	bioslines = peekbyte (0x40, 0x84) + 1;
3764 	use_peek = scrinfo.screenheight == bioslines;
3765   }
3766   if (use_peek) {
3767 	bioslines = peekbyte (0x40, 0x84) + 1;
3768 	bioscols = peekword (0x40, 0x4A);
3769   } else {
3770 #ifdef __DJGPP__
3771 	/* make sure changed size is detected (e.g. using vgamax) */
3772 	gppconio_init ();
3773 #endif
3774 	gettextinfo (& scrinfo);
3775 	bioslines = scrinfo.screenheight;
3776 	bioscols = scrinfo.screenwidth;
3777   }
3778 
3779   YMAX = bioslines - 1 - MENU;
3780   XMAX = bioscols - 1;
3781 }
3782 
3783 #endif	/* #ifdef conio */
3784 
3785 static int wincheck = 1;
3786 
3787 #ifdef __TURBOC__	/* try to improve Turbo-C getch behaviour */
3788 
3789 /*
3790  * getch () reads in a character from keyboard. We seem to need our
3791  * own low-level input routine since (at least with Turbo-C) the use
3792  * of getch () from conio.h makes the runtime system switch to normal
3793  * text mode on startup so that extended text modes could not be used.
3794  * This is really a very stupid chicane of Turbo-C.
3795  */
3796 int
dosgetch()3797 dosgetch ()
3798 {
3799   union REGS regs;
3800   int result;
3801 
3802 #ifdef getchBIOS
3803   /* Don't use; for some reason, this crap doesn't work.
3804      And if it's tweaked to work, it doesn't provide keypad keys.
3805      And it doesn't even help to avoid ^S/^Q/^C/^P handling either.
3806    */
3807   static int BIOSgetch = -1;
3808   if (BIOSgetch == -1) {
3809 	struct SREGS segs;
3810 	regs.h.ah = 0xC0;
3811 	int86x (0x15, & regs, & regs, & segs);
3812 	if (regs.x.cflag == 0 && peekbyte (segs.es, regs.x.bx + 6) & 0x40) {
3813 		regs.h.ah = 9;
3814 		int86 (0x16, & regs, & regs);
3815 		if (regs.h.al & 0x40) {
3816 			BIOSgetch = 0x20;
3817 		} else if (regs.h.al & 0x20) {
3818 			BIOSgetch = 0x10;
3819 		} else {
3820 			BIOSgetch = 0x00;
3821 		}
3822 	} else {
3823 		BIOSgetch = 0x00;
3824 	}
3825   }
3826 
3827   regs.h.ah = BIOSgetch;
3828   int86 (0x16, & regs, & regs);
3829 #else
3830   regs.h.ah = 0x07;
3831   intdos (& regs, & regs);
3832 #endif
3833 
3834   result = regs.h.al;
3835 
3836   return result;
3837 }
3838 
3839 #endif /* __TURBOC__ */
3840 
3841 void
ring_bell()3842 ring_bell ()
3843 {
3844   union REGS regs;
3845 
3846   regs.h.ah = 0x0E;
3847   regs.h.al = 7;
3848   regs.h.bh = 0;
3849   regs.h.bl = 0;
3850   int86 (0x10, & regs, & regs);
3851 }
3852 
3853 void
set_video_lines(r)3854 set_video_lines (r)
3855 /* 0/1/2: 200/350/400 lines */
3856   int r;
3857 {
3858   union REGS regs;
3859 
3860   regs.h.ah = 0x12;
3861   regs.h.bl = 0x30;
3862   regs.h.al = r;
3863 
3864   int86 (0x10, & regs, & regs);
3865 }
3866 
3867 int font_height = 16;
3868 void
set_font_height(r)3869 set_font_height (r)
3870 /* set font height in character pixels, <= 32 */
3871   int r;
3872 {
3873 #ifdef __TURBOC__
3874 #define useintr
3875 #endif
3876 
3877 #ifdef useintr
3878   struct REGPACK regs;
3879 
3880   regs.r_ax = 0x1130;
3881   regs.r_bx = 0;
3882   intr (0x10, & regs);
3883   regs.r_ax = 0x1110;
3884   regs.r_bx = r << 8;
3885   regs.r_cx = 256;
3886   regs.r_dx = 0;
3887 /*
3888   regs.r_bp = 0;
3889   regs.r_es = 0;
3890 */
3891   intr (0x10, & regs);
3892 #else
3893   union REGS regs;
3894 
3895   regs.h.ah = 0x11;
3896   regs.h.al = 0x10;
3897   regs.h.bh = r;
3898   font_height = r;
3899   regs.h.bl = 0;
3900   regs.x.cx = 256;
3901   regs.x.dx = 0;
3902 /*  regs.x.bp = 0;	ignored by Turbo-C's int86 function */
3903 /*  regs.x.es = 0;	not in structure but accepted by rotten C */
3904   int86 (0x10, & regs, & regs);
3905 #endif
3906 }
3907 
3908 void
set_grafmode_height(r,l)3909 set_grafmode_height (r, l)
3910 /* 0/1/2: font height 8/14/16 ; 1/2/3/n: 14/25/43/n lines */
3911   int r;
3912   int l;
3913 {
3914   union REGS regs;
3915 
3916   regs.h.ah = 0x11;
3917   if (r == 0) {
3918 	regs.h.al = 0x23;
3919   } else if (r == 1) {
3920 	regs.h.al = 0x22;
3921   } else {
3922 	regs.h.al = 0x24;
3923   }
3924   if (l <= 0) {
3925 	regs.h.bl = 1;
3926   } else if (l <= 3) {
3927 	regs.h.bl = l;
3928   } else {
3929 	regs.h.bl = 0;
3930 	regs.h.dl = l;
3931   }
3932 
3933   int86 (0x10, & regs, & regs);
3934 }
3935 
3936 void
set_fontbank(f)3937 set_fontbank (f)
3938 /* 0..7 */
3939   int f;
3940 {
3941   union REGS regs;
3942 
3943   regs.h.ah = 0x11;
3944   regs.h.al = 0x03;
3945   regs.h.bl = (f & 3) * 5 + (f & 4) * 12;
3946 
3947   int86 (0x10, & regs, & regs);
3948 }
3949 
3950 #ifdef conio
3951 static unsigned char norm_attr;	/* default character colours */
3952 static unsigned char inverse_attr;
3953 
3954 void
clear_screen()3955 clear_screen ()
3956 {
3957   clrscr ();
3958 }
3959 
3960 void
clear_eol()3961 clear_eol ()
3962 {
3963   clreol ();
3964 }
3965 
3966 void
erase_chars(n)3967 erase_chars (n)
3968   register int n;
3969 {
3970   while (n -- > 0) {
3971 	putchar (' ');
3972   }
3973 }
3974 
3975 void
scroll_forward()3976 scroll_forward ()
3977 {
3978   set_cursor (0, YMAX);
3979   putchar ('\n');
3980 }
3981 
3982 void
scroll_reverse()3983 scroll_reverse ()
3984 { /* only to be called if can_add_line or cursor is at top of screen */
3985   insline ();
3986 }
3987 
3988 void
add_line(y)3989 add_line (y)
3990   register int y;
3991 { /* only to be called if can_add_line == True */
3992   set_cursor (0, y);
3993   insline ();
3994 }
3995 
3996 void
delete_line(y)3997 delete_line (y)
3998   register int y;
3999 {
4000   set_cursor (0, y);
4001   delline ();
4002 }
4003 
4004 void
set_cursor(x,y)4005 set_cursor (x, y)
4006 {
4007   /*current_cursor_y = y;*/
4008   gotoxy (x + 1, y + 1 + MENU);
4009 }
4010 
4011 void
reverse_on()4012 reverse_on ()
4013 {
4014   textattr (inverse_attr);
4015 /*highvideo ();*/
4016 }
4017 
4018 void
reverse_off()4019 reverse_off ()
4020 {
4021   textattr (norm_attr);
4022 /*normvideo ();*/
4023 }
4024 
4025 void
altcset_on()4026 altcset_on ()
4027 {}
4028 
4029 void
altcset_off()4030 altcset_off ()
4031 {}
4032 
4033 static
4034 void
start_screen_mode(kb)4035 start_screen_mode (kb)
4036   int kb;
4037 {}
4038 
4039 static
4040 void
end_screen_mode()4041 end_screen_mode ()
4042 {}
4043 
4044 void
menu_mouse_mode(menu)4045 menu_mouse_mode (menu)
4046   FLAG menu;
4047 {
4048   in_menu_mouse_mode = menu;
4049 }
4050 
4051 void
screen_buffer(alt)4052 screen_buffer (alt)
4053   FLAG alt;
4054 {
4055 }
4056 
4057 void
get_term(TERM)4058 get_term (TERM)
4059   char * TERM;
4060 {
4061   getwinsize ();
4062 
4063   norm_attr = scrinfo.normattr;
4064   inverse_attr = ((norm_attr & 0x0F) << 4) | (norm_attr >> 4);
4065 }
4066 
4067 #endif	/* #ifdef conio */
4068 
4069 #endif	/* #ifdef msdos */
4070 
4071 
4072 /**************************************************************************
4073  * screen mode setting functions, alternatively by MSDOS BIOS calls or
4074  * ANSI sequences
4075  */
4076 
4077 static int textmode_height = 2;
4078 
4079 #ifdef msdos
4080 
4081 void
set_screen_mode(m)4082 set_screen_mode (m)
4083   int m;
4084 {
4085   union REGS regs;
4086 
4087   if (m >= 0) {
4088 	regs.h.ah = 0x00;
4089 	regs.h.al = m;
4090 	int86 (0x10, & regs, & regs);
4091   }
4092 }
4093 
4094 void
set_textmode_height(r)4095 set_textmode_height (r)
4096 /* 0/1/2: font height 8/14/16 */
4097   int r;
4098 {
4099   union REGS regs;
4100 
4101   regs.h.ah = 0x11;
4102   regs.h.bl = 0;
4103   textmode_height = r;
4104   if (r == 0) {
4105 	regs.h.al = 0x12;
4106   } else if (r == 1) {
4107 	regs.h.al = 0x11;
4108   } else {
4109 	regs.h.al = 0x14;
4110   }
4111 
4112   int86 (0x10, & regs, & regs);
4113 }
4114 
4115 #else /* #ifdef msdos - else use ANSI driver: */
4116 
4117 int screen_mode = 3	/* just an assumption, cannot be determined */;
4118 
4119 void
set_screen_mode(m)4120 set_screen_mode (m)
4121   int m;
4122 {
4123   char resize_str [8];
4124 
4125   if (m >= 0) {
4126 	if (m != 50 && m != 43) {
4127 		screen_mode = m;
4128 	}
4129 	build_string (resize_str, "\033[=%dh", m);
4130 	putescape (resize_str);
4131   }
4132 }
4133 
4134 void
set_textmode_height(r)4135 set_textmode_height (r)
4136 /* 0/1/2: font height 8/14/16 */
4137   int r;
4138 {
4139   textmode_height = r;
4140   if (r == 0) {
4141 	set_screen_mode (50);
4142   } else if (r == 1) {
4143 	set_screen_mode (43);
4144   } else {
4145 	set_screen_mode (screen_mode);
4146   }
4147 }
4148 
4149 #endif
4150 
4151 void
switch_textmode_height(cycle)4152 switch_textmode_height (cycle)
4153 /* True: cycle through font heights 8/14/16
4154    False: switch between font heights 8/16 */
4155   FLAG cycle;
4156 {
4157   if (textmode_height >= 2) {
4158 	set_textmode_height (0);
4159   } else if (cycle) {
4160 	set_textmode_height (textmode_height + 1);
4161   } else {
4162 	set_textmode_height (2);
4163   }
4164 }
4165 
4166 
4167 #define djconiox
4168 #ifdef djconio
4169 
4170 int ltab [] = {25, 28, 35, 40, 43, 50};
4171 
4172 void
maximize_restore_screen()4173 maximize_restore_screen ()
4174 {
4175 }
4176 
4177 void
resize_font(inc)4178 resize_font (inc)
4179   int inc;
4180 {
4181 }
4182 
4183 void
resize_the_screen(sb,keep_columns)4184 resize_the_screen (sb, keep_columns)
4185   FLAG sb;
4186   FLAG keep_columns;
4187 {
4188 /*  char resize_str [8]; */
4189   int lins = YMAX + 1 + MENU;
4190   int i;
4191 
4192   if (sb == BIGGER) {
4193 	i = 0;
4194 	while (i < arrlen (ltab) && ltab [i] <= lins) {
4195 		i ++;
4196 	}
4197 	if (i == arrlen (ltab)) {
4198 		i = 0;
4199 	}
4200   } else {
4201 	i = arrlen (ltab) - 1;
4202 	while (i >= 0 && ltab [i] >= lins) {
4203 		i --;
4204 	}
4205 	if (i < 0) {
4206 		i = arrlen (ltab) - 1;
4207 	}
4208   }
4209   _set_screen_lines (ltab [i]);
4210 }
4211 
4212 #else	/* #ifdef djconio */
4213 
4214 #ifdef msdos
4215 
4216 #include "dosvideo.t"
4217 
4218 void
maximize_restore_screen()4219 maximize_restore_screen ()
4220 {
4221 }
4222 
4223 void
resize_font(inc)4224 resize_font (inc)
4225   int inc;
4226 {
4227 }
4228 
4229 void
resize_the_screen(sb,keep_columns)4230 resize_the_screen (sb, keep_columns)
4231   FLAG sb;
4232   FLAG keep_columns;
4233 {
4234   if (keep_columns && ((sb == SMALLER && textmode_height > 0)
4235 			|| (sb == BIGGER && textmode_height < 2)))
4236   {
4237 	if (sb == SMALLER) {
4238 		set_textmode_height (textmode_height - 1);
4239 	} else {
4240 		set_textmode_height (textmode_height + 1);
4241 	}
4242   }
4243   else
4244   {
4245      int newtotal = 0;
4246      int newmode = -1;
4247      int totalchars = (XMAX + 1) * (YMAX + 1 + MENU);
4248      int i = 0;
4249      while (modetab [i].mode >= 0) {
4250 	int curtotal = modetab [i].cols * modetab [i].lins;
4251 	if (((sb == SMALLER && curtotal < totalchars && curtotal > newtotal) ||
4252 	     (sb == BIGGER && curtotal > totalchars && (newtotal == 0 || curtotal < newtotal)))
4253 	    && (keep_columns == False || modetab [i].cols == XMAX + 1))
4254 	{
4255 		newtotal = curtotal;
4256 		newmode = modetab [i].mode;
4257 	}
4258 	i ++;
4259      }
4260      if (newmode >= 0) {
4261 	set_screen_mode (newmode);
4262 	if (keep_columns) {
4263 		if (sb == BIGGER) {
4264 			set_textmode_height (0);
4265 		} else {
4266 			set_textmode_height (2);
4267 		}
4268 	}
4269      }
4270   }
4271 }
4272 
4273 #else	/* #ifdef msdos */
4274 
4275 static FLAG maximised = False;
4276 
4277 void
maximize_restore_screen()4278 maximize_restore_screen ()
4279 {
4280   if (maximised) {
4281 	putescape ("\033[9;0t");
4282 	maximised = False;
4283   } else {
4284 	/*putescape ("\033[9;1t");*/
4285 	putescape ("\033[9;2t");	/* mintty: true full screen */
4286 	maximised = True;
4287   }
4288 }
4289 
4290 void
resize_font(inc)4291 resize_font (inc)
4292   int inc;
4293 {
4294   if (mintty_version >= 503) {
4295 	if (inc > 0) {		/* increase font size */
4296 		putescape ("]7770;+1");
4297 	} else if (inc < 0) {	/* decrease font size */
4298 		putescape ("]7770;-1");
4299 	} else {		/* reset to default */
4300 		putescape ("]7770;");
4301 	}
4302   } else if (xterm_version >= 203 /* best guess */) {
4303 	if (inc > 0) {		/* increase font size */
4304 		putescape ("]50;#+1");
4305 	} else if (inc < 0) {	/* decrease font size */
4306 		putescape ("]50;#-1");
4307 	} else {		/* reset to default */
4308 		putescape ("]50;#");
4309 	}
4310   }
4311 }
4312 
4313 static
4314 void
resize_screen(l,c)4315 resize_screen (l, c)
4316   int l;
4317   int c;
4318 {
4319   static char s [22];
4320   build_string (s, "\033[8;%d;%dt", l, c);
4321   putescape (s);
4322 }
4323 
4324 static
4325 void
resize_vt(sb,keep_columns)4326 resize_vt (sb, keep_columns)
4327   FLAG sb;
4328   FLAG keep_columns;
4329 {
4330   if (keep_columns == True) {
4331 	/* change number of lines (VT420) */
4332 	int lines = YMAX + 1 + MENU;
4333 	static int vtlines [] = {24, 36, 48, 72, 144};
4334 	int i;
4335 	static char s [15];
4336 	if (sb == SMALLER) {
4337 		for (i = arrlen (vtlines) - 1; i >= 0; i --) {
4338 			if (lines > vtlines [i]) {
4339 				build_string (s, "\033[%dt", vtlines [i]);
4340 				putescape (s);
4341 				YMAX = vtlines [i] - 1 - MENU;
4342 				return;
4343 			}
4344 		}
4345 	} else {
4346 		for (i = 0; i < arrlen (vtlines); i ++) {
4347 			if (lines < vtlines [i]) {
4348 				build_string (s, "\033[%dt", vtlines [i]);
4349 				putescape (s);
4350 				YMAX = vtlines [i] - 1 - MENU;
4351 				return;
4352 			}
4353 		}
4354 	}
4355   } else {
4356 	/* switch 80/132 columns */
4357 	if (sb == SMALLER) {
4358 		putescape ("\033[?40h\033[?3l");
4359 		XMAX = 79;
4360 	} else {
4361 		putescape ("\033[?40h\033[?3h");
4362 		XMAX = 131;
4363 	}
4364   }
4365 }
4366 
4367 void
resize_the_screen(sb,keep_columns)4368 resize_the_screen (sb, keep_columns)
4369   FLAG sb;
4370   FLAG keep_columns;
4371 {
4372   if (decterm_version > 0) {
4373 	resize_vt (sb, keep_columns);
4374   } else {
4375 	int ldif = 6;
4376 	int coldif = 13;
4377 	if (sb == SMALLER) {
4378 		ldif = - ldif;
4379 		coldif = - coldif;
4380 	}
4381 	if (keep_columns == True) {
4382 		coldif = 0;
4383 	} else if (keep_columns == NOT_VALID) {
4384 		ldif = 0;
4385 	}
4386 
4387 	resize_screen (YMAX + 1 + MENU + ldif, XMAX + 1 + coldif);
4388   }
4389 }
4390 
4391 #endif
4392 
4393 #endif	/* #else djconio */
4394 
4395 
4396 #endif	/* #else CURSES */
4397 
4398 
4399 /*======================================================================*\
4400 |*			OS special					*|
4401 \*======================================================================*/
4402 
4403 #ifdef msdos
4404 
4405 unsigned int
get_codepage()4406 get_codepage ()
4407 {
4408   union REGS regs;
4409 
4410 #ifndef __TURBOC__
4411   __dpmi_regs mregs;
4412   short parblock [2];
4413 
4414   mregs.x.ax = 0x440C;
4415   mregs.x.bx = 1;	/* device handle */
4416   mregs.x.cx = 0x036A;	/* 3: CON, 0x6A: query selected code page */
4417   mregs.x.ds = __tb >> 4;
4418   mregs.x.dx = __tb & 0x0F;
4419   mregs.x.flags |= 1;	/* preset to detect unimplemented call */
4420   __dpmi_int (0x21, & mregs);
4421   if ((mregs.x.flags & 1) == 0) {
4422 	dosmemget (__tb, 4, parblock);
4423 	return parblock [1];
4424   }
4425 #endif
4426 
4427   /* 2F/AD02 -> BX=codepage
4428 	works with NLSFUNC driver, otherwise returns BX=FFFF, CY set
4429   */
4430   regs.x.ax = 0xAD02;
4431   regs.x.cflag = 1;	/* preset to detect unimplemented call */
4432   regs.x.bx = 0;	/* preset to detect unset result register */
4433   int86 (0x2F, & regs, & regs);
4434   if (regs.x.cflag == 0 && regs.x.bx > 1) {
4435 	return regs.x.bx;
4436   }
4437 
4438   regs.x.ax = 0x6601;
4439   regs.x.cflag = 1;	/* preset to detect unimplemented call */
4440   regs.x.bx = 0;	/* preset to detect unset result register */
4441   int86 (0x21, & regs, & regs);
4442   if (regs.x.cflag == 0) {
4443 	return regs.x.bx;
4444   }
4445 
4446   return 0;
4447 }
4448 
4449 #endif
4450 
4451 
4452 /*======================================================================*\
4453 |*			OS input					*|
4454 \*======================================================================*/
4455 
4456 #define dont_debug_select
4457 
4458 
4459 /*
4460  * Read a character from the operating system and handle interrupts.
4461  * Concerning problems due to the interference of read operations and
4462  * incoming signals (QUIT, WINCH) see the comments at readchar ().
4463  */
4464 
4465 #ifdef cygwin_hup_hang_fix
4466 
4467 static
4468 void
catch_alarm(signum)4469 catch_alarm (signum)
4470   int signum;
4471 {
4472 }
4473 
4474 /**
4475    Call this before select () to rescue it from hanging...
4476    Update: with current cygwin (1.7.15) there doesn't seem to be a need
4477    to care about hanging select after terminated terminal anymore...
4478  */
4479 static
4480 void
ialarm(msec)4481 ialarm (msec)
4482   int msec;
4483 {
4484 	struct itimerval timeout;
4485 	timeout.it_value.tv_sec = msec / 1000;
4486 	timeout.it_value.tv_usec = (msec % 1000) * 1000;
4487 	timeout.it_interval.tv_sec = 0;
4488 	timeout.it_interval.tv_usec = 0;
4489 
4490 	signal (SIGALRM, catch_alarm);
4491 	setitimer (ITIMER_REAL, & timeout, (struct itimerval *) 0);
4492 }
4493 
4494 #endif
4495 
4496 
4497 #ifdef TERMIO
4498 #define buffered_TERMIO
4499 #endif
4500 #ifdef _getch_
4501 #undef buffered_TERMIO
4502 #endif
4503 #undef buffered_TERMIO	/* works, but doesn't improve terminal pasting */
4504 
4505 #ifdef buffered_TERMIO
4506 #define cbuflen 22
4507 static char cbuf [cbuflen];
4508 static int cbufi = 0;
4509 static int cbufn = 0;
4510 #endif
4511 
4512 /*
4513  * Is a character available within msec milliseconds from file handle?
4514  */
4515 int
inputreadyafter(msec)4516 inputreadyafter (msec)
4517   int msec;
4518 {
4519 #ifdef buffered_TERMIO
4520   if (cbufi < cbufn) {
4521 	return 1;
4522   }
4523 #endif
4524 
4525   if (tty_closed) {
4526 #ifdef debug_select
4527 	printf ("(tty closed) select -> 0\n");
4528 #endif
4529 	return 0;
4530   } else {
4531 
4532 #ifdef selectpeek
4533 
4534 #ifdef FD_SET
4535 	fd_set readfds;	/* causes mined not to work in pipe mode */
4536 #else
4537 	int readfds;	/* gives compiler warnings on System V without casting */
4538 #endif
4539 
4540 	struct timeval timeoutstru;
4541 	register int nfds;
4542 
4543 	timeoutstru.tv_sec = msec / 1000;
4544 	timeoutstru.tv_usec = (msec % 1000) * 1000;
4545 
4546 #ifdef FD_SET
4547 	FD_ZERO (& readfds);
4548 	FD_SET (input_fd, & readfds);
4549 #else
4550 	readfds = 1 << input_fd;
4551 #endif
4552 
4553 #ifdef debug_select
4554 	printf ("inputreadyafter %d: select %04lX\n", msec, readfds);
4555 #endif
4556 
4557 	if (msec < 0) {
4558 		nfds = select (input_fd + 1, & readfds, 0, 0, 0);
4559 	} else {
4560 		nfds = select (input_fd + 1, & readfds, 0, 0, & timeoutstru);
4561 	}
4562 
4563 #ifdef debug_select
4564 	printf ("  ... -> #=%d\n", nfds);
4565 #endif
4566 
4567 	return nfds;
4568 
4569 #else	/* #ifdef selectpeek */
4570 
4571 #ifdef CURSES
4572 	int key;
4573 	int timerms = 0;
4574 	#define timestep 10
4575 
4576 	nodelay (stdscr, TRUE);
4577 	while (timerms < msec && (key = curs_readchar ()) == ERR) {
4578 		napms (timestep);
4579 		timerms += timestep;
4580 	}
4581 	nodelay (stdscr, FALSE);
4582 	if (key == ERR) {
4583 		return 0;
4584 	} else {
4585 		ungetch (key);
4586 		return 1;
4587 	}
4588 #else
4589 #ifdef msdos
4590 	if (mousegetch (msec) == -1) {
4591 		return 0;
4592 	} else {
4593 		return 1;
4594 	}
4595 #else
4596 #ifdef vms
4597 	return tthaschar (msec);
4598 #else
4599 	if (msec < 500
4600 	 && msec > 30	/* or flush_keyboard would block */
4601 	) {
4602 		return 1;
4603 	} else {
4604 		return 0;
4605 	}
4606 #endif
4607 #endif
4608 #endif
4609 
4610 #endif	/* #else selectpeek */
4611   }
4612 }
4613 
4614 
4615 /*
4616  * Read a char from operating system, handle interrupts if possible,
4617  * handle window size changes if possible.
4618  */
4619 
4620 #define dont_debug__readchar
4621 
4622 #ifdef debug__readchar
4623 #define trace__readchar(params)	printf params
4624 #else
4625 #define trace__readchar(params)
4626 #endif
4627 
4628 #ifdef selectread
4629 
4630 static
4631 int
strange(err)4632 strange (err)
4633   char * err;
4634 {
4635   ring_bell ();
4636   error2 ("Interrupted while reading from terminal: ", err);
4637   sleep (1);
4638   ring_bell ();
4639   return quit_char;
4640 }
4641 
4642 static
4643 int
__readchar_reporting_winchg(report_winchg)4644 __readchar_reporting_winchg (report_winchg)
4645   FLAG report_winchg;
4646 {
4647 #ifdef FD_SET
4648   fd_set readfds;
4649   fd_set exceptfds;
4650 #else
4651   int readfds;
4652   int exceptfds;	/* comments see above */
4653 #endif
4654 
4655   int selret;
4656 
4657 #ifndef _getch_
4658   character c;
4659   register int n;
4660 #endif
4661 
4662 #ifdef buffered_TERMIO
4663   if (cbufi < cbufn) {
4664 	return cbuf [cbufi ++];
4665   }
4666 #endif
4667 
4668   if (tty_closed) {
4669 	trace__readchar (("(tty closed) read -> quit\n"));
4670 	quit = True;
4671 	return quit_char;
4672   }
4673 
4674 select_getch:
4675 
4676   trace__readchar (("-> __readchar\n"));
4677   do {
4678 	trace__readchar (("__readchar do\n"));
4679 	if (winchg) {
4680 		trace_winchg (("__readchar -> winchg -> RDwin\n"));
4681 
4682 		if (isscreenmode && continued) {
4683 			continued = False;
4684 			/* recover from SIGSTOP */
4685 			raw_mode (False);
4686 			raw_mode (True);
4687 		}
4688 
4689 		trace__readchar (("< RDwin\n"));
4690 		RDwinchg ();
4691 		trace__readchar (("> RDwin\n"));
4692 	}
4693 
4694 /* the following would be obsolete with ISIG (termios)
4695    which is, however, not used anymore as it also suppresses ^\ interrupt;
4696    on the other hand, it is obsolete with setting VINTR to NDEF as well
4697  */
4698 #ifdef __CYGWIN__
4699 #define control_C_unsure
4700 #endif
4701 #ifdef CURSES
4702 #define control_C_unsure
4703 #endif
4704 
4705 #ifdef control_C_unsure
4706 	if (intr_char) {
4707 		intr_char = False;
4708 		return '\003';
4709 	}
4710 #endif
4711 
4712 #ifdef FD_SET
4713 	FD_ZERO (& readfds);
4714 	FD_SET (input_fd, & readfds);
4715 	FD_ZERO (& exceptfds);
4716 	FD_SET (input_fd, & exceptfds);
4717 #else
4718 	readfds = 1 << input_fd;
4719 	exceptfds = readfds;
4720 #endif
4721 
4722 	selret = select (input_fd + 1, & readfds, 0, & exceptfds, 0);
4723 	trace__readchar (("select -> %d [%X %X] (errno %d: %s)\n", selret, readfds, exceptfds, geterrno (), serror ()));
4724 
4725 #ifdef FD_SET
4726 	if (selret > 0 && FD_ISSET (input_fd, & readfds)) {
4727 #else
4728 	if (selret > 0 && readfds != 0) {
4729 #endif
4730 #ifdef _getch_
4731 	   return getch ();
4732 #else	/* #ifdef _getch_ */
4733 #ifdef buffered_TERMIO
4734 	   cbufn = read (input_fd, & cbuf, cbuflen);
4735 	   if (cbufn > 0) {
4736 		n = 1;
4737 		c = cbuf [0];
4738 		cbufi = 1;
4739 	   } else {
4740 		n = cbufn;
4741 	   }
4742 #else
4743 	   n = read (input_fd, & c, 1);
4744 #endif
4745 	   if (n == 1) {
4746 		trace__readchar (("read: %02X\n", c));
4747 		return c;
4748 	   } else if ((n == 0) || (geterrno () != EINTR)) {
4749 		trace__readchar (("read -> %d (errno %d: %s)\n", n, geterrno (), serror ()));
4750 		tty_closed = True;
4751 		panicio ("Terminal read error", serror ());
4752 	   } else {
4753 		trace__readchar (("read -> strange\n"));
4754 		return strange (serror ());
4755 	   }
4756 #endif	/* #else _getch_ */
4757 	} else {
4758 	   if (quit) {
4759 		trace__readchar (("select -> quit\n"));
4760 		return quit_char;
4761 
4762 	   } else if (winchg) {
4763 		trace_winchg (("select -> winchg\n"));
4764 		trace__readchar (("select -> winchg\n"));
4765 		if (report_winchg) {
4766 			trace_winchg (("-> return RDwin\n"));
4767 			/* raise WINCH exception */
4768 			keyproc = RDwin;
4769 			return (int) FUNcmd;
4770 		}
4771 
4772 	   } else if (intr_char) {
4773 		trace__readchar (("select -> intr_char\n"));
4774 		intr_char = False;
4775 		return '\003';
4776 
4777 	   } else if (hup) {
4778 		trace__readchar (("select -> hup -> repeat\n"));
4779 		hup = False;
4780 		goto select_getch;
4781 
4782 	   } else {
4783 		trace__readchar (("select -> strange\n"));
4784 		return strange ("exception");
4785 	   }
4786 	}
4787   } while (1);
4788 /* NOTREACHED */
4789 }
4790 
4791 #else	/* #ifdef selectread */
4792 
4793 static
4794 int
__readchar_reporting_winchg(report_winchg)4795 __readchar_reporting_winchg (report_winchg)
4796   FLAG report_winchg;
4797 {
4798 #ifdef _getch_
4799 
4800   int c;
4801 
4802   if (tty_closed) {
4803 	trace__readchar (("(tty closed) read -> quit\n"));
4804 	quit = True;
4805 	return quit_char;
4806   }
4807 
4808 #ifdef dosmouse
4809   c = mousegetch (-1);	/* no timeout */
4810   {
4811 	union REGS regs;
4812 	regs.h.ah = 2;
4813 	int86 (0x16, & regs, & regs);
4814 	if (c == FUNcmd) {
4815 		if (regs.h.al & 0x3) {
4816 			mouse_shift |= shift_button;
4817 		}
4818 		if (regs.h.al & 0x4) {
4819 			mouse_shift |= control_button;
4820 		}
4821 		if (regs.h.al & 0x8) {
4822 			mouse_shift |= alt_button;
4823 		}
4824 	} else {
4825 		if (regs.h.al & 0x3) {
4826 			keyshift |= shift_mask;
4827 		}
4828 		if (regs.h.al & 0x4) {
4829 			if (c == 0 || c >= ' ') {
4830 				keyshift |= ctrl_mask;
4831 			}
4832 			/* else: don't add another ctrl flag to ctrl keys */
4833 		}
4834 		if (regs.h.al & 0x8) {
4835 			keyshift |= alt_mask;
4836 		}
4837 	}
4838   }
4839 #else
4840   c = getch ();
4841 #endif
4842 
4843 #ifdef conio
4844   if (wincheck) {
4845 	int oldymax = YMAX;
4846 	int oldxmax = XMAX;
4847 	getwinsize ();
4848 	if (YMAX != oldymax || XMAX != oldxmax) {
4849 		winchg = True;
4850 		interrupted = True;
4851 		trace_winchg (("getch -> winchg\n"));
4852 		/* in MSDOS, RDwin calls getch,
4853 		   so it cannot be called directly here */
4854 	}
4855   }
4856 #endif
4857 
4858   if (intr_char) {
4859 	/* turn SIGINT signal into intr character */
4860 	/* Note: doesn't seem to be necessary */
4861 	intr_char = False;
4862 	c = '\003';
4863   }
4864 
4865 #else	/* #ifdef _getch_ */
4866 
4867 #ifdef vms
4868   int ret;
4869 #endif
4870   character c;
4871 
4872   if (tty_closed) {
4873 	trace__readchar (("(tty closed) read -> quit\n"));
4874 	quit = True;
4875 	return quit_char;
4876   }
4877 
4878 #ifdef vms
4879 
4880   ret = ttgetchar ();
4881   if (ret == VMS$ERROR) {
4882 	tty_closed = True;
4883 	panicio ("Terminal read error", serror ());
4884   }
4885   c = ret;
4886 
4887 #else
4888 
4889 #ifdef debug_select
4890   printf ("__readchar_reporting_winchg ...\n");
4891 #endif
4892 
4893 read_getch:
4894 
4895   if (read (input_fd, & c, 1) != 1 && quit == False) {
4896 #ifdef debug_select
4897 	printf ("  ... != 1\n");
4898 #endif
4899 
4900 	if (geterrno () == EINTR || geterrno () == EAGAIN) {
4901 	  if (winchg) {
4902 	    if (report_winchg) {
4903 		trace_winchg (("__readchar_reporting_winchg -> winchg\n"));
4904 		/* raise WINCH exception */
4905 		keyproc = RDwin;
4906 		return (int) FUNcmd;
4907 	    } else {	/* handle WINCH */
4908 		trace_winchg (("__readchar -> winchg -> RDwin\n"));
4909 
4910 		if (isscreenmode && continued) {
4911 			continued = False;
4912 			/* recover from SIGSTOP */
4913 			raw_mode (False);
4914 			raw_mode (True);
4915 		}
4916 
4917 		trace__readchar (("< RDwin\n"));
4918 		RDwinchg ();
4919 		trace__readchar (("> RDwin\n"));
4920 
4921 		goto read_getch;
4922 	    }
4923 	  } else {
4924 		goto read_getch;
4925 	  }
4926 	} else {
4927 		tty_closed = True;
4928 		panicio ("Terminal read error", serror ());
4929 	}
4930   }
4931 #ifdef debug_select
4932   printf ("  ... OK\n");
4933 #endif
4934 
4935 #endif	/* #else vms */
4936 
4937 #endif	/* #else _getch_ */
4938 
4939   if (quit) {
4940 	/* turn SIGQUIT or SIGBREAK signals into quit character */
4941 	/* Note: doesn't seem to work */
4942 	c = quit_char;
4943   }
4944 
4945   return c;
4946 }
4947 
4948 #endif	/* #else selectread */
4949 
4950 #define dont_debug___readchar
4951 
4952 static
4953 int
__readchar_reporting_winchg_trace(reporting_winchg)4954 __readchar_reporting_winchg_trace (reporting_winchg)
4955   FLAG reporting_winchg;
4956 {
4957   int ch = __readchar_reporting_winchg (reporting_winchg);
4958 #ifdef debug_qio
4959   char log [2];
4960   log [0] = ch;
4961   log [1] = 0;
4962   debuglog ("__readchar", log, "");
4963 #endif
4964 #ifdef debug___readchar
4965   if ((char) ch >= ' ')
4966 	printf ("__readchar %02X '%c'\n", ch, ch);
4967   else
4968 	printf ("__readchar %02X\n", ch);
4969 #endif
4970 
4971   return ch;
4972 }
4973 
4974 int
__readchar()4975 __readchar ()
4976 {
4977   return __readchar_reporting_winchg_trace (False);
4978 }
4979 
4980 int
__readchar_report_winchg()4981 __readchar_report_winchg ()
4982 {
4983   return __readchar_reporting_winchg_trace (True);
4984 }
4985 
4986 
4987 /*======================================================================*\
4988 |*			Enquire terminal properties			*|
4989 \*======================================================================*/
4990 
4991 #ifdef vms
4992 
4993 void
get_term(TERM)4994 get_term (TERM)
4995   char * TERM;
4996 {
4997   ttopen ();
4998   get_term_cap ("vt100");
4999 }
5000 
5001 void
getwinsize()5002 getwinsize ()
5003 {
5004   YMAX = ttrows - 1 - MENU;	/* # of lines */
5005   XMAX = ttcols - 1;	/* # of columns */
5006 }
5007 
5008 #else
5009 
5010 #if defined (unix) || defined (ANSI)
5011 
5012 /*
5013  * Get current window size
5014    If this does not work (e.g. on SCO Caldera Linux, or VMS (remote login),
5015    or likely whenever a real terminal is connected),
5016    the issue will be caught and handled by checkwinsize() by querying the terminal.
5017  */
5018 void
getwinsize()5019 getwinsize ()
5020 {
5021 #ifdef TIOCGWINSZ
5022   struct winsize winsiz;
5023   static int get_winsz = 1; /* check only once; on SunOS there was a
5024 				bug that after initial result values 0 0
5025 				(size not known to SunOS), further calls
5026 				would return erratic random values.
5027 			    */
5028 
5029   if (get_winsz) {
5030 	(void) ioctl (output_fd, TIOCGWINSZ, & winsiz);
5031 	if (winsiz.ws_row != 0) {
5032 		YMAX = winsiz.ws_row - 1 - MENU;
5033 	}
5034 	if (winsiz.ws_col != 0) {
5035 		XMAX = winsiz.ws_col - 1;
5036 	} else {
5037 		get_winsz = 0;
5038 	}
5039   }
5040 #else
5041 #ifdef TIOCGSIZE
5042   struct ttysize ttysiz;
5043 
5044   (void) ioctl (output_fd, TIOCGSIZE, & ttysiz);
5045   if (ttysiz.ts_lines != 0) {
5046 	YMAX = ttysiz.ts_lines - 1 - MENU;
5047   }
5048   if (ttysiz.ts_cols != 0) {
5049 	XMAX = ttysiz.ts_cols - 1;
5050   }
5051 #else
5052 #ifdef WIOCGETD
5053   struct uwdata uwdat;
5054 
5055   (void) ioctl (output_fd, WIOCGETD, & uwdat);
5056   if (uwdat.uw_height > 0) {
5057 	YMAX = uwdat.uw_height / uwdat.uw_vs - 1 - MENU;
5058   }
5059   if (uwdat.uw_width > 0) {
5060 	XMAX = uwdat.uw_width / uwdat.uw_hs - 1;
5061   }
5062 #else
5063 #warning  system does not support terminal size retrieval (but terminal is queried) 
5064   /* leave previous size assumption */
5065   return;
5066 #endif
5067 #endif
5068 #endif
5069 
5070 #ifdef CURSES
5071 # if defined (__PDCURSES__) || defined (NCURSES_VERSION)
5072   if (init_done) {
5073 	resize_term (YMAX + 1 + MENU, XMAX + 1);
5074   }
5075 # endif
5076 #endif
5077 
5078   trace_winchg (("getwinsize: %d * %d\n", XMAX + 1, YMAX + 1 + MENU));
5079 }
5080 
5081 /*
5082  * Get terminal information
5083  */
5084 void
get_term(TERMname)5085 get_term (TERMname)
5086   char * TERMname;
5087 {
5088   if (TERMname == NIL_PTR) {
5089 #ifdef __EMX__
5090 	TERMname = "ansi";
5091 #else
5092 	panic ("Terminal not specified", NIL_PTR);
5093 #endif
5094   }
5095 
5096   get_term_cap (TERMname);
5097   if (strisprefix ("xterm", TERMname)) {
5098 	title_string_pattern = "\033]2;%s\007\033]1;%s\007";
5099   } else if (strisprefix ("rxvt", TERMname)) {
5100 	title_string_pattern = "\033]2;%s\007\033]1;%s\007";
5101 #ifndef CURSES
5102   } else if (streq (TERMname, "cygwin")) {
5103 	title_string_pattern = "\033]2;%s\007\033]1;%s\007";
5104 	if (explicit_border_style) {
5105 		use_vga_block_graphics = False;
5106 	} else {
5107 		use_vt100_block_graphics = False;
5108 		use_pc_block_graphics = True;
5109 	}
5110 #endif
5111 #ifndef __MINGW32__
5112   } else if (strncmp (TERMname, "sun", 3) == 0 && ! streq (ttyname (output_fd), "/dev/console")) {
5113 	title_string_pattern = "\033]l%s\033\\\033]L%s\033\\";
5114 #endif
5115   } else if (strisprefix ("aixterm", TERMname)) {
5116 	title_string_pattern = "\033]2;%s\007\033]1;%s\007";
5117   } else if (strisprefix ("dtterm", TERMname)) {
5118 	title_string_pattern = "\033]2;%s\007\033]1;%s\007";
5119   } else if (strisprefix ("iris-", TERMname)) {
5120 	title_string_pattern = "\033P1.y%s\033\\\033P3.y%s\033\\";
5121   } else if (strisprefix ("hpterm", TERMname)) {
5122 	title_string_pattern = "\033&f0k%dD%s\033&f-1k%dD%s";
5123   } else {
5124 	title_string_pattern = "";
5125   }
5126 
5127   if (! ansi_esc) {
5128 	use_mouse_button_event_tracking = False;
5129   }
5130 
5131 /*
5132   build_string (text_buffer, "Terminal is %s, %d * %d.\n", TERMname, YMAX+1, XMAX+1);
5133   putstring (text_buffer);
5134 */
5135 }
5136 
5137 #endif	/* #ifdef unix || ANSI */
5138 
5139 #endif	/* #else vms */
5140 
5141 
5142 /*======================================================================*\
5143 |*			Screen attribute control			*|
5144 \*======================================================================*/
5145 
5146 #define dont_debug_disp_colour
5147 
5148 static
5149 int
rgb(col,for_256_colours)5150 rgb (col, for_256_colours)
5151   int col;
5152   FLAG for_256_colours;
5153 {
5154 	if (col < 16) {
5155 		if (col >= 8) {
5156 			col -= 8;
5157 		}
5158 		switch (col) {
5159 		case 0:	/* black */
5160 			return 0x000000;
5161 		case 1:	/* red */
5162 			return 0xFF0000;
5163 		case 2:	/* green */
5164 			return 0x00FF00;
5165 		case 3:	/* yellow */
5166 			return 0xFFFF00;
5167 		case 4:	/* blue */
5168 			return 0x0000FF;
5169 		case 5:	/* magenta */
5170 			return 0xFF00FF;
5171 		case 6:	/* cyan */
5172 			return 0x00FFFF;
5173 		case 7:	/* white */
5174 			return 0xFFFFFF;
5175 		default:	return 0;
5176 		}
5177 	} else if (for_256_colours || col >= 88) {
5178 		/* 256 colours: 16 VGA + 6×6×6 colour cube + 24 gray shades */
5179 		if (col >= 232) {
5180 			int gray = (col - 231) * 256 / 25;
5181 			return gray << 16 | gray << 8 | gray;
5182 		} else {
5183 			int r, g, b;
5184 			col -= 16;	/* clear VGA offset */
5185 			r = col / 36;
5186 			g = (col % 36) / 6;
5187 			b = col % 6;
5188 			r *= 0x33;
5189 			g *= 0x33;
5190 			b *= 0x33;
5191 			return r << 16 | g << 8 | b;
5192 		}
5193 	} else {
5194 		/* 88 colours: 16 VGA + 4×4×4 colour cube + 8 gray shades */
5195 		if (col >= 80) {
5196 			int gray = (col - 79) * 256 / 9;
5197 			return gray << 16 | gray << 8 | gray;
5198 		} else {
5199 			int r, g, b;
5200 			col -= 16;	/* clear VGA offset */
5201 			r = col / 16;
5202 			g = (col % 16) / 4;
5203 			b = col % 4;
5204 			r *= 0x55;
5205 			g *= 0x55;
5206 			b *= 0x55;
5207 			return r << 16 | g << 8 | b;
5208 		}
5209 	}
5210 }
5211 
5212 static
5213 int
R(rgb0)5214 R (rgb0)
5215   int rgb0;
5216 {
5217 	return rgb0 >> 16;
5218 }
5219 
5220 static
5221 int
G(rgb0)5222 G (rgb0)
5223   int rgb0;
5224 {
5225 	return (rgb0 >> 8) & 0xFF;
5226 }
5227 
5228 static
5229 int
B(rgb0)5230 B (rgb0)
5231   int rgb0;
5232 {
5233 	return rgb0 & 0xFF;
5234 }
5235 
5236 static
5237 unsigned int
dist(rgb1,rgb2)5238 dist (rgb1, rgb2)
5239   int rgb1, rgb2;
5240 {
5241 	int dr = R (rgb1) - R (rgb2);
5242 	int dg = G (rgb1) - G (rgb2);
5243 	int db = B (rgb1) - B (rgb2);
5244 	return dr * dr + dg * dg + db * db;
5245 }
5246 
5247 static
5248 int
map8(col,for_256_colours)5249 map8 (col, for_256_colours)
5250   int col;
5251   FLAG for_256_colours;
5252 {
5253 	unsigned int d = (unsigned int) -1;	/* max unsigned int */
5254 	int i;
5255 	int rgb_col = rgb (col, for_256_colours);
5256 	int repl_col = -1;
5257 
5258 	if (col >= 244) {
5259 		return 7;
5260 	} else if (col >= 232) {
5261 		return 0;
5262 	}
5263 	for (i = 0; i < 8; i ++) {
5264 		unsigned int dist_col = dist (rgb (i, for_256_colours), rgb_col);
5265 		if (dist_col < d) {
5266 			d = dist_col;
5267 			repl_col = i;
5268 		}
5269 #ifdef debug_disp_colour
5270 		printf (" %06X %06X dist %d col %d\n", rgb_col, rgb (i, for_256_colours), dist_col, repl_col);
5271 #endif
5272 	}
5273 	if (repl_col == 0) {
5274 		return 4;	/* replace black with blue */
5275 	}
5276 	if (repl_col == 7) {
5277 		return 3;	/* replace white with yellow */
5278 	}
5279 	return repl_col;
5280 }
5281 
5282 
5283 #ifdef CURSES
5284 
5285 void
disp_colour(c,for_256_colours)5286 disp_colour (c, for_256_colours)
5287   int c;
5288   FLAG for_256_colours;
5289 {
5290 	attrset (COLOR_PAIR (colour8_base + map8 (c, for_256_colours)));
5291 	if (dark_term) {
5292 		attron (A_BOLD);
5293 	}
5294 }
5295 
5296 void
emph_on()5297 emph_on ()
5298 {
5299 	attrset (COLOR_PAIR (emphcolor));
5300 	if (dark_term) {
5301 		attron (A_BOLD);
5302 	}
5303 }
5304 
5305 void
mark_on()5306 mark_on ()
5307 {
5308 	if (colour_token >= 0) {
5309 		disp_colour (colour_token, UNSURE);
5310 		colour_token = -1;
5311 	} else if (nonempty (markansi)) {
5312 		attrset (COLOR_PAIR (markcolor));
5313 	} else if (! dark_term) {
5314 		attrset (A_DIM);
5315 	}
5316 	if (dark_term) {
5317 		attron (A_BOLD);
5318 	}
5319 }
5320 
5321 void
mark_off()5322 mark_off ()
5323 {
5324 	standend ();
5325 }
5326 
5327 
5328 void
bold_on()5329 bold_on ()
5330 {
5331 	attrset (A_BOLD);
5332 }
5333 
5334 void
bold_off()5335 bold_off ()
5336 {
5337 	standend ();
5338 }
5339 
5340 void
underline_on()5341 underline_on ()
5342 {
5343 	attrset (A_UNDERLINE);
5344 }
5345 
5346 void
underline_off()5347 underline_off ()
5348 {
5349 	standend ();
5350 }
5351 
5352 void
blink_on()5353 blink_on ()
5354 {
5355 	attrset (A_BLINK);
5356 }
5357 
5358 void
blink_off()5359 blink_off ()
5360 {
5361 	standend ();
5362 }
5363 
5364 void
disp_normal()5365 disp_normal ()
5366 {
5367 	standend ();
5368 }
5369 
5370 void
disp_selected(bg,border)5371 disp_selected (bg, border)
5372   FLAG bg;
5373   FLAG border;
5374 /* for selected menu item */
5375 {
5376 /*	| selected item |
5377 	left border: bg && border (if graphic)
5378 	  selected item: bg && ! border
5379 	                right border: ! bg && border (if graphic)
5380 */
5381 	if (avoid_reverse_colour) {
5382 		/* workaround for buggy cygwin reverse bold colour handling */
5383 		if (bg) {
5384 			if (border) {
5385 				attrset (COLOR_PAIR (selcolor));
5386 			} else {
5387 				reverse_off ();
5388 				attrset (COLOR_PAIR (selcolor) | A_REVERSE | A_BOLD);
5389 			}
5390 		} else {
5391 			attrset ((border ? COLOR_PAIR (selcolor) : COLOR_PAIR (selcolor) | A_REVERSE));
5392 		}
5393 	} else {
5394 		if (nonempty (selansi)) {
5395 			attrset ((border ? COLOR_PAIR (selcolor) : COLOR_PAIR (selcolor) | A_REVERSE)
5396 				 | (bg ? A_REVERSE : 0)
5397 				 | (dark_term ? A_BOLD : 0)
5398 				 );
5399 		} else {
5400 			standout ();
5401 		}
5402 	}
5403 }
5404 
5405 
5406 void
unidisp_on()5407 unidisp_on ()
5408 /* for non-displayable or illegal Unicode characters */
5409 {
5410 	if (nonempty (uniansi)) {
5411 		/*attrset (COLOR_PAIR (unicolor));*/
5412 		attrset (COLOR_PAIR (specialcolor) | A_REVERSE);
5413 	} else {
5414 		standout ();
5415 	}
5416 }
5417 
5418 void
unidisp_off()5419 unidisp_off ()
5420 {
5421 	standend ();
5422 }
5423 
5424 
5425 void
specialdisp_on()5426 specialdisp_on ()
5427 /* for Unicode line end indications */
5428 {
5429 	if (nonempty (specialansi)) {
5430 		attrset (COLOR_PAIR (specialcolor));
5431 	} else {
5432 		standout ();
5433 	}
5434 }
5435 
5436 void
specialdisp_off()5437 specialdisp_off ()
5438 {
5439 	standend ();
5440 }
5441 
5442 
5443 void
combiningdisp_on()5444 combiningdisp_on ()
5445 /* for Unicode combining character indication in separated display mode */
5446 {
5447 	if (nonempty (combiningansi)) {
5448 		/*attrset (COLOR_PAIR (combiningcolor));*/
5449 		attrset (COLOR_PAIR (specialcolor) | A_REVERSE);
5450 	} else {
5451 		standout ();
5452 	}
5453 }
5454 
5455 void
combiningdisp_off()5456 combiningdisp_off ()
5457 {
5458 	standend ();
5459 }
5460 
5461 
5462 void
ctrldisp_on()5463 ctrldisp_on ()
5464 {
5465 	if (nonempty (ctrlansi)) {
5466 		attrset (COLOR_PAIR (ctrlcolor));
5467 	} else {
5468 		standout ();
5469 	}
5470 }
5471 
5472 void
ctrldisp_off()5473 ctrldisp_off ()
5474 {
5475 	standend ();
5476 }
5477 
5478 
5479 void
dispHTML_code()5480 dispHTML_code ()
5481 {
5482 	if (nonempty (HTMLansi)) {
5483 		attrset (COLOR_PAIR (HTMLcolor));
5484 	} else {
5485 		standout ();
5486 	}
5487 }
5488 
5489 void
dispHTML_comment()5490 dispHTML_comment ()
5491 {
5492 	if (nonempty (HTMLansi)) {
5493 		attrset (COLOR_PAIR (HTMLcomment));
5494 	} else {
5495 		standout ();
5496 	}
5497 }
5498 
5499 void
dispHTML_jsp()5500 dispHTML_jsp ()
5501 {
5502 	if (nonempty (HTMLansi)) {
5503 		attrset (COLOR_PAIR (HTMLjsp));
5504 	} else {
5505 		standout ();
5506 	}
5507 }
5508 
5509 void
dispXML_attrib()5510 dispXML_attrib ()
5511 {
5512 	if (nonempty (XMLattribansi)) {
5513 		attrset (COLOR_PAIR (XMLattrib));
5514 	} else {
5515 		standout ();
5516 	}
5517 }
5518 
5519 void
dispXML_value()5520 dispXML_value ()
5521 {
5522 	if (nonempty (XMLvalueansi)) {
5523 		attrset (COLOR_PAIR (XMLvalue));
5524 	} else {
5525 		standout ();
5526 	}
5527 }
5528 
5529 void
dispHTML_off()5530 dispHTML_off ()
5531 {
5532 	standend ();
5533 }
5534 
5535 
5536 void
menudisp_on()5537 menudisp_on ()
5538 {
5539 	if (nonempty (menuansi)) {
5540 		attrset (COLOR_PAIR (menucolor));
5541 	} else {
5542 		standout ();
5543 	}
5544 }
5545 
5546 void
menudisp_off()5547 menudisp_off ()
5548 {
5549 	standend ();
5550 }
5551 
5552 void
diagdisp_on()5553 diagdisp_on ()
5554 {
5555 	if (nonempty (diagansi)) {
5556 		attrset (COLOR_PAIR (diagcolor));
5557 	} else {
5558 		standout ();
5559 	}
5560 }
5561 
5562 void
diagdisp_off()5563 diagdisp_off ()
5564 {
5565 	standend ();
5566 }
5567 
5568 
5569 void
disp_scrollbar_foreground()5570 disp_scrollbar_foreground ()
5571 {
5572 	if (nonempty (scrollbgansi)) {
5573 		attrset (COLOR_PAIR (scrollfgcolor));
5574 	} else {
5575 		standout ();
5576 	}
5577 }
5578 
5579 void
disp_scrollbar_background()5580 disp_scrollbar_background ()
5581 {
5582 	if (nonempty (scrollbgansi)) {
5583 		attrset (COLOR_PAIR (scrollfgcolor) | A_REVERSE);
5584 	}
5585 }
5586 
5587 void
disp_scrollbar_off()5588 disp_scrollbar_off ()
5589 {
5590 	standend ();
5591 }
5592 
5593 
5594 void
menuborder_on()5595 menuborder_on ()
5596 {
5597 	if (! use_normalchars_boxdrawing) {
5598 		altcset_on ();
5599 	}
5600 #ifdef use_default_colour
5601 	attrset (COLOR_PAIR (menuborder) | (bold_border ? A_BOLD : 0));
5602 #endif
5603 	in_menu_border = True;
5604 }
5605 
5606 void
menuborder_off()5607 menuborder_off ()
5608 {
5609 	standend ();
5610 	if (! use_normalchars_boxdrawing) {
5611 		altcset_off ();
5612 	}
5613 	in_menu_border = False;
5614 }
5615 
5616 void
menuitem_on()5617 menuitem_on ()
5618 {
5619 #ifdef use_default_colour
5620 	attrset (COLOR_PAIR (menuitem) /* | A_BOLD */);
5621 #endif
5622 }
5623 
5624 void
menuitem_off()5625 menuitem_off ()
5626 {
5627 	standend ();
5628 }
5629 
5630 void
menuheader_on()5631 menuheader_on ()
5632 {
5633 	if (! use_normalchars_boxdrawing) {
5634 		altcset_off ();
5635 	}
5636 	if (avoid_reverse_colour) {
5637 		/* workaround for buggy cygwin reverse bold colour handling */
5638 		disp_normal ();
5639 		attrset (COLOR_PAIR (menuheader));
5640 	} else {
5641 		attrset (COLOR_PAIR (menuheader) | A_BOLD | A_REVERSE);
5642 	}
5643 	in_menu_border = False;
5644 }
5645 
5646 void
menuheader_off()5647 menuheader_off ()
5648 {
5649 	standend ();
5650 	in_menu_border = False;
5651 }
5652 
5653 #else	/* #ifdef CURSES */
5654 
5655 
5656 #ifdef conio
5657 
5658 void
disp_colour(c,for_256_colours)5659 disp_colour (c, for_256_colours)
5660   int c;
5661   FLAG for_256_colours;
5662 {
5663 	switch (map8 (c, for_256_colours)) {
5664 		case 0: textcolor (BLACK); break;
5665 		case 1: textcolor (RED); break;
5666 		case 2: textcolor (GREEN); break;
5667 		case 3: textcolor (YELLOW); break;
5668 		case 4: textcolor (BLUE); break;
5669 		case 5: textcolor (MAGENTA); break;
5670 		case 6: textcolor (CYAN); break;
5671 		case 7: textcolor (WHITE); break;
5672 	}
5673 	if (dark_term) {
5674 		highvideo ();
5675 	}
5676 }
5677 
5678 void
emph_on()5679 emph_on ()
5680 {
5681 	/* check emphansi ? */
5682 	textcolor (RED);
5683 	if (dark_term) {
5684 		highvideo ();
5685 	}
5686 }
5687 
5688 void
mark_on()5689 mark_on ()
5690 {
5691 	/* check markansi ? */
5692 	if (colour_token >= 0) {
5693 		disp_colour (colour_token, UNSURE);
5694 		colour_token = -1;
5695 	} else {
5696 		textcolor (RED);
5697 	}
5698 	if (dark_term) {
5699 		highvideo ();
5700 	}
5701 }
5702 
5703 void
mark_off()5704 mark_off ()
5705 {
5706 	normvideo ();
5707 }
5708 
5709 
5710 void
bold_on()5711 bold_on ()
5712 {
5713 	highvideo ();
5714 }
5715 
5716 void
bold_off()5717 bold_off ()
5718 {
5719 	normvideo ();
5720 }
5721 
5722 void
underline_on()5723 underline_on ()
5724 {
5725 	highvideo ();
5726 }
5727 
5728 void
underline_off()5729 underline_off ()
5730 {
5731 	normvideo ();
5732 }
5733 
5734 void
blink_on()5735 blink_on ()
5736 {
5737 #ifdef __DJGPP__
5738 	blinkvideo ();
5739 #else
5740 	highvideo ();
5741 #endif
5742 }
5743 
5744 void
blink_off()5745 blink_off ()
5746 {
5747 	normvideo ();
5748 }
5749 
5750 void
disp_normal()5751 disp_normal ()
5752 {
5753 	normvideo ();
5754 }
5755 
5756 void
disp_selected(bg,border)5757 disp_selected (bg, border)
5758   FLAG bg;
5759   FLAG border;
5760 {
5761 	/* check selansi ? */
5762 	if (bg) {
5763 		if (dark_term) {
5764 			highvideo ();
5765 		} else {
5766 			normvideo ();
5767 		}
5768 		textbackground (BLUE);
5769 		if (! border) {
5770 			textcolor (YELLOW);
5771 		}
5772 	} else {
5773 		textcolor (BLUE);
5774 	}
5775 }
5776 
5777 
5778 void
unidisp_on()5779 unidisp_on ()
5780 /* for non-displayable or illegal Unicode characters */
5781 {
5782 	/* check uniansi ? */
5783 	textbackground (CYAN);
5784 }
5785 
5786 void
unidisp_off()5787 unidisp_off ()
5788 {
5789 	normvideo ();
5790 }
5791 
5792 
5793 void
specialdisp_on()5794 specialdisp_on ()
5795 /* for Unicode line end indications */
5796 {
5797 	textcolor (CYAN);
5798 }
5799 
5800 void
specialdisp_off()5801 specialdisp_off ()
5802 {
5803 	normvideo ();
5804 }
5805 
5806 
5807 void
combiningdisp_on()5808 combiningdisp_on ()
5809 /* for Unicode combining character indication in separated display mode */
5810 {
5811 	textbackground (CYAN);
5812 	textcolor (BLACK);
5813 }
5814 
5815 void
combiningdisp_off()5816 combiningdisp_off ()
5817 {
5818 	normvideo ();
5819 }
5820 
5821 
5822 void
ctrldisp_on()5823 ctrldisp_on ()
5824 {
5825 	reverse_on ();
5826 }
5827 
5828 void
ctrldisp_off()5829 ctrldisp_off ()
5830 {
5831 	reverse_off ();
5832 }
5833 
5834 
5835 void
dispHTML_code()5836 dispHTML_code ()
5837 {
5838 	textcolor (LIGHTBLUE);
5839 }
5840 
5841 void
dispXML_attrib()5842 dispXML_attrib ()
5843 {
5844 	textcolor (RED);
5845 }
5846 
5847 void
dispXML_value()5848 dispXML_value ()
5849 {
5850 	textcolor (MAGENTA);
5851 }
5852 
5853 void
dispHTML_comment()5854 dispHTML_comment ()
5855 {
5856 	textcolor (LIGHTBLUE);
5857 	textbackground (YELLOW);
5858 }
5859 
5860 void
dispHTML_jsp()5861 dispHTML_jsp ()
5862 {
5863 	textcolor (CYAN);
5864 	textbackground (BLACK);
5865 }
5866 
5867 void
dispHTML_off()5868 dispHTML_off ()
5869 {
5870 	normvideo ();
5871 }
5872 
5873 
5874 void
menudisp_on()5875 menudisp_on ()
5876 {
5877 	reverse_on ();
5878 }
5879 
5880 void
menudisp_off()5881 menudisp_off ()
5882 {
5883 	reverse_off ();
5884 }
5885 
5886 void
diagdisp_on()5887 diagdisp_on ()
5888 {
5889 	reverse_on ();
5890 }
5891 
5892 void
diagdisp_off()5893 diagdisp_off ()
5894 {
5895 	reverse_off ();
5896 }
5897 
5898 
5899 void
disp_scrollbar_foreground()5900 disp_scrollbar_foreground ()
5901 {
5902 /*	textattr (CYAN);	*/
5903 	textbackground (BLUE);
5904 }
5905 
5906 void
disp_scrollbar_background()5907 disp_scrollbar_background ()
5908 {
5909 /*	textattr (BLUE);	*/
5910 	textbackground (CYAN);
5911 }
5912 
5913 void
disp_scrollbar_off()5914 disp_scrollbar_off ()
5915 {
5916 	normvideo ();
5917 }
5918 
5919 
5920 void
menuborder_on()5921 menuborder_on ()
5922 {
5923 	if (! use_normalchars_boxdrawing) {
5924 		altcset_on ();
5925 	}
5926 	textattr (RED);
5927 	if (bold_border) {
5928 		highvideo ();
5929 	}
5930 	in_menu_border = True;
5931 }
5932 
5933 void
menuborder_off()5934 menuborder_off ()
5935 {
5936 	normvideo ();
5937 	textattr (norm_attr);
5938 	if (! use_normalchars_boxdrawing) {
5939 		altcset_off ();
5940 	}
5941 	in_menu_border = False;
5942 }
5943 
5944 void
menuitem_on()5945 menuitem_on ()
5946 {
5947 	textbackground (YELLOW);
5948 	/* highvideo (); */
5949 }
5950 
5951 void
menuitem_off()5952 menuitem_off ()
5953 {
5954 	textattr (norm_attr);
5955 }
5956 
5957 void
menuheader_on()5958 menuheader_on ()
5959 {
5960 	if (! use_normalchars_boxdrawing) {
5961 		altcset_off ();
5962 	}
5963 	/*reverse_on ();*/
5964 	textbackground (RED);
5965 	textcolor (LIGHTGRAY);
5966 	in_menu_border = False;
5967 }
5968 
5969 void
menuheader_off()5970 menuheader_off ()
5971 {
5972 	textattr (norm_attr);
5973 	in_menu_border = False;
5974 }
5975 
5976 #else	/* #ifdef conio */
5977 
5978 
5979 static
5980 FLAG
putansistring(s)5981 putansistring (s)
5982   char * s;
5983 {
5984 	if (ansi_esc && nonempty (s)) {
5985 		if (suppress_colour && (* s == '3' || * s == '4')) {
5986 			/* e.g. for Android Terminal Emulator */
5987 			if (s == scrollfgansi) {
5988 				return False;
5989 			} else if (s == scrollbgansi) {
5990 				return True;
5991 			} else if (strstr (s, ";1")) {
5992 				putansistring ("1");
5993 				return False;
5994 			} else if (strstr (s, ";7")) {
5995 				putansistring ("7");
5996 				return False;
5997 			} else {
5998 				return False;
5999 			}
6000 		}
6001 		putescape ("\033[");
6002 		putescape (s);
6003 		putescape ("m");
6004 		return True;
6005 	} else {
6006 		return False;
6007 	}
6008 }
6009 
6010 void
disp_colour(c,for_256_colours)6011 disp_colour (c, for_256_colours)
6012   int c;
6013   FLAG for_256_colours;
6014 {
6015 	char ctrl [19];
6016 	int col8 = map8 (c, for_256_colours);
6017 
6018 	if (c < 8) {
6019 		build_string (ctrl, "3%d", c);
6020 	} else if (c < 16) {
6021 		build_string (ctrl, "9%d", c - 8);
6022 	} else {
6023 		if (colours_256 || colours_88) {
6024 			build_string (ctrl, "38;5;%d", c);
6025 		} else {
6026 			build_string (ctrl, "3%d", col8);
6027 		}
6028 	}
6029 #ifdef debug_disp_colour
6030 	printf ("disp_colour %d put <%s>\n", c, ctrl);
6031 #endif
6032 	(void) putansistring (ctrl);
6033 
6034 	if (col8 == 0 || col8 == 1 || col8 == 4) {
6035 		/* black, red, blue */
6036 		if (dark_term) {
6037 			bold_on ();
6038 		}
6039 	} else {
6040 		if (! dark_term) {
6041 			bold_on ();
6042 		}
6043 	}
6044 }
6045 
6046 void
emph_on()6047 emph_on ()
6048 {
6049 	if (dark_term) {
6050 		bold_on ();
6051 	}
6052 	(void) putansistring (emphansi);
6053 }
6054 
6055 void
mark_on()6056 mark_on ()
6057 {
6058 	if (dark_term) {
6059 		bold_on ();
6060 	} else {
6061 #if defined (unix) || defined (vms)
6062 		if (can_dim && ! screen_version && ansi_esc &&
6063 		    (! cMH || ! * cMH)) {
6064 			cMH = "";
6065 		}
6066 		termputstr (cMH, aff1);
6067 #endif
6068 	}
6069 	if (colour_token >= 0) {
6070 		disp_colour (colour_token, UNSURE);
6071 		colour_token = -1;
6072 	} else {
6073 		(void) putansistring (markansi);
6074 	}
6075 }
6076 
6077 void
mark_off()6078 mark_off ()
6079 {
6080 	if (! putansistring ("0")) {
6081 		termputstr (cME, aff1);
6082 	}
6083 }
6084 
6085 void
bold_on()6086 bold_on ()
6087 {
6088 	if (use_bold) {
6089 		termputstr (cMD, aff1);
6090 	}
6091 }
6092 
6093 void
bold_off()6094 bold_off ()
6095 {
6096 	if (use_bold) {
6097 		termputstr (cME, aff1);
6098 	}
6099 }
6100 
6101 void
underline_on()6102 underline_on ()
6103 {
6104 	termputstr (cUL, aff1);
6105 }
6106 
6107 void
underline_off()6108 underline_off ()
6109 {
6110 	termputstr (cME, aff1);
6111 }
6112 
6113 void
blink_on()6114 blink_on ()
6115 {
6116 	termputstr (cBL, aff1);
6117 }
6118 
6119 void
blink_off()6120 blink_off ()
6121 {
6122 	termputstr (cME, aff1);
6123 }
6124 
6125 void
disp_normal()6126 disp_normal ()
6127 {
6128 	if (screen_version > 0) {
6129 		/* workaround to reset attributes passed by transparently */
6130 		reverse_on ();
6131 		reverse_off ();
6132 	}
6133 	termputstr (cME, aff1);
6134 }
6135 
6136 static
6137 char *
reverse_colour(ansi)6138 reverse_colour (ansi)
6139   char * ansi;
6140 {
6141 	static char revansi [3];
6142 	if (ansi [0] == '3') {
6143 		revansi [0] = '4';
6144 	} else {
6145 		revansi [0] = '3';
6146 	}
6147 	revansi [1] = ansi [1];
6148 	revansi [2] = 0;
6149 	return revansi;
6150 }
6151 
6152 void
disp_selected(bg,border)6153 disp_selected (bg, border)
6154   FLAG bg;
6155   FLAG border;
6156 {
6157 /*	| selected item |
6158 	left border: bg && border (if graphic)
6159 	  selected item: bg && ! border
6160 	                right border: ! bg && border (if graphic)
6161 */
6162 	if (avoid_reverse_colour) {
6163 		/* workaround for buggy cygwin reverse bold colour handling */
6164 		if (bg) {
6165 			if (border) {
6166 				(void) putansistring (selansi);
6167 				reverse_on ();
6168 			} else {
6169 				reverse_off ();
6170 				(void) putansistring (reverse_colour (selansi));
6171 				(void) putansistring (reverse_colour (selfgansi));
6172 				bold_on ();
6173 			}
6174 		} else {
6175 			(void) putansistring (selansi);
6176 			if (! border) {
6177 				(void) putansistring (selfgansi);
6178 			}
6179 		}
6180 	} else {
6181 		(void) putansistring (selansi);
6182 		if (! border) {
6183 			(void) putansistring (selfgansi);
6184 		}
6185 		if (bg) {
6186 			reverse_on ();
6187 		}
6188 	}
6189 }
6190 
6191 
6192 void
unidisp_on()6193 unidisp_on ()
6194 /* for non-displayable or illegal Unicode characters */
6195 {
6196 	if (! putansistring (uniansi)) {
6197 		reverse_on ();
6198 	}
6199 }
6200 
6201 void
unidisp_off()6202 unidisp_off ()
6203 {
6204 	if (nonempty (uniansi)) {
6205 		if (! putansistring ("0")) {
6206 			reverse_off ();
6207 		}
6208 	} else {
6209 		reverse_off ();
6210 	}
6211 }
6212 
6213 
6214 void
specialdisp_on()6215 specialdisp_on ()
6216 /* for Unicode line end indications */
6217 {
6218 	if (! putansistring (specialansi)) {
6219 		reverse_on ();
6220 	}
6221 }
6222 
6223 void
specialdisp_off()6224 specialdisp_off ()
6225 {
6226 	if (nonempty (specialansi)) {
6227 		if (! putansistring ("0")) {
6228 			reverse_off ();
6229 		}
6230 	} else {
6231 		reverse_off ();
6232 	}
6233 }
6234 
6235 
6236 void
combiningdisp_on()6237 combiningdisp_on ()
6238 /* for Unicode combining character indication in separated display mode */
6239 {
6240 	if (! putansistring (combiningansi)) {
6241 		reverse_on ();
6242 	}
6243 }
6244 
6245 void
combiningdisp_off()6246 combiningdisp_off ()
6247 {
6248 	if (nonempty (combiningansi)) {
6249 		if (! putansistring ("0")) {
6250 			reverse_off ();
6251 		}
6252 	} else {
6253 		reverse_off ();
6254 	}
6255 }
6256 
6257 
6258 void
ctrldisp_on()6259 ctrldisp_on ()
6260 {
6261 	if (! putansistring (ctrlansi)) {
6262 		reverse_on ();
6263 	}
6264 }
6265 
6266 void
ctrldisp_off()6267 ctrldisp_off ()
6268 {
6269 	if (nonempty (ctrlansi)) {
6270 		if (! putansistring ("0")) {
6271 			reverse_off ();
6272 		}
6273 	} else {
6274 		reverse_off ();
6275 	}
6276 }
6277 
6278 
6279 void
dispHTML_code()6280 dispHTML_code ()
6281 {
6282 	if (! putansistring (HTMLansi)) {
6283 		mark_on ();
6284 	}
6285 }
6286 
6287 void
dispXML_attrib()6288 dispXML_attrib ()
6289 {
6290 	if (! putansistring (XMLattribansi)) {
6291 		if (! putansistring ("31")) {
6292 			mark_on ();
6293 		}
6294 	}
6295 }
6296 
6297 void
dispXML_value()6298 dispXML_value ()
6299 {
6300 	if (! putansistring (XMLvalueansi)) {
6301 		if (! putansistring ("35")) {
6302 			mark_on ();
6303 		}
6304 	}
6305 }
6306 
6307 void
dispHTML_comment()6308 dispHTML_comment ()
6309 {
6310 	char ctrl [19];
6311 
6312 	if (nonempty (HTMLansi)) {
6313 		if (fg_yellowish) {
6314 			build_string (ctrl, "%s;44;33", HTMLansi);
6315 		} else {
6316 			build_string (ctrl, "%s;43", HTMLansi);
6317 		}
6318 		if (! putansistring (ctrl)) {
6319 			mark_on ();
6320 		}
6321 	} else {
6322 		mark_on ();
6323 	}
6324 }
6325 
6326 void
dispHTML_jsp()6327 dispHTML_jsp ()
6328 {
6329 	if (nonempty (HTMLansi)) {
6330 		/*(void) putansistring ("36");*/
6331 		if (! putansistring ("36;40")) {
6332 			mark_on ();
6333 		}
6334 	} else {
6335 		mark_on ();
6336 	}
6337 }
6338 
6339 void
dispHTML_off()6340 dispHTML_off ()
6341 {
6342 	if (nonempty (HTMLansi)) {
6343 		if (! putansistring ("0")) {
6344 			mark_off ();
6345 		}
6346 	} else {
6347 		mark_off ();
6348 	}
6349 }
6350 
6351 
6352 void
menudisp_on()6353 menudisp_on ()
6354 {
6355 	if (! putansistring (menuansi)) {
6356 		reverse_on ();
6357 	}
6358 }
6359 
6360 void
menudisp_off()6361 menudisp_off ()
6362 {
6363 	if (nonempty (menuansi)) {
6364 		if (! putansistring ("0")) {
6365 			reverse_off ();
6366 		}
6367 	} else {
6368 		reverse_off ();
6369 	}
6370 }
6371 
6372 void
diagdisp_on()6373 diagdisp_on ()
6374 {
6375 	if (! putansistring (diagansi)) {
6376 		reverse_on ();
6377 	}
6378 }
6379 
6380 void
diagdisp_off()6381 diagdisp_off ()
6382 {
6383 	if (nonempty (diagansi)) {
6384 		if (! putansistring ("0")) {
6385 			reverse_off ();
6386 		}
6387 	} else {
6388 		reverse_off ();
6389 	}
6390 }
6391 
6392 
6393 void
disp_scrollbar_foreground()6394 disp_scrollbar_foreground ()
6395 {
6396 	if (suppress_colour) {
6397 		reverse_off ();
6398 	} else if (nonempty (scrollfgansi)) {
6399 		if (! putansistring (scrollfgansi)) {
6400 			reverse_on ();
6401 		}
6402 	} else {
6403 		(void) putansistring (scrollbgansi);
6404 		reverse_on ();
6405 	}
6406 }
6407 
6408 void
disp_scrollbar_background()6409 disp_scrollbar_background ()
6410 {
6411 	if (suppress_colour) {
6412 		reverse_on ();
6413 	} else {
6414 		reverse_off ();
6415 		if (! putansistring (scrollbgansi)) {
6416 			termputstr (cSO, aff1);
6417 		}
6418 	}
6419 }
6420 
6421 void
disp_scrollbar_off()6422 disp_scrollbar_off ()
6423 {
6424 	if (nonempty (scrollbgansi)) {
6425 		if (! putansistring ("0")) {
6426 			reverse_off ();
6427 		}
6428 	} else {
6429 		reverse_off ();
6430 	}
6431 }
6432 
6433 
6434 void
menuborder_on()6435 menuborder_on ()
6436 {
6437 	if (! use_normalchars_boxdrawing) {
6438 		altcset_on ();
6439 	}
6440 	if (bold_border) {
6441 		bold_on ();
6442 	}
6443 	(void) putansistring (borderansi);
6444 	in_menu_border = True;
6445 }
6446 
6447 void
menuborder_off()6448 menuborder_off ()
6449 {
6450 	(void) putansistring ("0");
6451 	if (! use_normalchars_boxdrawing) {
6452 		altcset_off ();
6453 	}
6454 	in_menu_border = False;
6455 }
6456 
6457 void
menuitem_on()6458 menuitem_on ()
6459 {
6460 	if (use_bgcolor) {
6461 		/* try to keep it visible on old buggy hanterm: */
6462 		/* - hopefully not needed anymore; */
6463 		/* - interferes unpleasantly with buggy
6464 		     bold/colour combination on gnome-terminal/konsole */
6465 		/* bold_on (); */
6466 
6467 		if (! putansistring (fg_yellowish ? "44;33" : "43;30")) {
6468 			reverse_on ();
6469 		}
6470 	} else {
6471 		if (! putansistring ("0;1")) {
6472 			reverse_on ();
6473 		}
6474 	}
6475 }
6476 
6477 void
menuitem_off()6478 menuitem_off ()
6479 {
6480 	if (! putansistring ("0")) {
6481 		reverse_off ();
6482 	}
6483 }
6484 
6485 void
menuheader_on()6486 menuheader_on ()
6487 {
6488 	if (! use_normalchars_boxdrawing) {
6489 		altcset_off ();
6490 	}
6491 	if (avoid_reverse_colour) {
6492 		/* workaround for buggy cygwin reverse bold colour handling */
6493 		disp_normal ();
6494 		if (dark_term) {
6495 			(void) putansistring ("37");
6496 		}
6497 		(void) putansistring (reverse_colour (borderansi));
6498 	} else {
6499 		if (dark_term) {
6500 			bold_on ();
6501 		}
6502 		/* Note: menu border colour is already switched on */
6503 		if (! putansistring ("7")) {
6504 			reverse_on ();
6505 		}
6506 	}
6507 	in_menu_border = False;
6508 }
6509 
6510 void
menuheader_off()6511 menuheader_off ()
6512 {
6513 	if (! putansistring ("0")) {
6514 		reverse_off ();
6515 	}
6516 	in_menu_border = False;
6517 }
6518 
6519 #endif	/* #else conio */
6520 
6521 
6522 #endif	/* #else CURSES */
6523 
6524 
6525 /*======================================================================*\
6526 |*			DOS mouse API					*|
6527 \*======================================================================*/
6528 
6529 #ifdef dosmouse
6530 #include "dosmouse.c"
6531 #endif
6532 
6533 
6534 /*======================================================================*\
6535 |*				End					*|
6536 \*======================================================================*/
6537