minix/commands/elle/eeterm.c
2010-04-07 11:25:51 +00:00

1283 lines
30 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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 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 <sgtty.h>
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());
}