1/* 2 * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3 * Copyright (C) Colin Harrison 2005-2008 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Except as contained in this notice, the name of the XFree86 Project 25 * shall not be used in advertising or otherwise to promote the sale, use 26 * or other dealings in this Software without prior written authorization 27 * from the XFree86 Project. 28 * 29 * Authors: Earle F. Philhower, III 30 * Colin Harrison 31 */ 32 33#ifdef HAVE_XWIN_CONFIG_H 34#include <xwin-config.h> 35#endif 36#include <stdio.h> 37#include <stdlib.h> 38#ifdef __CYGWIN__ 39#include <sys/resource.h> 40#include <sys/cygwin.h> 41#endif 42#include "win.h" 43 44#include <X11/Xwindows.h> 45#include <shellapi.h> 46 47#include "winprefs.h" 48#include "windisplay.h" 49#include "winmultiwindowclass.h" 50#include "winmultiwindowicons.h" 51 52/* Where will the custom menu commands start counting from? */ 53#define STARTMENUID WM_USER 54 55extern const char *winGetBaseDir(void); 56 57/* From winprefslex.l, the real parser */ 58extern int parse_file(FILE * fp); 59 60/* Currently in use command ID, incremented each new menu item created */ 61static int g_cmdid = STARTMENUID; 62 63/* 64 * Creates or appends a menu from a MENUPARSED structure 65 */ 66static HMENU 67MakeMenu(char *name, HMENU editMenu, int editItem) 68{ 69 int i; 70 int item; 71 MENUPARSED *m; 72 HMENU hmenu, hsub; 73 74 for (i = 0; i < pref.menuItems; i++) { 75 if (!strcmp(name, pref.menu[i].menuName)) 76 break; 77 } 78 79 /* Didn't find a match, bummer */ 80 if (i == pref.menuItems) { 81 ErrorF("MakeMenu: Can't find menu %s\n", name); 82 return NULL; 83 } 84 85 m = &(pref.menu[i]); 86 87 if (editMenu) { 88 hmenu = editMenu; 89 item = editItem; 90 } 91 else { 92 hmenu = CreatePopupMenu(); 93 if (!hmenu) { 94 ErrorF("MakeMenu: Unable to CreatePopupMenu() %s\n", name); 95 return NULL; 96 } 97 item = 0; 98 } 99 100 /* Add the menu items */ 101 for (i = 0; i < m->menuItems; i++) { 102 /* Only assign IDs one time... */ 103 if (m->menuItem[i].commandID == 0) 104 m->menuItem[i].commandID = g_cmdid++; 105 106 switch (m->menuItem[i].cmd) { 107 case CMD_EXEC: 108 case CMD_ALWAYSONTOP: 109 case CMD_RELOAD: 110 InsertMenu(hmenu, 111 item, 112 MF_BYPOSITION | MF_ENABLED | MF_STRING, 113 m->menuItem[i].commandID, m->menuItem[i].text); 114 break; 115 116 case CMD_SEPARATOR: 117 InsertMenu(hmenu, item, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); 118 break; 119 120 case CMD_MENU: 121 /* Recursive! */ 122 hsub = MakeMenu(m->menuItem[i].param, 0, 0); 123 if (hsub) 124 InsertMenu(hmenu, 125 item, 126 MF_BYPOSITION | MF_POPUP | MF_ENABLED | MF_STRING, 127 (UINT_PTR) hsub, m->menuItem[i].text); 128 break; 129 } 130 131 /* If item==-1 (means to add at end of menu) don't increment) */ 132 if (item >= 0) 133 item++; 134 } 135 136 return hmenu; 137} 138 139/* 140 * Callback routine that is executed once per window class. 141 * Removes or creates custom window settings depending on LPARAM 142 */ 143static wBOOL CALLBACK 144ReloadEnumWindowsProc(HWND hwnd, LPARAM lParam) 145{ 146 HICON hicon; 147 148 if (!hwnd) { 149 ErrorF("ReloadEnumWindowsProc: hwnd==NULL!\n"); 150 return FALSE; 151 } 152 153 /* It's our baby, either clean or dirty it */ 154 if (lParam == FALSE) { 155 /* Reset the window's icon to undefined. */ 156 hicon = (HICON) SendMessage(hwnd, WM_SETICON, ICON_BIG, 0); 157 158 /* If the old icon is generated on-the-fly, get rid of it, will regen */ 159 winDestroyIcon(hicon); 160 161 /* Same for the small icon */ 162 hicon = (HICON) SendMessage(hwnd, WM_SETICON, ICON_SMALL, 0); 163 winDestroyIcon(hicon); 164 165 /* Remove any menu additions; bRevert=TRUE destroys any modified menus */ 166 GetSystemMenu(hwnd, TRUE); 167 168 /* This window is now clean of our taint (but with undefined icons) */ 169 } 170 else { 171 /* Send a message to WM thread telling it re-evaluate the icon for this window */ 172 { 173 winWMMessageRec wmMsg; 174 175 WindowPtr pWin = GetProp(hwnd, WIN_WINDOW_PROP); 176 177 if (pWin) { 178 winPrivWinPtr pWinPriv = winGetWindowPriv(pWin); 179 winPrivScreenPtr s_pScreenPriv = pWinPriv->pScreenPriv; 180 181 wmMsg.msg = WM_WM_ICON_EVENT; 182 wmMsg.hwndWindow = hwnd; 183 wmMsg.iWindow = (Window) (INT_PTR) GetProp(hwnd, WIN_WID_PROP); 184 185 winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); 186 } 187 } 188 189 /* Update the system menu for this window */ 190 SetupSysMenu(hwnd); 191 192 /* That was easy... */ 193 } 194 195 return TRUE; 196} 197 198/* 199 * Removes any custom icons in classes, custom menus, etc. 200 * Frees all members in pref structure. 201 * Reloads the preferences file. 202 * Set custom icons and menus again. 203 */ 204static void 205ReloadPrefs(winPrivScreenPtr pScreenPriv) 206{ 207 int i; 208 209 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 210 211 /* First, iterate over all windows, deleting their icons and custom menus. 212 * This is really only needed because winDestroyIcon() will try to 213 * destroy the old global icons, which will have changed. 214 * It is probably better to set a windows USER_DATA to flag locally defined 215 * icons, and use that to accurately know when to destroy old icons. 216 */ 217 if (pScreenInfo->fMultiWindow) 218 EnumThreadWindows(g_dwCurrentThreadID, ReloadEnumWindowsProc, FALSE); 219 220 /* Now, free/clear all info from our prefs structure */ 221 for (i = 0; i < pref.menuItems; i++) 222 free(pref.menu[i].menuItem); 223 free(pref.menu); 224 pref.menu = NULL; 225 pref.menuItems = 0; 226 227 pref.rootMenuName[0] = 0; 228 229 free(pref.sysMenu); 230 pref.sysMenuItems = 0; 231 232 pref.defaultSysMenuName[0] = 0; 233 pref.defaultSysMenuPos = 0; 234 235 pref.iconDirectory[0] = 0; 236 pref.defaultIconName[0] = 0; 237 pref.trayIconName[0] = 0; 238 239 for (i = 0; i < pref.iconItems; i++) 240 if (pref.icon[i].hicon) 241 DestroyIcon((HICON) pref.icon[i].hicon); 242 free(pref.icon); 243 pref.icon = NULL; 244 pref.iconItems = 0; 245 246 /* Free global default X icon */ 247 if (g_hIconX) 248 DestroyIcon(g_hIconX); 249 if (g_hSmallIconX) 250 DestroyIcon(g_hSmallIconX); 251 252 /* Reset the custom command IDs */ 253 g_cmdid = STARTMENUID; 254 255 /* Load the updated resource file */ 256 LoadPreferences(); 257 258 g_hIconX = NULL; 259 g_hSmallIconX = NULL; 260 261 if (pScreenInfo->fMultiWindow) { 262 winInitGlobalIcons(); 263 264 /* Rebuild the icons and menus */ 265 EnumThreadWindows(g_dwCurrentThreadID, ReloadEnumWindowsProc, TRUE); 266 } 267 268 /* Whew, done */ 269} 270 271/* 272 * Check/uncheck the ALWAYSONTOP items in this menu 273 */ 274void 275HandleCustomWM_INITMENU(HWND hwnd, HMENU hmenu) 276{ 277 DWORD dwExStyle; 278 int i, j; 279 280 if (!hwnd || !hmenu) 281 return; 282 283 if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) 284 dwExStyle = MF_BYCOMMAND | MF_CHECKED; 285 else 286 dwExStyle = MF_BYCOMMAND | MF_UNCHECKED; 287 288 for (i = 0; i < pref.menuItems; i++) 289 for (j = 0; j < pref.menu[i].menuItems; j++) 290 if (pref.menu[i].menuItem[j].cmd == CMD_ALWAYSONTOP) 291 CheckMenuItem(hmenu, pref.menu[i].menuItem[j].commandID, 292 dwExStyle); 293 294} 295 296/* 297 * Searches for the custom WM_COMMAND command ID and performs action. 298 * Return TRUE if command is processed, FALSE otherwise. 299 */ 300Bool 301HandleCustomWM_COMMAND(HWND hwnd, WORD command, winPrivScreenPtr pScreenPriv) 302{ 303 int i, j; 304 MENUPARSED *m; 305 DWORD dwExStyle; 306 307 if (!command) 308 return FALSE; 309 310 for (i = 0; i < pref.menuItems; i++) { 311 m = &(pref.menu[i]); 312 for (j = 0; j < m->menuItems; j++) { 313 if (command == m->menuItem[j].commandID) { 314 /* Match! */ 315 switch (m->menuItem[j].cmd) { 316#ifdef __CYGWIN__ 317 case CMD_EXEC: 318 if (fork() == 0) { 319 struct rlimit rl; 320 int fd; 321 322 /* Close any open descriptors except for STD* */ 323 getrlimit(RLIMIT_NOFILE, &rl); 324 for (fd = STDERR_FILENO + 1; fd < rl.rlim_cur; fd++) 325 close(fd); 326 327 /* Disassociate any TTYs */ 328 setsid(); 329 330 execl("/bin/sh", 331 "/bin/sh", "-c", m->menuItem[j].param, NULL); 332 exit(0); 333 } 334 else 335 return TRUE; 336 break; 337#else 338 case CMD_EXEC: 339 { 340 /* Start process without console window */ 341 STARTUPINFO start; 342 PROCESS_INFORMATION child; 343 344 memset(&start, 0, sizeof(start)); 345 start.cb = sizeof(start); 346 start.dwFlags = STARTF_USESHOWWINDOW; 347 start.wShowWindow = SW_HIDE; 348 349 memset(&child, 0, sizeof(child)); 350 351 if (CreateProcess 352 (NULL, m->menuItem[j].param, NULL, NULL, FALSE, 0, NULL, 353 NULL, &start, &child)) { 354 CloseHandle(child.hThread); 355 CloseHandle(child.hProcess); 356 } 357 else 358 MessageBox(NULL, m->menuItem[j].param, 359 "Mingrc Exec Command Error!", 360 MB_OK | MB_ICONEXCLAMATION); 361 } 362 return TRUE; 363#endif 364 case CMD_ALWAYSONTOP: 365 if (!hwnd) 366 return FALSE; 367 368 /* Get extended window style */ 369 dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE); 370 371 /* Handle topmost windows */ 372 if (dwExStyle & WS_EX_TOPMOST) 373 SetWindowPos(hwnd, 374 HWND_NOTOPMOST, 375 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 376 else 377 SetWindowPos(hwnd, 378 HWND_TOPMOST, 379 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 380 { 381 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 382 if (pScreenInfo->fMultiWindow) 383 /* Reflect the changed Z order */ 384 winReorderWindowsMultiWindow(); 385 } 386 return TRUE; 387 388 case CMD_RELOAD: 389 ReloadPrefs(pScreenPriv); 390 return TRUE; 391 392 default: 393 return FALSE; 394 } 395 } /* match */ 396 } /* for j */ 397 } /* for i */ 398 399 return FALSE; 400} 401 402/* 403 * Add the default or a custom menu depending on the class match 404 */ 405void 406SetupSysMenu(HWND hwnd) 407{ 408 HMENU sys; 409 int i; 410 WindowPtr pWin; 411 char *res_name, *res_class; 412 413 if (!hwnd) 414 return; 415 416 pWin = GetProp(hwnd, WIN_WINDOW_PROP); 417 418 sys = GetSystemMenu(hwnd, FALSE); 419 if (!sys) 420 return; 421 422 if (pWin) { 423 /* First see if there's a class match... */ 424 if (winMultiWindowGetClassHint(pWin, &res_name, &res_class)) { 425 for (i = 0; i < pref.sysMenuItems; i++) { 426 if (!strcmp(pref.sysMenu[i].match, res_name) || 427 !strcmp(pref.sysMenu[i].match, res_class)) { 428 free(res_name); 429 free(res_class); 430 431 MakeMenu(pref.sysMenu[i].menuName, sys, 432 pref.sysMenu[i].menuPos == AT_START ? 0 : -1); 433 return; 434 } 435 } 436 437 /* No match, just free alloc'd strings */ 438 free(res_name); 439 free(res_class); 440 } /* Found wm_class */ 441 } /* if pwin */ 442 443 /* Fallback to system default */ 444 if (pref.defaultSysMenuName[0]) { 445 if (pref.defaultSysMenuPos == AT_START) 446 MakeMenu(pref.defaultSysMenuName, sys, 0); 447 else 448 MakeMenu(pref.defaultSysMenuName, sys, -1); 449 } 450} 451 452/* 453 * Possibly add a menu to the toolbar icon 454 */ 455void 456SetupRootMenu(HMENU root) 457{ 458 if (!root) 459 return; 460 461 if (pref.rootMenuName[0]) { 462 MakeMenu(pref.rootMenuName, root, 0); 463 } 464} 465 466/* 467 * Check for and return an overridden default ICON specified in the prefs 468 */ 469HICON 470winOverrideDefaultIcon(int size) 471{ 472 HICON hicon; 473 474 if (pref.defaultIconName[0]) { 475 hicon = LoadImageComma(pref.defaultIconName, pref.iconDirectory, size, size, 0); 476 if (hicon == NULL) 477 ErrorF("winOverrideDefaultIcon: LoadImageComma(%s) failed\n", 478 pref.defaultIconName); 479 480 return hicon; 481 } 482 483 return 0; 484} 485 486/* 487 * Return the HICON to use in the taskbar notification area 488 */ 489HICON 490winTaskbarIcon(void) 491{ 492 HICON hicon; 493 494 hicon = 0; 495 /* First try and load an overridden, if success then return it */ 496 if (pref.trayIconName[0]) { 497 hicon = LoadImageComma(pref.trayIconName, pref.iconDirectory, 498 GetSystemMetrics(SM_CXSMICON), 499 GetSystemMetrics(SM_CYSMICON), 0); 500 if (hicon == NULL) 501 ErrorF("winTaskbarIcon: LoadImageComma(%s) failed\n", 502 pref.trayIconName); 503 } 504 505 /* Otherwise return the default */ 506 if (!hicon) 507 hicon = (HICON) LoadImage(g_hInstance, 508 MAKEINTRESOURCE(IDI_XWIN), 509 IMAGE_ICON, 510 GetSystemMetrics(SM_CXSMICON), 511 GetSystemMetrics(SM_CYSMICON), 0); 512 513 return hicon; 514} 515 516/* 517 * Handle comma-ified icon names 518 * 519 * Parse a filename to extract an icon: 520 * If fname is exactly ",nnn" then extract icon from our resource 521 * else if it is "file,nnn" then extract icon nnn from that file 522 * else try to load it as an .ico file and if that fails return NULL 523 */ 524HICON 525LoadImageComma(char *fname, char *iconDirectory, int sx, int sy, int flags) 526{ 527 HICON hicon; 528 int i; 529 530 /* Some input error checking */ 531 if (!fname || !fname[0]) 532 return NULL; 533 534 i = 0; 535 hicon = NULL; 536 537 if (fname[0] == ',') { 538 /* It's the XWIN.EXE resource they want */ 539 i = atoi(fname + 1); 540 hicon = LoadImage(g_hInstance, 541 MAKEINTRESOURCE(i), IMAGE_ICON, sx, sy, flags); 542 } 543 else { 544 char *file = malloc(PATH_MAX + NAME_MAX + 2); 545 Bool convert = FALSE; 546 547 if (!file) 548 return NULL; 549 550 file[0] = 0; 551 552 /* If fname starts 'X:\', it's an absolute Windows path, do nothing */ 553 if (!(fname[0] && fname[1] == ':' && fname[2] == '\\')) { 554#ifdef __CYGWIN__ 555 /* If fname starts with '/', it's an absolute cygwin path, we'll 556 need to convert it */ 557 if (fname[0] == '/') { 558 convert = TRUE; 559 } 560 else 561#endif 562 if (iconDirectory) { 563 /* Otherwise, prepend the default icon directory, which 564 currently must be in absolute Windows path form */ 565 strcpy(file, iconDirectory); 566 if (iconDirectory[0]) 567 if (iconDirectory[strlen(iconDirectory) - 1] != '\\') 568 strcat(file, "\\"); 569 } 570 } 571 strcat(file, fname); 572 573 /* Trim off any ',index' */ 574 if (strrchr(file, ',')) { 575 *(strrchr(file, ',')) = 0; /* End string at comma */ 576 i = atoi(strrchr(fname, ',') + 1); 577 } 578 else { 579 i = -1; 580 } 581 582#ifdef __CYGWIN__ 583 /* Convert from Cygwin path to Windows path */ 584 if (convert) { 585 char *converted_file = cygwin_create_path(CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, file); 586 if (converted_file) { 587 free(file); 588 file = converted_file; 589 } 590 } 591#endif 592 593 if (i >= 0) { 594 /* Specified as <fname>,<index> */ 595 hicon = ExtractIcon(g_hInstance, file, i); 596 } 597 else { 598 /* Specified as just an .ico file */ 599 hicon = (HICON) LoadImage(NULL, 600 file, 601 IMAGE_ICON, 602 sx, sy, LR_LOADFROMFILE | flags); 603 } 604 free(file); 605 } 606 return hicon; 607} 608 609/* 610 * Check for a match of the window class to one specified in the 611 * ICONS{} section in the prefs file, and load the icon from a file 612 */ 613HICON 614winOverrideIcon(char *res_name, char *res_class, char *wmName) 615{ 616 int i; 617 HICON hicon; 618 619 for (i = 0; i < pref.iconItems; i++) { 620 if ((res_name && !strcmp(pref.icon[i].match, res_name)) || 621 (res_class && !strcmp(pref.icon[i].match, res_class)) || 622 (wmName && strstr(wmName, pref.icon[i].match))) { 623 if (pref.icon[i].hicon) 624 return pref.icon[i].hicon; 625 626 hicon = LoadImageComma(pref.icon[i].iconFile, pref.iconDirectory, 0, 0, LR_DEFAULTSIZE); 627 if (hicon == NULL) 628 ErrorF("winOverrideIcon: LoadImageComma(%s) failed\n", 629 pref.icon[i].iconFile); 630 631 pref.icon[i].hicon = hicon; 632 return hicon; 633 } 634 } 635 636 /* Didn't find the icon, fail gracefully */ 637 return 0; 638} 639 640/* 641 * Should we free this icon or leave it in memory (is it part of our 642 * ICONS{} overrides)? 643 */ 644int 645winIconIsOverride(HICON hicon) 646{ 647 int i; 648 649 if (!hicon) 650 return 0; 651 652 for (i = 0; i < pref.iconItems; i++) 653 if ((HICON) pref.icon[i].hicon == hicon) 654 return 1; 655 656 return 0; 657} 658 659/* 660 * Open and parse the XWinrc config file @path. 661 * If @path is NULL, use the built-in default. 662 */ 663static int 664winPrefsLoadPreferences(const char *path) 665{ 666 FILE *prefFile = NULL; 667 668 if (path) 669 prefFile = fopen(path, "r"); 670#ifdef __CYGWIN__ 671 else { 672 char defaultPrefs[] = 673 "MENU rmenu {\n" 674 " \"How to customize this menu\" EXEC \"xterm +tb -e man XWinrc\"\n" 675 " \"Launch xterm\" EXEC xterm\n" 676 " \"Load .XWinrc\" RELOAD\n" 677 " SEPARATOR\n" "}\n" "\n" "ROOTMENU rmenu\n"; 678 679 path = "built-in default"; 680 prefFile = fmemopen(defaultPrefs, strlen(defaultPrefs), "r"); 681 } 682#endif 683 684 if (!prefFile) { 685 ErrorF("LoadPreferences: %s not found\n", path); 686 return FALSE; 687 } 688 689 ErrorF("LoadPreferences: Loading %s\n", path); 690 691 if ((parse_file(prefFile)) != 0) { 692 ErrorF("LoadPreferences: %s is badly formed!\n", path); 693 fclose(prefFile); 694 return FALSE; 695 } 696 697 fclose(prefFile); 698 return TRUE; 699} 700 701/* 702 * Try and open ~/.XWinrc and system.XWinrc 703 * Load it into prefs structure for use by other functions 704 */ 705void 706LoadPreferences(void) 707{ 708 char *home; 709 char fname[PATH_MAX + NAME_MAX + 2]; 710 char szDisplay[512]; 711 char *szEnvDisplay; 712 int i, j; 713 char param[PARAM_MAX + 1]; 714 char *srcParam, *dstParam; 715 int parsed = FALSE; 716 717 /* First, clear all preference settings */ 718 memset(&pref, 0, sizeof(pref)); 719 720 /* Now try and find a ~/.xwinrc file */ 721 home = getenv("HOME"); 722 if (home) { 723 strcpy(fname, home); 724 if (fname[strlen(fname) - 1] != '/') 725 strcat(fname, "/"); 726 strcat(fname, ".XWinrc"); 727 parsed = winPrefsLoadPreferences(fname); 728 } 729 730 /* No home file found, check system default */ 731 if (!parsed) { 732 char buffer[MAX_PATH]; 733 734#ifdef RELOCATE_PROJECTROOT 735 snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir()); 736#else 737 strncpy(buffer, SYSCONFDIR "/X11/system.XWinrc", sizeof(buffer)); 738#endif 739 buffer[sizeof(buffer) - 1] = 0; 740 parsed = winPrefsLoadPreferences(buffer); 741 } 742 743 /* Neither user nor system configuration found, or were badly formed */ 744 if (!parsed) { 745 ErrorF 746 ("LoadPreferences: See \"man XWinrc\" to customize the XWin menu.\n"); 747 parsed = winPrefsLoadPreferences(NULL); 748 } 749 750 /* Setup a DISPLAY environment variable, need to allocate on heap */ 751 /* because putenv doesn't copy the argument... */ 752 winGetDisplayName(szDisplay, 0); 753 szEnvDisplay = (char *) (malloc(strlen(szDisplay) + strlen("DISPLAY=") + 1)); 754 if (szEnvDisplay) { 755 snprintf(szEnvDisplay, 512, "DISPLAY=%s", szDisplay); 756 putenv(szEnvDisplay); 757 } 758 759 /* Replace any "%display%" in menu commands with display string */ 760 for (i = 0; i < pref.menuItems; i++) { 761 for (j = 0; j < pref.menu[i].menuItems; j++) { 762 if (pref.menu[i].menuItem[j].cmd == CMD_EXEC) { 763 srcParam = pref.menu[i].menuItem[j].param; 764 dstParam = param; 765 while (*srcParam) { 766 if (!strncmp(srcParam, "%display%", 9)) { 767 memcpy(dstParam, szDisplay, strlen(szDisplay)); 768 dstParam += strlen(szDisplay); 769 srcParam += 9; 770 } 771 else { 772 *dstParam = *srcParam; 773 dstParam++; 774 srcParam++; 775 } 776 } 777 *dstParam = 0; 778 strcpy(pref.menu[i].menuItem[j].param, param); 779 } /* cmd==cmd_exec */ 780 } /* for all menuitems */ 781 } /* for all menus */ 782 783} 784 785/* 786 * Check for a match of the window class to one specified in the 787 * STYLES{} section in the prefs file, and return the style type 788 */ 789unsigned long 790winOverrideStyle(char *res_name, char *res_class, char *wmName) 791{ 792 int i; 793 794 for (i = 0; i < pref.styleItems; i++) { 795 if ((res_name && !strcmp(pref.style[i].match, res_name)) || 796 (res_class && !strcmp(pref.style[i].match, res_class)) || 797 (wmName && strstr(wmName, pref.style[i].match))) { 798 if (pref.style[i].type) 799 return pref.style[i].type; 800 } 801 } 802 803 /* Didn't find the style, fail gracefully */ 804 return STYLE_NONE; 805} 806