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
30 #include "libs/ftime.h"
35 #include <X11/Xutil.h>
36 #include <X11/cursorfont.h>
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 */
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 */
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 */
78 int fd_x
; /* fd for X connection */
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';
88 char *screen_background_color
;
89 static ModuleArgs
*module
;
91 Bool Swallowed
= False
;
95 . defaults are changed by commands during parse
96 . copied into items during parse
97 . displayed in the customization dialog
100 int itemcolorset
= 0;
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
;
117 sigact
.sa_flags
= SA_INTERRUPT
;
121 sigemptyset(&sigact
.sa_mask
);
122 sigaddset(&sigact
.sa_mask
, SIGALRM
);
123 sigact
.sa_handler
= TimerHandler
;
125 sigaction(SIGALRM
, &sigact
, NULL
);
128 #ifdef USE_BSD_SIGNALS
129 fvwmSetSignalMask( sigmask(SIGALRM
) );
131 signal(SIGALRM
, TimerHandler
); /* Dead pipe == Fvwm died */
132 #ifdef HAVE_SIGINTERRUPT
133 siginterrupt(SIGALRM
, 1);
140 /* copy a string until '"', or '\n', or '\0' */
141 static char *CopyQuotedString (char *cp
)
144 bp
= dp
= (char *)safemalloc(strlen(cp
) + 1);
146 switch (c
= *(cp
++)) {
163 /* copy a string until the first space */
164 static char *CopySolidString (char *cp
)
167 bp
= dp
= (char *)safemalloc(strlen(cp
) + 1);
173 } else if (isspace((unsigned char)c
) || c
== '\0') {
181 /* Command parsing section */
183 /* FvwmAnimate++ type command table */
184 typedef struct CommandTable
187 void (*function
)(char *);
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
},
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
},
245 {"Geometry",ct_Geometry
},
246 {"GrabServer",ct_GrabServer
},
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
},
256 {"Message",ct_Message
},
257 {"PadVText",ct_padVText
},
258 {"Position",ct_Position
},
259 {"Selection",ct_Selection
},
261 {"Timeout",ct_Timeout
},
262 {"TimeoutFont",ct_TimeoutFont
},
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
},
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
},
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
},
291 {"TimeoutFont",ct_TimeoutFont
}
294 /* If there were vars on the command line, do env var sustitution on
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
)
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) {
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 */
337 static void ParseConfigLine(char *buf
)
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);
351 if (strncasecmp(buf
, "Colorset", 8) == 0) {
352 LoadColorset(&buf
[8]);
355 if (strncasecmp(buf
, CatString3("*",module
->name
,0), module
->namelen
+1) != 0) {/* If its not for me */
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" */
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
);
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 */
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 */
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", "" */
406 if (strlen(cp
) > 5) {
407 fprintf(stderr
,"%s: arg for ActivateOnPress (%s) too long\n",
411 for (i
=0,j
=0;i
<strlen(cp
);i
++) {
412 if (cp
[i
] != ' ') { /* remove any spaces */
413 option
[j
++]=tolower(cp
[i
]);
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;
427 fprintf(stderr
,"%s: arg for ActivateOnPress (%s/%s) invalid\n",
428 module
->name
,option
,cp
);
431 static void ct_GrabServer(char *cp
)
435 static void ct_WarpPointer(char *cp
)
439 static void ct_Position(char *cp
)
449 while (!isspace((unsigned char)*cp
)) cp
++;
450 while (isspace((unsigned char)*cp
)) cp
++;
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
)
474 flags
= FScreenParseGeometry(cp
, &x
, &y
, &dummy
, &dummy
);
479 CF
.xneg
= (flags
&XNegative
);
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
);
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
);
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 */
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
);
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
);
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
)
564 cursor
=fvwmCursorNameToIndex(cp
);
566 fprintf(stderr
,"ButtonInPointer: invalid cursor name %s\n",cp
);
568 CF
.pointer
[button_in_pointer
] = XCreateFontCursor(dpy
,cursor
);
571 static void ct_ButtonPointer(char *cp
)
574 cursor
=fvwmCursorNameToIndex(cp
);
576 fprintf(stderr
,"ButtonPointer: invalid cursor name %s\n",cp
);
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
)
591 cursor
=fvwmCursorNameToIndex(cp
);
593 fprintf(stderr
,"InputPointer: invalid cursor name %s\n",cp
);
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
);
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
;
642 cur_line
->justify
= L_LEFTRIGHT
;
644 /* Define an area on the form that contains the current
646 syntax: *FFMessage Length nn, Font fn, Fore color, Back color
648 font,fg.bg default to text.
651 static void ct_Message(char *cp
)
654 bg_state
= 'u'; /* indicate b/g color now used. */
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 */
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
,
665 item
->text
.n
/4) * 4) + 2 * TEXT_SPC
;
666 item
->header
.size_y
= item
->header
.dt_ptr
->dt_Ffont
->height
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
));
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
)
679 int xgcv_mask
= GCForeground
;
681 if (dt
->dt_used
== 2) { /* fonts colors shadows */
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
)
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 */
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
)
720 xgcv
.font
= dt
->dt_Ffont
->font
->fid
;
722 dt
->dt_item_GC
= fvwmlib_XCreateGC(dpy
, CF
.frame
, xgcv_mask
, &xgcv
);
724 dt
->dt_colors
[c_itemlo
] = PictureBlackPixel();
725 dt
->dt_colors
[c_itemhi
] = PictureWhitePixel();
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
;
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
];
760 match_font
= font_names
[f_button
]; /* choices same as buttons */
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 */
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 */
775 } /* end all drawtables checked, no match */
777 /* Time to add a DrawTable */
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)
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>" */
822 bg_state
= 'u'; /* indicate b/g color now used. */
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
= "";
829 item
->text
.value
= CopyQuotedString(++cp
);
831 item
->text
.value
= "";
832 item
->text
.n
= strlen(item
->text
.value
);
834 item
->header
.size_x
= FlocaleTextWidth(item
->header
.dt_ptr
->dt_Ffont
,
836 item
->text
.n
) + 2 * TEXT_SPC
;
837 item
->header
.size_y
= item
->header
.dt_ptr
->dt_Ffont
->height
839 myfprintf((stderr
, "Text \"%s\" [%d, %d]\n", item
->text
.value
,
840 item
->header
.size_x
, item
->header
.size_y
));
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>" */
850 CF
.title
= CopyQuotedString(++cp
);
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
;
861 fprintf(stderr
,"Only one timeout per form allowed, skipped %s.\n",cp
);
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;
883 while (*cp
&& *cp
!= '\n' && !isspace((unsigned char)*cp
)) cp
++;
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");
894 item
->timeout
.command
= CopyQuotedString(++cp
);
895 /* skip over the whole quoted string to continue parsing */
896 cp
+= strlen(item
->timeout
.command
) + 1;
899 tmpbuf
= safestrdup(cp
);
901 while (!isspace((unsigned char)*tmpcp
)) tmpcp
++;
902 *tmpcp
= '\0'; /* cutoff command at first word */
903 item
->timeout
.command
= safestrdup(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");
917 item
->timeout
.text
= CopyQuotedString(++cp
);
919 item
->timeout
.text
= "";
920 item
->timeout
.len
= strlen(item
->timeout
.text
);
922 item
->header
.size_x
= FlocaleTextWidth(item
->header
.dt_ptr
->dt_Ffont
,
924 item
->timeout
.len
) + 2 * TEXT_SPC
;
925 item
->header
.size_y
= item
->header
.dt_ptr
->dt_Ffont
->height
927 myfprintf((stderr
, "Timeout %d \"%s\" [%d, %d]\n", item
->timeout
.timeleft
,
928 item
->timeout
.text
, item
->header
.size_x
, item
->header
.size_y
));
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
)
940 /* syntax: *FFInput <name> <size> "<init_value>" */
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 */
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
));
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
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");
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 */
1008 /* Cant do the actual reading of the data file here,
1009 we are already in a readconfig loop. */
1011 static void ReadFormData(void)
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 */
1030 CF
.file_to_read
= 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
)
1046 var_name
= CopySolidString(cp
); /* var */
1047 if (*var_name
== 0) {
1050 cp
+= strlen(var_name
);
1051 while (isspace((unsigned char)*cp
)) cp
++;
1053 if (CF
.cur_input
!= 0) {
1054 item
= CF
.cur_input
;
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 */
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 */
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
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... */
1103 i
<item
->selection
.n
;
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;
1110 choice_ptr
->choice
.init_on
= 0;
1112 } /* end all choices */
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 */
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
;
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",
1142 bg_state
= 'u'; /* indicate b/g color now used. */
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;
1155 item
->choice
.init_on
= 0;
1156 while (!isspace((unsigned char)*cp
)) cp
++;
1157 while (isspace((unsigned char)*cp
)) cp
++;
1159 item
->choice
.text
= CopyQuotedString(++cp
);
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
,
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
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
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
));
1186 static void ct_Button(char *cp
)
1188 /* syntax: *FFButton continue | restart | quit "<text>" */
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
;
1198 item
->button
.key
= IB_CONTINUE
;
1199 while (!isspace((unsigned char)*cp
)) cp
++;
1200 while (isspace((unsigned char)*cp
)) cp
++;
1202 item
->button
.text
= CopyQuotedString(++cp
);
1203 cp
+= strlen(item
->button
.text
) + 1;
1204 while (isspace((unsigned char)*cp
)) cp
++;
1206 item
->button
.text
= "";
1208 item
->button
.keypress
= *(++cp
) - '@';
1209 else if (*cp
== 'F')
1210 item
->button
.keypress
= 256 + atoi(++cp
);
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
,
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
,
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"
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"));
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 */
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 */
1311 /* After this config is read, figure it out */
1312 static void MassageConfig(void)
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 */
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 */
1339 switch (line
->justify
) {
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
;
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
;
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
;
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
1369 for (i
= 0 ; i
< line
->n
; i
++) {
1370 if (line
->items
[i
]->type
== I_INPUT
)
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
;
1381 extra
= (CF
.max_width
- line
->size_x
) / (line
->n
- 1);
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
;
1389 extra
= (CF
.max_width
- line
->size_x
) / extra
;
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
;
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)
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
) {
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 */
1429 prior
= item
->input
.value_history_count
- 1;
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",
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 */
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;
1471 item
->choice
.on
= item
->choice
.init_on
;
1477 /* redraw the frame */
1478 void RedrawFrame(XEvent
*pev
)
1481 Region region
= None
;
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
)
1492 item
= item
->header
.next
;
1498 pev
->xexpose
.x
, pev
->xexpose
.y
,
1499 pev
->xexpose
.width
, pev
->xexpose
.height
,
1504 XClearWindow(dpy
, CF
.frame
);
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
)
1526 dt_ptr
->dt_Fstr
->flags
.has_clip_region
= True
;
1527 dt_ptr
->dt_Fstr
->clip_region
= region
;
1531 dt_ptr
->dt_Fstr
->flags
.has_clip_region
= False
;
1534 switch (item
->type
) {
1539 RedrawTimeout(item
);
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
1558 FlocaleDrawString(dpy
,
1564 if (dt_ptr
&& dt_ptr
->dt_Fstr
)
1566 dt_ptr
->dt_Fstr
->flags
.has_clip_region
= False
;
1571 XDestroyRegion(region
);
1575 void RedrawText(Item
*item
)
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
))
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
;
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
);
1602 void RedrawTimeout(Item
*item
)
1605 char *tmpbuf
, *tmpptr
, *tmpbptr
;
1608 XClearArea(dpy
, CF
.frame
,
1609 item
->header
.pos_x
, item
->header
.pos_y
,
1610 item
->header
.size_x
, item
->header
.size_y
,
1613 tmpbuf
= safemalloc(item
->timeout
.len
+ 6);
1615 for (tmpptr
= item
->timeout
.text
; *tmpptr
!= '\0' &&
1616 !(tmpptr
[0] == '%' && tmpptr
[1] == '%'); tmpptr
++) {
1620 if (tmpptr
[0] == '%') {
1622 sprintf(tmpbptr
, "%d", item
->timeout
.timeleft
);
1623 tmpbptr
+= strlen(tmpbptr
);
1625 for (; *tmpptr
!= '\0'; tmpptr
++) {
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
))
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
;
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
);
1662 /* redraw an item */
1663 void RedrawItem (Item
*item
, int click
, XEvent
*pev
)
1666 static XSegment xsegs
[4];
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;
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. */
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
,
1691 /* If its not an expose event, the area assume the
1692 whole item is intersected. */
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
);
1704 dt_ptr
->dt_Fstr
->flags
.has_clip_region
= True
;
1705 dt_ptr
->dt_Fstr
->clip_region
= region
;
1709 dt_ptr
->dt_Fstr
->flags
.has_clip_region
= False
;
1713 switch (item
->type
) {
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
,
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
,
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
,
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
;
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
)
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
));
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
,
1832 XDrawArc(dpy
, item
->header
.win
, item
->header
.dt_ptr
->dt_item_GC
,
1833 5, 5, dx
- 10, dy
- 10, 0, 360 * 64);
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
]);
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
,
1853 if (item
->choice
.on
)
1854 XSetForeground(dpy
, item
->header
.dt_ptr
->dt_item_GC
,
1855 item
->header
.dt_ptr
->dt_colors
[c_itemhi
]);
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
,
1875 dx
= item
->header
.size_x
- 1;
1876 dy
= item
->header
.size_y
- 1;
1878 XSetForeground(dpy
, item
->header
.dt_ptr
->dt_item_GC
,
1879 item
->header
.dt_ptr
->dt_colors
[c_itemlo
]);
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
,
1894 XSetForeground(dpy
, item
->header
.dt_ptr
->dt_item_GC
,
1895 item
->header
.dt_ptr
->dt_colors
[c_itemhi
]);
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
,
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
;
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
));
1937 if (dt_ptr
&& dt_ptr
->dt_Fstr
)
1939 dt_ptr
->dt_Fstr
->flags
.has_clip_region
= False
;
1943 XDestroyRegion(region
);
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
)
1954 if (CSET_IS_TRANSPARENT(colorset
))
1956 if (CSET_IS_TRANSPARENT_PR_PURE(colorset
))
1958 XClearArea(dpy
, CF
.frame
, 0,0,0,0, False
);
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
);
1972 XClearArea(dpy
, CF
.frame
, 0,0,0,0, False
);
1977 if (!root_item_ptr
->header
.next
|| !CSET_IS_TRANSPARENT(itemcolorset
))
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
))
1991 if (CSET_IS_TRANSPARENT_PR_PURE(itemcolorset
))
1994 dpy
, item
->header
.win
, 0,0,0,0, False
);
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
);
2009 dpy
, item
->header
.win
, 0,0,0,0, False
);
2012 RedrawItem(item
, 0, NULL
);
2019 /* execute a command */
2020 void DoCommand (Item
*cmd
)
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
));
2042 if ( parsed_command
[0] == '!') { /* If command starts with ! */
2043 system(parsed_command
+1); /* Need synchronous execution */
2045 SendText(Channel
,parsed_command
, ref
);
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, */
2060 CF
.last_error
->header
.size_y
, False
);
2061 } /* end form has last_error field */
2062 if (cmd
->button
.key
== IB_QUIT
) {
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
) {
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)
2090 int gravity
= NorthWestGravity
;
2092 static XSetWindowAttributes xswa
;
2093 static XWMHints wmh
= { InputHint
, True
};
2094 static XSizeHints sh
=
2095 { PPosition
| PSize
| USPosition
| USSize
| PWinGravity
};
2096 XClassHint myclasshints
;
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
;
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
,
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 */
2151 x
= DisplayWidth(dpy
, screen
) - CF
.max_width
+ CF
.gx
;
2152 gravity
= NorthEastGravity
;
2160 y
= DisplayHeight(dpy
, screen
) - CF
.total_height
+ CF
.gy
;
2161 gravity
= SouthWestGravity
;
2167 if (CF
.xneg
&& CF
.yneg
)
2169 gravity
= SouthEastGravity
;
2171 scr
= FSCREEN_XYPOS
;
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
;
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
);
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
) {
2212 myfprintf((stderr
,"Checking alloc during OpenWindow on input\n"));
2213 CheckAlloc(item
,item
->header
.dt_ptr
); /* alloc colors and fonts needed */
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
);
2232 myfprintf((stderr
,"Checking alloc during Openwindow on choice\n"));
2233 CheckAlloc(item
,item
->header
.dt_ptr
); /* alloc colors and fonts needed */
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
);
2252 myfprintf((stderr
,"Checking alloc during Openwindow on button\n"));
2253 CheckAlloc(item
,item
->header
.dt_ptr
); /* alloc colors and fonts needed */
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
);
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
)
2304 process_message( packet
->type
, packet
->body
);
2306 static void process_message(unsigned long type
, unsigned long *body
)
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]);
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];
2326 if (CF
.last_error
) { /* if form has message area */
2327 /* ignore form size, its OK to write outside the window boundary */
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
,
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
,
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
);
2351 } /* module has last_error field */
2352 } /* end switch header */
2355 /* These are the message from fvwm FvwmForm understands after form is
2357 static void am_Map(char *);
2358 static void am_UnMap(char *);
2359 static void am_Stop(char *);
2360 static struct CommandTable am_table
[] =
2367 /* This is similar to the other 2 "Parse" functions. */
2368 static void ParseActiveMessage(char *buf
)
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)
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
;
2389 dt_ptr
->dt_used
= 0;
2392 XFreeGC(dpy
, dt_ptr
->dt_GC
);
2393 dt_ptr
->dt_GC
= None
;
2395 if(dt_ptr
->dt_item_GC
)
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
;
2410 CheckAlloc(item
, dt_ptr
);
2415 SetWindowBackground(
2416 dpy
, CF
.frame
, CF
.max_width
,
2418 &Colorset
[(colorset
)], Pdepth
,
2419 root_item_ptr
->header
.dt_ptr
->dt_GC
,
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 */
2441 } /* end colorset command */
2443 buf
, XINERAMA_CONFIG_STRING
, sizeof(XINERAMA_CONFIG_STRING
)-1)
2446 FScreenConfigureModule(buf
+ sizeof(XINERAMA_CONFIG_STRING
)-1);
2451 buf
, CatString3("*",module
->name
,0),
2452 module
->namelen
+1) != 0)
2454 /* If its not for me */
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 */
2463 /* this may be a configuration command of another same form */
2464 if (FindToken(p
, ct_table
, struct CommandTable
) == 0)
2466 stderr
,"%s: Active command unknown: %s\n",
2468 return; /* ignore it */
2471 p
=p
+strlen(e
->name
); /* skip over name */
2472 while (isspace((unsigned char)*p
)) p
++; /* skip whitespace */
2475 e
->function(p
); /* call cmd processor */
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)
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
))
2515 FD_SET(Channel
[1], &fds
);
2518 /* TA: 20091219: Using XFlush() here was always a nasty hack! See
2522 if (fvwmSelect(fd_width
, &fds
, NULL
, NULL
, NULL
) > 0) {
2523 if (FD_ISSET(Channel
[1], &fds
))
2525 if (FD_ISSET(fd_x
, &fds
))
2532 /* signal-handler to make the application quit */
2534 TerminateHandler(int sig
)
2536 fvwmSetTerminate(sig
);
2540 /* signal-handler to make the timer work */
2542 TimerHandler(int sig
)
2546 char *parsed_command
;
2548 timer
->timeout
.timeleft
--;
2549 if (timer
->timeout
.timeleft
<= 0) {
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
));
2561 if ( parsed_command
[0] == '!') { /* If command starts with ! */
2562 system(parsed_command
+1); /* Need synchronous execution */
2564 SendText(Channel
,parsed_command
, ref
);
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, */
2578 CF
.last_error
->header
.size_y
, False
);
2579 } /* end form has last_error field */
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 */
2590 RedrawTimeout(timer
);
2598 /* main procedure */
2599 int main (int argc
, char **argv
)
2605 freopen(".FvwmFormDebug","w",stderr
);
2608 FlocaleInit(LC_CTYPE
, "", "", "FvwmForm");
2610 module
= ParseModuleArgs(argc
,argv
,1); /* allow an alias */
2615 "FvwmForm Version "VERSION
" should only be executed by fvwm!\n");
2619 #ifdef HAVE_SIGACTION
2621 struct sigaction sigact
;
2624 sigact
.sa_flags
= SA_INTERRUPT
;
2626 sigact
.sa_flags
= 0;
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
);
2639 #ifdef USE_BSD_SIGNALS
2640 fvwmSetSignalMask( sigmask(SIGPIPE
) | sigmask(SIGTERM
) | sigmask(SIGINT
) );
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);
2652 Channel
[0] = module
->to_fvwm
;
2653 Channel
[1] = module
->from_fvwm
;
2655 dpy
= XOpenDisplay("");
2657 fprintf(stderr
,"%s: could not open display\n",module
->name
);
2660 /* From FvwmAnimate end */
2663 if (argc
>= 8) { /* if have arg 7 */
2664 if (strcasecmp(argv
[7],"preload") == 0) { /* if its preload */
2665 preload_yorn
= 'y'; /* remember that. */
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
);
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
) {
2707 MainLoop(); /* start */
2713 RETSIGTYPE
DeadPipe(int nonsense
)
2723 ErrorHandler(Display
*dpy
, XErrorEvent
*event
)
2725 /* some errors are OK=ish */
2726 if (event
->error_code
== BadPixmap
)
2728 if (event
->error_code
== BadDrawable
)
2730 if (FRenderGetErrorCodeBase() + FRenderBadPicture
== event
->error_code
)
2733 PrintXErrorAndCoredump(dpy
, event
, module
->name
);