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