|
|
1.1 ! root 1: /* $Header: uwm.c,v 1.8 87/08/20 19:17:40 swick Exp $ */ ! 2: #include <X11/copyright.h> ! 3: ! 4: /* ! 5: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. ! 6: * ! 7: * All Rights Reserved ! 8: * ! 9: * Permission to use, copy, modify, and distribute this software and its ! 10: * documentation for any purpose and without fee is hereby granted, ! 11: * provided that the above copyright notice appear in all copies and that ! 12: * both that copyright notice and this permission notice appear in ! 13: * supporting documentation, and that the name of Digital Equipment ! 14: * Corporation not be used in advertising or publicity pertaining to ! 15: * distribution of the software without specific, written prior permission. ! 16: * ! 17: * ! 18: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 19: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 20: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 21: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 22: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 23: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 24: * SOFTWARE. ! 25: */ ! 26: ! 27: ! 28: /* ! 29: * MODIFICATION HISTORY ! 30: * ! 31: * 000 -- M. Gancarz, DEC Ultrix Engineering Group ! 32: * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group, ! 33: * Western Software Lab. Convert to X11. ! 34: */ ! 35: ! 36: #ifndef lint ! 37: static char *sccsid = "%W% %G%"; ! 38: #endif ! 39: ! 40: #include <sys/time.h> ! 41: #include "uwm.h" ! 42: ! 43: #ifdef PROFIL ! 44: #include <signal.h> ! 45: /* ! 46: * Dummy handler for profiling. ! 47: */ ! 48: ptrap() ! 49: { ! 50: exit(0); ! 51: } ! 52: #endif ! 53: ! 54: #include <fcntl.h> ! 55: ! 56: #define gray_width 16 ! 57: #define gray_height 16 ! 58: static char gray_bits[] = { ! 59: 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, ! 60: 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, ! 61: 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, ! 62: 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa ! 63: }; ! 64: ! 65: ! 66: ! 67: Bool NeedRootInput=FALSE; ! 68: Bool ChkMline(); ! 69: char *sfilename; ! 70: extern FILE *yyin; ! 71: ! 72: /* ! 73: * Main program. ! 74: */ ! 75: main(argc, argv, environ) ! 76: int argc; ! 77: char **argv; ! 78: char **environ; ! 79: { ! 80: int hi; /* Button event high detail. */ ! 81: int lo; /* Button event low detail. */ ! 82: int x, y; /* Mouse X and Y coordinates. */ ! 83: int root_x, root_y; /* Mouse root X and Y coordinates. */ ! 84: int cur_x, cur_y; /* Current mouse X and Y coordinates. */ ! 85: int down_x, down_y; /* mouse X and Y at ButtonPress. */ ! 86: int str_width; /* Width in pixels of output string. */ ! 87: int pop_width, pop_height; /* Pop up window width and height. */ ! 88: int context; /* Root, window, or icon context. */ ! 89: int ptrmask; /* for QueryPointer */ ! 90: Bool func_stat; /* If true, function swallowed a ButtonUp. */ ! 91: Bool delta_done; /* If true, then delta functions are done. */ ! 92: Bool local; /* If true, then do not use system defaults. */ ! 93: register Binding *bptr; /* Pointer to Bindings list. */ ! 94: char *root_name; /* Root window name. */ ! 95: char *display = NULL; /* Display name pointer. */ ! 96: char message[128]; /* Error message buffer. */ ! 97: char *rc_file; /* Pointer to $HOME/.uwmrc. */ ! 98: Window event_win; /* Event window. */ ! 99: Window sub_win; /* Subwindow for XUpdateMouse calls. */ ! 100: Window root; /* Root window for QueryPointer. */ ! 101: XWindowAttributes event_info; /* Event window info. */ ! 102: XEvent button_event; /* Button input event. */ ! 103: GC gc; /* graphics context for gray background */ ! 104: XImage grayimage; /* for gray background */ ! 105: XGCValues xgc; /* to create font GCs */ ! 106: char *malloc(); ! 107: Bool fallbackMFont = False, /* using default GC font for menus, */ ! 108: fallbackPFont = False, /* popups, */ ! 109: fallbackIFont = False; /* icons */ ! 110: ! 111: #ifdef PROFIL ! 112: signal(SIGTERM, ptrap); ! 113: #endif ! 114: ! 115: /* ! 116: * Set up internal defaults. ! 117: */ ! 118: SetVarDefaults(); ! 119: ! 120: /* ! 121: * Parse the command line arguments. ! 122: */ ! 123: Argv = argv; ! 124: Environ = environ; ! 125: argc--, argv++; ! 126: while (argc) { ! 127: if (**argv == '-') { ! 128: if (!(strcmp(*argv, "-f"))) { ! 129: argc--, argv++; ! 130: if ((argc == 0) || (Startup_File[0] != '\0')) ! 131: Usage(); ! 132: strncpy(Startup_File, *argv, NAME_LEN); ! 133: } ! 134: else if (!(strcmp(*argv, "-b"))) ! 135: local = TRUE; ! 136: else Usage(); ! 137: } ! 138: else display = *argv; ! 139: argc--, argv++; ! 140: } ! 141: ! 142: /* ! 143: * Initialize the default bindings. ! 144: */ ! 145: if (!local) ! 146: InitBindings(); ! 147: ! 148: /* ! 149: * Read in and parse $HOME/.uwmrc, if it exists. ! 150: */ ! 151: sfilename = rc_file = malloc(NAME_LEN); ! 152: sprintf(rc_file, "%s/.uwmrc", getenv("HOME")); ! 153: if ((yyin = fopen(rc_file, "r")) != NULL) { ! 154: Lineno = 1; ! 155: yyparse(); ! 156: fclose(yyin); ! 157: if (Startup_File_Error) ! 158: Error("Bad .uwmrc file...aborting"); ! 159: } ! 160: ! 161: /* ! 162: * Read in and parse the startup file from the command line, if ! 163: * specified. ! 164: */ ! 165: if (Startup_File[0] != '\0') { ! 166: sfilename = Startup_File; ! 167: if ((yyin = fopen(Startup_File, "r")) == NULL) { ! 168: sprintf(message, "Cannot open startup file '%s'", Startup_File); ! 169: Error(message); ! 170: } ! 171: Lineno = 1; ! 172: yyparse(); ! 173: fclose(yyin); ! 174: if (Startup_File_Error) ! 175: Error("Bad startup file...aborting"); ! 176: } ! 177: ! 178: /* ! 179: * Verify the menu bindings. ! 180: */ ! 181: VerifyMenuBindings(); ! 182: if (Startup_File_Error) ! 183: Error("Bad startup file...aborting"); ! 184: ! 185: /* ! 186: * Open the display. ! 187: */ ! 188: if ((dpy = XOpenDisplay(display)) == NULL) ! 189: Error("Unable to open display"); ! 190: scr = DefaultScreen(dpy); ! 191: /* XSynchronize(dpy, 1); */ ! 192: ! 193: /* ! 194: * Set XErrorFunction to be non-terminating. ! 195: */ ! 196: XSetErrorHandler(XError); ! 197: ! 198: ! 199: /* ! 200: * Force child processes to disinherit the TCP file descriptor. ! 201: * This helps shell commands forked and exec'ed from menus ! 202: * to work properly. ! 203: */ ! 204: if ((status = fcntl(ConnectionNumber(dpy), F_SETFD, 1)) == -1) { ! 205: perror("uwm: child cannot disinherit TCP fd"); ! 206: Error("TCP file descriptor problems"); ! 207: } ! 208: ! 209: /* ! 210: * If the root window has not been named, name it. ! 211: */ ! 212: status = XFetchName(dpy, RootWindow(dpy, scr), &root_name); ! 213: if (root_name == NULL) ! 214: XStoreName(dpy, RootWindow(dpy, scr), " X Root Window "); ! 215: else free(root_name); ! 216: ! 217: ! 218: ScreenHeight = DisplayHeight(dpy, scr); ! 219: ScreenWidth = DisplayWidth(dpy, scr); ! 220: ! 221: /* ! 222: * Create and store the icon background pixmap. ! 223: */ ! 224: GrayPixmap = (Pixmap)XCreatePixmap(dpy, RootWindow(dpy, scr), ! 225: gray_width, gray_height, DefaultDepth(dpy,scr)); ! 226: xgc.foreground = BlackPixel(dpy, scr); ! 227: xgc.background = WhitePixel(dpy, scr); ! 228: gc = XCreateGC(dpy, GrayPixmap, GCForeground+GCBackground, &xgc); ! 229: grayimage.height = gray_width; ! 230: grayimage.width = gray_height; ! 231: grayimage.xoffset = 0; ! 232: grayimage.format = XYBitmap; ! 233: grayimage.data = (char *)gray_bits; ! 234: grayimage.byte_order = LSBFirst; ! 235: grayimage.bitmap_unit = 8; ! 236: grayimage.bitmap_bit_order = LSBFirst; ! 237: grayimage.bitmap_pad = 16; ! 238: grayimage.bytes_per_line = 2; ! 239: grayimage.depth = 1; ! 240: XPutImage(dpy, GrayPixmap, gc, &grayimage, 0, 0, ! 241: 0, 0, gray_width, gray_height); ! 242: XFreeGC(dpy, gc); ! 243: ! 244: ! 245: /* ! 246: * Set up icon window, icon cursor and pop-up window color parameters. ! 247: */ ! 248: if (Reverse) { ! 249: IBorder = WhitePixel(dpy, scr); ! 250: IBackground = GrayPixmap; ! 251: ITextForground = WhitePixel(dpy, scr); ! 252: ITextBackground = BlackPixel(dpy, scr); ! 253: PBorder = BlackPixel(dpy, scr); ! 254: PBackground = WhitePixel(dpy, scr); ! 255: PTextForground = BlackPixel(dpy, scr); ! 256: PTextBackground = WhitePixel(dpy, scr); ! 257: MBorder = WhitePixel(dpy, scr); ! 258: MBackground = BlackPixel(dpy, scr); ! 259: MTextForground = WhitePixel(dpy, scr); ! 260: MTextBackground = BlackPixel(dpy, scr); ! 261: } ! 262: else { ! 263: IBorder = BlackPixel(dpy, scr); ! 264: IBackground = GrayPixmap; ! 265: ITextForground = BlackPixel(dpy, scr); ! 266: ITextBackground = WhitePixel(dpy, scr); ! 267: PBorder = WhitePixel(dpy, scr); ! 268: PBackground = BlackPixel(dpy, scr); ! 269: PTextForground = WhitePixel(dpy, scr); ! 270: PTextBackground = BlackPixel(dpy, scr); ! 271: MBorder = BlackPixel(dpy, scr); ! 272: MBackground = WhitePixel(dpy, scr); ! 273: MTextForground = BlackPixel(dpy, scr); ! 274: MTextBackground = WhitePixel(dpy, scr); ! 275: } ! 276: ! 277: /* ! 278: * Store all the cursors. ! 279: */ ! 280: StoreCursors(); ! 281: ! 282: /* ! 283: * grab the mouse buttons according to the map structure ! 284: */ ! 285: Grab_Buttons(); ! 286: ! 287: /* ! 288: * Set initial focus to PointerRoot. ! 289: */ ! 290: XSetInputFocus(dpy, PointerRoot, None, CurrentTime); ! 291: ! 292: /* ! 293: * watch for initial window mapping and window destruction ! 294: */ ! 295: XSelectInput(dpy, RootWindow(dpy, scr), ! 296: SubstructureNotifyMask|SubstructureRedirectMask|FocusChangeMask| ! 297: (NeedRootInput ? EVENTMASK|OwnerGrabButtonMask : 0)); ! 298: ! 299: /* ! 300: * Retrieve the information structure for the specifed fonts and ! 301: * set the global font information pointers. ! 302: */ ! 303: IFontInfo = XLoadQueryFont(dpy, IFontName); ! 304: if (IFontInfo == NULL) { ! 305: fprintf(stderr, "uwm: Unable to open icon font '%s', using server default.\n", ! 306: IFontName); ! 307: IFontInfo = XQueryFont(dpy, DefaultGC(dpy, scr)->gid); ! 308: fallbackIFont = True; ! 309: } ! 310: PFontInfo = XLoadQueryFont(dpy, PFontName); ! 311: if (PFontInfo == NULL) { ! 312: fprintf(stderr, "uwm: Unable to open resize font '%s', using server default.\n", ! 313: PFontName); ! 314: if (fallbackIFont) ! 315: PFontInfo = IFontInfo; ! 316: else ! 317: PFontInfo = XQueryFont(dpy, DefaultGC(dpy, scr)->gid); ! 318: fallbackPFont = True; ! 319: } ! 320: MFontInfo = XLoadQueryFont(dpy, MFontName); ! 321: if (MFontInfo == NULL) { ! 322: fprintf(stderr, "uwm: Unable to open menu font '%s', using server default.\n", ! 323: MFontName); ! 324: if (fallbackIFont || fallbackPFont) ! 325: MFontInfo = fallbackPFont ? PFontInfo : IFontInfo; ! 326: else ! 327: MFontInfo = XQueryFont(dpy, DefaultGC(dpy, scr)->gid); ! 328: fallbackMFont = True; ! 329: } ! 330: ! 331: /* ! 332: * Calculate size of the resize pop-up window. ! 333: */ ! 334: str_width = XTextWidth(PFontInfo, PText, strlen(PText)); ! 335: pop_width = str_width + (PPadding << 1); ! 336: PWidth = pop_width + (PBorderWidth << 1); ! 337: pop_height = PFontInfo->ascent + PFontInfo->descent + (PPadding << 1); ! 338: PHeight = pop_height + (PBorderWidth << 1); ! 339: ! 340: /* ! 341: * Create the pop-up window. Create it at (0, 0) for now. We will ! 342: * move it where we want later. ! 343: */ ! 344: Pop = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), ! 345: 0, 0, ! 346: pop_width, pop_height, ! 347: PBorderWidth, ! 348: PBorder, PBackground); ! 349: if (Pop == FAILURE) Error("Can't create pop-up dimension display window."); ! 350: ! 351: /* ! 352: * Create the menus for later use. ! 353: */ ! 354: CreateMenus(); ! 355: ! 356: /* ! 357: * Create graphics context. ! 358: */ ! 359: xgc.foreground = ITextForground; ! 360: xgc.background = ITextBackground; ! 361: xgc.font = IFontInfo->fid; ! 362: xgc.graphics_exposures = FALSE; ! 363: IconGC = XCreateGC(dpy, ! 364: RootWindow(dpy, scr), ! 365: GCForeground+GCBackground+GCGraphicsExposures ! 366: +(fallbackIFont ? 0 : GCFont), &xgc); ! 367: xgc.foreground = MTextForground; ! 368: xgc.background = MTextBackground; ! 369: xgc.font = MFontInfo->fid; ! 370: MenuGC = XCreateGC(dpy, ! 371: RootWindow(dpy, scr), ! 372: GCForeground+GCBackground+(fallbackMFont ? 0 : GCFont), &xgc); ! 373: xgc.function = GXinvert; ! 374: xgc.plane_mask = MTextForground ^ MTextBackground; ! 375: MenuInvGC = XCreateGC(dpy, ! 376: RootWindow(dpy, scr), GCForeground+GCFunction+GCPlaneMask, &xgc); ! 377: xgc.foreground = PTextForground; ! 378: xgc.background = PTextBackground; ! 379: xgc.font = PFontInfo->fid; ! 380: PopGC = XCreateGC(dpy, ! 381: RootWindow(dpy, scr), ! 382: GCForeground+GCBackground+(fallbackPFont ? 0 : GCFont), &xgc); ! 383: xgc.line_width = DRAW_WIDTH; ! 384: xgc.foreground = DRAW_VALUE; ! 385: xgc.function = DRAW_FUNC; ! 386: xgc.subwindow_mode = IncludeInferiors; ! 387: DrawGC = XCreateGC(dpy, RootWindow(dpy, scr), ! 388: GCLineWidth+GCForeground+GCFunction+GCSubwindowMode, &xgc); ! 389: ! 390: ! 391: /* ! 392: * Tell the user we're alive and well. ! 393: */ ! 394: XBell(dpy, VOLUME_PERCENTAGE(Volume)); ! 395: ! 396: /* ! 397: * Main command loop. ! 398: */ ! 399: while (TRUE) { ! 400: ! 401: delta_done = func_stat = FALSE; ! 402: ! 403: /* ! 404: * Get the next mouse button event. Spin our wheels until ! 405: * a ButtonPressed event is returned. ! 406: * Note that mouse events within an icon window are handled ! 407: * in the "GetButton" function or by the icon's owner if ! 408: * it is not uwm. ! 409: */ ! 410: while (TRUE) { ! 411: if (!GetButton(&button_event)) continue; ! 412: if (button_event.type == ButtonPress) break; ! 413: } ! 414: ! 415: /* save mouse coords in case we want them later for a delta action */ ! 416: down_x = ((XButtonPressedEvent *)&button_event)->x; ! 417: down_y = ((XButtonPressedEvent *)&button_event)->y; ! 418: /* ! 419: * Okay, determine the event window and mouse coordinates. ! 420: */ ! 421: status = XTranslateCoordinates(dpy, ! 422: RootWindow(dpy, scr), RootWindow(dpy, scr), ! 423: ((XButtonPressedEvent *)&button_event)->x, ! 424: ((XButtonPressedEvent *)&button_event)->y, ! 425: &x, &y, ! 426: &event_win); ! 427: ! 428: if (status == FAILURE) continue; ! 429: ! 430: /* ! 431: * Determine the event window and context. ! 432: */ ! 433: if (event_win == 0) { ! 434: event_win = RootWindow(dpy, scr); ! 435: context = ROOT; ! 436: } else { ! 437: if (IsIcon(event_win, 0, 0, FALSE, NULL)) ! 438: context = ICON; ! 439: else context = WINDOW; ! 440: } ! 441: ! 442: /* ! 443: * Get the button event detail. ! 444: */ ! 445: lo = ((XButtonPressedEvent *)&button_event)->button; ! 446: hi = ((XButtonPressedEvent *)&button_event)->state; ! 447: ! 448: /* ! 449: * Determine which function was selected and invoke it. ! 450: */ ! 451: for(bptr = Blist; bptr; bptr = bptr->next) { ! 452: ! 453: if ((bptr->button != lo) || ! 454: (((int)bptr->mask & ModMask) != hi)) ! 455: continue; ! 456: ! 457: if (bptr->context != context) ! 458: continue; ! 459: ! 460: if (!(bptr->mask & ButtonDown)) ! 461: continue; ! 462: ! 463: /* ! 464: * Found a match! Invoke the function. ! 465: */ ! 466: if ((*bptr->func)(event_win, ! 467: (int)bptr->mask & ModMask, ! 468: bptr->button, ! 469: x, y, ! 470: bptr->menu)) { ! 471: func_stat = TRUE; ! 472: break; ! 473: } ! 474: } ! 475: ! 476: /* ! 477: * If the function ate the ButtonUp event, then restart the loop. ! 478: */ ! 479: if (func_stat) continue; ! 480: ! 481: while(TRUE) { ! 482: /* ! 483: * Wait for the next button event. ! 484: */ ! 485: if (XPending(dpy) && GetButton(&button_event)) { ! 486: ! 487: /* ! 488: * If it's not a release of the same button that was pressed, ! 489: * don't do the function bound to 'ButtonUp'. ! 490: */ ! 491: if (button_event.type != ButtonRelease) ! 492: break; ! 493: if (lo != ((XButtonReleasedEvent *)&button_event)->button) ! 494: break; ! 495: if ((hi|ButtonMask(lo)) != ! 496: ((XButtonReleasedEvent *)&button_event)->state) ! 497: break; ! 498: ! 499: /* ! 500: * Okay, determine the event window and mouse coordinates. ! 501: */ ! 502: status = XTranslateCoordinates(dpy, ! 503: RootWindow(dpy, scr), RootWindow(dpy, scr), ! 504: ((XButtonReleasedEvent *)&button_event)->x, ! 505: ((XButtonReleasedEvent *)&button_event)->y, ! 506: &x, &y, ! 507: &event_win); ! 508: ! 509: if (status == FAILURE) break; ! 510: ! 511: if (event_win == 0) { ! 512: event_win = RootWindow(dpy, scr); ! 513: context = ROOT; ! 514: } else { ! 515: if (IsIcon(event_win, 0, 0, FALSE, NULL)) ! 516: context = ICON; ! 517: else context = WINDOW; ! 518: } ! 519: ! 520: /* ! 521: * Determine which function was selected and invoke it. ! 522: */ ! 523: for(bptr = Blist; bptr; bptr = bptr->next) { ! 524: ! 525: if ((bptr->button != lo) || ! 526: (((int)bptr->mask & ModMask) != hi)) ! 527: continue; ! 528: ! 529: if (bptr->context != context) ! 530: continue; ! 531: ! 532: if (!(bptr->mask & ButtonUp)) ! 533: continue; ! 534: ! 535: /* ! 536: * Found a match! Invoke the function. ! 537: */ ! 538: (*bptr->func)(event_win, ! 539: (int)bptr->mask & ModMask, ! 540: bptr->button, ! 541: x, y, ! 542: bptr->menu); ! 543: } ! 544: break; ! 545: } ! 546: ! 547: XQueryPointer(dpy, RootWindow(dpy, scr), ! 548: &root, &event_win, &root_x, &root_y, &cur_x, &cur_y, &ptrmask); ! 549: if (!delta_done && ! 550: ((abs(cur_x - x) > Delta) || (abs(cur_y - y) > Delta))) { ! 551: /* ! 552: * Delta functions are done once (and only once.) ! 553: */ ! 554: delta_done = TRUE; ! 555: ! 556: /* ! 557: * Determine the new event window's coordinates. ! 558: * from the original ButtonPress event ! 559: */ ! 560: status = XTranslateCoordinates(dpy, ! 561: RootWindow(dpy, scr), RootWindow(dpy, scr), ! 562: down_x, down_y, &x, &y, &event_win); ! 563: if (status == FAILURE) break; ! 564: ! 565: /* ! 566: * Determine the event window and context. ! 567: */ ! 568: if (event_win == 0) { ! 569: event_win = RootWindow(dpy, scr); ! 570: context = ROOT; ! 571: } else { ! 572: if (IsIcon(event_win, 0, 0, FALSE, NULL)) ! 573: context = ICON; ! 574: else context = WINDOW; ! 575: } ! 576: ! 577: /* ! 578: * Determine which function was selected and invoke it. ! 579: */ ! 580: for(bptr = Blist; bptr; bptr = bptr->next) { ! 581: ! 582: if ((bptr->button != lo) || ! 583: (((int)bptr->mask & ModMask) != hi)) ! 584: continue; ! 585: ! 586: if (bptr->context != context) ! 587: continue; ! 588: ! 589: if (!(bptr->mask & DeltaMotion)) ! 590: continue; ! 591: ! 592: /* ! 593: * Found a match! Invoke the function. ! 594: */ ! 595: if ((*bptr->func)(event_win, ! 596: (int)bptr->mask & ModMask, ! 597: bptr->button, ! 598: x, y, ! 599: bptr->menu)) { ! 600: func_stat = TRUE; ! 601: break; ! 602: } ! 603: } ! 604: /* ! 605: * If the function ate the ButtonUp event, ! 606: * then restart the loop. ! 607: */ ! 608: if (func_stat) break; ! 609: } ! 610: } ! 611: } ! 612: } ! 613: ! 614: /* ! 615: * Initialize the default bindings. First, write the character array ! 616: * out to a temp file, then point the parser to it and read it in. ! 617: * Afterwards, we unlink the temp file. ! 618: */ ! 619: InitBindings() ! 620: { ! 621: char *mktemp(); ! 622: char *tempfile = TEMPFILE; /* Temporary filename. */ ! 623: register FILE *fp; /* Temporary file pointer. */ ! 624: register char **ptr; /* Default bindings string array pointer. */ ! 625: ! 626: /* ! 627: * Create and write the temp file. ! 628: */ ! 629: sfilename = mktemp(tempfile); ! 630: if ((fp = fopen(tempfile, "w")) == NULL) { ! 631: perror("uwm: cannot create temp file"); ! 632: exit(1); ! 633: } ! 634: for (ptr = DefaultBindings; *ptr; ptr++) { ! 635: fputs(*ptr, fp); ! 636: fputc('\n', fp); ! 637: } ! 638: fclose(fp); ! 639: ! 640: /* ! 641: * Read in the bindings from the temp file and parse them. ! 642: */ ! 643: if ((yyin = fopen(tempfile, "r")) == NULL) { ! 644: perror("uwm: cannot open temp file"); ! 645: exit(1); ! 646: } ! 647: Lineno = 1; ! 648: yyparse(); ! 649: fclose(yyin); ! 650: unlink(tempfile); ! 651: if (Startup_File_Error) ! 652: Error("Bad default bindings...aborting"); ! 653: ! 654: /* ! 655: * Parse the system startup file, if one exists. ! 656: */ ! 657: if ((yyin = fopen(SYSFILE, "r")) != NULL) { ! 658: sfilename = SYSFILE; ! 659: Lineno = 1; ! 660: yyparse(); ! 661: fclose(yyin); ! 662: if (Startup_File_Error) ! 663: Error("Bad system startup file...aborting"); ! 664: } ! 665: } ! 666: ! 667: /* ! 668: * Verify menu bindings by checking that a menu that is mapped actually ! 669: * exists. Stash a pointer in the binding to the relevant menu info data ! 670: * structure. ! 671: * Check nested menu consistency. ! 672: */ ! 673: VerifyMenuBindings() ! 674: { ! 675: Binding *bptr; ! 676: MenuLink *mptr; ! 677: ! 678: for(bptr = Blist; bptr; bptr = bptr->next) { ! 679: if (bptr->func == Menu) { ! 680: for(mptr = Menus; mptr; mptr = mptr->next) { ! 681: if(!(strcmp(bptr->menuname, mptr->menu->name))) { ! 682: bptr->menu = mptr->menu; ! 683: break; ! 684: } ! 685: } ! 686: if (mptr == NULL) { ! 687: fprintf(stderr, ! 688: "uwm: non-existent menu reference: \"%s\"\n", ! 689: bptr->menuname); ! 690: Startup_File_Error = TRUE; ! 691: } ! 692: } ! 693: } ! 694: CheckMenus(); ! 695: } ! 696: ! 697: /* ! 698: * Check nested menu consistency by verifying that every menu line that ! 699: * calls another menu references a menu that actually exists. ! 700: */ ! 701: CheckMenus() ! 702: { ! 703: MenuLink *ptr; ! 704: Bool errflag = FALSE; ! 705: ! 706: for(ptr = Menus; ptr; ptr = ptr->next) { ! 707: if (ChkMline(ptr->menu)) ! 708: errflag = TRUE; ! 709: } ! 710: if (errflag) ! 711: Error("Nested menu inconsistency"); ! 712: } ! 713: ! 714: Bool ChkMline(menu) ! 715: MenuInfo *menu; ! 716: { ! 717: MenuLine *ptr; ! 718: MenuLink *lptr; ! 719: Bool errflag = FALSE; ! 720: ! 721: for(ptr = menu->line; ptr; ptr = ptr->next) { ! 722: if (ptr->type == IsMenuFunction) { ! 723: for(lptr = Menus; lptr; lptr = lptr->next) { ! 724: if(!(strcmp(ptr->text, lptr->menu->name))) { ! 725: ptr->menu = lptr->menu; ! 726: break; ! 727: } ! 728: } ! 729: if (lptr == NULL) { ! 730: fprintf(stderr, ! 731: "uwm: non-existent menu reference: \"%s\"\n", ! 732: ptr->text); ! 733: errflag = TRUE; ! 734: } ! 735: } ! 736: } ! 737: return(errflag); ! 738: } ! 739: ! 740: /* ! 741: * Grab the mouse buttons according to the bindings list. ! 742: */ ! 743: Grab_Buttons() ! 744: { ! 745: Binding *bptr; ! 746: ! 747: for(bptr = Blist; bptr; bptr = bptr->next) ! 748: if ((bptr->context & (WINDOW | ICON | ROOT)) == ROOT) { ! 749: ! 750: /* don't grab buttons if you don't have to - allow application ! 751: access to buttons unless context includes window or icon */ ! 752: ! 753: NeedRootInput = TRUE; ! 754: } ! 755: else { ! 756: /* context includes a window, so must grab */ ! 757: Grab(bptr->mask); ! 758: } ! 759: } ! 760: ! 761: /* ! 762: * Grab a mouse button according to the given mask. ! 763: */ ! 764: Grab(mask) ! 765: unsigned int mask; ! 766: { ! 767: unsigned int m = LeftMask | MiddleMask | RightMask; ! 768: ! 769: switch (mask & m) { ! 770: case LeftMask: ! 771: XGrabButton(dpy, LeftButton, mask & ModMask, ! 772: RootWindow(dpy, scr), TRUE, EVENTMASK, ! 773: GrabModeAsync, GrabModeAsync, None, LeftButtonCursor); ! 774: break; ! 775: ! 776: case MiddleMask: ! 777: XGrabButton(dpy, MiddleButton, mask & ModMask, ! 778: RootWindow(dpy, scr), TRUE, EVENTMASK, ! 779: GrabModeAsync, GrabModeAsync, None, MiddleButtonCursor); ! 780: break; ! 781: ! 782: case RightMask: ! 783: XGrabButton(dpy, RightButton, mask & ModMask, ! 784: RootWindow(dpy, scr), TRUE, EVENTMASK, ! 785: GrabModeAsync, GrabModeAsync, None, RightButtonCursor); ! 786: break; ! 787: } ! 788: } ! 789: ! 790: /* ! 791: * Restore cursor to normal state. ! 792: */ ! 793: ResetCursor(button) ! 794: int button; ! 795: { ! 796: ! 797: switch (button) { ! 798: case LeftButton: ! 799: XChangeActivePointerGrab( ! 800: dpy, EVENTMASK, LeftButtonCursor, CurrentTime); ! 801: break; ! 802: ! 803: case MiddleButton: ! 804: XChangeActivePointerGrab( ! 805: dpy, EVENTMASK, MiddleButtonCursor, CurrentTime); ! 806: break; ! 807: ! 808: case RightButton: ! 809: XChangeActivePointerGrab( ! 810: dpy, EVENTMASK, RightButtonCursor, CurrentTime); ! 811: break; ! 812: } ! 813: } ! 814: ! 815: /* ! 816: * error routine for .uwmrc parser ! 817: */ ! 818: yyerror(s) ! 819: char*s; ! 820: { ! 821: fprintf(stderr, "uwm: %s: %d: %s\n", sfilename, Lineno, s); ! 822: Startup_File_Error = TRUE; ! 823: } ! 824: ! 825: /* ! 826: * Print usage message and quit. ! 827: */ ! 828: Usage() ! 829: { ! 830: fputs("Usage: uwm [-b] [-f <file>] [<host>:<display>]\n\n", stderr); ! 831: fputs("The -b option bypasses system and default bindings\n", stderr); ! 832: fputs("The -f option specifies an additional startup file\n", stderr); ! 833: exit(1); ! 834: } ! 835: ! 836: /* ! 837: * error handler for X I/O errors ! 838: */ ! 839: XIOError(dsp) ! 840: Display *dsp; ! 841: { ! 842: perror("uwm"); ! 843: exit(3); ! 844: } ! 845: ! 846: SetVarDefaults() ! 847: { ! 848: strcpy(IFontName, DEF_FONT); ! 849: strcpy(PFontName, DEF_FONT); ! 850: strcpy(MFontName, DEF_FONT); ! 851: Delta = DEF_DELTA; ! 852: IBorderWidth = DEF_ICON_BORDER_WIDTH; ! 853: HIconPad = DEF_ICON_PADDING; ! 854: VIconPad = DEF_ICON_PADDING; ! 855: PBorderWidth = DEF_POP_BORDER_WIDTH; ! 856: PPadding = DEF_POP_PADDING; ! 857: MBorderWidth = DEF_MENU_BORDER_WIDTH; ! 858: HMenuPad = DEF_MENU_PADDING; ! 859: VMenuPad = DEF_MENU_PADDING; ! 860: Volume = DEF_VOLUME; ! 861: Pushval = DEF_PUSH; ! 862: FocusSetByUser = FALSE; ! 863: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.