Merge from vendor branch WPA_SUPPLICANT:
[dragonfly.git] / games / hack / hack.topl.c
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.topl.c - version 1.0.2 */
3 /* $FreeBSD: src/games/hack/hack.topl.c,v 1.3 1999/11/16 02:57:12 billf Exp $ */
4 /* $DragonFly: src/games/hack/hack.topl.c,v 1.3 2006/08/21 19:45:32 pavalos Exp $ */
5
6 #include "hack.h"
7 extern int CO;
8
9 char toplines[BUFSZ];
10 xchar tlx, tly;                 /* set by pline; used by addtopl */
11
12 struct topl {
13         struct topl *next_topl;
14         char *topl_text;
15 } *old_toplines, *last_redone_topl;
16 #define OTLMAX  20              /* max nr of old toplines remembered */
17
18 static void     redotoplin(void);
19 static void     xmore(const char *);
20
21 int
22 doredotopl(void)
23 {
24         if(last_redone_topl)
25                 last_redone_topl = last_redone_topl->next_topl;
26         if(!last_redone_topl)
27                 last_redone_topl = old_toplines;
28         if(last_redone_topl){
29                 strcpy(toplines, last_redone_topl->topl_text);
30         }
31         redotoplin();
32         return(0);
33 }
34
35 static void
36 redotoplin(void)
37 {
38         home();
39         if(index(toplines, '\n')) cl_end();
40         putstr(toplines);
41         cl_end();
42         tlx = curx;
43         tly = cury;
44         flags.toplin = 1;
45         if(tly > 1)
46                 more();
47 }
48
49 void
50 remember_topl(void)
51 {
52 struct topl *tl;
53 int cnt = OTLMAX;
54         if(last_redone_topl &&
55            !strcmp(toplines, last_redone_topl->topl_text)) return;
56         if(old_toplines &&
57            !strcmp(toplines, old_toplines->topl_text)) return;
58         last_redone_topl = 0;
59         tl = (struct topl *)
60                 alloc((unsigned)(strlen(toplines) + sizeof(struct topl) + 1));
61         tl->next_topl = old_toplines;
62         tl->topl_text = (char *)(tl + 1);
63         strcpy(tl->topl_text, toplines);
64         old_toplines = tl;
65         while(cnt && tl){
66                 cnt--;
67                 tl = tl->next_topl;
68         }
69         if(tl && tl->next_topl){
70                 free((char *) tl->next_topl);
71                 tl->next_topl = 0;
72         }
73 }
74
75 void
76 addtopl(const char *s)
77 {
78         curs(tlx,tly);
79         if(tlx + (int)strlen(s) > CO) putsym('\n');
80         putstr(s);
81         tlx = curx;
82         tly = cury;
83         flags.toplin = 1;
84 }
85
86 static void
87 xmore(const char *s)    /* allowed chars besides space/return */
88 {
89         if(flags.toplin) {
90                 curs(tlx, tly);
91                 if(tlx + 8 > CO) putsym('\n'), tly++;
92         }
93
94         if(flags.standout)
95                 standoutbeg();
96         putstr("--More--");
97         if(flags.standout)
98                 standoutend();
99
100         xwaitforspace(s);
101         if(flags.toplin && tly > 1) {
102                 home();
103                 cl_end();
104                 docorner(1, tly-1);
105         }
106         flags.toplin = 0;
107 }
108
109 void
110 more(void)
111 {
112         xmore("");
113 }
114
115 void
116 cmore(const char *s)
117 {
118         xmore(s);
119 }
120
121 void
122 clrlin(void)
123 {
124         if(flags.toplin) {
125                 home();
126                 cl_end();
127                 if(tly > 1) docorner(1, tly-1);
128                 remember_topl();
129         }
130         flags.toplin = 0;
131 }
132
133 void
134 pline(const char *line, ...)
135 {
136         va_list ap;
137         va_start(ap, line);
138         vpline(line, ap);
139         va_end(ap);
140 }
141
142 /*VARARGS1*/
143 void
144 vpline(const char *line, va_list ap)
145 {
146         char pbuf[BUFSZ];
147         char *bp = pbuf, *tl;
148         int n,n0;
149
150         if(!line || !*line) return;
151         if(!index(line, '%')) strcpy(pbuf,line); else
152         vsprintf(pbuf, line, ap);
153         if(flags.toplin == 1 && !strcmp(pbuf, toplines)) return;
154         nscr();         /* %% */
155
156         /* If there is room on the line, print message on same line */
157         /* But messages like "You die..." deserve their own line */
158         n0 = strlen(bp);
159         if(flags.toplin == 1 && tly == 1 &&
160             n0 + (int)strlen(toplines) + 3 < CO-8 && /* room for --More-- */
161             strncmp(bp, "You ", 4)) {
162                 strcat(toplines, "  ");
163                 strcat(toplines, bp);
164                 tlx += 2;
165                 addtopl(bp);
166                 return;
167         }
168         if(flags.toplin == 1) more();
169         remember_topl();
170         toplines[0] = 0;
171         while(n0){
172                 if(n0 >= CO){
173                         /* look for appropriate cut point */
174                         n0 = 0;
175                         for(n = 0; n < CO; n++) if(bp[n] == ' ')
176                                 n0 = n;
177                         if(!n0) for(n = 0; n < CO-1; n++)
178                                 if(!letter(bp[n])) n0 = n;
179                         if(!n0) n0 = CO-2;
180                 }
181                 strncpy((tl = eos(toplines)), bp, n0);
182                 tl[n0] = 0;
183                 bp += n0;
184
185                 /* remove trailing spaces, but leave one */
186                 while(n0 > 1 && tl[n0-1] == ' ' && tl[n0-2] == ' ')
187                         tl[--n0] = 0;
188
189                 n0 = strlen(bp);
190                 if(n0 && tl[0]) strcat(tl, "\n");
191         }
192         redotoplin();
193 }
194
195 void
196 putsym(char c)
197 {
198         switch(c) {
199         case '\b':
200                 backsp();
201                 return;
202         case '\n':
203                 curx = 1;
204                 cury++;
205                 if(cury > tly) tly = cury;
206                 break;
207         default:
208                 if(curx == CO)
209                         putsym('\n');   /* 1 <= curx <= CO; avoid CO */
210                 else
211                         curx++;
212         }
213         putchar(c);
214 }
215
216 void
217 putstr(const char *s)
218 {
219         while(*s) putsym(*s++);
220 }