jkh@ardent.UUCP (Jordan K. Hubbard) (06/16/88)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 14 (of 17)." # Contents: awm/menus/track_menu.c # Wrapped by jkh@ardent on Thu Jun 16 00:44:24 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'awm/menus/track_menu.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'awm/menus/track_menu.c'\" else echo shar: Extracting \"'awm/menus/track_menu.c'\" \(26723 characters\) sed "s/^X//" >'awm/menus/track_menu.c' <<'END_OF_FILE' X#ident "%W% %G%" X X#ifndef lint X static char sccs_id[] = "@(#)track_menu.c 2.1 12/16/87 Siemens Corporate Research and Support, Inc."; X#endif X X X#include "X11/copyright.h" X X/* X RTL Menu Package Version 1.0 X by Joe Camaratta and Mike Berman, Siemens RTL, Princeton NJ, 1987 X X track_menu.c: bring up menus and track the mouse 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 * The menu package will break if you don't define this, but X * it's there in case you want to see just how and where the X * "eventstack" stuff is used and, if necessary, replace it. X */ X#define SAVE_EVENTS X X X#include <stdio.h> X#include "X11/Xlib.h" X#include "X11/cursorfont.h" X#include "arrow_icon.h" X#include "null_icon.h" X#include "menu.h" X#include "menu.def.h" X#include "menu.ext.h" X#include "dbug.h" X#ifdef SAVE_EVENTS X#include "eventstack.h" X#endif X X#define MIN(x,y) (((x) <= (y))? x:y) X#define MAX(x,y) (((x) >= (y))? x:y) X X#define CLICK_TIME 290 /* in milliseconds */ X X#define CursorLockMask (ButtonReleaseMask | ExposureMask) X X/* Event macros */ X X#define EventGetXCoord(rep) ((rep).xmotion.x) X#define EventGetYCoord(rep) ((rep).xmotion.y) X#define EventType(rep) ((rep).type) X#define EventXWindow(rep) ((rep).xcrossing.window) X#define EventXTime(rep) ((rep).xcrossing.time) X#define EventXMode(rep) ((rep).xcrossing.mode) X#define EventXRootX(rep) ((rep).xcrossing.x_root) X#define EventXRootY(rep) ((rep).xcrossing.y_root) X#define EventXDetail(rep) ((rep).xcrossing.detail) X#define EventMWindow(rep) ((rep).xmotion.window) X#define EventMTime(rep) ((rep).xmotion.time) X#define EventButton(rep) ((rep).xbutton.button) X#define EventBWindow(rep) ((rep).xbutton.window) X#define EventBTime(rep) ((rep).xbutton.time) X#define EventEX(rep) ((rep).xexpose.x) X#define EventEY(rep) ((rep).xexpose.y) X#define EventEWidth(rep) ((rep).xexpose.width) X#define EventEHeight(rep) ((rep).xexpose.height) X#define PointerEvent(rep) \ X ((EventType(rep) == ButtonPress) || \ X (EventType(rep) == ButtonRelease) || \ X (EventType(rep) == MotionNotify) || \ X (EventType(rep) == EnterNotify) || \ X (EventType(rep) == LeaveNotify) || \ X (EventType(rep) == FocusIn) || \ X (EventType(rep) == FocusOut)) X#define KeyEvent(rep) \ X ((EventType(rep) == KeyPress) || (EventType(rep) == KeyRelease)) X/* Possible states for the state machine */ typedef enum X{ X Initial, /* Inside a submenu, but not any item */ X CheckTrigger, /* Inside an item that has submenu, checking for pullright */ X Leaf, /* Inside an item with no submenu */ X Exit, /* Preparing to exit */ X LevelControl /* Not in any submenu, waiting to enter something */ X } State; X State InitialState(), CheckTriggerState(), LeafState(), LevelControlState(), X GetItemState(); bool EventNotSignificant(), PushSubmenu(); X void OutputEvent(), GetNextSignificantEvent(), PopSubmenu(), X Highlight(), Unhighlight(), DisplayInitialMenus(), LockCursor(), X TossExtraMoves(), UnlockCursor(); X void ProcessExposeEvents(); X void SaveTest(); X MenuItem *MenuGetItem(); Menu *MenuGetMenu(); X X/* global state variables */ X static MenuItem *current_item; static Menu *current_menu; static Window root_window; extern Display *dpy; extern int scr; static int level; /* submenu level */ static Time button_time; /* time button press invoked */ static Cursor wait_cursor = None; /* empty cursor for lock state */ static bool click_allowed; static bool lock_event_mask, unlock_event_mask; X extern int Autoselect; extern int MDelta; X X#ifdef SAVE_EVENTS static struct Ev_q *ev_save = 0; X#endif X X MenuItem *TrackMenu(root_menu, root_x, root_y, X init_button, root, buttime) Menu *root_menu; /* Pointer to root menu requested to pop up */ int root_x, root_y; /* Position to start menu */ int init_button; /* The # of button used to pop up menu */ Window root; /* Window label for parent of menu */ Time buttime; /* timestamp for button (or 0, if CLICK == 0) */ X{ X State CurrentState = LevelControl; X XEvent Event_Reply; X int open_x; X bool selected = FALSE; X MenuItem *selected_item; X X Entry("TrackMenu") X X /* Initialize globals */ X X button_time = buttime; X root_window = root; X level = 0; X current_menu = root_menu; X click_allowed = (TestOptionFlag(current_menu, clickokay))? TRUE : FALSE; X unlock_event_mask = (TestOptionFlag(current_menu, savebits))? X MenuEventMask : (MenuEventMask | ExposureMask); X lock_event_mask = (TestOptionFlag(current_menu, savebits))? X CursorLockMask : (CursorLockMask | ExposureMask); X X /* If not already done, set up the null cursor for lock state */ X if (wait_cursor == None) X { X Pixmap wc_pixmap; X XColor fg, bg; X X wc_pixmap = XCreateBitmapFromData (dpy, root_window, X null_icon_bits, X null_icon_width, null_icon_height); X wait_cursor = XCreatePixmapCursor (dpy, wc_pixmap, wc_pixmap, X &fg, &bg, 1, 1); X } X X X /* Block all other action by grabbing the server */ X /* XGrabServer (dpy); */ X /* Don't think we need to grab the server... so for now, we won't */ X X#ifdef SAVE_EVENTS X /* Get the present state, so it can be restored later */ X /* Any events on the queue when we start get saved now, restored later */ X SaveEvents (dpy, &ev_save, ~(unsigned long) ButtonReleaseMask); X#endif X X LockCursor(root_window); X if (!(current_item = X Display_Menu(current_menu, NULLMENU, root_x, root_y))) X { X CurrentState = Exit; X } X /* X * First item is a label and autoselect is on, so we want X * to push on to the first "real" item. X */ X if (ItemIsDeaf(current_item) && Autoselect) X current_item = current_item->nextItem; X LockCursor(ItemWindow(current_item)); X open_x = root_x; X X /* Push to appropriate previous item, if any */ X while (MenuHasInitialItem(current_menu) && (CurrentState != Exit)) X { X current_item = GetInitialItem(current_menu); X ClearInitialItem(current_menu); X X /* if the initial item can't be selected, take first in list */ X if (ItemIsNull(current_item) || ItemIsDisabled(current_item)) X { X current_item = MenuItems(current_menu); X break; X } X else if (ItemIsLeaf(current_item)) /* then we're done */ X break; X else X { X open_x += ItemGetArrowPosition(current_item); X if (!ItemIsDeaf(current_item)) X Highlight(current_item); X TossExtraMoves(ItemWindow(current_item)); X (void)PushSubmenu(open_x); X } X } X ProcessExposeEvents(); X if (CurrentState != Exit) X CurrentState = (ItemIsLeaf(current_item)) ? Leaf : CheckTrigger; X if (!ItemIsDeaf(current_item)) X Highlight(current_item); X XSync (dpy, 0); /* get release click, if it's in queue */ X#ifdef SAVE_EVENTS X DisposeEvents(dpy, (PointerMotionMask | EnterWindowMask | X LeaveWindowMask | ExposureMask)); X#endif X LockCursor(ItemWindow(current_item)); X PlacePointer(current_menu,current_item); X UnlockCursor(); X X /* State Machine */ X X while (CurrentState != Exit) X { X GetNextSignificantEvent(&Event_Reply, init_button); X switch (CurrentState) X { X case LevelControl: X CurrentState = LevelControlState(Event_Reply); X break; X case Initial: X CurrentState = InitialState(Event_Reply); X break; X case CheckTrigger: X CurrentState = CheckTriggerState(Event_Reply); X break; X case Leaf: X CurrentState = LeafState(Event_Reply, &selected); X break; X default: X Retch("(RTLmenu) YOW! Unknown State! (%d)\n", X CurrentState); X CurrentState = Exit; X break; X } X } X /* Clean up and exit */ X X selected_item = (selected)? current_item : NULLITEM; X while (level) X { X if (selected) X SetInitialItem(current_menu, current_item); X PopSubmenu(); X } X if (selected) X { X SetInitialItem(current_menu, current_item); X } X X Undisplay_Menu(current_menu); X UnlockCursor(); X XUngrabPointer(dpy, CurrentTime); X X /* Throw out any left over events from menu world */ X /* if (TestOptionFlag(current_menu, savebits)) { X XSync(dpy,1); X XUngrabServer(dpy, CurrentTime); add this if grab added! X } X else X XSync(dpy,0);*/ X X /* Push back any events that were lying around when menus started */ X X XFlush(dpy); X#ifdef SAVE_EVENTS X DisposeEvents(dpy, (PointerMotionMask | EnterWindowMask | X LeaveWindowMask | ExposureMask)); X RestoreEvents(dpy, &ev_save); X#endif X Leave(selected_item) X} X X/* Used for debugging */ X void OutputEvent(Event_Reply) XXEvent Event_Reply; X{ X Entry("OutputEvent") X X switch (EventType(Event_Reply)) X { X case ButtonPress: X case ButtonRelease: X DBUG_5("RTLmenu","Button Press/Release, button %d on window %d at time %d\n", X EventButton(Event_Reply), EventBWindow(Event_Reply), X EventBTime(Event_Reply)); X break; X case MotionNotify: X DBUG_5("RTLmenu","Motion Notify on window %d at time %d, x=%d\n", X EventMWindow(Event_Reply), EventMTime(Event_Reply), X EventGetXCoord(Event_Reply)); X break; X case EnterNotify: X DBUG_4("RTLmenu","Enter Notify on window %d at time %d\n", X EventXWindow(Event_Reply), EventXTime(Event_Reply)); X break; X case LeaveNotify: X DBUG_4("RTLmenu","Leave Notify on window %d at time %d\n", X EventXWindow(Event_Reply), EventXTime(Event_Reply)); X break; X default: X DBUG_3("RTLmenu","Unexpected event type %d\n", EventType(Event_Reply)); X break; X } X Leave_void X} X static bool locked = FALSE; X X/* Lock the cursor: make it disappear, and ignore events it generates. */ X/* Optionally, confine it to a single window. */ X/* (Using "None" for confine_window doesn't confine it. ) */ void LockCursor(confine_window) Window confine_window; X{ X int result; X X Entry("LockCursor") X X locked = TRUE; X result = XGrabPointer(dpy, X RootWindow(dpy, MenuScreen(current_menu)), X True, lock_event_mask, GrabModeSync, X GrabModeAsync, confine_window, X wait_cursor, CurrentTime); X DBUG_3("RTLmenu","Lock Cursor grab = %d\n",result); X Leave_void X} X X/* Unlock (and unconfine) the cursor. If cursor lock is not set, */ X/* this does nothing. */ X void UnlockCursor() X{ X int result; X X Entry("UnlockCursor") X X if (locked) X { X locked = FALSE; X result = XGrabPointer(dpy, X RootWindow(dpy, MenuScreen(current_menu)), X True, unlock_event_mask, X GrabModeAsync, GrabModeAsync, None, X MenuCursor(current_menu), CurrentTime); X DBUG_3("RTLmenu","Unlock Cursor grab = %d\n",result); X } X Leave_void X} X X/* Keep getting the X events, until finding one that may be interesting */ X/* to the operation of the state machine. */ X void GetNextSignificantEvent(Event_Reply,init_button) XXEvent *Event_Reply; int init_button; /* the button that initiated the menu */ X{ X XEvent Next_Event_Reply; X bool InsignificantEvent = True; X X Entry("GetNextSignificantEvent") X X /* Loop as long as any of a number of "insignificant" events */ X /* are found; when the event no longer matches one of the tests, */ X /* it is assumed to be "significant" and returned.*/ X do X { X XNextEvent(dpy, Event_Reply); X DBUG_EXECUTE("RTLmenu", OutputEvent(*Event_Reply)); X X /* If this event is an "enter", check whether there is a */ X /* "leave" for the same window already in the queue, */ X /* immediately following it; if so, throw them both out */ X /* and get the next event */ X /* NOTE: might try to look further ahead, but this is */ X /* tricky because other events might intervene. */ X X if ((EventType(*Event_Reply) == EnterNotify) && X (EventXMode(*Event_Reply) == NotifyNormal) && X (QLength(dpy) > 0) && X (MenuGetMenu(current_menu, EventXWindow(*Event_Reply)) X != current_menu)) X { X XPeekEvent(dpy, &Next_Event_Reply); X if ((EventType(Next_Event_Reply) == LeaveNotify) && X (EventXMode(Next_Event_Reply) == NotifyNormal) && X (EventXWindow(Next_Event_Reply) == EventXWindow(*Event_Reply))) X { X DBUG_2("RTLmenu","TOSS: Enter/leave pair.\n"); X XNextEvent(dpy, Event_Reply); X XNextEvent(dpy, Event_Reply); X } X } X#ifdef SAVE_EVENTS X if (EventNotSignificant(*Event_Reply, init_button)) X { X if (!(PointerEvent(*Event_Reply) || KeyEvent(*Event_Reply) X || EventType(*Event_Reply) == Expose)) X { X /* might be significant elsewhere -- save it for later */ X AddEventToStore(&ev_save, *Event_Reply); X } X } X else X#else X if (!EventNotSignificant(*Event_Reply, init_button)) X#endif X InsignificantEvent = FALSE; X } X while (InsignificantEvent); X X DBUG_2("RTLmenu","--->"); X Leave_void X} X X/* Check whether the event matches one of the events considered */ X/* "not significant".*/ bool EventNotSignificant(Event_Reply, init_button) XXEvent Event_Reply; int init_button; X{ X Entry("EventNotSignificant") X X /* Insignificant if not in following list */ X Leave(!((EventType(Event_Reply) == ButtonRelease) || X (EventType(Event_Reply) == ButtonPress) || X (EventType(Event_Reply) == MotionNotify) || X (EventType(Event_Reply) == EnterNotify) || X (EventType(Event_Reply) == Expose) || X (EventType(Event_Reply) == LeaveNotify)) X || X /* Insignificant if leave or enter is not "Normal" */ X (((EventType(Event_Reply) == LeaveNotify) || X (EventType(Event_Reply) == EnterNotify)) && X (EventXMode(Event_Reply) != NotifyNormal)) X || X /* Insignificant if hit button other than initial one */ X ((EventType(Event_Reply) == ButtonRelease) && X (EventButton(Event_Reply) != init_button)) X || X /* Insignificant if tail end of a click -- and clicks allowed */ X (click_allowed && X (EventType(Event_Reply) == ButtonRelease) && X (EventBTime(Event_Reply) - button_time < CLICK_TIME)) X ) X} X State LevelControlState(rep) XXEvent rep; X{ X State next_state; X Menu *entered_menu; X MenuItem *entered_item; X X Entry("LevelControlState") X switch (EventType(rep)) X { X case MotionNotify: X case LeaveNotify: X next_state = LevelControl; /* loop back to this state */ X break; X case EnterNotify: X /* Decide whether we've entered a menu window or item window */ X entered_menu = MenuGetMenu(current_menu, EventXWindow(rep)); X entered_item = MenuGetItem(current_menu,EventXWindow(rep)); X X if ((MenuIsNull(entered_menu)) && (ItemIsNull(entered_item))) X /* Must be some other window; carry on */ X next_state = LevelControl; X else if (!ItemIsNull(entered_item) && X MenuIsDisplayed(ItemMenu(entered_item))) X { X /* we entered an item, but not a window. This should only happen */ X /* when we stayed in the parent of the current submenu. So, */ X /* Pop that submenu and get to the item. */ X if (level) X { X LockCursor(ItemWindow(entered_item)); X PopSubmenu(); X ProcessExposeEvents(); X UnlockCursor(); X current_item = entered_item; X Highlight(current_item); X next_state = GetItemState(rep); X } X else /* I must be very confused... */ X { X Retch("(RTLmenu) Tried to pop the root menu...\n"); X next_state = Exit; X } X } X X else if (!MenuIsNull(entered_menu)&& X MenuIsDisplayed(entered_menu)) X { X /* entered a menu that is displayed */ X while ((current_menu != entered_menu) && level) X /* drop down the menu that was entered */ X PopSubmenu(); X ProcessExposeEvents(); X UnlockCursor(); X if (current_menu == entered_menu) X next_state = Initial; X else X { X next_state = Exit; X Retch("(RTLmenu) Couldn't find the menu I entered!!\n"); X } X } X else X next_state = LevelControl; X break; X case ButtonRelease: X next_state = Exit; X break; X default: X Retch("RTLmenu","YOW! Unexpected event! (%d)\n", rep.type); X next_state = Exit; X break; X } X Leave(next_state) X} X X/* Figure out the status of the item we've just entered */ State GetItemState(rep) XXEvent rep; X{ X int open_x; X State next_state; X X Entry("GetItemState") X if (ItemIsNull(current_item)) X { X Retch("(RTLmenu) null current item!"); X next_state = Exit; X } X else if (MenuIsNull(current_menu)) X { X Retch("(RTLmenu) null current menu!"); X next_state = Exit; X } X else if (ItemIsLeaf(current_item)) X { X if (MenuHasInitialItem(current_menu)) X ClearInitialItem(current_menu); X next_state = Leaf; X } X else if (EventGetXCoord(rep) >= (int)(ItemGetArrowPosition(current_item) - 4)) X { X /* entered item in "auto pop-up zone", i.e., over pull-right arrow. */ X LockCursor(ItemWindow(current_item)); X TossExtraMoves(ItemWindow(current_item)); X if (PushSubmenu(EventXRootX(rep))) X { X LockCursor(ItemWindow(current_item)); X PlacePointer(current_menu, current_item); X next_state = Initial; X ProcessExposeEvents(); X } X else X next_state = CheckTrigger; X UnlockCursor(); X } X else if (MenuHasInitialItem(current_menu)) X { X /* Entered menu has initial item -- move to it */ X DBUG_2("RTLmenu","Pushing for initial item."); X current_item = GetInitialItem(current_menu); X open_x = ItemGetArrowPosition(current_item) + X EventXRootX(rep); X ClearInitialItem(current_menu); X LockCursor(ItemWindow(current_item)); X if (PushSubmenu(open_x)) X { X ProcessExposeEvents(); X LockCursor(ItemWindow(current_item)); X PlacePointer(current_menu, current_item); X next_state = Initial; X } X UnlockCursor(); X } X else /* parent pull */ X next_state = CheckTrigger; X Leave(next_state) X} X State InitialState( rep) XXEvent rep; X{ X State next_state; X X Entry("Initial") X switch (EventType(rep)) X { X case EnterNotify: X if (MenuIsNull(current_menu)) X { X Retch("(RTLmenu) null current menu!?!?"); X next_state = Exit; X } X else if (EventXDetail(rep) == NotifyInferior) X next_state = Initial; X else X { X current_item = MenuGetItem(current_menu, EventXWindow(rep)); X if (ItemIsNull(current_item)) X { X /* Retch("(RTLmenu) Window entered not an item!\n"); */ X next_state = Exit; X } X else X { X Highlight(current_item); X next_state = GetItemState(rep); X } X } X break; X case LeaveNotify: X /* Decide whether we're actually leaving */ X /* this menu for another submenu or the root, */ X /* or going into an item. */ X next_state = (EventXDetail(rep) == NotifyInferior)? X Initial : LevelControl; X break; X case ButtonRelease: X next_state = Exit; X break; X case MotionNotify: X next_state = Initial; X break; X default: X Retch("(RTLmenu) YOW! Unexpected event! (%d)\n", rep.type); X next_state = Exit; X break; X } X Leave(next_state) X} X X#define NotSet -1 X/* Look to see if pull-right is requested */ State CheckTriggerState(rep) XXEvent rep; X{ X State next_state = CheckTrigger; X static int Trigger = NotSet; X static int OldX, NewX, childX, button; X X Entry("CheckTrigger") X if (MenuIsNull(current_menu) || ItemIsNull(current_item)) X { X Retch("(RTLmenu) Null menu or item..."); X next_state = Exit; X goto exit; X } X if (Trigger == NotSet) /* set it */ X { X Trigger = MIN(EventGetXCoord(rep) + MenuDelta(current_menu), X ItemGetArrowPosition(current_item)); X NewX = NotSet; X } X switch (EventType(rep)) X { X case LeaveNotify: X next_state = Initial; X Unhighlight(MenuGetItem(current_menu, EventXWindow(rep))); X Trigger = NotSet; X break; X case ButtonRelease: X next_state = Exit; X Trigger = NotSet; X break; X X case ButtonPress: X button = rep.xbutton.button; X while (TRUE) { X XNextEvent(dpy, &rep); X if (rep.type == ButtonRelease && X rep.xbutton.button == button) X break; X } X next_state = CheckTrigger; X childX = TestOptionFlag(current_menu, fixedchild) ? X (MenuX(current_menu) + ItemGetArrowPosition(current_item)) : X EventXRootX(rep); X Trigger = NotSet; X if (PushSubmenu(childX)) X { X next_state = LevelControl; X ProcessExposeEvents(); X LockCursor(ItemWindow(current_item)); X PlacePointer(current_menu, current_item); X } X UnlockCursor(); X break; X X case MotionNotify: X next_state = CheckTrigger; X OldX = NewX; X NewX = EventGetXCoord(rep); X if (NewX >= Trigger) X { X LockCursor(ItemWindow(current_item)); X childX = TestOptionFlag(current_menu, fixedchild)? X (MenuX(current_menu) + ItemGetArrowPosition(current_item)): X EventXRootX(rep); X Trigger = NotSet; X if (PushSubmenu(childX)) X { X next_state = LevelControl; X ProcessExposeEvents(); X LockCursor(ItemWindow(current_item)); X PlacePointer(current_menu, current_item); X } X UnlockCursor(); X } X else if (NewX < OldX) /* reverse motion */ X Trigger = MIN(Trigger, NewX + MenuDelta(current_menu)); X break; X X default: X Retch("(RTLmenu) YOW! Unexpected event!\n"); X next_state = Exit; X break; X } X exit: X Leave(next_state) X} X State LeafState(rep,selected) XXEvent rep; bool *selected; X{ X State next_state; X X Entry("LeafState") X switch(EventType(rep)) X { X case LeaveNotify: X Unhighlight(MenuGetItem(current_menu, EventXWindow(rep))); X next_state = Initial; X break; X X case ButtonRelease: X *selected = TRUE; X next_state = Exit; X break; X X case ButtonPress: X case EnterNotify: X case MotionNotify: /* if events set right, this never happens */ X next_state = Leaf; X break; X X default: X Retch("(RTLMenu) YOW! Unexpected event! (%d)\n", X rep.type); X next_state = Exit; X break; X } X Leave(next_state) X} X bool PushSubmenu(x) int x; X{ X int y; X bool pushed; X MenuItem *new_current_item; X X Entry("PushSubmenu") X X if (ItemIsNull(current_item)) X { X Retch("(RTLMenu) Can't push from null item.\n"); X pushed = FALSE; X } X else if (MenuIsNull(ItemSubmenu(current_item))) X { X Retch("(RTLmenu) Null submenu.\n"); X pushed = FALSE; X } X else if (ItemIsNull(MenuItems(ItemSubmenu(current_item)))) X /* submenu has no items -- don't push, but not an error */ X pushed = FALSE; X else X { X y = ItemGetMiddleY(current_item); X ++level; X X if (new_current_item = X Display_Menu(ItemSubmenu(current_item), current_menu, x, y)) X { X XFlush(dpy); X current_menu = ItemSubmenu(current_item); X current_item = new_current_item; X if (ItemIsDeaf(current_item) && Autoselect) X current_item = current_item->nextItem; X pushed = TRUE; X } X else X { X Retch("(RTLmenu) Display_Menu failed!\n"); X pushed = FALSE; X } X } X Leave(pushed) X} X void PopSubmenu() X{ X Menu *parent; X MenuItem *item; X X Entry("PopSubmenu") X --level; X parent = current_menu->parentMenu; X Undisplay_Menu(current_menu); X current_menu = parent; X if (!MenuIsNull(current_menu)) X { X item = MenuItemHighlighted(current_menu); X if (!ItemIsNull(item)) X { X current_item = item; X } X } X X Leave_void X} X void Highlight(item) MenuItem *item; X{ X MenuItem *old_highlight; X X Entry("Highlight") X X old_highlight = MenuItemHighlighted(current_menu); X if ((item != old_highlight) && /* else, already highlighted */ X (!ItemIsNull(item))) X { X if (!ItemIsNull(old_highlight) && !ItemIsDeaf(item)) X Unhighlight(old_highlight); X MenuInvert(ItemMenu(item), item); X SetHighlightItem(ItemMenu(item), item); X } X Leave_void X} X void Unhighlight(item) MenuItem *item; X{ X Entry("Unhighlight") X if (!ItemIsNull(item)) X { X if (MenuItemHighlighted(current_menu) == item) X { X MenuInvert(ItemMenu(item), item); X ResetHighlightItem(ItemMenu(item)); X } X } X Leave_void X} X void TossExtraMoves(window) Window window; X{ X XEvent ev; X X Entry("TossExtraMoves") X /* XSync(dpy,0); /* make sure they're all on the queue */ X while (XCheckTypedWindowEvent(dpy, window, MotionNotify, &ev)) X DBUG_2("RTLmenu","Tossing extra motion.\n"); X Leave_void X} X X void ProcessExposeEvents() X{ X MenuItem *item; X XEvent ev; X X Entry("ProcessExposeEvents") X X XSync(dpy,0); X while (XCheckTypedEvent(dpy, Expose, &ev)) X { X item = MenuGetItem(current_menu, EventXWindow(ev)); X if (!ItemIsNull(item)) X Draw_Item(ItemMenu(item), item, EventEX(ev), EventEY(ev), X EventEWidth(ev), EventEHeight(ev)); X } X Leave_void X} END_OF_FILE if test 26723 -ne `wc -c <'awm/menus/track_menu.c'`; then echo shar: \"'awm/menus/track_menu.c'\" unpacked with wrong size! fi # end of 'awm/menus/track_menu.c' fi echo shar: End of archive 14 \(of 17\). cp /dev/null ark14isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 17 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