xref: /netbsd/games/hack/hack.topl.c (revision bf9ec67e)
1 /*	$NetBSD: hack.topl.c,v 1.6 2002/05/26 00:12:12 wiz Exp $	*/
2 
3 /*
4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5  */
6 
7 #include <sys/cdefs.h>
8 #ifndef lint
9 __RCSID("$NetBSD: hack.topl.c,v 1.6 2002/05/26 00:12:12 wiz Exp $");
10 #endif				/* not lint */
11 
12 #include <stdlib.h>
13 #include "hack.h"
14 #include "extern.h"
15 
16 char            toplines[BUFSZ];
17 xchar           tlx, tly;	/* set by pline; used by addtopl */
18 
19 struct topl {
20 	struct topl    *next_topl;
21 	char           *topl_text;
22 }              *old_toplines, *last_redone_topl;
23 #define	OTLMAX	20		/* max nr of old toplines remembered */
24 
25 int
26 doredotopl()
27 {
28 	if (last_redone_topl)
29 		last_redone_topl = last_redone_topl->next_topl;
30 	if (!last_redone_topl)
31 		last_redone_topl = old_toplines;
32 	if (last_redone_topl) {
33 		(void) strcpy(toplines, last_redone_topl->topl_text);
34 	}
35 	redotoplin();
36 	return (0);
37 }
38 
39 void
40 redotoplin()
41 {
42 	home();
43 	if (strchr(toplines, '\n'))
44 		cl_end();
45 	putstr(toplines);
46 	cl_end();
47 	tlx = curx;
48 	tly = cury;
49 	flags.toplin = 1;
50 	if (tly > 1)
51 		more();
52 }
53 
54 void
55 remember_topl()
56 {
57 	struct topl    *tl;
58 	int             cnt = OTLMAX;
59 	if (last_redone_topl &&
60 	    !strcmp(toplines, last_redone_topl->topl_text))
61 		return;
62 	if (old_toplines &&
63 	    !strcmp(toplines, old_toplines->topl_text))
64 		return;
65 	last_redone_topl = 0;
66 	tl = (struct topl *)
67 		alloc((unsigned) (strlen(toplines) + sizeof(struct topl) + 1));
68 	tl->next_topl = old_toplines;
69 	tl->topl_text = (char *) (tl + 1);
70 	(void) strcpy(tl->topl_text, toplines);
71 	old_toplines = tl;
72 	while (cnt && tl) {
73 		cnt--;
74 		tl = tl->next_topl;
75 	}
76 	if (tl && tl->next_topl) {
77 		free((char *) tl->next_topl);
78 		tl->next_topl = 0;
79 	}
80 }
81 
82 void
83 addtopl(s)
84 	const char           *s;
85 {
86 	curs(tlx, tly);
87 	if (tlx + strlen(s) > CO)
88 		putsym('\n');
89 	putstr(s);
90 	tlx = curx;
91 	tly = cury;
92 	flags.toplin = 1;
93 }
94 
95 void
96 xmore(s)
97 	const char *s;	/* allowed chars besides space/return */
98 {
99 	if (flags.toplin) {
100 		curs(tlx, tly);
101 		if (tlx + 8 > CO)
102 			putsym('\n'), tly++;
103 	}
104 	if (flags.standout)
105 		standoutbeg();
106 	putstr("--More--");
107 	if (flags.standout)
108 		standoutend();
109 
110 	xwaitforspace(s);
111 	if (flags.toplin && tly > 1) {
112 		home();
113 		cl_end();
114 		docorner(1, tly - 1);
115 	}
116 	flags.toplin = 0;
117 }
118 
119 void
120 more()
121 {
122 	xmore("");
123 }
124 
125 void
126 cmore(s)
127 	const char           *s;
128 {
129 	xmore(s);
130 }
131 
132 void
133 clrlin()
134 {
135 	if (flags.toplin) {
136 		home();
137 		cl_end();
138 		if (tly > 1)
139 			docorner(1, tly - 1);
140 		remember_topl();
141 	}
142 	flags.toplin = 0;
143 }
144 
145 void
146 pline(const char *fmt, ...)
147 {
148 	va_list ap;
149 
150 	va_start(ap, fmt);
151 	vpline(fmt, ap);
152 	va_end(ap);
153 }
154 
155 void
156 vpline(line, ap)
157 	const char *line;
158 	va_list ap;
159 {
160 	char            pbuf[BUFSZ];
161 	char           *bp = pbuf, *tl;
162 	int             n, n0;
163 
164 	if (!line || !*line)
165 		return;
166 	if (!strchr(line, '%'))
167 		(void) strcpy(pbuf, line);
168 	else
169 		(void) vsprintf(pbuf, line, ap);
170 	if (flags.toplin == 1 && !strcmp(pbuf, toplines))
171 		return;
172 	nscr();			/* %% */
173 
174 	/* If there is room on the line, print message on same line */
175 	/* But messages like "You die..." deserve their own line */
176 	n0 = strlen(bp);
177 	if (flags.toplin == 1 && tly == 1 &&
178 	    n0 + strlen(toplines) + 3 < CO - 8 &&	/* leave room for
179 							 * --More-- */
180 	    strncmp(bp, "You ", 4)) {
181 		(void) strcat(toplines, "  ");
182 		(void) strcat(toplines, bp);
183 		tlx += 2;
184 		addtopl(bp);
185 		return;
186 	}
187 	if (flags.toplin == 1)
188 		more();
189 	remember_topl();
190 	toplines[0] = 0;
191 	while (n0) {
192 		if (n0 >= CO) {
193 			/* look for appropriate cut point */
194 			n0 = 0;
195 			for (n = 0; n < CO; n++)
196 				if (bp[n] == ' ')
197 					n0 = n;
198 			if (!n0)
199 				for (n = 0; n < CO - 1; n++)
200 					if (!letter(bp[n]))
201 						n0 = n;
202 			if (!n0)
203 				n0 = CO - 2;
204 		}
205 		(void) strncpy((tl = eos(toplines)), bp, n0);
206 		tl[n0] = 0;
207 		bp += n0;
208 
209 		/* remove trailing spaces, but leave one */
210 		while (n0 > 1 && tl[n0 - 1] == ' ' && tl[n0 - 2] == ' ')
211 			tl[--n0] = 0;
212 
213 		n0 = strlen(bp);
214 		if (n0 && tl[0])
215 			(void) strcat(tl, "\n");
216 	}
217 	redotoplin();
218 }
219 
220 void
221 putsym(c)
222 	char            c;
223 {
224 	switch (c) {
225 	case '\b':
226 		backsp();
227 		return;
228 	case '\n':
229 		curx = 1;
230 		cury++;
231 		if (cury > tly)
232 			tly = cury;
233 		break;
234 	default:
235 		if (curx == CO)
236 			putsym('\n');	/* 1 <= curx <= CO; avoid CO */
237 		else
238 			curx++;
239 	}
240 	(void) putchar(c);
241 }
242 
243 void
244 putstr(s)
245 	const char           *s;
246 {
247 	while (*s)
248 		putsym(*s++);
249 }
250