~brandontschaefer/+junk/break-x

« back to all changes in this revision

Viewing changes to hw/xwin/winprefs.c

  • Committer: Brandon Schaefer
  • Date: 2014-09-30 19:38:40 UTC
  • Revision ID: brandon.schaefer@canonical.com-20140930193840-a65z6qk8ze02cgsb
* Init commit to back this up

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "winmultiwindowclass.h"
 
48
 
 
49
/* Where will the custom menu commands start counting from? */
 
50
#define STARTMENUID WM_USER
 
51
 
 
52
extern const char *winGetBaseDir(void);
 
53
 
 
54
/* From winprefslex.l, the real parser */
 
55
extern int parse_file(FILE * fp);
 
56
 
 
57
/* Currently in use command ID, incremented each new menu item created */
 
58
static int g_cmdid = STARTMENUID;
 
59
 
 
60
/* Local function to handle comma-ified icon names */
 
61
static HICON LoadImageComma(char *fname, int sx, int sy, int flags);
 
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
#ifdef XWIN_MULTIWINDOW
 
140
/*
 
141
 * Callback routine that is executed once per window class.
 
142
 * Removes or creates custom window settings depending on LPARAM
 
143
 */
 
144
static wBOOL CALLBACK
 
145
ReloadEnumWindowsProc(HWND hwnd, LPARAM lParam)
 
146
{
 
147
    HICON hicon;
 
148
 
 
149
    if (!hwnd) {
 
150
        ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n");
 
151
        return FALSE;
 
152
    }
 
153
 
 
154
    /* It's our baby, either clean or dirty it */
 
155
    if (lParam == FALSE) {
 
156
        /* Reset the window's icon to undefined. */
 
157
        hicon = (HICON) SendMessage(hwnd, WM_SETICON, ICON_BIG, 0);
 
158
 
 
159
        /* If the old icon is generated on-the-fly, get rid of it, will regen */
 
160
        winDestroyIcon(hicon);
 
161
 
 
162
        /* Same for the small icon */
 
163
        hicon = (HICON) SendMessage(hwnd, WM_SETICON, ICON_SMALL, 0);
 
164
        winDestroyIcon(hicon);
 
165
 
 
166
        /* Remove any menu additions; bRevert=TRUE destroys any modified menus */
 
167
        GetSystemMenu(hwnd, TRUE);
 
168
 
 
169
        /* This window is now clean of our taint (but with undefined icons) */
 
170
    }
 
171
    else {
 
172
        /* Send a message to WM thread telling it re-evaluate the icon for this window */
 
173
        {
 
174
            winWMMessageRec wmMsg;
 
175
 
 
176
            WindowPtr pWin = GetProp(hwnd, WIN_WINDOW_PROP);
 
177
 
 
178
            if (pWin) {
 
179
                winPrivWinPtr pWinPriv = winGetWindowPriv(pWin);
 
180
                winPrivScreenPtr s_pScreenPriv = pWinPriv->pScreenPriv;
 
181
 
 
182
                wmMsg.msg = WM_WM_ICON_EVENT;
 
183
                wmMsg.hwndWindow = hwnd;
 
184
                wmMsg.iWindow = (Window) (INT_PTR) GetProp(hwnd, WIN_WID_PROP);
 
185
 
 
186
                winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
 
187
            }
 
188
        }
 
189
 
 
190
        /* Update the system menu for this window */
 
191
        SetupSysMenu(hwnd);
 
192
 
 
193
        /* That was easy... */
 
194
    }
 
195
 
 
196
    return TRUE;
 
197
}
 
198
#endif
 
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
 
207
ReloadPrefs(void)
 
