Merge from vendor branch GCC:
[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.4 2005/05/22 03:37:05 y0netan1 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, *tcUP, *CM, *ND, *XD, *tcBC, *SO, *SE, *TI, *TE;
16 static char *VS, *VE;
17 static int SG;
18 static char tcPC = '\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(__DECONST(char *, "NP")) ||
36             tgetflag(__DECONST(char *, "nx")))
37                 flags.nonull = 1;
38         if(pc = tgetstr(__DECONST(char *, "pc"), &tbufptr))
39                 tcPC = *pc;
40         if(!(tcBC = tgetstr(__DECONST(char *, "bc"), &tbufptr))) {
41                 if(!tgetflag(__DECONST(char *, "bs")))
42                         error("Terminal must backspace.");
43                 tcBC = tbufptr;
44                 tbufptr += 2;
45                 *tcBC = '\b';
46         }
47         HO = tgetstr(__DECONST(char *, "ho"), &tbufptr);
48         CO = tgetnum(__DECONST(char *, "co"));
49         LI = tgetnum(__DECONST(char *, "li"));
50         if(CO < COLNO || LI < ROWNO+2)
51                 setclipped();
52         if(!(CL = tgetstr(__DECONST(char *, "cl"), &tbufptr)))
53                 error("Hack needs CL.");
54         ND = tgetstr(__DECONST(char *, "nd"), &tbufptr);
55         if(tgetflag(__DECONST(char *, "os")))
56                 error("Hack can't have OS.");
57         CE = tgetstr(__DECONST(char *, "ce"), &tbufptr);
58         tcUP = tgetstr(__DECONST(char *, "up"), &tbufptr);
59         /* It seems that xd is no longer supported, and we should use
60            a linefeed instead; unfortunately this requires resetting
61            CRMOD, and many output routines will have to be modified
62            slightly. Let's leave that till the next release. */
63         XD = tgetstr(__DECONST(char *, "xd"), &tbufptr);
64 /* not:                 XD = tgetstr("do", &tbufptr); */
65         if(!(CM = tgetstr(__DECONST(char *, "cm"), &tbufptr))) {
66                 if(!tcUP && !HO)
67                         error("Hack needs CM or UP or HO.");
68                 printf("Playing hack on terminals without cm is suspect...\n");
69                 getret();
70         }
71         SO = tgetstr(__DECONST(char *, "so"), &tbufptr);
72         SE = tgetstr(__DECONST(char *, "se"), &tbufptr);
73         SG = tgetnum(__DECONST(char *, "sg"));
74         if(!SO || !SE || (SG > 0)) SO = SE = 0;
75         CD = tgetstr(__DECONST(char *, "cd"), &tbufptr);
76         set_whole_screen();             /* uses LI and CD */
77         if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
78         free(tptr);
79 }
80
81 start_screen()
82 {
83         xputs(TI);
84         xputs(VS);
85 }
86
87 end_screen()
88 {
89         xputs(VE);
90         xputs(TE);
91 }
92
93 /* Cursor movements */
94 extern xchar curx, cury;
95
96 curs(x, y)
97 int x, y;       /* not xchar: perhaps xchar is unsigned and
98                            curx-x would be unsigned as well */
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                 (void) 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 nocmov(x, y)
120 {
121         if (cury > y) {
122                 if(tcUP) {
123                         while (cury > y) {      /* Go up. */
124                                 xputs(tcUP);
125                                 cury--;
126                         }
127                 } else if(CM) {
128                         cmov(x, y);
129                 } else if(HO) {
130                         home();
131                         curs(x, y);
132                 } /* else impossible("..."); */
133         } else if (cury < y) {
134                 if(XD) {
135                         while(cury < y) {
136                                 xputs(XD);
137                                 cury++;
138                         }
139                 } else if(CM) {
140                         cmov(x, y);
141                 } else {
142                         while(cury < y) {
143                                 xputc('\n');
144                                 curx = 1;
145                                 cury++;
146                         }
147                 }
148         }
149         if (curx < x) {         /* Go to the right. */
150                 if(!ND) cmov(x, y); else        /* bah */
151                         /* should instead print what is there already */
152                 while (curx < x) {
153                         xputs(ND);
154                         curx++;
155                 }
156         } else if (curx > x) {
157                 while (curx > x) {      /* Go to the left. */
158                         xputs(tcBC);
159                         curx--;
160                 }
161         }
162 }
163
164 cmov(x, y)
165 int x, y;
166 {
167         xputs(tgoto(CM, x-1, y-1));
168         cury = y;
169         curx = x;
170 }
171
172 xputc(c) char c; {
173         (void) fputc(c, stdout);
174 }
175
176 xputs(s) char *s; {
177         tputs(s, 1, xputc);
178 }
179
180 cl_end() {
181         if(CE)
182                 xputs(CE);
183         else {  /* no-CE fix - free after Harold Rynes */
184                 /* this looks terrible, especially on a slow terminal
185                    but is better than nothing */
186                 int cx = curx, cy = cury;
187
188                 while(curx < COLNO) {
189                         xputc(' ');
190                         curx++;
191                 }
192                 curs(cx, cy);
193         }
194 }
195
196 clear_screen() {
197         xputs(CL);
198         curx = cury = 1;
199 }
200
201 home()
202 {
203         if(HO)
204                 xputs(HO);
205         else if(CM)
206                 xputs(tgoto(CM, 0, 0));
207         else
208                 curs(1, 1);     /* using tcUP ... */
209         curx = cury = 1;
210 }
211
212 standoutbeg()
213 {
214         if(SO) xputs(SO);
215 }
216
217 standoutend()
218 {
219         if(SE) xputs(SE);
220 }
221
222 backsp()
223 {
224         xputs(tcBC);
225         curx--;
226 }
227
228 bell()
229 {
230         (void) putchar('\007');         /* curx does not change */
231         (void) fflush(stdout);
232 }
233
234 static short tmspc10[] = {              /* from termcap */
235         0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 3, 2, 1
236 };
237
238 #if 0
239 delay_output() {
240         /* delay 50 ms - could also use a 'nap'-system call */
241         /* BUG: if the padding character is visible, as it is on the 5620
242            then this looks terrible. */
243         if(!flags.nonull)
244                 tputs("50", 1, xputc);
245
246                 /* cbosgd!cbcephus!pds for SYS V R2 */
247                 /* is this terminfo, or what? */
248                 /* tputs("$<50>", 1, xputc); */
249         else {
250                 (void) fflush(stdout);
251                 usleep(50*1000);
252         }
253         else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) {
254                 /* delay by sending cm(here) an appropriate number of times */
255                 int cmlen = strlen(tgoto(CM, curx-1, cury-1));
256                 int i = 500 + tmspc10[ospeed]/2;
257
258                 while(i > 0) {
259                         cmov(curx, cury);
260                         i -= cmlen*tmspc10[ospeed];
261                 }
262         }
263 }
264 #endif /* 0 */
265
266 cl_eos()                        /* free after Robert Viduya */
267 {                               /* must only be called with curx = 1 */
268
269         if(CD)
270                 xputs(CD);
271         else {
272                 int cx = curx, cy = cury;
273                 while(cury <= LI-2) {
274                         cl_end();
275                         xputc('\n');
276                         curx = 1;
277                         cury++;
278                 }
279                 cl_end();
280                 curs(cx, cy);
281         }
282 }