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