Merge from vendor branch BSDTAR:
[dragonfly.git] / games / hack / hack.termcap.c
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.termcap.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.termcap.c,v 1.10 1999/11/16 10:26:38 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.termcap.c,v 1.2 2003/06/17 04:25:24 dillon Exp $ */
5
6 #include <stdio.h>
7 #include <termcap.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include "config.h"     /* for ROWNO and COLNO */
11 #include "def.flag.h"   /* for flags.nonull */
12 extern long *alloc();
13
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         char *term;
25         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(tgetent(tptr, term) < 1)
34                 error("Unknown terminal type: %s.", term);
35         if(tgetflag("NP") || tgetflag("nx"))
36                 flags.nonull = 1;
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 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 int 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                 int 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, 3, 2, 1
235 };
236
237 #if 0
238 delay_output() {
239         /* delay 50 ms - could also use a 'nap'-system call */
240         /* BUG: if the padding character is visible, as it is on the 5620
241            then this looks terrible. */
242         if(!flags.nonull)
243                 tputs("50", 1, xputc);
244
245                 /* cbosgd!cbcephus!pds for SYS V R2 */
246                 /* is this terminfo, or what? */
247                 /* tputs("$<50>", 1, xputc); */
248         else {
249                 (void) fflush(stdout);
250                 usleep(50*1000);
251         }
252         else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) {
253                 /* delay by sending cm(here) an appropriate number of times */
254                 int cmlen = strlen(tgoto(CM, curx-1, cury-1));
255                 int i = 500 + tmspc10[ospeed]/2;
256
257                 while(i > 0) {
258                         cmov(curx, cury);
259                         i -= cmlen*tmspc10[ospeed];
260                 }
261         }
262 }
263 #endif /* 0 */
264
265 cl_eos()                        /* free after Robert Viduya */
266 {                               /* must only be called with curx = 1 */
267
268         if(CD)
269                 xputs(CD);
270         else {
271                 int cx = curx, cy = cury;
272                 while(cury <= LI-2) {
273                         cl_end();
274                         xputc('\n');
275                         curx = 1;
276                         cury++;
277                 }
278                 cl_end();
279                 curs(cx, cy);
280         }
281 }