Fix segfault setting MenuFace pixmap style for menus.
[fvwm.git] / fvwm / menustyle.c
blobe33df5a5249c5d81058dc8d7eea286eafa4c66b0
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 if (destmf->u.p)
138 destmf->u.p = NULL;
140 if (origmf->u.p)
141 destmf->u.p = PCacheFvwmPicture(
142 dpy, Scr.NoFocusWin, NULL, origmf->u.p->name,
143 fpa);
145 destmf->type = origmf->type;
146 break;
147 default:
148 break;
154 * Reads a menu face line into a structure (veliaa@rpi.edu)
157 static Boolean menustyle_parse_face(char *s, MenuFace *mf, int verbose)
159 char *style;
160 char *token;
161 char *action = s;
162 FvwmPictureAttributes fpa;
164 s = GetNextToken(s, &style);
165 if (style && strncasecmp(style, "--", 2) == 0)
167 free(style);
168 return True;
171 menustyle_free_face(mf);
172 mf->type = SimpleMenu;
174 /* determine menu style */
175 if (!style)
177 return True;
179 else if (StrEquals(style,"Solid"))
181 s = GetNextToken(s, &token);
182 if (token)
184 mf->type = SolidMenu;
185 mf->u.back = GetColor(token);
186 free(token);
188 else
190 if (verbose)
192 fvwm_msg(ERR, "menustyle_parse_face",
193 "no color given for Solid face type:"
194 " %s", action);
196 free(style);
197 return False;
201 else if (StrEquals(style+1, "Gradient"))
203 char **s_colors;
204 int npixels, nsegs, *perc;
205 XColor *xcs;
207 if (!IsGradientTypeSupported(style[0]))
209 return False;
212 /* translate the gradient string into an array of colors etc */
213 npixels = ParseGradient(s, NULL, &s_colors, &perc, &nsegs);
214 if (npixels <= 0)
216 return False;
218 /* dither ? */
219 mf->u.grad.do_dither = False;
220 if (Pdepth <= 8)
222 mf->u.grad.do_dither = True;
224 /* grab the colors */
225 xcs = AllocAllGradientColors(
226 s_colors, perc, nsegs, npixels, mf->u.grad.do_dither);
227 if (xcs == None)
229 return False;
232 mf->u.grad.xcs = xcs;
233 mf->u.grad.npixels = npixels;
234 mf->type = GradientMenu;
235 mf->gradient_type = toupper(style[0]);
238 else if (StrEquals(style,"Pixmap") || StrEquals(style,"TiledPixmap"))
240 s = GetNextToken(s, &token);
241 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
242 if (token)
244 mf->u.p = PCacheFvwmPicture(
245 dpy, Scr.NoFocusWin, NULL, token, fpa);
246 if (mf->u.p == NULL)
248 if (verbose)
250 fvwm_msg(ERR, "menustyle_parse_face",
251 "couldn't load pixmap %s",
252 token);
254 free(token);
255 free(style);
256 return False;
258 free(token);
259 mf->type = (StrEquals(style,"TiledPixmap")) ?
260 TiledPixmapMenu : PixmapMenu;
262 else
264 if (verbose)
266 fvwm_msg(ERR, "menustyle_parse_face",
267 "missing pixmap name for style %s",
268 style);
270 free(style);
271 return False;
274 else
276 if (verbose)
278 fvwm_msg(
279 ERR,
280 "menustyle_parse_face", "unknown style %s: %s",
281 style, action);
283 free(style);
284 return False;
286 free(style);
288 return True;
291 static void parse_vertical_spacing_line(
292 char *args, signed char *above, signed char *below,
293 signed char above_default, signed char below_default)
295 int val[2];
297 if (GetIntegerArguments(args, NULL, val, 2) != 2 ||
298 val[0] < MIN_VERTICAL_SPACING || val[0] > MAX_VERTICAL_SPACING ||
299 val[1] < MIN_VERTICAL_SPACING || val[1] > MAX_VERTICAL_SPACING)
301 /* illegal or missing parameters, return to default */
302 *above = above_default;
303 *below = below_default;
304 return;
306 *above = val[0];
307 *below = val[1];
309 return;
312 static void parse_vertical_margins_line(
313 char *args, unsigned char *top, unsigned char *bottom,
314 signed char top_default, signed char bottom_default)
316 int val[2];
318 if (GetIntegerArguments(args, NULL, val, 2) != 2 ||
319 val[0] < 0 || val[0] > MAX_MENU_MARGIN ||
320 val[1] < 0 || val[1] > MAX_MENU_MARGIN)
322 /* invalid or missing parameters, return to default */
323 *top = top_default;
324 *bottom = bottom_default;
325 return;
327 *top = val[0];
328 *bottom = val[1];
330 return;
333 static MenuStyle *menustyle_parse_old_style(F_CMD_ARGS)
335 char *buffer, *rest;
336 char *fore, *back, *stipple, *font, *style, *animated;
337 MenuStyle *ms = NULL;
339 rest = GetNextToken(action,&fore);
340 rest = GetNextToken(rest,&back);
341 rest = GetNextToken(rest,&stipple);
342 rest = GetNextToken(rest,&font);
343 rest = GetNextToken(rest,&style);
344 rest = GetNextToken(rest,&animated);
346 if (!fore || !back || !stipple || !font || !style)
348 fvwm_msg(ERR, "menustyle_parse_old_style",
349 "error in %s style specification", action);
351 else
353 buffer = (char *)alloca(strlen(action) + 100);
354 sprintf(buffer,
355 "* \"%s\", Foreground \"%s\", Background \"%s\", "
356 "Greyed \"%s\", Font \"%s\", \"%s\"",
357 style, fore, back, stipple, font,
358 (animated && StrEquals(animated, "anim")) ?
359 "Animation" : "AnimationOff");
360 fvwm_msg(OLD, "menustyle_parse_old_style",
361 "The old MenuStyle snytax has been deprecated. "
362 "Use 'MenuStyle %s' instead of 'MenuStyle %s'\n",
363 buffer, action);
364 action = buffer;
365 ms = menustyle_parse_style(F_PASS_ARGS);
368 if (fore)
370 free(fore);
372 if (back)
374 free(back);
376 if (stipple)
378 free(stipple);
380 if (font)
382 free(font);
384 if (style)
386 free(style);
388 if (animated)
390 free(animated);
393 return ms;
396 static int menustyle_get_styleopt_index(char *option)
398 char *optlist[] = {
399 "fvwm", "mwm", "win",
400 "Foreground", "Background", "Greyed",
401 "HilightBack", "HilightBackOff",
402 "ActiveFore", "ActiveForeOff",
403 "Hilight3DThick", "Hilight3DThin", "Hilight3DOff",
404 "Animation", "AnimationOff",
405 "Font",
406 "MenuFace",
407 "PopupDelay", "PopupOffset",
408 "TitleWarp", "TitleWarpOff",
409 "TitleUnderlines0", "TitleUnderlines1", "TitleUnderlines2",
410 "SeparatorsLong", "SeparatorsShort",
411 "TrianglesSolid", "TrianglesRelief",
412 "PopupImmediately", "PopupDelayed",
413 "DoubleClickTime",
414 "SidePic", "SideColor",
415 "PopupAsRootmenu", "PopupAsSubmenu",
416 "RemoveSubmenus", "HoldSubmenus",
417 "SubmenusRight", "SubmenusLeft",
418 "BorderWidth",
419 "Hilight3DThickness",
420 "ItemFormat",
421 "AutomaticHotkeys", "AutomaticHotkeysOff",
422 "VerticalItemSpacing",
423 "VerticalTitleSpacing",
424 "MenuColorset", "ActiveColorset", "GreyedColorset",
425 "SelectOnRelease",
426 "PopdownImmediately", "PopdownDelayed",
427 "PopdownDelay",
428 "PopupActiveArea",
429 "PopupIgnore", "PopupClose",
430 "MouseWheel", "ScrollOffPage",
431 "TrianglesUseFore",
432 "TitleColorset", "HilightTitleBack",
433 "TitleFont",
434 "VerticalMargins",
435 NULL
438 return GetTokenIndex(option, optlist, 0, NULL);
441 static void change_or_make_gc(GC *gc, unsigned long gcm, XGCValues *gcv)
443 if (*gc != None)
445 XChangeGC(dpy, *gc, gcm, gcv);
447 else
449 *gc = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, gcv);
452 return;
455 /* ---------------------------- interface functions ------------------------ */
457 MenuStyle *menustyle_get_default_style(void)
459 return default_menu_style;
462 void menustyle_free(MenuStyle *ms)
464 MenuStyle *before = default_menu_style;
466 if (!ms)
468 return;
470 menustyle_free_face(&ST_FACE(ms));
471 if (FORE_GC(ST_MENU_INACTIVE_GCS(ms)))
473 XFreeGC(dpy, FORE_GC(ST_MENU_INACTIVE_GCS(ms)));
475 if (FORE_GC(ST_MENU_ACTIVE_GCS(ms)))
477 XFreeGC(dpy, FORE_GC(ST_MENU_ACTIVE_GCS(ms)));
479 if (BACK_GC(ST_MENU_ACTIVE_GCS(ms)))
481 XFreeGC(dpy, BACK_GC(ST_MENU_ACTIVE_GCS(ms)));
483 if (HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)))
485 XFreeGC(dpy, HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)));
487 if (SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)))
489 XFreeGC(dpy, SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)));
491 if (HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)))
493 XFreeGC(dpy, HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)));
495 if (SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)))
497 XFreeGC(dpy, SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)));
499 if (FORE_GC(ST_MENU_STIPPLE_GCS(ms)))
501 XFreeGC(dpy, FORE_GC(ST_MENU_STIPPLE_GCS(ms)));
503 if (FORE_GC(ST_MENU_TITLE_GCS(ms)))
505 XFreeGC(dpy, FORE_GC(ST_MENU_TITLE_GCS(ms)));
507 if (BACK_GC(ST_MENU_TITLE_GCS(ms)))
509 XFreeGC(dpy, BACK_GC(ST_MENU_TITLE_GCS(ms)));
511 if (HILIGHT_GC(ST_MENU_TITLE_GCS(ms)))
513 XFreeGC(dpy, HILIGHT_GC(ST_MENU_TITLE_GCS(ms)));
515 if (SHADOW_GC(ST_MENU_TITLE_GCS(ms)))
517 XFreeGC(dpy, SHADOW_GC(ST_MENU_TITLE_GCS(ms)));
519 if (ST_SIDEPIC(ms))
521 PDestroyFvwmPicture(dpy, ST_SIDEPIC(ms));
523 if (ST_HAS_SIDE_COLOR(ms) == 1)
525 fvwmlib_free_colors(dpy, &ST_SIDE_COLOR(ms), 1, True);
527 if (ST_PSTDFONT(ms) && !ST_USING_DEFAULT_FONT(ms))
529 FlocaleUnloadFont(dpy, ST_PSTDFONT(ms));
531 if (ST_PTITLEFONT(ms) && !ST_USING_DEFAULT_TITLEFONT(ms))
533 FlocaleUnloadFont(dpy, ST_PTITLEFONT(ms));
535 if (ST_ITEM_FORMAT(ms))
537 free(ST_ITEM_FORMAT(ms));
540 fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).back,1,True);
541 fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).fore,1,True);
542 if (ST_HAS_STIPPLE_FORE(ms))
544 fvwmlib_free_colors(
545 dpy, &ST_MENU_STIPPLE_COLORS(ms).fore,1,True);
547 if (ST_HAS_ACTIVE_BACK(ms))
549 fvwmlib_free_colors(
550 dpy, &ST_MENU_ACTIVE_COLORS(ms).back,1,True);
552 if (ST_HAS_ACTIVE_FORE(ms))
554 fvwmlib_free_colors(
555 dpy, &ST_MENU_ACTIVE_COLORS(ms).fore,1,True);
558 while (ST_NEXT_STYLE(before) != ms)
560 /* Not too many checks, may segfault in race conditions */
561 before = ST_NEXT_STYLE(before);
564 ST_NEXT_STYLE(before) = ST_NEXT_STYLE(ms);
565 free(ST_NAME(ms));
566 free(ms);
568 return;
571 MenuStyle *menustyle_find(char *name)
573 MenuStyle *ms = default_menu_style;
575 while (ms)
577 if (strcasecmp(ST_NAME(ms),name)==0)
579 return ms;
581 ms = ST_NEXT_STYLE(ms);
584 return NULL;
587 void menustyle_update(MenuStyle *ms)
589 XGCValues gcv;
590 unsigned long gcm;
591 color_quad c_inactive;
592 color_quad c_active;
593 color_quad c_stipple;
594 color_quad c_title;
595 colorset_t *menu_cs = &Colorset[ST_CSET_MENU(ms)];
596 colorset_t *active_cs = &Colorset[ST_CSET_ACTIVE(ms)];
597 colorset_t *greyed_cs = &Colorset[ST_CSET_GREYED(ms)];
598 colorset_t *title_cs = &Colorset[ST_CSET_TITLE(ms)];
600 if (ST_USAGE_COUNT(ms) != 0)
602 fvwm_msg(ERR,"menustyle_update", "menu style %s is in use",
603 ST_NAME(ms));
604 return;
606 ST_IS_UPDATED(ms) = 1;
607 if (ST_USING_DEFAULT_FONT(ms))
609 ST_PSTDFONT(ms) = Scr.DefaultFont;
611 if (ST_USING_DEFAULT_TITLEFONT(ms))
613 ST_PTITLEFONT(ms) = ST_PSTDFONT(ms);
615 /* calculate colors based on foreground */
616 if (!ST_HAS_ACTIVE_FORE(ms))
618 ST_MENU_ACTIVE_COLORS(ms).fore = ST_MENU_COLORS(ms).fore;
620 /* calculate colors based on background */
621 if (!ST_HAS_ACTIVE_BACK(ms))
623 ST_MENU_ACTIVE_COLORS(ms).back = ST_MENU_COLORS(ms).back;
625 if (!ST_HAS_STIPPLE_FORE(ms))
627 ST_MENU_STIPPLE_COLORS(ms).fore = ST_MENU_COLORS(ms).back;
629 ST_MENU_STIPPLE_COLORS(ms).back = ST_MENU_COLORS(ms).back;
630 /* prepare colours for changing the gcs */
631 if (ST_HAS_MENU_CSET(ms))
633 c_inactive.fore = menu_cs->fg;
634 c_inactive.back = menu_cs->bg;
635 c_inactive.hilight = menu_cs->hilite;
636 c_inactive.shadow = menu_cs->shadow;
638 else
640 c_inactive.fore = ST_MENU_COLORS(ms).fore;
641 c_inactive.back = ST_MENU_COLORS(ms).back;
642 if (Pdepth > 2)
644 c_inactive.hilight = GetHilite(ST_MENU_COLORS(ms).back);
645 c_inactive.shadow = GetShadow(ST_MENU_COLORS(ms).back);
647 else
649 c_inactive.hilight = GetColor(DEFAULT_HILIGHT_COLOR);
650 c_inactive.shadow = GetColor(DEFAULT_SHADOW_COLOR);
653 if (ST_HAS_ACTIVE_CSET(ms))
655 c_active.fore = active_cs->fg;
656 c_active.back = active_cs->bg;
657 c_active.hilight = active_cs->hilite;
658 c_active.shadow = active_cs->shadow;
660 else
662 c_active.fore = ST_MENU_ACTIVE_COLORS(ms).fore;
663 c_active.back = ST_MENU_ACTIVE_COLORS(ms).back;
664 if (Pdepth > 2)
666 c_active.hilight =
667 GetHilite(ST_MENU_ACTIVE_COLORS(ms).back);
668 c_active.shadow =
669 GetShadow(ST_MENU_ACTIVE_COLORS(ms).back);
671 else
673 c_active.hilight = GetColor(DEFAULT_HILIGHT_COLOR);
674 c_active.shadow = GetColor(DEFAULT_SHADOW_COLOR);
677 if (ST_HAS_GREYED_CSET(ms))
679 c_stipple.fore = greyed_cs->fg;
680 c_stipple.back = greyed_cs->fg;
682 else
684 c_stipple.fore = ST_MENU_STIPPLE_COLORS(ms).fore;
685 c_stipple.back = ST_MENU_STIPPLE_COLORS(ms).back;
687 if (ST_HAS_TITLE_CSET(ms))
689 c_title.fore = title_cs->fg;
690 c_title.back = title_cs->bg;
691 c_title.hilight = title_cs->hilite;
692 c_title.shadow = title_cs->shadow;
694 else
696 c_title.fore = c_inactive.fore;
697 c_title.back = c_inactive.back;
698 c_title.hilight = c_inactive.hilight;
699 c_title.shadow = c_inactive.shadow;
701 /* override hilighting colours if necessary */
702 if (!ST_DO_HILIGHT_FORE(ms))
704 c_active.fore = c_inactive.fore;
706 if (!ST_DO_HILIGHT_BACK(ms))
708 c_active.back = c_inactive.back;
709 c_active.hilight = c_inactive.hilight;
710 c_active.shadow = c_inactive.shadow;
712 if (!ST_DO_HILIGHT_TITLE_BACK(ms))
714 c_title.fore = c_inactive.fore;
715 c_title.back = c_inactive.back;
716 c_title.hilight = c_inactive.hilight;
717 c_title.shadow = c_inactive.shadow;
719 /* make GC's */
720 gcm = GCFunction|GCLineWidth|GCForeground|GCBackground;
721 if (ST_PSTDFONT(ms)->font != NULL)
723 gcm |= GCFont;
724 gcv.font = ST_PSTDFONT(ms)->font->fid;
726 gcv.function = GXcopy;
727 gcv.line_width = 0;
728 /* update inactive menu gcs */
729 gcv.foreground = c_inactive.fore;
730 gcv.background = c_inactive.back;
731 change_or_make_gc(&FORE_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
732 BACK_GC(ST_MENU_INACTIVE_GCS(ms)) = FORE_GC(ST_MENU_INACTIVE_GCS(ms));
733 gcv.foreground = c_inactive.hilight;
734 gcv.background = c_inactive.shadow;
735 change_or_make_gc(&HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
736 gcv.foreground = c_inactive.shadow;
737 gcv.background = c_inactive.hilight;
738 change_or_make_gc(&SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv);
739 /* update active menu gcs */
740 gcv.foreground = c_active.fore;
741 gcv.background = c_active.back;
742 change_or_make_gc(&FORE_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
743 gcv.foreground = c_active.back;
744 gcv.background = c_active.fore;
746 if (ST_HAS_ACTIVE_CSET(ms) && active_cs->pixmap &&
747 active_cs->pixmap_type == PIXMAP_TILED)
749 gcv.tile = active_cs->pixmap;
750 gcv.fill_style = FillTiled;
751 change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)),
752 gcm | GCFillStyle | GCTile , &gcv);
754 else
756 gcv.fill_style = FillSolid;
757 change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)),
758 gcm | GCFillStyle , &gcv);
762 gcv.foreground = c_active.hilight;
763 gcv.background = c_active.shadow;
764 change_or_make_gc(&HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
765 gcv.foreground = c_active.shadow;
766 gcv.background = c_active.hilight;
767 change_or_make_gc(&SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv);
768 /* update title gcs */
769 if (ST_PTITLEFONT(ms)->font != NULL && ST_PSTDFONT(ms)->font == NULL)
771 if (ST_PSTDFONT(ms)->font == NULL)
773 gcm |= GCFont;
775 gcv.font = ST_PTITLEFONT(ms)->font->fid;
777 gcv.foreground = c_title.fore;
778 gcv.background = c_title.back;
779 change_or_make_gc(&FORE_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
780 gcv.foreground = c_title.back;
781 gcv.background = c_title.fore;
783 if (ST_HAS_TITLE_CSET(ms) && title_cs->pixmap &&
784 title_cs->pixmap_type == PIXMAP_TILED)
786 gcv.tile = title_cs->pixmap;
787 gcv.fill_style = FillTiled;
788 change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)),
789 gcm | GCFillStyle | GCTile , &gcv);
791 else
793 gcv.fill_style = FillSolid;
794 change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)),
795 gcm | GCFillStyle , &gcv);
798 gcv.foreground = c_title.hilight;
799 gcv.background = c_title.shadow;
800 change_or_make_gc(&HILIGHT_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
801 gcv.foreground = c_title.shadow;
802 gcv.background = c_title.hilight;
803 change_or_make_gc(&SHADOW_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv);
804 /* update stipple menu gcs */
805 SHADOW_GC(ST_MENU_STIPPLE_GCS(ms)) =
806 SHADOW_GC(ST_MENU_INACTIVE_GCS(ms));
807 if (Pdepth < 2)
809 gcv.fill_style = FillStippled;
810 gcv.stipple = Scr.gray_bitmap;
811 /* no need to reset fg/bg, FillStipple wins */
812 gcm |= GCStipple | GCFillStyle;
813 HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) =
814 SHADOW_GC(ST_MENU_INACTIVE_GCS(ms));
816 else
818 gcv.foreground = c_stipple.fore;
819 gcv.background = c_stipple.back;
820 HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) =
821 HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms));
823 change_or_make_gc(&FORE_GC(ST_MENU_STIPPLE_GCS(ms)), gcm, &gcv);
824 BACK_GC(ST_MENU_STIPPLE_GCS(ms)) = BACK_GC(ST_MENU_INACTIVE_GCS(ms));
826 return;
829 MenuStyle *menustyle_parse_style(F_CMD_ARGS)
831 char *name;
832 char *option = NULL;
833 char *poption = NULL;
834 char *optstring = NULL;
835 char *nextarg;
836 char *args = NULL;
837 char *arg1;
838 int on;
839 MenuStyle *ms;
840 MenuStyle *tmpms;
841 Bool is_initialised = True;
842 Bool has_gc_changed = False;
843 Bool is_default_style = False;
844 int val[2];
845 int n;
846 FlocaleFont *new_font = NULL;
847 int i;
848 KeyCode keycode;
849 FvwmPictureAttributes fpa;
851 action = GetNextToken(action, &name);
852 if (!name)
854 fvwm_msg(ERR, "NewMenuStyle",
855 "error in %s style specification",action);
856 return NULL;
859 ms = menustyle_find(name);
860 if (ms && ST_USAGE_COUNT(ms) != 0)
862 fvwm_msg(ERR,"NewMenuStyle", "menu style %s is in use", name);
863 return ms;
865 tmpms = (MenuStyle *)safemalloc(sizeof(MenuStyle));
866 if (ms)
868 /* copy the structure over our temporary menu face. */
869 memcpy(tmpms, ms, sizeof(MenuStyle));
870 if (ms == default_menu_style)
872 is_default_style = True;
874 free(name);
876 else
878 memset(tmpms, 0, sizeof(MenuStyle));
879 ST_NAME(tmpms) = name;
880 is_initialised = False;
882 ST_IS_UPDATED(tmpms) = 1;
884 /* Parse the options. */
885 while (!is_initialised || (action && *action))
887 on = 1;
888 if (!is_initialised)
890 /* some default configuration goes here for the new
891 * menu style */
892 ST_MENU_COLORS(tmpms).back =
893 GetColor(DEFAULT_BACK_COLOR);
894 ST_MENU_COLORS(tmpms).fore =
895 GetColor(DEFAULT_FORE_COLOR);
896 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
897 ST_USING_DEFAULT_FONT(tmpms) = True;
898 ST_FACE(tmpms).type = SimpleMenu;
899 ST_HAS_ACTIVE_FORE(tmpms) = 0;
900 ST_HAS_ACTIVE_BACK(tmpms) = 0;
901 ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU;
902 ST_DOUBLE_CLICK_TIME(tmpms) = DEFAULT_MENU_CLICKTIME;
903 ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY;
904 ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY;
905 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
906 ST_SCROLL_OFF_PAGE(tmpms) = 1;
907 ST_DO_HILIGHT_TITLE_BACK(tmpms) = 0;
908 ST_USING_DEFAULT_TITLEFONT(tmpms) = True;
909 has_gc_changed = True;
910 option = "fvwm";
912 else
914 /* Read next option specification (delimited by a comma
915 * or \0). */
916 args = action;
917 action = GetQuotedString(
918 action, &optstring, ",", NULL, NULL, NULL);
919 if (!optstring)
921 break;
923 args = GetNextToken(optstring, &option);
924 if (!option)
926 free(optstring);
927 break;
929 nextarg = GetNextToken(args, &arg1);
931 poption = option;
932 while (poption[0] == '!')
934 on ^= 1;
935 poption++;
937 switch((i = menustyle_get_styleopt_index(poption)))
939 case 0: /* fvwm */
940 case 1: /* mwm */
941 case 2: /* win */
942 if (i == 0)
944 ST_POPUP_OFFSET_PERCENT(tmpms) = 67;
945 ST_POPUP_OFFSET_ADD(tmpms) = 0;
946 ST_DO_POPUP_IMMEDIATELY(tmpms) = 0;
947 ST_DO_WARP_TO_TITLE(tmpms) = 1;
948 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0;
949 ST_RELIEF_THICKNESS(tmpms) = 1;
950 ST_TITLE_UNDERLINES(tmpms) = 1;
951 ST_HAS_LONG_SEPARATORS(tmpms) = 0;
952 ST_HAS_TRIANGLE_RELIEF(tmpms) = 1;
953 ST_DO_HILIGHT_BACK(tmpms) = 0;
954 ST_DO_HILIGHT_FORE(tmpms) = 0;
956 else if (i == 1)
958 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
959 ST_POPUP_OFFSET_ADD(tmpms) =
960 -DEFAULT_MENU_BORDER_WIDTH - 1;
961 ST_DO_POPUP_IMMEDIATELY(tmpms) = 1;
962 ST_DO_WARP_TO_TITLE(tmpms) = 0;
963 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0;
964 ST_RELIEF_THICKNESS(tmpms) = 2;
965 ST_TITLE_UNDERLINES(tmpms) = 2;
966 ST_HAS_LONG_SEPARATORS(tmpms) = 1;
967 ST_HAS_TRIANGLE_RELIEF(tmpms) = 1;
968 ST_DO_HILIGHT_BACK(tmpms) = 0;
969 ST_DO_HILIGHT_FORE(tmpms) = 0;
971 else /* i == 2 */
973 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
974 ST_POPUP_OFFSET_ADD(tmpms) =
975 -DEFAULT_MENU_BORDER_WIDTH - 3;
976 ST_DO_POPUP_IMMEDIATELY(tmpms) = 1;
977 ST_DO_WARP_TO_TITLE(tmpms) = 0;
978 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 1;
979 ST_RELIEF_THICKNESS(tmpms) = 0;
980 ST_TITLE_UNDERLINES(tmpms) = 1;
981 ST_HAS_LONG_SEPARATORS(tmpms) = 0;
982 ST_HAS_TRIANGLE_RELIEF(tmpms) = 0;
983 ST_DO_HILIGHT_BACK(tmpms) = 1;
984 ST_DO_HILIGHT_FORE(tmpms) = 1;
987 /* common settings */
988 ST_VERTICAL_MARGIN_TOP(tmpms) = 0;
989 ST_VERTICAL_MARGIN_BOTTOM(tmpms) = 0;
990 ST_CSET_MENU(tmpms) = 0;
991 ST_HAS_MENU_CSET(tmpms) = 0;
992 ST_CSET_ACTIVE(tmpms) = 0;
993 ST_HAS_ACTIVE_CSET(tmpms) = 0;
994 ST_CSET_GREYED(tmpms) = 0;
995 ST_HAS_GREYED_CSET(tmpms) = 0;
996 ST_BORDER_WIDTH(tmpms) = DEFAULT_MENU_BORDER_WIDTH;
997 ST_ACTIVE_AREA_PERCENT(tmpms) =
998 DEFAULT_MENU_POPUP_NOW_RATIO;
999 ST_ITEM_GAP_ABOVE(tmpms) =
1000 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET;
1001 ST_ITEM_GAP_BELOW(tmpms) =
1002 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2;
1003 ST_TITLE_GAP_ABOVE(tmpms) =
1004 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET;
1005 ST_TITLE_GAP_BELOW(tmpms) =
1006 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2;
1007 ST_USE_LEFT_SUBMENUS(tmpms) = 0;
1008 ST_IS_ANIMATED(tmpms) = 0;
1009 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = 0;
1010 menustyle_free_face(&ST_FACE(tmpms));
1011 ST_FACE(tmpms).type = SimpleMenu;
1012 if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms))
1014 FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms));
1016 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
1017 ST_USING_DEFAULT_FONT(tmpms) = True;
1018 has_gc_changed = True;
1019 if (ST_HAS_SIDE_COLOR(tmpms) == 1)
1021 fvwmlib_free_colors(
1022 dpy, &ST_SIDE_COLOR(tmpms), 1, True);
1023 ST_HAS_SIDE_COLOR(tmpms) = 0;
1025 ST_HAS_SIDE_COLOR(tmpms) = 0;
1026 if (ST_SIDEPIC(tmpms))
1028 PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms));
1029 ST_SIDEPIC(tmpms) = NULL;
1032 if (is_initialised == False)
1034 /* now begin the real work */
1035 is_initialised = True;
1036 continue;
1038 break;
1040 case 3: /* Foreground */
1041 fvwmlib_free_colors(
1042 dpy, &ST_MENU_COLORS(tmpms).fore, 1, True);
1043 if (arg1)
1045 ST_MENU_COLORS(tmpms).fore = GetColor(arg1);
1047 else
1049 ST_MENU_COLORS(tmpms).fore =
1050 GetColor(DEFAULT_FORE_COLOR);
1052 has_gc_changed = True;
1053 break;
1055 case 4: /* Background */
1056 fvwmlib_free_colors(
1057 dpy, &ST_MENU_COLORS(tmpms).back, 1, True);
1058 if (arg1)
1060 ST_MENU_COLORS(tmpms).back = GetColor(arg1);
1062 else
1064 ST_MENU_COLORS(tmpms).back =
1065 GetColor(DEFAULT_BACK_COLOR);
1067 has_gc_changed = True;
1068 break;
1070 case 5: /* Greyed */
1071 if (ST_HAS_STIPPLE_FORE(tmpms))
1073 fvwmlib_free_colors(
1074 dpy,
1075 &ST_MENU_STIPPLE_COLORS(tmpms).fore, 1,
1076 True);
1078 if (arg1 == NULL)
1080 ST_HAS_STIPPLE_FORE(tmpms) = 0;
1082 else
1084 ST_MENU_STIPPLE_COLORS(tmpms).fore =
1085 GetColor(arg1);
1086 ST_HAS_STIPPLE_FORE(tmpms) = 1;
1088 has_gc_changed = True;
1089 break;
1091 case 7: /* HilightBackOff */
1092 on ^= 1;
1093 /* fall throw */
1094 case 6: /* HilightBack */
1095 if (ST_HAS_ACTIVE_BACK(tmpms))
1097 fvwmlib_free_colors(
1098 dpy,
1099 &ST_MENU_ACTIVE_COLORS(tmpms).back, 1,
1100 True);
1102 if (arg1 == NULL || !on)
1104 ST_HAS_ACTIVE_BACK(tmpms) = 0;
1106 else
1108 ST_MENU_ACTIVE_COLORS(tmpms).back =
1109 GetColor(arg1);
1110 ST_HAS_ACTIVE_BACK(tmpms) = 1;
1112 ST_DO_HILIGHT_BACK(tmpms) = on;
1113 has_gc_changed = True;
1114 break;
1116 case 9: /* ActiveForeOff */
1117 on ^= 1;
1118 /* fall throw */
1119 case 8: /* ActiveFore */
1120 if (ST_HAS_ACTIVE_FORE(tmpms))
1122 fvwmlib_free_colors(
1123 dpy,
1124 &ST_MENU_ACTIVE_COLORS(tmpms).fore, 1,
1125 True);
1127 if (arg1 == NULL || !on)
1129 ST_HAS_ACTIVE_FORE(tmpms) = 0;
1131 else
1133 ST_MENU_ACTIVE_COLORS(tmpms).fore =
1134 GetColor(arg1);
1135 ST_HAS_ACTIVE_FORE(tmpms) = 1;
1137 ST_DO_HILIGHT_FORE(tmpms) = on;
1138 has_gc_changed = True;
1139 break;
1141 case 10: /* Hilight3DThick */
1142 ST_RELIEF_THICKNESS(tmpms) = 2;
1143 break;
1145 case 11: /* Hilight3DThin */
1146 ST_RELIEF_THICKNESS(tmpms) = 1;
1147 break;
1149 case 12: /* Hilight3DOff */
1150 ST_RELIEF_THICKNESS(tmpms) = 0;
1151 break;
1153 case 13: /* Animation */
1154 ST_IS_ANIMATED(tmpms) = on;
1155 break;
1157 case 14: /* AnimationOff */
1158 ST_IS_ANIMATED(tmpms) = !on;
1159 break;
1161 case 15: /* Font */
1162 if (arg1 != NULL &&
1163 !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm")))
1165 fvwm_msg(ERR, "NewMenuStyle",
1166 "Couldn't load font '%s'\n", arg1);
1167 break;
1169 if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms))
1171 FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms));
1173 if (arg1 == NULL)
1175 /* reset to screen font */
1176 ST_PSTDFONT(tmpms) = Scr.DefaultFont;
1177 ST_USING_DEFAULT_FONT(tmpms) = True;
1179 else
1181 ST_PSTDFONT(tmpms) = new_font;
1182 ST_USING_DEFAULT_FONT(tmpms) = False;
1184 has_gc_changed = True;
1185 break;
1187 case 16: /* MenuFace */
1188 while (args && *args != '\0' &&
1189 isspace((unsigned char)*args))
1191 args++;
1193 menustyle_parse_face(args, &ST_FACE(tmpms), True);
1194 break;
1196 case 17: /* PopupDelay */
1197 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1198 *val < 0)
1200 ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY;
1202 else
1204 ST_POPUP_DELAY(tmpms) = (*val+9)/10;
1206 break;
1208 case 18: /* PopupOffset */
1209 if ((n = GetIntegerArguments(args, NULL, val, 2)) == 0)
1211 fvwm_msg(ERR,"NewMenuStyle",
1212 "PopupOffset requires one or two"
1213 " arguments");
1215 else
1217 ST_POPUP_OFFSET_ADD(tmpms) = val[0];
1218 if (n == 2 && val[1] <= 100 && val[1] >= 0)
1220 ST_POPUP_OFFSET_PERCENT(tmpms) = val[1];
1222 else
1224 ST_POPUP_OFFSET_PERCENT(tmpms) = 100;
1227 break;
1229 case 19: /* TitleWarp */
1230 ST_DO_WARP_TO_TITLE(tmpms) = on;
1231 break;
1233 case 20: /* TitleWarpOff */
1234 ST_DO_WARP_TO_TITLE(tmpms) = !on;
1235 break;
1237 case 21: /* TitleUnderlines0 */
1238 ST_TITLE_UNDERLINES(tmpms) = 0;
1239 break;
1241 case 22: /* TitleUnderlines1 */
1242 ST_TITLE_UNDERLINES(tmpms) = 1;
1243 break;
1245 case 23: /* TitleUnderlines2 */
1246 ST_TITLE_UNDERLINES(tmpms) = 2;
1247 break;
1249 case 24: /* SeparatorsLong */
1250 ST_HAS_LONG_SEPARATORS(tmpms) = on;
1251 break;
1253 case 25: /* SeparatorsShort */
1254 ST_HAS_LONG_SEPARATORS(tmpms) = !on;
1255 break;
1257 case 26: /* TrianglesSolid */
1258 ST_HAS_TRIANGLE_RELIEF(tmpms) = !on;
1259 break;
1261 case 27: /* TrianglesRelief */
1262 ST_HAS_TRIANGLE_RELIEF(tmpms) = on;
1263 break;
1265 case 28: /* PopupImmediately */
1266 ST_DO_POPUP_IMMEDIATELY(tmpms) = on;
1267 break;
1269 case 29: /* PopupDelayed */
1270 ST_DO_POPUP_IMMEDIATELY(tmpms) = !on;
1271 break;
1273 case 30: /* DoubleClickTime */
1274 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1275 *val < 0)
1277 ST_DOUBLE_CLICK_TIME(tmpms) =
1278 DEFAULT_MENU_CLICKTIME;
1280 else
1282 ST_DOUBLE_CLICK_TIME(tmpms) = *val;
1284 break;
1286 case 31: /* SidePic */
1287 if (ST_SIDEPIC(tmpms))
1289 PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms));
1290 ST_SIDEPIC(tmpms) = NULL;
1292 if (arg1)
1294 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
1295 ST_SIDEPIC(tmpms) = PCacheFvwmPicture(
1296 dpy, Scr.NoFocusWin, NULL, arg1, fpa);
1297 if (!ST_SIDEPIC(tmpms))
1299 fvwm_msg(WARN, "NewMenuStyle",
1300 "Couldn't find pixmap %s",
1301 arg1);
1304 break;
1306 case 32: /* SideColor */
1307 if (ST_HAS_SIDE_COLOR(tmpms) == 1)
1309 fvwmlib_free_colors(
1310 dpy, &ST_SIDE_COLOR(tmpms), 1, True);
1311 ST_HAS_SIDE_COLOR(tmpms) = 0;
1313 if (arg1)
1315 ST_SIDE_COLOR(tmpms) = GetColor(arg1);
1316 ST_HAS_SIDE_COLOR(tmpms) = 1;
1318 break;
1320 case 33: /* PopupAsRootmenu */
1321 ST_DO_POPUP_AS(tmpms) = MDP_ROOT_MENU;
1322 break;
1324 case 34: /* PopupAsSubmenu */
1325 ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU;
1326 break;
1328 case 35: /* RemoveSubmenus */
1329 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = on;
1330 break;
1332 case 36: /* HoldSubmenus */
1333 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = !on;
1334 break;
1336 case 37: /* SubmenusRight */
1337 ST_USE_LEFT_SUBMENUS(tmpms) = !on;
1338 break;
1340 case 38: /* SubmenusLeft */
1341 ST_USE_LEFT_SUBMENUS(tmpms) = on;
1342 break;
1344 case 39: /* BorderWidth */
1345 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1346 *val < 0 || *val > MAX_MENU_BORDER_WIDTH)
1348 ST_BORDER_WIDTH(tmpms) =
1349 DEFAULT_MENU_BORDER_WIDTH;
1351 else
1353 ST_BORDER_WIDTH(tmpms) = *val;
1355 break;
1357 case 40: /* Hilight3DThickness */
1358 if (GetIntegerArguments(args, NULL, val, 1) > 0)
1360 if (*val < 0)
1362 *val = -*val;
1363 ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 1;
1365 else
1367 ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 0;
1369 if (*val > MAX_MENU_ITEM_RELIEF_THICKNESS)
1370 *val = MAX_MENU_ITEM_RELIEF_THICKNESS;
1371 ST_RELIEF_THICKNESS(tmpms) = *val;
1373 break;
1375 case 41: /* ItemFormat */
1376 if (ST_ITEM_FORMAT(tmpms))
1378 free(ST_ITEM_FORMAT(tmpms));
1379 ST_ITEM_FORMAT(tmpms) = NULL;
1381 if (arg1)
1383 ST_ITEM_FORMAT(tmpms) = safestrdup(arg1);
1385 break;
1387 case 42: /* AutomaticHotkeys */
1388 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = on;
1389 break;
1391 case 43: /* AutomaticHotkeysOff */
1392 ST_USE_AUTOMATIC_HOTKEYS(tmpms) = !on;
1393 break;
1395 case 44: /* VerticalItemSpacing */
1396 parse_vertical_spacing_line(
1397 args, &ST_ITEM_GAP_ABOVE(tmpms),
1398 &ST_ITEM_GAP_BELOW(tmpms),
1399 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET,
1400 DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2);
1401 break;
1403 case 45: /* VerticalTitleSpacing */
1404 parse_vertical_spacing_line(
1405 args, &ST_TITLE_GAP_ABOVE(tmpms),
1406 &ST_TITLE_GAP_BELOW(tmpms),
1407 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET,
1408 DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2);
1409 break;
1410 case 46: /* MenuColorset */
1411 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1412 *val < 0)
1414 ST_HAS_MENU_CSET(tmpms) = 0;
1415 ST_CSET_MENU(tmpms) = 0;
1417 else
1419 ST_HAS_MENU_CSET(tmpms) = 1;
1420 ST_CSET_MENU(tmpms) = *val;
1421 alloc_colorset(*val);
1423 has_gc_changed = True;
1424 break;
1425 case 47: /* ActiveColorset */
1426 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1427 *val < 0)
1429 ST_HAS_ACTIVE_CSET(tmpms) = 0;
1430 ST_CSET_ACTIVE(tmpms) = 0;
1432 else
1434 ST_HAS_ACTIVE_CSET(tmpms) = 1;
1435 ST_CSET_ACTIVE(tmpms) = *val;
1436 alloc_colorset(*val);
1438 has_gc_changed = True;
1439 break;
1441 case 48: /* GreyedColorset */
1442 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1443 *val < 0)
1445 ST_HAS_GREYED_CSET(tmpms) = 0;
1446 ST_CSET_GREYED(tmpms) = 0;
1448 else
1450 ST_HAS_GREYED_CSET(tmpms) = 1;
1451 ST_CSET_GREYED(tmpms) = *val;
1452 alloc_colorset(*val);
1454 has_gc_changed = True;
1455 break;
1457 case 49: /* SelectOnRelease */
1458 keycode = 0;
1459 if (arg1)
1461 keycode = XKeysymToKeycode(
1462 dpy, FvwmStringToKeysym(dpy, arg1));
1464 ST_SELECT_ON_RELEASE_KEY(tmpms) = keycode;
1465 break;
1467 case 50: /* PopdownImmediately */
1468 ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 1;
1469 break;
1471 case 51: /* PopdownDelayed */
1472 ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 0;
1473 break;
1475 case 52: /* PopdownDelay */
1476 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1477 *val < 0)
1479 ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY;
1481 else
1483 ST_POPDOWN_DELAY(tmpms) = (*val+9)/10;
1485 break;
1487 case 53: /* PopupActiveArea */
1488 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1489 *val <= 50 || *val > 100)
1491 ST_ACTIVE_AREA_PERCENT(tmpms) =
1492 DEFAULT_MENU_POPUP_NOW_RATIO;
1494 else
1496 ST_ACTIVE_AREA_PERCENT(tmpms) = *val;
1498 break;
1500 case 54: /* PopupIgnore */
1501 ST_DO_POPUP_AS(tmpms) = MDP_IGNORE;
1502 break;
1504 case 55: /* PopupClose */
1505 ST_DO_POPUP_AS(tmpms) = MDP_CLOSE;
1506 break;
1508 case 56: /* MouseWheel */
1509 if (arg1)
1511 if (StrEquals(arg1, "ActivatesItem"))
1513 ST_MOUSE_WHEEL(tmpms) = MMW_OFF;
1515 else if (StrEquals(arg1,
1516 "ScrollsMenuBackwards"))
1518 ST_MOUSE_WHEEL(tmpms) =
1519 MMW_MENU_BACKWARDS;
1521 else if (StrEquals(arg1, "ScrollsMenu"))
1523 ST_MOUSE_WHEEL(tmpms) = MMW_MENU;
1525 else if (StrEquals(arg1, "ScrollsPointer"))
1527 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
1529 else
1531 fvwm_msg(
1532 ERR, "NewMenuStyle",
1533 "unknown argument to"
1534 " MouseWheel '%s'",
1535 arg1);
1536 ST_MOUSE_WHEEL(tmpms) = MMW_POINTER;
1539 else
1541 ST_MOUSE_WHEEL(tmpms) =
1542 (on) ? MMW_POINTER : MMW_OFF;
1544 break;
1545 case 57: /* ScrollOffPage */
1546 ST_SCROLL_OFF_PAGE(tmpms) = on;
1547 break;
1549 case 58: /* TrianglesUseFore */
1550 ST_TRIANGLES_USE_FORE(tmpms) = on;
1551 break;
1552 case 59: /* TitleColorset */
1553 if (GetIntegerArguments(args, NULL, val, 1) == 0 ||
1554 *val < 0)
1556 ST_HAS_TITLE_CSET(tmpms) = 0;
1557 ST_CSET_TITLE(tmpms) = 0;
1559 else
1561 ST_HAS_TITLE_CSET(tmpms) = 1;
1562 ST_CSET_TITLE(tmpms) = *val;
1563 alloc_colorset(*val);
1565 has_gc_changed = True;
1566 break;
1567 case 60: /* TitleHilightBack */
1568 ST_DO_HILIGHT_TITLE_BACK(tmpms) = on;
1569 has_gc_changed = True;
1570 break;
1571 case 61: /* TitleFont */
1572 if (arg1 != NULL &&
1573 !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm")))
1575 fvwm_msg(ERR, "NewMenuStyle",
1576 "Couldn't load font '%s'\n", arg1);
1577 break;
1579 if (
1580 ST_PTITLEFONT(tmpms) &&
1581 !ST_USING_DEFAULT_TITLEFONT(tmpms))
1583 FlocaleUnloadFont(dpy, ST_PTITLEFONT(tmpms));
1585 if (arg1 == NULL)
1587 /* reset to screen font */
1588 ST_PTITLEFONT(tmpms) = Scr.DefaultFont;
1589 ST_USING_DEFAULT_TITLEFONT(tmpms) = True;
1591 else
1593 ST_PTITLEFONT(tmpms) = new_font;
1594 ST_USING_DEFAULT_TITLEFONT(tmpms) = False;
1596 has_gc_changed = True;
1597 break;
1598 case 62: /* VerticalMargins */
1599 parse_vertical_margins_line(
1600 args, &ST_VERTICAL_MARGIN_TOP(tmpms),
1601 &ST_VERTICAL_MARGIN_BOTTOM(tmpms),
1602 0, 0);
1603 break;
1605 #if 0
1606 case 99: /* PositionHints */
1607 /* to be implemented */
1608 break;
1609 #endif
1611 default:
1612 fvwm_msg(ERR, "NewMenuStyle", "unknown option '%s'",
1613 poption);
1614 break;
1615 } /* switch */
1617 if (option)
1619 free(option);
1620 option = NULL;
1622 free(optstring);
1623 optstring = NULL;
1624 if (arg1)
1626 free(arg1);
1627 arg1 = NULL;
1629 } /* while */
1631 if (has_gc_changed)
1633 menustyle_update(tmpms);
1636 if (default_menu_style == NULL)
1638 /* First MenuStyle MUST be the default style */
1639 default_menu_style = tmpms;
1640 ST_NEXT_STYLE(tmpms) = NULL;
1642 else if (ms)
1644 /* copy our new menu face over the old one */
1645 memcpy(ms, tmpms, sizeof(MenuStyle));
1646 free(tmpms);
1647 return ms;
1649 else
1651 MenuStyle *before = default_menu_style;
1653 /* add a new menu face to list */
1654 ST_NEXT_STYLE(tmpms) = NULL;
1655 while (ST_NEXT_STYLE(before))
1656 before = ST_NEXT_STYLE(before);
1657 ST_NEXT_STYLE(before) = tmpms;
1660 return tmpms;
1663 void menustyle_copy(MenuStyle *origms, MenuStyle *destms)
1665 FvwmPictureAttributes fpa;
1666 /* Copy origms to destms, be aware of all pointers in the MenuStyle
1667 strcture. Use the same order as in menustyle_parse_style */
1669 /* menu colors */
1670 fvwmlib_copy_color(
1671 dpy, &ST_MENU_COLORS(destms).fore,
1672 &ST_MENU_COLORS(origms).fore, True, True);
1673 fvwmlib_copy_color(
1674 dpy, &ST_MENU_COLORS(destms).back,
1675 &ST_MENU_COLORS(origms).back, True, True);
1676 /* Greyed */
1677 fvwmlib_copy_color(
1678 dpy, &ST_MENU_STIPPLE_COLORS(destms).fore,
1679 &ST_MENU_STIPPLE_COLORS(origms).fore,
1680 ST_HAS_STIPPLE_FORE(destms), ST_HAS_STIPPLE_FORE(origms));
1681 ST_MENU_STIPPLE_COLORS(destms).back =
1682 ST_MENU_STIPPLE_COLORS(origms).back;
1683 ST_HAS_STIPPLE_FORE(destms) = ST_HAS_STIPPLE_FORE(origms);
1685 /* HilightBack */
1686 fvwmlib_copy_color(
1687 dpy, &ST_MENU_ACTIVE_COLORS(destms).back,
1688 &ST_MENU_ACTIVE_COLORS(origms).back,
1689 ST_HAS_ACTIVE_BACK(destms), ST_HAS_ACTIVE_BACK(origms));
1690 ST_HAS_ACTIVE_BACK(destms) = ST_HAS_ACTIVE_BACK(origms);
1691 ST_DO_HILIGHT_BACK(destms) = ST_DO_HILIGHT_BACK(origms);
1693 /* ActiveFore */
1694 fvwmlib_copy_color(
1695 dpy, &ST_MENU_ACTIVE_COLORS(destms).fore,
1696 &ST_MENU_ACTIVE_COLORS(origms).fore,
1697 ST_HAS_ACTIVE_FORE(destms), ST_HAS_ACTIVE_FORE(origms));
1698 ST_HAS_ACTIVE_FORE(destms) = ST_HAS_ACTIVE_FORE(origms);
1699 ST_DO_HILIGHT_FORE(destms) = ST_DO_HILIGHT_FORE(origms);
1701 /* Hilight3D */
1702 ST_RELIEF_THICKNESS(destms) = ST_RELIEF_THICKNESS(origms);
1703 /* Animation */
1704 ST_IS_ANIMATED(destms) = ST_IS_ANIMATED(origms);
1706 /* font */
1707 if (ST_PSTDFONT(destms) && !ST_USING_DEFAULT_FONT(destms))
1709 FlocaleUnloadFont(dpy, ST_PSTDFONT(destms));
1711 if (ST_PSTDFONT(origms) && !ST_USING_DEFAULT_FONT(origms))
1713 if (!(ST_PSTDFONT(destms) =
1714 FlocaleLoadFont(dpy, ST_PSTDFONT(origms)->name, "fvwm")))
1716 ST_PSTDFONT(destms) = Scr.DefaultFont;
1717 ST_USING_DEFAULT_FONT(destms) = True;
1718 fvwm_msg(ERR, "CopyMenuStyle",
1719 "Couldn't load font '%s' use Default Font\n",
1720 ST_PSTDFONT(origms)->name);
1722 else
1724 ST_USING_DEFAULT_FONT(destms) = False;
1727 else
1729 ST_USING_DEFAULT_FONT(destms) = True;
1730 ST_PSTDFONT(destms) = Scr.DefaultFont;
1732 /* TitleFont */
1733 if (ST_PTITLEFONT(destms) && !ST_USING_DEFAULT_TITLEFONT(destms))
1735 FlocaleUnloadFont(dpy, ST_PTITLEFONT(destms));
1737 if (ST_PTITLEFONT(origms) && !ST_USING_DEFAULT_TITLEFONT(origms))
1739 if (
1740 !(ST_PTITLEFONT(destms) = FlocaleLoadFont(
1741 dpy, ST_PTITLEFONT(origms)->name, "fvwm")))
1743 ST_PTITLEFONT(destms) = Scr.DefaultFont;
1744 ST_USING_DEFAULT_TITLEFONT(destms) = True;
1745 fvwm_msg(ERR, "CopyMenuStyle",
1746 "Couldn't load font '%s' use Default Font\n",
1747 ST_PTITLEFONT(origms)->name);
1749 else
1751 ST_USING_DEFAULT_TITLEFONT(destms) = False;
1754 else
1756 ST_USING_DEFAULT_TITLEFONT(destms) = True;
1757 ST_PTITLEFONT(destms) = Scr.DefaultFont;
1759 /* MenuFace */
1760 menustyle_copy_face(&ST_FACE(destms), &ST_FACE(origms));
1762 /* PopupDelay */
1763 ST_POPUP_DELAY(destms) = ST_POPUP_DELAY(origms);
1764 /* PopupOffset */
1765 ST_POPUP_OFFSET_PERCENT(destms) = ST_POPUP_OFFSET_PERCENT(origms);
1766 ST_POPUP_OFFSET_ADD(destms) = ST_POPUP_OFFSET_ADD(origms);
1767 /* TitleWarp */
1768 ST_DO_WARP_TO_TITLE(destms) = ST_DO_WARP_TO_TITLE(origms);
1769 /* TitleUnderlines */
1770 ST_TITLE_UNDERLINES(destms) = ST_TITLE_UNDERLINES(origms);
1771 /* Separators */
1772 ST_HAS_LONG_SEPARATORS(destms) = ST_HAS_LONG_SEPARATORS(origms);
1773 /* Triangles */
1774 ST_HAS_TRIANGLE_RELIEF(destms) = ST_HAS_TRIANGLE_RELIEF(origms);
1775 /* PopupDelayed */
1776 ST_DO_POPUP_IMMEDIATELY(destms) = ST_DO_POPUP_IMMEDIATELY(origms);
1777 /* DoubleClickTime */
1778 ST_DOUBLE_CLICK_TIME(destms) = ST_DOUBLE_CLICK_TIME(origms);
1779 /* VerticalMargins */
1780 ST_VERTICAL_MARGIN_TOP(destms) = ST_VERTICAL_MARGIN_TOP(origms);
1781 ST_VERTICAL_MARGIN_BOTTOM(destms) = ST_VERTICAL_MARGIN_BOTTOM(origms);
1783 /* SidePic */
1784 if (ST_SIDEPIC(destms))
1786 PDestroyFvwmPicture(dpy, ST_SIDEPIC(destms));
1787 ST_SIDEPIC(destms) = NULL;
1789 if (ST_SIDEPIC(origms))
1791 fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
1792 ST_SIDEPIC(destms) = PCacheFvwmPicture(
1793 dpy, Scr.NoFocusWin, NULL, ST_SIDEPIC(origms)->name,
1794 fpa);
1797 /* side color */
1798 fvwmlib_copy_color(
1799 dpy, &ST_SIDE_COLOR(destms), &ST_SIDE_COLOR(origms),
1800 ST_HAS_SIDE_COLOR(destms), ST_HAS_SIDE_COLOR(origms));
1801 ST_HAS_SIDE_COLOR(destms) = ST_HAS_SIDE_COLOR(origms);
1803 /* PopupAsRootmenu */
1804 ST_DO_POPUP_AS(destms) = ST_DO_POPUP_AS(origms);
1805 /* RemoveSubmenus */
1806 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(destms) =
1807 ST_DO_UNMAP_SUBMENU_ON_POPDOWN(origms);
1808 /* SubmenusRight */
1809 ST_USE_LEFT_SUBMENUS(destms) = ST_USE_LEFT_SUBMENUS(origms);
1810 /* BorderWidth */
1811 ST_BORDER_WIDTH(destms) = ST_BORDER_WIDTH(origms);
1812 /* Hilight3DThickness */
1813 ST_IS_ITEM_RELIEF_REVERSED(destms) =
1814 ST_IS_ITEM_RELIEF_REVERSED(origms);
1816 /* ItemFormat */
1817 if (ST_ITEM_FORMAT(destms))
1819 free(ST_ITEM_FORMAT(destms));
1820 ST_ITEM_FORMAT(destms) = NULL;
1822 if (ST_ITEM_FORMAT(origms))
1824 ST_ITEM_FORMAT(destms) = safestrdup(ST_ITEM_FORMAT(origms));
1827 /* AutomaticHotkeys */
1828 ST_USE_AUTOMATIC_HOTKEYS(destms) = ST_USE_AUTOMATIC_HOTKEYS(origms);
1829 /* Item and Title Spacing */
1830 ST_ITEM_GAP_ABOVE(destms) = ST_ITEM_GAP_ABOVE(origms);
1831 ST_ITEM_GAP_BELOW(destms) = ST_ITEM_GAP_BELOW(origms);
1832 ST_TITLE_GAP_ABOVE(destms) = ST_TITLE_GAP_ABOVE(origms);
1833 ST_TITLE_GAP_BELOW(destms) = ST_TITLE_GAP_BELOW(origms);
1834 /* MenuColorset */
1835 ST_HAS_MENU_CSET(destms) = ST_HAS_MENU_CSET(origms);
1836 ST_CSET_MENU(destms) = ST_CSET_MENU(origms);
1837 /* ActiveColorset */
1838 ST_HAS_ACTIVE_CSET(destms) = ST_HAS_ACTIVE_CSET(origms);
1839 ST_CSET_ACTIVE(destms) = ST_CSET_ACTIVE(origms);
1840 /* MenuColorset */
1841 ST_HAS_GREYED_CSET(destms) = ST_HAS_GREYED_CSET(origms);
1842 ST_CSET_GREYED(destms) = ST_CSET_GREYED(origms);
1843 /* TitleColorset */
1844 ST_HAS_TITLE_CSET(destms) = ST_HAS_TITLE_CSET(origms);
1845 ST_CSET_TITLE(destms) = ST_CSET_TITLE(origms);
1846 /* SelectOnRelease */
1847 ST_SELECT_ON_RELEASE_KEY(destms) = ST_SELECT_ON_RELEASE_KEY(origms);
1848 /* PopdownImmediately */
1849 ST_DO_POPDOWN_IMMEDIATELY(destms) = ST_DO_POPDOWN_IMMEDIATELY(origms);
1850 /* PopdownDelay */
1851 ST_POPDOWN_DELAY(destms) = ST_POPDOWN_DELAY(origms);
1852 /* Scroll */
1853 ST_MOUSE_WHEEL(destms) = ST_MOUSE_WHEEL(origms);
1854 /* ScrollOffPage */
1855 ST_SCROLL_OFF_PAGE(destms) = ST_SCROLL_OFF_PAGE(origms);
1856 /* TrianglesUseFore */
1857 ST_TRIANGLES_USE_FORE(destms) = ST_TRIANGLES_USE_FORE(origms);
1858 /* Title */
1859 ST_DO_HILIGHT_TITLE_BACK(destms) = ST_DO_HILIGHT_TITLE_BACK(origms);
1861 menustyle_update(destms);
1863 return;
1866 /* ---------------------------- builtin commands --------------------------- */
1868 void CMD_CopyMenuStyle(F_CMD_ARGS)
1870 char *origname = NULL;
1871 char *destname = NULL;
1872 char *buffer;
1873 MenuStyle *origms;
1874 MenuStyle *destms;
1876 origname = PeekToken(action, &action);
1877 if (origname == NULL)
1879 fvwm_msg(ERR,"CopyMenuStyle", "need two arguments");
1880 return;
1883 origms = menustyle_find(origname);
1884 if (!origms)
1886 fvwm_msg(ERR, "CopyMenuStyle", "%s: no such menu style",
1887 origname);
1888 return;
1891 destname = PeekToken(action, &action);
1892 if (destname == NULL)
1894 fvwm_msg(ERR,"CopyMenuStyle", "need two arguments");
1895 return;
1898 if (action && *action)
1900 fvwm_msg(ERR,"CopyMenuStyle", "too many arguments");
1901 return;
1904 destms = menustyle_find(destname);
1905 if (!destms)
1907 /* create destms menu style */
1908 buffer = (char *)safemalloc(strlen(destname) + 3);
1909 sprintf(buffer,"\"%s\"",destname);
1910 action = buffer;
1911 destms = menustyle_parse_style(F_PASS_ARGS);
1912 free(buffer);
1913 if (!destms)
1915 /* this must never happen */
1916 fvwm_msg(ERR, "CopyMenuStyle",
1917 "impossible to create %s menu style",
1918 destname);
1919 return;
1923 if (strcasecmp("*",destname) == 0)
1925 fvwm_msg(ERR, "CopyMenuStyle",
1926 "You cannot copy on the default menu style");
1927 return;
1929 if (strcasecmp(ST_NAME(origms),destname) == 0)
1931 fvwm_msg(ERR, "CopyMenuStyle",
1932 "%s and %s identify the same menu style",
1933 ST_NAME(origms),destname);
1934 return;
1937 if (ST_USAGE_COUNT(destms) != 0)
1939 fvwm_msg(ERR, "CopyMenuStyle", "menu style %s is in use",
1940 destname);
1941 return;
1944 menustyle_copy(origms, destms);
1946 return;
1949 void CMD_MenuStyle(F_CMD_ARGS)
1951 char *option;
1952 char *poption;
1953 MenuStyle *dummy;
1955 GetNextSimpleOption(SkipNTokens(action, 1), &option);
1956 poption = option;
1957 while (poption && poption[0] == '!')
1959 poption++;
1961 if (option == NULL || menustyle_get_styleopt_index(poption) != -1)
1963 dummy = menustyle_parse_style(F_PASS_ARGS);
1965 else
1967 dummy = menustyle_parse_old_style(F_PASS_ARGS);
1969 if (option)
1971 free(option);
1974 return;