1 /* $OpenBSD: hack.topl.c,v 1.12 2016/01/09 18:33:15 mestre Exp $ */
2
3 /*
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5 * Amsterdam
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 /*
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 */
63
64 #include <stdio.h>
65 #include <stdlib.h>
66
67 #include "hack.h"
68
69 extern int CO;
70
71 char toplines[BUFSZ];
72 xchar tlx, tly; /* set by pline; used by addtopl */
73
74 struct topl {
75 struct topl *next_topl;
76 char *topl_text;
77 } *old_toplines, *last_redone_topl;
78 #define OTLMAX 20 /* max nr of old toplines remembered */
79
80 static void redotoplin(void);
81 static void xmore(char *);
82
83
84 int
doredotopl(void)85 doredotopl(void)
86 {
87 if(last_redone_topl)
88 last_redone_topl = last_redone_topl->next_topl;
89 if(!last_redone_topl)
90 last_redone_topl = old_toplines;
91 if(last_redone_topl){
92 (void) strlcpy(toplines, last_redone_topl->topl_text, sizeof toplines);
93 }
94 redotoplin();
95 return(0);
96 }
97
98 static void
redotoplin(void)99 redotoplin(void)
100 {
101 home();
102 if(strchr(toplines, '\n')) cl_end();
103 putstr(toplines);
104 cl_end();
105 tlx = curx;
106 tly = cury;
107 flags.toplin = 1;
108 if(tly > 1)
109 more();
110 }
111
112 void
remember_topl(void)113 remember_topl(void)
114 {
115 struct topl *tl;
116 int cnt = OTLMAX;
117 size_t slen;
118
119 if(last_redone_topl &&
120 !strcmp(toplines, last_redone_topl->topl_text)) return;
121 if(old_toplines &&
122 !strcmp(toplines, old_toplines->topl_text)) return;
123 last_redone_topl = 0;
124 slen = strlen(toplines) + 1;
125 tl = (struct topl *)
126 alloc(sizeof(struct topl) + slen);
127 tl->next_topl = old_toplines;
128 tl->topl_text = (char *)(tl + 1);
129 (void) strlcpy(tl->topl_text, toplines, slen);
130 old_toplines = tl;
131 while(cnt && tl){
132 cnt--;
133 tl = tl->next_topl;
134 }
135 if(tl && tl->next_topl){
136 free(tl->next_topl);
137 tl->next_topl = 0;
138 }
139 }
140
141 void
addtopl(char * s)142 addtopl(char *s)
143 {
144 curs(tlx,tly);
145 if(tlx + strlen(s) > CO) putsym('\n');
146 putstr(s);
147 tlx = curx;
148 tly = cury;
149 flags.toplin = 1;
150 }
151
152 static void
xmore(char * s)153 xmore(char *s)
154 {
155 if(flags.toplin) {
156 curs(tlx, tly);
157 if(tlx + 8 > CO) putsym('\n'), tly++;
158 }
159
160 if(flags.standout)
161 standoutbeg();
162 putstr("--More--");
163 if(flags.standout)
164 standoutend();
165
166 xwaitforspace(s);
167 if(flags.toplin && tly > 1) {
168 home();
169 cl_end();
170 docorner(1, tly-1);
171 }
172 flags.toplin = 0;
173 }
174
175 void
more(void)176 more(void)
177 {
178 xmore("");
179 }
180
181 void
cmore(char * s)182 cmore(char *s)
183 {
184 xmore(s);
185 }
186
187 void
clrlin(void)188 clrlin(void)
189 {
190 if(flags.toplin) {
191 home();
192 cl_end();
193 if(tly > 1) docorner(1, tly-1);
194 remember_topl();
195 }
196 flags.toplin = 0;
197 }
198
199 void
pline(const char * line,...)200 pline(const char *line, ...)
201 {
202 va_list ap;
203
204 va_start(ap, line);
205 vpline(line, ap);
206 va_end(ap);
207 }
208
209 void
vpline(const char * line,va_list ap)210 vpline(const char *line, va_list ap)
211 {
212 char pbuf[BUFSZ];
213 char *bp = pbuf, *tl;
214 int n,n0;
215
216 if(!line || !*line) return;
217 (void) vsnprintf(pbuf, sizeof pbuf, line, ap);
218 if(flags.toplin == 1 && !strcmp(pbuf, toplines)) return;
219 nscr(); /* %% */
220
221 /* If there is room on the line, print message on same line */
222 /* But messages like "You die..." deserve their own line */
223 n0 = strlen(bp);
224 if(flags.toplin == 1 && tly == 1 &&
225 n0 + strlen(toplines) + 3 < CO-8 && /* leave room for --More-- */
226 strncmp(bp, "You ", 4)) {
227 (void) strlcat(toplines, " ", sizeof toplines);
228 (void) strlcat(toplines, bp, sizeof toplines);
229 tlx += 2;
230 addtopl(bp);
231 return;
232 }
233 if(flags.toplin == 1) more();
234 remember_topl();
235 toplines[0] = 0;
236 while(n0){
237 if(n0 >= CO){
238 /* look for appropriate cut point */
239 n0 = 0;
240 for(n = 0; n < CO; n++) if(bp[n] == ' ')
241 n0 = n;
242 if(!n0) for(n = 0; n < CO-1; n++)
243 if(!letter(bp[n])) n0 = n;
244 if(!n0) n0 = CO-2;
245 }
246 (void) strncpy((tl = eos(toplines)), bp, n0);
247 tl[n0] = '\0';
248 bp += n0;
249
250 /* remove trailing spaces, but leave one */
251 while(n0 > 1 && tl[n0-1] == ' ' && tl[n0-2] == ' ')
252 tl[--n0] = 0;
253
254 n0 = strlen(bp);
255 if(n0 && tl[0])
256 (void) strlcat(tl, "\n",
257 toplines + sizeof toplines - tl);
258 }
259 redotoplin();
260 }
261
262 void
putsym(char c)263 putsym(char c)
264 {
265 switch(c) {
266 case '\b':
267 backsp();
268 return;
269 case '\n':
270 curx = 1;
271 cury++;
272 if(cury > tly) tly = cury;
273 break;
274 default:
275 if(curx == CO)
276 putsym('\n'); /* 1 <= curx <= CO; avoid CO */
277 else
278 curx++;
279 }
280 (void) putchar(c);
281 }
282
283 void
putstr(char * s)284 putstr(char *s)
285 {
286 while(*s) putsym(*s++);
287 }
288