home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************/
- /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
- /** Salt Lake City, Utah **/
- /** **/
- /** All Rights Reserved **/
- /** **/
- /** Permission to use, copy, modify, and distribute this software and **/
- /** its documentation for any purpose and without fee is hereby **/
- /** granted, provided that the above copyright notice appear in all **/
- /** copies and that both that copyright notice and this permis- **/
- /** sion notice appear in supporting documentation, and that the **/
- /** name of Evans & Sutherland not be used in advertising or publi- **/
- /** city pertaining to distribution of the software without specif- **/
- /** ic, written prior permission. **/
- /** **/
- /** EVANS & SUTHERLAND DISCLAIMS ALL WARRANTIES WITH REGARD TO **/
- /** THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILI- **/
- /** TY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND BE LIABLE **/
- /** FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAM- **/
- /** AGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, **/
- /** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS **/
- /** ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER- **/
- /** FORMANCE OF THIS SOFTWARE. **/
- /*****************************************************************************/
-
- /***********************************************************************
- *
- * $Header: menus.c,v 1.20 88/04/15 07:09:54 tlastran Exp $
- *
- * twm menu code
- *
- * 17-Nov-87 Thomas E. LaStrange File created
- *
- ***********************************************************************/
-
- #ifndef lint
- static char RCSinfo[] =
- "$Header: menus.c,v 1.20 88/04/15 07:09:54 tlastran Exp $";
- #endif
-
- #include <stdio.h>
- #include <signal.h>
- #include "twm.h"
- #include "gc.h"
- #include "menus.h"
- #include "events.h"
- #include "util.h"
- #include "gram.h"
-
- #include "pull.bm"
-
- MenuRoot *Menu[MAX_BUTTONS + 1]; /* one root per button */
- MenuItem *Item[MAX_BUTTONS + 1]; /* one action per button */
- MenuRoot *MenuList = NULL; /* head of the menu list */
- MenuRoot *LastMenu = NULL; /* the last menu */
- MenuRoot *ActiveMenu = NULL; /* the active menu */
- MenuItem *ActiveItem = NULL; /* the active menu item */
-
- /***********************************************************************
- *
- * Procedure:
- * InitMenus - initialize menu roots
- *
- ***********************************************************************
- */
-
- void
- InitMenus()
- {
- int i;
-
- for (i = 0; i < (MAX_BUTTONS + 1); i++)
- {
- Menu[i] = NULL;
- Item[i] = NULL;
- }
- }
-
- /***********************************************************************
- *
- * Procedure:
- * NewMenuRoot - create a new menu root
- *
- * Returned Value:
- * (MenuRoot *)
- *
- * Inputs:
- * name - the name of the menu root
- *
- ***********************************************************************
- */
-
- MenuRoot *
- NewMenuRoot(name)
- char *name;
- {
- MenuRoot *tmp;
-
- CreateGCs();
-
- tmp = (MenuRoot *) malloc(sizeof(MenuRoot));
- tmp->name = name;
- tmp->prev = NULL;
- tmp->first = NULL;
- tmp->last = NULL;
- tmp->items = 0;
- tmp->width = 0;
- tmp->mapped = FALSE;
- tmp->pull = FALSE;
- tmp->active = TRUE;
- tmp->shadow = XCreateSimpleWindow(dpy, Root,
- 0, 0, 10, 10, 1, Foreground, Foreground);
- tmp->w = XCreateSimpleWindow(dpy, Root,
- 0, 0, 10, 10, 1, Foreground, Background);
- XSelectInput(dpy, tmp->w, LeaveWindowMask);
-
- if (MenuList == NULL)
- {
- MenuList = tmp;
- MenuList->next = NULL;
- }
-
- if (LastMenu == NULL)
- {
- LastMenu = tmp;
- LastMenu->next = NULL;
- }
- else
- {
- LastMenu->next = tmp;
- LastMenu = tmp;
- LastMenu->next = NULL;
- }
-
- return (tmp);
- }
-
- /***********************************************************************
- *
- * Procedure:
- * AddToMenu - add an item to a root menu
- *
- * Returned Value:
- * (MenuItem *)
- *
- * Inputs:
- * menu - pointer to the root menu to add the item
- * item - the text to appear in the menu
- * action - the string to possibly execute
- * sub - the menu root if it is a pull-right entry
- * func - the numeric function
- *
- ***********************************************************************
- */
-
- MenuItem *
- AddToMenu(menu, item, action, sub, func)
- MenuRoot *menu;
- char *item, *action;
- MenuRoot *sub;
- int func;
- {
- unsigned long valuemask;
- XSetWindowAttributes attributes;
- MenuItem *tmp;
- int width;
-
- #ifdef DEBUG
- fprintf(stderr, "adding menu item=\"%s\", action=%s, sub=%d, f=%d\n",
- item, action, sub, func);
- #endif
-
- tmp = (MenuItem *) malloc(sizeof(MenuItem));
- tmp->root = menu;
-
- if (menu->first == NULL)
- {
- menu->first = tmp;
- tmp->prev = NULL;
- }
- else
- {
- menu->last->next = tmp;
- tmp->prev = menu->last;
- }
- menu->last = tmp;
-
- tmp->item = item;
- tmp->action = action;
- tmp->next = NULL;
- tmp->sub = NULL;
- tmp->pull = NULL;
- tmp->state = 0;
- tmp->func = func;
-
- width = XTextWidth(MenuFont, item, strlen(item));
- if (width > menu->width)
- menu->width = width;
-
- if (tmp->func != F_TITLE)
- {
- tmp->w = XCreateSimpleWindow(dpy, menu->w,
- 0, menu->items * (MenuFontHeight + 4),
- width, MenuFontHeight + 4,
- 0,
- Foreground, Background);
- XSelectInput(dpy, tmp->w, EnterWindowMask
- | LeaveWindowMask | ExposureMask);
- }
- else
- {
- tmp->w = XCreateSimpleWindow(dpy, menu->w,
- -1, menu->items * (MenuFontHeight + 4),
- width, MenuFontHeight + 2,
- 1,
- Foreground, Background);
- XSelectInput(dpy, tmp->w, ExposureMask);
- }
-
- if (sub != NULL)
- {
- Pixmap pm;
-
- tmp->sub = sub;
- pm = MakePixmap(tmp->w, MenuNormalGC,
- pull_bits, pull_width, pull_height);
-
- valuemask = CWEventMask | CWBackPixmap;
- attributes.background_pixmap = pm;
- attributes.event_mask = EnterWindowMask | LeaveWindowMask;
-
- tmp->pull = XCreateWindow(dpy, tmp->w,
- 0, 0,
- pull_width, pull_height,
- 0, DefaultDepth(dpy, 0), CopyFromParent, DefaultVisual(dpy, 0),
- valuemask, &attributes);
-
- XMapWindow(dpy, tmp->pull);
-
- menu->pull = TRUE;
- XSaveContext(dpy, tmp->pull, MenuContext, tmp);
- }
- menu->items += 1;
-
- XSaveContext(dpy, tmp->w, MenuContext, tmp);
-
- if (menu->items == 1)
- XSaveContext(dpy, tmp->root->w, MenuContext, tmp);
-
- return (tmp);
- }
-
- /***********************************************************************
- *
- * Procedure:
- * PopUpMenu - pop up a pull down menu
- *
- * Inputs:
- * menu - the root pointer of the menu to pop up
- * x - the x location of the mouse
- * y - the y location of the mouse
- *
- ***********************************************************************
- */
-
- void
- PopUpMenu(menu, x, y)
- MenuRoot *menu;
- int x, y;
- {
- int d_width, d_height, m_height;
- XWindowChanges xwc, pwc;
- unsigned int xwcm, pwcm;
- MenuItem *tmp;
-
- if (ActiveMenu != NULL)
- ActiveMenu->active = FALSE;
-
- menu->active = TRUE;
- ActiveMenu = menu;
- if (menu->mapped != TRUE)
- {
- if (menu->pull == TRUE)
- {
- menu->width += pull_width + 10;
- }
-
- xwcm = 0;
- xwcm |= CWWidth;
- xwc.width = menu->width + 10;
-
- pwcm = 0;
- pwcm |= CWX;
- pwc.x = xwc.width - pull_width;
-
- for (tmp = menu->first; tmp != NULL; tmp = tmp->next)
- {
- XConfigureWindow(dpy, tmp->w, xwcm, &xwc);
- if (tmp->pull != NULL)
- {
- XConfigureWindow(dpy, tmp->pull, pwcm, &pwc);
- }
- if (tmp->func != F_TITLE)
- tmp->y = 5;
- else
- {
- tmp->y = xwc.width - XTextWidth(MenuFont, tmp->item,
- strlen(tmp->item));
- tmp->y /= 2;
- }
- }
- }
- menu->mapped = TRUE;
-
- d_width = DisplayWidth(dpy, DefaultScreen(dpy));
- d_height = DisplayHeight(dpy, DefaultScreen(dpy));
- m_height = menu->items * (MenuFontHeight + 4);
-
- if ((x + menu->width + 10) > d_width)
- x = (d_width - menu->width - 20);
-
- if ((y + m_height + 10) > d_height)
- y = (d_height - m_height - 20);
-
- xwcm = 0;
- xwcm |= CWX;
- xwc.x = x - 1;
- xwcm |= CWY;
- xwc.y = y - ((MenuFontHeight + 4) / 2);
- xwcm |= CWWidth;
- xwc.width = menu->width + 10;
- xwcm |= CWHeight;
- xwc.height = m_height;
-
- XConfigureWindow(dpy, menu->w, xwcm, &xwc);
-
- xwc.x = xwc.x + 5;
- xwc.y = xwc.y + 5;
- /* xwc.width -= 20; xwc.height -= 20; */
-
- XConfigureWindow(dpy, menu->shadow, xwcm, &xwc);
- XWarpPointer(dpy, None, menu->w, 0, 0, 0, 0, 1, (MenuFontHeight + 4) / 2);
- XMapSubwindows(dpy, menu->w);
- XRaiseWindow(dpy, menu->shadow);
- XMapRaised(dpy, menu->w);
- XMapWindow(dpy, menu->shadow);
- }
-
- /***********************************************************************
- *
- * Procedure:
- * FindMenuRoot - look for a menu root
- *
- * Returned Value:
- * (MenuRoot *) - a pointer to the menu root structure
- *
- * Inputs:
- * name - the name of the menu root
- *
- ***********************************************************************
- */
-
- MenuRoot *
- FindMenuRoot(name)
- char *name;
- {
- MenuRoot *tmp;
-
- for (tmp = MenuList; tmp != NULL; tmp = tmp->next)
- {
- if (strcmp(name, tmp->name) == 0)
- return (tmp);
- }
- return NULL;
- }
-
- /***********************************************************************
- *
- * Procedure:
- * ExecuteFunction - execute a twm root function
- *
- * Inputs:
- * menu - the menu item to execute
- *
- ***********************************************************************
- */
-
- void
- ExecuteFunction(menu)
- MenuItem *menu;
- {
- Window w;
- unsigned long black;
- char tmp[200];
- char *ptr;
- int len;
- char buff[MAX_FILE_SIZE];
- int count, fd;
- MenuRoot *root, *tmp_root;
- MenuItem *item, *tmp_item;
-
- XGrabPointer(dpy, Root, True,
- ButtonReleaseMask | ButtonMotionMask,
- GrabModeAsync, GrabModeSync,
- Root, ClockCursor, CurrentTime);
-
- switch (menu->func)
- {
- case F_NOP:
- case F_TITLE:
- break;
-
- case F_CIRCLEUP:
- XCirculateSubwindowsUp(dpy, Root);
- break;
-
- case F_CIRCLEDOWN:
- XCirculateSubwindowsDown(dpy, Root);
- break;
-
- case F_VERSION:
- XMapRaised(dpy, VersionWindow);
- break;
-
- case F_EXEC:
- Execute(menu->action);
- break;
-
- case F_FOCUS:
- FocusOnRoot();
- break;
-
- case F_CUT:
- strcpy(tmp, menu->action);
- strcat(tmp, "\n");
- XStoreBytes(dpy, tmp, strlen(tmp));
- break;
-
- case F_CUTFILE:
- ptr = XFetchBytes(dpy, &count);
- if (count != 0)
- {
- if (sscanf(ptr, "%s", tmp) == 1)
- {
- fd = open(tmp, 0);
- if (fd >= 0)
- {
- count = read(fd, buff, MAX_FILE_SIZE - 1);
- if (count > 0)
- XStoreBytes(dpy, buff, strlen(buff));
-
- close(fd);
- }
- else
- {
- fprintf(stderr, "twm: couldn't open \"%s\"\n", tmp);
- }
- }
- XFree(ptr);
- }
- else
- {
- fprintf(stderr, "twm: nothing in the cut buffer\n");
- }
- break;
-
- case F_FILE:
- fd = open(menu->action, 0);
- if (fd >= 0)
- {
- count = read(fd, buff, MAX_FILE_SIZE - 1);
- if (count > 0)
- XStoreBytes(dpy, buff, strlen(buff));
-
- close(fd);
- }
- else
- {
- fprintf(stderr, "twm: couldn't open \"%s\"\n", menu->action);
- }
- break;
-
- case F_TWMRC:
- len = strlen(menu->action);
- if (len == 0)
- ptr = NULL;
- else
- {
- ptr = (char *)malloc(len+1);
- if (ptr == NULL)
- {
- fprintf(stderr, "twm: out of memory\n");
- exit(1);
- }
- strcpy(ptr, menu->action);
- }
-
- /* first get rid of the existing menu structure and destroy all
- * windows */
- for (root = MenuList; root != NULL;)
- {
- for (item = root->last; item != NULL;)
- {
- if (item->pull != NULL)
- {
- XDeleteContext(dpy, item->pull, MenuContext);
- XDestroyWindow(dpy, item->pull);
- }
- XDeleteContext(dpy, item->w, MenuContext);
- XDestroyWindow(dpy, item->w);
-
- free(item->item);
- free(item->action);
-
- tmp_item = item;
- item = item->prev;
- free(tmp_item);
- }
-
- XDeleteContext(dpy, root->w, MenuContext);
- XDestroyWindow(dpy, root->shadow);
- XDestroyWindow(dpy, root->w);
- free(root->name);
-
- tmp_root = root;
- root = root->next;
- free(tmp_root);
- }
- MenuList = NULL;
- LastMenu = NULL;
- ActiveMenu = NULL;
- ActiveItem = NULL;
-
- ParseTwmrc(ptr);
- break;
-
- case F_REFRESH:
- black = BlackPixel(dpy, DefaultScreen(dpy));
- w = XCreateSimpleWindow(dpy, Root,
- 0, 0, 9999, 9999, 0, black, black);
- XMapWindow(dpy, w);
- XDestroyWindow(dpy, w);
- XFlush(dpy);
- break;
-
- case F_QUIT:
- Done();
- break;
- }
- }
-
- /***********************************************************************
- *
- * Procedure:
- * Execute - execute the string by /bin/sh
- *
- * Inputs:
- * s - the string containing the command
- *
- ***********************************************************************
- */
-
- void
- Execute(s)
- char *s;
- {
- int status, pid, w;
- register int (*istat) (), (*qstat) ();
-
- if ((pid = vfork()) == 0)
- {
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- execl("/bin/sh", "sh", "-c", s, 0);
- _exit(127);
- }
- istat = signal(SIGINT, SIG_IGN);
- qstat = signal(SIGQUIT, SIG_IGN);
- while ((w = wait(&status)) != pid && w != -1);
- if (w == -1)
- status = -1;
- signal(SIGINT, istat);
- signal(SIGQUIT, qstat);
- }
-
- /***********************************************************************
- *
- * Procedure:
- * FocusOnRoot - put input focus on the root window
- *
- ***********************************************************************
- */
-
- void
- FocusOnRoot()
- {
- XSetInputFocus(dpy, Root, RevertToPointerRoot, CurrentTime);
- if (Focus != NULL)
- {
- XUnmapWindow(dpy, Focus->hilite_w);
- }
- Focus = NULL;
- FocusRoot = TRUE;
- }
-