1: #include "wm.h"
2:
3: #ifndef lint
4: static char *rcsid_wmsubs_c = "$Header: xnwm.c,v 10.4 86/02/01 16:02:23 tony Rel $";
5: #endif
6:
7: #define default_frame_width 5
8: #define default_mask MetaMask
9: #define "8x13"
10: #define default_size_font "8x13"
11: #define default_icon_font "8x13"
12: #define default_iconify_delta 5
13: #define 0
14: #define 0
15:
16: /* Default button assignments; the numbers are indices into the
17: menuOp array */
18:
19: #define default_left 0
20: #define default_middle 1
21: #define default_right 2
22: #define unassigned_button -1
23: #define -2
24:
25: /* Convert 0,1,2 into XRight(Middle,Left)Mask */
26: #define Button(i) (1 << (8 + (i)))
27:
28: #include "wm.cursor"
29:
30: #include "buttons.raster"
31: Pixmap buttonPixmap[3];
32:
33: Window ;
34: typedef int (*ptrToFunc) ();
35: int Raise(), Lower(), Move(), Resize(), IconifyOrDeIconify(),
36: Select(), Circulate(), Assign(), Unassigned();
37: char *label[] = {"Select", "Raise", "Move", "(De)Iconify",
38: "Lower", "Resize", "Circulate", "Assign", ""};
39: ptrToFunc menuOp[] = {Select, Raise, Move, IconifyOrDeIconify,
40: Lower, Resize, Circulate, Assign};
41: int needsWindow[] = {TRUE, TRUE, TRUE, TRUE,
42: TRUE, TRUE, FALSE, TRUE};
43: int canDoToMenu[] = {FALSE, TRUE, TRUE, FALSE,
44: TRUE, FALSE, TRUE, TRUE};
45: /* "item" needs an extra entry at the end */
46: Window item[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
47: int buttonFunc[3] = {default_right, default_middle, default_left};
48: int itemcount, itemWidth, itemHeight;
49: int , , , ;
50: char code[] = "srmilzc"; /* button assignment codes for command line */
51: int skinny = FALSE, twoRows = FALSE, vertical = FALSE;
52: int = -1;
53: int doingOp = FALSE;
54:
55: int savex, savey; /* Where and what the popup menu obscures */
56: Pixmap saveScreen;
57: Pixmap = 0; /* What the popup menu looks like */
58: int = FALSE; /* True if a popup image is saved */
59:
60: int reverse; /* whether to reverse the normal colors */
61: int buttonGXfunc; /* function to put up the button picture */
62:
63: char *index();
64:
65: main(argc, argv)
66: int argc;
67: char **argv;
68: {
69: Window w;
70: BEvent button;
71: int raisedMenu = FALSE;
72:
73: SetUpEverything(argc, argv);
74:
75: while (TRUE) {
76: GetButton(&button);
77:
78: /* If it's a ButtonReleased ignore; it's just left
79: over from some old click */
80:
81: if (button.type == ButtonReleased) continue;
82:
83: InterpretLocatorW(RootWindow, &w, button.location);
84:
85: /* If in background, raise menu or move back if just raised.
86: If using popup windows, map the popup window. Only do this
87: as long as the button is not bound to Select */
88:
89: if (w == 0 && NonSelect(&button)) {
90: if (popup) MapPopup(button.location);
91: else {
92: if (raisedMenu) XMoveWindow(menu, menuX, menuY);
93: else XRaiseWindow(menu);
94: raisedMenu = TRUE;
95: }
96: continue;
97: } else raisedMenu = FALSE;
98:
99: /* If in menu, do appropriate function */
100:
101: if (w == menu) {
102: ProcessMenuFunction(&button);
103: if (popup) UnmapPopup();
104: continue;
105: }
106:
107: /* Otherwise do preassigned button function */
108:
109: DoButtonFunc(&button, w);
110: }
111: }
112:
113: SetUpEverything(argc, argv)
114: int argc;
115: char **argv;
116: {
117: char *mfname = default_menu_font; /* font to use */
118: char *sfname = default_size_font; /* font to use */
119: char *ifname = default_icon_font; /* font to use */
120: char *location = "";
121: char display[256]; /* display to use */
122:
123: frameWidth = default_frame_width;
124: mask = default_mask;
125: iconifyDelta = default_iconify_delta;
126: menuX = menuY = 0;
127: freeze = TRUE;
128: popup = FALSE;
129: reverse = FALSE;
130:
131: GetDefaults(argv[0], &mfname, &sfname, &ifname, &location);
132: ProcessArgs(argc, argv, display, &mfname, &sfname, &ifname, &location);
133: OpenDisplay (display);
134: StoreCursors();
135: StorePixmaps();
136: SetUpFonts(mfname, sfname, ifname);
137: SetUpMenu(location);
138: GrabButtons();
139: InitializeWm();
140: }
141:
142: GetDefaults(progname, mfname, sfname, ifname, location)
143: char *progname;
144: char **mfname, **sfname, **ifname, **location;
145: {
146: register char *option;
147: int newmask = 0;
148:
149: if ((option = XGetDefault(progname,"MenuFont")) != NULL) {
150: *mfname = option;
151: }
152: if ((option = XGetDefault(progname,"SizeFont")) != NULL) {
153: *sfname = option;
154: }
155: if ((option = XGetDefault(progname,"IconFont")) != NULL) {
156: *ifname = option;
157: }
158: if ((option = XGetDefault(progname,"ReverseVideo")) != NULL) {
159: if (strcmp(option, "on") == 0) reverse = TRUE;
160: }
161: if ((option = XGetDefault(progname,"FrameWidth")) != NULL) {
162: frameWidth = atoi(option);
163: }
164: if ((option = XGetDefault(progname,"IconifyDelta")) != NULL) {
165: iconifyDelta = atoi(option);
166: }
167: if ((option = XGetDefault(progname,"MenuFormat")) != NULL) {
168: if (index(option, 't') != NULL) skinny = TRUE;
169: if (index(option, '2') != NULL) twoRows = skinny = TRUE;
170: if (index(option, 'v') != NULL) vertical = skinny = TRUE;
171: }
172: if ((option = XGetDefault(progname,"Freeze")) != NULL) {
173: if (strcmp(option, "off") == 0) freeze = FALSE;
174: }
175: if ((option = XGetDefault(progname,"KeyCombination")) != NULL) {
176: if (index(option, 'c') != NULL) newmask |= ControlMask;
177: if (index(option, 's') != NULL) newmask |= ShiftMask;
178: if (index(option, 'm') != NULL) newmask |= MetaMask;
179: if (index(option, 'l') != NULL) newmask |= ShiftLockMask;
180: if (index(option, 'n') != NULL) mask = 0;
181: else if (newmask) mask = newmask;
182: }
183: if ((option = XGetDefault(progname,"LeftButton")) != NULL) {
184: AssignButton(LeftButton, option[0]);
185: }
186: if ((option = XGetDefault(progname,"MiddleButton")) != NULL) {
187: AssignButton(MiddleButton, option[0]);
188: }
189: if ((option = XGetDefault(progname,"RightButton")) != NULL) {
190: AssignButton(RightButton, option[0]);
191: }
192: if ((option = XGetDefault(progname,"Geometry")) != NULL) {
193: *location = option;
194: }
195:
196: }
197:
198: ProcessArgs(argc, argv, display, mfname, sfname, ifname, location)
199: int argc;
200: char **argv;
201: char *display;
202: char **mfname, **sfname, **ifname, **location;
203: {
204: int i, newmask = 0, none = FALSE;
205: register char *arg;
206:
207: for (i = 1; i < argc; i++) {
208: arg = argv[i];
209: switch (*arg) {
210: case '\0':
211: continue;
212:
213: case '-':
214: arg++;
215: if (*arg == '\0') mask = 0;
216: else {
217: newmask = 0;
218: for (; *arg; arg++) {
219: switch (*arg) {
220: case 'h':
221: Syntax();
222: break;
223:
224: case 'c':
225: newmask |= ControlMask;
226: break;
227:
228: case 's':
229: newmask |= ShiftMask;
230: break;
231:
232: case 'm':
233: newmask |= MetaMask;
234: break;
235:
236: case 'l':
237: newmask |= ShiftLockMask;
238: break;
239:
240: case 'n':
241: none = TRUE;
242: break;
243:
244: case 'f':
245: freeze = FALSE;
246: break;
247:
248: case 'r':
249: reverse = TRUE;
250: break;
251:
252: case '2':
253: twoRows = skinny = TRUE;
254: vertical = FALSE;
255: break;
256:
257: case 'v':
258: vertical = skinny = TRUE;
259: twoRows = FALSE;
260: break;
261:
262: case 't':
263: skinny = TRUE;
264: vertical = twoRows = FALSE;
265: break;
266:
267: default:
268: Syntax();
269: break;
270: }
271: }
272: if (newmask) mask = newmask;
273: if (none) mask = 0;
274: }
275: break;
276:
277: case '@':
278: frameWidth = atoi(arg+1);
279: if (frameWidth < 0 || frameWidth > 100) {
280: errno = EDOM;
281: perror("xnwm:");
282: }
283: break;
284:
285: case '%':
286: iconifyDelta = atoi(arg+1);
287: break;
288:
289: case '=':
290: *location = arg+1;
291: break;
292:
293: default:
294: if (arg[1] == '=') {
295: switch (*arg) {
296: case 'l':
297: AssignButton(LeftButton, arg[2]);
298: break;
299:
300: case 'm':
301: AssignButton(MiddleButton, arg[2]);
302: break;
303:
304: case 'r':
305: AssignButton(RightButton, arg[2]);
306: break;
307:
308: default:
309: Syntax();
310: break;
311: }
312: } else if (arg[0] == 'f' && arg[2] == '=') {
313: switch (arg[1]) {
314: case 'm':
315: *mfname = arg+3;
316: break;
317:
318: case 's':
319: *sfname = arg+3;
320: break;
321:
322: case 'i':
323: *ifname = arg+3;
324: break;
325:
326: default:
327: Syntax();
328: break;
329: }
330: } else strcpy(display, arg);
331: }
332: }
333:
334: if (buttonFunc[RightButton] == popup_button ||
335: buttonFunc[MiddleButton] == popup_button ||
336: buttonFunc[LeftButton] == popup_button) {
337: popup = vertical = skinny = TRUE;
338: }
339: }
340:
341: AssignButton(which, arg)
342: int which;
343: char arg;
344: {
345: char *ch;
346:
347: if (arg == '\0') {
348: buttonFunc[which] = unassigned_button;
349: return;
350: } else if (arg == 'p') {
351: buttonFunc[which] = popup_button;
352: return;
353: }
354: ch = index(code, arg);
355: if (ch == NULL) {
356: errno = EDOM;
357: perror ("xnwm:");
358: } else buttonFunc[which] = ch - code;
359: }
360:
361: Syntax()
362: {
363: puts("Usage: xnwm {-csmln} {-f} {-r} {-2vt} {@[framewidth]}");
364: puts(" {%[iconifyDelta]} {=[{+-}xoff[{+-}yoff]]}");
365: puts(" {l={srmilzcp}} {m={srmilzcp}} {r={srmilzcp}}");
366: puts(" {fm=menu_font} {fs=size_font} {fi=icon_font}");
367: puts(" {[host]:vs}"); /* whew */
368:
369: exit(0);
370: }
371:
372: OpenDisplay(display)
373: char *display;
374: {
375: WindowInfo winfo;
376:
377: if (XOpenDisplay(display) == NULL) {
378: Error ("Couldn't open display in OpenDisplay");
379: }
380:
381: QueryWindow(RootWindow, &winfo);
382: screen_height = winfo.height;
383: screen_width = winfo.width;
384:
385: XSelectInput(RootWindow,
386: ButtonPressed | ButtonReleased | UnmapWindow | FocusChange);
387:
388: if (reverse) {
389: bgColor = BlackPixel;
390: bgPixmap = BlackPixmap;
391: fgColor = WhitePixel;
392: fgPixmap = WhitePixmap;
393: buttonGXfunc = GXor;
394: } else {
395: bgColor = WhitePixel;
396: bgPixmap = WhitePixmap;
397: fgColor = BlackPixel;
398: fgPixmap = BlackPixmap;
399: buttonGXfunc = GXand;
400: }
401: }
402:
403: StoreCursors()
404: {
405: wmCursor = XCreateCursor(nwm_width, nwm_height,
406: (caddr_t) nwm_bits, (caddr_t) NULL,
407: 1, 1,
408: fgColor, bgColor,
409: GXcopyInverted);
410: if (wmCursor == NULL) {
411: Error("Couldn't store wmCursor in StoreCursors");
412: }
413: }
414:
415: StorePixmaps()
416: {
417: static short gray_bits[] = {
418: 0xaaaa, 0x5555, 0xaaaa, 0x5555,
419: 0xaaaa, 0x5555, 0xaaaa, 0x5555,
420: 0xaaaa, 0x5555, 0xaaaa, 0x5555,
421: 0xaaaa, 0x5555, 0xaaaa, 0x5555
422: };
423:
424: buttonPixmap[RightButton] =
425: MakePixmap(button_width, button_height,
426: (caddr_t) rbutton_bits, bgColor, fgColor);
427:
428: buttonPixmap[MiddleButton] =
429: MakePixmap(button_width, button_height,
430: (caddr_t) mbutton_bits, bgColor, fgColor);
431:
432: buttonPixmap[LeftButton] =
433: MakePixmap(button_width, button_height,
434: (caddr_t) lbutton_bits, bgColor, fgColor);
435:
436: gray = MakePixmap(16, 16,
437: (caddr_t) gray_bits, bgColor, fgColor);
438: }
439:
440: Pixmap MakePixmap(width, height, bits, fg, bg)
441: int width, height;
442: caddr_t bits;
443: int fg, bg;
444: {
445: Bitmap b;
446: Pixmap p;
447:
448: b = XStoreBitmap(width, height, bits);
449: if (b == NULL) Error("Couldn't store bitmap in MakePixmap");
450: p = XMakePixmap (b, fg, bg);
451: if (p == NULL) Error("Couldn't make pixmap in MakePixmap");
452: XFreeBitmap(b);
453: return p;
454: }
455:
456: SetUpFonts(mfname, sfname, ifname)
457: char *mfname, *sfname, *ifname;
458: {
459: menufont = XGetFont(mfname);
460: if (menufont == NULL) Error("Couldn't store menu font in SetUpFont");
461: sizefont = XGetFont(sfname);
462: if (sizefont == NULL) Error("Couldn't store size font in SetUpFont");
463: iconfont = XGetFont(ifname);
464: if (iconfont == NULL) Error("Couldn't store icon font in SetUpFont");
465: }
466:
467: (location)
468: char *location;
469: {
470: register int i = 0;
471: int width = 0, textwidth;
472: int x, y;
473: char xSign, ySign;
474:
475: while (label[i][0] != '\0') {
476: textwidth = XQueryWidth(label[i], menufont);
477: if (textwidth == 0) {
478: Error("Couldn't query string width in SetUpMenu");
479: }
480: if (textwidth > width) width = textwidth;
481: i++;
482: }
483:
484: itemcount = i;
485: if (skinny) {
486: itemWidth = 1 + 3 + width + 3 + button_width + 3 + 1;
487: } else itemWidth = screen_width / itemcount;
488: itemHeight = 20;
489:
490: if (vertical) {
491: menuWidth = itemWidth;
492: menuHeight = itemcount * itemHeight;
493: } else if (twoRows) {
494: menuWidth = itemWidth * ((itemcount+1) >> 1);
495: menuHeight = itemHeight * 2;
496: } else {
497: menuWidth = itemWidth * itemcount;
498: menuHeight = itemHeight;
499: }
500: if (!popup && *location != '\0') {
501: /* Interpret the location string */
502:
503: InterpLocation(location, &x, &y, &xSign, &ySign);
504:
505: if (xSign == '+') menuX = x;
506: else menuX = screen_width - x - menuWidth;
507:
508: if (ySign == '+') menuY = y;
509: else menuY = screen_height - y - menuHeight;
510: }
511:
512: menu = XCreateWindow(RootWindow, menuX, menuY, menuWidth, menuHeight,
513: 1, fgPixmap, bgPixmap);
514: if (menu == NULL) Error ("Couldn't open menu in SetUpMenu");
515: XStoreName(menu, "xnwm menu");
516: XDefineCursor(menu, wmCursor);
517:
518: if (popup) XSelectInput(menu, LeaveWindow);
519: else XSelectInput(menu, ExposeWindow);
520:
521: if (!popup) {
522: x = y = -1;
523:
524: for (i = 0; i < itemcount; i++) {
525: if (twoRows && i == (itemcount+1) >> 1) {
526: y = itemHeight;
527: x = -1;
528: }
529: item[i] = XCreateWindow (menu, x, y, itemWidth, itemHeight, 1,
530: fgPixmap, bgPixmap);
531: if (item[i] == NULL) Error ("Couldn't open item in SetUpMenu");
532: if (vertical) y += itemHeight;
533: else x += itemWidth;
534: }
535: XMapSubwindows(menu);
536: XMapWindow(menu);
537: }
538:
539: menuWidth += 2; /* Consider the border in from now on */
540: menuHeight += 2;
541:
542: /* Don't draw anything; the expose event will cause that */
543: }
544:
545: InterpLocation(location, x, y, xSign, ySign)
546: register char *location;
547: register int *x, *y;
548: char *xSign, *ySign;
549: {
550: *xSign = *location;
551:
552: switch (*location) {
553: case '+':
554: case '-':
555: location++;
556: *x = 0;
557: while(*location >= '0' && *location <= '9') {
558: *x = 10 * *x + (*location++ - '0');
559: }
560: break;
561:
562: default:
563: Syntax();
564: break;
565: }
566:
567: *ySign = *location;
568:
569: switch (*location) {
570: case '+':
571: case '-':
572: location++;
573: *y = 0;
574: while(*location >= '0' && *location <= '9') {
575: *y = 10 * *y + (*location++ - '0');
576: }
577: break;
578:
579: default:
580: Syntax();
581: break;
582: }
583:
584: if (*location != '\0') Syntax();
585: }
586:
587: GrabButtons()
588: {
589: register int i;
590:
591: for (i = 0; i < 3; i++) {
592: if (buttonFunc[i] != unassigned_button) {
593: status = XGrabButton(RootWindow, wmCursor,
594: mask | Button(i),
595: ButtonPressed|ButtonReleased);
596: if (status == NULL) {
597: Error("Couldn't grab button in GrabButtons");
598: }
599: }
600: }
601: }
602:
603: (button)
604: BEvent *button;
605: {
606: Window w;
607: register int i = 0;
608:
609: InterpretLocatorW(menu, &w, button->location);
610: while (item[i] != NULL && item[i] != w) i++;
611:
612: if (item[i]) {
613: InvertButton(i);
614: DoOperation(i, button->detail);
615: DisplayButton(i);
616: lastMenuOp = i;
617: }
618: }
619:
620: DoOperation(i, which)
621: int i, which;
622: {
623: BEvent newbutton;
624: Window w;
625: WindowInfo winfo;
626:
627: /* First wait for the upbutton; if it doesn't occur or
628: occurs in a different window abort */
629:
630: GetButton(&newbutton);
631: InterpretLocatorW(menu, &w, newbutton.location);
632: if (!MatchUp(newbutton, which) || w != item[i]) return;
633:
634: doingOp = TRUE;
635:
636: /* If the function needs a window, get one */
637:
638: if (needsWindow[i]) {
639: status = XGrabMouse(RootWindow, wmCursor,
640: ButtonPressed | ButtonReleased);
641: if (status == NULL) Error ("Couldn't grab mouse in DoOperation");
642: GetButton(&newbutton);
643:
644: /* This should be the same button as was pushed to select
645: the function */
646:
647: if (!MatchDown(newbutton, which)) {
648: XUngrabMouse();
649: doingOp = FALSE;
650: return;
651: }
652:
653: InterpretLocatorW(RootWindow, &w, newbutton.location);
654: if (w == 0) w = RootWindow;
655: QueryWindow(w, &winfo);
656: }
657:
658: /* Now call the appropriate function */
659:
660: if (canDoToMenu[i] || w != menu) {
661: (*menuOp[i])(which, newbutton.location, w, &winfo);
662: }
663: doingOp = FALSE;
664:
665: if (needsWindow[i]) XUngrabMouse();
666: }
667:
668: /* Returns whether or not the button is bound to Select */
669:
670: int NonSelect(button)
671: BEvent *button;
672: {
673: int which = button->detail & 0xff; /* 0, 1, or 2 */
674: int func = buttonFunc[which];
675:
676: return (func < 0 || menuOp[func] != Select);
677: }
678:
679: DoButtonFunc(button, w)
680: BEvent *button;
681: Window w;
682: {
683: int which = button->detail & 0xff; /* 0, 1, or 2 */
684: register int func = buttonFunc[which];
685: WindowInfo winfo;
686:
687: if (func == unassigned_button) {
688: Unassigned();
689: return;
690: }
691:
692: /* popup_button signifies the button to map the popup window */
693:
694: if (func == popup_button) {
695: MapPopup(button->location);
696: return;
697: }
698:
699: if (w == 0) w = RootWindow;
700:
701: if (needsWindow[func]) {
702: status = XGrabMouse(RootWindow, wmCursor,
703: ButtonPressed|ButtonReleased);
704: if (status == 0) Error ("Couldn't grab mouse in DoButtonFunc");
705: QueryWindow(w, &winfo);
706: }
707:
708: InvertButton(func);
709: (*menuOp[func])(which, button->location, w, &winfo);
710: DisplayButton(func);
711:
712: if (needsWindow[func]) XUngrabMouse();
713: }
714:
715: Unassigned()
716: {
717: XFeep (3);
718: }
719:
720: (loc)
721: Locator loc;
722: {
723: int x, y;
724: Window w;
725: register int i;
726:
727: /* If there's not a saved popup image, create the buttons */
728:
729: if (!popupSaved) { /* Create the items */
730: XDestroySubwindows(menu); /* Get rid of old items */
731: x = y = -1;
732: for (i = 0; i < itemcount; i++) {
733: item[i] = XCreateWindow (menu, x, y, itemWidth, itemHeight, 1,
734: fgPixmap, bgPixmap);
735: if (item[i] == NULL) Error ("Couldn't open item in MapPopup");
736: y += itemHeight;
737: }
738: XMapSubwindows(menu);
739: }
740:
741: InterpretLocatorXY(RootWindow, &x, &y, loc);
742:
743: x -= menuWidth >> 1;
744: if (lastMenuOp == -1) y -= menuHeight >> 1;
745: else y -= lastMenuOp * (itemHeight+1) + (itemHeight >> 1);
746:
747: if (x < 0) x = 0;
748: else if (x + menuWidth > screen_width) {
749: x = screen_width - menuWidth;
750: }
751:
752: if (y < 0) y = 0;
753: else if (y + menuHeight > screen_height) {
754: y = screen_height - menuHeight;
755: }
756:
757: if (freeze) {
758: savex = x;
759: savey = y;
760: XGrabServer();
761: saveScreen = XPixmapSave(RootWindow, x, y, menuWidth, menuHeight);
762: if (saveScreen == 0) Error("Couldn't save screen in MapPopup");
763: }
764:
765: XMoveWindow(menu, x, y);
766: XMapWindow(menu);
767:
768: if (popupSaved) {
769: XPixmapPut(menu, 0, 0, 0, 0, menuWidth-2, menuHeight-2,
770: menuImage, GXcopy, AllPlanes);
771: } else {
772: for (i = 0; i < itemcount; i++) DisplayButton(i);;
773: menuImage = XPixmapSave(menu, 0, 0, menuWidth-2, menuHeight-2);
774: if (menuImage == 0) Error("Couldn't save menu in MapPopup");
775: }
776: QueryMouse(RootWindow, &x, &y, &w);
777: if (w != menu) UnmapPopup();
778: }
779:
780: ()
781: {
782: register int x, y, i;
783:
784: if (freeze && saveScreen != 0) {
785: XUnmapTransparent(menu);
786: XPixmapPut(RootWindow, 0, 0, savex, savey, menuWidth, menuHeight,
787: saveScreen, GXcopy, AllPlanes);
788: XFreePixmap(saveScreen);
789: XUngrabServer();
790: saveScreen = 0;
791: } else XUnmapWindow(menu);
792:
793: /* Now set things up so we don't have to map everything next time */
794:
795: if (!popupSaved) {
796: if (menuImage != 0) {
797: XDestroySubwindows(menu); /* Get rid of old items */
798: x = y = 0;
799: for (i = 0; i < itemcount; i++) {
800: item[i] = XCreateTransparency(menu, x, y,
801: itemWidth, itemHeight);
802: if (item[i] == NULL) {
803: Error("Couldn't open item in UnmapPopup");
804: }
805: y += itemHeight;
806: }
807: XMapSubwindows(menu);
808: popupSaved = TRUE;
809: }
810: }
811: }
812:
813: /* Undo the popup menu caching. We can't just test popupSaved, since
814: it gets set in UnmapPopup and we might be called in between */
815:
816: ()
817: {
818: if (menuImage != 0) {
819: XFreePixmap(menuImage);
820: menuImage = 0;
821: }
822:
823: if (popupSaved) popupSaved = FALSE;
824: }
825:
826: InvertButton(i)
827: int i;
828: {
829: if (item[i] == 0) return;
830:
831: XPixFill(item[i], -1, -1, 200, 200, 0, (Bitmap) 0,
832: GXinvert, 1);
833: }
834:
835: DisplayButton(i)
836: int i;
837: {
838: register int j;
839:
840: if (item[i] == 0) return;
841:
842: XPixSet(item[i], -1, -1, 200, 200, bgColor);
843: XText(item[i], 3, 3, label[i], strlen(label[i]), menufont,
844: fgColor, bgColor);
845: for (j = 0; j < 3; j++) {
846: if (buttonFunc[j] == i) {
847: XPixmapPut (item[buttonFunc[j]], 0, 0,
848: itemWidth - button_width - 3, 4,
849: button_width, button_height, buttonPixmap[j],
850: buttonGXfunc, AllPlanes);
851: }
852: }
853: }
854:
855: IconifyOrDeIconify(which, loc, w, winfo)
856: int which;
857: Locator loc;
858: Window w;
859: WindowInfo *winfo;
860: {
861: if (w == RootWindow) return;
862:
863: /* If we're trying to iconify an icon deiconify instead */
864:
865: if (winfo->type == IsIcon) Deiconify(which, loc, w, winfo);
866: else Iconify(which, loc, w, winfo);
867: }
868:
869: /* ARGSUSED */
870:
871: Assign(which, loc, w, winfo)
872: int which;
873: Locator loc;
874: Window w;
875: WindowInfo *winfo;
876: {
877: register int i;
878: int choice, cleared = FALSE;
879: BEvent newbutton;
880: Window neww;
881:
882: /* First make sure the new click was in the menu; if not
883: clear that button */
884:
885: if (w != menu) return;
886:
887: /* Now get rid of the old function assigned this button. But, don't
888: deassign the popup window button! */
889:
890: choice = buttonFunc[which];
891: if (choice == popup_button) return;
892:
893: if (popup) UnsavePopup(); /* The saved popup menu is invalid */
894:
895: if (choice >= 0) {
896: XClear(item[choice]);
897: buttonFunc[which] = unassigned_button;
898: DisplayButton(choice);
899: cleared = TRUE;
900: }
901:
902: /* Now find out which subwindow we were in */
903:
904: InterpretLocatorW(menu, &w, loc);
905: for (i = 0; item[i] != NULL && item[i] != w; i++) {}
906:
907: /* Can't assign Assign */
908:
909: if (menuOp[i] == NULL || menuOp[i] == Assign) {
910: if (cleared) XUngrabButton(mask | Button(which));
911: return;
912: }
913:
914: /* Now wait for the release; if it doesn't occur abort */
915:
916: GetButton(&newbutton);
917: if (!MatchUp(newbutton, which)) {
918: if (cleared) XUngrabButton(mask | Button(which));
919: return;
920: }
921:
922: InterpretLocatorW(menu, &neww, loc);
923:
924: if (neww != w) {
925: if (cleared) XUngrabButton(mask | Button(which));
926: return;
927: }
928:
929: /* Now assign that function to the button */
930:
931: buttonFunc[which] = i;
932:
933: XPixmapPut(item[i], 0, 0,
934: itemWidth - button_width - 3, 4,
935: button_width, button_height, buttonPixmap[which],
936: buttonGXfunc, AllPlanes);
937:
938: if (!cleared) { /* New assignment */
939: status = XGrabButton(RootWindow, wmCursor,
940: mask | Button(which),
941: ButtonPressed|ButtonReleased);
942: if (status == 0) Error ("Couldn't grab button in Assign");
943: }
944: }
945:
946: /* Returns whether or not this is a real event */
947:
948: int GetEvent(event)
949: XEvent *event;
950: {
951: XButtonEvent *be = (XButtonEvent *) event;
952: XLeaveWindowEvent *lwe = (XLeaveWindowEvent *) event;
953: XExposeEvent *ee = (XExposeEvent *) event;
954: XUnmapEvent *ue = (XUnmapEvent *) event;
955: XFocusChangeEvent *fce = (XFocusChangeEvent *) event;
956: WindowInfo winfo;
957: char *iconName;
958:
959: XNextEvent(event);
960:
961: /* If it's in the base window, no trouble */
962:
963: if (event->window == RootWindow) {
964: if (event->type == FocusChange) {
965: if (fce->detail == EnterWindow && fce->subwindow == 0) {
966: FocusOn(RootWindow);
967: FrameFocus();
968: }
969: return FALSE;
970:
971: } else if (event->type == UnmapWindow) {
972: FrameFocus(); /* The background has changed */
973: return FALSE;
974: }
975:
976: be->detail &= 0xff; /* mask out state of shift keys */
977: return TRUE;
978: }
979:
980: /* Is it the menu window? */
981:
982: if (event->window == menu) {
983: if (event->type == ExposeWindow) {
984: if (ee->subwindow != 0) RefreshMenu(ee->subwindow);
985: return FALSE;
986: }
987: if (event->type == LeaveWindow) {
988: if (lwe->subwindow == 0 && !doingOp) UnmapPopup();
989: return FALSE;
990: }
991: }
992:
993: /* Let's see if it's in an icon */
994:
995: QueryWindow(event->window, &winfo);
996:
997: if (winfo.type != IsIcon) return FALSE; /* Nope -- nothing */
998:
999: if (event->type == UnmapWindow) return FALSE;
1000:
1001: status = XFetchName(winfo.assoc_wind, &iconName);
1002: if (status == 0) Error ("Couldn't fetch name in GetButton");
1003:
1004: if (event->type == ExposeWindow) { /* Just refresh the icon */
1005: XClear(ee->window);
1006: if (iconName != NULL && iconName[0] != '\0') {
1007: XText(ee->window, 4, 4, iconName, strlen(iconName), iconfont,
1008: fgColor, bgColor);
1009: }
1010: } else EditIconName((XKeyPressedEvent *)be, iconName);
1011: if (iconName) free(iconName);
1012: return FALSE;
1013: }
1014:
1015: GetButton(event)
1016: BEvent *event;
1017: {
1018: while (!GetEvent(event)) ;
1019: }
1020:
1021: (w)
1022: Window w;
1023: {
1024: register int i;
1025:
1026: for (i = 0; i < itemcount && item[i] != w; i++) {}
1027: if (i >= itemcount) return;
1028: DisplayButton(i);
1029: }
1030:
1031: Error(string)
1032: char *string;
1033: {
1034: fprintf(stderr, "\nxmwm: %s", string);
1035: fprintf(stderr, "\n\n");
1036:
1037: if (errno != 0) {
1038: perror("xwm");
1039: fprintf(stderr, "\n");
1040: }
1041:
1042: exit(1);
1043: }
1044:
1045: Flush()
1046: {
1047: XFlush();
1048: }
1049:
1050: Sync()
1051: {
1052: XSync(FALSE);
1053: }