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