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