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