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