Maximus: Tiled Maximization
[wmaker-crm.git] / src / defaults.c
1 /* defaults.c - manage configuration through defaults db
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
22 */
23
24 #include "wconfig.h"
25
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <time.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <limits.h>
37 #include <signal.h>
38
39 #ifdef HAVE_DLFCN_H
40 # include <dlfcn.h>
41 #endif
42
43 #ifndef PATH_MAX
44 #define PATH_MAX DEFAULT_PATH_MAX
45 #endif
46
47 #include <X11/Xlib.h>
48 #include <X11/Xutil.h>
49 #include <X11/keysym.h>
50
51 #include <wraster.h>
52
53 #include "WindowMaker.h"
54 #include "wcore.h"
55 #include "framewin.h"
56 #include "window.h"
57 #include "texture.h"
58 #include "screen.h"
59 #include "resources.h"
60 #include "defaults.h"
61 #include "keybind.h"
62 #include "xmodifier.h"
63 #include "icon.h"
64 #include "funcs.h"
65 #include "actions.h"
66 #include "dock.h"
67 #include "workspace.h"
68 #include "properties.h"
69
70 #define MAX_SHORTCUT_LENGTH 32
71
72 #ifndef GLOBAL_DEFAULTS_SUBDIR
73 #define GLOBAL_DEFAULTS_SUBDIR "WindowMaker"
74 #endif
75
76 /***** Global *****/
77
78 extern WDDomain *WDWindowMaker;
79 extern WDDomain *WDWindowAttributes;
80 extern WDDomain *WDRootMenu;
81
82 extern int wScreenCount;
83
84 extern Atom _XA_WINDOWMAKER_ICON_SIZE;
85 extern Atom _XA_WINDOWMAKER_ICON_TILE;
86
87 /*
88 extern WMPropList *wDomainName;
89 extern WMPropList *wAttributeDomainName;
90 */
91 extern WPreferences wPreferences;
92
93 extern WShortKey wKeyBindings[WKBD_LAST];
94
95 typedef struct {
96 char *key;
97 char *default_value;
98 void *extra_data;
99 void *addr;
100 int (*convert) ();
101 int (*update) ();
102 WMPropList *plkey;
103 WMPropList *plvalue; /* default value */
104 } WDefaultEntry;
105
106 /* used to map strings to integers */
107 typedef struct {
108 char *string;
109 short value;
110 char is_alias;
111 } WOptionEnumeration;
112
113 /* type converters */
114 static int getBool();
115 static int getInt();
116 static int getCoord();
117 #if 0
118 /* this is not used yet */
119 static int getString();
120 #endif
121 static int getPathList();
122 static int getEnum();
123 static int getTexture();
124 static int getWSBackground();
125 static int getWSSpecificBackground();
126 static int getFont();
127 static int getColor();
128 static int getKeybind();
129 static int getModMask();
130 #ifdef NEWSTUFF
131 static int getRImage();
132 #endif
133 static int getPropList();
134
135 /* value setting functions */
136 static int setJustify();
137 static int setClearance();
138 static int setIfDockPresent();
139 static int setStickyIcons();
140 /*
141 static int setPositive();
142 */
143 static int setWidgetColor();
144 static int setIconTile();
145 static int setWinTitleFont();
146 static int setMenuTitleFont();
147 static int setMenuTextFont();
148 static int setIconTitleFont();
149 static int setIconTitleColor();
150 static int setIconTitleBack();
151 static int setLargeDisplayFont();
152 static int setWTitleColor();
153 static int setFTitleBack();
154 static int setPTitleBack();
155 static int setUTitleBack();
156 static int setResizebarBack();
157 static int setWorkspaceBack();
158 static int setWorkspaceSpecificBack();
159 #ifdef VIRTUAL_DESKTOP
160 static int setVirtualDeskEnable();
161 #endif
162 static int setMenuTitleColor();
163 static int setMenuTextColor();
164 static int setMenuDisabledColor();
165 static int setMenuTitleBack();
166 static int setMenuTextBack();
167 static int setHightlight();
168 static int setHightlightText();
169 static int setKeyGrab();
170 static int setDoubleClick();
171 static int setIconPosition();
172
173 static int setClipTitleFont();
174 static int setClipTitleColor();
175
176 static int setMenuStyle();
177 static int setSwPOptions();
178 static int updateUsableArea();
179
180 extern Cursor wCursor[WCUR_LAST];
181 static int getCursor();
182 static int setCursor();
183
184 /*
185 * Tables to convert strings to enumeration values.
186 * Values stored are char
187 */
188
189 /* WARNING: sum of length of all value strings must not exceed
190 * this value */
191 #define TOTAL_VALUES_LENGTH 80
192
193 #define REFRESH_WINDOW_TEXTURES (1<<0)
194 #define REFRESH_MENU_TEXTURE (1<<1)
195 #define REFRESH_MENU_FONT (1<<2)
196 #define REFRESH_MENU_COLOR (1<<3)
197 #define REFRESH_MENU_TITLE_TEXTURE (1<<4)
198 #define REFRESH_MENU_TITLE_FONT (1<<5)
199 #define REFRESH_MENU_TITLE_COLOR (1<<6)
200 #define REFRESH_WINDOW_TITLE_COLOR (1<<7)
201 #define REFRESH_WINDOW_FONT (1<<8)
202 #define REFRESH_ICON_TILE (1<<9)
203 #define REFRESH_ICON_FONT (1<<10)
204 #define REFRESH_WORKSPACE_BACK (1<<11)
205
206 #define REFRESH_BUTTON_IMAGES (1<<12)
207
208 #define REFRESH_ICON_TITLE_COLOR (1<<13)
209 #define REFRESH_ICON_TITLE_BACK (1<<14)
210
211 static WOptionEnumeration seFocusModes[] = {
212 {"Manual", WKF_CLICK, 0}, {"ClickToFocus", WKF_CLICK, 1},
213 {"Sloppy", WKF_SLOPPY, 0}, {"SemiAuto", WKF_SLOPPY, 1}, {"Auto", WKF_SLOPPY, 1},
214 {NULL, 0, 0}
215 };
216
217 static WOptionEnumeration seColormapModes[] = {
218 {"Manual", WCM_CLICK, 0}, {"ClickToFocus", WCM_CLICK, 1},
219 {"Auto", WCM_POINTER, 0}, {"FocusFollowMouse", WCM_POINTER, 1},
220 {NULL, 0, 0}
221 };
222
223 static WOptionEnumeration sePlacements[] = {
224 {"Auto", WPM_AUTO, 0},
225 {"Smart", WPM_SMART, 0},
226 {"Cascade", WPM_CASCADE, 0},
227 {"Random", WPM_RANDOM, 0},
228 {"Manual", WPM_MANUAL, 0},
229 {NULL, 0, 0}
230 };
231
232 static WOptionEnumeration seGeomDisplays[] = {
233 {"None", WDIS_NONE, 0},
234 {"Center", WDIS_CENTER, 0},
235 {"Corner", WDIS_TOPLEFT, 0},
236 {"Floating", WDIS_FRAME_CENTER, 0},
237 {"Line", WDIS_NEW, 0},
238 {NULL, 0, 0}
239 };
240
241 static WOptionEnumeration seSpeeds[] = {
242 {"UltraFast", SPEED_ULTRAFAST, 0},
243 {"Fast", SPEED_FAST, 0},
244 {"Medium", SPEED_MEDIUM, 0},
245 {"Slow", SPEED_SLOW, 0},
246 {"UltraSlow", SPEED_ULTRASLOW, 0},
247 {NULL, 0, 0}
248 };
249
250 static WOptionEnumeration seMouseButtonActions[] = {
251 {"None", WA_NONE, 0},
252 {"SelectWindows", WA_SELECT_WINDOWS, 0},
253 {"OpenApplicationsMenu", WA_OPEN_APPMENU, 0},
254 {"OpenWindowListMenu", WA_OPEN_WINLISTMENU, 0},
255 {NULL, 0, 0}
256 };
257
258 static WOptionEnumeration seMouseWheelActions[] = {
259 {"None", WA_NONE, 0},
260 {"SwitchWorkspaces", WA_SWITCH_WORKSPACES, 0},
261 {NULL, 0, 0}
262 };
263
264 static WOptionEnumeration seIconificationStyles[] = {
265 {"Zoom", WIS_ZOOM, 0},
266 {"Twist", WIS_TWIST, 0},
267 {"Flip", WIS_FLIP, 0},
268 {"None", WIS_NONE, 0},
269 {"random", WIS_RANDOM, 0},
270 {NULL, 0, 0}
271 };
272
273 static WOptionEnumeration seJustifications[] = {
274 {"Left", WTJ_LEFT, 0},
275 {"Center", WTJ_CENTER, 0},
276 {"Right", WTJ_RIGHT, 0},
277 {NULL, 0, 0}
278 };
279
280 static WOptionEnumeration seIconPositions[] = {
281 {"blv", IY_BOTTOM | IY_LEFT | IY_VERT, 0},
282 {"blh", IY_BOTTOM | IY_LEFT | IY_HORIZ, 0},
283 {"brv", IY_BOTTOM | IY_RIGHT | IY_VERT, 0},
284 {"brh", IY_BOTTOM | IY_RIGHT | IY_HORIZ, 0},
285 {"tlv", IY_TOP | IY_LEFT | IY_VERT, 0},
286 {"tlh", IY_TOP | IY_LEFT | IY_HORIZ, 0},
287 {"trv", IY_TOP | IY_RIGHT | IY_VERT, 0},
288 {"trh", IY_TOP | IY_RIGHT | IY_HORIZ, 0},
289 {NULL, 0, 0}
290 };
291
292 static WOptionEnumeration seMenuStyles[] = {
293 {"normal", MS_NORMAL, 0},
294 {"singletexture", MS_SINGLE_TEXTURE, 0},
295 {"flat", MS_FLAT, 0},
296 {NULL, 0, 0}
297 };
298
299 static WOptionEnumeration seDisplayPositions[] = {
300 {"none", WD_NONE, 0},
301 {"center", WD_CENTER, 0},
302 {"top", WD_TOP, 0},
303 {"bottom", WD_BOTTOM, 0},
304 {"topleft", WD_TOPLEFT, 0},
305 {"topright", WD_TOPRIGHT, 0},
306 {"bottomleft", WD_BOTTOMLEFT, 0},
307 {"bottomright", WD_BOTTOMRIGHT, 0},
308 {NULL, 0, 0}
309 };
310
311 static WOptionEnumeration seWorkspaceBorder[] = {
312 {"None", WB_NONE, 0},
313 {"LeftRight", WB_LEFTRIGHT, 0},
314 {"TopBottom", WB_TOPBOTTOM, 0},
315 {"AllDirections", WB_ALLDIRS, 0},
316 {NULL, 0, 0}
317 };
318
319 /*
320 * ALL entries in the tables bellow, NEED to have a default value
321 * defined, and this value needs to be correct.
322 */
323
324 /* these options will only affect the window manager on startup
325 *
326 * static defaults can't access the screen data, because it is
327 * created after these defaults are read
328 */
329 WDefaultEntry staticOptionList[] = {
330
331 {"ColormapSize", "4", NULL,
332 &wPreferences.cmap_size, getInt, NULL},
333 {"DisableDithering", "NO", NULL,
334 &wPreferences.no_dithering, getBool, NULL},
335 /* static by laziness */
336 {"IconSize", "64", NULL,
337 &wPreferences.icon_size, getInt, NULL},
338 {"ModifierKey", "Mod1", NULL,
339 &wPreferences.modifier_mask, getModMask, NULL},
340 {"DisableWSMouseActions", "NO", NULL,
341 &wPreferences.disable_root_mouse, getBool, NULL},
342 {"FocusMode", "manual", seFocusModes,
343 &wPreferences.focus_mode, getEnum, NULL}, /* have a problem when switching from manual to sloppy without restart */
344 {"NewStyle", "NO", NULL,
345 &wPreferences.new_style, getBool, NULL},
346 {"DisableDock", "NO", (void *)WM_DOCK,
347 NULL, getBool, setIfDockPresent},
348 {"DisableClip", "NO", (void *)WM_CLIP,
349 NULL, getBool, setIfDockPresent},
350 {"DisableMiniwindows", "NO", NULL,
351 &wPreferences.disable_miniwindows, getBool, NULL}
352 };
353
354 WDefaultEntry optionList[] = {
355 /* dynamic options */
356 {"IconPosition", "blh", seIconPositions,
357 &wPreferences.icon_yard, getEnum, setIconPosition},
358 {"IconificationStyle", "Zoom", seIconificationStyles,
359 &wPreferences.iconification_style, getEnum, NULL},
360 {"MouseLeftButtonAction", "SelectWindows", seMouseButtonActions,
361 &wPreferences.mouse_button1, getEnum, NULL},
362 {"MouseMiddleButtonAction", "OpenWindowListMenu", seMouseButtonActions,
363 &wPreferences.mouse_button2, getEnum, NULL},
364 {"MouseRightButtonAction", "OpenApplicationsMenu", seMouseButtonActions,
365 &wPreferences.mouse_button3, getEnum, NULL},
366 {"MouseWheelAction", "None", seMouseWheelActions,
367 &wPreferences.mouse_wheel, getEnum, NULL},
368 {"PixmapPath", DEF_PIXMAP_PATHS, NULL,
369 &wPreferences.pixmap_path, getPathList, NULL},
370 {"IconPath", DEF_ICON_PATHS, NULL,
371 &wPreferences.icon_path, getPathList, NULL},
372 {"ColormapMode", "auto", seColormapModes,
373 &wPreferences.colormap_mode, getEnum, NULL},
374 {"AutoFocus", "NO", NULL,
375 &wPreferences.auto_focus, getBool, NULL},
376 {"RaiseDelay", "0", NULL,
377 &wPreferences.raise_delay, getInt, NULL},
378 {"CirculateRaise", "NO", NULL,
379 &wPreferences.circ_raise, getBool, NULL},
380 {"Superfluous", "NO", NULL,
381 &wPreferences.superfluous, getBool, NULL},
382 {"AdvanceToNewWorkspace", "NO", NULL,
383 &wPreferences.ws_advance, getBool, NULL},
384 {"CycleWorkspaces", "NO", NULL,
385 &wPreferences.ws_cycle, getBool, NULL},
386 {"WorkspaceNameDisplayPosition", "center", seDisplayPositions,
387 &wPreferences.workspace_name_display_position, getEnum, NULL},
388 {"WorkspaceBorder", "None", seWorkspaceBorder,
389 &wPreferences.workspace_border_position, getEnum, updateUsableArea},
390 {"WorkspaceBorderSize", "0", NULL,
391 &wPreferences.workspace_border_size, getInt, updateUsableArea},
392 #ifdef VIRTUAL_DESKTOP
393 {"EnableVirtualDesktop", "NO", NULL,
394 &wPreferences.vdesk_enable, getBool, setVirtualDeskEnable},
395 {"VirtualEdgeExtendSpace", "0", NULL,
396 &wPreferences.vedge_bordersize, getInt, NULL},
397 {"VirtualEdgeHorizonScrollSpeed", "30", NULL,
398 &wPreferences.vedge_hscrollspeed, getInt, NULL},
399 {"VirtualEdgeVerticalScrollSpeed", "30", NULL,
400 &wPreferences.vedge_vscrollspeed, getInt, NULL},
401 {"VirtualEdgeResistance", "30", NULL,
402 &wPreferences.vedge_resistance, getInt, NULL},
403 {"VirtualEdgeAttraction", "30", NULL,
404 &wPreferences.vedge_attraction, getInt, NULL},
405 {"VirtualEdgeLeftKey", "None", (void *)WKBD_VDESK_LEFT,
406 NULL, getKeybind, setKeyGrab},
407 {"VirtualEdgeRightKey", "None", (void *)WKBD_VDESK_RIGHT,
408 NULL, getKeybind, setKeyGrab},
409 {"VirtualEdgeUpKey", "None", (void *)WKBD_VDESK_UP,
410 NULL, getKeybind, setKeyGrab},
411 {"VirtualEdgeDownKey", "None", (void *)WKBD_VDESK_DOWN,
412 NULL, getKeybind, setKeyGrab},
413 #endif
414 {"StickyIcons", "NO", NULL,
415 &wPreferences.sticky_icons, getBool, setStickyIcons},
416 {"SaveSessionOnExit", "NO", NULL,
417 &wPreferences.save_session_on_exit, getBool, NULL},
418 {"WrapMenus", "NO", NULL,
419 &wPreferences.wrap_menus, getBool, NULL},
420 {"ScrollableMenus", "NO", NULL,
421 &wPreferences.scrollable_menus, getBool, NULL},
422 {"MenuScrollSpeed", "medium", seSpeeds,
423 &wPreferences.menu_scroll_speed, getEnum, NULL},
424 {"IconSlideSpeed", "medium", seSpeeds,
425 &wPreferences.icon_slide_speed, getEnum, NULL},
426 {"ShadeSpeed", "medium", seSpeeds,
427 &wPreferences.shade_speed, getEnum, NULL},
428 {"DoubleClickTime", "250", (void *)&wPreferences.dblclick_time,
429 &wPreferences.dblclick_time, getInt, setDoubleClick,
430 },
431 {"AlignSubmenus", "NO", NULL,
432 &wPreferences.align_menus, getBool, NULL},
433 {"OpenTransientOnOwnerWorkspace", "NO", NULL,
434 &wPreferences.open_transients_with_parent, getBool, NULL},
435 {"WindowPlacement", "auto", sePlacements,
436 &wPreferences.window_placement, getEnum, NULL},
437 {"IgnoreFocusClick", "NO", NULL,
438 &wPreferences.ignore_focus_click, getBool, NULL},
439 {"UseSaveUnders", "NO", NULL,
440 &wPreferences.use_saveunders, getBool, NULL},
441 {"OpaqueMove", "NO", NULL,
442 &wPreferences.opaque_move, getBool, NULL},
443 {"DisableSound", "NO", NULL,
444 &wPreferences.no_sound, getBool, NULL},
445 {"DisableAnimations", "NO", NULL,
446 &wPreferences.no_animations, getBool, NULL},
447 {"DontLinkWorkspaces", "NO", NULL,
448 &wPreferences.no_autowrap, getBool, NULL},
449 {"AutoArrangeIcons", "NO", NULL,
450 &wPreferences.auto_arrange_icons, getBool, NULL},
451 {"NoWindowOverDock", "NO", NULL,
452 &wPreferences.no_window_over_dock, getBool, updateUsableArea},
453 {"NoWindowOverIcons", "NO", NULL,
454 &wPreferences.no_window_over_icons, getBool, updateUsableArea},
455 {"WindowPlaceOrigin", "(0, 0)", NULL,
456 &wPreferences.window_place_origin, getCoord, NULL},
457 {"ResizeDisplay", "corner", seGeomDisplays,
458 &wPreferences.size_display, getEnum, NULL},
459 {"MoveDisplay", "corner", seGeomDisplays,
460 &wPreferences.move_display, getEnum, NULL},
461 {"DontConfirmKill", "NO", NULL,
462 &wPreferences.dont_confirm_kill, getBool, NULL},
463 {"WindowTitleBalloons", "NO", NULL,
464 &wPreferences.window_balloon, getBool, NULL},
465 {"MiniwindowTitleBalloons", "NO", NULL,
466 &wPreferences.miniwin_balloon, getBool, NULL},
467 {"AppIconBalloons", "NO", NULL,
468 &wPreferences.appicon_balloon, getBool, NULL},
469 {"HelpBalloons", "NO", NULL,
470 &wPreferences.help_balloon, getBool, NULL},
471 {"EdgeResistance", "30", NULL,
472 &wPreferences.edge_resistance, getInt, NULL},
473 {"Attraction", "NO", NULL,
474 &wPreferences.attract, getBool, NULL},
475 {"DisableBlinking", "NO", NULL,
476 &wPreferences.dont_blink, getBool, NULL},
477 /* style options */
478 {"MenuStyle", "normal", seMenuStyles,
479 &wPreferences.menu_style, getEnum, setMenuStyle},
480 {"WidgetColor", "(solid, gray)", NULL,
481 NULL, getTexture, setWidgetColor,
482 },
483 {"WorkspaceSpecificBack", "()", NULL,
484 NULL, getWSSpecificBackground, setWorkspaceSpecificBack},
485 /* WorkspaceBack must come after WorkspaceSpecificBack or
486 * WorkspaceBack wont know WorkspaceSpecificBack was also
487 * specified and 2 copies of wmsetbg will be launched */
488 {"WorkspaceBack", "(solid, black)", NULL,
489 NULL, getWSBackground, setWorkspaceBack},
490 {"SmoothWorkspaceBack", "NO", NULL,
491 NULL, getBool, NULL},
492 {"IconBack", "(solid, gray)", NULL,
493 NULL, getTexture, setIconTile},
494 {"TitleJustify", "center", seJustifications,
495 &wPreferences.title_justification, getEnum, setJustify},
496 {"WindowTitleFont", DEF_TITLE_FONT, NULL,
497 NULL, getFont, setWinTitleFont,
498 },
499 {"WindowTitleExtendSpace", DEF_WINDOW_TITLE_EXTEND_SPACE, NULL,
500 &wPreferences.window_title_clearance, getInt, setClearance},
501 {"MenuTitleExtendSpace", DEF_MENU_TITLE_EXTEND_SPACE, NULL,
502 &wPreferences.menu_title_clearance, getInt, setClearance},
503 {"MenuTextExtendSpace", DEF_MENU_TEXT_EXTEND_SPACE, NULL,
504 &wPreferences.menu_text_clearance, getInt, setClearance},
505 {"MenuTitleFont", DEF_MENU_TITLE_FONT, NULL,
506 NULL, getFont, setMenuTitleFont},
507 {"MenuTextFont", DEF_MENU_ENTRY_FONT, NULL,
508 NULL, getFont, setMenuTextFont},
509 {"IconTitleFont", DEF_ICON_TITLE_FONT, NULL,
510 NULL, getFont, setIconTitleFont},
511 {"ClipTitleFont", DEF_CLIP_TITLE_FONT, NULL,
512 NULL, getFont, setClipTitleFont},
513 {"LargeDisplayFont", DEF_WORKSPACE_NAME_FONT, NULL,
514 NULL, getFont, setLargeDisplayFont},
515 {"HighlightColor", "white", NULL,
516 NULL, getColor, setHightlight},
517 {"HighlightTextColor", "black", NULL,
518 NULL, getColor, setHightlightText},
519 {"ClipTitleColor", "black", (void *)CLIP_NORMAL,
520 NULL, getColor, setClipTitleColor},
521 {"CClipTitleColor", "\"#454045\"", (void *)CLIP_COLLAPSED,
522 NULL, getColor, setClipTitleColor},
523 {"FTitleColor", "white", (void *)WS_FOCUSED,
524 NULL, getColor, setWTitleColor},
525 {"PTitleColor", "white", (void *)WS_PFOCUSED,
526 NULL, getColor, setWTitleColor},
527 {"UTitleColor", "black", (void *)WS_UNFOCUSED,
528 NULL, getColor, setWTitleColor},
529 {"FTitleBack", "(solid, black)", NULL,
530 NULL, getTexture, setFTitleBack},
531 {"PTitleBack", "(solid, \"#616161\")", NULL,
532 NULL, getTexture, setPTitleBack},
533 {"UTitleBack", "(solid, gray)", NULL,
534 NULL, getTexture, setUTitleBack},
535 {"ResizebarBack", "(solid, gray)", NULL,
536 NULL, getTexture, setResizebarBack},
537 {"MenuTitleColor", "white", NULL,
538 NULL, getColor, setMenuTitleColor},
539 {"MenuTextColor", "black", NULL,
540 NULL, getColor, setMenuTextColor},
541 {"MenuDisabledColor", "\"#616161\"", NULL,
542 NULL, getColor, setMenuDisabledColor},
543 {"MenuTitleBack", "(solid, black)", NULL,
544 NULL, getTexture, setMenuTitleBack},
545 {"MenuTextBack", "(solid, gray)", NULL,
546 NULL, getTexture, setMenuTextBack},
547 {"IconTitleColor", "white", NULL,
548 NULL, getColor, setIconTitleColor},
549 {"IconTitleBack", "black", NULL,
550 NULL, getColor, setIconTitleBack},
551 {"SwitchPanelImages", "(swtile.png, swback.png, 30, 40)", &wPreferences,
552 NULL, getPropList, setSwPOptions},
553 /* keybindings */
554 {"RootMenuKey", "None", (void *)WKBD_ROOTMENU,
555 NULL, getKeybind, setKeyGrab},
556 {"WindowListKey", "None", (void *)WKBD_WINDOWLIST,
557 NULL, getKeybind, setKeyGrab},
558 {"WindowMenuKey", "None", (void *)WKBD_WINDOWMENU,
559 NULL, getKeybind, setKeyGrab},
560 {"ClipLowerKey", "None", (void *)WKBD_CLIPLOWER,
561 NULL, getKeybind, setKeyGrab},
562 {"ClipRaiseKey", "None", (void *)WKBD_CLIPRAISE,
563 NULL, getKeybind, setKeyGrab},
564 {"ClipRaiseLowerKey", "None", (void *)WKBD_CLIPRAISELOWER,
565 NULL, getKeybind, setKeyGrab},
566 {"MiniaturizeKey", "None", (void *)WKBD_MINIATURIZE,
567 NULL, getKeybind, setKeyGrab},
568 {"HideKey", "None", (void *)WKBD_HIDE,
569 NULL, getKeybind, setKeyGrab},
570 {"HideOthersKey", "None", (void *)WKBD_HIDE_OTHERS,
571 NULL, getKeybind, setKeyGrab},
572 {"MoveResizeKey", "None", (void *)WKBD_MOVERESIZE,
573 NULL, getKeybind, setKeyGrab},
574 {"CloseKey", "None", (void *)WKBD_CLOSE,
575 NULL, getKeybind, setKeyGrab},
576 {"MaximizeKey", "None", (void *)WKBD_MAXIMIZE,
577 NULL, getKeybind, setKeyGrab},
578 {"VMaximizeKey", "None", (void *)WKBD_VMAXIMIZE,
579 NULL, getKeybind, setKeyGrab},
580 {"HMaximizeKey", "None", (void *)WKBD_HMAXIMIZE,
581 NULL, getKeybind, setKeyGrab},
582 {"LHMaximizeKey", "None", (void*)WKBD_LHMAXIMIZE,
583 NULL, getKeybind, setKeyGrab},
584 {"RHMaximizeKey", "None", (void*)WKBD_RHMAXIMIZE,
585 NULL, getKeybind, setKeyGrab},
586 {"MaximusKey", "None", (void*)WKBD_MAXIMUS,
587 NULL, getKeybind, setKeyGrab},
588 {"RaiseKey", "\"Meta+Up\"", (void *)WKBD_RAISE,
589 NULL, getKeybind, setKeyGrab},
590 {"LowerKey", "\"Meta+Down\"", (void *)WKBD_LOWER,
591 NULL, getKeybind, setKeyGrab},
592 {"RaiseLowerKey", "None", (void *)WKBD_RAISELOWER,
593 NULL, getKeybind, setKeyGrab},
594 {"ShadeKey", "None", (void *)WKBD_SHADE,
595 NULL, getKeybind, setKeyGrab},
596 {"SelectKey", "None", (void *)WKBD_SELECT,
597 NULL, getKeybind, setKeyGrab},
598 {"FocusNextKey", "None", (void *)WKBD_FOCUSNEXT,
599 NULL, getKeybind, setKeyGrab},
600 {"FocusPrevKey", "None", (void *)WKBD_FOCUSPREV,
601 NULL, getKeybind, setKeyGrab},
602 {"NextWorkspaceKey", "None", (void *)WKBD_NEXTWORKSPACE,
603 NULL, getKeybind, setKeyGrab},
604 {"PrevWorkspaceKey", "None", (void *)WKBD_PREVWORKSPACE,
605 NULL, getKeybind, setKeyGrab},
606 {"NextWorkspaceLayerKey", "None", (void *)WKBD_NEXTWSLAYER,
607 NULL, getKeybind, setKeyGrab},
608 {"PrevWorkspaceLayerKey", "None", (void *)WKBD_PREVWSLAYER,
609 NULL, getKeybind, setKeyGrab},
610 {"Workspace1Key", "None", (void *)WKBD_WORKSPACE1,
611 NULL, getKeybind, setKeyGrab},
612 {"Workspace2Key", "None", (void *)WKBD_WORKSPACE2,
613 NULL, getKeybind, setKeyGrab},
614 {"Workspace3Key", "None", (void *)WKBD_WORKSPACE3,
615 NULL, getKeybind, setKeyGrab},
616 {"Workspace4Key", "None", (void *)WKBD_WORKSPACE4,
617 NULL, getKeybind, setKeyGrab},
618 {"Workspace5Key", "None", (void *)WKBD_WORKSPACE5,
619 NULL, getKeybind, setKeyGrab},
620 {"Workspace6Key", "None", (void *)WKBD_WORKSPACE6,
621 NULL, getKeybind, setKeyGrab},
622 {"Workspace7Key", "None", (void *)WKBD_WORKSPACE7,
623 NULL, getKeybind, setKeyGrab},
624 {"Workspace8Key", "None", (void *)WKBD_WORKSPACE8,
625 NULL, getKeybind, setKeyGrab},
626 {"Workspace9Key", "None", (void *)WKBD_WORKSPACE9,
627 NULL, getKeybind, setKeyGrab},
628 {"Workspace10Key", "None", (void *)WKBD_WORKSPACE10,
629 NULL, getKeybind, setKeyGrab},
630 {"WindowShortcut1Key", "None", (void *)WKBD_WINDOW1,
631 NULL, getKeybind, setKeyGrab},
632 {"WindowShortcut2Key", "None", (void *)WKBD_WINDOW2,
633 NULL, getKeybind, setKeyGrab},
634 {"WindowShortcut3Key", "None", (void *)WKBD_WINDOW3,
635 NULL, getKeybind, setKeyGrab},
636 {"WindowShortcut4Key", "None", (void *)WKBD_WINDOW4,
637 NULL, getKeybind, setKeyGrab}
638 , {"WindowShortcut5Key", "None", (void *)WKBD_WINDOW5,
639 NULL, getKeybind, setKeyGrab},
640 {"WindowShortcut6Key", "None", (void *)WKBD_WINDOW6,
641 NULL, getKeybind, setKeyGrab},
642 {"WindowShortcut7Key", "None", (void *)WKBD_WINDOW7,
643 NULL, getKeybind, setKeyGrab},
644 {"WindowShortcut8Key", "None", (void *)WKBD_WINDOW8,
645 NULL, getKeybind, setKeyGrab},
646 {"WindowShortcut9Key", "None", (void *)WKBD_WINDOW9,
647 NULL, getKeybind, setKeyGrab},
648 {"WindowShortcut10Key", "None", (void *)WKBD_WINDOW10,
649 NULL, getKeybind, setKeyGrab},
650 {"ScreenSwitchKey", "None", (void *)WKBD_SWITCH_SCREEN,
651 NULL, getKeybind, setKeyGrab},
652
653 #ifdef KEEP_XKB_LOCK_STATUS
654 {"ToggleKbdModeKey", "None", (void *)WKBD_TOGGLE,
655 NULL, getKeybind, setKeyGrab},
656 {"KbdModeLock", "NO", NULL,
657 &wPreferences.modelock, getBool, NULL},
658 #endif /* KEEP_XKB_LOCK_STATUS */
659
660 {"NormalCursor", "(builtin, left_ptr)", (void *)WCUR_ROOT,
661 NULL, getCursor, setCursor},
662 {"ArrowCursor", "(builtin, top_left_arrow)", (void *)WCUR_ARROW,
663 NULL, getCursor, setCursor},
664 {"MoveCursor", "(builtin, fleur)", (void *)WCUR_MOVE,
665 NULL, getCursor, setCursor},
666 {"ResizeCursor", "(builtin, sizing)", (void *)WCUR_RESIZE,
667 NULL, getCursor, setCursor},
668 {"TopLeftResizeCursor", "(builtin, top_left_corner)",
669 (void *)WCUR_TOPLEFTRESIZE,
670 NULL, getCursor, setCursor},
671 {"TopRightResizeCursor", "(builtin, top_right_corner)",
672 (void *)WCUR_TOPRIGHTRESIZE,
673 NULL, getCursor, setCursor},
674 {"BottomLeftResizeCursor", "(builtin, bottom_left_corner)",
675 (void *)WCUR_BOTTOMLEFTRESIZE,
676 NULL, getCursor, setCursor},
677 {"BottomRightResizeCursor", "(builtin, bottom_right_corner)",
678 (void *)WCUR_BOTTOMRIGHTRESIZE,
679 NULL, getCursor, setCursor},
680 {"VerticalResizeCursor", "(builtin, sb_v_double_arrow)",
681 (void *)WCUR_VERTICALRESIZE,
682 NULL, getCursor, setCursor},
683 {"HorizontalResizeCursor", "(builtin, sb_h_double_arrow)",
684 (void *)WCUR_HORIZONRESIZE,
685 NULL, getCursor, setCursor},
686 {"WaitCursor", "(builtin, watch)", (void *)WCUR_WAIT,
687 NULL, getCursor, setCursor},
688 {"QuestionCursor", "(builtin, question_arrow)", (void *)WCUR_QUESTION,
689 NULL, getCursor, setCursor},
690 {"TextCursor", "(builtin, xterm)", (void *)WCUR_TEXT,
691 NULL, getCursor, setCursor},
692 {"SelectCursor", "(builtin, cross)", (void *)WCUR_SELECT,
693 NULL, getCursor, setCursor}
694 };
695
696 #if 0
697 static void rereadDefaults(void);
698 #endif
699
700 #if 0
701 static void rereadDefaults(void)
702 {
703 /* must defer the update because accessing X data from a
704 * signal handler can mess up Xlib */
705
706 }
707 #endif
708
709 static void initDefaults()
710 {
711 unsigned int i;
712 WDefaultEntry *entry;
713
714 WMPLSetCaseSensitive(False);
715
716 for (i = 0; i < sizeof(optionList) / sizeof(WDefaultEntry); i++) {
717 entry = &optionList[i];
718
719 entry->plkey = WMCreatePLString(entry->key);
720 if (entry->default_value)
721 entry->plvalue = WMCreatePropListFromDescription(entry->default_value);
722 else
723 entry->plvalue = NULL;
724 }
725
726 for (i = 0; i < sizeof(staticOptionList) / sizeof(WDefaultEntry); i++) {
727 entry = &staticOptionList[i];
728
729 entry->plkey = WMCreatePLString(entry->key);
730 if (entry->default_value)
731 entry->plvalue = WMCreatePropListFromDescription(entry->default_value);
732 else
733 entry->plvalue = NULL;
734 }
735
736 /*
737 wDomainName = WMCreatePLString(WMDOMAIN_NAME);
738 wAttributeDomainName = WMCreatePLString(WMATTRIBUTE_DOMAIN_NAME);
739
740 PLRegister(wDomainName, rereadDefaults);
741 PLRegister(wAttributeDomainName, rereadDefaults);
742 */
743 }
744
745 static WMPropList *readGlobalDomain(char *domainName, Bool requireDictionary)
746 {
747 WMPropList *globalDict = NULL;
748 char path[PATH_MAX];
749 struct stat stbuf;
750
751 snprintf(path, sizeof(path), "%s/%s/%s", SYSCONFDIR, GLOBAL_DEFAULTS_SUBDIR, domainName);
752 if (stat(path, &stbuf) >= 0) {
753 globalDict = WMReadPropListFromFile(path);
754 if (globalDict && requireDictionary && !WMIsPLDictionary(globalDict)) {
755 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"), domainName, path);
756 WMReleasePropList(globalDict);
757 globalDict = NULL;
758 } else if (!globalDict) {
759 wwarning(_("could not load domain %s from global defaults database"), domainName);
760 }
761 }
762
763 return globalDict;
764 }
765
766 #if defined(GLOBAL_PREAMBLE_MENU_FILE) || defined(GLOBAL_EPILOGUE_MENU_FILE)
767 static void prependMenu(WMPropList * destarr, WMPropList * array)
768 {
769 WMPropList *item;
770 int i;
771
772 for (i = 0; i < WMGetPropListItemCount(array); i++) {
773 item = WMGetFromPLArray(array, i);
774 if (item)
775 WMInsertInPLArray(destarr, i + 1, item);
776 }
777 }
778
779 static void appendMenu(WMPropList * destarr, WMPropList * array)
780 {
781 WMPropList *item;
782 int i;
783
784 for (i = 0; i < WMGetPropListItemCount(array); i++) {
785 item = WMGetFromPLArray(array, i);
786 if (item)
787 WMAddToPLArray(destarr, item);
788 }
789 }
790 #endif
791
792 /* Fixup paths for cached pixmaps from .AppInfo to Library/WindowMaker/... */
793 static Bool fixupCachedPixmapsPaths(WMPropList * dict)
794 {
795 WMPropList *allApps, *app, *props, *iconkey, *icon, *newicon;
796 char *path, *fixedpath, *ptr, *search;
797 int i, len, slen;
798 Bool changed = False;
799
800 search = "/.AppInfo/WindowMaker/";
801 slen = strlen(search);
802
803 iconkey = WMCreatePLString("Icon");
804 allApps = WMGetPLDictionaryKeys(dict);
805
806 for (i = 0; i < WMGetPropListItemCount(allApps); i++) {
807 app = WMGetFromPLArray(allApps, i);
808 props = WMGetFromPLDictionary(dict, app);
809 if (!props)
810 continue;
811 icon = WMGetFromPLDictionary(props, iconkey);
812 if (icon && WMIsPLString(icon)) {
813 path = WMGetFromPLString(icon);
814 ptr = strstr(path, search);
815 if (ptr) {
816 changed = True;
817 len = (ptr - path);
818 fixedpath = wmalloc(strlen(path) + 32);
819 strncpy(fixedpath, path, len);
820 fixedpath[len] = 0;
821 strcat(fixedpath, "/Library/WindowMaker/CachedPixmaps/");
822 strcat(fixedpath, ptr + slen);
823 newicon = WMCreatePLString(fixedpath);
824 WMPutInPLDictionary(props, iconkey, newicon);
825 WMReleasePropList(newicon);
826 wfree(fixedpath);
827 }
828 }
829 }
830
831 WMReleasePropList(allApps);
832 WMReleasePropList(iconkey);
833
834 return changed;
835 }
836
837 void wDefaultsMergeGlobalMenus(WDDomain * menuDomain)
838 {
839 WMPropList *menu = menuDomain->dictionary;
840 WMPropList *submenu;
841
842 if (!menu || !WMIsPLArray(menu))
843 return;
844
845 #ifdef GLOBAL_PREAMBLE_MENU_FILE
846 submenu = WMReadPropListFromFile(SYSCONFDIR "/" GLOBAL_DEFAULTS_SUBDIR "/" GLOBAL_PREAMBLE_MENU_FILE);
847
848 if (submenu && !WMIsPLArray(submenu)) {
849 wwarning(_("invalid global menu file %s"), GLOBAL_PREAMBLE_MENU_FILE);
850 WMReleasePropList(submenu);
851 submenu = NULL;
852 }
853 if (submenu) {
854 prependMenu(menu, submenu);
855 WMReleasePropList(submenu);
856 }
857 #endif
858
859 #ifdef GLOBAL_EPILOGUE_MENU_FILE
860 submenu = WMReadPropListFromFile(SYSCONFDIR "/" GLOBAL_DEFAULTS_SUBDIR "/" GLOBAL_EPILOGUE_MENU_FILE);
861
862 if (submenu && !WMIsPLArray(submenu)) {
863 wwarning(_("invalid global menu file %s"), GLOBAL_EPILOGUE_MENU_FILE);
864 WMReleasePropList(submenu);
865 submenu = NULL;
866 }
867 if (submenu) {
868 appendMenu(menu, submenu);
869 WMReleasePropList(submenu);
870 }
871 #endif
872
873 menuDomain->dictionary = menu;
874 }
875
876 #if 0
877 WMPropList *wDefaultsInit(int screen_number)
878 {
879 static int defaults_inited = 0;
880 WMPropList *dict;
881
882 if (!defaults_inited) {
883 initDefaults();
884 }
885
886 dict = PLGetDomain(wDomainName);
887 if (!dict) {
888 wwarning(_("could not read domain \"%s\" from defaults database"), WMGetFromPLString(wDomainName));
889 }
890
891 return dict;
892 }
893 #endif
894
895 void wDefaultsDestroyDomain(WDDomain * domain)
896 {
897 if (domain->dictionary)
898 WMReleasePropList(domain->dictionary);
899 wfree(domain->path);
900 wfree(domain);
901 }
902
903 WDDomain *wDefaultsInitDomain(char *domain, Bool requireDictionary)
904 {
905 WDDomain *db;
906 struct stat stbuf;
907 static int inited = 0;
908 char path[PATH_MAX];
909 char *the_path;
910 WMPropList *shared_dict = NULL;
911
912 if (!inited) {
913 inited = 1;
914 initDefaults();
915 }
916
917 db = wmalloc(sizeof(WDDomain));
918 memset(db, 0, sizeof(WDDomain));
919 db->domain_name = domain;
920 db->path = wdefaultspathfordomain(domain);
921 the_path = db->path;
922
923 if (the_path && stat(the_path, &stbuf) >= 0) {
924 db->dictionary = WMReadPropListFromFile(the_path);
925 if (db->dictionary) {
926 if (requireDictionary && !WMIsPLDictionary(db->dictionary)) {
927 WMReleasePropList(db->dictionary);
928 db->dictionary = NULL;
929 wwarning(_("Domain %s (%s) of defaults database is corrupted!"), domain, the_path);
930 }
931 if (strcmp(domain, "WMWindowAttributes") == 0 && db->dictionary) {
932 if (fixupCachedPixmapsPaths(db->dictionary)) {
933 WMWritePropListToFile(db->dictionary, db->path, True);
934 /* re-read the timestamp. if this fails take current time */
935 if (stat(db->path, &stbuf) < 0) {
936 stbuf.st_mtime = time(NULL);
937 }
938 }
939 }
940 db->timestamp = stbuf.st_mtime;
941 } else {
942 wwarning(_("could not load domain %s from user defaults database"), domain);
943 }
944 }
945
946 /* global system dictionary */
947 snprintf(path, sizeof(path), "%s/%s/%s", SYSCONFDIR, GLOBAL_DEFAULTS_SUBDIR, domain);
948 if (stat(path, &stbuf) >= 0) {
949 shared_dict = WMReadPropListFromFile(path);
950 if (shared_dict) {
951 if (requireDictionary && !WMIsPLDictionary(shared_dict)) {
952 wwarning(_("Domain %s (%s) of global defaults database is corrupted!"),
953 domain, path);
954 WMReleasePropList(shared_dict);
955 shared_dict = NULL;
956 } else {
957 if (db->dictionary && WMIsPLDictionary(shared_dict) &&
958 WMIsPLDictionary(db->dictionary)) {
959 WMMergePLDictionaries(shared_dict, db->dictionary, True);
960 WMReleasePropList(db->dictionary);
961 db->dictionary = shared_dict;
962 if (stbuf.st_mtime > db->timestamp)
963 db->timestamp = stbuf.st_mtime;
964 } else if (!db->dictionary) {
965 db->dictionary = shared_dict;
966 if (stbuf.st_mtime > db->timestamp)
967 db->timestamp = stbuf.st_mtime;
968 }
969 }
970 } else {
971 wwarning(_("could not load domain %s from global defaults database (%s)"), domain, path);
972 }
973 }
974
975 return db;
976 }
977
978 void wReadStaticDefaults(WMPropList * dict)
979 {
980 WMPropList *plvalue;
981 WDefaultEntry *entry;
982 unsigned int i;
983 void *tdata;
984
985 for (i = 0; i < sizeof(staticOptionList) / sizeof(WDefaultEntry); i++) {
986 entry = &staticOptionList[i];
987
988 if (dict)
989 plvalue = WMGetFromPLDictionary(dict, entry->plkey);
990 else
991 plvalue = NULL;
992
993 if (!plvalue) {
994 /* no default in the DB. Use builtin default */
995 plvalue = entry->plvalue;
996 }
997
998 if (plvalue) {
999 /* convert data */
1000 (*entry->convert) (NULL, entry, plvalue, entry->addr, &tdata);
1001 if (entry->update) {
1002 (*entry->update) (NULL, entry, tdata, entry->extra_data);
1003 }
1004 }
1005 }
1006 }
1007
1008 void wDefaultsCheckDomains(void)
1009 {
1010 WScreen *scr;
1011 struct stat stbuf;
1012 WMPropList *shared_dict = NULL;
1013 WMPropList *dict;
1014 int i;
1015
1016 #ifdef HEARTBEAT
1017 puts("Checking domains...");
1018 #endif
1019 if (stat(WDWindowMaker->path, &stbuf) >= 0 && WDWindowMaker->timestamp < stbuf.st_mtime) {
1020 #ifdef HEARTBEAT
1021 puts("Checking WindowMaker domain");
1022 #endif
1023 WDWindowMaker->timestamp = stbuf.st_mtime;
1024
1025 /* global dictionary */
1026 shared_dict = readGlobalDomain("WindowMaker", True);
1027 /* user dictionary */
1028 dict = WMReadPropListFromFile(WDWindowMaker->path);
1029 if (dict) {
1030 if (!WMIsPLDictionary(dict)) {
1031 WMReleasePropList(dict);
1032 dict = NULL;
1033 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
1034 "WindowMaker", WDWindowMaker->path);
1035 } else {
1036 if (shared_dict) {
1037 WMMergePLDictionaries(shared_dict, dict, True);
1038 WMReleasePropList(dict);
1039 dict = shared_dict;
1040 shared_dict = NULL;
1041 }
1042 for (i = 0; i < wScreenCount; i++) {
1043 scr = wScreenWithNumber(i);
1044 if (scr)
1045 wReadDefaults(scr, dict);
1046 }
1047 if (WDWindowMaker->dictionary) {
1048 WMReleasePropList(WDWindowMaker->dictionary);
1049 }
1050 WDWindowMaker->dictionary = dict;
1051 }
1052 } else {
1053 wwarning(_("could not load domain %s from user defaults database"), "WindowMaker");
1054 }
1055 if (shared_dict) {
1056 WMReleasePropList(shared_dict);
1057 }
1058 }
1059
1060 if (stat(WDWindowAttributes->path, &stbuf) >= 0 && WDWindowAttributes->timestamp < stbuf.st_mtime) {
1061 #ifdef HEARTBEAT
1062 puts("Checking WMWindowAttributes domain");
1063 #endif
1064 /* global dictionary */
1065 shared_dict = readGlobalDomain("WMWindowAttributes", True);
1066 /* user dictionary */
1067 dict = WMReadPropListFromFile(WDWindowAttributes->path);
1068 if (dict) {
1069 if (!WMIsPLDictionary(dict)) {
1070 WMReleasePropList(dict);
1071 dict = NULL;
1072 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
1073 "WMWindowAttributes", WDWindowAttributes->path);
1074 } else {
1075 if (shared_dict) {
1076 WMMergePLDictionaries(shared_dict, dict, True);
1077 WMReleasePropList(dict);
1078 dict = shared_dict;
1079 shared_dict = NULL;
1080 }
1081 if (WDWindowAttributes->dictionary) {
1082 WMReleasePropList(WDWindowAttributes->dictionary);
1083 }
1084 WDWindowAttributes->dictionary = dict;
1085 for (i = 0; i < wScreenCount; i++) {
1086 scr = wScreenWithNumber(i);
1087 if (scr) {
1088 RImage *image;
1089
1090 wDefaultUpdateIcons(scr);
1091
1092 /* Update the panel image if changed */
1093 /* Don't worry. If the image is the same these
1094 * functions will have no performance impact. */
1095 image = wDefaultGetImage(scr, "Logo", "WMPanel");
1096
1097 if (!image) {
1098 wwarning(_("could not load logo image for panels: %s"),
1099 RMessageForError(RErrorCode));
1100 } else {
1101 WMSetApplicationIconImage(scr->wmscreen, image);
1102 RReleaseImage(image);
1103 }
1104 }
1105 }
1106 }
1107 } else {
1108 wwarning(_("could not load domain %s from user defaults database"), "WMWindowAttributes");
1109 }
1110 WDWindowAttributes->timestamp = stbuf.st_mtime;
1111 if (shared_dict) {
1112 WMReleasePropList(shared_dict);
1113 }
1114 }
1115
1116 if (stat(WDRootMenu->path, &stbuf) >= 0 && WDRootMenu->timestamp < stbuf.st_mtime) {
1117 dict = WMReadPropListFromFile(WDRootMenu->path);
1118 #ifdef HEARTBEAT
1119 puts("Checking WMRootMenu domain");
1120 #endif
1121 if (dict) {
1122 if (!WMIsPLArray(dict) && !WMIsPLString(dict)) {
1123 WMReleasePropList(dict);
1124 dict = NULL;
1125 wwarning(_("Domain %s (%s) of defaults database is corrupted!"),
1126 "WMRootMenu", WDRootMenu->path);
1127 } else {
1128 if (WDRootMenu->dictionary) {
1129 WMReleasePropList(WDRootMenu->dictionary);
1130 }
1131 WDRootMenu->dictionary = dict;
1132 wDefaultsMergeGlobalMenus(WDRootMenu);
1133 }
1134 } else {
1135 wwarning(_("could not load domain %s from user defaults database"), "WMRootMenu");
1136 }
1137 WDRootMenu->timestamp = stbuf.st_mtime;
1138 }
1139 }
1140
1141 void wReadDefaults(WScreen * scr, WMPropList * new_dict)
1142 {
1143 WMPropList *plvalue, *old_value;
1144 WDefaultEntry *entry;
1145 unsigned int i, must_update;
1146 int update_workspace_back = 0; /* kluge :/ */
1147 unsigned int needs_refresh;
1148 void *tdata;
1149 WMPropList *old_dict = (WDWindowMaker->dictionary != new_dict ? WDWindowMaker->dictionary : NULL);
1150
1151 must_update = 0;
1152
1153 needs_refresh = 0;
1154
1155 for (i = 0; i < sizeof(optionList) / sizeof(WDefaultEntry); i++) {
1156 entry = &optionList[i];
1157
1158 if (new_dict)
1159 plvalue = WMGetFromPLDictionary(new_dict, entry->plkey);
1160 else
1161 plvalue = NULL;
1162
1163 if (!old_dict)
1164 old_value = NULL;
1165 else
1166 old_value = WMGetFromPLDictionary(old_dict, entry->plkey);
1167
1168 if (!plvalue && !old_value) {
1169 /* no default in the DB. Use builtin default */
1170 plvalue = entry->plvalue;
1171 if (plvalue && new_dict) {
1172 WMPutInPLDictionary(new_dict, entry->plkey, plvalue);
1173 must_update = 1;
1174 }
1175 } else if (!plvalue) {
1176 /* value was deleted from DB. Keep current value */
1177 continue;
1178 } else if (!old_value) {
1179 /* set value for the 1st time */
1180 } else if (!WMIsPropListEqualTo(plvalue, old_value)) {
1181 /* value has changed */
1182 } else {
1183
1184 if (strcmp(entry->key, "WorkspaceBack") == 0
1185 && update_workspace_back && scr->flags.backimage_helper_launched) {
1186 } else {
1187 /* value was not changed since last time */
1188 continue;
1189 }
1190 }
1191
1192 if (plvalue) {
1193 #ifdef DEBUG
1194 printf("Updating %s to %s\n", entry->key, WMGetPropListDescription(plvalue, False));
1195 #endif
1196 /* convert data */
1197 if ((*entry->convert) (scr, entry, plvalue, entry->addr, &tdata)) {
1198 /*
1199 * If the WorkspaceSpecificBack data has been changed
1200 * so that the helper will be launched now, we must be
1201 * sure to send the default background texture config
1202 * to the helper.
1203 */
1204 if (strcmp(entry->key, "WorkspaceSpecificBack") == 0
1205 && !scr->flags.backimage_helper_launched) {
1206 update_workspace_back = 1;
1207 }
1208 if (entry->update) {
1209 needs_refresh |= (*entry->update) (scr, entry, tdata, entry->extra_data);
1210 }
1211 }
1212 }
1213 }
1214
1215 if (needs_refresh != 0 && !scr->flags.startup) {
1216 int foo;
1217
1218 foo = 0;
1219 if (needs_refresh & REFRESH_MENU_TITLE_TEXTURE)
1220 foo |= WTextureSettings;
1221 if (needs_refresh & REFRESH_MENU_TITLE_FONT)
1222 foo |= WFontSettings;
1223 if (needs_refresh & REFRESH_MENU_TITLE_COLOR)
1224 foo |= WColorSettings;
1225 if (foo)
1226 WMPostNotificationName(WNMenuTitleAppearanceSettingsChanged, NULL,
1227 (void *)(uintptr_t) foo);
1228
1229 foo = 0;
1230 if (needs_refresh & REFRESH_MENU_TEXTURE)
1231 foo |= WTextureSettings;
1232 if (needs_refresh & REFRESH_MENU_FONT)
1233 foo |= WFontSettings;
1234 if (needs_refresh & REFRESH_MENU_COLOR)
1235 foo |= WColorSettings;
1236 if (foo)
1237 WMPostNotificationName(WNMenuAppearanceSettingsChanged, NULL, (void *)(uintptr_t) foo);
1238
1239 foo = 0;
1240 if (needs_refresh & REFRESH_WINDOW_FONT) {
1241 foo |= WFontSettings;
1242 }
1243 if (needs_refresh & REFRESH_WINDOW_TEXTURES) {
1244 foo |= WTextureSettings;
1245 }
1246 if (needs_refresh & REFRESH_WINDOW_TITLE_COLOR) {
1247 foo |= WColorSettings;
1248 }
1249 if (foo)
1250 WMPostNotificationName(WNWindowAppearanceSettingsChanged, NULL, (void *)(uintptr_t) foo);
1251
1252 if (!(needs_refresh & REFRESH_ICON_TILE)) {
1253 foo = 0;
1254 if (needs_refresh & REFRESH_ICON_FONT) {
1255 foo |= WFontSettings;
1256 }
1257 if (needs_refresh & REFRESH_ICON_TITLE_COLOR) {
1258 foo |= WTextureSettings;
1259 }
1260 if (needs_refresh & REFRESH_ICON_TITLE_BACK) {
1261 foo |= WTextureSettings;
1262 }
1263 if (foo)
1264 WMPostNotificationName(WNIconAppearanceSettingsChanged, NULL,
1265 (void *)(uintptr_t) foo);
1266 }
1267 if (needs_refresh & REFRESH_ICON_TILE)
1268 WMPostNotificationName(WNIconTileSettingsChanged, NULL, NULL);
1269 }
1270 }
1271
1272 void wDefaultUpdateIcons(WScreen * scr)
1273 {
1274 WAppIcon *aicon = scr->app_icon_list;
1275 WWindow *wwin = scr->focused_window;
1276 char *file;
1277
1278 while (aicon) {
1279 file = wDefaultGetIconFile(scr, aicon->wm_instance, aicon->wm_class, False);
1280 if ((file && aicon->icon->file && strcmp(file, aicon->icon->file) != 0)
1281 || (file && !aicon->icon->file)) {
1282 RImage *new_image;
1283
1284 if (aicon->icon->file)
1285 wfree(aicon->icon->file);
1286 aicon->icon->file = wstrdup(file);
1287
1288 new_image = wDefaultGetImage(scr, aicon->wm_instance, aicon->wm_class);
1289 if (new_image) {
1290 wIconChangeImage(aicon->icon, new_image);
1291 wAppIconPaint(aicon);
1292 }
1293 }
1294 aicon = aicon->next;
1295 }
1296
1297 if (!wPreferences.flags.noclip)
1298 wClipIconPaint(scr->clip_icon);
1299
1300 while (wwin) {
1301 if (wwin->icon && wwin->flags.miniaturized) {
1302 file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class, False);
1303 if ((file && wwin->icon->file && strcmp(file, wwin->icon->file) != 0)
1304 || (file && !wwin->icon->file)) {
1305 RImage *new_image;
1306
1307 if (wwin->icon->file)
1308 wfree(wwin->icon->file);
1309 wwin->icon->file = wstrdup(file);
1310
1311 new_image = wDefaultGetImage(scr, wwin->wm_instance, wwin->wm_class);
1312 if (new_image)
1313 wIconChangeImage(wwin->icon, new_image);
1314 }
1315 }
1316 wwin = wwin->prev;
1317 }
1318 }
1319
1320 /* --------------------------- Local ----------------------- */
1321
1322 #define GET_STRING_OR_DEFAULT(x, var) if (!WMIsPLString(value)) { \
1323 wwarning(_("Wrong option format for key \"%s\". Should be %s."), \
1324 entry->key, x); \
1325 wwarning(_("using default \"%s\" instead"), entry->default_value); \
1326 var = entry->default_value;\
1327 } else var = WMGetFromPLString(value)\
1328
1329
1330 static int string2index(WMPropList * key, WMPropList * val, char *def, WOptionEnumeration * values)
1331 {
1332 char *str;
1333 WOptionEnumeration *v;
1334 char buffer[TOTAL_VALUES_LENGTH];
1335
1336 if (WMIsPLString(val) && (str = WMGetFromPLString(val))) {
1337 for (v = values; v->string != NULL; v++) {
1338 if (strcasecmp(v->string, str) == 0)
1339 return v->value;
1340 }
1341 }
1342
1343 buffer[0] = 0;
1344 for (v = values; v->string != NULL; v++) {
1345 if (!v->is_alias) {
1346 if (buffer[0] != 0)
1347 strcat(buffer, ", ");
1348 strcat(buffer, v->string);
1349 }
1350 }
1351 wwarning(_("wrong option value for key \"%s\". Should be one of %s"), WMGetFromPLString(key), buffer);
1352
1353 if (def) {
1354 return string2index(key, val, NULL, values);
1355 }
1356
1357 return -1;
1358 }
1359
1360 /*
1361 * value - is the value in the defaults DB
1362 * addr - is the address to store the data
1363 * ret - is the address to store a pointer to a temporary buffer. ret
1364 * must not be freed and is used by the set functions
1365 */
1366 static int getBool(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
1367 {
1368 static char data;
1369 char *val;
1370 int second_pass = 0;
1371
1372 GET_STRING_OR_DEFAULT("Boolean", val);
1373
1374 again:
1375 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y'))
1376 || strcasecmp(val, "YES") == 0) {
1377
1378 data = 1;
1379 } else if ((val[1] == '\0' && (val[0] == 'n' || val[0] == 'N'))
1380 || strcasecmp(val, "NO") == 0) {
1381 data = 0;
1382 } else {
1383 int i;
1384 if (sscanf(val, "%i", &i) == 1) {
1385 if (i != 0)
1386 data = 1;
1387 else
1388 data = 0;
1389 } else {
1390 wwarning(_("can't convert \"%s\" to boolean for key \"%s\""), val, entry->key);
1391 if (second_pass == 0) {
1392 val = WMGetFromPLString(entry->plvalue);
1393 second_pass = 1;
1394 wwarning(_("using default \"%s\" instead"), val);
1395 goto again;
1396 }
1397 return False;
1398 }
1399 }
1400
1401 if (ret)
1402 *ret = &data;
1403 if (addr)
1404 *(char *)addr = data;
1405
1406 return True;
1407 }
1408
1409 static int getInt(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
1410 {
1411 static int data;
1412 char *val;
1413
1414 GET_STRING_OR_DEFAULT("Integer", val);
1415
1416 if (sscanf(val, "%i", &data) != 1) {
1417 wwarning(_("can't convert \"%s\" to integer for key \"%s\""), val, entry->key);
1418 val = WMGetFromPLString(entry->plvalue);
1419 wwarning(_("using default \"%s\" instead"), val);
1420 if (sscanf(val, "%i", &data) != 1) {
1421 return False;
1422 }
1423 }
1424
1425 if (ret)
1426 *ret = &data;
1427 if (addr)
1428 *(int *)addr = data;
1429
1430 return True;
1431 }
1432
1433 static int getCoord(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
1434 {
1435 static WCoord data;
1436 char *val_x, *val_y;
1437 int nelem, changed = 0;
1438 WMPropList *elem_x, *elem_y;
1439
1440 again:
1441 if (!WMIsPLArray(value)) {
1442 wwarning(_("Wrong option format for key \"%s\". Should be %s."), entry->key, "Coordinate");
1443 if (changed == 0) {
1444 value = entry->plvalue;
1445 changed = 1;
1446 wwarning(_("using default \"%s\" instead"), entry->default_value);
1447 goto again;
1448 }
1449 return False;
1450 }
1451
1452 nelem = WMGetPropListItemCount(value);
1453 if (nelem != 2) {
1454 wwarning(_("Incorrect number of elements in array for key \"%s\"."), entry->key);
1455 if (changed == 0) {
1456 value = entry->plvalue;
1457 changed = 1;
1458 wwarning(_("using default \"%s\" instead"), entry->default_value);
1459 goto again;
1460 }
1461 return False;
1462 }
1463
1464 elem_x = WMGetFromPLArray(value, 0);
1465 elem_y = WMGetFromPLArray(value, 1);
1466
1467 if (!elem_x || !elem_y || !WMIsPLString(elem_x) || !WMIsPLString(elem_y)) {
1468 wwarning(_("Wrong value for key \"%s\". Should be Coordinate."), entry->key);
1469 if (changed == 0) {
1470 value = entry->plvalue;
1471 changed = 1;
1472 wwarning(_("using default \"%s\" instead"), entry->default_value);
1473 goto again;
1474 }
1475 return False;
1476 }
1477
1478 val_x = WMGetFromPLString(elem_x);
1479 val_y = WMGetFromPLString(elem_y);
1480
1481 if (sscanf(val_x, "%i", &data.x) != 1 || sscanf(val_y, "%i", &data.y) != 1) {
1482 wwarning(_("can't convert array to integers for \"%s\"."), entry->key);
1483 if (changed == 0) {
1484 value = entry->plvalue;
1485 changed = 1;
1486 wwarning(_("using default \"%s\" instead"), entry->default_value);
1487 goto again;
1488 }
1489 return False;
1490 }
1491
1492 if (data.x < 0)
1493 data.x = 0;
1494 else if (data.x > scr->scr_width / 3)
1495 data.x = scr->scr_width / 3;
1496 if (data.y < 0)
1497 data.y = 0;
1498 else if (data.y > scr->scr_height / 3)
1499 data.y = scr->scr_height / 3;
1500
1501 if (ret)
1502 *ret = &data;
1503 if (addr)
1504 *(WCoord *) addr = data;
1505
1506 return True;
1507 }
1508
1509 static int getPropList(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
1510 {
1511 WMRetainPropList(value);
1512
1513 *ret = value;
1514
1515 return True;
1516 }
1517
1518 #if 0
1519 /* This function is not used at the moment. */
1520 static int getString(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
1521 {
1522 static char *data;
1523
1524 GET_STRING_OR_DEFAULT("String", data);
1525
1526 if (!data) {
1527 data = WMGetFromPLString(entry->plvalue);
1528 if (!data)
1529 return False;
1530 }
1531
1532 if (ret)
1533 *ret = &data;
1534 if (addr)
1535 *(char **)addr = wstrdup(data);
1536
1537 return True;
1538 }
1539 #endif
1540
1541 static int getPathList(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
1542 {
1543 static char *data;
1544 int i, count, len;
1545 char *ptr;
1546 WMPropList *d;
1547 int changed = 0;
1548
1549 again:
1550 if (!WMIsPLArray(value)) {
1551 wwarning(_("Wrong option format for key \"%s\". Should be %s."), entry->key, "an array of paths");
1552 if (changed == 0) {
1553 value = entry->plvalue;
1554 changed = 1;
1555 wwarning(_("using default \"%s\" instead"), entry->default_value);
1556 goto again;
1557 }
1558 return False;
1559 }
1560
1561 i = 0;
1562 count = WMGetPropListItemCount(value);
1563 if (count < 1) {
1564 if (changed == 0) {
1565 value = entry->plvalue;
1566 changed = 1;
1567 wwarning(_("using default \"%s\" instead"), entry->default_value);
1568 goto again;
1569 }
1570 return False;
1571 }
1572
1573 len = 0;
1574 for (i = 0; i < count; i++) {
1575 d = WMGetFromPLArray(value, i);
1576 if (!d || !WMIsPLString(d)) {
1577 count = i;
1578 break;
1579 }
1580 len += strlen(WMGetFromPLString(d)) + 1;
1581 }
1582
1583 ptr = data = wmalloc(len + 1);
1584
1585 for (i = 0; i < count; i++) {
1586 d = WMGetFromPLArray(value, i);
1587 if (!d || !WMIsPLString(d)) {
1588 break;
1589 }
1590 strcpy(ptr, WMGetFromPLString(d));
1591 ptr += strlen(WMGetFromPLString(d));
1592 *ptr = ':';
1593 ptr++;
1594 }
1595 ptr--;
1596 *(ptr--) = 0;
1597
1598 if (*(char **)addr != NULL) {
1599 wfree(*(char **)addr);
1600 }
1601 *(char **)addr = data;
1602
1603 return True;
1604 }
1605
1606 static int getEnum(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
1607 {
1608 static signed char data;
1609
1610 data = string2index(entry->plkey, value, entry->default_value, (WOptionEnumeration *) entry->extra_data);
1611 if (data < 0)
1612 return False;
1613
1614 if (ret)
1615 *ret = &data;
1616 if (addr)
1617 *(signed char *)addr = data;
1618
1619 return True;
1620 }
1621
1622 /*
1623 * (solid <color>)
1624 * (hgradient <color> <color>)
1625 * (vgradient <color> <color>)
1626 * (dgradient <color> <color>)
1627 * (mhgradient <color> <color> ...)
1628 * (mvgradient <color> <color> ...)
1629 * (mdgradient <color> <color> ...)
1630 * (igradient <color1> <color1> <thickness1> <color2> <color2> <thickness2>)
1631 * (tpixmap <file> <color>)
1632 * (spixmap <file> <color>)
1633 * (cpixmap <file> <color>)
1634 * (thgradient <file> <opaqueness> <color> <color>)
1635 * (tvgradient <file> <opaqueness> <color> <color>)
1636 * (tdgradient <file> <opaqueness> <color> <color>)
1637 * (function <lib> <function> ...)
1638 */
1639
1640 static WTexture *parse_texture(WScreen * scr, WMPropList * pl)
1641 {
1642 WMPropList *elem;
1643 char *val;
1644 int nelem;
1645 WTexture *texture = NULL;
1646
1647 nelem = WMGetPropListItemCount(pl);
1648 if (nelem < 1)
1649 return NULL;
1650
1651 elem = WMGetFromPLArray(pl, 0);
1652 if (!elem || !WMIsPLString(elem))
1653 return NULL;
1654 val = WMGetFromPLString(elem);
1655
1656 if (strcasecmp(val, "solid") == 0) {
1657 XColor color;
1658
1659 if (nelem != 2)
1660 return NULL;
1661
1662 /* get color */
1663
1664 elem = WMGetFromPLArray(pl, 1);
1665 if (!elem || !WMIsPLString(elem))
1666 return NULL;
1667 val = WMGetFromPLString(elem);
1668
1669 if (!XParseColor(dpy, scr->w_colormap, val, &color)) {
1670 wwarning(_("\"%s\" is not a valid color name"), val);
1671 return NULL;
1672 }
1673
1674 texture = (WTexture *) wTextureMakeSolid(scr, &color);
1675 } else if (strcasecmp(val, "dgradient") == 0
1676 || strcasecmp(val, "vgradient") == 0 || strcasecmp(val, "hgradient") == 0) {
1677 RColor color1, color2;
1678 XColor xcolor;
1679 int type;
1680
1681 if (nelem != 3) {
1682 wwarning(_("bad number of arguments in gradient specification"));
1683 return NULL;
1684 }
1685
1686 if (val[0] == 'd' || val[0] == 'D')
1687 type = WTEX_DGRADIENT;
1688 else if (val[0] == 'h' || val[0] == 'H')
1689 type = WTEX_HGRADIENT;
1690 else
1691 type = WTEX_VGRADIENT;
1692
1693 /* get from color */
1694 elem = WMGetFromPLArray(pl, 1);
1695 if (!elem || !WMIsPLString(elem))
1696 return NULL;
1697 val = WMGetFromPLString(elem);
1698
1699 if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
1700 wwarning(_("\"%s\" is not a valid color name"), val);
1701 return NULL;
1702 }
1703 color1.alpha = 255;
1704 color1.red = xcolor.red >> 8;
1705 color1.green = xcolor.green >> 8;
1706 color1.blue = xcolor.blue >> 8;
1707
1708 /* get to color */
1709 elem = WMGetFromPLArray(pl, 2);
1710 if (!elem || !WMIsPLString(elem)) {
1711 return NULL;
1712 }
1713 val = WMGetFromPLString(elem);
1714
1715 if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
1716 wwarning(_("\"%s\" is not a valid color name"), val);
1717 return NULL;
1718 }
1719 color2.alpha = 255;
1720 color2.red = xcolor.red >> 8;
1721 color2.green = xcolor.green >> 8;
1722 color2.blue = xcolor.blue >> 8;
1723
1724 texture = (WTexture *) wTextureMakeGradient(scr, type, &color1, &color2);
1725
1726 } else if (strcasecmp(val, "igradient") == 0) {
1727 RColor colors1[2], colors2[2];
1728 int th1, th2;
1729 XColor xcolor;
1730 int i;
1731
1732 if (nelem != 7) {
1733 wwarning(_("bad number of arguments in gradient specification"));
1734 return NULL;
1735 }
1736
1737 /* get from color */
1738 for (i = 0; i < 2; i++) {
1739 elem = WMGetFromPLArray(pl, 1 + i);
1740 if (!elem || !WMIsPLString(elem))
1741 return NULL;
1742 val = WMGetFromPLString(elem);
1743
1744 if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
1745 wwarning(_("\"%s\" is not a valid color name"), val);
1746 return NULL;
1747 }
1748 colors1[i].alpha = 255;
1749 colors1[i].red = xcolor.red >> 8;
1750 colors1[i].green = xcolor.green >> 8;
1751 colors1[i].blue = xcolor.blue >> 8;
1752 }
1753 elem = WMGetFromPLArray(pl, 3);
1754 if (!elem || !WMIsPLString(elem))
1755 return NULL;
1756 val = WMGetFromPLString(elem);
1757 th1 = atoi(val);
1758
1759 /* get from color */
1760 for (i = 0; i < 2; i++) {
1761 elem = WMGetFromPLArray(pl, 4 + i);
1762 if (!elem || !WMIsPLString(elem))
1763 return NULL;
1764 val = WMGetFromPLString(elem);
1765
1766 if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
1767 wwarning(_("\"%s\" is not a valid color name"), val);
1768 return NULL;
1769 }
1770 colors2[i].alpha = 255;
1771 colors2[i].red = xcolor.red >> 8;
1772 colors2[i].green = xcolor.green >> 8;
1773 colors2[i].blue = xcolor.blue >> 8;
1774 }
1775 elem = WMGetFromPLArray(pl, 6);
1776 if (!elem || !WMIsPLString(elem))
1777 return NULL;
1778 val = WMGetFromPLString(elem);
1779 th2 = atoi(val);
1780
1781 texture = (WTexture *) wTextureMakeIGradient(scr, th1, colors1, th2, colors2);
1782
1783 } else if (strcasecmp(val, "mhgradient") == 0
1784 || strcasecmp(val, "mvgradient") == 0 || strcasecmp(val, "mdgradient") == 0) {
1785 XColor color;
1786 RColor **colors;
1787 int i, count;
1788 int type;
1789
1790 if (nelem < 3) {
1791 wwarning(_("too few arguments in multicolor gradient specification"));
1792 return NULL;
1793 }
1794
1795 if (val[1] == 'h' || val[1] == 'H')
1796 type = WTEX_MHGRADIENT;
1797 else if (val[1] == 'v' || val[1] == 'V')
1798 type = WTEX_MVGRADIENT;
1799 else
1800 type = WTEX_MDGRADIENT;
1801
1802 count = nelem - 1;
1803
1804 colors = wmalloc(sizeof(RColor *) * (count + 1));
1805
1806 for (i = 0; i < count; i++) {
1807 elem = WMGetFromPLArray(pl, i + 1);
1808 if (!elem || !WMIsPLString(elem)) {
1809 for (--i; i >= 0; --i) {
1810 wfree(colors[i]);
1811 }
1812 wfree(colors);
1813 return NULL;
1814 }
1815 val = WMGetFromPLString(elem);
1816
1817 if (!XParseColor(dpy, scr->w_colormap, val, &color)) {
1818 wwarning(_("\"%s\" is not a valid color name"), val);
1819 for (--i; i >= 0; --i) {
1820 wfree(colors[i]);
1821 }
1822 wfree(colors);
1823 return NULL;
1824 } else {
1825 colors[i] = wmalloc(sizeof(RColor));
1826 colors[i]->red = color.red >> 8;
1827 colors[i]->green = color.green >> 8;
1828 colors[i]->blue = color.blue >> 8;
1829 }
1830 }
1831 colors[i] = NULL;
1832
1833 texture = (WTexture *) wTextureMakeMGradient(scr, type, colors);
1834 } else if (strcasecmp(val, "spixmap") == 0 ||
1835 strcasecmp(val, "cpixmap") == 0 || strcasecmp(val, "tpixmap") == 0) {
1836 XColor color;
1837 int type;
1838
1839 if (nelem != 3)
1840 return NULL;
1841
1842 if (val[0] == 's' || val[0] == 'S')
1843 type = WTP_SCALE;
1844 else if (val[0] == 'c' || val[0] == 'C')
1845 type = WTP_CENTER;
1846 else
1847 type = WTP_TILE;
1848
1849 /* get color */
1850 elem = WMGetFromPLArray(pl, 2);
1851 if (!elem || !WMIsPLString(elem)) {
1852 return NULL;
1853 }
1854 val = WMGetFromPLString(elem);
1855
1856 if (!XParseColor(dpy, scr->w_colormap, val, &color)) {
1857 wwarning(_("\"%s\" is not a valid color name"), val);
1858 return NULL;
1859 }
1860
1861 /* file name */
1862 elem = WMGetFromPLArray(pl, 1);
1863 if (!elem || !WMIsPLString(elem))
1864 return NULL;
1865 val = WMGetFromPLString(elem);
1866
1867 texture = (WTexture *) wTextureMakePixmap(scr, type, val, &color);
1868 } else if (strcasecmp(val, "thgradient") == 0
1869 || strcasecmp(val, "tvgradient") == 0 || strcasecmp(val, "tdgradient") == 0) {
1870 RColor color1, color2;
1871 XColor xcolor;
1872 int opacity;
1873 int style;
1874
1875 if (val[1] == 'h' || val[1] == 'H')
1876 style = WTEX_THGRADIENT;
1877 else if (val[1] == 'v' || val[1] == 'V')
1878 style = WTEX_TVGRADIENT;
1879 else
1880 style = WTEX_TDGRADIENT;
1881
1882 if (nelem != 5) {
1883 wwarning(_("bad number of arguments in textured gradient specification"));
1884 return NULL;
1885 }
1886
1887 /* get from color */
1888 elem = WMGetFromPLArray(pl, 3);
1889 if (!elem || !WMIsPLString(elem))
1890 return NULL;
1891 val = WMGetFromPLString(elem);
1892
1893 if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
1894 wwarning(_("\"%s\" is not a valid color name"), val);
1895 return NULL;
1896 }
1897 color1.alpha = 255;
1898 color1.red = xcolor.red >> 8;
1899 color1.green = xcolor.green >> 8;
1900 color1.blue = xcolor.blue >> 8;
1901
1902 /* get to color */
1903 elem = WMGetFromPLArray(pl, 4);
1904 if (!elem || !WMIsPLString(elem)) {
1905 return NULL;
1906 }
1907 val = WMGetFromPLString(elem);
1908
1909 if (!XParseColor(dpy, scr->w_colormap, val, &xcolor)) {
1910 wwarning(_("\"%s\" is not a valid color name"), val);
1911 return NULL;
1912 }
1913 color2.alpha = 255;
1914 color2.red = xcolor.red >> 8;
1915 color2.green = xcolor.green >> 8;
1916 color2.blue = xcolor.blue >> 8;
1917
1918 /* get opacity */
1919 elem = WMGetFromPLArray(pl, 2);
1920 if (!elem || !WMIsPLString(elem))
1921 opacity = 128;
1922 else
1923 val = WMGetFromPLString(elem);
1924
1925 if (!val || (opacity = atoi(val)) < 0 || opacity > 255) {
1926 wwarning(_("bad opacity value for tgradient texture \"%s\". Should be [0..255]"), val);
1927 opacity = 128;
1928 }
1929
1930 /* get file name */
1931 elem = WMGetFromPLArray(pl, 1);
1932 if (!elem || !WMIsPLString(elem))
1933 return NULL;
1934 val = WMGetFromPLString(elem);
1935
1936 texture = (WTexture *) wTextureMakeTGradient(scr, style, &color1, &color2, val, opacity);
1937 }
1938 #ifdef TEXTURE_PLUGIN
1939 else if (strcasecmp(val, "function") == 0) {
1940 WTexFunction *function;
1941 void (*initFunc) (Display *, Colormap);
1942 char *lib, *func, **argv;
1943 int i, argc;
1944
1945 if (nelem < 3)
1946 return NULL;
1947
1948 /* get the library name */
1949 elem = WMGetFromPLArray(pl, 1);
1950 if (!elem || !WMIsPLString(elem)) {
1951 return NULL;
1952 }
1953 lib = WMGetFromPLString(elem);
1954
1955 /* get the function name */
1956 elem = WMGetFromPLArray(pl, 2);
1957 if (!elem || !WMIsPLString(elem)) {
1958 return NULL;
1959 }
1960 func = WMGetFromPLString(elem);
1961
1962 argc = nelem - 2;
1963 argv = (char **)wmalloc(argc * sizeof(char *));
1964
1965 /* get the parameters */
1966 argv[0] = wstrdup(func);
1967 for (i = 0; i < argc - 1; i++) {
1968 elem = WMGetFromPLArray(pl, 3 + i);
1969 if (!elem || !WMIsPLString(elem)) {
1970 wfree(argv);
1971
1972 return NULL;
1973 }
1974 argv[i + 1] = wstrdup(WMGetFromPLString(elem));
1975 }
1976
1977 function = wTextureMakeFunction(scr, lib, func, argc, argv);
1978
1979 #ifdef HAVE_DLFCN_H
1980 if (function) {
1981 initFunc = dlsym(function->handle, "initWindowMaker");
1982 if (initFunc) {
1983 initFunc(dpy, scr->w_colormap);
1984 } else {
1985 wwarning(_("could not initialize library %s"), lib);
1986 }
1987 } else {
1988 wwarning(_("could not find function %s::%s"), lib, func);
1989 }
1990 #endif /* HAVE_DLFCN_H */
1991 texture = (WTexture *) function;
1992 }
1993 #endif /* TEXTURE_PLUGIN */
1994 else {
1995 wwarning(_("invalid texture type %s"), val);
1996 return NULL;
1997 }
1998 return texture;
1999 }
2000
2001 static int getTexture(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2002 {
2003 static WTexture *texture;
2004 int changed = 0;
2005
2006 again:
2007 if (!WMIsPLArray(value)) {
2008 wwarning(_("Wrong option format for key \"%s\". Should be %s."), entry->key, "Texture");
2009 if (changed == 0) {
2010 value = entry->plvalue;
2011 changed = 1;
2012 wwarning(_("using default \"%s\" instead"), entry->default_value);
2013 goto again;
2014 }
2015 return False;
2016 }
2017
2018 if (strcmp(entry->key, "WidgetColor") == 0 && !changed) {
2019 WMPropList *pl;
2020
2021 pl = WMGetFromPLArray(value, 0);
2022 if (!pl || !WMIsPLString(pl) || !WMGetFromPLString(pl)
2023 || strcasecmp(WMGetFromPLString(pl), "solid") != 0) {
2024 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
2025 entry->key, "Solid Texture");
2026
2027 value = entry->plvalue;
2028 changed = 1;
2029 wwarning(_("using default \"%s\" instead"), entry->default_value);
2030 goto again;
2031 }
2032 }
2033
2034 texture = parse_texture(scr, value);
2035
2036 if (!texture) {
2037 wwarning(_("Error in texture specification for key \"%s\""), entry->key);
2038 if (changed == 0) {
2039 value = entry->plvalue;
2040 changed = 1;
2041 wwarning(_("using default \"%s\" instead"), entry->default_value);
2042 goto again;
2043 }
2044 return False;
2045 }
2046
2047 if (ret)
2048 *ret = &texture;
2049
2050 if (addr)
2051 *(WTexture **) addr = texture;
2052
2053 return True;
2054 }
2055
2056 static int getWSBackground(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2057 {
2058 WMPropList *elem;
2059 int changed = 0;
2060 char *val;
2061 int nelem;
2062
2063 again:
2064 if (!WMIsPLArray(value)) {
2065 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
2066 "WorkspaceBack", "Texture or None");
2067 if (changed == 0) {
2068 value = entry->plvalue;
2069 changed = 1;
2070 wwarning(_("using default \"%s\" instead"), entry->default_value);
2071 goto again;
2072 }
2073 return False;
2074 }
2075
2076 /* only do basic error checking and verify for None texture */
2077
2078 nelem = WMGetPropListItemCount(value);
2079 if (nelem > 0) {
2080 elem = WMGetFromPLArray(value, 0);
2081 if (!elem || !WMIsPLString(elem)) {
2082 wwarning(_("Wrong type for workspace background. Should be a texture type."));
2083 if (changed == 0) {
2084 value = entry->plvalue;
2085 changed = 1;
2086 wwarning(_("using default \"%s\" instead"), entry->default_value);
2087 goto again;
2088 }
2089 return False;
2090 }
2091 val = WMGetFromPLString(elem);
2092
2093 if (strcasecmp(val, "None") == 0)
2094 return True;
2095 }
2096 *ret = WMRetainPropList(value);
2097
2098 return True;
2099 }
2100
2101 static int
2102 getWSSpecificBackground(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2103 {
2104 WMPropList *elem;
2105 int nelem;
2106 int changed = 0;
2107
2108 again:
2109 if (!WMIsPLArray(value)) {
2110 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
2111 "WorkspaceSpecificBack", "an array of textures");
2112 if (changed == 0) {
2113 value = entry->plvalue;
2114 changed = 1;
2115 wwarning(_("using default \"%s\" instead"), entry->default_value);
2116 goto again;
2117 }
2118 return False;
2119 }
2120
2121 /* only do basic error checking and verify for None texture */
2122
2123 nelem = WMGetPropListItemCount(value);
2124 if (nelem > 0) {
2125 while (nelem--) {
2126 elem = WMGetFromPLArray(value, nelem);
2127 if (!elem || !WMIsPLArray(elem)) {
2128 wwarning(_("Wrong type for background of workspace %i. Should be a texture."),
2129 nelem);
2130 }
2131 }
2132 }
2133
2134 *ret = WMRetainPropList(value);
2135
2136 #ifdef notworking
2137 /*
2138 * Kluge to force wmsetbg helper to set the default background.
2139 * If the WorkspaceSpecificBack is changed once wmaker has started,
2140 * the WorkspaceBack won't be sent to the helper, unless the user
2141 * changes it's value too. So, we must force this by removing the
2142 * value from the defaults DB.
2143 */
2144 if (!scr->flags.backimage_helper_launched && !scr->flags.startup) {
2145 WMPropList *key = WMCreatePLString("WorkspaceBack");
2146
2147 WMRemoveFromPLDictionary(WDWindowMaker->dictionary, key);
2148
2149 WMReleasePropList(key);
2150 }
2151 #endif
2152 return True;
2153 }
2154
2155 static int getFont(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2156 {
2157 static WMFont *font;
2158 char *val;
2159
2160 GET_STRING_OR_DEFAULT("Font", val);
2161
2162 font = WMCreateFont(scr->wmscreen, val);
2163 if (!font)
2164 font = WMCreateFont(scr->wmscreen, "fixed");
2165
2166 if (!font) {
2167 wfatal(_("could not load any usable font!!!"));
2168 exit(1);
2169 }
2170
2171 if (ret)
2172 *ret = font;
2173
2174 /* can't assign font value outside update function */
2175 wassertrv(addr == NULL, True);
2176
2177 return True;
2178 }
2179
2180 static int getColor(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2181 {
2182 static XColor color;
2183 char *val;
2184 int second_pass = 0;
2185
2186 GET_STRING_OR_DEFAULT("Color", val);
2187
2188 again:
2189 if (!wGetColor(scr, val, &color)) {
2190 wwarning(_("could not get color for key \"%s\""), entry->key);
2191 if (second_pass == 0) {
2192 val = WMGetFromPLString(entry->plvalue);
2193 second_pass = 1;
2194 wwarning(_("using default \"%s\" instead"), val);
2195 goto again;
2196 }
2197 return False;
2198 }
2199
2200 if (ret)
2201 *ret = &color;
2202
2203 assert(addr == NULL);
2204 /*
2205 if (addr)
2206 *(unsigned long*)addr = pixel;
2207 */
2208
2209 return True;
2210 }
2211
2212 static int getKeybind(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2213 {
2214 static WShortKey shortcut;
2215 KeySym ksym;
2216 char *val;
2217 char *k;
2218 char buf[MAX_SHORTCUT_LENGTH], *b;
2219
2220 GET_STRING_OR_DEFAULT("Key spec", val);
2221
2222 if (!val || strcasecmp(val, "NONE") == 0) {
2223 shortcut.keycode = 0;
2224 shortcut.modifier = 0;
2225 if (ret)
2226 *ret = &shortcut;
2227 return True;
2228 }
2229
2230 strncpy(buf, val, MAX_SHORTCUT_LENGTH);
2231
2232 b = (char *)buf;
2233
2234 /* get modifiers */
2235 shortcut.modifier = 0;
2236 while ((k = strchr(b, '+')) != NULL) {
2237 int mod;
2238
2239 *k = 0;
2240 mod = wXModifierFromKey(b);
2241 if (mod < 0) {
2242 wwarning(_("%s: invalid key modifier \"%s\""), entry->key, b);
2243 return False;
2244 }
2245 shortcut.modifier |= mod;
2246
2247 b = k + 1;
2248 }
2249
2250 /* get key */
2251 ksym = XStringToKeysym(b);
2252
2253 if (ksym == NoSymbol) {
2254 wwarning(_("%s:invalid kbd shortcut specification \"%s\""), entry->key, val);
2255 return False;
2256 }
2257
2258 shortcut.keycode = XKeysymToKeycode(dpy, ksym);
2259 if (shortcut.keycode == 0) {
2260 wwarning(_("%s:invalid key in shortcut \"%s\""), entry->key, val);
2261 return False;
2262 }
2263
2264 if (ret)
2265 *ret = &shortcut;
2266
2267 return True;
2268 }
2269
2270 static int getModMask(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2271 {
2272 static int mask;
2273 char *str;
2274
2275 GET_STRING_OR_DEFAULT("Modifier Key", str);
2276
2277 if (!str)
2278 return False;
2279
2280 mask = wXModifierFromKey(str);
2281 if (mask < 0) {
2282 wwarning(_("%s: modifier key %s is not valid"), entry->key, str);
2283 mask = 0;
2284 return False;
2285 }
2286
2287 if (addr)
2288 *(int *)addr = mask;
2289
2290 if (ret)
2291 *ret = &mask;
2292
2293 return True;
2294 }
2295
2296 #ifdef NEWSTUFF
2297 static int getRImages(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2298 {
2299 unsigned int mask;
2300 char *str;
2301 RImage *image;
2302 int i, n;
2303 int w, h;
2304
2305 GET_STRING_OR_DEFAULT("Image File Path", str);
2306 if (!str)
2307 return False;
2308
2309 image = RLoadImage(scr->rcontext, str, 0);
2310 if (!image) {
2311 wwarning(_("could not load image in option %s: %s"), entry->key, RMessageForError(RErrorCode));
2312 return False;
2313 }
2314
2315 if (*(RImage **) addr) {
2316 RReleaseImage(*(RImage **) addr);
2317 }
2318 if (addr)
2319 *(RImage **) addr = image;
2320
2321 assert(ret == NULL);
2322 /*
2323 if (ret)
2324 *(RImage**)ret = image;
2325 */
2326
2327 return True;
2328 }
2329 #endif
2330
2331 # include <X11/cursorfont.h>
2332 typedef struct {
2333 char *name;
2334 int id;
2335 } WCursorLookup;
2336
2337 #define CURSOR_ID_NONE (XC_num_glyphs)
2338
2339 static WCursorLookup cursor_table[] = {
2340 {"X_cursor", XC_X_cursor},
2341 {"arrow", XC_arrow},
2342 {"based_arrow_down", XC_based_arrow_down},
2343 {"based_arrow_up", XC_based_arrow_up},
2344 {"boat", XC_boat},
2345 {"bogosity", XC_bogosity},
2346 {"bottom_left_corner", XC_bottom_left_corner},
2347 {"bottom_right_corner", XC_bottom_right_corner},
2348 {"bottom_side", XC_bottom_side},
2349 {"bottom_tee", XC_bottom_tee},
2350 {"box_spiral", XC_box_spiral},
2351 {"center_ptr", XC_center_ptr},
2352 {"circle", XC_circle},
2353 {"clock", XC_clock},
2354 {"coffee_mug", XC_coffee_mug},
2355 {"cross", XC_cross},
2356 {"cross_reverse", XC_cross_reverse},
2357 {"crosshair", XC_crosshair},
2358 {"diamond_cross", XC_diamond_cross},
2359 {"dot", XC_dot},
2360 {"dotbox", XC_dotbox},
2361 {"double_arrow", XC_double_arrow},
2362 {"draft_large", XC_draft_large},
2363 {"draft_small", XC_draft_small},
2364 {"draped_box", XC_draped_box},
2365 {"exchange", XC_exchange},
2366 {"fleur", XC_fleur},
2367 {"gobbler", XC_gobbler},
2368 {"gumby", XC_gumby},
2369 {"hand1", XC_hand1},
2370 {"hand2", XC_hand2},
2371 {"heart", XC_heart},
2372 {"icon", XC_icon},
2373 {"iron_cross", XC_iron_cross},
2374 {"left_ptr", XC_left_ptr},
2375 {"left_side", XC_left_side},
2376 {"left_tee", XC_left_tee},
2377 {"leftbutton", XC_leftbutton},
2378 {"ll_angle", XC_ll_angle},
2379 {"lr_angle", XC_lr_angle},
2380 {"man", XC_man},
2381 {"middlebutton", XC_middlebutton},
2382 {"mouse", XC_mouse},
2383 {"pencil", XC_pencil},
2384 {"pirate", XC_pirate},
2385 {"plus", XC_plus},
2386 {"question_arrow", XC_question_arrow},
2387 {"right_ptr", XC_right_ptr},
2388 {"right_side", XC_right_side},
2389 {"right_tee", XC_right_tee},
2390 {"rightbutton", XC_rightbutton},
2391 {"rtl_logo", XC_rtl_logo},
2392 {"sailboat", XC_sailboat},
2393 {"sb_down_arrow", XC_sb_down_arrow},
2394 {"sb_h_double_arrow", XC_sb_h_double_arrow},
2395 {"sb_left_arrow", XC_sb_left_arrow},
2396 {"sb_right_arrow", XC_sb_right_arrow},
2397 {"sb_up_arrow", XC_sb_up_arrow},
2398 {"sb_v_double_arrow", XC_sb_v_double_arrow},
2399 {"shuttle", XC_shuttle},
2400 {"sizing", XC_sizing},
2401 {"spider", XC_spider},
2402 {"spraycan", XC_spraycan},
2403 {"star", XC_star},
2404 {"target", XC_target},
2405 {"tcross", XC_tcross},
2406 {"top_left_arrow", XC_top_left_arrow},
2407 {"top_left_corner", XC_top_left_corner},
2408 {"top_right_corner", XC_top_right_corner},
2409 {"top_side", XC_top_side},
2410 {"top_tee", XC_top_tee},
2411 {"trek", XC_trek},
2412 {"ul_angle", XC_ul_angle},
2413 {"umbrella", XC_umbrella},
2414 {"ur_angle", XC_ur_angle},
2415 {"watch", XC_watch},
2416 {"xterm", XC_xterm},
2417 {NULL, CURSOR_ID_NONE}
2418 };
2419
2420 static void check_bitmap_status(int status, char *filename, Pixmap bitmap)
2421 {
2422 switch (status) {
2423 case BitmapOpenFailed:
2424 wwarning(_("failed to open bitmap file \"%s\""), filename);
2425 break;
2426 case BitmapFileInvalid:
2427 wwarning(_("\"%s\" is not a valid bitmap file"), filename);
2428 break;
2429 case BitmapNoMemory:
2430 wwarning(_("out of memory reading bitmap file \"%s\""), filename);
2431 break;
2432 case BitmapSuccess:
2433 XFreePixmap(dpy, bitmap);
2434 break;
2435 }
2436 }
2437
2438 /*
2439 * (none)
2440 * (builtin, <cursor_name>)
2441 * (bitmap, <cursor_bitmap>, <cursor_mask>)
2442 */
2443 static int parse_cursor(WScreen * scr, WMPropList * pl, Cursor * cursor)
2444 {
2445 WMPropList *elem;
2446 char *val;
2447 int nelem;
2448 int status = 0;
2449
2450 nelem = WMGetPropListItemCount(pl);
2451 if (nelem < 1) {
2452 return (status);
2453 }
2454 elem = WMGetFromPLArray(pl, 0);
2455 if (!elem || !WMIsPLString(elem)) {
2456 return (status);
2457 }
2458 val = WMGetFromPLString(elem);
2459
2460 if (0 == strcasecmp(val, "none")) {
2461 status = 1;
2462 *cursor = None;
2463 } else if (0 == strcasecmp(val, "builtin")) {
2464 int i;
2465 int cursor_id = CURSOR_ID_NONE;
2466
2467 if (2 != nelem) {
2468 wwarning(_("bad number of arguments in cursor specification"));
2469 return (status);
2470 }
2471 elem = WMGetFromPLArray(pl, 1);
2472 if (!elem || !WMIsPLString(elem)) {
2473 return (status);
2474 }
2475 val = WMGetFromPLString(elem);
2476
2477 for (i = 0; NULL != cursor_table[i].name; i++) {
2478 if (0 == strcasecmp(val, cursor_table[i].name)) {
2479 cursor_id = cursor_table[i].id;
2480 break;
2481 }
2482 }
2483 if (CURSOR_ID_NONE == cursor_id) {
2484 wwarning(_("unknown builtin cursor name \"%s\""), val);
2485 } else {
2486 *cursor = XCreateFontCursor(dpy, cursor_id);
2487 status = 1;
2488 }
2489 } else if (0 == strcasecmp(val, "bitmap")) {
2490 char *bitmap_name;
2491 char *mask_name;
2492 int bitmap_status;
2493 int mask_status;
2494 Pixmap bitmap;
2495 Pixmap mask;
2496 unsigned int w, h;
2497 int x, y;
2498 XColor fg, bg;
2499
2500 if (3 != nelem) {
2501 wwarning(_("bad number of arguments in cursor specification"));
2502 return (status);
2503 }
2504 elem = WMGetFromPLArray(pl, 1);
2505 if (!elem || !WMIsPLString(elem)) {
2506 return (status);
2507 }
2508 val = WMGetFromPLString(elem);
2509 bitmap_name = FindImage(wPreferences.pixmap_path, val);
2510 if (!bitmap_name) {
2511 wwarning(_("could not find cursor bitmap file \"%s\""), val);
2512 return (status);
2513 }
2514 elem = WMGetFromPLArray(pl, 2);
2515 if (!elem || !WMIsPLString(elem)) {
2516 wfree(bitmap_name);
2517 return (status);
2518 }
2519 val = WMGetFromPLString(elem);
2520 mask_name = FindImage(wPreferences.pixmap_path, val);
2521 if (!mask_name) {
2522 wfree(bitmap_name);
2523 wwarning(_("could not find cursor bitmap file \"%s\""), val);
2524 return (status);
2525 }
2526 mask_status = XReadBitmapFile(dpy, scr->w_win, mask_name, &w, &h, &mask, &x, &y);
2527 bitmap_status = XReadBitmapFile(dpy, scr->w_win, bitmap_name, &w, &h, &bitmap, &x, &y);
2528 if ((BitmapSuccess == bitmap_status) && (BitmapSuccess == mask_status)) {
2529 fg.pixel = scr->black_pixel;
2530 bg.pixel = scr->white_pixel;
2531 XQueryColor(dpy, scr->w_colormap, &fg);
2532 XQueryColor(dpy, scr->w_colormap, &bg);
2533 *cursor = XCreatePixmapCursor(dpy, bitmap, mask, &fg, &bg, x, y);
2534 status = 1;
2535 }
2536 check_bitmap_status(bitmap_status, bitmap_name, bitmap);
2537 check_bitmap_status(mask_status, mask_name, mask);
2538 wfree(bitmap_name);
2539 wfree(mask_name);
2540 }
2541 return (status);
2542 }
2543
2544 static int getCursor(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *addr, void **ret)
2545 {
2546 static Cursor cursor;
2547 int status;
2548 int changed = 0;
2549
2550 again:
2551 if (!WMIsPLArray(value)) {
2552 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
2553 entry->key, "cursor specification");
2554 if (!changed) {
2555 value = entry->plvalue;
2556 changed = 1;
2557 wwarning(_("using default \"%s\" instead"), entry->default_value);
2558 goto again;
2559 }
2560 return (False);
2561 }
2562 status = parse_cursor(scr, value, &cursor);
2563 if (!status) {
2564 wwarning(_("Error in cursor specification for key \"%s\""), entry->key);
2565 if (!changed) {
2566 value = entry->plvalue;
2567 changed = 1;
2568 wwarning(_("using default \"%s\" instead"), entry->default_value);
2569 goto again;
2570 }
2571 return (False);
2572 }
2573 if (ret) {
2574 *ret = &cursor;
2575 }
2576 if (addr) {
2577 *(Cursor *) addr = cursor;
2578 }
2579 return (True);
2580 }
2581
2582 #undef CURSOR_ID_NONE
2583
2584 /* ---------------- value setting functions --------------- */
2585 static int setJustify(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
2586 {
2587 return REFRESH_WINDOW_TITLE_COLOR;
2588 }
2589
2590 static int setClearance(WScreen * scr, WDefaultEntry * entry, void *bar, void *foo)
2591 {
2592 return REFRESH_WINDOW_FONT | REFRESH_BUTTON_IMAGES | REFRESH_MENU_TITLE_FONT | REFRESH_MENU_FONT;
2593 }
2594
2595 static int setIfDockPresent(WScreen * scr, WDefaultEntry * entry, char *flag, long which)
2596 {
2597 switch (which) {
2598 case WM_DOCK:
2599 wPreferences.flags.nodock = wPreferences.flags.nodock || *flag;
2600 break;
2601 case WM_CLIP:
2602 wPreferences.flags.noclip = wPreferences.flags.noclip || *flag;
2603 break;
2604 default:
2605 break;
2606 }
2607 return 0;
2608 }
2609
2610 static int setStickyIcons(WScreen * scr, WDefaultEntry * entry, void *bar, void *foo)
2611 {
2612 if (scr->workspaces) {
2613 wWorkspaceForceChange(scr, scr->current_workspace);
2614 wArrangeIcons(scr, False);
2615 }
2616 return 0;
2617 }
2618
2619 #if not_used
2620 static int setPositive(WScreen * scr, WDefaultEntry * entry, int *value, void *foo)
2621 {
2622 if (*value <= 0)
2623 *(int *)foo = 1;
2624
2625 return 0;
2626 }
2627 #endif
2628
2629 static int setIconTile(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
2630 {
2631 Pixmap pixmap;
2632 RImage *img;
2633 int reset = 0;
2634
2635 img = wTextureRenderImage(*texture, wPreferences.icon_size,
2636 wPreferences.icon_size, ((*texture)->any.type & WREL_BORDER_MASK)
2637 ? WREL_ICON : WREL_FLAT);
2638 if (!img) {
2639 wwarning(_("could not render texture for icon background"));
2640 if (!entry->addr)
2641 wTextureDestroy(scr, *texture);
2642 return 0;
2643 }
2644 RConvertImage(scr->rcontext, img, &pixmap);
2645
2646 if (scr->icon_tile) {
2647 reset = 1;
2648 RReleaseImage(scr->icon_tile);
2649 XFreePixmap(dpy, scr->icon_tile_pixmap);
2650 }
2651
2652 scr->icon_tile = img;
2653
2654 /* put the icon in the noticeboard hint */
2655 PropSetIconTileHint(scr, img);
2656
2657 if (!wPreferences.flags.noclip) {
2658 if (scr->clip_tile) {
2659 RReleaseImage(scr->clip_tile);
2660 }
2661 scr->clip_tile = wClipMakeTile(scr, img);
2662 }
2663
2664 scr->icon_tile_pixmap = pixmap;
2665
2666 if (scr->def_icon_pixmap) {
2667 XFreePixmap(dpy, scr->def_icon_pixmap);
2668 scr->def_icon_pixmap = None;
2669 }
2670 if (scr->def_ticon_pixmap) {
2671 XFreePixmap(dpy, scr->def_ticon_pixmap);
2672 scr->def_ticon_pixmap = None;
2673 }
2674
2675 if (scr->icon_back_texture) {
2676 wTextureDestroy(scr, (WTexture *) scr->icon_back_texture);
2677 }
2678 scr->icon_back_texture = wTextureMakeSolid(scr, &((*texture)->any.color));
2679
2680 if (scr->clip_balloon)
2681 XSetWindowBackground(dpy, scr->clip_balloon, (*texture)->any.color.pixel);
2682
2683 /*
2684 * Free the texture as nobody else will use it, nor refer to it.
2685 */
2686 if (!entry->addr)
2687 wTextureDestroy(scr, *texture);
2688
2689 return (reset ? REFRESH_ICON_TILE : 0);
2690 }
2691
2692 static int setWinTitleFont(WScreen * scr, WDefaultEntry * entry, WMFont * font, void *foo)
2693 {
2694 if (scr->title_font) {
2695 WMReleaseFont(scr->title_font);
2696 }
2697 scr->title_font = font;
2698
2699 return REFRESH_WINDOW_FONT | REFRESH_BUTTON_IMAGES;
2700 }
2701
2702 static int setMenuTitleFont(WScreen * scr, WDefaultEntry * entry, WMFont * font, void *foo)
2703 {
2704 if (scr->menu_title_font) {
2705 WMReleaseFont(scr->menu_title_font);
2706 }
2707
2708 scr->menu_title_font = font;
2709
2710 return REFRESH_MENU_TITLE_FONT;
2711 }
2712
2713 static int setMenuTextFont(WScreen * scr, WDefaultEntry * entry, WMFont * font, void *foo)
2714 {
2715 if (scr->menu_entry_font) {
2716 WMReleaseFont(scr->menu_entry_font);
2717 }
2718 scr->menu_entry_font = font;
2719
2720 return REFRESH_MENU_FONT;
2721 }
2722
2723 static int setIconTitleFont(WScreen * scr, WDefaultEntry * entry, WMFont * font, void *foo)
2724 {
2725 if (scr->icon_title_font) {
2726 WMReleaseFont(scr->icon_title_font);
2727 }
2728
2729 scr->icon_title_font = font;
2730
2731 return REFRESH_ICON_FONT;
2732 }
2733
2734 static int setClipTitleFont(WScreen * scr, WDefaultEntry * entry, WMFont * font, void *foo)
2735 {
2736 if (scr->clip_title_font) {
2737 WMReleaseFont(scr->clip_title_font);
2738 }
2739
2740 scr->clip_title_font = font;
2741
2742 return REFRESH_ICON_FONT;
2743 }
2744
2745 static int setLargeDisplayFont(WScreen * scr, WDefaultEntry * entry, WMFont * font, void *foo)
2746 {
2747 if (scr->workspace_name_font) {
2748 WMReleaseFont(scr->workspace_name_font);
2749 }
2750
2751 scr->workspace_name_font = font;
2752
2753 return 0;
2754 }
2755
2756 static int setHightlight(WScreen * scr, WDefaultEntry * entry, XColor * color, void *foo)
2757 {
2758 if (scr->select_color)
2759 WMReleaseColor(scr->select_color);
2760
2761 scr->select_color = WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2762
2763 wFreeColor(scr, color->pixel);
2764
2765 return REFRESH_MENU_COLOR;
2766 }
2767
2768 static int setHightlightText(WScreen * scr, WDefaultEntry * entry, XColor * color, void *foo)
2769 {
2770 if (scr->select_text_color)
2771 WMReleaseColor(scr->select_text_color);
2772
2773 scr->select_text_color = WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2774
2775 wFreeColor(scr, color->pixel);
2776
2777 return REFRESH_MENU_COLOR;
2778 }
2779
2780 static int setClipTitleColor(WScreen * scr, WDefaultEntry * entry, XColor * color, long widx)
2781 {
2782 if (scr->clip_title_color[widx])
2783 WMReleaseColor(scr->clip_title_color[widx]);
2784 scr->clip_title_color[widx] = WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2785 #ifdef GRADIENT_CLIP_ARROW
2786 if (widx == CLIP_NORMAL) {
2787 RImage *image;
2788 RColor color1, color2;
2789 int pt = CLIP_BUTTON_SIZE * wPreferences.icon_size / 64;
2790 int as = pt - 15; /* 15 = 5+5+5 */
2791
2792 FREE_PIXMAP(scr->clip_arrow_gradient);
2793
2794 color1.red = (color->red >> 8) * 6 / 10;
2795 color1.green = (color->green >> 8) * 6 / 10;
2796 color1.blue = (color->blue >> 8) * 6 / 10;
2797
2798 color2.red = WMIN((color->red >> 8) * 20 / 10, 255);
2799 color2.green = WMIN((color->green >> 8) * 20 / 10, 255);
2800 color2.blue = WMIN((color->blue >> 8) * 20 / 10, 255);
2801
2802 image = RRenderGradient(as + 1, as + 1, &color1, &color2, RDiagonalGradient);
2803 RConvertImage(scr->rcontext, image, &scr->clip_arrow_gradient);
2804 RReleaseImage(image);
2805 }
2806 #endif /* GRADIENT_CLIP_ARROW */
2807
2808 wFreeColor(scr, color->pixel);
2809
2810 return REFRESH_ICON_TITLE_COLOR;
2811 }
2812
2813 static int setWTitleColor(WScreen * scr, WDefaultEntry * entry, XColor * color, long widx)
2814 {
2815 if (scr->window_title_color[widx])
2816 WMReleaseColor(scr->window_title_color[widx]);
2817
2818 scr->window_title_color[widx] =
2819 WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2820
2821 wFreeColor(scr, color->pixel);
2822
2823 return REFRESH_WINDOW_TITLE_COLOR;
2824 }
2825
2826 static int setMenuTitleColor(WScreen * scr, WDefaultEntry * entry, XColor * color, long widx)
2827 {
2828 if (scr->menu_title_color[0])
2829 WMReleaseColor(scr->menu_title_color[0]);
2830
2831 scr->menu_title_color[0] = WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2832
2833 wFreeColor(scr, color->pixel);
2834
2835 return REFRESH_MENU_TITLE_COLOR;
2836 }
2837
2838 static int setMenuTextColor(WScreen * scr, WDefaultEntry * entry, XColor * color, void *foo)
2839 {
2840 if (scr->mtext_color)
2841 WMReleaseColor(scr->mtext_color);
2842
2843 scr->mtext_color = WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2844
2845 if (WMColorPixel(scr->dtext_color) == WMColorPixel(scr->mtext_color)) {
2846 WMSetColorAlpha(scr->dtext_color, 0x7fff);
2847 } else {
2848 WMSetColorAlpha(scr->dtext_color, 0xffff);
2849 }
2850
2851 wFreeColor(scr, color->pixel);
2852
2853 return REFRESH_MENU_COLOR;
2854 }
2855
2856 static int setMenuDisabledColor(WScreen * scr, WDefaultEntry * entry, XColor * color, void *foo)
2857 {
2858 if (scr->dtext_color)
2859 WMReleaseColor(scr->dtext_color);
2860
2861 scr->dtext_color = WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2862
2863 if (WMColorPixel(scr->dtext_color) == WMColorPixel(scr->mtext_color)) {
2864 WMSetColorAlpha(scr->dtext_color, 0x7fff);
2865 } else {
2866 WMSetColorAlpha(scr->dtext_color, 0xffff);
2867 }
2868
2869 wFreeColor(scr, color->pixel);
2870
2871 return REFRESH_MENU_COLOR;
2872 }
2873
2874 static int setIconTitleColor(WScreen * scr, WDefaultEntry * entry, XColor * color, void *foo)
2875 {
2876 if (scr->icon_title_color)
2877 WMReleaseColor(scr->icon_title_color);
2878 scr->icon_title_color = WMCreateRGBColor(scr->wmscreen, color->red, color->green, color->blue, True);
2879
2880 wFreeColor(scr, color->pixel);
2881
2882 return REFRESH_ICON_TITLE_COLOR;
2883 }
2884
2885 static int setIconTitleBack(WScreen * scr, WDefaultEntry * entry, XColor * color, void *foo)
2886 {
2887 if (scr->icon_title_texture) {
2888 wTextureDestroy(scr, (WTexture *) scr->icon_title_texture);
2889 }
2890 scr->icon_title_texture = wTextureMakeSolid(scr, color);
2891
2892 return REFRESH_ICON_TITLE_BACK;
2893 }
2894
2895 static void trackDeadProcess(pid_t pid, unsigned char status, WScreen * scr)
2896 {
2897 close(scr->helper_fd);
2898 scr->helper_fd = 0;
2899 scr->helper_pid = 0;
2900 scr->flags.backimage_helper_launched = 0;
2901 }
2902
2903 static int setWorkspaceSpecificBack(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *bar)
2904 {
2905 WMPropList *val;
2906 char *str;
2907 int i;
2908
2909 if (scr->flags.backimage_helper_launched) {
2910 if (WMGetPropListItemCount(value) == 0) {
2911 SendHelperMessage(scr, 'C', 0, NULL);
2912 SendHelperMessage(scr, 'K', 0, NULL);
2913
2914 WMReleasePropList(value);
2915 return 0;
2916 }
2917 } else {
2918 pid_t pid;
2919 int filedes[2];
2920
2921 if (WMGetPropListItemCount(value) == 0)
2922 return 0;
2923
2924 if (pipe(filedes) < 0) {
2925 wsyserror("pipe() failed:can't set workspace specific background image");
2926
2927 WMReleasePropList(value);
2928 return 0;
2929 }
2930
2931 pid = fork();
2932 if (pid < 0) {
2933 wsyserror("fork() failed:can't set workspace specific background image");
2934 if (close(filedes[0]) < 0)
2935 wsyserror("could not close pipe");
2936 if (close(filedes[1]) < 0)
2937 wsyserror("could not close pipe");
2938
2939 } else if (pid == 0) {
2940 char *dither;
2941
2942 SetupEnvironment(scr);
2943
2944 if (close(0) < 0)
2945 wsyserror("could not close pipe");
2946 if (dup(filedes[0]) < 0) {
2947 wsyserror("dup() failed:can't set workspace specific background image");
2948 }
2949 dither = wPreferences.no_dithering ? "-m" : "-d";
2950 if (wPreferences.smooth_workspace_back)
2951 execlp("wmsetbg", "wmsetbg", "-helper", "-S", dither, NULL);
2952 else
2953 execlp("wmsetbg", "wmsetbg", "-helper", dither, NULL);
2954 wsyserror("could not execute wmsetbg");
2955 exit(1);
2956 } else {
2957
2958 if (fcntl(filedes[0], F_SETFD, FD_CLOEXEC) < 0) {
2959 wsyserror("error setting close-on-exec flag");
2960 }
2961 if (fcntl(filedes[1], F_SETFD, FD_CLOEXEC) < 0) {
2962 wsyserror("error setting close-on-exec flag");
2963 }
2964
2965 scr->helper_fd = filedes[1];
2966 scr->helper_pid = pid;
2967 scr->flags.backimage_helper_launched = 1;
2968
2969 wAddDeathHandler(pid, (WDeathHandler *) trackDeadProcess, scr);
2970
2971 SendHelperMessage(scr, 'P', -1, wPreferences.pixmap_path);
2972 }
2973
2974 }
2975
2976 for (i = 0; i < WMGetPropListItemCount(value); i++) {
2977 val = WMGetFromPLArray(value, i);
2978 if (val && WMIsPLArray(val) && WMGetPropListItemCount(val) > 0) {
2979 str = WMGetPropListDescription(val, False);
2980
2981 SendHelperMessage(scr, 'S', i + 1, str);
2982
2983 wfree(str);
2984 } else {
2985 SendHelperMessage(scr, 'U', i + 1, NULL);
2986 }
2987 }
2988 sleep(1);
2989
2990 WMReleasePropList(value);
2991 return 0;
2992 }
2993
2994 static int setWorkspaceBack(WScreen * scr, WDefaultEntry * entry, WMPropList * value, void *bar)
2995 {
2996 if (scr->flags.backimage_helper_launched) {
2997 char *str;
2998
2999 if (WMGetPropListItemCount(value) == 0) {
3000 SendHelperMessage(scr, 'U', 0, NULL);
3001 } else {
3002 /* set the default workspace background to this one */
3003 str = WMGetPropListDescription(value, False);
3004 if (str) {
3005 SendHelperMessage(scr, 'S', 0, str);
3006 wfree(str);
3007 SendHelperMessage(scr, 'C', scr->current_workspace + 1, NULL);
3008 } else {
3009 SendHelperMessage(scr, 'U', 0, NULL);
3010 }
3011 }
3012 } else if (WMGetPropListItemCount(value) > 0) {
3013 char *command;
3014 char *text;
3015 char *dither;
3016 int len;
3017
3018 SetupEnvironment(scr);
3019 text = WMGetPropListDescription(value, False);
3020 len = strlen(text) + 40;
3021 command = wmalloc(len);
3022 dither = wPreferences.no_dithering ? "-m" : "-d";
3023 if (wPreferences.smooth_workspace_back)
3024 snprintf(command, len, "wmsetbg %s -S -p '%s' &", dither, text);
3025 else
3026 snprintf(command, len, "wmsetbg %s -p '%s' &", dither, text);
3027 wfree(text);
3028 system(command);
3029 wfree(command);
3030 }
3031 WMReleasePropList(value);
3032
3033 return 0;
3034 }
3035
3036 #ifdef VIRTUAL_DESKTOP
3037 static int setVirtualDeskEnable(WScreen * scr, WDefaultEntry * entry, void *foo, void *bar)
3038 {
3039 wWorkspaceUpdateEdge(scr);
3040 return 0;
3041 }
3042 #endif
3043
3044 static int setWidgetColor(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
3045 {
3046 if (scr->widget_texture) {
3047 wTextureDestroy(scr, (WTexture *) scr->widget_texture);
3048 }
3049 scr->widget_texture = *(WTexSolid **) texture;
3050
3051 return 0;
3052 }
3053
3054 static int setFTitleBack(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
3055 {
3056 if (scr->window_title_texture[WS_FOCUSED]) {
3057 wTextureDestroy(scr, scr->window_title_texture[WS_FOCUSED]);
3058 }
3059 scr->window_title_texture[WS_FOCUSED] = *texture;
3060
3061 return REFRESH_WINDOW_TEXTURES;
3062 }
3063
3064 static int setPTitleBack(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
3065 {
3066 if (scr->window_title_texture[WS_PFOCUSED]) {
3067 wTextureDestroy(scr, scr->window_title_texture[WS_PFOCUSED]);
3068 }
3069 scr->window_title_texture[WS_PFOCUSED] = *texture;
3070
3071 return REFRESH_WINDOW_TEXTURES;
3072 }
3073
3074 static int setUTitleBack(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
3075 {
3076 if (scr->window_title_texture[WS_UNFOCUSED]) {
3077 wTextureDestroy(scr, scr->window_title_texture[WS_UNFOCUSED]);
3078 }
3079 scr->window_title_texture[WS_UNFOCUSED] = *texture;
3080
3081 return REFRESH_WINDOW_TEXTURES;
3082 }
3083
3084 static int setResizebarBack(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
3085 {
3086 if (scr->resizebar_texture[0]) {
3087 wTextureDestroy(scr, scr->resizebar_texture[0]);
3088 }
3089 scr->resizebar_texture[0] = *texture;
3090
3091 return REFRESH_WINDOW_TEXTURES;
3092 }
3093
3094 static int setMenuTitleBack(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
3095 {
3096 if (scr->menu_title_texture[0]) {
3097 wTextureDestroy(scr, scr->menu_title_texture[0]);
3098 }
3099 scr->menu_title_texture[0] = *texture;
3100
3101 return REFRESH_MENU_TITLE_TEXTURE;
3102 }
3103
3104 static int setMenuTextBack(WScreen * scr, WDefaultEntry * entry, WTexture ** texture, void *foo)
3105 {
3106 if (scr->menu_item_texture) {
3107 wTextureDestroy(scr, scr->menu_item_texture);
3108 wTextureDestroy(scr, (WTexture *) scr->menu_item_auxtexture);
3109 }
3110 scr->menu_item_texture = *texture;
3111
3112 scr->menu_item_auxtexture = wTextureMakeSolid(scr, &scr->menu_item_texture->any.color);
3113
3114 return REFRESH_MENU_TEXTURE;
3115 }
3116
3117 static int setKeyGrab(WScreen * scr, WDefaultEntry * entry, WShortKey * shortcut, long widx)
3118 {
3119 WWindow *wwin;
3120 wKeyBindings[widx] = *shortcut;
3121
3122 wwin = scr->focused_window;
3123
3124 while (wwin != NULL) {
3125 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
3126
3127 if (!WFLAGP(wwin, no_bind_keys)) {
3128 wWindowSetKeyGrabs(wwin);
3129 }
3130 wwin = wwin->prev;
3131 }
3132
3133 return 0;
3134 }
3135
3136 static int setIconPosition(WScreen * scr, WDefaultEntry * entry, void *bar, void *foo)
3137 {
3138 wScreenUpdateUsableArea(scr);
3139 wArrangeIcons(scr, True);
3140
3141 return 0;
3142 }
3143
3144 static int updateUsableArea(WScreen * scr, WDefaultEntry * entry, void *bar, void *foo)
3145 {
3146 wScreenUpdateUsableArea(scr);
3147
3148 return 0;
3149 }
3150
3151 static int setMenuStyle(WScreen * scr, WDefaultEntry * entry, int *value, void *foo)
3152 {
3153 return REFRESH_MENU_TEXTURE;
3154 }
3155
3156 static RImage *chopOffImage(RImage * image, int x, int y, int w, int h)
3157 {
3158 RImage *img = RCreateImage(w, h, image->format == RRGBAFormat);
3159
3160 RCopyArea(img, image, x, y, w, h, 0, 0);
3161
3162 return img;
3163 }
3164
3165 static int setSwPOptions(WScreen * scr, WDefaultEntry * entry, WMPropList * array, void *foo)
3166 {
3167 char *path;
3168 RImage *bgimage;
3169 int cwidth, cheight;
3170 WPreferences *prefs = (WPreferences *) foo;
3171
3172 if (!WMIsPLArray(array) || WMGetPropListItemCount(array) == 0) {
3173 if (prefs->swtileImage)
3174 RReleaseImage(prefs->swtileImage);
3175 prefs->swtileImage = NULL;
3176
3177 WMReleasePropList(array);
3178 return 0;
3179 }
3180
3181 switch (WMGetPropListItemCount(array)) {
3182 case 4:
3183 if (!WMIsPLString(WMGetFromPLArray(array, 1))) {
3184 wwarning(_("Invalid arguments for option \"%s\""), entry->key);
3185 break;
3186 } else
3187 path = FindImage(wPreferences.pixmap_path, WMGetFromPLString(WMGetFromPLArray(array, 1)));
3188
3189 if (!path) {
3190 wwarning(_("Could not find image \"%s\" for option \"%s\""),
3191 WMGetFromPLString(WMGetFromPLArray(array, 1)), entry->key);
3192 } else {
3193 bgimage = RLoadImage(scr->rcontext, path, 0);
3194 if (!bgimage) {
3195 wwarning(_("Could not load image \"%s\" for option \"%s\""), path, entry->key);
3196 wfree(path);
3197 } else {
3198 wfree(path);
3199
3200 cwidth = atoi(WMGetFromPLString(WMGetFromPLArray(array, 2)));
3201 cheight = atoi(WMGetFromPLString(WMGetFromPLArray(array, 3)));
3202
3203 if (cwidth <= 0 || cheight <= 0 ||
3204 cwidth >= bgimage->width - 2 || cheight >= bgimage->height - 2)
3205 wwarning(_("Invalid split sizes for SwitchPanel back image."));
3206 else {
3207 int i;
3208 int swidth, theight;
3209 for (i = 0; i < 9; i++) {
3210 if (prefs->swbackImage[i])
3211 RReleaseImage(prefs->swbackImage[i]);
3212 prefs->swbackImage[i] = NULL;
3213 }
3214 swidth = (bgimage->width - cwidth) / 2;
3215 theight = (bgimage->height - cheight) / 2;
3216
3217 prefs->swbackImage[0] = chopOffImage(bgimage, 0, 0, swidth, theight);
3218 prefs->swbackImage[1] = chopOffImage(bgimage, swidth, 0, cwidth, theight);
3219 prefs->swbackImage[2] = chopOffImage(bgimage, swidth + cwidth, 0,
3220 swidth, theight);
3221
3222 prefs->swbackImage[3] = chopOffImage(bgimage, 0, theight, swidth, cheight);
3223 prefs->swbackImage[4] = chopOffImage(bgimage, swidth, theight,
3224 cwidth, cheight);
3225 prefs->swbackImage[5] = chopOffImage(bgimage, swidth + cwidth, theight,
3226 swidth, cheight);
3227
3228 prefs->swbackImage[6] = chopOffImage(bgimage, 0, theight + cheight,
3229 swidth, theight);
3230 prefs->swbackImage[7] = chopOffImage(bgimage, swidth, theight + cheight,
3231 cwidth, theight);
3232 prefs->swbackImage[8] =
3233 chopOffImage(bgimage, swidth + cwidth, theight + cheight, swidth,
3234 theight);
3235
3236 // check if anything failed
3237 for (i = 0; i < 9; i++) {
3238 if (!prefs->swbackImage[i]) {
3239 for (; i >= 0; --i) {
3240 RReleaseImage(prefs->swbackImage[i]);
3241 prefs->swbackImage[i] = NULL;
3242 }
3243 break;
3244 }
3245 }
3246 }
3247 RReleaseImage(bgimage);
3248 }
3249 }
3250
3251 case 1:
3252 if (!WMIsPLString(WMGetFromPLArray(array, 0))) {
3253 wwarning(_("Invalid arguments for option \"%s\""), entry->key);
3254 break;
3255 } else
3256 path = FindImage(wPreferences.pixmap_path, WMGetFromPLString(WMGetFromPLArray(array, 0)));
3257
3258 if (!path) {
3259 wwarning(_("Could not find image \"%s\" for option \"%s\""),
3260 WMGetFromPLString(WMGetFromPLArray(array, 0)), entry->key);
3261 } else {
3262 if (prefs->swtileImage)
3263 RReleaseImage(prefs->swtileImage);
3264
3265 prefs->swtileImage = RLoadImage(scr->rcontext, path, 0);
3266 if (!prefs->swtileImage) {
3267 wwarning(_("Could not load image \"%s\" for option \"%s\""), path, entry->key);
3268 }
3269 wfree(path);
3270 }
3271 break;
3272
3273 default:
3274 wwarning(_("Invalid number of arguments for option \"%s\""), entry->key);
3275 break;
3276 }
3277
3278 WMReleasePropList(array);
3279
3280 return 0;
3281 }
3282
3283 /*
3284 static int
3285 setButtonImages(WScreen *scr, WDefaultEntry *entry, int *value, void *foo)
3286 {
3287 return REFRESH_BUTTON_IMAGES;
3288 }
3289 */
3290
3291 /*
3292 * Very ugly kluge.
3293 * Need access to the double click variables, so that all widgets in
3294 * wmaker panels will have the same dbl-click values.
3295 * TODO: figure a better way of dealing with it.
3296 */
3297 #include <WINGs/WINGsP.h>
3298
3299 static int setDoubleClick(WScreen * scr, WDefaultEntry * entry, int *value, void *foo)
3300 {
3301 extern _WINGsConfiguration WINGsConfiguration;
3302
3303 if (*value <= 0)
3304 *(int *)foo = 1;
3305
3306 WINGsConfiguration.doubleClickDelay = *value;
3307
3308 return 0;
3309 }
3310
3311 static int setCursor(WScreen * scr, WDefaultEntry * entry, Cursor * cursor, long widx)
3312 {
3313 if (wCursor[widx] != None) {
3314 XFreeCursor(dpy, wCursor[widx]);
3315 }
3316
3317 wCursor[widx] = *cursor;
3318
3319 if (widx == WCUR_ROOT && *cursor != None) {
3320 XDefineCursor(dpy, scr->root_win, *cursor);
3321 }
3322
3323 return 0;
3324 }