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, ®, ®);
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, ®, ®);
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, ®, ®);
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, ®, ®);
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, ®, ®);
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(®);
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, ®);
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, ®);
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, ®);
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, ®);
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, ®);
1943 reg.x.ax = 0x0100;
1944 reg.x.cx &= 0x1f1f;
1945 reg.x.cx |= (n & 0x6000);
1946 intbios(VIDEOBIOS, ®);
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, ®, ®);
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, ®, ®);
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, ®, ®);
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, ®, ®);
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(®, ®);
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