jcs's openbsd hax
openbsd
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
69extern int CO;
70
71char toplines[BUFSZ];
72xchar tlx, tly; /* set by pline; used by addtopl */
73
74struct 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
80static void redotoplin(void);
81static void xmore(char *);
82
83
84int
85doredotopl(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
98static void
99redotoplin(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
112void
113remember_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
141void
142addtopl(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
152static void
153xmore(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
175void
176more(void)
177{
178 xmore("");
179}
180
181void
182cmore(char *s)
183{
184 xmore(s);
185}
186
187void
188clrlin(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
199void
200pline(const char *line, ...)
201{
202 va_list ap;
203
204 va_start(ap, line);
205 vpline(line, ap);
206 va_end(ap);
207}
208
209void
210vpline(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
262void
263putsym(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
283void
284putstr(char *s)
285{
286 while(*s) putsym(*s++);
287}