Fix segfault when creating a tearoff menu using a Pixmap background.
[fvwm.git] / fvwm / menustyle.c
blob8f915439104b10680411141264d18a33711d5824
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;
137 /* Should never happen. */
138 if (destmf->u.p)
140 PDestroyFvwmPicture(dpy, destmf->u.p);
141 destmf->u.p = NULL;
144 if (origmf->u.p)
146 destmf->u.p = PCacheFvwmPicture(
147 dpy, Scr.NoFocusWin, NULL, origmf->u.p->name,
148 fpa);
151 destmf->type = origmf->type;
152 break;
153 default:
154 break;
160 * Reads a menu face line into a structure (veliaa@rpi.edu)
163 static Boolean menustyle_parse_face(char *s, MenuFace *mf, int verbose)
165 char *style;
166 char *token;
167 char *action = s;
168 FvwmPictureAttributes fpa;
170 s = GetNextToken(s, &style);
171 if (style && strncasecmp(style, "--", 2) == 0)
173 free(style);
174 return True;
177 menustyle_free_face(mf);
178 mf->type = SimpleMenu;
180 /* determine menu style */
181 if (!style)
183 return True;
185 else if (StrEquals(style,"Solid"))
187 s = GetNextToken(s, &token);
188 if (token)
190 mf->type = SolidMenu;
191 mf->u.back = GetColor(token);
192 free(token);
194 else
196 if (verbose)
198 fvwm_msg(ERR, "menustyle_parse_face",
199 "no color given for Solid face type:"
200 " %s", action);
202 free(style);
203 return False;
207 else if (StrEquals(style+1, "Gradient"))
209 char **s_colors;
210 int npixels, nsegs, *perc;
211 XColor *xcs;
213 if (!IsGradientTypeSupported(style[0]))
215 return False;
218 /* translate the gradient string into an array of colors etc */
219 npixels = ParseGradient(s, NULL, &s_colors, &perc, &nsegs);
220 if (npixels <= 0)
222 return False;
224 /* dither ? */
225 mf->u.grad.do_dither = False;
226 if (Pdepth <= 8)
228 mf->u.grad.do_dither = True;
230 /* grab the colors */
231 xcs = AllocAllGradientColors(
232 s_colors, perc, nsegs, npixels, mf->u.grad.do_dither);
233 if (xcs == None)
235 return False;
238 mf->u.grad.xcs = xcs;
239 mf->u.grad.npixels = npixels;
240 mf->type = GradientMenu;
241 mf->gradient_type = toupper(style[0]);
244 else if (StrEquals(style,"Pixmap") || StrEquals(style,"TiledPixmap"))
246 s = GetNextToken(s, &token);
247 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
248 if (token)
250 mf->u.p = PCacheFvwmPicture(
251 dpy, Scr.NoFocusWin, NULL, token, fpa);
252 if (mf->u.p == NULL)
254 if (verbose)
256 fvwm_msg(ERR, "menustyle_parse_face",
257 "couldn't load pixmap %s",
258 token);
260 free(token);
261 free(style);
262 return False;
264 free(token);
265 mf->type = (StrEquals(style,"TiledPixmap")) ?
266 TiledPixmapMenu : PixmapMenu;
268 else
270 if (verbose)
272 fvwm_msg(ERR, "menustyle_parse_face",
273 "missing pixmap name for style %s",
274 style);
276 free(style);
277 return False;
280 else
282 if (verbose)
284 fvwm_msg(
285 ERR,
286 "menustyle_parse_face", "unknown style %s: %s",
287 style, action);
289 free(style);
290 return False;
292 free(style);
294 return True;
297 static void parse_vertical_spacing_line(
298 char *args, signed char *above, signed char *below,
299 signed char above_default, signed char below_default)
301 int val[2];
303 if (GetIntegerArguments(args, NULL, val, 2) != 2 ||
304 val[0] < MIN_VERTICAL_SPACING || val[0] > MAX_VERTICAL_SPACING ||
305 val[1] < MIN_VERTICAL_SPACING || val[1] > MAX_VERTICAL_SPACING)
307 /* illegal or missing parameters, return to default */
308 *above = above_default;
309 *below = below_default;
310 return;
312 *above = val[0];
313 *below = val[1];
315 return;
318 static void parse_vertical_margins_line(
319 char *args, unsigned char *top, unsigned char *bottom,
320 signed char top_default, signed char bottom_default)
322 int val[2];
324 if (GetIntegerArguments(args, NULL, val, 2) != 2 ||
325 val[0] < 0 || val[0] > MAX_MENU_MARGIN ||
326 val[1] < 0 || val[1] > MAX_MENU_MARGIN)
328 /* invalid or missing parameters, return to default */
329 *top = top_default;
330 *bottom = bottom_default;
331 return;
333 *top = val[0];
334 *bottom = val[1];
336 return;
339 static MenuStyle *menustyle_parse_old_style(F_CMD_ARGS)
341 char *buffer, *rest;
342 char *fore, *back, *stipple, *font, *style, *animated;
343 MenuStyle *ms = NULL;
345 rest = GetNextToken(action,&fore);
346 rest = GetNextToken(rest,&back);
347 rest = GetNextToken(rest,&stipple);
348 rest = GetNextToken(rest,&font);
349 rest = GetNextToken(rest,&style);
350 rest = GetNextToken(rest,&animated);
352 if (!fore || !back || !stipple || !font || !style)
354 fvwm_msg(ERR, "menustyle_parse_old_style",
355 "error in %s style specification", action);
357 else
359 buffer = (char *)alloca(strlen(action) + 100);
360 sprintf(buffer,
361 "* \"%s\", Foreground \"%s\", Background \"%s\", "
362 "Greyed \"%s\", Font \"%s\", \"%s\"",
363 style, fore, back, stipple, font,
364 (animated && StrEquals(animated, "anim")) ?
365 "Animation" : "AnimationOff");
366 fvwm_msg(OLD, "menustyle_parse_old_style",
367 "The old MenuStyle snytax has been deprecated. "
368 "Use 'MenuStyle %s' instead of 'MenuStyle %s'\n",
369 buffer, action);
370 action = buffer;
371 ms = menustyle_parse_style(F_PASS_ARGS);
374 if (fore)
376 free(fore);
378 if (back)
380 free(back);
382 if (stipple)
384 free(stipple);
386 if (font)
388 free(font);
390 if (style)
392 free(style);
394 if (animated)
396 free(animated);
399 return ms;
402 static int menustyle_get_styleopt_index(char *option)
404 char *optlist[] = {
405 "fvwm", "mwm", "win",
406 "Foreground", "Background", "Greyed",
407 "HilightBack", "HilightBackOff",
408 "ActiveFore", "ActiveForeOff",
409 "Hilight3DThick", "Hilight3DThin", "Hilight3DOff",
410 "Animation", "AnimationOff",
411 "Font",
412 "MenuFace",
413 "PopupDelay", "PopupOffset",
414 "TitleWarp", "TitleWarpOff",
415 "TitleUnderlines0", "TitleUnderlines1", "TitleUnderlines2",
416 "SeparatorsLong", "SeparatorsShort",
417 "TrianglesSolid", "TrianglesRelief",
418 "PopupImmediately", "PopupDelayed",
419 "DoubleClickTime",
420 "SidePic", "SideColor",
421 "PopupAsRootmenu", "PopupAsSubmenu",
422 "RemoveSubmenus", "HoldSubmenus",
423 "SubmenusRight", "SubmenusLeft",
424 "BorderWidth",
425 "Hilight3DThickness",
426 "ItemFormat",
427 "AutomaticHotkeys", "AutomaticHotkeysOff",
428 "VerticalItemSpacing",
429 "VerticalTitleSpacing",
430 "MenuColorset", "ActiveColorset", "GreyedColorset",
431 "SelectOnRelease",
432 "PopdownImmediately", "PopdownDelayed",
433 "PopdownDelay",
434 "PopupActiveArea",
435 "PopupIgnore", "PopupClose",
436 "MouseWheel", "ScrollOffPage",
437 "TrianglesUseFore",
438 "TitleColorset", "HilightTitleBack",
439 "TitleFont",
440 "VerticalMargins",
441 NULL
444 return GetTokenIndex(option, optlist, 0, NULL);
447 static void change_or_make_gc(GC *gc, unsigned long gcm, XGCValues *gcv)
449 if (*gc != None)
451 XChangeGC(dpy, *gc, gcm, gcv);
453 else
455 *gc = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, gcv);
458 return;
461 /* ---------------------------- interface functions ------------------------ */
463 MenuStyle *menustyle_get_default_style(void)
465 return default_menu_style;
468 void menustyle_free(MenuStyle *ms)
470 MenuStyle *before = default_menu_style;
472 if (!ms)
474 return;
476 menustyle_free_face(&ST_FACE(ms));
477 if (FORE_GC(ST_MENU_INACTIVE_GCS(ms)))
479 XFreeGC(dpy, FORE_GC(ST_MENU_INACTIVE_GCS(ms)));
481 if (FORE_GC(ST_MENU_ACTIVE_GCS(ms)))
483 XFreeGC(dpy, FORE_GC(ST_MENU_ACTIVE_GCS(ms)));
485 if (BACK_GC(ST_MENU_ACTIVE_GCS(ms)))
487 XFreeGC(dpy, BACK_GC(ST_MENU_ACTIVE_GCS(ms)));
489 if (HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)))
491 XFreeGC(dpy, HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)));
493 if (SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)))
495 XFreeGC(dpy, SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)));
497 if (HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)))
499 XFreeGC(dpy, HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)));
501 if (SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)))
503 XFreeGC(dpy, SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)));
505 if (FORE_GC(ST_MENU_STIPPLE_GCS(ms)))
507 XFreeGC(dpy, FORE_GC(ST_MENU_STIPPLE_GCS(ms)));
509 if (FORE_GC(ST_MENU_TITLE_GCS(ms)))
511 XFreeGC(dpy, FORE_GC(ST_MENU_TITLE_GCS(ms)));
513 if (BACK_GC(ST_MENU_TITLE_GCS(ms)))
515 XFreeGC(dpy, BACK_GC(ST_MENU_TITLE_GCS(ms)));
517 if (HILIGHT_GC(ST_MENU_TITLE_GCS(ms)))
519 XFreeGC(dpy, HILIGHT_GC(ST_MENU_TITLE_GCS(ms)));
521 if (SHADOW_GC(ST_MENU_TITLE_GCS(ms)))
523 XFreeGC(dpy, SHADOW_GC(ST_MENU_TITLE_GCS(ms)));
525 if (ST_SIDEPIC(ms))
527 PDestroyFvwmPicture(dpy, ST_SIDEPIC(ms));
529 if (ST_HAS_SIDE_COLOR(ms) == 1)
531 fvwmlib_free_colors(dpy, &ST_SIDE_COLOR(ms), 1, True);
533 if (ST_PSTDFONT(ms) && !ST_USING_DEFAULT_FONT(ms))
535 FlocaleUnloadFont(dpy, ST_PSTDFONT(ms));
537 if (ST_PTITLEFONT(ms) && !ST_USING_DEFAULT_TITLEFONT(ms))
539 FlocaleUnloadFont(dpy, ST_PTITLEFONT(ms));
541 if (ST_ITEM_FORMAT(ms))
543 free(ST_ITEM_FORMAT(ms));
546 fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).back,1,True);
547 fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).fore,1,True);
548 if (ST_HAS_STIPPLE_FORE(ms))
550 fvwmlib_free_colors(
551 dpy, &ST_MENU_STIPPLE_COLORS(ms).fore,1,True);
553 if (ST_HAS_ACTIVE_BACK(ms))
555 fvwmlib_free_colors(
556 dpy, &ST_MENU_ACTIVE_COLORS(ms).back,1,True);
558 if (ST_HAS_ACTIVE_FORE(ms))
560 fvwmlib_free_colors(
561 dpy, &ST_MENU_ACTIVE_COLORS(ms).fore,1,True);
564 while (ST_NEXT_STYLE(before) != ms)
566 /* Not too many checks, may segfault in race conditions */
567 before = ST_NEXT_STYLE(before);
570 ST_NEXT_STYLE(before) = ST_NEXT_STYLE(ms);
571 free(ST_NAME(ms));
572 free(ms);
574 return;
577 MenuStyle *menustyle_find(char *name)
579 MenuStyle *ms = default_menu_style;
581 while (ms)
583 if (strcasecmp(ST_NAME(ms),name)==0)
585 return ms;
587 ms = ST_NEXT_STYLE(ms);
590 return NULL;
593 void menustyle_update(MenuStyle *ms)
595 XGCValues gcv;
596 unsigned long gcm;
597 color_quad c_inactive;
598 color_quad c_active;
599 color_quad c_stipple;
600 color_quad c_title;
601 colorset_t *menu_cs = &Colorset[ST_CSET_MENU(ms)];
602 colorset_t *active_cs = &Colorset[ST_CSET_ACTIVE(ms)];
603 colorset_t *greyed_cs = &Colorset[ST_CSET_GREYED(ms)];
604 colorset_t *title_cs = &Colorset[ST_CSET_TITLE(ms)];
606 if (ST_USAGE_COUNT(ms) != 0)
608 fvwm_msg(ERR,"menustyle_update", "menu style %s is in use",
609 ST_NAME(ms));
610 return;
612 ST_IS_UPDATED(ms) = 1;
613 if (ST_USING_DEFAULT_FONT(ms))
615 ST_PSTDFONT(ms) = Scr.DefaultFont;
617 if (ST_USING_DEFAULT_TITLEFONT(ms))
619 ST_PTITLEFONT(ms) = ST_PSTDFONT(ms);
621 /* calculate colors based on foreground */
622 if (!ST_HAS_ACTIVE_FORE(ms))
624 ST_MENU_ACTIVE_COLORS(ms).fore = ST_MENU_COLORS(ms).fore;
626 /* calculate colors based on background */
627 if (!ST_HAS_ACTIVE_BACK(ms))
629 ST_MENU_ACTIVE_COLORS(ms).back = ST_MENU_COLORS(ms).back;
631 if (!ST_HAS_STIPPLE_FORE(ms))
633 ST_MENU_STIPPLE_COLORS(ms).fore = ST_MENU_COLORS(ms).back;
635 ST_MENU_STIPPLE_COLORS(ms).back = ST_MENU_COLORS(ms).back;
636 /* prepare colours for changing the gcs */
637 if (ST_HAS_MENU_CSET(ms))
639 c_inactive.fore = menu_cs->fg;
640 c_inactive.back = menu_cs->bg;
641 c_inactive.hilight = menu_cs->hilite;
642 c_inactive.shadow = menu_cs->shadow;
644 else
646 c_inactive.fore = ST_MENU_COLORS(ms).fore;
647 c_inactive.back = ST_MENU_COLORS(ms).back;
648 if (Pdepth > 2)
650 c_inactive.hilight = GetHilite(ST_MENU_COLORS(ms).back);
651 c_inactive.shadow = GetShadow(ST_MENU_COLORS(ms).back);
653 else
655 c_inactive.hilight = GetColor(DEFAULT_HILIGHT_COLOR);
656 c_inactive.shadow = GetColor(DEFAULT_SHADOW_COLOR);
659 if (ST_HAS_ACTIVE_CSET(ms))
661 c_active.fore = active_cs->fg;
662 c_active.back = active_cs->bg;
663 c_active.hilight = active_cs->hilite;
664 c_active.shadow = active_cs->shadow;
666 else
668 c_active.fore = ST_MENU_ACTIVE_COLORS(ms).fore;
669 c_active.back = ST_MENU_ACTIVE_COLORS(ms).back;
670 if (Pdepth > 2)
672 c_active.hilight =
673 GetHilite(ST_MENU_ACTIVE_COLORS(ms).back);
674 c_active.shadow =
675 GetShadow(ST_MENU_ACTIVE_COLORS(ms).back);
677 else
679 c_active.hilight = GetColor(DEFAULT_HILIGHT_COLOR);
680 c_active.shadow = GetColor(DEFAULT_SHADOW_COLOR);
683 if (ST_HAS_GREYED_CSET(ms))
685 c_stipple.fore = greyed_cs->fg;
686 c_stipple.back = greyed_cs->fg;
688 else
690 c_stipple.fore = ST_MENU_STIPPLE_COLORS(ms).fore;
691 c_stipple.back = ST_MENU_STIPPLE_COLORS(ms).back;
693 if (ST_HAS_TITLE_CSET(ms))
695 c_title.fore = title_cs->fg;
696 c_title.back = title_cs->bg;
697 c_title.hilight = title_cs->hilite;
698 c_title.shadow = title_cs->shadow;
700 else
702 c_title.fore = c_inactive.fore;
703 c_title.back = c_inactive.back;
704 c_title.hilight = c_inactive.hilight;
705 c_title.shadow = c_inactive.shadow;
707 /* override hilighting colours if necessary */
708 if (!ST_DO_HILIGHT_FORE(ms))
710 c_active.fore = c_inactive.fore;
712 if (!ST_DO_HILIGHT_BACK(ms))
714 c_active.back = c_inactive.back;
715 c_active.hilight = c_inactive.hilight;
716 c_active.shadow = c_inactive.shadow;
718 if (!ST_DO_HILIGHT_TITLE_BACK(ms))
720 c_title.fore = c_inactive.fore;
721 c_title.back = c_inactive.back;
722 c_title.hilight = c_inactive.hilight;
723 c_title.shadow = c_inactive.shadow;
725 /* make GC's */
726 gcm = GCFunction|GCLineWidth|GCForeground|GCBackground;
727 if (ST_PSTDFONT(ms)->font != NULL)
729 gcm |= GCFont;
730 gcv.font = ST_PSTDFONT(ms)->font->fid;
732 gcv.function = GXcopy;
733 gcv.line_width = 0;
734 /* update inactive menu gcs */
735 gcv.foreground = c_inactive.fore;
736 gcv.background = c_inactive.back;
737 change_or_make_gc(&FORE_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
738 BACK_GC(ST_MENU_INACTIVE_GCS(ms)) = FORE_GC(ST_MENU_INACTIVE_GCS(ms));
739 gcv.foreground = c_inactive.hilight;
740 gcv.background = c_inactive.shadow;
741 change_or_make_gc(&HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
742 gcv.foreground = c_inactive.shadow;
743 gcv.background = c_inactive.hilight;
744 change_or_make_gc(&SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
745 /* update active menu gcs */
746 gcv.foreground = c_active.fore;
747 gcv.background = c_active.back;
748 change_or_make_gc(&FORE_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
749 gcv.foreground = c_active.back;
750 gcv.background = c_active.fore;
752 if (ST_HAS_ACTIVE_CSET(ms) && active_cs->pixmap &&
753 active_cs->pixmap_type == PIXMAP_TILED)
755 gcv.tile = active_cs->pixmap;
756 gcv.fill_style = FillTiled;
757 change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)),
758 gcm | GCFillStyle | GCTile , &gcv);
760 else
762 gcv.fill_style = FillSolid;
763 change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)),
764 gcm | GCFillStyle , &gcv);
768 gcv.foreground = c_active.hilight;
769 gcv.background = c_active.shadow;
770 change_or_make_gc(&HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
771 gcv.foreground = c_active.shadow;
772 gcv.background = c_active.hilight;
773 change_or_make_gc(&SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
774 /* update title gcs */
775 if (ST_PTITLEFONT(ms)->font != NULL && ST_PSTDFONT(ms)->font == NULL)
777 if (ST_PSTDFONT(ms)->font == NULL)
779 gcm |= GCFont;
781 gcv.font = ST_PTITLEFONT(ms)->font->fid;
783 gcv.foreground = c_title.fore;
784 gcv.background = c_title.back;
785 change_or_make_gc(&FORE_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
786 gcv.foreground = c_title.back;
787 gcv.background = c_title.fore;
789 if (ST_HAS_TITLE_CSET(ms) && title_cs->pixmap &&
790 title_cs->pixmap_type == PIXMAP_TILED)
792 gcv.tile = title_cs->pixmap;
793 gcv.fill_style = FillTiled;
794 change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)),
795 gcm | GCFillStyle | GCTile , &gcv);
797 else
799 gcv.fill_style = FillSolid;
800 change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)),
801 gcm | GCFillStyle , &gcv);
804 gcv.foreground = c_title.hilight;
805 gcv.background = c_title.shadow;
806 change_or_make_gc(&HILIGHT_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
807 gcv.foreground = c_title.shadow;
808 gcv.background = c_title.hilight;
809 change_or_make_gc(&SHADOW_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
810 /* update stipple menu gcs */
811 SHADOW_GC(ST_MENU_STIPPLE_GCS(ms)) =
812 SHADOW_GC(ST_MENU_INACTIVE_GCS(ms));
813 if (Pdepth < 2)
815 gcv.fill_style = FillStippled;
816 gcv.stipple = Scr.gray_bitmap;
817 /* no need to reset fg/bg, FillStipple wins */
818 gcm |= GCStipple | GCFillStyle;
819 HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) =
820 SHADOW_GC(ST_MENU_INACTIVE_GCS(ms));
822 else
824 gcv.foreground = c_stipple.fore;
825 gcv.background = c_stipple.back;
826 HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) =
827 HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms));
829 change_or_make_gc(&FORE_GC(ST_MENU_STIPPLE_GCS(ms)), gcm, &gcv);
830 BACK_GC(ST_MENU_STIPPLE_GCS(ms)) = BACK_GC(ST_MENU_INACTIVE_GCS(ms));
832 return;
835 MenuStyle *menustyle_parse_style(F_CMD_ARGS)
837 char *name;
838 char *option = NULL;
839 char *poption = NULL;
840 char *optstring = NULL;
841 char *nextarg;
842 char *args = NULL;
843 char *arg1;
844 int on;
845 MenuStyle *ms;
846 MenuStyle *tmpms;
847 Bool is_initialised = True;
848 Bool has_gc_changed = False;
849 Bool is_default_style = False;
850 int val[2];
851 int n;
852 FlocaleFont *new_font = NULL;
853 int i;
854 KeyCode keycode;
855 FvwmPictureAttributes fpa;
857 action = GetNextToken(action, &name);
858 if (!name)
860 fvwm_msg(ERR, "NewMenuStyle",
861 "error in %s style specification",action);
862 return NULL;
865 ms = menustyle_find(name);
866 if (ms && ST_USAGE_COUNT(ms) != 0)
868 fvwm_msg(ERR,"NewMenuStyle", "menu style %s is in use", name);
869 return ms;
871 tmpms = (MenuStyle *)safemalloc(sizeof(MenuStyle));
872 if (ms)
874 /* copy the structure over our temporary menu face. */
875 memcpy(tmpms, ms, sizeof(MenuStyle));
876 if (ms == default_menu_style)
878 is_default_style = True;
880 free(name);
882 else
884 memset(tmpms, 0, sizeof(MenuStyle));
885 ST_NAME(tmpms) = name;
886 is_initialised = False;
888 ST_IS_UPDATED(tmpms) = 1;
890 /* Parse the options. */
891 while (!is_initialised || (action && *action))
893 on = 1;
894 if (!is_initialised)
896 /* some default configuration goes here for the new
897 * menu style */
898 ST_MENU_COLORS(tmpms).back =
899 GetColor(DEFAULT_BACK_COLOR);
900 ST_MENU_COLORS(tmpms).fore =
901 GetColor(DEFAULT_FORE_COLOR);
902 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
903 ST_USING_DEFAULT_FONT(tmpms) = True;
904 ST_FACE(tmpms).type = SimpleMenu;
905 ST_HAS_ACTIVE_FORE(tmpms) = 0;
906 ST_HAS_ACTIVE_BACK(tmpms) = 0;
907 ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU;
908 ST_DOUBLE_CLICK_TIME(tmpms) = DEFAULT_MENU_CLICKTIME;
909 ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY;
910 ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY;
911 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
912 ST_SCROLL_OFF_PAGE(tmpms) = 1;
913 ST_DO_HILIGHT_TITLE_BACK(tmpms) = 0;
914 ST_USING_DEFAULT_TITLEFONT(tmpms) = True;
915 has_gc_changed = True;
916 option = "fvwm";
918 else
920 /* Read next option specification (delimited by a comma
921 * or \0). */
922 args = action;
923 action = GetQuotedString(
924 action, &optstring, ",", NULL, NULL, NULL);
925 if (!optstring)
927 break;
929 args = GetNextToken(optstring, &option);
930 if (!option)
932 free(optstring);
933 break;
935 nextarg = GetNextToken(args, &arg1);
937 poption = option;
938 while (poption[0] == '!')
940 on ^= 1;
941 poption++;
943 switch((i = menustyle_get_styleopt_index(poption)))
945 case 0: /* fvwm */
946 case 1: /* mwm */
947 case 2: /* win */
948 if (i == 0)
950 ST_POPUP_OFFSET_PERCENT(tmpms) = 67;
951 ST_POPUP_OFFSET_ADD(tmpms) = 0;
952 ST_DO_POPUP_IMMEDIATELY(tmpms) = 0;
953 ST_DO_WARP_TO_TITLE(tmpms) = 1;
954 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0;
955 ST_RELIEF_THICKNESS(tmpms) = 1;
956 ST_TITLE_UNDERLINES(tmpms) = 1;
957 ST_HAS_LONG_SEPARATORS(tmpms) = 0;
958 ST_HAS_TRIANGLE_RELIEF(tmpms) = 1;
959 ST_DO_HILIGHT_BACK(tmpms) = 0;
960 ST_DO_HILIGHT_FORE(tmpms) = 0;
962 else if (i == 1)
964 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
965 ST_POPUP_OFFSET_ADD(tmpms) =
966 -DEFAULT_MENU_BORDER_WIDTH - 1;
967 ST_DO_POPUP_IMMEDIATELY(tmpms) = 1;
968 ST_DO_WARP_TO_TITLE(tmpms) = 0;
969 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0;
970 ST_RELIEF_THICKNESS(tmpms) = 2;
971 ST_TITLE_UNDERLINES(tmpms) = 2;
972 ST_HAS_LONG_SEPARATORS(tmpms) = 1;
973 ST_HAS_TRIANGLE_RELIEF(tmpms) = 1;
974 ST_DO_HILIGHT_BACK(tmpms) = 0;
975 ST_DO_HILIGHT_FORE(tmpms) = 0;
977 else /* i == 2 */
979 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
980 ST_POPUP_OFFSET_ADD(tmpms) =
981 -DEFAULT_MENU_BORDER_WIDTH - 3;
982 ST_DO_POPUP_IMMEDIATELY(tmpms) = 1;
983 ST_DO_WARP_TO_TITLE(tmpms) = 0;
984 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 1;
985 ST_RELIEF_THICKNESS(tmpms) = 0;
986 ST_TITLE_UNDERLINES(tmpms) = 1;
987 ST_HAS_LONG_SEPARATORS(tmpms) = 0;
988 ST_HAS_TRIANGLE_RELIEF(tmpms) = 0;
989 ST_DO_HILIGHT_BACK(tmpms) = 1;
990 ST_DO_HILIGHT_FORE(tmpms) = 1;
993 /* common settings */
994 ST_VERTICAL_MARGIN_TOP(tmpms) = 0;
995 ST_VERTICAL_MARGIN_BOTTOM(tmpms) = 0;
996 ST_CSET_MENU(tmpms) = 0;
997 ST_HAS_MENU_CSET(tmpms) = 0;
998 ST_CSET_ACTIVE(tmpms) = 0;
999 ST_HAS_ACTIVE_CSET(tmpms) = 0;
1000 ST_CSET_GREYED(tmpms) = 0;
1001 ST_HAS_GREYED_CSET(tmpms) = 0;
1002 ST_BORDER_WIDTH(tmpms) = DEFAULT_MENU_BORDER_WIDTH;
1003 ST_ACTIVE_AREA_PERCENT(tmpms) =
1004 DEFAULT_MENU_POPUP_NOW_RATIO;
1005 ST_ITEM_GAP_ABOVE(tmpms) =
1006 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET;
1007 ST_ITEM_GAP_BELOW(tmpms) =
1008 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2;
1009 ST_TITLE_GAP_ABOVE(tmpms) =
1010 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET;
1011 ST_TITLE_GAP_BELOW(tmpms) =
1012 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2;
1013 ST_USE_LEFT_SUBMENUS(tmpms) = 0;
1014 ST_IS_ANIMATED(tmpms) = 0;
1015 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = 0;
1016 menustyle_free_face(&ST_FACE(tmpms));
1017 ST_FACE(tmpms).type = SimpleMenu;
1018 if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms))
1020 FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms));
1022 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
1023 ST_USING_DEFAULT_FONT(tmpms) = True;
1024 has_gc_changed = True;
1025 if (ST_HAS_SIDE_COLOR(tmpms) == 1)
1027 fvwmlib_free_colors(
1028 dpy, &ST_SIDE_COLOR(tmpms), 1, True);
1029 ST_HAS_SIDE_COLOR(tmpms) = 0;
1031 ST_HAS_SIDE_COLOR(tmpms) = 0;
1032 if (ST_SIDEPIC(tmpms))
1034 PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms));
1035 ST_SIDEPIC(tmpms) = NULL;
1038 if (is_initialised == False)
1040 /* now begin the real work */
1041 is_initialised = True;
1042 continue;
1044 break;
1046 case 3: /* Foreground */
1047 fvwmlib_free_colors(
1048 dpy, &ST_MENU_COLORS(tmpms).fore, 1, True);
1049 if (arg1)
1051 ST_MENU_COLORS(tmpms).fore = GetColor(arg1);
1053 else
1055 ST_MENU_COLORS(tmpms).fore =
1056 GetColor(DEFAULT_FORE_COLOR);
1058 has_gc_changed = True;
1059 break;
1061 case 4: /* Background */
1062 fvwmlib_free_colors(
1063 dpy, &ST_MENU_COLORS(tmpms).back, 1, True);
1064 if (arg1)
1066 ST_MENU_COLORS(tmpms).back = GetColor(arg1);
1068 else
1070 ST_MENU_COLORS(tmpms).back =
1071 GetColor(DEFAULT_BACK_COLOR);
1073 has_gc_changed = True;
1074 break;
1076 case 5: /* Greyed */
1077 if (ST_HAS_STIPPLE_FORE(tmpms))
1079 fvwmlib_free_colors(
1080 dpy,
1081 &ST_MENU_STIPPLE_COLORS(tmpms).fore, 1,
1082 True);
1084 if (arg1 == NULL)
1086 ST_HAS_STIPPLE_FORE(tmpms) = 0;
1088 else
1090 ST_MENU_STIPPLE_COLORS(tmpms).fore =
1091 GetColor(arg1);
1092 ST_HAS_STIPPLE_FORE(tmpms) = 1;
1094 has_gc_changed = True;
1095 break;
1097 case 7: /* HilightBackOff */
1098 on ^= 1;
1099 /* fall throw */
1100 case 6: /* HilightBack */
1101 if (ST_HAS_ACTIVE_BACK(tmpms))
1103 fvwmlib_free_colors(
1104 dpy,
1105 &ST_MENU_ACTIVE_COLORS(tmpms).back, 1,
1106 True);
1108 if (arg1 == NULL || !on)
1110 ST_HAS_ACTIVE_BACK(tmpms) = 0;
1112 else
1114 ST_MENU_ACTIVE_COLORS(tmpms).back =
1115 GetColor(arg1);
1116 ST_HAS_ACTIVE_BACK(tmpms) = 1;
1118 ST_DO_HILIGHT_BACK(tmpms) = on;
1119 has_gc_changed = True;
1120 break;
1122 case 9: /* ActiveForeOff */
1123 on ^= 1;
1124 /* fall throw */
1125 case 8: /* ActiveFore */
1126 if (ST_HAS_ACTIVE_FORE(tmpms))
1128 fvwmlib_free_colors(
1129 dpy,
1130 &ST_MENU_ACTIVE_COLORS(tmpms).fore, 1,
1131 True);
1133 if (arg1 == NULL || !on)
1135 ST_HAS_ACTIVE_FORE(tmpms) = 0;
1137 else
1139 ST_MENU_ACTIVE_COLORS(tmpms).fore =
1140 GetColor(arg1);
1141 ST_HAS_ACTIVE_FORE(tmpms) = 1;
1143 ST_DO_HILIGHT_FORE(tmpms) = on;
1144 has_gc_changed = True;
1145 break;
1147 case 10: /* Hilight3DThick */
1148 ST_RELIEF_THICKNESS(tmpms) = 2;
1149 break;
1151 case 11: /* Hilight3DThin */
1152 ST_RELIEF_THICKNESS(tmpms) = 1;
1153 break;
1155 case 12: /* Hilight3DOff */
1156 ST_RELIEF_THICKNESS(tmpms) = 0;
1157 break;
1159 case 13: /* Animation */
1160 ST_IS_ANIMATED(tmpms) = on;
1161 break;
1163 case 14: /* AnimationOff */
1164 ST_IS_ANIMATED(tmpms) = !on;
1165 break;
1167 case 15: /* Font */
1168 if (arg1 != NULL &&
1169 !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm")))
1171 fvwm_msg(ERR, "NewMenuStyle",
1172 "Couldn't load font '%s'\n", arg1);
1173 break;
1175 if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms))
1177 FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms));
1179 if (arg1 == NULL)
1181 /* reset to screen font */
1182 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
1183 ST_USING_DEFAULT_FONT(tmpms) = True;
1185 else
1187 ST_PSTDFONT(tmpms) = new_font;
1188 ST_USING_DEFAULT_FONT(tmpms) = False;
1190 has_gc_changed = True;
1191 break;
1193 case 16: /* MenuFace */
1194 while (args && *args != '\0' &&
1195 isspace((unsigned char)*args))
1197 args++;
1199 menustyle_parse_face(args, &ST_FACE(tmpms), True);
1200 break;
1202 case 17: /* PopupDelay */
1203 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1204 *val < 0)
1206 ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY;
1208 else
1210 ST_POPUP_DELAY(tmpms) = (*val+9)/10;
1212 break;
1214 case 18: /* PopupOffset */
1215 if ((n = GetIntegerArguments(args, NULL, val, 2)) == 0)
1217 fvwm_msg(ERR,"NewMenuStyle",
1218 "PopupOffset requires one or two"
1219 " arguments");
1221 else
1223 ST_POPUP_OFFSET_ADD(tmpms) = val[0];
1224 if (n == 2 && val[1] <= 100 && val[1] >= 0)
1226 ST_POPUP_OFFSET_PERCENT(tmpms) = val[1];
1228 else
1230 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
1233 break;
1235 case 19: /* TitleWarp */
1236 ST_DO_WARP_TO_TITLE(tmpms) = on;
1237 break;
1239 case 20: /* TitleWarpOff */
1240 ST_DO_WARP_TO_TITLE(tmpms) = !on;
1241 break;
1243 case 21: /* TitleUnderlines0 */
1244 ST_TITLE_UNDERLINES(tmpms) = 0;
1245 break;
1247 case 22: /* TitleUnderlines1 */
1248 ST_TITLE_UNDERLINES(tmpms) = 1;
1249 break;
1251 case 23: /* TitleUnderlines2 */
1252 ST_TITLE_UNDERLINES(tmpms) = 2;
1253 break;
1255 case 24: /* SeparatorsLong */
1256 ST_HAS_LONG_SEPARATORS(tmpms) = on;
1257 break;
1259 case 25: /* SeparatorsShort */
1260 ST_HAS_LONG_SEPARATORS(tmpms) = !on;
1261 break;
1263 case 26: /* TrianglesSolid */
1264 ST_HAS_TRIANGLE_RELIEF(tmpms) = !on;
1265 break;
1267 case 27: /* TrianglesRelief */
1268 ST_HAS_TRIANGLE_RELIEF(tmpms) = on;
1269 break;
1271 case 28: /* PopupImmediately */
1272 ST_DO_POPUP_IMMEDIATELY(tmpms) = on;
1273 break;
1275 case 29: /* PopupDelayed */
1276 ST_DO_POPUP_IMMEDIATELY(tmpms) = !on;
1277 break;
1279 case 30: /* DoubleClickTime */
1280 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1281 *val < 0)
1283 ST_DOUBLE_CLICK_TIME(tmpms) =
1284 DEFAULT_MENU_CLICKTIME;
1286 else
1288 ST_DOUBLE_CLICK_TIME(tmpms) = *val;
1290 break;
1292 case 31: /* SidePic */
1293 if (ST_SIDEPIC(tmpms))
1295 PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms));
1296 ST_SIDEPIC(tmpms) = NULL;
1298 if (arg1)
1300 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
1301 ST_SIDEPIC(tmpms) = PCacheFvwmPicture(
1302 dpy, Scr.NoFocusWin, NULL, arg1, fpa);
1303 if (!ST_SIDEPIC(tmpms))
1305 fvwm_msg(WARN, "NewMenuStyle",
1306 "Couldn't find pixmap %s",
1307 arg1);
1310 break;
1312 case 32: /* SideColor */
1313 if (ST_HAS_SIDE_COLOR(tmpms) == 1)
1315 fvwmlib_free_colors(
1316 dpy, &ST_SIDE_COLOR(tmpms), 1, True);
1317 ST_HAS_SIDE_COLOR(tmpms) = 0;
1319 if (arg1)
1321 ST_SIDE_COLOR(tmpms) = GetColor(arg1);
1322 ST_HAS_SIDE_COLOR(tmpms) = 1;
1324 break;
1326 case 33: /* PopupAsRootmenu */
1327 ST_DO_POPUP_AS(tmpms) = MDP_ROOT_MENU;
1328 break;
1330 case 34: /* PopupAsSubmenu */
1331 ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU;
1332 break;
1334 case 35: /* RemoveSubmenus */
1335 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = on;
1336 break;
1338 case 36: /* HoldSubmenus */
1339 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = !on;
1340 break;
1342 case 37: /* SubmenusRight */
1343 ST_USE_LEFT_SUBMENUS(tmpms) = !on;
1344 break;
1346 case 38: /* SubmenusLeft */
1347 ST_USE_LEFT_SUBMENUS(tmpms) = on;
1348 break;
1350 case 39: /* BorderWidth */
1351 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1352 *val < 0 || *val > MAX_MENU_BORDER_WIDTH)
1354 ST_BORDER_WIDTH(tmpms) =
1355 DEFAULT_MENU_BORDER_WIDTH;
1357 else
1359 ST_BORDER_WIDTH(tmpms) = *val;
1361 break;
1363 case 40: /* Hilight3DThickness */
1364 if (GetIntegerArguments(args, NULL, val, 1) > 0)
1366 if (*val < 0)
1368 *val = -*val;
1369 ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 1;
1371 else
1373 ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 0;
1375 if (*val > MAX_MENU_ITEM_RELIEF_THICKNESS)
1376 *val = MAX_MENU_ITEM_RELIEF_THICKNESS;
1377 ST_RELIEF_THICKNESS(tmpms) = *val;
1379 break;
1381 case 41: /* ItemFormat */
1382 if (ST_ITEM_FORMAT(tmpms))
1384 free(ST_ITEM_FORMAT(tmpms));
1385 ST_ITEM_FORMAT(tmpms) = NULL;
1387 if (arg1)
1389 ST_ITEM_FORMAT(tmpms) = safestrdup(arg1);
1391 break;
1393 case 42: /* AutomaticHotkeys */
1394 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = on;
1395 break;
1397 case 43: /* AutomaticHotkeysOff */
1398 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = !on;
1399 break;
1401 case 44: /* VerticalItemSpacing */
1402 parse_vertical_spacing_line(
1403 args, &ST_ITEM_GAP_ABOVE(tmpms),
1404 &ST_ITEM_GAP_BELOW(tmpms),
1405 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET,
1406 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2);
1407 break;
1409 case 45: /* VerticalTitleSpacing */
1410 parse_vertical_spacing_line(
1411 args, &ST_TITLE_GAP_ABOVE(tmpms),
1412 &ST_TITLE_GAP_BELOW(tmpms),
1413 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET,
1414 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2);
1415 break;
1416 case 46: /* MenuColorset */
1417 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1418 *val < 0)
1420 ST_HAS_MENU_CSET(tmpms) = 0;
1421 ST_CSET_MENU(tmpms) = 0;
1423 else
1425 ST_HAS_MENU_CSET(tmpms) = 1;
1426 ST_CSET_MENU(tmpms) = *val;
1427 alloc_colorset(*val);
1429 has_gc_changed = True;
1430 break;
1431 case 47: /* ActiveColorset */
1432 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1433 *val < 0)
1435 ST_HAS_ACTIVE_CSET(tmpms) = 0;
1436 ST_CSET_ACTIVE(tmpms) = 0;
1438 else
1440 ST_HAS_ACTIVE_CSET(tmpms) = 1;
1441 ST_CSET_ACTIVE(tmpms) = *val;
1442 alloc_colorset(*val);
1444 has_gc_changed = True;
1445 break;
1447 case 48: /* GreyedColorset */
1448 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1449 *val < 0)
1451 ST_HAS_GREYED_CSET(tmpms) = 0;
1452 ST_CSET_GREYED(tmpms) = 0;
1454 else
1456 ST_HAS_GREYED_CSET(tmpms) = 1;
1457 ST_CSET_GREYED(tmpms) = *val;
1458 alloc_colorset(*val);
1460 has_gc_changed = True;
1461 break;
1463 case 49: /* SelectOnRelease */
1464 keycode = 0;
1465 if (arg1)
1467 keycode = XKeysymToKeycode(
1468 dpy, FvwmStringToKeysym(dpy, arg1));
1470 ST_SELECT_ON_RELEASE_KEY(tmpms) = keycode;
1471 break;
1473 case 50: /* PopdownImmediately */
1474 ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 1;
1475 break;
1477 case 51: /* PopdownDelayed */
1478 ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 0;
1479 break;
1481 case 52: /* PopdownDelay */
1482 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1483 *val < 0)
1485 ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY;
1487 else
1489 ST_POPDOWN_DELAY(tmpms) = (*val+9)/10;
1491 break;
1493 case 53: /* PopupActiveArea */
1494 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1495 *val <= 50 || *val > 100)
1497 ST_ACTIVE_AREA_PERCENT(tmpms) =
1498 DEFAULT_MENU_POPUP_NOW_RATIO;
1500 else
1502 ST_ACTIVE_AREA_PERCENT(tmpms) = *val;
1504 break;
1506 case 54: /* PopupIgnore */
1507 ST_DO_POPUP_AS(tmpms) = MDP_IGNORE;
1508 break;
1510 case 55: /* PopupClose */
1511 ST_DO_POPUP_AS(tmpms) = MDP_CLOSE;
1512 break;
1514 case 56: /* MouseWheel */
1515 if (arg1)
1517 if (StrEquals(arg1, "ActivatesItem"))
1519 ST_MOUSE_WHEEL(tmpms) = MMW_OFF;
1521 else if (StrEquals(arg1,
1522 "ScrollsMenuBackwards"))
1524 ST_MOUSE_WHEEL(tmpms) =
1525 MMW_MENU_BACKWARDS;
1527 else if (StrEquals(arg1, "ScrollsMenu"))
1529 ST_MOUSE_WHEEL(tmpms) = MMW_MENU;
1531 else if (StrEquals(arg1, "ScrollsPointer"))
1533 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
1535 else
1537 fvwm_msg(
1538 ERR, "NewMenuStyle",
1539 "unknown argument to"
1540 " MouseWheel '%s'",
1541 arg1);
1542 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
1545 else
1547 ST_MOUSE_WHEEL(tmpms) =
1548 (on) ? MMW_POINTER : MMW_OFF;
1550 break;
1551 case 57: /* ScrollOffPage */
1552 ST_SCROLL_OFF_PAGE(tmpms) = on;
1553 break;
1555 case 58: /* TrianglesUseFore */
1556 ST_TRIANGLES_USE_FORE(tmpms) = on;
1557 break;
1558 case 59: /* TitleColorset */
1559 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1560 *val < 0)
1562 ST_HAS_TITLE_CSET(tmpms) = 0;
1563 ST_CSET_TITLE(tmpms) = 0;
1565 else
1567 ST_HAS_TITLE_CSET(tmpms) = 1;
1568 ST_CSET_TITLE(tmpms) = *val;
1569 alloc_colorset(*val);
1571 has_gc_changed = True;
1572 break;
1573 case 60: /* TitleHilightBack */
1574 ST_DO_HILIGHT_TITLE_BACK(tmpms) = on;
1575 has_gc_changed = True;
1576 break;
1577 case 61: /* TitleFont */
1578 if (arg1 != NULL &&
1579 !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm")))
1581 fvwm_msg(ERR, "NewMenuStyle",
1582 "Couldn't load font '%s'\n", arg1);
1583 break;
1585 if (
1586 ST_PTITLEFONT(tmpms) &&
1587 !ST_USING_DEFAULT_TITLEFONT(tmpms))
1589 FlocaleUnloadFont(dpy, ST_PTITLEFONT(tmpms));
1591 if (arg1 == NULL)
1593 /* reset to screen font */
1594 ST_PTITLEFONT(tmpms) = Scr.DefaultFont;
1595 ST_USING_DEFAULT_TITLEFONT(tmpms) = True;
1597 else
1599 ST_PTITLEFONT(tmpms) = new_font;
1600 ST_USING_DEFAULT_TITLEFONT(tmpms) = False;
1602 has_gc_changed = True;
1603 break;
1604 case 62: /* VerticalMargins */
1605 parse_vertical_margins_line(
1606 args, &ST_VERTICAL_MARGIN_TOP(tmpms),
1607 &ST_VERTICAL_MARGIN_BOTTOM(tmpms),
1608 0, 0);
1609 break;
1611 #if 0
1612 case 99: /* PositionHints */
1613 /* to be implemented */
1614 break;
1615 #endif
1617 default:
1618 fvwm_msg(ERR, "NewMenuStyle", "unknown option '%s'",
1619 poption);
1620 break;
1621 } /* switch */
1623 if (option)
1625 free(option);
1626 option = NULL;
1628 free(optstring);
1629 optstring = NULL;
1630 if (arg1)
1632 free(arg1);
1633 arg1 = NULL;
1635 } /* while */
1637 if (has_gc_changed)
1639 menustyle_update(tmpms);
1642 if (default_menu_style == NULL)
1644 /* First MenuStyle MUST be the default style */
1645 default_menu_style = tmpms;
1646 ST_NEXT_STYLE(tmpms) = NULL;
1648 else if (ms)
1650 /* copy our new menu face over the old one */
1651 memcpy(ms, tmpms, sizeof(MenuStyle));
1652 free(tmpms);
1653 return ms;
1655 else
1657 MenuStyle *before = default_menu_style;
1659 /* add a new menu face to list */
1660 ST_NEXT_STYLE(tmpms) = NULL;
1661 while (ST_NEXT_STYLE(before))
1662 before = ST_NEXT_STYLE(before);
1663 ST_NEXT_STYLE(before) = tmpms;
1666 return tmpms;
1669 void menustyle_copy(MenuStyle *origms, MenuStyle *destms)
1671 FvwmPictureAttributes fpa;
1672 /* Copy origms to destms, be aware of all pointers in the MenuStyle
1673 strcture. Use the same order as in menustyle_parse_style */
1675 /* menu colors */
1676 fvwmlib_copy_color(
1677 dpy, &ST_MENU_COLORS(destms).fore,
1678 &ST_MENU_COLORS(origms).fore, True, True);
1679 fvwmlib_copy_color(
1680 dpy, &ST_MENU_COLORS(destms).back,
1681 &ST_MENU_COLORS(origms).back, True, True);
1682 /* Greyed */
1683 fvwmlib_copy_color(
1684 dpy, &ST_MENU_STIPPLE_COLORS(destms).fore,
1685 &ST_MENU_STIPPLE_COLORS(origms).fore,
1686 ST_HAS_STIPPLE_FORE(destms), ST_HAS_STIPPLE_FORE(origms));
1687 ST_MENU_STIPPLE_COLORS(destms).back =
1688 ST_MENU_STIPPLE_COLORS(origms).back;
1689 ST_HAS_STIPPLE_FORE(destms) = ST_HAS_STIPPLE_FORE(origms);
1691 /* HilightBack */
1692 fvwmlib_copy_color(
1693 dpy, &ST_MENU_ACTIVE_COLORS(destms).back,
1694 &ST_MENU_ACTIVE_COLORS(origms).back,
1695 ST_HAS_ACTIVE_BACK(destms), ST_HAS_ACTIVE_BACK(origms));
1696 ST_HAS_ACTIVE_BACK(destms) = ST_HAS_ACTIVE_BACK(origms);
1697 ST_DO_HILIGHT_BACK(destms) = ST_DO_HILIGHT_BACK(origms);
1699 /* ActiveFore */
1700 fvwmlib_copy_color(
1701 dpy, &ST_MENU_ACTIVE_COLORS(destms).fore,
1702 &ST_MENU_ACTIVE_COLORS(origms).fore,
1703 ST_HAS_ACTIVE_FORE(destms), ST_HAS_ACTIVE_FORE(origms));
1704 ST_HAS_ACTIVE_FORE(destms) = ST_HAS_ACTIVE_FORE(origms);
1705 ST_DO_HILIGHT_FORE(destms) = ST_DO_HILIGHT_FORE(origms);
1707 /* Hilight3D */
1708 ST_RELIEF_THICKNESS(destms) = ST_RELIEF_THICKNESS(origms);
1709 /* Animation */
1710 ST_IS_ANIMATED(destms) = ST_IS_ANIMATED(origms);
1712 /* font */
1713 if (ST_PSTDFONT(destms) && !ST_USING_DEFAULT_FONT(destms))
1715 FlocaleUnloadFont(dpy, ST_PSTDFONT(destms));
1717 if (ST_PSTDFONT(origms) && !ST_USING_DEFAULT_FONT(origms))
1719 if (!(ST_PSTDFONT(destms) =
1720 FlocaleLoadFont(dpy, ST_PSTDFONT(origms)->name, "fvwm")))
1722 ST_PSTDFONT(destms) = Scr.DefaultFont;
1723 ST_USING_DEFAULT_FONT(destms) = True;
1724 fvwm_msg(ERR, "CopyMenuStyle",
1725 "Couldn't load font '%s' use Default Font\n",
1726 ST_PSTDFONT(origms)->name);
1728 else
1730 ST_USING_DEFAULT_FONT(destms) = False;
1733 else
1735 ST_USING_DEFAULT_FONT(destms) = True;
1736 ST_PSTDFONT(destms) = Scr.DefaultFont;
1738 /* TitleFont */
1739 if (ST_PTITLEFONT(destms) && !ST_USING_DEFAULT_TITLEFONT(destms))
1741 FlocaleUnloadFont(dpy, ST_PTITLEFONT(destms));
1743 if (ST_PTITLEFONT(origms) && !ST_USING_DEFAULT_TITLEFONT(origms))
1745 if (
1746 !(ST_PTITLEFONT(destms) = FlocaleLoadFont(
1747 dpy, ST_PTITLEFONT(origms)->name, "fvwm")))
1749 ST_PTITLEFONT(destms) = Scr.DefaultFont;
1750 ST_USING_DEFAULT_TITLEFONT(destms) = True;
1751 fvwm_msg(ERR, "CopyMenuStyle",
1752 "Couldn't load font '%s' use Default Font\n",
1753 ST_PTITLEFONT(origms)->name);
1755 else
1757 ST_USING_DEFAULT_TITLEFONT(destms) = False;
1760 else
1762 ST_USING_DEFAULT_TITLEFONT(destms) = True;
1763 ST_PTITLEFONT(destms) = Scr.DefaultFont;
1765 /* MenuFace */
1766 menustyle_copy_face(&ST_FACE(destms), &ST_FACE(origms));
1768 /* PopupDelay */
1769 ST_POPUP_DELAY(destms) = ST_POPUP_DELAY(origms);
1770 /* PopupOffset */
1771 ST_POPUP_OFFSET_PERCENT(destms) = ST_POPUP_OFFSET_PERCENT(origms);
1772 ST_POPUP_OFFSET_ADD(destms) = ST_POPUP_OFFSET_ADD(origms);
1773 /* TitleWarp */
1774 ST_DO_WARP_TO_TITLE(destms) = ST_DO_WARP_TO_TITLE(origms);
1775 /* TitleUnderlines */
1776 ST_TITLE_UNDERLINES(destms) = ST_TITLE_UNDERLINES(origms);
1777 /* Separators */
1778 ST_HAS_LONG_SEPARATORS(destms) = ST_HAS_LONG_SEPARATORS(origms);
1779 /* Triangles */
1780 ST_HAS_TRIANGLE_RELIEF(destms) = ST_HAS_TRIANGLE_RELIEF(origms);
1781 /* PopupDelayed */
1782 ST_DO_POPUP_IMMEDIATELY(destms) = ST_DO_POPUP_IMMEDIATELY(origms);
1783 /* DoubleClickTime */
1784 ST_DOUBLE_CLICK_TIME(destms) = ST_DOUBLE_CLICK_TIME(origms);
1785 /* VerticalMargins */
1786 ST_VERTICAL_MARGIN_TOP(destms) = ST_VERTICAL_MARGIN_TOP(origms);
1787 ST_VERTICAL_MARGIN_BOTTOM(destms) = ST_VERTICAL_MARGIN_BOTTOM(origms);
1789 /* SidePic */
1790 if (ST_SIDEPIC(destms))
1792 PDestroyFvwmPicture(dpy, ST_SIDEPIC(destms));
1793 ST_SIDEPIC(destms) = NULL;
1795 if (ST_SIDEPIC(origms))
1797 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
1798 ST_SIDEPIC(destms) = PCacheFvwmPicture(
1799 dpy, Scr.NoFocusWin, NULL, ST_SIDEPIC(origms)->name,
1800 fpa);
1803 /* side color */
1804 fvwmlib_copy_color(
1805 dpy, &ST_SIDE_COLOR(destms), &ST_SIDE_COLOR(origms),
1806 ST_HAS_SIDE_COLOR(destms), ST_HAS_SIDE_COLOR(origms));
1807 ST_HAS_SIDE_COLOR(destms) = ST_HAS_SIDE_COLOR(origms);
1809 /* PopupAsRootmenu */
1810 ST_DO_POPUP_AS(destms) = ST_DO_POPUP_AS(origms);
1811 /* RemoveSubmenus */
1812 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(destms) =
1813 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(origms);
1814 /* SubmenusRight */
1815 ST_USE_LEFT_SUBMENUS(destms) = ST_USE_LEFT_SUBMENUS(origms);
1816 /* BorderWidth */
1817 ST_BORDER_WIDTH(destms) = ST_BORDER_WIDTH(origms);
1818 /* Hilight3DThickness */
1819 ST_IS_ITEM_RELIEF_REVERSED(destms) =
1820 ST_IS_ITEM_RELIEF_REVERSED(origms);
1822 /* ItemFormat */
1823 if (ST_ITEM_FORMAT(destms))
1825 free(ST_ITEM_FORMAT(destms));
1826 ST_ITEM_FORMAT(destms) = NULL;
1828 if (ST_ITEM_FORMAT(origms))
1830 ST_ITEM_FORMAT(destms) = safestrdup(ST_ITEM_FORMAT(origms));
1833 /* AutomaticHotkeys */
1834 ST_USE_AUTOMATIC_HOTKEYS(destms) = ST_USE_AUTOMATIC_HOTKEYS(origms);
1835 /* Item and Title Spacing */
1836 ST_ITEM_GAP_ABOVE(destms) = ST_ITEM_GAP_ABOVE(origms);
1837 ST_ITEM_GAP_BELOW(destms) = ST_ITEM_GAP_BELOW(origms);
1838 ST_TITLE_GAP_ABOVE(destms) = ST_TITLE_GAP_ABOVE(origms);
1839 ST_TITLE_GAP_BELOW(destms) = ST_TITLE_GAP_BELOW(origms);
1840 /* MenuColorset */
1841 ST_HAS_MENU_CSET(destms) = ST_HAS_MENU_CSET(origms);
1842 ST_CSET_MENU(destms) = ST_CSET_MENU(origms);
1843 /* ActiveColorset */
1844 ST_HAS_ACTIVE_CSET(destms) = ST_HAS_ACTIVE_CSET(origms);
1845 ST_CSET_ACTIVE(destms) = ST_CSET_ACTIVE(origms);
1846 /* MenuColorset */
1847 ST_HAS_GREYED_CSET(destms) = ST_HAS_GREYED_CSET(origms);
1848 ST_CSET_GREYED(destms) = ST_CSET_GREYED(origms);
1849 /* TitleColorset */
1850 ST_HAS_TITLE_CSET(destms) = ST_HAS_TITLE_CSET(origms);
1851 ST_CSET_TITLE(destms) = ST_CSET_TITLE(origms);
1852 /* SelectOnRelease */
1853 ST_SELECT_ON_RELEASE_KEY(destms) = ST_SELECT_ON_RELEASE_KEY(origms);
1854 /* PopdownImmediately */
1855 ST_DO_POPDOWN_IMMEDIATELY(destms) = ST_DO_POPDOWN_IMMEDIATELY(origms);
1856 /* PopdownDelay */
1857 ST_POPDOWN_DELAY(destms) = ST_POPDOWN_DELAY(origms);
1858 /* Scroll */
1859 ST_MOUSE_WHEEL(destms) = ST_MOUSE_WHEEL(origms);
1860 /* ScrollOffPage */
1861 ST_SCROLL_OFF_PAGE(destms) = ST_SCROLL_OFF_PAGE(origms);
1862 /* TrianglesUseFore */
1863 ST_TRIANGLES_USE_FORE(destms) = ST_TRIANGLES_USE_FORE(origms);
1864 /* Title */
1865 ST_DO_HILIGHT_TITLE_BACK(destms) = ST_DO_HILIGHT_TITLE_BACK(origms);
1867 menustyle_update(destms);
1869 return;
1872 /* ---------------------------- builtin commands --------------------------- */
1874 void CMD_CopyMenuStyle(F_CMD_ARGS)
1876 char *origname = NULL;
1877 char *destname = NULL;
1878 char *buffer;
1879 MenuStyle *origms;
1880 MenuStyle *destms;
1882 origname = PeekToken(action, &action);
1883 if (origname == NULL)
1885 fvwm_msg(ERR,"CopyMenuStyle", "need two arguments");
1886 return;
1889 origms = menustyle_find(origname);
1890 if (!origms)
1892 fvwm_msg(ERR, "CopyMenuStyle", "%s: no such menu style",
1893 origname);
1894 return;
1897 destname = PeekToken(action, &action);
1898 if (destname == NULL)
1900 fvwm_msg(ERR,"CopyMenuStyle", "need two arguments");
1901 return;
1904 if (action && *action)
1906 fvwm_msg(ERR,"CopyMenuStyle", "too many arguments");
1907 return;
1910 destms = menustyle_find(destname);
1911 if (!destms)
1913 /* create destms menu style */
1914 buffer = (char *)safemalloc(strlen(destname) + 3);
1915 sprintf(buffer,"\"%s\"",destname);
1916 action = buffer;
1917 destms = menustyle_parse_style(F_PASS_ARGS);
1918 free(buffer);
1919 if (!destms)
1921 /* this must never happen */
1922 fvwm_msg(ERR, "CopyMenuStyle",
1923 "impossible to create %s menu style",
1924 destname);
1925 return;
1929 if (strcasecmp("*",destname) == 0)
1931 fvwm_msg(ERR, "CopyMenuStyle",
1932 "You cannot copy on the default menu style");
1933 return;
1935 if (strcasecmp(ST_NAME(origms),destname) == 0)
1937 fvwm_msg(ERR, "CopyMenuStyle",
1938 "%s and %s identify the same menu style",
1939 ST_NAME(origms),destname);
1940 return;
1943 if (ST_USAGE_COUNT(destms) != 0)
1945 fvwm_msg(ERR, "CopyMenuStyle", "menu style %s is in use",
1946 destname);
1947 return;
1950 menustyle_copy(origms, destms);
1952 return;
1955 void CMD_MenuStyle(F_CMD_ARGS)
1957 char *option;
1958 char *poption;
1959 MenuStyle *dummy;
1961 GetNextSimpleOption(SkipNTokens(action, 1), &option);
1962 poption = option;
1963 while (poption && poption[0] == '!')
1965 poption++;
1967 if (option == NULL || menustyle_get_styleopt_index(poption) != -1)
1969 dummy = menustyle_parse_style(F_PASS_ARGS);
1971 else
1973 dummy = menustyle_parse_old_style(F_PASS_ARGS);
1975 if (option)
1977 free(option);
1980 return;