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