Remove debug.
[fvwm.git] / fvwm / menustyle.c
blob81c37f0b94922f5d8c29474e517051b02ef3b9c9
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* ---------------------------- included header files ---------------------- */
19 #include "config.h"
21 #include <stdio.h>
22 #include <assert.h>
23 #include <X11/keysym.h>
25 #include "libs/fvwmlib.h"
26 #include "libs/Parse.h"
27 #include "libs/ColorUtils.h"
28 #include "libs/Picture.h"
29 #include "libs/PictureUtils.h"
30 #include "libs/Graphics.h"
31 #include "fvwm.h"
32 #include "externs.h"
33 #include "execcontext.h"
34 #include "functions.h"
35 #include "misc.h"
36 #include "screen.h"
37 #include "colorset.h"
38 #include "menustyle.h"
40 /* ---------------------------- local definitions -------------------------- */
42 /* ---------------------------- local macros ------------------------------- */
44 /* ---------------------------- imports ------------------------------------ */
46 /* ---------------------------- included code files ------------------------ */
48 /* ---------------------------- local types -------------------------------- */
50 /* ---------------------------- forward declarations ----------------------- */
52 /* ---------------------------- local variables ---------------------------- */
54 static MenuStyle *default_menu_style;
56 /* ---------------------------- exported variables (globals) --------------- */
58 /* ---------------------------- local functions ---------------------------- */
60 static void menustyle_free_face(MenuFace *mf)
62 switch (mf->type)
64 case GradientMenu:
65 if (Pdepth <= 8 && mf->u.grad.npixels > 0 &&
66 !mf->u.grad.do_dither)
68 Pixel *p;
69 int i;
71 p = (Pixel *)safemalloc(
72 mf->u.grad.npixels * sizeof(Pixel));
73 for(i=0; i < mf->u.grad.npixels; i++)
75 p[i] = mf->u.grad.xcs[i].pixel;
77 PictureFreeColors(
78 dpy, Pcmap, p, mf->u.grad.npixels, 0, False);
79 free(p);
81 free(mf->u.grad.xcs);
82 mf->u.grad.xcs = NULL;
83 break;
84 case PixmapMenu:
85 case TiledPixmapMenu:
86 if (mf->u.p)
88 PDestroyFvwmPicture(dpy, mf->u.p);
90 mf->u.p = NULL;
91 break;
92 case SolidMenu:
93 fvwmlib_free_colors(dpy, &mf->u.back, 1, True);
94 default:
95 break;
97 mf->type = SimpleMenu;
99 return;
102 static void menustyle_copy_face(MenuFace *destmf, MenuFace *origmf)
104 FvwmPictureAttributes fpa;
105 int i;
107 menustyle_free_face(destmf);
108 destmf->type = SimpleMenu;
109 switch (origmf->type)
111 case SolidMenu:
112 fvwmlib_copy_color(
113 dpy, &destmf->u.back, &origmf->u.back, False, True);
114 destmf->type = SolidMenu;
115 break;
116 case GradientMenu:
117 destmf->u.grad.xcs =
118 (XColor *)safemalloc(sizeof(XColor) *
119 origmf->u.grad.npixels);
120 memcpy(destmf->u.grad.xcs,
121 origmf->u.grad.xcs,
122 sizeof(XColor) * origmf->u.grad.npixels);
123 for (i = 0; i<origmf->u.grad.npixels;i++)
125 fvwmlib_clone_color(origmf->u.grad.xcs[i].pixel);
128 destmf->u.grad.npixels = origmf->u.grad.npixels;
129 destmf->u.grad.do_dither = origmf->u.grad.do_dither;
130 destmf->type = GradientMenu;
131 destmf->gradient_type = origmf->gradient_type;
132 break;
133 case PixmapMenu:
134 case TiledPixmapMenu:
135 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
136 destmf->u.p = PCacheFvwmPicture(
137 dpy, Scr.NoFocusWin, NULL, origmf->u.p->name,
138 fpa);
139 fvwmlib_copy_color(
140 dpy, &destmf->u.back, &origmf->u.back, False,True);
141 destmf->type = origmf->type;
142 break;
143 default:
144 break;
150 * Reads a menu face line into a structure (veliaa@rpi.edu)
153 static Boolean menustyle_parse_face(char *s, MenuFace *mf, int verbose)
155 char *style;
156 char *token;
157 char *action = s;
158 FvwmPictureAttributes fpa;
160 s = GetNextToken(s, &style);
161 if (style && strncasecmp(style, "--", 2) == 0)
163 free(style);
164 return True;
167 menustyle_free_face(mf);
168 mf->type = SimpleMenu;
170 /* determine menu style */
171 if (!style)
173 return True;
175 else if (StrEquals(style,"Solid"))
177 s = GetNextToken(s, &token);
178 if (token)
180 mf->type = SolidMenu;
181 mf->u.back = GetColor(token);
182 free(token);
184 else
186 if (verbose)
188 fvwm_msg(ERR, "menustyle_parse_face",
189 "no color given for Solid face type:"
190 " %s", action);
192 free(style);
193 return False;
197 else if (StrEquals(style+1, "Gradient"))
199 char **s_colors;
200 int npixels, nsegs, *perc;
201 XColor *xcs;
203 if (!IsGradientTypeSupported(style[0]))
205 return False;
208 /* translate the gradient string into an array of colors etc */
209 npixels = ParseGradient(s, NULL, &s_colors, &perc, &nsegs);
210 if (npixels <= 0)
212 return False;
214 /* dither ? */
215 mf->u.grad.do_dither = False;
216 if (Pdepth <= 8)
218 mf->u.grad.do_dither = True;
220 /* grab the colors */
221 xcs = AllocAllGradientColors(
222 s_colors, perc, nsegs, npixels, mf->u.grad.do_dither);
223 if (xcs == None)
225 return False;
228 mf->u.grad.xcs = xcs;
229 mf->u.grad.npixels = npixels;
230 mf->type = GradientMenu;
231 mf->gradient_type = toupper(style[0]);
234 else if (StrEquals(style,"Pixmap") || StrEquals(style,"TiledPixmap"))
236 s = GetNextToken(s, &token);
237 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
238 if (token)
240 mf->u.p = PCacheFvwmPicture(
241 dpy, Scr.NoFocusWin, NULL, token, fpa);
242 if (mf->u.p == NULL)
244 if (verbose)
246 fvwm_msg(ERR, "menustyle_parse_face",
247 "couldn't load pixmap %s",
248 token);
250 free(token);
251 free(style);
252 return False;
254 free(token);
255 mf->type = (StrEquals(style,"TiledPixmap")) ?
256 TiledPixmapMenu : PixmapMenu;
258 else
260 if (verbose)
262 fvwm_msg(ERR, "menustyle_parse_face",
263 "missing pixmap name for style %s",
264 style);
266 free(style);
267 return False;
270 else
272 if (verbose)
274 fvwm_msg(
275 ERR,
276 "menustyle_parse_face", "unknown style %s: %s",
277 style, action);
279 free(style);
280 return False;
282 free(style);
284 return True;
287 static void parse_vertical_spacing_line(
288 char *args, signed char *above, signed char *below,
289 signed char above_default, signed char below_default)
291 int val[2];
293 if (GetIntegerArguments(args, NULL, val, 2) != 2 ||
294 val[0] < MIN_VERTICAL_SPACING || val[0] > MAX_VERTICAL_SPACING ||
295 val[1] < MIN_VERTICAL_SPACING || val[1] > MAX_VERTICAL_SPACING)
297 /* illegal or missing parameters, return to default */
298 *above = above_default;
299 *below = below_default;
300 return;
302 *above = val[0];
303 *below = val[1];
305 return;
308 static void parse_vertical_margins_line(
309 char *args, unsigned char *top, unsigned char *bottom,
310 signed char top_default, signed char bottom_default)
312 int val[2];
314 if (GetIntegerArguments(args, NULL, val, 2) != 2 ||
315 val[0] < 0 || val[0] > MAX_MENU_MARGIN ||
316 val[1] < 0 || val[1] > MAX_MENU_MARGIN)
318 /* invalid or missing parameters, return to default */
319 *top = top_default;
320 *bottom = bottom_default;
321 return;
323 *top = val[0];
324 *bottom = val[1];
326 return;
329 static MenuStyle *menustyle_parse_old_style(F_CMD_ARGS)
331 char *buffer, *rest;
332 char *fore, *back, *stipple, *font, *style, *animated;
333 MenuStyle *ms = NULL;
335 rest = GetNextToken(action,&fore);
336 rest = GetNextToken(rest,&back);
337 rest = GetNextToken(rest,&stipple);
338 rest = GetNextToken(rest,&font);
339 rest = GetNextToken(rest,&style);
340 rest = GetNextToken(rest,&animated);
342 if (!fore || !back || !stipple || !font || !style)
344 fvwm_msg(ERR, "menustyle_parse_old_style",
345 "error in %s style specification", action);
347 else
349 buffer = (char *)alloca(strlen(action) + 100);
350 sprintf(buffer,
351 "* \"%s\", Foreground \"%s\", Background \"%s\", "
352 "Greyed \"%s\", Font \"%s\", \"%s\"",
353 style, fore, back, stipple, font,
354 (animated && StrEquals(animated, "anim")) ?
355 "Animation" : "AnimationOff");
356 fvwm_msg(OLD, "menustyle_parse_old_style",
357 "The old MenuStyle snytax has been deprecated. "
358 "Use 'MenuStyle %s' instead of 'MenuStyle %s'\n",
359 buffer, action);
360 action = buffer;
361 ms = menustyle_parse_style(F_PASS_ARGS);
364 if (fore)
366 free(fore);
368 if (back)
370 free(back);
372 if (stipple)
374 free(stipple);
376 if (font)
378 free(font);
380 if (style)
382 free(style);
384 if (animated)
386 free(animated);
389 return ms;
392 static int menustyle_get_styleopt_index(char *option)
394 char *optlist[] = {
395 "fvwm", "mwm", "win",
396 "Foreground", "Background", "Greyed",
397 "HilightBack", "HilightBackOff",
398 "ActiveFore", "ActiveForeOff",
399 "Hilight3DThick", "Hilight3DThin", "Hilight3DOff",
400 "Animation", "AnimationOff",
401 "Font",
402 "MenuFace",
403 "PopupDelay", "PopupOffset",
404 "TitleWarp", "TitleWarpOff",
405 "TitleUnderlines0", "TitleUnderlines1", "TitleUnderlines2",
406 "SeparatorsLong", "SeparatorsShort",
407 "TrianglesSolid", "TrianglesRelief",
408 "PopupImmediately", "PopupDelayed",
409 "DoubleClickTime",
410 "SidePic", "SideColor",
411 "PopupAsRootmenu", "PopupAsSubmenu",
412 "RemoveSubmenus", "HoldSubmenus",
413 "SubmenusRight", "SubmenusLeft",
414 "BorderWidth",
415 "Hilight3DThickness",
416 "ItemFormat",
417 "AutomaticHotkeys", "AutomaticHotkeysOff",
418 "VerticalItemSpacing",
419 "VerticalTitleSpacing",
420 "MenuColorset", "ActiveColorset", "GreyedColorset",
421 "SelectOnRelease",
422 "PopdownImmediately", "PopdownDelayed",
423 "PopdownDelay",
424 "PopupActiveArea",
425 "PopupIgnore", "PopupClose",
426 "MouseWheel", "ScrollOffPage",
427 "TrianglesUseFore",
428 "TitleColorset", "HilightTitleBack",
429 "TitleFont",
430 "VerticalMargins",
431 NULL
434 return GetTokenIndex(option, optlist, 0, NULL);
437 static void change_or_make_gc(GC *gc, unsigned long gcm, XGCValues *gcv)
439 if (*gc != None)
441 XChangeGC(dpy, *gc, gcm, gcv);
443 else
445 *gc = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, gcv);
448 return;
451 /* ---------------------------- interface functions ------------------------ */
453 MenuStyle *menustyle_get_default_style(void)
455 return default_menu_style;
458 void menustyle_free(MenuStyle *ms)
460 MenuStyle *before = default_menu_style;
462 if (!ms)
464 return;
466 menustyle_free_face(&ST_FACE(ms));
467 if (FORE_GC(ST_MENU_INACTIVE_GCS(ms)))
469 XFreeGC(dpy, FORE_GC(ST_MENU_INACTIVE_GCS(ms)));
471 if (FORE_GC(ST_MENU_ACTIVE_GCS(ms)))
473 XFreeGC(dpy, FORE_GC(ST_MENU_ACTIVE_GCS(ms)));
475 if (BACK_GC(ST_MENU_ACTIVE_GCS(ms)))
477 XFreeGC(dpy, BACK_GC(ST_MENU_ACTIVE_GCS(ms)));
479 if (HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)))
481 XFreeGC(dpy, HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)));
483 if (SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)))
485 XFreeGC(dpy, SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)));
487 if (HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)))
489 XFreeGC(dpy, HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)));
491 if (SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)))
493 XFreeGC(dpy, SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)));
495 if (FORE_GC(ST_MENU_STIPPLE_GCS(ms)))
497 XFreeGC(dpy, FORE_GC(ST_MENU_STIPPLE_GCS(ms)));
499 if (FORE_GC(ST_MENU_TITLE_GCS(ms)))
501 XFreeGC(dpy, FORE_GC(ST_MENU_TITLE_GCS(ms)));
503 if (BACK_GC(ST_MENU_TITLE_GCS(ms)))
505 XFreeGC(dpy, BACK_GC(ST_MENU_TITLE_GCS(ms)));
507 if (HILIGHT_GC(ST_MENU_TITLE_GCS(ms)))
509 XFreeGC(dpy, HILIGHT_GC(ST_MENU_TITLE_GCS(ms)));
511 if (SHADOW_GC(ST_MENU_TITLE_GCS(ms)))
513 XFreeGC(dpy, SHADOW_GC(ST_MENU_TITLE_GCS(ms)));
515 if (ST_SIDEPIC(ms))
517 PDestroyFvwmPicture(dpy, ST_SIDEPIC(ms));
519 if (ST_HAS_SIDE_COLOR(ms) == 1)
521 fvwmlib_free_colors(dpy, &ST_SIDE_COLOR(ms), 1, True);
523 if (ST_PSTDFONT(ms) && !ST_USING_DEFAULT_FONT(ms))
525 FlocaleUnloadFont(dpy, ST_PSTDFONT(ms));
527 if (ST_PTITLEFONT(ms) && !ST_USING_DEFAULT_TITLEFONT(ms))
529 FlocaleUnloadFont(dpy, ST_PTITLEFONT(ms));
531 if (ST_ITEM_FORMAT(ms))
533 free(ST_ITEM_FORMAT(ms));
536 fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).back,1,True);
537 fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).fore,1,True);
538 if (ST_HAS_STIPPLE_FORE(ms))
540 fvwmlib_free_colors(
541 dpy, &ST_MENU_STIPPLE_COLORS(ms).fore,1,True);
543 if (ST_HAS_ACTIVE_BACK(ms))
545 fvwmlib_free_colors(
546 dpy, &ST_MENU_ACTIVE_COLORS(ms).back,1,True);
548 if (ST_HAS_ACTIVE_FORE(ms))
550 fvwmlib_free_colors(
551 dpy, &ST_MENU_ACTIVE_COLORS(ms).fore,1,True);
554 while (ST_NEXT_STYLE(before) != ms)
556 /* Not too many checks, may segfault in race conditions */
557 before = ST_NEXT_STYLE(before);
560 ST_NEXT_STYLE(before) = ST_NEXT_STYLE(ms);
561 free(ST_NAME(ms));
562 free(ms);
564 return;
567 MenuStyle *menustyle_find(char *name)
569 MenuStyle *ms = default_menu_style;
571 while (ms)
573 if (strcasecmp(ST_NAME(ms),name)==0)
575 return ms;
577 ms = ST_NEXT_STYLE(ms);
580 return NULL;
583 void menustyle_update(MenuStyle *ms)
585 XGCValues gcv;
586 unsigned long gcm;
587 color_quad c_inactive;
588 color_quad c_active;
589 color_quad c_stipple;
590 color_quad c_title;
591 colorset_t *menu_cs = &Colorset[ST_CSET_MENU(ms)];
592 colorset_t *active_cs = &Colorset[ST_CSET_ACTIVE(ms)];
593 colorset_t *greyed_cs = &Colorset[ST_CSET_GREYED(ms)];
594 colorset_t *title_cs = &Colorset[ST_CSET_TITLE(ms)];
596 if (ST_USAGE_COUNT(ms) != 0)
598 fvwm_msg(ERR,"menustyle_update", "menu style %s is in use",
599 ST_NAME(ms));
600 return;
602 ST_IS_UPDATED(ms) = 1;
603 if (ST_USING_DEFAULT_FONT(ms))
605 ST_PSTDFONT(ms) = Scr.DefaultFont;
607 if (ST_USING_DEFAULT_TITLEFONT(ms))
609 ST_PTITLEFONT(ms) = ST_PSTDFONT(ms);
611 /* calculate colors based on foreground */
612 if (!ST_HAS_ACTIVE_FORE(ms))
614 ST_MENU_ACTIVE_COLORS(ms).fore = ST_MENU_COLORS(ms).fore;
616 /* calculate colors based on background */
617 if (!ST_HAS_ACTIVE_BACK(ms))
619 ST_MENU_ACTIVE_COLORS(ms).back = ST_MENU_COLORS(ms).back;
621 if (!ST_HAS_STIPPLE_FORE(ms))
623 ST_MENU_STIPPLE_COLORS(ms).fore = ST_MENU_COLORS(ms).back;
625 ST_MENU_STIPPLE_COLORS(ms).back = ST_MENU_COLORS(ms).back;
626 /* prepare colours for changing the gcs */
627 if (ST_HAS_MENU_CSET(ms))
629 c_inactive.fore = menu_cs->fg;
630 c_inactive.back = menu_cs->bg;
631 c_inactive.hilight = menu_cs->hilite;
632 c_inactive.shadow = menu_cs->shadow;
634 else
636 c_inactive.fore = ST_MENU_COLORS(ms).fore;
637 c_inactive.back = ST_MENU_COLORS(ms).back;
638 if (Pdepth > 2)
640 c_inactive.hilight = GetHilite(ST_MENU_COLORS(ms).back);
641 c_inactive.shadow = GetShadow(ST_MENU_COLORS(ms).back);
643 else
645 c_inactive.hilight = GetColor(DEFAULT_HILIGHT_COLOR);
646 c_inactive.shadow = GetColor(DEFAULT_SHADOW_COLOR);
649 if (ST_HAS_ACTIVE_CSET(ms))
651 c_active.fore = active_cs->fg;
652 c_active.back = active_cs->bg;
653 c_active.hilight = active_cs->hilite;
654 c_active.shadow = active_cs->shadow;
656 else
658 c_active.fore = ST_MENU_ACTIVE_COLORS(ms).fore;
659 c_active.back = ST_MENU_ACTIVE_COLORS(ms).back;
660 if (Pdepth > 2)
662 c_active.hilight =
663 GetHilite(ST_MENU_ACTIVE_COLORS(ms).back);
664 c_active.shadow =
665 GetShadow(ST_MENU_ACTIVE_COLORS(ms).back);
667 else
669 c_active.hilight = GetColor(DEFAULT_HILIGHT_COLOR);
670 c_active.shadow = GetColor(DEFAULT_SHADOW_COLOR);
673 if (ST_HAS_GREYED_CSET(ms))
675 c_stipple.fore = greyed_cs->fg;
676 c_stipple.back = greyed_cs->fg;
678 else
680 c_stipple.fore = ST_MENU_STIPPLE_COLORS(ms).fore;
681 c_stipple.back = ST_MENU_STIPPLE_COLORS(ms).back;
683 if (ST_HAS_TITLE_CSET(ms))
685 c_title.fore = title_cs->fg;
686 c_title.back = title_cs->bg;
687 c_title.hilight = title_cs->hilite;
688 c_title.shadow = title_cs->shadow;
690 else
692 c_title.fore = c_inactive.fore;
693 c_title.back = c_inactive.back;
694 c_title.hilight = c_inactive.hilight;
695 c_title.shadow = c_inactive.shadow;
697 /* override hilighting colours if necessary */
698 if (!ST_DO_HILIGHT_FORE(ms))
700 c_active.fore = c_inactive.fore;
702 if (!ST_DO_HILIGHT_BACK(ms))
704 c_active.back = c_inactive.back;
705 c_active.hilight = c_inactive.hilight;
706 c_active.shadow = c_inactive.shadow;
708 if (!ST_DO_HILIGHT_TITLE_BACK(ms))
710 c_title.fore = c_inactive.fore;
711 c_title.back = c_inactive.back;
712 c_title.hilight = c_inactive.hilight;
713 c_title.shadow = c_inactive.shadow;
715 /* make GC's */
716 gcm = GCFunction|GCLineWidth|GCForeground|GCBackground;
717 if (ST_PSTDFONT(ms)->font != NULL)
719 gcm |= GCFont;
720 gcv.font = ST_PSTDFONT(ms)->font->fid;
722 gcv.function = GXcopy;
723 gcv.line_width = 0;
724 /* update inactive menu gcs */
725 gcv.foreground = c_inactive.fore;
726 gcv.background = c_inactive.back;
727 change_or_make_gc(&FORE_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
728 BACK_GC(ST_MENU_INACTIVE_GCS(ms)) = FORE_GC(ST_MENU_INACTIVE_GCS(ms));
729 gcv.foreground = c_inactive.hilight;
730 gcv.background = c_inactive.shadow;
731 change_or_make_gc(&HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
732 gcv.foreground = c_inactive.shadow;
733 gcv.background = c_inactive.hilight;
734 change_or_make_gc(&SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
735 /* update active menu gcs */
736 gcv.foreground = c_active.fore;
737 gcv.background = c_active.back;
738 change_or_make_gc(&FORE_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
739 gcv.foreground = c_active.back;
740 gcv.background = c_active.fore;
742 if (ST_HAS_ACTIVE_CSET(ms) && active_cs->pixmap &&
743 active_cs->pixmap_type == PIXMAP_TILED)
745 gcv.tile = active_cs->pixmap;
746 gcv.fill_style = FillTiled;
747 change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)),
748 gcm | GCFillStyle | GCTile , &gcv);
750 else
752 gcv.fill_style = FillSolid;
753 change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)),
754 gcm | GCFillStyle , &gcv);
758 gcv.foreground = c_active.hilight;
759 gcv.background = c_active.shadow;
760 change_or_make_gc(&HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
761 gcv.foreground = c_active.shadow;
762 gcv.background = c_active.hilight;
763 change_or_make_gc(&SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
764 /* update title gcs */
765 if (ST_PTITLEFONT(ms)->font != NULL && ST_PSTDFONT(ms)->font == NULL)
767 if (ST_PSTDFONT(ms)->font == NULL)
769 gcm |= GCFont;
771 gcv.font = ST_PTITLEFONT(ms)->font->fid;
773 gcv.foreground = c_title.fore;
774 gcv.background = c_title.back;
775 change_or_make_gc(&FORE_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
776 gcv.foreground = c_title.back;
777 gcv.background = c_title.fore;
779 if (ST_HAS_TITLE_CSET(ms) && title_cs->pixmap &&
780 title_cs->pixmap_type == PIXMAP_TILED)
782 gcv.tile = title_cs->pixmap;
783 gcv.fill_style = FillTiled;
784 change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)),
785 gcm | GCFillStyle | GCTile , &gcv);
787 else
789 gcv.fill_style = FillSolid;
790 change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)),
791 gcm | GCFillStyle , &gcv);
794 gcv.foreground = c_title.hilight;
795 gcv.background = c_title.shadow;
796 change_or_make_gc(&HILIGHT_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
797 gcv.foreground = c_title.shadow;
798 gcv.background = c_title.hilight;
799 change_or_make_gc(&SHADOW_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
800 /* update stipple menu gcs */
801 SHADOW_GC(ST_MENU_STIPPLE_GCS(ms)) =
802 SHADOW_GC(ST_MENU_INACTIVE_GCS(ms));
803 if (Pdepth < 2)
805 gcv.fill_style = FillStippled;
806 gcv.stipple = Scr.gray_bitmap;
807 /* no need to reset fg/bg, FillStipple wins */
808 gcm |= GCStipple | GCFillStyle;
809 HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) =
810 SHADOW_GC(ST_MENU_INACTIVE_GCS(ms));
812 else
814 gcv.foreground = c_stipple.fore;
815 gcv.background = c_stipple.back;
816 HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) =
817 HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms));
819 change_or_make_gc(&FORE_GC(ST_MENU_STIPPLE_GCS(ms)), gcm, &gcv);
820 BACK_GC(ST_MENU_STIPPLE_GCS(ms)) = BACK_GC(ST_MENU_INACTIVE_GCS(ms));
822 return;
825 MenuStyle *menustyle_parse_style(F_CMD_ARGS)
827 char *name;
828 char *option = NULL;
829 char *poption = NULL;
830 char *optstring = NULL;
831 char *nextarg;
832 char *args = NULL;
833 char *arg1;
834 int on;
835 MenuStyle *ms;
836 MenuStyle *tmpms;
837 Bool is_initialised = True;
838 Bool has_gc_changed = False;
839 Bool is_default_style = False;
840 int val[2];
841 int n;
842 FlocaleFont *new_font = NULL;
843 int i;
844 KeyCode keycode;
845 FvwmPictureAttributes fpa;
847 action = GetNextToken(action, &name);
848 if (!name)
850 fvwm_msg(ERR, "NewMenuStyle",
851 "error in %s style specification",action);
852 return NULL;
855 ms = menustyle_find(name);
856 if (ms && ST_USAGE_COUNT(ms) != 0)
858 fvwm_msg(ERR,"NewMenuStyle", "menu style %s is in use", name);
859 return ms;
861 tmpms = (MenuStyle *)safemalloc(sizeof(MenuStyle));
862 if (ms)
864 /* copy the structure over our temporary menu face. */
865 memcpy(tmpms, ms, sizeof(MenuStyle));
866 if (ms == default_menu_style)
868 is_default_style = True;
870 free(name);
872 else
874 memset(tmpms, 0, sizeof(MenuStyle));
875 ST_NAME(tmpms) = name;
876 is_initialised = False;
878 ST_IS_UPDATED(tmpms) = 1;
880 /* Parse the options. */
881 while (!is_initialised || (action && *action))
883 on = 1;
884 if (!is_initialised)
886 /* some default configuration goes here for the new
887 * menu style */
888 ST_MENU_COLORS(tmpms).back =
889 GetColor(DEFAULT_BACK_COLOR);
890 ST_MENU_COLORS(tmpms).fore =
891 GetColor(DEFAULT_FORE_COLOR);
892 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
893 ST_USING_DEFAULT_FONT(tmpms) = True;
894 ST_FACE(tmpms).type = SimpleMenu;
895 ST_HAS_ACTIVE_FORE(tmpms) = 0;
896 ST_HAS_ACTIVE_BACK(tmpms) = 0;
897 ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU;
898 ST_DOUBLE_CLICK_TIME(tmpms) = DEFAULT_MENU_CLICKTIME;
899 ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY;
900 ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY;
901 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
902 ST_SCROLL_OFF_PAGE(tmpms) = 1;
903 ST_DO_HILIGHT_TITLE_BACK(tmpms) = 0;
904 ST_USING_DEFAULT_TITLEFONT(tmpms) = True;
905 has_gc_changed = True;
906 option = "fvwm";
908 else
910 /* Read next option specification (delimited by a comma
911 * or \0). */
912 args = action;
913 action = GetQuotedString(
914 action, &optstring, ",", NULL, NULL, NULL);
915 if (!optstring)
917 break;
919 args = GetNextToken(optstring, &option);
920 if (!option)
922 free(optstring);
923 break;
925 nextarg = GetNextToken(args, &arg1);
927 poption = option;
928 while (poption[0] == '!')
930 on ^= 1;
931 poption++;
933 switch((i = menustyle_get_styleopt_index(poption)))
935 case 0: /* fvwm */
936 case 1: /* mwm */
937 case 2: /* win */
938 if (i == 0)
940 ST_POPUP_OFFSET_PERCENT(tmpms) = 67;
941 ST_POPUP_OFFSET_ADD(tmpms) = 0;
942 ST_DO_POPUP_IMMEDIATELY(tmpms) = 0;
943 ST_DO_WARP_TO_TITLE(tmpms) = 1;
944 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0;
945 ST_RELIEF_THICKNESS(tmpms) = 1;
946 ST_TITLE_UNDERLINES(tmpms) = 1;
947 ST_HAS_LONG_SEPARATORS(tmpms) = 0;
948 ST_HAS_TRIANGLE_RELIEF(tmpms) = 1;
949 ST_DO_HILIGHT_BACK(tmpms) = 0;
950 ST_DO_HILIGHT_FORE(tmpms) = 0;
952 else if (i == 1)
954 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
955 ST_POPUP_OFFSET_ADD(tmpms) =
956 -DEFAULT_MENU_BORDER_WIDTH - 1;
957 ST_DO_POPUP_IMMEDIATELY(tmpms) = 1;
958 ST_DO_WARP_TO_TITLE(tmpms) = 0;
959 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0;
960 ST_RELIEF_THICKNESS(tmpms) = 2;
961 ST_TITLE_UNDERLINES(tmpms) = 2;
962 ST_HAS_LONG_SEPARATORS(tmpms) = 1;
963 ST_HAS_TRIANGLE_RELIEF(tmpms) = 1;
964 ST_DO_HILIGHT_BACK(tmpms) = 0;
965 ST_DO_HILIGHT_FORE(tmpms) = 0;
967 else /* i == 2 */
969 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
970 ST_POPUP_OFFSET_ADD(tmpms) =
971 -DEFAULT_MENU_BORDER_WIDTH - 3;
972 ST_DO_POPUP_IMMEDIATELY(tmpms) = 1;
973 ST_DO_WARP_TO_TITLE(tmpms) = 0;
974 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 1;
975 ST_RELIEF_THICKNESS(tmpms) = 0;
976 ST_TITLE_UNDERLINES(tmpms) = 1;
977 ST_HAS_LONG_SEPARATORS(tmpms) = 0;
978 ST_HAS_TRIANGLE_RELIEF(tmpms) = 0;
979 ST_DO_HILIGHT_BACK(tmpms) = 1;
980 ST_DO_HILIGHT_FORE(tmpms) = 1;
983 /* common settings */
984 ST_VERTICAL_MARGIN_TOP(tmpms) = 0;
985 ST_VERTICAL_MARGIN_BOTTOM(tmpms) = 0;
986 ST_CSET_MENU(tmpms) = 0;
987 ST_HAS_MENU_CSET(tmpms) = 0;
988 ST_CSET_ACTIVE(tmpms) = 0;
989 ST_HAS_ACTIVE_CSET(tmpms) = 0;
990 ST_CSET_GREYED(tmpms) = 0;
991 ST_HAS_GREYED_CSET(tmpms) = 0;
992 ST_BORDER_WIDTH(tmpms) = DEFAULT_MENU_BORDER_WIDTH;
993 ST_ACTIVE_AREA_PERCENT(tmpms) =
994 DEFAULT_MENU_POPUP_NOW_RATIO;
995 ST_ITEM_GAP_ABOVE(tmpms) =
996 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET;
997 ST_ITEM_GAP_BELOW(tmpms) =
998 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2;
999 ST_TITLE_GAP_ABOVE(tmpms) =
1000 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET;
1001 ST_TITLE_GAP_BELOW(tmpms) =
1002 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2;
1003 ST_USE_LEFT_SUBMENUS(tmpms) = 0;
1004 ST_IS_ANIMATED(tmpms) = 0;
1005 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = 0;
1006 menustyle_free_face(&ST_FACE(tmpms));
1007 ST_FACE(tmpms).type = SimpleMenu;
1008 if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms))
1010 FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms));
1012 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
1013 ST_USING_DEFAULT_FONT(tmpms) = True;
1014 has_gc_changed = True;
1015 if (ST_HAS_SIDE_COLOR(tmpms) == 1)
1017 fvwmlib_free_colors(
1018 dpy, &ST_SIDE_COLOR(tmpms), 1, True);
1019 ST_HAS_SIDE_COLOR(tmpms) = 0;
1021 ST_HAS_SIDE_COLOR(tmpms) = 0;
1022 if (ST_SIDEPIC(tmpms))
1024 PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms));
1025 ST_SIDEPIC(tmpms) = NULL;
1028 if (is_initialised == False)
1030 /* now begin the real work */
1031 is_initialised = True;
1032 continue;
1034 break;
1036 case 3: /* Foreground */
1037 fvwmlib_free_colors(
1038 dpy, &ST_MENU_COLORS(tmpms).fore, 1, True);
1039 if (arg1)
1041 ST_MENU_COLORS(tmpms).fore = GetColor(arg1);
1043 else
1045 ST_MENU_COLORS(tmpms).fore =
1046 GetColor(DEFAULT_FORE_COLOR);
1048 has_gc_changed = True;
1049 break;
1051 case 4: /* Background */
1052 fvwmlib_free_colors(
1053 dpy, &ST_MENU_COLORS(tmpms).back, 1, True);
1054 if (arg1)
1056 ST_MENU_COLORS(tmpms).back = GetColor(arg1);
1058 else
1060 ST_MENU_COLORS(tmpms).back =
1061 GetColor(DEFAULT_BACK_COLOR);
1063 has_gc_changed = True;
1064 break;
1066 case 5: /* Greyed */
1067 if (ST_HAS_STIPPLE_FORE(tmpms))
1069 fvwmlib_free_colors(
1070 dpy,
1071 &ST_MENU_STIPPLE_COLORS(tmpms).fore, 1,
1072 True);
1074 if (arg1 == NULL)
1076 ST_HAS_STIPPLE_FORE(tmpms) = 0;
1078 else
1080 ST_MENU_STIPPLE_COLORS(tmpms).fore =
1081 GetColor(arg1);
1082 ST_HAS_STIPPLE_FORE(tmpms) = 1;
1084 has_gc_changed = True;
1085 break;
1087 case 7: /* HilightBackOff */
1088 on ^= 1;
1089 /* fall throw */
1090 case 6: /* HilightBack */
1091 if (ST_HAS_ACTIVE_BACK(tmpms))
1093 fvwmlib_free_colors(
1094 dpy,
1095 &ST_MENU_ACTIVE_COLORS(tmpms).back, 1,
1096 True);
1098 if (arg1 == NULL || !on)
1100 ST_HAS_ACTIVE_BACK(tmpms) = 0;
1102 else
1104 ST_MENU_ACTIVE_COLORS(tmpms).back =
1105 GetColor(arg1);
1106 ST_HAS_ACTIVE_BACK(tmpms) = 1;
1108 ST_DO_HILIGHT_BACK(tmpms) = on;
1109 has_gc_changed = True;
1110 break;
1112 case 9: /* ActiveForeOff */
1113 on ^= 1;
1114 /* fall throw */
1115 case 8: /* ActiveFore */
1116 if (ST_HAS_ACTIVE_FORE(tmpms))
1118 fvwmlib_free_colors(
1119 dpy,
1120 &ST_MENU_ACTIVE_COLORS(tmpms).fore, 1,
1121 True);
1123 if (arg1 == NULL || !on)
1125 ST_HAS_ACTIVE_FORE(tmpms) = 0;
1127 else
1129 ST_MENU_ACTIVE_COLORS(tmpms).fore =
1130 GetColor(arg1);
1131 ST_HAS_ACTIVE_FORE(tmpms) = 1;
1133 ST_DO_HILIGHT_FORE(tmpms) = on;
1134 has_gc_changed = True;
1135 break;
1137 case 10: /* Hilight3DThick */
1138 ST_RELIEF_THICKNESS(tmpms) = 2;
1139 break;
1141 case 11: /* Hilight3DThin */
1142 ST_RELIEF_THICKNESS(tmpms) = 1;
1143 break;
1145 case 12: /* Hilight3DOff */
1146 ST_RELIEF_THICKNESS(tmpms) = 0;
1147 break;
1149 case 13: /* Animation */
1150 ST_IS_ANIMATED(tmpms) = on;
1151 break;
1153 case 14: /* AnimationOff */
1154 ST_IS_ANIMATED(tmpms) = !on;
1155 break;
1157 case 15: /* Font */
1158 if (arg1 != NULL &&
1159 !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm")))
1161 fvwm_msg(ERR, "NewMenuStyle",
1162 "Couldn't load font '%s'\n", arg1);
1163 break;
1165 if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms))
1167 FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms));
1169 if (arg1 == NULL)
1171 /* reset to screen font */
1172 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
1173 ST_USING_DEFAULT_FONT(tmpms) = True;
1175 else
1177 ST_PSTDFONT(tmpms) = new_font;
1178 ST_USING_DEFAULT_FONT(tmpms) = False;
1180 has_gc_changed = True;
1181 break;
1183 case 16: /* MenuFace */
1184 while (args && *args != '\0' &&
1185 isspace((unsigned char)*args))
1187 args++;
1189 menustyle_parse_face(args, &ST_FACE(tmpms), True);
1190 break;
1192 case 17: /* PopupDelay */
1193 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1194 *val < 0)
1196 ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY;
1198 else
1200 ST_POPUP_DELAY(tmpms) = (*val+9)/10;
1202 break;
1204 case 18: /* PopupOffset */
1205 if ((n = GetIntegerArguments(args, NULL, val, 2)) == 0)
1207 fvwm_msg(ERR,"NewMenuStyle",
1208 "PopupOffset requires one or two"
1209 " arguments");
1211 else
1213 ST_POPUP_OFFSET_ADD(tmpms) = val[0];
1214 if (n == 2 && val[1] <= 100 && val[1] >= 0)
1216 ST_POPUP_OFFSET_PERCENT(tmpms) = val[1];
1218 else
1220 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
1223 break;
1225 case 19: /* TitleWarp */
1226 ST_DO_WARP_TO_TITLE(tmpms) = on;
1227 break;
1229 case 20: /* TitleWarpOff */
1230 ST_DO_WARP_TO_TITLE(tmpms) = !on;
1231 break;
1233 case 21: /* TitleUnderlines0 */
1234 ST_TITLE_UNDERLINES(tmpms) = 0;
1235 break;
1237 case 22: /* TitleUnderlines1 */
1238 ST_TITLE_UNDERLINES(tmpms) = 1;
1239 break;
1241 case 23: /* TitleUnderlines2 */
1242 ST_TITLE_UNDERLINES(tmpms) = 2;
1243 break;
1245 case 24: /* SeparatorsLong */
1246 ST_HAS_LONG_SEPARATORS(tmpms) = on;
1247 break;
1249 case 25: /* SeparatorsShort */
1250 ST_HAS_LONG_SEPARATORS(tmpms) = !on;
1251 break;
1253 case 26: /* TrianglesSolid */
1254 ST_HAS_TRIANGLE_RELIEF(tmpms) = !on;
1255 break;
1257 case 27: /* TrianglesRelief */
1258 ST_HAS_TRIANGLE_RELIEF(tmpms) = on;
1259 break;
1261 case 28: /* PopupImmediately */
1262 ST_DO_POPUP_IMMEDIATELY(tmpms) = on;
1263 break;
1265 case 29: /* PopupDelayed */
1266 ST_DO_POPUP_IMMEDIATELY(tmpms) = !on;
1267 break;
1269 case 30: /* DoubleClickTime */
1270 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1271 *val < 0)
1273 ST_DOUBLE_CLICK_TIME(tmpms) =
1274 DEFAULT_MENU_CLICKTIME;
1276 else
1278 ST_DOUBLE_CLICK_TIME(tmpms) = *val;
1280 break;
1282 case 31: /* SidePic */
1283 if (ST_SIDEPIC(tmpms))
1285 PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms));
1286 ST_SIDEPIC(tmpms) = NULL;
1288 if (arg1)
1290 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
1291 ST_SIDEPIC(tmpms) = PCacheFvwmPicture(
1292 dpy, Scr.NoFocusWin, NULL, arg1, fpa);
1293 if (!ST_SIDEPIC(tmpms))
1295 fvwm_msg(WARN, "NewMenuStyle",
1296 "Couldn't find pixmap %s",
1297 arg1);
1300 break;
1302 case 32: /* SideColor */
1303 if (ST_HAS_SIDE_COLOR(tmpms) == 1)
1305 fvwmlib_free_colors(
1306 dpy, &ST_SIDE_COLOR(tmpms), 1, True);
1307 ST_HAS_SIDE_COLOR(tmpms) = 0;
1309 if (arg1)
1311 ST_SIDE_COLOR(tmpms) = GetColor(arg1);
1312 ST_HAS_SIDE_COLOR(tmpms) = 1;
1314 break;
1316 case 33: /* PopupAsRootmenu */
1317 ST_DO_POPUP_AS(tmpms) = MDP_ROOT_MENU;
1318 break;
1320 case 34: /* PopupAsSubmenu */
1321 ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU;
1322 break;
1324 case 35: /* RemoveSubmenus */
1325 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = on;
1326 break;
1328 case 36: /* HoldSubmenus */
1329 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = !on;
1330 break;
1332 case 37: /* SubmenusRight */
1333 ST_USE_LEFT_SUBMENUS(tmpms) = !on;
1334 break;
1336 case 38: /* SubmenusLeft */
1337 ST_USE_LEFT_SUBMENUS(tmpms) = on;
1338 break;
1340 case 39: /* BorderWidth */
1341 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1342 *val < 0 || *val > MAX_MENU_BORDER_WIDTH)
1344 ST_BORDER_WIDTH(tmpms) =
1345 DEFAULT_MENU_BORDER_WIDTH;
1347 else
1349 ST_BORDER_WIDTH(tmpms) = *val;
1351 break;
1353 case 40: /* Hilight3DThickness */
1354 if (GetIntegerArguments(args, NULL, val, 1) > 0)
1356 if (*val < 0)
1358 *val = -*val;
1359 ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 1;
1361 else
1363 ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 0;
1365 if (*val > MAX_MENU_ITEM_RELIEF_THICKNESS)
1366 *val = MAX_MENU_ITEM_RELIEF_THICKNESS;
1367 ST_RELIEF_THICKNESS(tmpms) = *val;
1369 break;
1371 case 41: /* ItemFormat */
1372 if (ST_ITEM_FORMAT(tmpms))
1374 free(ST_ITEM_FORMAT(tmpms));
1375 ST_ITEM_FORMAT(tmpms) = NULL;
1377 if (arg1)
1379 ST_ITEM_FORMAT(tmpms) = safestrdup(arg1);
1381 break;
1383 case 42: /* AutomaticHotkeys */
1384 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = on;
1385 break;
1387 case 43: /* AutomaticHotkeysOff */
1388 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = !on;
1389 break;
1391 case 44: /* VerticalItemSpacing */
1392 parse_vertical_spacing_line(
1393 args, &ST_ITEM_GAP_ABOVE(tmpms),
1394 &ST_ITEM_GAP_BELOW(tmpms),
1395 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET,
1396 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2);
1397 break;
1399 case 45: /* VerticalTitleSpacing */
1400 parse_vertical_spacing_line(
1401 args, &ST_TITLE_GAP_ABOVE(tmpms),
1402 &ST_TITLE_GAP_BELOW(tmpms),
1403 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET,
1404 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2);
1405 break;
1406 case 46: /* MenuColorset */
1407 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1408 *val < 0)
1410 ST_HAS_MENU_CSET(tmpms) = 0;
1411 ST_CSET_MENU(tmpms) = 0;
1413 else
1415 ST_HAS_MENU_CSET(tmpms) = 1;
1416 ST_CSET_MENU(tmpms) = *val;
1417 alloc_colorset(*val);
1419 has_gc_changed = True;
1420 break;
1421 case 47: /* ActiveColorset */
1422 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1423 *val < 0)
1425 ST_HAS_ACTIVE_CSET(tmpms) = 0;
1426 ST_CSET_ACTIVE(tmpms) = 0;
1428 else
1430 ST_HAS_ACTIVE_CSET(tmpms) = 1;
1431 ST_CSET_ACTIVE(tmpms) = *val;
1432 alloc_colorset(*val);
1434 has_gc_changed = True;
1435 break;
1437 case 48: /* GreyedColorset */
1438 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1439 *val < 0)
1441 ST_HAS_GREYED_CSET(tmpms) = 0;
1442 ST_CSET_GREYED(tmpms) = 0;
1444 else
1446 ST_HAS_GREYED_CSET(tmpms) = 1;
1447 ST_CSET_GREYED(tmpms) = *val;
1448 alloc_colorset(*val);
1450 has_gc_changed = True;
1451 break;
1453 case 49: /* SelectOnRelease */
1454 keycode = 0;
1455 if (arg1)
1457 keycode = XKeysymToKeycode(
1458 dpy, FvwmStringToKeysym(dpy, arg1));
1460 ST_SELECT_ON_RELEASE_KEY(tmpms) = keycode;
1461 break;
1463 case 50: /* PopdownImmediately */
1464 ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 1;
1465 break;
1467 case 51: /* PopdownDelayed */
1468 ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 0;
1469 break;
1471 case 52: /* PopdownDelay */
1472 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1473 *val < 0)
1475 ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY;
1477 else
1479 ST_POPDOWN_DELAY(tmpms) = (*val+9)/10;
1481 break;
1483 case 53: /* PopupActiveArea */
1484 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1485 *val <= 50 || *val > 100)
1487 ST_ACTIVE_AREA_PERCENT(tmpms) =
1488 DEFAULT_MENU_POPUP_NOW_RATIO;
1490 else
1492 ST_ACTIVE_AREA_PERCENT(tmpms) = *val;
1494 break;
1496 case 54: /* PopupIgnore */
1497 ST_DO_POPUP_AS(tmpms) = MDP_IGNORE;
1498 break;
1500 case 55: /* PopupClose */
1501 ST_DO_POPUP_AS(tmpms) = MDP_CLOSE;
1502 break;
1504 case 56: /* MouseWheel */
1505 if (arg1)
1507 if (StrEquals(arg1, "ActivatesItem"))
1509 ST_MOUSE_WHEEL(tmpms) = MMW_OFF;
1511 else if (StrEquals(arg1,
1512 "ScrollsMenuBackwards"))
1514 ST_MOUSE_WHEEL(tmpms) =
1515 MMW_MENU_BACKWARDS;
1517 else if (StrEquals(arg1, "ScrollsMenu"))
1519 ST_MOUSE_WHEEL(tmpms) = MMW_MENU;
1521 else if (StrEquals(arg1, "ScrollsPointer"))
1523 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
1525 else
1527 fvwm_msg(
1528 ERR, "NewMenuStyle",
1529 "unknown argument to"
1530 " MouseWheel '%s'",
1531 arg1);
1532 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
1535 else
1537 ST_MOUSE_WHEEL(tmpms) =
1538 (on) ? MMW_POINTER : MMW_OFF;
1540 break;
1541 case 57: /* ScrollOffPage */
1542 ST_SCROLL_OFF_PAGE(tmpms) = on;
1543 break;
1545 case 58: /* TrianglesUseFore */
1546 ST_TRIANGLES_USE_FORE(tmpms) = on;
1547 break;
1548 case 59: /* TitleColorset */
1549 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1550 *val < 0)
1552 ST_HAS_TITLE_CSET(tmpms) = 0;
1553 ST_CSET_TITLE(tmpms) = 0;
1555 else
1557 ST_HAS_TITLE_CSET(tmpms) = 1;
1558 ST_CSET_TITLE(tmpms) = *val;
1559 alloc_colorset(*val);
1561 has_gc_changed = True;
1562 break;
1563 case 60: /* TitleHilightBack */
1564 ST_DO_HILIGHT_TITLE_BACK(tmpms) = on;
1565 has_gc_changed = True;
1566 break;
1567 case 61: /* TitleFont */
1568 if (arg1 != NULL &&
1569 !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm")))
1571 fvwm_msg(ERR, "NewMenuStyle",
1572 "Couldn't load font '%s'\n", arg1);
1573 break;
1575 if (
1576 ST_PTITLEFONT(tmpms) &&
1577 !ST_USING_DEFAULT_TITLEFONT(tmpms))
1579 FlocaleUnloadFont(dpy, ST_PTITLEFONT(tmpms));
1581 if (arg1 == NULL)
1583 /* reset to screen font */
1584 ST_PTITLEFONT(tmpms) = Scr.DefaultFont;
1585 ST_USING_DEFAULT_TITLEFONT(tmpms) = True;
1587 else
1589 ST_PTITLEFONT(tmpms) = new_font;
1590 ST_USING_DEFAULT_TITLEFONT(tmpms) = False;
1592 has_gc_changed = True;
1593 break;
1594 case 62: /* VerticalMargins */
1595 parse_vertical_margins_line(
1596 args, &ST_VERTICAL_MARGIN_TOP(tmpms),
1597 &ST_VERTICAL_MARGIN_BOTTOM(tmpms),
1598 0, 0);
1599 break;
1601 #if 0
1602 case 99: /* PositionHints */
1603 /* to be implemented */
1604 break;
1605 #endif
1607 default:
1608 fvwm_msg(ERR, "NewMenuStyle", "unknown option '%s'",
1609 poption);
1610 break;
1611 } /* switch */
1613 if (option)
1615 free(option);
1616 option = NULL;
1618 free(optstring);
1619 optstring = NULL;
1620 if (arg1)
1622 free(arg1);
1623 arg1 = NULL;
1625 } /* while */
1627 if (has_gc_changed)
1629 menustyle_update(tmpms);
1632 if (default_menu_style == NULL)
1634 /* First MenuStyle MUST be the default style */
1635 default_menu_style = tmpms;
1636 ST_NEXT_STYLE(tmpms) = NULL;
1638 else if (ms)
1640 /* copy our new menu face over the old one */
1641 memcpy(ms, tmpms, sizeof(MenuStyle));
1642 free(tmpms);
1643 return ms;
1645 else
1647 MenuStyle *before = default_menu_style;
1649 /* add a new menu face to list */
1650 ST_NEXT_STYLE(tmpms) = NULL;
1651 while (ST_NEXT_STYLE(before))
1652 before = ST_NEXT_STYLE(before);
1653 ST_NEXT_STYLE(before) = tmpms;
1656 return tmpms;
1659 void menustyle_copy(MenuStyle *origms, MenuStyle *destms)
1661 FvwmPictureAttributes fpa;
1662 /* Copy origms to destms, be aware of all pointers in the MenuStyle
1663 strcture. Use the same order as in menustyle_parse_style */
1665 /* menu colors */
1666 fvwmlib_copy_color(
1667 dpy, &ST_MENU_COLORS(destms).fore,
1668 &ST_MENU_COLORS(origms).fore, True, True);
1669 fvwmlib_copy_color(
1670 dpy, &ST_MENU_COLORS(destms).back,
1671 &ST_MENU_COLORS(origms).back, True, True);
1672 /* Greyed */
1673 fvwmlib_copy_color(
1674 dpy, &ST_MENU_STIPPLE_COLORS(destms).fore,
1675 &ST_MENU_STIPPLE_COLORS(origms).fore,
1676 ST_HAS_STIPPLE_FORE(destms), ST_HAS_STIPPLE_FORE(origms));
1677 ST_MENU_STIPPLE_COLORS(destms).back =
1678 ST_MENU_STIPPLE_COLORS(origms).back;
1679 ST_HAS_STIPPLE_FORE(destms) = ST_HAS_STIPPLE_FORE(origms);
1681 /* HilightBack */
1682 fvwmlib_copy_color(
1683 dpy, &ST_MENU_ACTIVE_COLORS(destms).back,
1684 &ST_MENU_ACTIVE_COLORS(origms).back,
1685 ST_HAS_ACTIVE_BACK(destms), ST_HAS_ACTIVE_BACK(origms));
1686 ST_HAS_ACTIVE_BACK(destms) = ST_HAS_ACTIVE_BACK(origms);
1687 ST_DO_HILIGHT_BACK(destms) = ST_DO_HILIGHT_BACK(origms);
1689 /* ActiveFore */
1690 fvwmlib_copy_color(
1691 dpy, &ST_MENU_ACTIVE_COLORS(destms).fore,
1692 &ST_MENU_ACTIVE_COLORS(origms).fore,
1693 ST_HAS_ACTIVE_FORE(destms), ST_HAS_ACTIVE_FORE(origms));
1694 ST_HAS_ACTIVE_FORE(destms) = ST_HAS_ACTIVE_FORE(origms);
1695 ST_DO_HILIGHT_FORE(destms) = ST_DO_HILIGHT_FORE(origms);
1697 /* Hilight3D */
1698 ST_RELIEF_THICKNESS(destms) = ST_RELIEF_THICKNESS(origms);
1699 /* Animation */
1700 ST_IS_ANIMATED(destms) = ST_IS_ANIMATED(origms);
1702 /* font */
1703 if (ST_PSTDFONT(destms) && !ST_USING_DEFAULT_FONT(destms))
1705 FlocaleUnloadFont(dpy, ST_PSTDFONT(destms));
1707 if (ST_PSTDFONT(origms) && !ST_USING_DEFAULT_FONT(origms))
1709 if (!(ST_PSTDFONT(destms) =
1710 FlocaleLoadFont(dpy, ST_PSTDFONT(origms)->name, "fvwm")))
1712 ST_PSTDFONT(destms) = Scr.DefaultFont;
1713 ST_USING_DEFAULT_FONT(destms) = True;
1714 fvwm_msg(ERR, "CopyMenuStyle",
1715 "Couldn't load font '%s' use Default Font\n",
1716 ST_PSTDFONT(origms)->name);
1718 else
1720 ST_USING_DEFAULT_FONT(destms) = False;
1723 else
1725 ST_USING_DEFAULT_FONT(destms) = True;
1726 ST_PSTDFONT(destms) = Scr.DefaultFont;
1728 /* TitleFont */
1729 if (ST_PTITLEFONT(destms) && !ST_USING_DEFAULT_TITLEFONT(destms))
1731 FlocaleUnloadFont(dpy, ST_PTITLEFONT(destms));
1733 if (ST_PTITLEFONT(origms) && !ST_USING_DEFAULT_TITLEFONT(origms))
1735 if (
1736 !(ST_PTITLEFONT(destms) = FlocaleLoadFont(
1737 dpy, ST_PTITLEFONT(origms)->name, "fvwm")))
1739 ST_PTITLEFONT(destms) = Scr.DefaultFont;
1740 ST_USING_DEFAULT_TITLEFONT(destms) = True;
1741 fvwm_msg(ERR, "CopyMenuStyle",
1742 "Couldn't load font '%s' use Default Font\n",
1743 ST_PTITLEFONT(origms)->name);
1745 else
1747 ST_USING_DEFAULT_TITLEFONT(destms) = False;
1750 else
1752 ST_USING_DEFAULT_TITLEFONT(destms) = True;
1753 ST_PTITLEFONT(destms) = Scr.DefaultFont;
1755 /* MenuFace */
1756 menustyle_copy_face(&ST_FACE(destms), &ST_FACE(origms));
1758 /* PopupDelay */
1759 ST_POPUP_DELAY(destms) = ST_POPUP_DELAY(origms);
1760 /* PopupOffset */
1761 ST_POPUP_OFFSET_PERCENT(destms) = ST_POPUP_OFFSET_PERCENT(origms);
1762 ST_POPUP_OFFSET_ADD(destms) = ST_POPUP_OFFSET_ADD(origms);
1763 /* TitleWarp */
1764 ST_DO_WARP_TO_TITLE(destms) = ST_DO_WARP_TO_TITLE(origms);
1765 /* TitleUnderlines */
1766 ST_TITLE_UNDERLINES(destms) = ST_TITLE_UNDERLINES(origms);
1767 /* Separators */
1768 ST_HAS_LONG_SEPARATORS(destms) = ST_HAS_LONG_SEPARATORS(origms);
1769 /* Triangles */
1770 ST_HAS_TRIANGLE_RELIEF(destms) = ST_HAS_TRIANGLE_RELIEF(origms);
1771 /* PopupDelayed */
1772 ST_DO_POPUP_IMMEDIATELY(destms) = ST_DO_POPUP_IMMEDIATELY(origms);
1773 /* DoubleClickTime */
1774 ST_DOUBLE_CLICK_TIME(destms) = ST_DOUBLE_CLICK_TIME(origms);
1775 /* VerticalMargins */
1776 ST_VERTICAL_MARGIN_TOP(destms) = ST_VERTICAL_MARGIN_TOP(origms);
1777 ST_VERTICAL_MARGIN_BOTTOM(destms) = ST_VERTICAL_MARGIN_BOTTOM(origms);
1779 /* SidePic */
1780 if (ST_SIDEPIC(destms))
1782 PDestroyFvwmPicture(dpy, ST_SIDEPIC(destms));
1783 ST_SIDEPIC(destms) = NULL;
1785 if (ST_SIDEPIC(origms))
1787 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
1788 ST_SIDEPIC(destms) = PCacheFvwmPicture(
1789 dpy, Scr.NoFocusWin, NULL, ST_SIDEPIC(origms)->name,
1790 fpa);
1793 /* side color */
1794 fvwmlib_copy_color(
1795 dpy, &ST_SIDE_COLOR(destms), &ST_SIDE_COLOR(origms),
1796 ST_HAS_SIDE_COLOR(destms), ST_HAS_SIDE_COLOR(origms));
1797 ST_HAS_SIDE_COLOR(destms) = ST_HAS_SIDE_COLOR(origms);
1799 /* PopupAsRootmenu */
1800 ST_DO_POPUP_AS(destms) = ST_DO_POPUP_AS(origms);
1801 /* RemoveSubmenus */
1802 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(destms) =
1803 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(origms);
1804 /* SubmenusRight */
1805 ST_USE_LEFT_SUBMENUS(destms) = ST_USE_LEFT_SUBMENUS(origms);
1806 /* BorderWidth */
1807 ST_BORDER_WIDTH(destms) = ST_BORDER_WIDTH(origms);
1808 /* Hilight3DThickness */
1809 ST_IS_ITEM_RELIEF_REVERSED(destms) =
1810 ST_IS_ITEM_RELIEF_REVERSED(origms);
1812 /* ItemFormat */
1813 if (ST_ITEM_FORMAT(destms))
1815 free(ST_ITEM_FORMAT(destms));
1816 ST_ITEM_FORMAT(destms) = NULL;
1818 if (ST_ITEM_FORMAT(origms))
1820 ST_ITEM_FORMAT(destms) = safestrdup(ST_ITEM_FORMAT(origms));
1823 /* AutomaticHotkeys */
1824 ST_USE_AUTOMATIC_HOTKEYS(destms) = ST_USE_AUTOMATIC_HOTKEYS(origms);
1825 /* Item and Title Spacing */
1826 ST_ITEM_GAP_ABOVE(destms) = ST_ITEM_GAP_ABOVE(origms);
1827 ST_ITEM_GAP_BELOW(destms) = ST_ITEM_GAP_BELOW(origms);
1828 ST_TITLE_GAP_ABOVE(destms) = ST_TITLE_GAP_ABOVE(origms);
1829 ST_TITLE_GAP_BELOW(destms) = ST_TITLE_GAP_BELOW(origms);
1830 /* MenuColorset */
1831 ST_HAS_MENU_CSET(destms) = ST_HAS_MENU_CSET(origms);
1832 ST_CSET_MENU(destms) = ST_CSET_MENU(origms);
1833 /* ActiveColorset */
1834 ST_HAS_ACTIVE_CSET(destms) = ST_HAS_ACTIVE_CSET(origms);
1835 ST_CSET_ACTIVE(destms) = ST_CSET_ACTIVE(origms);
1836 /* MenuColorset */
1837 ST_HAS_GREYED_CSET(destms) = ST_HAS_GREYED_CSET(origms);
1838 ST_CSET_GREYED(destms) = ST_CSET_GREYED(origms);
1839 /* TitleColorset */
1840 ST_HAS_TITLE_CSET(destms) = ST_HAS_TITLE_CSET(origms);
1841 ST_CSET_TITLE(destms) = ST_CSET_TITLE(origms);
1842 /* SelectOnRelease */
1843 ST_SELECT_ON_RELEASE_KEY(destms) = ST_SELECT_ON_RELEASE_KEY(origms);
1844 /* PopdownImmediately */
1845 ST_DO_POPDOWN_IMMEDIATELY(destms) = ST_DO_POPDOWN_IMMEDIATELY(origms);
1846 /* PopdownDelay */
1847 ST_POPDOWN_DELAY(destms) = ST_POPDOWN_DELAY(origms);
1848 /* Scroll */
1849 ST_MOUSE_WHEEL(destms) = ST_MOUSE_WHEEL(origms);
1850 /* ScrollOffPage */
1851 ST_SCROLL_OFF_PAGE(destms) = ST_SCROLL_OFF_PAGE(origms);
1852 /* TrianglesUseFore */
1853 ST_TRIANGLES_USE_FORE(destms) = ST_TRIANGLES_USE_FORE(origms);
1854 /* Title */
1855 ST_DO_HILIGHT_TITLE_BACK(destms) = ST_DO_HILIGHT_TITLE_BACK(origms);
1857 menustyle_update(destms);
1859 return;
1862 /* ---------------------------- builtin commands --------------------------- */
1864 void CMD_CopyMenuStyle(F_CMD_ARGS)
1866 char *origname = NULL;
1867 char *destname = NULL;
1868 char *buffer;
1869 MenuStyle *origms;
1870 MenuStyle *destms;
1872 origname = PeekToken(action, &action);
1873 if (origname == NULL)
1875 fvwm_msg(ERR,"CopyMenuStyle", "need two arguments");
1876 return;
1879 origms = menustyle_find(origname);
1880 if (!origms)
1882 fvwm_msg(ERR, "CopyMenuStyle", "%s: no such menu style",
1883 origname);
1884 return;
1887 destname = PeekToken(action, &action);
1888 if (destname == NULL)
1890 fvwm_msg(ERR,"CopyMenuStyle", "need two arguments");
1891 return;
1894 if (action && *action)
1896 fvwm_msg(ERR,"CopyMenuStyle", "too many arguments");
1897 return;
1900 destms = menustyle_find(destname);
1901 if (!destms)
1903 /* create destms menu style */
1904 buffer = (char *)safemalloc(strlen(destname) + 3);
1905 sprintf(buffer,"\"%s\"",destname);
1906 action = buffer;
1907 destms = menustyle_parse_style(F_PASS_ARGS);
1908 free(buffer);
1909 if (!destms)
1911 /* this must never happen */
1912 fvwm_msg(ERR, "CopyMenuStyle",
1913 "impossible to create %s menu style",
1914 destname);
1915 return;
1919 if (strcasecmp("*",destname) == 0)
1921 fvwm_msg(ERR, "CopyMenuStyle",
1922 "You cannot copy on the default menu style");
1923 return;
1925 if (strcasecmp(ST_NAME(origms),destname) == 0)
1927 fvwm_msg(ERR, "CopyMenuStyle",
1928 "%s and %s identify the same menu style",
1929 ST_NAME(origms),destname);
1930 return;
1933 if (ST_USAGE_COUNT(destms) != 0)
1935 fvwm_msg(ERR, "CopyMenuStyle", "menu style %s is in use",
1936 destname);
1937 return;
1940 menustyle_copy(origms, destms);
1942 return;
1945 void CMD_MenuStyle(F_CMD_ARGS)
1947 char *option;
1948 char *poption;
1949 MenuStyle *dummy;
1951 GetNextSimpleOption(SkipNTokens(action, 1), &option);
1952 poption = option;
1953 while (poption && poption[0] == '!')
1955 poption++;
1957 if (option == NULL || menustyle_get_styleopt_index(poption) != -1)
1959 dummy = menustyle_parse_style(F_PASS_ARGS);
1961 else
1963 dummy = menustyle_parse_old_style(F_PASS_ARGS);
1965 if (option)
1967 free(option);
1970 return;