/*****************************************************************************/
/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
/** Salt Lake City, Utah **/
/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
/** Cambridge, Massachusetts **/
/** **/
/** 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 **/
/** names of Evans & Sutherland and M.I.T. not be used in advertising **/
/** in publicity pertaining to distribution of the software without **/
/** specific, written prior permission. **/
/** **/
/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
/** AGES OR ANY DAMAGES 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 PERFORMANCE OF THIS SOFTWARE. **/
/*****************************************************************************/
/***********************************************************************
*
* $XConsortium: menus.c,v 1.186 91/07/17 13:58:00 dave Exp $
*
* twm menu code
*
* 17-Nov-87 Thomas E. LaStrange File created
*
***********************************************************************/
#include <X11/Xmu/CharSet.h>
#include <X11/Xos.h>
/* djhjr - 10/27/02 */
#ifndef NO_REGEX_SUPPORT
#include <sys/types.h>
#include <regex.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#ifdef NEED_PROCESS_H
#include <process.h>
#endif
#include <ctype.h> /* DSE */
#include "twm.h"
#include "gc.h"
#include "menus.h"
#include "resize.h"
#include "events.h"
#include "util.h"
#include "parse.h"
#include "gram.h"
#include "screen.h"
#include "doors.h"
#include "desktop.h"
#include "add_window.h"
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
#include "sound.h"
#endif
#include "version.h"
#define strdup Strdup /* avoid conflict with system header files */
extern char *strdup(char *);
extern void IconUp(), IconDown(), CreateIconWindow();
/* djhjr - 4/26/99 */
extern void AppletDown();
/* djhjr - 12/2/01 */
extern void delete_pidfile();
/* djhjr - 10/27/02 */
extern int MatchName();
extern void ResizeTwmWindowContents();
extern void SetRaiseWindow();
extern char *Action;
extern int Context;
extern int ConstrainedMoveTime;
extern TwmWindow *ButtonWindow, *Tmp_win;
extern XEvent Event, ButtonEvent;
extern char *InitFile;
int RootFunction = F_NOFUNCTION;
MenuRoot *ActiveMenu = NULL; /* the active menu */
MenuItem *ActiveItem = NULL; /* the active menu item */
int MoveFunction = F_NOFUNCTION; /* or F_MOVE or F_FORCEMOVE */
int WindowMoved = FALSE;
int menuFromFrameOrWindowOrTitlebar = FALSE;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
int createSoundFromFunction = FALSE;
int destroySoundFromFunction = FALSE;
#endif
void BumpWindowColormap();
void DestroyMenu();
void HideIconManager();
void MakeMenu();
void SendDeleteWindowMessage();
void SendSaveYourselfMessage();
void WarpClass();
void WarpToScreen();
void WarpScreenToWindow();
Cursor NeedToDefer(); /* was an 'int' - Submitted by Michel Eyckmans */
int ConstMove = FALSE; /* constrained move variables */
/* for comparison against MoveDelta - djhjr - 9/5/98 */
static int MenuOrigX, MenuOrigY;
/* Globals used to keep track of whether the mouse has moved during
a resize function. */
int ResizeOrigX;
int ResizeOrigY;
extern int origx, origy, origWidth, origHeight;
int MenuDepth = 0; /* number of menus up */
static struct {
int x;
int y;
} MenuOrigins[MAXMENUDEPTH];
static Cursor LastCursor;
static char *actionHack = ""; /* Submitted by Michel Eyckmans */
/*
* context bitmaps for TwmWindows menu, f.showdesktop and f.showiconmgr
* djhjr - 9/10/99
*/
static int have_twmwindows = -1;
static int have_showdesktop = -1;
static int have_showlist = -1;
void WarpAlongRing();
/* djhjr - 4/18/96 */
void Paint3DEntry();
static void Identify();
void PaintNormalEntry();
/* djhjr - 5/13/98 */
static TwmWindow *next_by_class();
static int warp_if_warpunmapped();
/* djhjr - 7/31/98 */
static void setup_restart();
void RestartVtwm();
/* djhjr - 9/21/99 */
int FindMenuOrFuncInBindings();
int FindMenuOrFuncInWindows();
int FindMenuInMenus();
int FindFuncInMenus();
/* djhjr - 9/21/99 */
void HideIconMgr();
void ShowIconMgr();
/* djhjr - 9/17/02 */
static int do_squeezetitle();
/* djhjr */
#undef MAX
/* DSE */
#define MAX(x,y) ((x)>(y)?(x):(y))
#define SHADOWWIDTH 5 /* in pixels */
#define EDGE_OFFSET 5 /* DSE */
/* djhjr - 5/5/98
#define PULLDOWNMENU_OFFSET ((Scr->RightHandSidePulldownMenus)?\
(ActiveMenu->width - EDGE_OFFSET * 2 - Scr->pullW):\
(ActiveMenu->width >> 1)) * DSE *
*/
#define PULLDOWNMENU_OFFSET ((Scr->RightHandSidePulldownMenus)?\
(JunkWidth - EDGE_OFFSET * 2 - Scr->pullW):\
(JunkWidth >> 1))
/***********************************************************************
*
* Procedure:
* InitMenus - initialize menu roots
*
***********************************************************************
*/
void
InitMenus()
{
int i, j, k;
FuncKey *key, *tmp;
for (i = 0; i < MAX_BUTTONS+1; i++)
for (j = 0; j < NUM_CONTEXTS; j++)
for (k = 0; k < MOD_SIZE; k++)
{
Scr->Mouse[i][j][k].func = F_NOFUNCTION;
Scr->Mouse[i][j][k].item = NULL;
}
Scr->DefaultFunction.func = F_NOFUNCTION;
Scr->WindowFunction.func = F_NOFUNCTION;
if (FirstScreen)
{
for (key = Scr->FuncKeyRoot.next; key != NULL;)
{
free(key->name);
tmp = key;
key = key->next;
free((char *) tmp);
}
Scr->FuncKeyRoot.next = NULL;
}
}
/***********************************************************************
*
* Procedure:
* AddFuncKey - add a function key to the list
*
* Inputs:
* name - the name of the key
* cont - the context to look for the key press in
* mods - modifier keys that need to be pressed
* func - the function to perform
* win_name- the window name (if any)
* action - the action string associated with the function (if any)
*
***********************************************************************
*/
Bool AddFuncKey (name, cont, mods, func, win_name, action)
char *name;
int cont, mods, func;
char *win_name;
char *action;
{
FuncKey *tmp;
KeySym keysym;
KeyCode keycode;
/*
* Don't let a 0 keycode go through, since that means AnyKey to the
* XGrabKey call in GrabKeys().
*/
if ((keysym = XStringToKeysym(name)) == NoSymbol ||
(keycode = XKeysymToKeycode(dpy, keysym)) == 0)
{
return False;
}
/* see if there already is a key defined for this context */
for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
{
if (tmp->keysym == keysym &&
tmp->cont == cont &&
tmp->mods == mods)
break;
}
if (tmp == NULL)
{
tmp = (FuncKey *) malloc(sizeof(FuncKey));
tmp->next = Scr->FuncKeyRoot.next;
Scr->FuncKeyRoot.next = tmp;
}
tmp->name = name;
tmp->keysym = keysym;
tmp->keycode = keycode;
tmp->cont = cont;
tmp->mods = mods;
tmp->func = func;
tmp->win_name = win_name;
tmp->action = action;
return True;
}
int CreateTitleButton (name, func, action, menuroot, rightside, append)
char *name;
int func;
char *action;
MenuRoot *menuroot;
Bool rightside;
Bool append;
{
TitleButton *tb = (TitleButton *) malloc (sizeof(TitleButton));
if (!tb) {
fprintf (stderr,
"%s: unable to allocate %d bytes for title button\n",
ProgramName, sizeof(TitleButton));
return 0;
}
tb->next = NULL;
tb->name = name; /* note that we are not copying */
/* djhjr - 10/30/02
* djhjr - 4/19/96 *
tb->image = NULL;
*/
/* tb->bitmap = None;*/ /* WARNING, values not set yet */
tb->width = 0; /* see InitTitlebarButtons */
tb->height = 0; /* ditto */
tb->func = func;
tb->action = action;
tb->menuroot = menuroot;
tb->rightside = rightside;
if (rightside) {
Scr->TBInfo.nright++;
} else {
Scr->TBInfo.nleft++;
}
/*
* Cases for list:
*
* 1. empty list, prepend left put at head of list
* 2. append left, prepend right put in between left and right
* 3. append right put at tail of list
*
* Do not refer to widths and heights yet since buttons not created
* (since fonts not loaded and heights not known).
*/
if ((!Scr->TBInfo.head) || ((!append) && (!rightside))) { /* 1 */
tb->next = Scr->TBInfo.head;
Scr->TBInfo.head = tb;
} else if (append && rightside) { /* 3 */
register TitleButton *t;
for (t = Scr->TBInfo.head; t->next; t = t->next)
; /* SUPPRESS 530 */
t->next = tb;
tb->next = NULL;
} else { /* 2 */
register TitleButton *t, *prev = NULL;
for (t = Scr->TBInfo.head; t && !t->rightside; t = t->next)
prev = t;
if (prev) {
tb->next = prev->next;
prev->next = tb;
} else {
tb->next = Scr->TBInfo.head;
Scr->TBInfo.head = tb;
}
}
return 1;
}
/*
* InitTitlebarButtons - Do all the necessary stuff to load in a titlebar
* button. If we can't find the button, then put in a question; if we can't
* find the question mark, something is wrong and we are probably going to be
* in trouble later on.
*/
/* was of type 'void', now returns button height - djhjr - 12/10/98 */
int InitTitlebarButtons ()
{
Image *image;
TitleButton *tb;
int h, height;
/*
* initialize dimensions
*/
Scr->TBInfo.width = (Scr->TitleHeight -
2 * (Scr->FramePadding + Scr->ButtonIndent));
/* djhjr - 10/18/02
* djhjr - 4/19/96 *
* was 'Scr->use3Dtitles' - djhjr - 8/11/98 *
if (Scr->TitleBevelWidth > 0)
Scr->TBInfo.pad = ((Scr->TitlePadding > 1)
? ((Scr->TitlePadding + 1) / 2) : 0);
else
Scr->TBInfo.pad = ((Scr->TitlePadding > 1)
? ((Scr->TitlePadding + 1) / 2) : 1);
*/
Scr->TBInfo.pad = Scr->TitlePadding;
h = Scr->TBInfo.width - 2 * Scr->TBInfo.border;
/* djhjr - 10/30/02 */
if (!(h & 1)) h--;
height = h;
/*
* add in some useful buttons and bindings so that novices can still
* use the system. -- modified by DSE
*/
if (!Scr->NoDefaultTitleButtons) /* DSE */
{
/* insert extra buttons */
/* djhjr - 4/19/96 */
/* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */
if (Scr->TitleBevelWidth > 0) {
if (!CreateTitleButton (TBPM_3DDOT, F_ICONIFY, "", (MenuRoot *) NULL,
False, False))
fprintf (stderr, "%s: unable to add iconify button\n", ProgramName);
if (!CreateTitleButton (TBPM_3DRESIZE, F_RESIZE, "", (MenuRoot *) NULL,
True, True))
fprintf (stderr, "%s: unable to add resize button\n", ProgramName);
}
else {
if (!CreateTitleButton (TBPM_ICONIFY, F_ICONIFY, "", (MenuRoot *) NULL,
False, False))
fprintf(stderr,"%s: unable to add iconify button\n",ProgramName);
if (!CreateTitleButton (TBPM_RESIZE, F_RESIZE, "", (MenuRoot *) NULL,
True, True))
fprintf(stderr,"%s: unable to add resize button\n",ProgramName);
}
}
if (!Scr->NoDefaultMouseOrKeyboardBindings) /* DSE */
{
AddDefaultBindings ();
}
ComputeCommonTitleOffsets ();
/* djhjr - 6/15/98 - moved it back to here... */
/* djhjr - 9/14/96 - moved to CreateWindowTitlebarButtons()... */
/*
* load in images and do appropriate centering
*/
for (tb = Scr->TBInfo.head; tb; tb = tb->next) {
/* djhjr - 4/19/96
tb->bitmap = FindBitmap (tb->name, &tb->width, &tb->height);
if (!tb->bitmap) {
tb->bitmap = FindBitmap (TBPM_QUESTION, &tb->width, &tb->height);
if (!tb->bitmap) { * cannot happen (see util.c) *
fprintf (stderr,
"%s: unable to add titlebar button \"%s\"\n",
ProgramName, tb->name);
}
}
*/
/* djhjr - 9/21/96
tb->image = GetImage (tb->name, Scr->TitleC);
if (!tb->image) {
tb->image = GetImage (TBPM_QUESTION, Scr->TitleC);
if (!tb->image) { * cannot happen (see util.c) *
fprintf (stderr, "%s: unable to add titlebar button \"%s\"\n",
ProgramName, tb->name);
}
}
*/
/* added width and height - 10/30/02 */
image = GetImage (tb->name, h, h, Scr->ButtonBevelWidth * 2,
(Scr->ButtonColorIsFrame) ? Scr->BorderColorC : Scr->TitleC);
tb->width = image->width;
/* added 'height = ' - djhjr - 12/10/98 */
height = tb->height = image->height;
tb->dstx = (h - tb->width + 1) / 2;
if (tb->dstx < 0) { /* clip to minimize copying */
tb->srcx = -(tb->dstx);
tb->width = h;
tb->dstx = 0;
} else {
tb->srcx = 0;
}
tb->dsty = (h - tb->height + 1) / 2;
if (tb->dsty < 0) {
tb->srcy = -(tb->dsty);
tb->height = h;
tb->dsty = 0;
} else {
tb->srcy = 0;
}
} /* for(...) */
/* djhjr - 12/10/98 */
return (height > h) ? height : h;
/* ...end of moved */
}
/* djhjr - 10/30/02 */
void SetMenuIconPixmap(filename)
char *filename;
{
Scr->menuIconName = filename;
}
void PaintEntry(mr, mi, exposure)
MenuRoot *mr;
MenuItem *mi;
int exposure;
{
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0)
Paint3DEntry (mr, mi, exposure);
/* djhjr - 4/22/96 */
else
PaintNormalEntry (mr, mi, exposure);
}
void Paint3DEntry(mr, mi, exposure)
MenuRoot *mr;
MenuItem *mi;
int exposure;
{
int y_offset;
int text_y;
GC gc;
/* djhjr - 4/29/98
y_offset = mi->item_num * Scr->EntryHeight + 2;
*/
/* djhjr - 5/22/00
y_offset = mi->item_num * Scr->EntryHeight + Scr->MenuBevelWidth;
*/
y_offset = (mi->item_num - mr->top) * Scr->EntryHeight + Scr->MenuBevelWidth;
/* djhjr - 9/25/96
text_y = y_offset + Scr->MenuFont.y + 2;
*/
text_y = y_offset + (((Scr->EntryHeight - Scr->MenuFont.height) / 2) + Scr->MenuFont.y);
if (mi->func != F_TITLE)
{
int x, y;
if (mi->state)
{
/* djhjr - 9/25/96
Draw3DBorder (mr->w, 2, y_offset, mr->width - 4, Scr->EntryHeight, 1,
mi->highlight, off, True, False);
*/
/* djhjr - 4/29/98
Draw3DBorder (mr->w, 2, y_offset + 1, mr->width - 4, Scr->EntryHeight - 1, 1,
mi->highlight, off, True, False);
*/
Draw3DBorder (mr->w, Scr->MenuBevelWidth, y_offset + 1, mr->width - 2 * Scr->MenuBevelWidth, Scr->EntryHeight - 1, 1,
mi->highlight, off, True, False);
/* font was font.font->fid - djhjr - 9/14/03 */
FBF(mi->highlight.fore, mi->highlight.back, Scr->MenuFont);
/* djhjr - 4/29/98
XDrawImageString(dpy, mr->w, Scr->NormalGC, mi->x + 2, text_y, mi->item, mi->strlen);
*/
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_DrawImageString(dpy, mr->w, &Scr->MenuFont,
#else
XDrawImageString(dpy, mr->w,
#endif
Scr->NormalGC, mi->x + Scr->MenuBevelWidth, text_y, mi->item, mi->strlen);
gc = Scr->NormalGC;
}
else
{
if (mi->user_colors || !exposure)
{
XSetForeground (dpy, Scr->NormalGC, mi->normal.back);
/* djhjr - 9/25/96
XFillRectangle (dpy, mr->w, Scr->NormalGC, 2, y_offset,
mr->width - 4, Scr->EntryHeight);
*/
/* djhjr - 4/29/98
XFillRectangle (dpy, mr->w, Scr->NormalGC, 2, y_offset + 1,
mr->width - 4, Scr->EntryHeight - 1);
*/
XFillRectangle (dpy, mr->w, Scr->NormalGC, Scr->MenuBevelWidth, y_offset + 1,
mr->width - 2 * Scr->MenuBevelWidth, Scr->EntryHeight - 1);
/* font was font.font->fid - djhjr - 9/14/03 */
FBF (mi->normal.fore, mi->normal.back, Scr->MenuFont);
gc = Scr->NormalGC;
}
else
{
gc = Scr->MenuGC;
}
/* djhjr - 4/29/98
XDrawImageString (dpy, mr->w, gc, mi->x + 2, text_y, mi->item, mi->strlen);
*/
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_DrawImageString (dpy, mr->w, &Scr->MenuFont,
#else
XDrawImageString (dpy, mr->w,
#endif
gc, mi->x + Scr->MenuBevelWidth, text_y, mi->item, mi->strlen);
if (mi->separated)
{
/* this 'if (...)' - djhjr - 1/19/98 */
if (!Scr->BeNiceToColormap)
{
FB (Scr->MenuC.shadd, Scr->MenuC.shadc);
/* djhjr - 9/25/96
XDrawLine (dpy, mr->w, Scr->NormalGC, 1, y_offset + Scr->MenuFont.y + 5,
mr->width - 2, y_offset + Scr->MenuFont.y + 5);
*/
/* djhjr - 4/29/98
XDrawLine (dpy, mr->w, Scr->NormalGC, 1, y_offset + Scr->EntryHeight - 1,
mr->width - 2, y_offset + Scr->EntryHeight - 1);
*/
XDrawLine (dpy, mr->w, Scr->NormalGC, Scr->MenuBevelWidth + 1, y_offset + Scr->EntryHeight - 1,
mr->width - Scr->MenuBevelWidth - 3, y_offset + Scr->EntryHeight - 1);
}
FB (Scr->MenuC.shadc, Scr->MenuC.shadd);
/* djhjr - 9/25/96
XDrawLine (dpy, mr->w, Scr->NormalGC, 2, y_offset + Scr->MenuFont.y + 6,
mr->width - 3, y_offset + Scr->MenuFont.y + 6);
*/
/* djhjr - 4/29/98
XDrawLine (dpy, mr->w, Scr->NormalGC, 2, y_offset + Scr->EntryHeight,
mr->width - 3, y_offset + Scr->EntryHeight);
*/
XDrawLine (dpy, mr->w, Scr->NormalGC, Scr->MenuBevelWidth + 2, y_offset + Scr->EntryHeight,
mr->width - Scr->MenuBevelWidth - 2, y_offset + Scr->EntryHeight);
}
}
if (mi->func == F_MENU)
{
/* djhjr - 10/30/02
* create the pull right pixmap if needed *
if (Scr->pullPm == None)
{
Scr->pullPm = Create3DMenuIcon (Scr->MenuFont.height, &Scr->pullW,
&Scr->pullH, Scr->MenuC);
*/
Image *image;
Pixel back;
back = Scr->MenuC.back;
if (mi->state)
Scr->MenuC.back = mi->highlight.back;
else
Scr->MenuC.back = mi->normal.back;
Scr->pullW = Scr->pullH = Scr->MenuFont.height;
image = GetImage(Scr->menuIconName,
Scr->pullW, Scr->pullH,
0, Scr->MenuC);
Scr->MenuC.back = back;
/* djhjr - 10/30/02
}
*/
/* djhjr - 4/29/98
x = mr->width - Scr->pullW - 5;
*/
x = mr->width - Scr->pullW - Scr->MenuBevelWidth - EDGE_OFFSET;
/* djhjr - 9/25/96
y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2) + 2;
*/
y = y_offset + ((Scr->EntryHeight - Scr->pullH) / 2) + 1;
XCopyArea (dpy, image->pixmap, mr->w, gc, 0, 0, Scr->pullW, Scr->pullH, x, y);
}
}
else
{
/* djhjr - 4/29/96
Draw3DBorder (mr->w, 2, y_offset, mr->width - 4, Scr->EntryHeight, 1,
mi->normal, off, True, False);
*/
/* djhjr - 4/29/98
Draw3DBorder (mr->w, 2, y_offset, mr->width - 4, Scr->EntryHeight + 1, 1,
mi->normal, off, True, False);
*/
Draw3DBorder (mr->w, Scr->MenuBevelWidth, y_offset, mr->width - 2 * Scr->MenuBevelWidth, Scr->EntryHeight + 1, 1,
mi->normal, off, True, False);
/* djhjr - 4/29/96
FBF (mi->normal.fore, mi->normal.back, Scr->MenuFont.font->fid);
*/
/* font was font.font->fid - djhjr - 9/14/03 */
FBF (mi->normal.fore, mi->normal.back, Scr->MenuTitleFont);
/* djhjr - 9/25/96
XDrawImageString (dpy, mr->w, Scr->NormalGC, mi->x + 2, text_y, mi->item, mi->strlen);
*/
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_DrawImageString (dpy, mr->w, &Scr->MenuTitleFont,
#else
XDrawImageString (dpy, mr->w,
#endif
Scr->NormalGC, mi->x, text_y, mi->item, mi->strlen);
}
}
void PaintNormalEntry(mr, mi, exposure)
MenuRoot *mr;
MenuItem *mi;
int exposure;
{
int y_offset;
int text_y;
GC gc;
/* djhjr - 5/22/00
y_offset = mi->item_num * Scr->EntryHeight;
*/
y_offset = (mi->item_num - mr->top) * Scr->EntryHeight;
/* djhjr - 9/26/96
text_y = y_offset + Scr->MenuFont.y;
*/
text_y = y_offset + (((Scr->EntryHeight - Scr->MenuFont.height) / 2) + Scr->MenuFont.y);
if (mi->func != F_TITLE)
{
int x, y;
if (mi->state)
{
XSetForeground(dpy, Scr->NormalGC, mi->highlight.back);
XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, Scr->EntryHeight);
/* font was font.font->fid - djhjr - 9/14/03 */
FBF(mi->highlight.fore, mi->highlight.back, Scr->MenuFont);
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_DrawString(dpy, mr->w, &Scr->MenuFont,
#else
XDrawString(dpy, mr->w,
#endif
Scr->NormalGC, mi->x,
text_y, mi->item, mi->strlen);
gc = Scr->NormalGC;
}
else
{
if (mi->user_colors || !exposure)
{
XSetForeground(dpy, Scr->NormalGC, mi->normal.back);
XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, Scr->EntryHeight);
/* font was font.font->fid - djhjr - 9/14/03 */
FBF(mi->normal.fore, mi->normal.back, Scr->MenuFont);
gc = Scr->NormalGC;
}
else
{
gc = Scr->MenuGC;
}
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_DrawString(dpy, mr->w, &Scr->MenuFont,
#else
XDrawString(dpy, mr->w,
#endif
gc, mi->x, text_y, mi->item, mi->strlen);
if (mi->separated)
/* djhjr - 9/26/96
XDrawLine (dpy, mr->w, gc, 0, y_offset + Scr->MenuFont.y + 5,
mr->width, y_offset + Scr->MenuFont.y + 5);
*/
XDrawLine (dpy, mr->w, gc, 0, y_offset + Scr->EntryHeight - 1,
mr->width, y_offset + Scr->EntryHeight - 1);
}
if (mi->func == F_MENU)
{
/* djhjr - 10/30/02
* create the pull right pixmap if needed *
if (Scr->pullPm == None)
{
Scr->pullPm = CreateMenuIcon (Scr->MenuFont.height,
&Scr->pullW, &Scr->pullH);
*/
Image *image;
ColorPair cp;
cp.back = Scr->MenuC.back;
if (strncmp(Scr->menuIconName, ":xpm:", 5) != 0)
{
cp.fore = Scr->MenuC.fore;
Scr->MenuC.fore = (mi->state) ? mi->highlight.fore : mi->normal.fore;
Scr->MenuC.back = (mi->state) ? mi->highlight.back : mi->normal.back;
}
else
Scr->MenuC.back = (mi->state) ? mi->highlight.back : mi->normal.back;
Scr->pullW = Scr->pullH = Scr->MenuFont.height;
image = GetImage(Scr->menuIconName,
Scr->pullW, Scr->pullH,
0, Scr->MenuC);
Scr->MenuC.back = cp.back;
if (strncmp(Scr->menuIconName, ":xpm:", 5) != 0)
Scr->MenuC.fore = cp.fore;
/* djhjr - 10/30/02
}
*/
x = mr->width - Scr->pullW - EDGE_OFFSET;
/* djhjr - 9/26/96
y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2);
*/
y = y_offset + ((Scr->EntryHeight - Scr->pullH) / 2);
/* djhjr - 10/30/02
XCopyPlane(dpy, Scr->pullPm->pixmap, mr->w, gc, 0, 0,
Scr->pullW, Scr->pullH, x, y, 1);
*/
XCopyArea (dpy, image->pixmap, mr->w, gc, 0, 0,
Scr->pullW, Scr->pullH, x, y);
}
}
else
{
int y;
XSetForeground(dpy, Scr->NormalGC, mi->normal.back);
/* fill the rectangle with the title background color */
XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, Scr->EntryHeight);
XSetForeground(dpy, Scr->NormalGC, mi->normal.fore);
/* now draw the dividing lines */
if (y_offset)
XDrawLine (dpy, mr->w, Scr->NormalGC, 0, y_offset,
mr->width, y_offset);
y = ((mi->item_num+1) * Scr->EntryHeight)-1;
XDrawLine(dpy, mr->w, Scr->NormalGC, 0, y, mr->width, y);
/* djhjr - 4/29/96
FBF(mi->normal.fore, mi->normal.back, Scr->MenuFont.font->fid);
*/
/* font was font.font->fid - djhjr - 9/14/03 */
FBF (mi->normal.fore, mi->normal.back, Scr->MenuTitleFont);
/* finally render the title */
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_DrawString(dpy, mr->w, &Scr->MenuTitleFont,
#else
XDrawString(dpy, mr->w,
#endif
Scr->NormalGC, mi->x, text_y, mi->item, mi->strlen);
}
}
void PaintMenu(mr, e)
MenuRoot *mr;
XEvent *e;
{
MenuItem *mi;
/* djhjr - 5/22/00 */
int y_offset;
/* djhjr - 4/22/96 */
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0) {
/* djhjr - 4/29/98
Draw3DBorder (mr->w, 0, 0, mr->width, mr->height, 2, Scr->MenuC, off, False, False);
*/
Draw3DBorder (mr->w, 0, 0, mr->width, mr->height, Scr->MenuBevelWidth, Scr->MenuC, off, False, False);
}
for (mi = mr->first; mi != NULL; mi = mi->next)
{
/* djhjr - 5/22/00 */
if (mi->item_num < mr->top) continue;
/* djhjr - 5/22/00
int y_offset = mi->item_num * Scr->EntryHeight;
*/
y_offset = (mi->item_num - mr->top) * Scr->EntryHeight;
/* djhjr - 5/22/00 */
if (y_offset + Scr->EntryHeight > mr->height) break;
/* some servers want the previous entry redrawn - djhjr - 10/24/00 */
if (Scr->MenuBevelWidth > 0) y_offset += Scr->EntryHeight;
/*
* Be smart about handling the expose, redraw only the entries
* that we need to.
*/
/* those servers want the next entry redrawn, too - djhjr - 10/24/00 */
if (e->xexpose.y < (y_offset + Scr->EntryHeight) &&
(e->xexpose.y + e->xexpose.height) > y_offset - ((mr->shadow) ? Scr->EntryHeight : 0))
{
PaintEntry(mr, mi, True);
}
}
XSync(dpy, 0);
}
static Bool fromMenu;
extern int GlobalFirstTime; /* for StayUpMenus -- PF */
void UpdateMenu()
{
MenuItem *mi;
int i, x, y, x_root, y_root, entry;
int done;
MenuItem *badItem = NULL;
static int firstTime = True;
fromMenu = TRUE;
while (TRUE)
{ /* block until there is an event */
#ifdef NEVER /* see the '#else' - Steve Ratcliffe */
#if 0
if (!menuFromFrameOrWindowOrTitlebar && ! Scr->StayUpMenus) {
XMaskEvent(dpy,
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | ExposureMask |
VisibilityChangeMask | LeaveWindowMask |
ButtonMotionMask, &Event);
}
if (Event.type == MotionNotify) {
/* discard any extra motion events before a release */
while(XCheckMaskEvent(dpy,
ButtonMotionMask | ButtonReleaseMask, &Event))
if (Event.type == ButtonRelease)
break;
}
#else
while (XCheckMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | ExposureMask, &Event))
{ /* taken from tvtwm */
#endif /* 0 */
#else
/* Submitted by Steve Ratcliffe */
XNextEvent(dpy, &Event);
#endif /* NEVER */
if (!DispatchEvent ()) continue;
if (Event.type == ButtonRelease )
{ if (Scr->StayUpMenus)
{
if (firstTime == True)
{ /* it was the first release of the button */
firstTime = False;
}
else
{ /* thats the second we need to return now */
firstTime = True;
menuFromFrameOrWindowOrTitlebar = FALSE;
fromMenu = FALSE;
return;
}
}
else
{ /* not stay-up */
menuFromFrameOrWindowOrTitlebar = FALSE;
fromMenu = FALSE;
return;
}
}
if (Cancel) return;
#ifdef NEVER /* see the above - Steve Ratcliffe */
}
#endif
/* re-instated - Steve Ratcliffe */
if (Event.type != MotionNotify)
continue;
/* if we haven't received the enter notify yet, wait */
if (!ActiveMenu || !ActiveMenu->entered)
continue;
done = FALSE;
XQueryPointer( dpy, ActiveMenu->w, &JunkRoot, &JunkChild,
&x_root, &y_root, &x, &y, &JunkMask);
/* djhjr - 9/5/98 */
if (!ActiveItem)
if (abs(x_root - MenuOrigX) < Scr->MoveDelta &&
abs(y_root - MenuOrigY) < Scr->MoveDelta)
continue;
#if 0
/* if we haven't recieved the enter notify yet, wait */
if (ActiveMenu && !ActiveMenu->entered)
continue;
#endif
XFindContext(dpy, ActiveMenu->w, ScreenContext, (caddr_t *)&Scr);
JunkWidth = ActiveMenu->width;
JunkHeight = ActiveMenu->height;
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0)
{
x -= Scr->MenuBevelWidth;
y -= Scr->MenuBevelWidth;
JunkWidth -= 2 * Scr->MenuBevelWidth;
JunkHeight -= Scr->MenuBevelWidth;
}
/* djhjr - 5/22/00
if (x < 0 || y < 0 || x >= JunkWidth || y >= JunkHeight)
*/
if ((x < 0 || y < 0 || x >= JunkWidth || y >= JunkHeight) ||
(ActiveMenu->too_tall && (y < Scr->MenuScrollBorderWidth ||
y > JunkHeight - Scr->MenuScrollBorderWidth)))
{
if (ActiveItem && ActiveItem->func != F_TITLE)
{
ActiveItem->state = 0;
PaintEntry(ActiveMenu, ActiveItem, False);
}
ActiveItem = NULL;
/* menu scrolling - djhjr - 5/22/00 */
if (ActiveMenu->too_tall && x >= 0 && x < JunkWidth)
{
short j = ActiveMenu->top;
if (y < Scr->MenuScrollBorderWidth)
{
if (ActiveMenu->top - Scr->MenuScrollJump < 0)
continue;
else
j -= Scr->MenuScrollJump;
}
else if (y > JunkHeight - Scr->MenuScrollBorderWidth)
{
int k = JunkHeight / Scr->EntryHeight;
if (ActiveMenu->top + k >= ActiveMenu->items)
continue;
else
j += Scr->MenuScrollJump;
}
if (ActiveMenu->top != j)
{
ActiveMenu->top = j;
XClearArea(dpy, ActiveMenu->w, 0, 0, 0, 0, True);
}
}
continue;
}
/* look for the entry that the mouse is in */
/* djhjr - 5/22/00
entry = y / Scr->EntryHeight;
*/
entry = (y / Scr->EntryHeight) + ActiveMenu->top;
for (i = 0, mi = ActiveMenu->first; mi != NULL; i++, mi=mi->next)
{
if (i == entry)
break;
}
/* if there is an active item, we might have to turn it off */
if (ActiveItem)
{
/* is the active item the one we are on ? */
if (ActiveItem->item_num == entry && ActiveItem->state)
done = TRUE;
/* if we weren't on the active entry, let's turn the old
* active one off
*/
if (!done && ActiveItem->func != F_TITLE)
{
ActiveItem->state = 0;
PaintEntry(ActiveMenu, ActiveItem, False);
}
}
/* djhjr - 5/22/00 */
if (ActiveMenu->too_tall && y + Scr->EntryHeight > JunkHeight)
continue;
/* if we weren't on the active item, change the active item and turn
* it on
*/
if (!done)
{
ActiveItem = mi;
/* djhjr - 5/20/98
if (ActiveItem->func != F_TITLE && !ActiveItem->state)
*/
if (ActiveItem && ActiveItem->func != F_TITLE && !ActiveItem->state)
{
ActiveItem->state = 1;
PaintEntry(ActiveMenu, ActiveItem, False);
if (Scr->StayUpOptionalMenus) /* PF */
GlobalFirstTime = firstTime = False; /* PF */
}
}
/* now check to see if we were over the arrow of a pull right entry */
/* djhjr - 5/20/98
if (ActiveItem->func == F_MENU &&
*/
if (ActiveItem && ActiveItem->func == F_MENU &&
/* ((ActiveMenu->width - x) < (ActiveMenu->width >> 1))) */
( x > PULLDOWNMENU_OFFSET )) /* DSE */
{
MenuRoot *save = ActiveMenu;
int savex = MenuOrigins[MenuDepth - 1].x;
int savey = MenuOrigins[MenuDepth - 1].y;
if (MenuDepth < MAXMENUDEPTH) {
PopUpMenu (ActiveItem->sub,
(savex + PULLDOWNMENU_OFFSET), /* DSE */
(savey + ActiveItem->item_num * Scr->EntryHeight)
/*(savey + ActiveItem->item_num * Scr->EntryHeight +
(Scr->EntryHeight >> 1))*/, False);
} else if (!badItem) {
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
badItem = ActiveItem;
}
/* if the menu did get popped up, unhighlight the active item */
if (save != ActiveMenu && ActiveItem->state)
{
ActiveItem->state = 0;
PaintEntry(save, ActiveItem, False);
ActiveItem = NULL;
}
}
if (badItem != ActiveItem) badItem = NULL;
XFlush(dpy);
}
}
/***********************************************************************
*
* 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;
#define UNUSED_PIXEL ((unsigned long) (~0)) /* more than 24 bits */
tmp = (MenuRoot *) malloc(sizeof(MenuRoot));
/* djhjr - 5/22/96
tmp->hi_fore = UNUSED_PIXEL;
tmp->hi_back = UNUSED_PIXEL;
*/
tmp->highlight.fore = UNUSED_PIXEL;
tmp->highlight.back = UNUSED_PIXEL;
tmp->name = name;
tmp->prev = NULL;
tmp->first = NULL;
tmp->last = NULL;
tmp->items = 0;
tmp->width = 0;
tmp->mapped = NEVER_MAPPED;
tmp->pull = FALSE;
tmp->w = None;
tmp->shadow = None;
tmp->real_menu = FALSE;
/* djhjr - 5/22/00 */
tmp->too_tall = 0;
tmp->top = 0;
if (Scr->MenuList == NULL)
{
Scr->MenuList = tmp;
Scr->MenuList->next = NULL;
}
if (Scr->LastMenu == NULL)
{
Scr->LastMenu = tmp;
Scr->LastMenu->next = NULL;
}
else
{
Scr->LastMenu->next = tmp;
Scr->LastMenu = tmp;
Scr->LastMenu->next = NULL;
}
/* djhjr - 5/4/98
if (strcmp(name, TWM_WINDOWS) == 0)
*/
if (strcmp(name, TWM_WINDOWS) == 0 || strcmp(name, VTWM_WINDOWS) == 0)
Scr->Windows = tmp;
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
* fore - foreground color string
* back - background color string
*
***********************************************************************
*/
MenuItem *
AddToMenu(menu, item, action, sub, func, fore, back)
MenuRoot *menu;
char *item, *action;
MenuRoot *sub;
int func;
char *fore, *back;
{
MenuItem *tmp;
int width;
MyFont *font; /* DSE */
#ifdef DEBUG_MENUS
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->strlen = strlen(item);
tmp->action = action;
tmp->next = NULL;
tmp->sub = NULL;
tmp->state = 0;
tmp->func = func;
/* djhjr - 4/22/96 */
tmp->separated = 0;
if ( func == F_TITLE && (Scr->MenuTitleFont.name != NULL) ) /* DSE */
font= &(Scr->MenuTitleFont);
else
font= &(Scr->MenuFont);
if (!Scr->HaveFonts) CreateFonts();
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
width = MyFont_TextWidth(font,
#else
width = XTextWidth(font->font,
#endif
item, tmp->strlen);
if (width <= 0)
width = 1;
if (width > menu->width)
menu->width = width;
tmp->user_colors = FALSE;
if (Scr->Monochrome == COLOR && fore != NULL)
{
int save;
save = Scr->FirstTime;
Scr->FirstTime = TRUE;
/* djhjr - 4/22/96
GetColor(COLOR, &tmp->fore, fore);
GetColor(COLOR, &tmp->back, back);
*/
GetColor(COLOR, &tmp->normal.fore, fore);
GetColor(COLOR, &tmp->normal.back, back);
/* djhjr - 4/22/96 */
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
/* rem'd 'Scr->MenuBevelWidth' djhjr - 10/30/02 */
if (/*Scr->MenuBevelWidth > 0 && */!Scr->BeNiceToColormap) GetShadeColors (&tmp->normal);
Scr->FirstTime = save;
tmp->user_colors = TRUE;
}
if (sub != NULL)
{
tmp->sub = sub;
menu->pull = TRUE;
}
tmp->item_num = menu->items++;
return (tmp);
}
void MakeMenus()
{
MenuRoot *mr;
for (mr = Scr->MenuList; mr != NULL; mr = mr->next)
{
if (mr->real_menu == FALSE)
continue;
MakeMenu(mr);
}
}
void MakeMenu(mr)
MenuRoot *mr;
{
MenuItem *start, *end, *cur, *tmp;
XColor f1, f2, f3;
XColor b1, b2, b3;
XColor save_fore, save_back;
int num, i;
int fred, fgreen, fblue;
int bred, bgreen, bblue;
int width;
/* djhjr - 4/22/96 */
int borderwidth;
unsigned long valuemask;
XSetWindowAttributes attributes;
Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
MyFont *titleFont;
if ( Scr->MenuTitleFont.name != NULL ) /* DSE */
{
Scr->EntryHeight = MAX(Scr->MenuFont.height,
Scr->MenuTitleFont.height) + 4;
titleFont = &(Scr->MenuTitleFont);
}
else
{
Scr->EntryHeight = Scr->MenuFont.height + 4;
titleFont= &(Scr->MenuFont);
}
/* lets first size the window accordingly */
if (mr->mapped == NEVER_MAPPED)
{
if (mr->pull == TRUE)
{
mr->width += 16 + 2 * EDGE_OFFSET; /* DSE */
}
/* djhjr - 4/29/98
* djhjr - 9/18/96 *
if (Scr->use3Dmenus) mr->width += 4;
*/
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0) mr->width += 2 * Scr->MenuBevelWidth;
width = mr->width + 2 * EDGE_OFFSET; /* DSE */
for (cur = mr->first; cur != NULL; cur = cur->next)
{
if (cur->func != F_TITLE)
cur->x = EDGE_OFFSET; /* DSE */
else
{
cur->x = width -
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_TextWidth(titleFont,
#else
XTextWidth(titleFont->font,
#endif
cur->item, cur->strlen);
cur->x /= 2;
}
}
mr->height = mr->items * Scr->EntryHeight;
/* djhjr - 4/29/98
* djhjr - 4/22/96 *
if (Scr->use3Dmenus) mr->height += 4;
*/
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0) mr->height += 2 * Scr->MenuBevelWidth;
/* djhjr - 4/22/96 */
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
borderwidth = (Scr->MenuBevelWidth > 0) ? 0 : 1;
/* djhjr - 5/22/00 */
if (mr->height > Scr->MyDisplayHeight)
{
mr->too_tall = 1;
mr->height = Scr->MyDisplayHeight - borderwidth * 2;
}
/* added this 'if () ... else' - djhjr - 4/29/98 */
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0)
mr->width += 2 * Scr->MenuBevelWidth + 6;
else
mr->width += 10;
if (Scr->Shadow)
{
/*
* Make sure that you don't draw into the shadow window or else
* the background bits there will get saved
*/
valuemask = (CWBackPixel | CWBorderPixel);
attributes.background_pixel = Scr->MenuShadowColor;
attributes.border_pixel = Scr->MenuShadowColor;
if (Scr->SaveUnder) {
valuemask |= CWSaveUnder;
attributes.save_under = True;
}
mr->shadow = XCreateWindow (dpy, Scr->Root, 0, 0,
(unsigned int) mr->width,
(unsigned int) mr->height,
(unsigned int)0,
CopyFromParent,
(unsigned int) CopyFromParent,
(Visual *) CopyFromParent,
valuemask, &attributes);
}
valuemask = (CWBackPixel | CWBorderPixel | CWEventMask);
attributes.background_pixel = Scr->MenuC.back;
attributes.border_pixel = Scr->MenuC.fore;
attributes.event_mask = (ExposureMask | EnterWindowMask);
if (Scr->SaveUnder) {
valuemask |= CWSaveUnder;
attributes.save_under = True;
}
if (Scr->BackingStore) {
valuemask |= CWBackingStore;
attributes.backing_store = Always;
}
mr->w = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) mr->width,
/* djhjr - 4/22/96
(unsigned int) mr->height, (unsigned int) 1,
*/
(unsigned int) mr->height, (unsigned int) borderwidth,
CopyFromParent, (unsigned int) CopyFromParent,
(Visual *) CopyFromParent,
valuemask, &attributes);
XSaveContext(dpy, mr->w, MenuContext, (caddr_t)mr);
XSaveContext(dpy, mr->w, ScreenContext, (caddr_t)Scr);
mr->mapped = UNMAPPED;
}
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0 && (Scr->Monochrome == COLOR) && (mr->highlight.back == UNUSED_PIXEL)) {
XColor xcol;
char colname [32];
short save;
xcol.pixel = Scr->MenuC.back;
XQueryColor (dpy, cmap, &xcol);
sprintf (colname, "#%04x%04x%04x",
5 * (xcol.red / 6), 5 * (xcol.green / 6), 5 * (xcol.blue / 6));
save = Scr->FirstTime;
Scr->FirstTime = True;
GetColor (Scr->Monochrome, &mr->highlight.back, colname);
Scr->FirstTime = save;
}
/* djhjr - 4/22/96 */
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0 && (Scr->Monochrome == COLOR) && (mr->highlight.fore == UNUSED_PIXEL)) {
XColor xcol;
char colname [32];
short save;
xcol.pixel = Scr->MenuC.fore;
XQueryColor (dpy, cmap, &xcol);
sprintf (colname, "#%04x%04x%04x",
5 * (xcol.red / 6), 5 * (xcol.green / 6), 5 * (xcol.blue / 6));
save = Scr->FirstTime;
Scr->FirstTime = True;
GetColor (Scr->Monochrome, &mr->highlight.fore, colname);
Scr->FirstTime = save;
}
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0 && !Scr->BeNiceToColormap) GetShadeColors (&mr->highlight);
/* get the default colors into the menus */
for (tmp = mr->first; tmp != NULL; tmp = tmp->next)
{
/* djhjr - 4/22/96
if (!tmp->user_colors) {
if (tmp->func != F_TITLE) {
tmp->fore = Scr->MenuC.fore;
tmp->back = Scr->MenuC.back;
} else {
tmp->fore = Scr->MenuTitleC.fore;
tmp->back = Scr->MenuTitleC.back;
}
}
if (mr->hi_fore != UNUSED_PIXEL)
{
tmp->hi_fore = mr->hi_fore;
tmp->hi_back = mr->hi_back;
}
else
{
tmp->hi_fore = tmp->back;
tmp->hi_back = tmp->fore;
}
*/
if (!tmp->user_colors) {
if (tmp->func != F_TITLE) {
tmp->normal.fore = Scr->MenuC.fore;
tmp->normal.back = Scr->MenuC.back;
} else {
tmp->normal.fore = Scr->MenuTitleC.fore;
tmp->normal.back = Scr->MenuTitleC.back;
}
}
if (mr->highlight.fore != UNUSED_PIXEL)
{
tmp->highlight.fore = mr->highlight.fore;
tmp->highlight.back = mr->highlight.back;
}
else
{
tmp->highlight.fore = tmp->normal.back;
tmp->highlight.back = tmp->normal.fore;
}
/* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */
if (Scr->MenuBevelWidth > 0 && !Scr->BeNiceToColormap) {
if (tmp->func != F_TITLE)
GetShadeColors (&tmp->highlight);
else
GetShadeColors (&tmp->normal);
}
} /* end for(...) */
if (Scr->Monochrome == MONOCHROME || !Scr->InterpolateMenuColors)
return;
start = mr->first;
while (TRUE)
{
for (; start != NULL; start = start->next)
{
if (start->user_colors)
break;
}
if (start == NULL)
break;
for (end = start->next; end != NULL; end = end->next)
{
if (end->user_colors)
break;
}
if (end == NULL)
break;
/* we have a start and end to interpolate between */
num = end->item_num - start->item_num;
/* djhjr - 4/22/96
f1.pixel = start->fore;
XQueryColor(dpy, cmap, &f1);
f2.pixel = end->fore;
XQueryColor(dpy, cmap, &f2);
b1.pixel = start->back;
XQueryColor(dpy, cmap, &b1);
b2.pixel = end->back;
XQueryColor(dpy, cmap, &b2);
*/
f1.pixel = start->normal.fore;
XQueryColor(dpy, cmap, &f1);
f2.pixel = end->normal.fore;
XQueryColor(dpy, cmap, &f2);
b1.pixel = start->normal.back;
XQueryColor(dpy, cmap, &b1);
b2.pixel = end->normal.back;
XQueryColor(dpy, cmap, &b2);
fred = ((int)f2.red - (int)f1.red) / num;
fgreen = ((int)f2.green - (int)f1.green) / num;
fblue = ((int)f2.blue - (int)f1.blue) / num;
bred = ((int)b2.red - (int)b1.red) / num;
bgreen = ((int)b2.green - (int)b1.green) / num;
bblue = ((int)b2.blue - (int)b1.blue) / num;
f3 = f1;
f3.flags = DoRed | DoGreen | DoBlue;
b3 = b1;
b3.flags = DoRed | DoGreen | DoBlue;
/* djhjr - 4/23/96 */
start->highlight.back = start->normal.fore;
start->highlight.fore = start->normal.back;
num -= 1;
for (i = 0, cur = start->next; i < num; i++, cur = cur->next)
{
f3.red += fred;
f3.green += fgreen;
f3.blue += fblue;
save_fore = f3;
b3.red += bred;
b3.green += bgreen;
b3.blue += bblue;
save_back = b3;
if (Scr->DontInterpolateTitles && (cur->func == F_TITLE))
continue; /* DSE -- from tvtwm */
XAllocColor(dpy, cmap, &f3);
XAllocColor(dpy, cmap, &b3);
/* djhjr - 4/22/96
cur->hi_back = cur->fore = f3.pixel;
cur->hi_fore = cur->back = b3.pixel;
*/
cur->highlight.back = cur->normal.fore = f3.pixel;
cur->highlight.fore = cur->normal.back = b3.pixel;
cur->user_colors = True;
f3 = save_fore;
b3 = save_back;
}
start = end;
/* djhjr - 4/22/96
start->highlight.back = start->normal.fore;
start->highlight.fore = start->normal.back;
*/
}
}
/***********************************************************************
*
* Procedure:
* PopUpMenu - pop up a pull down menu
*
* Inputs:
* menu - the root pointer of the menu to pop up
* x, y - location of upper left of menu
* center - whether or not to center horizontally over position
*
***********************************************************************
*/
Bool PopUpMenu (menu, x, y, center)
MenuRoot *menu;
int x, y;
Bool center;
{
int WindowNameOffset, WindowNameCount;
TwmWindow **WindowNames;
TwmWindow *tmp_win2,*tmp_win3;
int mask;
int i;
int (*compar)() =
(Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1);
/* djhjr - 9/5/98 */
int x_root, y_root;
if (!menu) return False;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
if (!PlaySound(F_MENU)) PlaySound(S_MMAP);
#endif
/* djhjr - 5/22/00 */
menu->top = 0;
if (menu->w) XClearArea(dpy, menu->w, 0, 0, 0, 0, True);
InstallRootColormap();
if (menu == Scr->Windows)
{
TwmWindow *tmp_win;
/* this is the twm windows menu, let's go ahead and build it */
DestroyMenu (menu);
menu->first = NULL;
menu->last = NULL;
menu->items = 0;
menu->width = 0;
menu->mapped = NEVER_MAPPED;
/* djhjr - 5/4/98
AddToMenu(menu, "TWM Windows", NULLSTR, (MenuRoot *)NULL, F_TITLE,NULLSTR,NULLSTR);
*/
AddToMenu(menu, "VTWM Windows", NULLSTR, (MenuRoot *)NULL, F_TITLE,NULLSTR,NULLSTR);
WindowNameOffset=(char *)Scr->TwmRoot.next->name -
(char *)Scr->TwmRoot.next;
for(tmp_win = Scr->TwmRoot.next , WindowNameCount=0;
tmp_win != NULL;
tmp_win = tmp_win->next)
WindowNameCount++;
if (WindowNameCount != 0) /* Submitted by Jennifer Elaan */
{
WindowNames =
(TwmWindow **)malloc(sizeof(TwmWindow *)*WindowNameCount);
WindowNames[0] = Scr->TwmRoot.next;
for(tmp_win = Scr->TwmRoot.next->next , WindowNameCount=1;
tmp_win != NULL;
tmp_win = tmp_win->next,WindowNameCount++)
{
/* Submitted by Erik Agsjo <erik.agsjo@aktiedirekt.com> */
if (LookInList(Scr->DontShowInTWMWindows, tmp_win->full_name, &tmp_win->class))
{
WindowNameCount--;
continue;
}
tmp_win2 = tmp_win;
for (i=0;i<WindowNameCount;i++)
{
if ((*compar)(tmp_win2->name,WindowNames[i]->name) < 0)
{
tmp_win3 = tmp_win2;
tmp_win2 = WindowNames[i];
WindowNames[i] = tmp_win3;
}
}
WindowNames[WindowNameCount] = tmp_win2;
}
for (i=0; i<WindowNameCount; i++)
{
AddToMenu(menu, WindowNames[i]->name, (char *)WindowNames[i],
(MenuRoot *)NULL, F_POPUP,NULLSTR,NULLSTR);
if (!Scr->OldFashionedTwmWindowsMenu
&& Scr->Monochrome == COLOR)/*RFBCOLOR*/
{/*RFBCOLOR*/
menu->last->user_colors = TRUE;/*RFBCOLOR*/
/* djhjr - 4/22/96
menu->last->fore =
WindowNames[i]->virtual.fore;*RFBCOLOR*
*/
/* djhjr - 5/4/98
menu->last->normal.fore =
WindowNames[i]->virtual.fore;*RFBCOLOR*
*/
menu->last->normal.fore = Scr->MenuC.fore;
/* djhjr - 4/22/96
menu->last->back =
WindowNames[i]->virtual.back;*RFBCOLOR*
*/
menu->last->normal.back =
WindowNames[i]->virtual.back;
/**********************************************************/
/* */
/* Okay, okay, it's a bit of a kludge. */
/* */
/* On the other hand, it's nice to have the VTWM Windows */
/* menu come up with "the right colors". And the colors */
/* from the panner are not a bad choice... */
/* */
/**********************************************************/
}/*RFBCOLOR*/
}
free(WindowNames);
}
MakeMenu(menu);
}
if (menu->w == None || menu->items == 0) return False;
/* Prevent recursively bringing up menus. */
if (menu->mapped == MAPPED) return False;
/*
* Dynamically set the parent; this allows pull-ups to also be main
* menus, or to be brought up from more than one place.
*/
menu->prev = ActiveMenu;
/*
* Submitted by Steve Ratcliffe
*/
mask = ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | PointerMotionHintMask;
if (Scr->StayUpMenus)
mask |= PointerMotionMask;
XGrabPointer(dpy, Scr->Root, True, mask,
GrabModeAsync, GrabModeAsync,
Scr->Root, Scr->MenuCursor, CurrentTime);
ActiveMenu = menu;
menu->mapped = MAPPED;
menu->entered = FALSE;
if (center) {
x -= (menu->width / 2);
y -= (Scr->EntryHeight / 2); /* sticky menus would be nice here */
}
/*
* clip to screen
*/
/* next line and " - i" to "x = " and "y = " - djhjr - 5/22/00 */
i = (Scr->MenuBevelWidth > 0) ? 0 : 2;
if (x + menu->width > Scr->MyDisplayWidth) {
x = Scr->MyDisplayWidth - menu->width - i;
}
if (x < 0) x = 0;
if (y + menu->height > Scr->MyDisplayHeight) {
y = Scr->MyDisplayHeight - menu->height - i;
}
if (y < 0) y = 0;
MenuOrigins[MenuDepth].x = x;
MenuOrigins[MenuDepth].y = y;
MenuDepth++;
XMoveWindow(dpy, menu->w, x, y);
if (Scr->Shadow) {
XMoveWindow (dpy, menu->shadow, x + SHADOWWIDTH, y + SHADOWWIDTH);
}
if (Scr->Shadow) {
XRaiseWindow (dpy, menu->shadow);
}
XMapRaised(dpy, menu->w);
if (Scr->Shadow) {
XMapWindow (dpy, menu->shadow);
}
XSync(dpy, 0);
/* djhjr - 9/5/98 */
XQueryPointer(dpy, menu->w, &JunkRoot, &JunkChild,
&x_root, &y_root, &JunkX, &JunkY, &JunkMask);
MenuOrigX = x_root;
MenuOrigY = y_root;
return True;
}
/***********************************************************************
*
* Procedure:
* PopDownMenu - unhighlight the current menu selection and
* take down the menus
*
***********************************************************************
*/
void PopDownMenu()
{
MenuRoot *tmp;
if (ActiveMenu == NULL)
return;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
PlaySound(S_MUNMAP);
#endif
if (ActiveItem)
{
ActiveItem->state = 0;
PaintEntry(ActiveMenu, ActiveItem, False);
}
for (tmp = ActiveMenu; tmp != NULL; tmp = tmp->prev)
{
if (Scr->Shadow) {
XUnmapWindow (dpy, tmp->shadow);
}
XUnmapWindow(dpy, tmp->w);
tmp->mapped = UNMAPPED;
UninstallRootColormap();
}
XFlush(dpy);
ActiveMenu = NULL;
ActiveItem = NULL;
MenuDepth = 0;
if (Context == C_WINDOW || Context == C_FRAME || Context == C_TITLE)
{ menuFromFrameOrWindowOrTitlebar = TRUE;
}
}
/***********************************************************************
*
* 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 = Scr->MenuList; tmp != NULL; tmp = tmp->next)
{
if (strcmp(name, tmp->name) == 0)
return (tmp);
}
return NULL;
}
static Bool belongs_to_twm_window (t, w)
register TwmWindow *t;
register Window w;
{
if (!t) return False;
#if 0
StayUpMenus
if (w == t->frame || w == t->title_w || w == t->hilite_w ||
w == t->icon_w || w == t->icon_bm_w) return True;
#endif
if (t && t->titlebuttons) {
register TBWindow *tbw;
register int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
for (tbw = t->titlebuttons; nb > 0; tbw++, nb--) {
if (tbw->window == w) return True;
}
}
return False;
}
/*
* Hack^H^H^H^HWrapper to moves for non-menu contexts.
*
* djhjr - 10/11/01 10/4/02
*/
static void moveFromCenterWrapper(tmp_win)
TwmWindow *tmp_win;
{
if (!tmp_win->opaque_move) XUngrabServer(dpy);
WarpScreenToWindow(tmp_win);
/* now here's a nice little kludge... */
{
int hilite = tmp_win->highlight;
tmp_win->highlight = True;
SetBorder(tmp_win, (hilite) ? True : False);
tmp_win->highlight = hilite;
Scr->Focus = tmp_win;
}
if (!tmp_win->opaque_move) XGrabServer(dpy);
}
/*
* Jason P. Venner jason@tfs.com
* This function is used by F_WARPTO to match the action name
* against window names.
* Re-written to use list.c:MatchName(), allowing VTWM-style wilcards.
* djhjr - 10/27/02
*/
int MatchWinName(action, t)
char *action;
TwmWindow *t;
{
int matched = 0;
#ifndef NO_REGEX_SUPPORT
regex_t re;
#else
char re;
#endif
if (MatchName(t->full_name, action, &re, LTYPE_ANY_STRING))
if (MatchName(t->class.res_name, action, &re, LTYPE_ANY_STRING))
if (MatchName(t->class.res_class, action, &re, LTYPE_ANY_STRING))
matched = 1;
return (matched);
}
/***********************************************************************
*
* Procedure:
* ExecuteFunction - execute a twm root function
*
* Inputs:
* func - the function to execute
* action - the menu action to execute
* w - the window to execute this function on
* tmp_win - the twm window structure
* event - the event that caused the function
* context - the context in which the button was pressed
* pulldown- flag indicating execution from pull down menu
*
* Returns:
* TRUE if should continue with remaining actions else FALSE to abort
*
***********************************************************************
*/
extern int MovedFromKeyPress;
int
ExecuteFunction(func, action, w, tmp_win, eventp, context, pulldown)
int func;
char *action;
Window w;
TwmWindow *tmp_win;
XEvent *eventp;
int context;
int pulldown;
{
char tmp[200];
char *ptr;
char buff[MAX_FILE_SIZE];
int count, fd;
int do_next_action = TRUE;
actionHack = action; /* Submitted by Michel Eyckmans */
RootFunction = F_NOFUNCTION;
if (Cancel)
return TRUE; /* XXX should this be FALSE? */
switch (func)
{
case F_UPICONMGR:
case F_LEFTICONMGR:
case F_RIGHTICONMGR:
case F_DOWNICONMGR:
case F_FORWICONMGR:
case F_BACKICONMGR:
case F_NEXTICONMGR:
case F_PREVICONMGR:
case F_NOP:
case F_TITLE:
case F_DELTASTOP:
case F_RAISELOWER:
case F_WARP: /* PF */
case F_WARPCLASSNEXT: /* PF */
case F_WARPCLASSPREV: /* PF */
case F_WARPTOSCREEN:
case F_WARPTO:
case F_WARPRING:
case F_WARPTOICONMGR:
case F_COLORMAP:
/* djhjr - 4/30/96 */
case F_SEPARATOR:
/* djhjr - 12/14/98 */
case F_STATICICONPOSITIONS:
/* djhjr - 5/30/00 */
case F_WARPSNUG:
case F_WARPVISIBLE:
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
case F_SOUNDS:
#endif
/* djhjr - 10/2/01 */
case F_STRICTICONMGR:
/* djhjr - 9/9/02 */
case F_BINDBUTTONS:
case F_BINDKEYS:
case F_UNBINDBUTTONS:
case F_UNBINDKEYS:
break;
default:
XGrabPointer(dpy, Scr->Root, True,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
Scr->Root, Scr->WaitCursor, CurrentTime);
break;
}
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
switch (func)
{
case F_BEEP:
case F_SQUEEZECENTER:
case F_SQUEEZELEFT:
case F_SQUEEZERIGHT:
/* djhjr - 11/4/03 */
case F_MOVESCREEN:
case F_FORCEMOVE:
case F_MOVE:
case F_RESIZE:
case F_EXEC:
case F_DELETE:
case F_DELETEDOOR:
case F_DESTROY:
case F_DEICONIFY:
case F_ICONIFY:
case F_IDENTIFY:
case F_VERSION:
case F_QUIT:
case F_WARP:
case F_WARPCLASSNEXT:
case F_WARPCLASSPREV:
case F_WARPRING:
case F_WARPTO:
case F_WARPTOICONMGR:
case F_WARPTONEWEST:
case F_WARPTOSCREEN:
/* handle uniquely */
break;
case F_POPUP:
/* ignore */
break;
case F_LOWER:
case F_RAISE:
case F_RAISELOWER:
case F_NAIL:
case F_NAMEDOOR:
case F_BOTTOMZOOM:
case F_FULLZOOM:
case F_HORIZOOM:
case F_LEFTZOOM:
case F_RIGHTZOOM:
case F_TOPZOOM:
case F_ZOOM:
case F_BACKICONMGR:
case F_DOWNICONMGR:
case F_FORWICONMGR:
case F_LEFTICONMGR:
case F_RIGHTICONMGR:
case F_UPICONMGR:
case F_FOCUS:
case F_SAVEYOURSELF:
case F_STICKYABOVE:
case F_RING:
case F_WINREFRESH:
/* djhjr - 9/9/02 */
case F_BINDBUTTONS:
case F_BINDKEYS:
case F_UNBINDBUTTONS:
case F_UNBINDKEYS:
/* ignore if from a root menu */
if (Context != C_ROOT && Context != C_NO_CONTEXT)
PlaySound(func);
break;
default:
/* unconditional */
PlaySound(func);
break;
}
#endif
switch (func)
{
case F_NOP:
case F_TITLE:
break;
case F_DELTASTOP:
if (WindowMoved) do_next_action = FALSE;
break;
case F_RESTART:
/* added this 'case' and 'if () ... else ' - djhjr - 7/15/98 */
case F_STARTWM:
if (func == F_STARTWM)
{
/* dynamic allocation of (char **)my_argv - djhjr - 9/26/02 */
char *p, *delims = " \t";
char *new_argv = NULL, **my_argv = NULL;
int i = 0, j = 0;
p = strtok(action, delims);
while (p)
{
if (j >= i)
{
i += 5;
new_argv = (char *)realloc((char *)my_argv,
i * sizeof(char *));
if (new_argv == NULL)
{
fprintf(stderr,
"%s: unable to allocate %d bytes for execvp()\n",
ProgramName, i * sizeof(char *));
break;
}
else
my_argv = (char **)new_argv;
}
my_argv[j++] = strdup(p);
p = strtok(NULL, delims);
}
if (new_argv != NULL)
{
my_argv[j] = NULL;
/* djhjr - 7/31/98 */
setup_restart(eventp->xbutton.time);
execvp(*my_argv, my_argv);
fprintf(stderr, "%s: unable to start \"%s\"\n",
ProgramName, *my_argv);
new_argv = NULL;
}
if (new_argv == NULL)
{
i = 0;
while (i < j)
free(my_argv[i++]);
if (j)
free((char *)my_argv);
}
}
else
/* djhjr - 7/31/98 */
RestartVtwm(eventp->xbutton.time);
break;
case F_UPICONMGR:
case F_DOWNICONMGR:
case F_LEFTICONMGR:
case F_RIGHTICONMGR:
case F_FORWICONMGR:
case F_BACKICONMGR:
MoveIconManager(func);
break;
case F_NEXTICONMGR:
case F_PREVICONMGR:
JumpIconManager(func);
break;
case F_SHOWLIST:
/* added this 'if (...) else ...' - djhjr - 9/21/99 */
if (context == C_ROOT)
{
name_list *list;
ShowIconMgr(&Scr->iconmgr);
/*
* New code in list.c necessitates 'next_entry()' and
* 'contents_of_entry()' - djhjr - 10/20/01
*/
for (list = Scr->IconMgrs; list != NULL; list = next_entry(list))
ShowIconMgr((IconMgr *)contents_of_entry(list));
}
else
{
IconMgr *ip;
if ((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->full_name,
&tmp_win->class)) == NULL)
ip = &Scr->iconmgr;
ShowIconMgr(ip);
}
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
break;
case F_HIDELIST:
if (Scr->NoIconManagers)
break;
/* added argument - djhjr - 9/21/99 */
HideIconManager((context == C_ROOT) ? NULL : tmp_win);
break;
case F_SORTICONMGR:
/* djhjr - 6/10/98 */
if (Scr->NoIconManagers || Scr->iconmgr.count == 0)
break;
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
{
int save_sort;
save_sort = Scr->SortIconMgr;
Scr->SortIconMgr = TRUE;
if (context == C_ICONMGR)
SortIconManager((IconMgr *) NULL);
else if (tmp_win->iconmgr)
SortIconManager(tmp_win->iconmgrp);
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
Scr->SortIconMgr = save_sort;
}
break;
case F_IDENTIFY:
if (DeferExecution(context, func, Scr->SelectCursor))
{
return TRUE;
}
Identify(tmp_win);
break;
case F_VERSION:
Identify ((TwmWindow *) NULL);
break;
case F_ZOOMZOOM: /* RFB silly */
/* added args to iconmgrs - djhjr - 10/11/01 */
Zoom( None, NULL, None, NULL );
break;
case F_AUTOPAN:/*RFB F_AUTOPAN*/
{ /* toggle autopan *//*RFB F_AUTOPAN*/
static int saved;/*RFB F_AUTOPAN*/
if ( Scr->AutoPanX )
{ saved = Scr->AutoPanX;/*RFB F_AUTOPAN*/
Scr->AutoPanX = 0;/*RFB F_AUTOPAN*/
} else { /*RFB F_AUTOPAN*/
Scr->AutoPanX = saved;/*RFB F_AUTOPAN*/
/* if restart with no autopan, we'll set the
** variable but we won't pan
*/
RaiseAutoPan(); /* DSE */
}/*RFB F_AUTOPAN*/
break;/*RFB F_AUTOPAN*/
}/*RFB F_AUTOPAN*/
case F_STICKYABOVE: /* DSE */
if (Scr->StickyAbove) {
LowerSticky(); Scr->StickyAbove = FALSE;
/* don't change the order of execution! */
} else {
Scr->StickyAbove = TRUE; RaiseStickyAbove(); RaiseAutoPan();
/* don't change the order of execution! */
}
return TRUE;
/* break; *//* NOT REACHABLE */
case F_AUTORAISE:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
tmp_win->auto_raise = !tmp_win->auto_raise;
if (tmp_win->auto_raise) ++(Scr->NumAutoRaises);
else --(Scr->NumAutoRaises);
break;
case F_BEEP:
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
/* sound has priority over bell */
if (PlaySound(func)) break;
#endif
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
case F_POPUP:
tmp_win = (TwmWindow *)action;
if (Scr->WindowFunction.func != F_NOFUNCTION)
{
ExecuteFunction(Scr->WindowFunction.func,
Scr->WindowFunction.item->action,
w, tmp_win, eventp, C_FRAME, FALSE);
}
else
{
DeIconify(tmp_win);
XRaiseWindow (dpy, tmp_win->frame);
XRaiseWindow (dpy, tmp_win->VirtualDesktopDisplayWindow);
RaiseStickyAbove();
RaiseAutoPan();
}
break;
case F_RESIZE:
{
TwmWindow *focused = NULL; /* djhjr - 5/27/03 */
Bool fromtitlebar = False;
long releaseEvent;
long movementMask;
int resizefromcenter = 0; /* djhjr - 10/2/02 */
/* djhjr - 10/6/02 */
#ifndef NO_SOUND_SUPPORT
int did_playsound = FALSE;
#endif
if (DeferExecution(context, func, Scr->ResizeCursor))
return TRUE;
PopDownMenu();
if (pulldown)
XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0,
eventp->xbutton.x_root,
eventp->xbutton.y_root);
EventHandler[EnterNotify] = HandleUnknown;
EventHandler[LeaveNotify] = HandleUnknown;
/* allow the resizing of doors - djhjr - 2/22/99
if ((w != tmp_win->icon_w) && (context != C_DOOR))
*/
if (context == C_ICON) /* can't resize icons */
{
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
/*
* Resizing from a titlebar menu was handled uniquely long
* before I got here, and I added virtual windows and icon
* managers on 9/15/99 and 10/11/01, leveraging that code.
* It's all been integrated here.
* djhjr - 10/3/02
*/
if (Context & (C_FRAME_BIT | C_WINDOW_BIT | C_TITLE_BIT)
&& menuFromFrameOrWindowOrTitlebar)
{
XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY,
(unsigned int *)&DragWidth,
(unsigned int *)&DragHeight,
&JunkBW, &JunkDepth);
resizefromcenter = 2;
}
else if (Context == C_VIRTUAL_WIN)
{
TwmWindow *twin;
if ((XFindContext(dpy, eventp->xbutton.subwindow,
VirtualContext, (caddr_t *) &twin) == XCNOENT))
{
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
context = C_WINDOW;
tmp_win = twin;
resizefromcenter = 1;
}
else if (Context == C_ICONMGR && tmp_win->list)
{
/* added the second argument - djhjr - 5/28/00 */
if (!warp_if_warpunmapped(tmp_win, F_NOFUNCTION))
{
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
resizefromcenter = 1;
}
if (resizefromcenter)
{
WarpScreenToWindow(tmp_win);
XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0,
tmp_win->frame_x + tmp_win->frame_width / 2,
tmp_win->frame_y + tmp_win->frame_height / 2);
/* grr - djhjr - 5/27/03 */
focused = Scr->Focus;
Scr->Focus = tmp_win;
SetBorder(Scr->Focus, True);
/* save positions so we can tell if it was moved or not */
ResizeOrigX = tmp_win->frame_x + tmp_win->frame_width / 2;
ResizeOrigY = tmp_win->frame_y + tmp_win->frame_height / 2;
}
else
{
/* save position so we can tell if it was moved or not */
ResizeOrigX = eventp->xbutton.x_root;
ResizeOrigY = eventp->xbutton.y_root;
}
/* see if this is being done from the titlebar */
fromtitlebar = belongs_to_twm_window(tmp_win,
eventp->xbutton.window);
if (resizefromcenter == 2)
{
MenuStartResize(tmp_win, origDragX, origDragY,
DragWidth, DragHeight, Context);
releaseEvent = ButtonPress;
movementMask = PointerMotionMask;
}
else
{
StartResize(eventp, tmp_win, fromtitlebar, context);
fromtitlebar = False;
releaseEvent = ButtonRelease;
movementMask = ButtonMotionMask;
}
/* substantially re-worked - djhjr - 5/27/03 */
while (TRUE)
{
/* added exposure event masks - djhjr - 10/11/01 */
XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
ExposureMask | VisibilityChangeMask |
movementMask, &Event);
/*
* See down below, after this loop - djhjr - 5/27/03
*/
#if 0
/* discard crossing events before a release - djhjr - 10/11/01 */
if (Event.xany.type == EnterNotify ||
Event.xany.type == LeaveNotify)
{
/* this can't be the proper place - djhjr - 10/2/02 */
SetBorder(tmp_win, True);
continue;
}
#endif
/*
* Don't discard exposure events before release
* or window borders and/or their titles in the
* virtual desktop won't get redrawn - djhjr
*/
/* discard any extra motion events before a release */
if (Event.type == MotionNotify)
{
/* was 'ButtonMotionMask' - djhjr - 10/11/01 */
while (XCheckMaskEvent(dpy, releaseEvent | movementMask,
&Event))
{
if (Event.type == releaseEvent)
break;
}
}
/*
* See above, before this loop - djhjr - 5/27/03
*/
#if 0
if (fromtitlebar && Event.type == ButtonPress) {
fromtitlebar = False;
continue;
}
#endif
if (Event.type == releaseEvent)
{
if (Cancel)
{
if (tmp_win->opaque_resize)
{
ConstrainSize(tmp_win, &origWidth, &origHeight);
SetupWindow(tmp_win, origx, origy,
origWidth, origHeight, -1);
ResizeTwmWindowContents(tmp_win,
origWidth, origHeight);
}
else
MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
ResizeWindow = None;
resizing_window = 0;
do_next_action = FALSE;
}
else
{
if (resizefromcenter == 2)
{
/* added passing of 'Context' - djhjr - 9/30/02 */
MenuEndResize(tmp_win, Context);
}
else
EndResize();
/* DispatchEvent2() is depreciated - djhjr - 10/6/02 */
DispatchEvent();
/* djhjr - 5/27/03 11/2/03 */
if (!Scr->NoRaiseResize && !Scr->RaiseOnStart &&
WindowMoved)
{
XRaiseWindow(dpy, tmp_win->frame);
SetRaiseWindow(tmp_win);
}
}
break;
}
/* DispatchEvent2() is depreciated - djhjr - 10/6/02 */
if (!DispatchEvent()) continue;
if (Event.type != MotionNotify) continue;
XQueryPointer(dpy, Scr->Root,
&JunkRoot, &JunkChild, &JunkX, &JunkY,
&AddingX, &AddingY, &JunkMask);
if (!resizing_window &&
(abs(AddingX - ResizeOrigX) < Scr->MoveDelta &&
abs(AddingY - ResizeOrigY) < Scr->MoveDelta))
{
continue;
}
resizing_window = 1;
WindowMoved = TRUE;
/* djhjr - 5/27/03 11/3/03 */
if ((!Scr->NoRaiseResize && Scr->RaiseOnStart)
/* trap a Shape extention bug - djhjr - 5/27/03 */
|| (tmp_win->opaque_resize &&
(HasShape &&
(tmp_win->wShaped || tmp_win->squeeze_info)))
)
{
XRaiseWindow(dpy, tmp_win->frame);
SetRaiseWindow(tmp_win);
if (Scr->Virtual && tmp_win->VirtualDesktopDisplayWindow)
XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
}
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
if (did_playsound == FALSE)
{
PlaySound(func);
did_playsound = TRUE;
}
#endif
/* MenuDoResize() is depreciated - djhjr - 10/6/02 */
DoResize(AddingX, AddingY, tmp_win);
}
/* djhjr - 6/4/98
return TRUE;
*/
/* djhjr - 7/17/98
* djhjr - 4/7/98 *
if (!Scr->NoGrabServer) XUngrabServer(dpy);
*/
if (!tmp_win->opaque_resize) XUngrabServer(dpy);
/*
* All this stuff from resize.c:EndResize() - djhjr - 10/6/02
*/
if (!tmp_win->opaque_resize)
UninstallRootColormap();
/* discard queued enter and leave events - djhjr - 5/27/03 */
while (XCheckMaskEvent(dpy, EnterWindowMask | LeaveWindowMask,
&Event))
;
if (!Scr->NoRaiseResize)
{
RaiseStickyAbove (); /* DSE */
RaiseAutoPan();
}
/* update virtual coords */
tmp_win->virtual_frame_x = Scr->VirtualDesktopX + tmp_win->frame_x;
tmp_win->virtual_frame_y = Scr->VirtualDesktopY + tmp_win->frame_y;
/* UpdateDesktop(tmp_win); Stig */
/* djhjr - 5/27/03
MoveResizeDesktop(tmp_win, Scr->NoRaiseResize); * Stig *
*/
MoveResizeDesktop(tmp_win, Cancel | Scr->NoRaiseResize); /* Stig */
/* djhjr - 9/30/02 10/6/02 */
if (Context == C_VIRTUAL_WIN)
{
/*
* Mask a bug that calls MoveOutline(zeros) after the
* border has been repainted, leaving artifacts. I think
* I know what the bug is, but I can't seem to fix it.
*/
if (Scr->BorderBevelWidth > 0) PaintBorders(tmp_win, False);
JunkX = tmp_win->virtual_frame_x + tmp_win->frame_width / 2;
JunkY = tmp_win->virtual_frame_y + tmp_win->frame_height / 2;
XWarpPointer(dpy, None, Scr->VirtualDesktopDisplayOuter,
0, 0, 0, 0, SCALE_D(JunkX), SCALE_D(JunkY));
/* grr - djhjr - 5/27/03 */
SetBorder(Scr->Focus, False);
Scr->Focus = focused;
}
/* djhjr - 6/4/98 */
/* don't re-map if the window is the virtual desktop - djhjr - 2/28/99 */
if (Scr->VirtualReceivesMotionEvents &&
/* !tmp_win->opaque_resize && */
tmp_win->w != Scr->VirtualDesktopDisplayOuter)
{
XUnmapWindow(dpy, Scr->VirtualDesktopDisplay);
XMapWindow(dpy, Scr->VirtualDesktopDisplay);
}
break;
}
case F_ZOOM:
case F_HORIZOOM:
case F_FULLZOOM:
case F_LEFTZOOM:
case F_RIGHTZOOM:
case F_TOPZOOM:
case F_BOTTOMZOOM:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
/* djhjr - 4/1/00 */
PopDownMenu();
fullzoom(tmp_win, func);
/* UpdateDesktop(tmp_win); Stig */
MoveResizeDesktop(tmp_win, Scr->NoRaiseMove); /* Stig */
break;
case F_MOVE:
case F_FORCEMOVE:
{
static Time last_time = 0;
Window rootw;
Bool fromtitlebar = False;
int moving_icon = FALSE;
int constMoveDir, constMoveX, constMoveY;
int constMoveXL, constMoveXR, constMoveYT, constMoveYB;
int origX, origY;
long releaseEvent;
long movementMask;
int xl, yt, xr, yb;
int movefromcenter = 0; /* djhjr - 10/4/02 */
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
int did_playsound = FALSE;
#endif
if (DeferExecution(context, func, Scr->MoveCursor))
return TRUE;
PopDownMenu();
rootw = eventp->xbutton.root;
if (pulldown)
XWarpPointer(dpy, None, Scr->Root,
0, 0, 0, 0, eventp->xbutton.x_root,
eventp->xbutton.y_root);
EventHandler[EnterNotify] = HandleUnknown;
EventHandler[LeaveNotify] = HandleUnknown;
/* djhjr - 4/7/98
if (!Scr->NoGrabServer || !Scr->OpaqueMove) XGrabServer(dpy);
*/
/* djhjr - 7/17/98
if (!Scr->NoGrabServer) XGrabServer(dpy);
*/
if (!tmp_win->opaque_move) XGrabServer(dpy);
/* use initialized size... djhjr - 5/9/96
* djhjr - 4/27/96 *
Scr->SizeStringOffset = SIZE_HINDENT;
XResizeWindow(dpy, Scr->SizeWindow,
Scr->SizeStringWidth + SIZE_HINDENT * 2,
Scr->SizeFont.height + SIZE_VINDENT * 2);
*/
XGrabPointer(dpy, eventp->xbutton.root, True,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | PointerMotionMask,
/* PointerMotionHintMask */
GrabModeAsync, GrabModeAsync,
Scr->Root, Scr->MoveCursor, CurrentTime);
/* added this 'if (...) else' - djhjr - 10/11/01 */
if (context == C_VIRTUAL_WIN)
{
TwmWindow *twin;
if ((XFindContext(dpy, eventp->xbutton.subwindow,
VirtualContext, (caddr_t *) &twin) == XCNOENT))
{
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
tmp_win = twin;
moveFromCenterWrapper(tmp_win);
/* these two - djhjr - 10/4/02 */
w = tmp_win->frame;
movefromcenter = 1;
}
else
/* added this 'if (...) else' - djhjr - 9/15/99 */
if (context == C_ICONMGR && tmp_win->list)
{
/* added the second argument - djhjr - 5/28/00 */
if (!warp_if_warpunmapped(tmp_win, F_NOFUNCTION))
{
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
moveFromCenterWrapper(tmp_win); /* djhjr - 10/11/01 */
/* these two - djhjr - 10/4/02 */
w = tmp_win->frame;
movefromcenter = 1;
}
else
if (context == C_ICON && tmp_win->icon_w)
{
DragX = eventp->xbutton.x;
DragY = eventp->xbutton.y;
w = tmp_win->icon_w;
moving_icon = TRUE;
}
else if (w != tmp_win->icon_w)
{
XTranslateCoordinates(dpy, w, tmp_win->frame,
eventp->xbutton.x,
eventp->xbutton.y,
&DragX, &DragY, &JunkChild);
w = tmp_win->frame;
}
XMapRaised (dpy, Scr->SizeWindow);
DragWindow = None;
MoveFunction = func; /* set for DispatchEvent() */
XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY,
(unsigned int *)&DragWidth,
(unsigned int *)&DragHeight,
&JunkBW, &JunkDepth);
/* added this 'if (...) else' - djhjr - 10/4/02 */
if (menuFromFrameOrWindowOrTitlebar ||
movefromcenter || (moving_icon && fromMenu))
{
origX = DragX = origDragX + DragWidth / 2;
origY = DragY = origDragY + DragHeight / 2;
}
else
{
origX = eventp->xbutton.x_root;
origY = eventp->xbutton.y_root;
}
CurrentDragX = origDragX;
CurrentDragY = origDragY;
/*
* Only do the constrained move if timer is set -
* need to check it in case of stupid or wicked fast servers.
*/
if ( ConstrainedMoveTime &&
eventp->xbutton.time - last_time < ConstrainedMoveTime)
{
int width, height;
ConstMove = TRUE;
constMoveDir = MOVE_NONE;
constMoveX = eventp->xbutton.x_root - DragX - JunkBW;
constMoveY = eventp->xbutton.y_root - DragY - JunkBW;
width = DragWidth + 2 * JunkBW;
height = DragHeight + 2 * JunkBW;
constMoveXL = constMoveX + width/3;
constMoveXR = constMoveX + 2*(width/3);
constMoveYT = constMoveY + height/3;
constMoveYB = constMoveY + 2*(height/3);
XWarpPointer(dpy, None, w,
0, 0, 0, 0, DragWidth/2, DragHeight/2);
XQueryPointer(dpy, w, &JunkRoot, &JunkChild,
&JunkX, &JunkY, &DragX, &DragY, &JunkMask);
}
last_time = eventp->xbutton.time;
/* djhjr - 4/7/98
if (!Scr->OpaqueMove)
*/
if (!tmp_win->opaque_move)
{
InstallRootColormap();
/*if (!Scr->MoveDelta)*/ /* djhjr - 10/2/02 */
{
/*
* Draw initial outline. This was previously done the
* first time though the outer loop by dropping out of
* the XCheckMaskEvent inner loop down to one of the
* MoveOutline's below.
*/
MoveOutline(rootw,
origDragX - JunkBW, origDragY - JunkBW,
DragWidth + 2 * JunkBW, DragHeight + 2 * JunkBW,
tmp_win->frame_bw,
/* djhjr - 4/22/96
moving_icon ? 0 : tmp_win->title_height);
*/
moving_icon ? 0 : tmp_win->title_height + tmp_win->frame_bw3D);
/*
* This next line causes HandleButtonRelease to call
* XRaiseWindow(). This is solely to preserve the
* previous behaviour that raises a window being moved
* on button release even if you never actually moved
* any distance (unless you move less than MoveDelta or
* NoRaiseMove is set or OpaqueMove is set).
*
* It's set way down below; no need to force it here.
* djhjr - 10/4/02
*
* The code referred to above is 'if 0'd out now anyway.
* djhjr - 10/6/02
*/
/*DragWindow = w;*/
}
}
/*
* see if this is being done from the titlebar
*/
fromtitlebar = belongs_to_twm_window(tmp_win,
eventp->xbutton.window);
/* added 'movefromcenter' and 'moving_icon' - djhjr - 10/4/02 */
if ((menuFromFrameOrWindowOrTitlebar && !fromtitlebar) ||
movefromcenter || (moving_icon && fromMenu))
{
/* warp the pointer to the middle of the window */
XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0,
origDragX + DragWidth / 2,
origDragY + DragHeight / 2);
SetBorder(tmp_win, True); /* grr */
XFlush(dpy);
}
/* djhjr - 4/27/96 */
DisplayPosition(CurrentDragX, CurrentDragY);
if (menuFromFrameOrWindowOrTitlebar)
{
releaseEvent = ButtonPress;
movementMask = PointerMotionMask;
}
else
{
releaseEvent = ButtonRelease;
movementMask = ButtonMotionMask;
}
while (TRUE)
{
/* block until there is an interesting event */
XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
ExposureMask | VisibilityChangeMask |
movementMask, &Event);
/*
* See down below, after this loop - djhjr - 5/23/03
*/
#if 0
/* throw away enter and leave events until release */
if (Event.xany.type == EnterNotify ||
Event.xany.type == LeaveNotify)
{
continue;
}
#endif
/*
* Don't discard exposure events before release
* or window borders and/or their titles in the
* virtual desktop won't get redrawn - djhjr
*/
/* discard any extra motion events before a release */
if (Event.type == MotionNotify)
{
while (XCheckMaskEvent(dpy, movementMask | releaseEvent,
&Event))
{
if (Event.type == releaseEvent)
break;
}
}
/*
* There used to be a couple of routines that handled the
* cancel functionality here, each doing a portion of the
* job, then returning immediately. They became redundant
* to just letting program execution fall through. So now,
* the 'if (Event.type == releaseEvent) if (Cancel)' below
* does just that, clearing a few flags first.
* djhjr - 10/6/02
*/
if (fromtitlebar && Event.type == ButtonPress)
{
fromtitlebar = False;
CurrentDragX = origX = Event.xbutton.x_root;
CurrentDragY = origY = Event.xbutton.y_root;
XTranslateCoordinates(dpy, rootw, tmp_win->frame,
origX, origY,
&DragX, &DragY, &JunkChild);
continue;
}
/* DispatchEvent2() is depreciated - djhjr - 10/6/02 */
if (!DispatchEvent()) continue;
/* re-wrote this stuff - djhjr - 10/4/02 5/24/03 11/2/03 */
if (Event.type == releaseEvent)
{
MoveOutline(rootw, 0, 0, 0, 0, 0, 0);
if (Cancel)
{
DragWindow = None;
ConstMove = WindowMoved = do_next_action = FALSE;
}
else if (WindowMoved)
{
if (moving_icon)
{
tmp_win->icon_moved = TRUE;
XMoveWindow(dpy, tmp_win->icon_w,
CurrentDragX, CurrentDragY);
if (!Scr->NoRaiseMove && !Scr->RaiseOnStart)
{
XRaiseWindow(dpy, tmp_win->icon_w);
SetRaiseWindow(tmp_win->icon_w);
}
}
else
{
if (movefromcenter)
{
tmp_win->frame_x = Event.xbutton.x_root -
DragWidth / 2;
tmp_win->frame_y = Event.xbutton.y_root -
DragHeight / 2;
}
else
{
tmp_win->frame_x = CurrentDragX;
tmp_win->frame_y = CurrentDragY;
}
XMoveWindow(dpy, tmp_win->frame,
tmp_win->frame_x, tmp_win->frame_y);
SendConfigureNotify(tmp_win, tmp_win->frame_x,
tmp_win->frame_y);
if (!Scr->NoRaiseMove && !Scr->RaiseOnStart)
{
XRaiseWindow(dpy, tmp_win->frame);
SetRaiseWindow(tmp_win);
}
}
}
break;
}
/* something left to do only if the pointer moved */
if (Event.type != MotionNotify) continue;
XQueryPointer(dpy, rootw, &(eventp->xmotion.root), &JunkChild,
&(eventp->xmotion.x_root),
&(eventp->xmotion.y_root),
&JunkX, &JunkY, &JunkMask);
if (DragWindow == None &&
abs(eventp->xmotion.x_root - origX) < Scr->MoveDelta &&
abs(eventp->xmotion.y_root - origY) < Scr->MoveDelta)
{
continue;
}
WindowMoved = TRUE;
DragWindow = w;
/* djhjr - 4/7/98
if (!Scr->NoRaiseMove && Scr->OpaqueMove)
*/
/* djhjr - 10/6/02
if (!Scr->NoRaiseMove && tmp_win->opaque_move)
XRaiseWindow(dpy, DragWindow);
*/
/* djhjr - 5/24/03 11/3/03 */
if (!Scr->NoRaiseMove && Scr->RaiseOnStart)
{
if (moving_icon)
{
XRaiseWindow(dpy, tmp_win->icon_w);
SetRaiseWindow(tmp_win->icon_w);
}
else
{
XRaiseWindow(dpy, tmp_win->frame);
SetRaiseWindow(tmp_win);
if (Scr->Virtual &&
tmp_win->VirtualDesktopDisplayWindow)
XRaiseWindow(dpy,
tmp_win->VirtualDesktopDisplayWindow);
}
}
if (ConstMove)
{
switch (constMoveDir)
{
case MOVE_NONE:
if (eventp->xmotion.x_root < constMoveXL ||
eventp->xmotion.x_root > constMoveXR)
{
constMoveDir = MOVE_HORIZ;
}
if (eventp->xmotion.y_root < constMoveYT ||
eventp->xmotion.y_root > constMoveYB)
{
constMoveDir = MOVE_VERT;
}
XQueryPointer(dpy, DragWindow, &JunkRoot,
&JunkChild, &JunkX, &JunkY,
&DragX, &DragY, &JunkMask);
break;
case MOVE_VERT:
constMoveY = eventp->xmotion.y_root - DragY -
JunkBW;
break;
case MOVE_HORIZ:
constMoveX = eventp->xmotion.x_root - DragX -
JunkBW;
break;
}
xl = constMoveX;
yt = constMoveY;
}
else if (DragWindow != None)
{
/* added 'movefromcenter' and 'moving_icon' - djhjr - 10/4/02 */
if (!menuFromFrameOrWindowOrTitlebar &&
!movefromcenter && !(moving_icon && fromMenu))
{
xl = eventp->xmotion.x_root - DragX - JunkBW;
yt = eventp->xmotion.y_root - DragY - JunkBW;
}
else
{
xl = eventp->xmotion.x_root - (DragWidth / 2);
yt = eventp->xmotion.y_root - (DragHeight / 2);
}
}
if ((ConstMove && constMoveDir != MOVE_NONE) ||
DragWindow != None)
{
int width = DragWidth + 2 * JunkBW;
int height = DragHeight + 2 * JunkBW;
if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
{
xr = xl + width;
yb = yt + height;
if (xl < 0) xl = 0;
if (xr > Scr->MyDisplayWidth)
xl = Scr->MyDisplayWidth - width;
if (yt < 0) yt = 0;
if (yb > Scr->MyDisplayHeight)
yt = Scr->MyDisplayHeight - height;
}
CurrentDragX = xl;
CurrentDragY = yt;
/* djhjr - 6/22/01 10/6/02 */
#ifndef NO_SOUND_SUPPORT
if ((!ConstMove || constMoveDir != MOVE_NONE) &&
did_playsound == FALSE)
{
PlaySound(func);
did_playsound = TRUE;
}
#endif
/* djhjr - 4/7/98
if (Scr->OpaqueMove)
*/
if (tmp_win->opaque_move)
XMoveWindow(dpy, DragWindow, xl, yt);
else
MoveOutline(eventp->xmotion.root, xl, yt,
width, height, tmp_win->frame_bw,
/* djhjr - 4/22/96
moving_icon ? 0 : tmp_win->title_height);
*/
moving_icon ? 0 : tmp_win->title_height + tmp_win->frame_bw3D);
/* djhjr - 4/17/98
* move the small representation window
* this knows a bit much about the internals i guess
* XMoveWindow(dpy, tmp_win->VirtualDesktopDisplayWindow, SCALE_D(xl), SCALE_D(yt));
*/
if (Scr->VirtualReceivesMotionEvents)
{
tmp_win->virtual_frame_x = R_TO_V_X(xl);
tmp_win->virtual_frame_y = R_TO_V_Y(yt);
/* djhjr - 5/24/03
MoveResizeDesktop(tmp_win, Scr->NoRaiseMove);
*/
MoveResizeDesktop(tmp_win, TRUE);
}
/* djhjr - 4/27/96 */
DisplayPosition (xl, yt);
}
}
/* djhjr - 7/17/98
* djhjr - 4/7/98 *
if (!Scr->NoGrabServer) XUngrabServer(dpy);
*/
if (!tmp_win->opaque_move) XUngrabServer(dpy);
/* djhjr - 4/27/96 */
XUnmapWindow (dpy, Scr->SizeWindow);
MovedFromKeyPress = False;
if (!tmp_win->opaque_move)
UninstallRootColormap();
/* discard queued enter and leave events - djhjr - 5/23/03 */
while (XCheckMaskEvent(dpy, EnterWindowMask | LeaveWindowMask,
&Event))
;
/* from events.c:HandleButtonRelease() - djhjr - 10/6/02 */
if (!Scr->NoRaiseMove)
{
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
}
/* update virtual coords */
tmp_win->virtual_frame_x = Scr->VirtualDesktopX + tmp_win->frame_x;
tmp_win->virtual_frame_y = Scr->VirtualDesktopY + tmp_win->frame_y;
/* UpdateDesktop() hoses the stacking order - djhjr - 10/6/02 */
/* djhjr - 5/24/03
MoveResizeDesktop(tmp_win, Scr->NoRaiseMove);
*/
MoveResizeDesktop(tmp_win, Cancel | Scr->NoRaiseMove);
/* djhjr - 10/4/02 10/6/02 */
if (Context == C_VIRTUAL_WIN)
{
/*
* Mask a bug that calls MoveOutline(zeros) after the
* border has been repainted, leaving artifacts. I think
* I know what the bug is, but I can't seem to fix it.
*/
if (Scr->BorderBevelWidth > 0) PaintBorders(tmp_win, False);
JunkX = tmp_win->virtual_frame_x + tmp_win->frame_width / 2;
JunkY = tmp_win->virtual_frame_y + tmp_win->frame_height / 2;
XWarpPointer(dpy, None, Scr->VirtualDesktopDisplayOuter,
0, 0, 0, 0, SCALE_D(JunkX), SCALE_D(JunkY));
}
/* djhjr - 6/4/98 */
/* don't re-map if the window is the virtual desktop - djhjr - 2/28/99 */
if (Scr->VirtualReceivesMotionEvents &&
/* !tmp_win->opaque_move && */
tmp_win->w != Scr->VirtualDesktopDisplayOuter)
{
XUnmapWindow(dpy, Scr->VirtualDesktopDisplay);
XMapWindow(dpy, Scr->VirtualDesktopDisplay);
}
MoveFunction = F_NOFUNCTION; /* clear for DispatchEvent() */
/* sanity check (also in events.c:HandleButtonRelease()) - djhjr - 10/6/02 */
DragWindow = None;
ConstMove = FALSE;
break;
}
case F_FUNCTION:
{
MenuRoot *mroot;
MenuItem *mitem;
Cursor cursor;
if ((mroot = FindMenuRoot(action)) == NULL)
{
fprintf (stderr, "%s: couldn't find function \"%s\"\n",
ProgramName, action);
return TRUE;
}
/*
* Changed this 'if ()' for deferred keyboard events (see also events.c)
* Submitted by Michel Eyckmans
*
if (NeedToDefer(mroot) && DeferExecution(context, func, Scr->SelectCursor))
*/
if ((cursor = NeedToDefer(mroot)) != None && DeferExecution(context, func, cursor))
return TRUE;
else
{
for (mitem = mroot->first; mitem != NULL; mitem = mitem->next)
{
if (!ExecuteFunction (mitem->func, mitem->action, w,
tmp_win, eventp, context, pulldown))
break;
}
}
}
break;
case F_DEICONIFY:
case F_ICONIFY:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
/* added '|| (...)' - djhjr - 6/3/03 */
if (tmp_win->icon ||
(func == F_DEICONIFY && tmp_win == tmp_win->list->twm))
{
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(func);
#endif
DeIconify(tmp_win);
/*
* now HERE's a fine bit of kludge! it's to mask a hole in the
* code I can't find that messes up when trying to warp to the
* de-iconified window not in the real screen when WarpWindows
* isn't used. see also the change in DeIconify().
* djhjr - 1/24/98
*/
if (!Scr->WarpWindows && (Scr->WarpCursor ||
LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)))
{
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
WarpToWindow(tmp_win); /* PF */
}
}
else if (func == F_ICONIFY)
{
/* djhjr - 9/10/99 */
TwmDoor *d;
TwmWindow *tmgr = NULL, *twin = NULL;
MenuRoot *mr;
/* sanity check for what's next - djhjr - 9/10/99 */
if (XFindContext(dpy, tmp_win->w, DoorContext,
(caddr_t *)&d) != XCNOENT)
{
twin = tmp_win;
tmp_win = d->twin;
}
/*
* don't iconify if there's no way to get it back - not fool-proof
* djhjr - 9/10/99
*/
if (tmp_win->iconify_by_unmapping)
{
/* iconified by unmapping */
if (tmp_win->list) tmgr = tmp_win->list->iconmgr->twm_win;
if ((tmgr && !tmgr->mapped && tmgr->iconify_by_unmapping) ||
((Scr->IconManagerDontShow ||
LookInList(Scr->IconMgrNoShow, tmp_win->full_name, &tmp_win->class)) &&
LookInList(Scr->IconMgrShow, tmp_win->full_name, &tmp_win->class) == (char *)NULL))
{
/* icon manager not mapped or not shown in one */
if (have_twmwindows == -1)
{
have_twmwindows = 0;
/* better than two calls to FindMenuRoot() */
for (mr = Scr->MenuList; mr != NULL; mr = mr->next)
if (strcmp(mr->name, TWM_WINDOWS) == 0 ||
strcmp(mr->name, VTWM_WINDOWS) == 0)
{
/* djhjr - 9/21/99 */
have_twmwindows = FindMenuOrFuncInBindings(C_ALL_BITS, mr, F_NOFUNCTION);
break;
}
}
/* djhjr - 9/21/99 */
if (have_showdesktop == -1)
have_showdesktop = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWDESKTOP);
if (have_showlist == -1)
have_showlist = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWLIST);
/* djhjr - 9/21/99 */
if (!FindMenuOrFuncInWindows(tmp_win, have_twmwindows, mr, F_NOFUNCTION) ||
LookInList(Scr->DontShowInTWMWindows, tmp_win->full_name, &tmp_win->class))
{
/* no TwmWindows menu or not shown in it */
if (tmp_win->w == Scr->VirtualDesktopDisplayOuter &&
FindMenuOrFuncInWindows(tmp_win, have_showdesktop, NULL, F_SHOWDESKTOP))
;
else if (tmp_win->iconmgr &&
FindMenuOrFuncInWindows(tmp_win, have_showlist, NULL, F_SHOWLIST))
;
else if (tmgr &&
FindMenuOrFuncInWindows(tmgr, have_showlist, NULL, F_SHOWLIST))
;
else
{
/* no f.showdesktop or f.showiconmgr */
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
if (twin) tmp_win = twin;
break;
}
}
}
}
if (twin) tmp_win = twin;
if (tmp_win->list || !Scr->NoIconifyIconManagers) /* PF */
{
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(func);
#endif
Iconify (tmp_win, eventp->xbutton.x_root - EDGE_OFFSET, /* DSE */
eventp->xbutton.y_root - EDGE_OFFSET); /* DSE */
}
}
break;
case F_RAISELOWER:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (!WindowMoved) {
XWindowChanges xwc;
xwc.stack_mode = Opposite;
if (w != tmp_win->icon_w)
w = tmp_win->frame;
XConfigureWindow (dpy, w, CWStackMode, &xwc);
XConfigureWindow (dpy, tmp_win->VirtualDesktopDisplayWindow, CWStackMode, &xwc);
/* ug */
XLowerWindow(dpy, Scr->VirtualDesktopDScreen);
}
break;
case F_RAISE:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
/* check to make sure raise is not from the WindowFunction */
if (w == tmp_win->icon_w && Context != C_ROOT)
XRaiseWindow(dpy, tmp_win->icon_w);
else
{
XRaiseWindow(dpy, tmp_win->frame);
XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
}
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
break;
case F_LOWER:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (!(Scr->StickyAbove && tmp_win->nailed)) { /* DSE */
if (w == tmp_win->icon_w)
XLowerWindow(dpy, tmp_win->icon_w);
else
{ XLowerWindow(dpy, tmp_win->frame);
XLowerWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
XLowerWindow(dpy, Scr->VirtualDesktopDScreen);
}
} /* DSE */
break;
case F_FOCUS:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (tmp_win->icon == FALSE)
{
if (!Scr->FocusRoot && Scr->Focus == tmp_win)
{
FocusOnRoot();
}
else
{
if (Scr->Focus != NULL) {
SetBorder (Scr->Focus, False);
/* djhjr - 4/25/96
if (Scr->Focus->hilite_w)
XUnmapWindow (dpy, Scr->Focus->hilite_w);
*/
PaintTitleHighlight(Scr->Focus, off);
}
InstallWindowColormaps (0, tmp_win);
/* djhjr - 4/25/96
if (tmp_win->hilite_w) XMapWindow (dpy, tmp_win->hilite_w);
*/
PaintTitleHighlight(tmp_win, on);
SetBorder (tmp_win, True);
SetFocus (tmp_win, eventp->xbutton.time);
Scr->FocusRoot = FALSE;
Scr->Focus = tmp_win;
}
}
break;
case F_DESTROY:
if (DeferExecution(context, func, Scr->DestroyCursor))
return TRUE;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
/* flag for the handler */
if (PlaySound(func)) destroySoundFromFunction = TRUE;
#endif
/* djhjr - 9/10/96 */
if (tmp_win == Scr->VirtualDesktopDisplayTwin)
{
/* added this 'if (...) ...' and 'if (...) else' - djhjr - 9/21/99 */
if (have_showdesktop == -1)
have_showdesktop = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWDESKTOP);
if (FindMenuOrFuncInWindows(tmp_win, have_showdesktop, NULL, F_SHOWDESKTOP))
XUnmapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame);
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
{
TwmDoor *d;
if (XFindContext(dpy, tmp_win->w, DoorContext,
(caddr_t *) &d) != XCNOENT)
{
/* djhjr - 9/10/99
XBell(dpy, 0);
*/
/* for some reason, we don't get the button up event - djhjr - 9/10/99 */
ButtonPressed = -1;
door_delete(tmp_win->w, d);
break;
}
}
if (tmp_win->iconmgr) /* don't send ourself a message */
{
/* added this 'if (...) ...' and 'if (...) else ...' - djhjr - 9/21/99 */
if (have_showlist == -1)
have_showlist = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWLIST);
if (FindMenuOrFuncInWindows(tmp_win, have_showlist, NULL, F_SHOWLIST))
/* added argument - djhjr - 9/21/99 */
HideIconManager(tmp_win);
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
}
else
{
/* djhjr - 4/26/99 */
AppletDown(tmp_win);
XKillClient(dpy, tmp_win->w);
}
break;
case F_DELETE:
if (DeferExecution(context, func, Scr->DestroyCursor))
return TRUE;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
/* flag for the handler */
if (PlaySound(func)) destroySoundFromFunction = TRUE;
#endif
/* djhjr - 9/21/99 */
if (tmp_win == Scr->VirtualDesktopDisplayTwin)
{
if (have_showdesktop == -1)
have_showdesktop = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWDESKTOP);
if (FindMenuOrFuncInWindows(tmp_win, have_showdesktop, NULL, F_SHOWDESKTOP))
XUnmapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame);
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
/* djhjr - 9/10/99 */
{
TwmDoor *d;
if (XFindContext(dpy, tmp_win->w, DoorContext,
(caddr_t *) &d) != XCNOENT)
{
/* for some reason, we don't get the button up event - djhjr - 9/10/99 */
ButtonPressed = -1;
door_delete(tmp_win->w, d);
break;
}
}
if (tmp_win->iconmgr) /* don't send ourself a message */
{
/* added this 'if (...) ...' and 'if (...) else ...' - djhjr - 9/21/99 */
if (have_showlist == -1)
have_showlist = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWLIST);
if (FindMenuOrFuncInWindows(tmp_win, have_showlist, NULL, F_SHOWLIST))
/* added argument - djhjr - 9/21/99 */
HideIconManager(tmp_win);
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
}
else if (tmp_win->protocols & DoesWmDeleteWindow)
{
/* djhjr - 4/26/99 */
AppletDown(tmp_win);
SendDeleteWindowMessage (tmp_win, LastTimestamp());
}
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
case F_SAVEYOURSELF:
if (DeferExecution (context, func, Scr->SelectCursor))
return TRUE;
if (tmp_win->protocols & DoesWmSaveYourself)
SendSaveYourselfMessage (tmp_win, LastTimestamp());
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
case F_CIRCLEUP:
XCirculateSubwindowsUp(dpy, Scr->Root);
break;
case F_CIRCLEDOWN:
XCirculateSubwindowsDown(dpy, Scr->Root);
break;
case F_EXEC:
PopDownMenu();
if (!Scr->NoGrabServer) {
XUngrabServer (dpy);
XSync (dpy, 0);
}
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
/* flag for the handler */
if (PlaySound(func)) createSoundFromFunction = TRUE;
#endif
Execute(action);
break;
case F_UNFOCUS:
FocusOnRoot();
break;
case F_CUT:
strcpy(tmp, action);
strcat(tmp, "\n");
XStoreBytes(dpy, tmp, strlen(tmp));
break;
case F_CUTFILE:
ptr = XFetchBytes(dpy, &count);
if (ptr) {
if (sscanf (ptr, "%s", tmp) == 1) {
XFree (ptr);
ptr = ExpandFilename(tmp);
if (ptr) {
fd = open (ptr, 0);
if (fd >= 0) {
count = read (fd, buff, MAX_FILE_SIZE - 1);
if (count > 0) XStoreBytes (dpy, buff, count);
close(fd);
} else {
fprintf (stderr,
"%s: unable to open cut file \"%s\"\n",
ProgramName, tmp);
}
if (ptr != tmp) free (ptr);
}
} else {
XFree(ptr);
}
} else {
fprintf(stderr, "%s: cut buffer is empty\n", ProgramName);
}
break;
case F_WARPTOSCREEN:
{
if (strcmp (action, WARPSCREEN_NEXT) == 0) {
WarpToScreen (Scr->screen + 1, 1);
} else if (strcmp (action, WARPSCREEN_PREV) == 0) {
WarpToScreen (Scr->screen - 1, -1);
} else if (strcmp (action, WARPSCREEN_BACK) == 0) {
WarpToScreen (PreviousScreen, 0);
} else {
WarpToScreen (atoi (action), 0);
}
}
break;
case F_COLORMAP:
{
if (strcmp (action, COLORMAP_NEXT) == 0) {
BumpWindowColormap (tmp_win, 1);
} else if (strcmp (action, COLORMAP_PREV) == 0) {
BumpWindowColormap (tmp_win, -1);
} else {
BumpWindowColormap (tmp_win, 0);
}
}
break;
case F_WARPCLASSNEXT: /* PF */
case F_WARPCLASSPREV: /* PF */
WarpClass(func == F_WARPCLASSNEXT, tmp_win, action);
break;
case F_WARPTONEWEST: /* PF */
/* added '&& warp_if_warpunmapped()' - djhjr - 5/13/98 */
/* added the second argument - djhjr - 5/28/00 */
if (Scr->Newest && warp_if_warpunmapped(Scr->Newest, F_NOFUNCTION))
{
RaiseStickyAbove();
RaiseAutoPan();
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(func);
#endif
WarpToWindow(Scr->Newest);
}
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
case F_WARPTO:
{
register TwmWindow *t;
/* djhjr - 6/3/03 */
int did_warpto = FALSE;
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
{
/*
* This used to fall through into F_WARP, but the
* warp_if_warpunmapped() meant this loop couldn't
* continue to look for a match in the window list.
* djhjr - 10/27/02
*/
/* jason@tfs.com */
if (MatchWinName(action, t) == 0 &&
warp_if_warpunmapped(t, func))
{
tmp_win = t; /* PF */
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(func);
#endif
did_warpto = TRUE;
WarpToWindow(tmp_win); /* PF */
break;
}
}
/* djhjr - 6/3/03 */
if (!did_warpto)
DoAudible();
}
break;
case F_WARP: /* PF */
{ /* PF */
/* added '&& warp_if_warpunmapped()' - djhjr - 5/13/98 */
/* added the second argument - djhjr - 5/28/00 */
if (tmp_win && warp_if_warpunmapped(tmp_win, F_NOFUNCTION)) /* PF */
{
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(func);
#endif
WarpToWindow(tmp_win); /* PF */
} else {
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
}
} /* PF */
break;
case F_WARPTOICONMGR:
{
TwmWindow *t;
int len;
/* djhjr - 5/13/98
Window raisewin = None, iconwin = None;
*/
/*
* raisewin now points to the window's icon manager entry, and
* iconwin now points to raisewin's icon manager - djhjr - 5/30/00
*
TwmWindow *raisewin = None;
Window iconwin = None;
*/
WList *raisewin = NULL;
TwmWindow *iconwin = None;
len = strlen(action);
if (len == 0) {
if (tmp_win && tmp_win->list) {
/* djhjr - 5/13/98
raisewin = tmp_win->list->iconmgr->twm_win->frame;
*/
/* djhjr - 5/30/00
raisewin = tmp_win->list->iconmgr->twm_win;
iconwin = tmp_win->list->icon;
*/
raisewin = tmp_win->list;
} else if (Scr->iconmgr.active) {
/* djhjr - 5/13/98
raisewin = Scr->iconmgr.twm_win->frame;
*/
/* djhjr - 5/30/00
raisewin = Scr->iconmgr.twm_win;
iconwin = Scr->iconmgr.active->w;
*/
raisewin = Scr->iconmgr.active;
}
} else {
for (t = Scr->TwmRoot.next; t != NULL; t = t->next) {
if (strncmp (action, t->icon_name, len) == 0) {
if (t->list && t->list->iconmgr->twm_win->mapped) {
/* djhjr - 5/13/98
raisewin = t->list->iconmgr->twm_win->frame;
*/
/* djhjr - 5/30/00
raisewin = t->list->iconmgr->twm_win;
iconwin = t->list->icon;
*/
raisewin = t->list;
break;
}
}
}
}
/* djhjr - 6/14/00 */
if (!raisewin)
{
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
/* djhjr - 5/30/00 */
iconwin = raisewin->iconmgr->twm_win;
/* added '&& warp_if_warpunmapped()' - djhjr - 5/13/98 */
/* added the second argument - djhjr - 5/28/00 */
/* was 'raisewin' - djhjr - 5/30/00 */
if (iconwin && warp_if_warpunmapped(iconwin, F_NOFUNCTION)) {
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(func);
#endif
/* djhjr - 5/30/00
XWarpPointer (dpy, None, iconwin, 0, 0, 0, 0,
EDGE_OFFSET, EDGE_OFFSET); * DSE *
*/
WarpInIconMgr(raisewin, iconwin);
} else {
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
}
}
break;
case F_SQUEEZELEFT:/*RFB*/
{
static SqueezeInfo left_squeeze = { J_LEFT, 0, 0 };
/* too much dup'd code - djhjr - 9/17/02 */
if (do_squeezetitle(context, func, tmp_win, &left_squeeze))
return TRUE; /* deferred */
}
break;
case F_SQUEEZERIGHT:/*RFB*/
{
static SqueezeInfo right_squeeze = { J_RIGHT, 0, 0 };
/* too much dup'd code - djhjr - 9/17/02 */
if (do_squeezetitle(context, func, tmp_win, &right_squeeze))
return TRUE; /* deferred */
}
break;
case F_SQUEEZECENTER:/*RFB*/
{
static SqueezeInfo center_squeeze = { J_CENTER, 0, 0 };
/* too much dup'd code - djhjr - 9/17/02 */
if (do_squeezetitle(context, func, tmp_win, ¢er_squeeze))
return TRUE; /* deferred */
}
break;
case F_RING:/*RFB*/
if (DeferExecution (context, func, Scr->SelectCursor))
return TRUE;
if ( tmp_win->ring.next || tmp_win->ring.prev )
RemoveWindowFromRing(tmp_win);
else
AddWindowToRing(tmp_win);
#ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */
tmp_win->ring.cursor_valid = False;
#endif
break;
case F_WARPRING:
switch (action[0]) {
case 'n':
WarpAlongRing (&eventp->xbutton, True);
break;
case 'p':
WarpAlongRing (&eventp->xbutton, False);
break;
default:
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
break;
}
break;
case F_FILE:
action = ExpandFilename(action);
fd = open(action, 0);
if (fd >= 0)
{
count = read(fd, buff, MAX_FILE_SIZE - 1);
if (count > 0)
XStoreBytes(dpy, buff, count);
close(fd);
}
else
{
fprintf (stderr, "%s: unable to open file \"%s\"\n",
ProgramName, action);
}
break;
case F_REFRESH:
{
XSetWindowAttributes attributes;
unsigned long valuemask;
valuemask = (CWBackPixel | CWBackingStore | CWSaveUnder);
attributes.background_pixel = Scr->Black;
attributes.backing_store = NotUseful;
attributes.save_under = False;
w = XCreateWindow (dpy, Scr->Root, 0, 0,
(unsigned int) Scr->MyDisplayWidth,
(unsigned int) Scr->MyDisplayHeight,
(unsigned int) 0,
CopyFromParent, (unsigned int) CopyFromParent,
(Visual *) CopyFromParent, valuemask,
&attributes);
XMapWindow (dpy, w);
XDestroyWindow (dpy, w);
XFlush (dpy);
}
break;
case F_WINREFRESH:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
if (context == C_ICON && tmp_win->icon_w)
w = XCreateSimpleWindow(dpy, tmp_win->icon_w,
0, 0, 9999, 9999, 0, Scr->Black, Scr->Black);
else
w = XCreateSimpleWindow(dpy, tmp_win->frame,
0, 0, 9999, 9999, 0, Scr->Black, Scr->Black);
XMapWindow(dpy, w);
XDestroyWindow(dpy, w);
XFlush(dpy);
break;
case F_NAIL:
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
tmp_win->nailed = !tmp_win->nailed;
/* update the vd display */
/* UpdateDesktop(tmp_win); Stig */
NailDesktop(tmp_win); /* Stig */
#ifdef DEBUG
fprintf(stdout, "%s: nail state of %s is now %s\n",
ProgramName, tmp_win->name, (tmp_win->nailed ? "nailed" : "free"));
#endif /* DEBUG */
RaiseStickyAbove(); /* DSE */
RaiseAutoPan(); /* DSE */
break;
/*
* move a percentage in a particular direction
*/
case F_PANDOWN:
PanRealScreen(0, (atoi(action) * Scr->MyDisplayHeight) / 100
/* DSE */ ,NULL,NULL);
break;
case F_PANLEFT:
PanRealScreen(-((atoi(action) * Scr->MyDisplayWidth) / 100), 0
/* DSE */ ,NULL,NULL);
break;
case F_PANRIGHT:
PanRealScreen((atoi(action) * Scr->MyDisplayWidth) / 100, 0
/* DSE */ ,NULL,NULL);
break;
case F_PANUP:
PanRealScreen(0, -((atoi(action) * Scr->MyDisplayHeight) / 100)
/* DSE */ ,NULL,NULL);
break;
case F_RESETDESKTOP:
SetRealScreen(0, 0);
break;
/*SNUG*/ /* Robert Forsman added these two functions <thoth@ufl.edu> */
/*SNUG*/ {
/*SNUG*/ TwmWindow *scan;
/*SNUG*/ int right, left, up, down;
/*SNUG*/ int inited;
/*SNUG*/ case F_SNUGDESKTOP:
/*SNUG*/
/*SNUG*/ inited = 0;
/*SNUG*/ for (scan = Scr->TwmRoot.next; scan!=NULL; scan = scan->next)
/*SNUG*/ {
/*SNUG*/ if (scan->nailed)
/*SNUG*/ continue;
/*SNUG*/ if (scan->frame_x > Scr->MyDisplayWidth ||
/*SNUG*/ scan->frame_y > Scr->MyDisplayHeight)
/*SNUG*/ continue;
/*SNUG*/ if (scan->frame_x+scan->frame_width < 0 ||
/*SNUG*/ scan->frame_y+scan->frame_height < 0)
/*SNUG*/ continue;
/*SNUG*/ if ( inited==0 || scan->frame_x<right )
/*SNUG*/ right = scan->frame_x;
/*SNUG*/ if ( inited==0 || scan->frame_y<up )
/*SNUG*/ up = scan->frame_y;
/*SNUG*/ if ( inited==0 || scan->frame_x+scan->frame_width>left )
/*SNUG*/ left = scan->frame_x+scan->frame_width;
/*SNUG*/ if ( inited==0 || scan->frame_y+scan->frame_height>down )
/*SNUG*/ down = scan->frame_y+scan->frame_height;
/*SNUG*/ inited = 1;
/*SNUG*/ }
/*SNUG*/ if (inited)
/*SNUG*/ {
/*SNUG*/ int dx,dy;
/*SNUG*/ if (left-right < Scr->MyDisplayWidth && (right<0 || left>Scr->MyDisplayWidth) )
/*SNUG*/ dx = right - ( Scr->MyDisplayWidth - (left-right) ) /2;
/*SNUG*/ else
/*SNUG*/ dx = 0;
/*SNUG*/ if (down-up < Scr->MyDisplayHeight && (up<0 || down>Scr->MyDisplayHeight) )
/*SNUG*/ dy = up - (Scr->MyDisplayHeight - (down-up) ) /2;
/*SNUG*/ else
/*SNUG*/ dy = 0;
/*SNUG*/ if (dx!=0 || dy!=0)
/*SNUG*/ PanRealScreen(dx,dy,NULL,NULL);
/*SNUG*/ /* DSE */
/*SNUG*/ else
/*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
/*SNUG*/ }
/*SNUG*/ else
/*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
/*SNUG*/ break;
/*SNUG*/
/*SNUG*/ case F_SNUGWINDOW:
/*SNUG*/ if (DeferExecution(context, func, Scr->SelectCursor))
/*SNUG*/ return TRUE;
/*SNUG*/
/*SNUG*/ inited = 0;
/*SNUG*/ right = tmp_win->frame_x;
/*SNUG*/ left = tmp_win->frame_x + tmp_win->frame_width;
/*SNUG*/ up = tmp_win->frame_y;
/*SNUG*/ down = tmp_win->frame_y + tmp_win->frame_height;
/*SNUG*/ inited = 1;
/*SNUG*/ if (inited)
/*SNUG*/ {
/*SNUG*/ int dx,dy;
/*SNUG*/ dx = 0;
/*SNUG*/ if (left-right < Scr->MyDisplayWidth)
/*SNUG*/ {
/*SNUG*/ if (right<0)
/*SNUG*/ dx = right;
/*SNUG*/ else if (left>Scr->MyDisplayWidth)
/*SNUG*/ dx = left - Scr->MyDisplayWidth;
/*SNUG*/ }
/*SNUG*/
/*SNUG*/ dy = 0;
/*SNUG*/ if (down-up < Scr->MyDisplayHeight)
/*SNUG*/ {
/*SNUG*/ if (up<0)
/*SNUG*/ dy = up;
/*SNUG*/ else if (down>Scr->MyDisplayHeight)
/*SNUG*/ dy = down - Scr->MyDisplayHeight;
/*SNUG*/ }
/*SNUG*/
/*SNUG*/ if (dx!=0 || dy!=0)
/*SNUG*/ PanRealScreen(dx,dy,NULL,NULL);
/*SNUG*/ /* DSE */
/*SNUG*/ else
/*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
/*SNUG*/ }
/*SNUG*/ else
/*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
/*SNUG*/
/*SNUG*/ break;
/*SNUG*/ }
/* Next four submitted by Seth Robertson - 9/9/02 */
case F_BINDBUTTONS:
{
int i, j;
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
for (i = 0; i < MAX_BUTTONS+1; i++)
for (j = 0; j < MOD_SIZE; j++)
if (Scr->Mouse[i][C_WINDOW][j].func != F_NOFUNCTION)
XGrabButton(dpy, i, j, tmp_win->frame,
True, ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync, None,
Scr->FrameCursor);
break;
}
case F_BINDKEYS:
{
FuncKey *tmp;
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
if (tmp->cont == C_WINDOW)
/* djhjr - 9/10/03
XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True,
GrabModeAsync, GrabModeAsync);
*/
GrabModKeys(tmp_win->w, tmp);
break;
}
case F_UNBINDBUTTONS:
{
int i, j;
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
for (i = 0; i < MAX_BUTTONS+1; i++)
for (j = 0; j < MOD_SIZE; j++)
if (Scr->Mouse[i][C_WINDOW][j].func != F_NOFUNCTION)
XUngrabButton(dpy, i, j, tmp_win->frame);
break;
}
case F_UNBINDKEYS:
{
FuncKey *tmp;
if (DeferExecution(context, func, Scr->SelectCursor))
return TRUE;
for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next)
if (tmp->cont == C_WINDOW)
/* djhjr - 9/10/03
XUngrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w);
*/
UngrabModKeys(tmp_win->w, tmp);
break;
}
case F_MOVESCREEN:
/*
* Breaks badly if not called by the default button press.
*/
{
long releaseEvent = ButtonRelease;
long movementMask = ButtonMotionMask;
#ifndef NO_SOUND_SUPPORT
int did_playsound = FALSE;
#endif
StartMoveWindowInDesktop(eventp->xmotion);
while (TRUE)
{
/* added exposure event masks - djhjr - 10/11/01 */
XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
ExposureMask | VisibilityChangeMask |
movementMask, &Event);
/*
* Don't discard exposure events before release
* or window borders and/or their titles in the
* virtual desktop won't get redrawn - djhjr
*/
/* discard any extra motion events before a release */
if (Event.type == MotionNotify)
{
/* was 'ButtonMotionMask' - djhjr - 10/11/01 */
while (XCheckMaskEvent(dpy, releaseEvent | movementMask,
&Event))
{
if (Event.type == releaseEvent)
break;
}
}
if (Event.type == releaseEvent)
{
EndMoveWindowOnDesktop();
break;
}
if (!DispatchEvent()) continue;
if (Event.type != MotionNotify) continue;
#ifndef NO_SOUND_SUPPORT
if (did_playsound == FALSE)
{
PlaySound(func);
did_playsound = TRUE;
}
#endif
DoMoveWindowOnDesktop(Event.xmotion.x, Event.xmotion.y);
}
/* discard queued enter and leave events */
while (XCheckMaskEvent(dpy, EnterWindowMask | LeaveWindowMask,
&Event))
;
/* will clear the XGrabPointer() in events.c:HandleButtonPress() */
ButtonPressed = -1;
break;
}
case F_SNAP:
SnapRealScreen();
/* and update the data structures */
SetRealScreen(Scr->VirtualDesktopX, Scr->VirtualDesktopY);
break;
case F_SNAPREALSCREEN:
Scr->snapRealScreen = ! Scr->snapRealScreen;
break;
/* djhjr - 12/14/98 */
case F_STATICICONPOSITIONS:
Scr->StaticIconPositions = ! Scr->StaticIconPositions;
break;
/* djhjr - 12/14/98 */
case F_STRICTICONMGR:
{
TwmWindow *t;
Scr->StrictIconManager = ! Scr->StrictIconManager;
if (Scr->StrictIconManager)
{
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
if (!t->icon)
RemoveIconManager(t);
}
else
{
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
if (!t->list)
AddIconManager(t);
}
break;
}
case F_SETREALSCREEN:
{
int newx = Scr->VirtualDesktopX;
int newy = Scr->VirtualDesktopY;
/* parse the geometry */
JunkMask = XParseGeometry (action, &JunkX, &JunkY, &JunkWidth, &JunkHeight);
if (JunkMask & XValue)
newx = JunkX;
if (JunkMask & YValue)
newy = JunkY;
if (newx < 0)
newx = Scr->VirtualDesktopWidth + newx;
if (newy < 0)
newy = Scr->VirtualDesktopHeight + newy;
SetRealScreen(newx, newy);
break;
}
case F_HIDEDESKTOP:
if (Scr->Virtual)
XUnmapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame);
break;
case F_SHOWDESKTOP:
if (Scr->Virtual) {
XMapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame);
/* djhjr - 9/14/96 */
if (Scr->VirtualDesktopDisplayTwin->icon)
DeIconify(Scr->VirtualDesktopDisplayTwin);
}
break;
case F_ENTERDOOR:
{
TwmDoor *d;
if (XFindContext(dpy, tmp_win->w, DoorContext,
(caddr_t *) &d) != XCNOENT)
door_enter(tmp_win->w, d);
break;
}
case F_DELETEDOOR:
{ /*marcel@duteca.et.tudelft.nl*/
TwmDoor *d;
if (DeferExecution(context, func, Scr->DestroyCursor))
return TRUE;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
/* flag for the handler */
if (PlaySound(func)) destroySoundFromFunction = TRUE;
#endif
if (XFindContext(dpy, tmp_win->w, DoorContext,
(caddr_t *) &d) != XCNOENT)
{
/* for some reason, we don't get the button up event - djhjr - 5/13/99 */
ButtonPressed = -1;
door_delete(tmp_win->w, d);
}
break;
}
case F_NEWDOOR:
PopDownMenu();
door_new();
break;
/* djhjr - 4/20/98 */
case F_NAMEDOOR:
{
TwmDoor *d;
if (XFindContext(dpy, tmp_win->w, DoorContext,
(caddr_t *) &d) != XCNOENT)
door_paste_name(tmp_win->w, d);
break;
}
case F_QUIT:
/* djhjr - 9/14/96 - it's in Done()...
SetRealScreen(0,0);
*/
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
if (PlaySound(func))
{
/* allow time to emit */
if (Scr->PauseOnQuit) sleep(Scr->PauseOnQuit);
}
else
PlaySoundDone();
#endif
Done();
break;
case F_VIRTUALGEOMETRIES:
Scr->GeometriesAreVirtual = ! Scr->GeometriesAreVirtual;
break;
/* submitted by Ugen Antsilevitch - 5/28/00 */
case F_WARPVISIBLE:
Scr->WarpVisible = ! Scr->WarpVisible;
break;
/* djhjr - 5/30/00 */
case F_WARPSNUG:
Scr->WarpSnug = ! Scr->WarpSnug;
break;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
case F_SOUNDS:
ToggleSounds();
break;
/* djhjr - 11/15/02 */
case F_PLAYSOUND:
PlaySoundAdhoc(action);
break;
#endif
}
if (ButtonPressed == -1) XUngrabPointer(dpy, CurrentTime);
return do_next_action;
}
/***********************************************************************
*
* Procedure:
* DeferExecution - defer the execution of a function to the
* next button press if the context is C_ROOT
*
* Inputs:
* context - the context in which the mouse button was pressed
* func - the function to defer
* cursor - the cursor to display while waiting
*
***********************************************************************
*/
int
DeferExecution(context, func, cursor)
int context, func;
Cursor cursor;
{
if (context == C_ROOT)
{
LastCursor = cursor;
XGrabPointer(dpy, Scr->Root, True,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
Scr->Root, cursor, CurrentTime);
RootFunction = func;
Action = actionHack; /* Submitted by Michel Eyckmans */
return (TRUE);
}
return (FALSE);
}
/***********************************************************************
*
* Procedure:
* ReGrab - regrab the pointer with the LastCursor;
*
***********************************************************************
*/
void ReGrab()
{
XGrabPointer(dpy, Scr->Root, True,
ButtonPressMask | ButtonReleaseMask,
GrabModeAsync, GrabModeAsync,
Scr->Root, LastCursor, CurrentTime);
}
/***********************************************************************
*
* Procedure:
* NeedToDefer - checks each function in the list to see if it
* is one that needs to be defered.
*
* Inputs:
* root - the menu root to check
*
***********************************************************************
*/
/* was of type 'int' - Submitted by Michel Eyckmans */
Cursor
NeedToDefer(root)
MenuRoot *root;
{
MenuItem *mitem;
for (mitem = root->first; mitem != NULL; mitem = mitem->next)
{
switch (mitem->func)
{
case F_RESIZE:
return Scr->ResizeCursor; /* Submitted by Michel Eyckmans */
case F_MOVE:
case F_FORCEMOVE:
return Scr->MoveCursor; /* Submitted by Michel Eyckmans */
/* these next four - Submitted by Michel Eyckmans */
case F_DELETE:
case F_DELETEDOOR:
case F_DESTROY:
return Scr->DestroyCursor;
case F_IDENTIFY: /* was with 'F_RESIZE' - Submitted by Michel Eyckmans */
case F_DEICONIFY:
case F_ICONIFY:
case F_RAISELOWER:
case F_RAISE:
case F_LOWER:
case F_FOCUS:
case F_WINREFRESH:
case F_ZOOM:
case F_FULLZOOM:
case F_HORIZOOM:
case F_RIGHTZOOM:
case F_LEFTZOOM:
case F_TOPZOOM:
case F_BOTTOMZOOM:
case F_AUTORAISE:
case F_NAIL:
case F_SNUGWINDOW:
return Scr->SelectCursor;
}
}
return None;
}
void
Execute(s)
char *s;
{
static char buf[256];
char *ds = DisplayString (dpy);
char *colon, *dot1;
char oldDisplay[256];
char *doisplay;
int restorevar = 0;
char *append_this = " &";
char *es = (char *)malloc(strlen(s)+strlen(append_this)+1);
sprintf(es,s);
/* a new copy of s, with extra space incase -- DSE */
if (Scr->EnhancedExecResources) /* DSE */
{
/* chop all space characters from the end of the string */
while ( isspace ( es[strlen(es)-1] ) )
{
es[strlen(es)-1] = '\0';
}
switch ( es[strlen(es)-1] ) /* last character */
{
case ';':
es[strlen(es)-1] = '\0'; /* remove the semicolon */
break;
case '&': /* already there so do nothing */
break;
default:
strcat(es,append_this); /* don't block the window manager */
break;
}
}
oldDisplay[0] = '\0';
doisplay=getenv("DISPLAY");
if (doisplay)
strcpy (oldDisplay, doisplay);
/*
* Build a display string using the current screen number, so that
* X programs which get fired up from a menu come up on the screen
* that they were invoked from, unless specifically overridden on
* their command line.
*/
colon = rindex (ds, ':');
if (colon) { /* if host[:]:dpy */
strcpy (buf, "DISPLAY=");
strcat (buf, ds);
colon = buf + 8 + (colon - ds); /* use version in buf */
dot1 = index (colon, '.'); /* first period after colon */
if (!dot1) dot1 = colon + strlen (colon); /* if not there, append */
(void) sprintf (dot1, ".%d", Scr->screen);
putenv (buf);
restorevar = 1;
}
(void) system (es); /* DSE */
free (es); /* DSE */
if (restorevar) { /* why bother? */
(void) sprintf (buf, "DISPLAY=%s", oldDisplay);
putenv (buf);
}
}
/***********************************************************************
*
* Procedure:
* FocusOnRoot - put input focus on the root window
*
***********************************************************************
*/
void
FocusOnRoot()
{
SetFocus ((TwmWindow *) NULL, LastTimestamp());
if (Scr->Focus != NULL)
{
SetBorder (Scr->Focus, False);
/* djhjr - 4/25/96
if (Scr->Focus->hilite_w) XUnmapWindow (dpy, Scr->Focus->hilite_w);
*/
PaintTitleHighlight(Scr->Focus, off);
}
InstallWindowColormaps(0, &Scr->TwmRoot);
Scr->Focus = NULL;
Scr->FocusRoot = TRUE;
}
void DeIconify(tmp_win)
TwmWindow *tmp_win;
{
TwmWindow *t;
/*
* De-iconify the main window first
*/
/* re-vamped the zoom stuff - djhjr - 10/11/01 */
if (Scr->DoZoom && Scr->ZoomCount > 0)
{
IconMgr *ipf = NULL;
Window wt = None, wf = None;
if (tmp_win->icon)
{
if (tmp_win->icon_on)
{
wf = tmp_win->icon_w; wt = tmp_win->frame;
}
else if (tmp_win->list) /* djhjr - 10/11/01 */
{
wf = tmp_win->list->w; wt = tmp_win->frame;
ipf = tmp_win->list->iconmgr;
}
else if (tmp_win->group != None)
{
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
if (tmp_win->group == t->w)
{
if (t->icon_on)
wf = t->icon_w;
else if (t->list) /* djhjr - 10/11/01 */
{
wf = t->list->w;
ipf = t->list->iconmgr;
}
wt = tmp_win->frame;
break;
}
}
}
/* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */
if (Scr->ZoomZoom || (wf != None && wt != None))
Zoom(wf, ipf, wt, NULL); /* RFBZOOM */
}
XMapWindow(dpy, tmp_win->w);
tmp_win->mapped = TRUE;
if (Scr->NoRaiseDeicon)
XMapWindow(dpy, tmp_win->frame);
else
{
XMapRaised(dpy, tmp_win->frame);
XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow);
}
SetMapStateProp(tmp_win, NormalState);
if (tmp_win->icon_w) {
XUnmapWindow(dpy, tmp_win->icon_w);
IconDown (tmp_win);
}
tmp_win->icon = FALSE;
tmp_win->icon_on = FALSE;
if (tmp_win->list)
XUnmapWindow(dpy, tmp_win->list->icon);
/*
* RemoveIconManager() done in events.c:HandleMapNotify()
*/
UpdateDesktop(tmp_win);
/*
* Now de-iconify transients
*/
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
{
if (t->transient && t->transientfor == tmp_win->w)
{
/* this 'if (...) else' (see also Iconify()) - djhjr - 6/22/99 */
if (Scr->DontDeiconifyTransients && t->icon_w &&
t->icon == TRUE && t->icon_on == FALSE)
{
IconUp(t);
XMapRaised(dpy, t->icon_w);
t->icon_on = TRUE;
}
else
{
/* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */
if (t->icon_on)
Zoom(t->icon_w, NULL, t->frame, NULL);
else
Zoom(tmp_win->icon_w, NULL, t->frame, NULL);
XMapWindow(dpy, t->w);
t->mapped = TRUE;
if (Scr->NoRaiseDeicon)
XMapWindow(dpy, t->frame);
else
{
XMapRaised(dpy, t->frame);
XRaiseWindow(dpy, t->VirtualDesktopDisplayWindow);
}
SetMapStateProp(t, NormalState);
if (t->icon_w)
{
XUnmapWindow(dpy, t->icon_w);
IconDown (t);
}
t->icon = FALSE;
t->icon_on = FALSE;
if (t->list) XUnmapWindow(dpy, t->list->icon);
/*
* RemoveIconManager() done in events.c:HandleMapNotify()
*/
UpdateDesktop(t);
}
}
}
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
/*
* added '&& Scr->WarpWindows'.
* see the kludge in ExecuteFunction(F_ICONIFY, ...).
* djhjr - 1/24/98
*/
if (((Scr->WarpCursor ||
LookInList(Scr->WarpCursorL, tmp_win->full_name,
&tmp_win->class)) &&
tmp_win->icon) && Scr->WarpWindows)
WarpToWindow (tmp_win);
XSync (dpy, 0);
}
void Iconify(tmp_win, def_x, def_y)
TwmWindow *tmp_win;
int def_x, def_y;
{
TwmWindow *t;
int iconify;
XWindowAttributes winattrs;
unsigned long eventMask;
/* djhjr - 6/22/99 */
short fake_icon;
iconify = ((!tmp_win->iconify_by_unmapping) || tmp_win->transient);
if (iconify)
{
if (tmp_win->icon_w == None)
CreateIconWindow(tmp_win, def_x, def_y);
else
IconUp(tmp_win);
XMapRaised(dpy, tmp_win->icon_w);
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
}
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
eventMask = winattrs.your_event_mask;
/*
* Iconify transients first
*/
for (t = Scr->TwmRoot.next; t != NULL; t = t->next)
{
if (t->transient && t->transientfor == tmp_win->w)
{
/* RemoveFromDesktop(t); Stig */
/*
* Prevent the receipt of an UnmapNotify, since that would
* cause a transition to the Withdrawn state.
*/
t->mapped = FALSE;
XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask);
XUnmapWindow(dpy, t->w);
XSelectInput(dpy, t->w, eventMask);
XUnmapWindow(dpy, t->frame);
/* moved to make zooms more aesthetically pleasing -- DSE */
if (iconify)
{
/* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */
if (t->icon_on)
Zoom(t->icon_w, NULL, tmp_win->icon_w, NULL);
else
Zoom(t->frame, NULL, tmp_win->icon_w, NULL);
}
if (t->icon_w)
XUnmapWindow(dpy, t->icon_w);
SetMapStateProp(t, IconicState);
SetBorder (t, False);
if (t == Scr->Focus)
{
SetFocus ((TwmWindow *) NULL, LastTimestamp());
Scr->Focus = NULL;
Scr->FocusRoot = TRUE;
}
/*
* let current status ride, but "fake out" UpdateDesktop()
* (see also DeIconify()) - djhjr - 6/22/99
*/
fake_icon = t->icon;
t->icon = TRUE;
t->icon_on = FALSE;
/* djhjr - 10/2/01 */
if (Scr->StrictIconManager)
if (!t->list)
AddIconManager(t);
if (t->list) XMapWindow(dpy, t->list->icon);
UpdateDesktop(t);
/* restore icon status - djhjr - 6/22/99 */
t->icon = fake_icon;
}
}
/*
* Now iconify the main window
*/
/* if (iconify) RFBZOOM*/
/* RemoveFromDesktop(tmp_win); Stig */
/*
* Prevent the receipt of an UnmapNotify, since that would
* cause a transition to the Withdrawn state.
*/
tmp_win->mapped = FALSE;
XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
XUnmapWindow(dpy, tmp_win->w);
XSelectInput(dpy, tmp_win->w, eventMask);
XUnmapWindow(dpy, tmp_win->frame);
SetMapStateProp(tmp_win, IconicState);
SetBorder (tmp_win, False);
if (tmp_win == Scr->Focus)
{
SetFocus ((TwmWindow *) NULL, LastTimestamp());
Scr->Focus = NULL;
Scr->FocusRoot = TRUE;
}
tmp_win->icon = TRUE;
if (iconify)
tmp_win->icon_on = TRUE;
else
tmp_win->icon_on = FALSE;
/* djhjr - 10/2/01 */
if (Scr->StrictIconManager)
if (!tmp_win->list)
AddIconManager(tmp_win);
/* moved to make zooms more aesthetically pleasing -- DSE */
/* moved again to ensure an icon manager entry exists - djhjr - 10/11/01 */
/* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */
if (iconify)
Zoom(tmp_win->frame, NULL, tmp_win->icon_w, NULL);
else if (tmp_win->list) /* djhjr - 10/11/01 */
Zoom(tmp_win->frame, NULL, tmp_win->list->w, tmp_win->list->iconmgr);
if (tmp_win->list)
XMapWindow(dpy, tmp_win->list->icon);
UpdateDesktop(tmp_win);
XSync (dpy, 0);
}
static void Identify (t)
TwmWindow *t;
{
int i, n, twidth, width, height;
int x, y;
unsigned int wwidth, wheight, bw, depth;
Window junk;
int px, py, dummy;
unsigned udummy;
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
PlaySound(F_IDENTIFY);
#endif
n = 0;
(void) sprintf(Info[n++], "%s", Version);
Info[n++][0] = '\0';
if (t) {
XGetGeometry (dpy, t->w, &JunkRoot, &JunkX, &JunkY,
&wwidth, &wheight, &bw, &depth);
(void) XTranslateCoordinates (dpy, t->w, Scr->Root, 0, 0,
&x, &y, &junk);
/* looks bad with variable fonts... djhjr - 5/10/96
(void) sprintf(Info[n++], "Name = \"%s\"", t->full_name);
(void) sprintf(Info[n++], "Class.res_name = \"%s\"", t->class.res_name);
(void) sprintf(Info[n++], "Class.res_class = \"%s\"", t->class.res_class);
Info[n++][0] = '\0';
(void) sprintf(Info[n++], "Geometry/root = %dx%d+%d+%d", wwidth, wheight, x, y);
(void) sprintf(Info[n++], "Border width = %d", bw);
(void) sprintf(Info[n++], "Depth = %d", depth);
*/
(void) sprintf(Info[n++], "Name: \"%s\"", t->full_name);
(void) sprintf(Info[n++], "Class.res_name: \"%s\"", t->class.res_name);
(void) sprintf(Info[n++], "Class.res_class: \"%s\"", t->class.res_class);
Info[n++][0] = '\0';
(void) sprintf(Info[n++], "Geometry/root: %dx%d+%d+%d", wwidth, wheight, x, y);
(void) sprintf(Info[n++], "Border width: %d", bw);
(void) sprintf(Info[n++], "Depth: %d", depth);
Info[n++][0] = '\0';
}
/* djhjr - 9/19/96 */
#ifndef NO_BUILD_INFO
else
{
char is_m4, is_xpm;
char is_rplay; /* djhjr - 6/22/01 */
char is_regex; /* djhjr - 10/20/01 */
char is_i18n; /* djhjr - 10/20/01 */
/* djhjr - 6/22/99 */
#ifdef WE_REALLY_DO_WANT_TO_SEE_THIS
(void) sprintf(Info[n++], "X Server: %s Version %d.%d Release %d",
ServerVendor(dpy), ProtocolVersion(dpy), ProtocolRevision(dpy),
VendorRelease(dpy));
#endif
/*
* Was a 'do ... while()' that accessed unallocated memory.
* This and the change to Imakefile submitted by Takeharu Kato
*/
i = 0;
while (lastmake[i][0] != '\0')
(void) sprintf(Info[n++], "%s", lastmake[i++]);
/* djhjr - 1/31/99 */
#ifdef NO_M4_SUPPORT
is_m4 = '-';
#else
is_m4 = '+';
#endif
#ifdef NO_XPM_SUPPORT
is_xpm = '-';
#else
is_xpm = '+';
#endif
/* djhjr - 6/22/01 */
#ifdef NO_SOUND_SUPPORT
is_rplay = '-';
#else
is_rplay = '+';
#endif
/* djhjr - 6/22/01 */
#ifdef NO_REGEX_SUPPORT
is_regex = '-';
#else
is_regex = '+';
#endif
/* djhjr - 9/14/03 */
#ifdef NO_I18N_SUPPORT
is_i18n = '-';
#else
is_i18n = '+';
#endif
(void) sprintf(Info[n++],
"Options: %ci18n %cm4 %cregex %crplay %cxpm",
is_i18n, is_m4, is_regex, is_rplay, is_xpm);
Info[n++][0] = '\0';
}
#endif
(void) sprintf(Info[n++], "Click to dismiss...");
/* figure out the width and height of the info window */
/* djhjr - 4/29/98
height = (n * (Scr->InfoFont.height+2)) + 10; * some padding *
*/
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
i = (Scr->InfoBevelWidth > 0) ? Scr->InfoBevelWidth + 8 : 10;
height = (n * (Scr->InfoFont.height+2)) + i; /* some padding */
width = 1;
for (i = 0; i < n; i++)
{
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
twidth = MyFont_TextWidth(&Scr->InfoFont,
#else
twidth = XTextWidth(Scr->InfoFont.font,
#endif
Info[i], strlen(Info[i]));
if (twidth > width)
width = twidth;
}
if (InfoLines) XUnmapWindow(dpy, Scr->InfoWindow);
/* djhjr - 4/29/98
width += 20; * some padding *
*/
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
i = (Scr->InfoBevelWidth > 0) ? Scr->InfoBevelWidth + 18 : 20;
width += i; /* some padding */
if (XQueryPointer (dpy, Scr->Root, &JunkRoot, &JunkChild, &px, &py,
&dummy, &dummy, &udummy)) {
px -= (width / 2);
py -= (height / 3);
/* added this 'if ()' - djhjr - 4/29/98 */
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
if (Scr->InfoBevelWidth > 0)
{
if (px + width + 2 * Scr->InfoBevelWidth >= Scr->MyDisplayWidth)
px = Scr->MyDisplayWidth - width - 2 * Scr->InfoBevelWidth;
if (py + height + 2 * Scr->InfoBevelWidth >= Scr->MyDisplayHeight)
py = Scr->MyDisplayHeight - height - 2 * Scr->InfoBevelWidth;
}
else
{
if (px + width + BW2 >= Scr->MyDisplayWidth)
px = Scr->MyDisplayWidth - width - BW2;
if (py + height + BW2 >= Scr->MyDisplayHeight)
py = Scr->MyDisplayHeight - height - BW2;
}
if (px < 0) px = 0;
if (py < 0) py = 0;
} else {
px = py = 0;
}
XMoveResizeWindow(dpy, Scr->InfoWindow, px, py, width, height);
/* done in HandleExpose() in events.c - djhjr - 4/30/98 */
#ifdef NEVER
/* djhjr - 5/9/96 */
if (Scr->use3Dborders > 0)
{
XGetGeometry (dpy, Scr->InfoWindow, &JunkRoot, &JunkX, &JunkY,
&JunkWidth, &JunkHeight, &JunkBW, &JunkDepth);
Draw3DBorder(Scr->InfoWindow, 0, 0, JunkWidth, JunkHeight,
/* djhjr - 4/29/98
BW, Scr->DefaultC, off, False, False);
*/
Scr->InfoBevelWidth, Scr->DefaultC, off, False, False);
}
#endif
XMapRaised(dpy, Scr->InfoWindow);
InfoLines = n;
}
void SetMapStateProp(tmp_win, state)
TwmWindow *tmp_win;
int state;
{
unsigned long data[2]; /* "suggested" by ICCCM version 1 */
data[0] = (unsigned long) state;
data[1] = (unsigned long) (tmp_win->iconify_by_unmapping ? None :
tmp_win->icon_w);
XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32,
PropModeReplace, (unsigned char *) data, 2);
}
Bool GetWMState (w, statep, iwp)
Window w;
int *statep;
Window *iwp;
{
Atom actual_type;
int actual_format;
unsigned long nitems, bytesafter;
unsigned long *datap = NULL;
Bool retval = False;
/* used to test for '!datap' - djhjr - 1/10/98 */
if (XGetWindowProperty (dpy, w, _XA_WM_STATE, 0L, 2L, False, _XA_WM_STATE,
&actual_type, &actual_format, &nitems, &bytesafter,
(unsigned char **) &datap) != Success ||
actual_type == None)
return False;
if (nitems <= 2) { /* "suggested" by ICCCM version 1 */
*statep = (int) datap[0];
*iwp = (Window) datap[1];
retval = True;
}
XFree ((char *) datap);
return retval;
}
/*
* BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS
*/
void BumpWindowColormap (tmp, inc)
TwmWindow *tmp;
int inc;
{
int i, j, previously_installed;
ColormapWindow **cwins;
if (!tmp) return;
if (inc && tmp->cmaps.number_cwins > 0) {
cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *)*
tmp->cmaps.number_cwins);
if (cwins) {
if ((previously_installed =
(Scr->cmapInfo.cmaps == &tmp->cmaps) &&
tmp->cmaps.number_cwins)) {
for (i = tmp->cmaps.number_cwins; i-- > 0; )
tmp->cmaps.cwins[i]->colormap->state = 0;
}
for (i = 0; i < tmp->cmaps.number_cwins; i++) {
j = i - inc;
if (j >= tmp->cmaps.number_cwins)
j -= tmp->cmaps.number_cwins;
else if (j < 0)
j += tmp->cmaps.number_cwins;
cwins[j] = tmp->cmaps.cwins[i];
}
free((char *) tmp->cmaps.cwins);
tmp->cmaps.cwins = cwins;
if (tmp->cmaps.number_cwins > 1)
memset( tmp->cmaps.scoreboard, 0,
ColormapsScoreboardLength(&tmp->cmaps));
if (previously_installed)
InstallWindowColormaps(PropertyNotify, (TwmWindow *) NULL);
}
} else
FetchWmColormapWindows (tmp);
}
void HideIconManager(tmp_win)
TwmWindow *tmp_win;
{
/* added this 'if (...) else ...' - djhjr - 9/21/99 */
if (tmp_win == NULL)
{
name_list *list;
HideIconMgr(&Scr->iconmgr);
/*
* New code in list.c necessitates 'next_entry()' and
* 'contents_of_entry()' - djhjr - 10/20/01
*/
for (list = Scr->IconMgrs; list != NULL; list = next_entry(list))
HideIconMgr((IconMgr *)contents_of_entry(list));
}
else
{
IconMgr *ip;
if ((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->full_name,
&tmp_win->class)) == NULL)
ip = &Scr->iconmgr;
HideIconMgr(ip);
}
}
/* djhjr - 9/21/99 */
void HideIconMgr(ip)
IconMgr *ip;
{
/* djhjr - 6/10/98 */
if (ip->count == 0)
return;
SetMapStateProp (ip->twm_win, WithdrawnState);
XUnmapWindow(dpy, ip->twm_win->frame);
if (ip->twm_win->icon_w)
XUnmapWindow (dpy, ip->twm_win->icon_w);
ip->twm_win->mapped = FALSE;
ip->twm_win->icon = TRUE;
}
/* djhjr - 9/21/99 */
void ShowIconMgr(ip)
IconMgr *ip;
{
/* added the second condition - djhjr - 6/10/98 */
if (Scr->NoIconManagers || ip->count == 0)
return;
DeIconify(ip->twm_win);
XRaiseWindow(dpy, ip->twm_win->frame);
XRaiseWindow(dpy, ip->twm_win->VirtualDesktopDisplayWindow);
}
void SetBorder (tmp, onoroff)
TwmWindow *tmp;
Bool onoroff;
{
if (tmp->highlight)
{
/* djhjr - 4/22/96 */
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
if (Scr->BorderBevelWidth > 0)
PaintBorders (tmp, onoroff);
else
{
if (onoroff)
{
/* djhjr - 4/24/96
XSetWindowBorder (dpy, tmp->frame, tmp->border);
*/
/* djhjr - 11/17/97
XSetWindowBorder (dpy, tmp->frame, tmp->border_tile.back);
*/
XSetWindowBorder (dpy, tmp->frame, tmp->border.back);
if (tmp->title_w)
/* djhjr - 4/24/96
XSetWindowBorder (dpy, tmp->title_w, tmp->border);
*/
/* djhjr - 11/17/97
XSetWindowBorder (dpy, tmp->title_w, tmp->border_tile.back);
*/
XSetWindowBorder (dpy, tmp->title_w, tmp->border.back);
}
else
{
XSetWindowBorderPixmap (dpy, tmp->frame, tmp->gray);
if (tmp->title_w)
XSetWindowBorderPixmap (dpy, tmp->title_w, tmp->gray);
}
}
/* djhjr - 11/17/97 */
/* rem'd out test for button color - djhjr - 9/15/99 */
if (/*Scr->ButtonColorIsFrame && */tmp->titlebuttons)
{
int i, nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
TBWindow *tbw;
/* collapsed two functions - djhjr - 8/10/98 */
for (i = 0, tbw = tmp->titlebuttons; i < nb; i++, tbw++)
PaintTitleButton(tmp, tbw, (onoroff) ? 2 : 1);
}
}
}
void DestroyMenu (menu)
MenuRoot *menu;
{
MenuItem *item;
if (menu->w) {
XDeleteContext (dpy, menu->w, MenuContext);
XDeleteContext (dpy, menu->w, ScreenContext);
if (Scr->Shadow) XDestroyWindow (dpy, menu->shadow);
XDestroyWindow(dpy, menu->w);
}
for (item = menu->first; item; ) {
MenuItem *tmp = item;
item = item->next;
free ((char *) tmp);
}
}
/*
* warping routines
*/
/* for moves and resizes from center - djhjr - 10/4/02 */
void WarpScreenToWindow(t)
TwmWindow *t;
{
int warpwin = Scr->WarpWindows;
int warpsnug = Scr->WarpSnug;
Scr->WarpWindows = Scr->WarpSnug = FALSE;
WarpToWindow(t);
Scr->WarpWindows = warpwin;
Scr->WarpSnug = warpsnug;
/*
* This is an attempt to have windows redraw themselves, but
* it doesn't always work (non-raising windows in particular).
*/
XSync(dpy, 0);
}
/* was in-lined in WarpToWindow() - djhjr - 5/30/00 */
void WarpWindowOrScreen(t)
TwmWindow *t;
{
/*
* we are either moving the window onto the screen, or the screen to the
* window, the distances remain the same
*/
if ((t->frame_x < Scr->MyDisplayWidth)
&& (t->frame_y < Scr->MyDisplayHeight)
&& (t->frame_x + t->frame_width >= 0)
&& (t->frame_y + t->frame_height >= 0))
{
/*
* window is visible; you can simply
* snug it if WarpSnug or WarpWindows is set -- DSE
*/
if (Scr->WarpSnug || Scr->WarpWindows)
{
int right,left,up,down,dx,dy;
/*
* Adjustment for border widths submitted by Steve Ratcliffe
* Note: Do not include the 3D border width!
*/
right = t->frame_x;
left = t->frame_x + t->frame_width + 2 * t->frame_bw;
up = t->frame_y;
down = t->frame_y + t->frame_height + 2 * t->frame_bw;
dx = 0;
if (left-right < Scr->MyDisplayWidth)
{
if (right<0)
dx = right;
else if (left>Scr->MyDisplayWidth)
dx = left - Scr->MyDisplayWidth;
}
dy = 0;
if (down-up < Scr->MyDisplayHeight)
{
if (up<0)
dy = up;
else if (down>Scr->MyDisplayHeight)
dy = down - Scr->MyDisplayHeight;
}
if (dx!=0 || dy!=0) {
/* added 'Scr->WarpSnug ||' - djhjr - 5/30/00 */
if (Scr->WarpSnug || Scr->WarpWindows)
{
/* move the window */
VirtualMoveWindow(t, t->virtual_frame_x - dx,
t->virtual_frame_y - dy);
}
else
{
/* move the screen */
PanRealScreen(dx,dy,NULL,NULL);
}
}
}
}
else
{
/*
* Window is invisible; we need to move it or the screen.
*/
int xdiff, ydiff;
xdiff = ((Scr->MyDisplayWidth - t->frame_width) / 2) - t->frame_x;
ydiff = ((Scr->MyDisplayHeight - t->frame_height) / 2) - t->frame_y;
/* added 'Scr->WarpSnug ||' - djhjr - 5/30/00 */
if (Scr->WarpSnug || Scr->WarpWindows)
{
/* move the window */
VirtualMoveWindow(t, t->virtual_frame_x + xdiff,
t->virtual_frame_y + ydiff);
}
else
{
/* move the screen */
PanRealScreen(-xdiff, -ydiff,NULL,NULL); /* DSE */
}
}
if (t->auto_raise || !Scr->NoRaiseWarp)
AutoRaiseWindow (t);
}
/* for icon manager management - djhjr - 5/30/00 */
void WarpInIconMgr(w, t)
WList *w;
TwmWindow *t;
{
int x, y, pan_margin = 0;
/* djhjr - 9/9/02 */
int bw = t->frame_bw3D + t->frame_bw;
RaiseStickyAbove();
RaiseAutoPan();
WarpWindowOrScreen(t);
/* was 'Scr->BorderWidth' - djhjr - 9/9/02 */
x = w->x + bw + EDGE_OFFSET + 5;
x += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw;
y = w->y + bw + w->height / 2;
y += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw;
y += w->iconmgr->twm_win->title_height;
/*
* adjust the pointer for partially visible windows and the
* AutoPan border width
*/
if (Scr->AutoPanX) pan_margin = Scr->AutoPanBorderWidth;
if (x + t->frame_x >= Scr->MyDisplayWidth - pan_margin)
x = Scr->MyDisplayWidth - t->frame_x - pan_margin - 2;
if (x + t->frame_x <= pan_margin)
x = -t->frame_x + pan_margin + 2;
if (y + t->frame_y >= Scr->MyDisplayHeight - pan_margin)
y = Scr->MyDisplayHeight - t->frame_y - pan_margin - 2;
if (y + t->frame_y <= pan_margin)
y = -t->frame_y + pan_margin + 2;
XWarpPointer(dpy, None, t->frame, 0, 0, 0, 0, x, y); /* DSE */
}
/*
* substantially re-written and added passing 'next' to next_by_class()
*
* djhjr - 5/13/98 6/6/98 6/15/98
*/
#ifdef ORIGINAL_WARPCLASS
void WarpClass (next, t, class)
int next;
TwmWindow *t;
char *class;
{
int len = strlen(class);
if (!strncmp(class, t->class.res_class, len))
t = next_by_class(t, class);
else
t = next_by_class((TwmWindow *)NULL, class);
if (t) {
if (Scr->WarpUnmapped || t->mapped) {
if (!t->mapped) DeIconify (t);
if (!Scr->NoRaiseWarp)
{
XRaiseWindow (dpy, t->frame);
}
XRaiseWindow (dpy, t->VirtualDesktopDisplayWindow);
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
WarpToWindow (t);
}
}
}
#else /* ORIGINAL_WARPCLASS */
void WarpClass(next, t, class)
int next;
TwmWindow *t;
char *class;
{
TwmWindow *tt;
XClassHint ch;
int i;
/*
* if an empty class string
* if a TwmWindow
* class = the TwmWindow's class
* else if a window with focus
* if it's classed
* class = the focused window's class
* else
* return
* if still an empty class string
* class = "VTWM"
*/
if (!strlen(class))
{
if (t)
class = t->class.res_class;
else if (Scr->Focus)
{
i = XGetClassHint(dpy, Scr->Focus->w, &ch);
if (i && !strncmp(class, ch.res_class, strlen(class)))
class = ch.res_class;
}
/* djhjr - 6/21/00 */
else
{
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
return;
}
}
if (!strlen(class) || !strncmp(class, "VTWM", 4))
class = "VTWM";
/* djhjr - 8/3/98
if (!(tt = next_by_class(next, t, class)))
if (t) tt = t;
*/
/* djhjr - 5/28/00 */
while (1)
{
tt = NULL;
do
{
if ((tt = next_by_class(next, t, class)))
{
/* multiple icon managers: gotta test for those without entries */
if (tt->iconmgr && tt->iconmgrp->count == 0)
{
t = tt;
tt = NULL;
}
}
else if (t)
tt = t;
else
break;
} while (!tt);
/* added the second argument - djhjr - 5/28/00 */
if (tt && warp_if_warpunmapped(tt, (next) ? F_WARPCLASSNEXT: F_WARPCLASSPREV))
{
RaiseStickyAbove(); /* DSE */
RaiseAutoPan();
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound((next) ? F_WARPCLASSNEXT: F_WARPCLASSPREV);
#endif
WarpToWindow(tt);
/* djhjr - 5/28/00 */
break;
}
/* djhjr - 5/28/00
else
XBell(dpy, 0);
*/
t = tt;
} /* while (1) */
}
#endif /* ORIGINAL_WARPCLASS */
/* moved from add_window.c - djhjr - 10/27/02 */
void AddWindowToRing(tmp_win)
TwmWindow *tmp_win;
{
if (Scr->Ring)
{
/* link window in after Scr->Ring */
tmp_win->ring.prev = Scr->Ring;
tmp_win->ring.next = Scr->Ring->ring.next;
/* Scr->Ring's next's prev points to this */
/*if (Scr->Ring->ring.next->ring.prev)*/
Scr->Ring->ring.next->ring.prev = tmp_win;
/* Scr->Ring's next points to this */
Scr->Ring->ring.next = tmp_win;
}
else
tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win;
}
/* moved from events.c - djhjr - 10/27/02 */
void RemoveWindowFromRing(tmp_win)
TwmWindow *tmp_win;
{
/* unlink window */
if (tmp_win->ring.prev)
tmp_win->ring.prev->ring.next = tmp_win->ring.next;
if (tmp_win->ring.next)
tmp_win->ring.next->ring.prev = tmp_win->ring.prev;
/* if window was only thing in ring, null out ring */
if (Scr->Ring == tmp_win)
Scr->Ring = (tmp_win->ring.next != tmp_win) ?
tmp_win->ring.next : (TwmWindow *)NULL;
/* if window was ring leader, set to next (or null) */
if (!Scr->Ring || Scr->RingLeader == tmp_win)
Scr->RingLeader = Scr->Ring;
tmp_win->ring.next = tmp_win->ring.prev = NULL;
}
void WarpAlongRing (ev, forward)
XButtonEvent *ev;
Bool forward;
{
TwmWindow *r, *head;
/*
* Re-vamped much of this to properly handle icon managers, and
* clean up dumb code I added some time back.
* djhjr - 11/8/01
* Cleaned it up again. I musta been high. Twice.
* djhjr - 10/27/02
*/
if (!(head = (Scr->RingLeader) ? Scr->RingLeader : Scr->Ring))
{
DoAudible();
return;
}
if (forward)
r = head->ring.next;
else
r = head->ring.prev;
while (r && r != head)
{
if (r->mapped || warp_if_warpunmapped(r, F_WARPRING))
break;
r = (forward) ? r->ring.next : r->ring.prev;
}
if (r && r->mapped)
{
#ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */
TwmWindow *p = Scr->RingLeader, *t;
#endif
/* done in WarpToWindow - djhjr - 10/27/02
Scr->RingLeader = r;
*/
RaiseStickyAbove();
RaiseAutoPan();
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(F_WARPRING);
#endif
WarpToWindow (r);
#ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */
if (p && p->mapped &&
XFindContext (dpy, ev->window, TwmContext, (caddr_t *)&t) == XCSUCCESS &&
p == t)
{
p->ring.cursor_valid = True;
p->ring.curs_x = ev->x_root - t->frame_x;
p->ring.curs_y = ev->y_root - t->frame_y;
if (p->ring.curs_x < -p->frame_bw ||
p->ring.curs_x >= p->frame_width + p->frame_bw ||
p->ring.curs_y < -p->frame_bw ||
p->ring.curs_y >= p->frame_height + p->frame_bw)
{
/* somehow out of window */
p->ring.curs_x = p->frame_width / 2;
p->ring.curs_y = p->frame_height / 2;
}
}
#endif
}
else
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
}
void WarpToScreen (n, inc)
int n, inc;
{
Window dumwin;
int x, y, dumint;
unsigned int dummask;
ScreenInfo *newscr = NULL;
while (!newscr) {
/* wrap around */
if (n < 0)
n = NumScreens - 1;
else if (n >= NumScreens)
n = 0;
newscr = ScreenList[n];
if (!newscr) { /* make sure screen is managed */
if (inc) { /* walk around the list */
n += inc;
continue;
}
fprintf (stderr, "%s: unable to warp to unmanaged screen %d\n",
ProgramName, n);
DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
return;
}
}
if (Scr->screen == n) return; /* already on that screen */
PreviousScreen = Scr->screen;
XQueryPointer (dpy, Scr->Root, &dumwin, &dumwin, &x, &y,
&dumint, &dumint, &dummask);
/* djhjr - 6/3/03 */
#ifndef NO_SOUND_SUPPORT
PlaySound(F_WARPTOSCREEN);
#endif
XWarpPointer (dpy, None, newscr->Root, 0, 0, 0, 0, x, y);
return;
}
void WarpToWindow (t)
TwmWindow *t;
{
int x, y;
int pan_margin = 0; /* djhjr - 5/28/00 */
int bw = t->frame_bw3D + t->frame_bw; /* djhjr - 9/9/02 */
Window w = t->frame; /* djhjr - 5/30/00 */
WarpWindowOrScreen(t); /* djhjr - 5/30/00 */
#ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */
if (t->ring.cursor_valid) {
x = t->ring.curs_x;
y = t->ring.curs_y;
}
else {
x = t->frame_width / 2;
y = t->frame_height / 2;
}
#else
/* added this 'if (...) else' - djhjr - 6/10/98 */
if (t->iconmgr)
{
/* djhjr - 5/30/00
if (t->iconmgrp->count > 0)
XWarpPointer(dpy, None, t->iconmgrp->first->icon, 0,0,0,0,
EDGE_OFFSET, EDGE_OFFSET);
return;
*/
if (t->iconmgrp->count > 0)
{
w = t->iconmgrp->twm_win->frame;
/* was 'Scr->BorderWidth' - djhjr - 9/9/02 */
x = t->iconmgrp->x + bw + EDGE_OFFSET + 5;
x += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw;
y = t->iconmgrp->y + bw + t->iconmgrp->first->height / 2;
y += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw;
y += t->iconmgrp->twm_win->title_height;
}
}
else if (!t->title_w)
{
/* added this 'if (...) else' - djhjr - 10/16/02 */
if (Scr->WarpCentered & WARPC_UNTITLED)
{
x = t->frame_width / 2;
y = t->frame_height / 2;
}
else
{
x = t->frame_width / 2;
y = (t->wShaped) ? bw : bw / 2; /* djhjr - 9/9/02 */
}
}
else
{
/* added this 'if (...) else' - djhjr - 10/16/02 */
if (Scr->WarpCentered & WARPC_TITLED)
{
x = t->frame_width / 2;
y = t->frame_height / 2;
}
else
{
/*
* Added 't->title_x + ' to handle titlebars that
* aren't flush left.
* Submitted by Steve Ratcliffe
* was '(t->frame_bw3D + t->frame_bw)' - djhjr - 9/9/02
*/
x = t->title_x + t->title_width / 2 + bw;
y = t->title_height / 2 + bw;
}
}
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
if (!Scr->BorderBevelWidth > 0) y -= t->frame_bw;
#endif
/*
* adjust the pointer for partially visible windows and the
* AutoPan border width - djhjr - 5/30/00
* was '(t->frame_bw3D + t->frame_bw)' - djhjr - 9/9/02
*/
if (Scr->AutoPanX) pan_margin = Scr->AutoPanBorderWidth;
if (x + t->frame_x >= Scr->MyDisplayWidth - pan_margin)
x = Scr->MyDisplayWidth - t->frame_x - pan_margin - 2;
if (x + t->frame_x <= pan_margin)
{
if (t->title_w)
x = t->title_width - (t->frame_x + t->title_width) +
pan_margin + 2;
else
x = -t->frame_x + pan_margin + 2;
}
/* added test for centered warps - djhjr - 10/16/02 */
if (t->title_w && !(Scr->WarpCentered & WARPC_TITLED) &&
(x < t->title_x || x > t->title_x + t->title_width))
{
y = t->title_height + bw / 2;
}
if (y + t->frame_y >= Scr->MyDisplayHeight - pan_margin)
{
y = Scr->MyDisplayHeight - t->frame_y - pan_margin - 2;
/* move centered warp to titlebar - djhjr - 10/16/02 */
if (y < t->title_y + t->title_height)
x = t->title_x + t->title_width / 2 + bw;
}
if (y + t->frame_y <= pan_margin)
y = -t->frame_y + pan_margin + 2;
/* was 't->frame' - djhjr - 5/30/00 */
XWarpPointer (dpy, None, w, 0, 0, 0, 0, x, y);
/* djhjr - 10/27/02 */
if (t->ring.next) Scr->RingLeader = t;
}
/*
* substantially re-written and added receiving and using 'next'
*
* djhjr - 5/13/98 5/19/98 6/6/98 6/15/98
*/
#ifdef ORIGINAL_WARPCLASS
TwmWindow *
next_by_class (t, class)
TwmWindow *t;
char *class;
{
TwmWindow *tt;
int len = strlen(class);
if (t)
for (tt = t->next; tt != NULL; tt = tt->next)
if (!strncmp(class, tt->class.res_class, len)) return tt;
for (tt = Scr->TwmRoot.next; tt != NULL; tt = tt->next)
if (!strncmp(class, tt->class.res_class, len)) return tt;
return NULL;
}
#else /* ORIGINAL_WARPCLASS */
static TwmWindow *
next_by_class (next, t, class)
int next;
TwmWindow *t;
char *class;
{
static TwmWindow *tp = NULL;
TwmWindow *tt, *tl;
int i, len = strlen(class);
XClassHint ch;
#ifdef DEBUG_WARPCLASS
fprintf(stderr, "class=\"%s\", next=%d, %s t, ", class, next, (t) ? "have" : "no");
#endif
/* forward or backward from current */
tl = (next) ? ((tp) ? tp->next : Scr->TwmRoot.next) : ((tp) ? tp->prev : Scr->TwmRoot.prev);
for (tt = (next) ? ((t) ? t->next : tl) : ((t) ? t->prev : tl);
tt != NULL;
tt = (next) ? tt->next : tt->prev)
if (Scr->WarpUnmapped || tt->mapped)
{
i = XGetClassHint(dpy, tt->w, &ch);
if (i && !strncmp(class, ch.res_class, len))
{
#ifdef DEBUG_WARPCLASS
fprintf(stderr, "matched \"%s\" \"%s\"\n", tt->class.res_class, tt->class.res_name);
#endif
tp = tt;
return tp;
}
else
{
#ifdef DEBUG_WARPCLASS
fprintf(stderr, "(1) skipping \"%s\"\n", (i) ? tt->class.res_class : "NO RES_CLASS!");
#endif
if (i == 0) break;
}
}
/* no match, wrap and retry */
tp = tl = NULL;
for (tt = Scr->TwmRoot.next; tt != NULL; tt = tt->next)
if (Scr->WarpUnmapped || tt->mapped)
{
i = XGetClassHint(dpy, tt->w, &ch);
if (i && !strncmp(class, ch.res_class, len))
{
if (next)
{
#ifdef DEBUG_WARPCLASS
fprintf(stderr, "next wrapped to \"%s\ \"%s\"\n", tt->class.res_class, tt->class.res_name);
#endif
tp = tt;
return tp;
}
else
tl = tt;
}
#ifdef DEBUG_WARPCLASS
else
fprintf(stderr, "(2) skipping \"%s\"\n", (i) ? tt->class.res_class : "NO RES_CLASS!");
#endif
}
#ifdef DEBUG_WARPCLASS
i = 0; if (tl) i = XGetClassHint(dpy, tl->w, &ch);
fprintf(stderr, "prev wrapped to \"%s\ \"%s\"\n", (i) ? ch.res_class : "NO RES_CLASS!", (i) ? ch.res_name : "NO RES_CLASS!");
#endif
tp = tl;
return tp;
}
#endif /* ORIGINAL_WARPCLASS */
/* this was inlined in many places, and even more now - djhjr - 5/13/98 */
/* added the second argument - djhjr - 5/28/00 */
static int warp_if_warpunmapped(w, func)
TwmWindow *w;
int func;
{
/* skip empty icon managers - 10/27/02 */
if (w && (w->iconmgr && w->iconmgrp->count == 0))
return (0);
if (Scr->WarpUnmapped || w->mapped)
{
/* submitted by Ugen Antsilevitch - 5/28/00 */
/* if F_NOFUNCTION, override WarpVisible - djhjr - 5/28/00 */
if (func != F_NOFUNCTION && Scr->WarpVisible)
{
int pan_margin = 0;
if (Scr->AutoPanX) pan_margin = Scr->AutoPanBorderWidth;
if (w->frame_x >= Scr->MyDisplayWidth - pan_margin ||
w->frame_y >= Scr->MyDisplayHeight - pan_margin ||
w->frame_x + w->frame_width <= pan_margin ||
w->frame_y + w->frame_height <= pan_margin)
return 0;
}
if (!w->mapped) DeIconify(w);
if (!Scr->NoRaiseWarp) XRaiseWindow(dpy, w->frame);
XRaiseWindow(dpy, w->VirtualDesktopDisplayWindow);
return (1);
}
return (0);
}
/* djhjr - 9/17/02 */
static int
do_squeezetitle(context, func, tmp_win, squeeze)
int context, func;
TwmWindow *tmp_win;
SqueezeInfo *squeeze;
{
if (DeferExecution (context, func, Scr->SelectCursor))
return TRUE;
/* honor "Don't Squeeze" resources - djhjr - 9/17/02 */
if (Scr->SqueezeTitle &&
!LookInList(Scr->DontSqueezeTitleL, tmp_win->full_name, &tmp_win->class))
{
if ( tmp_win->title_height ) /* Not for untitled windows! */
{
PopDownMenu(); /* djhjr - 9/17/02 */
#ifndef NO_SOUND_SUPPORT
PlaySound(func);
#endif
tmp_win->squeeze_info = squeeze;
SetFrameShape( tmp_win );
/* Can't go in SetFrameShape()... - djhjr - 4/1/00 */
if (Scr->WarpCursor ||
LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class))
WarpToWindow(tmp_win);
}
}
else
DoAudible();
return FALSE;
}
/*
* Two functions to handle a restart from a SIGUSR1 signal
* (see also twm.c:Done() and twm.c:QueueRestartVtwm())
*
* adapted from TVTWM-pl11 - djhjr - 7/31/98
*/
static void setup_restart(time)
Time time;
{
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
CloseSound();
#endif
SetRealScreen(0,0);
XSync (dpy, 0);
Reborder (time);
XSync (dpy, 0);
/* djhjr - 3/13/97 */
XCloseDisplay(dpy);
/* djhjr - 12/2/01 */
delete_pidfile();
}
void RestartVtwm(time)
Time time;
{
setup_restart(time);
execvp(*Argv, Argv);
fprintf (stderr, "%s: unable to restart \"%s\"\n", ProgramName, *Argv);
}
/*
* ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all
* client messages will have the following form:
*
* event type ClientMessage
* message type _XA_WM_PROTOCOLS
* window tmp->w
* format 32
* data[0] message atom
* data[1] time stamp
*/
static void send_clientmessage (w, a, timestamp)
Window w;
Atom a;
Time timestamp;
{
XClientMessageEvent ev;
ev.type = ClientMessage;
ev.window = w;
ev.message_type = _XA_WM_PROTOCOLS;
ev.format = 32;
ev.data.l[0] = a;
ev.data.l[1] = timestamp;
XSendEvent (dpy, w, False, 0L, (XEvent *) &ev);
}
void SendDeleteWindowMessage (tmp, timestamp)
TwmWindow *tmp;
Time timestamp;
{
send_clientmessage (tmp->w, _XA_WM_DELETE_WINDOW, timestamp);
}
void SendSaveYourselfMessage (tmp, timestamp)
TwmWindow *tmp;
Time timestamp;
{
send_clientmessage (tmp->w, _XA_WM_SAVE_YOURSELF, timestamp);
}
void SendTakeFocusMessage (tmp, timestamp)
TwmWindow *tmp;
Time timestamp;
{
send_clientmessage (tmp->w, _XA_WM_TAKE_FOCUS, timestamp);
}
/* djhjr - 4/27/96 */
void DisplayPosition (x, y)
int x, y;
{
char str [100];
int i;
/* djhjr - 5/10/96
char signx = '+';
char signy = '+';
if (x < 0) {
x = -x;
signx = '-';
}
if (y < 0) {
y = -y;
signy = '-';
}
i = sprintf (str, " %c%-4d %c%-4d ", signx, x, signy, y);
*/
/*
* Non-SysV systems - specifically, BSD-derived systems - return a
* pointer to the string, not its length. Submitted by Goran Larsson
i = sprintf (str, "%+6d %-+6d", x, y);
*/
sprintf (str, "%+6d %-+6d", x, y);
i = strlen (str);
XRaiseWindow (dpy, Scr->SizeWindow);
/* font was font.font->fid - djhjr - 9/14/03 */
FBF (Scr->DefaultC.fore, Scr->DefaultC.back, Scr->SizeFont);
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
#else
XDrawImageString (dpy, Scr->SizeWindow,
#endif
Scr->NormalGC,
/* djhjr - 5/9/96
Scr->SizeStringOffset,
*/
(Scr->SizeStringWidth -
/* djhjr - 9/14/03 */
#ifndef NO_I18N_SUPPORT
MyFont_TextWidth(&Scr->SizeFont,
#else
XTextWidth(Scr->SizeFont.font,
#endif
str, i)) / 2,
/* djhjr - 4/29/98
Scr->SizeFont.font->ascent + SIZE_VINDENT,
*/
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
/* djhjr - 9/14/03
Scr->SizeFont.font->ascent +
*/
Scr->SizeFont.ascent +
SIZE_VINDENT +
((Scr->InfoBevelWidth > 0) ? Scr->InfoBevelWidth : 0),
str, i);
/* I know, I know, but the above code overwrites it... djhjr - 5/9/96 */
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
if (Scr->InfoBevelWidth > 0)
Draw3DBorder(Scr->SizeWindow, 0, 0,
Scr->SizeStringWidth,
/* djhjr - 4/29/98
(unsigned int) (Scr->SizeFont.height + SIZE_VINDENT*2),
BW, Scr->DefaultC, off, False, False);
*/
/* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
(unsigned int) (Scr->SizeFont.height + SIZE_VINDENT*2) +
((Scr->InfoBevelWidth > 0) ? 2 * Scr->InfoBevelWidth : 0),
Scr->InfoBevelWidth, Scr->DefaultC, off, False, False);
}
/* djhjr - 9/21/99 */
int FindMenuOrFuncInBindings(contexts, mr, func)
int contexts;
MenuRoot *mr;
int func;
{
MenuRoot *start;
FuncKey *key;
int found = 0; /* context bitmap for menu or function */
int i, j, k, l, fallback = 0;
if (mr)
{
if (Scr->DefaultFunction.func == F_MENU)
if (FindMenuInMenus(Scr->DefaultFunction.menu, mr))
fallback = 1;
}
else
{
if (Scr->DefaultFunction.func == func)
fallback = 1;
else if (Scr->DefaultFunction.func == F_MENU)
if (FindFuncInMenus(Scr->DefaultFunction.menu, func))
fallback = 1;
}
for (j = 0; j < NUM_CONTEXTS; j++)
{
if ((contexts & (1 << j)) == 0) continue;
if (fallback)
{
found |= (1 << j);
continue;
}
for (i = 0; i < MAX_BUTTONS + 1; i++)
{
l = 0;
for (k = 0; k < MOD_SIZE; k++)
{
if (mr)
{
if (Scr->Mouse[i][j][k].func == F_MENU)
l = FindMenuInMenus(Scr->Mouse[i][j][k].menu, mr);
}
else
{
if (Scr->Mouse[i][j][k].func == func)
l = 1;
else if (Scr->Mouse[i][j][k].func == F_MENU)
l = FindFuncInMenus(Scr->Mouse[i][j][k].menu, func);
}
if (l)
{
found |= (1 << j);
i = MAX_BUTTONS + 1;
break;
}
}
}
l = 0;
for (key = Scr->FuncKeyRoot.next; key != NULL; key = key->next)
if (key->cont & (1 << j))
{
if (mr)
{
if (key->func == F_MENU)
for (start = Scr->MenuList; start != NULL; start = start->next)
if (strcmp(start->name, key->action) == 0)
{
l = FindMenuInMenus(start, mr);
break;
}
}
else
{
if (key->func == func)
l = 1;
else if (key->func == F_MENU)
for (start = Scr->MenuList; start != NULL; start = start->next)
if (strcmp(start->name, key->action) == 0)
{
l = FindFuncInMenus(start, func);
break;
}
}
if (l)
{
found |= (1 << j);
break;
}
}
}
return found;
}
/* djhjr - 9/21/99 */
int FindMenuOrFuncInWindows(tmp_win, contexts, mr, func)
TwmWindow *tmp_win;
int contexts;
MenuRoot *mr;
int func;
{
TwmWindow *twin;
TwmDoor *d;
TBWindow *tbw;
int i, nb;
if (contexts & C_ROOT_BIT) return 1;
for (twin = Scr->TwmRoot.next; twin != NULL; twin = twin->next)
if (twin != tmp_win)
{
/*
* if this window is an icon manager,
* skip the windows that aren't in it
*/
if (tmp_win->iconmgr && twin->list &&
tmp_win != twin->list->iconmgr->twm_win)
continue;
if (twin->mapped)
{
for (i = 1; i < C_ALL_BITS; i = (1 << i))
{
if ((contexts & i) == 0) continue;
switch (i)
{
case C_WINDOW_BIT:
case C_FRAME_BIT:
break;
case C_TITLE_BIT:
if (!twin->title_height) continue;
break;
case C_VIRTUAL_BIT:
if (twin->w != Scr->VirtualDesktopDisplayOuter)
continue;
break;
case C_DOOR_BIT:
if (XFindContext(dpy, twin->w, DoorContext,
(caddr_t *)&d) == XCNOENT)
continue;
break;
default:
continue;
break;
}
return 1;
}
if (twin->titlebuttons)
{
nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
for (tbw = twin->titlebuttons; nb > 0; tbw++, nb--)
if (mr)
{
if (tbw->info->menuroot)
if (FindMenuInMenus(tbw->info->menuroot, mr))
return 1;
}
else
{
if (tbw->info->func == func)
return 1;
else if (tbw->info->menuroot)
if (FindFuncInMenus(tbw->info->menuroot, func))
return 1;
}
}
}
else if (!twin->iconify_by_unmapping)
{
/* not mapped and shows an icon */
if (contexts & C_ICON_BIT) return 1;
}
}
return 0;
}
/* djhjr - 9/21/99 */
int FindMenuInMenus(start, sought)
MenuRoot *start, *sought;
{
MenuItem *mi;
if (!start) return 0; /* submitted by Jonathan Paisley - 11/11/02 */
if (start == sought) return 1;
for (mi = start->first; mi != NULL; mi = mi->next)
if (mi->sub)
if (FindMenuInMenus(mi->sub, sought))
return 1;
return 0;
}
/* djhjr - 9/21/99 */
int FindFuncInMenus(mr, func)
MenuRoot *mr;
int func;
{
MenuItem *mi;
for (mi = mr->first; mi != NULL; mi = mi->next)
if (mi->func == func)
return 1;
else if (mi->sub)
if (FindFuncInMenus(mi->sub, func))
return 1;
return 0;
}
/* djhjr - 6/22/01 */
void DoAudible()
{
#ifndef NO_SOUND_SUPPORT
if (PlaySound(S_BELL)) return;
#endif
XBell(dpy, 0);
}
syntax highlighted by Code2HTML, v. 0.9.1