xref: /openbsd/games/hack/hack.topl.c (revision 78b63d65)
1 /*	$OpenBSD: hack.topl.c,v 1.4 2001/01/28 23:41:46 niklas Exp $	*/
2 
3 /*
4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
5  */
6 
7 #ifndef lint
8 static char rcsid[] = "$OpenBSD: hack.topl.c,v 1.4 2001/01/28 23:41:46 niklas Exp $";
9 #endif /* not lint */
10 
11 #include "hack.h"
12 #include <stdio.h>
13 extern char *eos();
14 extern int CO;
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 doredotopl(){
26 	if(last_redone_topl)
27 		last_redone_topl = last_redone_topl->next_topl;
28 	if(!last_redone_topl)
29 		last_redone_topl = old_toplines;
30 	if(last_redone_topl){
31 		(void) strcpy(toplines, last_redone_topl->topl_text);
32 	}
33 	redotoplin();
34 	return(0);
35 }
36 
37 redotoplin() {
38 	home();
39 	if(strchr(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 remember_topl() {
50 register struct topl *tl;
51 register int cnt = OTLMAX;
52 	if(last_redone_topl &&
53 	   !strcmp(toplines, last_redone_topl->topl_text)) return;
54 	if(old_toplines &&
55 	   !strcmp(toplines, old_toplines->topl_text)) return;
56 	last_redone_topl = 0;
57 	tl = (struct topl *)
58 		alloc((unsigned)(strlen(toplines) + sizeof(struct topl) + 1));
59 	tl->next_topl = old_toplines;
60 	tl->topl_text = (char *)(tl + 1);
61 	(void) strcpy(tl->topl_text, toplines);
62 	old_toplines = tl;
63 	while(cnt && tl){
64 		cnt--;
65 		tl = tl->next_topl;
66 	}
67 	if(tl && tl->next_topl){
68 		free((char *) tl->next_topl);
69 		tl->next_topl = 0;
70 	}
71 }
72 
73 addtopl(s) char *s; {
74 	curs(tlx,tly);
75 	if(tlx + strlen(s) > CO) putsym('\n');
76 	putstr(s);
77 	tlx = curx;
78 	tly = cury;
79 	flags.toplin = 1;
80 }
81 
82 xmore(s)
83 char *s;	/* allowed chars besides space/return */
84 {
85 	if(flags.toplin) {
86 		curs(tlx, tly);
87 		if(tlx + 8 > CO) putsym('\n'), tly++;
88 	}
89 
90 	if(flags.standout)
91 		standoutbeg();
92 	putstr("--More--");
93 	if(flags.standout)
94 		standoutend();
95 
96 	xwaitforspace(s);
97 	if(flags.toplin && tly > 1) {
98 		home();
99 		cl_end();
100 		docorner(1, tly-1);
101 	}
102 	flags.toplin = 0;
103 }
104 
105 more(){
106 	xmore("");
107 }
108 
109 cmore(s)
110 register char *s;
111 {
112 	xmore(s);
113 }
114 
115 clrlin(){
116 	if(flags.toplin) {
117 		home();
118 		cl_end();
119 		if(tly > 1) docorner(1, tly-1);
120 		remember_topl();
121 	}
122 	flags.toplin = 0;
123 }
124 
125 /*VARARGS1*/
126 pline(line,arg1,arg2,arg3,arg4,arg5,arg6)
127 register char *line,*arg1,*arg2,*arg3,*arg4,*arg5,*arg6;
128 {
129 	char pbuf[BUFSZ];
130 	register char *bp = pbuf, *tl;
131 	register int n,n0;
132 
133 	if(!line || !*line) return;
134 	if(!strchr(line, '%')) (void) strcpy(pbuf,line); else
135 	(void) sprintf(pbuf,line,arg1,arg2,arg3,arg4,arg5,arg6);
136 	if(flags.toplin == 1 && !strcmp(pbuf, toplines)) return;
137 	nscr();		/* %% */
138 
139 	/* If there is room on the line, print message on same line */
140 	/* But messages like "You die..." deserve their own line */
141 	n0 = strlen(bp);
142 	if(flags.toplin == 1 && tly == 1 &&
143 	    n0 + strlen(toplines) + 3 < CO-8 &&  /* leave room for --More-- */
144 	    strncmp(bp, "You ", 4)) {
145 		(void) strcat(toplines, "  ");
146 		(void) strcat(toplines, bp);
147 		tlx += 2;
148 		addtopl(bp);
149 		return;
150 	}
151 	if(flags.toplin == 1) more();
152 	remember_topl();
153 	toplines[0] = 0;
154 	while(n0){
155 		if(n0 >= CO){
156 			/* look for appropriate cut point */
157 			n0 = 0;
158 			for(n = 0; n < CO; n++) if(bp[n] == ' ')
159 				n0 = n;
160 			if(!n0) for(n = 0; n < CO-1; n++)
161 				if(!letter(bp[n])) n0 = n;
162 			if(!n0) n0 = CO-2;
163 		}
164 		(void) strncpy((tl = eos(toplines)), bp, n0);
165 		tl[n0] = '\0';
166 		bp += n0;
167 
168 		/* remove trailing spaces, but leave one */
169 		while(n0 > 1 && tl[n0-1] == ' ' && tl[n0-2] == ' ')
170 			tl[--n0] = 0;
171 
172 		n0 = strlen(bp);
173 		if(n0 && tl[0]) (void) strcat(tl, "\n");
174 	}
175 	redotoplin();
176 }
177 
178 putsym(c) char c; {
179 	switch(c) {
180 	case '\b':
181 		backsp();
182 		return;
183 	case '\n':
184 		curx = 1;
185 		cury++;
186 		if(cury > tly) tly = cury;
187 		break;
188 	default:
189 		if(curx == CO)
190 			putsym('\n');	/* 1 <= curx <= CO; avoid CO */
191 		else
192 			curx++;
193 	}
194 	(void) putchar(c);
195 }
196 
197 putstr(s) register char *s; {
198 	while(*s) putsym(*s++);
199 }
200