824 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			824 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining
 | |
|  * a copy of this software and associated documentation files (the
 | |
|  * "Software"), to deal in the Software without restriction, including
 | |
|  * without limitation the rights to use, copy, modify, merge, publish,
 | |
|  * distribute, sublicense, and/or sell copies of the Software, and to
 | |
|  * permit persons to whom the Software is furnished to do so, subject to
 | |
|  * the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be
 | |
|  * included in all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | |
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | |
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | |
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
 | |
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 | |
|  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | |
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
|  *
 | |
|  * Except as contained in this notice, the name of the XFree86 Project
 | |
|  * shall not be used in advertising or otherwise to promote the sale, use
 | |
|  * or other dealings in this Software without prior written authorization
 | |
|  * from the XFree86 Project.
 | |
|  *
 | |
|  * Authors:     Earle F. Philhower, III
 | |
|  */
 | |
| /* $XFree86: $ */
 | |
| 
 | |
| #ifdef HAVE_XWIN_CONFIG_H
 | |
| #include <xwin-config.h>
 | |
| #endif
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #ifdef __CYGWIN__
 | |
| #include <sys/resource.h>
 | |
| #endif
 | |
| #include "win.h"
 | |
| 
 | |
| #include <X11/Xwindows.h>
 | |
| #include <shellapi.h>
 | |
| 
 | |
| #include "winprefs.h"
 | |
| #include "winmultiwindowclass.h"
 | |
| 
 | |
| /* Where will the custom menu commands start counting from? */
 | |
| #define STARTMENUID WM_USER
 | |
| 
 | |
| /* External global variables */
 | |
| #ifdef XWIN_MULTIWINDOW
 | |
| extern DWORD g_dwCurrentThreadID;
 | |
| #endif
 | |
| 
 | |
| extern const char *winGetBaseDir(void);
 | |
| 
 | |
| /* From winmultiwindowflex.l, the real parser */
 | |
| extern void parse_file (FILE *fp);
 | |
| 
 | |
| /* From winprefyacc.y, the pref structure loaded by the parser */
 | |
| extern WINPREFS pref;
 | |
| 
 | |
| /* The global X default icon */
 | |
| extern HICON		g_hIconX;
 | |
| extern HICON		g_hSmallIconX;
 | |
| 
 | |
| /* Currently in use command ID, incremented each new menu item created */
 | |
| static int g_cmdid = STARTMENUID;
 | |
| 
 | |
| 
 | |
| /* Defined in DIX */
 | |
| extern char *display;
 | |
| 
 | |
| /* Local function to handle comma-ified icon names */
 | |
| static HICON
 | |
| LoadImageComma (char *fname, int sx, int sy, int flags);
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Creates or appends a menu from a MENUPARSED structure
 | |
|  */
 | |
| static HMENU
 | |
| MakeMenu (char *name,
 | |
| 	  HMENU editMenu,
 | |
| 	  int editItem)
 | |
