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