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