Path: utzoo!attcan!uunet!husc6!bloom-beacon!ardent.UUCP!jkh
From: jkh@ardent.UUCP (Jordan K. Hubbard)
Newsgroups: comp.windows.x
Subject: awm kit, Part07
Message-ID: <8806060231.AA24878@ardent.ardent.com>
Date: 6 Jun 88 02:31:30 GMT
Sender: daemon@bloom-beacon.MIT.EDU
Organization: The Internet
Lines: 1334
#! /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 '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
X#include
X#include
X#include
X#include "awm.h"
X#include "X11/Xutil.h"
X#include "X11/cursorfont.h"
X
X#ifdef PROFIL
X#include
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 ] [-e ] [:]\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