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