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