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