/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International * This software is quasi-public; it may be used freely with * like software, but may NOT be sold or made part of licensed * products without permission of the author. */ /* * EETERM ELLE Terminal Driver. * Directly supports DM2500, H-19, Omron 8025AG, Coherent/IBM-PC, TVI925. * Others also supported if using TX_TERMCAP. */ #include "elle.h" /* Define terminal indices (there may be holes but C preprocessor is too * stupid to let us close them). Should be one TN_ definition for every * hardwired terminal type, even though whether or not it is actually * compiled depends on which TX_ switches are defined. */ #define TN_TERMCAP 0 #define TN_DM2500 1 #define TN_H19 2 #define TN_OM8025 3 #define TN_COHIBM 4 /* Coherent IBM-PC console */ #define TN_TVI925 5 #if TX_COHIBM && !(TX_H19) /* Ensure H19 defined if COHIBM is. */ #define TX_H19 1 #endif #ifndef TXS_DEFAULT /* If no default is explicitly specified */ #define TXS_DEFAULT "H19" /* Then settle for H-19 */ #endif /*TXS_DEFAULT*/ extern char *tv_stype; /* If set, specifies terminal type */ extern int tibfmsk; /* Crock to mask off parity (meta) bit */ static int tv_padc; /* Pad character to use */ static int tv_cspeed; /* # msec per char (set from trm_ospeed) */ static int tv_type; /* Index of selected terminal type */ /* Internal functions */ static void tpadn(), tpad(); /* Character speed table, indexed by system output speed value (0-017). * Value in table is 100 * <# msec used per character>. */ static int cspdtab[] = { /* Val Idx Baud CPS Time/char in msec */ 0, /* 0 Hangup - ---- */ 13333, /* 1 50 7.5 133.33 (Baudot) */ 10000, /* 2 75 10 100.0 (Baudot) */ 10000, /* 3 110 10 100.0 */ 8200, /* 4 134.5 12.2 82.0 (IBM2741) */ 6666, /* 5 150 15 66.6666 */ 5000, /* 6 200 20 50.0 */ 3333, /* 7 300 30 33.3333 */ 1666, /* 8 600 60 16.6666 */ 833, /* 9 1200 120 8.3333 */ 555, /* 10 1800 180 5.5555 */ 416, /* 11 2400 240 4.1666 */ 208, /* 12 4800 480 2.0833 */ 104, /* 13 9600 960 1.04166 */ 0, /* 14 Ext A ? ? */ 0 /* 15 Ext B ? ? */ }; #if TX_TERMCAP /* Declarations for TERMCAP stuff. Only EETERM knows about them. */ /* Termcap routines */ extern int tgetent(), tgetnum(), tgetflag(), tputs(); extern char *tgetstr(), *tgoto(); static int getcap(); /* Internal routines */ static void putpad(), putnpad(), putpar(); /* Gross disgusting externals that must be defined for TERMCAP rtns */ char PC; /* Pad char */ char *BC; /* Backspace to use, if not ^H */ char *UP; /* Cursor up */ short ospeed; /* Terminal output speed */ /* Termcap numerical values/flags */ static int tc_am, /* TRUE if has auto-wrap */ tc_km; /* TRUE if meta key exists */ /* Termcap capability strings we want to know about */ struct tcap { char tcicod1, tcicod2, *tccap; }; static struct tcap tcap[] = { #define TC_al tcap[0].tccap /* Add (insert) line */ {'a','l', 0}, #define TC_AL tcap[1].tccap /* Add N lines */ {'A','L', 0}, #define TC_bc tcap[2].tccap /* Backspace Char (for BC) */ {'b','c', 0}, #define TC_ce tcap[3].tccap /* Erase to end of line (CLEOL) */ {'c','e', 0}, #define TC_cl tcap[4].tccap /* Clear screen */ {'c','l', 0}, #define TC_cm tcap[5].tccap /* Cursor motion */ {'c','m', 0}, #define TC_dc tcap[6].tccap /* Delete char */ {'d','c', 0}, #define TC_DC tcap[7].tccap /* Delete N chars */ {'D','C', 0}, #define TC_dl tcap[8].tccap /* Delete line */ {'d','l', 0}, #define TC_DL tcap[9].tccap /* Delete N lines */ {'D','L', 0}, #define TC_dm tcap[10].tccap /* Delete mode on */ {'d','m', 0}, #define TC_ed tcap[11].tccap /* Delete mode off */ {'e','d', 0}, #define TC_ei tcap[12].tccap /* Insert mode off */ {'e','i', 0}, #define TC_ia tcap[13].tccap /* Add line while in insert mode (see note) */ {'i','a', 0}, #define TC_ic tcap[14].tccap /* Insert blank char */ {'i','c', 0}, #define TC_IC tcap[15].tccap /* Insert N blank chars */ {'I','C', 0}, #define TC_id tcap[16].tccap /* Delete line while in del mode (see note) */ {'i','d', 0}, #define TC_im tcap[17].tccap /* Insert mode on */ {'i','m', 0}, #define TC_ip tcap[18].tccap /* Padding to send after char insertion */ {'i','p', 0}, #define TC_mm tcap[19].tccap /* String to set (turn on) meta-key mode */ {'m','m', 0}, #define TC_mo tcap[20].tccap /* String to reset (turn off) meta-key mode */ {'m','o', 0}, #define TC_pc tcap[21].tccap /* Pad Char (for PC) */ {'p','c', 0}, #define TC_se tcap[22].tccap /* End standout mode */ {'s','e', 0}, #define TC_so tcap[23].tccap /* Enter standout mode */ {'s','o', 0}, #define TC_te tcap[24].tccap /* String to end programs that use termcap */ {'t','e', 0}, #define TC_ti tcap[25].tccap /* String to beg programs that use termcap */ {'t','i', 0}, #define TC_up tcap[26].tccap /* Move cursor up (for UP) */ {'u','p', 0}, #define TC_vb tcap[27].tccap /* Visible bell */ {'v','b', 0}, }; #define NTCAPS ((sizeof(tcap))/(sizeof(struct tcap))) /* # entries */ /* * There are many other things that must be taken into account. * The termcap code here will probably not work for many termcap entries, * but the only sure way to find out which ones they are is to try them. */ /* Note that the "ia" and "id" strings are not defined by the TERMCAP doc; * their usage here is derived from examining other TERMCAP-using programs. * Sigh!!!! */ #endif /*TX_TERMCAP*/ /* T_INIT is called once only at program startup, to identify the * terminal type and set up any one-time things. * T_FATAL is only called if some routine detects an error related to the * terminal specification, before any initialization is done. * It prints a short error message and exits the program. * T_ENTER is called after TS_ENTER to set the terminal parameters for * editing (as opposed to normal typeout). It may be called * several times. * T_EXIT is called before TS_EXIT to restore normal typeout modes. * It is called on exit from the program, and perhaps other times. */ t_init() { char *getenv(); /* Set some default parameters */ scr_ht = 24; scr_wid = 79; trm_flags = 0; tvc_cin = 1; /* Assume 1 char per char I/D pos */ tvc_cdn = 1; tvc_pos = 4; /* Default abs-move cost is 4 chars */ tvc_bs = 1; /* Default backspace cost is 1 char */ tv_cspeed = cspdtab[trm_ospeed]; /* Find # msec per char */ /* First must determine terminal type, and check for terminals * that are hardwired into ELLE. */ if(!tv_stype /* String set in command line args? */ #if !(V6) && !(tv_stype = getenv("TERM")) /* or given by TERM var? */ #endif /*-V6*/ ) tv_stype = TXS_DEFAULT; /* No, try using default */ if(0) ; /* Sigh, stupid construct */ #if TX_H19 else if(ustrcmp(tv_stype,"H19")) tv_type = TN_H19; #endif /*TX_H19*/ #if TX_OM8025 else if(ustrcmp(tv_stype,"OM8025")) tv_type = TN_OM8025; #endif /*TX_OM8025*/ #if TX_DM2500 else if(ustrcmp(tv_stype,"DM2500")) tv_type = TN_DM2500; else if(ustrcmp(tv_stype,"DM3025")) tv_type = TN_DM2500; #endif /*TX_DM2500*/ #if TX_COHIBM else if(ustrcmp(tv_stype,"COHIBM")) tv_type = TN_COHIBM; #endif /*TX_COHIBM*/ #if TX_TVI925 else if(ustrcmp(tv_stype,"TVI925")) tv_type = TN_TVI925; #endif /*TX_TVI925*/ #if TX_TERMCAP /* This should be last thing */ else if(getcap(tv_stype)) tv_type = TN_TERMCAP; #endif /*TX_TERMCAP*/ else t_fatal("type unknown"); /* Ugh, barf and exit */ /* Terminal selected, now initialize parameters for it. */ switch(tv_type) { #if TX_DM2500 case TN_DM2500: tv_padc = 0177; /* Use rubout for pad */ tvc_pos = 3; /* Only 3 chars for abs mov */ tvc_ci = 2; /* tvc_cin = 1; */ /* Default is OK */ tvc_cd = 2; /* tvc_cdn = 1; */ /* Default is OK */ tvc_ld = 2; tvc_ldn = 1; tvc_li = 2; tvc_lin = 1; if(trm_ospeed == 13) /* If 9600, */ { tvc_cin = 5; /* Sigh, high cost */ tvc_cdn = 2; tvc_lin = 18; tvc_ldn = 2; } trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL|TF_METAKEY; break; #endif /*TX_DM2500*/ #if TX_H19 case TN_H19: trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL; tvc_ci = 8; /* tvc_cin = 1; */ /* default is ok */ tvc_cd = 0; tvc_cdn = 2; /* tvc_ld = 0; */ /* Default is OK */ tvc_ldn = 1 << (trm_ospeed - 7); /* tvc_li = 0; */ /* Default is OK */ tvc_lin = tvc_ldn; break; #endif /*TX_H19*/ #if TX_COHIBM case TN_COHIBM: trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL|TF_METAKEY|TF_DIRVID; /* Always use lowest possible costs */ /* tvc_ci = 0; */ /* Default */ tvc_cin = 2; /* tvc_cd = 0; */ /* Default */ tvc_cdn = 2; /* tvc_ld = 0; */ /* Default */ tvc_ldn = 2; /* tvc_li = 0; */ /* Default */ tvc_lin = 2; break; #endif /*TX_COHIBM*/ #if TX_OM8025 case TN_OM8025: trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL; tvc_pos = 6; /* tvc_ci = tvc_cd = 0; */ /* Default */ tvc_cin = 4; tvc_cdn = 2; /* tvc_ld = tvc_li = 0; */ /* Default */ tvc_ldn = 10; /* Crude approx */ tvc_lin = 10; if(trm_ospeed > 7) /* If faster than 300 baud */ trm_flags &= ~TF_IDLIN; /* Turn off LID */ break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: trm_flags |= TF_IDLIN|TF_IDCHR|TF_CLEOL; tvc_ci = tvc_cd = tvc_cin = tvc_cdn = tvc_ldn = tvc_lin = 2; break; #endif /*TX_TVI925*/ } if(tibfmsk < 0) /* If mask is still default -1, set it. */ tibfmsk = ((trm_flags&TF_METAKEY) ? 0377 : 0177); } /* T_FATAL(str) - prints error message and exits. */ t_fatal(str) char *str; { writerr("ELLE: \""); writerr(tv_stype); writerr("\" terminal "); writerr(str); writerr("\n"); exit(1); /* Terminate with prejudice */ } /* T_ENTER is called after TS_ENTER to set the terminal parameters for * editing (as opposed to normal typeout). * Standout mode must initially be off. */ t_enter() { switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: putpad(TC_ti); if(tc_km) putpad(TC_mm); /* Use meta if poss */ #if FX_SOWIND t_standout(0); /* Ensure standout mode off */ #endif break; #endif /*TX_TERMCAP*/ #if TX_DM2500 case TN_DM2500: tput(030); /* Just in case, flush stray modes */ break; #endif /*TX_DM2500*/ #if TX_COHIBM case TN_COHIBM: /* Note TN_H19 will exist too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: /* Enter ZDS (Heath) mode, then * Exit graphics mode (G) Exit ins-char mode (O) * exit rev video mode (q) exit hold-screen mode (\) * set cursor on (y5) */ tputz("\033[?2h\033G\033O\033q\033\\\033y5"); /* Set Discard-at-EOL (w) * Set no auto-CR (y9) * Enable 25th line (x1) */ tputz("\033w\033y9\033x1"); break; #endif /*TX_H19*/ } } /* T_EXIT - Leave editing modes. This function should restore ** the terminal's modes to what they were before ELLE was started. ** Standout mode is turned off. */ t_exit() { switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: if(tc_km) putpad(TC_mo); /* Turn off meta */ putpad(TC_te); break; #endif /*TX_TERMCAP*/ #if TX_DM2500 case TN_DM2500: tput(035); /* Turn on roll mode */ break; #endif /*TX_DM2500*/ #if TX_COHIBM case TN_COHIBM: /* If this exists, TN_H19 will too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: tputz("\033v"); /* Turn EOL-wrap back on */ #if DNTTY tputz("\033<"); /* Return to ANSI mode */ #endif /*DNTTY*/ break; #endif /*TX_H19*/ } } /* T_CLEAR() - Clears the screen and homes the cursor. * Always valid - ELLE refuses to support terminals without this. */ t_clear () { switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: putnpad(TC_cl,scr_ht); break; #endif /*TX_TERMCAP*/ #if TX_DM2500 case TN_DM2500: tputz("\036\036"); /* Double Master Clear */ break; #endif /*TX_DM2500*/ #if TX_COHIBM case TN_COHIBM: /* Note TN_H19 will exist too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: tputz("\033E"); /* tputn(zpadstr,9); */ break; #endif /*TX_H19*/ #if TX_OM8025 case TN_OM8025: tputz("\033H\033J"); /* Home then CLEOS */ tpad(1000); /* One second!!!! */ break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: tput(032); /* ^Z */ break; #endif /*TX_TVI925*/ } curs_lin = curs_col = 0; } /* T_CURPOS(y, x) - Absolute move. Place cursor in given position * regardless of where it currently is. * Updates curs_lin, curs_col. * Always valid -- ELLE refuses to support terminals without this. */ t_curpos (lin, col) register int lin, col; { if(col > scr_wid) /* Easiest to catch here */ col = scr_wid; /* Do absolute positioning */ switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: putpad(tgoto(TC_cm, col, lin)); break; #endif /*TX_TERMCAP*/ #if TX_DM2500 case TN_DM2500: tput(014); tput(col^0140); tput(lin^0140); break; #endif /*TX_DM2500*/ #if TX_COHIBM case TN_COHIBM: /* If this exists, TN_H19 will too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: tputz("\033Y"); tput(lin+040); tput(col+040); break; #endif /*TX_H19*/ #if TX_OM8025 case TN_OM8025: tputz("\033\175"); tput(0100+((lin+1)>>4)); tput(0100+((lin+1)&017)); tput(0100+((col+1)>>4)); tput(0100+((col+1)&017)); break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: tputz("\033="); tput(lin+040); tput(col+040); break; #endif /*TX_TVI925*/ } curs_lin = lin; curs_col = col; } /* T_BACKSPACE() - Back up 1 character position. * Updates curs_col. * Only valid if tvc_bs has a "reasonable" value ( < 1000) */ t_backspace() { #if TX_TERMCAP if(BC) tputz(BC); /* Use alternate BS */ else #endif tput('\010'); /* Send BS */ --curs_col; } /* T_BELL() - Ring terminal's bell (or flash something, or whatever). * Forces out all output thus far, to ensure immediate attention. * This used to be an unbuffered feep, but was changed to use normal * output path in order to avoid messing up terminal escape sequences. */ t_bell() { #if TXC_VISBEL && TX_TERMCAP if(TC_vb) tputz(TC_vb); /* Do visible bell if possible */ else #endif tput(BELL); tbufls(); /* Force it out */ } /* T_CLEOL() - Clear to End Of Line. * Only valid if trm_flags has TF_CLEOL set. */ t_cleol () { switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: putpad(TC_ce); break; #endif /*TX_TERMCAP*/ #if TX_DM2500 case TN_DM2500: tput(027); break; #endif /*TX_DM2500*/ #if TX_COHIBM case TN_COHIBM: /* If this exists, TN_H19 will too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: tputz("\033K"); break; #endif /*TX_H19*/ #if TX_OM8025 case TN_OM8025: tputz("\033K"); tpad(41); /* 1/25 sec padding */ break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: tputz("\033T"); break; #endif /*TX_TVI925*/ } } /* T_INSLIN(n, bot) - Insert lines in window. * n - # blank lines to insert. * bot - # of last line of current window * * The current line is moved down and N blank lines inserted. * Lines which are moved past bot are lost. * May leave cursor in random place. * Only valid if trm_flags has TF_IDLIN set. */ t_inslin (n, bot) int n; /* number of lines */ int bot; /* line number of last line in window */ { register i, j; int savc,savl; if((i = n) <= 0) return; if(bot < (scr_ht-1)) { savc = curs_col; savl = curs_lin; t_curpos(bot-i, 0); t_dellin(i, scr_ht); t_curpos(savl, savc); } switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: if(TC_AL) putpar(TC_AL, i, i); else if(TC_ia) { putpad(TC_im); do { putpad(TC_ia); } while(--i); putpad(TC_ei); } else do { putnpad(TC_al, scr_ht - curs_lin); } while(--i); break; #endif /*TX_TERMCAP*/ #if TX_DM2500 case TN_DM2500: tput(020); /* Enter I/D mode */ do { tput(012); /* Insert line */ switch(trm_ospeed) { case 13: j = 17; break; /* 9600 */ case 12: j = 8; break; /* 4800 */ case 11: j = 4; break; /* 2400 */ case 9: j = 2; break; /* 1200 */ default: j = 0; break; } tpadn(j); } while(--i); tput(030); /* Exit I/D mode */ break; #endif /*TX_DM2500*/ #if TX_H19 /* NOTE: H19 supposedly requires 19 ms for each line during line I/D * operations. * In actual practice, at 9600 baud 25 pads are necessary (24 wont work!) * for both I and D. Plus esc-E needs 9 pads. */ case TN_H19: do { tputz("\033L"); switch(trm_ospeed) { case 13: j = 25; break; case 9: j = 4; break; case 7: j = 1; break; default: j = 0; break; } tpadn(j); } while(--i); break; #endif /*TX_H19*/ #if TX_COHIBM case TN_COHIBM: do { tputz("\033L"); /* no padding required */ } while(--i); break; #endif /*TX_COHIBM*/ #if TX_OM8025 case TN_OM8025: do { tputz("\033L"); tpad(100*(scr_ht - curs_lin)); /* .1 per moved line*/ } while(--i); break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: do tputz("\033E"); while(--i); break; #endif /*TX_TVI925*/ } } /* T_DELLIN(n, bot) - Delete lines from window. * n - # lines to delete. * bot - # of last line of current window. * The current line, and N-1 following lines, are deleted. * Blank lines are inserted past bot. * Cursor should be left at original position. * Only valid if trm_flags has TF_IDLIN set. */ t_dellin (n, bot) int n; /* number of lines */ int bot; /* line number of last line in window */ { register i, j; int savl, savc; if((i = n) <= 0) return; switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: if(TC_DL) putpar(TC_DL, i, i); else if(TC_id) { putpad(TC_dm); do putpad(TC_id); while(--i); putpad(TC_ed); } else do { putnpad(TC_dl,scr_ht - curs_lin); } while(--i); break; #endif /*TX_TERMCAP*/ #if TX_DM2500 case TN_DM2500: tput(020); do { tput(032); if(trm_ospeed >= 13) /* 9600 */ tput(0177); } while(--i); tput(030); break; #endif /*TX_DM2500*/ #if TX_H19 case TN_H19: do { tputz("\033M"); switch(trm_ospeed){ case 13: j = 25; break; case 9: j = 4; break; case 7: j = 1; break; default: j = 0; break; } tpadn(j); } while(--i); break; #endif /*TX_H19*/ #if TX_COHIBM case TN_COHIBM: do { tputz("\033M"); /* no padding required */ } while(--i); break; #endif /*TX_COHIBM*/ #if TX_OM8025 case TN_OM8025: do { tputz("\033M"); tpad(100*(scr_ht - curs_lin)); } while(--i); break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: do { tputz("\033R"); } while(--i); break; #endif /*TX_TVI925*/ } if(bot < (scr_ht-1)) { savl = curs_lin; savc = curs_col; t_curpos(bot-n,0); t_inslin(n,scr_ht); t_curpos(savl,savc); } } /* T_INSCHR(n, str) - Insert n chars in current line * n - # characters to insert * str - Pointer to char string. If 0, insert spaces. * * Insert N characters from string str at current position. * The cursor may move but curs_col must be updated. * Only valid if trm_flags has TF_IDCHR set. */ t_inschr(n, str) int n; char *str; { register int i; register char *cp; if((i = n) <= 0) return; cp = str; switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: putpad(TC_im); /* Go into insert mode */ if(TC_IC) { putpar(TC_IC, i, 1); if(cp) tputn(cp, i); else do tput(SP); while(--i); } else do { if(TC_ic) putpad(TC_ic); if(cp) tput(*cp++); else tput(SP); if(TC_ip) putpad(TC_ip); } while(--i); putpad(TC_ei); /* Exit insert mode */ curs_col += n; break; #endif /*TX_TERMCAP*/ #if TX_COHIBM case TN_COHIBM: /* If this exists, TN_H19 will too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: tputz("\033@"); /* Enter ins char mode */ do { if(cp) tput(*cp++); else tput(SP); } while(--i); tputz("\033O"); /* Exit ins char mode */ curs_col += n; break; #endif /*TX_H19*/ #if TX_DM2500 case TN_DM2500: tput(020); /* Enter I/D mode */ if(trm_ospeed == 13) /* 9600 baud lossage */ { do { tputz(" \177"); /* SP and DEL */ } while(--i); tput(030); i = n; if(i < 3) /* If close enough, */ tputn("\010\010", i); /* use BSes */ else t_curpos(curs_lin, curs_col); } else /* Not 9600, can win */ { do { tput(034); } while(--i); tput(030); if(cp == 0) return; i = n; } do { if(cp) tput(*cp++); else tput(SP); } while(--i); curs_col += n; break; #endif /*TX_DM2500*/ #if TX_OM8025 case TN_OM8025: do { tputz("\033@"); if(cp) tput(*cp++); else tput(SP); } while(--i); curs_col += n; break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: do { tputz("\033Q"); } while(--i); if(cp) { tputn(cp, n); curs_col += n; } break; #endif /*TX_TVI925*/ } } /* T_DELCHR(n) - Delete N chars in current line. * Deletes the N characters to the right of the cursor. Remaining * chars are shifted left. The cursor should not move. * Only valid if trm_flags has TF_IDCHR set. */ t_delchr(n) /* Delete N chars at current loc */ int n; { register int i; if((i = n) <= 0) return; switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: putpad(TC_dm); /* Enter delete mode */ if(TC_DC) putpar(TC_DC, i, 1); else do { /* Delete char while in del mode */ putpad(TC_dc); } while(--i); putpad(TC_ed); /* Exit delete mode */ break; #endif /*TX_TERMCAP*/ #if TX_COHIBM case TN_COHIBM: /* If this exists, TN_H19 will too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: do tputz("\033N"); while(--i); break; #endif /*TX_H19*/ #if TX_DM2500 case TN_DM2500: tput(020); /* Enter I/D mode */ do if(trm_ospeed == 13) /* 9600? */ tputz("\010\177"); /* BS and DEL */ else tput(010); while(--i); tput(030); /* Exit I/D mode */ break; #endif /*TX_DM2500*/ #if TX_OM8025 case TN_OM8025: do tputz("\033P"); while (--i); break; #endif /*TX_OM8025*/ #if TX_TVI925 case TN_TVI925: do { tputz("\033W"); } while(--i); #endif /*TX_TVI925*/ } } #if FX_SOWIND /* T_STANDOUT(n) - Enter or leave standout mode. * n - 0 to return to normal display mode, * 1 to enter standout display mode. * This is usually reverse video but may be something else. * * Only valid if trm_flags has TF_SO set. */ t_standout(on) int on; { switch(tv_type) { #if TX_TERMCAP case TN_TERMCAP: putpad(on ? TC_so : TC_se); break; #endif /*TX_TERMCAP*/ #if TX_COHIBM case TN_COHIBM: /* Note TN_H19 will exist too */ #endif /*TX_COHIBM*/ #if TX_H19 case TN_H19: tputz(on ? "\033p" : "\033q"); break; #endif /*TX_H19*/ } } #endif /*FX_SOWIND*/ /* TPADN(n) - Output N pad chars. */ static void tpadn(n) int n; { register int i, pad; if((i = n) > 0) { pad = tv_padc; do { tput(pad); } while(--i); } } /* TPAD(msec) - Output padding for given # of milliseconds. */ static void tpad(n) int n; { register int i, i2; i = n; while(i > 0) { if((i2 = 320) < i) /* So can use integers */ i2 = i; i -= i2; i2 *= 100; while((i2 -= tv_cspeed) > 0) tput(tv_padc); } } #if TX_TERMCAP /* * Print the string str, interpreting padding. */ int tput(); /* Our output function */ static void putpad(str) char *str; { if(str) tputs(str, 1, tput); /* Invoke TERMCAP function */ } static void putnpad(str,n) char *str; int n; { if(str) tputs(str, n, tput); } static void putpar(str, par, n) /* Wish we had tparm() */ char *str; int par,n; { putnpad(tgoto(str, 0, par), n); } #endif /*TX_TERMCAP*/ /* * Read in the stuff from termcap upon startup. */ #if TX_TERMCAP static int tstrlen(), tstrlp(); #ifndef TCAPSLEN #define TCAPSLEN 1024 /* Default size of buffer for TERMCAP strings */ #endif /*-TCAPSLEN*/ static int getcap(stype) char *stype; { register char *t; register int i; int buflen; char *tcbuf, *tcbptr; /* Pointers into termcap buffer */ char tmpstr[4]; char tmpbuf[TCAPSLEN]; /* Allocate from stack */ char *malloc(); char *realloc(); /* First see if can find the terminal type. */ if((tgetent(tmpbuf, stype)) != 1) return(0); /* Found it! Set up a string buffer to save the caps. */ if(!(tcbuf = malloc(TCAPSLEN))) /* Get permanent buffer */ t_fatal(" - cannot allocate termcap buffer"); tcbptr = tcbuf; /* Now gobble all the string caps that ELLE wants to know about. */ tmpstr[3] = '\0'; i = NTCAPS; do { tmpstr[0] = tcap[i].tcicod1; /* Make str of the code */ tmpstr[1] = tcap[i].tcicod2; tcap[i].tccap = tgetstr(tmpstr, &tcbptr); /* Get cap */ } while(--i); buflen = tcbptr - tcbuf; /* String buffer done, finalize */ if(buflen >= TCAPSLEN) t_fatal("description too big!"); realloc(tcbuf, buflen); /* Free up unused part of buffer */ /* (this better not move it!!!) */ /* Now get the number/flag stuff that ELLE needs. */ tc_am = tgetflag("am"); /* auto wrap */ if (tgetflag("xn")) tc_am = 0; /* auto wrap at 81st char, nice! */ tc_km = (tgetflag("km") /* TTY has meta key */ || tgetflag("MT")); /* Alternate version of "km"?? */ scr_ht = tgetnum("li"); /* Set screen height (# lines) */ scr_wid = tgetnum("co"); /* Set screen width (# cols) */ ts_winsize(); /* Now initialize the stupid external vars that TERMCAP rtns want. */ if(TC_pc) PC = *TC_pc; /* Pad char */ BC = TC_bc; /* Backspace str (if no BS) */ UP = TC_up; /* Cursor up */ ospeed = trm_ospeed; /* Put output speed here */ /* Basic data extracted, now mull over it and set the remaining * ELLE variables */ #if FX_SOWIND if(tgetnum("sg") <= 0) /* If no magic cookie problems */ { if (TC_so && TC_se) /* And have standout caps, */ trm_flags |= TF_SO; /* Say has standout cap */ } #endif if (!(TC_cm && TC_cl)) t_fatal("lacks cursor addressing or clear screen."); tvc_pos = tstrlen(TC_cm); /* Find cost of abs move */ if(BC) /* Find cost of backspace */ tvc_bs = tstrlen(BC); /* Find costs for doing I/D char operations */ if ((TC_im||TC_ic) && (TC_dm||TC_dc)) { trm_flags |= TF_IDCHR; tvc_ci = tstrlen(TC_im)+tstrlen(TC_ei); tvc_cin = tstrlen(TC_ic)+1+tstrlen(TC_ip); if(TC_IC) /* If have multi-IC, use it */ { tvc_ci += tstrlp(TC_IC, 1); tvc_cin = 1; } tvc_cd = tstrlen(TC_dm)+tstrlen(TC_ed); tvc_cdn = tstrlen(TC_dc); if(TC_DC) /* If have multi-DC, use it */ { tvc_cd += tstrlp(TC_DC, 1); tvc_cdn = 0; } } /* Find costs for doing I/D line operations */ if ((TC_ia || TC_al) && (TC_id || TC_dl)) { trm_flags |= TF_IDLIN; tvc_li = 0; /* Usual case */ tvc_lin = tstrlen(TC_al); if(TC_AL) /* If have multi-IL, use it */ { tvc_li = tstrlp(TC_AL, 1); tvc_lin = tstrlp(TC_AL, 2) - tvc_lin; } else if(TC_ia) { tvc_li = tstrlen(TC_im)+tstrlen(TC_ei); tvc_lin = tstrlen(TC_ia); } tvc_ld = 0; /* Usual case */ tvc_ldn = tstrlen(TC_dl); if(TC_DL) /* If have multi-DL, use it */ { tvc_ld = tstrlp(TC_DL, 1); tvc_ldn = tstrlp(TC_DL, 2) - tvc_ld; } else if(TC_id) { tvc_ld = tstrlen(TC_dm)+tstrlen(TC_ed); tvc_ldn = tstrlen(TC_id); } } if (tc_am) { scr_wid--; /* For now, avoid invoking wrap. */ #if 0 trm_flags |= AUTOWRAP; /* */ #endif } if (TC_ce) trm_flags |= TF_CLEOL; /* Term has CLEOL? */ if (tc_km) trm_flags |= TF_METAKEY; /* Term has meta key? */ return(1); } /* Pair of routines which conspire in order to find # chars actually output * by a particular termcap string. */ static int _tslen; /* Stored count */ static void _tslinc(ch) { _tslen++; } static int tstrlen(str) char *str; { _tslen = 0; if(str && str[0]) tputs(str, 1, _tslinc); /* Mult padding by just 1 */ return(_tslen); } static int tstrlp(str, par) /* Same but with parameter */ char *str; int par; { #if 0 if(str) { char *cp = tgoto(str, 0, par); int i = strlen(cp); while(--i >= 0) printf(" %o", *cp++); printf("\n"); } #endif return !str ? 0 : tstrlen(tgoto(str, 0, par)); } #endif /*TX_TERMCAP*/ /* Direct-Video terminal output routine * Currently only COHERENT has this capability. */ #if COHERENT #include struct vidctl { int v_position; /* Position in video memory */ int v_count; /* Number of characters to transfer */ char *v_buffer; /* Character buffer to read/write */ }; /* * Attribute masks for TIOVPUTB - attributes occupy odd addresses * in video memory. */ #define VNORM 0x07 /* Ordinary Video */ #define VINTE 0x08 /* Intense video */ #define VBLIN 0x80 /* Blinking video */ #define VREVE 0x70 /* Reverse video */ #define VUNDE 0x01 /* Underline video (mono board) */ /* T_DIRECT(line, col, string, len) - Do direct-video output of string. * Puts the string ("len" chars in length) on the screen starting at * the X,Y character position given by col, line. * This routine is only called if terminal has the "TF_DIRVID" flag set. */ t_direct(lin, col, str, len) int lin, col; register char *str; register int len; { register char *cp; char vbuf[MAXLINE*2]; struct vidctl v; if(len <= 0) return; tbufls(); /* Ensure normal output is forced out */ v.v_position = (lin*80 + col)*2; v.v_count = len*2; v.v_buffer = cp = vbuf; do { *cp++ = *str++; *cp++ = VNORM; } while(--len); ioctl(1, TIOVPUTB, &v); } #endif /*COHERENT*/ /* * Terminal Output buffering routines */ static char tbuf[TOBFSIZ]; /* Output buffer */ static int tbufcnt = 0; /* # chars of room left in buffer */ static char *tbufp = 0; /* Pointer to deposit in buffer */ tput(ch) int ch; { if(--tbufcnt < 0) tbufls(); *tbufp++ = ch; } tputz(str) char *str; { register int c; register char *cp, *tp; cp = str; tp = tbufp; while(c = *cp++) { if(--tbufcnt < 0) { tbufp = tp; tbufls(); tp = tbufp; } *tp++ = c; } tbufp = tp; } tputn(str,cnt) char *str; int cnt; { register int c; register char *cp, *tp; cp = str; tp = tbufp; if((c = cnt) > 0) do { if(--tbufcnt < 0) { tbufp = tp; tbufls(); tp = tbufp; } *tp++ = *cp++; } while(--c); tbufp = tp; } tbufls() { register int cnt; if(tbufp && (cnt = tbufp - tbuf) > 0) /* # chars written */ write(1, tbuf, cnt); /* Out they go */ tbufp = tbuf; tbufcnt = TOBFSIZ-1; /* Allow for usual expected decrement */ } /* * Terminal Input buffering routines */ int tibfmsk = -1; /* Mask AND'ed with input chars (external) */ static char tibuf[TIBFSIZ]; /* TTY input buffer */ static char *tibfp; /* Pointer to read from buffer */ static int tibfcnt = 0; /* # chars left to be read from buffer */ tgetc() { #if SUN register int c; extern int sun_winfd, sun_rdevf; if(sun_winfd) { if(!sun_rdevf) return(sun_input(1)&tibfmsk); sun_rdevf = 0; /* Check mouse too, but only once! */ c = sun_input(0); if(c != -1) c &= tibfmsk; return(c); } #endif /*SUN*/ while(--tibfcnt < 0) tibfcnt = read(0,(tibfp = tibuf),TIBFSIZ); return((*tibfp++)&tibfmsk); } tinwait() { return(tibfcnt > 0 || ts_inp()); }