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