pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

termcap.c (6177B)


      1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
      2 /* termcap.c - version 1.0.3 */
      3 
      4 #include <stdio.h>
      5 #include "config.h"	/* for ROWNO and COLNO */
      6 #include "flag.h"	/* for flags.nonull */
      7 extern char *tgetstr(), *tgoto(), *getenv();
      8 extern long *alloc();
      9 
     10 #ifndef lint
     11 extern			/* it is defined in libtermlib (libtermcap) */
     12 #endif /* lint /**/
     13 	short ospeed;		/* terminal baudrate; used by tputs */
     14 static char tbuf[512];
     15 static char	*HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
     16 static char	*VS, *VE;
     17 char		*US, *UE;
     18 static int SG;
     19 static char PC = '\0';
     20 char *CD;		/* tested in pri.c: docorner() */
     21 int CO, LI;		/* used in pri.c and whatis.c */
     22 
     23 startup()
     24 {
     25 	register char *term;
     26 	register char *tptr;
     27 	char *tbufptr, *pc;
     28 
     29 	tptr = (char *) alloc(1024);
     30 
     31 	tbufptr = tbuf;
     32 
     33 	if(!(term = getenv("TERM")))
     34 # ifdef MSDOS
     35 		term = "ibmpc-mono";
     36 # else
     37 		error("Can't get TERM.");
     38 # endif
     39 	if(!strncmp(term, "5620", 4))
     40 		flags.nonull = 1;	/* this should be a termcap flag */
     41 	if(tgetent(tptr, term) < 1)
     42 		error("Unknown terminal type: %s.", term);
     43 	TI = tgetstr("ti", &tbufptr);
     44 	TE = tgetstr("te", &tbufptr);
     45 	VS = VE = "";
     46 
     47 	if(pc = tgetstr("pc", &tbufptr))
     48 		PC = *pc;
     49 	if(!(BC = tgetstr("bc", &tbufptr))) {	
     50 		if(!tgetflag("bs"))
     51 			error("Terminal must backspace.");
     52 		BC = tbufptr;
     53 		tbufptr += 2;
     54 		*BC = '\b';
     55 	}
     56 	HO = tgetstr("ho", &tbufptr);
     57 	CO = tgetnum("co");
     58 	LI = tgetnum("li");
     59 	if(CO < COLNO || LI < ROWNO+2)
     60 		setclipped();
     61 	if(!(CL = tgetstr("cl", &tbufptr)))
     62 		error("Hack needs CL.");
     63 	ND = tgetstr("nd", &tbufptr);
     64 	if(tgetflag("os"))
     65 		error("Hack can't have OS.");
     66 	CE = tgetstr("ce", &tbufptr);
     67 	UP = tgetstr("up", &tbufptr);
     68 	/* It seems that xd is no longer supported, and we should use
     69 	   a linefeed instead; unfortunately this requires resetting
     70 	   CRMOD, and many output routines will have to be modified
     71 	   slightly. Let's leave that till the next release. */
     72 	XD = tgetstr("xd", &tbufptr);
     73 /* not: 		XD = tgetstr("do", &tbufptr); */
     74 	if(!(CM = tgetstr("cm", &tbufptr))) {
     75 		if(!UP && !HO)
     76 			error("Hack needs CM or UP or HO.");
     77 		printf("Playing hack on terminals without cm is suspect...\n");
     78 		getret();
     79 	}
     80 	US = SO = tgetstr("so", &tbufptr);
     81 	UE = SE = tgetstr("se", &tbufptr);
     82 	US = tgetstr("us", &tbufptr);
     83 	UE = tgetstr("ue", &tbufptr);
     84 	SG = tgetnum("sg");	/* -1: not fnd; else # of spaces left by so */
     85 	if(!SO || !SE || (SG > 0)) SO = SE = 0;
     86 	CD = tgetstr("cd", &tbufptr);
     87 	set_whole_screen();		/* uses LI and CD */
     88 	if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
     89 	free(tptr);
     90 }
     91 
     92 start_screen()
     93 {
     94 	xputs(TI);
     95 	xputs(VS);
     96 
     97 	/* Select normal ASCII and line drawing character sets.
     98 	 */
     99 	if (flags.DECRainbow)
    100 		xputs("\033(B\033)0");
    101 }
    102 
    103 end_screen()
    104 {
    105 	clear_screen();
    106 	xputs(VE);
    107 	xputs(TE);
    108 }
    109 
    110 /* Cursor movements */
    111 extern xchar curx, cury;
    112 
    113 curs(x, y)
    114 register int x, y;	/* not xchar: perhaps xchar is unsigned and
    115 			   curx-x would be unsigned as well */
    116 {
    117 
    118 	if (y == cury && x == curx)
    119 		return;
    120 	if(!ND && (curx != x || x <= 3)) {	/* Extremely primitive */
    121 		cmov(x, y);			/* bunker!wtm */
    122 		return;
    123 	}
    124 	if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
    125 		nocmov(x, y);
    126 	else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
    127 		(void) putchar('\r');
    128 		curx = 1;
    129 		nocmov(x, y);
    130 	} else if(!CM) {
    131 		nocmov(x, y);
    132 	} else
    133 		cmov(x, y);
    134 }
    135 
    136 nocmov(x, y)
    137 {
    138 	if (cury > y) {
    139 		if(UP) {
    140 			while (cury > y) {	/* Go up. */
    141 				xputs(UP);
    142 				cury--;
    143 			}
    144 		} else if(CM) {
    145 			cmov(x, y);
    146 		} else if(HO) {
    147 			home();
    148 			curs(x, y);
    149 		} /* else impossible("..."); */
    150 	} else if (cury < y) {
    151 		if(XD) {
    152 			while(cury < y) {
    153 				xputs(XD);
    154 				cury++;
    155 			}
    156 		} else if(CM) {
    157 			cmov(x, y);
    158 		} else {
    159 			while(cury < y) {
    160 				xputc('\n');
    161 				curx = 1;
    162 				cury++;
    163 			}
    164 		}
    165 	}
    166 	if (curx < x) {		/* Go to the right. */
    167 		if(!ND) cmov(x, y); else	/* bah */
    168 			/* should instead print what is there already */
    169 		while (curx < x) {
    170 			xputs(ND);
    171 			curx++;
    172 		}
    173 	} else if (curx > x) {
    174 		while (curx > x) {	/* Go to the left. */
    175 			xputs(BC);
    176 			curx--;
    177 		}
    178 	}
    179 }
    180 
    181 cmov(x, y)
    182 register x, y;
    183 {
    184 	xputs(tgoto(CM, x-1, y-1));
    185 	cury = y;
    186 	curx = x;
    187 }
    188 
    189 xputc(c) char c; {
    190 	(void) fputc(c, stdout);
    191 }
    192 
    193 xputs(s) char *s; {
    194 #ifdef MSDOS
    195 	fputs(s, stdout);
    196 #else
    197 	tputs(s, 1, xputc);
    198 #endif
    199 }
    200 
    201 cl_end() {
    202 	if(CE)
    203 		xputs(CE);
    204 	else {	/* no-CE fix - free after Harold Rynes */
    205 		/* this looks terrible, especially on a slow terminal
    206 		   but is better than nothing */
    207 		register cx = curx, cy = cury;
    208 
    209 		while(curx < COLNO) {
    210 			xputc(' ');
    211 			curx++;
    212 		}
    213 		curs(cx, cy);
    214 	}
    215 }
    216 
    217 clear_screen() {
    218 	xputs(CL);
    219 	home();
    220 }
    221 
    222 home()
    223 {
    224 	if(HO)
    225 		xputs(HO);
    226 	else if(CM)
    227 		xputs(tgoto(CM, 0, 0));
    228 	else
    229 		curs(1, 1);	/* using UP ... */
    230 	curx = cury = 1;
    231 }
    232 
    233 standoutbeg()
    234 {
    235 	if(SO) xputs(SO);
    236 }
    237 
    238 standoutend()
    239 {
    240 	if(SE) xputs(SE);
    241 }
    242 
    243 backsp()
    244 {
    245 	xputs(BC);
    246 	curx--;
    247 }
    248 
    249 bell()
    250 {
    251 #ifdef DGK
    252 	if (flags.silent) return;
    253 #endif /* DGK /**/
    254 	(void) putchar('\007');		/* curx does not change */
    255 	(void) fflush(stdout);
    256 }
    257 
    258 static short tmspc10[] = {		/* from termcap */
    259 	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
    260 };
    261 
    262 delay_output() {
    263 	/* delay 50 ms - could also use a 'nap'-system call */
    264 	/* BUG: if the padding character is visible, as it is on the 5620
    265 	   then this looks terrible. */
    266 #ifdef MSDOS
    267 	/* simulate the delay with "cursor here" */
    268 	register i;
    269 	for (i = 0; i < 3; i++) {
    270 		cmov(curx, cury);
    271 		(void) fflush(stdout);
    272 	}
    273 #else
    274 	if(!flags.nonull)
    275 		tputs("50", 1, xputc);
    276 
    277 		/* cbosgd!cbcephus!pds for SYS V R2 */
    278 		/* is this terminfo, or what? */
    279 		/* tputs("$<50>", 1, xputc); */
    280 
    281 	else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) {
    282 		/* delay by sending cm(here) an appropriate number of times */
    283 		register int cmlen = strlen(tgoto(CM, curx-1, cury-1));
    284 		register int i = 500 + tmspc10[ospeed]/2;
    285 
    286 		while(i > 0) {
    287 			cmov(curx, cury);
    288 			i -= cmlen*tmspc10[ospeed];
    289 		}
    290 	}
    291 #endif /* MSDOS /**/
    292 }
    293 
    294 cl_eos()			/* free after Robert Viduya */
    295 {				/* must only be called with curx = 1 */
    296 
    297 	if(CD)
    298 		xputs(CD);
    299 	else {
    300 		register int cx = curx, cy = cury;
    301 		while(cury <= LI-2) {
    302 			cl_end();
    303 			xputc('\n');
    304 			curx = 1;
    305 			cury++;
    306 		}
    307 		cl_end();
    308 		curs(cx, cy);
    309 	}
    310 }