v01i050: twm: Tom's Window Manager, Part05/07
Mike Wexler
mikew at wyse.wyse.com
Sat Sep 24 01:45:30 AEST 1988
Submitted-by: tom%hpfctel at 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 at 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
More information about the Comp.sources.x
mailing list