1706f2543Smrg/*
2706f2543Smrg * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3706f2543Smrg * Copyright (C) Colin Harrison 2005-2008
4706f2543Smrg *
5706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining
6706f2543Smrg * a copy of this software and associated documentation files (the
7706f2543Smrg * "Software"), to deal in the Software without restriction, including
8706f2543Smrg * without limitation the rights to use, copy, modify, merge, publish,
9706f2543Smrg * distribute, sublicense, and/or sell copies of the Software, and to
10706f2543Smrg * permit persons to whom the Software is furnished to do so, subject to
11706f2543Smrg * the following conditions:
12706f2543Smrg *
13706f2543Smrg * The above copyright notice and this permission notice shall be
14706f2543Smrg * included in all copies or substantial portions of the Software.
15706f2543Smrg *
16706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19706f2543Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
20706f2543Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21706f2543Smrg * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22706f2543Smrg * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23706f2543Smrg *
24706f2543Smrg * Except as contained in this notice, the name of the XFree86 Project
25706f2543Smrg * shall not be used in advertising or otherwise to promote the sale, use
26706f2543Smrg * or other dealings in this Software without prior written authorization
27706f2543Smrg * from the XFree86 Project.
28706f2543Smrg *
29706f2543Smrg * Authors:     Earle F. Philhower, III
30706f2543Smrg *              Colin Harrison
31706f2543Smrg */
32706f2543Smrg
33706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
34706f2543Smrg#include <xwin-config.h>
35706f2543Smrg#endif
36706f2543Smrg#include <stdio.h>
37706f2543Smrg#include <stdlib.h>
38706f2543Smrg#ifdef __CYGWIN__
39706f2543Smrg#include <sys/resource.h>
40706f2543Smrg#endif
41706f2543Smrg#include "win.h"
42706f2543Smrg
43706f2543Smrg#include <X11/Xwindows.h>
44706f2543Smrg#include <shellapi.h>
45706f2543Smrg
46706f2543Smrg#include "winprefs.h"
47706f2543Smrg#include "winmultiwindowclass.h"
48706f2543Smrg
49706f2543Smrg/* Where will the custom menu commands start counting from? */
50706f2543Smrg#define STARTMENUID WM_USER
51706f2543Smrg
52706f2543Smrgextern const char *winGetBaseDir(void);
53706f2543Smrg
54706f2543Smrg/* From winmultiwindowflex.l, the real parser */
55706f2543Smrgextern void parse_file (FILE *fp);
56706f2543Smrg
57706f2543Smrg
58706f2543Smrg/* Currently in use command ID, incremented each new menu item created */
59706f2543Smrgstatic int g_cmdid = STARTMENUID;
60706f2543Smrg
61706f2543Smrg
62706f2543Smrg/* Defined in DIX */
63706f2543Smrgextern char *display;
64706f2543Smrg
65706f2543Smrg/* Local function to handle comma-ified icon names */
66706f2543Smrgstatic HICON
67706f2543SmrgLoadImageComma (char *fname, int sx, int sy, int flags);
68706f2543Smrg
69706f2543Smrg
70706f2543Smrg/*
71706f2543Smrg * Creates or appends a menu from a MENUPARSED structure
72706f2543Smrg */
73706f2543Smrgstatic HMENU
74706f2543SmrgMakeMenu (char *name,
75706f2543Smrg	  HMENU editMenu,
76706f2543Smrg	  int editItem)
77706f2543Smrg{
78706f2543Smrg  int i;
79706f2543Smrg  int item;
80706f2543Smrg  MENUPARSED *m;
81706f2543Smrg  HMENU hmenu, hsub;
82706f2543Smrg
83706f2543Smrg  for (i=0; i<pref.menuItems; i++)
84706f2543Smrg    {
85706f2543Smrg      if (!strcmp(name, pref.menu[i].menuName))
86706f2543Smrg	break;
87706f2543Smrg    }
88706f2543Smrg
89706f2543Smrg  /* Didn't find a match, bummer */
90706f2543Smrg  if (i==pref.menuItems)
91706f2543Smrg    {
92706f2543Smrg      ErrorF("MakeMenu: Can't find menu %s\n", name);
93706f2543Smrg      return NULL;
94706f2543Smrg    }
95706f2543Smrg
96706f2543Smrg  m = &(pref.menu[i]);
97706f2543Smrg
98706f2543Smrg  if (editMenu)
99706f2543Smrg    {
100706f2543Smrg      hmenu = editMenu;
101706f2543Smrg      item = editItem;
102706f2543Smrg    }
103706f2543Smrg  else
104706f2543Smrg    {
105706f2543Smrg      hmenu = CreatePopupMenu();
106706f2543Smrg      if (!hmenu)
107706f2543Smrg	{
108706f2543Smrg	  ErrorF("MakeMenu: Unable to CreatePopupMenu() %s\n", name);
109706f2543Smrg	  return NULL;
110706f2543Smrg	}
111706f2543Smrg      item = 0;
112706f2543Smrg    }
113706f2543Smrg
114706f2543Smrg  /* Add the menu items */
115706f2543Smrg  for (i=0; i<m->menuItems; i++)
116706f2543Smrg    {
117706f2543Smrg      /* Only assign IDs one time... */
118706f2543Smrg      if ( m->menuItem[i].commandID == 0 )
119706f2543Smrg	m->menuItem[i].commandID = g_cmdid++;
120706f2543Smrg
121706f2543Smrg      switch (m->menuItem[i].cmd)
122706f2543Smrg	{
123706f2543Smrg	case CMD_EXEC:
124706f2543Smrg	case CMD_ALWAYSONTOP:
125706f2543Smrg	case CMD_RELOAD:
126706f2543Smrg	  InsertMenu (hmenu,
127706f2543Smrg		      item,
128706f2543Smrg		      MF_BYPOSITION|MF_ENABLED|MF_STRING,
129706f2543Smrg		      m->menuItem[i].commandID,
130706f2543Smrg		      m->menuItem[i].text);
131706f2543Smrg	  break;
132706f2543Smrg
133706f2543Smrg	case CMD_SEPARATOR:
134706f2543Smrg	  InsertMenu (hmenu,
135706f2543Smrg		      item,
136706f2543Smrg		      MF_BYPOSITION|MF_SEPARATOR,
137706f2543Smrg		      0,
138706f2543Smrg		      NULL);
139706f2543Smrg	  break;
140706f2543Smrg
141706f2543Smrg	case CMD_MENU:
142706f2543Smrg	  /* Recursive! */
143706f2543Smrg	  hsub = MakeMenu (m->menuItem[i].param, 0, 0);
144706f2543Smrg	  if (hsub)
145706f2543Smrg	    InsertMenu (hmenu,
146706f2543Smrg			item,
147706f2543Smrg			MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
148706f2543Smrg			(UINT_PTR)hsub,
149706f2543Smrg			m->menuItem[i].text);
150706f2543Smrg	  break;
151706f2543Smrg	}
152706f2543Smrg
153706f2543Smrg      /* If item==-1 (means to add at end of menu) don't increment) */
154706f2543Smrg      if (item>=0)
155706f2543Smrg	item++;
156706f2543Smrg    }
157706f2543Smrg
158706f2543Smrg  return hmenu;
159706f2543Smrg}
160706f2543Smrg
161706f2543Smrg
162706f2543Smrg#ifdef XWIN_MULTIWINDOW
163706f2543Smrg/*
164706f2543Smrg * Callback routine that is executed once per window class.
165706f2543Smrg * Removes or creates custom window settings depending on LPARAM
166706f2543Smrg */
167706f2543Smrgstatic wBOOL CALLBACK
168706f2543SmrgReloadEnumWindowsProc (HWND hwnd, LPARAM lParam)
169706f2543Smrg{
170706f2543Smrg  HICON   hicon;
171706f2543Smrg  Window  wid;
172706f2543Smrg
173706f2543Smrg  if (!hwnd) {
174706f2543Smrg    ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n");
175706f2543Smrg    return FALSE;
176706f2543Smrg  }
177706f2543Smrg
178706f2543Smrg  /* It's our baby, either clean or dirty it */
179706f2543Smrg  if (lParam==FALSE)
180706f2543Smrg    {
181706f2543Smrg      /* Reset the window's icon to undefined. */
182706f2543Smrg      hicon = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, 0);
183706f2543Smrg
184706f2543Smrg      /* If the old icon is generated on-the-fly, get rid of it, will regen */
185706f2543Smrg      winDestroyIcon (hicon);
186706f2543Smrg
187706f2543Smrg      /* Same for the small icon */
188706f2543Smrg      hicon = (HICON)SendMessage(hwnd, WM_SETICON, ICON_SMALL, 0);
189706f2543Smrg      winDestroyIcon (hicon);
190706f2543Smrg
191706f2543Smrg      /* Remove any menu additions; bRevert=TRUE destroys any modified menus */
192706f2543Smrg      GetSystemMenu (hwnd, TRUE);
193706f2543Smrg
194706f2543Smrg      /* This window is now clean of our taint (but with undefined icons) */
195706f2543Smrg    }
196706f2543Smrg  else
197706f2543Smrg    {
198706f2543Smrg      /* winUpdateIcon() will set the icon default, dynamic, or from xwinrc */
199706f2543Smrg      wid = (Window)GetProp (hwnd, WIN_WID_PROP);
200706f2543Smrg      if (wid)
201706f2543Smrg	winUpdateIcon (wid);
202706f2543Smrg
203706f2543Smrg      /* Update the system menu for this window */
204706f2543Smrg      SetupSysMenu ((unsigned long)hwnd);
205706f2543Smrg
206706f2543Smrg      /* That was easy... */
207706f2543Smrg    }
208706f2543Smrg
209706f2543Smrg  return TRUE;
210706f2543Smrg}
211706f2543Smrg#endif
212706f2543Smrg
213706f2543Smrg
214706f2543Smrg/*
215706f2543Smrg * Removes any custom icons in classes, custom menus, etc.
216706f2543Smrg * Frees all members in pref structure.
217706f2543Smrg * Reloads the preferences file.
218706f2543Smrg * Set custom icons and menus again.
219706f2543Smrg */
220706f2543Smrgstatic void
221706f2543SmrgReloadPrefs (void)
222706f2543Smrg{
223706f2543Smrg  int i;
224706f2543Smrg
225706f2543Smrg#ifdef XWIN_MULTIWINDOW
226706f2543Smrg  /* First, iterate over all windows, deleting their icons and custom menus.
227706f2543Smrg   * This is really only needed because winDestroyIcon() will try to
228706f2543Smrg   * destroy the old global icons, which will have changed.
229706f2543Smrg   * It is probably better to set a windows USER_DATA to flag locally defined
230706f2543Smrg   * icons, and use that to accurately know when to destroy old icons.
231706f2543Smrg   */
232706f2543Smrg  EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE);
233706f2543Smrg#endif
234706f2543Smrg
235706f2543Smrg  /* Now, free/clear all info from our prefs structure */
236706f2543Smrg  for (i=0; i<pref.menuItems; i++)
237706f2543Smrg    free (pref.menu[i].menuItem);
238706f2543Smrg  free (pref.menu);
239706f2543Smrg  pref.menu = NULL;
240706f2543Smrg  pref.menuItems = 0;
241706f2543Smrg
242706f2543Smrg  pref.rootMenuName[0] = 0;
243706f2543Smrg
244706f2543Smrg  free (pref.sysMenu);
245706f2543Smrg  pref.sysMenuItems = 0;
246706f2543Smrg
247706f2543Smrg  pref.defaultSysMenuName[0] = 0;
248706f2543Smrg  pref.defaultSysMenuPos = 0;
249706f2543Smrg
250706f2543Smrg  pref.iconDirectory[0] = 0;
251706f2543Smrg  pref.defaultIconName[0] = 0;
252706f2543Smrg  pref.trayIconName[0] = 0;
253706f2543Smrg
254706f2543Smrg  for (i=0; i<pref.iconItems; i++)
255706f2543Smrg    if (pref.icon[i].hicon)
256706f2543Smrg      DestroyIcon ((HICON)pref.icon[i].hicon);
257706f2543Smrg  free (pref.icon);
258706f2543Smrg  pref.icon = NULL;
259706f2543Smrg  pref.iconItems = 0;
260706f2543Smrg
261706f2543Smrg  /* Free global default X icon */
262706f2543Smrg  if (g_hIconX)
263706f2543Smrg    DestroyIcon (g_hIconX);
264706f2543Smrg  if (g_hSmallIconX)
265706f2543Smrg    DestroyIcon (g_hSmallIconX);
266706f2543Smrg
267706f2543Smrg  /* Reset the custom command IDs */
268706f2543Smrg  g_cmdid = STARTMENUID;
269706f2543Smrg
270706f2543Smrg  /* Load the updated resource file */
271706f2543Smrg  LoadPreferences();
272706f2543Smrg
273706f2543Smrg  g_hIconX = NULL;
274706f2543Smrg  g_hSmallIconX = NULL;
275706f2543Smrg
276706f2543Smrg#ifdef XWIN_MULTIWINDOW
277706f2543Smrg  winInitGlobalIcons();
278706f2543Smrg#endif
279706f2543Smrg
280706f2543Smrg#ifdef XWIN_MULTIWINDOW
281706f2543Smrg  /* Rebuild the icons and menus */
282706f2543Smrg  EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, TRUE);
283706f2543Smrg#endif
284706f2543Smrg
285706f2543Smrg  /* Whew, done */
286706f2543Smrg}
287706f2543Smrg
288706f2543Smrg/*
289706f2543Smrg * Check/uncheck the ALWAYSONTOP items in this menu
290706f2543Smrg */
291706f2543Smrgvoid
292706f2543SmrgHandleCustomWM_INITMENU(unsigned long hwndIn,
293706f2543Smrg			unsigned long hmenuIn)
294706f2543Smrg{
295706f2543Smrg  HWND    hwnd;
296706f2543Smrg  HMENU   hmenu;
297706f2543Smrg  DWORD   dwExStyle;
298706f2543Smrg  int     i, j;
299706f2543Smrg
300706f2543Smrg  hwnd = (HWND)hwndIn;
301706f2543Smrg  hmenu = (HMENU)hmenuIn;
302706f2543Smrg  if (!hwnd || !hmenu)
303706f2543Smrg    return;
304706f2543Smrg
305706f2543Smrg  if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
306706f2543Smrg    dwExStyle = MF_BYCOMMAND | MF_CHECKED;
307706f2543Smrg  else
308706f2543Smrg    dwExStyle = MF_BYCOMMAND | MF_UNCHECKED;
309706f2543Smrg
310706f2543Smrg  for (i=0; i<pref.menuItems; i++)
311706f2543Smrg    for (j=0; j<pref.menu[i].menuItems; j++)
312706f2543Smrg      if (pref.menu[i].menuItem[j].cmd==CMD_ALWAYSONTOP)
313706f2543Smrg	CheckMenuItem (hmenu, pref.menu[i].menuItem[j].commandID, dwExStyle );
314706f2543Smrg
315706f2543Smrg}
316706f2543Smrg
317706f2543Smrg/*
318706f2543Smrg * Searches for the custom WM_COMMAND command ID and performs action.
319706f2543Smrg * Return TRUE if command is proccessed, FALSE otherwise.
320706f2543Smrg */
321706f2543SmrgBool
322706f2543SmrgHandleCustomWM_COMMAND (unsigned long hwndIn,
323706f2543Smrg			int           command)
324706f2543Smrg{
325706f2543Smrg  HWND hwnd;
326706f2543Smrg  int i, j;
327706f2543Smrg  MENUPARSED *m;
328706f2543Smrg  DWORD			dwExStyle;
329706f2543Smrg
330706f2543Smrg  hwnd = (HWND)hwndIn;
331706f2543Smrg
332706f2543Smrg  if (!command)
333706f2543Smrg    return FALSE;
334706f2543Smrg
335706f2543Smrg  for (i=0; i<pref.menuItems; i++)
336706f2543Smrg    {
337706f2543Smrg      m = &(pref.menu[i]);
338706f2543Smrg      for (j=0; j<m->menuItems; j++)
339706f2543Smrg	{
340706f2543Smrg	  if (command==m->menuItem[j].commandID)
341706f2543Smrg	    {
342706f2543Smrg	      /* Match! */
343706f2543Smrg	      switch(m->menuItem[j].cmd)
344706f2543Smrg		{
345706f2543Smrg#ifdef __CYGWIN__
346706f2543Smrg		case CMD_EXEC:
347706f2543Smrg		  if (fork()==0)
348706f2543Smrg		    {
349706f2543Smrg		      struct rlimit rl;
350706f2543Smrg		      unsigned long i;
351706f2543Smrg
352706f2543Smrg		      /* Close any open descriptors except for STD* */
353706f2543Smrg		      getrlimit (RLIMIT_NOFILE, &rl);
354706f2543Smrg		      for (i = STDERR_FILENO+1; i < rl.rlim_cur; i++)
355706f2543Smrg			close(i);
356706f2543Smrg
357706f2543Smrg		      /* Disassociate any TTYs */
358706f2543Smrg		      setsid();
359706f2543Smrg
360706f2543Smrg		      execl ("/bin/sh",
361706f2543Smrg			     "/bin/sh",
362706f2543Smrg			     "-c",
363706f2543Smrg			     m->menuItem[j].param,
364706f2543Smrg			     NULL);
365706f2543Smrg		      exit (0);
366706f2543Smrg		    }
367706f2543Smrg		  else
368706f2543Smrg		    return TRUE;
369706f2543Smrg		  break;
370706f2543Smrg#else
371706f2543Smrg		case CMD_EXEC:
372706f2543Smrg                  {
373706f2543Smrg		    /* Start process without console window */
374706f2543Smrg		    STARTUPINFO start;
375706f2543Smrg		    PROCESS_INFORMATION child;
376706f2543Smrg
377706f2543Smrg		    memset (&start, 0, sizeof (start));
378706f2543Smrg		    start.cb = sizeof (start);
379706f2543Smrg		    start.dwFlags = STARTF_USESHOWWINDOW;
380706f2543Smrg		    start.wShowWindow = SW_HIDE;
381706f2543Smrg
382706f2543Smrg		    memset (&child, 0, sizeof (child));
383706f2543Smrg
384706f2543Smrg		    if (CreateProcess (NULL, m->menuItem[j].param, NULL, NULL, FALSE, 0,
385706f2543Smrg				       NULL, NULL, &start, &child))
386706f2543Smrg		    {
387706f2543Smrg			CloseHandle (child.hThread);
388706f2543Smrg			CloseHandle (child.hProcess);
389706f2543Smrg		    }
390706f2543Smrg		    else
391706f2543Smrg			MessageBox(NULL, m->menuItem[j].param, "Mingrc Exec Command Error!", MB_OK | MB_ICONEXCLAMATION);
392706f2543Smrg                  }
393706f2543Smrg		  return TRUE;
394706f2543Smrg#endif
395706f2543Smrg		case CMD_ALWAYSONTOP:
396706f2543Smrg		  if (!hwnd)
397706f2543Smrg		    return FALSE;
398706f2543Smrg
399706f2543Smrg		  /* Get extended window style */
400706f2543Smrg		  dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
401706f2543Smrg
402706f2543Smrg		  /* Handle topmost windows */
403706f2543Smrg		  if (dwExStyle & WS_EX_TOPMOST)
404706f2543Smrg		    SetWindowPos (hwnd,
405706f2543Smrg				  HWND_NOTOPMOST,
406706f2543Smrg				  0, 0,
407706f2543Smrg				  0, 0,
408706f2543Smrg				  SWP_NOSIZE | SWP_NOMOVE);
409706f2543Smrg		  else
410706f2543Smrg		    SetWindowPos (hwnd,
411706f2543Smrg				  HWND_TOPMOST,
412706f2543Smrg				  0, 0,
413706f2543Smrg				  0, 0,
414706f2543Smrg				  SWP_NOSIZE | SWP_NOMOVE);
415706f2543Smrg#if XWIN_MULTIWINDOW
416706f2543Smrg		  /* Reflect the changed Z order */
417706f2543Smrg		  winReorderWindowsMultiWindow ();
418706f2543Smrg#endif
419706f2543Smrg		  return TRUE;
420706f2543Smrg
421706f2543Smrg		case CMD_RELOAD:
422706f2543Smrg		  ReloadPrefs();
423706f2543Smrg		  return TRUE;
424706f2543Smrg
425706f2543Smrg		default:
426706f2543Smrg		  return FALSE;
427706f2543Smrg	      }
428706f2543Smrg	    } /* match */
429706f2543Smrg	} /* for j */
430706f2543Smrg    } /* for i */
431706f2543Smrg
432706f2543Smrg  return FALSE;
433706f2543Smrg}
434706f2543Smrg
435706f2543Smrg
436706f2543Smrg#ifdef XWIN_MULTIWINDOW
437706f2543Smrg/*
438706f2543Smrg * Add the default or a custom menu depending on the class match
439706f2543Smrg */
440706f2543Smrgvoid
441706f2543SmrgSetupSysMenu (unsigned long hwndIn)
442706f2543Smrg{
443706f2543Smrg  HWND    hwnd;
444706f2543Smrg  HMENU	  sys;
445706f2543Smrg  int     i;
446706f2543Smrg  WindowPtr pWin;
447706f2543Smrg  char *res_name, *res_class;
448706f2543Smrg
449706f2543Smrg  hwnd = (HWND)hwndIn;
450706f2543Smrg  if (!hwnd)
451706f2543Smrg    return;
452706f2543Smrg
453706f2543Smrg  pWin = GetProp (hwnd, WIN_WINDOW_PROP);
454706f2543Smrg
455706f2543Smrg  sys = GetSystemMenu (hwnd, FALSE);
456706f2543Smrg  if (!sys)
457706f2543Smrg    return;
458706f2543Smrg
459706f2543Smrg  if (pWin)
460706f2543Smrg    {
461706f2543Smrg      /* First see if there's a class match... */
462706f2543Smrg      if (winMultiWindowGetClassHint (pWin, &res_name, &res_class))
463706f2543Smrg	{
464706f2543Smrg	  for (i=0; i<pref.sysMenuItems; i++)
465706f2543Smrg	    {
466706f2543Smrg	      if (!strcmp(pref.sysMenu[i].match, res_name) ||
467706f2543Smrg		  !strcmp(pref.sysMenu[i].match, res_class) )
468706f2543Smrg		{
469706f2543Smrg		  free(res_name);
470706f2543Smrg		  free(res_class);
471706f2543Smrg
472706f2543Smrg		  MakeMenu (pref.sysMenu[i].menuName, sys,
473706f2543Smrg			    pref.sysMenu[i].menuPos==AT_START?0:-1);
474706f2543Smrg		  return;
475706f2543Smrg		}
476706f2543Smrg	    }
477706f2543Smrg
478706f2543Smrg	  /* No match, just free alloc'd strings */
479706f2543Smrg	  free(res_name);
480706f2543Smrg	  free(res_class);
481706f2543Smrg	} /* Found wm_class */
482706f2543Smrg    } /* if pwin */
483706f2543Smrg
484706f2543Smrg  /* Fallback to system default */
485706f2543Smrg  if (pref.defaultSysMenuName[0])
486706f2543Smrg    {
487706f2543Smrg      if (pref.defaultSysMenuPos==AT_START)
488706f2543Smrg	MakeMenu (pref.defaultSysMenuName, sys, 0);
489706f2543Smrg      else
490706f2543Smrg	MakeMenu (pref.defaultSysMenuName, sys, -1);
491706f2543Smrg    }
492706f2543Smrg}
493706f2543Smrg#endif
494706f2543Smrg
495706f2543Smrg
496706f2543Smrg/*
497706f2543Smrg * Possibly add a menu to the toolbar icon
498706f2543Smrg */
499706f2543Smrgvoid
500706f2543SmrgSetupRootMenu (unsigned long hmenuRoot)
501706f2543Smrg{
502706f2543Smrg  HMENU root;
503706f2543Smrg
504706f2543Smrg  root = (HMENU)hmenuRoot;
505706f2543Smrg  if (!root)
506706f2543Smrg    return;
507706f2543Smrg
508706f2543Smrg  if (pref.rootMenuName[0])
509706f2543Smrg    {
510706f2543Smrg      MakeMenu(pref.rootMenuName, root, 0);
511706f2543Smrg    }
512706f2543Smrg}
513706f2543Smrg
514706f2543Smrg
515706f2543Smrg/*
516706f2543Smrg * Check for and return an overridden default ICON specified in the prefs
517706f2543Smrg */
518706f2543SmrgHICON
519706f2543SmrgwinOverrideDefaultIcon(int size)
520706f2543Smrg{
521706f2543Smrg  HICON hicon;
522706f2543Smrg
523706f2543Smrg  if (pref.defaultIconName[0])
524706f2543Smrg    {
525706f2543Smrg      hicon = LoadImageComma (pref.defaultIconName, size, size, 0);
526706f2543Smrg      if (hicon==NULL)
527706f2543Smrg        ErrorF ("winOverrideDefaultIcon: LoadImageComma(%s) failed\n",
528706f2543Smrg		pref.defaultIconName);
529706f2543Smrg
530706f2543Smrg      return hicon;
531706f2543Smrg    }
532706f2543Smrg
533706f2543Smrg  return 0;
534706f2543Smrg}
535706f2543Smrg
536706f2543Smrg
537706f2543Smrg/*
538706f2543Smrg * Return the HICON to use in the taskbar notification area
539706f2543Smrg */
540706f2543SmrgHICON
541706f2543SmrgwinTaskbarIcon(void)
542706f2543Smrg{
543706f2543Smrg  HICON hicon;
544706f2543Smrg
545706f2543Smrg  hicon = 0;
546706f2543Smrg  /* First try and load an overridden, if success then return it */
547706f2543Smrg  if (pref.trayIconName[0])
548706f2543Smrg    {
549706f2543Smrg      hicon = LoadImageComma (pref.trayIconName,
550706f2543Smrg			      GetSystemMetrics (SM_CXSMICON),
551706f2543Smrg			      GetSystemMetrics (SM_CYSMICON),
552706f2543Smrg			      0 );
553706f2543Smrg    }
554706f2543Smrg
555706f2543Smrg  /* Otherwise return the default */
556706f2543Smrg  if (!hicon)
557706f2543Smrg    hicon =  (HICON) LoadImage (g_hInstance,
558706f2543Smrg				MAKEINTRESOURCE(IDI_XWIN),
559706f2543Smrg				IMAGE_ICON,
560706f2543Smrg				GetSystemMetrics (SM_CXSMICON),
561706f2543Smrg				GetSystemMetrics (SM_CYSMICON),
562706f2543Smrg				0);
563706f2543Smrg
564706f2543Smrg  return hicon;
565706f2543Smrg}
566706f2543Smrg
567706f2543Smrg
568706f2543Smrg/*
569706f2543Smrg * Parse a filename to extract an icon:
570706f2543Smrg *  If fname is exactly ",nnn" then extract icon from our resource
571706f2543Smrg *  else if it is "file,nnn" then extract icon nnn from that file
572706f2543Smrg *  else try to load it as an .ico file and if that fails return NULL
573706f2543Smrg */
574706f2543Smrgstatic HICON
575706f2543SmrgLoadImageComma (char *fname, int sx, int sy, int flags)
576706f2543Smrg{
577706f2543Smrg  HICON  hicon;
578706f2543Smrg  int    index;
579706f2543Smrg  char   file[PATH_MAX+NAME_MAX+2];
580706f2543Smrg
581706f2543Smrg  /* Some input error checking */
582706f2543Smrg  if (!fname || !fname[0])
583706f2543Smrg    return NULL;
584706f2543Smrg
585706f2543Smrg  index = 0;
586706f2543Smrg  hicon = NULL;
587706f2543Smrg
588706f2543Smrg  if (fname[0]==',')
589706f2543Smrg    {
590706f2543Smrg      /* It's the XWIN.EXE resource they want */
591706f2543Smrg      index = atoi (fname+1);
592706f2543Smrg      hicon = LoadImage (g_hInstance,
593706f2543Smrg                        MAKEINTRESOURCE(index),
594706f2543Smrg                        IMAGE_ICON,
595706f2543Smrg                        sx,
596706f2543Smrg                        sy,
597706f2543Smrg                        flags);
598706f2543Smrg    }
599706f2543Smrg  else
600706f2543Smrg    {
601706f2543Smrg      file[0] = 0;
602706f2543Smrg      /* Prepend path if not given a "X:\" filename */
603706f2543Smrg      if ( !(fname[0] && fname[1]==':' && fname[2]=='\\') )
604706f2543Smrg        {
605706f2543Smrg         strcpy (file, pref.iconDirectory);
606706f2543Smrg         if (pref.iconDirectory[0])
607706f2543Smrg           if (fname[strlen(fname)-1]!='\\')
608706f2543Smrg             strcat (file, "\\");
609706f2543Smrg        }
610706f2543Smrg      strcat (file, fname);
611706f2543Smrg
612706f2543Smrg      if (strrchr (file, ','))
613706f2543Smrg       {
614706f2543Smrg         /* Specified as <fname>,<index> */
615706f2543Smrg
616706f2543Smrg         *(strrchr (file, ',')) = 0; /* End string at comma */
617706f2543Smrg         index = atoi (strrchr (fname, ',') + 1);
618706f2543Smrg         hicon = ExtractIcon (g_hInstance, file, index);
619706f2543Smrg       }
620706f2543Smrg      else
621706f2543Smrg       {
622706f2543Smrg         /* Just an .ico file... */
623706f2543Smrg
624706f2543Smrg         hicon = (HICON)LoadImage (NULL,
625706f2543Smrg                                   file,
626706f2543Smrg                                   IMAGE_ICON,
627706f2543Smrg                                   sx,
628706f2543Smrg                                   sy,
629706f2543Smrg                                   LR_LOADFROMFILE|flags);
630706f2543Smrg       }
631706f2543Smrg    }
632706f2543Smrg  return hicon;
633706f2543Smrg}
634706f2543Smrg
635706f2543Smrg/*
636706f2543Smrg * Check for a match of the window class to one specified in the
637706f2543Smrg * ICONS{} section in the prefs file, and load the icon from a file
638706f2543Smrg */
639706f2543SmrgHICON
640706f2543SmrgwinOverrideIcon (unsigned long longWin)
641706f2543Smrg{
642706f2543Smrg  WindowPtr pWin = (WindowPtr) longWin;
643706f2543Smrg  char *res_name, *res_class;
644706f2543Smrg  int i;
645706f2543Smrg  HICON hicon;
646706f2543Smrg  char *wmName;
647706f2543Smrg
648706f2543Smrg  if (pWin==NULL)
649706f2543Smrg    return 0;
650706f2543Smrg
651706f2543Smrg  /* If we can't find the class, we can't override from default! */
652706f2543Smrg  if (!winMultiWindowGetClassHint (pWin, &res_name, &res_class))
653706f2543Smrg    return 0;
654706f2543Smrg
655706f2543Smrg  winMultiWindowGetWMName (pWin, &wmName);
656706f2543Smrg
657706f2543Smrg  for (i=0; i<pref.iconItems; i++) {
658706f2543Smrg    if (!strcmp(pref.icon[i].match, res_name) ||
659706f2543Smrg	!strcmp(pref.icon[i].match, res_class) ||
660706f2543Smrg	(wmName && strstr(wmName, pref.icon[i].match)))
661706f2543Smrg      {
662706f2543Smrg	free (res_name);
663706f2543Smrg	free (res_class);
664706f2543Smrg	free(wmName);
665706f2543Smrg
666706f2543Smrg	if (pref.icon[i].hicon)
667706f2543Smrg	  return pref.icon[i].hicon;
668706f2543Smrg
669706f2543Smrg       hicon = LoadImageComma (pref.icon[i].iconFile, 0, 0, LR_DEFAULTSIZE);
670706f2543Smrg       if (hicon==NULL)
671706f2543Smrg         ErrorF ("winOverrideIcon: LoadImageComma(%s) failed\n",
672706f2543Smrg                  pref.icon[i].iconFile);
673706f2543Smrg
674706f2543Smrg	pref.icon[i].hicon = hicon;
675706f2543Smrg	return hicon;
676706f2543Smrg      }
677706f2543Smrg  }
678706f2543Smrg
679706f2543Smrg  /* Didn't find the icon, fail gracefully */
680706f2543Smrg  free (res_name);
681706f2543Smrg  free (res_class);
682706f2543Smrg  free(wmName);
683706f2543Smrg
684706f2543Smrg  return 0;
685706f2543Smrg}
686706f2543Smrg
687706f2543Smrg
688706f2543Smrg/*
689706f2543Smrg * Should we free this icon or leave it in memory (is it part of our
690706f2543Smrg * ICONS{} overrides)?
691706f2543Smrg */
692706f2543Smrgint
693706f2543SmrgwinIconIsOverride(unsigned hiconIn)
694706f2543Smrg{
695706f2543Smrg  HICON hicon;
696706f2543Smrg  int i;
697706f2543Smrg
698706f2543Smrg  hicon = (HICON)hiconIn;
699706f2543Smrg
700706f2543Smrg  if (!hicon)
701706f2543Smrg    return 0;
702706f2543Smrg
703706f2543Smrg  for (i=0; i<pref.iconItems; i++)
704706f2543Smrg    if ((HICON)pref.icon[i].hicon == hicon)
705706f2543Smrg      return 1;
706706f2543Smrg
707706f2543Smrg  return 0;
708706f2543Smrg}
709706f2543Smrg
710706f2543Smrg
711706f2543Smrg
712706f2543Smrg/*
713706f2543Smrg * Try and open ~/.XWinrc and system.XWinrc
714706f2543Smrg * Load it into prefs structure for use by other functions
715706f2543Smrg */
716706f2543Smrgvoid
717706f2543SmrgLoadPreferences (void)
718706f2543Smrg{
719706f2543Smrg  char *home;
720706f2543Smrg  char fname[PATH_MAX+NAME_MAX+2];
721706f2543Smrg  FILE *prefFile;
722706f2543Smrg  char szDisplay[512];
723706f2543Smrg  char *szEnvDisplay;
724706f2543Smrg  int i, j;
725706f2543Smrg  char param[PARAM_MAX+1];
726706f2543Smrg  char *srcParam, *dstParam;
727706f2543Smrg
728706f2543Smrg  /* First, clear all preference settings */
729706f2543Smrg  memset (&pref, 0, sizeof(pref));
730706f2543Smrg  prefFile = NULL;
731706f2543Smrg
732706f2543Smrg  /* Now try and find a ~/.xwinrc file */
733706f2543Smrg  home = getenv ("HOME");
734706f2543Smrg  if (home)
735706f2543Smrg    {
736706f2543Smrg      strcpy (fname, home);
737706f2543Smrg      if (fname[strlen(fname)-1]!='/')
738706f2543Smrg	strcat (fname, "/");
739706f2543Smrg      strcat (fname, ".XWinrc");
740706f2543Smrg
741706f2543Smrg      prefFile = fopen (fname, "r");
742706f2543Smrg      if (prefFile)
743706f2543Smrg	ErrorF ("winPrefsLoadPreferences: %s\n", fname);
744706f2543Smrg    }
745706f2543Smrg
746706f2543Smrg  /* No home file found, check system default */
747706f2543Smrg  if (!prefFile)
748706f2543Smrg    {
749706f2543Smrg      char buffer[MAX_PATH];
750706f2543Smrg#ifdef RELOCATE_PROJECTROOT
751706f2543Smrg      snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir());
752706f2543Smrg#else
753706f2543Smrg      strncpy(buffer, SYSCONFDIR"/X11/system.XWinrc", sizeof(buffer));
754706f2543Smrg#endif
755706f2543Smrg      buffer[sizeof(buffer)-1] = 0;
756706f2543Smrg      prefFile = fopen (buffer, "r");
757706f2543Smrg      if (prefFile)
758706f2543Smrg	ErrorF ("winPrefsLoadPreferences: %s\n", buffer);
759706f2543Smrg    }
760706f2543Smrg
761706f2543Smrg  /* If we could open it, then read the settings and close it */
762706f2543Smrg  if (prefFile)
763706f2543Smrg    {
764706f2543Smrg      parse_file (prefFile);
765706f2543Smrg      fclose (prefFile);
766706f2543Smrg    }
767706f2543Smrg
768706f2543Smrg  /* Setup a DISPLAY environment variable, need to allocate on heap */
769706f2543Smrg  /* because putenv doesn't copy the argument... */
770706f2543Smrg  snprintf (szDisplay, 512, "DISPLAY=127.0.0.1:%s.0", display);
771706f2543Smrg  szEnvDisplay = (char *)(malloc (strlen(szDisplay)+1));
772706f2543Smrg  if (szEnvDisplay)
773706f2543Smrg    {
774706f2543Smrg      strcpy (szEnvDisplay, szDisplay);
775706f2543Smrg      putenv (szEnvDisplay);
776706f2543Smrg    }
777706f2543Smrg
778706f2543Smrg  /* Replace any "%display%" in menu commands with display string */
779706f2543Smrg  snprintf (szDisplay, 512, "127.0.0.1:%s.0", display);
780706f2543Smrg  for (i=0; i<pref.menuItems; i++)
781706f2543Smrg    {
782706f2543Smrg      for (j=0; j<pref.menu[i].menuItems; j++)
783706f2543Smrg	{
784706f2543Smrg	  if (pref.menu[i].menuItem[j].cmd==CMD_EXEC)
785706f2543Smrg	    {
786706f2543Smrg	      srcParam = pref.menu[i].menuItem[j].param;
787706f2543Smrg	      dstParam = param;
788706f2543Smrg	      while (*srcParam) {
789706f2543Smrg		if (!strncmp(srcParam, "%display%", 9))
790706f2543Smrg		  {
791706f2543Smrg		    memcpy (dstParam, szDisplay, strlen(szDisplay));
792706f2543Smrg		    dstParam += strlen(szDisplay);
793706f2543Smrg		    srcParam += 9;
794706f2543Smrg		  }
795706f2543Smrg		else
796706f2543Smrg		  {
797706f2543Smrg		    *dstParam = *srcParam;
798706f2543Smrg		    dstParam++;
799706f2543Smrg		    srcParam++;
800706f2543Smrg		  }
801706f2543Smrg	      }
802706f2543Smrg	      *dstParam = 0;
803706f2543Smrg	      strcpy (pref.menu[i].menuItem[j].param, param);
804706f2543Smrg	    } /* cmd==cmd_exec */
805706f2543Smrg	} /* for all menuitems */
806706f2543Smrg    } /* for all menus */
807706f2543Smrg
808706f2543Smrg}
809706f2543Smrg
810706f2543Smrg
811706f2543Smrg/*
812706f2543Smrg * Check for a match of the window class to one specified in the
813706f2543Smrg * STYLES{} section in the prefs file, and return the style type
814706f2543Smrg */
815706f2543Smrgunsigned long
816706f2543SmrgwinOverrideStyle (unsigned long longpWin)
817706f2543Smrg{
818706f2543Smrg  WindowPtr pWin = (WindowPtr) longpWin;
819706f2543Smrg  char *res_name, *res_class;
820706f2543Smrg  int i;
821706f2543Smrg  char *wmName;
822706f2543Smrg
823706f2543Smrg  if (pWin==NULL)
824706f2543Smrg    return STYLE_NONE;
825706f2543Smrg
826706f2543Smrg  /* If we can't find the class, we can't override from default! */
827706f2543Smrg  if (!winMultiWindowGetClassHint (pWin, &res_name, &res_class))
828706f2543Smrg    return STYLE_NONE;
829706f2543Smrg
830706f2543Smrg  winMultiWindowGetWMName (pWin, &wmName);
831706f2543Smrg
832706f2543Smrg  for (i=0; i<pref.styleItems; i++) {
833706f2543Smrg    if (!strcmp(pref.style[i].match, res_name) ||
834706f2543Smrg	!strcmp(pref.style[i].match, res_class) ||
835706f2543Smrg	(wmName && strstr(wmName, pref.style[i].match)))
836706f2543Smrg      {
837706f2543Smrg	free (res_name);
838706f2543Smrg	free (res_class);
839706f2543Smrg	free(wmName);
840706f2543Smrg
841706f2543Smrg	if (pref.style[i].type)
842706f2543Smrg	  return pref.style[i].type;
843706f2543Smrg      }
844706f2543Smrg  }
845706f2543Smrg
846706f2543Smrg  /* Didn't find the style, fail gracefully */
847706f2543Smrg  free (res_name);
848706f2543Smrg  free (res_class);
849706f2543Smrg  free(wmName);
850706f2543Smrg
851706f2543Smrg  return STYLE_NONE;
852706f2543Smrg}
853