208
{
 
209
    int i;
 
210
 
 
211
#ifdef XWIN_MULTIWINDOW
 
212
    /* First, iterate over all windows, deleting their icons and custom menus.
 
213
     * This is really only needed because winDestroyIcon() will try to
 
214
     * destroy the old global icons, which will have changed.
 
215
     * It is probably better to set a windows USER_DATA to flag locally defined
 
216
     * icons, and use that to accurately know when to destroy old icons.
 
217
     */
 
218
    EnumThreadWindows(g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE);
 
219
#endif
 
220
 
 
221
    /* Now, free/clear all info from our prefs structure */
 
222
    for (i = 0; i < pref.menuItems; i++)
 
223
        free(pref.menu[i].menuItem);
 
224
    free(pref.menu);
 
225
    pref.menu = NULL;
 
226
    pref.menuItems = 0;
 
227
 
 
228
    pref.rootMenuName[0] = 0;
 
229
 
 
230
    free(pref.sysMenu);
 
231
    pref.sysMenuItems = 0;
 
232
 
 
233
    pref.defaultSysMenuName[0] = 0;
 
234
    pref.defaultSysMenuPos = 0;
 
235
 
 
236
    pref.iconDirectory[0] = 0;
 
237
    pref.defaultIconName[0] = 0;
 
238
    pref.trayIconName[0] = 0;
 
239
 
 
240
    for (i = 0; i < pref.iconItems; i++)
 
241
        if (pref.icon[i].hicon)
 
242
            DestroyIcon((HICON) pref.icon[i].hicon);
 
243
    free(pref.icon);
 
244
    pref.icon = NULL;
 
245
    pref.iconItems = 0;
 
246
 
 
247
    /* Free global default X icon */
 
248
    if (g_hIconX)
 
249
        DestroyIcon(g_hIconX);
 
250
    if (g_hSmallIconX)
 
251
        DestroyIcon(g_hSmallIconX);
 
252
 
 
253
    /* Reset the custom command IDs */
 
254
    g_cmdid = STARTMENUID;
 
255
 
 
256
    /* Load the updated resource file */
 
257
    LoadPreferences();
 
258
 
 
259
    g_hIconX = NULL;
 
260
    g_hSmallIconX = NULL;
 
261
 
 
262
#ifdef XWIN_MULTIWINDOW
 
263
    winInitGlobalIcons();
 
264
#endif
 
265
 
 
266
#ifdef XWIN_MULTIWINDOW
 
267
    /* Rebuild the icons and menus */
 
268
    EnumThreadWindows(g_dwCurrentThreadID, ReloadEnumWindowsProc, TRUE);
 
269
#endif
 
270
 
 
271
    /* Whew, done */
 
272
}
 
273
 
 
274
/*
 
275
 * Check/uncheck the ALWAYSONTOP items in this menu
 
276
 */
 
277
void
 
278
HandleCustomWM_INITMENU(HWND hwnd, HMENU hmenu)
 
279
{
 
280
    DWORD dwExStyle;
 
281
    int i, j;
 
282
 
 
283
    if (!hwnd || !hmenu)
 
284
        return;
 
285
 
 
286
    if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
 
287
        dwExStyle = MF_BYCOMMAND | MF_CHECKED;
 
288
    else
 
289
        dwExStyle = MF_BYCOMMAND | MF_UNCHECKED;
 
290
 
 
291
    for (i = 0; i < pref.menuItems; i++)
 
292
        for (j = 0; j < pref.menu[i].menuItems; j++)
 
293
            if (pref.menu[i].menuItem[j].cmd == CMD_ALWAYSONTOP)
 
294
                CheckMenuItem(hmenu, pref.menu[i].menuItem[j].commandID,
 
295
                              dwExStyle);
 
296
 
 
297
}
 
298
 
 
299
/*
 
300
 * Searches for the custom WM_COMMAND command ID and performs action.
 
301
 * Return TRUE if command is proccessed, FALSE otherwise.
 
302
 */
 
303
Bool
 
304
HandleCustomWM_COMMAND(HWND hwnd, int command)
 
