toml@marvin.Solbourne.COM (Tom LaStrange) (08/30/90)
Submitted-by: toml@marvin.Solbourne.COM (Tom LaStrange) Posting-number: Volume 9, Issue 5 Archive-name: tvtwm/part04 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting test in a file # 3. Execute the file with /bin/sh (not csh) to create the files: # #menus.c # # Created by toml () on Wed Aug 29 08:43:33 MDT 1990 # if test -f 'menus.c' then echo shar: will not over-write existing file "menus.c" else echo extracting "menus.c" sed 's/^X//' >menus.c <<'SHAR_EOF' X/*****************************************************************************/ X/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ X/** Salt Lake City, Utah **/ X/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ X/** Cambridge, Massachusetts **/ 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/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ X/** in publicity pertaining to distribution of the software without **/ X/** specific, written prior permission. **/ X/** **/ X/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ X/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ X/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ X/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ X/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ X/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ X/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ X/** OR PERFORMANCE OF THIS SOFTWARE. **/ X/*****************************************************************************/ X X X/*********************************************************************** X * X * $XConsortium: menus.c,v 1.156 90/03/23 13:30:49 jim Exp $ X * X * twm menu code X * X * 17-Nov-87 Thomas E. LaStrange File created X * X ***********************************************************************/ X X#if !defined(lint) && !defined(SABER) Xstatic char RCSinfo[] = X"$XConsortium: menus.c,v 1.156 90/03/23 13:30:49 jim Exp $"; X#endif X X#include <stdio.h> X#include <signal.h> X#include <X11/Xos.h> X#include "twm.h" X#include "gc.h" X#include "menus.h" X#include "resize.h" X#include "events.h" X#include "util.h" X#include "parse.h" X#include "gram.h" X#include "screen.h" X#include <X11/bitmaps/menu12> X#include "version.h" X#include "vdt.h" X#include "add_window.h" X#include "patchlevel.h" X Xextern XEvent Event; X Xint RootFunction = NULL; XMenuRoot *ActiveMenu = NULL; /* the active menu */ XMenuItem *ActiveItem = NULL; /* the active menu item */ Xint MoveFunction; /* either F_MOVE or F_FORCEMOVE */ Xint WindowMoved = FALSE; X Xint ConstMove = FALSE; /* constrained move variables */ Xint ConstMoveDir; Xint ConstMoveX; Xint ConstMoveY; Xint ConstMoveXL; Xint ConstMoveXR; Xint ConstMoveYT; Xint ConstMoveYB; X Xint MenuDepth = 0; /* number of menus up */ Xstatic struct { X int x; X int y; X} MenuOrigins[MAXMENUDEPTH]; Xstatic Cursor LastCursor; X Xvoid WarpAlongRing(), WarpToWindow(); X Xextern char *Action; Xextern int Context; Xextern TwmWindow *ButtonWindow, *Tmp_win; Xextern XEvent Event, ButtonEvent; Xextern char *InitFile; Xstatic void Identify(); X X#define SHADOWWIDTH 5 /* in pixels */ 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 { X Scr->Mouse[i][j][k].func = NULL; X Scr->Mouse[i][j][k].item = NULL; X } X X Scr->DefaultFunction.func = NULL; X Scr->WindowFunction.func = NULL; X X if (FirstScreen) X { X for (key = Scr->FuncKeyRoot.next; key != NULL;) X { X free(key->name); X tmp = key; X key = key->next; X free((char *) tmp); X } X Scr->FuncKeyRoot.next = NULL; X } X 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 * win_name- the window name (if any) X * action - the action string associated with the function (if any) X * X *********************************************************************** X */ X XBool AddFuncKey (name, cont, mods, func, win_name, action) X char *name; X int cont, mods, func; X char *win_name; X char *action; X{ X FuncKey *tmp; X KeySym keysym; X KeyCode keycode; X X /* X * Don't let a 0 keycode go through, since that means AnyKey to the X * XGrabKey call in GrabKeys(). X */ X if ((keysym = XStringToKeysym(name)) == NoSymbol || X (keycode = XKeysymToKeycode(dpy, keysym)) == 0) X { X return False; X } X X /* see if there already is a key defined for this context */ X for (tmp = Scr->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 = Scr->FuncKeyRoot.next; X Scr->FuncKeyRoot.next = tmp; X } X X tmp->name = name; X tmp->keysym = keysym; X tmp->keycode = keycode; X tmp->cont = cont; X tmp->mods = mods; X tmp->func = func; X tmp->win_name = win_name; X tmp->action = action; X X return True; X} X Xint CreateTitleButton (name, func, action, menuroot, rightside, append) X char *name; X int func; X char *action; X MenuRoot *menuroot; X Bool rightside; X Bool append; X{ X TitleButton *tb = (TitleButton *) malloc (sizeof(TitleButton)); X X if (!tb) { X fprintf (stderr, X "%s: unable to allocate %d bytes for title button\n", X ProgramName, sizeof(TitleButton)); X return 0; X } X X tb->next = NULL; X tb->name = name; /* note that we are not copying */ X tb->bitmap = None; /* WARNING, values not set yet */ X tb->width = 0; /* see InitTitlebarButtons */ X tb->height = 0; /* ditto */ X tb->func = func; X tb->action = action; X tb->menuroot = menuroot; X tb->rightside = rightside; X if (rightside) { X Scr->TBInfo.nright++; X } else { X Scr->TBInfo.nleft++; X } X X /* X * Cases for list: X * X * 1. empty list, prepend left put at head of list X * 2. append left, prepend right put in between left and right X * 3. append right put at tail of list X * X * Do not refer to widths and heights yet since buttons not created X * (since fonts not loaded and heights not known). X */ X if ((!Scr->TBInfo.head) || ((!append) && (!rightside))) { /* 1 */ X tb->next = Scr->TBInfo.head; X Scr->TBInfo.head = tb; X } else if (append && rightside) { /* 3 */ X register TitleButton *t; X for (t = Scr->TBInfo.head; t->next; t = t->next) ; X t->next = tb; X tb->next = NULL; X } else { /* 2 */ X register TitleButton *t, *prev = NULL; X for (t = Scr->TBInfo.head; t && !t->rightside; t = t->next) { X prev = t; X } X if (prev) { X tb->next = prev->next; X prev->next = tb; X } else { X tb->next = Scr->TBInfo.head; X Scr->TBInfo.head = tb; X } X } X X return 1; X} X X X/* X * InitTitlebarButtons - Do all the necessary stuff to load in a titlebar X * button. If we can't find the button, then put in a question; if we can't X * find the question mark, something is wrong and we are probably going to be X * in trouble later on. X */ Xvoid InitTitlebarButtons () X{ X TitleButton *tb; X int h; X X /* X * initialize dimensions X */ X Scr->TBInfo.width = (Scr->TitleHeight - X 2 * (Scr->FramePadding + Scr->ButtonIndent)); X Scr->TBInfo.pad = ((Scr->TitlePadding > 1) X ? ((Scr->TitlePadding + 1) / 2) : 1); X h = Scr->TBInfo.width - 2 * Scr->TBInfo.border; X X /* X * add in some useful buttons and bindings so that novices can still X * use the system. X */ X if (!Scr->NoDefaults) { X /* insert extra buttons */ X if (!CreateTitleButton (TBPM_ICONIFY, F_ICONIFY, "", (MenuRoot *) NULL, X False, False)) { X fprintf (stderr, "%s: unable to add iconify button\n", X ProgramName); X } X if (!CreateTitleButton (TBPM_RESIZE, F_RESIZE, "", (MenuRoot *) NULL, X True, True)) { X fprintf (stderr, "%s: unable to add resize button\n", X ProgramName); X } X AddDefaultBindings (); X } X ComputeCommonTitleOffsets (); X X /* X * load in images and do appropriate centering X */ X X for (tb = Scr->TBInfo.head; tb; tb = tb->next) { X tb->bitmap = FindBitmap (tb->name, &tb->width, &tb->height); X if (!tb->bitmap) { X tb->bitmap = FindBitmap (TBPM_QUESTION, &tb->width, &tb->height); X if (!tb->bitmap) { /* cannot happen (see util.c) */ X fprintf (stderr, X "%s: unable to add titlebar button \"%s\"\n", X ProgramName, tb->name); X } X } X X tb->dstx = (h - tb->width + 1) / 2; X if (tb->dstx < 0) { /* clip to minimize copying */ X tb->srcx = -(tb->dstx); X tb->width = h; X tb->dstx = 0; X } else { X tb->srcx = 0; X } X tb->dsty = (h - tb->height + 1) / 2; X if (tb->dsty < 0) { X tb->srcy = -(tb->dsty); X tb->height = h; X tb->dsty = 0; X } else { X tb->srcy = 0; X } X } X} X X XPaintEntry(mr, mi, exposure) XMenuRoot *mr; XMenuItem *mi; Xint exposure; X{ X int y_offset; X int text_y; X GC gc; X X#ifdef DEBUG_MENUS X fprintf(stderr, "Paint entry\n"); X#endif X y_offset = mi->item_num * Scr->EntryHeight; X text_y = y_offset + Scr->MenuFont.y; X X if (mi->func != F_TITLE) X { X int x, y; X X if (mi->state) X { X XSetForeground(dpy, Scr->NormalGC, mi->hi_back); X X XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, X mr->width, Scr->EntryHeight); X X FBF(mi->hi_fore, mi->hi_back, Scr->MenuFont.font->fid); X X XDrawString(dpy, mr->w, Scr->NormalGC, mi->x, X text_y, mi->item, mi->strlen); X X gc = Scr->NormalGC; X } X else X { X if (mi->user_colors || !exposure) X { X XSetForeground(dpy, Scr->NormalGC, mi->back); X X XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, X mr->width, Scr->EntryHeight); X X FBF(mi->fore, mi->back, Scr->MenuFont.font->fid); X gc = Scr->NormalGC; X } X else X gc = Scr->MenuGC; X X XDrawString(dpy, mr->w, gc, mi->x, X text_y, mi->item, mi->strlen); X } X X if (mi->func == F_MENU) X { X X /* create the pull right pixmap if needed */ X if (Scr->pullPm == None) X { X Scr->pullPm = XCreatePixmapFromBitmapData(dpy, Scr->Root, X menu12_bits, menu12_width, menu12_height, 1, 0, 1); X } X x = mr->width - menu12_width - 5; X y = y_offset + ((Scr->MenuFont.height - menu12_height) / 2); X XCopyPlane(dpy, Scr->pullPm, mr->w, gc, 0, 0, X menu12_width, menu12_height, x, y, 1); X } X } X else X { X int y; X X XSetForeground(dpy, Scr->NormalGC, mi->back); X X /* fill the rectangle with the title background color */ X XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, X mr->width, Scr->EntryHeight); X X { X XSetForeground(dpy, Scr->NormalGC, mi->fore); X /* now draw the dividing lines */ X if (y_offset) X XDrawLine (dpy, mr->w, Scr->NormalGC, 0, y_offset, X mr->width, y_offset); X y = ((mi->item_num+1) * Scr->EntryHeight)-1; X XDrawLine(dpy, mr->w, Scr->NormalGC, 0, y, mr->width, y); X } X X FBF(mi->fore, mi->back, Scr->MenuFont.font->fid); X /* finally render the title */ X XDrawString(dpy, mr->w, Scr->NormalGC, mi->x, X text_y, mi->item, mi->strlen); X } X} X X XPaintMenu(mr, e) XMenuRoot *mr; XXEvent *e; X{ X MenuItem *mi; X X for (mi = mr->first; mi != NULL; mi = mi->next) X { X int y_offset = mi->item_num * Scr->EntryHeight; X X /* be smart about handling the expose, redraw only the entries X * that we need to X */ X if (e->xexpose.y < (y_offset + Scr->EntryHeight) && X (e->xexpose.y + e->xexpose.height) > y_offset) X { X PaintEntry(mr, mi, True); X } X } X XSync(dpy, 0); X} X X XUpdateMenu() X{ X MenuItem *mi; X int i, x, y, x_root, y_root, entry; X int done; X MenuItem *badItem = NULL; X X while (TRUE) X { X while (XCheckMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | X EnterWindowMask | ExposureMask, &Event)) X { X if (!DispatchEvent ()) continue; X if (Event.type == ButtonRelease || Cancel) X return; X } X X /* if we haven't recieved the enter notify yet, wait */ X if (ActiveMenu && !ActiveMenu->entered) X continue; X X done = FALSE; X XQueryPointer( dpy, ActiveMenu->w, &JunkRoot, &JunkChild, X &x_root, &y_root, &x, &y, &JunkMask); X X XFindContext(dpy, ActiveMenu->w, ScreenContext, (caddr_t *)&Scr); X X if (x < 0 || y < 0 || X x >= ActiveMenu->width || y >= ActiveMenu->height) X { X if (ActiveItem && ActiveItem->func != F_TITLE) X { X ActiveItem->state = 0; X PaintEntry(ActiveMenu, ActiveItem, False); X } X ActiveItem = NULL; X continue; X } X X /* look for the entry that the mouse is in */ X entry = y / Scr->EntryHeight; X for (i = 0, mi = ActiveMenu->first; mi != NULL; i++, mi=mi->next) X { X if (i == entry) X break; X } X X /* if there is an active item, we might have to turn it off */ X if (ActiveItem) X { X /* is the active item the one we are on ? */ X if (ActiveItem->item_num == entry && ActiveItem->state) X done = TRUE; X X /* if we weren't on the active entry, let's turn the old X * active one off X */ X if (!done && ActiveItem->func != F_TITLE) X { X ActiveItem->state = 0; X PaintEntry(ActiveMenu, ActiveItem, False); X } X } X X /* if we weren't on the active item, change the active item and turn X * it on X */ X if (!done) X { X ActiveItem = mi; X if (ActiveItem->func != F_TITLE && !ActiveItem->state) X { X ActiveItem->state = 1; X PaintEntry(ActiveMenu, ActiveItem, False); X } X } X X /* now check to see if we were over the arrow of a pull right entry */ X if (ActiveItem->func == F_MENU && X ((ActiveMenu->width - x) < (ActiveMenu->width >> 1))) X { X MenuRoot *save = ActiveMenu; X int savex = MenuOrigins[MenuDepth - 1].x; X int savey = MenuOrigins[MenuDepth - 1].y; X X if (MenuDepth < MAXMENUDEPTH) { X PopUpMenu (ActiveItem->sub, (savex + (ActiveMenu->width >> 1)), X (savey + ActiveItem->item_num * Scr->EntryHeight + X (Scr->EntryHeight >> 1)), False); X } else if (!badItem) { X XBell (dpy, 0); X badItem = ActiveItem; X } X X /* if the menu did get popped up, unhighlight the active item */ X if (save != ActiveMenu && ActiveItem->state) X { X ActiveItem->state = 0; X PaintEntry(save, ActiveItem, False); X ActiveItem = NULL; X } X } X if (badItem != ActiveItem) badItem = NULL; X XFlush(dpy); X } 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 X tmp = (MenuRoot *) malloc(sizeof(MenuRoot)); X tmp->hi_fore = -1; X tmp->hi_back = -1; 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 = NEVER_MAPPED; X tmp->pull = FALSE; X tmp->w = None; X tmp->shadow = None; X tmp->real_menu = FALSE; X X if (Scr->MenuList == NULL) X { X Scr->MenuList = tmp; X Scr->MenuList->next = NULL; X } X X if (Scr->LastMenu == NULL) X { X Scr->LastMenu = tmp; X Scr->LastMenu->next = NULL; X } X else X { X Scr->LastMenu->next = tmp; X Scr->LastMenu = tmp; X Scr->LastMenu->next = NULL; X } X X if (strcmp(name, TWM_WINDOWS) == 0) X Scr->Windows = tmp; 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 * fore - foreground color string X * back - background color string X * X *********************************************************************** X */ X XMenuItem * XAddToMenu(menu, item, action, sub, func, fore, back) X MenuRoot *menu; X char *item, *action; X MenuRoot *sub; X int func; X char *fore, *back; X{ X MenuItem *tmp; X int width; X X#ifdef DEBUG_MENUS 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->strlen = strlen(item); X tmp->action = action; X tmp->next = NULL; X tmp->sub = NULL; X tmp->state = 0; X tmp->func = func; X X if (!Scr->HaveFonts) CreateFonts(); X width = XTextWidth(Scr->MenuFont.font, item, tmp->strlen); X if (width <= 0) X width = 1; X if (width > menu->width) X menu->width = width; X X tmp->user_colors = FALSE; X if (Scr->Monochrome == COLOR && fore != NULL) X { X int save; X X save = Scr->FirstTime; X Scr->FirstTime = TRUE; X GetColor(COLOR, &tmp->fore, fore); X GetColor(COLOR, &tmp->back, back); X Scr->FirstTime = save; X tmp->user_colors = TRUE; X } X if (sub != NULL) X { X tmp->sub = sub; X menu->pull = TRUE; X } X tmp->item_num = menu->items++; X X return (tmp); X} X XMakeMenus() X{ X MenuRoot *mr; X X for (mr = Scr->MenuList; mr != NULL; mr = mr->next) X { X if (mr->real_menu == FALSE) X continue; X X MakeMenu(mr); X } X} X XMakeMenu(mr) XMenuRoot *mr; X{ X MenuItem *start, *end, *cur, *tmp; X XColor f1, f2, f3; X XColor b1, b2, b3; X XColor save_fore, save_back; X int num, i; X int fred, fgreen, fblue; X int bred, bgreen, bblue; X int width; X unsigned long valuemask; X XSetWindowAttributes attributes; X Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; X X Scr->EntryHeight = Scr->MenuFont.height + 4; X X /* lets first size the window accordingly */ X if (mr->mapped == NEVER_MAPPED) X { X if (mr->pull == TRUE) X { X mr->width += 16 + 10; X } X X width = mr->width + 10; X X for (cur = mr->first; cur != NULL; cur = cur->next) X { X if (cur->func != F_TITLE) X cur->x = 5; X else X { X cur->x = width - XTextWidth(Scr->MenuFont.font, cur->item, X cur->strlen); X cur->x /= 2; X } X } X mr->height = mr->items * Scr->EntryHeight; X mr->width += 10; X X if (Scr->Shadow) X { X /* X * Make sure that you don't draw into the shadow window or else X * the background bits there will get saved X */ X valuemask = (CWBackPixel | CWBorderPixel); X attributes.background_pixel = Scr->MenuShadowColor; X attributes.border_pixel = Scr->MenuShadowColor; X if (Scr->SaveUnder) { X valuemask |= CWSaveUnder; X attributes.save_under = True; X } X mr->shadow = XCreateWindow (dpy, Scr->Root, 0, 0, X (unsigned int) mr->width, X (unsigned int) mr->height, X (unsigned int)0, X CopyFromParent, X (unsigned int) CopyFromParent, X (Visual *) CopyFromParent, X valuemask, &attributes); X } X X valuemask = (CWBackPixel | CWBorderPixel | CWEventMask); X attributes.background_pixel = Scr->MenuC.back; X attributes.border_pixel = Scr->MenuC.fore; X attributes.event_mask = (ExposureMask | EnterWindowMask); X if (Scr->SaveUnder) { X valuemask |= CWSaveUnder; X attributes.save_under = True; X } X if (Scr->BackingStore) { X valuemask |= CWBackingStore; X attributes.backing_store = Always; X } X mr->w = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) mr->width, X (unsigned int) mr->height, (unsigned int) 1, X CopyFromParent, (unsigned int) CopyFromParent, X (Visual *) CopyFromParent, X valuemask, &attributes); X X X XSaveContext(dpy, mr->w, MenuContext, (caddr_t)mr); X XSaveContext(dpy, mr->w, ScreenContext, (caddr_t)Scr); X X mr->mapped = UNMAPPED; X } X X /* get the default colors into the menus */ X for (tmp = mr->first; tmp != NULL; tmp = tmp->next) X { X if (!tmp->user_colors) { X if (tmp->func != F_TITLE) { X tmp->fore = Scr->MenuC.fore; X tmp->back = Scr->MenuC.back; X } else { X tmp->fore = Scr->MenuTitleC.fore; X tmp->back = Scr->MenuTitleC.back; X } X } X X if (mr->hi_fore != -1) X { X tmp->hi_fore = mr->hi_fore; X tmp->hi_back = mr->hi_back; X } X else X { X tmp->hi_fore = tmp->back; X tmp->hi_back = tmp->fore; X } X } X X if (Scr->Monochrome == MONOCHROME || !Scr->InterpolateMenuColors) X return; X X start = mr->first; X while (TRUE) X { X for (; start != NULL; start = start->next) X { X if (start->user_colors) X break; X } X if (start == NULL) X break; X X for (end = start->next; end != NULL; end = end->next) X { X if (end->user_colors) X break; X } X if (end == NULL) X break; X X /* we have a start and end to interpolate between */ X num = end->item_num - start->item_num; X X f1.pixel = start->fore; X XQueryColor(dpy, cmap, &f1); X f2.pixel = end->fore; X XQueryColor(dpy, cmap, &f2); X X b1.pixel = start->back; X XQueryColor(dpy, cmap, &b1); X b2.pixel = end->back; X XQueryColor(dpy, cmap, &b2); X X fred = ((int)f2.red - (int)f1.red) / num; X fgreen = ((int)f2.green - (int)f1.green) / num; X fblue = ((int)f2.blue - (int)f1.blue) / num; X X bred = ((int)b2.red - (int)b1.red) / num; X bgreen = ((int)b2.green - (int)b1.green) / num; X bblue = ((int)b2.blue - (int)b1.blue) / num; X X f3 = f1; X f3.flags = DoRed | DoGreen | DoBlue; X X b3 = b1; X b3.flags = DoRed | DoGreen | DoBlue; X X num -= 1; X for (i = 0, cur = start->next; i < num; i++, cur = cur->next) X { X f3.red += fred; X f3.green += fgreen; X f3.blue += fblue; X save_fore = f3; X X b3.red += bred; X b3.green += bgreen; X b3.blue += bblue; X save_back = b3; X X XAllocColor(dpy, cmap, &f3); X XAllocColor(dpy, cmap, &b3); X cur->fore = f3.pixel; X cur->back = b3.pixel; X cur->user_colors = True; X X f3 = save_fore; X b3 = save_back; X } X start = end; X } 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, y - location of upper left of menu X * center - whether or not to center horizontally over position X * X *********************************************************************** X */ X XBool PopUpMenu (menu, x, y, center) X MenuRoot *menu; X int x, y; X Bool center; X{ X if (!menu) return False; X X InstallRootColormap(); X X if (menu == Scr->Windows) X { X TwmWindow *tmp_win; X X /* this is the twm windows menu, let's go ahead and build it */ X X DestroyMenu (menu); X X menu->first = NULL; X menu->last = NULL; X menu->items = 0; X menu->width = 0; X menu->mapped = NEVER_MAPPED; X X AddToMenu(menu, "TWM Windows", NULLSTR, NULL, F_TITLE,NULLSTR,NULLSTR); X for (tmp_win = Scr->TwmRoot.next; X tmp_win != NULL; X tmp_win = tmp_win->next) X { X AddToMenu (menu, tmp_win->name, (char *) tmp_win, NULL, F_POPUP, X NULLSTR, NULLSTR); X } X MakeMenu(menu); X } X X if (menu->w == None || menu->items == 0) return False; X X /* Prevent recursively bringing up menus. */ X if (menu->mapped == MAPPED) return False; X X /* X * Dynamically set the parent; this allows pull-ups to also be main X * menus, or to be brought up from more than one place. X */ X menu->prev = ActiveMenu; X X XGrabPointer(dpy, Scr->Root, True, X ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeAsync, X Scr->Root, Scr->MenuCursor, CurrentTime); X X ActiveMenu = menu; X menu->mapped = MAPPED; X menu->entered = FALSE; X X if (center) { X x -= (menu->width / 2); X y -= (Scr->EntryHeight / 2); /* sticky menus would be nice here */ X } X X /* X * clip to screen X */ X if (x + menu->width > Scr->MyDisplayWidth) { X x = Scr->MyDisplayWidth - menu->width; X } X if (x < 0) x = 0; X if (y + menu->height > Scr->MyDisplayHeight) { X y = Scr->MyDisplayHeight - menu->height; X } X if (y < 0) y = 0; X X MenuOrigins[MenuDepth].x = x; X MenuOrigins[MenuDepth].y = y; X MenuDepth++; X X XMoveWindow(dpy, menu->w, x, y); X if (Scr->Shadow) { X XMoveWindow (dpy, menu->shadow, x + SHADOWWIDTH, y + SHADOWWIDTH); X } X if (Scr->Shadow) { X XRaiseWindow (dpy, menu->shadow); X } X XMapRaised(dpy, menu->w); X if (Scr->Shadow) { X XMapWindow (dpy, menu->shadow); X } X XSync(dpy, 0); X return True; X} X X/*********************************************************************** X * X * Procedure: X * PopDownMenu - unhighlight the current menu selection and X * take down the menus X * X *********************************************************************** X */ X XPopDownMenu() X{ X MenuRoot *tmp; X X if (ActiveMenu == NULL) X return; X X if (ActiveItem) X { X ActiveItem->state = 0; X PaintEntry(ActiveMenu, ActiveItem, False); X } X X for (tmp = ActiveMenu; tmp != NULL; tmp = tmp->prev) X { X if (Scr->Shadow) { X XUnmapWindow (dpy, tmp->shadow); X } X XUnmapWindow(dpy, tmp->w); X tmp->mapped = UNMAPPED; X UninstallRootColormap(); X } X X XFlush(dpy); X ActiveMenu = NULL; X ActiveItem = NULL; X MenuDepth = 0; 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 = Scr->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 * 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 * Returns: X * TRUE if should continue with remaining actions else FALSE to abort X * X *********************************************************************** X */ X Xint XExecuteFunction(func, action, w, tmp_win, eventp, context, pulldown) X int func; X char *action; X Window w; X TwmWindow *tmp_win; X XEvent *eventp; X int context; X int pulldown; X{ X static Time last_time = 0; X X char tmp[200]; X char *ptr; X char buff[MAX_FILE_SIZE]; X int count, fd; X Window rootw; X int origX, origY; X int do_next_action = TRUE; X int moving_icon = FALSE; X extern int ConstrainedMoveTime; X X RootFunction = NULL; X if (Cancel) X return TRUE; /* XXX should this be FALSE? */ X X switch (func) X { X case F_UPICONMGR: X case F_LEFTICONMGR: X case F_RIGHTICONMGR: X case F_DOWNICONMGR: X case F_FORWICONMGR: X case F_BACKICONMGR: X case F_NEXTICONMGR: X case F_PREVICONMGR: X case F_NOP: X case F_TITLE: X case F_DELTASTOP: X case F_RAISELOWER: X case F_WARPTOSCREEN: X case F_WARPTO: X case F_WARPRING: X case F_WARPTOICONMGR: X case F_COLORMAP: X break; X default: X XGrabPointer(dpy, Scr->Root, True, X ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeAsync, X Scr->Root, Scr->WaitCursor, CurrentTime); X break; X } X X switch (func) X { X case F_NOP: X case F_TITLE: X break; X X case F_PANNER: X if (Scr->Panner) { X if (XFindContext (dpy, Scr->Panner, TwmContext, (caddr_t *)&tmp_win) != XCSUCCESS) X tmp_win = AddWindow(Scr->Panner, FALSE, NULL); X if (tmp_win->mapped) { X UnmapFrame(tmp_win); X tmp_win->mapped = FALSE; X } X else { X if (tmp_win->icon) X DeIconify(tmp_win); X else X MapFrame(tmp_win); X tmp_win->mapped = TRUE; X } X } X break; X X case F_SCROLLHOME: X case F_SCROLLLEFT: X case F_SCROLLRIGHT: X case F_SCROLLUP: X case F_SCROLLDOWN: X ScrollDesktop(func); X break; X X case F_DELTASTOP: X if (WindowMoved) do_next_action = FALSE; X break; X X case F_RESTART: X XSync (dpy, 0); X Reborder (); X XSync (dpy, 0); X execvp(*Argv, Argv); X fprintf (stderr, "%s: unable to restart: %s\n", ProgramName, *Argv); X break; X X case F_UPICONMGR: X case F_DOWNICONMGR: X case F_LEFTICONMGR: X case F_RIGHTICONMGR: X case F_FORWICONMGR: X case F_BACKICONMGR: X MoveIconManager(func); X break; X X case F_NEXTICONMGR: X case F_PREVICONMGR: X JumpIconManager(func); X break; X X case F_SHOWLIST: X if (Scr->NoIconManagers) X break; X DeIconify(Scr->iconmgr.twm_win); X RaiseFrame(Scr->iconmgr.twm_win); X break; X X case F_HIDELIST: X if (Scr->NoIconManagers) X break; X HideIconManager (); X break; X X case F_STICK: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X if (Scr->VirtualDesktop) { X int x, y; X Window junkChild; X X if (tmp_win->sticky) { X XReparentWindow(dpy, tmp_win->frame, Scr->VirtualDesktop, X tmp_win->frame_x + Scr->vdtPositionX, X tmp_win->frame_y + Scr->vdtPositionY); X if (tmp_win->icon_w) { X XReparentWindow(dpy, tmp_win->icon_w, Scr->VirtualDesktop, X tmp_win->icon_loc_x + Scr->vdtPositionX, X tmp_win->icon_loc_y + Scr->vdtPositionY); X tmp_win->icon_loc_x += Scr->vdtPositionX; X tmp_win->icon_loc_y += Scr->vdtPositionY; X } X if (!tmp_win->icon) X XMapRaised(dpy, tmp_win->virtualWindow); X else if (tmp_win->virtualIcon) X XMapRaised(dpy, tmp_win->virtualIcon); X tmp_win->root = Scr->VirtualDesktop; X tmp_win->frame_x += Scr->vdtPositionX; X tmp_win->frame_y += Scr->vdtPositionY; X tmp_win->sticky = False; X SetSWM_ROOT(tmp_win); X SetTWM_FLAGS(tmp_win); X } X else { X XReparentWindow(dpy, tmp_win->frame, Scr->Root, X tmp_win->frame_x - Scr->vdtPositionX, X tmp_win->frame_y - Scr->vdtPositionY); X if (tmp_win->icon_w) { X XReparentWindow(dpy, tmp_win->icon_w, Scr->Root, X tmp_win->icon_loc_x - Scr->vdtPositionX, X tmp_win->icon_loc_y - Scr->vdtPositionY); X tmp_win->icon_loc_x -= Scr->vdtPositionX; X tmp_win->icon_loc_y -= Scr->vdtPositionY; X } X XUnmapWindow(dpy, tmp_win->virtualWindow); X if (tmp_win->virtualIcon) X XUnmapWindow(dpy, tmp_win->virtualIcon); X tmp_win->root = Scr->Root; X tmp_win->frame_x -= Scr->vdtPositionX; X tmp_win->frame_y -= Scr->vdtPositionY; X tmp_win->sticky = True; X SetSWM_ROOT(tmp_win); X SetTWM_FLAGS(tmp_win); X } X } X break; X X case F_SORTICONMGR: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X { X int save_sort; X X save_sort = Scr->SortIconMgr; X Scr->SortIconMgr = TRUE; X X if (context == C_ICONMGR) X SortIconManager((IconMgr *) NULL); X else if (tmp_win->iconmgr) X SortIconManager(tmp_win->iconmgrp); X else X XBell(dpy, 0); X X Scr->SortIconMgr = save_sort; X } X break; X X case F_IDENTIFY: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X Identify(tmp_win); X break; X X case F_VERSION: X Identify ((TwmWindow *) NULL); X break; X X case F_AUTORAISE: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X tmp_win->auto_raise = !tmp_win->auto_raise; X break; X X case F_BEEP: X XBell(dpy, 0); X break; X X case F_POPUP: X tmp_win = (TwmWindow *)action; X if (Scr->WindowFunction.func != NULL) X { X ExecuteFunction(Scr->WindowFunction.func, X Scr->WindowFunction.item->action, X w, tmp_win, eventp, C_FRAME, FALSE); X } X else X { X DeIconify(tmp_win); X if (Scr->VirtualDesktop) X ScrollToQuadrant(tmp_win); X RaiseFrame (tmp_win); X } X break; X X case F_RESIZE: X EventHandler[EnterNotify] = HandleUnknown; X EventHandler[LeaveNotify] = HandleUnknown; X if (DeferExecution(context, func, Scr->MoveCursor)) X return TRUE; X X PopDownMenu(); X X if (pulldown) X XWarpPointer(dpy, None, Scr->Root, X 0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root); X X if (w != tmp_win->icon_w) { /* can't resize icons */ X Bool fromtitlebar = False; /* controls AutoRelativeResizing */ X X /* X * see if this is being done from the titlebar X */ X if (tmp_win && tmp_win->titlebuttons) { X register TBWindow *tbw; X register int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; X for (tbw = tmp_win->titlebuttons; nb > 0; tbw++, nb--) { X if (tbw->window == w) { X fromtitlebar = True; X break; X } X } X } X X StartResize (eventp, tmp_win, fromtitlebar); X return TRUE; X } X break; X X X case F_ZOOM: X case F_HORIZOOM: X case F_FULLZOOM: X case F_LEFTZOOM: X case F_RIGHTZOOM: X case F_TOPZOOM: X case F_BOTTOMZOOM: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X fullzoom(tmp_win, func); X break; X X case F_MOVE: X case F_FORCEMOVE: X if (DeferExecution(context, func, Scr->MoveCursor)) X return TRUE; X X PopDownMenu(); X rootw = eventp->xbutton.root; X MoveFunction = func; X X if (pulldown) X XWarpPointer(dpy, None, Scr->Root, X 0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root); X X if (context == C_ICON && tmp_win->icon_w) X { X DragIcon(tmp_win, eventp, pulldown); X } X else if (w != tmp_win->icon_w) X { X DragFrame(tmp_win, eventp, pulldown); X } X#ifdef OLD_MOVE X if (DeferExecution(context, func, Scr->MoveCursor)) X return TRUE; X X PopDownMenu(); X rootw = eventp->xbutton.root; X MoveFunction = func; X X if (pulldown) X XWarpPointer(dpy, None, Scr->Root, X 0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root); X X EventHandler[EnterNotify] = HandleUnknown; X EventHandler[LeaveNotify] = HandleUnknown; X X if (!Scr->NoGrabServer || !Scr->OpaqueMove) { X XGrabServer(dpy); X } X XGrabPointer(dpy, eventp->xbutton.root, True, X ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeAsync, X Scr->Root, Scr->MoveCursor, CurrentTime); X X if (context == C_ICON && tmp_win->icon_w) X { X w = tmp_win->icon_w; X DragVirtual = tmp_win->virtualIcon; X DragX = eventp->xbutton.x; X DragY = eventp->xbutton.y; X moving_icon = TRUE; X } X else if (w != tmp_win->icon_w) X { X XTranslateCoordinates(dpy, w, tmp_win->frame, X eventp->xbutton.x, X eventp->xbutton.y, X &DragX, &DragY, &JunkChild); X X w = tmp_win->frame; X DragVirtual = tmp_win->virtualWindow; X } X X DragWindow = None; X X XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY, X (unsigned int *)&DragWidth, (unsigned int *)&DragHeight, &JunkBW, X &JunkDepth); X X origX = eventp->xbutton.x_root; X origY = eventp->xbutton.y_root; X CurrentDragX = origDragX; X CurrentDragY = origDragY; X X /* X * only do the constrained move if timer is set; need to check it X * in case of stupid or wicked fast servers X */ X if (ConstrainedMoveTime && X (eventp->xbutton.time - last_time) < ConstrainedMoveTime) X { X int width, height; X X ConstMove = TRUE; X ConstMoveDir = MOVE_NONE; X ConstMoveX = eventp->xbutton.x_root - DragX - JunkBW; X ConstMoveY = eventp->xbutton.y_root - DragY - JunkBW; X width = DragWidth + 2 * JunkBW; X height = DragHeight + 2 * JunkBW; 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, w, X 0, 0, 0, 0, DragWidth/2, DragHeight/2); X X XQueryPointer(dpy, w, &JunkRoot, &JunkChild, X &JunkX, &JunkY, &DragX, &DragY, &JunkMask); X } X last_time = eventp->xbutton.time; X X if (!Scr->OpaqueMove) X InstallRootColormap(); X X while (TRUE) X { X int done; X X done = FALSE; X while (XCheckMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | X EnterWindowMask | LeaveWindowMask | X ExposureMask, &Event)) X { X /* throw away enter and leave events until release */ X if (Event.xany.type == EnterNotify || X Event.xany.type == LeaveNotify) continue; X X if (!DispatchEvent ()) continue; X X if (Cancel) X { X WindowMoved = FALSE; X if (!Scr->OpaqueMove) X UninstallRootColormap(); X return TRUE; /* XXX should this be FALSE? */ X } X if (Event.type == ButtonRelease) X { X MoveOutline(rootw, 0, 0, 0, 0, 0, 0); X done = TRUE; X if (moving_icon && X ((CurrentDragX != origDragX || X CurrentDragY != origDragY))) X tmp_win->icon_moved = TRUE; X break; X } X } X X if (done) X break; X X /* X * WARNING - mashing event X */ X XQueryPointer(dpy, rootw, &(eventp->xmotion.root), &JunkChild, X &(eventp->xmotion.x_root), &(eventp->xmotion.y_root), X &JunkX, &JunkY, &JunkMask); X X if (DragWindow == None && X abs(eventp->xmotion.x_root - origX) < Scr->MoveDelta && X abs(eventp->xmotion.y_root - origY) < Scr->MoveDelta) X continue; X X WindowMoved = TRUE; X DragWindow = w; X X if (!Scr->NoRaiseMove && Scr->OpaqueMove) /* can't restore... */ X XRaiseWindow(dpy, DragWindow); X X if (ConstMove) X { X switch (ConstMoveDir) X { X case MOVE_NONE: X if (eventp->xmotion.x_root < ConstMoveXL || X eventp->xmotion.x_root > ConstMoveXR) X ConstMoveDir = MOVE_HORIZ; X X if (eventp->xmotion.y_root < ConstMoveYT || X eventp->xmotion.y_root > ConstMoveYB) X ConstMoveDir = MOVE_VERT; X X XQueryPointer(dpy, DragWindow, &JunkRoot, &JunkChild, X &JunkX, &JunkY, &DragX, &DragY, &JunkMask); X break; X X case MOVE_VERT: X ConstMoveY = eventp->xmotion.y_root - DragY - JunkBW; X break; X X case MOVE_HORIZ: X ConstMoveX= eventp->xmotion.x_root - DragX - JunkBW; X break; X } X X if (ConstMoveDir != MOVE_NONE) X { X int xl, yt, xr, yb, w, h; X X xl = ConstMoveX; X yt = ConstMoveY; X w = DragWidth + 2 * JunkBW; X h = DragHeight + 2 * JunkBW; X X if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE) X { X xr = xl + w; X yb = yt + h; X X if (xl < 0) X xl = 0; X if (xr > Scr->MyDisplayWidth) X xl = Scr->MyDisplayWidth - w; X X if (yt < 0) X yt = 0; X if (yb > Scr->MyDisplayHeight) X yt = Scr->MyDisplayHeight - h; X } X CurrentDragX = xl; X CurrentDragY = yt; X if (Scr->OpaqueMove) X XMoveWindow(dpy, DragWindow, xl, yt); X else X MoveOutline(eventp->xmotion.root, xl, yt, w, h, X tmp_win->frame_bw, X moving_icon ? 0 : tmp_win->title_height); X } X } X else if (DragWindow != None) X { X int xl, yt, xr, yb, w, h; X X xl = eventp->xmotion.x_root - DragX - JunkBW; X yt = eventp->xmotion.y_root - DragY - JunkBW; X w = DragWidth + 2 * JunkBW; X h = DragHeight + 2 * JunkBW; X X if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE) X { X xr = xl + w; X yb = yt + h; X X if (xl < 0) X xl = 0; X if (xr > Scr->MyDisplayWidth) X xl = Scr->MyDisplayWidth - w; X X if (yt < 0) X yt = 0; X if (yb > Scr->MyDisplayHeight) X yt = Scr->MyDisplayHeight - h; X } X X CurrentDragX = xl; X CurrentDragY = yt; X if (Scr->OpaqueMove) X XMoveWindow(dpy, DragWindow, xl, yt); X else X MoveOutline(eventp->xmotion.root, xl, yt, w, h, X tmp_win->frame_bw, X moving_icon ? 0 : tmp_win->title_height); X } X X } X X if (!Scr->OpaqueMove && DragWindow == None) X UninstallRootColormap(); X#endif /* OLD_MOVE */ 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, "%s: couldn't find function \"%s\"\n", X ProgramName, action); X return TRUE; X } X X if (NeedToDefer(mroot) && DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X else X { X for (mitem = mroot->first; mitem != NULL; mitem = mitem->next) X { X if (!ExecuteFunction (mitem->func, mitem->action, w, X tmp_win, eventp, context, pulldown)) X break; X } X } X } X break; X X case F_DEICONIFY: X case F_ICONIFY: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X if (tmp_win->icon) X { X DeIconify(tmp_win); X } X else if (func == F_ICONIFY) X { X Iconify (tmp_win, eventp->xbutton.x_root - 5, X eventp->xbutton.y_root - 5); X } X break; X X case F_RAISELOWER: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X if (!WindowMoved) { X Window virtual; X XWindowChanges xwc; X X xwc.stack_mode = Opposite; X virtual = tmp_win->virtualIcon; X if (w != tmp_win->icon_w) { X w = tmp_win->frame; X virtual = tmp_win->virtualWindow; X } X XConfigureWindow (dpy, w, CWStackMode, &xwc); X if (tmp_win->sticky && Scr->VirtualDesktop) X XLowerWindow(dpy, Scr->VirtualDesktop); X if (virtual) X XConfigureWindow (dpy, virtual, CWStackMode, &xwc); X } X break; X X case F_RAISE: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X if (w == tmp_win->icon_w) X RaiseIcon(tmp_win); X else X RaiseFrame(tmp_win); X X break; X X case F_LOWER: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X if (w == tmp_win->icon_w) X LowerIcon(tmp_win); X else X LowerFrame(tmp_win); X X break; X X case F_FOCUS: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X if (tmp_win->icon == FALSE) X { X if (!Scr->FocusRoot && Scr->Focus == tmp_win) X { X FocusOnRoot(); X } X else X { X if (Scr->Focus != NULL) { X SetBorder (Scr->Focus, False); X if (Scr->Focus->hilite_w) X XUnmapWindow (dpy, Scr->Focus->hilite_w); X } X X InstallWindowColormaps (0, tmp_win); X if (tmp_win->hilite_w) XMapWindow (dpy, tmp_win->hilite_w); X SetBorder (tmp_win, True); X SetFocus (tmp_win); X Scr->FocusRoot = FALSE; X Scr->Focus = tmp_win; X } X } X break; X X case F_DESTROY: X if (DeferExecution(context, func, Scr->DestroyCursor)) X return TRUE; X X if (tmp_win->iconmgr) X XBell(dpy, 0); X else if (tmp_win->w == Scr->Panner) { X UnmapFrame(tmp_win); X tmp_win->mapped = FALSE; X } X else X XKillClient(dpy, tmp_win->w); X break; X X case F_DELETE: X if (DeferExecution(context, func, Scr->DestroyCursor)) X return TRUE; X X if (tmp_win->iconmgr) /* don't send ourself a message */ X HideIconManager (); X else if (tmp_win->protocols & DoesWmDeleteWindow) X SendDeleteWindowMessage (tmp_win, LastTimestamp()); X else X XBell (dpy, 0); X break; X X case F_SAVEYOURSELF: X if (DeferExecution (context, func, Scr->SelectCursor)) X return TRUE; X X if (tmp_win->protocols & DoesWmSaveYourself) X SendSaveYourselfMessage (tmp_win, LastTimestamp()); X else X XBell (dpy, 0); X break; X X case F_CIRCLEUP: X XCirculateSubwindowsUp(dpy, Scr->Root); X break; X X case F_CIRCLEDOWN: X XCirculateSubwindowsDown(dpy, Scr->Root); X break; X X case F_EXEC: X PopDownMenu(); X if (!Scr->NoGrabServer) { X XUngrabServer (dpy); X XSync (dpy, 0); X } 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 (ptr) { X if (sscanf (ptr, "%s", tmp) == 1) { X XFree (ptr); X ptr = ExpandFilename(tmp); X if (ptr) { X fd = open (ptr, 0); X if (fd >= 0) { X count = read (fd, buff, MAX_FILE_SIZE - 1); X if (count > 0) XStoreBytes (dpy, buff, count); X close(fd); X } else { X fprintf (stderr, X "%s: unable to open cut file \"%s\"\n", X ProgramName, tmp); X } X if (ptr != tmp) free (ptr); X } X } else { X XFree(ptr); X } X } else { X fprintf(stderr, "%s: cut buffer is empty\n", ProgramName); X } X break; X X case F_WARPTOSCREEN: X { X if (strcmp (action, WARPSCREEN_NEXT) == 0) { X WarpToScreen (Scr->screen + 1, 1); X } else if (strcmp (action, WARPSCREEN_PREV) == 0) { X WarpToScreen (Scr->screen - 1, -1); X } else if (strcmp (action, WARPSCREEN_BACK) == 0) { X WarpToScreen (PreviousScreen, 0); X } else { X WarpToScreen (atoi (action), 0); X } X } X break; X X case F_COLORMAP: X { X if (strcmp (action, COLORMAP_NEXT) == 0) { X BumpWindowColormap (tmp_win, 1); X } else if (strcmp (action, COLORMAP_PREV) == 0) { X BumpWindowColormap (tmp_win, -1); X } else { X BumpWindowColormap (tmp_win, 0); X } X } X break; X X case F_WARPTO: X { X register TwmWindow *t; X int len; X X len = strlen(action); X X for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { X if (!strncmp(action, t->name, len)) break; X } X if (!t) { X for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { X if (!strncmp(action, t->class.res_name, len)) break; X } X if (!t) { X for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { X if (!strncmp(action, t->class.res_class, len)) break; X } X } X } X X if (t) { X if (Scr->WarpUnmapped || t->mapped) { X if (!t->mapped) DeIconify (t); X RaiseFrame (t); X WarpToWindow (t); X } X } else { X XBell (dpy, 0); X } X } X break; X X case F_WARPTOICONMGR: X { X TwmWindow *t; X int len; X Window raisewin = None, iconwin = None; X TwmWindow *raiseFrame; X X len = strlen(action); X if (len == 0) { X if (tmp_win && tmp_win->list) { X raisewin = tmp_win->list->iconmgr->twm_win->frame; X raiseFrame = tmp_win->list->iconmgr->twm_win; X iconwin = tmp_win->list->icon; X } else if (Scr->iconmgr.active) { X raisewin = Scr->iconmgr.twm_win->frame; X raiseFrame = Scr->iconmgr.twm_win; X iconwin = Scr->iconmgr.active->w; X } X } else { X for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { X if (strncmp (action, t->icon_name, len) == 0) { X if (t->list && t->list->iconmgr->twm_win->mapped) { X raisewin = t->list->iconmgr->twm_win->frame; X raiseFrame = t->list->iconmgr->twm_win; X iconwin = t->list->icon; X break; X } X } X } X } X X if (raisewin) { X RaiseFrame (raiseFrame); X XWarpPointer (dpy, None, iconwin, 0,0,0,0, 5, 5); X } else { X XBell (dpy, 0); X } X } X break; X X case F_WARPRING: X switch (action[0]) { X case 'n': X WarpAlongRing (&eventp->xbutton, True); X break; X case 'p': X WarpAlongRing (&eventp->xbutton, False); X break; X default: X XBell (dpy, 0); X break; 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, "%s: unable to open file \"%s\"\n", X ProgramName, action); X } X break; X X case F_REFRESH: X { X XSetWindowAttributes attributes; X unsigned long valuemask; X X valuemask = (CWBackPixel | CWBackingStore | CWSaveUnder); X attributes.background_pixel = Scr->Black; X attributes.backing_store = NotUseful; X attributes.save_under = False; X w = XCreateWindow (dpy, Scr->Root, 0, 0, X (unsigned int) Scr->MyDisplayWidth, X (unsigned int) Scr->MyDisplayHeight, X (unsigned int) 0, X CopyFromParent, (unsigned int) CopyFromParent, X (Visual *) CopyFromParent, valuemask, X &attributes); X XMapWindow (dpy, w); X XDestroyWindow (dpy, w); X XFlush (dpy); X } X break; X X case F_WINREFRESH: X if (DeferExecution(context, func, Scr->SelectCursor)) X return TRUE; X X if (context == C_ICON && tmp_win->icon_w) X w = XCreateSimpleWindow(dpy, tmp_win->icon_w, X 0, 0, 9999, 9999, 0, Scr->Black, Scr->Black); X else X w = XCreateSimpleWindow(dpy, tmp_win->frame, X 0, 0, 9999, 9999, 0, Scr->Black, Scr->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 X if (ButtonPressed == -1) XUngrabPointer(dpy, CurrentTime); X return do_next_action; 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 LastCursor = cursor; X XGrabPointer(dpy, Scr->Root, True, X ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeAsync, X Scr->Root, cursor, CurrentTime); X X RootFunction = func; X X return (TRUE); X } X X return (FALSE); X} X X X/*********************************************************************** X * X * Procedure: X * ReGrab - regrab the pointer with the LastCursor; X * X *********************************************************************** X */ X XReGrab() X{ X XGrabPointer(dpy, Scr->Root, True, X ButtonPressMask | ButtonReleaseMask, X GrabModeAsync, GrabModeAsync, X Scr->Root, LastCursor, CurrentTime); X} X X/*********************************************************************** X * X * Procedure: X * NeedToDefer - checks each function in the list to see if it X * is one that needs to be defered. X * X * Inputs: X * root - the menu root to check X * X *********************************************************************** X */ X XNeedToDefer(root) XMenuRoot *root; X{ X MenuItem *mitem; X X for (mitem = root->first; mitem != NULL; mitem = mitem->next) X { X switch (mitem->func) X { X case F_IDENTIFY: X case F_RESIZE: X case F_MOVE: X case F_FORCEMOVE: X case F_DEICONIFY: X case F_ICONIFY: X case F_RAISELOWER: X case F_RAISE: X case F_LOWER: X case F_FOCUS: X case F_DESTROY: X case F_WINREFRESH: X case F_ZOOM: X case F_FULLZOOM: X case F_HORIZOOM: X case F_RIGHTZOOM: X case F_LEFTZOOM: X case F_TOPZOOM: X case F_BOTTOMZOOM: X case F_AUTORAISE: 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 static char buf[256]; X char *ds = DisplayString (dpy); X char *colon, *dot1; X char oldDisplay[256]; X char *doisplay; X int restorevar = 0; X X oldDisplay[0] = '\0'; X doisplay=getenv("DISPLAY"); X if (doisplay) X strcpy (oldDisplay, doisplay); X X /* X * Build a display string using the current screen number, so that X * X programs which get fired up from a menu come up on the screen X * that they were invoked from, unless specifically overridden on X * their command line. X */ X colon = rindex (ds, ':'); X if (colon) { /* if host[:]:dpy */ X strcpy (buf, "DISPLAY="); X strcat (buf, ds); X colon = buf + 8 + (colon - ds); /* use version in buf */ X dot1 = index (colon, '.'); /* first period after colon */ X if (!dot1) dot1 = colon + strlen (colon); /* if not there, append */ X (void) sprintf (dot1, ".%d", Scr->screen); X putenv (buf); X restorevar = 1; X } X X (void) system (s); X X if (restorevar) { /* why bother? */ X (void) sprintf (buf, "DISPLAY=%s", oldDisplay); X putenv (buf); X } X} X X/*********************************************************************** X * X * Procedure: X * FocusOnRoot - put input focus on the root window X * X *********************************************************************** X */ X Xvoid XFocusOnRoot() X{ X SetFocus ((TwmWindow *) NULL); X if (Scr->Focus != NULL) X { X SetBorder (Scr->Focus, False); X if (Scr->Focus->hilite_w) XUnmapWindow (dpy, Scr->Focus->hilite_w); X } X InstallWindowColormaps(0, &Scr->TwmRoot); X Scr->Focus = NULL; X Scr->FocusRoot = TRUE; X} X XDeIconify(tmp_win) XTwmWindow *tmp_win; X{ X TwmWindow *t; X X /* de-iconify group members (if any) */ X if (tmp_win->group == tmp_win->w) X { X for (t = Scr->TwmRoot.next; t != NULL; t = t->next) X { X if (tmp_win->group == t->group && X tmp_win->group != t->w && t->icon) X { X if (t->icon_on) X Zoom(t->icon_w, t->frame); X else X Zoom(tmp_win->icon_w, t->frame); X X t->mapped = TRUE; X if (!Scr->NoRaiseDeicon) X RaiseFrame(t); X MapFrame(t); X SetMapStateProp(t, NormalState); X X if (t->icon_w) { X UnmapIcon(t); X IconDown (t); X } X if (t->list) XUnmapWindow(dpy, t->list->icon); X t->icon = FALSE; X t->icon_on = FALSE; X } X } X } X X /* now de-iconify the main window */ X if (tmp_win->icon) X { X if (tmp_win->icon_on) X Zoom(tmp_win->icon_w, tmp_win->frame); X else if (tmp_win->group != NULL) X { X for (t = Scr->TwmRoot.next; t != NULL; t = t->next) X { X if (tmp_win->group == t->w && t->icon_on) X { X Zoom(t->icon_w, tmp_win->frame); X break; X } X } X } X } X X X tmp_win->mapped = TRUE; X if (!Scr->NoRaiseDeicon) X RaiseFrame(tmp_win); X MapFrame(tmp_win); X SetMapStateProp(tmp_win, NormalState); X X if (tmp_win->icon_w) { X UnmapIcon(tmp_win); X IconDown (tmp_win); X } X if (tmp_win->list) X XUnmapWindow(dpy, tmp_win->list->icon); X if ((Scr->WarpCursor || X LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)) && X tmp_win->icon) X WarpToWindow (tmp_win); X tmp_win->icon = FALSE; X tmp_win->icon_on = FALSE; X XSync (dpy, 0); X} X XIconify(tmp_win, def_x, def_y) XTwmWindow *tmp_win; Xint def_x, def_y; X{ X TwmWindow *t; X int iconify; X XWindowAttributes winattrs; X unsigned long eventMask; X X iconify = ((!tmp_win->iconify_by_unmapping) || tmp_win->transient); X if (iconify) X { X if (tmp_win->icon_w == NULL) X CreateIconWindow(tmp_win, def_x, def_y); X else X IconUp(tmp_win); X MapIcon(tmp_win); X } X if (tmp_win->list) X XMapWindow(dpy, tmp_win->list->icon); X X XGetWindowAttributes(dpy, tmp_win->w, &winattrs); X eventMask = winattrs.your_event_mask; X X /* iconify group members first */ X if (tmp_win->group == tmp_win->w) X { X for (t = Scr->TwmRoot.next; t != NULL; t = t->next) X { X if (tmp_win->group == t->group && tmp_win->group != t->w) X { X if (iconify) X { X if (t->icon_on) X Zoom(t->icon_w, tmp_win->icon_w); X else X Zoom(t->frame, tmp_win->icon_w); X } X X /* X * Prevent the receipt of an UnmapNotify, since that would X * cause a transition to the Withdrawn state. X */ X t->mapped = FALSE; X XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask); X UnmapFrame(t); X XSelectInput(dpy, t->w, eventMask); X if (t->icon_w) X UnmapIcon(t); X SetMapStateProp(t, IconicState); X SetBorder (t, False); X if (t == Scr->Focus) X { X SetFocus ((TwmWindow *) NULL); X Scr->Focus = NULL; X Scr->FocusRoot = TRUE; X } X if (t->list) XMapWindow(dpy, t->list->icon); X t->icon = TRUE; X t->icon_on = FALSE; X } X } X } X X if (iconify) X Zoom(tmp_win->frame, tmp_win->icon_w); X X /* X * Prevent the receipt of an UnmapNotify, since that would X * cause a transition to the Withdrawn state. X */ X tmp_win->mapped = FALSE; X XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask); X UnmapFrame(tmp_win); X XSelectInput(dpy, tmp_win->w, eventMask); X SetMapStateProp(tmp_win, IconicState); X X SetBorder (tmp_win, False); X if (tmp_win == Scr->Focus) X { X SetFocus ((TwmWindow *) NULL); X Scr->Focus = NULL; X Scr->FocusRoot = TRUE; X } X tmp_win->icon = TRUE; X if (iconify) X tmp_win->icon_on = TRUE; X else X tmp_win->icon_on = FALSE; X XSync (dpy, 0); X} X Xstatic void Identify (t) XTwmWindow *t; X{ X int i, n, twidth, width, height; X int x, y; X unsigned int wwidth, wheight, bw, depth; X Window junk; X int px, py, dummy; X unsigned udummy; X X n = 0; X (void) sprintf(Info[n++], "tvtwm version: %s", Version); X (void) sprintf(Info[n++], "Patchlevel %d", PATCHLEVEL); X Info[n++][0] = '\0'; X X if (t) { X XGetGeometry (dpy, t->w, &JunkRoot, &JunkX, &JunkY, X &wwidth, &wheight, &bw, &depth); X (void) XTranslateCoordinates (dpy, t->w, Scr->Root, JunkX, JunkY, X &x, &y, &junk); X (void) sprintf(Info[n++], "Name = \"%s\"", t->full_name); X (void) sprintf(Info[n++], "Class.res_name = \"%s\"", t->class.res_name); X (void) sprintf(Info[n++], "Class.res_class = \"%s\"", t->class.res_class); X Info[n++][0] = '\0'; X (void) sprintf(Info[n++], "Geometry/root = %dx%d+%d+%d", wwidth, wheight, X x, y); X (void) sprintf(Info[n++], "Border width = %d", bw); X (void) sprintf(Info[n++], "Depth = %d", depth); X } X X Info[n++][0] = '\0'; X (void) sprintf(Info[n++], "Click to dismiss...."); X X /* figure out the width and height of the info window */ X height = n * (Scr->DefaultFont.height+2); X width = 1; X for (i = 0; i < n; i++) X { X twidth = XTextWidth(Scr->DefaultFont.font, Info[i], X strlen(Info[i])); X if (twidth > width) X width = twidth; X } X if (InfoLines) XUnmapWindow(dpy, Scr->InfoWindow); X X width += 10; /* some padding */ X if (XQueryPointer (dpy, Scr->Root, &JunkRoot, &JunkChild, &px, &py, X &dummy, &dummy, &udummy)) { X px -= (width / 2); X py -= (height / 3); X if (px + width + BW2 >= Scr->MyDisplayWidth) X px = Scr->MyDisplayWidth - width - BW2; X if (py + height + BW2 >= Scr->MyDisplayHeight) X py = Scr->MyDisplayHeight - height - BW2; X if (px < 0) px = 0; X if (py < 0) py = 0; X } else { X px = py = 0; X } X XMoveResizeWindow(dpy, Scr->InfoWindow, px, py, width, height); X XMapRaised(dpy, Scr->InfoWindow); X InfoLines = n; X} X XSetMapStateProp(tmp_win, state) XTwmWindow *tmp_win; Xint state; X{ X unsigned long data[2]; /* "suggested" by ICCCM version 1 */ X X data[0] = (unsigned long) state; X data[1] = (unsigned long) (tmp_win->iconify_by_unmapping ? None : X tmp_win->icon_w); X X XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32, X PropModeReplace, (unsigned char *) data, 2); X} X XBool GetWMState (w, statep, iwp) X Window w; X int *statep; X Window *iwp; X{ X Atom actual_type; X int actual_format; X unsigned long nitems, bytesafter; X unsigned long *datap = NULL; X Bool retval = False; X X if (XGetWindowProperty (dpy, w, _XA_WM_STATE, 0L, 2L, False, _XA_WM_STATE, X &actual_type, &actual_format, &nitems, &bytesafter, X (unsigned char **) &datap) != Success || !datap) X return False; X X if (nitems <= 2) { /* "suggested" by ICCCM version 1 */ X *statep = (int) datap[0]; X *iwp = (Window) datap[1]; X retval = True; X } X X XFree ((char *) datap); X return retval; X} X X XWarpToScreen (n, inc) X int n, inc; X{ X Window dumwin; X int x, y, dumint; X unsigned int dummask; X ScreenInfo *newscr = NULL; X X while (!newscr) { X /* wrap around */ X if (n < 0) X n = NumScreens - 1; X else if (n >= NumScreens) X n = 0; X X newscr = ScreenList[n]; X if (!newscr) { /* make sure screen is managed */ X if (inc) { /* walk around the list */ X n += inc; X continue; X } X fprintf (stderr, "%s: unable to warp to unmanaged screen %d\n", X ProgramName, n); X XBell (dpy, 0); X return; X } X } X X if (Scr->screen == n) return; /* already on that screen */ X X PreviousScreen = Scr->screen; X XQueryPointer (dpy, Scr->Root, &dumwin, &dumwin, &x, &y, X &dumint, &dumint, &dummask); X X XWarpPointer (dpy, None, newscr->Root, 0, 0, 0, 0, x, y); X return; X} X X X/* X * BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS X */ X XBumpWindowColormap (tmp, inc) X TwmWindow *tmp; X int inc; X{ X int i, j, previously_installed; X ColormapWindow **cwins; X X if (!tmp) return; X X if (inc && tmp->cmaps.number_cwins > 0) { X cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *)* X tmp->cmaps.number_cwins); X if (cwins) { X if (previously_installed = (Scr->cmapInfo.cmaps == &tmp->cmaps && X tmp->cmaps.number_cwins)) { X for (i = tmp->cmaps.number_cwins; i-- > 0; ) X tmp->cmaps.cwins[i]->colormap->state = 0; X } X X for (i = 0; i < tmp->cmaps.number_cwins; i++) { X j = i - inc; X if (j >= tmp->cmaps.number_cwins) X j -= tmp->cmaps.number_cwins; X else if (j < 0) X j += tmp->cmaps.number_cwins; X cwins[j] = tmp->cmaps.cwins[i]; X } X X free((char *) tmp->cmaps.cwins); X X tmp->cmaps.cwins = cwins; X X if (tmp->cmaps.number_cwins > 1) X bzero (tmp->cmaps.scoreboard, X ColormapsScoreboardLength(&tmp->cmaps)); X X if (previously_installed) X InstallWindowColormaps(PropertyNotify, (TwmWindow *) NULL); X } X } else X FetchWmColormapWindows (tmp); X} X XHideIconManager () X{ X SetMapStateProp (Scr->iconmgr.twm_win, WithdrawnState); X UnmapFrame(Scr->iconmgr.twm_win); X if (Scr->iconmgr.twm_win->icon_w) X UnmapIcon(Scr->iconmgr.twm_win); X Scr->iconmgr.twm_win->mapped = FALSE; X Scr->iconmgr.twm_win->icon = TRUE; X} X X XSetBorder (tmp, onoroff) X TwmWindow *tmp; X Bool onoroff; X{ X if (tmp->highlight) { X if (onoroff) { X XSetWindowBorder (dpy, tmp->frame, tmp->border); X if (tmp->title_w) X XSetWindowBorder (dpy, tmp->title_w, tmp->border); X } else { X XSetWindowBorderPixmap (dpy, tmp->frame, tmp->gray); X if (tmp->title_w) X XSetWindowBorderPixmap (dpy, tmp->title_w, tmp->gray); X } X } X} X XDestroyMenu (menu) X MenuRoot *menu; X{ X MenuItem *item; X X if (menu->w) { X XDeleteContext (dpy, menu->w, MenuContext); X XDeleteContext (dpy, menu->w, ScreenContext); X if (Scr->Shadow) XDestroyWindow (dpy, menu->shadow); X XDestroyWindow(dpy, menu->w); X } X X for (item = menu->first; item; ) { X MenuItem *tmp = item; X item = item->next; X free ((char *) tmp); X } X} X X/* X * warping routines X */ Xvoid WarpAlongRing (ev, forward) X XButtonEvent *ev; X Bool forward; X{ X TwmWindow *r, *head; X X if (Scr->RingLeader) X head = Scr->RingLeader; X else if (!(head = Scr->Ring)) X return; X X if (forward) { X for (r = head->ring.next; r != head; r = r->ring.next) { X if (!r || r->mapped) break; X } X } else { X for (r = head->ring.prev; r != head; r = r->ring.prev) { X if (!r || r->mapped) break; X } X } X X if (r && r != head) { X TwmWindow *p = Scr->RingLeader, *t; X X Scr->RingLeader = r; X WarpToWindow (r); X X if (p && p->mapped && X XFindContext (dpy, ev->window, TwmContext, (caddr_t *)&t) == XCSUCCESS && X p == t) { X p->ring.cursor_valid = True; X p->ring.curs_x = ev->x_root - t->frame_x; X p->ring.curs_y = ev->y_root - t->frame_y; X if (p->ring.curs_x < -p->frame_bw || X p->ring.curs_x >= p->frame_width + p->frame_bw || X p->ring.curs_y < -p->frame_bw || X p->ring.curs_y >= p->frame_height + p->frame_bw) { X /* somehow out of window */ X p->ring.curs_x = p->frame_width / 2; X p->ring.curs_y = p->frame_height / 2; X } X } X } X} X Xvoid WarpToWindow (t) X TwmWindow *t; X{ X int x, y; X X /* if we have the virtual desktop, attempt to make the window X * somewhat visible X */ X if (Scr->VirtualDesktop) X ScrollToQuadrant(t); X X if (t->auto_raise || !Scr->NoRaiseWarp) AutoRaiseWindow (t); X if (t->ring.cursor_valid) { X x = t->ring.curs_x; X y = t->ring.curs_y; X } else { X x = t->frame_width / 2; X y = t->frame_height / 2; X } X XWarpPointer (dpy, None, t->frame, 0, 0, 0, 0, x, y); X} X X X/* X * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all X * client messages will have the following form: X * X * event type ClientMessage X * message type _XA_WM_PROTOCOLS X * window tmp->w X * format 32 X * data[0] message atom X * data[1] time stamp X */ Xstatic void send_clientmessage (w, a, timestamp) X Window w; X Atom a; X Time timestamp; X{ X XClientMessageEvent ev; X X ev.type = ClientMessage; X ev.window = w; X ev.message_type = _XA_WM_PROTOCOLS; X ev.format = 32; X ev.data.l[0] = a; X ev.data.l[1] = timestamp; X XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); X} X XSendDeleteWindowMessage (tmp, timestamp) X TwmWindow *tmp; X Time timestamp; X{ X send_clientmessage (tmp->w, _XA_WM_DELETE_WINDOW, timestamp); X} X XSendSaveYourselfMessage (tmp, timestamp) X TwmWindow *tmp; X Time timestamp; X{ X send_clientmessage (tmp->w, _XA_WM_SAVE_YOURSELF, timestamp); X} X X XSendTakeFocusMessage (tmp, timestamp) X TwmWindow *tmp; X Time timestamp; X{ X send_clientmessage (tmp->w, _XA_WM_TAKE_FOCUS, timestamp); X} SHAR_EOF if test 64620 -ne "`wc -c < menus.c`" then echo shar: error transmitting "menus.c" '(should have been 64620 characters)' fi fi # end of shell archive exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.