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