| {
 | |
|   int i;
 | |
|   int item;
 | |
|   MENUPARSED *m;
 | |
|   HMENU hmenu, hsub;
 | |
| 
 | |
|   for (i=0; i<pref.menuItems; i++)
 | |
|     {
 | |
|       if (!strcmp(name, pref.menu[i].menuName))
 | |
| 	break;
 | |
|     }
 | |
|   
 | |
|   /* Didn't find a match, bummer */
 | |
|   if (i==pref.menuItems)
 | |
|     {
 | |
|       ErrorF("MakeMenu: Can't find menu %s\n", name);
 | |
|       return NULL;
 | |
|     }
 | |
|   
 | |
|   m = &(pref.menu[i]);
 | |
| 
 | |
|   if (editMenu)
 | |
|     {
 | |
|       hmenu = editMenu;
 | |
|       item = editItem;
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       hmenu = CreatePopupMenu();
 | |
|       if (!hmenu)
 | |
| 	{
 | |
| 	  ErrorF("MakeMenu: Unable to CreatePopupMenu() %s\n", name);
 | |
| 	  return NULL;
 | |
| 	}
 | |
|       item = 0;
 | |
|     }
 | |
| 
 | |
|   /* Add the menu items */
 | |
|   for (i=0; i<m->menuItems; i++)
 | |
|     {
 | |
|       /* Only assign IDs one time... */
 | |
|       if ( m->menuItem[i].commandID == 0 )
 | |
| 	m->menuItem[i].commandID = g_cmdid++;
 | |
| 
 | |
|       switch (m->menuItem[i].cmd)
 | |
| 	{
 | |
| 	case CMD_EXEC:
 | |
| 	case CMD_ALWAYSONTOP:
 | |
| 	case CMD_RELOAD:
 | |
| 	  InsertMenu (hmenu,
 | |
| 		      item,
 | |
| 		      MF_BYPOSITION|MF_ENABLED|MF_STRING,
 | |
| 		      m->menuItem[i].commandID,
 | |
| 		      m->menuItem[i].text);
 | |
| 	  break;
 | |
| 	  
 | |
| 	case CMD_SEPARATOR:
 | |
| 	  InsertMenu (hmenu,
 | |
| 		      item,
 | |
| 		      MF_BYPOSITION|MF_SEPARATOR,
 | |
| 		      0,
 | |
| 		      NULL);
 | |
| 	  break;
 | |
| 	  
 | |
| 	case CMD_MENU:
 | |
| 	  /* Recursive! */
 | |
| 	  hsub = MakeMenu (m->menuItem[i].param, 0, 0);
 | |
| 	  if (hsub)
 | |
| 	    InsertMenu (hmenu,
 | |
| 			item,
 | |
| 			MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
 | |
| 			(UINT_PTR)hsub,
 | |
| 			m->menuItem[i].text);
 | |
| 	  break;
 | |
| 	}
 | |
| 
 | |
|       /* If item==-1 (means to add at end of menu) don't increment) */
 | |
|       if (item>=0)
 | |
| 	item++;
 | |
|     }
 | |
| 
 | |
|   return hmenu;
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifdef XWIN_MULTIWINDOW
 | |
| /*
 | |
|  * Callback routine that is executed once per window class.
 | |
|  * Removes or creates custom window settings depending on LPARAM
 | |
|  */
 | |
| static wBOOL CALLBACK
 | |
| ReloadEnumWindowsProc (HWND hwnd, LPARAM lParam)
 | |
| {
 | |
|   HICON   hicon;
 | |
|   Window  wid;
 | |
| 
 | |
|   if (!hwnd) {
 | |
|     ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n");
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   /* It's our baby, either clean or dirty it */
 | |
|   if (lParam==FALSE) 
 | |
|     {
 | |
|       hicon = (HICON)GetClassLong(hwnd, GCL_HICON);
 | |
| 
 | |
|       /* Unselect any icon in the class structure */
 | |
|       SetClassLong (hwnd, GCL_HICON, (LONG)LoadIcon (NULL, IDI_APPLICATION));
 | |
| 
 | |
|       /* If it's generated on-the-fly, get rid of it, will regen */
 | |
|       winDestroyIcon (hicon);
 | |
|      
 | |
|       hicon = (HICON)GetClassLong(hwnd, GCL_HICONSM);
 | |
| 
 | |
|       /* Unselect any icon in the class structure */
 | |
|       SetClassLong (hwnd, GCL_HICONSM, 0);
 | |
| 
 | |
|       /* If it's generated on-the-fly, get rid of it, will regen */
 | |
|       winDestroyIcon (hicon);
 | |
|       
 | |
|       /* Remove any menu additions, use bRevert flag */
 | |
|       GetSystemMenu (hwnd, TRUE);
 | |
|       
 | |
|       /* This window is now clean of our taint */
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       /* Make the icon default, dynamic, or from xwinrc */
 | |
|       SetClassLong (hwnd, GCL_HICON, (LONG)g_hIconX);
 | |
|       SetClassLong (hwnd, GCL_HICONSM, (LONG)g_hSmallIconX);
 | |
|       wid = (Window)GetProp (hwnd, WIN_WID_PROP);
 | |
|       if (wid)
 | |
| 	winUpdateIcon (wid);
 | |
|       /* Update the system menu for this window */
 | |
|       SetupSysMenu ((unsigned long)hwnd);
 | |
| 
 | |
|       /* That was easy... */
 | |
|     }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Removes any custom icons in classes, custom menus, etc.
 | |
|  * Frees all members in pref structure.
 | |
|  * Reloads the preferences file.
 | |
|  * Set custom icons and menus again.
 | |
|  */
 | |
| static void
 | |
| ReloadPrefs (void)
 | |
| {
 | |
|   int i;
 | |
| 
 | |
| #ifdef XWIN_MULTIWINDOW
 | |
|   /* First, iterate over all windows replacing their icon with system */
 | |
|   /* default one and deleting any custom system menus                 */
 | |
|   EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE);
 | |
| #endif
 | |
|   
 | |
|   /* Now, free/clear all info from our prefs structure */
 | |
|   for (i=0; i<pref.menuItems; i++)
 | |
|     free (pref.menu[i].menuItem);
 | |
|   free (pref.menu);
 | |
|   pref.menu = NULL;
 | |
|   pref.menuItems = 0;
 | |
| 
 | |
|   pref.rootMenuName[0] = 0;
 | |
| 
 | |
|   free (pref.sysMenu);
 | |
|   pref.sysMenuItems = 0;
 | |
| 
 | |
|   pref.defaultSysMenuName[0] = 0;
 | |
|   pref.defaultSysMenuPos = 0;
 | |
| 
 | |
|   pref.iconDirectory[0] = 0;
 | |
|   pref.defaultIconName[0] = 0;
 | |
|   pref.trayIconName[0] = 0;
 | |
| 
 | |
|   for (i=0; i<pref.iconItems; i++)
 | |
|     if (pref.icon[i].hicon)
 | |
|       DestroyIcon ((HICON)pref.icon[i].hicon);
 | |
|   free (pref.icon);
 | |
|   pref.icon = NULL;
 | |
|   pref.iconItems = 0;
 | |
|   
 | |
|   /* Free global default X icon */
 | |
|   if (g_hIconX) 
 | |
|     DestroyIcon (g_hIconX);
 | |
|   if (g_hSmallIconX)
 | |
|     DestroyIcon (g_hSmallIconX);  
 | |
| 
 | |
|   /* Reset the custom command IDs */
 | |
|   g_cmdid = STARTMENUID;
 | |
| 
 | |
|   /* Load the updated resource file */
 | |
|   LoadPreferences();
 | |
| 
 | |
|   g_hIconX = NULL;
 | |
|   g_hSmallIconX = NULL;
 | |
| 
 | |
| #ifdef XWIN_MULTIWINDOW
 | |
|   winInitGlobalIcons();
 | |
| #endif
 | |
|   
 | |
| #ifdef XWIN_MULTIWINDOW
 | |
|   /* Rebuild the icons and menus */
 | |
|   EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, TRUE);
 | |
| #endif
 | |
| 
 | |
|   /* Whew, done */
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check/uncheck the ALWAYSONTOP items in this menu
 | |
|  */
 | |
| void
 | |
| HandleCustomWM_INITMENU(unsigned long hwndIn,
 | |
| 			unsigned long hmenuIn)
 | |
| {
 | |
|   HWND    hwnd;
 | |
|   HMENU   hmenu;
 | |
|   DWORD   dwExStyle;
 | |
|   int     i, j;
 | |
| 
 | |
|   hwnd = (HWND)hwndIn;
 | |
|   hmenu = (HMENU)hmenuIn;
 | |
|   if (!hwnd || !hmenu) 
 | |
|     return;
 | |
|   
 | |
|   if (GetWindowLong (hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
 | |
|     dwExStyle = MF_BYCOMMAND | MF_CHECKED;
 | |
|   else
 | |
|     dwExStyle = MF_BYCOMMAND | MF_UNCHECKED;
 | |
| 
 | |
|   for (i=0; i<pref.menuItems; i++)
 | |
|     for (j=0; j<pref.menu[i].menuItems; j++)
 | |
|       if (pref.menu[i].menuItem[j].cmd==CMD_ALWAYSONTOP)
 | |
| 	CheckMenuItem (hmenu, pref.menu[i].menuItem[j].commandID, dwExStyle );
 | |
|   
 | |
| }
 | |
|     
 | |
| /*
 | |
|  * Searches for the custom WM_COMMAND command ID and performs action.
 | |
|  * Return TRUE if command is proccessed, FALSE otherwise.
 | |
|  */
 | |
| Bool
 | |
| HandleCustomWM_COMMAND (unsigned long hwndIn,
 | |
| 			int           command)
 | |
| {
 | |
|   HWND hwnd;
 | |
|   int i, j;
 | |
|   MENUPARSED *m;
 | |
|   DWORD			dwExStyle;
 | |
| 
 | |
|   hwnd = (HWND)hwndIn;
 | |
| 
 | |
|   if (!command)
 | |
|     return FALSE;
 | |
| 
 | |
|   for (i=0; i<pref.menuItems; i++)
 | |
|     {
 | |
|       m = &(pref.menu[i]);
 | |
|       for (j=0; j<m->menuItems; j++)
 | |
| 	{
 | |
| 	  if (command==m->menuItem[j].commandID)
 | |
| 	    {
 | |
| 	      /* Match! */
 | |
| 	      switch(m->menuItem[j].cmd)
 | |
| 		{
 | |
| #ifdef __CYGWIN__
 | |
| 		case CMD_EXEC:
 | |
| 		  if (fork()==0)
 | |
| 		    {
 | |
| 		      struct rlimit rl;
 | |
| 		      unsigned long i;
 | |
| 
 | |
| 		      /* Close any open descriptors except for STD* */
 | |
| 		      getrlimit (RLIMIT_NOFILE, &rl);
 | |
| 		      for (i = STDERR_FILENO+1; i < rl.rlim_cur; i++)
 | |
| 			close(i);
 | |
| 
 | |
| 		      /* Disassociate any TTYs */
 | |
| 		      setsid();
 | |
| 
 | |
| 		      execl ("/bin/sh",
 | |
| 			     "/bin/sh",
 | |
| 			     "-c",
 | |
| 			     m->menuItem[j].param,
 | |
| 			     NULL);
 | |
| 		      exit (0);
 | |
| 		    }
 | |
| 		  else
 | |
| 		    return TRUE;
 | |
| 		  break;
 | |
| #else
 | |
| 		case CMD_EXEC:
 | |
|                   {
 | |
| 		    /* Start process without console window */
 | |
| 		    STARTUPINFO start;
 | |
| 		    PROCESS_INFORMATION child;
 | |
| 
 | |
| 		    memset (&start, 0, sizeof (start));
 | |
| 		    start.cb = sizeof (start);
 | |
| 		    start.dwFlags = STARTF_USESHOWWINDOW;
 | |
| 		    start.wShowWindow = SW_HIDE;
 | |
| 
 | |
| 		    memset (&child, 0, sizeof (child));
 | |
| 
 | |
| 		    if (CreateProcess (NULL, m->menuItem[j].param, NULL, NULL, FALSE, 0,
 | |
| 				       NULL, NULL, &start, &child))
 | |
| 		    {
 | |
| 			CloseHandle (child.hThread);
 | |
| 			CloseHandle (child.hProcess);
 | |
| 		    }
 | |
| 		    else
 | |
| 			MessageBox(NULL, m->menuItem[j].param, "Mingrc Exec Command Error!", MB_OK | MB_ICONEXCLAMATION);
 | |
|                   }
 | |
| 		  return TRUE;
 | |
| #endif
 | |
| 		case CMD_ALWAYSONTOP:
 | |
| 		  if (!hwnd)
 | |
| 		    return FALSE;
 | |
| 
 | |
| 		  /* Get extended window style */
 | |
| 		  dwExStyle = GetWindowLong (hwnd, GWL_EXSTYLE);
 | |
| 		  
 | |
| 		  /* Handle topmost windows */
 | |
| 		  if (dwExStyle & WS_EX_TOPMOST)
 | |
| 		    SetWindowPos (hwnd,
 | |
| 				  HWND_NOTOPMOST,
 | |
| 				  0, 0,
 | |
| 				  0, 0,
 | |
| 				  SWP_NOSIZE | SWP_NOMOVE);
 | |
| 		  else
 | |
| 		    SetWindowPos (hwnd,
 | |
| 				  HWND_TOPMOST,
 | |
| 				  0, 0,
 | |
| 				  0, 0,
 | |
| 				  SWP_NOSIZE | SWP_NOMOVE);
 | |
| #if XWIN_MULTIWINDOW
 | |
| 		  /* Reflect the changed Z order */
 | |
| 		  winReorderWindowsMultiWindow ();
 | |
| #endif
 | |
| 		  return TRUE;
 | |
| 		  
 | |
| 		case CMD_RELOAD:
 | |
| 		  ReloadPrefs();
 | |
| 		  return TRUE;
 | |
| 
 | |
| 		default:
 | |
| 		  return FALSE;
 | |
| 	      }
 | |
| 	    } /* match */
 | |
| 	} /* for j */
 | |
|     } /* for i */
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifdef XWIN_MULTIWINDOW
 | |
| /*
 | |
|  * Add the default or a custom menu depending on the class match
 | |
|  */
 | |
| void
 | |
| SetupSysMenu (unsigned long hwndIn)
 | |
| {
 | |
|   HWND    hwnd;
 | |
|   HMENU	  sys;
 | |
|   int     i;
 | |
|   WindowPtr pWin;
 | |
|   char *res_name, *res_class;
 | |
| 
 | |
|   hwnd = (HWND)hwndIn;
 | |
|   if (!hwnd)
 | |
|     return;
 | |
| 
 | |
|   pWin = GetProp (hwnd, WIN_WINDOW_PROP);
 | |
|   
 | |
|   sys = GetSystemMenu (hwnd, FALSE);
 | |
|   if (!sys)
 | |
|     return;
 | |
| 
 | |
|   if (pWin)
 | |
|     {
 | |
|       /* First see if there's a class match... */
 | |
|       if (winMultiWindowGetClassHint (pWin, &res_name, &res_class))
 | |
| 	{
 | |
| 	  for (i=0; i<pref.sysMenuItems; i++)
 | |
| 	    {
 | |
| 	      if (!strcmp(pref.sysMenu[i].match, res_name) ||
 | |
| 		  !strcmp(pref.sysMenu[i].match, res_class) ) 
 | |
| 		{
 | |
| 		  free(res_name);
 | |
| 		  free(res_class);
 | |
|   
 | |
| 		  MakeMenu (pref.sysMenu[i].menuName, sys,
 | |
| 			    pref.sysMenu[i].menuPos==AT_START?0:-1);
 | |
| 		  return;
 | |
| 		}
 | |
| 	    }
 | |
| 	  
 | |
| 	  /* No match, just free alloc'd strings */
 | |
| 	  free(res_name);
 | |
| 	  free(res_class);
 | |
| 	} /* Found wm_class */
 | |
|     } /* if pwin */
 | |
| 
 | |
|   /* Fallback to system default */
 | |
|   if (pref.defaultSysMenuName[0])
 | |
|     {
 | |
|       if (pref.defaultSysMenuPos==AT_START)
 | |
| 	MakeMenu (pref.defaultSysMenuName, sys, 0);
 | |
|       else
 | |
| 	MakeMenu (pref.defaultSysMenuName, sys, -1);
 | |
|     }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Possibly add a menu to the toolbar icon
 | |
|  */
 | |
| void
 | |
| SetupRootMenu (unsigned long hmenuRoot)
 | |
| {
 | |
|   HMENU root;
 | |
| 
 | |
|   root = (HMENU)hmenuRoot;
 | |
|   if (!root)
 | |
|     return;
 | |
| 
 | |
|   if (pref.rootMenuName[0])
 | |
|     {
 | |
|       MakeMenu(pref.rootMenuName, root, 0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Check for and return an overridden default ICON specified in the prefs
 | |
|  */
 | |
| unsigned long
 | |
| winOverrideDefaultIcon(int size)
 | |
| {
 | |
|   HICON hicon;
 | |
|   
 | |
|   if (pref.defaultIconName[0])
 | |
|     {
 | |
|       hicon = LoadImageComma (pref.defaultIconName, size, size, 0);
 | |
|       if (hicon==NULL)
 | |
|         ErrorF ("winOverrideDefaultIcon: LoadImageComma(%s) failed\n",
 | |
| 		pref.defaultIconName);
 | |
| 
 | |
|       return (unsigned long)hicon;
 | |
|     }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Return the HICON to use in the taskbar notification area
 | |
|  */
 | |
| unsigned long
 | |
| winTaskbarIcon(void)
 | |
| {
 | |
|   HICON hicon;
 | |
| 
 | |
|   hicon = 0;
 | |
|   /* First try and load an overridden, if success then return it */
 | |
|   if (pref.trayIconName[0])
 | |
|     {
 | |
|       hicon = LoadImageComma (pref.trayIconName,
 | |
| 			      GetSystemMetrics (SM_CXSMICON),
 | |
| 			      GetSystemMetrics (SM_CYSMICON),
 | |
| 			      0 );
 | |
|     }
 | |
| 
 | |
|   /* Otherwise return the default */
 | |
|   if (!hicon)
 | |
|     hicon =  (HICON) LoadImage (g_hInstance,
 | |
| 				MAKEINTRESOURCE(IDI_XWIN),
 | |
| 				IMAGE_ICON,
 | |
| 				GetSystemMetrics (SM_CXSMICON),
 | |
| 				GetSystemMetrics (SM_CYSMICON),
 | |
| 				0);
 | |
| 
 | |
|   return (unsigned long)hicon;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Parse a filename to extract an icon:
 | |
|  *  If fname is exactly ",nnn" then extract icon from our resource
 | |
|  *  else if it is "file,nnn" then extract icon nnn from that file
 | |
|  *  else try to load it as an .ico file and if that fails return NULL
 | |
|  */
 | |
| static HICON
 | |
| LoadImageComma (char *fname, int sx, int sy, int flags)
 | |
| {
 | |
|   HICON  hicon;
 | |
|   int    index;
 | |
|   char   file[PATH_MAX+NAME_MAX+2];
 | |
| 
 | |
|   /* Some input error checking */
 | |
|   if (!fname || !fname[0])
 | |
|     return NULL;
 | |
| 
 | |
|   index = 0;
 | |
|   hicon = NULL;
 | |
| 
 | |
|   if (fname[0]==',')
 | |
|     {
 | |
|       /* It's the XWIN.EXE resource they want */
 | |
|       index = atoi (fname+1);
 | |
|       hicon = LoadImage (g_hInstance,
 | |
|                         MAKEINTRESOURCE(index),
 | |
|                         IMAGE_ICON,
 | |
|                         sx,
 | |
|                         sy,
 | |
|                         flags);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       file[0] = 0;
 | |
|       /* Prepend path if not given a "X:\" filename */
 | |
|       if ( !(fname[0] && fname[1]==':' && fname[2]=='\\') )
 | |
|         {
 | |
|          strcpy (file, pref.iconDirectory);
 | |
|          if (pref.iconDirectory[0])
 | |
|            if (fname[strlen(fname)-1]!='\\')
 | |
|              strcat (file, "\\");
 | |
|         }
 | |
|       strcat (file, fname);
 | |
| 
 | |
|       if (strrchr (file, ','))
 | |
|        {
 | |
|          /* Specified as <fname>,<index> */
 | |
| 
 | |
|          *(strrchr (file, ',')) = 0; /* End string at comma */
 | |
|          index = atoi (strrchr (fname, ',') + 1);
 | |
|          hicon = ExtractIcon (g_hInstance, file, index);
 | |
|        }
 | |
|       else
 | |
|        {
 | |
|          /* Just an .ico file... */
 | |
| 
 | |
|          hicon = (HICON)LoadImage (NULL,
 | |
|                                    file,
 | |
|                                    IMAGE_ICON,
 | |
|                                    sx,
 | |
|                                    sy,
 | |
|                                    LR_LOADFROMFILE|flags);
 | |
|        }
 | |
|     }
 | |
|   return hicon;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check for a match of the window class to one specified in the
 | |
|  * ICONS{} section in the prefs file, and load the icon from a file
 | |
|  */
 | |
| unsigned long
 | |
| winOverrideIcon (unsigned long longWin)
 | |
| {
 | |
|   WindowPtr pWin = (WindowPtr) longWin;
 | |
|   char *res_name, *res_class;
 | |
|   int i;
 | |
|   HICON hicon;
 | |
|   char *wmName;
 | |
| 
 | |
|   if (pWin==NULL)
 | |
|     return 0;
 | |
| 
 | |
|   /* If we can't find the class, we can't override from default! */
 | |
|   if (!winMultiWindowGetClassHint (pWin, &res_name, &res_class))
 | |
|     return 0;
 | |
| 
 | |
|   winMultiWindowGetWMName (pWin, &wmName);
 | |
|   
 | |
|   for (i=0; i<pref.iconItems; i++) {
 | |
|     if (!strcmp(pref.icon[i].match, res_name) ||
 | |
| 	!strcmp(pref.icon[i].match, res_class) ||
 | |
| 	(wmName && strstr(wmName, pref.icon[i].match))) 
 | |
|       {
 | |
| 	free (res_name);
 | |
| 	free (res_class);
 | |
| 	if (wmName)
 | |
| 	  free (wmName);
 | |
| 
 | |
| 	if (pref.icon[i].hicon)
 | |
| 	  return pref.icon[i].hicon;
 | |
| 
 | |
|        hicon = LoadImageComma (pref.icon[i].iconFile, 0, 0, LR_DEFAULTSIZE);
 | |
|        if (hicon==NULL)
 | |
|          ErrorF ("winOverrideIcon: LoadImageComma(%s) failed\n",
 | |
|                   pref.icon[i].iconFile);
 | |
| 
 | |
| 	pref.icon[i].hicon = (unsigned long)hicon;
 | |
| 	return (unsigned long)hicon;
 | |
|       }
 | |
|   }
 | |
|   
 | |
|   /* Didn't find the icon, fail gracefully */
 | |
|   free (res_name);
 | |
|   free (res_class);
 | |
|   if (wmName)
 | |
|     free (wmName);
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Should we free this icon or leave it in memory (is it part of our
 | |
|  * ICONS{} overrides)?
 | |
|  */
 | |
| int
 | |
| winIconIsOverride(unsigned hiconIn)
 | |
| {
 | |
|   HICON hicon;
 | |
|   int i;
 | |
| 
 | |
|   hicon = (HICON)hiconIn;
 | |
| 
 | |
|   if (!hicon)
 | |
|     return 0;
 | |
|   
 | |
|   for (i=0; i<pref.iconItems; i++)
 | |
|     if ((HICON)pref.icon[i].hicon == hicon)
 | |
|       return 1;
 | |
|   
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Try and open ~/.XWinrc and /usr/X11R6/lib/X11/system.XWinrc
 | |
|  * Load it into prefs structure for use by other functions
 | |
|  */
 | |
| void
 | |
| LoadPreferences ()
 | |
| {
 | |
|   char *home;
 | |
|   char fname[PATH_MAX+NAME_MAX+2];
 | |
|   FILE *prefFile;
 | |
|   char szDisplay[512];
 | |
|   char *szEnvDisplay;
 | |
|   int i, j;
 | |
|   char param[PARAM_MAX+1];
 | |
|   char *srcParam, *dstParam;
 | |
| 
 | |
|   /* First, clear all preference settings */
 | |
|   memset (&pref, 0, sizeof(pref));
 | |
|   prefFile = NULL;
 | |
| 
 | |
|   /* Now try and find a ~/.xwinrc file */
 | |
|   home = getenv ("HOME");
 | |
|   if (home)
 | |
|     {
 | |
|       strcpy (fname, home);
 | |
|       if (fname[strlen(fname)-1]!='/')
 | |
| 	strcat (fname, "/");
 | |
|       strcat (fname, ".XWinrc");
 | |
|       
 | |
|       prefFile = fopen (fname, "r");
 | |
|       if (prefFile)
 | |
| 	ErrorF ("winPrefsLoadPreferences: %s\n", fname);
 | |
|     }
 | |
| 
 | |
|   /* No home file found, check system default */
 | |
|   if (!prefFile)
 | |
|     {
 | |
|       char buffer[MAX_PATH];
 | |
| #ifdef RELOCATE_PROJECTROOT
 | |
|       snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir());
 | |
| #else
 | |
|       strncpy(buffer, PROJECTROOT"/lib/X11/system.XWinrc", sizeof(buffer));
 | |
| #endif
 | |
|       buffer[sizeof(buffer)-1] = 0;
 | |
|       prefFile = fopen (buffer, "r");
 | |
|       if (prefFile)
 | |
| 	ErrorF ("winPrefsLoadPreferences: %s\n", buffer);
 | |
|     }
 | |
| 
 | |
|   /* If we could open it, then read the settings and close it */
 | |
|   if (prefFile)
 | |
|     {
 | |
|       parse_file (prefFile);
 | |
|       fclose (prefFile);
 | |
|     }
 | |
| 
 | |
|   /* Setup a DISPLAY environment variable, need to allocate on heap */
 | |
|   /* because putenv doesn't copy the argument... */
 | |
|   snprintf (szDisplay, 512, "DISPLAY=127.0.0.1:%s.0", display);
 | |
|   szEnvDisplay = (char *)(malloc (strlen(szDisplay)+1));
 | |
|   if (szEnvDisplay)
 | |
|     {
 | |
|       strcpy (szEnvDisplay, szDisplay);
 | |
|       putenv (szEnvDisplay);
 | |
|     }
 | |
| 
 | |
|   /* Replace any "%display%" in menu commands with display string */
 | |
|   snprintf (szDisplay, 512, "127.0.0.1:%s.0", display);
 | |
|   for (i=0; i<pref.menuItems; i++)
 | |
|     {
 | |
|       for (j=0; j<pref.menu[i].menuItems; j++)
 | |
| 	{
 | |
| 	  if (pref.menu[i].menuItem[j].cmd==CMD_EXEC)
 | |
| 	    {
 | |
| 	      srcParam = pref.menu[i].menuItem[j].param;
 | |
| 	      dstParam = param;
 | |
| 	      while (*srcParam) {
 | |
| 		if (!strncmp(srcParam, "%display%", 9))
 | |
| 		  {
 | |
| 		    memcpy (dstParam, szDisplay, strlen(szDisplay));
 | |
| 		    dstParam += strlen(szDisplay);
 | |
| 		    srcParam += 9;
 | |
| 		  }
 | |
| 		else
 | |
| 		  {
 | |
| 		    *dstParam = *srcParam;
 | |
| 		    dstParam++;
 | |
| 		    srcParam++;
 | |
| 		  }
 | |
| 	      }
 | |
| 	      *dstParam = 0;
 | |
| 	      strcpy (pref.menu[i].menuItem[j].param, param);
 | |
| 	    } /* cmd==cmd_exec */
 | |
| 	} /* for all menuitems */
 | |
|     } /* for all menus */
 | |
| 
 | |
| }
 |