xref: /openbsd-src/games/hack/hack.topl.c (revision aed906e4b20d9afbda31247cdb6acf6f29da8819)
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