#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef __CYGWIN__
#include <sys/resource.h>
#endif
#include "win.h"
#include <X11/Xwindows.h>
#include <shellapi.h>
#include "winprefs.h"
#include "winmultiwindowclass.h"
#define STARTMENUID WM_USER
#ifdef XWIN_MULTIWINDOW
extern DWORD g_dwCurrentThreadID;
#endif
extern const char *winGetBaseDir(void);
extern void parse_file (FILE *fp);
extern WINPREFS pref;
extern HICON g_hIconX;
extern HICON g_hSmallIconX;
static int g_cmdid = STARTMENUID;
extern char *display;
static HICON
LoadImageComma (char *fname, int sx, int sy, int flags);
static HMENU
MakeMenu (char *name,
HMENU editMenu,
int editItem)
{
int i;
int item;
MENUPARSED *m;
HMENU hmenu, hsub;
for (i=0; i<pref.menuItems; i++)
{
if (!strcmp(name, pref.menu[i].menuName))
break;
}
if (i==pref.menuItems)
{
ErrorF("MakeMenu: Can't find menu %s\n", name);
return NULL;
}
m = &(pref.menu[i]);
if (editMenu)
{
hmenu = editMenu;
item = editItem;
}
else
{
hmenu = CreatePopupMenu();
if (!hmenu)
{
ErrorF("MakeMenu: Unable to CreatePopupMenu() %s\n", name);
return NULL;
}
item = 0;
}
for (i=0; i<m->menuItems; i++)
{
if ( m->menuItem[i].commandID == 0 )
m->menuItem[i].commandID = g_cmdid++;
switch (m->menuItem[i].cmd)
{
case CMD_EXEC:
case CMD_ALWAYSONTOP:
case CMD_RELOAD:
InsertMenu (hmenu,
item,
MF_BYPOSITION|MF_ENABLED|MF_STRING,
m->menuItem[i].commandID,
m->menuItem[i].text);
break;
case CMD_SEPARATOR:
InsertMenu (hmenu,
item,
MF_BYPOSITION|MF_SEPARATOR,
0,
NULL);
break;
case CMD_MENU:
hsub = MakeMenu (m->menuItem[i].param, 0, 0);
if (hsub)
InsertMenu (hmenu,
item,
MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,
(UINT_PTR)hsub,
m->menuItem[i].text);
break;
}
if (item>=0)
item++;
}
return hmenu;
}
#ifdef XWIN_MULTIWINDOW
static wBOOL CALLBACK
ReloadEnumWindowsProc (HWND hwnd, LPARAM lParam)
{
HICON hicon;
Window wid;
if (!hwnd) {
ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n");
return FALSE;
}
if (lParam==FALSE)
{
hicon = (HICON)GetClassLong(hwnd, GCL_HICON);
SetClassLong (hwnd, GCL_HICON, (LONG)LoadIcon (NULL, IDI_APPLICATION));
winDestroyIcon (hicon);
hicon = (HICON)GetClassLong(hwnd, GCL_HICONSM);
SetClassLong (hwnd, GCL_HICONSM, 0);
winDestroyIcon (hicon);
GetSystemMenu (hwnd, TRUE);
}
else
{
SetClassLong (hwnd, GCL_HICON, (LONG)g_hIconX);
SetClassLong (hwnd, GCL_HICONSM, (LONG)g_hSmallIconX);
wid = (Window)GetProp (hwnd, WIN_WID_PROP);
if (wid)
winUpdateIcon (wid);
SetupSysMenu ((unsigned long)hwnd);
}
return TRUE;
}
#endif
static void
ReloadPrefs (void)
{
int i;
#ifdef XWIN_MULTIWINDOW
EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE);
#endif
for (i=0; i<pref.menuItems; i++)
free (pref.menu[i].menuItem);
free (pref.menu);
pref.menu = NULL;
pref.menuItems = 0;
pref.rootMenuName[0] = 0;
free (pref.sysMenu);
pref.sysMenuItems = 0;
pref.defaultSysMenuName[0] = 0;
pref.defaultSysMenuPos = 0;
pref.iconDirectory[0] = 0;
pref.defaultIconName[0] = 0;
pref.trayIconName[0] = 0;
for (i=0; i<pref.iconItems; i++)
if (pref.icon[i].hicon)
DestroyIcon ((HICON)pref.icon[i].hicon);
free (pref.icon);
pref.icon = NULL;
pref.iconItems = 0;
if (g_hIconX)
DestroyIcon (g_hIconX);
if (g_hSmallIconX)
DestroyIcon (g_hSmallIconX);
g_cmdid = STARTMENUID;
LoadPreferences();
g_hIconX = NULL;
g_hSmallIconX = NULL;
#ifdef XWIN_MULTIWINDOW
winInitGlobalIcons();
#endif
#ifdef XWIN_MULTIWINDOW
EnumThreadWindows (g_dwCurrentThreadID, ReloadEnumWindowsProc, TRUE);
#endif
}
void
HandleCustomWM_INITMENU(unsigned long hwndIn,
unsigned long hmenuIn)
{
HWND hwnd;
HMENU hmenu;
DWORD dwExStyle;
int i, j;
hwnd = (HWND)hwndIn;
hmenu = (HMENU)hmenuIn;
if (!hwnd || !hmenu)
return;
if (GetWindowLong (hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
dwExStyle = MF_BYCOMMAND | MF_CHECKED;
else
dwExStyle = MF_BYCOMMAND | MF_UNCHECKED;
for (i=0; i<pref.menuItems; i++)
for (j=0; j<pref.menu[i].menuItems; j++)
if (pref.menu[i].menuItem[j].cmd==CMD_ALWAYSONTOP)
CheckMenuItem (hmenu, pref.menu[i].menuItem[j].commandID, dwExStyle );
}
Bool
HandleCustomWM_COMMAND (unsigned long hwndIn,
int command)
{
HWND hwnd;
int i, j;
MENUPARSED *m;
DWORD dwExStyle;
hwnd = (HWND)hwndIn;
if (!command)
return FALSE;
for (i=0; i<pref.menuItems; i++)
{
m = &(pref.menu[i]);
for (j=0; j<m->menuItems; j++)
{
if (command==m->menuItem[j].commandID)
{
switch(m->menuItem[j].cmd)
{
#ifdef __CYGWIN__
case CMD_EXEC:
if (fork()==0)
{
struct rlimit rl;
unsigned long i;
getrlimit (RLIMIT_NOFILE, &rl);
for (i = STDERR_FILENO+1; i < rl.rlim_cur; i++)
close(i);
setsid();
execl ("/bin/sh",
"/bin/sh",
"-c",
m->menuItem[j].param,
NULL);
exit (0);
}
else
return TRUE;
break;
#else
case CMD_EXEC:
{
STARTUPINFO start;
PROCESS_INFORMATION child;
memset (&start, 0, sizeof (start));
start.cb = sizeof (start);
start.dwFlags = STARTF_USESHOWWINDOW;
start.wShowWindow = SW_HIDE;
memset (&child, 0, sizeof (child));
if (CreateProcess (NULL, m->menuItem[j].param, NULL, NULL, FALSE, 0,
NULL, NULL, &start, &child))
{
CloseHandle (child.hThread);
CloseHandle (child.hProcess);
}
else
MessageBox(NULL, m->menuItem[j].param, "Mingrc Exec Command Error!", MB_OK | MB_ICONEXCLAMATION);
}
return TRUE;
#endif
case CMD_ALWAYSONTOP:
if (!hwnd)
return FALSE;
dwExStyle = GetWindowLong (hwnd, GWL_EXSTYLE);
if (dwExStyle & WS_EX_TOPMOST)
SetWindowPos (hwnd,
HWND_NOTOPMOST,
0, 0,
0, 0,
SWP_NOSIZE | SWP_NOMOVE);
else
SetWindowPos (hwnd,
HWND_TOPMOST,
0, 0,
0, 0,
SWP_NOSIZE | SWP_NOMOVE);
#if XWIN_MULTIWINDOW
winReorderWindowsMultiWindow ();
#endif
return TRUE;
case CMD_RELOAD:
ReloadPrefs();
return TRUE;
default:
return FALSE;
}
}
}
}
return FALSE;
}
#ifdef XWIN_MULTIWINDOW
void
SetupSysMenu (unsigned long hwndIn)
{
HWND hwnd;
HMENU sys;
int i;
WindowPtr pWin;
char *res_name, *res_class;
hwnd = (HWND)hwndIn;
if (!hwnd)
return;
pWin = GetProp (hwnd, WIN_WINDOW_PROP);
sys = GetSystemMenu (hwnd, FALSE);
if (!sys)
return;
if (pWin)
{
if (winMultiWindowGetClassHint (pWin, &res_name, &res_class))
{
for (i=0; i<pref.sysMenuItems; i++)
{
if (!strcmp(pref.sysMenu[i].match, res_name) ||
!strcmp(pref.sysMenu[i].match, res_class) )
{
free(res_name);
free(res_class);
MakeMenu (pref.sysMenu[i].menuName, sys,
pref.sysMenu[i].menuPos==AT_START?0:-1);
return;
}
}
free(res_name);
free(res_class);
}
}
if (pref.defaultSysMenuName[0])
{
if (pref.defaultSysMenuPos==AT_START)
MakeMenu (pref.defaultSysMenuName, sys, 0);
else
MakeMenu (pref.defaultSysMenuName, sys, -1);
}
}
#endif
void
SetupRootMenu (unsigned long hmenuRoot)
{
HMENU root;
root = (HMENU)hmenuRoot;
if (!root)
return;
if (pref.rootMenuName[0])
{
MakeMenu(pref.rootMenuName, root, 0);
}
}
unsigned long
winOverrideDefaultIcon(int size)
{
HICON hicon;
if (pref.defaultIconName[0])
{
hicon = LoadImageComma (pref.defaultIconName, size, size, 0);
if (hicon==NULL)
ErrorF ("winOverrideDefaultIcon: LoadImageComma(%s) failed\n",
pref.defaultIconName);
return (unsigned long)hicon;
}
return 0;
}
unsigned long
winTaskbarIcon(void)
{
HICON hicon;
hicon = 0;
if (pref.trayIconName[0])
{
hicon = LoadImageComma (pref.trayIconName,
GetSystemMetrics (SM_CXSMICON),
GetSystemMetrics (SM_CYSMICON),
0 );
}
if (!hicon)
hicon = (HICON) LoadImage (g_hInstance,
MAKEINTRESOURCE(IDI_XWIN),
IMAGE_ICON,
GetSystemMetrics (SM_CXSMICON),
GetSystemMetrics (SM_CYSMICON),
0);
return (unsigned long)hicon;
}
static HICON
LoadImageComma (char *fname, int sx, int sy, int flags)
{
HICON hicon;
int index;
char file[PATH_MAX+NAME_MAX+2];
if (!fname || !fname[0])
return NULL;
index = 0;
hicon = NULL;
if (fname[0]==',')
{
index = atoi (fname+1);
hicon = LoadImage (g_hInstance,
MAKEINTRESOURCE(index),
IMAGE_ICON,
sx,
sy,
flags);
}
else
{
file[0] = 0;
if ( !(fname[0] && fname[1]==':' && fname[2]=='\\') )
{
strcpy (file, pref.iconDirectory);
if (pref.iconDirectory[0])
if (fname[strlen(fname)-1]!='\\')
strcat (file, "\\");
}
strcat (file, fname);
if (strrchr (file, ','))
{
*(strrchr (file, ',')) = 0;
index = atoi (strrchr (fname, ',') + 1);
hicon = ExtractIcon (g_hInstance, file, index);
}
else
{
hicon = (HICON)LoadImage (NULL,
file,
IMAGE_ICON,
sx,
sy,
LR_LOADFROMFILE|flags);
}
}
return hicon;
}
unsigned long
winOverrideIcon (unsigned long longWin)
{
WindowPtr pWin = (WindowPtr) longWin;
char *res_name, *res_class;
int i;
HICON hicon;
char *wmName;
if (pWin==NULL)
return 0;
if (!winMultiWindowGetClassHint (pWin, &res_name, &res_class))
return 0;
winMultiWindowGetWMName (pWin, &wmName);
for (i=0; i<pref.iconItems; i++) {
if (!strcmp(pref.icon[i].match, res_name) ||
!strcmp(pref.icon[i].match, res_class) ||
(wmName && strstr(wmName, pref.icon[i].match)))
{
free (res_name);
free (res_class);
if (wmName)
free (wmName);
if (pref.icon[i].hicon)
return pref.icon[i].hicon;
hicon = LoadImageComma (pref.icon[i].iconFile, 0, 0, LR_DEFAULTSIZE);
if (hicon==NULL)
ErrorF ("winOverrideIcon: LoadImageComma(%s) failed\n",
pref.icon[i].iconFile);
pref.icon[i].hicon = (unsigned long)hicon;
return (unsigned long)hicon;
}
}
free (res_name);
free (res_class);
if (wmName)
free (wmName);
return 0;
}
int
winIconIsOverride(unsigned hiconIn)
{
HICON hicon;
int i;
hicon = (HICON)hiconIn;
if (!hicon)
return 0;
for (i=0; i<pref.iconItems; i++)
if ((HICON)pref.icon[i].hicon == hicon)
return 1;
return 0;
}
void
LoadPreferences ()
{
char *home;
char fname[PATH_MAX+NAME_MAX+2];
FILE *prefFile;
char szDisplay[512];
char *szEnvDisplay;
int i, j;
char param[PARAM_MAX+1];
char *srcParam, *dstParam;
memset (&pref, 0, sizeof(pref));
prefFile = NULL;
home = getenv ("HOME");
if (home)
{
strcpy (fname, home);
if (fname[strlen(fname)-1]!='/')
strcat (fname, "/");
strcat (fname, ".XWinrc");
prefFile = fopen (fname, "r");
if (prefFile)
ErrorF ("winPrefsLoadPreferences: %s\n", fname);
}
if (!prefFile)
{
char buffer[MAX_PATH];
#ifdef RELOCATE_PROJECTROOT
snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir());
#else
strncpy(buffer, PROJECTROOT"/lib/X11/system.XWinrc", sizeof(buffer));
#endif
buffer[sizeof(buffer)-1] = 0;
prefFile = fopen (buffer, "r");
if (prefFile)
ErrorF ("winPrefsLoadPreferences: %s\n", buffer);
}
if (prefFile)
{
parse_file (prefFile);
fclose (prefFile);
}
snprintf (szDisplay, 512, "DISPLAY=127.0.0.1:%s.0", display);
szEnvDisplay = (char *)(malloc (strlen(szDisplay)+1));
if (szEnvDisplay)
{
strcpy (szEnvDisplay, szDisplay);
putenv (szEnvDisplay);
}
snprintf (szDisplay, 512, "127.0.0.1:%s.0", display);
for (i=0; i<pref.menuItems; i++)
{
for (j=0; j<pref.menu[i].menuItems; j++)
{
if (pref.menu[i].menuItem[j].cmd==CMD_EXEC)
{
srcParam = pref.menu[i].menuItem[j].param;
dstParam = param;
while (*srcParam) {
if (!strncmp(srcParam, "%display%", 9))
{
memcpy (dstParam, szDisplay, strlen(szDisplay));
dstParam += strlen(szDisplay);
srcParam += 9;
}
else
{
*dstParam = *srcParam;
dstParam++;
srcParam++;
}
}
*dstParam = 0;
strcpy (pref.menu[i].menuItem[j].param, param);
}
}
}
}