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