1 /*
2 * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 * Copyright (C) Colin Harrison 2005-2008
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Except as contained in this notice, the name of the XFree86 Project
25 * shall not be used in advertising or otherwise to promote the sale, use
26 * or other dealings in this Software without prior written authorization
27 * from the XFree86 Project.
28 *
29 * Authors: Earle F. Philhower, III
30 * Colin Harrison
31 */
32
33 #ifdef HAVE_XWIN_CONFIG_H
34 #include <xwin-config.h>
35 #endif
36 #include <stdio.h>
37 #include <stdlib.h>
38 #ifdef __CYGWIN__
39 #include <sys/resource.h>
40 #include <sys/cygwin.h>
41 #endif
42 #include "win.h"
43
44 #include <X11/Xwindows.h>
45 #include <shellapi.h>
46
47 #include "winprefs.h"
48 #include "windisplay.h"
49 #include "winmultiwindowclass.h"
50 #include "winmultiwindowicons.h"
51
52 /* Where will the custom menu commands start counting from? */
53 #define STARTMENUID WM_USER
54
55 extern const char *winGetBaseDir(void);
56
57 /* From winprefslex.l, the real parser */
58 extern int parse_file(FILE * fp);
59
60 /* Currently in use command ID, incremented each new menu item created */
61 static int g_cmdid = STARTMENUID;
62
63 /*
64 * Creates or appends a menu from a MENUPARSED structure
65 */
66 static HMENU
MakeMenu(char * name,HMENU editMenu,int editItem)67 MakeMenu(char *name, HMENU editMenu, int editItem)
68 {
69 int i;
70 int item;
71 MENUPARSED *m;
72 HMENU hmenu, hsub;
73
74 for (i = 0; i < pref.menuItems; i++) {
75 if (!strcmp(name, pref.menu[i].menuName))
76 break;
77 }
78
79 /* Didn't find a match, bummer */
80 if (i == pref.menuItems) {
81 ErrorF("MakeMenu: Can't find menu %s\n", name);
82 return NULL;
83 }
84
85 m = &(pref.menu[i]);
86
87 if (editMenu) {
88 hmenu = editMenu;
89 item = editItem;
90 }
91 else {
92 hmenu = CreatePopupMenu();
93 if (!hmenu) {
94 ErrorF("MakeMenu: Unable to CreatePopupMenu() %s\n", name);
95 return NULL;
96 }
97 item = 0;
98 }
99
100 /* Add the menu items */
101 for (i = 0; i < m->menuItems; i++) {
102 /* Only assign IDs one time... */
103 if (m->menuItem[i].commandID == 0)
104 m->menuItem[i].commandID = g_cmdid++;
105
106 switch (m->menuItem[i].cmd) {
107 case CMD_EXEC:
108 case CMD_ALWAYSONTOP:
109 case CMD_RELOAD:
110 InsertMenu(hmenu,
111 item,
112 MF_BYPOSITION | MF_ENABLED | MF_STRING,
113 m->menuItem[i].commandID, m->menuItem[i].text);
114 break;
115
116 case CMD_SEPARATOR:
117 InsertMenu(hmenu, item, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
118 break;
119
120 case CMD_MENU:
121 /* Recursive! */
122 hsub = MakeMenu(m->menuItem[i].param, 0, 0);
123 if (hsub)
124 InsertMenu(hmenu,
125 item,
126 MF_BYPOSITION | MF_POPUP | MF_ENABLED | MF_STRING,
127 (UINT_PTR) hsub, m->menuItem[i].text);
128 break;
129 }
130
131 /* If item==-1 (means to add at end of menu) don't increment) */
132 if (item >= 0)
133 item++;
134 }
135
136 return hmenu;
137 }
138
139 /*
140 * Callback routine that is executed once per window class.
141 * Removes or creates custom window settings depending on LPARAM
142 */
143 static wBOOL CALLBACK
ReloadEnumWindowsProc(HWND hwnd,LPARAM lParam)144 ReloadEnumWindowsProc(HWND hwnd, LPARAM lParam)
145 {
146 HICON hicon;
147
148 if (!hwnd) {
149 ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n");
150 return FALSE;
151 }
152
153 /* It's our baby, either clean or dirty it */
154 if (lParam == FALSE) {
155 /* Reset the window's icon to undefined. */
156 hicon = (HICON) SendMessage(hwnd, WM_SETICON, ICON_BIG, 0);
157
158 /* If the old icon is generated on-the-fly, get rid of it, will regen */
159 winDestroyIcon(hicon);
160
161 /* Same for the small icon */
162 hicon = (HICON) SendMessage(hwnd, WM_SETICON, ICON_SMALL, 0);
163 winDestroyIcon(hicon);
164
165 /* Remove any menu additions; bRevert=TRUE destroys any modified menus */
166 GetSystemMenu(hwnd, TRUE);
167
168 /* This window is now clean of our taint (but with undefined icons) */
169 }
170 else {
171 /* Send a message to WM thread telling it re-evaluate the icon for this window */
172 {
173 winWMMessageRec wmMsg;
174
175 WindowPtr pWin = GetProp(hwnd, WIN_WINDOW_PROP);
176
177 if (pWin) {
178 winPrivWinPtr pWinPriv = winGetWindowPriv(pWin);
179 winPrivScreenPtr s_pScreenPriv = pWinPriv->pScreenPriv;
180
181 wmMsg.msg = WM_WM_ICON_EVENT;
182 wmMsg.hwndWindow = hwnd;
183 wmMsg.iWindow = (Window) (INT_PTR) GetProp(hwnd, WIN_WID_PROP);
184
185 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
186 }
187 }
188
189 /* Update the system menu for this window */
190 SetupSysMenu(hwnd);
191
192 /* That was easy... */
193 }
194
195 return TRUE;
196 }
197
198 /*
199 * Removes any custom icons in classes, custom menus, etc.
200 * Frees all members in pref structure.
201 * Reloads the preferences file.
202 * Set custom icons and menus again.
203 */
204 static void
ReloadPrefs(winPrivScreenPtr pScreenPriv)205 ReloadPrefs(winPrivScreenPtr pScreenPriv)
206 {
207 int i;
208
209 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
210
211 /* First, iterate over all windows, deleting their icons and custom menus.
212 * This is really only needed because winDestroyIcon() will try to
213 * destroy the old global icons, which will have changed.
214 * It is probably better to set a windows USER_DATA to flag locally defined
215 * icons, and use that to accurately know when to destroy old icons.
216 */
217 if (pScreenInfo->fMultiWindow)
218 EnumThreadWindows(g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE);
219
220 /* Now, free/clear all info from our prefs structure */
221 for (i = 0; i < pref.menuItems; i++)
222 free(pref.menu[i].menuItem);
223 free(pref.menu);
224 pref.menu = NULL;
225 pref.menuItems = 0;
226
227 pref.rootMenuName[0] = 0;
228
229 free(pref.sysMenu);
230 pref.sysMenuItems = 0;
231
232 pref.defaultSysMenuName[0] = 0;
233 pref.defaultSysMenuPos = 0;
234
235 pref.iconDirectory[0] = 0;
236 pref.defaultIconName[0] = 0;
237 pref.trayIconName[0] = 0;
238
239 for (i = 0; i < pref.iconItems; i++)
240 if (pref.icon[i].hicon)
241 DestroyIcon((HICON) pref.icon[i].hicon);
242 free(pref.icon);
243 pref.icon = NULL;
244 pref.iconItems = 0;
245
246 /* Free global default X icon */
247 if (g_hIconX)
248 DestroyIcon(g_hIconX);
249 if (g_hSmallIconX)
250 DestroyIcon(g_hSmallIconX);
251
252 /* Reset the custom command IDs */
253 g_cmdid = STARTMENUID;
254
255 /* Load the updated resource file */
256 LoadPreferences();
257
258 g_hIconX = NULL;
259 g_hSmallIconX = NULL;
260
261 if (pScreenInfo->fMultiWindow) {
262 winInitGlobalIcons();
263
264 /* Rebuild the icons and menus */
265 EnumThreadWindows(g_dwCurrentThreadID, ReloadEnumWindowsProc, TRUE);
266 }
267
268 /* Whew, done */
269 }
270
271 /*
272 * Check/uncheck the ALWAYSONTOP items in this menu
273 */
274 void
HandleCustomWM_INITMENU(HWND hwnd,HMENU hmenu)275 HandleCustomWM_INITMENU(HWND hwnd, HMENU hmenu)
276 {
277 DWORD dwExStyle;
278 int i, j;
279
280 if (!hwnd || !hmenu)
281 return;
282
283 if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
284 dwExStyle = MF_BYCOMMAND | MF_CHECKED;
285 else
286 dwExStyle = MF_BYCOMMAND | MF_UNCHECKED;
287
288 for (i = 0; i < pref.menuItems; i++)
289 for (j = 0; j < pref.menu[i].menuItems; j++)
290 if (pref.menu[i].menuItem[j].cmd == CMD_ALWAYSONTOP)
291 CheckMenuItem(hmenu, pref.menu[i].menuItem[j].commandID,
292 dwExStyle);
293
294 }
295
296 /*
297 * Searches for the custom WM_COMMAND command ID and performs action.
298 * Return TRUE if command is processed, FALSE otherwise.
299 */
300 Bool
HandleCustomWM_COMMAND(HWND hwnd,WORD command,winPrivScreenPtr pScreenPriv)301 HandleCustomWM_COMMAND(HWND hwnd, WORD command, winPrivScreenPtr pScreenPriv)
302 {
303 int i, j;
304 MENUPARSED *m;
305 DWORD dwExStyle;
306
307 if (!command)
308 return FALSE;
309
310 for (i = 0; i < pref.menuItems; i++) {
311 m = &(pref.menu[i]);
312 for (j = 0; j < m->menuItems; j++) {
313 if (command == m->menuItem[j].commandID) {
314 /* Match! */
315 switch (m->menuItem[j].cmd) {
316 #ifdef __CYGWIN__
317 case CMD_EXEC:
318 if (fork() == 0) {
319 struct rlimit rl;
320 int fd;
321
322 /* Close any open descriptors except for STD* */
323 getrlimit(RLIMIT_NOFILE, &rl);
324 for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++)
325 close(fd);
326
327 /* Disassociate any TTYs */
328 setsid();
329
330 execl("/bin/sh",
331 "/bin/sh", "-c", m->menuItem[j].param, NULL);
332 exit(0);
333 }
334 else
335 return TRUE;
336 break;
337 #else
338 case CMD_EXEC:
339 {
340 /* Start process without console window */
341 STARTUPINFO start;
342 PROCESS_INFORMATION child;
343
344 memset(&start, 0, sizeof(start));
345 start.cb = sizeof(start);
346 start.dwFlags = STARTF_USESHOWWINDOW;
347 start.wShowWindow = SW_HIDE;
348
349 memset(&child, 0, sizeof(child));
350
351 if (CreateProcess
352 (NULL, m->menuItem[j].param, NULL, NULL, FALSE, 0, NULL,
353 NULL, &start, &child)) {
354 CloseHandle(child.hThread);
355 CloseHandle(child.hProcess);
356 }
357 else
358 MessageBox(NULL, m->menuItem[j].param,
359 "Mingrc Exec Command Error!",
360 MB_OK | MB_ICONEXCLAMATION);
361 }
362 return TRUE;
363 #endif
364 case CMD_ALWAYSONTOP:
365 if (!hwnd)
366 return FALSE;
367
368 /* Get extended window style */
369 dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
370
371 /* Handle topmost windows */
372 if (dwExStyle & WS_EX_TOPMOST)
373 SetWindowPos(hwnd,
374 HWND_NOTOPMOST,
375 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
376 else
377 SetWindowPos(hwnd,
378 HWND_TOPMOST,
379 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
380 {
381 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
382 if (pScreenInfo->fMultiWindow)
383 /* Reflect the changed Z order */
384 winReorderWindowsMultiWindow();
385 }
386 return TRUE;
387
388 case CMD_RELOAD:
389 ReloadPrefs(pScreenPriv);
390 return TRUE;
391
392 default:
393 return FALSE;
394 }
395 } /* match */
396 } /* for j */
397 } /* for i */
398
399 return FALSE;
400 }
401
402 /*
403 * Add the default or a custom menu depending on the class match
404 */
405 void
SetupSysMenu(HWND hwnd)406 SetupSysMenu(HWND hwnd)
407 {
408 HMENU sys;
409 int i;
410 WindowPtr pWin;
411 char *res_name, *res_class;
412
413 if (!hwnd)
414 return;
415
416 pWin = GetProp(hwnd, WIN_WINDOW_PROP);
417
418 sys = GetSystemMenu(hwnd, FALSE);
419 if (!sys)
420 return;
421
422 if (pWin) {
423 /* First see if there's a class match... */
424 if (winMultiWindowGetClassHint(pWin, &res_name, &res_class)) {
425 for (i = 0; i < pref.sysMenuItems; i++) {
426 if (!strcmp(pref.sysMenu[i].match, res_name) ||
427 !strcmp(pref.sysMenu[i].match, res_class)) {
428 free(res_name);
429 free(res_class);
430
431 MakeMenu(pref.sysMenu[i].menuName, sys,
432 pref.sysMenu[i].menuPos == AT_START ? 0 : -1);
433 return;
434 }
435 }
436
437 /* No match, just free alloc'd strings */
438 free(res_name);
439 free(res_class);
440 } /* Found wm_class */
441 } /* if pwin */
442
443 /* Fallback to system default */
444 if (pref.defaultSysMenuName[0]) {
445 if (pref.defaultSysMenuPos == AT_START)
446 MakeMenu(pref.defaultSysMenuName, sys, 0);
447 else
448 MakeMenu(pref.defaultSysMenuName, sys, -1);
449 }
450 }
451
452 /*
453 * Possibly add a menu to the toolbar icon
454 */
455 void
SetupRootMenu(HMENU root)456 SetupRootMenu(HMENU root)
457 {
458 if (!root)
459 return;
460
461 if (pref.rootMenuName[0]) {
462 MakeMenu(pref.rootMenuName, root, 0);
463 }
464 }
465
466 /*
467 * Check for and return an overridden default ICON specified in the prefs
468 */
469 HICON
winOverrideDefaultIcon(int size)470 winOverrideDefaultIcon(int size)
471 {
472 HICON hicon;
473
474 if (pref.defaultIconName[0]) {
475 hicon = LoadImageComma(pref.defaultIconName, pref.iconDirectory, size, size, 0);
476 if (hicon == NULL)
477 ErrorF("winOverrideDefaultIcon: LoadImageComma(%s) failed\n",
478 pref.defaultIconName);
479
480 return hicon;
481 }
482
483 return 0;
484 }
485
486 /*
487 * Return the HICON to use in the taskbar notification area
488 */
489 HICON
winTaskbarIcon(void)490 winTaskbarIcon(void)
491 {
492 HICON hicon;
493
494 hicon = 0;
495 /* First try and load an overridden, if success then return it */
496 if (pref.trayIconName[0]) {
497 hicon = LoadImageComma(pref.trayIconName, pref.iconDirectory,
498 GetSystemMetrics(SM_CXSMICON),
499 GetSystemMetrics(SM_CYSMICON), 0);
500 if (hicon == NULL)
501 ErrorF("winTaskbarIcon: LoadImageComma(%s) failed\n",
502 pref.trayIconName);
503 }
504
505 /* Otherwise return the default */
506 if (!hicon)
507 hicon = (HICON) LoadImage(g_hInstance,
508 MAKEINTRESOURCE(IDI_XWIN),
509 IMAGE_ICON,
510 GetSystemMetrics(SM_CXSMICON),
511 GetSystemMetrics(SM_CYSMICON), 0);
512
513 return hicon;
514 }
515
516 /*
517 * Handle comma-ified icon names
518 *
519 * Parse a filename to extract an icon:
520 * If fname is exactly ",nnn" then extract icon from our resource
521 * else if it is "file,nnn" then extract icon nnn from that file
522 * else try to load it as an .ico file and if that fails return NULL
523 */
524 HICON
LoadImageComma(char * fname,char * iconDirectory,int sx,int sy,int flags)525 LoadImageComma(char *fname, char *iconDirectory, int sx, int sy, int flags)
526 {
527 HICON hicon;
528 int i;
529
530 /* Some input error checking */
531 if (!fname || !fname[0])
532 return NULL;
533
534 i = 0;
535 hicon = NULL;
536
537 if (fname[0] == ',') {
538 /* It's the XWIN.EXE resource they want */
539 i = atoi(fname + 1);
540 hicon = LoadImage(g_hInstance,
541 MAKEINTRESOURCE(i), IMAGE_ICON, sx, sy, flags);
542 }
543 else {
544 char *file = malloc(PATH_MAX + NAME_MAX + 2);
545 Bool convert = FALSE;
546
547 if (!file)
548 return NULL;
549
550 file[0] = 0;
551
552 /* If fname starts 'X:\', it's an absolute Windows path, do nothing */
553 if (!(fname[0] && fname[1] == ':' && fname[2] == '\\')) {
554 #ifdef __CYGWIN__
555 /* If fname starts with '/', it's an absolute cygwin path, we'll
556 need to convert it */
557 if (fname[0] == '/') {
558 convert = TRUE;
559 }
560 else
561 #endif
562 if (iconDirectory) {
563 /* Otherwise, prepend the default icon directory, which
564 currently must be in absolute Windows path form */
565 strcpy(file, iconDirectory);
566 if (iconDirectory[0])
567 if (iconDirectory[strlen(iconDirectory) - 1] != '\\')
568 strcat(file, "\\");
569 }
570 }
571 strcat(file, fname);
572
573 /* Trim off any ',index' */
574 if (strrchr(file, ',')) {
575 *(strrchr(file, ',')) = 0; /* End string at comma */
576 i = atoi(strrchr(fname, ',') + 1);
577 }
578 else {
579 i = -1;
580 }
581
582 #ifdef __CYGWIN__
583 /* Convert from Cygwin path to Windows path */
584 if (convert) {
585 char *converted_file = cygwin_create_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, file);
586 if (converted_file) {
587 free(file);
588 file = converted_file;
589 }
590 }
591 #endif
592
593 if (i >= 0) {
594 /* Specified as <fname>,<index> */
595 hicon = ExtractIcon(g_hInstance, file, i);
596 }
597 else {
598 /* Specified as just an .ico file */
599 hicon = (HICON) LoadImage(NULL,
600 file,
601 IMAGE_ICON,
602 sx, sy, LR_LOADFROMFILE | flags);
603 }
604 free(file);
605 }
606 return hicon;
607 }
608
609 /*
610 * Check for a match of the window class to one specified in the
611 * ICONS{} section in the prefs file, and load the icon from a file
612 */
613 HICON
winOverrideIcon(char * res_name,char * res_class,char * wmName)614 winOverrideIcon(char *res_name, char *res_class, char *wmName)
615 {
616 int i;
617 HICON hicon;
618
619 for (i = 0; i < pref.iconItems; i++) {
620 if ((res_name && !strcmp(pref.icon[i].match, res_name)) ||
621 (res_class && !strcmp(pref.icon[i].match, res_class)) ||
622 (wmName && strstr(wmName, pref.icon[i].match))) {
623 if (pref.icon[i].hicon)
624 return pref.icon[i].hicon;
625
626 hicon = LoadImageComma(pref.icon[i].iconFile, pref.iconDirectory, 0, 0, LR_DEFAULTSIZE);
627 if (hicon == NULL)
628 ErrorF("winOverrideIcon: LoadImageComma(%s) failed\n",
629 pref.icon[i].iconFile);
630
631 pref.icon[i].hicon = hicon;
632 return hicon;
633 }
634 }
635
636 /* Didn't find the icon, fail gracefully */
637 return 0;
638 }
639
640 /*
641 * Should we free this icon or leave it in memory (is it part of our
642 * ICONS{} overrides)?
643 */
644 int
winIconIsOverride(HICON hicon)645 winIconIsOverride(HICON hicon)
646 {
647 int i;
648
649 if (!hicon)
650 return 0;
651
652 for (i = 0; i < pref.iconItems; i++)
653 if ((HICON) pref.icon[i].hicon == hicon)
654 return 1;
655
656 return 0;
657 }
658
659 /*
660 * Open and parse the XWinrc config file @path.
661 * If @path is NULL, use the built-in default.
662 */
663 static int
winPrefsLoadPreferences(const char * path)664 winPrefsLoadPreferences(const char *path)
665 {
666 FILE *prefFile = NULL;
667
668 if (path)
669 prefFile = fopen(path, "r");
670 #ifdef __CYGWIN__
671 else {
672 char defaultPrefs[] =
673 "MENU rmenu {\n"
674 " \"How to customize this menu\" EXEC \"xterm +tb -e man XWinrc\"\n"
675 " \"Launch xterm\" EXEC xterm\n"
676 " \"Load .XWinrc\" RELOAD\n"
677 " SEPARATOR\n" "}\n" "\n" "ROOTMENU rmenu\n";
678
679 path = "built-in default";
680 prefFile = fmemopen(defaultPrefs, strlen(defaultPrefs), "r");
681 }
682 #endif
683
684 if (!prefFile) {
685 ErrorF("LoadPreferences: %s not found\n", path);
686 return FALSE;
687 }
688
689 ErrorF("LoadPreferences: Loading %s\n", path);
690
691 if ((parse_file(prefFile)) != 0) {
692 ErrorF("LoadPreferences: %s is badly formed!\n", path);
693 fclose(prefFile);
694 return FALSE;
695 }
696
697 fclose(prefFile);
698 return TRUE;
699 }
700
701 /*
702 * Try and open ~/.XWinrc and system.XWinrc
703 * Load it into prefs structure for use by other functions
704 */
705 void
LoadPreferences(void)706 LoadPreferences(void)
707 {
708 char *home;
709 char fname[PATH_MAX + NAME_MAX + 2];
710 char szDisplay[512];
711 char *szEnvDisplay;
712 int i, j;
713 char param[PARAM_MAX + 1];
714 char *srcParam, *dstParam;
715 int parsed = FALSE;
716
717 /* First, clear all preference settings */
718 memset(&pref, 0, sizeof(pref));
719
720 /* Now try and find a ~/.xwinrc file */
721 home = getenv("HOME");
722 if (home) {
723 strcpy(fname, home);
724 if (fname[strlen(fname) - 1] != '/')
725 strcat(fname, "/");
726 strcat(fname, ".XWinrc");
727 parsed = winPrefsLoadPreferences(fname);
728 }
729
730 /* No home file found, check system default */
731 if (!parsed) {
732 char buffer[MAX_PATH];
733
734 #ifdef RELOCATE_PROJECTROOT
735 snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir());
736 #else
737 strncpy(buffer, SYSCONFDIR "/X11/system.XWinrc", sizeof(buffer));
738 #endif
739 buffer[sizeof(buffer) - 1] = 0;
740 parsed = winPrefsLoadPreferences(buffer);
741 }
742
743 /* Neither user nor system configuration found, or were badly formed */
744 if (!parsed) {
745 ErrorF
746 ("LoadPreferences: See \"man XWinrc\" to customize the XWin menu.\n");
747 parsed = winPrefsLoadPreferences(NULL);
748 }
749
750 /* Setup a DISPLAY environment variable, need to allocate on heap */
751 /* because putenv doesn't copy the argument... */
752 winGetDisplayName(szDisplay, 0);
753 szEnvDisplay = (char *) (malloc(strlen(szDisplay) + strlen("DISPLAY=") + 1));
754 if (szEnvDisplay) {
755 snprintf(szEnvDisplay, 512, "DISPLAY=%s", szDisplay);
756 putenv(szEnvDisplay);
757 }
758
759 /* Replace any "%display%" in menu commands with display string */
760 for (i = 0; i < pref.menuItems; i++) {
761 for (j = 0; j < pref.menu[i].menuItems; j++) {
762 if (pref.menu[i].menuItem[j].cmd == CMD_EXEC) {
763 srcParam = pref.menu[i].menuItem[j].param;
764 dstParam = param;
765 while (*srcParam) {
766 if (!strncmp(srcParam, "%display%", 9)) {
767 memcpy(dstParam, szDisplay, strlen(szDisplay));
768 dstParam += strlen(szDisplay);
769 srcParam += 9;
770 }
771 else {
772 *dstParam = *srcParam;
773 dstParam++;
774 srcParam++;
775 }
776 }
777 *dstParam = 0;
778 strcpy(pref.menu[i].menuItem[j].param, param);
779 } /* cmd==cmd_exec */
780 } /* for all menuitems */
781 } /* for all menus */
782
783 }
784
785 /*
786 * Check for a match of the window class to one specified in the
787 * STYLES{} section in the prefs file, and return the style type
788 */
789 unsigned long
winOverrideStyle(char * res_name,char * res_class,char * wmName)790 winOverrideStyle(char *res_name, char *res_class, char *wmName)
791 {
792 int i;
793
794 for (i = 0; i < pref.styleItems; i++) {
795 if ((res_name && !strcmp(pref.style[i].match, res_name)) ||
796 (res_class && !strcmp(pref.style[i].match, res_class)) ||
797 (wmName && strstr(wmName, pref.style[i].match))) {
798 if (pref.style[i].type)
799 return pref.style[i].type;
800 }
801 }
802
803 /* Didn't find the style, fail gracefully */
804 return STYLE_NONE;
805 }
806