jkh@ardent.UUCP (Jordan K. Hubbard) (06/06/88)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 7 (of 8)." # Contents: awm.c # Wrapped by jkh@ardent on Sun Jun 5 18:56:37 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'awm.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'awm.c'\" else echo shar: Extracting \"'awm.c'\" \(35562 characters\) sed "s/^X//" >'awm.c' <<'END_OF_FILE' X/* $Header: awm.c,v 1.8 87/08/20 19:17:40 swick Exp $ */ X X/* X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. X * X * All Rights Reserved X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation, and that the name of Digital Equipment X * Corporation not be used in advertising or publicity pertaining to X * distribution of the software without specific, written prior permission. X * X * X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X X X/* X * MODIFICATION HISTORY X * X * 000 -- M. Gancarz, DEC Ultrix Engineering Group X * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group, X * Western Software Lab. Convert to X11. X * 002 -- Jordan Hubbard, U.C. Berkeley. Add title bar context stuff. X * 003 -- Jordan Hubbard, Ardent Computer. Add gadgets. X */ X X#ifndef lint static char *sccsid = "%W% %G%"; X#endif X X#include <sys/time.h> X#include <signal.h> X#include <fcntl.h> X#include <sys/ioctl.h> X#include "awm.h" X#include "X11/Xutil.h" X#include "X11/cursorfont.h" X X#ifdef PROFIL X#include <signal.h> X/* X * Dummy handler for profiling. X */ ptrap() X{ X exit(0); X} X#endif X X#define gray_width 16 X#define gray_height 16 static char gray_bits[] = { X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, X 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa X }; X Boolean NeedRootInput=FALSE; MenuOptionsMask options; char *sfilename; char execfile[NAME_LEN]; /* Pointer to file to exec with -e */ Boolean Snatched; extern FILE *yyin; extern int errorStatus; extern int ErrorHandler(); extern XContext AwmContext; X Pixel ForeColor, BackColor; X X/* X * Main program. X */ main(argc, argv, environ) int argc; char **argv; char **environ; X{ X int hi; /* Button event high detail. */ X int lo; /* Button event low detail. */ X int x, y; /* Mouse X and Y coordinates. */ X int root_x, root_y; /* Mouse root X and Y coordinates. */ X int cur_x, cur_y; /* Current mouse X and Y coordinates. */ X int down_x, down_y; /* mouse X and Y at ButtonPress. */ X int str_width; /* Width in pixels of output string. */ X int pop_width, pop_height; /* Pop up window width and height. */ X int context; /* Root, window, or icon context. */ X int ptrmask; /* for QueryPointer */ X Boolean func_stat; /* If true, function swallowed a ButtonUp. */ X Boolean delta_done; /* If true, then delta functions are done. */ X Boolean local; /* If true, then do not use system defaults. */ X register Binding *bptr; /* Pointer to Bindings list. */ X char *root_name; /* Root window name. */ X char *cp; /* scratch */ X char *display = NULL; /* Display name pointer. */ X char message[128]; /* Error message buffer. */ X char *rc_file; /* Pointer to $HOME/.awmrc. */ X Window event_win; /* Event window. */ X Window sub_win; /* Subwindow for XUpdateMouse calls. */ X Window root; /* Root window for QueryPointer. */ X XWindowAttributes event_info;/* Event window info. */ X AwmInfoPtr awi; X XEvent button_event; /* Button input event. */ X GC gc; /* graphics context for gray background */ X XImage grayimage; /* for gray background */ X XGCValues xgc; /* to create font GCs */ X char *malloc(); X XSetWindowAttributes swa; X unsigned long valuemask; X Window bwin; /* Button window */ X int num; X X /* next three variables are for XQueryWindow */ X Window junk; X Window *kiddies; X unsigned int nkids; X X extern int Fheight; X X Entry("main") X X#ifdef PROFIL X signal(SIGTERM, ptrap); X#endif X X /* X * Parse the command line arguments. X */ X Argv = argv; X Environ = environ; X execfile[0] == '\0'; X local = FALSE; X argc--, argv++; X /* X * The destruction of '-e' args below is to prevent the startup X * command from being invoked again if we do an f.restart (see X * Restart.c and Argv) X */ X while (argc) { X if (**argv == '-') { X if (!strcmp(*argv, "-display") || !strcmp(*argv, "-d")) { X argc--; argv++; X if (argc <= 0) X Usage(); X display = *argv; X } X else if (!(strcmp(*argv, "-f"))) { X argc--, argv++; X if ((argc == 0) || (Startup_File[0] != '\0')) X Usage(); X strncpy(Startup_File, *argv, NAME_LEN); X } X else if (!(strcmp(*argv, "-e"))) { X strcpy(*argv, "--"); /* destroy the arg */ X argc--; argv++; X if ((argc == 0) || (execfile[0] != '\0')) X Usage(); X strncpy(execfile, *argv, NAME_LEN); X } X /* Destroyed arg, skip over what used to be filename for -e */ X else if (!(strcmp(*argv, "--"))) { X argv++; argc--; X continue; X } X else if (!(strcmp(*argv, "-b"))) X local = TRUE; X X else Usage(); X } X else X Usage(); X argc--, argv++; X } X X /* Open the damn display */ X if ((dpy = XOpenDisplay(display)) == NULL) { X fprintf(stderr, "awm: Unable to open display\n"); X exit(1); X } X scr = DefaultScreen(dpy); X X /* X * Set XErrorFunction to be non-terminating. X */ X XSetErrorHandler(ErrorHandler); X X /* X * Force child processes to disinherit the TCP file descriptor. X * This helps shell commands forked and exec'ed from menus X * to work properly. God knows if this works under SysV. X */ X if ((status = fcntl(ConnectionNumber(dpy), F_SETFD, 1)) == -1) { X perror("awm: child cannot disinherit TCP fd"); X Error("TCP file descriptor problems"); X } X X /* X * Initialize the menus for later use. X */ X RTLMenu_Option_Set(options, rightoffset); X RTLMenu_Initialize(options); X X /* X * Create and store the icon background pixmap. X */ X GrayPixmap = (Pixmap)XCreatePixmap(dpy, RootWindow(dpy, scr), X gray_width, gray_height, DefaultDepth(dpy,scr)); X xgc.foreground = BlackPixel(dpy, scr); X xgc.background = WhitePixel(dpy, scr); X gc = XCreateGC(dpy, GrayPixmap, GCForeground | GCBackground, &xgc); X grayimage.height = gray_width; X grayimage.width = gray_height; X grayimage.xoffset = 0; X grayimage.format = XYBitmap; X grayimage.data = (char *)gray_bits; X grayimage.byte_order = LSBFirst; X grayimage.bitmap_unit = 8; X grayimage.bitmap_bit_order = LSBFirst; X grayimage.bitmap_pad = 16; X grayimage.bytes_per_line = 2; X grayimage.depth = 1; X XPutImage(dpy, GrayPixmap, gc, &grayimage, 0, 0, X 0, 0, gray_width, gray_height); X XFreeGC(dpy, gc); X X /* Init the context manager stuff */ X AwmContext = XUniqueContext(); X X /* X * Get all the defaults we expect from the resource manager. X */ X FocusSetByUser = FALSE; X Get_Defaults(); X /* X * Initialize the default bindings. X */ X if (!local) X InitBindings(); X X /* X * Read in and parse $HOME/.awmrc, if it exists. X */ X sfilename = rc_file = malloc(NAME_LEN); X sprintf(rc_file, "%s/.awmrc", getenv("HOME")); X if ((yyin = fopen(rc_file, "r")) != NULL) { X Lineno = 1; X yyparse(); X fclose(yyin); X if (Startup_File_Error) X Error("Bad .awmrc file...aborting"); X } X X /* X * Read in and parse the startup file from the command line, if X * specified. X */ X if (Startup_File[0] != '\0') { X sfilename = Startup_File; X if ((yyin = fopen(Startup_File, "r")) == NULL) { X sprintf(message, "Cannot open startup file '%s'", Startup_File); X Error(message); X } X Lineno = 1; X yyparse(); X fclose(yyin); X if (Startup_File_Error) X Error("Bad startup file...aborting"); X } X X if (Startup_File_Error) X Error("Bad startup file...aborting"); X /* X * Catch some of the basic signals so we don't get rudely killed without X * cleaning up first. X */ X signal(SIGHUP, Quit); X signal(SIGTERM, Quit); X signal(SIGQUIT, Quit); X signal(SIGINT, Quit); X X /* X * If the root window has not been named, name it. X */ X status = XFetchName(dpy, RootWindow(dpy, scr), &root_name); X if (root_name == NULL) X XStoreName(dpy, RootWindow(dpy, scr), " X Root Window "); X else free(root_name); X /* register the root window */ X RegisterWindow(RootWindow(dpy, scr)); X X ScreenHeight = DisplayHeight(dpy, scr); X ScreenWidth = DisplayWidth(dpy, scr); X X/* X*/ X /* X * Create the menus. This function also sticks the RTL menu "handle" into the X * appropriate binding after it's been created and initialized. X */ X Create_Menus(); X X /* X * check the gadgets. X */ X if (CheckGadgets()) { X fprintf(stderr, "Error in gadget declarations. Exiting...\n"); X Cleanup(); X exit(1); X } X X /* X * Store all the cursors. X */ X StoreCursors(); X X /* X * grab the mouse buttons according to the map structure X */ X Grab_Buttons(); X X /* X * Initialize titlebar data. X */ X if (Titles) X Init_Titles(); X /* X * Set initial focus to PointerRoot. X */ X XSetInputFocus(dpy, PointerRoot, None, CurrentTime); X /* X * watch for initial window mapping and window destruction X */ X X errorStatus = False; X swa.event_mask = (SubstructureRedirectMask | FocusChangeMask | X (NeedRootInput ? EVENTMASK | OwnerGrabButtonMask : 0)); X XChangeWindowAttributes(dpy, RootWindow(dpy, scr), CWEventMask, &swa); X XSync(dpy, False); X if (errorStatus == True) { X fprintf(stderr, X "Hmmm.. Looks like you're running another window manager!\n"); X exit(1); X } X /* X * Before we go creating more windows, we buzz through the ones that X * are currently mapped and reparent and/or select on them as necessary X * (for autoraise and titles). X */ X X if (XQueryTree(dpy, DefaultRootWindow(dpy), &junk, &junk, &kiddies, &nkids) X != BadWindow) { X unsigned int i, nmap = 0; X Window *tomap = (Window *)malloc(sizeof(Window) * nkids); X X for (i = 0; i < nkids; i++) { X XWindowAttributes xwa; X Window transient; X AwmInfoPtr awi; X X XGetWindowAttributes(dpy, kiddies[i], &xwa); X X /* check to see if it's a popup or something */ X XGetTransientForHint(dpy, kiddies[i], &transient); X if (xwa.class == InputOutput && xwa.map_state == IsViewable && X xwa.override_redirect == False && transient == None) { X awi = RegisterWindow(kiddies[i]); X awi->placed = TRUE; X if (Titles) { /* add title to this window */ X tomap[nmap++] = AddTitle(kiddies[i]); X if (UseGadgets) { X if (IsTitled(kiddies[i])) X PutGadgets(kiddies[i]); X } X } X XSelectInput(dpy, kiddies[i], (EnterWindowMask | X LeaveWindowMask | X PropertyChangeMask)); X } X } X XFree(kiddies); X for (i = 0; i < nmap; i++) X XMapWindow(dpy, tomap[i]); X free(tomap); X } X /* X * Calculate size of the resize pop-up window. X */ X valuemask = CWBorderPixel | CWBackPixel; X swa.border_pixel = PBorder; X swa.background_pixel = PBackground; X if (SaveUnder) { X swa.save_under = True; X valuemask |= CWSaveUnder; X } X str_width = XTextWidth(PFontInfo, PText, strlen(PText)); X pop_width = str_width + (PPadding << 1); X PWidth = pop_width + (PBorderWidth << 1); X pop_height = PFontInfo->ascent + PFontInfo->descent + (PPadding << 1); X PHeight = pop_height + (PBorderWidth << 1); X X /* X * Create the pop-up window. Create it at (0, 0) for now. We will X * move it where we want later. X */ X Pop = XCreateWindow(dpy, RootWindow(dpy, scr), X 0, 0, X pop_width, pop_height, X PBorderWidth, X 0, X CopyFromParent, X CopyFromParent, X valuemask, X &swa); X if (Pop == FAILURE) X Error("Can't create pop-up dimension display window."); X X /* X * Create graphics context. X */ X xgc.foreground = ITextForeground; X xgc.background = ITextBackground; X xgc.font = IFontInfo->fid; X xgc.graphics_exposures = FALSE; X IconGC = XCreateGC(dpy, X RootWindow(dpy, scr), X (GCForeground|GCBackground|GCGraphicsExposures|GCFont), X &xgc); X X xgc.foreground = PForeground; X xgc.background = PBackground; X xgc.font = PFontInfo->fid; X PopGC = XCreateGC(dpy, X RootWindow(dpy, scr), X (GCForeground|GCBackground|GCFont), &xgc); X xgc.line_width = DRAW_WIDTH; X xgc.foreground = DRAW_VALUE; X xgc.function = DRAW_FUNC; X xgc.subwindow_mode = IncludeInferiors; X DrawGC = XCreateGC(dpy, RootWindow(dpy, scr), X GCLineWidth|GCForeground|GCFunction|GCSubwindowMode, &xgc); X /* X * As our last "startup" task, invoke the execfile if was specified. X */ X if (execfile[0] != '\0') { X if (access(execfile, X_OK) == 0) { X if (vfork() == 0) { X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGHUP, SIG_IGN); X signal(SIGTSTP, SIG_IGN); X execl("/bin/sh", "sh", execfile, 0); X _exit(127); X } X } X } X /* X * Tell the user we're alive and well. X */ X XBell(dpy, VOLUME_PERCENTAGE(Volume)); X X /* X * Main command loop. X */ X while (TRUE) { X X delta_done = func_stat = FALSE; X X /* X * Get the next mouse button event. Spin our wheels until X * a ButtonPressed event is returned. X * Note that mouse events within an icon window are handled X * in the "GetButton" function or by the icon's owner if X * it is not awm. X */ X while (TRUE) { X if (!GetButton(&button_event)) X continue; X else if (button_event.type == ButtonPress) X break; X } X bwin = button_event.xbutton.window; X /* save mouse coords in case we want them later for a delta action */ X down_x = button_event.xbutton.x; X down_y = button_event.xbutton.y; X X /* X * Okay, determine the event window and mouse coordinates. X */ X status = XTranslateCoordinates(dpy, X bwin, X RootWindow(dpy, scr), X button_event.xbutton.x, X button_event.xbutton.y, X &x, &y, X &event_win); X if (status == BadWindow) X continue; X X awi = GetAwmInfo(bwin); X if (awi->frame == bwin) X context = BORDER; X else if (awi->title == bwin) X context = TITLE; X else if (IsGadgetWin(bwin, &num)) X context = GADGET | (1 << (num + BITS_USED)); X else if (awi->icon == bwin) X context = ICON; X else if (awi->client == RootWindow(dpy, scr)) { X event_win = RootWindow(dpy, scr); X context = ROOT; X } X else X context = WINDOW; X /* X * Get the button event detail. X */ X lo = button_event.xbutton.button; X hi = button_event.xbutton.state; X X /* X * Determine which function was selected and invoke it. X */ X for(bptr = Blist; bptr; bptr = bptr->next) { X if ((bptr->button != lo) || X (((int)bptr->mask & ModMask) != hi)) X continue; X X if ((bptr->context & context) != context) X continue; X X if (!(bptr->mask & ButtonDown)) X continue; X X /* X * Found a match! Invoke the function. X */ X if ((*bptr->func)(event_win, (int)bptr->mask & ModMask, X bptr->button, X x, y, X bptr->menu, bptr->menuname)) X func_stat = TRUE; X break; X } X X /* X * If the function ate the ButtonUp event, then restart the loop. X */ X X if (func_stat) X continue; X while (TRUE) { X /* X * Wait for the next button event. X */ X if (XPending(dpy) && GetButton(&button_event)) { X bwin = button_event.xbutton.window; X X /* X * If it's not a release of button that was pressed, X * don't do the function bound to 'ButtonUp'. X */ X if (button_event.type != ButtonRelease) X break; X if (lo != button_event.xbutton.button) X break; X if ((hi | ButtonMask(lo)) != button_event.xbutton.state) X break; X /* X * Okay, determine the event window and mouse coordinates. X */ X status = XTranslateCoordinates(dpy, X bwin, X RootWindow(dpy, scr), X button_event.xbutton.x, X button_event.xbutton.y, X &x, &y, X &event_win); X if (status == BadWindow) X break; X X awi = GetAwmInfo(bwin); X if (awi->frame == bwin) X context = BORDER; X else if (awi->title == bwin) X context = TITLE; X else if (IsGadgetWin(bwin, &num)) X context = GADGET | (1 << (num + BITS_USED)); X else if (bwin == awi->icon) X context = ICON; X else if (!event_win || awi->client == RootWindow(dpy, scr)) { X event_win = RootWindow(dpy, scr); X context = ROOT; X } X else X context = WINDOW; X /* X * Determine which function was selected and invoke it. X */ X for(bptr = Blist; bptr; bptr = bptr->next) { X X if ((bptr->button != lo) || X (((int)bptr->mask & ModMask) != hi)) X continue; X X if (!((bptr->context & context) == context)) X continue; X X if (!(bptr->mask & ButtonUp)) X continue; X X /* X * Found a match! Invoke the function. X */ X X (*bptr->func)(event_win, X (int)bptr->mask & ModMask, X bptr->button, X x, y, X bptr->menu, bptr->menuname); X break; X } X break; X } X XQueryPointer(dpy, RootWindow(dpy, scr), X &root, &junk, &root_x, &root_y, &cur_x, &cur_y, X &ptrmask); X if (!delta_done && X (abs(cur_x - x) > Delta || abs(cur_y - y) > Delta)) { X /* X * Delta functions are done once (and only once.) X */ X delta_done = TRUE; X X /* X * Determine the new event window's coordinates from the original X * ButtonPress event. X */ X status = XTranslateCoordinates(dpy, bwin, RootWindow(dpy, scr), X down_x, down_y, &x, &y, &junk); X if (status == BadWindow) X break; X /* X * Determine the event window and context. X */ X if (awi->title == bwin) X context = TITLE; X else if (IsGadgetWin(bwin, &num)) X context = GADGET | (1 << (num + BITS_USED)); X else if (event_win == RootWindow(dpy, scr)) X context = ROOT; X else if (awi->icon == bwin) X context = ICON; X else X context = WINDOW; X /* X * Determine which function was selected and invoke it. X */ X for(bptr = Blist; bptr; bptr = bptr->next) { X X if ((bptr->button != lo) || X (((int)bptr->mask & ModMask) != hi)) X continue; X X if (!((bptr->context & context) == context)) X continue; X X if (!(bptr->mask & DeltaMotion)) X continue; X X /* X * Found a match! Invoke the function. X */ X X if ((*bptr->func)(event_win, X (int)bptr->mask & ModMask, X bptr->button, X x, y, X bptr->menu, bptr->menuname)) { X func_stat = TRUE; X break; X } X } X break; X } X /* X * If the function ate the ButtonUp event, X * then restart the loop. X */ X X if (func_stat) X break; X } X } X} X X/* X * Get defaults from the resource manager. Most of these things used to be X * in the rc file, but they really belong here, I think. X */ Get_Defaults() X{ X register char *cp; X X /* X * Get the pixmap search path, if it exists. X */ X awmPath = GetStringRes("path", NULL); X X Autoselect = GetBoolRes("autoselect", FALSE); X Autoraise = GetBoolRes("autoraise", FALSE); X Freeze = GetBoolRes("freeze", FALSE); X Grid = GetBoolRes("grid", FALSE); X Titles = GetBoolRes("titles", FALSE); X TitlePush = GetBoolRes("title.push", TRUE); X UseGadgets = GetBoolRes("gadgets", FALSE); X Hilite = GetBoolRes("hilite", FALSE); X RootResizeBox = GetBoolRes("rootResizeBox", FALSE); X ResizeRelative = GetBoolRes("resizeRelative", FALSE); X NIcon = GetBoolRes("normali", TRUE); X ShowName = GetBoolRes("showName", TRUE); X NWindow = GetBoolRes("normalw", TRUE); X Push = GetBoolRes("pushRelative", FALSE); X Reverse = GetBoolRes("reverse", FALSE); X SaveUnder = GetBoolRes("saveUnder", FALSE); X Wall = GetBoolRes("wall", FALSE); X WarpOnRaise = GetBoolRes("warpOnRaise", FALSE); X WarpOnIconify = GetBoolRes("warpOnIconify", FALSE); X WarpOnDeIconify = GetBoolRes("warpOnDeIconify", FALSE); X Zap = GetBoolRes("zap", FALSE); X X GadgetPad = GetIntRes("gadget.pad", DEF_GADGET_PAD); X HIconPad = GetIntRes("icon.vPad", DEF_ICON_PAD); X VIconPad = GetIntRes("icon.hPad", DEF_ICON_PAD); X RaiseDelay = GetIntRes("raiseDelay", DEF_RAISE_DELAY); X MaxColors = GetIntRes("maxColors", DEF_MAX_COLORS); X PBorderWidth = GetIntRes("popup.borderWidth", DEF_POP_BORDER_WIDTH); X IBorderWidth = GetIntRes("icon.borderWidth", DEF_ICON_BORDER_WIDTH); X PPadding = GetIntRes("popup.pad", DEF_POP_PAD); X MBorderWidth = GetIntRes("menu.borderWidth", DEF_MENU_BORDER_WIDTH); X MItemBorder = GetIntRes("menu.itemBorder", 1); X MDelta = GetIntRes("menu.delta", DEF_MENU_DELTA); X MPad = GetIntRes("menu.pad", DEF_MENU_PAD); X Delta = GetIntRes("delta", DEF_DELTA); X Volume = GetIntRes("volume", DEF_VOLUME); X Pushval = GetIntRes("push", DEF_PUSH); X BContext = GetIntRes("BC.width", DEF_BCONTEXT_WIDTH); X BCursor = GetIntRes("BC.cursor", DEF_BCONTEXT_CURSOR); X TCursor = GetIntRes("title.cursor", DEF_TITLE_CURSOR); X X /* X * Retrieve the information structure for the specifed fonts and X * set the global font information pointers. X */ X /* Default foreground/background colors */ X ForeColor = GetColorRes("foreground", (Reverse) ? X WhitePixel(dpy, scr) : BlackPixel(dpy, scr)); X BackColor = GetColorRes("background", (Reverse) ? X BlackPixel(dpy, scr) : WhitePixel(dpy, scr)); X X IFontInfo = GetFontRes("icon.font", DEF_ICON_FONT); X PFontInfo = GetFontRes("popup.font", DEF_POPUP_FONT); X MFontInfo = GetFontRes("menu.font", DEF_MENU_FONT); X MBoldFontInfo = GetFontRes("menu.boldFont", DEF_BOLD_FONT); X X BForeground = GetColorRes("BC.foreground", ForeColor); X BBackground = GetColorRes("BC.background", BackColor); X IForeground = GetColorRes("icon.foreground", ForeColor); X IBackground = GetColorRes("icon.background", BackColor); X IBorder = GetColorRes("icon.border", IForeground); X ITextForeground = GetColorRes("icon.text.foreground", IForeground); X ITextBackground = GetColorRes("icon.text.background", IBackground); X PBorder = GetColorRes("popup.border", ForeColor); X PForeground = GetColorRes("popup.foreground", PBorder); X PBackground = GetColorRes("popup.background", BackColor); X MForeground = GetColorRes("menu.foreground", ForeColor); X MBackground = GetColorRes("menu.background", BackColor); X MBorder = GetColorRes("menu.border", MForeground); X X IBackPixmap = GetPixmapRes("icon.pixmap", GrayPixmap, IForeground, X IBackground); X X#ifdef NEATEN X AbsMinWidth = GetIntRes("neaten.absMinWidth", DEFAULT_ABS_MIN); X AbsMinHeight = GetIntRes("neaten.absMinHeight", DEFAULT_ABS_MIN); X X RetainSize = GetBoolRes("neaten.retainSize", TRUE); X KeepOpen = GetBoolRes("neaten.keepOpen", TRUE); X Fill = GetBoolRes("neaten.fill", TRUE); X UsePriorities = GetBoolRes("neaten.usePriorities", TRUE); X FixTopOfStack = GetBoolRes("neaten.fixTopOfStack", TRUE); X X PrimaryIconPlacement = GetStringRes("neaten.primaryIconPlacement", X DEF_PRIMARY_PLACEMENT); X SecondaryIconPlacement = GetStringRes("neaten.secondaryIconPlacement", X DEF_SECONDARY_PLACEMENT); X#endif X X Leave_void X} X X/* X * Look up string resource "string". If undefined, return "def_val" X */ char *GetStringRes(string, def_val) char *string, *def_val; X{ X char *cp; X X Entry("GetStringRes") X X if ((cp = XGetDefault(dpy, NAME, string)) || X (cp = XGetDefault(dpy, CLASS, string))) { X if (!strlen(cp)) X Leave(def_val) X else X Leave(cp); X } X Leave(def_val) X} X X/* X * Look up boolean resource "string". If undefined, return "def_val" X */ Boolean GetBoolRes(string, def_val) char *string; Boolean def_val; X{ X char *cp; X X Entry("GetBoolRes") X X if ((cp = XGetDefault(dpy, NAME, string)) || X (cp = XGetDefault(dpy, CLASS, string))) { X if (!strlen(cp)) X Leave(def_val) X X /* look for "yes" (or "yeah" or "yup" ...) */ X if (*cp == 'y' || *cp == 'Y') X Leave(TRUE) X else if (!strcmp(cp, "on") || !strcmp(cp, "ON") || X !strcmp(cp, "On")) X Leave(TRUE) X else X Leave(FALSE) X } X Leave(def_val) X} X X/* X * Look up integer resource "string". If undefined or non-numeric, X * return def_val. X */ int GetIntRes(string, def_val) char *string; int def_val; X{ X char *cp; X X Entry("GetIntRes") X X if ((cp = XGetDefault(dpy, NAME, string)) || X (cp = XGetDefault(dpy, CLASS, string))) { X if (!strlen(cp) || !(*cp >= '0' && *cp <= '9')) X Leave(def_val) X Leave(atoi(cp)) X } X Leave(def_val) X} X X/* X * Try to load pixmap file named by resource "string". Return 0 if unsuccessful. X * Otherwise, set width, height and return data. X */ char *GetPixmapDataRes(string, wide, high) char *string; int *wide, *high; X{ X char *cp, *cp2; X X Entry("GetPixmapDataRes") X X if ((cp = XGetDefault(dpy, NAME, string)) || X (cp = XGetDefault(dpy, CLASS, string))) { X char *data; X int junk; X X cp2 = expand_from_path(cp); X if (!cp2) { X fprintf(stderr, "awm: Can't find pixmap file '%s' for '%s'\n", X cp, string); X Leave(0) X } X if (XReadBitmapFileData(cp2, wide, high, &data, &junk, &junk) X != BitmapSuccess) { X fprintf(stderr, "awm: Can't read pixmap file '%s' for '%s'.\n", X cp, string); X } X else { X Leave(data) X } X } X Leave(0) X} X X/* X * Try to allocate pixmap resources named by "string", return "def_pix" if not found. X */ Pixmap GetPixmapRes(string, def_pix, fg, bg) char *string; Pixmap def_pix; Pixel fg, bg; X{ X char *data; X Pixmap tmp; X int wide, high; X X if (data = GetPixmapDataRes(string, &wide, &high)) { X tmp = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr), X data, wide, high, fg, bg, X DefaultDepth(dpy, scr)); X XFree(data); X if (!tmp) { X fprintf(stderr, "awm: Can't create pixmap '%s', using default.\n", string); X tmp = def_pix; X } X } X else X tmp = def_pix; X Leave(tmp) X} X X/* X * Try to allocate color resource named by "string", return "color" if not found. X */ Pixel GetColorRes(string, color) char *string; Pixel color; X{ X char *cp; X Pixel tmp_color; X X Entry("GetColorRes") X X if ((cp = XGetDefault(dpy, NAME, string)) || X (cp = XGetDefault(dpy, CLASS, string))) { X if ((tmp_color = LookupColor(cp)) != NOCOLOR) X Leave(tmp_color) X else X tmp_color = color; X } X else X tmp_color = color; X Leave(tmp_color) X} X X/* X * Try and get font resource "string", using "default" if not found. If X * neither are available, use server default. X */ X XXFontStruct *GetFontRes(string, dflt) char *string, *dflt; X{ X char *cp; X XFontStruct *tmp; X static XFontStruct *def_font = 0; X X Entry("GetFontRes") X X if (!def_font) X def_font = XLoadQueryFont(dpy, DEF_FONT); X X if ((cp = XGetDefault(dpy, NAME, string)) || X (cp = XGetDefault(dpy, CLASS, string))) { X if (tmp = XLoadQueryFont(dpy, cp)) X Leave(tmp) X else X fprintf(stderr, "awm: Can't load %s '%s', trying '%s'.\n", X string, cp, dflt); X } X if (!dflt) /* NULL means we're not supposed to try again */ X Leave(NULL) X if (tmp = XLoadQueryFont(dpy, dflt)) X Leave(tmp) X else X fprintf(stderr, "awm: Can't open default font '%s', using server default.\n", dflt); X Leave(def_font) X} X AwmInfoPtr GetAwmInfo(w) Window w; X{ X static AwmInfoPtr tmp; X X Entry("GetAwmInfo") X X if (!XFindContext(dpy, w, AwmContext, &tmp)) X Leave(tmp) X else X Leave((AwmInfoPtr)NULL) X} X AwmInfoPtr RegisterWindow(w) Window w; X{ X AwmInfoPtr tmp; X X Entry("RegisterWindow") X tmp = (AwmInfoPtr)malloc(sizeof(AwmInfo)); X tmp->client = w; X tmp->title = tmp->frame = tmp->icon = (Window)0; X tmp->gadgets = (Window *)0; X tmp->name = (char *)0; X tmp->own = (Boolean)FALSE; X tmp->back = tmp->bold = tmp->BC_back = tmp->BC_bold = X tmp->iconPixmap = (Pixmap)0; X tmp->state = WINDOW; X tmp->winGC = XCreateGC(dpy, w, (unsigned long)0, 0); X tmp->placed = FALSE; X XSaveContext(dpy, w, AwmContext, tmp); X Leave(tmp) X} X X/* X * Initialize the default bindings. First, write the character array X * out to a temp file, then point the parser to it and read it in. X * Afterwards, we unlink the temp file. X */ InitBindings() X{ X char *mktemp(); X char *tempfile; X register FILE *fp; /* Temporary file pointer. */ X register char **ptr; /* Default bindings string array pointer. */ X X Entry("InitBindings") X X /* X * Create and write the temp file. X */ X /* X * This used to just call mktemp() on TEMPFILE, which was very X * evil as it involved writing on a string constant. This extra X * mastication is necessary to prevent that. X */ X tempfile = (char *)malloc(strlen(TEMPFILE) + 1); X strcpy(tempfile, TEMPFILE); X sfilename = mktemp(tempfile); X if ((fp = fopen(tempfile, "w")) == NULL) { X perror("awm: cannot create temp file"); X exit(1); X } X for (ptr = DefaultBindings; *ptr; ptr++) { X fputs(*ptr, fp); X fputc('\n', fp); X } X fclose(fp); X X /* X * Read in the bindings from the temp file and parse them. X */ X if ((yyin = fopen(tempfile, "r")) == NULL) { X perror("awm: cannot open temp file"); X exit(1); X } X Lineno = 1; X yyparse(); X fclose(yyin); X unlink(tempfile); X free(tempfile); X if (Startup_File_Error) X Error("Bad default bindings...aborting"); X X /* X * Parse the system startup file, if one exists. X */ X if ((yyin = fopen(SYSFILE, "r")) != NULL) { X sfilename = SYSFILE; X Lineno = 1; X yyparse(); X fclose(yyin); X if (Startup_File_Error) X Error("Bad system startup file...aborting"); X } X Leave_void X} X X/* X * Create the menus and alter any appropriate bindings so that the RTL menu X * handle is passed along in subsequent actions. X */ Create_Menus() X{ X Binding *bptr; X MenuInfo *minfo; X MenuLink *lnk; X X Entry("Create_Menus") X X /* X * We start with the bindings list because we don't want to bother X * creating a menu that's been declared but not referenced. X */ X for(bptr = Blist; bptr; bptr = bptr->next) { X if (bptr->func == DoMenu) { X if (minfo = (MenuInfo *)FindMenu(bptr->menuname)) X bptr->menu = (RTLMenu)create_menu(minfo); X else { X fprintf(stderr, "awm: non-existent menu reference: \"%s\"\n", X bptr->menuname); X Startup_File_Error = TRUE; X } X } X } X for (lnk = Menus; lnk; lnk = lnk->next) { X free(lnk->menu); X free(lnk); X } X Leave_void X} X X/* X * Grab the mouse buttons according to the bindings list. X */ X Grab_Buttons() X{ X Binding *bptr; X X Entry("Grab_Buttons") X X /* X * don't grab buttons if you don't have to - allow application X * access to buttons unless context includes window. X */ X for (bptr = Blist; bptr; bptr = bptr->next) { X if (bptr->context == ROOT) X NeedRootInput = TRUE; X else if (bptr->context & WINDOW) /* We gotta grab on windows */ X GrabAll(bptr->mask); X } X Leave_void X} X X/* X * Register a grab on all windows in the hierarchy. This is better than X * registering a grab on the RootWindow since it leaves button/key chords X * available for other contexts. X */ GrabAll(mask) unsigned int mask; X{ X int junk, nkids; X Window *kiddies; X X Entry("GrabAll") X X if (XQueryTree(dpy, DefaultRootWindow(dpy), &junk, &junk, &kiddies, &nkids) X != BadWindow) { X unsigned int i; X X for (i = 0; i < nkids; i++) { X Window transient; X XWindowAttributes xwa; X X /* check to see if it's a popup or something */ X XGetWindowAttributes(dpy, kiddies[i], &xwa); X XGetTransientForHint(dpy, kiddies[i], &transient); X if (xwa.class == InputOutput && xwa.map_state == IsViewable && X xwa.override_redirect == False && transient == None) X Grab(mask, kiddies[i]); X } X } X else { X fprintf(stderr, "awm: Can't XQueryTree in GrabAll!\n"); X exit(1); X } X} X X/* X * Grab a mouse button according to the given mask. X */ Grab(mask, w) unsigned int mask; Window w; X{ X unsigned int m = LeftMask | MiddleMask | RightMask; X X Entry("Grab") X X switch (mask & m) { X case LeftMask: X XGrabButton(dpy, LeftButton, mask & ModMask, w, TRUE, EVENTMASK, X GrabModeAsync, GrabModeAsync, None, LeftButtonCursor); X break; X X case MiddleMask: X XGrabButton(dpy, MiddleButton, mask & ModMask, w, TRUE, EVENTMASK, X GrabModeAsync, GrabModeAsync, None, MiddleButtonCursor); X break; X X case RightMask: X XGrabButton(dpy, RightButton, mask & ModMask, w, TRUE, EVENTMASK, X GrabModeAsync, GrabModeAsync, None, RightButtonCursor); X break; X } X Leave_void X} X X/* X * Restore cursor to normal state. X */ ResetCursor(button) int button; X{ X Entry("ResetCursor") X X switch (button) { X case LeftButton: X XChangeActivePointerGrab( X dpy, EVENTMASK, LeftButtonCursor, CurrentTime); X break; X X case MiddleButton: X XChangeActivePointerGrab( X dpy, EVENTMASK, MiddleButtonCursor, CurrentTime); X break; X X case RightButton: X XChangeActivePointerGrab( X dpy, EVENTMASK, RightButtonCursor, CurrentTime); X break; X } X Leave_void X} X X/* X * error routine for .awmrc parser X */ yyerror(s) char*s; X{ X Entry("yyerror") X X fprintf(stderr, "awm: %s: Line %d: %s\n", sfilename, Lineno, s); X Startup_File_Error = TRUE; X Leave_void X} X X/* X * warning routine for .awmrc parser X */ yywarn(s) char*s; X{ X Entry("yywarn") X X fprintf(stderr, "awm: Warning: %s: Line %d: %s\n", sfilename, Lineno, s); X Leave_void X} X X/* X * Print usage message and quit. X */ Usage() X{ X Entry("Usage") X X fputs("Usage: awm [-b] [-f <file>] [-e <file>] [<host>:<display>]\n\n", X stderr); X fputs("The -b option bypasses system and default bindings\n", stderr); X fputs("The -f option specifies an alternate startup file\n", stderr); X fputs("The -e option specifies a program/script to exec after startup\n", X stderr); X exit(1); X} X X/* X * error handler for X I/O errors X */ XXIOError(dsp) Display *dsp; X{ X perror("awm"); X exit(3); X} END_OF_FILE if test 35562 -ne `wc -c <'awm.c'`; then echo shar: \"'awm.c'\" unpacked with wrong size! fi # end of 'awm.c' fi echo shar: End of archive 7 \(of 8\). cp /dev/null ark7isdone MISSING="" for I in 1 2 3 4 5 6 7 8 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 8 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0