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