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