xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

winprefs.c (23681B)


      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 }