xref: /openbsd/games/hack/hack.termcap.c (revision aed906e4)
1 /*	$OpenBSD: hack.termcap.c,v 1.9 2016/01/09 18:33:15 mestre Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <curses.h>
65 #include <stdlib.h>
66 #include <term.h>
67 
68 #include "hack.h"
69 
70 static char tbuf[512];
71 static char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
72 static char *VS, *VE;
73 static int SG;
74 static char PC = '\0';
75 char *CD;		/* tested in pri.c: docorner() */
76 int CO, LI;		/* used in pri.c and whatis.c */
77 
78 static void nocmov(int, int);
79 static void cmov(int, int);
80 static int  xputc(int);
81 static void xputs(char *);
82 
83 void
startup(void)84 startup(void)
85 {
86 	char *term;
87 	char *tptr;
88 	char *tbufptr, *pc;
89 
90 	tptr = (char *) alloc(1024);
91 
92 	tbufptr = tbuf;
93 	if(!(term = getenv("TERM")))
94 		error("Can't get TERM.");
95 	if(!strncmp(term, "5620", 4))
96 		flags.nonull = 1;	/* this should be a termcap flag */
97 	if(tgetent(tptr, term) < 1)
98 		error("Unknown terminal type: %s.", term);
99 	if ((pc = tgetstr("pc", &tbufptr)))
100 		PC = *pc;
101 	if(!(BC = tgetstr("le", &tbufptr))) {
102 		if(!tgetflag("bs"))
103 			error("Terminal must backspace.");
104 		BC = tbufptr;
105 		tbufptr += 2;
106 		*BC = '\b';
107 	}
108 	HO = tgetstr("ho", &tbufptr);
109 	CO = tgetnum("co");
110 	LI = tgetnum("li");
111 	if(CO < COLNO || LI < ROWNO+2)
112 		setclipped();
113 	if(!(CL = tgetstr("cl", &tbufptr)))
114 		error("Hack needs CL.");
115 	ND = tgetstr("nd", &tbufptr);
116 	if(tgetflag("os"))
117 		error("Hack can't have OS.");
118 	CE = tgetstr("ce", &tbufptr);
119 	UP = tgetstr("up", &tbufptr);
120 	/* It seems that xd is no longer supported, and we should use
121 	   a linefeed instead; unfortunately this requires resetting
122 	   CRMOD, and many output routines will have to be modified
123 	   slightly. Let's leave that till the next release. */
124 	XD = tgetstr("xd", &tbufptr);
125 /* not: 		XD = tgetstr("do", &tbufptr); */
126 	if(!(CM = tgetstr("cm", &tbufptr))) {
127 		if(!UP && !HO)
128 			error("Hack needs CM or UP or HO.");
129 		printf("Playing hack on terminals without cm is suspect...\n");
130 		getret();
131 	}
132 	SO = tgetstr("so", &tbufptr);
133 	SE = tgetstr("se", &tbufptr);
134 	SG = tgetnum("sg");	/* -1: not fnd; else # of spaces left by so */
135 	if(!SO || !SE || (SG > 0)) SO = SE = 0;
136 	CD = tgetstr("cd", &tbufptr);
137 	set_whole_screen();		/* uses LI and CD */
138 	if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
139 	free(tptr);
140 }
141 
142 void
start_screen(void)143 start_screen(void)
144 {
145 	xputs(TI);
146 	xputs(VS);
147 }
148 
149 void
end_screen(void)150 end_screen(void)
151 {
152 	xputs(VE);
153 	xputs(TE);
154 }
155 
156 /* Cursor movements */
157 extern xchar curx, cury;
158 
159 /* int x, y;     not xchar: perhaps xchar is unsigned and
160  * curx-x would be unsigned as well
161  */
162 void
curs(int x,int y)163 curs(int x, int y)
164 {
165 	if (y == cury && x == curx)
166 		return;
167 	if(!ND && (curx != x || x <= 3)) {	/* Extremely primitive */
168 		cmov(x, y);			/* bunker!wtm */
169 		return;
170 	}
171 	if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
172 		nocmov(x, y);
173 	else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
174 		(void) putchar('\r');
175 		curx = 1;
176 		nocmov(x, y);
177 	} else if(!CM) {
178 		nocmov(x, y);
179 	} else
180 		cmov(x, y);
181 }
182 
183 static void
nocmov(int x,int y)184 nocmov(int x, int y)
185 {
186 	if (cury > y) {
187 		if(UP) {
188 			while (cury > y) {	/* Go up. */
189 				xputs(UP);
190 				cury--;
191 			}
192 		} else if(CM) {
193 			cmov(x, y);
194 		} else if(HO) {
195 			home();
196 			curs(x, y);
197 		} /* else impossible("..."); */
198 	} else if (cury < y) {
199 		if(XD) {
200 			while(cury < y) {
201 				xputs(XD);
202 				cury++;
203 			}
204 		} else if(CM) {
205 			cmov(x, y);
206 		} else {
207 			while(cury < y) {
208 				xputc('\n');
209 				curx = 1;
210 				cury++;
211 			}
212 		}
213 	}
214 	if (curx < x) {		/* Go to the right. */
215 		if(!ND) cmov(x, y); else	/* bah */
216 			/* should instead print what is there already */
217 		while (curx < x) {
218 			xputs(ND);
219 			curx++;
220 		}
221 	} else if (curx > x) {
222 		while (curx > x) {	/* Go to the left. */
223 			xputs(BC);
224 			curx--;
225 		}
226 	}
227 }
228 
229 static void
cmov(int x,int y)230 cmov(int x, int y)
231 {
232 	xputs(tgoto(CM, x-1, y-1));
233 	cury = y;
234 	curx = x;
235 }
236 
237 static int
xputc(int c)238 xputc(int c)
239 {
240 	return fputc(c, stdout);
241 }
242 
243 static void
xputs(char * s)244 xputs(char *s)
245 {
246 	tputs(s, 1, xputc);
247 }
248 
249 void
cl_end(void)250 cl_end(void)
251 {
252 	if(CE)
253 		xputs(CE);
254 	else {	/* no-CE fix - free after Harold Rynes */
255 		/* this looks terrible, especially on a slow terminal
256 		   but is better than nothing */
257 		int cx = curx, cy = cury;
258 
259 		while(curx < COLNO) {
260 			xputc(' ');
261 			curx++;
262 		}
263 		curs(cx, cy);
264 	}
265 }
266 
267 void
clr_screen(void)268 clr_screen(void)
269 {
270 	xputs(CL);
271 	curx = cury = 1;
272 }
273 
274 void
home(void)275 home(void)
276 {
277 	if(HO)
278 		xputs(HO);
279 	else if(CM)
280 		xputs(tgoto(CM, 0, 0));
281 	else
282 		curs(1, 1);	/* using UP ... */
283 	curx = cury = 1;
284 }
285 
286 void
standoutbeg(void)287 standoutbeg(void)
288 {
289 	if(SO) xputs(SO);
290 }
291 
292 void
standoutend(void)293 standoutend(void)
294 {
295 	if(SE) xputs(SE);
296 }
297 
298 void
backsp(void)299 backsp(void)
300 {
301 	xputs(BC);
302 	curx--;
303 }
304 
305 void
hackbell(void)306 hackbell(void)
307 {
308 	(void) putchar('\007');		/* curx does not change */
309 	(void) fflush(stdout);
310 }
311 
312 /* free after Robert Viduya
313  * must only be called with curx = 1
314  */
315 void
cl_eos(void)316 cl_eos(void)
317 {
318 
319 	if(CD)
320 		xputs(CD);
321 	else {
322 		int cx = curx, cy = cury;
323 		while(cury <= LI-2) {
324 			cl_end();
325 			xputc('\n');
326 			curx = 1;
327 			cury++;
328 		}
329 		cl_end();
330 		curs(cx, cy);
331 	}
332 }
333