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