1 /*
2 * Copyright (C) 1998 Sasha Vasko <sasha at aftercode.net>
3 * Copyright (C) 1998 Makoto Kato <m_kato@ga2.so-net.ne.jp>
4 * Copyright (C) 1996 Michael Beam
5 * Copyright (C) 1996 Takanori Kubota
6 * Copyright (C) 1995 Thomas Zuwei Feng
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #include "../../configure.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <ctype.h>
30 #include <fcntl.h>
31 #include <X11/Xlib.h>
32 #include <X11/X.h>
33 #include <X11/Xutil.h>
34 #include <X11/cursorfont.h>
35 #define XK_MISCELLANY
36 #include <X11/keysymdef.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/time.h>
40 #if defined ___AIX || defined _AIX || defined ___AIXV3
41 #include <sys/select.h>
42 #endif
43 #ifdef I18N
44 #include <X11/Xlocale.h>
45 #define XDrawImageString(t,u,v,w,x,y,z) XmbDrawImageString(t,u,FONTSET,v,w,x,y,z)
46 #endif
47
48 #include "../../include/aftersteplib.h"
49 #include "../../include/style.h"
50 #include "../../include/screen.h"
51 #include "../../include/module.h"
52
53 void
dummy()54 dummy ()
55 {
56 }
57
58 #ifdef DEBUG
59 #define fprintf fprintf
60 #else
61 #define fprintf dummy
62 #endif
63
64
65 #define TEXT_SPC 3
66 #define BOX_SPC 3
67 #define ITEM_HSPC 10
68 #define ITEM_VSPC 5
69
70 /* tba: use dynamic buffer expanding */
71 #define MAX_LINES 64
72 #define MAX_ITEMS 256
73 #define ITEMS_PER_LINE 64
74 #define CHOICES_PER_SEL 64
75
76 #define I_TEXT 1
77 #define I_INPUT 2
78 #define I_SELECT 3
79 #define I_CHOICE 4
80 #define I_BUTTON 5
81
82 #define IS_SINGLE 1
83 #define IS_MULTIPLE 2
84
85 #define IB_CONTINUE 1
86 #define IB_RESTART 2
87 #define IB_QUIT 3
88
89 typedef union _item
90 {
91 int type; /* item type, one of I_TEXT .. I_BUTTON */
92 struct _head
93 { /* common header */
94 int type;
95 int win; /* X window id */
96 char *name; /* identifier name */
97 int size_x, size_y; /* size of bounding box */
98 int pos_x, pos_y; /* position of top-left corner */
99 }
100 header;
101 struct
102 { /* I_TEXT */
103 struct _head head;
104 int n; /* string length */
105 char *value; /* string to display */
106 }
107 text;
108 struct
109 { /* I_INPUT */
110 struct _head head;
111 int buf; /* input string buffer */
112 int n; /* string length */
113 char *value; /* input string */
114 char *init_value; /* default string */
115 char *blanks; /* blank string */
116 int size; /* input field size */
117 int left; /* position of the left-most displayed char */
118 int o_cursor; /* store relative cursor position */
119 }
120 input;
121 struct
122 { /* I_SELECT */
123 struct _head head;
124 int key; /* one of IS_MULTIPLE, IS_SINGLE */
125 int n; /* number of choices */
126 union _item **choices; /* list of choices */
127 }
128 select;
129 struct
130 { /* I_CHOICE */
131 struct _head head;
132 int on; /* selected or not */
133 int init_on; /* initially selected or not */
134 char *value; /* value if selected */
135 int n; /* text string length */
136 char *text; /* text string */
137 union _item *sel; /* selection it belongs to */
138 }
139 choice;
140 struct
141 { /* I_BUTTON */
142 struct _head head;
143 int key; /* one of IB_CONTINUE, IB_RESTART, IB_QUIT */
144 int n; /* # of commands */
145 int len; /* text length */
146 char *text; /* text string */
147 int keypress; /* short cut */
148 /* Afterstep command to execute */
149 char **commands;
150 }
151 button;
152 }
153 Item;
154
155
156 #define L_LEFT 1
157 #define L_RIGHT 2
158 #define L_CENTER 3
159 #define L_LEFTRIGHT 4
160
161 typedef struct _line
162 {
163 int n; /* number of items on the line */
164 int justify; /* justification */
165 int size_x, size_y; /* size of bounding rectangle */
166 Item **items; /* list of items */
167 }
168 Line;
169
170
171 /* global variables */
172 char *MyName; /* program name, e.g. Form */
173
174 int fd[2]; /* fd for Afterstep<->Module packets */
175 int fd_err;
176 FILE *fp_err;
177
178 Line lines[MAX_LINES];
179 int n_lines;
180 Item items[MAX_ITEMS];
181 int n_items;
182 Item def_button;
183
184 int grab_server = 0, server_grabbed = 0;
185 int gx, gy, geom = 0;
186 int warp_pointer = 0;
187
188 Display *dpy;
189 int fd_x; /* fd for X connection */
190
191 ScreenInfo Scr;
192
193 Window root, frame, ref;
194 Colormap d_cmap;
195 int screen;
196 int scr_depth;
197
198 int max_width, total_height; /* frame size */
199
200 enum
201 {
202 c_back, c_fore, c_itemback, c_itemfore, c_itemlo, c_itemhi
203 };
204 char *color_names[4] =
205 {
206 "Light Gray", "Black", "Gray50", "Wheat"
207 };
208 long colors[6];
209
210 enum
211 {
212 f_text, f_input, f_button
213 };
214 char *font_names[3] =
215 {
216 "fixed",
217 "fixed",
218 "fixed"
219 };
220 Font fonts[3];
221 XFontStruct *xfs[3];
222 #ifdef I18N
223 XFontSet xfset[3];
224 #endif
225
226 Cursor xc_ibeam, xc_hand;
227
228 GC gc_text, gc_input, gc_button;
229
230 Item *cur_text;
231 int abs_cursor;
232 int rel_cursor;
233
234 static char *buf;
235 static int N = 8;
236
237 /* copy a string until '\0', or up to n chars, and delete trailing spaces */
238 char *
copystring(char * cp,int n)239 copystring (char *cp, int n)
240 {
241 char *dp, *bp;
242 if (n == 0)
243 n = strlen (cp);
244 bp = dp = (char *) safemalloc (n + 1);
245 while (n-- > 0)
246 *dp++ = *cp++;
247 while (isspace ((unsigned char) *(--dp)));
248 *(++dp) = '\0';
249 return bp;
250 }
251
252 void
DeadPipe(int nonsense)253 DeadPipe (int nonsense)
254 {
255 exit (0);
256 }
257
258
259 /* copy a string until '"', or '\n', or '\0' */
260 char *
CopyQuotedString(char * cp)261 CopyQuotedString (char *cp)
262 {
263 char *dp, *bp, c;
264 bp = dp = (char *) safemalloc (strlen (cp) + 1);
265 while (1)
266 {
267 switch (c = *(cp++))
268 {
269 case '\\':
270 *(dp++) = *(cp++);
271 break;
272 case '\"':
273 case '\n':
274 case '\0':
275 *dp = '\0';
276 return bp;
277 break;
278 default:
279 *(dp++) = c;
280 break;
281 }
282 }
283 }
284
285 /* copy a string until the first space */
286 char *
CopySolidString(char * cp)287 CopySolidString (char *cp)
288 {
289 char *dp, *bp, c;
290 bp = dp = (char *) safemalloc (strlen (cp) + 1);
291 while (1)
292 {
293 c = *(cp++);
294 if (c == '\\')
295 {
296 *(dp++) = '\\';
297 *(dp++) = *(cp++);
298 }
299 else if (isspace ((unsigned char) c) || c == '\0')
300 {
301 *dp = '\0';
302 return bp;
303 }
304 else
305 *(dp++) = c;
306 }
307 }
308
309 /* get the font height */
310 int
FontHeight(XFontStruct * xfs)311 FontHeight (XFontStruct * xfs)
312 {
313 return (xfs->ascent + xfs->descent);
314 }
315
316 /* get the font width, for fixed-width font only */
317 int
FontWidth(XFontStruct * xfs)318 FontWidth (XFontStruct * xfs)
319 {
320 return (xfs->per_char[0].width);
321 }
322
323 /* read the configuration file */
324 void
ParseOptions(char * file_name)325 ParseOptions (char *file_name)
326 {
327 FILE *fp, *fopen ();
328 int prog_name_len, i, j, l, extra;
329 char line_buf[MAXLINELENGTH];
330 char *cp;
331 Line *cur_line, *line;
332 Item *item, *cur_sel = NULL, *cur_button = NULL;
333 #ifdef I18N
334 XFontStruct **fs_list;
335 char **ml;
336 int mc;
337 char *ds;
338 char *fn_tmp;
339 int fn_tmp_length;
340 #endif
341
342 #define AddToLine(item) { cur_line->items[cur_line->n++] = item; cur_line->size_x += item->header.size_x; if (cur_line->size_y < item->header.size_y) cur_line->size_y = item->header.size_y; }
343
344 n_items = 0;
345 n_lines = 0;
346
347 /* default line in case the first *FFLine is missing */
348 lines[0].n = 0;
349 lines[0].justify = L_CENTER;
350 lines[0].size_x = lines[0].size_y = 0;
351 lines[0].items = (Item **) safemalloc (sizeof (Item *) * ITEMS_PER_LINE);
352 cur_line = lines;
353
354 /* default button is for initial functions */
355 cur_button = &def_button;
356 def_button.button.n = 0;
357 def_button.button.commands = (char **) safemalloc (sizeof (char *) * MAX_ITEMS);
358 def_button.button.key = IB_CONTINUE;
359
360 /* default fonts in case the *FFont's are missing */
361 #ifdef I18N
362 xfset[f_text] = xfset[f_input] = xfset[f_button] = XCreateFontSet (dpy, "fixed", &ml, &mc, &ds);
363 XFontsOfFontSet (xfset[f_text], &fs_list, &ml);
364 xfs[f_text] = xfs[f_input] = xfs[f_button] = fs_list[0];
365 #else
366 xfs[f_text] = xfs[f_input] = xfs[f_button] =
367 XLoadQueryFont (dpy, "fixed");
368 #endif
369 fonts[f_text] = fonts[f_input] = fonts[f_button] = xfs[f_text]->fid;
370
371 if (!(fp = fopen (file_name, "r")))
372 {
373 fprintf (fp_err, "%s: can't open config file %s.\n", MyName, file_name);
374 exit (1);
375 }
376 prog_name_len = strlen (MyName);
377 while (fgets (line_buf, sizeof (line_buf), fp))
378 {
379 cp = line_buf;
380 while (isspace (*cp))
381 cp++; /* skip blanks */
382 if (*cp != '*')
383 continue;
384 if (strncmp (++cp, MyName, prog_name_len) != 0)
385 continue;
386 cp += prog_name_len;
387 /* at this point we have recognized "*Form" */
388 if (strncmp (cp, "GrabServer", 10) == 0)
389 {
390 grab_server = 1;
391 continue;
392 }
393 else if (strncmp (cp, "WarpPointer", 11) == 0)
394 {
395 warp_pointer = 1;
396 }
397 else if (strncmp (cp, "Position", 8) == 0)
398 {
399 cp += 8;
400 geom = 1;
401 while (isspace (*cp))
402 cp++;
403 gx = atoi (cp);
404 while (!isspace (*cp))
405 cp++;
406 while (isspace (*cp))
407 cp++;
408 gy = atoi (cp);
409 fprintf (fp_err, "Position @ (%d, %d)\n", gx, gy);
410 continue;
411 }
412 else if (strncmp (cp, "Fore", 4) == 0)
413 {
414 cp += 4;
415 while (isspace (*cp))
416 cp++;
417 color_names[c_fore] = copystring (cp, 0);
418 fprintf (fp_err, "ColorFore: %s\n", color_names[c_fore]);
419 continue;
420 }
421 else if (strncmp (cp, "Back", 4) == 0)
422 {
423 cp += 4;
424 while (isspace (*cp))
425 cp++;
426 color_names[c_back] = copystring (cp, 0);
427 fprintf (fp_err, "ColorBack: %s\n", color_names[c_back]);
428 continue;
429 }
430 else if (strncmp (cp, "ItemFore", 8) == 0)
431 {
432 cp += 8;
433 while (isspace (*cp))
434 cp++;
435 color_names[c_itemfore] = copystring (cp, 0);
436 fprintf (fp_err, "ColorItemFore: %s\n", color_names[c_itemfore]);
437 continue;
438 }
439 else if (strncmp (cp, "ItemBack", 8) == 0)
440 {
441 cp += 8;
442 while (isspace (*cp))
443 cp++;
444 color_names[c_itemback] = copystring (cp, 0);
445 fprintf (fp_err, "ColorItemBack: %s\n", color_names[c_itemback]);
446 continue;
447 }
448 else if (strncmp (cp, "Font", 4) == 0)
449 {
450 cp += 4;
451 while (isspace (*cp))
452 cp++;
453 font_names[f_text] = copystring (cp, 0);
454 fprintf (fp_err, "Font: %s\n", font_names[f_text]);
455 #ifdef I18N
456 if ((xfset[f_text] = XCreateFontSet (dpy, font_names[f_text], &ml, &mc,
457 &ds)) == NULL)
458 {
459 fprintf (fp_err, "can't get font %s\n", font_names[f_text]);
460 fn_tmp_length = strlen (font_names[f_text]) + strlen (",-*--14-*");
461 fn_tmp = safemalloc (fn_tmp_length + 1);
462 strcpy (fn_tmp, font_names[f_text]);
463 strcat (fn_tmp, ",-*--14-*");
464 fprintf (fp_err, "trying...%s\n", fn_tmp);
465 if ((xfset[f_text] = XCreateFontSet (dpy, fn_tmp, &ml, &mc, &ds))
466 == NULL)
467 {
468 fprintf (fp_err, "can't get font %s\n", fn_tmp);
469 fprintf (fp_err, "trying... fixed\n");
470 if ((xfset[f_text] = XCreateFontSet (dpy, "fixed,-*--14-*", &ml,
471 &mc, &ds)) == NULL)
472 {
473 fprintf (fp_err, "no fontset available\n");
474 exit (1);
475 }
476 }
477 }
478 XFontsOfFontSet (xfset[f_text], &fs_list, &ml);
479 xfs[f_text] = fs_list[0];
480 #else
481 xfs[f_text] = XLoadQueryFont (dpy, font_names[f_text]);
482 #endif
483 fonts[f_text] = xfs[f_text]->fid;
484 continue;
485 }
486 else if (strncmp (cp, "ButtonFont", 10) == 0)
487 {
488 cp += 10;
489 while (isspace (*cp))
490 cp++;
491 font_names[f_button] = copystring (cp, 0);
492 fprintf (fp_err, "ButtonFont: %s\n", font_names[f_button]);
493 #ifdef I18N
494 if ((xfset[f_button] = XCreateFontSet (dpy, font_names[f_button], &ml,
495 &mc, &ds)) == NULL)
496 {
497 fprintf (fp_err, "can't get font %s\n", font_names[f_button]);
498 fn_tmp_length = strlen (font_names[f_button]) + strlen (",-*--14-*");
499 fn_tmp = safemalloc (fn_tmp_length + 1);
500 strcpy (fn_tmp, font_names[f_button]);
501 strcat (fn_tmp, ",-*--14-*");
502 fprintf (fp_err, "trying...%s\n", fn_tmp);
503 if ((xfset[f_button] = XCreateFontSet (dpy, fn_tmp, &ml, &mc, &ds))
504 == NULL)
505 {
506 fprintf (fp_err, "can't get font %s\n", fn_tmp);
507 fprintf (fp_err, "trying... fixed\n");
508 if ((xfset[f_button] = XCreateFontSet (dpy, "fixed,-*--14-*", &ml,
509 &mc, &ds)) == NULL)
510 {
511 fprintf (fp_err, "no fontset available\n");
512 exit (1);
513 }
514 }
515 }
516 XFontsOfFontSet (xfset[f_button], &fs_list, &ml);
517 xfs[f_button] = fs_list[0];
518 #else
519 xfs[f_button] = XLoadQueryFont (dpy, font_names[f_button]);
520 #endif
521 fonts[f_button] = xfs[f_button]->fid;
522 continue;
523 }
524 else if (strncmp (cp, "InputFont", 9) == 0)
525 {
526 cp += 9;
527 while (isspace (*cp))
528 cp++;
529 font_names[f_input] = copystring (cp, 0);
530 fprintf (fp_err, "InputFont: %s\n", font_names[f_input]);
531 #ifdef I18N
532 if ((xfset[f_input] = XCreateFontSet (dpy, font_names[f_input], &ml,
533 &mc, &ds)) == NULL)
534 {
535 fprintf (fp_err, "can't get font %s\n", font_names[f_input]);
536 fn_tmp_length = strlen (font_names[f_input]) + strlen (",-*--14-*");
537 fn_tmp = safemalloc (fn_tmp_length + 1);
538 strcpy (fn_tmp, font_names[f_input]);
539 strcat (fn_tmp, ",-*--14-*");
540 fprintf (fp_err, "trying...%s\n", fn_tmp);
541 if ((xfset[f_button] = XCreateFontSet (dpy, fn_tmp, &ml, &mc, &ds))
542 == NULL)
543 {
544 fprintf (fp_err, "can't get font %s\n", fn_tmp);
545 fprintf (fp_err, "trying... fixed\n");
546 if ((xfset[f_button] = XCreateFontSet (dpy, "fixed,-*--14-*", &ml,
547 &mc, &ds)) == NULL)
548 {
549 fprintf (fp_err, "no fontset available\n");
550 exit (1);
551 }
552 }
553 }
554 XFontsOfFontSet (xfset[f_input], &fs_list, &ml);
555 xfs[f_input] = fs_list[0];
556 #else
557 xfs[f_input] = XLoadQueryFont (dpy, font_names[f_input]);
558 #endif
559 fonts[f_input] = xfs[f_input]->fid;
560 continue;
561 }
562 else if (strncmp (cp, "Line", 4) == 0)
563 {
564 cp += 4;
565 cur_line = lines + n_lines++;
566 while (isspace (*cp))
567 cp++;
568 if (strncmp (cp, "left", 4) == 0)
569 cur_line->justify = L_LEFT;
570 else if (strncmp (cp, "right", 5) == 0)
571 cur_line->justify = L_RIGHT;
572 else if (strncmp (cp, "center", 6) == 0)
573 cur_line->justify = L_CENTER;
574 else
575 cur_line->justify = L_LEFTRIGHT;
576 cur_line->n = 0;
577 cur_line->items = (Item **) safemalloc (sizeof (Item *) * ITEMS_PER_LINE);
578 continue;
579 }
580 else if (strncmp (cp, "Text", 4) == 0)
581 {
582 /* syntax: *FFText "<text>" */
583 cp += 4;
584 item = items + n_items++;
585 item->type = I_TEXT;
586 item->header.name = "";
587 while (isspace (*cp))
588 cp++;
589 if (*cp == '\"')
590 item->text.value = CopyQuotedString (++cp);
591 else
592 item->text.value = "";
593 item->text.n = strlen (item->text.value);
594 #ifdef I18N
595 item->header.size_x = XmbTextEscapement (xfset[f_text], item->text.value,
596 item->text.n) + 2 * TEXT_SPC;
597 #else
598 item->header.size_x = XTextWidth (xfs[f_text], item->text.value,
599 item->text.n) + 2 * TEXT_SPC;
600 #endif
601 item->header.size_y = FontHeight (xfs[f_text]) + 2 * TEXT_SPC;
602 fprintf (fp_err, "Text \"%s\" [%d, %d]\n", item->text.value,
603 item->header.size_x, item->header.size_y);
604 AddToLine (item);
605 continue;
606 }
607 else if (strncmp (cp, "Input", 5) == 0)
608 {
609 /* syntax: *FFInput <name> <size> "<init_value>" */
610 cp += 5;
611 item = items + n_items++;
612 item->type = I_INPUT;
613 while (isspace (*cp))
614 cp++;
615 item->header.name = CopySolidString (cp);
616 cp += strlen (item->header.name);
617 while (isspace (*cp))
618 cp++;
619 item->input.size = atoi (cp);
620 while (!isspace (*cp))
621 cp++;
622 while (isspace (*cp))
623 cp++;
624 if (*cp == '\"')
625 item->input.init_value = CopyQuotedString (++cp);
626 else
627 item->input.init_value = "";
628 item->input.blanks = (char *) safemalloc (item->input.size);
629 for (j = 0; j < item->input.size; j++)
630 item->input.blanks[j] = ' ';
631 item->input.buf = strlen (item->input.init_value) + 1;
632 item->input.value = (char *) safemalloc (item->input.buf);
633 item->header.size_x = FontWidth (xfs[f_input]) * item->input.size
634 + 2 * TEXT_SPC + 2 * BOX_SPC;
635 item->header.size_y = FontHeight (xfs[f_input]) + 3 * TEXT_SPC
636 + 2 * BOX_SPC;
637 fprintf (fp_err, "Input, %s, [%d], \"%s\"\n", item->header.name,
638 item->input.size, item->input.init_value);
639 AddToLine (item);
640 }
641 else if (strncmp (cp, "Selection", 9) == 0)
642 {
643 /* syntax: *FFSelection <name> single | multiple */
644 cp += 9;
645 cur_sel = items + n_items++;
646 cur_sel->type = I_SELECT;
647 while (isspace (*cp))
648 cp++;
649 cur_sel->header.name = CopySolidString (cp);
650 cp += strlen (cur_sel->header.name);
651 while (isspace (*cp))
652 cp++;
653 if (strncmp (cp, "multiple", 8) == 0)
654 cur_sel->select.key = IS_MULTIPLE;
655 else
656 cur_sel->select.key = IS_SINGLE;
657 cur_sel->select.n = 0;
658 cur_sel->select.choices =
659 (Item **) safemalloc (sizeof (Item *) * CHOICES_PER_SEL);
660 continue;
661 }
662 else if (strncmp (cp, "Choice", 6) == 0)
663 {
664 /* syntax: *FFChoice <name> <value> [on | _off_] ["<text>"] */
665 cp += 6;
666 item = items + n_items++;
667 item->type = I_CHOICE;
668 while (isspace (*cp))
669 cp++;
670 item->header.name = CopySolidString (cp);
671 cp += strlen (item->header.name);
672 while (isspace (*cp))
673 cp++;
674 item->choice.value = CopySolidString (cp);
675 cp += strlen (item->choice.value);
676 while (isspace (*cp))
677 cp++;
678 if (strncmp (cp, "on", 2) == 0)
679 item->choice.init_on = 1;
680 else
681 item->choice.init_on = 0;
682 while (!isspace (*cp))
683 cp++;
684 while (isspace (*cp))
685 cp++;
686 if (*cp == '\"')
687 item->choice.text = CopyQuotedString (++cp);
688 else
689 item->choice.text = "";
690 item->choice.n = strlen (item->choice.text);
691 item->choice.sel = cur_sel;
692 cur_sel->select.choices[cur_sel->select.n++] = item;
693 item->header.size_y = FontHeight (xfs[f_text]) + 2 * TEXT_SPC;
694 item->header.size_x = FontHeight (xfs[f_text]) + 4 * TEXT_SPC +
695 #ifdef I18N
696 XmbTextEscapement (xfset[f_text], item->choice.text, item->choice.n);
697 #else
698 XTextWidth (xfs[f_text], item->choice.text, item->choice.n);
699 #endif
700 fprintf (fp_err, "Choice %s, \"%s\", [%d, %d]\n", item->header.name,
701 item->choice.text, item->header.size_x, item->header.size_y);
702 AddToLine (item);
703 continue;
704 }
705 else if (strncmp (cp, "Button", 6) == 0)
706 {
707 /* syntax: *FFButton continue | restart | quit "<text>" */
708 cp += 6;
709 item = items + n_items++;
710 item->type = I_BUTTON;
711 item->header.name = "";
712 while (isspace (*cp))
713 cp++;
714 if (strncmp (cp, "restart", 7) == 0)
715 item->button.key = IB_RESTART;
716 else if (strncmp (cp, "quit", 4) == 0)
717 item->button.key = IB_QUIT;
718 else
719 item->button.key = IB_CONTINUE;
720 while (!isspace (*cp))
721 cp++;
722 while (isspace (*cp))
723 cp++;
724 if (*cp == '\"')
725 {
726 item->button.text = CopyQuotedString (++cp);
727 cp += strlen (item->button.text) + 1;
728 while (isspace (*cp))
729 cp++;
730 }
731 else
732 item->button.text = "";
733 if (*cp == '^')
734 item->button.keypress = *(++cp) - '@';
735 else if (*cp == 'F')
736 item->button.keypress = 256 + atoi (++cp);
737 else
738 item->button.keypress = -1;
739 item->button.len = strlen (item->button.text);
740 item->button.n = 0;
741 item->button.commands = (char **) safemalloc (sizeof (char *) * MAX_ITEMS);
742 item->header.size_y = FontHeight (xfs[f_button]) + 2 * TEXT_SPC
743 + 2 * BOX_SPC;
744 item->header.size_x = 2 * TEXT_SPC + 2 * BOX_SPC
745 #ifdef I18N
746 + XmbTextEscapement (xfset[f_button], item->button.text, item->button.len);
747 #else
748 + XTextWidth (xfs[f_button], item->button.text, item->button.len);
749 #endif
750 AddToLine (item);
751 cur_button = item;
752 continue;
753 }
754 else if (strncmp (cp, "Command", 7) == 0)
755 {
756 /* syntax: *FFCommand <command> */
757 cp += 7;
758 while (isspace (*cp))
759 cp++;
760 cur_button->button.commands[cur_button->button.n++] =
761 copystring (cp, 0);
762 }
763 } /* end of switch() */
764 /* get the geometry right */
765 max_width = 0;
766 total_height = ITEM_VSPC;
767 for (l = 0; l < n_lines; l++)
768 {
769 line = lines + l;
770 for (i = 0; i < line->n; i++)
771 {
772 line->items[i]->header.pos_y = total_height;
773 if (line->items[i]->header.size_y < line->size_y)
774 line->items[i]->header.pos_y += (line->size_y - line->items[i]->header.size_y) / 2 + 1;
775 }
776 total_height += ITEM_VSPC + line->size_y;
777 line->size_x += (line->n + 1) * ITEM_HSPC;
778 if (line->size_x > max_width)
779 max_width = line->size_x;
780 }
781 for (l = 0; l < n_lines; l++)
782 {
783 int width;
784 line = lines + l;
785 fprintf (fp_err, "Line[%d], %d, %d items\n", l, line->justify, line->n);
786 switch (line->justify)
787 {
788 case L_LEFT:
789 width = ITEM_HSPC;
790 for (i = 0; i < line->n; i++)
791 {
792 line->items[i]->header.pos_x = width;
793 width += ITEM_HSPC + line->items[i]->header.size_x;
794 }
795 break;
796 case L_RIGHT:
797 width = max_width - line->size_x + ITEM_HSPC;
798 for (i = 0; i < line->n; i++)
799 {
800 line->items[i]->header.pos_x = width;
801 width += ITEM_HSPC + line->items[i]->header.size_x;
802 }
803 break;
804 case L_CENTER:
805 width = (max_width - line->size_x) / 2 + ITEM_HSPC;
806 for (i = 0; i < line->n; i++)
807 {
808 line->items[i]->header.pos_x = width;
809 fprintf (fp_err, "Line[%d], Item[%d] @ (%d, %d)\n", l, i,
810 line->items[i]->header.pos_x, line->items[i]->header.pos_y);
811 width += ITEM_HSPC + line->items[i]->header.size_x;
812 }
813 break;
814 case L_LEFTRIGHT:
815 /* count the number of inputs on the line - the extra space will be
816 * shared amongst these if there are any, otherwise it will be added
817 * as space in between the elements
818 */
819 extra = 0;
820 for (i = 0; i < line->n; i++)
821 {
822 if (line->items[i]->type == I_INPUT)
823 extra++;
824 }
825 if (extra == 0)
826 {
827 if (line->n < 2)
828 { /* same as L_CENTER */
829 width = (max_width - line->size_x) / 2 + ITEM_HSPC;
830 for (i = 0; i < line->n; i++)
831 {
832 line->items[i]->header.pos_x = width;
833 width += ITEM_HSPC + line->items[i]->header.size_x;
834 }
835 }
836 else
837 {
838 extra = (max_width - line->size_x) / (line->n - 1);
839 width = ITEM_HSPC;
840 for (i = 0; i < line->n; i++)
841 {
842 line->items[i]->header.pos_x = width;
843 width += ITEM_HSPC + line->items[i]->header.size_x + extra;
844 }
845 }
846 }
847 else
848 {
849 extra = (max_width - line->size_x) / extra;
850 width = ITEM_HSPC;
851 for (i = 0; i < line->n; i++)
852 {
853 line->items[i]->header.pos_x = width;
854 if (line->items[i]->type == I_INPUT)
855 line->items[i]->header.size_x += extra;
856 width += ITEM_HSPC + line->items[i]->header.size_x;
857 }
858 }
859 break;
860 }
861 }
862 fclose (fp);
863 }
864
865 #define MAX_INTENSITY 65535
866
867 /* allocate color cells */
868 void
GetColors()869 GetColors ()
870 {
871 Visual *visual = DefaultVisual (dpy, screen);
872 XColor xc_item;
873 int red = 0, green = 0, blue = 0, tmp1, tmp2;
874 if (scr_depth < 8)
875 {
876 colors[c_back] = colors[c_itemback] = WhitePixel (dpy, screen);
877 colors[c_fore] = colors[c_itemfore] = colors[c_itemlo] = colors[c_itemhi]
878 = BlackPixel (dpy, screen);
879 }
880 else if (visual->class == TrueColor ||
881 visual->class == StaticColor ||
882 visual->class == StaticGray)
883 {
884 if (XParseColor (dpy, d_cmap, color_names[c_fore], &xc_item) &&
885 XAllocColor (dpy, d_cmap, &xc_item))
886 colors[c_fore] = xc_item.pixel;
887 else
888 colors[c_fore] = BlackPixel (dpy, screen);
889
890 if (XParseColor (dpy, d_cmap, color_names[c_back], &xc_item) &&
891 XAllocColor (dpy, d_cmap, &xc_item))
892 colors[c_back] = xc_item.pixel;
893 else
894 colors[c_back] = WhitePixel (dpy, screen);
895
896 if (XParseColor (dpy, d_cmap, color_names[c_itemfore], &xc_item) &&
897 XAllocColor (dpy, d_cmap, &xc_item))
898 colors[c_itemfore] = xc_item.pixel;
899 else
900 colors[c_itemfore] = BlackPixel (dpy, screen);
901
902 if (XParseColor (dpy, d_cmap, color_names[c_itemback], &xc_item) &&
903 XAllocColor (dpy, d_cmap, &xc_item))
904 colors[c_itemback] = xc_item.pixel;
905 else
906 colors[c_itemback] = WhitePixel (dpy, screen);
907
908 if (XParseColor (dpy, d_cmap, color_names[c_itemback], &xc_item))
909 {
910 red = (int) xc_item.red;
911 green = (int) xc_item.green;
912 blue = (int) xc_item.blue;
913 xc_item.red = (60 * red) / 100;
914 xc_item.green = (60 * green) / 100;
915 xc_item.blue = (60 * blue) / 100;
916 if (XAllocColor (dpy, d_cmap, &xc_item))
917 colors[c_itemlo] = xc_item.pixel;
918 else
919 colors[c_itemlo] = BlackPixel (dpy, screen);
920 }
921 else
922 colors[c_itemlo] = BlackPixel (dpy, screen);
923
924 if (XParseColor (dpy, d_cmap, color_names[c_itemback], &xc_item))
925 {
926 tmp1 = (14 * red) / 10;
927 if (tmp1 > MAX_INTENSITY)
928 tmp1 = MAX_INTENSITY;
929 tmp2 = (MAX_INTENSITY + red) / 2;
930 xc_item.red = (tmp1 > tmp2) ? tmp1 : tmp2;
931 tmp1 = (14 * green) / 10;
932 if (tmp1 > MAX_INTENSITY)
933 tmp1 = MAX_INTENSITY;
934 tmp2 = (MAX_INTENSITY + green) / 2;
935 xc_item.green = (tmp1 > tmp2) ? tmp1 : tmp2;
936 tmp1 = (14 * blue) / 10;
937 if (tmp1 > MAX_INTENSITY)
938 tmp1 = MAX_INTENSITY;
939 tmp2 = (MAX_INTENSITY + blue) / 2;
940 xc_item.blue = (tmp1 > tmp2) ? tmp1 : tmp2;
941 if (XAllocColor (dpy, d_cmap, &xc_item))
942 colors[c_itemhi] = xc_item.pixel;
943 else
944 colors[c_itemhi] = BlackPixel (dpy, screen);
945 }
946 else
947 colors[c_itemhi] = BlackPixel (dpy, screen);
948 }
949 else if (!XAllocColorCells (dpy, d_cmap, 0, NULL, 0, colors, 6))
950 {
951 colors[c_back] = colors[c_itemback] = WhitePixel (dpy, screen);
952 colors[c_fore] = colors[c_itemfore] = colors[c_itemlo] = colors[c_itemhi]
953 = BlackPixel (dpy, screen);
954 }
955 else
956 {
957 XStoreNamedColor (dpy, d_cmap, color_names[c_fore], colors[c_fore],
958 DoRed | DoGreen | DoBlue);
959 XStoreNamedColor (dpy, d_cmap, color_names[c_back], colors[c_back],
960 DoRed | DoGreen | DoBlue);
961 XStoreNamedColor (dpy, d_cmap, color_names[c_itemfore],
962 colors[c_itemfore], DoRed | DoGreen | DoBlue);
963 XStoreNamedColor (dpy, d_cmap, color_names[c_itemback],
964 colors[c_itemback], DoRed | DoGreen | DoBlue);
965 XParseColor (dpy, d_cmap, color_names[c_itemback], &xc_item);
966 red = (int) xc_item.red;
967 green = (int) xc_item.green;
968 blue = (int) xc_item.blue;
969 xc_item.red = (60 * red) / 100;
970 xc_item.green = (60 * green) / 100;
971 xc_item.blue = (60 * blue) / 100;
972 xc_item.pixel = colors[c_itemlo];
973 xc_item.flags = DoRed | DoGreen | DoBlue;
974 XStoreColor (dpy, d_cmap, &xc_item);
975 XParseColor (dpy, d_cmap, color_names[c_itemback], &xc_item);
976 tmp1 = (14 * red) / 10;
977 if (tmp1 > MAX_INTENSITY)
978 tmp1 = MAX_INTENSITY;
979 tmp2 = (MAX_INTENSITY + red) / 2;
980 xc_item.red = (tmp1 > tmp2) ? tmp1 : tmp2;
981 tmp1 = (14 * green) / 10;
982 if (tmp1 > MAX_INTENSITY)
983 tmp1 = MAX_INTENSITY;
984 tmp2 = (MAX_INTENSITY + green) / 2;
985 xc_item.green = (tmp1 > tmp2) ? tmp1 : tmp2;
986 tmp1 = (14 * blue) / 10;
987 if (tmp1 > MAX_INTENSITY)
988 tmp1 = MAX_INTENSITY;
989 tmp2 = (MAX_INTENSITY + blue) / 2;
990 xc_item.blue = (tmp1 > tmp2) ? tmp1 : tmp2;
991 xc_item.pixel = colors[c_itemhi];
992 xc_item.flags = DoRed | DoGreen | DoBlue;
993 XStoreColor (dpy, d_cmap, &xc_item);
994 }
995 }
996
997
998 /* reset all the values */
999 void
Restart()1000 Restart ()
1001 {
1002 int i;
1003 Item *item;
1004
1005 cur_text = NULL;
1006 abs_cursor = rel_cursor = 0;
1007 for (i = 0; i < n_items; i++)
1008 {
1009 item = items + i;
1010 switch (item->type)
1011 {
1012 case I_INPUT:
1013 if (!cur_text)
1014 cur_text = item;
1015 item->input.n = strlen (item->input.init_value);
1016 strcpy (item->input.value, item->input.init_value);
1017 item->input.left = 0;
1018 item->input.o_cursor = 0;
1019 break;
1020 case I_CHOICE:
1021 item->choice.on = item->choice.init_on;
1022 break;
1023 }
1024 }
1025 }
1026
1027 /* redraw the frame */
1028 void
RedrawFrame()1029 RedrawFrame ()
1030 {
1031 int i, x, y;
1032 Item *item;
1033
1034 for (i = 0; i < n_items; i++)
1035 {
1036 item = items + i;
1037 switch (item->type)
1038 {
1039 case I_TEXT:
1040 x = item->header.pos_x + TEXT_SPC;
1041 y = item->header.pos_y + TEXT_SPC + xfs[f_text]->ascent;
1042 #undef FONTSET
1043 #define FONTSET xfset[f_text]
1044 XDrawImageString (dpy, frame, gc_text, x, y, item->text.value,
1045 item->text.n);
1046 break;
1047 case I_CHOICE:
1048 x = item->header.pos_x + TEXT_SPC + item->header.size_y;
1049 y = item->header.pos_y + TEXT_SPC + xfs[f_text]->ascent;
1050 XDrawImageString (dpy, frame, gc_text, x, y, item->choice.text,
1051 item->choice.n);
1052 break;
1053 }
1054 }
1055 }
1056
1057 /* redraw an item */
1058 void
RedrawItem(Item * item,int click)1059 RedrawItem (Item * item, int click)
1060 {
1061 int dx, dy, len, x;
1062 static XSegment xsegs[4];
1063
1064 switch (item->type)
1065 {
1066 case I_INPUT:
1067 dx = item->header.size_x - 1;
1068 dy = item->header.size_y - 1;
1069 XSetForeground (dpy, gc_button, colors[c_itemlo]);
1070 xsegs[0].x1 = 0, xsegs[0].y1 = 0;
1071 xsegs[0].x2 = 0, xsegs[0].y2 = dy;
1072 xsegs[1].x1 = 0, xsegs[1].y1 = 0;
1073 xsegs[1].x2 = dx, xsegs[1].y2 = 0;
1074 xsegs[2].x1 = 1, xsegs[2].y1 = 1;
1075 xsegs[2].x2 = 1, xsegs[2].y2 = dy - 1;
1076 xsegs[3].x1 = 1, xsegs[3].y1 = 1;
1077 xsegs[3].x2 = dx - 1, xsegs[3].y2 = 1;
1078 XDrawSegments (dpy, item->header.win, gc_button, xsegs, 4);
1079 XSetForeground (dpy, gc_button, colors[c_itemhi]);
1080 xsegs[0].x1 = 1, xsegs[0].y1 = dy;
1081 xsegs[0].x2 = dx, xsegs[0].y2 = dy;
1082 xsegs[1].x1 = 2, xsegs[1].y1 = dy - 1;
1083 xsegs[1].x2 = dx, xsegs[1].y2 = dy - 1;
1084 xsegs[2].x1 = dx, xsegs[2].y1 = 1;
1085 xsegs[2].x2 = dx, xsegs[2].y2 = dy;
1086 xsegs[3].x1 = dx - 1, xsegs[3].y1 = 2;
1087 xsegs[3].x2 = dx - 1, xsegs[3].y2 = dy;
1088 XDrawSegments (dpy, item->header.win, gc_button, xsegs, 4);
1089 if (click)
1090 {
1091 x = BOX_SPC + TEXT_SPC + FontWidth (xfs[f_input]) * abs_cursor - 1;
1092 XSetForeground (dpy, gc_button, colors[c_itemback]);
1093 XDrawLine (dpy, item->header.win, gc_button,
1094 x, BOX_SPC, x, dy - BOX_SPC);
1095 }
1096 len = item->input.n - item->input.left;
1097 if (len > item->input.size)
1098 len = item->input.size;
1099 else
1100 #undef FONTSET
1101 #define FONTSET xfset[f_input]
1102 XDrawImageString (dpy, item->header.win, gc_input,
1103 BOX_SPC + TEXT_SPC + FontWidth (xfs[f_input]) * len,
1104 BOX_SPC + TEXT_SPC + xfs[f_input]->ascent,
1105 item->input.blanks, item->input.size - len);
1106 XDrawImageString (dpy, item->header.win, gc_input,
1107 BOX_SPC + TEXT_SPC,
1108 BOX_SPC + TEXT_SPC + xfs[f_input]->ascent,
1109 item->input.value + item->input.left, len);
1110 if (item == cur_text && !click)
1111 {
1112 x = BOX_SPC + TEXT_SPC + FontWidth (xfs[f_input]) * abs_cursor - 1;
1113 XDrawLine (dpy, item->header.win, gc_input,
1114 x, BOX_SPC, x, dy - BOX_SPC);
1115 }
1116 break;
1117 case I_CHOICE:
1118 dx = dy = item->header.size_y - 1;
1119 if (item->choice.on)
1120 {
1121 XSetForeground (dpy, gc_button, colors[c_itemfore]);
1122 if (item->choice.sel->select.key == IS_MULTIPLE)
1123 {
1124 xsegs[0].x1 = 5, xsegs[0].y1 = 5;
1125 xsegs[0].x2 = dx - 5, xsegs[0].y2 = dy - 5;
1126 xsegs[1].x1 = 5, xsegs[1].y1 = dy - 5;
1127 xsegs[1].x2 = dx - 5, xsegs[1].y2 = 5;
1128 XDrawSegments (dpy, item->header.win, gc_button, xsegs, 2);
1129 }
1130 else
1131 {
1132 XDrawArc (dpy, item->header.win, gc_button,
1133 5, 5, dx - 10, dy - 10, 0, 360 * 64);
1134 }
1135 }
1136 else
1137 XClearWindow (dpy, item->header.win);
1138 if (item->choice.on)
1139 XSetForeground (dpy, gc_button, colors[c_itemlo]);
1140 else
1141 XSetForeground (dpy, gc_button, colors[c_itemhi]);
1142 xsegs[0].x1 = 0, xsegs[0].y1 = 0;
1143 xsegs[0].x2 = 0, xsegs[0].y2 = dy;
1144 xsegs[1].x1 = 0, xsegs[1].y1 = 0;
1145 xsegs[1].x2 = dx, xsegs[1].y2 = 0;
1146 xsegs[2].x1 = 1, xsegs[2].y1 = 1;
1147 xsegs[2].x2 = 1, xsegs[2].y2 = dy - 1;
1148 xsegs[3].x1 = 1, xsegs[3].y1 = 1;
1149 xsegs[3].x2 = dx - 1, xsegs[3].y2 = 1;
1150 XDrawSegments (dpy, item->header.win, gc_button, xsegs, 4);
1151 if (item->choice.on)
1152 XSetForeground (dpy, gc_button, colors[c_itemhi]);
1153 else
1154 XSetForeground (dpy, gc_button, colors[c_itemlo]);
1155 xsegs[0].x1 = 1, xsegs[0].y1 = dy;
1156 xsegs[0].x2 = dx, xsegs[0].y2 = dy;
1157 xsegs[1].x1 = 2, xsegs[1].y1 = dy - 1;
1158 xsegs[1].x2 = dx, xsegs[1].y2 = dy - 1;
1159 xsegs[2].x1 = dx, xsegs[2].y1 = 1;
1160 xsegs[2].x2 = dx, xsegs[2].y2 = dy;
1161 xsegs[3].x1 = dx - 1, xsegs[3].y1 = 2;
1162 xsegs[3].x2 = dx - 1, xsegs[3].y2 = dy;
1163 XDrawSegments (dpy, item->header.win, gc_button, xsegs, 4);
1164 break;
1165 case I_BUTTON:
1166 dx = item->header.size_x - 1;
1167 dy = item->header.size_y - 1;
1168 if (click)
1169 XSetForeground (dpy, gc_button, colors[c_itemlo]);
1170 else
1171 XSetForeground (dpy, gc_button, colors[c_itemhi]);
1172 xsegs[0].x1 = 0, xsegs[0].y1 = 0;
1173 xsegs[0].x2 = 0, xsegs[0].y2 = dy;
1174 xsegs[1].x1 = 0, xsegs[1].y1 = 0;
1175 xsegs[1].x2 = dx, xsegs[1].y2 = 0;
1176 xsegs[2].x1 = 1, xsegs[2].y1 = 1;
1177 xsegs[2].x2 = 1, xsegs[2].y2 = dy - 1;
1178 xsegs[3].x1 = 1, xsegs[3].y1 = 1;
1179 xsegs[3].x2 = dx - 1, xsegs[3].y2 = 1;
1180 XDrawSegments (dpy, item->header.win, gc_button, xsegs, 4);
1181 if (click)
1182 XSetForeground (dpy, gc_button, colors[c_itemhi]);
1183 else
1184 XSetForeground (dpy, gc_button, colors[c_itemlo]);
1185 xsegs[0].x1 = 1, xsegs[0].y1 = dy;
1186 xsegs[0].x2 = dx, xsegs[0].y2 = dy;
1187 xsegs[1].x1 = 2, xsegs[1].y1 = dy - 1;
1188 xsegs[1].x2 = dx, xsegs[1].y2 = dy - 1;
1189 xsegs[2].x1 = dx, xsegs[2].y1 = 1;
1190 xsegs[2].x2 = dx, xsegs[2].y2 = dy;
1191 xsegs[3].x1 = dx - 1, xsegs[3].y1 = 2;
1192 xsegs[3].x2 = dx - 1, xsegs[3].y2 = dy;
1193 XDrawSegments (dpy, item->header.win, gc_button, xsegs, 4);
1194 XSetForeground (dpy, gc_button, colors[c_itemfore]);
1195 #undef FONTSET
1196 #define FONTSET xfset[f_button]
1197 XDrawImageString (dpy, item->header.win, gc_button,
1198 BOX_SPC + TEXT_SPC,
1199 BOX_SPC + TEXT_SPC + xfs[f_button]->ascent,
1200 item->button.text, item->button.len);
1201 break;
1202 }
1203 XFlush (dpy);
1204 }
1205
1206 void
ToggleChoice(Item * item)1207 ToggleChoice (Item * item)
1208 {
1209 int i;
1210 Item *sel = item->choice.sel;
1211
1212 if (sel->select.key == IS_SINGLE)
1213 {
1214 if (!item->choice.on)
1215 {
1216 for (i = 0; i < sel->select.n; i++)
1217 {
1218 if (sel->select.choices[i]->choice.on)
1219 {
1220 sel->select.choices[i]->choice.on = 0;
1221 RedrawItem (sel->select.choices[i], 0);
1222 }
1223 }
1224 item->choice.on = 1;
1225 RedrawItem (item, 0);
1226 }
1227 }
1228 else
1229 { /* IS_MULTIPLE */
1230 item->choice.on = !item->choice.on;
1231 RedrawItem (item, 0);
1232 }
1233 }
1234
1235 /* do var substitution for command string */
1236 void
ParseCommand(int dn,char * sp,char end,int * dn1,char ** sp1)1237 ParseCommand (int dn, char *sp, char end, int *dn1, char **sp1)
1238 #define AddChar(chr) { if (dn >= N) { N *= 2; buf = (char *)realloc(buf, N); } buf[dn++] = (chr); }
1239 {
1240 static char var[256];
1241 char c, x, *wp, *cp, *vp;
1242 int i, j, dn2;
1243 Item *item;
1244
1245 while (1)
1246 {
1247 c = *(sp++);
1248 if (c == '\0' || c == end)
1249 { /* end of substitution */
1250 *dn1 = dn;
1251 *sp1 = sp;
1252 return;
1253 }
1254 if (c == '\\')
1255 { /* escape char */
1256 AddChar ('\\');
1257 AddChar (*(sp++));
1258 goto next_loop;
1259 }
1260 if (c == '$')
1261 { /* variable */
1262 if (*sp != '(')
1263 goto normal_char;
1264 wp = ++sp;
1265 vp = var;
1266 while (1)
1267 {
1268 x = *(sp++);
1269 if (x == '\\')
1270 {
1271 *(vp++) = '\\';
1272 *(vp++) = *(sp++);
1273 }
1274 else if (x == ')' || x == '?' || x == '!')
1275 {
1276 *(vp++) = '\0';
1277 break;
1278 }
1279 else if (!isspace (x))
1280 *(vp++) = x;
1281 }
1282 for (i = 0; i < n_items; i++)
1283 {
1284 item = items + i;
1285 if (strcmp (var, item->header.name) == 0)
1286 {
1287 switch (item->type)
1288 {
1289 case I_INPUT:
1290 if (x == ')')
1291 {
1292 for (cp = item->input.value; *cp != '\0'; cp++)
1293 {
1294 if (!isalnum (*cp))
1295 AddChar ('\\');
1296 AddChar (*cp);
1297 }
1298 }
1299 else
1300 {
1301 ParseCommand (dn, sp, ')', &dn2, &sp);
1302 if ((x == '?' && strlen (item->input.value) > 0) ||
1303 (x == '!' && strlen (item->input.value) == 0))
1304 dn = dn2;
1305 }
1306 break;
1307 case I_CHOICE:
1308 if (x == ')')
1309 {
1310 for (cp = item->choice.value; *cp != '\0'; cp++)
1311 AddChar (*cp);
1312 }
1313 else
1314 {
1315 ParseCommand (dn, sp, ')', &dn2, &sp);
1316 if ((x == '?' && item->choice.on) ||
1317 (x == '!' && !item->choice.on))
1318 dn = dn2;
1319 }
1320 break;
1321 case I_SELECT:
1322 if (x != ')')
1323 ParseCommand (dn, sp, ')', &dn2, &sp);
1324 AddChar (' ');
1325 for (j = 0; j < item->select.n; j++)
1326 {
1327 if (item->select.choices[j]->choice.on)
1328 {
1329 for (cp = item->select.choices[j]->choice.value;
1330 *cp != '\0'; cp++)
1331 AddChar (*cp);
1332 AddChar (' ');
1333 }
1334 }
1335 break;
1336 }
1337 goto next_loop;
1338 }
1339 }
1340 goto next_loop;
1341 }
1342 normal_char:
1343 AddChar (c);
1344 next_loop:
1345 ;
1346 }
1347 }
1348
1349 /* execute a command */
1350 void
DoCommand(Item * cmd)1351 DoCommand (Item * cmd)
1352 {
1353 int i, k, dn, len;
1354 char *sp;
1355
1356 /* pre-command */
1357 if (cmd->button.key == IB_QUIT)
1358 XWithdrawWindow (dpy, frame, screen);
1359
1360 for (k = 0; k < cmd->button.n; k++)
1361 {
1362 /* construct command */
1363 ParseCommand (0, cmd->button.commands[k], '\0', &dn, &sp);
1364 AddChar ('\0');
1365 fprintf (fp_err, "Final command[%d]: [%s]\n", k, buf);
1366
1367 /* send command */
1368 write (fd[1], &ref, sizeof (Window));
1369 len = strlen (buf);
1370 write (fd[1], &len, sizeof (int));
1371 write (fd[1], buf, len);
1372 len = 1;
1373 write (fd[1], &len, sizeof (int));
1374 }
1375
1376 /* post-command */
1377 if (cmd->button.key == IB_QUIT)
1378 {
1379 if (grab_server)
1380 XUngrabServer (dpy);
1381 exit (0);
1382 }
1383 if (cmd->button.key == IB_RESTART)
1384 {
1385 Restart ();
1386 for (i = 0; i < n_items; i++)
1387 {
1388 if (items[i].type == I_INPUT)
1389 {
1390 XClearWindow (dpy, items[i].header.win);
1391 RedrawItem (items + i, 0);
1392 }
1393 if (items[i].type == I_CHOICE)
1394 RedrawItem (items + i, 0);
1395 }
1396 }
1397 }
1398
1399 /* open the windows */
1400 void
OpenWindows()1401 OpenWindows ()
1402 {
1403 int i, x, y;
1404 Item *item;
1405 static XColor xcf, xcb;
1406 static XSetWindowAttributes xswa;
1407 static XGCValues xgcv;
1408 static XWMHints wmh =
1409 {InputHint, True};
1410 static XSizeHints sh =
1411 {PPosition | PSize | USPosition | USSize};
1412 static int xgcv_mask = GCBackground | GCForeground | GCFont;
1413
1414 xc_ibeam = XCreateFontCursor (dpy, XC_xterm);
1415 xc_hand = XCreateFontCursor (dpy, XC_hand2);
1416 xcf.pixel = WhitePixel (dpy, screen);
1417 XQueryColor (dpy, d_cmap, &xcf);
1418 xcb.pixel = colors[c_itemback];
1419 XQueryColor (dpy, d_cmap, &xcb);
1420 XRecolorCursor (dpy, xc_ibeam, &xcf, &xcb);
1421
1422 /* the frame window first */
1423 if (geom)
1424 {
1425 if (gx >= 0)
1426 x = gx;
1427 else
1428 x = DisplayWidth (dpy, screen) - max_width + gx;
1429 if (gy >= 0)
1430 y = gy;
1431 else
1432 y = DisplayHeight (dpy, screen) - total_height + gy;
1433 }
1434 else
1435 {
1436 x = (DisplayWidth (dpy, screen) - max_width) / 2;
1437 y = (DisplayHeight (dpy, screen) - total_height) / 2;
1438 }
1439 frame = XCreateSimpleWindow (dpy, root, x, y, max_width, total_height,
1440 0, BlackPixel (dpy, screen), colors[c_back]);
1441 XSelectInput (dpy, frame, KeyPressMask | ExposureMask);
1442 XStoreName (dpy, frame, MyName);
1443 XSetWMHints (dpy, frame, &wmh);
1444 sh.x = x, sh.y = y;
1445 sh.width = max_width, sh.height = total_height;
1446 XSetWMNormalHints (dpy, frame, &sh);
1447
1448 xgcv.foreground = colors[c_fore];
1449 xgcv.background = colors[c_back];
1450 xgcv.font = fonts[f_text];
1451 gc_text = XCreateGC (dpy, frame, xgcv_mask, &xgcv);
1452 xgcv.background = colors[c_itemback];
1453 xgcv.foreground = colors[c_itemfore];
1454 xgcv.font = fonts[f_input];
1455 gc_input = XCreateGC (dpy, frame, xgcv_mask, &xgcv);
1456 xgcv.font = fonts[f_button];
1457 gc_button = XCreateGC (dpy, frame, xgcv_mask, &xgcv);
1458
1459 for (i = 0; i < n_items; i++)
1460 {
1461 item = items + i;
1462 switch (item->type)
1463 {
1464 case I_INPUT:
1465 item->header.win =
1466 XCreateSimpleWindow (dpy, frame,
1467 item->header.pos_x, item->header.pos_y,
1468 item->header.size_x, item->header.size_y,
1469 0, colors[c_back], colors[c_itemback]);
1470 XSelectInput (dpy, item->header.win, ButtonPressMask | ExposureMask);
1471 xswa.cursor = xc_ibeam;
1472 XChangeWindowAttributes (dpy, item->header.win, CWCursor, &xswa);
1473 break;
1474 case I_CHOICE:
1475 item->header.win =
1476 XCreateSimpleWindow (dpy, frame,
1477 item->header.pos_x, item->header.pos_y,
1478 item->header.size_y, item->header.size_y,
1479 0, colors[c_back], colors[c_itemback]);
1480 XSelectInput (dpy, item->header.win, ButtonPressMask | ExposureMask);
1481 xswa.cursor = xc_hand;
1482 XChangeWindowAttributes (dpy, item->header.win, CWCursor, &xswa);
1483 break;
1484 case I_BUTTON:
1485 item->header.win =
1486 XCreateSimpleWindow (dpy, frame,
1487 item->header.pos_x, item->header.pos_y,
1488 item->header.size_x, item->header.size_y,
1489 0, colors[c_back], colors[c_itemback]);
1490 XSelectInput (dpy, item->header.win,
1491 ButtonPressMask | ExposureMask);
1492 xswa.cursor = xc_hand;
1493 XChangeWindowAttributes (dpy, item->header.win, CWCursor, &xswa);
1494 break;
1495 }
1496 }
1497 Restart ();
1498 XMapRaised (dpy, frame);
1499 XMapSubwindows (dpy, frame);
1500 if (warp_pointer)
1501 {
1502 XWarpPointer (dpy, None, frame, 0, 0, 0, 0,
1503 max_width / 2, total_height - 1);
1504 }
1505 DoCommand (&def_button);
1506 }
1507
1508 /* read something from Afterstep */
1509 void
ReadAfterstep()1510 ReadAfterstep ()
1511 {
1512 static char buffer[32];
1513 int n;
1514
1515 n = read (fd[0], buffer, 32);
1516 if (n == 0)
1517 {
1518 if (grab_server)
1519 XUngrabServer (dpy);
1520 exit (0);
1521 }
1522 }
1523
1524 /* read an X event */
1525 void
ReadXServer()1526 ReadXServer ()
1527 {
1528 static XEvent event;
1529 int i, old_cursor = 0, keypress;
1530 Item *item, *old_item;
1531 KeySym ks;
1532 char *sp, *dp, *ep;
1533 static char buf[10], n;
1534
1535 while (XEventsQueued (dpy, QueuedAfterReading))
1536 {
1537 XNextEvent (dpy, &event);
1538 if (event.xany.window == frame)
1539 {
1540 switch (event.type)
1541 {
1542 case Expose:
1543 RedrawFrame ();
1544 if (grab_server && !server_grabbed)
1545 {
1546 if (GrabSuccess ==
1547 XGrabPointer (dpy, frame, True, 0, GrabModeAsync, GrabModeAsync,
1548 None, None, CurrentTime))
1549 server_grabbed = 1;
1550 }
1551 break;
1552 case KeyPress: /* we do text input here */
1553 n = XLookupString (&event.xkey, buf, 10, &ks, NULL);
1554 keypress = buf[0];
1555 fprintf (fp_err, "Keypress [%s]\n", buf);
1556 if (n == 0)
1557 { /* not a regular key, translate it into one */
1558 switch (ks)
1559 {
1560 case XK_Home:
1561 case XK_Begin:
1562 buf[0] = '\001'; /* ^A */
1563 break;
1564 case XK_End:
1565 buf[0] = '\005'; /* ^E */
1566 break;
1567 case XK_Left:
1568 buf[0] = '\002'; /* ^B */
1569 break;
1570 case XK_Right:
1571 buf[0] = '\006'; /* ^F */
1572 break;
1573 case XK_Up:
1574 buf[0] = '\020'; /* ^P */
1575 break;
1576 case XK_Down:
1577 buf[0] = '\016'; /* ^N */
1578 break;
1579 default:
1580 if (ks >= XK_F1 && ks <= XK_F35)
1581 {
1582 buf[0] = '\0';
1583 keypress = 257 + ks - XK_F1;
1584 }
1585 else
1586 goto no_redraw; /* no action for this event */
1587 }
1588 }
1589 if (!cur_text)
1590 { /* no text input fields */
1591 for (i = 0; i < n_items; i++)
1592 {
1593 item = items + i;
1594 fprintf (fp_err, "Button[%d], keypress==%d\n", i,
1595 item->button.keypress);
1596 if (item->type == I_BUTTON && item->button.keypress == buf[0])
1597 {
1598 RedrawItem (item, 1);
1599 sleep (1);
1600 RedrawItem (item, 0);
1601 DoCommand (item);
1602 goto no_redraw;
1603 }
1604 }
1605 break;
1606 }
1607 switch (buf[0])
1608 {
1609 case '\001': /* ^A */
1610 old_cursor = abs_cursor;
1611 rel_cursor = 0;
1612 abs_cursor = 0;
1613 cur_text->input.left = 0;
1614 goto redraw_newcursor;
1615 break;
1616 case '\005': /* ^E */
1617 old_cursor = abs_cursor;
1618 rel_cursor = cur_text->input.n;
1619 if ((cur_text->input.left = rel_cursor - cur_text->input.size) < 0)
1620 cur_text->input.left = 0;
1621 abs_cursor = rel_cursor - cur_text->input.left;
1622 goto redraw_newcursor;
1623 break;
1624 case '\002': /* ^B */
1625 old_cursor = abs_cursor;
1626 if (rel_cursor > 0)
1627 {
1628 rel_cursor--;
1629 abs_cursor--;
1630 if (abs_cursor <= 0 && rel_cursor > 0)
1631 {
1632 abs_cursor++;
1633 cur_text->input.left--;
1634 }
1635 }
1636 goto redraw_newcursor;
1637 break;
1638 case '\006': /* ^F */
1639 old_cursor = abs_cursor;
1640 if (rel_cursor < cur_text->input.n)
1641 {
1642 rel_cursor++;
1643 abs_cursor++;
1644 if (abs_cursor >= cur_text->input.size &&
1645 rel_cursor < cur_text->input.n)
1646 {
1647 abs_cursor--;
1648 cur_text->input.left++;
1649 }
1650 }
1651 goto redraw_newcursor;
1652 break;
1653 case '\010': /* ^H */
1654 case '\177': /* DEL */
1655 old_cursor = abs_cursor;
1656 if (rel_cursor > 0)
1657 {
1658 sp = cur_text->input.value + rel_cursor;
1659 dp = sp - 1;
1660 for (; *dp = *sp, *sp != '\0'; dp++, sp++);
1661 cur_text->input.n--;
1662 rel_cursor--;
1663 if (rel_cursor < abs_cursor)
1664 {
1665 abs_cursor--;
1666 if (abs_cursor <= 0 && rel_cursor > 0)
1667 {
1668 abs_cursor++;
1669 cur_text->input.left--;
1670 }
1671 }
1672 else
1673 cur_text->input.left--;
1674 }
1675 goto redraw_newcursor;
1676 break;
1677 case '\004': /* ^D */
1678 if (rel_cursor < cur_text->input.n)
1679 {
1680 sp = cur_text->input.value + rel_cursor + 1;
1681 dp = sp - 1;
1682 for (; *dp = *sp, *sp != '\0'; dp++, sp++);
1683 cur_text->input.n--;
1684 goto redraw;
1685 }
1686 break;
1687 case '\013': /* ^K */
1688 cur_text->input.value[rel_cursor] = '\0';
1689 cur_text->input.n = rel_cursor;
1690 goto redraw;
1691 case '\025': /* ^U */
1692 old_cursor = abs_cursor;
1693 cur_text->input.value[0] = '\0';
1694 cur_text->input.n = cur_text->input.left = 0;
1695 rel_cursor = abs_cursor = 0;
1696 goto redraw_newcursor;
1697 case '\t':
1698 case '\n':
1699 case '\015':
1700 case '\016': /* LINEFEED, TAB, RETURN, ^N, jump to the next field */
1701 for (i = (cur_text - items) + 1; i < n_items; i++)
1702 {
1703 item = items + i;
1704 if (item->type == I_INPUT)
1705 {
1706 old_item = cur_text;
1707 old_item->input.o_cursor = rel_cursor;
1708 cur_text = item;
1709 RedrawItem (old_item, 1);
1710 rel_cursor = item->input.o_cursor;
1711 abs_cursor = rel_cursor - item->input.left;
1712 goto redraw;
1713 }
1714 }
1715 /* end of all text input fields, check for buttons */
1716 for (i = 0; i < n_items; i++)
1717 {
1718 item = items + i;
1719 fprintf (fp_err, "Button[%d], keypress==%d\n", i,
1720 item->button.keypress);
1721 if (item->type == I_BUTTON && item->button.keypress == buf[0])
1722 {
1723 RedrawItem (item, 1);
1724 sleep (1);
1725 RedrawItem (item, 0);
1726 DoCommand (item);
1727 goto no_redraw;
1728 }
1729 }
1730 /* goto the first text input field */
1731 for (i = 0; i < n_items; i++)
1732 {
1733 item = items + i;
1734 if (item->type == I_INPUT)
1735 {
1736 old_item = cur_text;
1737 old_item->input.o_cursor = rel_cursor;
1738 cur_text = item;
1739 RedrawItem (old_item, 1);
1740 rel_cursor = item->input.o_cursor;
1741 abs_cursor = rel_cursor - item->input.left;
1742 goto redraw;
1743 }
1744 }
1745 break;
1746 default:
1747 old_cursor = abs_cursor;
1748 if (buf[0] >= ' ' && buf[0] < '\177')
1749 { /* regular char */
1750 if (++(cur_text->input.n) >= cur_text->input.buf)
1751 {
1752 cur_text->input.buf += cur_text->input.size;
1753 cur_text->input.value =
1754 (char *) realloc (cur_text->input.value,
1755 cur_text->input.buf);
1756 }
1757 dp = cur_text->input.value + cur_text->input.n;
1758 sp = dp - 1;
1759 ep = cur_text->input.value + rel_cursor;
1760 for (; *dp = *sp, sp != ep; sp--, dp--);
1761 *ep = buf[0];
1762 rel_cursor++;
1763 abs_cursor++;
1764 if (abs_cursor >= cur_text->input.size)
1765 {
1766 if (rel_cursor < cur_text->input.n)
1767 abs_cursor = cur_text->input.size - 1;
1768 else
1769 abs_cursor = cur_text->input.size;
1770 cur_text->input.left = rel_cursor - abs_cursor;
1771 }
1772 goto redraw_newcursor;
1773 }
1774 /* unrecognized key press, check for buttons */
1775 for (i = 0; i < n_items; i++)
1776 {
1777 item = items + i;
1778 fprintf (fp_err, "Button[%d], keypress==%d\n", i,
1779 item->button.keypress);
1780 if (item->type == I_BUTTON && item->button.keypress == keypress)
1781 {
1782 RedrawItem (item, 1);
1783 sleep (1); /* .5 seconds */
1784 RedrawItem (item, 0);
1785 DoCommand (item);
1786 goto no_redraw;
1787 }
1788 }
1789 break;
1790 }
1791 redraw_newcursor:
1792 {
1793 int x, dy;
1794 x = BOX_SPC + TEXT_SPC + FontWidth (xfs[f_input]) * old_cursor - 1;
1795 dy = cur_text->header.size_y - 1;
1796 XSetForeground (dpy, gc_button, colors[c_itemback]);
1797 XDrawLine (dpy, cur_text->header.win, gc_button,
1798 x, BOX_SPC, x, dy - BOX_SPC);
1799 }
1800 redraw:
1801 {
1802 int len, x, dy;
1803 len = cur_text->input.n - cur_text->input.left;
1804 if (len > cur_text->input.size)
1805 len = cur_text->input.size;
1806 else
1807 #undef FONTSET
1808 #define FONTSET xfset[f_input]
1809 XDrawImageString (dpy, cur_text->header.win, gc_input,
1810 BOX_SPC + TEXT_SPC +
1811 FontWidth (xfs[f_input]) * len,
1812 BOX_SPC + TEXT_SPC + xfs[f_input]->ascent,
1813 cur_text->input.blanks,
1814 cur_text->input.size - len);
1815 XDrawImageString (dpy, cur_text->header.win, gc_input,
1816 BOX_SPC + TEXT_SPC,
1817 BOX_SPC + TEXT_SPC + xfs[f_input]->ascent,
1818 cur_text->input.value + cur_text->input.left, len);
1819 x = BOX_SPC + TEXT_SPC + FontWidth (xfs[f_input]) * abs_cursor - 1;
1820 dy = cur_text->header.size_y - 1;
1821 XDrawLine (dpy, cur_text->header.win, gc_input,
1822 x, BOX_SPC, x, dy - BOX_SPC);
1823 }
1824 no_redraw:
1825 break; /* end of case KeyPress */
1826 } /* end of switch (event.type) */
1827 continue;
1828 } /* end of if (event.xany.window == frame) */
1829 for (i = 0; i < n_items; i++)
1830 {
1831 item = items + i;
1832 if (event.xany.window == item->header.win)
1833 {
1834 switch (event.type)
1835 {
1836 case Expose:
1837 RedrawItem (item, 0);
1838 break;
1839 case ButtonPress:
1840 if (item->type == I_INPUT)
1841 {
1842 old_item = cur_text;
1843 old_item->input.o_cursor = rel_cursor;
1844 cur_text = item;
1845 RedrawItem (old_item, 1);
1846 abs_cursor = (event.xbutton.x - BOX_SPC -
1847 TEXT_SPC + FontWidth (xfs[f_input]) / 2)
1848 / FontWidth (xfs[f_input]);
1849 if (abs_cursor < 0)
1850 abs_cursor = 0;
1851 if (abs_cursor > item->input.size)
1852 abs_cursor = item->input.size;
1853 rel_cursor = abs_cursor + item->input.left;
1854 if (rel_cursor < 0)
1855 rel_cursor = 0;
1856 if (rel_cursor > item->input.n)
1857 rel_cursor = item->input.n;
1858 if (rel_cursor > 0 && rel_cursor == item->input.left)
1859 item->input.left--;
1860 if (rel_cursor < item->input.n &&
1861 rel_cursor == item->input.left + item->input.size)
1862 item->input.left++;
1863 abs_cursor = rel_cursor - item->input.left;
1864 RedrawItem (item, 0);
1865 }
1866 if (item->type == I_CHOICE)
1867 ToggleChoice (item);
1868 if (item->type == I_BUTTON)
1869 {
1870 RedrawItem (item, 1);
1871 XGrabPointer (dpy, item->header.win, False, ButtonReleaseMask,
1872 GrabModeAsync, GrabModeAsync,
1873 None, None, CurrentTime);
1874 }
1875 break;
1876 case ButtonRelease:
1877 RedrawItem (item, 0);
1878 if (grab_server && server_grabbed)
1879 {
1880 XGrabPointer (dpy, frame, True, 0, GrabModeAsync, GrabModeAsync,
1881 None, None, CurrentTime);
1882 XFlush (dpy);
1883 }
1884 else
1885 {
1886 XUngrabPointer (dpy, CurrentTime);
1887 XFlush (dpy);
1888 }
1889 if (event.xbutton.x >= 0 &&
1890 event.xbutton.x < item->header.size_x &&
1891 event.xbutton.y >= 0 &&
1892 event.xbutton.y < item->header.size_y)
1893 {
1894 DoCommand (item);
1895 }
1896 break;
1897 }
1898 }
1899 } /* end of for (i = 0 */
1900 } /* while loop */
1901 }
1902
1903 /* main event loop */
1904 void
MainLoop()1905 MainLoop ()
1906 {
1907 fd_set fds;
1908
1909 while (1)
1910 {
1911 FD_ZERO (&fds);
1912 FD_SET (fd[0], &fds);
1913 FD_SET (fd_x, &fds);
1914
1915 XFlush (dpy);
1916 if (select (32, &fds, NULL, NULL, NULL) > 0)
1917 {
1918 if (FD_ISSET (fd[0], &fds))
1919 ReadAfterstep ();
1920 if (FD_ISSET (fd_x, &fds))
1921 ReadXServer ();
1922 }
1923 }
1924 }
1925
1926 void
version(void)1927 version (void)
1928 {
1929 printf ("%s version %s\n", MyName, VERSION);
1930 exit (0);
1931 }
1932
1933 void
usage(void)1934 usage (void)
1935 {
1936 printf ("Usage:\n"
1937 "%s [-v|--version] [-h|--help] [--window window-id] [script-name]\n", MyName);
1938 exit (0);
1939 }
1940
1941 /* main procedure */
1942 int
main(int argc,char ** argv)1943 main (int argc, char **argv)
1944 {
1945 char configfile[255];
1946 char *realconfigfile;
1947 FILE *fdopen ();
1948 char *temp;
1949 int i;
1950 char *global_config_file = NULL;
1951
1952 buf = (char *) safemalloc (N); /* some kludge */
1953
1954 #ifdef DEBUG
1955 fd_err = open (".FormErrors", O_WRONLY | O_CREAT, 0777);
1956 fp_err = fdopen (fd_err, "w");
1957 #else
1958 fd_err = open ("/dev/null", O_WRONLY, 0);
1959 fp_err = fdopen (fd_err, "w");
1960 #endif
1961
1962 #ifdef I18N
1963 if (setlocale (LC_CTYPE, "") == NULL)
1964 fprintf (fp_err, "can't set locale\n");
1965 #endif
1966
1967 ref = None;
1968
1969 /* Save our program name - for error messages */
1970 temp = strrchr (argv[0], '/');
1971 MyName = temp ? temp + 1 : argv[0];
1972
1973 for (i = 1; i < argc && *argv[i] == '-'; i++)
1974 {
1975 if (!strcmp (argv[i], "-h") || !strcmp (argv[i], "--help"))
1976 usage ();
1977 else if (!strcmp (argv[i], "-v") || !strcmp (argv[i], "--version"))
1978 version ();
1979 else if (!strcmp (argv[i], "-w") || !strcmp (argv[i], "--window"))
1980 ref = strtol (argv[++i], NULL, 16);
1981 else if (!strcmp (argv[i], "-c") || !strcmp (argv[i], "--context"))
1982 i++;
1983 else if (!strcmp (argv[i], "-f") && i + 1 < argc)
1984 global_config_file = argv[++i];
1985 }
1986
1987 if (i < argc)
1988 MyName = argv[i++];
1989
1990 #ifdef DEBUG
1991 fprintf (fp_err, "ref == %d\n", ref);
1992 #endif
1993
1994 if ((dpy = XOpenDisplay ("")) == NULL)
1995 {
1996 fprintf (stderr, "%s: couldn't open display %s\n",
1997 MyName, XDisplayName (""));
1998 exit (1);
1999 }
2000 screen = DefaultScreen (dpy);
2001
2002 /* connect to AfterStep */
2003 temp = module_get_socket_property (RootWindow (dpy, screen));
2004 fd[0] = fd[1] = module_connect (temp);
2005 XFree (temp);
2006 if (fd[0] < 0)
2007 {
2008 fprintf (stderr, "%s: unable to establish connection to AfterStep\n", MyName);
2009 exit (1);
2010 }
2011 temp = safemalloc (9 + strlen (MyName) + 1);
2012 sprintf (temp, "SET_NAME %s", MyName);
2013 SendInfo (fd, temp, None);
2014 free (temp);
2015
2016 fd_x = XConnectionNumber (dpy);
2017 root = RootWindow (dpy, screen);
2018 scr_depth = DefaultDepth (dpy, screen);
2019 d_cmap = DefaultColormap (dpy, screen);
2020
2021 if (global_config_file != NULL)
2022 ParseOptions (global_config_file);
2023 else
2024 {
2025 sprintf (configfile, "%s/forms", AFTER_DIR);
2026 realconfigfile = PutHome (configfile);
2027
2028 if ((CheckFile (realconfigfile)) == -1)
2029 {
2030 free (realconfigfile);
2031 sprintf (configfile, "%s/forms", AFTER_SHAREDIR);
2032 realconfigfile = PutHome (configfile);
2033 }
2034 ParseOptions (realconfigfile);
2035 }
2036
2037 GetColors ();
2038
2039 OpenWindows ();
2040
2041 MainLoop ();
2042
2043 return 0;
2044 }
2045