/* * term.c * * Terminal Module */ #include #include #include #include #include #include "machine.h" #if defined (DJGPP) && (DJGPP >= 2) #include #endif #ifdef USESTDARGH #include #else #include #endif #ifdef DEBUG extern char *_mtrace_file; #endif #if MSDOS #include #include # ifdef PC98 # define NOTUSEBIOS # endif # ifdef DJGPP # include # include # include # if defined (DJGPP) && (DJGPP >= 2) # include # else # define __dpmi_regs _go32_dpmi_registers # define __dpmi_int(v,r) ((r) -> x.ss = (r) -> x.sp = 0, \ _go32_dpmi_simulate_int(v, r)) # define _dos_ds _go32_info_block.selector_for_linear_memory # endif # define intdos2(rp) __dpmi_int(0x21, rp) # define getkeybuf(o) _farpeekw(_dos_ds, KEYBUFWORKSEG * 0x10 + o) # define putkeybuf(o, n) _farpokew(_dos_ds, KEYBUFWORKSEG * 0x10 + o, n) # else /* !DJGPP */ # include # include # include typedef union REGS __dpmi_regs; # define intdos2(rp) int86(0x21, rp, rp) # define getkeybuf(o) (*((u_short far *)MK_FP(KEYBUFWORKSEG, o))) # define putkeybuf(o, n) (*((u_short far *)MK_FP(KEYBUFWORKSEG, o)) = n) # ifdef LSI_C static int _asm_sti __P_((char *)); static int _asm_cli __P_((char *)); # define enable() _asm_sti("\n\tsti\n") # define disable() _asm_cli("\n\tcli\n") # endif # endif /* !DJGPP */ #define TTYNAME "CON" #else /* !MSDOS */ #include #include #include #define TTYNAME "/dev/tty" typedef struct _keyseq_t { u_short code; u_char len; char *str; } keyseq_t; typedef struct _kstree_t { int key; int num; struct _kstree_t *next; } kstree_t; #ifdef USETERMIOS # ifdef USETERMIO # undef USETERMIO # endif #include #include /* for Linux libc6 */ typedef struct termios termioctl_t; #define tioctl(d, r, a) ((r) ? tcsetattr(d, (r) - 1, a) : tcgetattr(d, a)) #define getspeed(t) cfgetospeed(&t) #define REQGETP 0 #define REQSETP (TCSAFLUSH + 1) #endif #ifdef USETERMIO #include typedef struct termio termioctl_t; #define tioctl ioctl #define getspeed(t) ((t).c_cflag & CBAUD) #define REQGETP TCGETA #define REQSETP TCSETAF #endif #if !defined (USETERMIO) && !defined (USETERMIOS) #define USESGTTY #include typedef struct sgttyb termioctl_t; #define tioctl ioctl #define getspeed(t) ((t).sg_ospeed) #define REQGETP TIOCGETP #define REQSETP TIOCSETP #endif #ifdef USESELECTH #include #endif #endif /* !MSDOS */ #ifndef NOSTDLIBH #include #endif #include #ifdef NOERRNO extern int errno; #endif #include "term.h" #define MAXPRINTBUF 255 #define GETSIZE "\033[6n" #define SIZEFMT "\033[%d;%dR" #if !MSDOS extern int tgetent __P_((char *, char *)); extern int tgetnum __P_((char *)); extern int tgetflag __P_((char *)); extern char *tgetstr __P_((char *, char **)); extern char *tgoto __P_((char *, int, int)); extern int tputs __P_((char *, int, int (*)__P_((int)))); #define BUFUNIT 16 #define TERMCAPSIZE 2048 #ifndef PENDIN #define PENDIN 0 #endif #ifndef IEXTEN #define IEXTEN 0 #endif #ifndef ECHOCTL #define ECHOCTL 0 #endif #ifndef ECHOKE #define ECHOKE 0 #endif #ifndef OCRNL #define OCRNL 0 #endif #ifndef ONOCR #define ONOCR 0 #endif #ifndef ONLRET #define ONLRET 0 #endif #ifndef TAB3 #define TAB3 OXTABS #endif #ifndef VINTR #define VINTR 0 #endif #ifndef VQUIT #define VQUIT 1 #endif #ifndef VEOF #define VEOF 4 #endif #ifndef VEOL #define VEOL 5 #endif #define not(x) (~(x) & 0xffff) #ifndef FREAD # ifdef _FREAD # define FREAD _FREAD # else # define FREAD (O_RDONLY + 1) # endif #endif #ifndef FD_SET typedef struct fd_set { int fds_bits[1]; } fd_set; # define FD_ZERO(p) (((p) -> fds_bits[0]) = 0) # define FD_SET(n, p) (((p) -> fds_bits[0]) |= (1 << (n))) #endif #endif /* !MSDOS */ static int NEAR err2 __P_((char *)); static int NEAR defaultterm __P_((VOID_A)); static int NEAR maxlocate __P_((int *, int *)); static int NEAR getxy __P_((int *, int *)); #if MSDOS # if !defined (DJGPP) || defined (NOTUSEBIOS) || defined (PC98) static int NEAR dosgettime __P_((u_char [])); # endif #else /* !MSDOS */ # ifdef USESGTTY static int NEAR ttymode __P_((int, u_short, u_short, u_short, u_short)); # else static int NEAR ttymode __P_((int, u_short, u_short, u_short, u_short, u_short, u_short, int, int)); # endif static int NEAR tgetstr2 __P_((char **, char *)); static int NEAR tgetstr3 __P_((char **, char *, char *)); static kstree_t *NEAR newkeyseq __P_((kstree_t *, int)); static int NEAR freekeyseq __P_((kstree_t *, int)); static int NEAR cmpkeyseq __P_((CONST VOID_P, CONST VOID_P)); static int NEAR sortkeyseq __P_((VOID_A)); # ifdef DEBUG static int NEAR freeterment __P_((VOID_A)); # endif #endif /* !MSDOS */ short ospeed = 0; char PC ='\0'; char *BC = NULL; char *UP = NULL; int n_column = 0; int n_lastcolumn = 0; int n_line = 0; int stable_standout = 0; char *t_init = NULL; char *t_end = NULL; char *t_metamode = NULL; char *t_nometamode = NULL; char *t_scroll = NULL; char *t_keypad = NULL; char *t_nokeypad = NULL; char *t_normalcursor = NULL; char *t_highcursor = NULL; char *t_nocursor = NULL; char *t_setcursor = NULL; char *t_resetcursor = NULL; char *t_bell = NULL; char *t_vbell = NULL; char *t_clear = NULL; char *t_normal = NULL; char *t_bold = NULL; char *t_reverse = NULL; char *t_dim = NULL; char *t_blink = NULL; char *t_standout = NULL; char *t_underline = NULL; char *end_standout = NULL; char *end_underline = NULL; char *l_clear = NULL; char *l_insert = NULL; char *l_delete = NULL; char *c_insert = NULL; char *c_delete = NULL; char *c_store = NULL; char *c_restore = NULL; char *c_locate = NULL; char *c_home = NULL; char *c_return = NULL; char *c_newline = NULL; char *c_scrollforw = NULL; char *c_scrollrev = NULL; char *c_up = NULL; char *c_down = NULL; char *c_right = NULL; char *c_left = NULL; char *c_nup = NULL; char *c_ndown = NULL; char *c_nright = NULL; char *c_nleft = NULL; u_char cc_intr = CTRL('c'); u_char cc_quit = CTRL('\\'); u_char cc_eof = CTRL('d'); u_char cc_eol = 255; VOID_T (*keywaitfunc)__P_((VOID_A)) = NULL; #if !MSDOS int usegetcursor = 0; #endif int ttyio = -1; FILE *ttyout = NULL; #if MSDOS #ifdef PC98 #define KEYBUFWORKSEG 0x00 #define KEYBUFWORKSIZ 0x20 #define KEYBUFWORKMIN 0x502 #define KEYBUFWORKMAX 0x522 #define KEYBUFWORKTOP 0x524 #define KEYBUFWORKEND 0x526 #define KEYBUFWORKCNT 0x528 static u_char specialkey[] = "\032:=<;89>\25667bcdefghijk\202\203\204\205\206\207\210\211\212\213?"; static u_char metakey[] = "\035-+\037\022 !\"\027#$%/.\030\031\020\023\036\024\026,\021*\025)"; #else #define KEYBUFWORKSEG 0x40 #define KEYBUFWORKSIZ 0x20 #define KEYBUFWORKMIN getkeybuf(0x80) #define KEYBUFWORKMAX (KEYBUFWORKMIN + KEYBUFWORKSIZ) #define KEYBUFWORKTOP (KEYBUFWORKMIN - 4) #define KEYBUFWORKEND (KEYBUFWORKMIN - 2) static u_char specialkey[] = "\003HPMKRSGOIQ;<=>?@ABCDTUVWXYZ[\\]\206"; static u_char metakey[] = "\0360. \022!\"#\027$%&21\030\031\020\023\037\024\026/\021-\025,"; #endif #if defined (PC98) || defined (NOTUSEBIOS) static int nextchar = '\0'; #endif #ifdef NOTUSEBIOS static u_short keybuftop = 0; #endif static int specialkeycode[] = { 0, K_UP, K_DOWN, K_RIGHT, K_LEFT, K_IC, K_DC, K_HOME, K_END, K_PPAGE, K_NPAGE, K_F(1), K_F(2), K_F(3), K_F(4), K_F(5), K_F(6), K_F(7), K_F(8), K_F(9), K_F(10), K_F(11), K_F(12), K_F(13), K_F(14), K_F(15), K_F(16), K_F(17), K_F(18), K_F(19), K_F(20), K_HELP }; #else /* !MSDOS */ static keyseq_t keyseq[K_MAX - K_MIN + 1]; static kstree_t *keyseqtree = NULL; #endif /* !MSDOS */ #if MSDOS || !defined (TIOCSTI) static u_char ungetbuf[10]; static int ungetnum = 0; #endif static int termflags = 0; #define F_INITTTY 001 #define F_TERMENT 002 #define F_INITTERM 004 #if MSDOS int inittty(reset) int reset; { static int dupin = -1; static int dupout = -1; long l; #ifndef DJGPP static u_char dupbrk; union REGS reg; #endif if (ttyio < 0 && (ttyio = open(TTYNAME, O_RDWR, 0600)) < 0) ttyio = dup(STDERR_FILENO); if (reset && !(termflags & F_INITTTY)) return(0); if (!reset) { #ifdef NOTUSEBIOS if (!keybuftop) keybuftop = getkeybuf(KEYBUFWORKTOP); #endif #ifndef DJGPP reg.x.ax = 0x3300; int86(0x21, ®, ®); dupbrk = reg.h.dl; #endif if (((!(l = ftell(stdin)) || l == -1) && ((dupin = dup(STDIN_FILENO)) < 0 || dup2(ttyio, STDIN_FILENO) < 0)) || ((!(l = ftell(stdout)) || l == -1) && ((dupout = dup(STDOUT_FILENO)) < 0 || dup2(ttyio, STDOUT_FILENO) < 0))) err2(NULL); termflags |= F_INITTTY; } else { #ifndef DJGPP reg.x.ax = 0x3301; reg.h.dl = dupbrk; int86(0x21, ®, ®); #endif if ((dupin >= 0 && dup2(dupin, STDIN_FILENO) < 0) || (dupout >= 0 && dup2(dupout, STDOUT_FILENO) < 0)) { termflags &= ~F_INITTTY; err2(NULL); } } return(0); } int cooked2(VOID_A) { #ifndef DJGPP union REGS reg; reg.x.ax = 0x3301; reg.h.dl = 1; int86(0x21, ®, ®); #endif return(0); } int cbreak2(VOID_A) { #ifndef DJGPP union REGS reg; reg.x.ax = 0x3301; reg.h.dl = 0; int86(0x21, ®, ®); #endif return(0); } int raw2(VOID_A) { #ifndef DJGPP union REGS reg; reg.x.ax = 0x3301; reg.h.dl = 0; int86(0x21, ®, ®); #endif return(0); } int echo2(VOID_A) { return(0); } int noecho2(VOID_A) { return(0); } int nl2(VOID_A) { return(0); } int nonl2(VOID_A) { return(0); } int tabs(VOID_A) { return(0); } int notabs(VOID_A) { return(0); } int keyflush(VOID_A) { __dpmi_regs reg; disable(); reg.x.ax = 0x0c00; intdos2(®); #ifdef NOTUSEBIOS keybuftop = getkeybuf(KEYBUFWORKTOP); #endif enable(); return(0); } #else /* !MSDOS */ int inittty(reset) int reset; { #ifdef USESGTTY static int dupttyflag; struct tchars cc; #endif static termioctl_t dupttyio; termioctl_t tty; if (ttyio < 0 && (ttyio = open(TTYNAME, O_RDWR, 0600)) < 0) ttyio = dup(STDERR_FILENO); if (reset && !(termflags & F_INITTTY)) return(0); if (tioctl(ttyio, REQGETP, &tty) < 0) { termflags &= ~F_INITTTY; err2(NULL); } if (!reset) { memcpy((char *)&dupttyio, (char *)&tty, sizeof(termioctl_t)); #ifdef USESGTTY if (tioctl(ttyio, TIOCLGET, &dupttyflag) < 0 || tioctl(ttyio, TIOCGETC, &cc) < 0) { termflags &= ~F_INITTTY; err2(NULL); } cc_intr = cc.t_intrc; cc_quit = cc.t_quitc; cc_eof = cc.t_eofc; cc_eol = cc.t_brkc; #else cc_intr = dupttyio.c_cc[VINTR]; cc_quit = dupttyio.c_cc[VQUIT]; cc_eof = dupttyio.c_cc[VEOF]; cc_eol = dupttyio.c_cc[VEOL]; #endif ospeed = getspeed(dupttyio); termflags |= F_INITTTY; } else if (tioctl(ttyio, REQSETP, &dupttyio) < 0 #ifdef USESGTTY || tioctl(ttyio, TIOCLSET, &dupttyflag) < 0 #endif ) { termflags &= ~F_INITTTY; err2(NULL); } return(0); } #ifdef USESGTTY static int NEAR ttymode(d, set, reset, lset, lreset) int d; u_short set, reset, lset, lreset; { termioctl_t tty; int lflag; if (ioctl(d, TIOCLGET, &lflag) < 0) err2(NULL); if (tioctl(d, REQGETP, &tty) < 0) err2(NULL); if (set) tty.sg_flags |= set; if (reset) tty.sg_flags &= reset; if (set) lflag |= lset; if (lreset) lflag &= lreset; if (ioctl(d, TIOCLSET, &lflag) < 0) err2(NULL); #else static int NEAR ttymode(d, set, reset, iset, ireset, oset, oreset, min, time) int d; u_short set, reset, iset, ireset, oset, oreset; int min, time; { termioctl_t tty; if (tioctl(d, REQGETP, &tty) < 0) err2(NULL); if (set) tty.c_lflag |= set; if (reset) tty.c_lflag &= reset; if (iset) tty.c_iflag |= iset; if (ireset) tty.c_iflag &= ireset; if (oset) tty.c_oflag |= oset; if (oreset) tty.c_oflag &= oreset; if (min) { tty.c_cc[VMIN] = min; tty.c_cc[VTIME] = time; } #endif if (tioctl(d, REQSETP, &tty) < 0) err2(NULL); return(0); } int cooked2(VOID_A) { #ifdef USESGTTY ttymode(ttyio, 0, not(CBREAK | RAW), LPASS8, not(LLITOUT | LPENDIN)); #else ttymode(ttyio, ISIG | ICANON | IEXTEN, not(PENDIN), BRKINT | IXON, not(IGNBRK | ISTRIP), # if (VEOF == VMIN) || (VEOL == VTIME) OPOST, 0, '\004', 255); # else OPOST, 0, 0, 0); # endif #endif return(0); } int cbreak2(VOID_A) { #ifdef USESGTTY ttymode(ttyio, CBREAK, 0, LLITOUT, 0); #else ttymode(ttyio, ISIG | IEXTEN, not(ICANON), BRKINT | IXON, not(IGNBRK), OPOST, 0, 1, 0); #endif return(0); } int raw2(VOID_A) { #ifdef USESGTTY ttymode(ttyio, RAW, 0, LLITOUT, 0); #else ttymode(ttyio, 0, not(ISIG | ICANON | IEXTEN), IGNBRK, not(BRKINT | IXON), 0, not(OPOST), 1, 0); #endif return(0); } int echo2(VOID_A) { #ifdef USESGTTY ttymode(ttyio, ECHO, 0, LCRTBS | LCRTERA | LCRTKIL | LCTLECH, 0); #else ttymode(ttyio, ECHO | ECHOE | ECHOCTL | ECHOKE, not(ECHONL), 0, 0, 0, 0, 0, 0); #endif return(0); } int noecho2(VOID_A) { #ifdef USESGTTY ttymode(ttyio, 0, not(ECHO), 0, not(LCRTBS | LCRTERA)); #else ttymode(ttyio, 0, not(ECHO | ECHOE | ECHOK | ECHONL), 0, 0, 0, 0, 0, 0); #endif return(0); } int nl2(VOID_A) { #ifdef USESGTTY ttymode(ttyio, CRMOD, 0, 0, 0); #else ttymode(ttyio, 0, 0, ICRNL, 0, ONLCR, not(OCRNL | ONOCR | ONLRET), 0, 0); #endif return(0); } int nonl2(VOID_A) { #ifdef USESGTTY ttymode(ttyio, 0, not(CRMOD), 0, 0); #else ttymode(ttyio, 0, 0, 0, not(ICRNL), 0, not(ONLCR), 0, 0); #endif return(0); } int tabs(VOID_A) { #ifdef USESGTTY ttymode(ttyio, 0, not(XTABS), 0, 0); #else ttymode(ttyio, 0, 0, 0, 0, 0, not(TAB3), 0, 0); #endif return(0); } int notabs(VOID_A) { #ifdef USESGTTY ttymode(ttyio, XTABS, 0, 0, 0); #else ttymode(ttyio, 0, 0, 0, 0, TAB3, 0, 0, 0); #endif return(0); } int keyflush(VOID_A) { #ifdef USESGTTY int i = FREAD; tioctl(ttyio, TIOCFLUSH, &i); #else /* !USESGTTY */ # ifdef USETERMIOS tcflush(ttyio, TCIFLUSH); # else tioctl(ttyio, TCFLSH, 0); # endif #endif /* !USESGTTY */ return(0); } #endif /* !MSDOS */ int exit2(no) int no; { if (termflags & F_TERMENT) putterm(t_normal); endterm(); inittty(1); keyflush(); #ifdef DEBUG freeterment(); if (ttyio >= 0) close(ttyio); if (ttyout && ttyout != stdout) fclose(ttyout); muntrace(); #endif exit(no); return(0); } static int NEAR err2(mes) char *mes; { int duperrno; duperrno = errno; if (termflags & F_TERMENT) putterm(t_normal); endterm(); inittty(1); fprintf(stderr, "\007\n"); errno = duperrno; if (mes) fprintf(stderr, "%s\n", mes); else perror(TTYNAME); exit(2); return(0); } static int NEAR defaultterm(VOID_A) { #if !MSDOS int i; #endif BC = "\010"; UP = "\033[A"; n_column = 80; #if MSDOS n_lastcolumn = 79; n_line = 25; #else n_lastcolumn = 80; n_line = 24; #endif #ifdef PC98 t_init = "\033[>1h"; t_end = "\033[>1l"; t_metamode = "\033)3"; t_nometamode = "\033)0"; #else t_init = ""; t_end = ""; t_metamode = ""; t_nometamode = ""; #endif #if MSDOS t_scroll = ""; t_keypad = ""; t_nokeypad = ""; t_normalcursor = "\033[>5l"; t_highcursor = "\033[>5l"; t_nocursor = "\033[>5h"; t_setcursor = "\033[s"; t_resetcursor = "\033[u"; #else t_scroll = "\033[%i%d;%dr"; t_keypad = "\033[?1h\033="; t_nokeypad = "\033[?1l\033>"; t_normalcursor = "\033[?25h"; t_highcursor = "\033[?25h"; t_nocursor = "\033[?25l"; t_setcursor = "\0337"; t_resetcursor = "\0338"; #endif t_bell = "\007"; t_vbell = "\007"; t_clear = "\033[;H\033[2J"; t_normal = "\033[m"; t_bold = "\033[1m"; t_reverse = "\033[7m"; t_dim = "\033[2m"; t_blink = "\033[5m"; t_standout = "\033[7m"; t_underline = "\033[4m"; end_standout = "\033[m"; end_underline = "\033[m"; l_clear = "\033[K"; l_insert = "\033[L"; l_delete = "\033[M"; c_insert = ""; c_delete = ""; #ifdef MSDOS c_store = "\033[s"; c_restore = "\033[u"; c_locate = "\033[%d;%dH"; #else c_store = "\0337"; c_restore = "\0338"; c_locate = "\033[%i%d;%dH"; #endif c_home = "\033[H"; c_return = "\r"; c_newline = "\n"; c_scrollforw = "\n"; c_scrollrev = ""; c_up = "\033[A"; c_down = "\012"; c_right = "\033[C"; c_left = "\010"; c_nup = "\033[%dA"; c_ndown = "\033[%dB"; c_nright = "\033[%dC"; c_nleft = "\033[%dD"; #if !MSDOS for (i = 0; i <= K_MAX - K_MIN; i++) keyseq[i].str = NULL; keyseq[K_UP - K_MIN].str = "\033OA"; keyseq[K_DOWN - K_MIN].str = "\033OB"; keyseq[K_RIGHT - K_MIN].str = "\033OC"; keyseq[K_LEFT - K_MIN].str = "\033OD"; keyseq[K_HOME - K_MIN].str = "\033[4~"; keyseq[K_BS - K_MIN].str = "\010"; keyseq[K_F(1) - K_MIN].str = "\033[11~"; keyseq[K_F(2) - K_MIN].str = "\033[12~"; keyseq[K_F(3) - K_MIN].str = "\033[13~"; keyseq[K_F(4) - K_MIN].str = "\033[14~"; keyseq[K_F(5) - K_MIN].str = "\033[15~"; keyseq[K_F(6) - K_MIN].str = "\033[17~"; keyseq[K_F(7) - K_MIN].str = "\033[18~"; keyseq[K_F(8) - K_MIN].str = "\033[19~"; keyseq[K_F(9) - K_MIN].str = "\033[20~"; keyseq[K_F(10) - K_MIN].str = "\033[21~"; keyseq[K_F(11) - K_MIN].str = "\033[23~"; keyseq[K_F(12) - K_MIN].str = "\033[24~"; keyseq[K_F(13) - K_MIN].str = "\033[25~"; keyseq[K_F(14) - K_MIN].str = "\033[26~"; keyseq[K_F(15) - K_MIN].str = "\033[28~"; keyseq[K_F(16) - K_MIN].str = "\033[29~"; keyseq[K_F(17) - K_MIN].str = "\033[31~"; keyseq[K_F(18) - K_MIN].str = "\033[32~"; keyseq[K_F(19) - K_MIN].str = "\033[33~"; keyseq[K_F(20) - K_MIN].str = "\033[34~"; keyseq[K_F(21) - K_MIN].str = "\033OP"; keyseq[K_F(22) - K_MIN].str = "\033OQ"; keyseq[K_F(23) - K_MIN].str = "\033OR"; keyseq[K_F(24) - K_MIN].str = "\033OS"; keyseq[K_F(25) - K_MIN].str = "\033OT"; keyseq[K_F(26) - K_MIN].str = "\033OU"; keyseq[K_F(27) - K_MIN].str = "\033OV"; keyseq[K_F(28) - K_MIN].str = "\033OW"; keyseq[K_F(29) - K_MIN].str = "\033OX"; keyseq[K_F(30) - K_MIN].str = "\033OY"; keyseq[K_F('*') - K_MIN].str = "\033Oj"; keyseq[K_F('+') - K_MIN].str = "\033Ok"; keyseq[K_F(',') - K_MIN].str = "\033Ol"; keyseq[K_F('-') - K_MIN].str = "\033Om"; keyseq[K_F('.') - K_MIN].str = "\033On"; keyseq[K_F('/') - K_MIN].str = "\033Oo"; keyseq[K_F('0') - K_MIN].str = "\033Op"; keyseq[K_F('1') - K_MIN].str = "\033Oq"; keyseq[K_F('2') - K_MIN].str = "\033Or"; keyseq[K_F('3') - K_MIN].str = "\033Os"; keyseq[K_F('4') - K_MIN].str = "\033Ot"; keyseq[K_F('5') - K_MIN].str = "\033Ou"; keyseq[K_F('6') - K_MIN].str = "\033Ov"; keyseq[K_F('7') - K_MIN].str = "\033Ow"; keyseq[K_F('8') - K_MIN].str = "\033Ox"; keyseq[K_F('9') - K_MIN].str = "\033Oy"; keyseq[K_F('=') - K_MIN].str = "\033OX"; keyseq[K_F('?') - K_MIN].str = "\033OM"; keyseq[K_DL - K_MIN].str = ""; keyseq[K_IL - K_MIN].str = ""; keyseq[K_DC - K_MIN].str = "\177"; keyseq[K_IC - K_MIN].str = "\033[2~"; keyseq[K_CLR - K_MIN].str = ""; keyseq[K_PPAGE - K_MIN].str = "\033[5~"; keyseq[K_NPAGE - K_MIN].str = "\033[6~"; keyseq[K_ENTER - K_MIN].str = "\033[9~"; keyseq[K_END - K_MIN].str = "\033[1~"; #endif return(0); } static int NEAR maxlocate(yp, xp) int *yp, *xp; { int i; #if MSDOS char *cp; if (t_setcursor && t_resetcursor) putterms(t_setcursor); if ((cp = tparamstr(c_locate, 0, 999))) { for (i = 0; cp[i]; i++) bdos(0x06, cp[i], 0); free(cp); } if ((cp = tparamstr(c_ndown, 999, 999))) { for (i = 0; cp[i]; i++) bdos(0x06, cp[i], 0); free(cp); } #else if (t_setcursor && t_resetcursor) putterms(t_setcursor); locate(998, 998); tflush(); #endif i = getxy(yp, xp); if (t_setcursor && t_resetcursor) putterms(t_resetcursor); return(i); } static int NEAR getxy(yp, xp) int *yp, *xp; { char *format, buf[sizeof(SIZEFMT) + 4]; int i, j, k, tmp, count, *val[2]; format = SIZEFMT; #if MSDOS for (i = 0; i < sizeof(GETSIZE) - 1; i++) bdos(0x06, GETSIZE[i], 0); #else write(ttyio, GETSIZE, sizeof(GETSIZE) - 1); #endif for (i = 0; i < sizeof(buf) - 1; i++) { #if MSDOS buf[i] = bdos(0x07, 0x00, 0); #else buf[i] = getch2(); #endif if (buf[i] == format[sizeof(SIZEFMT) - 2]) break; } keyflush(); buf[++i] = '\0'; count = 0; val[0] = yp; val[1] = xp; for (i = j = 0; format[i] && buf[j]; i++) { if (format[i] == '%' && format[++i] == 'd' && count < 2) { tmp = 0; k = j; for (; buf[j]; j++) { if (!buf[j] || buf[j] == format[i + 1]) break; tmp = tmp * 10 + buf[j] - '0'; } if (j == k) break; *val[count++] = tmp; } else if (format[i] != buf[j++]) break; } return(count); } #if MSDOS char *tparamstr(s, arg1, arg2) char *s; int arg1, arg2; { char *cp, buf[MAXPRINTBUF + 1]; sprintf(buf, s, arg1, arg2); if (!(cp = (char *)malloc(strlen(buf) + 1))) err2(NULL); strcpy(cp, buf); return(cp); } int getterment(VOID_A) { if (termflags & F_TERMENT) return(-1); defaultterm(); termflags |= F_TERMENT; return(0); } #else /* !MSDOS */ char *tparamstr(s, arg1, arg2) char *s; int arg1, arg2; { char *buf; int i, j, n, sw, size, args[2]; if (!s) return(NULL); if (!(buf = (char *)malloc(size = BUFUNIT))) err2(NULL); args[0] = arg1; args[1] = arg2; for (i = j = n = 0; s[i]; i++) { if (j + 5 >= size) { size += BUFUNIT; if (!(buf = (char *)realloc(buf, size))) err2(NULL); } if (s[i] != '%') buf[j++] = s[i]; else if (s[++i] == '%') buf[j++] = '%'; else if (n >= 2) { free(buf); return(NULL); } else switch (s[i]) { case 'd': sprintf(buf + j, "%d", args[n++]); j += strlen(buf + j); break; case '2': sprintf(buf + j, "%2d", args[n++]); j += 2; break; case '3': sprintf(buf + j, "%3d", args[n++]); j += 3; break; case '.': sprintf(buf + (j++), "%c", args[n++]); break; case '+': if (!s[++i]) { free(buf); return(NULL); } sprintf(buf + (j++), "%c", args[n++] + s[i]); break; case '>': if (!s[++i] || !s[i + 1]) { free(buf); return(NULL); } if (args[n] > s[i++]) args[n] += s[i]; break; case 'r': sw = args[0]; args[0] = args[1]; args[1] = sw; break; case 'i': args[0]++; args[1]++; break; case 'n': args[0] ^= 0140; args[1] ^= 0140; break; case 'B': args[n] = ((args[n] / 10) << 4) | (args[n] % 10); break; case 'D': args[n] -= 2 * (args[n] % 16); break; default: free(buf); return(NULL); /*NOTREACHED*/ break; } } buf[j] = '\0'; return(buf); } static int NEAR tgetstr2(term, s) char **term; char *s; { char strbuf[TERMCAPSIZE]; char *p, *cp; p = strbuf; if ((cp = tgetstr(s, &p)) || (cp = *term)) { if (!(*term = (char *)malloc(strlen(cp) + 1))) err2(NULL); strcpy(*term, cp); } return(0); } static int NEAR tgetstr3(term, str1, str2) char **term; char *str1, *str2; { char strbuf[TERMCAPSIZE]; char *p, *cp; p = strbuf; if (!(cp = tgetstr(str1, &p)) && (cp = tparamstr(tgetstr(str2, &p), 1, 1))) *term = cp; else if (cp || (cp = *term)) { if (!(*term = (char *)malloc(strlen(cp) + 1))) err2(NULL); strcpy(*term, cp); } return(0); } static kstree_t *NEAR newkeyseq(parent, num) kstree_t *parent; int num; { kstree_t *new; int i, n; if (!parent || !(parent -> next)) new = (kstree_t *)malloc(sizeof(kstree_t) * num); else new = (kstree_t *)realloc(parent -> next, sizeof(kstree_t) * num); if (!new) err2(NULL); if (!parent) n = 0; else { n = parent -> num; parent -> num = num; parent -> next = new; } for (i = n; i < num; i++) { new[i].key = -1; new[i].num = 0; new[i].next = (kstree_t *)NULL; } return(new); } static int NEAR freekeyseq(list, n) kstree_t *list; int n; { int i; if (!list) return(-1); for (i = list[n].num - 1; i >= 0; i--) freekeyseq(list[n].next, i); if (!n) free(list); return(0); } static int NEAR cmpkeyseq(vp1, vp2) CONST VOID_P vp1; CONST VOID_P vp2; { if (!((keyseq_t *)vp1) -> str) return(-1); if (!((keyseq_t *)vp2) -> str) return(1); return(strcmp(((keyseq_t *)vp1) -> str, ((keyseq_t *)vp2) -> str)); } static int NEAR sortkeyseq(VOID_A) { kstree_t *p; int i, j, k; qsort(keyseq, K_MAX - K_MIN + 1, sizeof(keyseq_t), cmpkeyseq); if (keyseqtree) freekeyseq(keyseqtree, 0); keyseqtree = newkeyseq(NULL, 1); for (i = 0; i <= K_MAX - K_MIN; i++) { p = keyseqtree; for (j = 0; j < keyseq[i].len; j++) { for (k = 0; k < p -> num; k++) { if (keyseq[i].str[j] == keyseq[p -> next[k].key].str[j]) break; } if (k >= p -> num) { newkeyseq(p, k + 1); p -> next[k].key = i; } p = &(p -> next[k]); } } return(0); } int getterment(VOID_A) { char *cp, *termname, buf[TERMCAPSIZE]; int i, j; if (termflags & F_TERMENT) return(-1); if (!(termname = (char *)getenv("TERM"))) termname = "unknown"; #ifdef DEBUG _mtrace_file = "tgetent(x4)"; #endif if (tgetent(buf, termname) <= 0) err2("No TERMCAP prepared"); if (!(ttyout = fdopen(ttyio, "w+"))) ttyout = stdout; defaultterm(); cp = ""; tgetstr2(&cp, "pc"); PC = *cp; free(cp); tgetstr2(&BC, "bc"); tgetstr2(&UP, "up"); n_column = n_lastcolumn = tgetnum("co"); n_line = tgetnum("li"); if (!tgetflag("xn")) n_lastcolumn--; stable_standout = tgetflag("xs"); tgetstr2(&t_init, "ti"); tgetstr2(&t_end, "te"); tgetstr2(&t_metamode, "mm"); tgetstr2(&t_nometamode, "mo"); tgetstr2(&t_scroll, "cs"); tgetstr2(&t_keypad, "ks"); tgetstr2(&t_nokeypad, "ke"); tgetstr2(&t_normalcursor, "ve"); tgetstr2(&t_highcursor, "vs"); tgetstr2(&t_nocursor, "vi"); tgetstr2(&t_setcursor, "sc"); tgetstr2(&t_resetcursor, "rc"); tgetstr2(&t_bell, "bl"); tgetstr2(&t_vbell, "vb"); tgetstr2(&t_clear, "cl"); tgetstr2(&t_normal, "me"); tgetstr2(&t_bold, "md"); tgetstr2(&t_reverse, "mr"); tgetstr2(&t_dim, "mh"); tgetstr2(&t_blink, "mb"); tgetstr2(&t_standout, "so"); tgetstr2(&t_underline, "us"); tgetstr2(&end_standout, "se"); tgetstr2(&end_underline, "ue"); tgetstr2(&l_clear, "ce"); tgetstr2(&l_insert, "al"); tgetstr2(&l_delete, "dl"); tgetstr3(&c_insert, "ic", "IC"); tgetstr3(&c_delete, "dc", "DC"); tgetstr2(&c_store, "sc"); tgetstr2(&c_restore, "rc"); tgetstr2(&c_locate, "cm"); tgetstr2(&c_home, "ho"); tgetstr2(&c_return, "cr"); tgetstr2(&c_newline, "nl"); tgetstr2(&c_scrollforw, "sf"); tgetstr2(&c_scrollrev, "sr"); tgetstr3(&c_up, "up", "UP"); tgetstr3(&c_down, "do", "DO"); tgetstr3(&c_right, "nd", "RI"); tgetstr3(&c_left, "le", "LE"); tgetstr2(&c_nup, "UP"); tgetstr2(&c_ndown, "DO"); tgetstr2(&c_nright, "RI"); tgetstr2(&c_nleft, "LE"); tgetstr2(&(keyseq[K_UP - K_MIN].str), "ku"); tgetstr2(&(keyseq[K_DOWN - K_MIN].str), "kd"); tgetstr2(&(keyseq[K_RIGHT - K_MIN].str), "kr"); tgetstr2(&(keyseq[K_LEFT - K_MIN].str), "kl"); tgetstr2(&(keyseq[K_HOME - K_MIN].str), "kh"); tgetstr2(&(keyseq[K_BS - K_MIN].str), "kb"); tgetstr2(&(keyseq[K_F(1) - K_MIN].str), "l1"); tgetstr2(&(keyseq[K_F(2) - K_MIN].str), "l2"); tgetstr2(&(keyseq[K_F(3) - K_MIN].str), "l3"); tgetstr2(&(keyseq[K_F(4) - K_MIN].str), "l4"); tgetstr2(&(keyseq[K_F(5) - K_MIN].str), "l5"); tgetstr2(&(keyseq[K_F(6) - K_MIN].str), "l6"); tgetstr2(&(keyseq[K_F(7) - K_MIN].str), "l7"); tgetstr2(&(keyseq[K_F(8) - K_MIN].str), "l8"); tgetstr2(&(keyseq[K_F(9) - K_MIN].str), "l9"); tgetstr2(&(keyseq[K_F(10) - K_MIN].str), "la"); tgetstr2(&(keyseq[K_F(21) - K_MIN].str), "k1"); tgetstr2(&(keyseq[K_F(22) - K_MIN].str), "k2"); tgetstr2(&(keyseq[K_F(23) - K_MIN].str), "k3"); tgetstr2(&(keyseq[K_F(24) - K_MIN].str), "k4"); tgetstr2(&(keyseq[K_F(25) - K_MIN].str), "k5"); tgetstr2(&(keyseq[K_F(26) - K_MIN].str), "k6"); tgetstr2(&(keyseq[K_F(27) - K_MIN].str), "k7"); tgetstr2(&(keyseq[K_F(28) - K_MIN].str), "k8"); tgetstr2(&(keyseq[K_F(29) - K_MIN].str), "k9"); tgetstr2(&(keyseq[K_F(30) - K_MIN].str), "k0"); tgetstr2(&(keyseq[K_DL - K_MIN].str), "kL"); tgetstr2(&(keyseq[K_IL - K_MIN].str), "kA"); tgetstr2(&(keyseq[K_DC - K_MIN].str), "kD"); tgetstr2(&(keyseq[K_IC - K_MIN].str), "kI"); tgetstr2(&(keyseq[K_CLR - K_MIN].str), "kC"); tgetstr2(&(keyseq[K_EOL - K_MIN].str), "kE"); tgetstr2(&(keyseq[K_PPAGE - K_MIN].str), "kP"); tgetstr2(&(keyseq[K_NPAGE - K_MIN].str), "kN"); tgetstr2(&(keyseq[K_ENTER - K_MIN].str), "@8"); tgetstr2(&(keyseq[K_BEG - K_MIN].str), "@1"); tgetstr2(&(keyseq[K_END - K_MIN].str), "@7"); for (i = 0; i <= K_MAX - K_MIN; i++) keyseq[i].code = K_MIN + i; for (i = 11; i <= 20; i++) { keyseq[K_F(i + 10) - K_MIN].code = K_F(i - 10); if (!keyseq[K_F(i) - K_MIN].str) continue; cp = (char *)malloc(strlen(keyseq[K_F(i) - K_MIN].str) + 1); if (!cp) err2(NULL); strcpy(cp, keyseq[K_F(i) - K_MIN].str); keyseq[K_F(i) - K_MIN].str = cp; } for (i = 31; K_F(i) < K_DL; i++) { if (!keyseq[K_F(i) - K_MIN].str) continue; cp = (char *)malloc(strlen(keyseq[K_F(i) - K_MIN].str) + 1); if (!cp) err2(NULL); strcpy(cp, keyseq[K_F(i) - K_MIN].str); keyseq[K_F(i) - K_MIN].str = cp; keyseq[K_F(i) - K_MIN].code = i; } keyseq[K_F('?') - K_MIN].code = CR; for (i = 0; i <= K_MAX - K_MIN; i++) { if (!(keyseq[i].str)) keyseq[i].len = 0; else { for (j = 0; keyseq[i].str[j]; j++) keyseq[i].str[j] &= 0x7f; keyseq[i].len = j; } } sortkeyseq(); termflags |= F_TERMENT; return(0); } #ifdef DEBUG static int NEAR freeterment(VOID_A) { int i; if (!(termflags & F_TERMENT)) return(-1); if (BC) free(BC); if (UP) free(UP); if (t_init) free(t_init); if (t_end) free(t_end); if (t_metamode) free(t_metamode); if (t_nometamode) free(t_nometamode); if (t_scroll) free(t_scroll); if (t_keypad) free(t_keypad); if (t_nokeypad) free(t_nokeypad); if (t_normalcursor) free(t_normalcursor); if (t_highcursor) free(t_highcursor); if (t_nocursor) free(t_nocursor); if (t_setcursor) free(t_setcursor); if (t_resetcursor) free(t_resetcursor); if (t_bell) free(t_bell); if (t_vbell) free(t_vbell); if (t_clear) free(t_clear); if (t_normal) free(t_normal); if (t_bold) free(t_bold); if (t_reverse) free(t_reverse); if (t_dim) free(t_dim); if (t_blink) free(t_blink); if (t_standout) free(t_standout); if (t_underline) free(t_underline); if (end_standout) free(end_standout); if (end_underline) free(end_underline); if (l_clear) free(l_clear); if (l_insert) free(l_insert); if (l_delete) free(l_delete); if (c_insert) free(c_insert); if (c_delete) free(c_delete); if (c_store) free(c_store); if (c_restore) free(c_restore); if (c_locate) free(c_locate); if (c_home) free(c_home); if (c_return) free(c_return); if (c_newline) free(c_newline); if (c_scrollforw) free(c_scrollforw); if (c_scrollrev) free(c_scrollrev); if (c_up) free(c_up); if (c_down) free(c_down); if (c_right) free(c_right); if (c_left) free(c_left); if (c_nup) free(c_nup); if (c_ndown) free(c_ndown); if (c_nright) free(c_nright); if (c_nleft) free(c_nleft); for (i = 0; i <= K_MAX - K_MIN; i++) if (keyseq[i].str) free(keyseq[i].str); if (keyseqtree) freekeyseq(keyseqtree, 0); termflags &= ~F_TERMENT; return(0); } #endif int setkeyseq(n, str, len) int n; char *str; int len; { int i, j; for (i = 0; i <= K_MAX - K_MIN; i++) if (keyseq[i].code == n) { if (keyseq[i].str) free(keyseq[i].str); keyseq[i].str = str; keyseq[i].len = len; break; } if (i > K_MAX - K_MIN) return(-1); if (str) for (i = 0; i <= K_MAX - K_MIN; i++) { if (keyseq[i].code == n || !(keyseq[i].str) || keyseq[i].len != len) continue; for (j = 0; j < len; j++) if (keyseq[i].str[j] != str[j]) break; if (j >= len) { free(keyseq[i].str); keyseq[i].str = NULL; keyseq[i].len = 0; } } sortkeyseq(); return(0); } char *getkeyseq(n, lenp) int n, *lenp; { int i; for (i = 0; i <= K_MAX - K_MIN; i++) if (keyseq[i].code == n) { if (lenp) *lenp = keyseq[i].len; return(keyseq[i].str); } if (lenp) *lenp = 0; return(NULL); } #endif /* !MSDOS */ int initterm(VOID_A) { if (!(termflags & F_TERMENT)) getterment(); putterms(t_keypad); putterms(t_init); tflush(); termflags |= F_INITTERM; return(0); } int endterm(VOID_A) { if (!(termflags & F_INITTERM)) return(-1); putterms(t_nokeypad); putterms(t_end); tflush(); termflags &= ~F_INITTERM; return(0); } #if MSDOS int putch2(c) int c; { bdos(0x06, c & 0xff, 0); return(c); } int cputs2(s) char *s; { int i, x, y; for (i = 0; s[i]; i++) { if (s[i] != '\t') { bdos(0x06, s[i], 0); continue; } keyflush(); if (getxy(&y, &x) != 2) x = 1; do { bdos(0x06, ' ', 0); } while (x++ % 8); } return(0); } /*ARGSUSED*/ int kbhit2(usec) u_long usec; { #if defined (NOTUSEBIOS) || !defined (DJGPP) || (DJGPP < 2) union REGS reg; #else # ifndef PC98 fd_set readfds; struct timeval timeout; # endif #endif if (ungetnum > 0) return(1); #ifdef NOTUSEBIOS if (nextchar) return(1); reg.x.ax = 0x4406; reg.x.bx = STDIN_FILENO; putterms(t_metamode); int86(0x21, ®, ®); putterms(t_nometamode); return((reg.x.flags & 1) ? 0 : reg.h.al); #else /* !NOTUSEBIOS */ # ifdef PC98 if (nextchar) return(1); reg.h.ah = 0x01; int86(0x18, ®, ®); return(reg.h.bh != 0); # else /* !PC98 */ # if defined (DJGPP) && (DJGPP >= 2) timeout.tv_sec = 0L; timeout.tv_usec = usec; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); return(select(STDIN_FILENO + 1, &readfds, NULL, NULL, &timeout)); # else /* !DJGPP || DJGPP < 2 */ reg.h.ah = 0x01; int86(0x16, ®, ®); return((reg.x.flags & 0x40) ? 0 : 1); # endif /* !DJGPP || DJGPP < 2 */ # endif /* !PC98 */ #endif /* !NOTUSEBIOS */ } int getch2(VOID_A) { #ifdef NOTUSEBIOS u_short key, top; #endif #if defined (PC98) && !defined (NOTUSEBIOS) union REGS reg; #endif #if defined (PC98) || defined (NOTUSEBIOS) int ch; if (nextchar) { ch = nextchar; nextchar = '\0'; return(ch); } #endif if (ungetnum > 0) return((int)ungetbuf[--ungetnum]); #ifndef NOTUSEBIOS # ifdef PC98 reg.h.ah = 0x00; int86(0x18, ®, ®); if (!(ch = reg.h.al)) nextchar = reg.h.ah; return(ch); # else /* !PC98 */ return(bdos(0x07, 0x00, 0) & 0xff); # endif /* !PC98 */ #else /* NOTUSEBIOS */ disable(); top = keybuftop; for (;;) { if (top == getkeybuf(KEYBUFWORKEND)) { key = 0xffff; break; } key = getkeybuf(top); # ifdef PC98 if ((ch = (key & 0xff))) { if (ch < 0x80 || (ch > 0x9f && ch < 0xe0)) break; key &= 0xff00; if (strchr(metakey, (key >> 8))) break; } # else if ((ch = (key & 0xff)) && ch != 0xe0 && ch != 0xf0) break; key &= 0xff00; # endif if (strchr(specialkey, (key >> 8))) break; if ((top += 2) >= KEYBUFWORKMAX) top = KEYBUFWORKMIN; } putterms(t_metamode); ch = (bdos(0x07, 0x00, 0) & 0xff); putterms(t_nometamode); keybuftop = getkeybuf(KEYBUFWORKTOP); if (!(key & 0xff)) { while (kbhit2(1000000L / SENSEPERSEC)) { if (keybuftop != getkeybuf(KEYBUFWORKTOP)) break; putterms(t_metamode); bdos(0x07, 0x00, 0); putterms(t_nometamode); } ch = '\0'; nextchar = (key >> 8); } enable(); return(ch); #endif /* NOTUSEBIOS */ } #if !defined (DJGPP) || defined (NOTUSEBIOS) || defined (PC98) static int NEAR dosgettime(tbuf) u_char tbuf[]; { union REGS reg; reg.x.ax = 0x2c00; intdos(®, ®); tbuf[0] = reg.h.ch; tbuf[1] = reg.h.cl; tbuf[2] = reg.h.dh; return(0); } #endif /*ARGSUSED*/ int getkey2(sig) int sig; { #if !defined (DJGPP) || defined (NOTUSEBIOS) || defined (PC98) static u_char tbuf1[3] = {0xff, 0xff, 0xff}; u_char tbuf2[3]; #endif #if defined (DJGPP) && (DJGPP >= 2) static int count = SENSEPERSEC; #endif int i, ch; #if defined (DJGPP) && !defined (NOTUSEBIOS) && !defined (PC98) do { i = kbhit2(1000000L / SENSEPERSEC); # if defined (DJGPP) && (DJGPP >= 2) if (sig && !(--count)) { count = SENSEPERSEC; raise(sig); } # endif } while (!i); #else /* !DJGPP || NOTUSEBIOS || PC98 */ if (tbuf1[0] == 0xff) dosgettime(tbuf1); while (!kbhit2(1000000L / SENSEPERSEC)) { dosgettime(tbuf2); if (memcmp((char *)tbuf1, (char *)tbuf2, sizeof(tbuf1))) { # if !defined (DJGPP) || (DJGPP >= 2) if (sig) raise(sig); # endif memcpy((char *)tbuf1, (char *)tbuf2, sizeof(tbuf1)); } } #endif /* !DJGPP || NOTUSEBIOS || PC98 */ ch = getch2(); if (ch) switch (ch) { case '\010': ch = K_BS; break; case '\177': ch = K_DC; break; default: break; } else #if defined (PC98) || defined (NOTUSEBIOS) \ || (defined (DJGPP) && (DJGPP >= 2)) if (kbhit2(WAITKEYPAD * 1000L)) #endif { ch = getch2(); for (i = 0; i < sizeof(specialkey) / sizeof(u_char) - 1; i++) if (ch == specialkey[i]) return(specialkeycode[i]); for (i = 0; i <= 'z' - 'a'; i++) if (ch == metakey[i]) return(('a' + i) | 0x80); ch = K_NOKEY; } return(ch); } int ungetch2(c) u_char c; { if (ungetnum >= sizeof(ungetbuf) / sizeof(u_char) - 1) return(EOF); ungetbuf[ungetnum++] = c; return(c); } /*ARGSUSED*/ int setscroll(s, e) int s, e; { return(0); } int locate(x, y) int x, y; { cprintf2(c_locate, ++y, ++x); return(0); } int tflush(VOID_A) { return(0); } int getwsize(xmax, ymax) int xmax, ymax; { int x, y; if (xmax <= 0 || ymax <= 0) return(-1); keyflush(); if (maxlocate(&y, &x) != 2) x = y = -1; if (x > 0) { n_lastcolumn = (n_lastcolumn < n_column) ? x - 1 : x; n_column = x; } if (y > 0) n_line = y; if (n_column < xmax) err2("Column size too small"); if (n_line < ymax) err2("Line size too small"); return(0); } #else /* !MSDOS */ int putch2(c) int c; { return(fputc(c, ttyout)); } int putch3(c) int c; { return(fputc(c & 0x7f, ttyout)); } int cputs2(str) char *str; { return(fputs(str, ttyout)); } int kbhit2(usec) u_long usec; { #ifdef NOSELECT return((usec) ? 1 : 0); #else fd_set readfds; struct timeval timeout; timeout.tv_sec = 0L; timeout.tv_usec = usec; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); return(select(STDIN_FILENO + 1, &readfds, NULL, NULL, &timeout)); #endif } int getch2(VOID_A) { u_char ch; int i; while ((i = read(ttyio, &ch, sizeof(u_char))) < 0 && errno == EINTR); if (i < sizeof(u_char)) return(EOF); return((int)ch); } int getkey2(sig) int sig; { static int count = SENSEPERSEC; kstree_t *p; int i, j, ch, key; do { key = kbhit2(1000000L / SENSEPERSEC); if (sig && !(--count)) { count = SENSEPERSEC; kill(getpid(), sig); } if (keywaitfunc) (*keywaitfunc)(); #ifndef TIOCSTI if (ungetnum > 0) return((int)ungetbuf[--ungetnum]); #endif } while (!key); key = ch = getch2(); p = keyseqtree; if (key == ESC) { if (!kbhit2(WAITKEYPAD * 1000L)) return(key); ch = getch2(); if (isalpha(ch) && !kbhit2(WAITMETA * 1000L)) return(ch | 0x80); for (j = 0; j < p -> num; j++) if (key == keyseq[p -> next[j].key].str[0]) break; if (j >= p -> num) return(key); p = &(p -> next[j]); if (keyseq[p -> key].len == 1) return(keyseq[p -> key].code); } else { for (j = 0; j < p -> num; j++) if (key == keyseq[p -> next[j].key].str[0]) break; if (j >= p -> num) return(key); p = &(p -> next[j]); if (keyseq[p -> key].len == 1) return(keyseq[p -> key].code); if (!kbhit2(WAITKEYPAD * 1000L)) return(key); ch = getch2(); } for (i = 1; p && p -> next; i++) { for (j = 0; j < p -> num; j++) if (ch == keyseq[p -> next[j].key].str[i]) break; if (j >= p -> num) return(key); p = &(p -> next[j]); if (keyseq[p -> key].len == i + 1) return(keyseq[p -> key].code); if (!kbhit2(WAITKEYPAD * 1000L)) return(key); ch = getch2(); } return(key); } int ungetch2(c) u_char c; { #ifdef TIOCSTI ioctl(ttyio, TIOCSTI, &c); #else if (ungetnum >= sizeof(ungetbuf) / sizeof(u_char) - 1) return(EOF); ungetbuf[ungetnum++] = c; #endif return(c); } int setscroll(s, e) int s, e; { char *cp; if ((cp = tparamstr(t_scroll, s, e))) { putterms(cp); free(cp); } return(0); } int locate(x, y) int x, y; { #ifdef DEBUG _mtrace_file = "tgoto(x2)"; #endif putterms(tgoto(c_locate, x, y)); return(0); } int tflush(VOID_A) { fflush(ttyout); return(0); } int getwsize(xmax, ymax) int xmax, ymax; { int x, y, tx, ty; #ifdef TIOCGWINSZ struct winsize ws; #else #ifdef WIOCGETD struct uwdate ws; #else #ifdef TIOCGSIZE struct ttysize ts; #endif #endif #endif if (xmax <= 0 || ymax <= 0) return(-1); x = y = -1; #ifdef TIOCGWINSZ if (ioctl(ttyio, TIOCGWINSZ, &ws) >= 0) { if (ws.ws_col > 0) x = ws.ws_col; if (ws.ws_row > 0) y = ws.ws_row; } #else #ifdef WIOCGETD ws.uw_hs = ws.uw_vs = 0; if (ioctl(ttyio, WIOCGETD, &ws) >= 0) { if (ws.uw_width > 0 && ws.uw_hs > 0) x = ws.uw_width / ws.uw_hs; if (ws.uw_height > 0 && ws.uw_vs > 0) y = ws.uw_height / ws.uw_vs; } #else #ifdef TIOCGSIZE if (ioctl(ttyio, TIOCGSIZE, &ts) >= 0) { if (ts.ts_cols > 0) x = ts.ts_cols; if (ts.ts_lines > 0) y = ts.ts_lines; } #endif #endif #endif if (usegetcursor || x < 0 || y < 0) { setscroll(-1, -1); if (maxlocate(&ty, &tx) == 2) { x = tx; y = ty; #ifdef TIOCGWINSZ if (ws.ws_col <= 0 || ws.ws_xpixel <= 0) ws.ws_xpixel = 0; else ws.ws_xpixel += (x - ws.ws_col) * (ws.ws_xpixel / ws.ws_col); if (ws.ws_row <= 0 || ws.ws_ypixel <= 0) ws.ws_ypixel = 0; else ws.ws_ypixel += (y - ws.ws_row) * (ws.ws_ypixel / ws.ws_row); ws.ws_col = x; ws.ws_row = y; ioctl(ttyio, TIOCSWINSZ, &ws); #else #ifdef WIOCGETD if (ws.uw_hs > 0 && ws.uw_vs > 0) { ws.uw_width = x * ws.uw_hs; ws.uw_height = y * ws.uw_vs; ioctl(ttyio, WIOCSETD, &ws); } #else #ifdef TIOCGSIZE ts.ts_cols = x; ts.ts_lines = y; ioctl(ttyio, TIOCSSIZE, &ts); #endif #endif #endif } } if (x > 0) { n_lastcolumn = (n_lastcolumn < n_column) ? x - 1 : x; n_column = x; } if (y > 0) n_line = y; if (n_column < xmax) err2("Column size too small"); if (n_line < ymax) err2("Line size too small"); setscroll(-1, n_line - 1); return(0); } #endif /* !MSDOS */ #ifdef USESTDARGH /*VARARGS1*/ int cprintf2(CONST char *fmt, ...) { va_list args; char buf[MAXPRINTBUF + 1]; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); #else /* !USESTDARGH */ # ifndef NOVSPRINTF /*VARARGS1*/ int cprintf2(fmt, va_alist) CONST char *fmt; va_dcl { va_list args; char buf[MAXPRINTBUF + 1]; va_start(args); vsprintf(buf, fmt, args); va_end(args); # else /* NOVSPRINTF */ int cprintf2(fmt, arg1, arg2, arg3, arg4, arg5, arg6) char *fmt; { char buf[MAXPRINTBUF + 1]; sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); # endif /* NOVSPRINTF */ #endif /* !USESTDARGH */ return(cputs2(buf)); } int chgcolor(color, reverse) int color, reverse; { if (!reverse) cprintf2("\033[%dm", color + ANSI_NORMAL); else if (color == ANSI_BLACK) cprintf2("\033[%dm\033[%dm", ANSI_WHITE + ANSI_NORMAL, color + ANSI_REVERSE); else cprintf2("\033[%dm\033[%dm", ANSI_BLACK + ANSI_NORMAL, color + ANSI_REVERSE); return(0); }