winprefs.c revision 6747b715
105b261ecSmrg/* 205b261ecSmrg * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 36747b715Smrg * Copyright (C) Colin Harrison 2005-2008 405b261ecSmrg * 505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining 605b261ecSmrg * a copy of this software and associated documentation files (the 705b261ecSmrg * "Software"), to deal in the Software without restriction, including 805b261ecSmrg * without limitation the rights to use, copy, modify, merge, publish, 905b261ecSmrg * distribute, sublicense, and/or sell copies of the Software, and to 1005b261ecSmrg * permit persons to whom the Software is furnished to do so, subject to 1105b261ecSmrg * the following conditions: 1205b261ecSmrg * 1305b261ecSmrg * The above copyright notice and this permission notice shall be 1405b261ecSmrg * included in all copies or substantial portions of the Software. 1505b261ecSmrg * 1605b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1705b261ecSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1805b261ecSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1905b261ecSmrg * NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 2005b261ecSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2105b261ecSmrg * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2205b261ecSmrg * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2305b261ecSmrg * 2405b261ecSmrg * Except as contained in this notice, the name of the XFree86 Project 2505b261ecSmrg * shall not be used in advertising or otherwise to promote the sale, use 2605b261ecSmrg * or other dealings in this Software without prior written authorization 2705b261ecSmrg * from the XFree86 Project. 2805b261ecSmrg * 2905b261ecSmrg * Authors: Earle F. Philhower, III 306747b715Smrg * Colin Harrison 3105b261ecSmrg */ 3205b261ecSmrg 3305b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3405b261ecSmrg#include <xwin-config.h> 3505b261ecSmrg#endif 3605b261ecSmrg#include <stdio.h> 3705b261ecSmrg#include <stdlib.h> 3805b261ecSmrg#ifdef __CYGWIN__ 3905b261ecSmrg#include <sys/resource.h> 4005b261ecSmrg#endif 4105b261ecSmrg#include "win.h" 4205b261ecSmrg 4305b261ecSmrg#include <X11/Xwindows.h> 4405b261ecSmrg#include <shellapi.h> 4505b261ecSmrg 4605b261ecSmrg#include "winprefs.h" 4705b261ecSmrg#include "winmultiwindowclass.h" 4805b261ecSmrg 4905b261ecSmrg/* Where will the custom menu commands start counting from? */ 5005b261ecSmrg#define STARTMENUID WM_USER 5105b261ecSmrg 5205b261ecSmrg/* External global variables */ 5305b261ecSmrg#ifdef XWIN_MULTIWINDOW 5405b261ecSmrgextern DWORD g_dwCurrentThreadID; 5505b261ecSmrg#endif 5605b261ecSmrg 5705b261ecSmrgextern const char *winGetBaseDir(void); 5805b261ecSmrg 5905b261ecSmrg/* From winmultiwindowflex.l, the real parser */ 6005b261ecSmrgextern void parse_file (FILE *fp); 6105b261ecSmrg 6205b261ecSmrg/* From winprefyacc.y, the pref structure loaded by the parser */ 6305b261ecSmrgextern WINPREFS pref; 6405b261ecSmrg 6505b261ecSmrg/* The global X default icon */ 6605b261ecSmrgextern HICON g_hIconX; 6705b261ecSmrgextern HICON g_hSmallIconX; 6805b261ecSmrg 6905b261ecSmrg/* Currently in use command ID, incremented each new menu item created */ 7005b261ecSmrgstatic int g_cmdid = STARTMENUID; 7105b261ecSmrg 7205b261ecSmrg 7305b261ecSmrg/* Defined in DIX */ 7405b261ecSmrgextern char *display; 7505b261ecSmrg 7605b261ecSmrg/* Local function to handle comma-ified icon names */ 7705b261ecSmrgstatic HICON 7805b261ecSmrgLoadImageComma (char *fname, int sx, int sy, int flags); 7905b261ecSmrg 8005b261ecSmrg 8105b261ecSmrg/* 8205b261ecSmrg * Creates or appends a menu from a MENUPARSED structure 8305b261ecSmrg */ 8405b261ecSmrgstatic HMENU 8505b261ecSmrgMakeMenu (char *name, 8605b261ecSmrg HMENU editMenu, 8705b261ecSmrg int editItem) 8805b261ecSmrg{ 8905b261ecSmrg int i; 9005b261ecSmrg int item; 9105b261ecSmrg MENUPARSED *m; 9205b261ecSmrg HMENU hmenu, hsub; 9305b261ecSmrg 9405b261ecSmrg for (i=0; i<pref.menuItems; i++) 9505b261ecSmrg { 9605b261ecSmrg if (!strcmp(name, pref.menu[i].menuName)) 9705b261ecSmrg break; 9805b261ecSmrg } 9905b261ecSmrg 10005b261ecSmrg /* Didn't find a match, bummer */ 10105b261ecSmrg if (i==pref.menuItems) 10205b261ecSmrg { 10305b261ecSmrg ErrorF("MakeMenu: Can't find menu %s\n", name); 10405b261ecSmrg return NULL; 10505b261ecSmrg } 10605b261ecSmrg 10705b261ecSmrg m = &(pref.menu[i]); 10805b261ecSmrg 10905b261ecSmrg if (editMenu) 11005b261ecSmrg { 11105b261ecSmrg hmenu = editMenu; 11205b261ecSmrg item = editItem; 11305b261ecSmrg } 11405b261ecSmrg else 11505b261ecSmrg { 11605b261ecSmrg hmenu = CreatePopupMenu(); 11705b261ecSmrg if (!hmenu) 11805b261ecSmrg { 11905b261ecSmrg ErrorF("MakeMenu: Unable to CreatePopupMenu() %s\n", name); 12005b261ecSmrg return NULL; 12105b261ecSmrg } 12205b261ecSmrg item = 0; 12305b261ecSmrg } 12405b261ecSmrg 12505b261ecSmrg /* Add the menu items */ 12605b261ecSmrg for (i=0; i<m->menuItems; i++) 12705b261ecSmrg { 12805b261ecSmrg /* Only assign IDs one time... */ 12905b261ecSmrg if ( m->menuItem[i].commandID == 0 ) 13005b261ecSmrg m->menuItem[i].commandID = g_cmdid++; 13105b261ecSmrg 13205b261ecSmrg switch (m->menuItem[i].cmd) 13305b261ecSmrg { 13405b261ecSmrg case CMD_EXEC: 13505b261ecSmrg case CMD_ALWAYSONTOP: 13605b261ecSmrg case CMD_RELOAD: 13705b261ecSmrg InsertMenu (hmenu, 13805b261ecSmrg item, 13905b261ecSmrg MF_BYPOSITION|MF_ENABLED|MF_STRING, 14005b261ecSmrg m->menuItem[i].commandID, 14105b261ecSmrg m->menuItem[i].text); 14205b261ecSmrg break; 14305b261ecSmrg 14405b261ecSmrg case CMD_SEPARATOR: 14505b261ecSmrg InsertMenu (hmenu, 14605b261ecSmrg item, 14705b261ecSmrg MF_BYPOSITION|MF_SEPARATOR, 14805b261ecSmrg 0, 14905b261ecSmrg NULL); 15005b261ecSmrg break; 15105b261ecSmrg 15205b261ecSmrg case CMD_MENU: 15305b261ecSmrg /* Recursive! */ 15405b261ecSmrg hsub = MakeMenu (m->menuItem[i].param, 0, 0); 15505b261ecSmrg if (hsub) 15605b261ecSmrg InsertMenu (hmenu, 15705b261ecSmrg item, 15805b261ecSmrg MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING, 15905b261ecSmrg (UINT_PTR)hsub, 16005b261ecSmrg m->menuItem[i].text); 16105b261ecSmrg break; 16205b261ecSmrg } 16305b261ecSmrg 16405b261ecSmrg /* If item==-1 (means to add at end of menu) don't increment) */ 16505b261ecSmrg if (item>=0) 16605b261ecSmrg item++; 16705b261ecSmrg } 16805b261ecSmrg 16905b261ecSmrg return hmenu; 17005b261ecSmrg} 17105b261ecSmrg 17205b261ecSmrg 17305b261ecSmrg#ifdef XWIN_MULTIWINDOW 17405b261ecSmrg/* 17505b261ecSmrg * Callback routine that is executed once per window class. 17605b261ecSmrg * Removes or creates custom window settings depending on LPARAM 17705b261ecSmrg */ 17805b261ecSmrgstatic wBOOL CALLBACK 17905b261ecSmrgReloadEnumWindowsProc (HWND hwnd, LPARAM lParam) 18005b261ecSmrg{ 18105b261ecSmrg HICON hicon; 18205b261ecSmrg Window wid; 18305b261ecSmrg 18405b261ecSmrg if (!hwnd) { 18505b261ecSmrg ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n"); 18605b261ecSmrg return FALSE; 18705b261ecSmrg } 18805b261ecSmrg 18905b261ecSmrg /* It's our baby, either clean or dirty it */ 19005b261ecSmrg if (lParam==FALSE) 19105b261ecSmrg { 1926747b715Smrg /* Reset the window's icon to undefined. */ 1936747b715Smrg hicon = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, 0); 19405b261ecSmrg 1956747b715Smrg /* If the old icon is generated on-the-fly, get rid of it, will regen */ 19605b261ecSmrg winDestroyIcon (hicon); 19705b261ecSmrg 1986747b715Smrg /* Same for the small icon */ 1996747b715Smrg hicon = (HICON)SendMessage(hwnd, WM_SETICON, ICON_SMALL, 0); 20005b261ecSmrg winDestroyIcon (hicon); 2016747b715Smrg 2026747b715Smrg /* Remove any menu additions; bRevert=TRUE destroys any modified menus */ 20305b261ecSmrg GetSystemMenu (hwnd, TRUE); 20405b261ecSmrg 2056747b715Smrg /* This window is now clean of our taint (but with undefined icons) */ 20605b261ecSmrg } 20705b261ecSmrg else 20805b261ecSmrg { 2096747b715Smrg /* winUpdateIcon() will set the icon default, dynamic, or from xwinrc */ 21005b261ecSmrg wid = (Window)GetProp (hwnd, WIN_WID_PROP); 21105b261ecSmrg if (wid) 21205b261ecSmrg winUpdateIcon (wid); 2136747b715Smrg 21405b261ecSmrg /* Update the system menu for this window */ 21505b261ecSmrg SetupSysMenu ((unsigned long)hwnd); 21605b261ecSmrg 21705b261ecSmrg /* That was easy... */ 21805b261ecSmrg } 21905b261ecSmrg 22005b261ecSmrg return TRUE; 22105b261ecSmrg} 22205b261ecSmrg#endif 22305b261ecSmrg 22405b261ecSmrg 22505b261ecSmrg/* 22605b261ecSmrg * Removes any custom icons in classes, custom menus, etc. 22705b261ecSmrg * Frees all members in pref structure. 22805b261ecSmrg * Reloads the preferences file. 22905b261ecSmrg * Set custom icons and menus again. 23005b261ecSmrg */ 23105b261ecSmrgstatic void 23205b261ecSmrgReloadPrefs (void) 23305b261ecSmrg{ 23405b261ecSmrg int i; 23505b261ecSmrg 23605b261ecSmrg#ifdef XWIN_MULTIWINDOW 2376747b715Smrg /* First, iterate over all windows, deleting their icons and custom menus. 2386747b715Smrg * This is really only needed because winDestroyIcon() will try to 2396747b715Smrg * destroy the old global icons, which will have changed. 2406747b715Smrg * It is probably better to set a windows USER_DATA to flag locally defined 2416747b715Smrg * icons, and use that to accurately know when to destroy old icons. 2426747b715Smrg */ 24305b261ecSmrg EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE); 24405b261ecSmrg#endif 24505b261ecSmrg 24605b261ecSmrg /* Now, free/clear all info from our prefs structure */ 24705b261ecSmrg for (i=0; i<pref.menuItems; i++) 24805b261ecSmrg free (pref.menu[i].menuItem); 24905b261ecSmrg free (pref.menu); 25005b261ecSmrg pref.menu = NULL; 25105b261ecSmrg pref.menuItems = 0; 25205b261ecSmrg 25305b261ecSmrg pref.rootMenuName[0] = 0; 25405b261ecSmrg 25505b261ecSmrg free (pref.sysMenu); 25605b261ecSmrg pref.sysMenuItems = 0; 25705b261ecSmrg 25805b261ecSmrg pref.defaultSysMenuName[0] = 0; 25905b261ecSmrg pref.defaultSysMenuPos = 0; 26005b261ecSmrg 26105b261ecSmrg pref.iconDirectory[0] = 0; 26205b261ecSmrg pref.defaultIconName[0] = 0; 26305b261ecSmrg pref.trayIconName[0] = 0; 26405b261ecSmrg 26505b261ecSmrg for (i=0; i<pref.iconItems; i++) 26605b261ecSmrg if (pref.icon[i].hicon) 26705b261ecSmrg DestroyIcon ((HICON)pref.icon[i].hicon); 26805b261ecSmrg free (pref.icon); 26905b261ecSmrg pref.icon = NULL; 27005b261ecSmrg pref.iconItems = 0; 27105b261ecSmrg 27205b261ecSmrg /* Free global default X icon */ 27305b261ecSmrg if (g_hIconX) 27405b261ecSmrg DestroyIcon (g_hIconX); 27505b261ecSmrg if (g_hSmallIconX) 27605b261ecSmrg DestroyIcon (g_hSmallIconX); 27705b261ecSmrg 27805b261ecSmrg /* Reset the custom command IDs */ 27905b261ecSmrg g_cmdid = STARTMENUID; 28005b261ecSmrg 28105b261ecSmrg /* Load the updated resource file */ 28205b261ecSmrg LoadPreferences(); 28305b261ecSmrg 28405b261ecSmrg g_hIconX = NULL; 28505b261ecSmrg g_hSmallIconX = NULL; 28605b261ecSmrg 28705b261ecSmrg#ifdef XWIN_MULTIWINDOW 28805b261ecSmrg winInitGlobalIcons(); 28905b261ecSmrg#endif 29005b261ecSmrg 29105b261ecSmrg#ifdef XWIN_MULTIWINDOW 29205b261ecSmrg /* Rebuild the icons and menus */ 29305b261ecSmrg EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, TRUE); 29405b261ecSmrg#endif 29505b261ecSmrg 29605b261ecSmrg /* Whew, done */ 29705b261ecSmrg} 29805b261ecSmrg 29905b261ecSmrg/* 30005b261ecSmrg * Check/uncheck the ALWAYSONTOP items in this menu 30105b261ecSmrg */ 30205b261ecSmrgvoid 30305b261ecSmrgHandleCustomWM_INITMENU(unsigned long hwndIn, 30405b261ecSmrg unsigned long hmenuIn) 30505b261ecSmrg{ 30605b261ecSmrg HWND hwnd; 30705b261ecSmrg HMENU hmenu; 30805b261ecSmrg DWORD dwExStyle; 30905b261ecSmrg int i, j; 31005b261ecSmrg 31105b261ecSmrg hwnd = (HWND)hwndIn; 31205b261ecSmrg hmenu = (HMENU)hmenuIn; 31305b261ecSmrg if (!hwnd || !hmenu) 31405b261ecSmrg return; 31505b261ecSmrg 3166747b715Smrg if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) 31705b261ecSmrg dwExStyle = MF_BYCOMMAND | MF_CHECKED; 31805b261ecSmrg else 31905b261ecSmrg dwExStyle = MF_BYCOMMAND | MF_UNCHECKED; 32005b261ecSmrg 32105b261ecSmrg for (i=0; i<pref.menuItems; i++) 32205b261ecSmrg for (j=0; j<pref.menu[i].menuItems; j++) 32305b261ecSmrg if (pref.menu[i].menuItem[j].cmd==CMD_ALWAYSONTOP) 32405b261ecSmrg CheckMenuItem (hmenu, pref.menu[i].menuItem[j].commandID, dwExStyle ); 32505b261ecSmrg 32605b261ecSmrg} 32705b261ecSmrg 32805b261ecSmrg/* 32905b261ecSmrg * Searches for the custom WM_COMMAND command ID and performs action. 33005b261ecSmrg * Return TRUE if command is proccessed, FALSE otherwise. 33105b261ecSmrg */ 33205b261ecSmrgBool 33305b261ecSmrgHandleCustomWM_COMMAND (unsigned long hwndIn, 33405b261ecSmrg int command) 33505b261ecSmrg{ 33605b261ecSmrg HWND hwnd; 33705b261ecSmrg int i, j; 33805b261ecSmrg MENUPARSED *m; 33905b261ecSmrg DWORD dwExStyle; 34005b261ecSmrg 34105b261ecSmrg hwnd = (HWND)hwndIn; 34205b261ecSmrg 34305b261ecSmrg if (!command) 34405b261ecSmrg return FALSE; 34505b261ecSmrg 34605b261ecSmrg for (i=0; i<pref.menuItems; i++) 34705b261ecSmrg { 34805b261ecSmrg m = &(pref.menu[i]); 34905b261ecSmrg for (j=0; j<m->menuItems; j++) 35005b261ecSmrg { 35105b261ecSmrg if (command==m->menuItem[j].commandID) 35205b261ecSmrg { 35305b261ecSmrg /* Match! */ 35405b261ecSmrg switch(m->menuItem[j].cmd) 35505b261ecSmrg { 35605b261ecSmrg#ifdef __CYGWIN__ 35705b261ecSmrg case CMD_EXEC: 35805b261ecSmrg if (fork()==0) 35905b261ecSmrg { 36005b261ecSmrg struct rlimit rl; 36105b261ecSmrg unsigned long i; 36205b261ecSmrg 36305b261ecSmrg /* Close any open descriptors except for STD* */ 36405b261ecSmrg getrlimit (RLIMIT_NOFILE, &rl); 36505b261ecSmrg for (i = STDERR_FILENO+1; i < rl.rlim_cur; i++) 36605b261ecSmrg close(i); 36705b261ecSmrg 36805b261ecSmrg /* Disassociate any TTYs */ 36905b261ecSmrg setsid(); 37005b261ecSmrg 37105b261ecSmrg execl ("/bin/sh", 37205b261ecSmrg "/bin/sh", 37305b261ecSmrg "-c", 37405b261ecSmrg m->menuItem[j].param, 37505b261ecSmrg NULL); 37605b261ecSmrg exit (0); 37705b261ecSmrg } 37805b261ecSmrg else 37905b261ecSmrg return TRUE; 38005b261ecSmrg break; 38105b261ecSmrg#else 38205b261ecSmrg case CMD_EXEC: 38305b261ecSmrg { 38405b261ecSmrg /* Start process without console window */ 38505b261ecSmrg STARTUPINFO start; 38605b261ecSmrg PROCESS_INFORMATION child; 38705b261ecSmrg 38805b261ecSmrg memset (&start, 0, sizeof (start)); 38905b261ecSmrg start.cb = sizeof (start); 39005b261ecSmrg start.dwFlags = STARTF_USESHOWWINDOW; 39105b261ecSmrg start.wShowWindow = SW_HIDE; 39205b261ecSmrg 39305b261ecSmrg memset (&child, 0, sizeof (child)); 39405b261ecSmrg 39505b261ecSmrg if (CreateProcess (NULL, m->menuItem[j].param, NULL, NULL, FALSE, 0, 39605b261ecSmrg NULL, NULL, &start, &child)) 39705b261ecSmrg { 39805b261ecSmrg CloseHandle (child.hThread); 39905b261ecSmrg CloseHandle (child.hProcess); 40005b261ecSmrg } 40105b261ecSmrg else 40205b261ecSmrg MessageBox(NULL, m->menuItem[j].param, "Mingrc Exec Command Error!", MB_OK | MB_ICONEXCLAMATION); 40305b261ecSmrg } 40405b261ecSmrg return TRUE; 40505b261ecSmrg#endif 40605b261ecSmrg case CMD_ALWAYSONTOP: 40705b261ecSmrg if (!hwnd) 40805b261ecSmrg return FALSE; 40905b261ecSmrg 41005b261ecSmrg /* Get extended window style */ 4116747b715Smrg dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE); 41205b261ecSmrg 41305b261ecSmrg /* Handle topmost windows */ 41405b261ecSmrg if (dwExStyle & WS_EX_TOPMOST) 41505b261ecSmrg SetWindowPos (hwnd, 41605b261ecSmrg HWND_NOTOPMOST, 41705b261ecSmrg 0, 0, 41805b261ecSmrg 0, 0, 41905b261ecSmrg SWP_NOSIZE | SWP_NOMOVE); 42005b261ecSmrg else 42105b261ecSmrg SetWindowPos (hwnd, 42205b261ecSmrg HWND_TOPMOST, 42305b261ecSmrg 0, 0, 42405b261ecSmrg 0, 0, 42505b261ecSmrg SWP_NOSIZE | SWP_NOMOVE); 42605b261ecSmrg#if XWIN_MULTIWINDOW 42705b261ecSmrg /* Reflect the changed Z order */ 42805b261ecSmrg winReorderWindowsMultiWindow (); 42905b261ecSmrg#endif 43005b261ecSmrg return TRUE; 43105b261ecSmrg 43205b261ecSmrg case CMD_RELOAD: 43305b261ecSmrg ReloadPrefs(); 43405b261ecSmrg return TRUE; 43505b261ecSmrg 43605b261ecSmrg default: 43705b261ecSmrg return FALSE; 43805b261ecSmrg } 43905b261ecSmrg } /* match */ 44005b261ecSmrg } /* for j */ 44105b261ecSmrg } /* for i */ 44205b261ecSmrg 44305b261ecSmrg return FALSE; 44405b261ecSmrg} 44505b261ecSmrg 44605b261ecSmrg 44705b261ecSmrg#ifdef XWIN_MULTIWINDOW 44805b261ecSmrg/* 44905b261ecSmrg * Add the default or a custom menu depending on the class match 45005b261ecSmrg */ 45105b261ecSmrgvoid 45205b261ecSmrgSetupSysMenu (unsigned long hwndIn) 45305b261ecSmrg{ 45405b261ecSmrg HWND hwnd; 45505b261ecSmrg HMENU sys; 45605b261ecSmrg int i; 45705b261ecSmrg WindowPtr pWin; 45805b261ecSmrg char *res_name, *res_class; 45905b261ecSmrg 46005b261ecSmrg hwnd = (HWND)hwndIn; 46105b261ecSmrg if (!hwnd) 46205b261ecSmrg return; 46305b261ecSmrg 46405b261ecSmrg pWin = GetProp (hwnd, WIN_WINDOW_PROP); 46505b261ecSmrg 46605b261ecSmrg sys = GetSystemMenu (hwnd, FALSE); 46705b261ecSmrg if (!sys) 46805b261ecSmrg return; 46905b261ecSmrg 47005b261ecSmrg if (pWin) 47105b261ecSmrg { 47205b261ecSmrg /* First see if there's a class match... */ 47305b261ecSmrg if (winMultiWindowGetClassHint (pWin, &res_name, &res_class)) 47405b261ecSmrg { 47505b261ecSmrg for (i=0; i<pref.sysMenuItems; i++) 47605b261ecSmrg { 47705b261ecSmrg if (!strcmp(pref.sysMenu[i].match, res_name) || 47805b261ecSmrg !strcmp(pref.sysMenu[i].match, res_class) ) 47905b261ecSmrg { 48005b261ecSmrg free(res_name); 48105b261ecSmrg free(res_class); 48205b261ecSmrg 48305b261ecSmrg MakeMenu (pref.sysMenu[i].menuName, sys, 48405b261ecSmrg pref.sysMenu[i].menuPos==AT_START?0:-1); 48505b261ecSmrg return; 48605b261ecSmrg } 48705b261ecSmrg } 48805b261ecSmrg 48905b261ecSmrg /* No match, just free alloc'd strings */ 49005b261ecSmrg free(res_name); 49105b261ecSmrg free(res_class); 49205b261ecSmrg } /* Found wm_class */ 49305b261ecSmrg } /* if pwin */ 49405b261ecSmrg 49505b261ecSmrg /* Fallback to system default */ 49605b261ecSmrg if (pref.defaultSysMenuName[0]) 49705b261ecSmrg { 49805b261ecSmrg if (pref.defaultSysMenuPos==AT_START) 49905b261ecSmrg MakeMenu (pref.defaultSysMenuName, sys, 0); 50005b261ecSmrg else 50105b261ecSmrg MakeMenu (pref.defaultSysMenuName, sys, -1); 50205b261ecSmrg } 50305b261ecSmrg} 50405b261ecSmrg#endif 50505b261ecSmrg 50605b261ecSmrg 50705b261ecSmrg/* 50805b261ecSmrg * Possibly add a menu to the toolbar icon 50905b261ecSmrg */ 51005b261ecSmrgvoid 51105b261ecSmrgSetupRootMenu (unsigned long hmenuRoot) 51205b261ecSmrg{ 51305b261ecSmrg HMENU root; 51405b261ecSmrg 51505b261ecSmrg root = (HMENU)hmenuRoot; 51605b261ecSmrg if (!root) 51705b261ecSmrg return; 51805b261ecSmrg 51905b261ecSmrg if (pref.rootMenuName[0]) 52005b261ecSmrg { 52105b261ecSmrg MakeMenu(pref.rootMenuName, root, 0); 52205b261ecSmrg } 52305b261ecSmrg} 52405b261ecSmrg 52505b261ecSmrg 52605b261ecSmrg/* 52705b261ecSmrg * Check for and return an overridden default ICON specified in the prefs 52805b261ecSmrg */ 5296747b715SmrgHICON 53005b261ecSmrgwinOverrideDefaultIcon(int size) 53105b261ecSmrg{ 53205b261ecSmrg HICON hicon; 53305b261ecSmrg 53405b261ecSmrg if (pref.defaultIconName[0]) 53505b261ecSmrg { 53605b261ecSmrg hicon = LoadImageComma (pref.defaultIconName, size, size, 0); 53705b261ecSmrg if (hicon==NULL) 53805b261ecSmrg ErrorF ("winOverrideDefaultIcon: LoadImageComma(%s) failed\n", 53905b261ecSmrg pref.defaultIconName); 54005b261ecSmrg 5416747b715Smrg return hicon; 54205b261ecSmrg } 54305b261ecSmrg 54405b261ecSmrg return 0; 54505b261ecSmrg} 54605b261ecSmrg 54705b261ecSmrg 54805b261ecSmrg/* 54905b261ecSmrg * Return the HICON to use in the taskbar notification area 55005b261ecSmrg */ 5516747b715SmrgHICON 55205b261ecSmrgwinTaskbarIcon(void) 55305b261ecSmrg{ 55405b261ecSmrg HICON hicon; 55505b261ecSmrg 55605b261ecSmrg hicon = 0; 55705b261ecSmrg /* First try and load an overridden, if success then return it */ 55805b261ecSmrg if (pref.trayIconName[0]) 55905b261ecSmrg { 56005b261ecSmrg hicon = LoadImageComma (pref.trayIconName, 56105b261ecSmrg GetSystemMetrics (SM_CXSMICON), 56205b261ecSmrg GetSystemMetrics (SM_CYSMICON), 56305b261ecSmrg 0 ); 56405b261ecSmrg } 56505b261ecSmrg 56605b261ecSmrg /* Otherwise return the default */ 56705b261ecSmrg if (!hicon) 56805b261ecSmrg hicon = (HICON) LoadImage (g_hInstance, 56905b261ecSmrg MAKEINTRESOURCE(IDI_XWIN), 57005b261ecSmrg IMAGE_ICON, 57105b261ecSmrg GetSystemMetrics (SM_CXSMICON), 57205b261ecSmrg GetSystemMetrics (SM_CYSMICON), 57305b261ecSmrg 0); 57405b261ecSmrg 5756747b715Smrg return hicon; 57605b261ecSmrg} 57705b261ecSmrg 57805b261ecSmrg 57905b261ecSmrg/* 58005b261ecSmrg * Parse a filename to extract an icon: 58105b261ecSmrg * If fname is exactly ",nnn" then extract icon from our resource 58205b261ecSmrg * else if it is "file,nnn" then extract icon nnn from that file 58305b261ecSmrg * else try to load it as an .ico file and if that fails return NULL 58405b261ecSmrg */ 58505b261ecSmrgstatic HICON 58605b261ecSmrgLoadImageComma (char *fname, int sx, int sy, int flags) 58705b261ecSmrg{ 58805b261ecSmrg HICON hicon; 58905b261ecSmrg int index; 59005b261ecSmrg char file[PATH_MAX+NAME_MAX+2]; 59105b261ecSmrg 59205b261ecSmrg /* Some input error checking */ 59305b261ecSmrg if (!fname || !fname[0]) 59405b261ecSmrg return NULL; 59505b261ecSmrg 59605b261ecSmrg index = 0; 59705b261ecSmrg hicon = NULL; 59805b261ecSmrg 59905b261ecSmrg if (fname[0]==',') 60005b261ecSmrg { 60105b261ecSmrg /* It's the XWIN.EXE resource they want */ 60205b261ecSmrg index = atoi (fname+1); 60305b261ecSmrg hicon = LoadImage (g_hInstance, 60405b261ecSmrg MAKEINTRESOURCE(index), 60505b261ecSmrg IMAGE_ICON, 60605b261ecSmrg sx, 60705b261ecSmrg sy, 60805b261ecSmrg flags); 60905b261ecSmrg } 61005b261ecSmrg else 61105b261ecSmrg { 61205b261ecSmrg file[0] = 0; 61305b261ecSmrg /* Prepend path if not given a "X:\" filename */ 61405b261ecSmrg if ( !(fname[0] && fname[1]==':' && fname[2]=='\\') ) 61505b261ecSmrg { 61605b261ecSmrg strcpy (file, pref.iconDirectory); 61705b261ecSmrg if (pref.iconDirectory[0]) 61805b261ecSmrg if (fname[strlen(fname)-1]!='\\') 61905b261ecSmrg strcat (file, "\\"); 62005b261ecSmrg } 62105b261ecSmrg strcat (file, fname); 62205b261ecSmrg 62305b261ecSmrg if (strrchr (file, ',')) 62405b261ecSmrg { 62505b261ecSmrg /* Specified as <fname>,<index> */ 62605b261ecSmrg 62705b261ecSmrg *(strrchr (file, ',')) = 0; /* End string at comma */ 62805b261ecSmrg index = atoi (strrchr (fname, ',') + 1); 62905b261ecSmrg hicon = ExtractIcon (g_hInstance, file, index); 63005b261ecSmrg } 63105b261ecSmrg else 63205b261ecSmrg { 63305b261ecSmrg /* Just an .ico file... */ 63405b261ecSmrg 63505b261ecSmrg hicon = (HICON)LoadImage (NULL, 63605b261ecSmrg file, 63705b261ecSmrg IMAGE_ICON, 63805b261ecSmrg sx, 63905b261ecSmrg sy, 64005b261ecSmrg LR_LOADFROMFILE|flags); 64105b261ecSmrg } 64205b261ecSmrg } 64305b261ecSmrg return hicon; 64405b261ecSmrg} 64505b261ecSmrg 64605b261ecSmrg/* 64705b261ecSmrg * Check for a match of the window class to one specified in the 64805b261ecSmrg * ICONS{} section in the prefs file, and load the icon from a file 64905b261ecSmrg */ 6506747b715SmrgHICON 65105b261ecSmrgwinOverrideIcon (unsigned long longWin) 65205b261ecSmrg{ 65305b261ecSmrg WindowPtr pWin = (WindowPtr) longWin; 65405b261ecSmrg char *res_name, *res_class; 65505b261ecSmrg int i; 65605b261ecSmrg HICON hicon; 65705b261ecSmrg char *wmName; 65805b261ecSmrg 65905b261ecSmrg if (pWin==NULL) 66005b261ecSmrg return 0; 66105b261ecSmrg 66205b261ecSmrg /* If we can't find the class, we can't override from default! */ 66305b261ecSmrg if (!winMultiWindowGetClassHint (pWin, &res_name, &res_class)) 66405b261ecSmrg return 0; 66505b261ecSmrg 66605b261ecSmrg winMultiWindowGetWMName (pWin, &wmName); 66705b261ecSmrg 66805b261ecSmrg for (i=0; i<pref.iconItems; i++) { 66905b261ecSmrg if (!strcmp(pref.icon[i].match, res_name) || 67005b261ecSmrg !strcmp(pref.icon[i].match, res_class) || 67105b261ecSmrg (wmName && strstr(wmName, pref.icon[i].match))) 67205b261ecSmrg { 67305b261ecSmrg free (res_name); 67405b261ecSmrg free (res_class); 6756747b715Smrg free(wmName); 67605b261ecSmrg 67705b261ecSmrg if (pref.icon[i].hicon) 67805b261ecSmrg return pref.icon[i].hicon; 67905b261ecSmrg 68005b261ecSmrg hicon = LoadImageComma (pref.icon[i].iconFile, 0, 0, LR_DEFAULTSIZE); 68105b261ecSmrg if (hicon==NULL) 68205b261ecSmrg ErrorF ("winOverrideIcon: LoadImageComma(%s) failed\n", 68305b261ecSmrg pref.icon[i].iconFile); 68405b261ecSmrg 6856747b715Smrg pref.icon[i].hicon = hicon; 6866747b715Smrg return hicon; 68705b261ecSmrg } 68805b261ecSmrg } 68905b261ecSmrg 69005b261ecSmrg /* Didn't find the icon, fail gracefully */ 69105b261ecSmrg free (res_name); 69205b261ecSmrg free (res_class); 6936747b715Smrg free(wmName); 69405b261ecSmrg 69505b261ecSmrg return 0; 69605b261ecSmrg} 69705b261ecSmrg 69805b261ecSmrg 69905b261ecSmrg/* 70005b261ecSmrg * Should we free this icon or leave it in memory (is it part of our 70105b261ecSmrg * ICONS{} overrides)? 70205b261ecSmrg */ 70305b261ecSmrgint 70405b261ecSmrgwinIconIsOverride(unsigned hiconIn) 70505b261ecSmrg{ 70605b261ecSmrg HICON hicon; 70705b261ecSmrg int i; 70805b261ecSmrg 70905b261ecSmrg hicon = (HICON)hiconIn; 71005b261ecSmrg 71105b261ecSmrg if (!hicon) 71205b261ecSmrg return 0; 71305b261ecSmrg 71405b261ecSmrg for (i=0; i<pref.iconItems; i++) 71505b261ecSmrg if ((HICON)pref.icon[i].hicon == hicon) 71605b261ecSmrg return 1; 71705b261ecSmrg 71805b261ecSmrg return 0; 71905b261ecSmrg} 72005b261ecSmrg 72105b261ecSmrg 72205b261ecSmrg 72305b261ecSmrg/* 7246747b715Smrg * Try and open ~/.XWinrc and system.XWinrc 72505b261ecSmrg * Load it into prefs structure for use by other functions 72605b261ecSmrg */ 72705b261ecSmrgvoid 7286747b715SmrgLoadPreferences (void) 72905b261ecSmrg{ 73005b261ecSmrg char *home; 73105b261ecSmrg char fname[PATH_MAX+NAME_MAX+2]; 73205b261ecSmrg FILE *prefFile; 73305b261ecSmrg char szDisplay[512]; 73405b261ecSmrg char *szEnvDisplay; 73505b261ecSmrg int i, j; 73605b261ecSmrg char param[PARAM_MAX+1]; 73705b261ecSmrg char *srcParam, *dstParam; 73805b261ecSmrg 73905b261ecSmrg /* First, clear all preference settings */ 74005b261ecSmrg memset (&pref, 0, sizeof(pref)); 74105b261ecSmrg prefFile = NULL; 74205b261ecSmrg 74305b261ecSmrg /* Now try and find a ~/.xwinrc file */ 74405b261ecSmrg home = getenv ("HOME"); 74505b261ecSmrg if (home) 74605b261ecSmrg { 74705b261ecSmrg strcpy (fname, home); 74805b261ecSmrg if (fname[strlen(fname)-1]!='/') 74905b261ecSmrg strcat (fname, "/"); 75005b261ecSmrg strcat (fname, ".XWinrc"); 75105b261ecSmrg 75205b261ecSmrg prefFile = fopen (fname, "r"); 75305b261ecSmrg if (prefFile) 75405b261ecSmrg ErrorF ("winPrefsLoadPreferences: %s\n", fname); 75505b261ecSmrg } 75605b261ecSmrg 75705b261ecSmrg /* No home file found, check system default */ 75805b261ecSmrg if (!prefFile) 75905b261ecSmrg { 76005b261ecSmrg char buffer[MAX_PATH]; 76105b261ecSmrg#ifdef RELOCATE_PROJECTROOT 76205b261ecSmrg snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir()); 76305b261ecSmrg#else 7646747b715Smrg strncpy(buffer, SYSCONFDIR"/X11/system.XWinrc", sizeof(buffer)); 76505b261ecSmrg#endif 76605b261ecSmrg buffer[sizeof(buffer)-1] = 0; 76705b261ecSmrg prefFile = fopen (buffer, "r"); 76805b261ecSmrg if (prefFile) 76905b261ecSmrg ErrorF ("winPrefsLoadPreferences: %s\n", buffer); 77005b261ecSmrg } 77105b261ecSmrg 77205b261ecSmrg /* If we could open it, then read the settings and close it */ 77305b261ecSmrg if (prefFile) 77405b261ecSmrg { 77505b261ecSmrg parse_file (prefFile); 77605b261ecSmrg fclose (prefFile); 77705b261ecSmrg } 77805b261ecSmrg 77905b261ecSmrg /* Setup a DISPLAY environment variable, need to allocate on heap */ 78005b261ecSmrg /* because putenv doesn't copy the argument... */ 78105b261ecSmrg snprintf (szDisplay, 512, "DISPLAY=127.0.0.1:%s.0", display); 78205b261ecSmrg szEnvDisplay = (char *)(malloc (strlen(szDisplay)+1)); 78305b261ecSmrg if (szEnvDisplay) 78405b261ecSmrg { 78505b261ecSmrg strcpy (szEnvDisplay, szDisplay); 78605b261ecSmrg putenv (szEnvDisplay); 78705b261ecSmrg } 78805b261ecSmrg 78905b261ecSmrg /* Replace any "%display%" in menu commands with display string */ 79005b261ecSmrg snprintf (szDisplay, 512, "127.0.0.1:%s.0", display); 79105b261ecSmrg for (i=0; i<pref.menuItems; i++) 79205b261ecSmrg { 79305b261ecSmrg for (j=0; j<pref.menu[i].menuItems; j++) 79405b261ecSmrg { 79505b261ecSmrg if (pref.menu[i].menuItem[j].cmd==CMD_EXEC) 79605b261ecSmrg { 79705b261ecSmrg srcParam = pref.menu[i].menuItem[j].param; 79805b261ecSmrg dstParam = param; 79905b261ecSmrg while (*srcParam) { 80005b261ecSmrg if (!strncmp(srcParam, "%display%", 9)) 80105b261ecSmrg { 80205b261ecSmrg memcpy (dstParam, szDisplay, strlen(szDisplay)); 80305b261ecSmrg dstParam += strlen(szDisplay); 80405b261ecSmrg srcParam += 9; 80505b261ecSmrg } 80605b261ecSmrg else 80705b261ecSmrg { 80805b261ecSmrg *dstParam = *srcParam; 80905b261ecSmrg dstParam++; 81005b261ecSmrg srcParam++; 81105b261ecSmrg } 81205b261ecSmrg } 81305b261ecSmrg *dstParam = 0; 81405b261ecSmrg strcpy (pref.menu[i].menuItem[j].param, param); 81505b261ecSmrg } /* cmd==cmd_exec */ 81605b261ecSmrg } /* for all menuitems */ 81705b261ecSmrg } /* for all menus */ 81805b261ecSmrg 81905b261ecSmrg} 8206747b715Smrg 8216747b715Smrg 8226747b715Smrg/* 8236747b715Smrg * Check for a match of the window class to one specified in the 8246747b715Smrg * STYLES{} section in the prefs file, and return the style type 8256747b715Smrg */ 8266747b715Smrgunsigned long 8276747b715SmrgwinOverrideStyle (unsigned long longpWin) 8286747b715Smrg{ 8296747b715Smrg WindowPtr pWin = (WindowPtr) longpWin; 8306747b715Smrg char *res_name, *res_class; 8316747b715Smrg int i; 8326747b715Smrg char *wmName; 8336747b715Smrg 8346747b715Smrg if (pWin==NULL) 8356747b715Smrg return STYLE_NONE; 8366747b715Smrg 8376747b715Smrg /* If we can't find the class, we can't override from default! */ 8386747b715Smrg if (!winMultiWindowGetClassHint (pWin, &res_name, &res_class)) 8396747b715Smrg return STYLE_NONE; 8406747b715Smrg 8416747b715Smrg winMultiWindowGetWMName (pWin, &wmName); 8426747b715Smrg 8436747b715Smrg for (i=0; i<pref.styleItems; i++) { 8446747b715Smrg if (!strcmp(pref.style[i].match, res_name) || 8456747b715Smrg !strcmp(pref.style[i].match, res_class) || 8466747b715Smrg (wmName && strstr(wmName, pref.style[i].match))) 8476747b715Smrg { 8486747b715Smrg free (res_name); 8496747b715Smrg free (res_class); 8506747b715Smrg free(wmName); 8516747b715Smrg 8526747b715Smrg if (pref.style[i].type) 8536747b715Smrg return pref.style[i].type; 8546747b715Smrg } 8556747b715Smrg } 8566747b715Smrg 8576747b715Smrg /* Didn't find the style, fail gracefully */ 8586747b715Smrg free (res_name); 8596747b715Smrg free (res_class); 8606747b715Smrg free(wmName); 8616747b715Smrg 8626747b715Smrg return STYLE_NONE; 8636747b715Smrg} 864