305
{
 
306
    int i, j;
 
307
    MENUPARSED *m;
 
308
    DWORD dwExStyle;
 
309
 
 
310
    if (!command)
 
311
        return FALSE;
 
312
 
 
313
    for (i = 0; i < pref.menuItems; i++) {
 
314
        m = &(pref.menu[i]);
 
315
        for (j = 0; j < m->menuItems; j++) {
 
316
            if (command == m->menuItem[j].commandID) {
 
317
                /* Match! */
 
318
                switch (m->menuItem[j].cmd) {
 
319
#ifdef __CYGWIN__
 
320
                case CMD_EXEC:
 
321
                    if (fork() == 0) {
 
322
                        struct rlimit rl;
 
323
                        int fd;
 
324
 
 
325
                        /* Close any open descriptors except for STD* */
 
326
                        getrlimit(RLIMIT_NOFILE, &rl);
 
327
                        for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++)
 
328
                            close(fd);
 
329
 
 
330
                        /* Disassociate any TTYs */
 
331
                        setsid();
 
332
 
 
333
                        execl("/bin/sh",
 
334
                              "/bin/sh", "-c", m->menuItem[j].param, NULL);
 
335
                        exit(0);
 
336
                    }
 
337
                    else
 
338
                        return TRUE;
 
339
                    break;
 
340
#else
 
341
                case CMD_EXEC:
 
342
                {
 
343
                    /* Start process without console window */
 
344
                    STARTUPINFO start;
 
345
                    PROCESS_INFORMATION child;
 
346
 
 
347
                    memset(&start, 0, sizeof(start));
 
348
                    start.cb = sizeof(start);
 
349
                    start.dwFlags = STARTF_USESHOWWINDOW;
 
350
                    start.wShowWindow = SW_HIDE;
 
351
 
 
352
                    memset(&child, 0, sizeof(child));
 
353
 
 
354
                    if (CreateProcess
 
355
                        (NULL, m->menuItem[j].param, NULL, NULL, FALSE, 0, NULL,
 
356
                         NULL, &start, &child)) {
 
357
                        CloseHandle(child.hThread);
 
358
                        CloseHandle(child.hProcess);
 
359
                    }
 
360
                    else
 
361
                        MessageBox(NULL, m->menuItem[j].param,
 
362
                                   "Mingrc Exec Command Error!",
 
363
                                   MB_OK | MB_ICONEXCLAMATION);
 
364
                }
 
365
                    return TRUE;
 
366
#endif
 
367
                case CMD_ALWAYSONTOP:
 
368
                    if (!hwnd)
 
369
                        return FALSE;
 
370
 
 
371
                    /* Get extended window style */
 
372
                    dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
 
373
 
 
374
                    /* Handle topmost windows */
 
375
                    if (dwExStyle & WS_EX_TOPMOST)
 
376
                        SetWindowPos(hwnd,
 
377
                                     HWND_NOTOPMOST,
 
378
                                     0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
 
379
                    else
 
380
                        SetWindowPos(hwnd,
 
381
                                     HWND_TOPMOST,
 
382
                                     0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
 
383
#if XWIN_MULTIWINDOW
 
384
                    /* Reflect the changed Z order */
 
385
                    winReorderWindowsMultiWindow();
 
386
#endif
 
387
                    return TRUE;
 
388
 
 
389
                case CMD_RELOAD:
 
390
                    ReloadPrefs();
 
391
                    return TRUE;
 
392
 
 
393
                default:
 
394
                    return FALSE;
 
395
                }
 
396
            }                   /* match */
 
397
        }                       /* for j */
 
398
    }                           /* for i */
 
399
 
 
400
    return FALSE;
 
401
}
 
402
 
 
403
#ifdef XWIN_MULTIWINDOW
 
404
/*
 
405
 * Add the default or a custom menu depending on the class match
 
406
 */
 
407
void
 
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
#endif
 
454
 
 
455
/*
 
456
 * Possibly add a menu to the toolbar icon
 
457
 */
 
458
void
 
459
SetupRootMenu(HMENU root)
 
460
{
 
461
    if (!root)
 
462
        return;
 
463
 
 
464
    if (pref.rootMenuName[0]) {
 
465
        MakeMenu(pref.rootMenuName, root, 0);
 
466
    }
 
467
}
 
468
 
 
469
/*
 
470
 * Check for and return an overridden default ICON specified in the prefs
 
471
 */
 
472
HICON
 
473
winOverrideDefaultIcon(int size)
 
474
{
 
475
    HICON hicon;
 
476
 
 
477
    if (pref.defaultIconName[0]) {
 
478
        hicon = LoadImageComma(pref.defaultIconName, size, size, 0);
 
479
        if (hicon == NULL)
 
480
            ErrorF("winOverrideDefaultIcon: LoadImageComma(%s) failed\n",
 
481
                   pref.defaultIconName);
 
482
 
 
483
        return hicon;
 
484
    }
 
485
 
 
486
    return 0;
 
487
}
 
488
 
 
489
/*
 
490
 * Return the HICON to use in the taskbar notification area
 
491
 */
 
492
HICON
 
493
winTaskbarIcon(void)
 
494
{
 
495
    HICON hicon;
 
496
 
 
497
    hicon = 0;
 
498
    /* First try and load an overridden, if success then return it */
 
499
    if (pref.trayIconName[0]) {
 
500
        hicon = LoadImageComma(pref.trayIconName,
 
501
                               GetSystemMetrics(SM_CXSMICON),
 
502
                               GetSystemMetrics(SM_CYSMICON), 0);
 
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
 * Parse a filename to extract an icon:
 
518
 *  If fname is exactly ",nnn" then extract icon from our resource
 
519
 *  else if it is "file,nnn" then extract icon nnn from that file
 
520
 *  else try to load it as an .ico file and if that fails return NULL
 
521
 */
 
522
static HICON
 
523
LoadImageComma(char *fname, int sx, int sy, int flags)
 
524
{
 
525
    HICON hicon;
 
526
    int i;
 
527
    char file[PATH_MAX + NAME_MAX + 2];
 
528
 
 
529
    /* Some input error checking */
 
530
    if (!fname || !fname[0])
 
531
        return NULL;
 
532
 
 
533
    i = 0;
 
534
    hicon = NULL;
 
535
 
 
536
    if (fname[0] == ',') {
 
537
        /* It's the XWIN.EXE resource they want */
 
538
        i = atoi(fname + 1);
 
539
        hicon = LoadImage(g_hInstance,
 
540
                          MAKEINTRESOURCE(i), IMAGE_ICON, sx, sy, flags);
 
541
    }
 
542
    else {
 
543
        file[0] = 0;
 
544
        /* Prepend path if not given a "X:\" filename */
 
545
        if (!(fname[0] && fname[1] == ':' && fname[2] == '\\')) {
 
546
            strcpy(file, pref.iconDirectory);
 
547
            if (pref.iconDirectory[0])
 
548
                if (fname[strlen(fname) - 1] != '\\')
 
549
                    strcat(file, "\\");
 
550
        }
 
551
        strcat(file, fname);
 
552
 
 
553
        if (strrchr(file, ',')) {
 
554
            /* Specified as <fname>,<index> */
 
555
 
 
556
            *(strrchr(file, ',')) = 0;  /* End string at comma */
 
557
            i = atoi(strrchr(fname, ',') + 1);
 
558
            hicon = ExtractIcon(g_hInstance, file, i);
 
559
        }
 
560
        else {
 
561
            /* Just an .ico file... */
 
562
 
 
563
            hicon = (HICON) LoadImage(NULL,
 
564
                                      file,
 
565
                                      IMAGE_ICON,
 
566
                                      sx, sy, LR_LOADFROMFILE | flags);
 
567
        }
 
568
    }
 
569
    return hicon;
 
570
}
 
571
 
 
572
/*
 
573
 * Check for a match of the window class to one specified in the
 
574
 * ICONS{} section in the prefs file, and load the icon from a file
 
575
 */
 
576
HICON
 
577
winOverrideIcon(char *res_name, char *res_class, char *wmName)
 
578
{
 
579
    int i;
 
580
    HICON hicon;
 
581
 
 
582
    for (i = 0; i < pref.iconItems; i++) {
 
583
        if ((res_name && !strcmp(pref.icon[i].match, res_name)) ||
 
584
            (res_class && !strcmp(pref.icon[i].match, res_class)) ||
 
585
            (wmName && strstr(wmName, pref.icon[i].match))) {
 
586
            if (pref.icon[i].hicon)
 
587
                return pref.icon[i].hicon;
 
588
 
 
589
            hicon = LoadImageComma(pref.icon[i].iconFile, 0, 0, LR_DEFAULTSIZE);
 
590
            if (hicon == NULL)
 
591
                ErrorF("winOverrideIcon: LoadImageComma(%s) failed\n",
 
592
                       pref.icon[i].iconFile);
 
593
 
 
594
            pref.icon[i].hicon = hicon;
 
595
            return hicon;
 
596
        }
 
597
    }
 
598
 
 
599
    /* Didn't find the icon, fail gracefully */
 
600
    return 0;
 
601
}
 
602
 
 
603
/*
 
604
 * Should we free this icon or leave it in memory (is it part of our
 
605
 * ICONS{} overrides)?
 
606
 */
 
607
int
 
608
winIconIsOverride(HICON hicon)
 
609
{
 
610
    int i;
 
611
 
 
612
    if (!hicon)
 
613
        return 0;
 
614
 
 
615
    for (i = 0; i < pref.iconItems; i++)
 
616
        if ((HICON) pref.icon[i].hicon == hicon)
 
617
            return 1;
 
618
 
 
619
    return 0;
 
620
}
 
621
 
 
622
/*
 
623
 * Open and parse the XWinrc config file @path.
 
624
 * If @path is NULL, use the built-in default.
 
625
 */
 
626
static int
 
627
winPrefsLoadPreferences(char *path)
 
628
{
 
629
    FILE *prefFile = NULL;
 
630
 
 
631
    if (path)
 
632
        prefFile = fopen(path, "r");
 
633
#ifdef __CYGWIN__
 
634
    else {
 
635
        char defaultPrefs[] =
 
636
            "MENU rmenu {\n"
 
637
            "  \"How to customize this menu\" EXEC \"xterm +tb -e man XWinrc\"\n"
 
638
            "  \"Launch xterm\" EXEC xterm\n"
 
639
            "  \"Load .XWinrc\" RELOAD\n"
 
640
            "  SEPARATOR\n" "}\n" "\n" "ROOTMENU rmenu\n";
 
641
 
 
642
        path = "built-in default";
 
643
        prefFile = fmemopen(defaultPrefs, strlen(defaultPrefs), "r");
 
644
    }
 
645
#endif
 
646
 
 
647
    if (!prefFile) {
 
648
        ErrorF("LoadPreferences: %s not found\n", path);
 
649
        return FALSE;
 
650
    }
 
651
 
 
652
    ErrorF("LoadPreferences: Loading %s\n", path);
 
653
 
 
654
    if ((parse_file(prefFile)) != 0) {
 
655
        ErrorF("LoadPreferences: %s is badly formed!\n", path);
 
656
        fclose(prefFile);
 
657
        return FALSE;
 
658
    }
 
659
 
 
660
    fclose(prefFile);
 
661
    return TRUE;
 
662
}
 
663
 
 
664
/*
 
665
 * Try and open ~/.XWinrc and system.XWinrc
 
666
 * Load it into prefs structure for use by other functions
 
667
 */
 
668
void
 
669
LoadPreferences(void)
 
670
{
 
671
    char *home;
 
672
    char fname[PATH_MAX + NAME_MAX + 2];
 
673
    char szDisplay[512];
 
674
    char *szEnvDisplay;
 
675
    int i, j;
 
676
    char param[PARAM_MAX + 1];
 
677
    char *srcParam, *dstParam;
 
678
    int parsed = FALSE;
 
679
 
 
680
    /* First, clear all preference settings */
 
681
    memset(&pref, 0, sizeof(pref));
 
682
 
 
683
    /* Now try and find a ~/.xwinrc file */
 
684
    home = getenv("HOME");
 
685
    if (home) {
 
686
        strcpy(fname, home);
 
687
        if (fname[strlen(fname) - 1] != '/')
 
688
            strcat(fname, "/");
 
689
        strcat(fname, ".XWinrc");
 
690
        parsed = winPrefsLoadPreferences(fname);
 
691
    }
 
692
 
 
693
    /* No home file found, check system default */
 
694
    if (!parsed) {
 
695
        char buffer[MAX_PATH];
 
696
 
 
697
#ifdef RELOCATE_PROJECTROOT
 
698
        snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir());
 
699
#else
 
700
        strncpy(buffer, SYSCONFDIR "/X11/system.XWinrc", sizeof(buffer));
 
701
#endif
 
702
        buffer[sizeof(buffer) - 1] = 0;
 
703
        parsed = winPrefsLoadPreferences(buffer);
 
704
    }
 
705
 
 
706
    /* Neither user nor system configuration found, or were badly formed */
 
707
    if (!parsed) {
 
708
        ErrorF
 
709
            ("LoadPreferences: See \"man XWinrc\" to customize the XWin menu.\n");
 
710
        parsed = winPrefsLoadPreferences(NULL);
 
711
    }
 
712
 
 
713
    /* Setup a DISPLAY environment variable, need to allocate on heap */
 
714
    /* because putenv doesn't copy the argument... */
 
715
    snprintf(szDisplay, 512, "DISPLAY=127.0.0.1:%s.0", display);
 
716
    szEnvDisplay = (char *) (malloc(strlen(szDisplay) + 1));
 
717
    if (szEnvDisplay) {
 
718
        strcpy(szEnvDisplay, szDisplay);
 
719
        putenv(szEnvDisplay);
 
720
    }
 
721
 
 
722
    /* Replace any "%display%" in menu commands with display string */
 
723
    snprintf(szDisplay, 512, "127.0.0.1:%s.0", display);
 
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
 */
 
753
unsigned long
 
754
winOverrideStyle(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
}