1 /*
2  *	term.c
3  *
4  *	Terminal Module
5  */
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <signal.h>
11 #include <fcntl.h>
12 #include "machine.h"
13 
14 #if	defined (DJGPP) && (DJGPP >= 2)
15 #include <time.h>
16 #endif
17 
18 #ifdef	USESTDARGH
19 #include <stdarg.h>
20 #else
21 #include <varargs.h>
22 #endif
23 
24 #ifdef	DEBUG
25 extern char *_mtrace_file;
26 #endif
27 
28 #if	MSDOS
29 #include <dos.h>
30 #include <io.h>
31 # ifdef	PC98
32 # define	NOTUSEBIOS
33 # else
34 # define	USEVIDEOBIOS
35 # define	VIDEOBIOS	0x10
36 # define	BIOSSEG		0x40
37 # define	CURRPAGE	0x62
38 # define	SCRHEIGHT	0x84
39 # define	SCRWIDTH	0x4a
40 # endif
41 # ifdef	DJGPP
42 # include <dpmi.h>
43 # include <go32.h>
44 # include <sys/farptr.h>
45 #  if	defined (DJGPP) && (DJGPP >= 2)
46 #  include <libc/dosio.h>
47 #  else
48 #  define	__dpmi_regs	_go32_dpmi_registers
49 #  define	__dpmi_int(v,r)	((r) -> x.ss = (r) -> x.sp = 0, \
50 				_go32_dpmi_simulate_int(v, r))
51 #  define	_dos_ds		_go32_info_block.selector_for_linear_memory
52 #  endif
53 # define	intdos2(rp)	__dpmi_int(0x21, rp)
54 # define	getkeybuf(o)	_farpeekw(_dos_ds, KEYBUFWORKSEG * 0x10 + o)
55 # define	putkeybuf(o, n)	_farpokew(_dos_ds, KEYBUFWORKSEG * 0x10 + o, n)
56 # define	intbios(v, rp)	__dpmi_int(v, rp)
57 # define	getbiosbyte(o)	_farpeekb(_dos_ds, BIOSSEG * 0x10 + o)
58 # else	/* !DJGPP */
59 # include <sys/types.h>
60 # include <sys/timeb.h>
61 typedef union REGS	__dpmi_regs;
62 # define	intdos2(rp)	int86(0x21, rp, rp)
63 # define	getkeybuf(o)	(*((u_short far *)MK_FP(KEYBUFWORKSEG, o)))
64 # define	putkeybuf(o, n)	(*((u_short far *)MK_FP(KEYBUFWORKSEG, o)) = n)
65 # define	intbios(v, rp)	int86(v, rp, rp)
66 # define	getbiosbyte(o)	(*((u_char far *)MK_FP(BIOSSEG, o)))
67 #  ifdef	LSI_C
68 static int _asm_sti __P_((char *));
69 static int _asm_cli __P_((char *));
70 #  define	enable()	_asm_sti("\n\tsti\n")
71 #  define	disable()	_asm_cli("\n\tcli\n")
72 #  endif
73 # endif	/* !DJGPP */
74 #define	TTYNAME		"CON"
75 #else	/* !MSDOS */
76 #include <sys/types.h>
77 #include <sys/file.h>
78 #include <sys/time.h>
79 #define	TTYNAME		"/dev/tty"
80 
81 typedef struct _keyseq_t {
82 	u_short code;
83 	u_char len;
84 	char *str;
85 } keyseq_t;
86 
87 typedef struct _kstree_t {
88 	int key;
89 	int num;
90 	struct _kstree_t *next;
91 } kstree_t;
92 
93 #ifdef	USETERMIOS
94 # ifdef	USETERMIO
95 # undef	USETERMIO
96 # endif
97 #include <termios.h>
98 #include <sys/ioctl.h>	/* for Linux libc6 */
99 typedef struct termios	termioctl_t;
100 #define	tioctl(d, r, a)	((r) ? tcsetattr(d, (r) - 1, a) : tcgetattr(d, a))
101 #define	getspeed(t)	cfgetospeed(&t)
102 #define	REQGETP		0
103 #define	REQSETP		(TCSAFLUSH + 1)
104 #endif
105 
106 #ifdef	USETERMIO
107 #include <termio.h>
108 typedef struct termio	termioctl_t;
109 #define	tioctl		ioctl
110 #define	getspeed(t)	((t).c_cflag & CBAUD)
111 #define	REQGETP		TCGETA
112 #define	REQSETP		TCSETAF
113 #endif
114 
115 #if	!defined (USETERMIO) && !defined (USETERMIOS)
116 #define	USESGTTY
117 #include <sgtty.h>
118 typedef struct sgttyb	termioctl_t;
119 #define	tioctl		ioctl
120 #define	getspeed(t)	((t).sg_ospeed)
121 #define	REQGETP		TIOCGETP
122 #define	REQSETP		TIOCSETP
123 #endif
124 
125 #ifdef	USESELECTH
126 #include <sys/select.h>
127 #endif
128 #endif	/* !MSDOS */
129 
130 #ifndef	NOSTDLIBH
131 #include <stdlib.h>
132 #endif
133 
134 #include <errno.h>
135 #ifdef	NOERRNO
136 extern int errno;
137 #endif
138 
139 #include "term.h"
140 
141 #define	MAXPRINTBUF	255
142 #define	GETSIZE		"\033[6n"
143 #define	SIZEFMT		"\033[%d;%dR"
144 
145 #if	!MSDOS
146 # ifdef	USETERMINFO
147 # include <curses.h>
148 # include <term.h>
149 # define	tgetnum2(s)		(s)
150 # define	tgetflag2(s)		(s)
151 # define	tgoto2(s, p1, p2)	tparm(s, p2, p1, \
152 					0, 0, 0, 0, 0, 0, 0)
153 # define	TERM_pc			pad_char
154 # define	TERM_bc			NULL
155 # define	TERM_co			columns
156 # define	TERM_li			lines
157 # define	TERM_xn			eat_newline_glitch
158 # define	TERM_xs			ceol_standout_glitch
159 # define	TERM_ti			enter_ca_mode
160 # define	TERM_te			exit_ca_mode
161 # define	TERM_mm			meta_on
162 # define	TERM_mo			meta_off
163 # define	TERM_cs			change_scroll_region
164 # define	TERM_ks			keypad_xmit
165 # define	TERM_ke			keypad_local
166 # define	TERM_ve			cursor_normal
167 # define	TERM_vs			cursor_visible
168 # define	TERM_vi			cursor_invisible
169 # define	TERM_sc			save_cursor
170 # define	TERM_rc			restore_cursor
171 # define	TERM_bl			bell
172 # define	TERM_vb			flash_screen
173 # define	TERM_cl			clear_screen
174 # define	TERM_me			exit_attribute_mode
175 # define	TERM_md			enter_bold_mode
176 # define	TERM_mr			enter_reverse_mode
177 # define	TERM_mh			enter_dim_mode
178 # define	TERM_mb			enter_blink_mode
179 # define	TERM_so			enter_standout_mode
180 # define	TERM_us			enter_underline_mode
181 # define	TERM_se			exit_standout_mode
182 # define	TERM_ue			exit_underline_mode
183 # define	TERM_ce			clr_eol
184 # define	TERM_al			insert_line
185 # define	TERM_dl			delete_line
186 # define	TERM_ic			insert_character
187 # define	TERM_IC			parm_ich
188 # define	TERM_dc			delete_character
189 # define	TERM_DC			parm_dch
190 # define	TERM_cm			cursor_address
191 # define	TERM_ho			cursor_home
192 # define	TERM_cr			carriage_return
193 # define	TERM_nl			NULL
194 # define	TERM_sf			scroll_forward
195 # define	TERM_sr			scroll_reverse
196 # define	TERM_up			cursor_up
197 # define	TERM_UP			parm_up_cursor
198 # define	TERM_do			cursor_down
199 # define	TERM_DO			parm_down_cursor
200 # define	TERM_nd			cursor_right
201 # define	TERM_RI			parm_right_cursor
202 # define	TERM_le			cursor_left
203 # define	TERM_LE			parm_left_cursor
204 # define	TERM_ku			key_up
205 # define	TERM_kd			key_down
206 # define	TERM_kr			key_right
207 # define	TERM_kl			key_left
208 # define	TERM_kh			key_home
209 # define	TERM_kb			key_backspace
210 # define	TERM_l1			lab_f1
211 # define	TERM_l2			lab_f2
212 # define	TERM_l3			lab_f3
213 # define	TERM_l4			lab_f4
214 # define	TERM_l5			lab_f5
215 # define	TERM_l6			lab_f6
216 # define	TERM_l7			lab_f7
217 # define	TERM_l8			lab_f8
218 # define	TERM_l9			lab_f9
219 # define	TERM_la			lab_f10
220 # define	TERM_F1			key_f11
221 # define	TERM_F2			key_f12
222 # define	TERM_F3			key_f13
223 # define	TERM_F4			key_f14
224 # define	TERM_F5			key_f15
225 # define	TERM_F6			key_f16
226 # define	TERM_F7			key_f17
227 # define	TERM_F8			key_f18
228 # define	TERM_F9			key_f19
229 # define	TERM_FA			key_f20
230 # define	TERM_k1			key_f1
231 # define	TERM_k2			key_f2
232 # define	TERM_k3			key_f3
233 # define	TERM_k4			key_f4
234 # define	TERM_k5			key_f5
235 # define	TERM_k6			key_f6
236 # define	TERM_k7			key_f7
237 # define	TERM_k8			key_f8
238 # define	TERM_k9			key_f9
239 # define	TERM_k10		key_f10
240 # define	TERM_k0			key_f0
241 # define	TERM_kL			key_dl
242 # define	TERM_kA			key_il
243 # define	TERM_kD			key_dc
244 # define	TERM_kI			key_ic
245 # define	TERM_kC			key_clear
246 # define	TERM_kE			key_eol
247 # define	TERM_kP			key_ppage
248 # define	TERM_kN			key_npage
249 # define	TERM_at8		key_enter
250 # define	TERM_at1		key_beg
251 # define	TERM_at7		key_end
252 # else	/* !USETERMINFO */
253 extern int tgetent __P_((char *, char *));
254 extern int tgetnum __P_((char *));
255 extern int tgetflag __P_((char *));
256 extern char *tgetstr __P_((char *, char **));
257 extern char *tgoto __P_((char *, int, int));
258 extern int tputs __P_((char *, int, int (*)__P_((int))));
259 # define	tgetnum2		tgetnum
260 # define	tgetflag2		tgetflag
261 # define	tgoto2			tgoto
262 # define	TERM_pc			"pc"
263 # define	TERM_bc			"bc"
264 # define	TERM_co			"co"
265 # define	TERM_li			"li"
266 # define	TERM_xn			"xn"
267 # define	TERM_xs			"xs"
268 # define	TERM_ti			"ti"
269 # define	TERM_te			"te"
270 # define	TERM_mm			"mm"
271 # define	TERM_mo			"mo"
272 # define	TERM_cs			"cs"
273 # define	TERM_ks			"ks"
274 # define	TERM_ke			"ke"
275 # define	TERM_ve			"ve"
276 # define	TERM_vs			"vs"
277 # define	TERM_vi			"vi"
278 # define	TERM_sc			"sc"
279 # define	TERM_rc			"rc"
280 # define	TERM_bl			"bl"
281 # define	TERM_vb			"vb"
282 # define	TERM_cl			"cl"
283 # define	TERM_me			"me"
284 # define	TERM_md			"md"
285 # define	TERM_mr			"mr"
286 # define	TERM_mh			"mh"
287 # define	TERM_mb			"mb"
288 # define	TERM_so			"so"
289 # define	TERM_us			"us"
290 # define	TERM_se			"se"
291 # define	TERM_ue			"ue"
292 # define	TERM_ce			"ce"
293 # define	TERM_al			"al"
294 # define	TERM_dl			"dl"
295 # define	TERM_ic			"ic"
296 # define	TERM_IC			"IC"
297 # define	TERM_dc			"dc"
298 # define	TERM_DC			"DC"
299 # define	TERM_cm			"cm"
300 # define	TERM_ho			"ho"
301 # define	TERM_cr			"cr"
302 # define	TERM_nl			"nl"
303 # define	TERM_sf			"sf"
304 # define	TERM_sr			"sr"
305 # define	TERM_up			"up"
306 # define	TERM_UP			"UP"
307 # define	TERM_do			"do"
308 # define	TERM_DO			"DO"
309 # define	TERM_nd			"nd"
310 # define	TERM_RI			"RI"
311 # define	TERM_le			"le"
312 # define	TERM_LE			"LE"
313 # define	TERM_ku			"ku"
314 # define	TERM_kd			"kd"
315 # define	TERM_kr			"kr"
316 # define	TERM_kl			"kl"
317 # define	TERM_kh			"kh"
318 # define	TERM_kb			"kb"
319 # define	TERM_l1			"l1"
320 # define	TERM_l2			"l2"
321 # define	TERM_l3			"l3"
322 # define	TERM_l4			"l4"
323 # define	TERM_l5			"l5"
324 # define	TERM_l6			"l6"
325 # define	TERM_l7			"l7"
326 # define	TERM_l8			"l8"
327 # define	TERM_l9			"l9"
328 # define	TERM_la			"la"
329 # define	TERM_F1			"F1"
330 # define	TERM_F2			"F2"
331 # define	TERM_F3			"F3"
332 # define	TERM_F4			"F4"
333 # define	TERM_F5			"F5"
334 # define	TERM_F6			"F6"
335 # define	TERM_F7			"F7"
336 # define	TERM_F8			"F8"
337 # define	TERM_F9			"F9"
338 # define	TERM_FA			"FA"
339 # define	TERM_k1			"k1"
340 # define	TERM_k2			"k2"
341 # define	TERM_k3			"k3"
342 # define	TERM_k4			"k4"
343 # define	TERM_k5			"k5"
344 # define	TERM_k6			"k6"
345 # define	TERM_k7			"k7"
346 # define	TERM_k8			"k8"
347 # define	TERM_k9			"k9"
348 # define	TERM_k10		"k;"
349 # define	TERM_k0			"k0"
350 # define	TERM_kL			"kL"
351 # define	TERM_kA			"kA"
352 # define	TERM_kD			"kD"
353 # define	TERM_kI			"kI"
354 # define	TERM_kC			"kC"
355 # define	TERM_kE			"kE"
356 # define	TERM_kP			"kP"
357 # define	TERM_kN			"kN"
358 # define	TERM_at8		"@8"
359 # define	TERM_at1		"@1"
360 # define	TERM_at7		"@7"
361 # endif	/* !USETERMINFO */
362 
363 #define	BUFUNIT		16
364 #define	TERMCAPSIZE	2048
365 
366 #ifndef	PENDIN
367 #define	PENDIN		0
368 #endif
369 #ifndef	IEXTEN
370 #define	IEXTEN		0
371 #endif
372 #ifndef	ECHOCTL
373 #define	ECHOCTL		0
374 #endif
375 #ifndef	ECHOKE
376 #define	ECHOKE		0
377 #endif
378 #ifndef	OCRNL
379 #define	OCRNL		0
380 #endif
381 #ifndef	ONOCR
382 #define	ONOCR		0
383 #endif
384 #ifndef	ONLRET
385 #define	ONLRET		0
386 #endif
387 #ifndef	TAB3
388 #define	TAB3		OXTABS
389 #endif
390 #ifndef	VINTR
391 #define	VINTR		0
392 #endif
393 #ifndef	VQUIT
394 #define	VQUIT		1
395 #endif
396 #ifndef	VEOF
397 #define	VEOF		4
398 #endif
399 #ifndef	VEOL
400 #define	VEOL		5
401 #endif
402 #define	not(x)		(~(x) & 0xffff)
403 
404 #ifndef	FREAD
405 # ifdef	_FREAD
406 # define	FREAD	_FREAD
407 # else
408 # define	FREAD	(O_RDONLY + 1)
409 # endif
410 #endif
411 
412 #ifndef	FD_SET
413 typedef struct fd_set {
414 	int fds_bits[1];
415 } fd_set;
416 # define	FD_ZERO(p)	(((p) -> fds_bits[0]) = 0)
417 # define	FD_SET(n, p)	(((p) -> fds_bits[0]) |= (1 << (n)))
418 #endif
419 #endif	/* !MSDOS */
420 
421 #ifndef	LSI_C
422 #define	safe_dup	dup
423 #define	safe_dup2	dup2
424 #else
425 static int NEAR safe_dup __P_((int));
426 static int NEAR safe_dup2 __P_((int, int));
427 #endif
428 static int NEAR err2 __P_((char *));
429 static int NEAR defaultterm __P_((VOID_A));
430 static int NEAR maxlocate __P_((int *, int *));
431 #if	MSDOS
432 # ifdef	USEVIDEOBIOS
433 static int NEAR bioslocate __P_((int, int));
434 static int NEAR biosscroll __P_((int, int, int, int, int));
435 static int NEAR biosputch __P_((int, int));
436 static int NEAR bioscurstype __P_((int));
437 static int NEAR chgattr __P_((int));
438 static int NEAR evalcsi __P_((char *));
439 # endif
440 # if	!defined (DJGPP) || defined (NOTUSEBIOS) || defined (PC98)
441 static int NEAR dosgettime __P_((u_char []));
442 # endif
443 #else	/* !MSDOS */
444 # ifdef	USESGTTY
445 static int NEAR ttymode __P_((int, u_short, u_short, u_short, u_short));
446 # else
447 static int NEAR ttymode __P_((int, u_short, u_short, u_short, u_short,
448 		u_short, u_short, int, int));
449 # endif
450 static char *NEAR tgetstr2 __P_((char **, char *));
451 static char *NEAR tgetstr3 __P_((char **, char *, char *));
452 static char *NEAR tgetkeyseq __P_((int, char *));
453 static kstree_t *NEAR newkeyseq __P_((kstree_t *, int));
454 static int NEAR freekeyseq __P_((kstree_t *, int));
455 static int NEAR cmpkeyseq __P_((CONST VOID_P, CONST VOID_P));
456 static int NEAR sortkeyseq __P_((VOID_A));
457 # ifdef	DEBUG
458 static int NEAR freeterment __P_((VOID_A));
459 # endif
460 #endif	/* !MSDOS */
461 
462 #ifdef	LSI_C
463 extern u_char _openfile[];
464 #endif
465 #if	!MSDOS && !defined (USETERMINFO)
466 # ifdef	NOTERMVAR
467 # define	T_EXTERN
468 # else
469 # define	T_EXTERN	extern
470 # endif
471 T_EXTERN short ospeed;
472 T_EXTERN char PC;
473 T_EXTERN char *BC;
474 T_EXTERN char *UP;
475 #endif
476 int n_column = 0;
477 int n_lastcolumn = 0;
478 int n_line = 0;
479 int stable_standout = 0;
480 char *t_init = NULL;
481 char *t_end = NULL;
482 char *t_metamode = NULL;
483 char *t_nometamode = NULL;
484 char *t_scroll = NULL;
485 char *t_keypad = NULL;
486 char *t_nokeypad = NULL;
487 char *t_normalcursor = NULL;
488 char *t_highcursor = NULL;
489 char *t_nocursor = NULL;
490 char *t_setcursor = NULL;
491 char *t_resetcursor = NULL;
492 char *t_bell = NULL;
493 char *t_vbell = NULL;
494 char *t_clear = NULL;
495 char *t_normal = NULL;
496 char *t_bold = NULL;
497 char *t_reverse = NULL;
498 char *t_dim = NULL;
499 char *t_blink = NULL;
500 char *t_standout = NULL;
501 char *t_underline = NULL;
502 char *end_standout = NULL;
503 char *end_underline = NULL;
504 char *l_clear = NULL;
505 char *l_insert = NULL;
506 char *l_delete = NULL;
507 char *c_insert = NULL;
508 char *c_delete = NULL;
509 char *c_locate = NULL;
510 char *c_home = NULL;
511 char *c_return = NULL;
512 char *c_newline = NULL;
513 char *c_scrollforw = NULL;
514 char *c_scrollrev = NULL;
515 char *c_up = NULL;
516 char *c_down = NULL;
517 char *c_right = NULL;
518 char *c_left = NULL;
519 char *c_nup = NULL;
520 char *c_ndown = NULL;
521 char *c_nright = NULL;
522 char *c_nleft = NULL;
523 u_char cc_intr = CTRL('c');
524 u_char cc_quit = CTRL('\\');
525 #if	MSDOS
526 u_char cc_eof = CTRL('z');
527 #else
528 u_char cc_eof = CTRL('d');
529 #endif
530 u_char cc_eol = 255;
531 VOID_T (*keywaitfunc)__P_((VOID_A)) = NULL;
532 #if	!MSDOS
533 int usegetcursor = 0;
534 #endif
535 int ttyio = -1;
536 FILE *ttyout = NULL;
537 
538 #if	MSDOS
539 # ifdef	PC98
540 #define	KEYBUFWORKSEG	0x00
541 #define	KEYBUFWORKSIZ	0x20
542 #define	KEYBUFWORKMIN	0x502
543 #define	KEYBUFWORKMAX	0x522
544 #define	KEYBUFWORKTOP	0x524
545 #define	KEYBUFWORKEND	0x526
546 #define	KEYBUFWORKCNT	0x528
547 static u_char specialkey[] = "\032:=<;89>\25667bcdefghijk\202\203\204\205\206\207\210\211\212\213?";
548 static u_char metakey[] = "\035-+\037\022 !\"\027#$%/.\030\031\020\023\036\024\026,\021*\025)";
549 # else	/* !PC98 */
550 #define	KEYBUFWORKSEG	0x40
551 #define	KEYBUFWORKSIZ	0x20
552 #define	KEYBUFWORKMIN	getkeybuf(0x80)
553 #define	KEYBUFWORKMAX	(KEYBUFWORKMIN + KEYBUFWORKSIZ)
554 #define	KEYBUFWORKTOP	(KEYBUFWORKMIN - 4)
555 #define	KEYBUFWORKEND	(KEYBUFWORKMIN - 2)
556 static u_char specialkey[] = "\003HPMKRSGOIQ;<=>?@ABCDTUVWXYZ[\\]\206";
557 static u_char metakey[] = "\0360. \022!\"#\027$%&21\030\031\020\023\037\024\026/\021-\025,";
558 # endif	/* !PC98 */
559 # if	defined (PC98) || defined (NOTUSEBIOS)
560 static int nextchar = '\0';
561 # endif
562 # ifdef	NOTUSEBIOS
563 static u_short keybuftop = 0;
564 # endif
565 # ifdef	USEVIDEOBIOS
566 static u_short videoattr = 0x07;
567 # endif
568 static int specialkeycode[] = {
569 	0,
570 	K_UP, K_DOWN, K_RIGHT, K_LEFT,
571 	K_IC, K_DC, K_HOME, K_END, K_PPAGE, K_NPAGE,
572 	K_F(1), K_F(2), K_F(3), K_F(4), K_F(5),
573 	K_F(6), K_F(7), K_F(8), K_F(9), K_F(10),
574 	K_F(11), K_F(12), K_F(13), K_F(14), K_F(15),
575 	K_F(16), K_F(17), K_F(18), K_F(19), K_F(20), K_HELP
576 };
577 #define	SPECIALKEYSIZ	((int)(sizeof(specialkeycode) / sizeof(int)))
578 #else	/* !MSDOS */
579 static keyseq_t keyseq[K_MAX - K_MIN + 1];
580 static kstree_t *keyseqtree = NULL;
581 #endif	/* !MSDOS */
582 
583 #if	MSDOS || !defined (TIOCSTI)
584 static u_char ungetbuf[10];
585 static int ungetnum = 0;
586 #endif
587 
588 static int termflags = 0;
589 #define	F_INITTTY	001
590 #define	F_TERMENT	002
591 #define	F_INITTERM	004
592 #define	F_TTYCHANGED	010
593 #define	F_RESETTTY	(F_INITTTY | F_TTYCHANGED)
594 
595 
596 #ifdef	LSI_C
safe_dup(oldd)597 static int NEAR safe_dup(oldd)
598 int oldd;
599 {
600 	int fd;
601 
602 	if ((fd = dup(oldd)) < 0) return(-1);
603 	if (fd < SYS_OPEN && oldd >= 0 && oldd < SYS_OPEN)
604 		_openfile[fd] = _openfile[oldd];
605 	return(fd);
606 }
607 
safe_dup2(oldd,newd)608 static int NEAR safe_dup2(oldd, newd)
609 int oldd, newd;
610 {
611 	int fd;
612 
613 	if ((fd = dup2(oldd, newd)) < 0) return(-1);
614 	if (newd >= 0 && newd < SYS_OPEN && oldd >= 0 && oldd < SYS_OPEN)
615 		_openfile[newd] = _openfile[oldd];
616 	return(fd);
617 }
618 #endif	/* LSI_C */
619 
opentty(VOID_A)620 int opentty(VOID_A)
621 {
622 	if (ttyio < 0 && (ttyio = open(TTYNAME, O_RDWR, 0600)) < 0
623 	&& (ttyio = safe_dup(STDERR_FILENO)) < 0)
624 		err2(0);
625 	return(ttyio);
626 }
627 
628 #if	MSDOS
inittty(reset)629 int inittty(reset)
630 int reset;
631 {
632 	static int dupin = -1;
633 	static int dupout = -1;
634 	long l;
635 #ifndef	DJGPP
636 	static u_char dupbrk;
637 	union REGS reg;
638 #endif
639 
640 	opentty();
641 	if (reset && !(termflags & F_INITTTY)) return(0);
642 	if (!reset) {
643 #ifdef	NOTUSEBIOS
644 		if (!keybuftop) keybuftop = getkeybuf(KEYBUFWORKTOP);
645 #endif
646 #ifndef	DJGPP
647 		reg.x.ax = 0x3300;
648 		int86(0x21, &reg, &reg);
649 		dupbrk = reg.h.dl;
650 #endif
651 		if (((!(l = ftell(stdin)) || l == -1)
652 		&& ((dupin = safe_dup(STDIN_FILENO)) < 0
653 		|| safe_dup2(ttyio, STDIN_FILENO) < 0))
654 		|| ((!(l = ftell(stdout)) || l == -1)
655 		&& ((dupout = safe_dup(STDOUT_FILENO)) < 0
656 		|| safe_dup2(ttyio, STDOUT_FILENO) < 0)))
657 			err2(NULL);
658 		termflags |= F_INITTTY;
659 	}
660 	else {
661 #ifndef	DJGPP
662 		reg.x.ax = 0x3301;
663 		reg.h.dl = dupbrk;
664 		int86(0x21, &reg, &reg);
665 #endif
666 		if ((dupin >= 0 && safe_dup2(dupin, STDIN_FILENO) < 0)
667 		|| (dupout >= 0 && safe_dup2(dupout, STDOUT_FILENO) < 0)) {
668 			termflags &= ~F_INITTTY;
669 			err2(NULL);
670 		}
671 	}
672 	return(0);
673 }
674 
cooked2(VOID_A)675 int cooked2(VOID_A)
676 {
677 #ifndef	DJGPP
678 	union REGS reg;
679 
680 	reg.x.ax = 0x3301;
681 	reg.h.dl = 1;
682 	int86(0x21, &reg, &reg);
683 #endif
684 	return(0);
685 }
686 
cbreak2(VOID_A)687 int cbreak2(VOID_A)
688 {
689 #ifndef	DJGPP
690 	union REGS reg;
691 
692 	reg.x.ax = 0x3301;
693 	reg.h.dl = 0;
694 	int86(0x21, &reg, &reg);
695 #endif
696 	return(0);
697 }
698 
raw2(VOID_A)699 int raw2(VOID_A)
700 {
701 #ifndef	DJGPP
702 	union REGS reg;
703 
704 	reg.x.ax = 0x3301;
705 	reg.h.dl = 0;
706 	int86(0x21, &reg, &reg);
707 #endif
708 	return(0);
709 }
710 
echo2(VOID_A)711 int echo2(VOID_A)
712 {
713 	return(0);
714 }
715 
noecho2(VOID_A)716 int noecho2(VOID_A)
717 {
718 	return(0);
719 }
720 
nl2(VOID_A)721 int nl2(VOID_A)
722 {
723 	return(0);
724 }
725 
nonl2(VOID_A)726 int nonl2(VOID_A)
727 {
728 	return(0);
729 }
730 
tabs(VOID_A)731 int tabs(VOID_A)
732 {
733 	return(0);
734 }
735 
notabs(VOID_A)736 int notabs(VOID_A)
737 {
738 	return(0);
739 }
740 
keyflush(VOID_A)741 int keyflush(VOID_A)
742 {
743 	__dpmi_regs reg;
744 
745 	disable();
746 	reg.x.ax = 0x0c00;
747 	intdos2(&reg);
748 #ifdef	NOTUSEBIOS
749 	keybuftop = getkeybuf(KEYBUFWORKTOP);
750 #endif
751 	enable();
752 	return(0);
753 }
754 
755 #else	/* !MSDOS */
756 
inittty(reset)757 int inittty(reset)
758 int reset;
759 {
760 #ifdef	USESGTTY
761 	static int dupttyflag;
762 	struct tchars cc;
763 #endif
764 	static termioctl_t dupttyio;
765 	termioctl_t tty;
766 
767 	opentty();
768 	if (reset && (termflags & F_RESETTTY) != F_RESETTTY) return(0);
769 	if (tioctl(ttyio, REQGETP, &tty) < 0) {
770 		termflags &= ~F_INITTTY;
771 		close(ttyio);
772 		ttyio = -1;
773 		err2(NULL);
774 	}
775 	if (!reset) {
776 		memcpy((char *)&dupttyio, (char *)&tty, sizeof(termioctl_t));
777 #ifdef	USESGTTY
778 		if (tioctl(ttyio, TIOCLGET, &dupttyflag) < 0
779 		|| tioctl(ttyio, TIOCGETC, &cc) < 0) {
780 			termflags &= ~F_INITTTY;
781 			err2(NULL);
782 		}
783 		cc_intr = cc.t_intrc;
784 		cc_quit = cc.t_quitc;
785 		cc_eof = cc.t_eofc;
786 		cc_eol = cc.t_brkc;
787 #else
788 		cc_intr = dupttyio.c_cc[VINTR];
789 		cc_quit = dupttyio.c_cc[VQUIT];
790 		cc_eof = dupttyio.c_cc[VEOF];
791 		cc_eol = dupttyio.c_cc[VEOL];
792 #endif
793 #ifndef	USETERMINFO
794 		ospeed = getspeed(dupttyio);
795 #endif
796 		termflags |= F_INITTTY;
797 	}
798 	else if (tioctl(ttyio, REQSETP, &dupttyio) < 0
799 #ifdef	USESGTTY
800 	|| tioctl(ttyio, TIOCLSET, &dupttyflag) < 0
801 #endif
802 	) {
803 		termflags &= ~F_INITTTY;
804 		close(ttyio);
805 		ttyio = -1;
806 		err2(NULL);
807 	}
808 
809 	return(0);
810 }
811 
812 #ifdef	USESGTTY
ttymode(d,set,reset,lset,lreset)813 static int NEAR ttymode(d, set, reset, lset, lreset)
814 int d;
815 u_short set, reset, lset, lreset;
816 {
817 	termioctl_t tty;
818 	int lflag;
819 
820 	if (ioctl(d, TIOCLGET, &lflag) < 0) err2(NULL);
821 	if (tioctl(d, REQGETP, &tty) < 0) err2(NULL);
822 	if (set) tty.sg_flags |= set;
823 	if (reset) tty.sg_flags &= reset;
824 	if (set) lflag |= lset;
825 	if (lreset) lflag &= lreset;
826 	if (ioctl(d, TIOCLSET, &lflag) < 0) err2(NULL);
827 #else
828 static int NEAR ttymode(d, set, reset, iset, ireset, oset, oreset, vmin, vtime)
829 int d;
830 u_short set, reset, iset, ireset, oset, oreset;
831 int vmin, vtime;
832 {
833 	termioctl_t tty;
834 
835 	if (tioctl(d, REQGETP, &tty) < 0) err2(NULL);
836 	if (set) tty.c_lflag |= set;
837 	if (reset) tty.c_lflag &= reset;
838 	if (iset) tty.c_iflag |= iset;
839 	if (ireset) tty.c_iflag &= ireset;
840 	if (oset) tty.c_oflag |= oset;
841 	if (oreset) tty.c_oflag &= oreset;
842 	if (vmin) {
843 		tty.c_cc[VMIN] = vmin;
844 		tty.c_cc[VTIME] = vtime;
845 	}
846 #endif
847 	if (tioctl(d, REQSETP, &tty) < 0) err2(NULL);
848 	termflags |= F_TTYCHANGED;
849 	return(0);
850 }
851 
cooked2(VOID_A)852 int cooked2(VOID_A)
853 {
854 #ifdef	USESGTTY
855 	ttymode(ttyio, 0, not(CBREAK | RAW), LPASS8, not(LLITOUT | LPENDIN));
856 #else
857 	ttymode(ttyio, ISIG | ICANON | IEXTEN, not(PENDIN),
858 		BRKINT | IXON, not(IGNBRK | ISTRIP),
859 # if	(VEOF == VMIN) || (VEOL == VTIME)
860 		OPOST, 0, '\004', 255);
861 # else
862 		OPOST, 0, 0, 0);
863 # endif
864 #endif
865 	return(0);
866 }
867 
cbreak2(VOID_A)868 int cbreak2(VOID_A)
869 {
870 #ifdef	USESGTTY
871 	ttymode(ttyio, CBREAK, 0, LLITOUT, 0);
872 #else
873 	ttymode(ttyio, ISIG | IEXTEN, not(ICANON),
874 		BRKINT | IXON, not(IGNBRK), OPOST, 0, 1, 0);
875 #endif
876 	return(0);
877 }
878 
raw2(VOID_A)879 int raw2(VOID_A)
880 {
881 #ifdef	USESGTTY
882 	ttymode(ttyio, RAW, 0, LLITOUT, 0);
883 #else
884 	ttymode(ttyio, 0, not(ISIG | ICANON | IEXTEN),
885 		IGNBRK, not(BRKINT | IXON), 0, not(OPOST), 1, 0);
886 #endif
887 	return(0);
888 }
889 
echo2(VOID_A)890 int echo2(VOID_A)
891 {
892 #ifdef	USESGTTY
893 	ttymode(ttyio, ECHO, 0, LCRTBS | LCRTERA | LCRTKIL | LCTLECH, 0);
894 #else
895 	ttymode(ttyio, ECHO | ECHOE | ECHOCTL | ECHOKE, not(ECHONL),
896 		0, 0, 0, 0, 0, 0);
897 #endif
898 	return(0);
899 }
900 
noecho2(VOID_A)901 int noecho2(VOID_A)
902 {
903 #ifdef	USESGTTY
904 	ttymode(ttyio, 0, not(ECHO), 0, not(LCRTBS | LCRTERA));
905 #else
906 	ttymode(ttyio, 0, not(ECHO | ECHOE | ECHOK | ECHONL), 0, 0,
907 		0, 0, 0, 0);
908 #endif
909 	return(0);
910 }
911 
nl2(VOID_A)912 int nl2(VOID_A)
913 {
914 #ifdef	USESGTTY
915 	ttymode(ttyio, CRMOD, 0, 0, 0);
916 #else
917 	ttymode(ttyio, 0, 0, ICRNL, 0,
918 		ONLCR, not(OCRNL | ONOCR | ONLRET), 0, 0);
919 #endif
920 	return(0);
921 }
922 
nonl2(VOID_A)923 int nonl2(VOID_A)
924 {
925 #ifdef	USESGTTY
926 	ttymode(ttyio, 0, not(CRMOD), 0, 0);
927 #else
928 	ttymode(ttyio, 0, 0, 0, not(ICRNL), 0, not(ONLCR), 0, 0);
929 #endif
930 	return(0);
931 }
932 
tabs(VOID_A)933 int tabs(VOID_A)
934 {
935 #ifdef	USESGTTY
936 	ttymode(ttyio, 0, not(XTABS), 0, 0);
937 #else
938 	ttymode(ttyio, 0, 0, 0, 0, 0, not(TAB3), 0, 0);
939 #endif
940 	return(0);
941 }
942 
notabs(VOID_A)943 int notabs(VOID_A)
944 {
945 #ifdef	USESGTTY
946 	ttymode(ttyio, XTABS, 0, 0, 0);
947 #else
948 	ttymode(ttyio, 0, 0, 0, 0, TAB3, 0, 0, 0);
949 #endif
950 	return(0);
951 }
952 
keyflush(VOID_A)953 int keyflush(VOID_A)
954 {
955 #ifdef	USESGTTY
956 	int i = FREAD;
957 	tioctl(ttyio, TIOCFLUSH, &i);
958 #else	/* !USESGTTY */
959 # ifdef	USETERMIOS
960 	tcflush(ttyio, TCIFLUSH);
961 # else
962 	tioctl(ttyio, TCFLSH, 0);
963 # endif
964 #endif	/* !USESGTTY */
965 	return(0);
966 }
967 #endif	/* !MSDOS */
968 
ttyiomode(VOID_A)969 int ttyiomode(VOID_A)
970 {
971 	raw2();
972 	noecho2();
973 	nonl2();
974 	notabs();
975 	putterms(t_keypad);
976 	tflush();
977 	return(0);
978 }
979 
stdiomode(VOID_A)980 int stdiomode(VOID_A)
981 {
982 	cooked2();
983 	echo2();
984 	nl2();
985 	tabs();
986 	putterms(t_nokeypad);
987 	tflush();
988 	return(0);
989 }
990 
exit2(no)991 int exit2(no)
992 int no;
993 {
994 	if (termflags & F_TERMENT) putterm(t_normal);
995 	endterm();
996 	inittty(1);
997 	keyflush();
998 #ifdef	DEBUG
999 # if	!MSDOS
1000 	freeterment();
1001 # endif
1002 	if (ttyio >= 0) close(ttyio);
1003 	if (ttyout && ttyout != stdout) fclose(ttyout);
1004 	muntrace();
1005 #endif
1006 	exit(no);
1007 	return(0);
1008 }
1009 
err2(mes)1010 static int NEAR err2(mes)
1011 char *mes;
1012 {
1013 	int duperrno;
1014 
1015 	duperrno = errno;
1016 	if (termflags & F_INITTTY) {
1017 		if (termflags & F_TERMENT) putterm(t_normal);
1018 		endterm();
1019 		cooked2();
1020 		echo2();
1021 		nl2();
1022 		tabs();
1023 	}
1024 	fputs("\007\n", stderr);
1025 	errno = duperrno;
1026 	if (!mes) perror(TTYNAME);
1027 	else {
1028 		fputs(mes, stderr);
1029 		fputc('\n', stderr);
1030 	}
1031 	inittty(1);
1032 	exit(2);
1033 	return(0);
1034 }
1035 
defaultterm(VOID_A)1036 static int NEAR defaultterm(VOID_A)
1037 {
1038 #if	!MSDOS
1039 	int i;
1040 #endif
1041 
1042 	n_column = 80;
1043 #if	MSDOS
1044 	n_lastcolumn = 79;
1045 	n_line = 25;
1046 #else
1047 # ifndef	USETERMINFO
1048 	PC ='\0';
1049 	BC = "\010";
1050 	UP = "\033[A";
1051 # endif
1052 	n_lastcolumn = 80;
1053 	n_line = 24;
1054 #endif
1055 #ifdef	PC98
1056 	t_init = "\033[>1h";
1057 	t_end = "\033[>1l";
1058 	t_metamode = "\033)3";
1059 	t_nometamode = "\033)0";
1060 #else
1061 	t_init = "";
1062 	t_end = "";
1063 	t_metamode = "";
1064 	t_nometamode = "";
1065 #endif
1066 #if	MSDOS
1067 	t_scroll = "";
1068 	t_keypad = "";
1069 	t_nokeypad = "";
1070 	t_normalcursor = "\033[>5l";
1071 	t_highcursor = "\033[>5l";
1072 	t_nocursor = "\033[>5h";
1073 	t_setcursor = "\033[s";
1074 	t_resetcursor = "\033[u";
1075 #else	/* !MSDOS */
1076 	t_scroll = "\033[%i%d;%dr";
1077 # ifdef	BOW
1078 	/* hack for bowpad */
1079 	t_keypad = "";
1080 	t_nokeypad = "";
1081 	t_normalcursor = "";
1082 	t_highcursor = "";
1083 	t_nocursor = "";
1084 # else
1085 	t_keypad = "\033[?1h\033=";
1086 	t_nokeypad = "\033[?1l\033>";
1087 	t_normalcursor = "\033[?25h";
1088 	t_highcursor = "\033[?25h";
1089 	t_nocursor = "\033[?25l";
1090 # endif
1091 	t_setcursor = "\0337";
1092 	t_resetcursor = "\0338";
1093 #endif	/* !MSDOS */
1094 	t_bell = "\007";
1095 	t_vbell = "\007";
1096 	t_clear = "\033[;H\033[2J";
1097 	t_normal = "\033[m";
1098 	t_bold = "\033[1m";
1099 	t_reverse = "\033[7m";
1100 	t_dim = "\033[2m";
1101 	t_blink = "\033[5m";
1102 	t_standout = "\033[7m";
1103 	t_underline = "\033[4m";
1104 	end_standout = "\033[m";
1105 	end_underline = "\033[m";
1106 	l_clear = "\033[K";
1107 	l_insert = "\033[L";
1108 	l_delete = "\033[M";
1109 	c_insert = "";
1110 	c_delete = "";
1111 #ifdef	MSDOS
1112 	c_locate = "\033[%d;%dH";
1113 #else
1114 	c_locate = "\033[%i%d;%dH";
1115 #endif
1116 	c_home = "\033[H";
1117 	c_return = "\r";
1118 	c_newline = "\n";
1119 	c_scrollforw = "\n";
1120 	c_scrollrev = "";
1121 	c_up = "\033[A";
1122 	c_down = "\012";
1123 	c_right = "\033[C";
1124 	c_left = "\010";
1125 	c_nup = "\033[%dA";
1126 	c_ndown = "\033[%dB";
1127 	c_nright = "\033[%dC";
1128 	c_nleft = "\033[%dD";
1129 
1130 #if	!MSDOS
1131 	for (i = 0; i <= K_MAX - K_MIN; i++) keyseq[i].str = NULL;
1132 	keyseq[K_UP - K_MIN].str = "\033OA";
1133 	keyseq[K_DOWN - K_MIN].str = "\033OB";
1134 	keyseq[K_RIGHT - K_MIN].str = "\033OC";
1135 	keyseq[K_LEFT - K_MIN].str = "\033OD";
1136 	keyseq[K_HOME - K_MIN].str = "\033[4~";
1137 	keyseq[K_BS - K_MIN].str = "\010";
1138 	keyseq[K_F(1) - K_MIN].str = "\033[11~";
1139 	keyseq[K_F(2) - K_MIN].str = "\033[12~";
1140 	keyseq[K_F(3) - K_MIN].str = "\033[13~";
1141 	keyseq[K_F(4) - K_MIN].str = "\033[14~";
1142 	keyseq[K_F(5) - K_MIN].str = "\033[15~";
1143 	keyseq[K_F(6) - K_MIN].str = "\033[17~";
1144 	keyseq[K_F(7) - K_MIN].str = "\033[18~";
1145 	keyseq[K_F(8) - K_MIN].str = "\033[19~";
1146 	keyseq[K_F(9) - K_MIN].str = "\033[20~";
1147 	keyseq[K_F(10) - K_MIN].str = "\033[21~";
1148 	keyseq[K_F(11) - K_MIN].str = "\033[23~";
1149 	keyseq[K_F(12) - K_MIN].str = "\033[24~";
1150 	keyseq[K_F(13) - K_MIN].str = "\033[25~";
1151 	keyseq[K_F(14) - K_MIN].str = "\033[26~";
1152 	keyseq[K_F(15) - K_MIN].str = "\033[28~";
1153 	keyseq[K_F(16) - K_MIN].str = "\033[29~";
1154 	keyseq[K_F(17) - K_MIN].str = "\033[31~";
1155 	keyseq[K_F(18) - K_MIN].str = "\033[32~";
1156 	keyseq[K_F(19) - K_MIN].str = "\033[33~";
1157 	keyseq[K_F(20) - K_MIN].str = "\033[34~";
1158 	keyseq[K_F(21) - K_MIN].str = "\033OP";
1159 	keyseq[K_F(22) - K_MIN].str = "\033OQ";
1160 	keyseq[K_F(23) - K_MIN].str = "\033OR";
1161 	keyseq[K_F(24) - K_MIN].str = "\033OS";
1162 	keyseq[K_F(25) - K_MIN].str = "\033OT";
1163 	keyseq[K_F(26) - K_MIN].str = "\033OU";
1164 	keyseq[K_F(27) - K_MIN].str = "\033OV";
1165 	keyseq[K_F(28) - K_MIN].str = "\033OW";
1166 	keyseq[K_F(29) - K_MIN].str = "\033OX";
1167 	keyseq[K_F(30) - K_MIN].str = "\033OY";
1168 
1169 	keyseq[K_F('*') - K_MIN].str = "\033Oj";
1170 	keyseq[K_F('+') - K_MIN].str = "\033Ok";
1171 	keyseq[K_F(',') - K_MIN].str = "\033Ol";
1172 	keyseq[K_F('-') - K_MIN].str = "\033Om";
1173 	keyseq[K_F('.') - K_MIN].str = "\033On";
1174 	keyseq[K_F('/') - K_MIN].str = "\033Oo";
1175 	keyseq[K_F('0') - K_MIN].str = "\033Op";
1176 	keyseq[K_F('1') - K_MIN].str = "\033Oq";
1177 	keyseq[K_F('2') - K_MIN].str = "\033Or";
1178 	keyseq[K_F('3') - K_MIN].str = "\033Os";
1179 	keyseq[K_F('4') - K_MIN].str = "\033Ot";
1180 	keyseq[K_F('5') - K_MIN].str = "\033Ou";
1181 	keyseq[K_F('6') - K_MIN].str = "\033Ov";
1182 	keyseq[K_F('7') - K_MIN].str = "\033Ow";
1183 	keyseq[K_F('8') - K_MIN].str = "\033Ox";
1184 	keyseq[K_F('9') - K_MIN].str = "\033Oy";
1185 	keyseq[K_F('=') - K_MIN].str = "\033OX";
1186 	keyseq[K_F('?') - K_MIN].str = "\033OM";
1187 	keyseq[K_DL - K_MIN].str = "";
1188 	keyseq[K_IL - K_MIN].str = "";
1189 	keyseq[K_DC - K_MIN].str = "\177";
1190 	keyseq[K_IC - K_MIN].str = "\033[2~";
1191 	keyseq[K_CLR - K_MIN].str = "";
1192 	keyseq[K_PPAGE - K_MIN].str = "\033[5~";
1193 	keyseq[K_NPAGE - K_MIN].str = "\033[6~";
1194 	keyseq[K_ENTER - K_MIN].str = "\033[9~";
1195 	keyseq[K_END - K_MIN].str = "\033[1~";
1196 #endif	/* !MSDOS */
1197 	return(0);
1198 }
1199 
1200 #if	MSDOS && defined (USEVIDEOBIOS)
maxlocate(yp,xp)1201 static int NEAR maxlocate(yp, xp)
1202 int *yp, *xp;
1203 {
1204 	*xp = getbiosbyte(SCRWIDTH);
1205 	*yp = getbiosbyte(SCRHEIGHT) + 1;
1206 	return(0);
1207 }
1208 
getxy(yp,xp)1209 int getxy(yp, xp)
1210 int *yp, *xp;
1211 {
1212 	__dpmi_regs reg;
1213 
1214 	reg.x.ax = 0x0300;
1215 	reg.h.bh = getbiosbyte(CURRPAGE);
1216 	intbios(VIDEOBIOS, &reg);
1217 	*xp = reg.h.dl + 1;
1218 	*yp = reg.h.dh + 1;
1219 	return(0);
1220 }
1221 
1222 #else	/* !MSDOS || !USEVIDEOBIOS */
1223 
maxlocate(yp,xp)1224 static int NEAR maxlocate(yp, xp)
1225 int *yp, *xp;
1226 {
1227 	int i;
1228 # if	MSDOS
1229 	char *cp;
1230 
1231 	if (t_setcursor && t_resetcursor) putterms(t_setcursor);
1232 	if ((cp = tparamstr(c_locate, 0, 999))) {
1233 		for (i = 0; cp[i]; i++) bdos(0x06, cp[i], 0);
1234 		free(cp);
1235 	}
1236 	if ((cp = tparamstr(c_ndown, 999, 999))) {
1237 		for (i = 0; cp[i]; i++) bdos(0x06, cp[i], 0);
1238 		free(cp);
1239 	}
1240 # else
1241 	if (t_setcursor && t_resetcursor) putterms(t_setcursor);
1242 	locate(998, 998);
1243 	tflush();
1244 # endif
1245 	i = getxy(yp, xp);
1246 	if (t_setcursor && t_resetcursor) putterms(t_resetcursor);
1247 	return(i);
1248 }
1249 
getxy(yp,xp)1250 int getxy(yp, xp)
1251 int *yp, *xp;
1252 {
1253 	char *format, buf[sizeof(SIZEFMT) + 4];
1254 	int i, j, k, tmp, count, *val[2];
1255 
1256 	format = SIZEFMT;
1257 	keyflush();
1258 # if	MSDOS
1259 	for (i = 0; i < sizeof(GETSIZE) - 1; i++) bdos(0x06, GETSIZE[i], 0);
1260 # else
1261 	if (!usegetcursor) return(-1);
1262 	write(ttyio, GETSIZE, sizeof(GETSIZE) - 1);
1263 # endif
1264 
1265 	do {
1266 # if	MSDOS
1267 		buf[0] = bdos(0x07, 0x00, 0);
1268 # else
1269 	        buf[0] = getch2();
1270 # endif
1271 	} while (buf[0] != format[0]);
1272 	for (i = 1; i < sizeof(buf) - 1; i++) {
1273 # if	MSDOS
1274 		buf[i] = bdos(0x07, 0x00, 0);
1275 # else
1276 		buf[i] = getch2();
1277 # endif
1278 		if (buf[i] == format[sizeof(SIZEFMT) - 2]) break;
1279 	}
1280 	keyflush();
1281 	buf[++i] = '\0';
1282 
1283 	count = 0;
1284 	val[0] = yp;
1285 	val[1] = xp;
1286 
1287 	for (i = j = 0; format[i] && buf[j]; i++) {
1288 		if (format[i] == '%' && format[++i] == 'd' && count < 2) {
1289 			tmp = 0;
1290 			k = j;
1291 			for (; buf[j]; j++) {
1292 				if (!buf[j] || buf[j] == format[i + 1]) break;
1293 				tmp = tmp * 10 + buf[j] - '0';
1294 			}
1295 			if (j == k) break;
1296 			*val[count++] = tmp;
1297 		}
1298 		else if (format[i] != buf[j++]) break;
1299 	}
1300 	if (count != 2) return(-1);
1301 	return(0);
1302 }
1303 #endif	/* !MSDOS || !USEVIDEOBIOS */
1304 
1305 #if	MSDOS
tparamstr(s,arg1,arg2)1306 char *tparamstr(s, arg1, arg2)
1307 char *s;
1308 int arg1, arg2;
1309 {
1310 	char *cp, buf[MAXPRINTBUF + 1];
1311 
1312 	sprintf(buf, s, arg1, arg2);
1313 	if (!(cp = (char *)malloc(strlen(buf) + 1))) err2(NULL);
1314 	strcpy(cp, buf);
1315 	return(cp);
1316 }
1317 
getterment(VOID_A)1318 int getterment(VOID_A)
1319 {
1320 	if (termflags & F_TERMENT) return(-1);
1321 	defaultterm();
1322 	termflags |= F_TERMENT;
1323 	return(0);
1324 }
1325 
1326 #else	/* !MSDOS */
1327 
tparamstr(s,arg1,arg2)1328 char *tparamstr(s, arg1, arg2)
1329 char *s;
1330 int arg1, arg2;
1331 {
1332 	char *buf;
1333 # ifdef	USETERMINFO
1334 #  ifdef	DEBUG
1335 	if (!s) return(NULL);
1336 	_mtrace_file = "tparm(start)";
1337 	s = tparm(s, arg1, arg2, 0, 0, 0, 0, 0, 0, 0);
1338 	if (_mtrace_file) _mtrace_file = NULL;
1339 	else {
1340 		_mtrace_file = "tparm(end)";
1341 		malloc(0);	/* dummy alloc */
1342 	}
1343 	if (!s) return(NULL);
1344 #  else
1345 	if (!s || !(s = tparm(s, arg1, arg2, 0, 0, 0, 0, 0, 0, 0)))
1346 		return(NULL);
1347 #  endif
1348 	if (!(buf = (char *)malloc(strlen(s) + 1))) err2(NULL);
1349 	strcpy(buf, s);
1350 # else	/* USETERMINFO */
1351 	int i, j, n, sw, size, args[2];
1352 
1353 	if (!s) return(NULL);
1354 	if (!(buf = (char *)malloc(size = BUFUNIT))) err2(NULL);
1355 	args[0] = arg1;
1356 	args[1] = arg2;
1357 
1358 	for (i = j = n = 0; s[i]; i++) {
1359 		if (j + 5 >= size) {
1360 			size += BUFUNIT;
1361 			if (!(buf = (char *)realloc(buf, size))) err2(NULL);
1362 		}
1363 		if (s[i] != '%') buf[j++] = s[i];
1364 		else if (s[++i] == '%') buf[j++] = '%';
1365 		else if (n >= 2) {
1366 			free(buf);
1367 			return(NULL);
1368 		}
1369 		else switch (s[i]) {
1370 			case 'd':
1371 				sprintf(buf + j, "%d", args[n++]);
1372 				j += strlen(buf + j);
1373 				break;
1374 			case '2':
1375 				sprintf(buf + j, "%02d", args[n++]);
1376 				j += 2;
1377 				break;
1378 			case '3':
1379 				sprintf(buf + j, "%03d", args[n++]);
1380 				j += 3;
1381 				break;
1382 			case '.':
1383 				sprintf(buf + (j++), "%c", args[n++]);
1384 				break;
1385 			case '+':
1386 				if (!s[++i]) {
1387 					free(buf);
1388 					return(NULL);
1389 				}
1390 				sprintf(buf + (j++), "%c", args[n++] + s[i]);
1391 				break;
1392 			case '>':
1393 				if (!s[++i] || !s[i + 1]) {
1394 					free(buf);
1395 					return(NULL);
1396 				}
1397 				if (args[n] > s[i++]) args[n] += s[i];
1398 				break;
1399 			case 'r':
1400 				sw = args[0];
1401 				args[0] = args[1];
1402 				args[1] = sw;
1403 				break;
1404 			case 'i':
1405 				args[0]++;
1406 				args[1]++;
1407 				break;
1408 			case 'n':
1409 				args[0] ^= 0140;
1410 				args[1] ^= 0140;
1411 				break;
1412 			case 'B':
1413 				args[n] = ((args[n] / 10) << 4)
1414 					| (args[n] % 10);
1415 				break;
1416 			case 'D':
1417 				args[n] -= 2 * (args[n] % 16);
1418 				break;
1419 			default:
1420 				free(buf);
1421 				return(NULL);
1422 /*NOTREACHED*/
1423 				break;
1424 		}
1425 	}
1426 
1427 	buf[j] = '\0';
1428 # endif	/* USETERMINFO */
1429 	return(buf);
1430 }
1431 
tgetstr2(term,s)1432 static char *NEAR tgetstr2(term, s)
1433 char **term, *s;
1434 {
1435 # ifndef	USETERMINFO
1436 	char strbuf[TERMCAPSIZE];
1437 	char *p;
1438 
1439 	p = strbuf;
1440 	s = tgetstr(s, &p);
1441 # endif
1442 	if (s || (s = *term)) {
1443 		if (!(*term = (char *)malloc(strlen(s) + 1))) err2(NULL);
1444 		strcpy(*term, s);
1445 	}
1446 	return(*term);
1447 }
1448 
tgetstr3(term,str1,str2)1449 static char *NEAR tgetstr3(term, str1, str2)
1450 char **term, *str1, *str2;
1451 {
1452 # ifdef	USETERMINFO
1453 	if (!str1 && (str1 = tparamstr(str2, 1, 1))) *term = str1;
1454 # else
1455 	char strbuf[TERMCAPSIZE];
1456 	char *p;
1457 
1458 	p = strbuf;
1459 	if (!(str1 = tgetstr(str1, &p))
1460 	&& (str1 = tparamstr(tgetstr(str2, &p), 1, 1))) *term = str1;
1461 # endif
1462 	else if (str1 || (str1 = *term)) {
1463 		if (!(*term = (char *)malloc(strlen(str1) + 1))) err2(NULL);
1464 		strcpy(*term, str1);
1465 	}
1466 	return(*term);
1467 }
1468 
tgetkeyseq(n,s)1469 static char *NEAR tgetkeyseq(n, s)
1470 int n;
1471 char *s;
1472 {
1473 	char *cp;
1474 	int i, j;
1475 
1476 	n -= K_MIN;
1477 	cp = NULL;
1478 	if (!tgetstr2(&cp, s)) return(NULL);
1479 	if (keyseq[n].str) {
1480 		free(keyseq[n].str);
1481 		keyseq[n].str = NULL;
1482 	}
1483 	for (i = 0; i <= K_MAX - K_MIN; i++) {
1484 		if (!(keyseq[i].str)) continue;
1485 		for (j = 0; cp[j]; j++)
1486 			if ((cp[j] & 0x7f) != (keyseq[i].str[j] & 0x7f))
1487 				break;
1488 		if (!cp[j]) {
1489 			free(keyseq[i].str);
1490 			keyseq[i].str = NULL;
1491 		}
1492 	}
1493 	keyseq[n].str = cp;
1494 	return(cp);
1495 }
1496 
newkeyseq(parent,num)1497 static kstree_t *NEAR newkeyseq(parent, num)
1498 kstree_t *parent;
1499 int num;
1500 {
1501 	kstree_t *new;
1502 	int i, n;
1503 
1504 	if (!parent || !(parent -> next))
1505 		new = (kstree_t *)malloc(sizeof(kstree_t) * num);
1506 	else new = (kstree_t *)realloc(parent -> next, sizeof(kstree_t) * num);
1507 	if (!new) err2(NULL);
1508 
1509 	if (!parent) n = 0;
1510 	else {
1511 		n = parent -> num;
1512 		parent -> num = num;
1513 		parent -> next = new;
1514 	}
1515 
1516 	for (i = n; i < num; i++) {
1517 		new[i].key = -1;
1518 		new[i].num = 0;
1519 		new[i].next = (kstree_t *)NULL;
1520 	}
1521 
1522 	return(new);
1523 }
1524 
freekeyseq(list,n)1525 static int NEAR freekeyseq(list, n)
1526 kstree_t *list;
1527 int n;
1528 {
1529 	int i;
1530 
1531 	if (!list) return(-1);
1532 	for (i = list[n].num - 1; i >= 0; i--) freekeyseq(list[n].next, i);
1533 	if (!n) free(list);
1534 	return(0);
1535 }
1536 
cmpkeyseq(vp1,vp2)1537 static int NEAR cmpkeyseq(vp1, vp2)
1538 CONST VOID_P vp1;
1539 CONST VOID_P vp2;
1540 {
1541 	if (!((keyseq_t *)vp1) -> str) return(-1);
1542 	if (!((keyseq_t *)vp2) -> str) return(1);
1543 	return(strcmp(((keyseq_t *)vp1) -> str, ((keyseq_t *)vp2) -> str));
1544 }
1545 
sortkeyseq(VOID_A)1546 static int NEAR sortkeyseq(VOID_A)
1547 {
1548 	kstree_t *p;
1549 	int i, j, k;
1550 
1551 	qsort(keyseq, K_MAX - K_MIN + 1, sizeof(keyseq_t), cmpkeyseq);
1552 	if (keyseqtree) freekeyseq(keyseqtree, 0);
1553 
1554 	keyseqtree = newkeyseq(NULL, 1);
1555 
1556 	for (i = 0; i <= K_MAX - K_MIN; i++) {
1557 		p = keyseqtree;
1558 		for (j = 0; j < keyseq[i].len; j++) {
1559 			for (k = 0; k < p -> num; k++) {
1560 				if (keyseq[i].str[j]
1561 				== keyseq[p -> next[k].key].str[j]) break;
1562 			}
1563 			if (k >= p -> num) {
1564 				newkeyseq(p, k + 1);
1565 				p -> next[k].key = i;
1566 			}
1567 			p = &(p -> next[k]);
1568 		}
1569 	}
1570 
1571 	return(0);
1572 }
1573 
getterment(VOID_A)1574 int getterment(VOID_A)
1575 {
1576 	char *cp, *terminalname, buf[TERMCAPSIZE];
1577 	int i, j;
1578 
1579 	if (termflags & F_TERMENT) return(-1);
1580 	if (!(ttyout = fdopen(ttyio, "w+"))) ttyout = stdout;
1581 	if (!(terminalname = (char *)getenv("TERM"))) terminalname = "unknown";
1582 # ifdef	USETERMINFO
1583 #  ifdef	DEBUG
1584 	_mtrace_file = "setupterm(start)";
1585 	setupterm(terminalname, fileno(ttyout), &i);
1586 	if (_mtrace_file) _mtrace_file = NULL;
1587 	else {
1588 		_mtrace_file = "setupterm(end)";
1589 		malloc(0);	/* dummy alloc */
1590 	}
1591 #  else
1592 	setupterm(terminalname, fileno(ttyout), &i);
1593 #  endif
1594 	if (i != 1) err2("No TERMINFO is prepared");
1595 	defaultterm();
1596 # else	/* !USETERMINFO */
1597 #  ifdef	DEBUG
1598 	_mtrace_file = "tgetent(start)";
1599 	i = tgetent(buf, terminalname);
1600 	if (_mtrace_file) _mtrace_file = NULL;
1601 	else {
1602 		_mtrace_file = "tgetent(end)";
1603 		malloc(0);	/* dummy malloc */
1604 	}
1605 	if (i <= 0) err2("No TERMCAP is prepared");
1606 #  else
1607 	if (tgetent(buf, terminalname) <= 0) err2("No TERMCAP is prepared");
1608 #  endif
1609 
1610 	defaultterm();
1611 	cp = "";
1612 	tgetstr2(&cp, TERM_pc);
1613 	PC = *cp;
1614 	free(cp);
1615 	tgetstr2(&BC, TERM_bc);
1616 	tgetstr2(&UP, TERM_up);
1617 # endif
1618 
1619 	cp = NULL;
1620 	if (tgetstr2(&cp, TERM_ku) || tgetstr2(&cp, TERM_kd)
1621 	|| tgetstr2(&cp, TERM_kr) || tgetstr2(&cp, TERM_kl)) {
1622 		free(cp);
1623 		t_keypad = t_nokeypad = "";
1624 		keyseq[K_UP - K_MIN].str =
1625 		keyseq[K_DOWN - K_MIN].str =
1626 		keyseq[K_RIGHT - K_MIN].str =
1627 		keyseq[K_LEFT - K_MIN].str = NULL;
1628 	}
1629 
1630 	n_column = n_lastcolumn = tgetnum2(TERM_co);
1631 	n_line = tgetnum2(TERM_li);
1632 	if (!tgetflag2(TERM_xn)) n_lastcolumn--;
1633 	stable_standout = tgetflag2(TERM_xs);
1634 	tgetstr2(&t_init, TERM_ti);
1635 	tgetstr2(&t_end, TERM_te);
1636 	tgetstr2(&t_metamode, TERM_mm);
1637 	tgetstr2(&t_nometamode, TERM_mo);
1638 	tgetstr2(&t_scroll, TERM_cs);
1639 	tgetstr2(&t_keypad, TERM_ks);
1640 	tgetstr2(&t_nokeypad, TERM_ke);
1641 	tgetstr2(&t_normalcursor, TERM_ve);
1642 	tgetstr2(&t_highcursor, TERM_vs);
1643 	tgetstr2(&t_nocursor, TERM_vi);
1644 	tgetstr2(&t_setcursor, TERM_sc);
1645 	tgetstr2(&t_resetcursor, TERM_rc);
1646 	tgetstr2(&t_bell, TERM_bl);
1647 	tgetstr2(&t_vbell, TERM_vb);
1648 	tgetstr2(&t_clear, TERM_cl);
1649 	tgetstr2(&t_normal, TERM_me);
1650 	tgetstr2(&t_bold, TERM_md);
1651 	tgetstr2(&t_reverse, TERM_mr);
1652 	tgetstr2(&t_dim, TERM_mh);
1653 	tgetstr2(&t_blink, TERM_mb);
1654 	tgetstr2(&t_standout, TERM_so);
1655 	tgetstr2(&t_underline, TERM_us);
1656 	tgetstr2(&end_standout, TERM_se);
1657 	tgetstr2(&end_underline, TERM_ue);
1658 	tgetstr2(&l_clear, TERM_ce);
1659 	tgetstr2(&l_insert, TERM_al);
1660 	tgetstr2(&l_delete, TERM_dl);
1661 	tgetstr3(&c_insert, TERM_ic, TERM_IC);
1662 	tgetstr3(&c_delete, TERM_dc, TERM_DC);
1663 	tgetstr2(&c_locate, TERM_cm);
1664 	tgetstr2(&c_home, TERM_ho);
1665 	tgetstr2(&c_return, TERM_cr);
1666 	tgetstr2(&c_newline, TERM_nl);
1667 	tgetstr2(&c_scrollforw, TERM_sf);
1668 	tgetstr2(&c_scrollrev, TERM_sr);
1669 	tgetstr3(&c_up, TERM_up, TERM_UP);
1670 	tgetstr3(&c_down, TERM_do, TERM_DO);
1671 	tgetstr3(&c_right, TERM_nd, TERM_RI);
1672 	tgetstr3(&c_left, TERM_le, TERM_LE);
1673 	tgetstr2(&c_nup, TERM_UP);
1674 	tgetstr2(&c_ndown, TERM_DO);
1675 	tgetstr2(&c_nright, TERM_RI);
1676 	tgetstr2(&c_nleft, TERM_LE);
1677 
1678 	for (i = 0; i <= K_MAX - K_MIN; i++) if (keyseq[i].str) {
1679 		cp = (char *)malloc(strlen(keyseq[i].str) + 1);
1680 		if (!cp) err2(NULL);
1681 		strcpy(cp, keyseq[i].str);
1682 		keyseq[i].str = cp;
1683 	}
1684 
1685 	tgetkeyseq(K_UP, TERM_ku);
1686 	tgetkeyseq(K_DOWN, TERM_kd);
1687 	tgetkeyseq(K_RIGHT, TERM_kr);
1688 	tgetkeyseq(K_LEFT, TERM_kl);
1689 	tgetkeyseq(K_HOME, TERM_kh);
1690 	tgetkeyseq(K_BS, TERM_kb);
1691 	tgetkeyseq(K_F(1), TERM_l1);
1692 	tgetkeyseq(K_F(2), TERM_l2);
1693 	tgetkeyseq(K_F(3), TERM_l3);
1694 	tgetkeyseq(K_F(4), TERM_l4);
1695 	tgetkeyseq(K_F(5), TERM_l5);
1696 	tgetkeyseq(K_F(6), TERM_l6);
1697 	tgetkeyseq(K_F(7), TERM_l7);
1698 	tgetkeyseq(K_F(8), TERM_l8);
1699 	tgetkeyseq(K_F(9), TERM_l9);
1700 	tgetkeyseq(K_F(10), TERM_la);
1701 	tgetkeyseq(K_F(11), TERM_F1);
1702 	tgetkeyseq(K_F(12), TERM_F2);
1703 	tgetkeyseq(K_F(13), TERM_F3);
1704 	tgetkeyseq(K_F(14), TERM_F4);
1705 	tgetkeyseq(K_F(15), TERM_F5);
1706 	tgetkeyseq(K_F(16), TERM_F6);
1707 	tgetkeyseq(K_F(17), TERM_F7);
1708 	tgetkeyseq(K_F(18), TERM_F8);
1709 	tgetkeyseq(K_F(19), TERM_F9);
1710 	tgetkeyseq(K_F(20), TERM_FA);
1711 	tgetkeyseq(K_F(21), TERM_k1);
1712 	tgetkeyseq(K_F(22), TERM_k2);
1713 	tgetkeyseq(K_F(23), TERM_k3);
1714 	tgetkeyseq(K_F(24), TERM_k4);
1715 	tgetkeyseq(K_F(25), TERM_k5);
1716 	tgetkeyseq(K_F(26), TERM_k6);
1717 	tgetkeyseq(K_F(27), TERM_k7);
1718 	tgetkeyseq(K_F(28), TERM_k8);
1719 	tgetkeyseq(K_F(29), TERM_k9);
1720 	tgetkeyseq(K_F(30), TERM_k10);
1721 	tgetkeyseq(K_F(30), TERM_k0);
1722 	tgetkeyseq(K_DL, TERM_kL);
1723 	tgetkeyseq(K_IL, TERM_kA);
1724 	tgetkeyseq(K_DC, TERM_kD);
1725 	tgetkeyseq(K_IC, TERM_kI);
1726 	tgetkeyseq(K_CLR, TERM_kC);
1727 	tgetkeyseq(K_EOL, TERM_kE);
1728 	tgetkeyseq(K_PPAGE, TERM_kP);
1729 	tgetkeyseq(K_NPAGE, TERM_kN);
1730 	tgetkeyseq(K_ENTER, TERM_at8);
1731 	tgetkeyseq(K_BEG, TERM_at1);
1732 	tgetkeyseq(K_END, TERM_at7);
1733 
1734 	for (i = 0; i <= K_MAX - K_MIN; i++) keyseq[i].code = K_MIN + i;
1735 	for (i = 21; i <= 30; i++)
1736 		keyseq[K_F(i) - K_MIN].code = K_F(i - 20) & 01000;
1737 	for (i = 31; K_F(i) < K_DL; i++)
1738 		if (keyseq[K_F(i) - K_MIN].str)
1739 			keyseq[K_F(i) - K_MIN].code = i;
1740 	keyseq[K_F('?') - K_MIN].code = K_CR;
1741 
1742 	for (i = 0; i <= K_MAX - K_MIN; i++) {
1743 		if (!(keyseq[i].str)) keyseq[i].len = 0;
1744 		else {
1745 			for (j = 0; keyseq[i].str[j]; j++)
1746 				keyseq[i].str[j] &= 0x7f;
1747 			keyseq[i].len = j;
1748 		}
1749 	}
1750 	sortkeyseq();
1751 
1752 	termflags |= F_TERMENT;
1753 	return(0);
1754 }
1755 
1756 # ifdef	DEBUG
freeterment(VOID_A)1757 static int NEAR freeterment(VOID_A)
1758 {
1759 	int i;
1760 
1761 	if (!(termflags & F_TERMENT)) return(-1);
1762 
1763 #  ifndef	USETERMINFO
1764 	if (BC) free(BC);
1765 	if (UP) free(UP);
1766 #  endif
1767 	if (t_init) free(t_init);
1768 	if (t_end) free(t_end);
1769 	if (t_metamode) free(t_metamode);
1770 	if (t_nometamode) free(t_nometamode);
1771 	if (t_scroll) free(t_scroll);
1772 	if (t_keypad) free(t_keypad);
1773 	if (t_nokeypad) free(t_nokeypad);
1774 	if (t_normalcursor) free(t_normalcursor);
1775 	if (t_highcursor) free(t_highcursor);
1776 	if (t_nocursor) free(t_nocursor);
1777 	if (t_setcursor) free(t_setcursor);
1778 	if (t_resetcursor) free(t_resetcursor);
1779 	if (t_bell) free(t_bell);
1780 	if (t_vbell) free(t_vbell);
1781 	if (t_clear) free(t_clear);
1782 	if (t_normal) free(t_normal);
1783 	if (t_bold) free(t_bold);
1784 	if (t_reverse) free(t_reverse);
1785 	if (t_dim) free(t_dim);
1786 	if (t_blink) free(t_blink);
1787 	if (t_standout) free(t_standout);
1788 	if (t_underline) free(t_underline);
1789 	if (end_standout) free(end_standout);
1790 	if (end_underline) free(end_underline);
1791 	if (l_clear) free(l_clear);
1792 	if (l_insert) free(l_insert);
1793 	if (l_delete) free(l_delete);
1794 	if (c_insert) free(c_insert);
1795 	if (c_delete) free(c_delete);
1796 	if (c_locate) free(c_locate);
1797 	if (c_home) free(c_home);
1798 	if (c_return) free(c_return);
1799 	if (c_newline) free(c_newline);
1800 	if (c_scrollforw) free(c_scrollforw);
1801 	if (c_scrollrev) free(c_scrollrev);
1802 	if (c_up) free(c_up);
1803 	if (c_down) free(c_down);
1804 	if (c_right) free(c_right);
1805 	if (c_left) free(c_left);
1806 	if (c_nup) free(c_nup);
1807 	if (c_ndown) free(c_ndown);
1808 	if (c_nright) free(c_nright);
1809 	if (c_nleft) free(c_nleft);
1810 
1811 	for (i = 0; i <= K_MAX - K_MIN; i++)
1812 		if (keyseq[i].str) free(keyseq[i].str);
1813 	if (keyseqtree) freekeyseq(keyseqtree, 0);
1814 
1815 	termflags &= ~F_TERMENT;
1816 	return(0);
1817 }
1818 # endif	/* DEBUG */
1819 
setkeyseq(n,str,len)1820 int setkeyseq(n, str, len)
1821 int n;
1822 char *str;
1823 int len;
1824 {
1825 	int i;
1826 
1827 	for (i = 0; i <= K_MAX - K_MIN; i++) if (keyseq[i].code == n) {
1828 		if (keyseq[i].str) free(keyseq[i].str);
1829 		keyseq[i].str = str;
1830 		keyseq[i].len = len;
1831 		break;
1832 	}
1833 	if (i > K_MAX - K_MIN) return(-1);
1834 
1835 	if (str) for (i = 0; i <= K_MAX - K_MIN; i++) {
1836 		if ((keyseq[i].code & 0777) == n
1837 		|| !(keyseq[i].str) || keyseq[i].len != len)
1838 			continue;
1839 		if (!memcmp(str, keyseq[i].str, len)) {
1840 			free(keyseq[i].str);
1841 			keyseq[i].str = NULL;
1842 			keyseq[i].len = 0;
1843 		}
1844 	}
1845 	sortkeyseq();
1846 	return(0);
1847 }
1848 
getkeyseq(n,lenp)1849 char *getkeyseq(n, lenp)
1850 int n, *lenp;
1851 {
1852 	int i;
1853 
1854 	for (i = 0; i <= K_MAX - K_MIN; i++) if (keyseq[i].code == n) {
1855 		if (lenp) *lenp = keyseq[i].len;
1856 		return((keyseq[i].str) ? keyseq[i].str : "");
1857 	}
1858 	if (lenp) *lenp = 0;
1859 	return(NULL);
1860 }
1861 #endif	/* !MSDOS */
1862 
initterm(VOID_A)1863 int initterm(VOID_A)
1864 {
1865 	if (!(termflags & F_TERMENT)) getterment();
1866 	putterms(t_keypad);
1867 	putterms(t_init);
1868 	tflush();
1869 	termflags |= F_INITTERM;
1870 	return(0);
1871 }
1872 
endterm(VOID_A)1873 int endterm(VOID_A)
1874 {
1875 	if (!(termflags & F_INITTERM)) return(-1);
1876 	putterms(t_nokeypad);
1877 	putterms(t_end);
1878 	tflush();
1879 	termflags &= ~F_INITTERM;
1880 	return(0);
1881 }
1882 
1883 #if	MSDOS
1884 # ifdef	USEVIDEOBIOS
bioslocate(x,y)1885 static int NEAR bioslocate(x, y)
1886 int x, y;
1887 {
1888 	__dpmi_regs reg;
1889 
1890 	reg.x.ax = 0x0200;
1891 	reg.h.bh = getbiosbyte(CURRPAGE);
1892 	reg.h.dh = y - 1;
1893 	reg.h.dl = x - 1;
1894 	intbios(VIDEOBIOS, &reg);
1895 	return(0);
1896 }
1897 
biosscroll(d,sx,sy,ex,ey)1898 static int NEAR biosscroll(d, sx, sy, ex, ey)
1899 int d, sx, sy, ex, ey;
1900 {
1901 	__dpmi_regs reg;
1902 
1903 	if (sx > ex || sy > ey) return(0);
1904 	if (d >= 0) {
1905 		reg.h.ah = 0x06;
1906 		reg.h.al = d;
1907 	}
1908 	else {
1909 		reg.h.ah = 0x07;
1910 		reg.h.al = -d;
1911 	}
1912 	reg.h.bh = videoattr;
1913 	reg.h.ch = sy - 1;
1914 	reg.h.cl = sx - 1;
1915 	reg.h.dh = ey - 1;
1916 	reg.h.dl = ex - 1;
1917 	intbios(VIDEOBIOS, &reg);
1918 	return(0);
1919 }
1920 
biosputch(c,n)1921 static int NEAR biosputch(c, n)
1922 int c, n;
1923 {
1924 	__dpmi_regs reg;
1925 
1926 	reg.h.ah = 0x09;
1927 	reg.h.al = (c & 0xff);
1928 	reg.h.bh = getbiosbyte(CURRPAGE);
1929 	reg.h.bl = videoattr;
1930 	reg.x.cx = n;
1931 	intbios(VIDEOBIOS, &reg);
1932 	return(c);
1933 }
1934 
bioscurstype(n)1935 static int NEAR bioscurstype(n)
1936 int n;
1937 {
1938 	__dpmi_regs reg;
1939 
1940 	reg.x.ax = 0x0300;
1941 	reg.h.bh = getbiosbyte(CURRPAGE);
1942 	intbios(VIDEOBIOS, &reg);
1943 	reg.x.ax = 0x0100;
1944 	reg.x.cx &= 0x1f1f;
1945 	reg.x.cx |= (n & 0x6000);
1946 	intbios(VIDEOBIOS, &reg);
1947 	return(0);
1948 }
1949 
putch2(c)1950 int putch2(c)
1951 int c;
1952 {
1953 	static int needscroll = 0;
1954 	int n, x, y, w, h;
1955 
1956 	if (c == '\007') {
1957 		bdos(0x06, '\007', 0);
1958 		return(c);
1959 	}
1960 
1961 	getxy(&y, &x);
1962 	w = getbiosbyte(SCRWIDTH);
1963 	h = getbiosbyte(SCRHEIGHT) + 1;
1964 
1965 	if (c == '\b') {
1966 		if (x > 1) x--;
1967 		needscroll = 0;
1968 	}
1969 	else if (c == '\t') {
1970 		if (x >= w && y >= h && needscroll) {
1971 			x = 1;
1972 			biosscroll(1, 1, 1, w, h);
1973 			bioslocate(x, y);
1974 		}
1975 		needscroll = 0;
1976 
1977 		n = 8 - ((x - 1) % 8);
1978 		if (x + n <= w) x += n;
1979 		else {
1980 			n = w - x + 1;
1981 			x = 1;
1982 			if (y < h) y++;
1983 			else {
1984 				x = w;
1985 				needscroll = 1;
1986 			}
1987 		}
1988 		biosputch(' ', n);
1989 	}
1990 	else if (c == '\r') {
1991 		x = 1;
1992 		needscroll = 0;
1993 	}
1994 	else if (c == '\n') {
1995 		if (y < h) y++;
1996 		else biosscroll(1, 1, 1, w, h);
1997 		needscroll = 0;
1998 	}
1999 	else {
2000 		if (x >= w && y >= h && needscroll) {
2001 			x = 1;
2002 			biosscroll(1, 1, 1, w, h);
2003 			bioslocate(x, y);
2004 		}
2005 		needscroll = 0;
2006 
2007 		if (x < w) x++;
2008 		else {
2009 			x = 1;
2010 			if (y < h) y++;
2011 			else {
2012 				x = w;
2013 				needscroll = 1;
2014 			}
2015 		}
2016 		biosputch(c, 1);
2017 	}
2018 
2019 	bioslocate(x, y);
2020 	return(c);
2021 }
2022 
chgattr(n)2023 static int NEAR chgattr(n)
2024 int n;
2025 {
2026 	switch (n) {
2027 		case 0:
2028 			videoattr = 0x07;
2029 			break;
2030 		case 1:
2031 			videoattr |= 0x08;
2032 			break;
2033 		case 4:
2034 			videoattr &= 0xf0;
2035 			videoattr |= 0x01;
2036 			break;
2037 		case 5:
2038 			videoattr |= 0x80;
2039 			break;
2040 		case 7:
2041 			videoattr = 0x70;
2042 			break;
2043 		case 8:
2044 			videoattr = 0x08;
2045 			break;
2046 		case 30:
2047 		case 31:
2048 		case 32:
2049 		case 33:
2050 		case 34:
2051 		case 35:
2052 		case 36:
2053 		case 37:
2054 			videoattr &= 0xf0;
2055 			n -= 30;
2056 			if (n & 1) videoattr |= 0x04;
2057 			if (n & 2) videoattr |= 0x02;
2058 			if (n & 4) videoattr |= 0x01;
2059 			break;
2060 		case 40:
2061 		case 41:
2062 		case 42:
2063 		case 43:
2064 		case 44:
2065 		case 45:
2066 		case 46:
2067 		case 47:
2068 			videoattr &= 0x0f;
2069 			n -= 40;
2070 			if (n & 1) videoattr |= 0x40;
2071 			if (n & 2) videoattr |= 0x20;
2072 			if (n & 4) videoattr |= 0x10;
2073 			break;
2074 		default:
2075 			break;
2076 	}
2077 
2078 	return(videoattr);
2079 }
2080 
evalcsi(s)2081 static int NEAR evalcsi(s)
2082 char *s;
2083 {
2084 	static int savex, savey;
2085 	int i, x, y, w, h, n1, n2;
2086 
2087 	i = 0;
2088 	if (s[i] == '>') {
2089 		n1 = -1;
2090 
2091 		if (isdigit(s[++i])) {
2092 			n1 = s[i++] - '0';
2093 			while (isdigit(s[i])) n1 = n1 * 10 + s[i++] - '0';
2094 		}
2095 
2096 		if (s[i] == 'h') {
2097 			if (n1 == 5) bioscurstype(0x2000);
2098 			else i = -1;
2099 		}
2100 		else if (s[i] == 'l') {
2101 			if (n1 == 5) bioscurstype(0x0000);
2102 			else i = -1;
2103 		}
2104 		else i = -1;
2105 	}
2106 	else {
2107 		getxy(&y, &x);
2108 		w = getbiosbyte(SCRWIDTH);
2109 		h = getbiosbyte(SCRHEIGHT) + 1;
2110 		n1 = n2 = -1;
2111 
2112 		if (isdigit(s[i])) {
2113 			n1 = s[i++] - '0';
2114 			while (isdigit(s[i])) n1 = n1 * 10 + s[i++] - '0';
2115 		}
2116 		if (s[i] == ';' && isdigit(s[++i])) {
2117 			n2 = s[i++] - '0';
2118 			while (isdigit(s[i])) n2 = n2 * 10 + s[i++] - '0';
2119 		}
2120 
2121 		switch (s[i]) {
2122 			case 'A':
2123 				if (n1 <= 0) n1 = 1;
2124 				if ((y -= n1) <= 0) y = 1;
2125 				bioslocate(x, y);
2126 				break;
2127 			case 'B':
2128 				if (n1 <= 0) n1 = 1;
2129 				if ((y += n1) > h) y = h;
2130 				bioslocate(x, y);
2131 				break;
2132 			case 'C':
2133 				if (n1 <= 0) n1 = 1;
2134 				if ((x += n1) > w) x = w;
2135 				bioslocate(x, y);
2136 				break;
2137 			case 'D':
2138 				if (n1 <= 0) n1 = 1;
2139 				if ((x -= n1) <= 0) x = 1;
2140 				bioslocate(x, y);
2141 				break;
2142 			case 'H':
2143 			case 'f':
2144 				x = n2;
2145 				y = n1;
2146 				if (x <= 0) x = 1;
2147 				else if (x > w) x = w;
2148 				if (y <= 0) y = 1;
2149 				else if (y > h) y = h;
2150 				bioslocate(x, y);
2151 				break;
2152 			case 'm':
2153 				if (n1 < 0) chgattr(0);
2154 				else {
2155 					chgattr(n1);
2156 					if (n2 >= 0) chgattr(n2);
2157 				}
2158 				break;
2159 			case 's':
2160 				savex = x;
2161 				savey = y;
2162 				break;
2163 			case 'u':
2164 				x = savex;
2165 				y = savey;
2166 				if (x <= 0) x = 1;
2167 				else if (x > w) x = w;
2168 				if (y <= 0) y = 1;
2169 				else if (y > h) y = h;
2170 				bioslocate(savex, savey);
2171 				break;
2172 			case 'L':
2173 				if (n1 <= 0) n1 = 1;
2174 				biosscroll(-n1, 1, y, w, h);
2175 				bioslocate(1, y);
2176 				break;
2177 			case 'M':
2178 				if (n1 <= 0) n1 = 1;
2179 				biosscroll(n1, 1, y, w, h);
2180 				bioslocate(1, y);
2181 				break;
2182 			case 'J':
2183 				switch (n1) {
2184 					case -1:
2185 					case 0:
2186 						biosscroll(0, x, y, w, y);
2187 						biosscroll(0, 1, y + 1, w, h);
2188 						break;
2189 					case 1:
2190 						biosscroll(0, 1, y, x, y);
2191 						biosscroll(0, 1, 1, w, y - 1);
2192 						break;
2193 					case 2:
2194 						biosscroll(0, 1, 1, w, h);
2195 						bioslocate(1, 1);
2196 						break;
2197 					default:
2198 						break;
2199 				}
2200 				break;
2201 			case 'K':
2202 				switch (n1) {
2203 					case -1:
2204 					case 0:
2205 						biosscroll(0, x, y, w, y);
2206 						break;
2207 					case 1:
2208 						biosscroll(0, 1, y, x, y);
2209 						break;
2210 					case 2:
2211 						biosscroll(0, 1, y, w, y);
2212 						break;
2213 					default:
2214 						break;
2215 				}
2216 				break;
2217 			default:
2218 				i = -1;
2219 				break;
2220 		}
2221 	}
2222 
2223 	return(i);
2224 }
2225 
cputs2(s)2226 int cputs2(s)
2227 char *s;
2228 {
2229 	int i, n;
2230 
2231 	for (i = 0; s[i]; i++) {
2232 		if (s[i] != '\033' || s[i + 1] != '[') putch2(s[i]);
2233 		else if ((n = evalcsi(&s[i + 2])) >= 0) i += n + 2;
2234 	}
2235 	return(0);
2236 }
2237 # else	/* !USEVIDEOBIOS */
2238 
putch2(c)2239 int putch2(c)
2240 int c;
2241 {
2242 	bdos(0x06, c & 0xff, 0);
2243 	return(c);
2244 }
2245 
cputs2(s)2246 int cputs2(s)
2247 char *s;
2248 {
2249 	int i, x, y;
2250 
2251 	for (i = 0; s[i]; i++) {
2252 		if (s[i] != '\t') {
2253 			bdos(0x06, s[i], 0);
2254 			continue;
2255 		}
2256 
2257 		keyflush();
2258 		if (getxy(&y, &x) < 0) x = 1;
2259 		do {
2260 			bdos(0x06, ' ', 0);
2261 		} while (x++ % 8);
2262 	}
2263 	return(0);
2264 }
2265 # endif	/* !USEVIDEOBIOS */
2266 
2267 /*ARGSUSED*/
kbhit2(usec)2268 int kbhit2(usec)
2269 u_long usec;
2270 {
2271 #if	defined (NOTUSEBIOS) || !defined (DJGPP) || (DJGPP < 2)
2272 	union REGS reg;
2273 #else
2274 # ifndef	PC98
2275 	fd_set readfds;
2276 	struct timeval tv;
2277 	int n;
2278 # endif
2279 #endif
2280 
2281 	if (ungetnum > 0) return(1);
2282 #ifdef	NOTUSEBIOS
2283 	if (nextchar) return(1);
2284 	reg.x.ax = 0x4406;
2285 	reg.x.bx = STDIN_FILENO;
2286 	putterms(t_metamode);
2287 	int86(0x21, &reg, &reg);
2288 	putterms(t_nometamode);
2289 	return((reg.x.flags & 1) ? 0 : reg.h.al);
2290 #else	/* !NOTUSEBIOS */
2291 # ifdef	PC98
2292 	if (nextchar) return(1);
2293 	reg.h.ah = 0x01;
2294 	int86(0x18, &reg, &reg);
2295 	return(reg.h.bh != 0);
2296 # else	/* !PC98 */
2297 #  if	defined (DJGPP) && (DJGPP >= 2)
2298 	tv.tv_sec = 0L;
2299 	tv.tv_usec = usec;
2300 	FD_ZERO(&readfds);
2301 	FD_SET(STDIN_FILENO, &readfds);
2302 
2303 	do {
2304 		n = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
2305 	} while (n < 0);
2306 	return(n);
2307 #  else	/* !DJGPP || DJGPP < 2 */
2308 	reg.h.ah = 0x01;
2309 	int86(0x16, &reg, &reg);
2310 	return((reg.x.flags & 0x40) ? 0 : 1);
2311 #  endif	/* !DJGPP || DJGPP < 2 */
2312 # endif	/* !PC98 */
2313 #endif	/* !NOTUSEBIOS */
2314 }
2315 
getch2(VOID_A)2316 int getch2(VOID_A)
2317 {
2318 #ifdef	NOTUSEBIOS
2319 	u_short key, top;
2320 #endif
2321 #if	defined (PC98) && !defined (NOTUSEBIOS)
2322 	union REGS reg;
2323 #endif
2324 #if	defined (PC98) || defined (NOTUSEBIOS)
2325 	int ch;
2326 
2327 	if (nextchar) {
2328 		ch = nextchar;
2329 		nextchar = '\0';
2330 		return(ch);
2331 	}
2332 #endif
2333 	if (ungetnum > 0) return((int)ungetbuf[--ungetnum]);
2334 
2335 #ifndef	NOTUSEBIOS
2336 # ifdef	PC98
2337 	reg.h.ah = 0x00;
2338 	int86(0x18, &reg, &reg);
2339 
2340 	if (!(ch = reg.h.al)) nextchar = reg.h.ah;
2341 	return(ch);
2342 # else	/* !PC98 */
2343 	return(bdos(0x07, 0x00, 0) & 0xff);
2344 # endif	/* !PC98 */
2345 #else	/* NOTUSEBIOS */
2346 	disable();
2347 	top = keybuftop;
2348 	for (;;) {
2349 		if (top == getkeybuf(KEYBUFWORKEND)) {
2350 			key = 0xffff;
2351 			break;
2352 		}
2353 		key = getkeybuf(top);
2354 # ifdef	PC98
2355 		if ((ch = (key & 0xff))) {
2356 			if (ch < 0x80 || (ch > 0x9f && ch < 0xe0)) break;
2357 			key &= 0xff00;
2358 			if (strchr(metakey, (key >> 8))) break;
2359 		}
2360 # else
2361 		if ((ch = (key & 0xff)) && ch != 0xe0 && ch != 0xf0) break;
2362 		key &= 0xff00;
2363 # endif
2364 		if (strchr(specialkey, (key >> 8))) break;
2365 		if ((top += 2) >= KEYBUFWORKMAX) top = KEYBUFWORKMIN;
2366 	}
2367 	putterms(t_metamode);
2368 	ch = (bdos(0x07, 0x00, 0) & 0xff);
2369 	putterms(t_nometamode);
2370 	keybuftop = getkeybuf(KEYBUFWORKTOP);
2371 	if (!(key & 0xff)) {
2372 		while (kbhit2(1000000L / SENSEPERSEC)) {
2373 			if (keybuftop != getkeybuf(KEYBUFWORKTOP)) break;
2374 			putterms(t_metamode);
2375 			bdos(0x07, 0x00, 0);
2376 			putterms(t_nometamode);
2377 		}
2378 		ch = '\0';
2379 		nextchar = (key >> 8);
2380 	}
2381 	enable();
2382 	return(ch);
2383 #endif	/* NOTUSEBIOS */
2384 }
2385 
2386 #if	!defined (DJGPP) || defined (NOTUSEBIOS) || defined (PC98)
dosgettime(tbuf)2387 static int NEAR dosgettime(tbuf)
2388 u_char tbuf[];
2389 {
2390 	union REGS reg;
2391 
2392 	reg.x.ax = 0x2c00;
2393 	intdos(&reg, &reg);
2394 	tbuf[0] = reg.h.ch;
2395 	tbuf[1] = reg.h.cl;
2396 	tbuf[2] = reg.h.dh;
2397 	return(0);
2398 }
2399 #endif
2400 
2401 /*ARGSUSED*/
getkey2(sig)2402 int getkey2(sig)
2403 int sig;
2404 {
2405 #if	!defined (DJGPP) || defined (NOTUSEBIOS) || defined (PC98)
2406 	static u_char tbuf1[3] = {0xff, 0xff, 0xff};
2407 	u_char tbuf2[3];
2408 #endif
2409 #if	defined (DJGPP) && (DJGPP >= 2)
2410 	static int count = SENSEPERSEC;
2411 #endif
2412 	int i, ch;
2413 
2414 #if	defined (DJGPP) && !defined (NOTUSEBIOS) && !defined (PC98)
2415 	do {
2416 		i = kbhit2(1000000L / SENSEPERSEC);
2417 # if	defined (DJGPP) && (DJGPP >= 2)
2418 		if (sig && !(--count)) {
2419 			count = SENSEPERSEC;
2420 			raise(sig);
2421 		}
2422 # endif
2423 	} while (!i);
2424 #else	/* !DJGPP || NOTUSEBIOS || PC98 */
2425 	if (tbuf1[0] == 0xff) dosgettime(tbuf1);
2426 	while (!kbhit2(1000000L / SENSEPERSEC)) {
2427 		dosgettime(tbuf2);
2428 		if (memcmp((char *)tbuf1, (char *)tbuf2, sizeof(tbuf1))) {
2429 # if	!defined (DJGPP) || (DJGPP >= 2)
2430 			if (sig) raise(sig);
2431 # endif
2432 			memcpy((char *)tbuf1, (char *)tbuf2, sizeof(tbuf1));
2433 		}
2434 	}
2435 #endif	/* !DJGPP || NOTUSEBIOS || PC98 */
2436 	ch = getch2();
2437 
2438 	if (ch) switch (ch) {
2439 		case '\010':
2440 			ch = K_BS;
2441 			break;
2442 		case '\177':
2443 			ch = K_DC;
2444 			break;
2445 		default:
2446 			break;
2447 	}
2448 	else
2449 #if	defined (PC98) || defined (NOTUSEBIOS) \
2450 || (defined (DJGPP) && (DJGPP >= 2))
2451 	if (kbhit2(WAITKEYPAD * 1000L))
2452 #endif
2453 	{
2454 		ch = getch2();
2455 		for (i = 0; i < SPECIALKEYSIZ; i++)
2456 			if (ch == specialkey[i]) return(specialkeycode[i]);
2457 		for (i = 0; i <= 'z' - 'a'; i++)
2458 			if (ch == metakey[i]) return(('a' + i) | 0x80);
2459 		ch = K_NOKEY;
2460 	}
2461 	return(ch);
2462 }
2463 
ungetch2(c)2464 int ungetch2(c)
2465 u_char c;
2466 {
2467 	if (ungetnum >= sizeof(ungetbuf) / sizeof(u_char) - 1) return(EOF);
2468 	ungetbuf[ungetnum++] = c;
2469 	return(c);
2470 }
2471 
2472 /*ARGSUSED*/
setscroll(s,e)2473 int setscroll(s, e)
2474 int s, e;
2475 {
2476 	return(0);
2477 }
2478 
locate(x,y)2479 int locate(x, y)
2480 int x, y;
2481 {
2482 	cprintf2(c_locate, ++y, ++x);
2483 	return(0);
2484 }
2485 
tflush(VOID_A)2486 int tflush(VOID_A)
2487 {
2488 	return(0);
2489 }
2490 
getwsize(xmax,ymax)2491 int getwsize(xmax, ymax)
2492 int xmax, ymax;
2493 {
2494 	int x, y;
2495 
2496 	keyflush();
2497 	if (maxlocate(&y, &x) < 0) x = y = -1;
2498 
2499 	if (x > 0) {
2500 		n_lastcolumn = (n_lastcolumn < n_column) ? x - 1 : x;
2501 		n_column = x;
2502 	}
2503 	if (y > 0) n_line = y;
2504 
2505 	if (n_column <= 0 || n_column < xmax) err2("Column size too small");
2506 	if (n_line <= 0 || n_line < ymax) err2("Line size too small");
2507 
2508 	return(0);
2509 }
2510 
2511 #else	/* !MSDOS */
2512 
putch2(c)2513 int putch2(c)
2514 int c;
2515 {
2516 	return(fputc(c, ttyout));
2517 }
2518 
putch3(c)2519 int putch3(c)
2520 int c;
2521 {
2522 	return(fputc(c & 0x7f, ttyout));
2523 }
2524 
cputs2(str)2525 int cputs2(str)
2526 char *str;
2527 {
2528 	return(fputs(str, ttyout));
2529 }
2530 
kbhit2(usec)2531 int kbhit2(usec)
2532 u_long usec;
2533 {
2534 # ifdef	NOSELECT
2535 	return((usec) ? 1 : 0);
2536 # else
2537 	fd_set readfds;
2538 	struct timeval tv;
2539 	int n;
2540 
2541 	tv.tv_sec = 0L;
2542 	tv.tv_usec = usec;
2543 	FD_ZERO(&readfds);
2544 	FD_SET(STDIN_FILENO, &readfds);
2545 
2546 	do {
2547 		n = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
2548 	} while (n < 0);
2549 	return(n);
2550 # endif
2551 }
2552 
getch2(VOID_A)2553 int getch2(VOID_A)
2554 {
2555 	u_char ch;
2556 	int i;
2557 
2558 	while ((i = read(ttyio, &ch, sizeof(u_char))) < 0 && errno == EINTR);
2559 	if (i < sizeof(u_char)) return(EOF);
2560 	return((int)ch);
2561 }
2562 
getkey2(sig)2563 int getkey2(sig)
2564 int sig;
2565 {
2566 	static int count = SENSEPERSEC;
2567 	kstree_t *p;
2568 	int i, j, ch, key;
2569 
2570 	do {
2571 		key = kbhit2(1000000L / SENSEPERSEC);
2572 		if (sig && !(--count)) {
2573 			count = SENSEPERSEC;
2574 			kill(getpid(), sig);
2575 		}
2576 		if (keywaitfunc) (*keywaitfunc)();
2577 # ifndef	TIOCSTI
2578 		if (ungetnum > 0) return((int)ungetbuf[--ungetnum]);
2579 # endif
2580 	} while (!key);
2581 
2582 	key = ch = getch2();
2583 	if (!(p = keyseqtree)) return(key);
2584 
2585 	if (key == K_ESC) {
2586 		if (!kbhit2(WAITKEYPAD * 1000L)) return(key);
2587 		ch = getch2();
2588 		if (isalpha(ch) && !kbhit2(WAITMETA * 1000L))
2589 			return(ch | 0x80);
2590 		for (j = 0; j < p -> num; j++)
2591 			if (key == keyseq[p -> next[j].key].str[0]) break;
2592 		if (j >= p -> num) return(key);
2593 		p = &(p -> next[j]);
2594 		if (keyseq[p -> key].len == 1)
2595 			return(keyseq[p -> key].code & 0777);
2596 	}
2597 	else {
2598 		for (j = 0; j < p -> num; j++)
2599 			if (key == keyseq[p -> next[j].key].str[0]) break;
2600 		if (j >= p -> num) return(key);
2601 		p = &(p -> next[j]);
2602 		if (keyseq[p -> key].len == 1)
2603 			return(keyseq[p -> key].code & 0777);
2604 		if (!kbhit2(WAITKEYPAD * 1000L)) return(key);
2605 		ch = getch2();
2606 	}
2607 
2608 	for (i = 1; p && p -> next; i++) {
2609 		for (j = 0; j < p -> num; j++)
2610 			if (ch == keyseq[p -> next[j].key].str[i]) break;
2611 		if (j >= p -> num) return(key);
2612 		p = &(p -> next[j]);
2613 		if (keyseq[p -> key].len == i + 1)
2614 			return(keyseq[p -> key].code & 0777);
2615 		if (!kbhit2(WAITKEYPAD * 1000L)) return(key);
2616 		ch = getch2();
2617 	}
2618 	return(key);
2619 }
2620 
ungetch2(c)2621 int ungetch2(c)
2622 u_char c;
2623 {
2624 # ifdef	TIOCSTI
2625 	ioctl(ttyio, TIOCSTI, &c);
2626 # else
2627 	if (ungetnum >= sizeof(ungetbuf) / sizeof(u_char) - 1) return(EOF);
2628 	ungetbuf[ungetnum++] = c;
2629 # endif
2630 	return(c);
2631 }
2632 
setscroll(s,e)2633 int setscroll(s, e)
2634 int s, e;
2635 {
2636 	char *cp;
2637 
2638 	if ((cp = tparamstr(t_scroll, s, e))) {
2639 		putterms(cp);
2640 		free(cp);
2641 	}
2642 	return(0);
2643 }
2644 
locate(x,y)2645 int locate(x, y)
2646 int x, y;
2647 {
2648 # ifdef	DEBUG
2649 	char *cp;
2650 
2651 	_mtrace_file = "tgoto(start)";
2652 	cp = tgoto2(c_locate, x, y);
2653 	if (_mtrace_file) _mtrace_file = NULL;
2654 	else {
2655 		_mtrace_file = "tgoto(end)";
2656 		malloc(0);	/* dummy malloc */
2657 	}
2658 	putterms(cp);
2659 # else
2660 	putterms(tgoto2(c_locate, x, y));
2661 # endif
2662 	return(0);
2663 }
2664 
tflush(VOID_A)2665 int tflush(VOID_A)
2666 {
2667 	fflush(ttyout);
2668 	return(0);
2669 }
2670 
getwsize(xmax,ymax)2671 int getwsize(xmax, ymax)
2672 int xmax, ymax;
2673 {
2674 	int x, y, tx, ty;
2675 # ifdef	TIOCGWINSZ
2676 	struct winsize ws;
2677 # else
2678 #  ifdef	WIOCGETD
2679 	struct uwdate ws;
2680 #  else
2681 #   ifdef	TIOCGSIZE
2682 	struct ttysize ts;
2683 #   endif
2684 #  endif
2685 # endif
2686 
2687 	x = y = -1;
2688 # ifdef	TIOCGWINSZ
2689 	if (ioctl(ttyio, TIOCGWINSZ, &ws) >= 0) {
2690 		if (ws.ws_col > 0) x = ws.ws_col;
2691 		if (ws.ws_row > 0) y = ws.ws_row;
2692 	}
2693 # else	/* !TIOCGWINSZ */
2694 #  ifdef	WIOCGETD
2695 	ws.uw_hs = ws.uw_vs = 0;
2696 	if (ioctl(ttyio, WIOCGETD, &ws) >= 0) {
2697 		if (ws.uw_width > 0 && ws.uw_hs > 0)
2698 			x = ws.uw_width / ws.uw_hs;
2699 		if (ws.uw_height > 0 && ws.uw_vs > 0)
2700 			y = ws.uw_height / ws.uw_vs;
2701 	}
2702 #  else	/* !WIOCGETD */
2703 #   ifdef	TIOCGSIZE
2704 	if (ioctl(ttyio, TIOCGSIZE, &ts) >= 0) {
2705 		if (ts.ts_cols > 0) x = ts.ts_cols;
2706 		if (ts.ts_lines > 0) y = ts.ts_lines;
2707 	}
2708 #   endif
2709 #  endif	/* !WIOCGETD */
2710 # endif	/* !TIOCGWINSZ */
2711 
2712 	if (usegetcursor || x < 0 || y < 0) {
2713 		setscroll(-1, -1);
2714 		if (maxlocate(&ty, &tx) >= 0) {
2715 			x = tx;
2716 			y = ty;
2717 # ifdef	TIOCGWINSZ
2718 			if (ws.ws_col <= 0 || ws.ws_xpixel <= 0)
2719 				ws.ws_xpixel = 0;
2720 			else ws.ws_xpixel += (x - ws.ws_col)
2721 					* (ws.ws_xpixel / ws.ws_col);
2722 			if (ws.ws_row <= 0 || ws.ws_ypixel <= 0)
2723 				ws.ws_ypixel = 0;
2724 			else ws.ws_ypixel += (y - ws.ws_row)
2725 					* (ws.ws_ypixel / ws.ws_row);
2726 			ws.ws_col = x;
2727 			ws.ws_row = y;
2728 			ioctl(ttyio, TIOCSWINSZ, &ws);
2729 # else	/* !TIOCGWINSZ */
2730 #  ifdef	WIOCGETD
2731 			if (ws.uw_hs > 0 && ws.uw_vs > 0) {
2732 				ws.uw_width = x * ws.uw_hs;
2733 				ws.uw_height = y * ws.uw_vs;
2734 				ioctl(ttyio, WIOCSETD, &ws);
2735 			}
2736 #  else	/* !WIOCGETD */
2737 #   ifdef	TIOCGSIZE
2738 			ts.ts_cols = x;
2739 			ts.ts_lines = y;
2740 			ioctl(ttyio, TIOCSSIZE, &ts);
2741 #   endif
2742 #  endif	/* !WIOCGETD */
2743 # endif	/* !TIOCGWINSZ */
2744 		}
2745 	}
2746 
2747 	if (x > 0) {
2748 		n_lastcolumn = (n_lastcolumn < n_column) ? x - 1 : x;
2749 		n_column = x;
2750 	}
2751 	if (y > 0) n_line = y;
2752 
2753 	if (n_column <= 0 || n_column < xmax) err2("Column size too small");
2754 	if (n_line <= 0 || n_line < ymax) err2("Line size too small");
2755 
2756 	if (xmax > 0 && ymax > 0) setscroll(-1, n_line - 1);
2757 	return(0);
2758 }
2759 #endif	/* !MSDOS */
2760 
2761 #ifdef	USESTDARGH
2762 /*VARARGS1*/
cprintf2(CONST char * fmt,...)2763 int cprintf2(CONST char *fmt, ...)
2764 {
2765 	va_list args;
2766 	char buf[MAXPRINTBUF + 1];
2767 
2768 	va_start(args, fmt);
2769 	vsprintf(buf, fmt, args);
2770 	va_end(args);
2771 #else	/* !USESTDARGH */
2772 # ifndef	NOVSPRINTF
2773 /*VARARGS1*/
2774 int cprintf2(fmt, va_alist)
2775 CONST char *fmt;
2776 va_dcl
2777 {
2778 	va_list args;
2779 	char buf[MAXPRINTBUF + 1];
2780 
2781 	va_start(args);
2782 	vsprintf(buf, fmt, args);
2783 	va_end(args);
2784 # else	/* NOVSPRINTF */
2785 int cprintf2(fmt, arg1, arg2, arg3, arg4, arg5, arg6)
2786 char *fmt;
2787 {
2788 	char buf[MAXPRINTBUF + 1];
2789 
2790 	sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
2791 # endif	/* NOVSPRINTF */
2792 #endif	/* !USESTDARGH */
2793 	return(cputs2(buf));
2794 }
2795 
2796 int chgcolor(color, reverse)
2797 int color, reverse;
2798 {
2799 	if (!reverse) cprintf2("\033[%dm", color + ANSI_NORMAL);
2800 	else if (color == ANSI_BLACK)
2801 		cprintf2("\033[%dm\033[%dm",
2802 			ANSI_WHITE + ANSI_NORMAL, color + ANSI_REVERSE);
2803 	else cprintf2("\033[%dm\033[%dm",
2804 			ANSI_BLACK + ANSI_NORMAL, color + ANSI_REVERSE);
2805 	return(0);
2806 }
2807