cvsimport
[fvwm.git] / modules / FvwmForm / FvwmForm.c
blob2b4d0ecca91b108f45506b1140d9c07c438eec08
1 /* -*-c-*- */
2 /* FvwmForm is original work of Thomas Zuwei Feng.
4 * Copyright Feb 1995, Thomas Zuwei Feng. No guarantees or warantees are
5 * provided or implied in any way whatsoever. Use this program at your own
6 * risk. Permission to use, modify, and redistribute this program is hereby
7 * given, provided that this copyright is kept intact. */
9 /* This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "libs/ftime.h"
31 #include <fcntl.h>
33 #include <X11/Xlib.h>
34 #include <X11/X.h>
35 #include <X11/Xutil.h>
36 #include <X11/cursorfont.h>
37 #define XK_MISCELLANY
38 #include <X11/keysymdef.h>
40 #include "libs/Module.h" /* for headersize, etc. */
41 #include "libs/fvwmlib.h"
42 #include "libs/fvwmsignal.h"
43 #include "libs/ColorUtils.h"
44 #include "libs/Cursor.h"
45 #include "libs/envvar.h"
46 #include "libs/Graphics.h"
47 #include "libs/Parse.h"
48 #include "libs/Strings.h"
49 #include "libs/System.h"
50 #include "libs/XError.h"
52 #include "libs/PictureBase.h" /* for PictureInitCMap */
53 #include "libs/Colorset.h"
54 #include "libs/FScreen.h"
55 #include "libs/FShape.h"
56 #include "libs/FRenderInit.h"
57 #include "libs/Rectangles.h"
59 #include "FvwmForm.h" /* common FvwmForm stuff */
61 /* globals that are exported, keep in sync with externs in FvwmForm.h */
62 Form cur_form; /* current form */
64 /* Link list roots */
65 Item *root_item_ptr; /* pointer to root of item list */
66 Line root_line = {&root_line, /* ->next */
67 0, /* number of items */
68 L_CENTER,0,0, /* justify, size x/y */
69 0, /* current array size */
70 0}; /* items ptr */
71 Line *cur_line = &root_line; /* curr line in parse rtns */
72 char preload_yorn='n'; /* init to non-preload */
73 Item *item; /* current during parse */
74 Item *cur_sel, *cur_button; /* current during parse */
75 Item *timer = NULL; /* timeout tracking */
76 Display *dpy;
77 Atom wm_del_win;
78 int fd_x; /* fd for X connection */
79 Window root, ref;
80 int screen;
81 char *color_names[4];
82 char bg_state = 'd'; /* in default state */
83 /* d = default state */
84 /* s = set by command (must be in "d" state for first "back" cmd to set it) */
85 /* u = used (color allocated, too late to accept "back") */
86 char endDefaultsRead = 'n';
87 char *font_names[4];
88 char *screen_background_color;
89 static ModuleArgs *module;
90 int Channel[2];
91 Bool Swallowed = False;
93 /* Font/color stuff
94 The colors are:
95 . defaults are changed by commands during parse
96 . copied into items during parse
97 . displayed in the customization dialog
99 int colorset = -1;
100 int itemcolorset = 0;
102 /* prototypes */
103 static void AssignDrawTable(Item *);
104 static void AddItem(void);
105 static void PutDataInForm(char *);
106 static void ReadFormData(void);
107 static void FormVarsCheck(char **);
108 static RETSIGTYPE TimerHandler(int);
109 static int ErrorHandler(Display *dpy, XErrorEvent *error_event);
110 static void SetupTimer(void)
112 #ifdef HAVE_SIGACTION
114 struct sigaction sigact;
116 #ifdef SA_INTERRUPT
117 sigact.sa_flags = SA_INTERRUPT;
118 #else
119 sigact.sa_flags = 0;
120 #endif
121 sigemptyset(&sigact.sa_mask);
122 sigaddset(&sigact.sa_mask, SIGALRM);
123 sigact.sa_handler = TimerHandler;
125 sigaction(SIGALRM, &sigact, NULL);
127 #else
128 #ifdef USE_BSD_SIGNALS
129 fvwmSetSignalMask( sigmask(SIGALRM) );
130 #endif
131 signal(SIGALRM, TimerHandler); /* Dead pipe == Fvwm died */
132 #ifdef HAVE_SIGINTERRUPT
133 siginterrupt(SIGALRM, 1);
134 #endif
135 #endif
137 alarm(1);
140 /* copy a string until '"', or '\n', or '\0' */
141 static char *CopyQuotedString (char *cp)
143 char *dp, *bp, c;
144 bp = dp = (char *)safemalloc(strlen(cp) + 1);
145 while (1) {
146 switch (c = *(cp++)) {
147 case '\\':
148 *(dp++) = *(cp++);
149 break;
150 case '\"':
151 case '\n':
152 case '\0':
153 *dp = '\0';
154 return bp;
155 break;
156 default:
157 *(dp++) = c;
158 break;
163 /* copy a string until the first space */
164 static char *CopySolidString (char *cp)
166 char *dp, *bp, c;
167 bp = dp = (char *)safemalloc(strlen(cp) + 1);
168 while (1) {
169 c = *(cp++);
170 if (c == '\\') {
171 *(dp++) = '\\';
172 *(dp++) = *(cp++);
173 } else if (isspace((unsigned char)c) || c == '\0') {
174 *dp = '\0';
175 return bp;
176 } else
177 *(dp++) = c;
181 /* Command parsing section */
183 /* FvwmAnimate++ type command table */
184 typedef struct CommandTable
186 char *name;
187 void (*function)(char *);
188 } ct;
189 static void ct_ActivateOnPress(char *);
190 static void ct_Back(char *);
191 static void ct_Button(char *);
192 static void ct_ButtonFont(char *);
193 static void ct_ButtonInPointer(char *);
194 static void ct_ButtonInPointerBack(char *);
195 static void ct_ButtonInPointerFore(char *);
196 static void ct_ButtonPointer(char *);
197 static void ct_ButtonPointerBack(char *);
198 static void ct_ButtonPointerFore(char *);
199 static void ct_Choice(char *);
200 static void ct_Command(char *);
201 static void ct_Font(char *);
202 static void ct_Fore(char *);
203 static void ct_GrabServer(char *);
204 static void ct_Input(char *);
205 static void ct_InputFont(char *);
206 static void ct_ItemBack(char *);
207 static void ct_ItemFore(char *);
208 static void ct_Line(char *);
209 static void ct_Message(char *);
210 static void ct_Geometry(char *);
211 static void ct_Position(char *);
212 static void ct_Read(char *);
213 static void ct_Selection(char *);
214 static void ct_Text(char *);
215 static void ct_InputPointer(char *);
216 static void ct_InputPointerBack(char *);
217 static void ct_InputPointerFore(char *);
218 static void ct_Timeout(char *);
219 static void ct_TimeoutFont(char *);
220 static void ct_Title(char *);
221 static void ct_UseData(char *);
222 static void ct_padVText(char *);
223 static void ct_WarpPointer(char *);
224 static void ct_Colorset(char *);
225 static void ct_ItemColorset(char *);
227 /* Must be in Alphabetic order (caseless) */
228 static struct CommandTable ct_table[] =
230 {"ActivateOnPress",ct_ActivateOnPress},
231 {"Back",ct_Back},
232 {"Button",ct_Button},
233 {"ButtonFont",ct_ButtonFont},
234 {"ButtonInPointer",ct_ButtonInPointer},
235 {"ButtonInPointerBack",ct_ButtonInPointerBack},
236 {"ButtonInPointerFore",ct_ButtonInPointerFore},
237 {"ButtonPointer",ct_ButtonPointer},
238 {"ButtonPointerBack",ct_ButtonPointerBack},
239 {"ButtonPointerFore",ct_ButtonPointerFore},
240 {"Choice",ct_Choice},
241 {"Colorset",ct_Colorset},
242 {"Command",ct_Command},
243 {"Font",ct_Font},
244 {"Fore",ct_Fore},
245 {"Geometry",ct_Geometry},
246 {"GrabServer",ct_GrabServer},
247 {"Input",ct_Input},
248 {"InputFont",ct_InputFont},
249 {"InputPointer",ct_InputPointer},
250 {"InputPointerBack",ct_InputPointerBack},
251 {"InputPointerFore",ct_InputPointerFore},
252 {"ItemBack",ct_ItemBack},
253 {"ItemColorset",ct_ItemColorset},
254 {"ItemFore",ct_ItemFore},
255 {"Line",ct_Line},
256 {"Message",ct_Message},
257 {"PadVText",ct_padVText},
258 {"Position",ct_Position},
259 {"Selection",ct_Selection},
260 {"Text",ct_Text},
261 {"Timeout",ct_Timeout},
262 {"TimeoutFont",ct_TimeoutFont},
263 {"Title",ct_Title},
264 {"UseData",ct_UseData},
265 {"WarpPointer",ct_WarpPointer}
267 /* These commands are the default setting commands,
268 read before the other form defining commands. */
269 static struct CommandTable def_table[] =
271 {"ActivateOnPress",ct_ActivateOnPress},
272 {"Back",ct_Back},
273 {"ButtonFont",ct_ButtonFont},
274 {"ButtonInPointer",ct_ButtonInPointer},
275 {"ButtonInPointerBack",ct_ButtonInPointerBack},
276 {"ButtonInPointerFore",ct_ButtonInPointerFore},
277 {"ButtonPointer",ct_ButtonPointer},
278 {"ButtonPointerBack",ct_ButtonPointerBack},
279 {"ButtonPointerFore",ct_ButtonPointerFore},
280 {"Colorset",ct_Colorset},
281 {"Font",ct_Font},
282 {"Fore",ct_Fore},
283 {"InputFont",ct_InputFont},
284 {"InputPointer",ct_InputPointer},
285 {"InputPointerBack",ct_InputPointerBack},
286 {"InputPointerFore",ct_InputPointerFore},
287 {"ItemBack",ct_ItemBack},
288 {"ItemColorset",ct_ItemColorset},
289 {"ItemFore",ct_ItemFore},
290 {"Read",ct_Read},
291 {"TimeoutFont",ct_TimeoutFont}
294 /* If there were vars on the command line, do env var sustitution on
295 all input. */
296 static void FormVarsCheck(char **p)
298 if (CF.have_env_var) { /* if cmd line vars */
299 if (strlen(*p) + 200 > CF.expand_buffer_size) { /* fast and loose */
300 CF.expand_buffer_size = strlen(*p) + 2000; /* new size */
301 if (CF.expand_buffer) { /* already have one */
302 CF.expand_buffer = saferealloc(CF.expand_buffer, CF.expand_buffer_size);
303 } else { /* first time */
304 CF.expand_buffer = safemalloc(CF.expand_buffer_size);
307 strcpy(CF.expand_buffer,*p);
308 *p = CF.expand_buffer;
309 envExpand(*p,CF.expand_buffer_size); /* expand the command in place */
313 static void ParseDefaults(char *buf)
315 char *p;
316 struct CommandTable *e;
317 if (buf[strlen(buf)-1] == '\n') { /* if line ends with newline */
318 buf[strlen(buf)-1] = '\0'; /* strip off \n */
320 /* Accept commands beginning with "*FvwmFormDefault".
321 This is to make sure defaults are read first.
322 Note the hack w. bg_state. */
323 if (strncasecmp(buf, "*FvwmFormDefault", 16) == 0) {
324 p=buf+16;
325 FormVarsCheck(&p); /* do var substitution if called for */
326 e = FindToken(p,def_table,struct CommandTable);/* find cmd in table */
327 if (e != 0) { /* if its valid */
328 p=p+strlen(e->name); /* skip over name */
329 while (isspace((unsigned char)*p)) p++; /* skip whitespace */
330 e->function(p); /* call cmd processor */
331 bg_state = 'd'; /* stay in default state */
334 } /* end function */
337 static void ParseConfigLine(char *buf)
339 char *p;
340 struct CommandTable *e;
341 if (buf[strlen(buf)-1] == '\n') { /* if line ends with newline */
342 buf[strlen(buf)-1] = '\0'; /* strip off \n */
345 if (strncasecmp(buf, XINERAMA_CONFIG_STRING,
346 sizeof(XINERAMA_CONFIG_STRING)-1) == 0)
348 FScreenConfigureModule(buf + sizeof(XINERAMA_CONFIG_STRING)-1);
349 return;
351 if (strncasecmp(buf, "Colorset", 8) == 0) {
352 LoadColorset(&buf[8]);
353 return;
355 if (strncasecmp(buf, CatString3("*",module->name,0), module->namelen+1) != 0) {/* If its not for me */
356 return;
357 } /* Now I know its for me. */
358 p = buf+module->namelen+1; /* jump to end of my name */
359 /* at this point we have recognized "*FvwmForm" */
360 FormVarsCheck(&p);
361 e = FindToken(p,ct_table,struct CommandTable);/* find cmd in table */
362 if (e == 0) { /* if no match */
363 fprintf(stderr,"%s: unknown command: %s\n",module->name,buf);
364 return;
367 p=p+strlen(e->name); /* skip over name */
368 while (isspace((unsigned char)*p)) p++; /* skip whitespace */
370 FormVarsCheck(&p); /* do var substitution if called for */
372 e->function(p); /* call cmd processor */
373 return;
374 } /* end function */
376 /* Expands item array */
377 static void ExpandArray(Line *this_line)
379 if (this_line->n + 1 >= this_line->item_array_size) { /* no empty space */
380 this_line->item_array_size += ITEMS_PER_EXPANSION; /* get bigger */
381 this_line->items =
382 (Item **)saferealloc((void *)this_line->items,
383 (sizeof(Item *) * this_line->item_array_size));
384 } /* end array full */
387 /* Function to add an item to the current line */
388 static void AddToLine(Item *newItem)
390 ExpandArray(cur_line); /* expand item array if needed */
391 cur_line->items[cur_line->n++] = newItem; /* add to lines item array */
392 cur_line->size_x += newItem->header.size_x; /* incr lines width */
393 if (cur_line->size_y < newItem->header.size_y) { /* new item bigger */
394 cur_line->size_y = newItem->header.size_y; /* then line is bigger */
399 /* All the functions starting with "ct_" (command table) are called thru
400 their function pointers. Arg 1 is always the rest of the command. */
401 static void ct_ActivateOnPress(char *cp)
403 /* arg can be "on", "off", "0", 1", "true", "false", "" */
404 char option[6];
405 int i,j;
406 if (strlen(cp) > 5) {
407 fprintf(stderr,"%s: arg for ActivateOnPress (%s) too long\n",
408 module->name,cp);
409 return;
411 for (i=0,j=0;i<strlen(cp);i++) {
412 if (cp[i] != ' ') { /* remove any spaces */
413 option[j++]=tolower(cp[i]);
416 option[j]=0;
417 if (strcmp(option,"on") == 0
418 || strcmp(option,"true") == 0
419 || strcmp(option,"1") == 0
420 || (cp == 0 || strcmp(option,"")) == 0) {
421 CF.activate_on_press = 1;
422 } else if (strcmp(option,"off") == 0
423 || strcmp(option,"false") == 0
424 || strcmp(option,"0") == 0) {
425 CF.activate_on_press = 0;
426 } else {
427 fprintf(stderr,"%s: arg for ActivateOnPress (%s/%s) invalid\n",
428 module->name,option,cp);
431 static void ct_GrabServer(char *cp)
433 CF.grab_server = 1;
435 static void ct_WarpPointer(char *cp)
437 CF.warp_pointer = 1;
439 static void ct_Position(char *cp)
441 CF.have_geom = 1;
442 CF.gx = atoi(cp);
443 CF.xneg = 0;
444 if (CF.gx < 0)
446 CF.gx = -1 - CF.gx;
447 CF.xneg = 1;
449 while (!isspace((unsigned char)*cp)) cp++;
450 while (isspace((unsigned char)*cp)) cp++;
451 CF.gy = atoi(cp);
452 CF.yneg = 0;
453 if (CF.gy < 0)
455 CF.gy = -1 - CF.gy;
456 CF.yneg = 1;
458 myfprintf((stderr, "Position @ (%c%d%c%d)\n",
459 (CF.xneg)?'-':'+',CF.gx, (CF.yneg)?'-':'+',CF.gy));
461 static void ct_Geometry(char *cp)
463 int x = 0;
464 int y = 0;
465 int flags;
466 unsigned int dummy;
468 CF.gx = 0;
469 CF.gy = 0;
470 CF.xneg = 0;
471 CF.yneg = 0;
472 while (isspace(*cp))
473 cp++;
474 flags = FScreenParseGeometry(cp, &x, &y, &dummy, &dummy);
475 if (flags&XValue)
477 CF.have_geom = 1;
478 CF.gx = x;
479 CF.xneg = (flags&XNegative);
481 if (flags&YValue)
483 CF.have_geom = 1;
484 CF.gy = y;
485 CF.yneg = (flags&YNegative);
487 myfprintf((stderr, "Geometry @ (%c%d%c%d)\n",
488 (CF.xneg)?'-':'+',CF.gx, (CF.yneg)?'-':'+',CF.gy));
490 static void ct_Fore(char *cp)
492 if (color_names[c_fg])
493 free(color_names[c_fg]);
494 color_names[c_fg] = safestrdup(cp);
495 colorset = -1;
496 myfprintf((stderr, "ColorFore: %s\n", color_names[c_fg]));
498 static void ct_Back(char *cp)
500 if (color_names[c_bg])
501 free(color_names[c_bg]);
502 color_names[c_bg] = safestrdup(cp);
503 if (bg_state == 'd')
505 if (screen_background_color)
506 free(screen_background_color);
507 screen_background_color = safestrdup(color_names[c_bg]);
508 bg_state = 's'; /* indicate set by command */
510 colorset = -1;
511 myfprintf((stderr, "ColorBack: %s, screen background %s, bg_state %c\n",
512 color_names[c_bg],screen_background_color,(int)bg_state));
514 static void ct_Colorset(char *cp)
516 sscanf(cp, "%d", &colorset);
517 AllocColorset(colorset);
519 static void ct_ItemFore(char *cp)
521 if (color_names[c_item_fg])
522 free(color_names[c_item_fg]);
523 color_names[c_item_fg] = safestrdup(cp);
524 itemcolorset = -1;
525 myfprintf((stderr, "ColorItemFore: %s\n", color_names[c_item_fg]));
527 static void ct_ItemBack(char *cp)
529 if (color_names[c_item_bg])
530 free(color_names[c_item_bg]);
531 color_names[c_item_bg] = safestrdup(cp);
532 itemcolorset = -1;
533 myfprintf((stderr, "ColorItemBack: %s\n", color_names[c_item_bg]));
535 static void ct_ItemColorset(char *cp)
537 sscanf(cp, "%d", &itemcolorset);
538 AllocColorset(itemcolorset);
540 static void ct_Font(char *cp)
542 if (font_names[f_text])
543 free(font_names[f_text]);
544 CopyStringWithQuotes(&font_names[f_text], cp);
545 myfprintf((stderr, "Font: %s\n", font_names[f_text]));
547 static void ct_TimeoutFont(char *cp)
549 if (font_names[f_timeout])
550 free(font_names[f_timeout]);
551 CopyStringWithQuotes(&font_names[f_timeout], cp);
552 myfprintf((stderr, "TimeoutFont: %s\n", font_names[f_timeout]));
554 static void ct_ButtonFont(char *cp)
556 if (font_names[f_button])
557 free(font_names[f_button]);
558 CopyStringWithQuotes(&font_names[f_button], cp);
559 myfprintf((stderr, "ButtonFont: %s\n", font_names[f_button]));
561 static void ct_ButtonInPointer(char *cp)
563 int cursor;
564 cursor=fvwmCursorNameToIndex(cp);
565 if (cursor == -1) {
566 fprintf(stderr,"ButtonInPointer: invalid cursor name %s\n",cp);
567 } else {
568 CF.pointer[button_in_pointer] = XCreateFontCursor(dpy,cursor);
571 static void ct_ButtonPointer(char *cp)
573 int cursor;
574 cursor=fvwmCursorNameToIndex(cp);
575 if (cursor == -1) {
576 fprintf(stderr,"ButtonPointer: invalid cursor name %s\n",cp);
577 } else {
578 CF.pointer[button_pointer] = XCreateFontCursor(dpy,cursor);
581 static void ct_InputFont(char *cp)
583 if (font_names[f_input])
584 free(font_names[f_input]);
585 CopyStringWithQuotes(&font_names[f_input], cp);
586 myfprintf((stderr, "InputFont: %s\n", font_names[f_input]));
588 static void ct_InputPointer(char *cp)
590 int cursor;
591 cursor=fvwmCursorNameToIndex(cp);
592 if (cursor == -1) {
593 fprintf(stderr,"InputPointer: invalid cursor name %s\n",cp);
594 } else {
595 CF.pointer[input_pointer] = XCreateFontCursor(dpy,cursor);
598 /* process buttons using an index to the ___ array */
599 static void color_arg(Ptr_color *color_cell, char *color_name);
600 static void color_arg(Ptr_color *color_cell, char *color_name) {
601 if (color_name && *color_name) {
602 color_cell->pointer_color.pixel = GetColor(color_name);
603 color_cell->used=1;
607 /* arg is a color name, alloc the color */
608 static void ct_ButtonInPointerBack(char *cp) {
609 color_arg(&CF.p_c[button_in_back],cp);
611 static void ct_ButtonInPointerFore(char *cp) {
612 color_arg(&CF.p_c[button_in_fore],cp);
614 static void ct_ButtonPointerBack(char *cp) {
615 color_arg(&CF.p_c[button_back],cp);
617 static void ct_ButtonPointerFore(char *cp) {
618 color_arg(&CF.p_c[button_fore],cp);
620 static void ct_InputPointerBack(char *cp) {
621 color_arg(&CF.p_c[input_back],cp);
623 static void ct_InputPointerFore(char *cp) {
624 color_arg(&CF.p_c[input_fore],cp);
627 static void ct_Line(char *cp)
629 /* malloc new line */
630 cur_line->next = (struct _line *)safemalloc(sizeof(struct _line));
631 memset(cur_line->next, 0, sizeof(struct _line));
632 cur_line = cur_line->next; /* new current line */
633 cur_line->next = &root_line; /* new next ptr, (actually root) */
635 if (strncasecmp(cp, "left", 4) == 0)
636 cur_line->justify = L_LEFT;
637 else if (strncasecmp(cp, "right", 5) == 0)
638 cur_line->justify = L_RIGHT;
639 else if (strncasecmp(cp, "center", 6) == 0)
640 cur_line->justify = L_CENTER;
641 else
642 cur_line->justify = L_LEFTRIGHT;
644 /* Define an area on the form that contains the current
645 fvwm error message.
646 syntax: *FFMessage Length nn, Font fn, Fore color, Back color
647 len default is 70
648 font,fg.bg default to text.
651 static void ct_Message(char *cp)
653 AddItem();
654 bg_state = 'u'; /* indicate b/g color now used. */
655 item->type = I_TEXT;
656 /* Item now added to list of items, now it needs a pointer
657 to the correct DrawTable. */
658 AssignDrawTable(item);
659 item->header.name = "FvwmMessage"; /* No purpose to this? dje */
660 item->text.value = safemalloc(80); /* point at last error recvd */
661 item->text.n = 80;
662 strcpy(item->text.value,"A mix of chars. MM20"); /* 20 mixed width chars */
663 item->header.size_x = (FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
664 item->text.value,
665 item->text.n/4) * 4) + 2 * TEXT_SPC;
666 item->header.size_y = item->header.dt_ptr->dt_Ffont->height
667 + CF.padVText;
668 memset(item->text.value,' ',80); /* Clear it out */
669 myfprintf((stderr, "Message area [%d, %d]\n",
670 item->header.size_x, item->header.size_y));
671 AddToLine(item);
672 CF.last_error = item; /* save location of message item */
675 /* allocate colors and fonts needed */
676 static void CheckAlloc(Item *this_item,DrawTable *dt)
678 XGCValues xgcv;
679 int xgcv_mask = GCForeground;
681 if (dt->dt_used == 2) { /* fonts colors shadows */
682 return;
684 if (dt->dt_used == 0) { /* if nothing allocated */
685 dt->dt_colors[c_fg] = (colorset < 0)
686 ? GetColor(dt->dt_color_names[c_fg])
687 : Colorset[colorset].fg;
688 dt->dt_colors[c_bg] = (colorset < 0)
689 ? GetColor(dt->dt_color_names[c_bg])
690 : Colorset[colorset].bg;
692 xgcv.foreground = dt->dt_colors[c_fg];
693 xgcv.background = dt->dt_colors[c_bg];
694 if (dt->dt_Ffont->font != NULL)
696 xgcv_mask |= GCFont;
697 xgcv.font = dt->dt_Ffont->font->fid;
699 xgcv_mask |= GCBackground;
700 dt->dt_GC = fvwmlib_XCreateGC(dpy, CF.frame, xgcv_mask, &xgcv);
702 dt->dt_used = 1; /* fore/back font allocated */
704 if (this_item->type == I_TEXT
705 || this_item->type == I_TIMEOUT) { /* If no shadows needed */
706 return;
708 dt->dt_colors[c_item_fg] = (itemcolorset < 0)
709 ? GetColor(dt->dt_color_names[c_item_fg])
710 : Colorset[itemcolorset].fg;
711 dt->dt_colors[c_item_bg] = (itemcolorset < 0)
712 ? GetColor(dt->dt_color_names[c_item_bg])
713 : Colorset[itemcolorset].bg;
714 xgcv.foreground = dt->dt_colors[c_item_fg];
715 xgcv.background = dt->dt_colors[c_item_bg];
716 xgcv_mask = GCForeground;
717 if (dt->dt_Ffont->font != NULL)
719 xgcv_mask |= GCFont;
720 xgcv.font = dt->dt_Ffont->font->fid;
722 dt->dt_item_GC = fvwmlib_XCreateGC(dpy, CF.frame, xgcv_mask, &xgcv);
723 if (Pdepth < 2) {
724 dt->dt_colors[c_itemlo] = PictureBlackPixel();
725 dt->dt_colors[c_itemhi] = PictureWhitePixel();
726 } else {
727 dt->dt_colors[c_itemlo] = (itemcolorset < 0)
728 ? GetShadow(dt->dt_colors[c_item_bg])
729 : Colorset[itemcolorset].shadow;
730 dt->dt_colors[c_itemhi] = (itemcolorset < 0)
731 ? GetHilite(dt->dt_colors[c_item_bg])
732 : Colorset[itemcolorset].hilite;
734 dt->dt_used = 2; /* fully allocated */
738 /* Input is the current item. Assign a drawTable entry to it. */
739 static void AssignDrawTable(Item *adt_item)
741 DrawTable *find_dt, *last_dt;
742 char *match_text_fore;
743 char *match_text_back;
744 char *match_item_fore;
745 char *match_item_back;
746 char *match_font;
747 DrawTable *new_dt; /* pointer to a new one */
749 match_text_fore = color_names[c_fg];
750 match_text_back = color_names[c_bg];
751 match_item_fore = color_names[c_item_fg];
752 match_item_back = color_names[c_item_bg];
753 if (adt_item->type == I_TEXT) {
754 match_font = font_names[f_text];
755 } else if (adt_item->type == I_TIMEOUT) {
756 match_font = font_names[f_timeout];
757 } else if (adt_item->type == I_INPUT) {
758 match_font = font_names[f_input];
759 } else {
760 match_font = font_names[f_button]; /* choices same as buttons */
762 last_dt = 0;
763 for (find_dt = CF.roots_dt; /* start at front */
764 find_dt != 0; /* until end */
765 find_dt = find_dt->dt_next) { /* follow next pointer */
766 last_dt = find_dt;
767 if ((strcasecmp(match_text_fore,find_dt->dt_color_names[c_fg]) == 0) &&
768 (strcasecmp(match_text_back,find_dt->dt_color_names[c_bg]) == 0) &&
769 (strcasecmp(match_item_fore,find_dt->dt_color_names[c_item_fg]) == 0) &&
770 (strcasecmp(match_item_back,find_dt->dt_color_names[c_item_bg]) == 0) &&
771 (strcasecmp(match_font,find_dt->dt_font_name) == 0)) { /* Match */
772 adt_item->header.dt_ptr = find_dt; /* point item to drawtable */
773 return; /* done */
774 } /* end match */
775 } /* end all drawtables checked, no match */
777 /* Time to add a DrawTable */
778 /* get one */
779 new_dt = (struct _drawtable *)safemalloc(sizeof(struct _drawtable));
780 memset(new_dt, 0, sizeof(struct _drawtable));
781 new_dt->dt_next = 0; /* new end of list */
782 if (CF.roots_dt == 0) { /* If first entry in list */
783 CF.roots_dt = new_dt; /* set root pointer */
784 } else { /* not first entry */
785 last_dt->dt_next = new_dt; /* link old to new */
788 new_dt->dt_font_name = safestrdup(match_font);
789 new_dt->dt_color_names[c_fg] = safestrdup(match_text_fore);
790 new_dt->dt_color_names[c_bg] = safestrdup(match_text_back);
791 new_dt->dt_color_names[c_item_fg] = safestrdup(match_item_fore);
792 new_dt->dt_color_names[c_item_bg] = safestrdup(match_item_back);
793 new_dt->dt_used = 0; /* show nothing allocated */
794 new_dt->dt_Ffont = FlocaleLoadFont(dpy, new_dt->dt_font_name, module->name);
795 FlocaleAllocateWinString(&new_dt->dt_Fstr);
797 myfprintf((stderr,"Created drawtable with %s %s %s %s %s\n",
798 new_dt->dt_color_names[c_fg], new_dt->dt_color_names[c_bg],
799 new_dt->dt_color_names[c_item_fg],
800 new_dt->dt_color_names[c_item_bg],
801 new_dt->dt_font_name));
802 adt_item->header.dt_ptr = new_dt; /* point item to new drawtable */
805 /* input/output is global "item" - currently allocated last item */
806 static void AddItem(void)
808 Item *save_item;
809 save_item = (Item *)item; /* save current item */
810 item = (Item *)safecalloc(sizeof(Item),1); /* get a new item */
811 if (save_item == 0) { /* if first item */
812 root_item_ptr = item; /* save root item */
813 } else { /* else not first item */
814 save_item->header.next = item; /* link prior to new */
818 static void ct_Text(char *cp)
820 /* syntax: *FFText "<text>" */
821 AddItem();
822 bg_state = 'u'; /* indicate b/g color now used. */
823 item->type = I_TEXT;
824 /* Item now added to list of items, now it needs a pointer
825 to the correct DrawTable. */
826 AssignDrawTable(item);
827 item->header.name = "";
828 if (*cp == '\"')
829 item->text.value = CopyQuotedString(++cp);
830 else
831 item->text.value = "";
832 item->text.n = strlen(item->text.value);
834 item->header.size_x = FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
835 item->text.value,
836 item->text.n) + 2 * TEXT_SPC;
837 item->header.size_y = item->header.dt_ptr->dt_Ffont->height
838 + CF.padVText;
839 myfprintf((stderr, "Text \"%s\" [%d, %d]\n", item->text.value,
840 item->header.size_x, item->header.size_y));
841 AddToLine(item);
843 /* Set the form's title.
844 The default is the aliasname.
845 If there is no quoted string, create a blank title. */
846 static void ct_Title(char *cp)
848 /* syntax: *FFTitle "<text>" */
849 if (*cp == '\"')
850 CF.title = CopyQuotedString(++cp);
851 else
852 CF.title = "";
853 myfprintf((stderr, "Title \"%s\"\n", CF.title));
855 static void ct_Timeout(char *cp)
857 /* syntax: *FFTimeout seconds <Command> "Text" */
858 char *tmpcp, *tmpbuf;
860 if (timer != NULL) {
861 fprintf(stderr,"Only one timeout per form allowed, skipped %s.\n",cp);
862 return;
864 AddItem();
865 bg_state = 'u'; /* indicate b/g color now used. */
866 item->type = I_TIMEOUT;
867 /* Item now added to list of items, now it needs a pointer
868 to the correct DrawTable. */
869 AssignDrawTable(item);
870 item->header.name = "";
872 item->timeout.timeleft = atoi(cp);
873 if (item->timeout.timeleft < 0)
875 item->timeout.timeleft = 0;
877 else if (item->timeout.timeleft > 99999)
879 item->timeout.timeleft = 99999;
881 timer = item;
883 while (*cp && *cp != '\n' && !isspace((unsigned char)*cp)) cp++;
884 /* skip timeout */
885 while (*cp && *cp != '\n' && isspace((unsigned char)*cp)) cp++;
886 /* move up to command */
888 if (!*cp || *cp == '\n') {
889 fprintf(stderr,"Improper arguments specified for FvwmForm Timeout.\n");
890 return;
893 if (*cp == '\"') {
894 item->timeout.command = CopyQuotedString(++cp);
895 /* skip over the whole quoted string to continue parsing */
896 cp += strlen(item->timeout.command) + 1;
898 else {
899 tmpbuf = safestrdup(cp);
900 tmpcp = tmpbuf;
901 while (!isspace((unsigned char)*tmpcp)) tmpcp++;
902 *tmpcp = '\0'; /* cutoff command at first word */
903 item->timeout.command = safestrdup(tmpbuf);
904 free(tmpbuf);
905 while (!isspace((unsigned char)*cp)) cp++; /* move past command again */
908 while (*cp && *cp != '\n' && isspace((unsigned char)*cp)) cp++;
909 /* move up to next arg */
911 if (!*cp || *cp == '\n') {
912 fprintf(stderr,"Improper arguments specified for FvwmForm Timeout.\n");
913 return;
916 if (*cp == '\"') {
917 item->timeout.text = CopyQuotedString(++cp);
918 } else
919 item->timeout.text = "";
920 item->timeout.len = strlen(item->timeout.text);
922 item->header.size_x = FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
923 item->timeout.text,
924 item->timeout.len) + 2 * TEXT_SPC;
925 item->header.size_y = item->header.dt_ptr->dt_Ffont->height
926 + CF.padVText;
927 myfprintf((stderr, "Timeout %d \"%s\" [%d, %d]\n", item->timeout.timeleft,
928 item->timeout.text, item->header.size_x, item->header.size_y));
929 AddToLine(item);
931 static void ct_padVText(char *cp)
933 /* syntax: *FFText "<padVText pixels>" */
934 CF.padVText = atoi(cp);
935 myfprintf((stderr, "Text Vertical Padding %d\n", CF.padVText));
937 static void ct_Input(char *cp)
939 int j;
940 /* syntax: *FFInput <name> <size> "<init_value>" */
941 AddItem();
942 item->type = I_INPUT;
943 AssignDrawTable(item);
944 item->header.name = CopySolidString(cp);
945 cp += strlen(item->header.name);
946 while (isspace((unsigned char)*cp)) cp++;
947 item->input.size = atoi(cp);
948 while (!isspace((unsigned char)*cp)) cp++;
949 while (isspace((unsigned char)*cp)) cp++;
950 item->input.init_value = safestrdup(""); /* init */
951 if (*cp == '\"') {
952 free(item->input.init_value);
953 item->input.init_value = CopyQuotedString(++cp);
955 item->input.blanks = (char *)safemalloc(item->input.size);
956 for (j = 0; j < item->input.size; j++)
957 item->input.blanks[j] = ' ';
958 item->input.buf = strlen(item->input.init_value) + 1;
959 item->input.value = (char *)safemalloc(item->input.buf);
960 item->input.value[0] = 0; /* avoid reading unitialized data */
962 item->header.size_x = item->header.dt_ptr->dt_Ffont->max_char_width
963 * item->input.size + 2 * TEXT_SPC + 2 * BOX_SPC;
964 item->header.size_y = item->header.dt_ptr->dt_Ffont->height
965 + 3 * TEXT_SPC + 2 * BOX_SPC;
966 myfprintf((stderr,"Input size_y is %d\n",item->header.size_y));
968 if (CF.cur_input == 0) { /* first input field */
969 item->input.next_input = item; /* ring, next field is first field */
970 item->input.prev_input = item; /* ring, prev field is first field */
971 CF.first_input = item; /* save loc of first item */
972 } else { /* not first field */
973 CF.cur_input->input.next_input = item; /* old next ptr point to this item */
974 item->input.prev_input = CF.cur_input; /* current items prev is old item */
975 item->input.next_input = CF.first_input; /* next is first item */
976 CF.first_input->input.prev_input = item; /* prev in first is this item */
978 CF.cur_input = item; /* new current input item */
979 myfprintf((stderr, "Input, %s, [%d], \"%s\"\n", item->header.name,
980 item->input.size, item->input.init_value));
981 AddToLine(item);
983 static void ct_Read(char *cp)
985 /* syntax: *FFRead 0 | 1 */
986 myfprintf((stderr,"Got read command, char is %c\n",(int)*cp));
987 endDefaultsRead = *cp; /* copy whatever it is */
989 /* read and save vars from a file for later use in form
990 painting.
992 static void ct_UseData(char *cp)
994 /* syntax: *FFUseData filename cmd_prefix */
995 CF.file_to_read = CopySolidString(cp);
996 if (*CF.file_to_read == 0) {
997 fprintf(stderr,"UseData command missing first arg, File to read\n");
998 return;
1000 cp += strlen(CF.file_to_read);
1001 while (isspace((unsigned char)*cp)) cp++;
1002 CF.leading = CopySolidString(cp);
1003 if (*CF.leading == 0) {
1004 fprintf(stderr,"UseData command missing second arg, Leading\n");
1005 CF.file_to_read = 0; /* stop read */
1006 return;
1008 /* Cant do the actual reading of the data file here,
1009 we are already in a readconfig loop. */
1011 static void ReadFormData(void)
1013 int leading_len;
1014 char *line_buf; /* ptr to curr config line */
1015 char cmd_buffer[200];
1016 sprintf(cmd_buffer,"read %s Quiet",CF.file_to_read);
1017 SendText(Channel,cmd_buffer,0); /* read data */
1018 leading_len = strlen(CF.leading);
1019 InitGetConfigLine(Channel, CF.leading); /* ask for certain lines */
1020 while (GetConfigLine(Channel,&line_buf),line_buf) { /* while there is some */
1021 if (strncasecmp(line_buf, CF.leading, leading_len) == 0) { /* leading = */
1022 if (line_buf[strlen(line_buf)-1] == '\n') { /* if line ends with nl */
1023 line_buf[strlen(line_buf)-1] = '\0'; /* strip off \n */
1025 PutDataInForm(line_buf+leading_len); /* pass arg, space, value */
1026 } /* end match on arg 2, "leading" */
1027 } /* end while there is config data */
1028 free(CF.file_to_read); /* dont need it anymore */
1029 free(CF.leading);
1030 CF.file_to_read = 0;
1031 CF.leading = 0;
1034 Input is a line with varname space value.
1035 Search form for matching input fields and set values.
1036 If you don't get a match on an input field, try a choice.
1038 static void PutDataInForm(char *cp)
1040 char *var_name;
1041 char *var_value;
1042 int var_len, i;
1043 Item *item;
1044 Line *line;
1046 var_name = CopySolidString(cp); /* var */
1047 if (*var_name == 0) {
1048 return;
1050 cp += strlen(var_name);
1051 while (isspace((unsigned char)*cp)) cp++;
1052 var_value = cp;
1053 if (CF.cur_input != 0) {
1054 item = CF.cur_input;
1055 do {
1056 if (strcasecmp(var_name,item->header.name) == 0) {
1057 var_len = strlen(cp);
1058 if (item->input.init_value)
1059 free(item->input.init_value);
1060 item->input.init_value = safemalloc(var_len+1);
1061 strcpy(item->input.init_value,cp); /* new initial value in field */
1062 if (item->input.value)
1063 free(item->input.value);
1064 item->input.buf = var_len+1;
1065 item->input.value = safemalloc(item->input.buf);
1066 strcpy(item->input.value,cp); /* new value in field */
1067 free(var_name); /* goto's have their uses */
1068 return;
1070 item=item->input.next_input; /* next input field */
1071 } while (item != CF.cur_input); /* while not end of ring */
1073 /* You have a matching line, but it doesn't match an input
1074 field. What to do? I know, try a choice. */
1075 line = &root_line; /* start at first line */
1076 do { /* for all lines */
1077 for (i = 0; i < line->n; i++) { /* all items on line */
1078 item = line->items[i];
1079 if (item->type == I_CHOICE) { /* choice is good */
1080 if (strcasecmp(var_name,item->header.name) == 0) { /* match */
1081 item->choice.init_on = 0;
1082 if (strncasecmp(cp, "on", 2) == 0) {
1083 item->choice.init_on = 1; /* set default state */
1084 free(var_name); /* goto's have their uses */
1085 return;
1089 } /* end all items in line */
1090 line = line->next; /* go to next line */
1091 } while (line != &root_line); /* do all lines */
1092 /* You have a matching line, it didn't match an input field,
1093 and it didn't match a choice. I've got it, it may match a
1094 selection, in which case we should use the value to
1095 set the choices! */
1096 for (item = root_item_ptr; item != 0;
1097 item = item->header.next) {/* all items */
1098 if (item->type == I_SELECT) { /* selection is good */
1099 if (strcasecmp(var_name,item->header.name) == 0) { /* match */
1100 /* Now find the choices for this selection... */
1101 Item *choice_ptr;
1102 for (i = 0;
1103 i<item->selection.n;
1104 i++) {
1105 choice_ptr=item->selection.choices[i];
1106 /* if the choice value matches the selection */
1107 if (strcmp(choice_ptr->choice.value,var_value) == 0) {
1108 choice_ptr->choice.init_on = 1;
1109 } else {
1110 choice_ptr->choice.init_on = 0;
1112 } /* end all choices */
1113 } /* end match */
1114 } /* end selection */
1115 } /* end all items */
1116 free(var_name); /* not needed now */
1118 static void ct_Selection(char *cp)
1120 /* syntax: *FFSelection <name> single | multiple */
1121 AddItem();
1122 cur_sel = item; /* save ptr as cur_sel */
1123 cur_sel->type = I_SELECT;
1124 cur_sel->header.name = CopySolidString(cp);
1125 cp += strlen(cur_sel->header.name);
1126 while (isspace((unsigned char)*cp)) cp++;
1127 if (strncasecmp(cp, "multiple", 8) == 0)
1128 cur_sel->selection.key = IS_MULTIPLE;
1129 else
1130 cur_sel->selection.key = IS_SINGLE;
1132 static void ct_Choice(char *cp)
1134 /* syntax: *FFChoice <name> <value> [on | _off_] ["<text>"] */
1135 /* This next edit is a liitle weak, the selection should be right
1136 before the choice. At least a core dump is avoided. */
1137 if (cur_sel == 0) { /* need selection for a choice */
1138 fprintf(stderr,"%s: Need selection for choice %s\n",
1139 module->name, cp);
1140 return;
1142 bg_state = 'u'; /* indicate b/g color now used. */
1143 AddItem();
1144 item->type = I_CHOICE;
1145 AssignDrawTable(item);
1146 item->header.name = CopySolidString(cp);
1147 cp += strlen(item->header.name);
1148 while (isspace((unsigned char)*cp)) cp++;
1149 item->choice.value = CopySolidString(cp);
1150 cp += strlen(item->choice.value);
1151 while (isspace((unsigned char)*cp)) cp++;
1152 if (strncasecmp(cp, "on", 2) == 0)
1153 item->choice.init_on = 1;
1154 else
1155 item->choice.init_on = 0;
1156 while (!isspace((unsigned char)*cp)) cp++;
1157 while (isspace((unsigned char)*cp)) cp++;
1158 if (*cp == '\"')
1159 item->choice.text = CopyQuotedString(++cp);
1160 else
1161 item->choice.text = "";
1162 item->choice.n = strlen(item->choice.text);
1163 item->choice.sel = cur_sel;
1165 if (cur_sel->selection.choices_array_count
1166 <= cur_sel->selection.n) { /* no room */
1167 cur_sel->selection.choices_array_count += CHOICES_PER_SEL_EXPANSION;
1168 cur_sel->selection.choices =
1169 (Item **)saferealloc((void *)cur_sel->selection.choices,
1170 sizeof(Item *) *
1171 cur_sel->selection.choices_array_count); /* expand */
1174 cur_sel->selection.choices[cur_sel->selection.n++] = item;
1175 item->header.size_y = item->header.dt_ptr->dt_Ffont->height
1176 + 2 * TEXT_SPC;
1177 /* this is weird, the x dimension is the sum of the height and width? */
1178 item->header.size_x = item->header.dt_ptr->dt_Ffont->height
1179 + 4 * TEXT_SPC +
1180 FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
1181 item->choice.text, item->choice.n);
1182 myfprintf((stderr, "Choice %s, \"%s\", [%d, %d]\n", item->header.name,
1183 item->choice.text, item->header.size_x, item->header.size_y));
1184 AddToLine(item);
1186 static void ct_Button(char *cp)
1188 /* syntax: *FFButton continue | restart | quit "<text>" */
1189 AddItem();
1190 item->type = I_BUTTON;
1191 AssignDrawTable(item);
1192 item->header.name = "";
1193 if (strncasecmp(cp, "restart", 7) == 0)
1194 item->button.key = IB_RESTART;
1195 else if (strncasecmp(cp, "quit", 4) == 0)
1196 item->button.key = IB_QUIT;
1197 else
1198 item->button.key = IB_CONTINUE;
1199 while (!isspace((unsigned char)*cp)) cp++;
1200 while (isspace((unsigned char)*cp)) cp++;
1201 if (*cp == '\"') {
1202 item->button.text = CopyQuotedString(++cp);
1203 cp += strlen(item->button.text) + 1;
1204 while (isspace((unsigned char)*cp)) cp++;
1205 } else
1206 item->button.text = "";
1207 if (*cp == '^')
1208 item->button.keypress = *(++cp) - '@';
1209 else if (*cp == 'F')
1210 item->button.keypress = 256 + atoi(++cp);
1211 else
1212 item->button.keypress = -1;
1213 item->button.len = strlen(item->button.text);
1214 item->header.size_y = item->header.dt_ptr->dt_Ffont->height
1215 + 2 * TEXT_SPC + 2 * BOX_SPC;
1216 item->header.size_x = 2 * TEXT_SPC + 2 * BOX_SPC
1217 + FlocaleTextWidth(item->header.dt_ptr->dt_Ffont, item->button.text,
1218 item->button.len);
1219 AddToLine(item);
1220 cur_button = item;
1221 myfprintf((stderr,"Created button, fore %s, bg %s, text %s\n",
1222 item->header.dt_ptr->dt_color_names[c_item_fg],
1223 item->header.dt_ptr->dt_color_names[c_item_bg],
1224 item->button.text));
1226 static void ct_Command(char *cp)
1228 /* syntax: *FFCommand <command> */
1229 if (cur_button->button.button_array_size <= cur_button->button.n)
1231 cur_button->button.button_array_size += BUTTON_COMMAND_EXPANSION;
1232 cur_button->button.commands =
1233 (char **)saferealloc((void *)cur_button->button.commands,
1234 sizeof(char *) *
1235 cur_button->button.button_array_size);
1237 cur_button->button.commands[cur_button->button.n++] = safestrdup(cp);
1240 /* End of ct_ routines */
1242 /* Init constants with values that can be freed later. */
1243 static void InitConstants(void) {
1244 color_names[0]=safestrdup("Light Gray");
1245 color_names[1]=safestrdup("Black");
1246 color_names[2]=safestrdup("Gray50");
1247 color_names[3]=safestrdup("Wheat");
1248 font_names[0]=safestrdup("8x13bold");
1249 font_names[1]=safestrdup("8x13bold");
1250 font_names[2]=safestrdup("8x13bold");
1251 font_names[3]=safestrdup("8x13bold");
1252 screen_background_color=safestrdup("Light Gray");
1253 CF.p_c[input_fore].pointer_color.pixel = PictureWhitePixel();
1254 CF.p_c[input_back].pointer_color.pixel = PictureBlackPixel();
1255 CF.p_c[button_fore].pointer_color.pixel = PictureBlackPixel();
1256 CF.p_c[button_back].pointer_color.pixel = PictureWhitePixel();
1257 /* The in pointer is the reverse of the hover pointer. */
1258 CF.p_c[button_in_fore].pointer_color.pixel = PictureWhitePixel();
1259 CF.p_c[button_in_back].pointer_color.pixel = PictureBlackPixel();
1262 /* read the configuration file */
1263 static void ReadDefaults(void)
1265 char *line_buf; /* ptr to curr config line */
1267 /* default button is for initial functions */
1268 cur_button = &CF.def_button;
1269 CF.def_button.button.key = IB_CONTINUE;
1272 * Reading .FvwmFormDefault for every form seems slow.
1274 * This next bit puts a command at the end of the module command
1275 * queue in fvwm that indicates whether the file has to be read.
1277 * Read defaults looking for "*FvwmFormDefaultRead"
1278 * if not there, send read,
1279 * then "*FvwmFormDefaultRead y",
1280 * then look thru defaults again.
1281 * The customization dialog sends "*FvwmFormDefaultRead n"
1282 * to start over.
1284 InitGetConfigLine(Channel,"*FvwmFormDefault");
1285 while (GetConfigLine(Channel,&line_buf),line_buf) { /* get config from fvwm */
1286 ParseDefaults(line_buf); /* process default config lines 1st */
1288 if (endDefaultsRead == 'y') { /* defaults read already */
1289 myfprintf((stderr,"Defaults read, no need to read file.\n"));
1290 return;
1291 } /* end defaults read already */
1292 SendText(Channel,"read .FvwmForm Quiet",0); /* read default config */
1293 SendText(Channel,"*FvwmFormDefaultRead y",0); /* remember you read it */
1295 InitGetConfigLine(Channel,"*FvwmFormDefault");
1296 while (GetConfigLine(Channel,&line_buf),line_buf) { /* get config from fvwm */
1297 ParseDefaults(line_buf); /* process default config lines 1st */
1299 } /* done */
1301 static void ReadConfig(void)
1303 char *line_buf; /* ptr to curr config line */
1305 InitGetConfigLine(Channel,CatString3("*",module->name,0));
1306 while (GetConfigLine(Channel,&line_buf),line_buf) { /* get config from fvwm */
1307 ParseConfigLine(line_buf); /* process config lines */
1309 } /* done */
1311 /* After this config is read, figure it out */
1312 static void MassageConfig(void)
1314 int i, extra;
1315 Line *line; /* for scanning form lines */
1317 if (CF.file_to_read) { /* if theres a data file to read */
1318 ReadFormData(); /* go read it */
1320 /* get the geometry right */
1321 CF.max_width = 0;
1322 CF.total_height = ITEM_VSPC;
1323 line = &root_line; /* start at first line */
1324 do { /* for all lines */
1325 for (i = 0; i < line->n; i++) {
1326 line->items[i]->header.pos_y = CF.total_height;
1327 if (line->items[i]->header.size_y < line->size_y)
1328 line->items[i]->header.pos_y +=
1329 (line->size_y - line->items[i]->header.size_y) / 2 + 1 ;
1330 } /* end all items in line */
1331 CF.total_height += ITEM_VSPC + line->size_y;
1332 line->size_x += (line->n + 1) * ITEM_HSPC;
1333 if (line->size_x > CF.max_width)
1334 CF.max_width = line->size_x;
1335 line = line->next; /* go to next line */
1336 } while (line != &root_line); /* do all lines */
1337 do { /* note, already back at root_line */
1338 int width;
1339 switch (line->justify) {
1340 case L_LEFT:
1341 width = ITEM_HSPC;
1342 for (i = 0; i < line->n; i++) {
1343 line->items[i]->header.pos_x = width;
1344 width += ITEM_HSPC + line->items[i]->header.size_x;
1346 break;
1347 case L_RIGHT:
1348 width = CF.max_width - line->size_x + ITEM_HSPC;
1349 for (i = 0; i < line->n; i++) {
1350 line->items[i]->header.pos_x = width;
1351 width += ITEM_HSPC + line->items[i]->header.size_x;
1353 break;
1354 case L_CENTER:
1355 width = (CF.max_width - line->size_x) / 2 + ITEM_HSPC;
1356 for (i = 0; i < line->n; i++) {
1357 line->items[i]->header.pos_x = width;
1358 myfprintf((stderr, "Line Item[%d] @ (%d, %d)\n", i,
1359 line->items[i]->header.pos_x, line->items[i]->header.pos_y));
1360 width += ITEM_HSPC + line->items[i]->header.size_x;
1362 break;
1363 case L_LEFTRIGHT:
1364 /* count the number of inputs on the line - the extra space will be
1365 * shared amongst these if there are any, otherwise it will be added
1366 * as space in between the elements
1368 extra = 0 ;
1369 for (i = 0 ; i < line->n ; i++) {
1370 if (line->items[i]->type == I_INPUT)
1371 extra++ ;
1373 if (extra == 0) {
1374 if (line->n < 2) { /* same as L_CENTER */
1375 width = (CF.max_width - line->size_x) / 2 + ITEM_HSPC;
1376 for (i = 0; i < line->n; i++) {
1377 line->items[i]->header.pos_x = width;
1378 width += ITEM_HSPC + line->items[i]->header.size_x;
1380 } else {
1381 extra = (CF.max_width - line->size_x) / (line->n - 1);
1382 width = ITEM_HSPC;
1383 for (i = 0; i < line->n; i++) {
1384 line->items[i]->header.pos_x = width;
1385 width += ITEM_HSPC + line->items[i]->header.size_x + extra;
1388 } else {
1389 extra = (CF.max_width - line->size_x) / extra ;
1390 width = ITEM_HSPC ;
1391 for (i = 0 ; i < line->n ; i++) {
1392 line->items[i]->header.pos_x = width ;
1393 if (line->items[i]->type == I_INPUT)
1394 line->items[i]->header.size_x += extra ;
1395 width += ITEM_HSPC + line->items[i]->header.size_x ;
1398 break;
1400 line = line->next; /* go to next line */
1401 } while (line != &root_line); /* do all lines */
1404 /* reset all the values (also done on first display) */
1405 static void Restart(void)
1407 Item *item;
1409 CF.cur_input = NULL;
1410 CF.abs_cursor = CF.rel_cursor = 0;
1411 for (item = root_item_ptr; item != 0;
1412 item = item->header.next) {/* all items */
1413 switch (item->type) {
1414 case I_INPUT:
1415 if (!CF.cur_input)
1416 CF.cur_input = item;
1418 /* save old input values in a recall ring. */
1419 if (item->input.value && item->input.value[0] != 0) { /* ? to save */
1420 if (item->input.value_history_ptr == 0) { /* no history yet */
1421 item->input.value_history_ptr =
1422 (char **)safecalloc(sizeof(char *), 50);
1423 item->input.value_history_ptr[0] = safestrdup(item->input.value);
1424 item->input.value_history_count = 1; /* next insertion point */
1425 myfprintf((stderr,"Initial save of %s in slot 0\n",
1426 item->input.value_history_ptr[0]));
1427 } else { /* we have a history */
1428 int prior;
1429 prior = item->input.value_history_count - 1;
1430 if (prior < 0) {
1431 for (prior = VH_SIZE - 1;
1432 CF.cur_input->input.value_history_ptr[prior] == 0;
1433 --prior); /* find last used slot */
1435 myfprintf((stderr,"Prior is %d, compare %s to %s\n",
1436 prior, item->input.value,
1437 item->input.value_history_ptr[prior]));
1439 if ( strcmp(item->input.value, item->input.value_history_ptr[prior])
1440 != 0) { /* different value */
1441 if (item->input.value_history_ptr[item->input.value_history_count])
1443 free(item->input.value_history_ptr[
1444 item->input.value_history_count]);
1445 myfprintf((stderr,"Freeing old item in slot %d\n",
1446 item->input.value_history_count));
1448 item->input.value_history_ptr[item->input.value_history_count] =
1449 safestrdup(item->input.value); /* save value ptr in array */
1450 myfprintf((stderr,"Save of %s in slot %d\n",
1451 item->input.value,
1452 item->input.value_history_count));
1454 /* leave count pointing at the next insertion point. */
1455 if (item->input.value_history_count < VH_SIZE - 1) { /* not full */
1456 ++item->input.value_history_count; /* next slot */
1457 } else {
1458 item->input.value_history_count = 0; /* wrap around */
1460 } /* end something different */
1461 } /* end have a history */
1462 myfprintf((stderr,"New history yankat %d\n",
1463 item->input.value_history_yankat));
1464 } /* end something to save */
1465 item->input.value_history_yankat = item->input.value_history_count;
1466 item->input.n = strlen(item->input.init_value);
1467 strcpy(item->input.value, item->input.init_value);
1468 item->input.left = 0;
1469 break;
1470 case I_CHOICE:
1471 item->choice.on = item->choice.init_on;
1472 break;
1477 /* redraw the frame */
1478 void RedrawFrame(XEvent *pev)
1480 Item *item;
1481 Region region = None;
1483 Bool clear = False;
1484 if (FftSupport)
1486 item = root_item_ptr;
1487 while(item != 0 && !clear)
1489 if ((item->type == I_TEXT || item->type == I_CHOICE) &&
1490 item->header.dt_ptr->dt_Ffont->fftf.fftfont != NULL)
1491 clear = True;
1492 item = item->header.next;
1494 if (clear && pev)
1496 XClearArea(
1497 dpy, CF.frame,
1498 pev->xexpose.x, pev->xexpose.y,
1499 pev->xexpose.width, pev->xexpose.height,
1500 False);
1502 else
1504 XClearWindow(dpy, CF.frame);
1507 if (pev)
1509 XRectangle r;
1511 r.x = pev->xexpose.x;
1512 r.y = pev->xexpose.y;
1513 r.width = pev->xexpose.width;
1514 r.height = pev->xexpose.height;
1515 region = XCreateRegion();
1516 XUnionRectWithRegion (&r, region, region);
1518 for (item = root_item_ptr; item != 0;
1519 item = item->header.next) { /* all items */
1520 DrawTable *dt_ptr = item->header.dt_ptr;
1522 if (dt_ptr && dt_ptr->dt_Fstr)
1524 if (region)
1526 dt_ptr->dt_Fstr->flags.has_clip_region = True;
1527 dt_ptr->dt_Fstr->clip_region = region;
1529 else
1531 dt_ptr->dt_Fstr->flags.has_clip_region = False;
1534 switch (item->type) {
1535 case I_TEXT:
1536 RedrawText(item);
1537 break;
1538 case I_TIMEOUT:
1539 RedrawTimeout(item);
1540 break;
1541 case I_CHOICE:
1542 dt_ptr->dt_Fstr->win = CF.frame;
1543 dt_ptr->dt_Fstr->gc = dt_ptr->dt_GC;
1544 dt_ptr->dt_Fstr->str = item->choice.text;
1545 dt_ptr->dt_Fstr->x = item->header.pos_x
1546 + TEXT_SPC + item->header.size_y;
1547 dt_ptr->dt_Fstr->y = item->header.pos_y
1548 + TEXT_SPC + dt_ptr->dt_Ffont->ascent;
1549 dt_ptr->dt_Fstr->len = item->choice.n;
1550 dt_ptr->dt_Fstr->flags.has_colorset = False;
1551 if (itemcolorset >= 0)
1553 dt_ptr->dt_Fstr->colorset =
1554 &Colorset[itemcolorset];
1555 dt_ptr->dt_Fstr->flags.has_colorset
1556 = True;
1558 FlocaleDrawString(dpy,
1559 dt_ptr->dt_Ffont,
1560 dt_ptr->dt_Fstr,
1561 FWS_HAVE_LENGTH);
1562 break;
1564 if (dt_ptr && dt_ptr->dt_Fstr)
1566 dt_ptr->dt_Fstr->flags.has_clip_region = False;
1569 if (region)
1571 XDestroyRegion(region);
1575 void RedrawText(Item *item)
1577 char *p;
1579 CheckAlloc(item,item->header.dt_ptr); /* alloc colors and fonts needed */
1580 item->header.dt_ptr->dt_Fstr->len = item->text.n;
1581 if ((p = memchr(item->text.value, '\0', item->header.dt_ptr->dt_Fstr->len))
1582 != NULL)
1583 item->header.dt_ptr->dt_Fstr->len = p - item->text.value;
1584 item->header.dt_ptr->dt_Fstr->win = CF.frame;
1585 item->header.dt_ptr->dt_Fstr->gc = item->header.dt_ptr->dt_GC;
1586 item->header.dt_ptr->dt_Fstr->str = item->text.value;
1587 item->header.dt_ptr->dt_Fstr->x = item->header.pos_x + TEXT_SPC;
1588 item->header.dt_ptr->dt_Fstr->y = item->header.pos_y + ( CF.padVText / 2 ) +
1589 item->header.dt_ptr->dt_Ffont->ascent;
1590 item->header.dt_ptr->dt_Fstr->flags.has_colorset = False;
1591 if (colorset >= 0)
1593 item->header.dt_ptr->dt_Fstr->colorset = &Colorset[colorset];
1594 item->header.dt_ptr->dt_Fstr->flags.has_colorset = True;
1596 FlocaleDrawString(dpy,
1597 item->header.dt_ptr->dt_Ffont,
1598 item->header.dt_ptr->dt_Fstr, FWS_HAVE_LENGTH);
1599 return;
1602 void RedrawTimeout(Item *item)
1604 char *p;
1605 char *tmpbuf, *tmpptr, *tmpbptr;
1606 int reallen;
1608 XClearArea(dpy, CF.frame,
1609 item->header.pos_x, item->header.pos_y,
1610 item->header.size_x, item->header.size_y,
1611 False);
1613 tmpbuf = safemalloc(item->timeout.len + 6);
1614 tmpbptr = tmpbuf;
1615 for (tmpptr = item->timeout.text; *tmpptr != '\0' &&
1616 !(tmpptr[0] == '%' && tmpptr[1] == '%'); tmpptr++) {
1617 *tmpbptr = *tmpptr;
1618 tmpbptr++;
1620 if (tmpptr[0] == '%') {
1621 tmpptr++; tmpptr++;
1622 sprintf(tmpbptr, "%d", item->timeout.timeleft);
1623 tmpbptr += strlen(tmpbptr);
1625 for (; *tmpptr != '\0'; tmpptr++) {
1626 *tmpbptr = *tmpptr;
1627 tmpbptr++;
1629 *tmpbptr = '\0';
1631 reallen = strlen(tmpbuf);
1632 item->header.size_x = FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
1633 tmpbuf, reallen) + 2 * TEXT_SPC;
1634 item->header.size_y = item->header.dt_ptr->dt_Ffont->height + CF.padVText;
1636 CheckAlloc(item,item->header.dt_ptr); /* alloc colors and fonts needed */
1637 item->header.dt_ptr->dt_Fstr->len = reallen;
1638 if ((p = memchr(item->timeout.text, '\0', item->header.dt_ptr->dt_Fstr->len))
1639 != NULL)
1640 item->header.dt_ptr->dt_Fstr->len = p - tmpbuf;
1641 item->header.dt_ptr->dt_Fstr->win = CF.frame;
1642 item->header.dt_ptr->dt_Fstr->gc = item->header.dt_ptr->dt_GC;
1643 item->header.dt_ptr->dt_Fstr->flags.has_colorset = False;
1644 if (colorset >= 0)
1646 item->header.dt_ptr->dt_Fstr->colorset = &Colorset[colorset];
1647 item->header.dt_ptr->dt_Fstr->flags.has_colorset = True;
1649 if (item->header.dt_ptr->dt_Fstr->str != NULL)
1650 free(item->header.dt_ptr->dt_Fstr->str);
1651 item->header.dt_ptr->dt_Fstr->str = safestrdup(tmpbuf);
1652 item->header.dt_ptr->dt_Fstr->x = item->header.pos_x + TEXT_SPC;
1653 item->header.dt_ptr->dt_Fstr->y = item->header.pos_y + ( CF.padVText / 2 ) +
1654 item->header.dt_ptr->dt_Ffont->ascent;
1655 FlocaleDrawString(dpy,
1656 item->header.dt_ptr->dt_Ffont,
1657 item->header.dt_ptr->dt_Fstr, FWS_HAVE_LENGTH);
1658 free(tmpbuf);
1659 return;
1662 /* redraw an item */
1663 void RedrawItem (Item *item, int click, XEvent *pev)
1665 int dx, dy, len, x;
1666 static XSegment xsegs[4];
1667 XRectangle r,inter;
1668 Region region = None;
1669 Bool text_inter = True;
1670 DrawTable *dt_ptr = item->header.dt_ptr;
1672 /* Init intersection to size of the item. */
1673 inter.x = BOX_SPC + TEXT_SPC - 1;
1674 inter.y = BOX_SPC;
1675 inter.width = item->header.size_x - (2 * BOX_SPC) - 2 - TEXT_SPC;
1676 inter.height = (item->header.size_y - 1) - 2 * BOX_SPC + 1;
1677 /* This is a slightly altered expose event from ReadXServer. */
1678 if (pev)
1680 r.x = pev->xexpose.x;
1681 r.y = pev->xexpose.y;
1682 r.width = pev->xexpose.width;
1683 r.height = pev->xexpose.height;
1684 text_inter = frect_get_intersection(
1685 r.x, r.y, r.width, r.height,
1686 inter.x,inter.y,inter.width,inter.height,
1687 &inter);
1689 else
1691 /* If its not an expose event, the area assume the
1692 whole item is intersected. */
1693 r.x = inter.x;
1694 r.y = inter.y;
1695 r.width = inter.width;
1696 r.height = inter.height;
1698 if (pev && text_inter && dt_ptr && dt_ptr->dt_Fstr)
1700 region = XCreateRegion();
1701 XUnionRectWithRegion (&r, region, region);
1702 if (region)
1704 dt_ptr->dt_Fstr->flags.has_clip_region = True;
1705 dt_ptr->dt_Fstr->clip_region = region;
1707 else
1709 dt_ptr->dt_Fstr->flags.has_clip_region = False;
1713 switch (item->type) {
1714 case I_INPUT:
1715 if (!text_inter)
1717 return;
1719 /* Create frame (pressed in): */
1720 dx = item->header.size_x - 1;
1721 dy = item->header.size_y - 1;
1722 /*fprintf(stderr,"GC: %lu\n", item->header.dt_ptr->dt_item_GC);*/
1723 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1724 item->header.dt_ptr->dt_colors[c_itemlo]);
1726 /* around 12/26/99, added XClearArea to this function.
1727 this was done to deal with display corruption during
1728 multifield paste. dje */
1729 if (frect_get_intersection(
1730 r.x, r.y, r.width, r.height,
1731 inter.x, inter.y, inter.width, inter.height,
1732 &inter))
1734 XClearArea(
1735 dpy, item->header.win,
1736 inter.x, inter.y, inter.width, inter.height, False);
1739 xsegs[0].x1 = 0, xsegs[0].y1 = 0;
1740 xsegs[0].x2 = 0, xsegs[0].y2 = dy;
1741 xsegs[1].x1 = 0, xsegs[1].y1 = 0;
1742 xsegs[1].x2 = dx, xsegs[1].y2 = 0;
1743 xsegs[2].x1 = 1, xsegs[2].y1 = 1;
1744 xsegs[2].x2 = 1, xsegs[2].y2 = dy - 1;
1745 xsegs[3].x1 = 1, xsegs[3].y1 = 1;
1746 xsegs[3].x2 = dx - 1, xsegs[3].y2 = 1;
1747 XDrawSegments(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1748 xsegs, 4);
1749 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1750 item->header.dt_ptr->dt_colors[c_itemhi]);
1751 xsegs[0].x1 = 1, xsegs[0].y1 = dy;
1752 xsegs[0].x2 = dx, xsegs[0].y2 = dy;
1753 xsegs[1].x1 = 2, xsegs[1].y1 = dy - 1;
1754 xsegs[1].x2 = dx, xsegs[1].y2 = dy - 1;
1755 xsegs[2].x1 = dx, xsegs[2].y1 = 1;
1756 xsegs[2].x2 = dx, xsegs[2].y2 = dy;
1757 xsegs[3].x1 = dx - 1, xsegs[3].y1 = 2;
1758 xsegs[3].x2 = dx - 1, xsegs[3].y2 = dy;
1759 XDrawSegments(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1760 xsegs, 4);
1762 if (click) {
1763 x = BOX_SPC + TEXT_SPC +
1764 FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
1765 item->input.value, CF.abs_cursor) - 1;
1766 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1767 item->header.dt_ptr->dt_colors[c_item_bg]);
1768 XDrawLine(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1769 x, BOX_SPC, x, dy - BOX_SPC);
1770 myfprintf((stderr,"Line %d/%d - %d/%d (first)\n",
1771 x, BOX_SPC, x, dy - BOX_SPC));
1773 len = item->input.n - item->input.left;
1774 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1775 item->header.dt_ptr->dt_colors[c_item_fg]);
1776 item->header.dt_ptr->dt_Fstr->win = item->header.win;
1777 item->header.dt_ptr->dt_Fstr->gc = item->header.dt_ptr->dt_item_GC;
1778 item->header.dt_ptr->dt_Fstr->flags.has_colorset = False;
1779 if (itemcolorset >= 0)
1781 item->header.dt_ptr->dt_Fstr->colorset = &Colorset[itemcolorset];
1782 item->header.dt_ptr->dt_Fstr->flags.has_colorset = True;
1784 if (len > item->input.size)
1785 len = item->input.size;
1786 else
1788 item->header.dt_ptr->dt_Fstr->str = item->input.blanks;
1789 item->header.dt_ptr->dt_Fstr->x = BOX_SPC + TEXT_SPC +
1790 FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
1791 item->input.blanks, len);
1792 item->header.dt_ptr->dt_Fstr->y = BOX_SPC + TEXT_SPC
1793 + item->header.dt_ptr->dt_Ffont->ascent;
1794 item->header.dt_ptr->dt_Fstr->len = item->input.size - len;
1795 FlocaleDrawString(dpy,
1796 item->header.dt_ptr->dt_Ffont,
1797 item->header.dt_ptr->dt_Fstr, FWS_HAVE_LENGTH);
1799 item->header.dt_ptr->dt_Fstr->str = item->input.value;
1800 item->header.dt_ptr->dt_Fstr->x = BOX_SPC + TEXT_SPC;
1801 item->header.dt_ptr->dt_Fstr->y = BOX_SPC + TEXT_SPC
1802 + item->header.dt_ptr->dt_Ffont->ascent;
1803 item->header.dt_ptr->dt_Fstr->len = len;
1804 FlocaleDrawString(dpy,
1805 item->header.dt_ptr->dt_Ffont,
1806 item->header.dt_ptr->dt_Fstr, FWS_HAVE_LENGTH);
1807 if (item == CF.cur_input && !click) {
1808 x = BOX_SPC + TEXT_SPC +
1809 FlocaleTextWidth(item->header.dt_ptr->dt_Ffont,
1810 item->input.value,CF.abs_cursor)
1811 - 1;
1812 XDrawLine(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1813 x, BOX_SPC, x, dy - BOX_SPC);
1814 myfprintf((stderr,"Line %d/%d - %d/%d\n",
1815 x, BOX_SPC, x, dy - BOX_SPC));
1817 myfprintf((stderr,"Just drew input field. click %d\n",(int)click));
1818 break;
1819 case I_CHOICE:
1820 dx = dy = item->header.size_y - 1;
1821 if (item->choice.on) {
1822 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1823 item->header.dt_ptr->dt_colors[c_item_fg]);
1824 if (item->choice.sel->selection.key == IS_MULTIPLE) {
1825 xsegs[0].x1 = 5, xsegs[0].y1 = 5;
1826 xsegs[0].x2 = dx - 5, xsegs[0].y2 = dy - 5;
1827 xsegs[1].x1 = 5, xsegs[1].y1 = dy - 5;
1828 xsegs[1].x2 = dx - 5, xsegs[1].y2 = 5;
1829 XDrawSegments(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1830 xsegs, 2);
1831 } else {
1832 XDrawArc(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1833 5, 5, dx - 10, dy - 10, 0, 360 * 64);
1835 } else
1836 XClearWindow(dpy, item->header.win);
1837 if (item->choice.on)
1838 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1839 item->header.dt_ptr->dt_colors[c_itemlo]);
1840 else
1841 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1842 item->header.dt_ptr->dt_colors[c_itemhi]);
1843 xsegs[0].x1 = 0, xsegs[0].y1 = 0;
1844 xsegs[0].x2 = 0, xsegs[0].y2 = dy;
1845 xsegs[1].x1 = 0, xsegs[1].y1 = 0;
1846 xsegs[1].x2 = dx, xsegs[1].y2 = 0;
1847 xsegs[2].x1 = 1, xsegs[2].y1 = 1;
1848 xsegs[2].x2 = 1, xsegs[2].y2 = dy - 1;
1849 xsegs[3].x1 = 1, xsegs[3].y1 = 1;
1850 xsegs[3].x2 = dx - 1, xsegs[3].y2 = 1;
1851 XDrawSegments(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1852 xsegs, 4);
1853 if (item->choice.on)
1854 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1855 item->header.dt_ptr->dt_colors[c_itemhi]);
1856 else
1857 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1858 item->header.dt_ptr->dt_colors[c_itemlo]);
1859 xsegs[0].x1 = 1, xsegs[0].y1 = dy;
1860 xsegs[0].x2 = dx, xsegs[0].y2 = dy;
1861 xsegs[1].x1 = 2, xsegs[1].y1 = dy - 1;
1862 xsegs[1].x2 = dx, xsegs[1].y2 = dy - 1;
1863 xsegs[2].x1 = dx, xsegs[2].y1 = 1;
1864 xsegs[2].x2 = dx, xsegs[2].y2 = dy;
1865 xsegs[3].x1 = dx - 1, xsegs[3].y1 = 2;
1866 xsegs[3].x2 = dx - 1, xsegs[3].y2 = dy;
1867 XDrawSegments(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1868 xsegs, 4);
1869 break;
1870 case I_BUTTON:
1871 if (!text_inter)
1873 return;
1875 dx = item->header.size_x - 1;
1876 dy = item->header.size_y - 1;
1877 if (click)
1878 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1879 item->header.dt_ptr->dt_colors[c_itemlo]);
1880 else
1881 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1882 item->header.dt_ptr->dt_colors[c_itemhi]);
1883 xsegs[0].x1 = 0, xsegs[0].y1 = 0;
1884 xsegs[0].x2 = 0, xsegs[0].y2 = dy;
1885 xsegs[1].x1 = 0, xsegs[1].y1 = 0;
1886 xsegs[1].x2 = dx, xsegs[1].y2 = 0;
1887 xsegs[2].x1 = 1, xsegs[2].y1 = 1;
1888 xsegs[2].x2 = 1, xsegs[2].y2 = dy - 1;
1889 xsegs[3].x1 = 1, xsegs[3].y1 = 1;
1890 xsegs[3].x2 = dx - 1, xsegs[3].y2 = 1;
1891 XDrawSegments(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1892 xsegs, 4);
1893 if (click)
1894 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1895 item->header.dt_ptr->dt_colors[c_itemhi]);
1896 else
1897 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1898 item->header.dt_ptr->dt_colors[c_itemlo]);
1899 xsegs[0].x1 = 1, xsegs[0].y1 = dy;
1900 xsegs[0].x2 = dx, xsegs[0].y2 = dy;
1901 xsegs[1].x1 = 2, xsegs[1].y1 = dy - 1;
1902 xsegs[1].x2 = dx, xsegs[1].y2 = dy - 1;
1903 xsegs[2].x1 = dx, xsegs[2].y1 = 1;
1904 xsegs[2].x2 = dx, xsegs[2].y2 = dy;
1905 xsegs[3].x1 = dx - 1, xsegs[3].y1 = 2;
1906 xsegs[3].x2 = dx - 1, xsegs[3].y2 = dy;
1907 XDrawSegments(dpy, item->header.win, item->header.dt_ptr->dt_item_GC,
1908 xsegs, 4);
1909 XSetForeground(dpy, item->header.dt_ptr->dt_item_GC,
1910 item->header.dt_ptr->dt_colors[c_item_fg]);
1911 item->header.dt_ptr->dt_Fstr->win = item->header.win;
1912 item->header.dt_ptr->dt_Fstr->gc = item->header.dt_ptr->dt_item_GC;
1913 item->header.dt_ptr->dt_Fstr->flags.has_colorset = False;
1914 if (itemcolorset >= 0)
1916 item->header.dt_ptr->dt_Fstr->colorset = &Colorset[itemcolorset];
1917 item->header.dt_ptr->dt_Fstr->flags.has_colorset = True;
1919 item->header.dt_ptr->dt_Fstr->str = item->button.text;
1920 item->header.dt_ptr->dt_Fstr->x = BOX_SPC + TEXT_SPC;
1921 item->header.dt_ptr->dt_Fstr->y = BOX_SPC + TEXT_SPC
1922 + item->header.dt_ptr->dt_Ffont->ascent;
1923 item->header.dt_ptr->dt_Fstr->len = item->button.len;
1924 if (FftSupport)
1926 if (item->header.dt_ptr->dt_Ffont->fftf.fftfont != NULL)
1927 XClearArea(dpy, item->header.win,
1928 inter.x, inter.y, inter.width, inter.height, False);
1930 FlocaleDrawString(dpy,
1931 item->header.dt_ptr->dt_Ffont,
1932 item->header.dt_ptr->dt_Fstr, FWS_HAVE_LENGTH);
1933 myfprintf((stderr,"Just put %s into a button\n",
1934 item->button.text));
1935 break;
1937 if (dt_ptr && dt_ptr->dt_Fstr)
1939 dt_ptr->dt_Fstr->flags.has_clip_region = False;
1941 if (region)
1943 XDestroyRegion(region);
1945 XFlush(dpy);
1948 /* update transparency if background colorset is transparent */
1949 /* window has moved redraw the background if it is transparent */
1950 void UpdateRootTransapency(Bool pr_only, Bool do_draw)
1952 Item *item;
1954 if (CSET_IS_TRANSPARENT(colorset))
1956 if (CSET_IS_TRANSPARENT_PR_PURE(colorset))
1958 XClearArea(dpy, CF.frame, 0,0,0,0, False);
1959 if (do_draw)
1961 RedrawFrame(NULL);
1964 else if (!pr_only || CSET_IS_TRANSPARENT_PR(colorset))
1966 SetWindowBackground(
1967 dpy, CF.frame, CF.max_width, CF.total_height,
1968 &Colorset[(colorset)], Pdepth,
1969 root_item_ptr->header.dt_ptr->dt_GC, False);
1970 if (do_draw)
1972 XClearArea(dpy, CF.frame, 0,0,0,0, False);
1973 RedrawFrame(NULL);
1977 if (!root_item_ptr->header.next || !CSET_IS_TRANSPARENT(itemcolorset))
1979 return;
1981 for (item = root_item_ptr->header.next; item != NULL;
1982 item = item->header.next)
1984 if (item->header.win != None)
1986 if (CSET_IS_TRANSPARENT_PR(itemcolorset) &&
1987 !CSET_IS_TRANSPARENT(colorset))
1989 continue;
1991 if (CSET_IS_TRANSPARENT_PR_PURE(itemcolorset))
1993 XClearArea(
1994 dpy, item->header.win, 0,0,0,0, False);
1995 if (do_draw)
1997 RedrawItem(item, 0, NULL);
2000 else if (!pr_only ||
2001 CSET_IS_TRANSPARENT_PR(itemcolorset))
2003 SetWindowBackground(
2004 dpy, item->header.win,
2005 item->header.size_x, item->header.size_y,
2006 &Colorset[(itemcolorset)], Pdepth,
2007 item->header.dt_ptr->dt_GC, False);
2008 XClearArea(
2009 dpy, item->header.win, 0,0,0,0, False);
2010 if (do_draw)
2012 RedrawItem(item, 0, NULL);
2019 /* execute a command */
2020 void DoCommand (Item *cmd)
2022 int k, dn;
2023 char *sp;
2024 Item *item;
2026 /* pre-command */
2027 if (cmd->button.key == IB_QUIT)
2029 if (!XWithdrawWindow(dpy, CF.frame, screen))
2031 /* hm, what can we do now? just ignore this situation. */
2035 for (k = 0; k < cmd->button.n; k++) {
2036 char *parsed_command;
2037 /* construct command */
2038 parsed_command = ParseCommand(0, cmd->button.commands[k], '\0', &dn, &sp);
2039 myfprintf((stderr, "Final command[%d]: [%s]\n", k, parsed_command));
2041 /* send command */
2042 if ( parsed_command[0] == '!') { /* If command starts with ! */
2043 system(parsed_command+1); /* Need synchronous execution */
2044 } else {
2045 SendText(Channel,parsed_command, ref);
2049 /* post-command */
2050 if (CF.last_error) { /* if form has last_error field */
2051 memset(CF.last_error->text.value, ' ', CF.last_error->text.n); /* clear */
2052 /* To do this more elegantly, the window resize logic should recalculate
2053 size_x for the Message as the window resizes. Right now, just clear
2054 a nice wide area. dje */
2055 XClearArea(dpy,CF.frame,
2056 CF.last_error->header.pos_x,
2057 CF.last_error->header.pos_y,
2058 /* CF.last_error->header.size_x, */
2059 2000,
2060 CF.last_error->header.size_y, False);
2061 } /* end form has last_error field */
2062 if (cmd->button.key == IB_QUIT) {
2063 if (CF.grab_server)
2064 XUngrabServer(dpy);
2065 /* This is a temporary bug workaround for the pipe drainage problem */
2066 SendQuitNotification(Channel); /* let commands complete */
2067 /* Note how the window is withdrawn, but execution continues until
2068 the quit notifcation catches up with this module...
2069 Should not be a problem, there shouldn't be any more commands
2070 coming into FvwmForm. dje */
2072 else if (cmd->button.key == IB_RESTART) {
2073 Restart();
2074 for (item = root_item_ptr; item != 0;
2075 item = item->header.next) { /* all items */
2076 if (item->type == I_INPUT) {
2077 XClearWindow(dpy, item->header.win);
2078 RedrawItem(item, 0, NULL);
2080 if (item->type == I_CHOICE)
2081 RedrawItem(item, 0, NULL);
2086 /* open the windows */
2087 static void OpenWindows(void)
2089 int x, y;
2090 int gravity = NorthWestGravity;
2091 Item *item;
2092 static XSetWindowAttributes xswa;
2093 static XWMHints wmh = { InputHint, True };
2094 static XSizeHints sh =
2095 { PPosition | PSize | USPosition | USSize | PWinGravity};
2096 XClassHint myclasshints;
2097 fscreen_scr_t scr;
2099 if (!CF.pointer[input_pointer]) {
2100 CF.pointer[input_pointer] = XCreateFontCursor(dpy, XC_xterm);
2102 if (!CF.pointer[button_in_pointer]) {
2103 CF.pointer[button_in_pointer] = XCreateFontCursor(dpy, XC_hand2);
2105 if (!CF.pointer[button_pointer]) {
2106 CF.pointer[button_pointer] = XCreateFontCursor(dpy,XC_hand2);
2108 CF.screen_background = (colorset < 0)
2109 ? GetColor(screen_background_color)
2110 : Colorset[colorset].bg;
2112 if (!CF.p_c[input_back].used) { /* if not set, use screen b/g */
2113 CF.p_c[input_back].pointer_color.pixel = CF.screen_background;
2115 myfprintf((stderr,
2116 "screen bg %X, getcolor bg %X, colorset bg %X colorset %d\n",
2117 (int)CF.screen_background,
2118 (int)GetColor(screen_background_color),
2119 (int)Colorset[colorset].bg,
2120 (int)colorset));
2121 XQueryColor(dpy, Pcmap, &CF.p_c[input_fore].pointer_color);
2122 XQueryColor(dpy, Pcmap, &CF.p_c[input_back].pointer_color);
2123 XRecolorCursor(dpy, CF.pointer[input_pointer],
2124 &CF.p_c[input_fore].pointer_color,
2125 &CF.p_c[input_back].pointer_color);
2126 myfprintf((stderr,"input fore %X, back %X\n",
2127 (int)CF.p_c[input_fore].pointer_color.pixel,
2128 (int)CF.p_c[input_back].pointer_color.pixel));
2129 /* The input cursor is handled differently than the 2 button cursors. */
2130 XQueryColor(dpy, Pcmap, &CF.p_c[button_fore].pointer_color);
2131 XQueryColor(dpy, Pcmap, &CF.p_c[button_back].pointer_color);
2132 XRecolorCursor(dpy, CF.pointer[button_pointer],
2133 &CF.p_c[button_fore].pointer_color,
2134 &CF.p_c[button_back].pointer_color);
2135 myfprintf((stderr,"button fore %X, back %X\n",
2136 (int)CF.p_c[button_fore].pointer_color.pixel,
2137 (int)CF.p_c[button_back].pointer_color.pixel));
2138 XQueryColor(dpy, Pcmap, &CF.p_c[button_in_fore].pointer_color);
2139 XQueryColor(dpy, Pcmap, &CF.p_c[button_in_back].pointer_color);
2140 XRecolorCursor(dpy, CF.pointer[button_in_pointer],
2141 &CF.p_c[button_in_fore].pointer_color,
2142 &CF.p_c[button_in_back].pointer_color);
2143 myfprintf((stderr,"button in fore %X, back %X\n",
2144 (int)CF.p_c[button_in_fore].pointer_color.pixel,
2145 (int)CF.p_c[button_in_back].pointer_color.pixel));
2146 /* the frame window first */
2147 if (CF.have_geom)
2149 if (CF.xneg)
2151 x = DisplayWidth(dpy, screen) - CF.max_width + CF.gx;
2152 gravity = NorthEastGravity;
2154 else
2156 x = CF.gx;
2158 if (CF.yneg)
2160 y = DisplayHeight(dpy, screen) - CF.total_height + CF.gy;
2161 gravity = SouthWestGravity;
2163 else
2165 y = CF.gy;
2167 if (CF.xneg && CF.yneg)
2169 gravity = SouthEastGravity;
2171 scr = FSCREEN_XYPOS;
2172 } else {
2173 FScreenCenterOnScreen(
2174 NULL, FSCREEN_CURRENT, &x, &y, CF.max_width, CF.total_height);
2175 scr = FSCREEN_CURRENT;
2177 /* hack to prevent mapping on wrong screen with StartsOnScreen */
2178 FScreenMangleScreenIntoUSPosHints(FSCREEN_CURRENT, &sh);
2179 xswa.background_pixel = CF.screen_background;
2180 xswa.border_pixel = 0;
2181 xswa.colormap = Pcmap;
2182 myfprintf((stderr,
2183 "going to create window w. bg %s, b/g pixel %X, black pixel %X\n",
2184 screen_background_color,
2185 (int)xswa.background_pixel,
2186 BlackPixel(dpy, screen)));
2187 CF.frame = XCreateWindow(dpy, root, x, y, CF.max_width, CF.total_height, 0,
2188 Pdepth, InputOutput, Pvisual,
2189 CWColormap | CWBackPixel | CWBorderPixel, &xswa);
2190 wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
2191 XSetWMProtocols(dpy, CF.frame, &wm_del_win, 1);
2192 XSelectInput(dpy, CF.frame,
2193 KeyPressMask | ExposureMask | StructureNotifyMask |
2194 VisibilityChangeMask);
2195 if (!CF.title) {
2196 CF.title = module->name;
2198 XStoreName(dpy, CF.frame, CF.title);
2199 XSetWMHints(dpy, CF.frame, &wmh);
2200 myclasshints.res_name = module->name;
2201 myclasshints.res_class = "FvwmForm";
2202 XSetClassHint(dpy,CF.frame,&myclasshints);
2203 sh.width = CF.max_width;
2204 sh.height = CF.total_height;
2205 sh.win_gravity = gravity;
2206 XSetWMNormalHints(dpy, CF.frame, &sh);
2208 for (item = root_item_ptr; item != 0;
2209 item = item->header.next) { /* all items */
2210 switch (item->type) {
2211 case I_INPUT:
2212 myfprintf((stderr,"Checking alloc during OpenWindow on input\n"));
2213 CheckAlloc(item,item->header.dt_ptr); /* alloc colors and fonts needed */
2214 item->header.win =
2215 XCreateSimpleWindow(dpy, CF.frame,
2216 item->header.pos_x, item->header.pos_y,
2217 item->header.size_x, item->header.size_y,
2218 0, CF.screen_background,
2219 item->header.dt_ptr->dt_colors[c_item_bg]);
2220 XSelectInput(dpy, item->header.win, ButtonPressMask | ExposureMask);
2221 xswa.cursor = CF.pointer[input_pointer];
2222 XChangeWindowAttributes(dpy, item->header.win, CWCursor, &xswa);
2223 if (itemcolorset >= 0)
2225 SetWindowBackground(dpy, item->header.win,
2226 item->header.size_x, item->header.size_y,
2227 &Colorset[(itemcolorset)], Pdepth,
2228 item->header.dt_ptr->dt_GC, True);
2230 break;
2231 case I_CHOICE:
2232 myfprintf((stderr,"Checking alloc during Openwindow on choice\n"));
2233 CheckAlloc(item,item->header.dt_ptr); /* alloc colors and fonts needed */
2234 item->header.win =
2235 XCreateSimpleWindow(dpy, CF.frame,
2236 item->header.pos_x, item->header.pos_y,
2237 item->header.size_y, item->header.size_y,
2238 0, CF.screen_background,
2239 item->header.dt_ptr->dt_colors[c_item_bg]);
2240 XSelectInput(dpy, item->header.win, ButtonPressMask | ExposureMask);
2241 xswa.cursor = CF.pointer[button_pointer];
2242 XChangeWindowAttributes(dpy, item->header.win, CWCursor, &xswa);
2243 if (itemcolorset >= 0)
2245 SetWindowBackground(dpy, item->header.win,
2246 item->header.size_x, item->header.size_y,
2247 &Colorset[(itemcolorset)], Pdepth,
2248 item->header.dt_ptr->dt_GC, True);
2250 break;
2251 case I_BUTTON:
2252 myfprintf((stderr,"Checking alloc during Openwindow on button\n"));
2253 CheckAlloc(item,item->header.dt_ptr); /* alloc colors and fonts needed */
2254 item->header.win =
2255 XCreateSimpleWindow(dpy, CF.frame,
2256 item->header.pos_x, item->header.pos_y,
2257 item->header.size_x, item->header.size_y,
2258 0, CF.screen_background,
2259 item->header.dt_ptr->dt_colors[c_item_bg]);
2260 XSelectInput(dpy, item->header.win,
2261 ButtonPressMask | ExposureMask);
2262 xswa.cursor = CF.pointer[button_pointer];
2263 XChangeWindowAttributes(dpy, item->header.win, CWCursor, &xswa);
2264 if (itemcolorset >= 0)
2266 SetWindowBackground(dpy, item->header.win,
2267 item->header.size_x, item->header.size_y,
2268 &Colorset[(itemcolorset)], Pdepth,
2269 item->header.dt_ptr->dt_GC, True);
2271 break;
2274 Restart();
2275 if (colorset >= 0)
2277 CheckAlloc(root_item_ptr,root_item_ptr->header.dt_ptr);
2278 SetWindowBackground(dpy, CF.frame, CF.max_width, CF.total_height,
2279 &Colorset[(colorset)], Pdepth,
2280 root_item_ptr->header.dt_ptr->dt_GC, True);
2282 if (preload_yorn != 'y') { /* if not a preload */
2283 XMapRaised(dpy, CF.frame);
2284 XMapSubwindows(dpy, CF.frame);
2285 if (CF.warp_pointer) {
2286 FWarpPointer(dpy, None, CF.frame, 0, 0, 0, 0,
2287 CF.max_width / 2, CF.total_height - 1);
2290 DoCommand(&CF.def_button);
2293 static void process_message(unsigned long, unsigned long *); /* proto */
2294 static void ParseActiveMessage(char *); /* proto */
2296 /* read something from Fvwm */
2297 static void ReadFvwm(void)
2300 FvwmPacket* packet = ReadFvwmPacket(Channel[1]);
2301 if ( packet == NULL )
2302 exit(0);
2303 else
2304 process_message( packet->type, packet->body );
2306 static void process_message(unsigned long type, unsigned long *body)
2308 switch (type) {
2309 case M_CONFIG_INFO: /* any module config command */
2310 myfprintf((stderr,"process_message: Got command: %s\n", (char *)&body[3]));
2311 ParseActiveMessage((char *)&body[3]);
2312 break;
2313 case MX_PROPERTY_CHANGE:
2314 if (body[0] == MX_PROPERTY_CHANGE_BACKGROUND &&
2315 ((!Swallowed && body[2] == 0) || (Swallowed && body[2] == CF.frame)))
2317 UpdateRootTransapency(True, True);
2319 else if (body[0] == MX_PROPERTY_CHANGE_SWALLOW && body[2] == CF.frame)
2321 Swallowed = body[1];
2323 break;
2324 case M_ERROR:
2325 case M_STRING:
2326 if (CF.last_error) { /* if form has message area */
2327 /* ignore form size, its OK to write outside the window boundary */
2328 int msg_len;
2329 char *msg_ptr;
2330 /* Clear old message first */
2331 memset(CF.last_error->text.value, ' ', CF.last_error->text.n); /* clear */
2332 XClearArea(dpy,CF.frame,
2333 CF.last_error->header.pos_x,
2334 CF.last_error->header.pos_y,
2335 2000,
2336 CF.last_error->header.size_y, False);
2337 msg_ptr = (char *)&body[3];
2338 msg_len = strlen(msg_ptr);
2339 if (msg_ptr[msg_len-1] == '\n') { /* line ends w newline */
2340 msg_ptr[msg_len-1] = '\0'; /* strip off \n */
2342 if (CF.last_error->text.n <= msg_len) { /* if message wont fit */
2343 CF.last_error->text.value = saferealloc(CF.last_error->text.value,
2344 msg_len * 2);
2345 CF.last_error->text.n = msg_len * 2;
2347 strncpy(CF.last_error->text.value,msg_ptr,
2348 CF.last_error->text.n);
2349 RedrawText(CF.last_error);
2350 break;
2351 } /* module has last_error field */
2352 } /* end switch header */
2355 /* These are the message from fvwm FvwmForm understands after form is
2356 active. */
2357 static void am_Map(char *);
2358 static void am_UnMap(char *);
2359 static void am_Stop(char *);
2360 static struct CommandTable am_table[] =
2362 {"Map",am_Map},
2363 {"Stop",am_Stop},
2364 {"UnMap",am_UnMap}
2367 /* This is similar to the other 2 "Parse" functions. */
2368 static void ParseActiveMessage(char *buf)
2370 char *p;
2371 struct CommandTable *e;
2372 if (buf[strlen(buf)-1] == '\n')
2373 { /* if line ends with newline */
2374 buf[strlen(buf)-1] = '\0'; /* strip off \n */
2377 if (strncasecmp(buf, "Colorset", 8) == 0)
2379 Item *item;
2380 int n = LoadColorset(&buf[8]);
2381 if(n == colorset || n == itemcolorset)
2383 for (item = root_item_ptr; item != 0;
2384 item = item->header.next)
2386 DrawTable *dt_ptr = item->header.dt_ptr;
2387 if (dt_ptr)
2389 dt_ptr->dt_used = 0;
2390 if(dt_ptr->dt_GC)
2392 XFreeGC(dpy, dt_ptr->dt_GC);
2393 dt_ptr->dt_GC = None;
2395 if(dt_ptr->dt_item_GC)
2397 XFreeGC(
2398 dpy,
2399 dt_ptr->dt_item_GC);
2400 dt_ptr->dt_item_GC = None;
2404 for (item = root_item_ptr; item != 0;
2405 item = item->header.next)
2407 DrawTable *dt_ptr = item->header.dt_ptr;
2408 if (dt_ptr)
2410 CheckAlloc(item, dt_ptr);
2413 if (colorset >= 0)
2415 SetWindowBackground(
2416 dpy, CF.frame, CF.max_width,
2417 CF.total_height,
2418 &Colorset[(colorset)], Pdepth,
2419 root_item_ptr->header.dt_ptr->dt_GC,
2420 False);
2421 RedrawFrame(NULL);
2423 for (item = root_item_ptr->header.next; item != 0;
2424 item = item->header.next)
2426 DrawTable *dt_ptr = item->header.dt_ptr;
2427 if (dt_ptr && itemcolorset >= 0 &&
2428 item->header.win != 0)
2430 SetWindowBackground(
2431 dpy, item->header.win,
2432 item->header.size_x,
2433 item->header.size_y,
2434 &Colorset[(itemcolorset)],
2435 Pdepth, dt_ptr->dt_GC, True);
2436 RedrawItem(item, 0, NULL);
2437 } /* end item has a drawtable */
2438 } /* end all items */
2440 return;
2441 } /* end colorset command */
2442 if (strncasecmp(
2443 buf, XINERAMA_CONFIG_STRING, sizeof(XINERAMA_CONFIG_STRING)-1)
2444 == 0)
2446 FScreenConfigureModule(buf + sizeof(XINERAMA_CONFIG_STRING)-1);
2447 return;
2449 if (
2450 strncasecmp(
2451 buf, CatString3("*",module->name,0),
2452 module->namelen+1) != 0)
2454 /* If its not for me */
2455 return;
2456 } /* Now I know its for me. */
2457 p = buf+module->namelen+1; /* jump to end of my name */
2458 /* at this point we have recognized "*FvwmForm" */
2459 e = FindToken(p,am_table,struct CommandTable);/* find cmd in table */
2460 if (e == 0)
2462 /* if no match */
2463 /* this may be a configuration command of another same form */
2464 if (FindToken(p, ct_table, struct CommandTable) == 0)
2465 fprintf(
2466 stderr,"%s: Active command unknown: %s\n",
2467 module->name,buf);
2468 return; /* ignore it */
2471 p=p+strlen(e->name); /* skip over name */
2472 while (isspace((unsigned char)*p)) p++; /* skip whitespace */
2474 FormVarsCheck(&p);
2475 e->function(p); /* call cmd processor */
2476 return;
2477 } /* end function */
2479 static void am_Map(char *cp)
2481 XMapRaised(dpy, CF.frame);
2482 XMapSubwindows(dpy, CF.frame);
2483 if (CF.warp_pointer) {
2484 FWarpPointer(dpy, None, CF.frame, 0, 0, 0, 0,
2485 CF.max_width / 2, CF.total_height - 1);
2487 myfprintf((stderr, "Map: got it\n"));
2489 static void am_UnMap(char *cp)
2491 XUnmapWindow(dpy, CF.frame);
2492 myfprintf((stderr, "UnMap: got it\n"));
2494 static void am_Stop(char *cp)
2496 /* syntax: *FFStop */
2497 myfprintf((stderr,"Got stop command.\n"));
2498 exit (0); /* why bother, just exit. */
2501 /* main event loop */
2502 static void MainLoop(void)
2504 fd_set fds;
2505 fd_set_size_t fd_width = GetFdWidth();
2507 while ( !isTerminated ) {
2508 /* TA: 20091219: Automatically flush the buffer from the XServer and
2509 * process each request as we receive them.
2511 while(FPending(dpy))
2512 ReadXServer();
2514 FD_ZERO(&fds);
2515 FD_SET(Channel[1], &fds);
2516 FD_SET(fd_x, &fds);
2518 /* TA: 20091219: Using XFlush() here was always a nasty hack! See
2519 * comments above.
2521 /*XFlush(dpy);*/
2522 if (fvwmSelect(fd_width, &fds, NULL, NULL, NULL) > 0) {
2523 if (FD_ISSET(Channel[1], &fds))
2524 ReadFvwm();
2525 if (FD_ISSET(fd_x, &fds))
2526 ReadXServer();
2532 /* signal-handler to make the application quit */
2533 static RETSIGTYPE
2534 TerminateHandler(int sig)
2536 fvwmSetTerminate(sig);
2537 SIGNAL_RETURN;
2540 /* signal-handler to make the timer work */
2541 static RETSIGTYPE
2542 TimerHandler(int sig)
2544 int dn;
2545 char *sp;
2546 char *parsed_command;
2548 timer->timeout.timeleft--;
2549 if (timer->timeout.timeleft <= 0) {
2550 /* pre-command */
2551 if (!XWithdrawWindow(dpy, CF.frame, screen))
2553 /* hm, what can we do now? just ignore this situation. */
2556 /* construct command */
2557 parsed_command = ParseCommand(0, timer->timeout.command, '\0', &dn, &sp);
2558 myfprintf((stderr, "Final command: %s\n", parsed_command));
2560 /* send command */
2561 if ( parsed_command[0] == '!') { /* If command starts with ! */
2562 system(parsed_command+1); /* Need synchronous execution */
2563 } else {
2564 SendText(Channel,parsed_command, ref);
2567 /* post-command */
2568 if (CF.last_error) { /* if form has last_error field */
2569 memset(CF.last_error->text.value, ' ', CF.last_error->text.n); /* clear */
2570 /* To do this more elegantly, the window resize logic should recalculate
2571 size_x for the Message as the window resizes. Right now, just clear
2572 a nice wide area. dje */
2573 XClearArea(dpy,CF.frame,
2574 CF.last_error->header.pos_x,
2575 CF.last_error->header.pos_y,
2576 /* CF.last_error->header.size_x, */
2577 2000,
2578 CF.last_error->header.size_y, False);
2579 } /* end form has last_error field */
2580 if (CF.grab_server)
2581 XUngrabServer(dpy);
2582 /* This is a temporary bug workaround for the pipe drainage problem */
2583 SendQuitNotification(Channel); /* let commands complete */
2584 /* Note how the window is withdrawn, but execution continues until
2585 the quit notifcation catches up with this module...
2586 Should not be a problem, there shouldn't be any more commands
2587 coming into FvwmForm. dje */
2589 else {
2590 RedrawTimeout(timer);
2591 alarm(1);
2594 SIGNAL_RETURN;
2598 /* main procedure */
2599 int main (int argc, char **argv)
2601 int i;
2602 char cmd[200];
2604 #ifdef DEBUGTOFILE
2605 freopen(".FvwmFormDebug","w",stderr);
2606 #endif
2608 FlocaleInit(LC_CTYPE, "", "", "FvwmForm");
2610 module = ParseModuleArgs(argc,argv,1); /* allow an alias */
2611 if (module == NULL)
2613 fprintf(
2614 stderr,
2615 "FvwmForm Version "VERSION" should only be executed by fvwm!\n");
2616 exit(1);
2619 #ifdef HAVE_SIGACTION
2621 struct sigaction sigact;
2623 #ifdef SA_INTERRUPT
2624 sigact.sa_flags = SA_INTERRUPT;
2625 #else
2626 sigact.sa_flags = 0;
2627 #endif
2628 sigemptyset(&sigact.sa_mask);
2629 sigaddset(&sigact.sa_mask, SIGTERM);
2630 sigaddset(&sigact.sa_mask, SIGPIPE);
2631 sigaddset(&sigact.sa_mask, SIGINT);
2632 sigact.sa_handler = TerminateHandler;
2634 sigaction(SIGPIPE, &sigact, NULL);
2635 sigaction(SIGTERM, &sigact, NULL);
2636 sigaction(SIGINT, &sigact, NULL);
2638 #else
2639 #ifdef USE_BSD_SIGNALS
2640 fvwmSetSignalMask( sigmask(SIGPIPE) | sigmask(SIGTERM) | sigmask(SIGINT) );
2641 #endif
2642 signal(SIGPIPE, TerminateHandler); /* Dead pipe == Fvwm died */
2643 signal(SIGTERM, TerminateHandler);
2644 signal(SIGINT, TerminateHandler);
2645 #ifdef HAVE_SIGINTERRUPT
2646 siginterrupt(SIGPIPE, 1);
2647 siginterrupt(SIGTERM, 1);
2648 siginterrupt(SIGINT, 1);
2649 #endif
2650 #endif
2652 Channel[0] = module->to_fvwm;
2653 Channel[1] = module->from_fvwm;
2655 dpy = XOpenDisplay("");
2656 if (dpy==NULL) {
2657 fprintf(stderr,"%s: could not open display\n",module->name);
2658 exit(1);
2660 /* From FvwmAnimate end */
2662 i = 7;
2663 if (argc >= 8) { /* if have arg 7 */
2664 if (strcasecmp(argv[7],"preload") == 0) { /* if its preload */
2665 preload_yorn = 'y'; /* remember that. */
2666 i = 8;
2669 for (;i<argc;i++) { /* look at remaining args */
2670 if (strchr(argv[i],'=')) { /* if its a candidate */
2671 putenv(argv[i]); /* save it away */
2672 CF.have_env_var = 'y'; /* remember we have at least one */
2675 ref = strtol(argv[4], NULL, 16); /* capture reference window */
2676 if (ref == 0) ref = None;
2677 myfprintf((stderr, "ref == %d\n", (int)ref));
2679 flib_init_graphics(dpy);
2681 fd_x = XConnectionNumber(dpy);
2683 screen = DefaultScreen(dpy);
2684 root = RootWindow(dpy, screen);
2686 InitConstants();
2687 ReadDefaults(); /* get config from fvwm */
2689 if (strcasecmp(module->name,"FvwmForm") != 0) { /* if not already read */
2690 sprintf(cmd,"read %s Quiet",module->name); /* read quiet modules config */
2691 SendText(Channel,cmd,0);
2694 ReadConfig(); /* get config from fvwm */
2696 MassageConfig(); /* add data, calc window x/y */
2698 /* tell fvwm about our mask */
2699 SetMessageMask(Channel, M_SENDCONFIG|M_CONFIG_INFO|M_ERROR|M_STRING);
2700 SetMessageMask(Channel, MX_PROPERTY_CHANGE);
2701 XSetErrorHandler(ErrorHandler);
2702 OpenWindows(); /* create initial window */
2703 SendFinishedStartupNotification(Channel);/* tell fvwm we're running */
2704 if (timer != NULL) {
2705 SetupTimer();
2707 MainLoop(); /* start */
2709 return 0; /* */
2713 RETSIGTYPE DeadPipe(int nonsense)
2715 exit(0);
2716 SIGNAL_RETURN;
2720 X Error Handler
2722 static int
2723 ErrorHandler(Display *dpy, XErrorEvent *event)
2725 /* some errors are OK=ish */
2726 if (event->error_code == BadPixmap)
2727 return 0;
2728 if (event->error_code == BadDrawable)
2729 return 0;
2730 if (FRenderGetErrorCodeBase() + FRenderBadPicture == event->error_code)
2731 return 0;
2733 PrintXErrorAndCoredump(dpy, event, module->name);
2734 return 0;