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