mikew@wyse.wyse.com (Mike Wexler) (09/23/88)
Submitted-by: tom%hpfctel@sde.hp.com (Tom LaStrange) Posting-number: Volume 1, Issue 50 Archive-name: twm/part05 #! /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 5 (of 7)." # Contents: add_window.c menus.c # Wrapped by mikew@wyse on Thu Sep 22 16:21:24 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'add_window.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'add_window.c'\" else echo shar: Extracting \"'add_window.c'\" \(23909 characters\) sed "s/^X//" >'add_window.c' <<'END_OF_FILE' X/*****************************************************************************/ X/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ X/** Salt Lake City, Utah **/ X/** **/ X/** All Rights Reserved **/ X/** **/ X/** Permission to use, copy, modify, and distribute this software and **/ X/** its documentation for any purpose and without fee is hereby **/ X/** granted, provided that the above copyright notice appear in all **/ X/** copies and that both that copyright notice and this permis- **/ X/** sion notice appear in supporting documentation, and that the **/ X/** name of Evans & Sutherland not be used in advertising or publi- **/ X/** city pertaining to distribution of the software without specif- **/ X/** ic, written prior permission. **/ X/** **/ X/** EVANS & SUTHERLAND DISCLAIMS ALL WARRANTIES WITH REGARD TO **/ X/** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILI- **/ X/** TY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND BE LIABLE **/ X/** FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAM- **/ X/** AGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, **/ X/** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS **/ X/** ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER- **/ X/** FORMANCE OF THIS SOFTWARE. **/ X/*****************************************************************************/ X X/********************************************************************** X * X * $Header: add_window.c,v 1.38 88/09/09 11:59:28 toml Exp $ X * X * Add a new window, put the titlbar and other stuff around X * the window X * X * 31-Mar-88 Tom LaStrange Initial Version. X * X **********************************************************************/ X X#ifndef lint Xstatic char RCSinfo[]= X"$Header: add_window.c,v 1.38 88/09/09 11:59:28 toml Exp $"; X#endif lint X X#include <stdio.h> X#include "twm.h" X#include <X11/Xatom.h> X#include "add_window.h" X#include "util.h" X#include "resize.h" X#include "gram.h" X#include "list.h" X#include "events.h" X#include "menus.h" X X#include "iconify.bm" X#include "resize.bm" X#ifndef NOFOCUS X#include "focus.bm" X#else X#define focus_width 0 X#endif X#include "hilite.bm" X Xint AddingX; Xint AddingY; Xint AddingW; Xint AddingH; X Xchar NoName[] = "No Name"; /* name if no name is specified */ X X/*********************************************************************** X * X * Procedure: X * AddWindow - add a new window to the twm list X * X * Returned Value: X * (TwmWindow *) - pointer to the TwmWindow structure X * X * Inputs: X * w - the window id of the window to add X * X *********************************************************************** X */ X XTwmWindow * XAddWindow(w) XWindow w; X{ X TwmWindow *tmp_win; /* new twm window structure */ X char *prop; X unsigned long valuemask; /* mask for create windows */ X XSetWindowAttributes attributes; /* attributes for create windows */ X XSetWindowAttributes grav_attr; /* gravity attributes to set */ X int width, len; /* tmp variable */ X int junk1, junk2, junk3; X int x; X Pixmap pm; /* tmp pixmap variable */ X XWindowChanges xwc; /* change window structure */ X unsigned int xwcm; /* change window mask */ X int dont_know; /* don't know where to put the window */ X XColor blob, cret; X XEvent event; X X#ifdef DEBUG X fprintf(stderr, "AddWindow: w = 0x%x\n", w); X#endif X X /* allocate space for the twm window */ X tmp_win = (TwmWindow *)malloc(sizeof(TwmWindow)); X tmp_win->w = w; X X XSelectInput(dpy, tmp_win->w, PropertyChangeMask); X XGetWindowAttributes(dpy, tmp_win->w, &tmp_win->attr); X XFetchName(dpy, tmp_win->w, &tmp_win->name); X tmp_win->class = NoClass; X XGetClassHint(dpy, tmp_win->w, &tmp_win->class); X X#ifdef DEBUG X fprintf(stderr, " name = \"%s\"\n", tmp_win->name); X#endif X tmp_win->wmhints = XGetWMHints(dpy, tmp_win->w); X /* X if (tmp_win->wmhints && (tmp_win->wmhints->flags & WindowGroupHint)) X printf("flags = 0x%x, group = 0x%x\n", X tmp_win->wmhints->flags, X tmp_win->wmhints->window_group); X */ X X if (XGetNormalHints(dpy, tmp_win->w, &tmp_win->hints) == 0) X tmp_win->hints.flags = 0; X X if (strncmp("xterm", tmp_win->class.res_name, 5) == 0 || X strncmp("XTerm", tmp_win->class.res_class, 5) == 0 || X strncmp("hpterm", tmp_win->class.res_name, 6) == 0 || X strncmp("HPterm", tmp_win->class.res_class, 6) == 0) X tmp_win->xterm = TRUE; X else X tmp_win->xterm = FALSE; X X dont_know = TRUE; X if (tmp_win->hints.flags & PPosition) X { X#ifdef DEBUG X fprintf(stderr, " program specified hints\n"); X#endif X tmp_win->attr.x = tmp_win->hints.x; X tmp_win->attr.y = tmp_win->hints.y; X tmp_win->attr.width = tmp_win->hints.width; X tmp_win->attr.height = tmp_win->hints.height; X } X if (tmp_win->hints.flags & USPosition) X { X#ifdef DEBUG X fprintf(stderr, " user specified hints\n"); X#endif X dont_know = FALSE; X tmp_win->attr.x = tmp_win->hints.x; X tmp_win->attr.y = tmp_win->hints.y; X tmp_win->attr.width = tmp_win->hints.width; X tmp_win->attr.height = tmp_win->hints.height; X } X X if (tmp_win->name == NULL) X tmp_win->name = NoName; X if (tmp_win->class.res_name == NULL) X tmp_win->class.res_name = NoName; X if (tmp_win->class.res_class == NULL) X tmp_win->class.res_class = NoName; X X tmp_win->full_name = tmp_win->name; X X tmp_win->highlight = !(short)LookInList(NO_HILITE, tmp_win->full_name, X &tmp_win->class); X tmp_win->auto_raise = (short)LookInList(AUTO_RAISE, tmp_win->full_name, X &tmp_win->class); X if (LookInList(NO_TITLE, tmp_win->full_name, &tmp_win->class)) X tmp_win->title_height = 0; X else X tmp_win->title_height = TITLE_BAR_HEIGHT + BorderWidth; X X if (HandlingEvents && dont_know) X { X if (!(tmp_win->wmhints && tmp_win->wmhints->flags & StateHint && X tmp_win->wmhints->initial_state == IconicState) && X (tmp_win->xterm || (tmp_win->attr.x == 0 && tmp_win->attr.y == 0))) X { X width = XTextWidth(InitialFont, tmp_win->name, X strlen(tmp_win->name)) + 20; X XResizeWindow(dpy, InitialWindow, width, InitialFontHeight + 4); X XMapRaised(dpy, InitialWindow); X XDrawImageString(dpy, InitialWindow, InitialNormalGC, X 10, 2 + InitialFont->ascent, X tmp_win->name, strlen(tmp_win->name)); X X AddingW = tmp_win->attr.width; X AddingH = tmp_win->attr.height; X X XGrabPointer(dpy, Root, False, X ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeSync, X Root, UpperLeftCursor, CurrentTime); X X AddingW = tmp_win->attr.width + 2 * BorderWidth; X AddingH = tmp_win->attr.height + tmp_win->title_height + X 2 * BorderWidth; X X while (TRUE) X { X XQueryPointer(dpy, Root, &JunkRoot, &JunkChild, X &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask); X X MoveOutline(Root, AddingX, AddingY, AddingW, AddingH); X X if (XCheckTypedEvent(dpy, ButtonPress, &event)) X { X AddingX = event.xbutton.x_root; X AddingY = event.xbutton.y_root; X break; X } X } X X if (event.xbutton.button == Button2) X { X XWarpPointer(dpy, None, Root, 0, 0, 0, 0, X AddingX + AddingW/2, AddingY + AddingH/2); X AddStartResize(tmp_win, AddingX, AddingY, AddingW, AddingH); X X while (TRUE) X { X int lastx, lasty; X X XQueryPointer(dpy, Root, &JunkRoot, &JunkChild, X &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask); X X if (lastx != AddingX || lasty != AddingY) X { X DoResize(AddingX, AddingY, tmp_win); X X lastx = AddingX; X lasty = AddingY; X } X X if (XCheckTypedEvent(dpy, ButtonRelease, &event)) X { X AddEndResize(tmp_win); X break; X } X } X } X X MoveOutline(Root, 0, 0, 0, 0); X XUnmapWindow(dpy, InitialWindow); X XUngrabPointer(dpy, CurrentTime); X X tmp_win->attr.x = AddingX; X tmp_win->attr.y = AddingY + tmp_win->title_height; X tmp_win->attr.width = AddingW - 2 * BorderWidth; X tmp_win->attr.height = AddingH - tmp_win->title_height - X (2 * BorderWidth); X } X } X X if (tmp_win->attr.y < tmp_win->title_height) X tmp_win->attr.y = tmp_win->title_height; X X xwcm = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; X X#ifdef DEBUG X fprintf(stderr, " position window %d, %d %dx%d\n", X tmp_win->attr.x, X tmp_win->attr.y, X tmp_win->attr.width, X tmp_win->attr.height); X#endif X xwc.x = tmp_win->attr.x + tmp_win->attr.border_width; X xwc.y = tmp_win->attr.y + tmp_win->attr.border_width; X xwc.width = tmp_win->attr.width; X xwc.height = tmp_win->attr.height; X xwc.border_width = 0; X X XConfigureWindow(dpy, tmp_win->w, xwcm, &xwc); X X tmp_win->name_width = XTextWidth(TitleBarFont, tmp_win->name, X strlen(tmp_win->name)); X X if (XGetWindowProperty(dpy, tmp_win->w, XA_WM_ICON_NAME, 0, 200, False, X XA_STRING, &junk1, &junk2, &junk3, &len, &tmp_win->icon_name)) X tmp_win->icon_name = tmp_win->name; X X if (tmp_win->icon_name == NULL) X tmp_win->icon_name = tmp_win->name; X X tmp_win->iconified = FALSE; X tmp_win->icon = FALSE; X X /* add the window into the twm list */ X tmp_win->next = TwmRoot.next; X if (TwmRoot.next != NULL) X TwmRoot.next->prev = tmp_win; X tmp_win->prev = &TwmRoot; X TwmRoot.next = tmp_win; X X /* create windows */ X X tmp_win->frame_x = tmp_win->attr.x; X tmp_win->frame_y = tmp_win->attr.y - tmp_win->title_height; X X tmp_win->frame = XCreateSimpleWindow(dpy, Root, X tmp_win->frame_x, X tmp_win->frame_y, X tmp_win->attr.width, X tmp_win->attr.height + tmp_win->title_height, X BorderWidth, X BorderColor, TitleBackground); X X tmp_win->title_w = XCreateSimpleWindow(dpy, tmp_win->frame, X -BorderWidth, -BorderWidth, X tmp_win->attr.width, TITLE_BAR_HEIGHT, X BorderWidth, X BorderColor, TitleBackground); X X if (Highlight && tmp_win->highlight) X { X XSetWindowBorderPixmap(dpy, tmp_win->frame, GrayTile); X XSetWindowBorderPixmap(dpy, tmp_win->title_w, GrayTile); X } X X /* the three buttons have the pixmap as the background of the X * window, that way I don't have to worry about repainting them X * on expose events. X */ X X valuemask = CWEventMask | CWBackPixmap; X attributes.event_mask = ButtonPressMask | ButtonReleaseMask; X attributes.background_pixmap = MakePixmap(tmp_win->title_w, TitleNormalGC, X iconify_bits, iconify_width, iconify_height); X X tmp_win->iconify_w = XCreateWindow(dpy, tmp_win->title_w, X TITLE_BAR_SPACE, TITLE_BAR_SPACE, X iconify_width, iconify_height, X 0, d_depth, CopyFromParent, X d_visual, valuemask, &attributes); X X#ifndef NOFOCUS X attributes.background_pixmap = MakePixmap(tmp_win->title_w, TitleNormalGC, X focus_bits, focus_width, focus_height); X X tmp_win->focus_w = XCreateWindow(dpy, tmp_win->title_w, X tmp_win->attr.width - resize_width -3 - focus_width, TITLE_BAR_SPACE, X iconify_width, iconify_height, X 0, d_depth, CopyFromParent, X d_visual, valuemask, &attributes); X#endif X X attributes.background_pixmap = MakePixmap(tmp_win->title_w, TitleNormalGC, X resize_bits, resize_width, resize_height); X X tmp_win->resize_w = XCreateWindow(dpy, tmp_win->title_w, X tmp_win->attr.width - resize_width - 1, X TITLE_BAR_SPACE, X resize_width, resize_height, X 0, d_depth, CopyFromParent, X d_visual, valuemask, &attributes); X X valuemask = CWBackPixmap; X attributes.background_pixmap = MakePixmap(tmp_win->title_w, TitleNormalGC, X hilite_bits, hilite_width, hilite_height); X X tmp_win->hilite_w = XCreateWindow(dpy, tmp_win->title_w, X TitleBarX, 1, X 10, hilite_height, X 0, d_depth, CopyFromParent, X d_visual, valuemask, &attributes); X X XDefineCursor(dpy, tmp_win->frame, ArrowCursor); X XDefineCursor(dpy, tmp_win->title_w, ArrowCursor); X XDefineCursor(dpy, tmp_win->iconify_w, ButtonCursor); X#ifndef NOFOCUS X XDefineCursor(dpy, tmp_win->focus_w, ButtonCursor); X#endif X XDefineCursor(dpy, tmp_win->resize_w, ButtonCursor); X X XSelectInput(dpy, tmp_win->w, StructureNotifyMask | PropertyChangeMask); X XSelectInput(dpy, tmp_win->frame, X SubstructureRedirectMask | X ButtonPressMask | ButtonReleaseMask | X EnterWindowMask | LeaveWindowMask); X X XSelectInput(dpy, tmp_win->title_w, X KeyPressMask | X ButtonPressMask | ButtonReleaseMask | ExposureMask); X X grav_attr.win_gravity = NorthWestGravity; X grav_attr.bit_gravity = ForgetGravity; X XChangeWindowAttributes(dpy, tmp_win->w, X CWBitGravity | CWWinGravity, &grav_attr); X XChangeWindowAttributes(dpy, tmp_win->frame, X CWBitGravity | CWWinGravity, &grav_attr); X X XAddToSaveSet(dpy, tmp_win->w); X XReparentWindow(dpy, tmp_win->w, tmp_win->frame, 0, tmp_win->title_height); X X SetupWindow(tmp_win, X tmp_win->frame_x, X tmp_win->frame_y, X tmp_win->attr.width, X tmp_win->attr.height + tmp_win->title_height); X X pm = NULL; X tmp_win->forced = FALSE; X X /* now go through the steps to get an icon window, if ForceIcon is X * set, then no matter what else is defined, the bitmap from the X * .twmrc file is used X */ X if (ForceIcon) X { X Pixmap bm; X XImage *image; X unsigned mask; X X if ((bm = (Pixmap)LookInNameList(ICONS, tmp_win->full_name)) == NULL) X bm = (Pixmap)LookInList(ICONS, tmp_win->full_name, &tmp_win->class); X if (bm != NULL) X { X XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY, X &tmp_win->icon_width, &tmp_win->icon_height, X &JunkBW, &JunkDepth); X X /* X mask = IconForeground ^ IconBackground; X image = XGetImage(dpy, bm, 0, 0, tmp_win->icon_width, X tmp_win->icon_height, AllPlanes, XYPixmap); X */ X X pm = XCreatePixmap(dpy, Root, tmp_win->icon_width, X tmp_win->icon_height, d_depth); X X /* the copy plane works on color ! */ X XCopyPlane(dpy, bm, pm, IconNormalGC, X 0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 ); X X /* X this code works on a monochrome system X X XPutImage(dpy, pm, IconNormalGC, X image, 0, 0, 0, 0, tmp_win->icon_width, tmp_win->icon_height); X */ X tmp_win->forced = TRUE; X } X } X X /* if the pixmap is still NULL, we didn't get one from the above code, X * that could mean that ForceIcon was not set, or that the window X * was not in the Icons list, now check the WM hints for an icon X */ X if (pm == NULL && tmp_win->wmhints && X tmp_win->wmhints->flags & IconPixmapHint) X { X X XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap, X &JunkRoot, &JunkX, &JunkY, X &tmp_win->icon_width, &tmp_win->icon_height, &JunkBW, &JunkDepth); X X pm = XCreatePixmap(dpy, Root, tmp_win->icon_width, tmp_win->icon_height, X d_depth); X X XCopyPlane(dpy, tmp_win->wmhints->icon_pixmap, pm, IconNormalGC, X 0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 ); X } X X /* if we still haven't got an icon, let's look in the Icon list X * if ForceIcon is not set X */ X if (pm == NULL && !ForceIcon) X { X Pixmap bm; X XImage *image; X unsigned mask; X X if ((bm = (Pixmap)LookInNameList(ICONS, tmp_win->full_name)) == NULL) X bm = (Pixmap)LookInList(ICONS, tmp_win->full_name, &tmp_win->class); X if (bm != NULL) X { X XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY, X &tmp_win->icon_width, &tmp_win->icon_height, X &JunkBW, &JunkDepth); X X /* X mask = IconForeground ^ IconBackground; X image = XGetImage(dpy, bm, 0, 0, tmp_win->icon_width, X tmp_win->icon_height, AllPlanes, XYPixmap); X */ X X pm = XCreatePixmap(dpy, Root, tmp_win->icon_width, X tmp_win->icon_height, d_depth); X X /* the copy plane works on color ! */ X XCopyPlane(dpy, bm, pm, IconNormalGC, X 0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 ); X X /* X this code works on a monochrome system X X XPutImage(dpy, pm, IconNormalGC, X image, 0, 0, 0, 0, tmp_win->icon_width, tmp_win->icon_height); X */ X } X } X X /* if we still don't have an icon, assign the UnknownIcon */ X X if (pm == NULL && UnknownPm != NULL) X { X XImage *image; X unsigned mask; X X tmp_win->icon_width = UnknownWidth; X tmp_win->icon_height = UnknownHeight; X mask = IconForeground ^ IconBackground; X image = XGetImage(dpy, UnknownPm, 0, 0, tmp_win->icon_width, X tmp_win->icon_height, AllPlanes, XYPixmap); X X pm = XCreatePixmap(dpy, Root, tmp_win->icon_width, X tmp_win->icon_height, d_depth); X X /* the copy plane works on color ! */ X XCopyPlane(dpy, UnknownPm, pm, IconNormalGC, X 0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 ); X X /* X this code works on a monochrome system X X XPutImage(dpy, pm, IconNormalGC, X image, 0, 0, 0, 0, tmp_win->icon_width, tmp_win->icon_height); X */ X } X X if (pm == NULL) X { X tmp_win->icon_height = 0; X tmp_win->icon_width = 0; X valuemask = 0; X } X else X { X valuemask = CWBackPixmap; X attributes.background_pixmap = pm; X } X X tmp_win->icon_w_width = XTextWidth(IconFont, X tmp_win->icon_name, strlen(tmp_win->icon_name)); X X tmp_win->icon_w_width += 6; X if (tmp_win->icon_w_width < tmp_win->icon_width) X { X tmp_win->icon_x = (tmp_win->icon_width - tmp_win->icon_w_width)/2; X tmp_win->icon_x += 3; X tmp_win->icon_w_width = tmp_win->icon_width; X } X else X { X tmp_win->icon_x = 3; X } X tmp_win->icon_y = tmp_win->icon_height + IconFontHeight; X X if (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint) X { X tmp_win->icon_w = tmp_win->wmhints->icon_window; X } X else X { X tmp_win->icon_w = XCreateSimpleWindow(dpy, Root, X 0,0, X tmp_win->icon_w_width, X tmp_win->icon_height + IconFontHeight + 4, X 2, IconBorderColor, IconBackground); X } X X XSelectInput(dpy, tmp_win->icon_w, X KeyPressMask | X ButtonPressMask | ButtonReleaseMask | ExposureMask); X X tmp_win->icon_bm_w = NULL; X if (pm != NULL) X { X if (tmp_win->icon_w_width == tmp_win->icon_width) X x = 0; X else X x = (tmp_win->icon_w_width - tmp_win->icon_width)/2; X X tmp_win->icon_bm_w = XCreateWindow(dpy, tmp_win->icon_w, X x, 0, tmp_win->icon_width, tmp_win->icon_height, X 0, d_depth, CopyFromParent, X d_visual, valuemask, &attributes); X } X X XDefineCursor(dpy, tmp_win->icon_w, ArrowCursor); X X GrabButtons(tmp_win); X GrabKeys(tmp_win); X X XSaveContext(dpy, tmp_win->w, TwmContext, tmp_win); X XSaveContext(dpy, tmp_win->frame, TwmContext, tmp_win); X XSaveContext(dpy, tmp_win->title_w, TwmContext, tmp_win); X XSaveContext(dpy, tmp_win->iconify_w, TwmContext, tmp_win); X XSaveContext(dpy, tmp_win->resize_w, TwmContext, tmp_win); X XSaveContext(dpy, tmp_win->icon_w, TwmContext, tmp_win); X#ifndef NOFOCUS X XSaveContext(dpy, tmp_win->focus_w, TwmContext, tmp_win); X#endif X XSaveContext(dpy, tmp_win->hilite_w, TwmContext, tmp_win); X X SetHints(tmp_win); X X return (tmp_win); X} X X/*********************************************************************** X * X * Procedure: X * MappedNotOverride - checks to see if we should really X * put a twm frame on the window X * X * Returned Value: X * TRUE - go ahead and frame the window X * FALSE - don't frame the window X * X * Inputs: X * w - the window to check X * X *********************************************************************** X */ X Xint XMappedNotOverride(w) X Window w; X{ X XWindowAttributes wa; X X XGetWindowAttributes(dpy, w, &wa); X return ((wa.map_state != IsUnmapped) && (wa.override_redirect != True)); X} X X/*********************************************************************** X * X * Procedure: X * GrabAllButtons - grab needed buttons for all windows X * X *********************************************************************** X */ X Xvoid XGrabAllButtons() X{ X TwmWindow *tmp_win; X X for (tmp_win = TwmRoot.next; tmp_win != NULL; tmp_win = tmp_win->next) X { X GrabButtons(tmp_win); X } X} X X/*********************************************************************** X * X * Procedure: X * GrabAllKeys - grab needed keys for all windows X * X *********************************************************************** X */ X Xvoid XGrabAllKeys() X{ X TwmWindow *tmp_win; X X for (tmp_win = TwmRoot.next; tmp_win != NULL; tmp_win = tmp_win->next) X { X GrabKeys(tmp_win); X } X} X X/*********************************************************************** X * X * Procedure: X * UngrabAllButtons - ungrab buttons for all windows X * X *********************************************************************** X */ X Xvoid XUngrabAllButtons() X{ X TwmWindow *tmp_win; X X for (tmp_win = TwmRoot.next; tmp_win != NULL; tmp_win = tmp_win->next) X { X UngrabButtons(tmp_win); X } X} X X/*********************************************************************** X * X * Procedure: X * UngrabAllKeys - ungrab keys for all windows X * X *********************************************************************** X */ X Xvoid XUngrabAllKeys() X{ X TwmWindow *tmp_win; X X for (tmp_win = TwmRoot.next; tmp_win != NULL; tmp_win = tmp_win->next) X { X UngrabKeys(tmp_win); X } X} X X/*********************************************************************** X * X * Procedure: X * GrabButtons - grab needed buttons for the window X * X * Inputs: X * tmp_win - the twm window structure to use X * X *********************************************************************** X */ X Xvoid XGrabButtons(tmp_win) XTwmWindow *tmp_win; X{ X int i, j; X X for (i = 0; i < MAX_BUTTONS+1; i++) X { X for (j = 0; j < MOD_SIZE; j++) X { X if (Mouse[i][C_WINDOW][j].func != NULL) X { X XGrabButton(dpy, i, j, tmp_win->w, X True, ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeAsync, None, ArrowCursor); X } X } X } X} X X/*********************************************************************** X * X * Procedure: X * GrabKeys - grab needed keys for the window X * X * Inputs: X * tmp_win - the twm window structure to use X * X *********************************************************************** X */ X Xvoid XGrabKeys(tmp_win) XTwmWindow *tmp_win; X{ X FuncKey *tmp; X X for (tmp = FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) X { X switch (tmp->cont) X { X case C_WINDOW: X XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True, X GrabModeAsync, GrabModeAsync); X break; X X case C_ICON: X XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w, True, X GrabModeAsync, GrabModeAsync); X X case C_TITLE: X XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w, True, X GrabModeAsync, GrabModeAsync); X break; X X /* X case C_ROOT: X XGrabKey(dpy, tmp->keycode, tmp->mods, Root, True, X GrabModeAsync, GrabModeAsync); X break; X */ X } X } X} X X/*********************************************************************** X * X * Procedure: X * UngrabButtons - ungrab buttons for windows X * X * Inputs: X * tmp_win - the twm window structure to use X * X *********************************************************************** X */ X Xvoid XUngrabButtons(tmp_win) XTwmWindow *tmp_win; X{ X int i; X X for (i = 0; i < MAX_BUTTONS+1; i++) X { X XUngrabButton(dpy, i, AnyModifier, tmp_win->w); X } X} X X/*********************************************************************** X * X * Procedure: X * UngrabKeys - ungrab keys for windows X * X * Inputs: X * tmp_win - the twm window structure to use X * X *********************************************************************** X */ X Xvoid XUngrabKeys(tmp_win) XTwmWindow *tmp_win; X{ X FuncKey *tmp; X X for (tmp = FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) X { X switch (tmp->cont) X { X case C_WINDOW: X XUngrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w); X break; X X case C_ICON: X XUngrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->icon_w); X X case C_TITLE: X XUngrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->title_w); X break; X X case C_ROOT: X XUngrabKey(dpy, tmp->keycode, tmp->mods, Root); X break; X } X } X} END_OF_FILE if test 23909 -ne `wc -c <'add_window.c'`; then echo shar: \"'add_window.c'\" unpacked with wrong size! fi # end of 'add_window.c' fi if test -f 'menus.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'menus.c'\" else echo shar: Extracting \"'menus.c'\" \(24165 characters\) sed "s/^X//" >'menus.c' <<'END_OF_FILE' X/*****************************************************************************/ X/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ X/** Salt Lake City, Utah **/ X/** **/ X/** All Rights Reserved **/ X/** **/ X/** Permission to use, copy, modify, and distribute this software and **/ X/** its documentation for any purpose and without fee is hereby **/ X/** granted, provided that the above copyright notice appear in all **/ X/** copies and that both that copyright notice and this permis- **/ X/** sion notice appear in supporting documentation, and that the **/ X/** name of Evans & Sutherland not be used in advertising or publi- **/ X/** city pertaining to distribution of the software without specif- **/ X/** ic, written prior permission. **/ X/** **/ X/** EVANS & SUTHERLAND DISCLAIMS ALL WARRANTIES WITH REGARD TO **/ X/** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILI- **/ X/** TY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND BE LIABLE **/ X/** FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAM- **/ X/** AGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, **/ X/** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS **/ X/** ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER- **/ X/** FORMANCE OF THIS SOFTWARE. **/ X/*****************************************************************************/ X X/*********************************************************************** X * X * $Header: menus.c,v 1.49 88/09/09 10:37:51 toml Exp $ X * X * twm menu code X * X * 17-Nov-87 Thomas E. LaStrange File created X * X ***********************************************************************/ X X#ifndef lint Xstatic char RCSinfo[] = X"$Header: menus.c,v 1.49 88/09/09 10:37:51 toml Exp $"; X#endif X X#include <stdio.h> X#include <signal.h> X#include "twm.h" X#include "gc.h" X#include "menus.h" X#include "events.h" X#include "util.h" X#include "gram.h" X X#include "pull.bm" X Xint RootFunction = NULL; XMenuRoot *MenuList = NULL; /* head of the menu list */ XMenuRoot *LastMenu = NULL; /* the last menu */ XMenuRoot *ActiveMenu = NULL; /* the active menu */ XMenuItem *ActiveItem = NULL; /* the active menu item */ XMouseButton Mouse[MAX_BUTTONS+1][NUM_CONTEXTS][MOD_SIZE]; XMouseButton DefaultFunction; XFuncKey FuncKeyRoot; /* head of function key list */ X X/*********************************************************************** X * X * Procedure: X * InitMenus - initialize menu roots X * X *********************************************************************** X */ X Xvoid XInitMenus() X{ X int i, j, k; X FuncKey *key, *tmp; X X for (i = 0; i < MAX_BUTTONS+1; i++) X for (j = 0; j < NUM_CONTEXTS; j++) X for (k = 0; k < MOD_SIZE; k++) X Mouse[i][j][k].func = NULL; X X DefaultFunction.func = NULL; X X Mouse[1][C_TITLE][0].func = F_RAISE; X Mouse[2][C_TITLE][0].func = F_MOVE; X Mouse[3][C_TITLE][0].func = F_LOWER; X X Mouse[1][C_ICON][0].func = F_RAISE; X Mouse[2][C_ICON][0].func = F_MOVE; X Mouse[3][C_ICON][0].func = F_LOWER; X X for (key = FuncKeyRoot.next; key != NULL;) X { X free(key->name); X tmp = key; X key = key->next; X free(tmp); X } X FuncKeyRoot.next = NULL; X} X X/*********************************************************************** X * X * Procedure: X * AddFuncKey - add a function key to the list X * X * Inputs: X * name - the name of the key X * cont - the context to look for the key press in X * mods - modifier keys that need to be pressed X * func - the function to perform X * action - the action string associated with the function (if any) X * X *********************************************************************** X */ X Xvoid XAddFuncKey(name, cont, mods, func, action) X char *name; X int cont, mods, func; X char *action; X{ X FuncKey *tmp; X KeySym keysym; X X if ((keysym = XStringToKeysym(name)) == NoSymbol) X { X fprintf(stderr, "twm: unknown key name \"%s\"\n", name); X return; X } X X /* see if there already is a key defined for this context */ X for (tmp = FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) X { X if (tmp->keysym == keysym && X tmp->cont == cont && X tmp->mods == mods) X break; X } X X if (tmp == NULL) X { X tmp = (FuncKey *) malloc(sizeof(FuncKey)); X tmp->next = FuncKeyRoot.next; X FuncKeyRoot.next = tmp; X } X X tmp->name = name; X tmp->keysym = keysym; X tmp->keycode = XKeysymToKeycode(dpy, keysym); X tmp->cont = cont; X tmp->mods = mods; X tmp->func = func; X tmp->action = action; X} X X/*********************************************************************** X * X * Procedure: X * NewMenuRoot - create a new menu root X * X * Returned Value: X * (MenuRoot *) X * X * Inputs: X * name - the name of the menu root X * X *********************************************************************** X */ X XMenuRoot * XNewMenuRoot(name) X char *name; X{ X MenuRoot *tmp; X unsigned long valuemask; X XSetWindowAttributes attributes; X X CreateGCs(); X X tmp = (MenuRoot *) malloc(sizeof(MenuRoot)); X tmp->name = name; X tmp->prev = NULL; X tmp->first = NULL; X tmp->last = NULL; X tmp->items = 0; X tmp->width = 0; X tmp->mapped = FALSE; X tmp->pull = FALSE; X tmp->active = TRUE; X tmp->shadow = XCreateSimpleWindow(dpy, Root, X 0, 0, 10, 10, 1, MenuShadowColor, MenuShadowColor); X tmp->w = XCreateSimpleWindow(dpy, Root, X 0, 0, 10, 10, 1, MenuForeground, MenuBackground); X XSelectInput(dpy, tmp->w, LeaveWindowMask); X X valuemask = CWSaveUnder; X attributes.save_under = True; X XChangeWindowAttributes(dpy, tmp->shadow, valuemask, &attributes); X XChangeWindowAttributes(dpy, tmp->w, valuemask, &attributes); X X if (MenuList == NULL) X { X MenuList = tmp; X MenuList->next = NULL; X } X X if (LastMenu == NULL) X { X LastMenu = tmp; X LastMenu->next = NULL; X } X else X { X LastMenu->next = tmp; X LastMenu = tmp; X LastMenu->next = NULL; X } X X return (tmp); X} X X/*********************************************************************** X * X * Procedure: X * AddToMenu - add an item to a root menu X * X * Returned Value: X * (MenuItem *) X * X * Inputs: X * menu - pointer to the root menu to add the item X * item - the text to appear in the menu X * action - the string to possibly execute X * sub - the menu root if it is a pull-right entry X * func - the numeric function X * X *********************************************************************** X */ X XMenuItem * XAddToMenu(menu, item, action, sub, func) X MenuRoot *menu; X char *item, *action; X MenuRoot *sub; X int func; X{ X unsigned long valuemask; X XSetWindowAttributes attributes; X MenuItem *tmp; X int width; X X#ifdef DEBUG X fprintf(stderr, "adding menu item=\"%s\", action=%s, sub=%d, f=%d\n", X item, action, sub, func); X#endif X X tmp = (MenuItem *) malloc(sizeof(MenuItem)); X tmp->root = menu; X X if (menu->first == NULL) X { X menu->first = tmp; X tmp->prev = NULL; X } X else X { X menu->last->next = tmp; X tmp->prev = menu->last; X } X menu->last = tmp; X X tmp->item = item; X tmp->action = action; X tmp->next = NULL; X tmp->sub = NULL; X tmp->pull = NULL; X tmp->state = 0; X tmp->func = func; X X width = XTextWidth(MenuFont, item, strlen(item)); X if (width <= 0) X width = 1; X if (width > menu->width) X menu->width = width; X X if (tmp->func != F_TITLE) X { X tmp->w = XCreateSimpleWindow(dpy, menu->w, X 0, menu->items * (MenuFontHeight + 4), X width, MenuFontHeight + 4, X 0, X MenuForeground, MenuBackground); X XSelectInput(dpy, tmp->w, EnterWindowMask X | LeaveWindowMask | ExposureMask); X } X else X { X tmp->w = XCreateSimpleWindow(dpy, menu->w, X -1, menu->items * (MenuFontHeight + 4), X width, MenuFontHeight + 2, X 1, X MenuForeground, MenuTitleBackground); X XSelectInput(dpy, tmp->w, ExposureMask); X } X X valuemask = CWBackingStore; X attributes.backing_store = Always; X XChangeWindowAttributes(dpy, tmp->w, valuemask, &attributes); X X if (sub != NULL) X { X Pixmap pm; X X tmp->sub = sub; X pm = MakeCenteredPixmap(tmp->w, MenuNormalGC, X pull_width, MenuFontHeight + 4, X pull_bits, pull_width, pull_height); X X valuemask = CWEventMask | CWBackPixmap; X attributes.background_pixmap = pm; X attributes.event_mask = EnterWindowMask | LeaveWindowMask; X X tmp->pull = XCreateWindow(dpy, tmp->w, X 0, 0, X pull_width, MenuFontHeight + 4, X 0, d_depth, CopyFromParent, X d_visual, valuemask, &attributes); X X XMapWindow(dpy, tmp->pull); X X menu->pull = TRUE; X XSaveContext(dpy, tmp->pull, MenuContext, tmp); X } X menu->items += 1; X X XSaveContext(dpy, tmp->w, MenuContext, tmp); X X if (menu->items == 1) X XSaveContext(dpy, tmp->root->w, MenuContext, tmp); X X return (tmp); X} X X/*********************************************************************** X * X * Procedure: X * PopUpMenu - pop up a pull down menu X * X * Inputs: X * menu - the root pointer of the menu to pop up X * x - the x location of the mouse X * y - the y location of the mouse X * X *********************************************************************** X */ X Xvoid XPopUpMenu(menu, x, y) X MenuRoot *menu; X int x, y; X{ X int m_height; X XWindowChanges xwc, pwc; X unsigned int xwcm, pwcm; X MenuItem *tmp; X X if (menu == NULL) X return; X X if (ActiveMenu != NULL) X ActiveMenu->active = FALSE; X X menu->active = TRUE; X ActiveMenu = menu; X if (menu->mapped != TRUE) X { X if (menu->pull == TRUE) X { X menu->width += pull_width + 10; X } X X xwcm = 0; X xwcm |= CWWidth; X xwc.width = menu->width + 10; X X pwcm = 0; X pwcm |= CWX; X pwc.x = xwc.width - pull_width; X X for (tmp = menu->first; tmp != NULL; tmp = tmp->next) X { X XConfigureWindow(dpy, tmp->w, xwcm, &xwc); X if (tmp->pull != NULL) X { X XConfigureWindow(dpy, tmp->pull, pwcm, &pwc); X } X if (tmp->func != F_TITLE) X tmp->y = 5; X else X { X tmp->y = xwc.width - XTextWidth(MenuFont, tmp->item, X strlen(tmp->item)); X tmp->y /= 2; X } X } X } X menu->mapped = TRUE; X X m_height = menu->items * (MenuFontHeight + 4); X X if ((x + 10) > MyDisplayWidth) X x = (MyDisplayWidth - 30); X X if ((y + m_height + 10) > MyDisplayHeight) X y = (MyDisplayHeight - m_height); X X xwcm = CWX | CWY | CWWidth | CWHeight; X X xwc.x = x - menu->width + 10; X if (xwc.x < 0) X xwc.x = 0; X xwc.y = y - ((MenuFontHeight + 4) / 2); X xwc.width = menu->width + 10; X xwc.height = m_height; X X XConfigureWindow(dpy, menu->w, xwcm, &xwc); X X xwc.x = xwc.x + 5; X xwc.y = xwc.y + 5; X X XConfigureWindow(dpy, menu->shadow, xwcm, &xwc); X XWarpPointer(dpy, None, menu->w, 0, 0, 0, 0, X menu->width - 10, (MenuFontHeight + 4) / 2); X XMapSubwindows(dpy, menu->w); X XRaiseWindow(dpy, menu->shadow); X XMapRaised(dpy, menu->w); X XMapWindow(dpy, menu->shadow); X} X X/*********************************************************************** X * X * Procedure: X * FindMenuRoot - look for a menu root X * X * Returned Value: X * (MenuRoot *) - a pointer to the menu root structure X * X * Inputs: X * name - the name of the menu root X * X *********************************************************************** X */ X XMenuRoot * XFindMenuRoot(name) X char *name; X{ X MenuRoot *tmp; X X for (tmp = MenuList; tmp != NULL; tmp = tmp->next) X { X if (strcmp(name, tmp->name) == 0) X return (tmp); X } X return NULL; X} X X/*********************************************************************** X * X * Procedure: X * ExecuteFunction - execute a twm root function X * X * Inputs: X * func - the function to execute X * action - the menu action to execute X * w - the window to execute this function on X * tmp_win - the twm window structure X * event - the event that caused the function X * context - the context in which the button was pressed X * pulldown- flag indicating execution from pull down menu X * X *********************************************************************** X */ X Xvoid XExecuteFunction(func, action, w, tmp_win, event, context, pulldown) X int func; X char *action; X Window w; X TwmWindow *tmp_win; X XEvent event; X int context; X int pulldown; X{ X static Time last_time = 0; X X char tmp[200]; X char *ptr; X int len; X char buff[MAX_FILE_SIZE]; X int count, fd; X MenuRoot *root, *tmp_root; X MenuItem *item, *tmp_item; X X XGrabPointer(dpy, Root, True, X ButtonReleaseMask, X GrabModeAsync, GrabModeSync, X Root, ClockCursor, CurrentTime); X X switch (func) X { X case F_NOP: X case F_TITLE: X break; X X case F_BEEP: X XBell(dpy, screen); X break; X X case F_RESIZE: X if (DeferExecution(context, func, MoveCursor)) X return; X X if (pulldown) X XWarpPointer(dpy, None, Root, X 0, 0, 0, 0, event.xbutton.x_root, event.xbutton.y_root); X X if (w != tmp_win->icon_w) X { X EventHandler[EnterNotify] = HandleUnknown; X EventHandler[LeaveNotify] = HandleUnknown; X EventHandler[Expose] = HandleUnknown; X StartResize(event, tmp_win); X return; X } X break; X X case F_MOVE: X if (DeferExecution(context, func, MoveCursor)) X return; X X if (pulldown) X XWarpPointer(dpy, None, Root, X 0, 0, 0, 0, event.xbutton.x_root, event.xbutton.y_root); X X EventHandler[EnterNotify] = HandleUnknown; X EventHandler[LeaveNotify] = HandleUnknown; X EventHandler[Expose] = HandleUnknown; X X /* redraw the text in the title bar or the icon window if X * needed, we have disabled expose event handling so we must X * do it here X */ X if (context == C_TITLE) X { X XDrawImageString(dpy, tmp_win->title_w, X TitleNormalGC, X TitleBarX, TitleBarY, X tmp_win->name, strlen(tmp_win->name)); X } X else if (context == C_ICON) X { X XDrawImageString(dpy, tmp_win->icon_w, X IconNormalGC, X tmp_win->icon_x, tmp_win->icon_y, X tmp_win->icon_name, strlen(tmp_win->icon_name)); X } X X XGrabServer(dpy); X XGrabPointer(dpy, event.xbutton.root, True, X ButtonReleaseMask, X GrabModeAsync, GrabModeSync, X Root, MoveCursor, CurrentTime); X X if (context == C_ICON) X w = tmp_win->icon_w; X else if (w != tmp_win->icon_w) X w = tmp_win->frame; X X DragX = event.xbutton.x; X DragY = event.xbutton.y; X X if (context == C_WINDOW) X DragY += tmp_win->title_height; X X DragWindow = w; X X XGetGeometry(dpy, w, &JunkRoot, &JunkX, &JunkY, X &DragWidth, &DragHeight, &JunkBW, X &JunkDepth); X X MoveOutline((Window)event.xbutton.root, X event.xbutton.x_root-DragX-BorderWidth, X event.xbutton.y_root-DragY-BorderWidth, X DragWidth + 2 * BorderWidth, X DragHeight + 2 * BorderWidth); X X if ((event.xbutton.time - last_time) < 400) X { X int width, height; X X ConstMove = TRUE; X ConstMoveDir = MOVE_NONE; X ConstMoveX = event.xbutton.x_root - DragX - BorderWidth; X ConstMoveY = event.xbutton.y_root - DragY - BorderWidth; X width = DragWidth + 2 * BorderWidth; X height = DragHeight + 2 * BorderWidth; X ConstMoveXL = ConstMoveX + width/3; X ConstMoveXR = ConstMoveX + 2*(width/3); X ConstMoveYT = ConstMoveY + height/3; X ConstMoveYB = ConstMoveY + 2*(height/3); X X XWarpPointer(dpy, None, DragWindow, X 0, 0, 0, 0, DragWidth/2, DragHeight/2); X X XQueryPointer(dpy, DragWindow, &JunkRoot, &JunkChild, X &JunkX, &JunkY, &DragX, &DragY, &JunkMask); X } X last_time = event.xbutton.time; X return; X break; X X case F_FUNCTION: X { X MenuRoot *mroot; X MenuItem *mitem; X X if ((mroot = FindMenuRoot(action)) == NULL) X { X fprintf(stderr, "twm: couldn't find function \"%s\"\n", action); X } X else X { X for (mitem = mroot->first; mitem != NULL; mitem = mitem->next) X { X ExecuteFunction(mitem->func, mitem->action, w, tmp_win, X event, context, pulldown); X } X } X } X break; X X case F_ICONIFY: X if (DeferExecution(context, func, DotCursor)) X return; X X if (tmp_win->icon) X { X Zoom(tmp_win->icon_w, tmp_win->frame); X X XUnmapWindow(dpy, tmp_win->icon_w); X XMapWindow(dpy, tmp_win->w); X if (NoRaiseDeicon) X XMapWindow(dpy, tmp_win->frame); X else X XMapRaised(dpy, tmp_win->frame); X X if (WarpCursor) X { X XWarpPointer(dpy, None, tmp_win->frame, X 0, 0, 0, 0, 30, 8); X } X tmp_win->icon = FALSE; X } X else X { X if (!tmp_win->iconified) X { X int final_x, final_y; X X if (tmp_win->wmhints && X tmp_win->wmhints->flags & IconPositionHint) X { X final_x = tmp_win->wmhints->icon_x; X final_y = tmp_win->wmhints->icon_y; X } X else X { X final_x = event.xbutton.x_root - 5; X final_y = event.xbutton.y_root - 5; X } X X if (final_x > MyDisplayWidth) X final_x = MyDisplayWidth - tmp_win->icon_w_width - X (2 * BorderWidth); X X if (final_y > MyDisplayHeight) X final_y = MyDisplayHeight - tmp_win->icon_height - X IconFontHeight - 4 - (2 * BorderWidth); X X XMoveWindow(dpy, tmp_win->icon_w, final_x, final_y); X tmp_win->iconified = TRUE; X } X X Zoom(tmp_win->frame, tmp_win->icon_w); X XUnmapWindow(dpy, tmp_win->frame); X XUnmapWindow(dpy, tmp_win->w); X XMapSubwindows(dpy, tmp_win->icon_w); X XMapRaised(dpy, tmp_win->icon_w); X if (tmp_win == Focus) X { X XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, X CurrentTime); X Focus = NULL; X FocusRoot = TRUE; X } X tmp_win->icon = TRUE; X } X SetHints(tmp_win); X break; X X case F_RAISE: X if (DeferExecution(context, func, DotCursor)) X return; X X if (w == tmp_win->icon_w) X { X Zoom(tmp_win->icon_w, tmp_win->frame); X XUnmapWindow(dpy, tmp_win->icon_w); X XMapWindow(dpy, tmp_win->w); X if (NoRaiseDeicon) X XMapWindow(dpy, tmp_win->frame); X else X XMapRaised(dpy, tmp_win->frame); X X if (WarpCursor) X { X XWarpPointer(dpy, None, tmp_win->frame, X 0, 0, 0, 0, 30, 8); X } X tmp_win->icon = FALSE; X } X else X { X XRaiseWindow(dpy, tmp_win->frame); X } X break; X X case F_LOWER: X if (DeferExecution(context, func, DotCursor)) X return; X X XLowerWindow(dpy, tmp_win->frame); X break; X X case F_FOCUS: X if (DeferExecution(context, func, DotCursor)) X return; X X if (tmp_win->icon == FALSE) X { X if (Focus != NULL && Focus != tmp_win) X { X if (Highlight && Focus->highlight) X { X XSetWindowBorderPixmap(dpy, Focus->frame, GrayTile); X XSetWindowBorderPixmap(dpy, Focus->title_w, GrayTile); X } X XUnmapWindow(dpy, Focus->hilite_w); X } X XMapWindow(dpy, tmp_win->hilite_w); X XSetWindowBorder(dpy, tmp_win->frame, BorderColor); X XSetWindowBorder(dpy, tmp_win->title_w, BorderColor); X XSetInputFocus(dpy, tmp_win->w, RevertToPointerRoot, X CurrentTime); X FocusRoot = FALSE; X Focus = tmp_win; X } X break; X X case F_DESTROY: X if (DeferExecution(context, func, SkullCursor)) X return; X X XKillClient(dpy, tmp_win->w); X break; X X case F_CIRCLEUP: X XCirculateSubwindowsUp(dpy, Root); X break; X X case F_CIRCLEDOWN: X XCirculateSubwindowsDown(dpy, Root); X break; X X case F_VERSION: X XMapRaised(dpy, VersionWindow); X break; X X case F_EXEC: X Execute(action); X break; X X case F_UNFOCUS: X FocusOnRoot(); X break; X X case F_CUT: X strcpy(tmp, action); X strcat(tmp, "\n"); X XStoreBytes(dpy, tmp, strlen(tmp)); X break; X X case F_CUTFILE: X ptr = XFetchBytes(dpy, &count); X if (count != 0) X { X if (sscanf(ptr, "%s", tmp) == 1) X { X ptr = ExpandFilename(tmp); X fd = open(ptr, 0); X if (fd >= 0) X { X count = read(fd, buff, MAX_FILE_SIZE - 1); X if (count > 0) X XStoreBytes(dpy, buff, count); X X close(fd); X } X else X { X fprintf(stderr, "twm: couldn't open \"%s\"\n", tmp); X } X } X XFree(ptr); X } X else X { X fprintf(stderr, "twm: nothing in the cut buffer\n"); X } X break; X X case F_FILE: X action = ExpandFilename(action); X fd = open(action, 0); X if (fd >= 0) X { X count = read(fd, buff, MAX_FILE_SIZE - 1); X if (count > 0) X XStoreBytes(dpy, buff, count); X X close(fd); X } X else X { X fprintf(stderr, "twm: couldn't open \"%s\"\n", action); X } X break; X X case F_TWMRC: X len = strlen(action); X if (len == 0) X ptr = NULL; X else X { X ptr = (char *)malloc(len+1); X if (ptr == NULL) X { X fprintf(stderr, "twm: out of memory\n"); X exit(1); X } X strcpy(ptr, action); X ptr = ExpandFilename(ptr); X } X X /* first get rid of the existing menu structure and destroy all X * windows */ X for (root = MenuList; root != NULL;) X { X for (item = root->last; item != NULL;) X { X if (item->pull != NULL) X { X XDeleteContext(dpy, item->pull, MenuContext); X XDestroyWindow(dpy, item->pull); X } X XDeleteContext(dpy, item->w, MenuContext); X XDestroyWindow(dpy, item->w); X X free(item->item); X free(item->action); X X tmp_item = item; X item = item->prev; X free(tmp_item); X } X X XDeleteContext(dpy, root->w, MenuContext); X XDestroyWindow(dpy, root->shadow); X XDestroyWindow(dpy, root->w); X free(root->name); X X tmp_root = root; X root = root->next; X free(tmp_root); X } X MenuList = NULL; X LastMenu = NULL; X ActiveMenu = NULL; X ActiveItem = NULL; X X UngrabAllButtons(); X UngrabAllKeys(); X X ParseTwmrc(ptr); X X GrabAllButtons(); X GrabAllKeys(); X break; X X case F_REFRESH: X w = XCreateSimpleWindow(dpy, Root, X 0, 0, 9999, 9999, 0, Black, Black); X XMapWindow(dpy, w); X XDestroyWindow(dpy, w); X XFlush(dpy); X break; X X case F_WINREFRESH: X if (DeferExecution(context, func, DotCursor)) X return; X X if (context == C_ICON) X w = XCreateSimpleWindow(dpy, tmp_win->icon_w, X 0, 0, 9999, 9999, 0, Black, Black); X else X w = XCreateSimpleWindow(dpy, tmp_win->frame, X 0, 0, 9999, 9999, 0, Black, Black); X X XMapWindow(dpy, w); X XDestroyWindow(dpy, w); X XFlush(dpy); X break; X X case F_QUIT: X Done(); X break; X } X XUngrabPointer(dpy, CurrentTime); X} X X/*********************************************************************** X * X * Procedure: X * DeferExecution - defer the execution of a function to the X * next button press if the context is C_ROOT X * X * Inputs: X * context - the context in which the mouse button was pressed X * func - the function to defer X * cursor - the cursor to display while waiting X * X *********************************************************************** X */ X Xint XDeferExecution(context, func, cursor) Xint context, func; XCursor cursor; X{ X if (context == C_ROOT) X { X XGrabPointer(dpy, Root, True, X ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeSync, X Root, cursor, CurrentTime); X X RootFunction = func; X X return (TRUE); X } X X return (FALSE); X} X X/*********************************************************************** X * X * Procedure: X * Execute - execute the string by /bin/sh X * X * Inputs: X * s - the string containing the command X * X *********************************************************************** X */ X Xvoid XExecute(s) X char *s; X{ X int status, pid, w; X register int (*istat) (), (*qstat) (); X X if ((pid = vfork()) == 0) X { X signal(SIGINT, SIG_DFL); X signal(SIGQUIT, SIG_DFL); X signal(SIGHUP, SIG_DFL); X execl("/bin/sh", "sh", "-c", s, 0); X _exit(127); X } X istat = signal(SIGINT, SIG_IGN); X qstat = signal(SIGQUIT, SIG_IGN); X while ((w = wait(&status)) != pid && w != -1); X if (w == -1) X status = -1; X signal(SIGINT, istat); X signal(SIGQUIT, qstat); X} X X/*********************************************************************** X * X * Procedure: X * FocusOnRoot - put input focus on the root window X * X *********************************************************************** X */ X Xvoid XFocusOnRoot() X{ X XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); X if (Focus != NULL) X { X if (Highlight && Focus->highlight) X { X XSetWindowBorderPixmap(dpy, Focus->frame, GrayTile); X XSetWindowBorderPixmap(dpy, Focus->title_w, GrayTile); X } X XUnmapWindow(dpy, Focus->hilite_w); X } X Focus = NULL; X FocusRoot = TRUE; X} X END_OF_FILE if test 24165 -ne `wc -c <'menus.c'`; then echo shar: \"'menus.c'\" unpacked with wrong size! fi # end of 'menus.c' fi echo shar: End of archive 5 \(of 7\). cp /dev/null ark5isdone MISSING="" for I in 1 2 3 4 5 6 7 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 7 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 -- Mike Wexler(wyse!mikew) Phone: (408)433-1000 x1330