1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <string.h>
4 
5 #include "scr.h"
6 #include "dir.h"
7 #include "deco.h"
8 
9 #define SWAP(a,b) { register t; t = a; a = b; b = t; }
10 
11 struct choice {
12 	char *name;
13 	int namlen;
14 	int r, c;
15 };
16 
17 static struct choice tab [3];
18 static cnum;
19 static void (*attron) ();
20 static int (*attroff) ();
21 static BOX *mbox;
22 
23 static void initchoice (int row, int col, char *c1, char *c2, char *c3);
24 static void drawchoice (int ch);
25 static int menuchoice (void);
26 
error(char * s,...)27 void error (char *s, ...)
28 {
29 	char buf [100];
30 	va_list ap;
31 
32 	va_start (ap, s);
33 	vsprintf (buf, s, ap);
34 	va_end (ap);
35 	getchoice (1, " Error ", buf, 0, " Ok ", 0, 0);
36 }
37 
message(char * name,char * s,...)38 void message (char *name, char *s, ...)
39 {
40 	char buf [100];
41 	va_list ap;
42 
43 	va_start (ap, s);
44 	vsprintf (buf, s, ap);
45 	va_end (ap);
46 	getchoice (0, name, buf, 0, 0, 0, 0);
47 }
48 
endmesg()49 void endmesg ()
50 {
51 	if (mbox)
52 		VUngetBox (mbox);
53 	mbox = 0;
54 }
55 
getchoice(int bold,char * head,char * msg,char * mesg2,char * c1,char * c2,char * c3)56 int getchoice (int bold, char *head, char *msg, char *mesg2,
57 	char *c1, char *c2, char *c3)
58 {
59 	int len, ch;
60 	int isattr;
61 	register r, c, w, h;
62 	BOX *box;
63 	char mesg[67];
64 
65 	strncpy(mesg, msg, sizeof (mesg));
66 	mesg[sizeof(mesg)-1] = 0;
67 	w = strlen (mesg);
68 	if (mesg2) {
69 		len = strlen (mesg2);
70 		if (len > w)
71 			w = len;
72 	}
73 	len = strlen (head);
74 	if (len > w)
75 		w = len;
76 	len = 0;
77 	if (c1)
78 		len += strlen (c1);
79 	if (c2)
80 		len += strlen (c2);
81 	if (c3)
82 		len += strlen (c3);
83 	if (len > w)
84 		w = len;
85 	h = 6;
86 	w += 10;
87 	if (bold)
88 		r = LINES/2;
89 	else
90 		r = LINES/4;
91 	c = (80 - w) / 2;
92 
93 	box = VGetBox (r-1, c-2, h+2, w+4);             /* save box */
94 	isattr = VStandOut ();
95 	if (bold)
96 		VSetBold ();
97 	else
98 		VSetDim ();
99 	VFillBox (r-1, c-2, h+2, w+4, ' ');             /* clear */
100 	VDrawBox (r, c, h, w);                          /* draw margins */
101 	VMPutString (r, c + (w-strlen(head)) / 2, head); /* head */
102 	if (mesg2) {
103 		VMPutString (r+1, c + (w-strlen(mesg)) / 2, mesg);
104 		VMPutString (r+2, c + (w-strlen(mesg2)) / 2, mesg2);
105 	} else
106 		VMPutString (r+2, c + (w-strlen(mesg)) / 2, mesg);
107 
108 	if (c1) {
109 		if (isattr) {
110 			attron = VStandEnd;
111 			attroff = VStandOut;
112 		} else {
113 			attron = 0;
114 			attroff = 0;
115 		}
116 		initchoice (r+4, c+w/2, c1, c2, c3);
117 
118 		ch = menuchoice ();
119 		VStandEnd ();
120 		VSetNormal ();
121 		VUngetBox (box);
122 		VFreeBox (box);
123 		return (ch);
124 	} else {
125 		/* message */
126 		VStandEnd ();
127 		VSetNormal ();
128 		mbox = box;
129 		hidecursor ();
130 		VSync ();
131 #ifdef DOC
132 		KeyGet ();
133 #endif
134 		return (0);
135 	}
136 }
137 
initchoice(int row,int col,char * c1,char * c2,char * c3)138 static void initchoice (int row, int col, char *c1, char *c2, char *c3)
139 {
140 	register i, w;
141 
142 	cnum = c2 ? (c3 ? 3 : 2) : 1;
143 	tab[0].name = c1;
144 	tab[1].name = c2;
145 	tab[2].name = c3;
146 	w = cnum-1;
147 	for (i=0; i<cnum; ++i) {
148 		w += tab[i].namlen = strlen (tab[i].name);
149 		tab[i].r = row;
150 	}
151 	tab[0].c = col-w/2;
152 	tab[1].c = tab[0].c + tab[0].namlen + 1;
153 	tab[2].c = tab[1].c + tab[1].namlen + 1;
154 }
155 
menuchoice()156 static int menuchoice ()
157 {
158 	int ch = 0;
159 
160 	for (;;) {
161 		drawchoice (ch);
162 		hidecursor ();
163 		VSync ();
164 		switch (KeyGet ()) {
165 		default:
166 			VBeep ();
167 			continue;
168 		case cntrl (']'):       /* redraw screen */
169 			VRedraw ();
170 			continue;
171 		case cntrl ('['):
172 		case cntrl ('C'):
173 		case meta ('J'):        /* f0 */
174 			return (-1);
175 		case cntrl ('M'):
176 		case cntrl ('J'):
177 			return (ch);
178 		case ' ':
179 		case cntrl ('I'):
180 		case meta ('r'):        /* right */
181 			if (++ch >= cnum)
182 				ch = 0;
183 			continue;
184 		case meta ('b'):        /* backspace */
185 		case meta ('l'):        /* left */
186 			if (--ch < 0)
187 				ch = cnum-1;
188 			continue;
189 		}
190 	}
191 }
192 
drawchoice(int ch)193 static void drawchoice (int ch)
194 {
195 	register i;
196 
197 	for (i=0; i<cnum; ++i) {
198 		if (i == ch) {
199 			if (attron)
200 				(*attron) ();
201 			VMPutString (tab[i].r, tab[i].c, tab[i].name);
202 			if (! attron) {
203 				VMPutChar (tab[i].r, tab[i].c, '[');
204 				VMPutChar (tab[i].r, tab[i].c + strlen (tab[i].name) - 1, ']');
205 			}
206 			if (attroff)
207 				(*attroff) ();
208 		} else
209 			VMPutString (tab[i].r, tab[i].c, tab[i].name);
210 	}
211 }
212 
editstring(int r,int c,int w,char * str,int cp)213 static char *editstring (int r, int c, int w, char *str, int cp)
214 {
215 	register key, k;
216 	int firstkey = 1;
217 
218 	if (cp) {
219 		for (cp=0; str[cp]; ++cp);
220 		firstkey = 0;
221 	}
222 	for (; ; firstkey=0) {
223 		VClearBox (r, c, 1, w);
224 		VMPutString (r, c, str);
225 		VMove (r, c+cp);
226 		VSync ();
227 		switch (key = KeyGet ()) {
228 		default:
229 			if (key<' ' || (key>'~' && key<0300) || key>0377) {
230 				VBeep ();
231 				continue;
232 			}
233 			if (firstkey) {
234 				str[0] = key;
235 				str[1] = 0;
236 				cp = 1;
237 				continue;
238 			}
239 			for (k=cp; str[k]; ++k)
240 				SWAP (key, str[k]);
241 			str [k] = key;
242 			str [w] = str [k+1] = 0;
243 			/* fall through */
244 		case meta ('r'):        /* right */
245 			if (str [cp]) {
246 				++cp;
247 				if (cp >= w)
248 					cp = w-1;
249 			}
250 			continue;
251 		case meta ('l'):        /* left */
252 			if (--cp < 0)
253 				cp = 0;
254 			continue;
255 		case cntrl (']'):       /* redraw screen */
256 			VRedraw ();
257 			continue;
258 		case cntrl ('C'):
259 		case cntrl ('['):
260 		case meta ('J'):        /* f0 */
261 			return (0);
262 		case cntrl ('M'):
263 		case cntrl ('J'):
264 			return (str);
265 		case cntrl ('I'):
266 			if (str [cp])
267 				while (str [++cp]);
268 			else
269 				cp = 0;
270 			continue;
271 		case meta ('h'):        /* home */
272 			cp = 0;
273 			continue;
274 		case meta ('e'):        /* end */
275 			while (str [cp])
276 				++cp;
277 			continue;
278 		case meta ('b'):        /* back space */
279 			if (cp) {
280 				for (k=cp--; str[k]; ++k)
281 					str[k-1] = str[k];
282 				str [k-1] = 0;
283 			}
284 			continue;
285 		case cntrl ('G'):       /* delete */
286 			if (! str [cp])
287 				continue;
288 			for (k=cp+1; str[k]; ++k)
289 				str[k-1] = str[k];
290 			str [k-1] = 0;
291 			continue;
292 		case cntrl ('Y'):       /* clear line */
293 			str [cp = 0] = 0;
294 			continue;
295 		}
296 	}
297 }
298 
getstring(int w,char * str,char * head,char * mesg)299 char *getstring (int w, char *str, char *head, char *mesg)
300 {
301 	register r, c, h;
302 	int len;
303 	BOX *box;
304 	static char buf [81];
305 
306 	len = strlen (mesg);
307 	if (len > w)
308 		w = len;
309 	len = strlen (head);
310 	if (len > w)
311 		w = len;
312 	h = 4;
313 	w += 4;
314 	r = LINES/4;
315 	c = (78 - w) / 2;
316 
317 	box = VGetBox (r-1, c-2, h+2, w+4);             /* save box */
318 	VStandOut ();
319 	VSetDim ();
320 	VFillBox (r-1, c-2, h+2, w+4, ' ');             /* clear */
321 	VDrawBox (r, c, h, w);                          /* draw margins */
322 	VMPutString (r, c + (w-strlen(head)) / 2, head); /* head */
323 	VMPutString (r+1, c+2, mesg);                   /* message */
324 	VStandEnd ();
325 	VSetNormal ();
326 
327 	strncpy (buf, str ? str : "", 80);
328 
329 	str = editstring (r+2, c+2, w-4, buf, 0);
330 	VUngetBox (box);
331 	VFreeBox (box);
332 	return (str);
333 }
334 
getwstring(int w,char * str,char * head,char * mesg)335 char *getwstring (int w, char *str, char *head, char *mesg)
336 {
337 	register r, c, h;
338 	int len;
339 	BOX *box;
340 	static char buf [81];
341 
342 	len = strlen (mesg);
343 	if (len > w)
344 		w = len;
345 	len = strlen (head);
346 	if (len > w)
347 		w = len;
348 	h = 4;
349 	w += 4;
350 	r = LINES/4;
351 	c = BASECOL (cur) + (PAGEWID - w) / 2;
352 	if (c < 3)
353 		c = 3;
354 	else if (c > 76-w)
355 		c = 76-w;
356 
357 	box = VGetBox (r-1, c-2, h+2, w+4);             /* save box */
358 	VStandOut ();
359 	VSetDim ();
360 	VFillBox (r-1, c-2, h+2, w+4, ' ');             /* clear */
361 	VDrawBox (r, c, h, w);                          /* draw margins */
362 	VMPutString (r, c + (w-strlen(head)) / 2, head); /* head */
363 	VMPutString (r+1, c+2, mesg);                   /* message */
364 	VStandEnd ();
365 	VSetNormal ();
366 
367 	strncpy (buf, str ? str : "", 80);
368 
369 	str = editstring (r+2, c+2, w-4, buf, 1);
370 	VUngetBox (box);
371 	VFreeBox (box);
372 	return (str);
373 }
374