mikew@wyse.wyse.com (Mike Wexler) (02/18/89)
Submitted-by: kmw@ardent (Ken Wallich) Posting-number: Volume 3, Issue 19 Archive-name: awm2/part03 #! /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 3 (of 12)." # Contents: Resize.c menus/menu.c menus/menu.ext.h # Wrapped by mikew@wyse on Fri Feb 17 10:50:21 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Resize.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Resize.c'\" else echo shar: Extracting \"'Resize.c'\" \(15574 characters\) sed "s/^X//" >'Resize.c' <<'END_OF_FILE' X X X X#ifndef lint Xstatic char *rcsid_Resize_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/Resize.c,v 1.2 89/02/07 21:23:37 jkh Exp $"; X#endif lint X X#include "X11/copyright.h" X/* X * X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca. X * X * Copyright 1987 by Jordan Hubbard. X * X * X * All Rights Reserved X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation, and that the name of Ardent Computer X * Corporation or Jordan Hubbard not be used in advertising or publicity X * pertaining to distribution of the software without specific, written X * prior permission. X * X */ X X/* X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. X * X * All Rights Reserved X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation, and that the name of Digital Equipment X * Corporation not be used in advertising or publicity pertaining to X * distribution of the software without specific, written prior permission. X * X * X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X X/* X * MODIFICATION HISTORY X * X * 000 -- M. Gancarz, DEC Ultrix Engineering Group X * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group X * Convert to X11 X * 002 -- Jordan Hubbard, U.C. berkeley. X * Added alternate placement of resize window, code for title bar X * support. X */ X X#include "awm.h" X#include "X11/Xutil.h" X X#define max(a,b) ( (a) > (b) ? (a) : (b) ) X#define min(a,b) ( (a) > (b) ? (b) : (a) ) X#define makemult(a, b) ((b==1) ? (a) : (((int)((a) / (b))) * (b)) ) X X/*ARGSUSED*/ XBoolean Resize(window, mask, button, x0, y0) XWindow window; /* Event window. */ Xint mask; /* Button/key mask. */ Xint button; /* Button event detail. */ Xint x0, y0; /* Event mouse position. */ X{ X XWindowAttributes client_info; /* client window info. */ X XWindowAttributes frame_info; /* frame window info */ X int x1, y1; /* fixed box corner */ X int x2, y2; /* moving box corner */ X int x, y; X int xinc, yinc; X int minwidth, minheight; X int maxwidth, maxheight; X int ox, oy; /* which quadrant of window */ X int pop_x, pop_y; /* location of pop window */ X int hsize, vsize; /* dynamic size */ X int delta; X int junk_x, junk_y; X unsigned int ptrmask; /* pointer status word */ X int num_vectors; /* Number of vectors to XDraw. */ X Window sub_win; /* Mouse query sub window. */ X Window root; /* Root query window. */ X XEvent button_event, *b_ev; /* Button event packet. */ X XSegment box[MAX_BOX_VECTORS]; /* Box drawing vertex buffer. */ X XSegment zap[MAX_ZAP_VECTORS]; /* Zap drawing vertex buffer. */ X Boolean stop; /* Should the window stop changing? */ X XSizeHints sizehints; X XWindowChanges values; X int width_offset, height_offset; /* to subtract if resize increments */ X int x_offset, y_offset; /* add to pointer to get anchor */ X AwmInfoPtr awi; X int (*storegrid_func)(); /* which StoreGrid routine to use */ X int (*storebox_func)(); /* which StoreBox routing to use */ X int buttonConfirmEvent; X extern void ungrab_pointer(); X extern void grab_pointer(); X X Entry("Resize") X X /* X * Do nothing if the event window is the root window. X */ X if (window == RootWindow(dpy, scr)) X Leave(FALSE) X X /* X * Gather info about the event window. X */ X awi = GetAwmInfo(window); X if (!awi) X Leave(FALSE) X /* X * Do not resize an icon window. X */ X if (window == awi->icon) X Leave(FALSE) X X window = awi->client; X b_ev = &button_event; X buttonConfirmEvent = ButtonRelease; X X status = XGetWindowAttributes(dpy, window, &client_info); X if (status == FAILURE) X Leave(FALSE) X X if (awi->frame) { /* we have to compensate */ X status = XGetWindowAttributes(dpy, awi->frame, &frame_info); X client_info.y = frame_info.y; X client_info.x = frame_info.x; X if (status == FAILURE) X Leave(FALSE) X if (DECORATED(awi)) { X if (awi->title) X client_info.y += titleHeight + 2; X if (awi->attrs & AT_BORDER) { X client_info.x += BContext + 1; X if (!awi->title) X client_info.y += BContext + 1; X } X } X } X X /* X * Clear The vector buffers. X */ X bzero(box, sizeof(box)); X if (Zap) X bzero(zap, sizeof(zap)); X storegrid_func = StoreGridBox; X storebox_func = StoreBox; X X /* X * If we are here then we have a resize operation in progress. X */ X X /* X * Turn on the resize cursor. X */ X grab_pointer(); X /* X * calculate fixed point (x1, y1) and varying point (x2, y2). X */ X hsize = client_info.width; X vsize = client_info.height; X x1 = client_info.x; X y1 = client_info.y; X x2 = x1 + hsize; X y2 = y1 + vsize; X X /* X * Get the event window resize hint. X */ X sizehints.flags = 0; X XGetSizeHints(dpy, window, &sizehints, XA_WM_NORMAL_HINTS); X CheckConsistency(&sizehints); X X /* until there are better WM_HINTS, we'll assume that the client's X * minimum width and height are the appropriate offsets to subtract X * when resizing with an explicit resize increment. X */ X if ((sizehints.flags & PMinSize) && (sizehints.flags & PResizeInc)) { X width_offset = sizehints.min_width; X height_offset = sizehints.min_height; X } else X width_offset = height_offset = 0; X X /* X * decide what resize mode we are in. Always rubberband if window X * is too small. X */ X if (client_info.width > 2 && client_info.height > 2) { X ox = ((x0 - client_info.x) * 3) / client_info.width; X oy = ((y0 - client_info.y) * 3) / client_info.height; X if ((ox + oy) & 1) { X if (ox & 1) { X /* fix up size hints so that we will never change width */ X sizehints.min_width = sizehints.max_width = X client_info.width; X if ((sizehints.flags & PMinSize) == 0) { X sizehints.min_height = 0; X sizehints.flags |= PMinSize; X } X if ((sizehints.flags & PMaxSize) == 0) { X sizehints.max_height = DisplayHeight(dpy, scr); X sizehints.flags |= PMaxSize; X } X } X if (oy & 1) { X /* fix up size hints so that we will never change height */ X sizehints.min_height = sizehints.max_height = X client_info.height; X if ((sizehints.flags & PMinSize)==0) { X sizehints.min_width = 0; X sizehints.flags |= PMinSize; X } X if ((sizehints.flags & PMaxSize)==0) { X sizehints.max_width = DisplayWidth(dpy, scr); X sizehints.flags |= PMaxSize; X } X } X } X } X else ox = oy = 2; X /* change fixed point to one that shouldn't move */ X if (oy == 0) { X y = y1; y1 = y2; y2 = y; X } X if (ox == 0) { X x = x1; x1 = x2; x2 = x; X } X if (sizehints.flags & PMinSize) { X minwidth = sizehints.min_width; X minheight = sizehints.min_height; X } else { X minwidth = 0; X minheight = 0; X } X if (sizehints.flags & PMaxSize) { X maxwidth = max(sizehints.max_width, minwidth); X maxheight = max(sizehints.max_height, minheight); X } else { X maxwidth = DisplayWidth(dpy, scr); X maxheight = DisplayHeight(dpy, scr); X } X if (sizehints.flags & PResizeInc) { X xinc = sizehints.width_inc; X yinc = sizehints.height_inc; X } else { X xinc = 1; X yinc = 1; X } X switch (ox) { X case 0: X pop_x = x1 - PWidth; X break; X case 1: X pop_x = x1 + (hsize - PWidth) / 2; X break; X case 2: X pop_x = x1; X break; X } X switch (oy) { X case 0: X pop_y = y1 - PHeight; X break; X case 1: X pop_y = y1 + (vsize - PHeight) / 2; X break; X case 2: X pop_y = y1; X break; X } X /* X * Double expose on the target window is too expensive for some reason X * or another. Paint the popup window in the upper left hand X * corner of the screen if RootResizeBox is FALSE. This is also X * more-or-less consistent with the position of the map request popup. X */ X if (RootResizeBox == TRUE) X values.x = values.y = 0; X else { X if (pop_x < 0 || pop_x > (DisplayWidth(dpy, scr) - PWidth)) X pop_x = 0; X if (pop_y < 0 || pop_y > (DisplayHeight(dpy, scr) - PHeight)) X pop_y = 0; X values.x = pop_x; X values.y = pop_y; X } X values.stack_mode = Above; X XConfigureWindow(dpy, Pop, (unsigned int) CWX|CWY|CWStackMode, &values); X XMapWindow(dpy, Pop); X if (Grid) { X num_vectors = (*storegrid_func)(box, X MIN(x1, x2), MIN(y1, y2), X MAX(x1, x2), MAX(y1, y2)); X } X else { X num_vectors = (*storebox_func)(box, X MIN(x1, x2), MIN(y1, y2), X MAX(x1, x2), MAX(y1, y2)); X } X X /* X * If we freeze the server, then we will draw solid X * lines instead of flickering ones during resizing. X */ X if (Freeze) X XGrabServer(dpy); X /* protect us from ourselves */ X Snatched = True; X /* X * Process any pending exposure events before drawing the box. X */ X while (QLength(dpy) > 0) { X XPeekEvent(dpy, b_ev); X if (b_ev->xany.window == RootWindow(dpy, scr)) X break; X GetButton(b_ev); X } X if (ResizeRelative) { X x_offset = x2 - x0; X y_offset = y2 - y0; X } X else X x_offset = y_offset = 0; X X /* X * Now draw the box. X */ X DrawBox(); X Frozen = window; X X stop = FALSE; X x = -1; y = -1; X X while (!stop) { X if (x != x2 || y != y2) { X x = x2; y = y2; X X /* X * If we've frozen the server, then erase X * the old box. X */ X if (Freeze) X DrawBox(); X X if (Grid) { X num_vectors = (*storegrid_func)(box, X MIN(x1, x), MIN(y1, y), X MAX(x1, x), MAX(y1, y)); X } X else { X num_vectors = (*storebox_func)(box, X MIN(x1, x), MIN(y1, y), X MAX(x1, x), MAX(y1, y)); X } X X if (Freeze) X DrawBox(); X X { X int Hsize = (hsize - width_offset) / xinc; X int Vsize = (vsize - height_offset) / yinc; X int pos = 4; X PText[0] = (Hsize>99) ? (Hsize / 100 + '0') : ' '; X PText[1] = (Hsize>9) ? ((Hsize / 10) % 10 + '0') : ' '; X PText[2] = Hsize % 10 + '0'; X if (Vsize>99) PText[pos++] = Vsize / 100 + '0'; X if (Vsize>9) PText[pos++] = (Vsize / 10) % 10 + '0'; X PText[pos++] = Vsize % 10 + '0'; X while (pos<7) PText[pos++] = ' '; X } X /* X * If the font is not fixed width we have to X * clear the window to guarantee that the characters X * that were there before are erased. X */ X if (!(PFontInfo->per_char)) X XClearWindow(dpy, Pop); X XDrawImageString( X dpy, Pop, PopGC, X PPadding, PPadding+PFontInfo->ascent, X PText, PTextSize); X } X if (!Freeze) { X DrawBox(); X DrawBox(); X } X X if (XPending(dpy) && !ProcessRequests(box, num_vectors) && X GetButton(b_ev)) { X if ((b_ev->xany.type != ButtonPress) && X (b_ev->xany.type != ButtonRelease)) X continue; /* spurious menu event... */ X X if (Freeze) { X DrawBox(); X Frozen = (Window)0; X XUngrabServer(dpy); X } X X if (b_ev->xany.type == buttonConfirmEvent && X b_ev->xbutton.button == button) X stop = TRUE; X else { X XUnmapWindow(dpy, Pop); X ResetCursor(button); X Snatched = False; X ungrab_pointer(); X Leave(TRUE) X } X } X else { X XQueryPointer(dpy, RootWindow(dpy, scr), &root, X &sub_win, &x2, &y2, &junk_x, &junk_y, &ptrmask); X x2 += x_offset; /* get to anchor point */ X y2 += y_offset; X } X hsize = max(min(abs (x2 - x1), maxwidth), minwidth); X hsize = makemult(hsize - minwidth, xinc) + minwidth; X X vsize = max(min(abs(y2 - y1), maxheight), minheight); X vsize = makemult(vsize - minheight, yinc) + minheight; X if (sizehints.flags & PAspect) { X if ((hsize * sizehints.max_aspect.y > X vsize * sizehints.max_aspect.x)) { X delta = makemult((hsize * sizehints.max_aspect.y / X sizehints.max_aspect.x) - vsize, X yinc); X if ((vsize + delta <= maxheight)) X vsize += delta; X else { X delta = makemult(hsize - X (sizehints.max_aspect.x * X vsize/sizehints.max_aspect.y), X xinc); X if (hsize - delta >= minwidth) X hsize -= delta; X } X } X if (hsize * sizehints.min_aspect.y < vsize * X sizehints.min_aspect.x) { X delta = makemult((sizehints.min_aspect.x * X vsize/sizehints.min_aspect.y) - hsize, X xinc); X if (hsize + delta <= maxwidth) X hsize += delta; X else { X delta = makemult(vsize - X (hsize*sizehints.min_aspect.y / X sizehints.min_aspect.x), X yinc); X if (vsize - delta >= minheight) X vsize -= delta; X } X } X X } X if (ox == 0) X x2 = x1 - hsize; X else X x2 = x1 + hsize; X X if (oy == 0) X y2 = y1 - vsize; X else X y2 = y1 + vsize; X X } X if (x2 < x1) { X x = x1; x1 = x2; x2 = x; X } X if (y2 < y1) { X y = y1; y1 = y2; y2 = y; X } X XUnmapWindow(dpy, Pop); X if ((x1 !=client_info.x) || (y1 != client_info.y) || X (hsize != client_info.width) || X (vsize != client_info.height)) { X XWindowChanges xwc; X X xwc.x = x1; X xwc.y = y1; X xwc.width = hsize; X xwc.height = vsize; X ConfigureWindow(window, X (unsigned int) CWX | CWY | CWHeight | CWWidth, &xwc); X } X Snatched = False; X ungrab_pointer(); X Leave(TRUE) X} X XCheckConsistency(hints) XXSizeHints *hints; X{ X Entry("CheckConsistency") X X if (hints->min_height < 0) X hints->min_height = 0; X if (hints->min_width < 0) X hints->min_width = 0; X X if (hints->max_height <= 0 || hints->max_width <= 0) X hints->flags &= ~PMaxSize; X X hints->min_height = min(DisplayHeight(dpy, scr), hints->min_height); X hints->min_width = min(DisplayWidth(dpy, scr), hints->min_width); X X hints->max_height = min(DisplayHeight(dpy, scr), hints->max_height); X hints->max_width = min(DisplayWidth(dpy, scr), hints->max_width); X X if ((hints->flags & PMinSize) && (hints->flags & PMaxSize) && X ((hints->min_height > hints->max_height) || X (hints->min_width > hints->max_width))) X hints->flags &= ~(PMinSize|PMaxSize); X X if ((hints->flags & PAspect) && X (hints->min_aspect.x * hints->max_aspect.y > X hints->max_aspect.x * hints->min_aspect.y)) X hints->flags &= ~(PAspect); X Leave_void X} END_OF_FILE if test 15574 -ne `wc -c <'Resize.c'`; then echo shar: \"'Resize.c'\" unpacked with wrong size! fi # end of 'Resize.c' fi if test -f 'menus/menu.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'menus/menu.c'\" else echo shar: Extracting \"'menus/menu.c'\" \(33843 characters\) sed "s/^X//" >'menus/menu.c' <<'END_OF_FILE' X X#ifndef lint X static char sccs_id[] = "@(#)menu.c 2.1 12/16/87 Siemens Corporate Research and Support, Inc."; X#endif X X X/* X RTL Menu Package Version 1.0 X by Joe Camaratta and Mike Berman, Siemens RTL, Princeton NJ, 1987 X X menu.c: menu utility and support functions. X X Originally hacked by Adam J. Richter, based on the menu package for xterm. X ( misc.c X10/6.6 ) X X */ X X/* X * X * Changed in various and subtle ways by Jordan Hubbard, Ardent Computer. X * February 1st, 1988: Removed dependence on oldX by nuking AssocTable X * stuff in favor of contexts. Added "label" panes, useful for titling X * purposes. Variable height items, variable fonts, pictoral panes X * (pixmaps) for cute graphic menus. X */ X X/* X * X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca. X * X * Copyright 1987 by Jordan Hubbard. X * X * X * All Rights Reserved X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation, and that the name of Ardent Computer X * Corporation or Jordan Hubbard not be used in advertising or publicity X * pertaining to distribution of the software without specific, written X * prior permission. X * X */ X X X/* X X Copyright 1987 by X Siemens Corporate Research and Support, Inc., Princeton, New Jersey X X Permission to use, copy, modify, and distribute this software X and its documentation for any purpose and without fee is X hereby granted, provided that the above copyright notice X appear in all copies and that both that copyright notice and X this permission notice appear in supporting documentation, and X that the name of Siemens not be used in advertising or X publicity pertaining to distribution of the software without X specific, written prior permission. Siemens makes no X representations about the suitability of this software for any X purpose. It is provided "as is" without express or implied X warranty. X X */ X X/* X X Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology X X Permission to use, copy, modify, and distribute this X software and its documentation for any purpose and without X fee is hereby granted, provided that the above copyright X notice appear in all copies and that both that copyright X notice and this permission notice appear in supporting X documentation, and that the name of M.I.T. not be used in X advertising or publicity pertaining to distribution of the X software without specific, written prior permission. X M.I.T. makes no representations about the suitability of X this software for any purpose. It is provided "as is" X without express or implied warranty. X X */ X X/* X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. X * X * All Rights Reserved X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation, and that the name of Digital Equipment X * Corporation not be used in advertising or publicity pertaining to X * distribution of the software without specific, written prior permission. X * X * X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS X * SOFTWARE. X */ X X/* Got that? Good! Now, there is actually some code in here.. */ X X X#include <stdio.h> X#include "X11/Xlib.h" X#include "X11/cursorfont.h" X#include "X11/Xutil.h" X#include "X11/Intrinsic.h" X X#include "menu.h" X#include "menu.def.h" X#include "gray1.h" X#include "arrow_icon.h" X#include "dbug.h" X X#define MakeEven(x) ((x%2 == 0)? x : x-1) X X X#define InvertPlane 1 X Xstatic char Check_MarkBits[] = { X 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, X 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 X }; X XMenu MenuDefault; X X/* X * the following have already been set my GetDefaults() X * by the time we get here. X */ XXFontStruct *MFontInfo; XXFontStruct *MBoldFontInfo; Xint MBorderWidth, MPad, MDelta, MItemBorder; XPixel MForeground, MBackground, MBorder; X Xextern Boolean SaveUnder; Xextern int Reverse; Xextern Display *dpy; Xextern int scr; X Xstatic XContext Menu_context; Xstatic XContext Item_context; Xstatic contexts_created = FALSE; X XMenuItem *AddMenuItem(), *Display_Menu(), *MenuGetItem(), X *MenuItemByName(), *MenuItemByData(), *GetInitialItem(), *MoveMenu(); XBoolean DisposeItem(), SetItemCheck(), SetItemDisable(), Recalc_Menu(), X SetupItems(), MapMenu(), SetItemText(), SetupMenuWindow(); Xvoid DisposeMenu(), InitMenu(), Undisplay_Menu(), MenuInvert(), X PlacePointer(), Draw_Menu(), Draw_Item(), SetInitialItem(), X ClearInitialItem(), Generate_Menu_Entries(), UnmapMenu(), X SetInputMask(); XMenu *NewMenu(), *MenuGetMenu(); Xint ItemGetMiddleY(); X X/* X * AddMenuItem() adds a menu item to an existing menu, at the end of the X * list, which are number sequentially from zero. The menuitem index is X * return, or -1 if failed. X */ X XMenuItem *AddMenuItem(menu, text, bitmap_file) XMenu *menu; Xchar *text; Xchar *bitmap_file; X{ X MenuItem *menuitem, **next; X int junk; X char *data; X X Entry("AddMenuItem") X X if (!menu || (!text && !bitmap_file) || (menuitem = allocate(MenuItem, 1)) X == (MenuItem *)0) X Leave(NULLITEM) X bzero((char *)menuitem, sizeof(MenuItem)); X ItemText(menuitem) = allocate(char, (strlen(text) + 1)); X strcpy(ItemText(menuitem), text); X ItemTextLength(menuitem) = strlen(text); X if (bitmap_file) { X bitmap_file = (char *)expand_from_path(bitmap_file); X if (XmuReadBitmapDataFromFile(bitmap_file, X &(menuitem->itemTextWidth), X &(menuitem->itemHeight), X &data, X &junk, &junk) != BitmapSuccess) { X fprintf(stderr, "awm: Can't read bitmap file '%s'\n", X bitmap_file); X exit(1); X } X menuitem->itemBackground = X XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr), X data, X menuitem->itemTextWidth, X menuitem->itemHeight, X MForeground, X MBackground, X DefaultDepth(dpy, scr)); X if (!menuitem->itemBackground) { X fprintf(stderr, "awm: Can't create pixmap for file '%s'\n", X bitmap_file); X exit(1); X } X free(data); X free(bitmap_file); X } X for(next = &menu->menuItems; *next; next = &(*next)->nextItem); X X *next = menuitem; X X SetMenuFlag(menu, menuChanged); X Leave(menuitem) X} X X/* X * DisposeItem() releases the memory allocated for the given indexed X * menuitem. Nonzero is returned if an item was actual disposed of. X * It also checks to see whether the item we're disposing is the X * initial item for the menu -- if so, null out the initial item. X */ XBoolean DisposeItem(menu, item) XMenu *menu; XMenuItem *item; X{ X MenuItem **next, **last, *menuitem; X X Entry("DisposeItem") X X if (MenuIsNull(menu) || ItemIsNull(item)) X Leave(FALSE) X next = &MenuItems(menu); X do { X if(!*next) X Leave(FALSE) X last = next; X next = &(*next)->nextItem; X } while((*last != item) && !ItemIsNull(*next)); X menuitem = *last; X *last = *next; X if (ItemWindow(menuitem)) { X XDeleteContext(dpy, ItemWindow(menuitem), Item_context); X XDestroyWindow(dpy, ItemWindow(menuitem)); X } X if (ItemIsInitialItem(menu, menuitem)) X ClearInitialItem(menu); X X if (ItemText(menuitem)) X free((char*)ItemText(menuitem)); X free((char*)menuitem); X X SetMenuFlag(menu, menuChanged); X Leave(TRUE) X} X X/* X * DisposeMenu() releases the memory allocated for the given menu. X */ Xvoid DisposeMenu(menu) XMenu *menu; X{ X Entry("DisposeMenu") X X if(!menu) X Leave_void X if (TestMenuFlag(menu, menuMapped)) X UnmapMenu(menu); X while(DisposeItem(menu, MenuItems(menu))); X if(MenuWindow(menu)) { X XDeleteContext(dpy, MenuWindow(menu), Menu_context); X XDestroyWindow(dpy, MenuWindow(menu)); X } X XFreePixmap (dpy, MenuGreyPixmap(menu)); X XFreePixmap (dpy, MenuArrowPixmap(menu)); X XFreePixmap (dpy, MenuCheckmarkPixmap(menu)); X XFreeGC (dpy, MenuNormalGC(menu)); X XFreeGC (dpy, MenuInvertGC(menu)); X XFreeGC (dpy, menu->boldGC); X X if (MenuHasInitialItem(menu)) X ClearInitialItem(menu); X free((char*) menu); X Leave_void X} X Xstatic char *Name; X Xvoid InitMenu(name, options) Xchar *name; Xunsigned int options; X{ X char *cp; X X Entry("InitMenu") X X Name = name; X MenuDefault.menuFlags = menuChanged; X X MenuDefault.menuInitialItemText = (char *) NULL; X MenuDefault.display = dpy; X MenuDefault.screen = scr; X MenuDefault.menuOptions = options; X Leave_void X} X X/* X * ItemText changes the text of item of the menu. X */ XBoolean SetItemText(menu, item, text) XMenu *menu; XMenuItem *item; Xchar *text; X{ X Entry("SetItemText") X X if (strcmp (ItemText(item), text) == 0) X Leave (True) X X if(ItemText(item)) X free((char *) ItemText(item)); X X ItemText(item) = allocate(char, (strlen(text) + 1)); X strcpy(ItemText(item), text); X X ItemTextLength(item) = strlen (text); X SetMenuFlag(menu, menuChanged); X X (void) Recalc_Menu (menu); X Leave(TRUE) X} X X/* X * NewMenu() returns a pointer to an initialized new Menu structure, or NULL X * if failed. X * X * The Menu structure _menuDefault contains the default menu settings. X */ XMenu *NewMenu() X{ X extern Pixmap MakeGreyStipple (); X Menu *menu = 0; X X XGCValues gcValues; X X static unsigned long gcMask = X (GCFunction | GCForeground | GCBackground | GCFont | GCStipple | X GCSubwindowMode | GCGraphicsExposures); X X char *cp; X X Entry("NewMenu") X X /* X * Allocate the memory for the menu structure. X */ X if(MenuIsNull((menu = allocate(Menu, 1)))) X Leave(NULLMENU) X X /* X * Initialize to default values. X */ X *menu = MenuDefault; X gcValues.font = MFontInfo->fid; X X /* X * If the menu cursor hasn't been given, make a default one. X */ X X MenuCursor(menu) = XCreateFontCursor (dpy, XC_right_ptr); X MenuArrowPixmap(menu) = XCreatePixmapFromBitmapData(dpy, X RootWindow(dpy, scr), X arrow_bits, X arrow_width, X arrow_height, X MForeground, X MBackground, X DefaultDepth(dpy, scr)); X X MenuGreyPixmap(menu) = XCreateBitmapFromData(dpy, X RootWindow(dpy, scr), X gray1_bits, X gray1_width, gray1_height); X X MenuCheckmarkPixmap(menu) = XCreatePixmapFromBitmapData(dpy, X RootWindow(dpy, scr), X Check_MarkBits, X checkMarkWidth, X checkMarkHeight, X MForeground, X MBackground, X DefaultDepth(dpy, scr)); X X gcValues.foreground = MForeground; X gcValues.background = MBackground; X X gcValues.stipple = MenuGreyPixmap(menu); X gcValues.function = GXcopy; X gcValues.subwindow_mode = IncludeInferiors; X gcValues.graphics_exposures = False; X MenuNormalGC(menu) = X XCreateGC (dpy, RootWindow(dpy, scr), X gcMask, X &gcValues); X /* reverse */ X gcValues.foreground = MBackground; X gcValues.background = MForeground; X X MenuInvertGC(menu) = XCreateGC(dpy, RootWindow (dpy, scr), X gcMask, X &gcValues); X gcValues.foreground = MForeground; X gcValues.background = MBackground; X gcValues.font = MBoldFontInfo->fid; X menu->boldGC = XCreateGC(dpy, RootWindow(dpy, scr), X gcMask, X &gcValues); X Leave(menu) X} X X X/* X * SetItemCheck sets the check state of item of the menu to "state". X */ XBoolean SetItemCheck(menu, item, state) XMenu *menu; XMenuItem *item; Xint state; X{ X Entry("SetItemCheck") X X if (TestItemFlag(item,itemChecked) == state) /* Exit if unchanged */ X Leave (True) X X if (state) X SetItemFlag(item, itemChecked); X else X ResetItemFlag(item, itemChecked); X X SetItemFlag(item, itemChanged); X SetMenuFlag(menu, menuItemChanged); X X Leave(TRUE) X} X/* X * SetItemDeaf sets the "deaf" state of item of the menu to "state". X * "deaf" means that the item is display only and not sensitive to input. X */ XBoolean SetItemDeaf(menu, item, state) XMenu *menu; XMenuItem *item; Xint state; X{ X Entry("SetItemDeaf") X X if (TestItemFlag(item,itemDeaf) == state) /* Exit if unchanged */ X Leave (True) X X if (state) X SetItemFlag(item, itemDeaf); X else X ResetItemFlag(item, itemDeaf); X X SetItemFlag(item, itemChanged); X SetMenuFlag(menu, menuItemChanged); X if (ItemIsInitialItem(menu, item)) X ClearInitialItem(menu); X Leave(TRUE) X} X X/* X * SetItemDisable sets the disable state of item "n" of the menu to "state". X */ XBoolean SetItemDisable(menu, item, state) XMenu *menu; XMenuItem *item; Xint state; X{ X Entry("SetItemDisable") X X if (TestItemFlag(item,itemDisabled) == state) /* Exit if unchanged */ X Leave (True) X X if(state) X { X SetItemFlag(item, itemDisabled); X /* if disabled item is currently initial item, null initial item */ X if (ItemIsInitialItem(menu, item)) X ClearInitialItem(menu); X } X else X ResetItemFlag(item, itemDisabled); X X SetItemFlag(item, itemChanged); X SetMenuFlag(menu, menuItemChanged); X X Leave(TRUE) X} X XMenuItem *Display_Menu(menu, parent, x, y) XMenu *menu; XMenu *parent; Xint x; Xint y; X{ X MenuItem *item; X X Entry("Display_Menu") X X if (MenuIsNull(menu)) X Leave(FALSE) X X MenuParent(menu) = parent; X X if (MenuIsNull(parent)) X MenuNested(menu) = 0; X else X MenuNested(menu) = MenuNested(parent) + 1; X if (!MenuWindow(menu) || TestMenuFlag(menu, X (menuChanged | menuItemChanged))) { X if (!SetupMenuWindow(menu)) X Leave(NULL) X Generate_Menu_Entries(menu); X } X if (TestOptionFlag(menu,savebits) && X (MenuSavedPixmap(menu) != (Pixmap) 0)) X SetInputMask(menu, MenuIgnoreMask); X else X SetInputMask(menu, ExposureMask); X if (!(item = MoveMenu(menu, x, y)) || !MapMenu(menu)) X Leave(FALSE) X Draw_Menu(menu); X X Leave(item) X} X Xvoid Undisplay_Menu(menu) XMenu *menu; X{ X Entry("Undisplay_Menu") X X if (MenuIsNull(menu)) X Leave_void X X MenuParent(menu) = NULLMENU; X MenuNested(menu) = 0; X X UnmapMenu(menu); X Leave_void X} X Xvoid MenuInvert(menu, item) XMenu *menu; XMenuItem *item; X{ X Entry("MenuInvert") X X XFillRectangle(dpy, X ItemWindow(item), X MenuInvertGC(menu), X 0, 0, X MenuWidth(menu), X item->itemHeight); X Leave_void X} X X/* X * Recalculate all of the various menu and item variables. X */ XBoolean Recalc_Menu(menu) XMenu *menu; X{ X MenuItem *item; X int max, height, fontheight, boldfontheight, nitems; X /* Gets set to false first time we see an item with text */ X unsigned int menuIsPictures = TRUE; X X Entry("Recalc_Menu") X X /* X * We must have already gotten the menu font. X */ X if(!MFontInfo) X Leave(FALSE) X /* X * Initialize the various max width variables. X */ X fontheight = MFontInfo->ascent + MFontInfo->descent + 2; X boldfontheight = MBoldFontInfo->ascent + MBoldFontInfo->descent + 2; X height = nitems = 0; X MenuMaxTextWidth(menu) = 0; X /* X * The item height is the maximum of the font height and the X * checkbox height, unless we find out that it's a pixmap (in which X * case, most of these values are overridden). X */ X max = fontheight; X if(checkMarkHeight > max) X max = checkMarkHeight; X X max += 2*MItemBorder; X max = MakeEven(max); X X /* X * Go through the menu item list. X */ X for(item = MenuItems(menu) ; item ; item = ItemNext(item)) { X if (item->itemBackground) /* pixmap is static size */ X max = item->itemHeight; X else { X if (ItemIsDeaf(item)) /* It's a label, use bold info */ X max = boldfontheight; X else X max = fontheight; X } X if (checkMarkHeight > max) X max = checkMarkHeight; X if (!item->itemBackground) { X max += 2 * MItemBorder; X max = MakeEven(max); X item->itemHeight = max; X } X height += max; X nitems++; X /* X * Check the text width with the max value stored in X * menu. X */ X if (!item->itemBackground) { X if ((ItemTextWidth(item) = XTextWidth(ItemIsDeaf(item) ? X MBoldFontInfo X : MFontInfo, X ItemText(item), X strlen (ItemText(item)))) X > MenuMaxTextWidth(menu)) X MenuMaxTextWidth(menu) = ItemTextWidth(item); X menuIsPictures = FALSE; X } X /* ItemTextWidth is really pixmap size. Yick. */ X else { X if (ItemTextWidth(item) > MenuMaxTextWidth(menu)) X MenuMaxTextWidth(menu) = ItemTextWidth(item); X } X X } X /* X * Set the menu height and then set the menu width. X */ X MenuHeight(menu) = height; X menu->avgHeight = height / nitems; X X if (menuIsPictures == TRUE) X MenuWidth(menu) = MenuMaxTextWidth(menu) + (2 * MItemBorder); X else { X MenuWidth(menu) = 4 * MenuItemPad(menu) + MenuMaxTextWidth(menu) + X checkMarkWidth + arrow_width + (2 * MItemBorder); X } X MenuItemWidth(menu) = MenuWidth(menu) - (2 * MItemBorder); X Leave(TRUE) X} X X/* X * Figure out where to popup the menu, relative to the where the button was X * pressed. X * Returns pointer to initial item to warp to. X */ Xstatic MenuItem *MoveMenu(menu, ev_x, ev_y) XMenu *menu; Xint ev_x, ev_y; X{ X int x, y; X int total_width, total_height; X int offset; X MenuItem *item; X Window junk; X int r_x, foo, state; X X Entry("MoveMenu") X X /* X * Get the coordinates of the mouse when the button was pressed. X */ X X total_width = MenuWidth(menu) + 2 * MenuBorderWidth(menu); X total_height = MenuHeight(menu) + 2 * MenuBorderWidth(menu); X X XQueryPointer(dpy, RootWindow(dpy, scr), &junk, &junk, &r_x, &y, X &foo, &foo, &state); X x = ev_x - MenuItemPad(menu); X if (x < 0) X x = 0; X else if (TestOptionFlag(menu, rightoffset) && X !MenuIsNull(MenuParent(menu))) X { X /* check whether parent is close to right edge... */ X /* "too close" means that child would leave < delta of its parent */ X /* visible to its left. */ X if (TestOptionFlag(menu, bigoffset)) X { X if (MenuX(MenuParent(menu)) + MenuWidth(MenuParent(menu)) > X DisplayWidth(dpy, scr) - total_width) X x = MenuX(MenuParent(menu)) X - total_width + 2*MenuBorderWidth(menu); X } X else X { X if (MenuX(MenuParent(menu)) + MenuDelta(MenuParent(menu)) > X DisplayWidth(dpy, scr) - total_width) X { X x = (MenuX(MenuParent(menu)) + MenuWidth(MenuParent(menu)) + X 2 * MenuBorderWidth(MenuParent(menu)) X - total_width - MenuDelta(menu)); X } X } X } X if (x + total_width > X DisplayWidth(dpy, scr)) X x = DisplayWidth(dpy, scr) X - total_width; X X /* X * If we have an initial item, try to popup the menu centered X * vertically within this item. X */ X if(MenuHasInitialItem(menu)) { X int tmp_y; X X /* X * Look through the item list. "y" is the vertical position X * of the top of the current item and "n" is the item number. X */ X offset = MenuBorderWidth(menu); X for(item = MenuItems(menu) ; ;) { X /* X * On finding the initial item, center within this item. X */ X if (ItemIsInitialItem(menu, item)) { X y -= offset; X break; X } X else X offset += item->itemHeight; X /* X * If we run out of items, turn off the initial item X * and treat this as if no initial item. X */ X if(!(item = ItemNext(item))) { X ClearInitialItem(menu); X break; X } X } X } X X if (y < 0) X y = 0; X else if (y + total_height > X DisplayHeight(dpy, scr)) X { X y = DisplayHeight(dpy, scr) X - (total_height + 1); X } X y = MakeEven(y) + 1; X XMoveWindow(dpy, MenuWindow(menu), x, y); X MenuX(menu) = x; X MenuY(menu) = y; X X if (!ItemIsInitialItem(menu, item)) X item = MenuItems(menu); X Leave(item) X} X X Xvoid PlacePointer(menu, item) XMenu *menu; XMenuItem *item; X{ X int y; X X Entry("PlacePointer") X X y = ItemGetMiddleY(item); X X XWarpPointer(dpy, None, X RootWindow(dpy, scr), X 0, 0, 0, 0, X MenuX(menu) + MPad + (MenuWidth(menu) / 2), y); X Leave_void X} X X/* X * Map the menu window. X */ Xstatic Boolean MapMenu(menu) XMenu *menu; X{ X Entry("MapMenu") X X if (!TestMenuFlag(menu, menuMapped)) X MenuItemHighlighted(menu) = NULLITEM; X X /* X * Actually map the window. X */ X X if (TestOptionFlag(menu,savebits)) X { X if ((MenuSavedPixmap(menu) == (Pixmap) 0) || X (MenuOldWidth(menu) != MenuWidth(menu)) || X (MenuOldHeight(menu) != MenuHeight(menu)) || X (MenuOldBorderWidth(menu) != MenuBorderWidth(menu))) X { X if (MenuSavedPixmap(menu) != (Pixmap) 0) X XFreePixmap(dpy, MenuSavedPixmap(menu)); X X MenuSavedPixmap(menu) = X XCreatePixmap(dpy, X RootWindow(dpy, scr), X MenuWidth(menu) + 2*MenuBorderWidth(menu), X MenuHeight(menu) + 2*MenuBorderWidth(menu), X DefaultDepth(dpy, scr)); X DBUG_5("Pixmaps","Created pixmap: width %d, height %d, depth %d\n", X MenuWidth(menu) + 2*MenuBorderWidth(menu), X MenuHeight(menu) + 2*MenuBorderWidth(menu), X DefaultDepth(dpy, scr)); X MenuOldWidth(menu) = MenuWidth(menu); X MenuOldHeight(menu) = MenuHeight(menu); X MenuOldBorderWidth(menu) = MenuBorderWidth(menu); X } X else X SetInputMask(menu, ExposureMask); X X if (MenuSavedPixmap(menu) != (Pixmap) 0) { X /* XFillRectangle(dpy, X MenuSavedPixmap(menu), X SaveGC, X 0,0, X MenuWidth(menu) + 2*MenuBorderWidth(menu), X MenuHeight(menu) + 2*MenuBorderWidth(menu)); */ X SetInputMask(menu, MenuIgnoreMask); X XCopyArea(dpy, X RootWindow(dpy, scr), X MenuSavedPixmap(menu), X MenuNormalGC(menu), X MenuX(menu), X MenuY(menu), X (unsigned int) (MenuWidth(menu) + 2*MenuBorderWidth(menu)), X (unsigned int) (MenuHeight(menu) + 2*MenuBorderWidth(menu)), X 0, 0); X } X else X SetInputMask(menu, ExposureMask); X X } X X XRaiseWindow(dpy, MenuWindow(menu)); X XMapWindow(dpy, MenuWindow(menu)); X SetMenuFlag(menu, menuMapped); X Leave(TRUE) X} X Xstatic void Generate_Menu_Entries (menu) XMenu *menu; X{ X MenuItem *item; X X Entry("Generate_Menu_Entries") X X for (item = MenuItems(menu); item; (item = ItemNext(item))) { X X if (ItemGenerator(item)) { X char *newText; X X (ItemGenerator(item)) (&newText, &ItemCallback(item)); X SetItemText (menu, item, newText); X } X X if (ItemCheckproc(item)) X SetItemCheck (menu, item, (ItemCheckproc(item))(menu,item)); X } X Leave_void X} X X/* X * Draw the entire menu in the blank window. X */ Xvoid Draw_Menu(menu) XMenu *menu; X{ X MenuItem *item; X X Entry("Draw_Menu") X X ResetMenuFlag(menu, menuChanged); X /* X * For each item in the list, first draw any check mark and then X * draw the rest of it. X */ X for(item = MenuItems(menu) ; item ; item = ItemNext(item)) { X if (TestOptionFlag(menu, savebits)) X { X /* go ahead and draw it, don't wait for exposes */ X Draw_Item(menu, item); X } X } X Leave_void X} X X/* X * Draw the item at vertical position y. X */ Xvoid Draw_Item(menu, item) XMenu *menu; XMenuItem *item; X{ X int y; /* baseline */ X int x = MenuItemPad(menu); X int x1 = 2 * MenuItemPad(menu) + checkMarkWidth; X int pad; X int high; X XGCValues gcValues; X GC theGC; X X Entry("Draw_Item") X X high = (MenuItemHighlighted(menu) == item); X theGC = high ? MenuInvertGC(menu) : MenuNormalGC(menu); X X if (TestItemFlag(item, itemDisabled)) X { X gcValues.fill_style = FillOpaqueStippled; X XChangeGC(dpy, theGC, (GCFillStyle), &gcValues); X } X X if (!item->itemBackground) { X XFillRectangle(dpy, ItemWindow(item), X (high) ? MenuNormalGC(menu) : MenuInvertGC(menu), X 0, 0, MenuWidth(menu), item->itemHeight); X X /* X * Draw the check mark, possibly dimmed, wherever is necessary. X */ X } X if(TestItemFlag(item, itemChecked)){ X XCopyArea (dpy, MenuCheckmarkPixmap(menu), X ItemWindow(item), X theGC, X 0, 0, checkMarkWidth, checkMarkHeight, X (int) x, (item->itemHeight - checkMarkHeight) / 2); X } X /* Draw submenu indicator arrow */ X if(ItemSubmenu(item)) { X XCopyArea (dpy, MenuArrowPixmap(menu), X ItemWindow(item), X theGC, X 0, 0, X arrow_width, arrow_height, X (int) (x + MenuItemWidth(menu) - X arrow_width - MenuItemPad(menu)), X (item->itemHeight - arrow_height) / 2 - 1); X } X /* X * Draw the text, centered vertically. X */ X if (!item->itemBackground) { X if (!TestItemFlag(item, itemDeaf)) { X pad = (item->itemHeight - X (MFontInfo->ascent + MFontInfo->descent)) / 2; X y = item->itemHeight - pad - MFontInfo->descent; X X XDrawImageString(dpy, ItemWindow(item), X theGC, X x1, y, ItemText(item), ItemTextLength(item)); X if (TestItemFlag(item, itemDisabled)) X { X gcValues.fill_style = FillSolid; X XChangeGC(dpy, theGC, X (GCFillStyle), &gcValues); X } X X } X else { X pad = (item->itemHeight - (MBoldFontInfo->ascent + X MBoldFontInfo->descent)) / 2; X y = item->itemHeight - pad - MBoldFontInfo->descent; X XDrawImageString(dpy, ItemWindow(item), menu->boldGC, x1, y, X ItemText(item), ItemTextLength(item)); X } X } X Leave_void X} X X X/* X * UnmapMenu() unmaps a menu, if it is currently mapped. X */ Xstatic void UnmapMenu(menu) XMenu *menu; X{ X Entry("UnmapMenu") X X if(!menu || !(TestMenuFlag(menu, menuMapped))) X Leave_void X XUnmapWindow(dpy, MenuWindow(menu)); X X if (TestOptionFlag(menu, savebits)) X { X if (MenuSavedPixmap(menu)) X XCopyArea (dpy, X MenuSavedPixmap(menu), X RootWindow (dpy, scr), X MenuNormalGC(menu), X 0, 0, X MenuWidth(menu) + 2*MenuBorderWidth(menu), X MenuHeight(menu) + 2*MenuBorderWidth(menu), X MenuX(menu), MenuY(menu)); X X } X ResetMenuFlag(menu, menuMapped); X Leave_void X} X X Xstatic Boolean SetupMenuWindow (menu) XMenu *menu; X{ X int changed = TestMenuFlag(menu, (menuChanged | menuItemChanged)); X X Entry("SetupMenuWindow") X X if (contexts_created == FALSE) { X contexts_created = TRUE; X Menu_context = XUniqueContext(); X Item_context = XUniqueContext(); X } X X /* X * If the entire menu has changed, throw away any saved pixmap and X * then call RecalcMenu(). X */ X X if(changed & menuChanged) { X if(!Recalc_Menu(menu)) X Leave(FALSE) X changed &= ~menuItemChanged; X } X X if(!MenuWindow(menu)) { X static unsigned long valuemask = X CWOverrideRedirect | CWBorderPixel | CWBackPixel; X XSetWindowAttributes attributes; X X attributes.override_redirect = True; X attributes.border_pixel = MBorder; X attributes.background_pixel = MBackground; X if (SaveUnder) { X attributes.save_under = True; X valuemask |= CWSaveUnder; X } X X if((MenuWindow(menu) = X XCreateWindow(dpy, X RootWindow(dpy, scr), X 0, 0, X MenuWidth(menu), MenuHeight(menu), X MenuBorderWidth(menu), X DefaultDepth(dpy, scr), X InputOutput, X DefaultVisual(dpy, scr), X valuemask, &attributes) X ) == (Window)0) X Leave(FALSE) X else if (SetupItems(menu) == FALSE) X Leave(FALSE) X X XSaveContext(dpy, MenuWindow(menu), Menu_context, (char *) menu); X XMapSubwindows(dpy, MenuWindow(menu)); X X XDefineCursor(dpy, MenuWindow(menu), MenuCursor(menu)); X } X else if(changed & menuChanged) { X XResizeWindow(dpy, MenuWindow(menu), X MenuWidth(menu), MenuHeight(menu)); X if (SetupItems(menu) == FALSE) X Leave(FALSE) X XMapSubwindows(dpy, MenuWindow(menu)); X } X Leave(TRUE) X} X Xstatic Boolean SetupItems(menu) XMenu *menu; X{ X int y; X MenuItem *item; X int changed = TestMenuFlag(menu, (menuChanged | menuItemChanged)); X X Entry("SetupItems") X X for (item = MenuItems(menu), y = 0; item; X y += item->itemHeight, item = ItemNext(item)) { X if (!ItemWindow(item)) { X static unsigned long valuemask = X (CWOverrideRedirect | CWBorderPixel | CWBackPixel); X XSetWindowAttributes attributes; X X attributes.override_redirect = True; X attributes.border_pixel = MBorder; X attributes.background_pixel = MBackground; X X if((ItemWindow(item) = X XCreateWindow(dpy, X MenuWindow(menu), X 0, y, X MenuItemWidth(menu), X item->itemHeight - (2 * MItemBorder), X MItemBorder, X DefaultDepth(dpy, scr), X InputOutput, X DefaultVisual(dpy, scr), X valuemask, &attributes) X ) == (Window) 0) X Leave(FALSE) X if (item->itemBackground) { X XSetWindowBackgroundPixmap(dpy, ItemWindow(item), X item->itemBackground); X XFreePixmap(dpy, item->itemBackground); X } X ItemMenu(item) = menu; X XSaveContext(dpy, ItemWindow(item), Item_context, X (char *) item); X XDefineCursor(dpy, ItemWindow(item), X MenuCursor(menu)); X } X X else if (changed & menuChanged) { X XResizeWindow(dpy, ItemWindow(item), X MenuItemWidth(menu), X item->itemHeight - (2 * MItemBorder)); X XMoveWindow(dpy, ItemWindow(item), 0, y); X } X } X Leave(TRUE) X} X Xstatic void SetInputMask(menu, mask) XMenu *menu; Xunsigned int mask; X{ X MenuItem *item; X X Entry("SetInputMask") X X XSelectInput(dpy, MenuWindow(menu), X (mask | MenuEventMask)); X for(item = MenuItems(menu) ; item ; item = ItemNext(item)) X { X if (TestItemFlag(item, itemDisabled) || TestItemFlag(item, itemDeaf)) X XSelectInput(dpy, ItemWindow(item), X (mask | MenuIgnoreMask)); X else if (ItemIsLeaf(item)) X XSelectInput(dpy, ItemWindow(item), X (mask | NormalItemEventMask)); X else X XSelectInput(dpy, ItemWindow(item), X (mask | SubmenuItemEventMask)); X } X Leave_void X} X XMenuItem *MenuItemByData(menu, data) XMenu* menu; Xpointer data; X{ X MenuItem *item; X X Entry("MenuItemByData") X X for (item = MenuItems(menu); X !ItemIsNull(item) && (ItemData(item) != data); X item = ItemNext(item)); X X Leave(item) X} X XMenuItem *MenuItemByName (menu, name) XMenu *menu; Xchar *name; X{ X MenuItem *item; X X Entry("MenuItemByName") X X for (item = MenuItems(menu); item; item = ItemNext(item)) X if (strcmp (name, ItemText(item)) == 0) X Leave(item) X Leave(NULLITEM) X} X XMenuItem *MenuGetItem(menu, window) XMenu *menu; XWindow window; X{ X MenuItem *foo = 0; X Window tmpwindow = window; X X Entry("MenuGetItem") X X if (!menu || !window) X Leave(NULLITEM) X if (window == menu->menuWindow) X if (menu->highlightedItem) X tmpwindow = menu->highlightedItem->itemWindow; X XFindContext(dpy, tmpwindow, Item_context, &foo); X Leave(foo) X} X XMenu *MenuGetMenu(menu, window) XMenu *menu; XWindow window; X{ X Menu *bar = 0; X X Entry("MenuGetMenu") X X XFindContext(dpy, window, Menu_context, &bar); X Leave(bar) X} X Xint ItemGetMiddleY(item) XMenuItem *item; X{ X Window child; X XWindowAttributes attributes; X int x, y; X X Entry("ItemGetMiddleY") X X XGetWindowAttributes(dpy, ItemWindow(item), &attributes); X XTranslateCoordinates(dpy, X MenuWindow(ItemMenu(item)), X RootWindow(dpy, scr), X attributes.x, attributes.y, X &x, &y, &child); X Leave((item->itemHeight / 2) + y) X} X Xvoid SetInitialItem(menu, item) XMenu *menu; XMenuItem *item; X{ X extern char *realloc(); X X Entry("SetInitialItem") X X if (MenuHasInitialItem(menu)) { X if (strlen(MenuInitialItemText(menu)) < strlen(ItemText(item))) X MenuInitialItemText(menu) = X realloc(MenuInitialItemText(menu), X strlen(ItemText(item)) + 1); X } X else X MenuInitialItemText(menu) = X allocate(char,(strlen(ItemText(item)) + 1)); X strcpy(MenuInitialItemText(menu), ItemText(item)); X Leave_void X} X Xvoid ClearInitialItem(menu) XMenu *menu; X{ X Entry("ClearInitialItem") X X if (MenuHasInitialItem(menu)) { X free(MenuInitialItemText(menu)); X MenuInitialItemText(menu) = (char *) NULL; X } X Leave_void X} X XMenuItem *GetInitialItem(menu) XMenu *menu; X{ X MenuItem *item; X X Entry("GetInitialItem") X X if (MenuHasInitialItem(menu)) { X for(item = MenuItems(menu) ; item ; item = ItemNext(item)) { X if (ItemIsInitialItem(menu, item)) X Leave(item) X } X } X Leave((MenuItem *) NULL) X} X X X/* Some utility functions */ X Xvoid Retch(s, p1, p2, p3, p4) Xchar *s; Xlong p1, p2, p3, p4; X{ X char buffer[1024]; X X sprintf(buffer, s, p1, p2, p3, p4); X fprintf(stderr, "Error in %s %s\n", curr_rtn(), buffer); X return; X} END_OF_FILE if test 33843 -ne `wc -c <'menus/menu.c'`; then echo shar: \"'menus/menu.c'\" unpacked with wrong size! fi # end of 'menus/menu.c' fi if test -f 'menus/menu.ext.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'menus/menu.ext.h'\" else echo shar: Extracting \"'menus/menu.ext.h'\" \(1789 characters\) sed "s/^X//" >'menus/menu.ext.h' <<'END_OF_FILE' X X/* X#ifndef lint Xstatic char sccs_id[] = "@(#)menu.extern.h 2.1 12/16/87 Siemens Corporate Research and Support, Inc."; X#endif X*/ X X X/* X RTL Menu Package Version 1.0 X by Joe Camaratta and Mike Berman, Siemens RTL, Princeton NJ, 1987 X X menu.extern.h: external function declarations for menu package X*/ X X#include "X11/copyright.h" X/* X * X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca. X * X * Copyright 1987 by Jordan Hubbard. X * X * X * All Rights Reserved X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation, and that the name of Ardent Computer X * Corporation or Jordan Hubbard not be used in advertising or publicity X * pertaining to distribution of the software without specific, written X * prior permission. X * X */ X Xextern MenuItem *AddMenuItem(); Xextern Boolean DisposeItem(); Xextern void DisposeMenu(); Xextern void InitMenu(); Xextern Boolean SetItemText(); Xextern Menu *NewMenu(); Xextern Boolean SetItemCheck(); Xextern Boolean SetItemDisable(); Xextern MenuItem *Display_Menu(); Xextern void Undisplay_Menu(); Xextern void MenuInvert(); Xextern void PlacePointer(); Xextern void Draw_Menu(); Xextern void Draw_Item(); X Xextern MenuItem *MenuGetItem(); Xextern MenuItem *MenuItemByName(); Xextern MenuItem *MenuItemByData(); Xextern Menu *MenuGetMenu(); Xextern int ItemGetMiddleY(); Xextern void SetInitialItem(); Xextern void ClearInitialItem(); Xextern MenuItem *GetInitialItem(); X Xextern MenuItem *TrackMenu(); X X X X X X X X X X END_OF_FILE if test 1789 -ne `wc -c <'menus/menu.ext.h'`; then echo shar: \"'menus/menu.ext.h'\" unpacked with wrong size! fi # end of 'menus/menu.ext.h' fi echo shar: End of archive 3 \(of 12\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 12 archives. rm -f ark[1-9]isdone ark[1-9][0-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 Moderator of comp.sources.x