]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.termcap.c
Generate <>& symbolically. I'm avoiding .../dist/... directories for now.
[bsdgames-darwin.git] / hack / hack.termcap.c
1 /* $NetBSD: hack.termcap.c,v 1.11 2001/11/02 18:27:00 christos Exp $ */
2
3 /*
4 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5 */
6
7 #include <sys/cdefs.h>
8 #ifndef lint
9 __RCSID("$NetBSD: hack.termcap.c,v 1.11 2001/11/02 18:27:00 christos Exp $");
10 #endif /* not lint */
11
12 #include <string.h>
13 #include <termios.h>
14 #include <termcap.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include "hack.h"
18 #include "extern.h"
19 #include "def.flag.h" /* for flags.nonull */
20
21 static struct tinfo *info;
22 static char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
23 static char *VS, *VE;
24 static int SG;
25 static char PC = '\0';
26 static char BC_char = '\b'; /* if bc is not set use this */
27 char *CD; /* tested in pri.c: docorner() */
28 int CO, LI; /* used in pri.c and whatis.c */
29
30 void
31 startup()
32 {
33 char *term;
34 char *pc;
35
36
37 if (!(term = getenv("TERM")))
38 error("Can't get TERM.");
39 if (!strncmp(term, "5620", 4))
40 flags.nonull = 1; /* this should be a termcap flag */
41 if (t_getent(&info, term) < 1)
42 error("Unknown terminal type: %s.", term);
43 if ((pc = t_agetstr(info, "pc")) != NULL)
44 PC = *pc;
45 if (!(BC = t_agetstr(info, "bc"))) {
46 if (!t_getflag(info, "bs"))
47 error("Terminal must backspace.");
48 BC = &BC_char;
49 }
50 HO = t_agetstr(info, "ho");
51 CO = t_getnum(info, "co");
52 LI = t_getnum(info, "li");
53 if (CO < COLNO || LI < ROWNO + 2)
54 setclipped();
55 if (!(CL = t_agetstr(info, "cl")))
56 error("Hack needs CL.");
57 ND = t_agetstr(info, "nd");
58 if (t_getflag(info, "os"))
59 error("Hack can't have OS.");
60 CE = t_agetstr(info, "ce");
61 UP = t_agetstr(info, "up");
62 /*
63 * It seems that xd is no longer supported, and we should use a
64 * linefeed instead; unfortunately this requires resetting CRMOD, and
65 * many output routines will have to be modified slightly. Let's
66 * leave that till the next release.
67 */
68 XD = t_agetstr(info, "xd");
69 /* not: XD = t_agetstr(info, "do"); */
70 if (!(CM = t_agetstr(info, "cm"))) {
71 if (!UP && !HO)
72 error("Hack needs CM or UP or HO.");
73 printf("Playing hack on terminals without cm is suspect...\n");
74 getret();
75 }
76 SO = t_agetstr(info, "so");
77 SE = t_agetstr(info, "se");
78 SG = t_getnum(info, "sg"); /* -1: not fnd; else # of spaces left by so */
79 if (!SO || !SE || (SG > 0))
80 SO = SE = 0;
81 CD = t_agetstr(info, "cd");
82 set_whole_screen(); /* uses LI and CD */
83 }
84
85 void
86 start_screen()
87 {
88 xputs(TI);
89 xputs(VS);
90 }
91
92 void
93 end_screen()
94 {
95 xputs(VE);
96 xputs(TE);
97 }
98
99 /* Cursor movements */
100 void
101 curs(x, y)
102 int x, y; /* not xchar: perhaps xchar is unsigned and
103 * curx-x would be unsigned as well */
104 {
105
106 if (y == cury && x == curx)
107 return;
108 if (!ND && (curx != x || x <= 3)) { /* Extremely primitive */
109 cmov(x, y); /* bunker!wtm */
110 return;
111 }
112 if (abs(cury - y) <= 3 && abs(curx - x) <= 3)
113 nocmov(x, y);
114 else if ((x <= 3 && abs(cury - y) <= 3) || (!CM && x < abs(curx - x))) {
115 (void) putchar('\r');
116 curx = 1;
117 nocmov(x, y);
118 } else if (!CM) {
119 nocmov(x, y);
120 } else
121 cmov(x, y);
122 }
123
124 void
125 nocmov(x, y)
126 int x, y;
127 {
128 if (cury > y) {
129 if (UP) {
130 while (cury > y) { /* Go up. */
131 xputs(UP);
132 cury--;
133 }
134 } else if (CM) {
135 cmov(x, y);
136 } else if (HO) {
137 home();
138 curs(x, y);
139 } /* else impossible("..."); */
140 } else if (cury < y) {
141 if (XD) {
142 while (cury < y) {
143 xputs(XD);
144 cury++;
145 }
146 } else if (CM) {
147 cmov(x, y);
148 } else {
149 while (cury < y) {
150 xputc('\n');
151 curx = 1;
152 cury++;
153 }
154 }
155 }
156 if (curx < x) { /* Go to the right. */
157 if (!ND)
158 cmov(x, y);
159 else /* bah */
160 /* should instead print what is there already */
161 while (curx < x) {
162 xputs(ND);
163 curx++;
164 }
165 } else if (curx > x) {
166 while (curx > x) { /* Go to the left. */
167 xputs(BC);
168 curx--;
169 }
170 }
171 }
172
173 void
174 cmov(x, y)
175 int x, y;
176 {
177 char buf[256];
178
179 if (t_goto(info, CM, x - 1, y - 1, buf, 255) >= 0) {
180 xputs(buf);
181 cury = y;
182 curx = x;
183 }
184 }
185
186 int
187 xputc(c)
188 char c;
189 {
190 return (fputc(c, stdout));
191 }
192
193 void
194 xputs(s)
195 char *s;
196 {
197 tputs(s, 1, xputc);
198 }
199
200 void
201 cl_end()
202 {
203 if (CE)
204 xputs(CE);
205 else { /* no-CE fix - free after Harold Rynes */
206 /*
207 * this looks terrible, especially on a slow terminal but is
208 * better than nothing
209 */
210 int cx = curx, cy = cury;
211
212 while (curx < COLNO) {
213 xputc(' ');
214 curx++;
215 }
216 curs(cx, cy);
217 }
218 }
219
220 void
221 clear_screen()
222 {
223 xputs(CL);
224 curx = cury = 1;
225 }
226
227 void
228 home()
229 {
230 char buf[256];
231
232 if (HO)
233 xputs(HO);
234 else if ((CM) && (t_goto(info, CM, 0, 0, buf, 255) >= 0))
235 xputs(buf);
236 else
237 curs(1, 1); /* using UP ... */
238 curx = cury = 1;
239 }
240
241 void
242 standoutbeg()
243 {
244 if (SO)
245 xputs(SO);
246 }
247
248 void
249 standoutend()
250 {
251 if (SE)
252 xputs(SE);
253 }
254
255 void
256 backsp()
257 {
258 xputs(BC);
259 curx--;
260 }
261
262 void
263 bell()
264 {
265 (void) putchar('\007'); /* curx does not change */
266 (void) fflush(stdout);
267 }
268
269 void
270 delay_output()
271 {
272
273 /* delay 50 ms - could also use a 'nap'-system call */
274 /* or the usleep call like this :-) */
275 usleep(50000);
276 }
277
278 void
279 cl_eos()
280 { /* free after Robert Viduya *//* must only be
281 * called with curx = 1 */
282
283 if (CD)
284 xputs(CD);
285 else {
286 int cx = curx, cy = cury;
287 while (cury <= LI - 2) {
288 cl_end();
289 xputc('\n');
290 curx = 1;
291 cury++;
292 }
293 cl_end();
294 curs(cx, cy);
295 }
296 }