mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-30 09:58:55 +02:00
had numerous problems, the main one being that each of the three commands was inconsistent: "expand toggle" inverts the expansion of the selection and syncs with the layout. But "expand" expands the layout where instances overlap the box and does not sync to the selection, and "unexpand" unexpands the layout where the box completely surrounds instances. Added a set of options to "expand" and "unexpand" so that these functions can be made consistent with each other. All varieties of the function now always sync the selection and the layout.
1268 lines
28 KiB
C
1268 lines
28 KiB
C
/* windCmdSZ.c -
|
|
*
|
|
* This file contains Magic command routines for those commands
|
|
* that are valid in all windows.
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * 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. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windCmdSZ.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h> /* for sleep() */
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "tcltk/tclmagic.h"
|
|
#include "utils/magic.h"
|
|
#include "textio/textio.h"
|
|
#include "utils/geometry.h"
|
|
#include "tiles/tile.h"
|
|
#include "windows/windows.h"
|
|
#include "graphics/glyphs.h"
|
|
#include "windows/windInt.h"
|
|
#include "utils/undo.h"
|
|
#include "utils/utils.h"
|
|
#include "utils/signals.h"
|
|
#include "textio/txcommands.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "dbwind/dbwind.h"
|
|
#include "graphics/graphics.h"
|
|
|
|
/* C99 compat */
|
|
#include "commands/commands.h"
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windScrollCmd --
|
|
*
|
|
* Scroll the view around
|
|
*
|
|
* Usage:
|
|
* scroll dir [amount [units]]
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window underneath the cursor is changed.
|
|
* Note: behavior has been changed from original. To have "amount"
|
|
* parsed as a fractional scroll amount, "units" *must* be declared
|
|
* as "w". Otherwise, no units implies that "amount" is an absolute
|
|
* value.
|
|
*
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windScrollCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
Rect r;
|
|
int xsize, ysize;
|
|
Point p;
|
|
int pos, locargc = cmd->tx_argc;
|
|
float amount;
|
|
bool doFractional = FALSE;
|
|
|
|
if ( (cmd->tx_argc < 2) || (cmd->tx_argc > 4) )
|
|
{
|
|
TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]);
|
|
return;
|
|
}
|
|
|
|
if (w == NULL)
|
|
{
|
|
TxError("Point to a window first.\n");
|
|
return;
|
|
}
|
|
|
|
if ((w->w_flags & WIND_SCROLLABLE) == 0) {
|
|
TxError("Sorry, can't scroll this window.\n");
|
|
return;
|
|
};
|
|
|
|
pos = GeoNameToPos(cmd->tx_argv[1], FALSE, TRUE);
|
|
if (pos < 0 || pos == GEO_CENTER)
|
|
return;
|
|
|
|
if (cmd->tx_argc == 2) /* default = half-screen pan */
|
|
{
|
|
r = w->w_screenArea;
|
|
amount = 0.5;
|
|
doFractional = TRUE;
|
|
}
|
|
else if (cmd->tx_argc == 4)
|
|
{
|
|
char unitc = cmd->tx_argv[3][0];
|
|
|
|
if (unitc == 'w')
|
|
r = w->w_screenArea;
|
|
else if (unitc == 'l')
|
|
r = *(w->w_bbox);
|
|
else
|
|
{
|
|
TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]);
|
|
TxError(" 'units' must be one of 'w' (window) or 'l' (layout);\n");
|
|
return;
|
|
}
|
|
|
|
if (sscanf(cmd->tx_argv[2], "%f", &amount) != 1)
|
|
{
|
|
TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]);
|
|
TxError(" 'amount' is a fractional value.\n");
|
|
return;
|
|
}
|
|
doFractional = TRUE;
|
|
}
|
|
|
|
if (doFractional)
|
|
{
|
|
xsize = (r.r_xtop - r.r_xbot) * amount;
|
|
ysize = (r.r_ytop - r.r_ybot) * amount;
|
|
}
|
|
else
|
|
{
|
|
/* Alternate syntax: parse for integer coordinate amount to scroll */
|
|
xsize = cmdParseCoord(w, cmd->tx_argv[2], TRUE, TRUE);
|
|
ysize = cmdParseCoord(w, cmd->tx_argv[2], TRUE, FALSE);
|
|
}
|
|
|
|
p.p_x = 0;
|
|
p.p_y = 0;
|
|
|
|
switch (pos)
|
|
{
|
|
case GEO_NORTH:
|
|
p.p_y = -ysize;
|
|
break;
|
|
case GEO_SOUTH:
|
|
p.p_y = ysize;
|
|
break;
|
|
case GEO_EAST:
|
|
p.p_x = -xsize;
|
|
break;
|
|
case GEO_WEST:
|
|
p.p_x = xsize;
|
|
break;
|
|
case GEO_NORTHEAST:
|
|
p.p_x = -xsize;
|
|
p.p_y = -ysize;
|
|
break;
|
|
case GEO_NORTHWEST:
|
|
p.p_x = xsize;
|
|
p.p_y = -ysize;
|
|
break;
|
|
case GEO_SOUTHEAST:
|
|
p.p_x = -xsize;
|
|
p.p_y = ysize;
|
|
break;
|
|
case GEO_SOUTHWEST:
|
|
p.p_x = xsize;
|
|
p.p_y = ysize;
|
|
break;
|
|
}
|
|
|
|
if (doFractional)
|
|
WindScroll(w, (Point *) NULL, &p);
|
|
else
|
|
{
|
|
/* Direction is reversed w/respect to above call to WindScroll() */
|
|
p.p_x = -p.p_x;
|
|
p.p_y = -p.p_y;
|
|
WindScroll(w, &p, (Point *) NULL);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windSetpointCmd --
|
|
*
|
|
* Use the x, y specified as the location of the point tool for the
|
|
* next command.
|
|
*
|
|
* Results:
|
|
* None. Under the Tcl interpreter, returns the screen and layout
|
|
* coordinates as a list of four integers: sx sy lx ly.
|
|
*
|
|
* Side effects:
|
|
* global variables.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windSetpointCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
int wid;
|
|
Point rootPoint;
|
|
#ifdef MAGIC_WRAPPER
|
|
char *ptstr;
|
|
#endif
|
|
|
|
if ((cmd->tx_argc != 4) && (cmd->tx_argc != 3) && (cmd->tx_argc != 1))
|
|
goto usage;
|
|
if ((cmd->tx_argc != 1) && !
|
|
(StrIsInt(cmd->tx_argv[1]) && StrIsInt(cmd->tx_argv[2])) )
|
|
goto usage;
|
|
|
|
if (cmd->tx_argc == 4) {
|
|
if (StrIsInt(cmd->tx_argv[3]))
|
|
wid = atoi(cmd->tx_argv[3]);
|
|
else if (GrWindowIdPtr)
|
|
wid = (*GrWindowIdPtr)(cmd->tx_argv[3]);
|
|
else
|
|
wid = WIND_UNKNOWN_WINDOW;
|
|
}
|
|
else if (w != NULL)
|
|
wid = w->w_wid;
|
|
else {
|
|
windCheckOnlyWindow(&w, DBWclientID);
|
|
if (w != NULL)
|
|
wid = w->w_wid;
|
|
else
|
|
wid = WIND_UNKNOWN_WINDOW;
|
|
}
|
|
|
|
/* Ensure a valid window, if possible */
|
|
if (w == NULL) w = WindSearchWid(wid);
|
|
|
|
if (cmd->tx_argc == 1)
|
|
{
|
|
if (w != (MagWindow *) NULL)
|
|
{
|
|
WindPointToSurface(w, &cmd->tx_p, &rootPoint, (Rect *) NULL);
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
ptstr = (char *)Tcl_Alloc(50);
|
|
sprintf(ptstr, "%d %d %d %d", cmd->tx_p.p_x, cmd->tx_p.p_y,
|
|
rootPoint.p_x, rootPoint.p_y);
|
|
Tcl_SetResult(magicinterp, ptstr, TCL_DYNAMIC);
|
|
#else
|
|
TxPrintf("Point is at screen coordinates (%d, %d) in window %d.\n",
|
|
cmd->tx_p.p_x, cmd->tx_p.p_y, w->w_wid);
|
|
TxPrintf("Point is at layout coordinates (%d, %d)\n",
|
|
rootPoint.p_x, rootPoint.p_y);
|
|
#endif
|
|
} else {
|
|
TxPrintf("Point is at screen coordinates (%d, %d).\n",
|
|
cmd->tx_p.p_x, cmd->tx_p.p_y);
|
|
}
|
|
}
|
|
else {
|
|
int yval;
|
|
|
|
yval = atoi(cmd->tx_argv[2]);
|
|
|
|
/* Reinterpret coordinates according to the graphics package */
|
|
switch (WindPackageType)
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
/* Windows have origin at lower-left corner */
|
|
yval = w->w_allArea.r_ytop - yval;
|
|
break;
|
|
}
|
|
TxSetPoint(atoi(cmd->tx_argv[1]), yval, wid);
|
|
}
|
|
return;
|
|
|
|
usage:
|
|
TxError("Usage: %s [x y [window ID|name]]\n", cmd->tx_argv[0]);
|
|
}
|
|
|
|
int
|
|
windSetPrintProc(name, val)
|
|
char *name;
|
|
char *val;
|
|
{
|
|
TxPrintf("%s = \"%s\"\n", name, val);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windSleepCmd --
|
|
*
|
|
* Take a nap.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windSleepCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
int time;
|
|
|
|
if (cmd->tx_argc != 2)
|
|
{
|
|
TxError("Usage: %s seconds\n", cmd->tx_argv[0]);
|
|
return;
|
|
}
|
|
|
|
time = atoi(cmd->tx_argv[1]);
|
|
for ( ; time > 1; time--)
|
|
{
|
|
sleep(1);
|
|
if (SigInterruptPending) return;
|
|
}
|
|
}
|
|
|
|
#ifndef MAGIC_WRAPPER
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windSourceCmd --
|
|
*
|
|
* Implement the "source" command.
|
|
* Process a file as a list of commands.
|
|
*
|
|
* Usage:
|
|
* source filename
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Whatever the commands request.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windSourceCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
FILE *f;
|
|
|
|
if (cmd->tx_argc != 2)
|
|
{
|
|
TxError("Usage: %s filename\n", cmd->tx_argv[0]);
|
|
return;
|
|
}
|
|
|
|
f = PaOpen(cmd->tx_argv[1], "r", (char *) NULL, ".",
|
|
SysLibPath, (char **) NULL);
|
|
if (f == NULL)
|
|
TxError("Couldn't read from %s.\n", cmd->tx_argv[1]);
|
|
else {
|
|
TxDispatch(f);
|
|
(void) fclose(f);
|
|
};
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windSpecialOpenCmd --
|
|
*
|
|
* Open a new window at the cursor position. Give it a default size,
|
|
* and take the client's name from the command line. Pass the rest of
|
|
* the command arguments off to the client.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windSpecialOpenCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
WindClient wc;
|
|
Rect area;
|
|
bool haveCoords;
|
|
char *client;
|
|
|
|
haveCoords = FALSE;
|
|
|
|
if (cmd->tx_argc < 2) goto usage;
|
|
haveCoords = StrIsInt(cmd->tx_argv[1]);
|
|
if (haveCoords && (
|
|
(cmd->tx_argc < 6) ||
|
|
!StrIsInt(cmd->tx_argv[2]) ||
|
|
!StrIsInt(cmd->tx_argv[3]) ||
|
|
!StrIsInt(cmd->tx_argv[4])
|
|
)) goto usage;
|
|
if (haveCoords)
|
|
client = cmd->tx_argv[5];
|
|
else
|
|
client = cmd->tx_argv[1];
|
|
|
|
wc = WindGetClient(client, FALSE);
|
|
/* clients whose names begin with '*' are hidden */
|
|
if ((wc == (WindClient) NULL) || (client[0] == '*')) goto usage;
|
|
|
|
if (haveCoords) {
|
|
windCheckOnlyWindow(&w, wc);
|
|
|
|
area.r_xbot = atoi(cmd->tx_argv[1]);
|
|
area.r_ybot = atoi(cmd->tx_argv[2]);
|
|
area.r_xtop = MAX(atoi(cmd->tx_argv[3]), area.r_xbot + WIND_MIN_WIDTH);
|
|
area.r_ytop = MAX(atoi(cmd->tx_argv[4]), area.r_ybot + WIND_MIN_HEIGHT);
|
|
/* Assume that the client will print an error message if it fails */
|
|
(void) WindCreate(wc, &area, FALSE, cmd->tx_argc - 6, cmd->tx_argv + 6);
|
|
}
|
|
else {
|
|
area.r_xbot = cmd->tx_p.p_x - CREATE_WIDTH/2;
|
|
area.r_xtop = cmd->tx_p.p_x + CREATE_WIDTH/2;
|
|
area.r_ybot = cmd->tx_p.p_y - CREATE_HEIGHT/2;
|
|
area.r_ytop = cmd->tx_p.p_y + CREATE_HEIGHT/2;
|
|
/* Assume that the client will print an error message if it fails */
|
|
(void) WindCreate(wc, &area, TRUE, cmd->tx_argc - 2, cmd->tx_argv + 2);
|
|
}
|
|
|
|
return;
|
|
|
|
usage:
|
|
TxPrintf("Usage: specialopen [leftx bottomy rightx topy] type [args]\n");
|
|
TxPrintf("Valid window types are:\n");
|
|
WindPrintClientList(FALSE);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windNamesCmd --
|
|
*
|
|
* Register or retrieve the name associated with the layout window
|
|
*
|
|
* Results:
|
|
* Returns the name as a Tcl string result. If "all" is selected,
|
|
* or if w is NULL and cannot be determined, returns a list of all
|
|
* window names. The first argument may also be a window client
|
|
* type, in which case only windows of that type are returned.
|
|
*
|
|
* Note:
|
|
* This routine can easily be made "generic", not Tcl-specific.
|
|
* However, of the graphics interfaces available, only Tcl/Tk keeps
|
|
* track of windows by name.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windNamesCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
bool doforall = FALSE;
|
|
WindClient wc = (WindClient)NULL;
|
|
MagWindow *sw;
|
|
|
|
if (cmd->tx_argc > 2)
|
|
{
|
|
TxError("Usage: windownames [all | client_type]\n");
|
|
return;
|
|
}
|
|
if (cmd->tx_argc == 2)
|
|
{
|
|
if (!strncmp(cmd->tx_argv[1], "all", 3))
|
|
doforall = TRUE;
|
|
#ifndef THREE_D
|
|
else if (!strncmp(cmd->tx_argv[1], "wind3d", 6))
|
|
{
|
|
return; // do nothing
|
|
}
|
|
#endif /* THREE_D */
|
|
else
|
|
{
|
|
wc = WindGetClient(cmd->tx_argv[1], FALSE);
|
|
if (wc == (WindClient) NULL)
|
|
{
|
|
TxError("Usage: windownames [all | client_type]\n");
|
|
TxPrintf("Valid window types are:\n");
|
|
WindPrintClientList(FALSE);
|
|
return;
|
|
}
|
|
doforall = TRUE;
|
|
}
|
|
}
|
|
|
|
if (cmd->tx_argc == 1)
|
|
{
|
|
wc = DBWclientID;
|
|
windCheckOnlyWindow(&w, wc);
|
|
if (w == (MagWindow *)NULL)
|
|
doforall = TRUE;
|
|
}
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
if (doforall == TRUE)
|
|
{
|
|
Tcl_Obj *tlist;
|
|
|
|
tlist = Tcl_NewListObj(0, NULL);
|
|
for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow)
|
|
if ((wc == NULL) || (sw->w_client == wc))
|
|
{
|
|
if (GrWindowNamePtr)
|
|
Tcl_ListObjAppendElement(magicinterp, tlist,
|
|
Tcl_NewStringObj((*GrWindowNamePtr)(sw), -1));
|
|
else
|
|
Tcl_ListObjAppendElement(magicinterp, tlist,
|
|
Tcl_NewIntObj(sw->w_wid));
|
|
}
|
|
Tcl_SetObjResult(magicinterp, tlist);
|
|
}
|
|
else
|
|
{
|
|
if (GrWindowNamePtr)
|
|
Tcl_SetResult(magicinterp, (*GrWindowNamePtr)(w), NULL);
|
|
else
|
|
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(w->w_wid));
|
|
}
|
|
#else
|
|
if (doforall == TRUE)
|
|
{
|
|
if (GrWindowNamePtr)
|
|
TxPrintf("Window ID Window Name\n");
|
|
else
|
|
TxPrintf("Window ID\n");
|
|
for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow)
|
|
if ((wc == (WindClient)NULL) || (sw->w_client == wc))
|
|
{
|
|
if (GrWindowNamePtr)
|
|
TxPrintf("%d %s\n", sw->w_wid, (*GrWindowNamePtr)(sw));
|
|
else
|
|
TxPrintf("%d\n", sw->w_wid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GrWindowNamePtr)
|
|
TxPrintf("Window ID = %d, Name = %s\n", w->w_wid,
|
|
(*GrWindowNamePtr)(w));
|
|
else
|
|
TxPrintf("Window ID = %d\n", w->w_wid);
|
|
}
|
|
#endif /* !MAGIC_WRAPPER */
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windUnderCmd --
|
|
*
|
|
* Move a window underneath the other windows.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Screen updates.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windUnderCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
if (cmd->tx_argc != 1)
|
|
{
|
|
TxError("Usage: %s\n", cmd->tx_argv[0]);
|
|
}
|
|
if (w == NULL)
|
|
{
|
|
TxError("Point to a window first.\n");
|
|
return;
|
|
}
|
|
WindUnder(w);
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windUndoCmd
|
|
*
|
|
* Implement the "undo" command.
|
|
*
|
|
* Usage:
|
|
* undo [count]
|
|
*
|
|
* If a count is supplied, the last count events are undone. The default
|
|
* count if none is given is 1.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Calls the undo module.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windUndoCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
int count;
|
|
|
|
if (cmd->tx_argc > 3)
|
|
{
|
|
TxError("Usage: undo [count]\n");
|
|
TxError(" undo print [count]\n");
|
|
TxError(" undo enable|disable\n");
|
|
return;
|
|
}
|
|
else if (cmd->tx_argc == 3)
|
|
{
|
|
if (strncmp(cmd->tx_argv[1], "print", 5))
|
|
{
|
|
TxError("Usage: undo print count\n");
|
|
return;
|
|
}
|
|
else if (!StrIsInt(cmd->tx_argv[2]))
|
|
{
|
|
TxError("Usage: undo print count\n");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
/* Implement undo stack trace */
|
|
UndoStackTrace((-1) - atoi(cmd->tx_argv[2]));
|
|
return;
|
|
}
|
|
}
|
|
else if (cmd->tx_argc == 2)
|
|
{
|
|
if (!StrIsInt(cmd->tx_argv[1]))
|
|
{
|
|
if (!strcmp(cmd->tx_argv[1], "enable"))
|
|
UndoEnable();
|
|
else if (!strcmp(cmd->tx_argv[1], "disable"))
|
|
UndoDisable();
|
|
else
|
|
TxError("Option must be a count (integer)\n");
|
|
return;
|
|
}
|
|
count = atoi(cmd->tx_argv[1]);
|
|
if (count < 0)
|
|
{
|
|
TxError("Count must be a positive integer\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
count = 1;
|
|
|
|
if (count == 0)
|
|
{
|
|
UndoEnable();
|
|
}
|
|
else
|
|
{
|
|
if (UndoBackward(count) == 0)
|
|
TxPrintf("Nothing more to undo\n");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windUpdateCmd --
|
|
*
|
|
* Force an update of the graphics screen. This is usually only called
|
|
* from command scripts.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Display updates.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windUpdateCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
if (cmd->tx_argc == 1)
|
|
WindUpdate();
|
|
#ifdef MAGIC_WRAPPER
|
|
else if (cmd->tx_argc > 2)
|
|
goto badusage;
|
|
else if (!strcmp(cmd->tx_argv[1], "suspend"))
|
|
GrDisplayStatus = DISPLAY_SUSPEND;
|
|
else if (!strcmp(cmd->tx_argv[1], "resume"))
|
|
GrDisplayStatus = DISPLAY_IDLE;
|
|
else
|
|
goto badusage;
|
|
#else
|
|
else if (cmd->tx_argc >= 2)
|
|
goto badusage;
|
|
#endif
|
|
return;
|
|
|
|
badusage:
|
|
TxError("Usage: %s [suspend | resume]\n", cmd->tx_argv[0]);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windVersionCmd --
|
|
*
|
|
* Print version information.
|
|
*
|
|
* Usage:
|
|
* version
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Prints on stdout.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windVersionCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
if (cmd->tx_argc != 1) {
|
|
TxError("Usage: %s\n", cmd->tx_argv[0]);
|
|
return;
|
|
}
|
|
|
|
TxPrintf("Version %s revision %s. Compiled on %s.\n",
|
|
MagicVersion, MagicRevision, MagicCompileTime);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windViewCmd --
|
|
*
|
|
* Implement the "View" command.
|
|
* Change the view in the selected window so everything is visible.
|
|
*
|
|
* Usage:
|
|
* view
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window underneath the cursor is changed.
|
|
* In Tcl version, if supplied with the argument "get", the
|
|
* interpreter return value is set to the current view position.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windViewCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
if (w == NULL)
|
|
return;
|
|
|
|
if (cmd->tx_argc == 1)
|
|
{
|
|
if ((w->w_flags & WIND_SCROLLABLE) == 0) {
|
|
TxError("Sorry, can't zoom out this window.\n");
|
|
return;
|
|
}
|
|
WindView(w);
|
|
}
|
|
else if (cmd->tx_argc == 2)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_Obj *listxy, *fval;
|
|
|
|
listxy = Tcl_NewListObj(0, NULL);
|
|
#endif
|
|
|
|
if (!strncmp(cmd->tx_argv[1], "get", 3))
|
|
{
|
|
char *vllx, *vlly, *vurx, *vury;
|
|
|
|
vllx = DBWPrintValue(w->w_surfaceArea.r_xbot, w, TRUE);
|
|
vlly = DBWPrintValue(w->w_surfaceArea.r_ybot, w, FALSE);
|
|
vurx = DBWPrintValue(w->w_surfaceArea.r_xtop, w, TRUE);
|
|
vury = DBWPrintValue(w->w_surfaceArea.r_ytop, w, FALSE);
|
|
|
|
/* NOTE: The surface area is in screen (pixel) coordinates
|
|
* and so does not follow the "units" display type.
|
|
*/
|
|
#ifndef MAGIC_WRAPPER
|
|
TxPrintf("(%s, %s) to (%s, %s)\n", vllx, vlly, vurx, vury);
|
|
#else
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vllx, -1));
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vlly, -1));
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vurx, -1));
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vury, -1));
|
|
Tcl_SetObjResult(magicinterp, listxy);
|
|
#endif
|
|
}
|
|
else if (!strncmp(cmd->tx_argv[1], "bbox", 4))
|
|
{
|
|
char *vllx, *vlly, *vurx, *vury;
|
|
|
|
vllx = DBWPrintValue(w->w_bbox->r_xbot, w, TRUE);
|
|
vlly = DBWPrintValue(w->w_bbox->r_ybot, w, FALSE);
|
|
vurx = DBWPrintValue(w->w_bbox->r_xtop, w, TRUE);
|
|
vury = DBWPrintValue(w->w_bbox->r_ytop, w, FALSE);
|
|
|
|
#ifndef MAGIC_WRAPPER
|
|
TxPrintf("(%s, %s) to (%s, %s)\n", vllx, vlly, vurx, vury);
|
|
#else
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vllx, -1));
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vlly, -1));
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vurx, -1));
|
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
|
Tcl_NewStringObj(vury, -1));
|
|
Tcl_SetObjResult(magicinterp, listxy);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
char *sptr, *pptr;
|
|
Rect r;
|
|
|
|
// Parse out coordinates where all coordinates have been
|
|
// put into a single string argument, as happens when the
|
|
// coordinates are a Tcl list, e.g., from "[box values]"
|
|
|
|
sptr = cmd->tx_argv[1];
|
|
if ((pptr = strchr(sptr, ' ')) == NULL) return;
|
|
*pptr++ = '\0';
|
|
r.r_xbot = cmdParseCoord(w, sptr, FALSE, TRUE);
|
|
|
|
sptr = pptr;
|
|
if ((pptr = strchr(sptr, ' ')) == NULL) return;
|
|
*pptr++ = '\0';
|
|
r.r_ybot = cmdParseCoord(w, sptr, FALSE, TRUE);
|
|
|
|
sptr = pptr;
|
|
if ((pptr = strchr(sptr, ' ')) == NULL) return;
|
|
*pptr++ = '\0';
|
|
r.r_xtop = cmdParseCoord(w, sptr, FALSE, TRUE);
|
|
r.r_ytop = cmdParseCoord(w, pptr, FALSE, TRUE);
|
|
|
|
/* Redisplay */
|
|
WindMove(w, &r);
|
|
}
|
|
}
|
|
else if (cmd->tx_argc == 5)
|
|
{
|
|
Rect r;
|
|
r.r_xbot = cmdParseCoord(w, cmd->tx_argv[1], FALSE, TRUE);
|
|
r.r_ybot = cmdParseCoord(w, cmd->tx_argv[2], FALSE, FALSE);
|
|
r.r_xtop = cmdParseCoord(w, cmd->tx_argv[3], FALSE, TRUE);
|
|
r.r_ytop = cmdParseCoord(w, cmd->tx_argv[4], FALSE, FALSE);
|
|
|
|
/* Redisplay */
|
|
WindMove(w, &r);
|
|
}
|
|
else
|
|
{
|
|
TxError("Usage: view [get|bbox|llx lly urx ury]\n");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windXviewCmd --
|
|
*
|
|
* Implement the "Xview" command.
|
|
* Change the view in the selected window so everything is visible, but
|
|
* not expanded.
|
|
*
|
|
* Usage:
|
|
* xview
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window underneath the cursor is changed. The root cell of the
|
|
* window is unexpanded.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windXviewCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
CellUse *celluse;
|
|
int ViewUnexpandFunc();
|
|
|
|
if (w == NULL)
|
|
return;
|
|
|
|
if ((w->w_flags & WIND_SCROLLABLE) == 0) {
|
|
TxError("Sorry, can't zoom out this window.\n");
|
|
return;
|
|
};
|
|
|
|
celluse = (CellUse *) (w->w_surfaceID);
|
|
DBExpandAll(celluse, &(celluse->cu_bbox),
|
|
((DBWclientRec *)w->w_clientData)->dbw_bitmask, DB_UNEXPAND,
|
|
ViewUnexpandFunc,
|
|
(ClientData)(pointertype) (((DBWclientRec *)w->w_clientData)->dbw_bitmask));
|
|
|
|
WindView(w);
|
|
}
|
|
|
|
/* This function is called for each cell whose expansion status changed.
|
|
* It forces the cells area to be redisplayed, then returns 0 to keep
|
|
* looking for more cells to unexpand.
|
|
*/
|
|
|
|
int
|
|
ViewUnexpandFunc(use, windowMask)
|
|
CellUse *use; /* Use that was just unexpanded. */
|
|
int windowMask; /* Window where it was unexpanded. */
|
|
{
|
|
if (use->cu_parent == NULL) return 0;
|
|
DBWAreaChanged(use->cu_parent, &use->cu_bbox, windowMask,
|
|
(TileTypeBitMask *) NULL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windScrollBarsCmd --
|
|
*
|
|
* Change the flag which says whether new windows will have scroll bars.
|
|
*
|
|
* Usage:
|
|
* windscrollbars [on|off]
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* A flag is changed.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windScrollBarsCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
int place;
|
|
static const char * const onoff[] = {"on", "off", 0};
|
|
static const bool truth[] = {TRUE, FALSE};
|
|
|
|
if (cmd->tx_argc != 2) goto usage;
|
|
|
|
place = Lookup(cmd->tx_argv[1], onoff);
|
|
if (place < 0) goto usage;
|
|
|
|
if (truth[place])
|
|
{
|
|
WindDefaultFlags |= WIND_SCROLLBARS;
|
|
TxPrintf("New windows will have scroll bars.\n");
|
|
}
|
|
else
|
|
{
|
|
WindDefaultFlags &= ~WIND_SCROLLBARS;
|
|
TxPrintf("New windows will not have scroll bars.\n");
|
|
}
|
|
return;
|
|
|
|
usage:
|
|
TxError("Usage: %s [on|off]\n", cmd->tx_argv[0]);
|
|
return;
|
|
}
|
|
|
|
#ifndef MAGIC_WRAPPER
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windSendCmd --
|
|
*
|
|
* Send a command to a certain window type. If possible we will pass a
|
|
* arbitrarily chosen window of that type down to the client.
|
|
*
|
|
* Usage:
|
|
* send type command
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Whatever the client does
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windSendCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
MagWindow *toWindow;
|
|
WindClient client;
|
|
TxCommand newcmd;
|
|
extern int windSendCmdFunc();
|
|
|
|
if (cmd->tx_argc < 3) goto usage;
|
|
if (cmd->tx_argv[1][0] == '*') goto usage; /* hidden window client */
|
|
|
|
client = WindGetClient(cmd->tx_argv[1], FALSE);
|
|
if (client == (WindClient) NULL) goto usage;
|
|
toWindow = (MagWindow *) NULL;
|
|
(void) WindSearch(client, (ClientData) NULL, (Rect *) NULL,
|
|
windSendCmdFunc, (ClientData) &toWindow);
|
|
{
|
|
int i;
|
|
newcmd = *cmd;
|
|
newcmd.tx_argc -= 2;
|
|
for (i = 0; i < newcmd.tx_argc; i++) {
|
|
newcmd.tx_argv[i] = newcmd.tx_argv[i + 2];
|
|
};
|
|
}
|
|
newcmd.tx_wid = WIND_UNKNOWN_WINDOW;
|
|
if (toWindow != NULL) newcmd.tx_wid = toWindow->w_wid;
|
|
(void) WindSendCommand(toWindow, &newcmd, FALSE);
|
|
return;
|
|
|
|
usage:
|
|
TxError("Usage: send type command\n");
|
|
TxPrintf("Valid window types are:\n");
|
|
WindPrintClientList(FALSE);
|
|
return;
|
|
}
|
|
|
|
int
|
|
windSendCmdFunc(w, cd)
|
|
MagWindow *w;
|
|
ClientData cd;
|
|
{
|
|
*((MagWindow **) cd) = w;
|
|
return 1;
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Structure used by "position" command to pass to WindSearch */
|
|
/* as client data. */
|
|
|
|
typedef struct _cdwpos {
|
|
FILE *file;
|
|
bool doFrame;
|
|
} cdwpos;
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windPositionsCmd --
|
|
*
|
|
* Print out the positions of the windows.
|
|
*
|
|
* Usage:
|
|
* windowpositions [file]
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* A file is written.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windPositionsCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
extern int windPositionsFunc();
|
|
char *filename = NULL;
|
|
cdwpos windpos;
|
|
|
|
windpos.doFrame = FALSE;
|
|
windpos.file = stdout;
|
|
|
|
if (cmd->tx_argc > 3) goto usage;
|
|
if (cmd->tx_argc > 1)
|
|
{
|
|
if (!strncmp(cmd->tx_argv[1], "frame", 5))
|
|
{
|
|
windpos.doFrame = TRUE;
|
|
if (cmd->tx_argc == 3)
|
|
filename = cmd->tx_argv[2];
|
|
}
|
|
else if (cmd->tx_argc == 2)
|
|
filename = cmd->tx_argv[1];
|
|
else
|
|
goto usage;
|
|
}
|
|
|
|
if (filename) {
|
|
windpos.file = fopen(filename, "w");
|
|
if (windpos.file == (FILE *) NULL)
|
|
{
|
|
TxError("Could not open file %s for writing.\n", filename);
|
|
return;
|
|
};
|
|
}
|
|
(void) WindSearch((WindClient) NULL, (ClientData) NULL, (Rect *) NULL,
|
|
windPositionsFunc, (ClientData) &windpos);
|
|
if (filename) (void) fclose(windpos.file);
|
|
return;
|
|
|
|
usage:
|
|
TxError("Usage: windowpositions [file]\n");
|
|
return;
|
|
}
|
|
|
|
int
|
|
windPositionsFunc(w, cdata)
|
|
MagWindow *w;
|
|
ClientData cdata;
|
|
{
|
|
cdwpos *windpos = (cdwpos *)cdata;
|
|
Rect r;
|
|
|
|
if (windpos->doFrame)
|
|
r = w->w_frameArea;
|
|
else
|
|
r = w->w_screenArea;
|
|
|
|
if (windpos->file == stdout)
|
|
#ifdef MAGIC_WRAPPER
|
|
{
|
|
Tcl_Obj *lobj;
|
|
|
|
lobj = Tcl_NewListObj(0, NULL);
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_xbot));
|
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_ybot));
|
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_xtop));
|
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_ytop));
|
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
|
Tcl_NewStringObj(((clientRec *)w->w_client)->w_clientName,
|
|
strlen(((clientRec *)w->w_client)->w_clientName)));
|
|
Tcl_SetObjResult(magicinterp, lobj);
|
|
}
|
|
#else
|
|
TxPrintf("specialopen %d %d %d %d %s\n",
|
|
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop,
|
|
((clientRec *) w->w_client)->w_clientName);
|
|
#endif
|
|
else
|
|
fprintf((FILE *)cdata, "specialopen %d %d %d %d %s\n",
|
|
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop,
|
|
((clientRec *) w->w_client)->w_clientName);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windZoomCmd --
|
|
*
|
|
* Implement the "zoom" command.
|
|
* Change the view in the selected window by the given scale factor.
|
|
*
|
|
* Usage:
|
|
* zoom amount
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window underneath the cursor is changed.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windZoomCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
float factor;
|
|
|
|
if (w == NULL)
|
|
return;
|
|
|
|
if ((w->w_flags & WIND_SCROLLABLE) == 0) {
|
|
TxError("Sorry, can't zoom this window.\n");
|
|
return;
|
|
};
|
|
|
|
if (cmd->tx_argc != 2)
|
|
{
|
|
TxError("Usage: %s factor\n", cmd->tx_argv[0]);
|
|
return;
|
|
}
|
|
|
|
factor = MagAtof(cmd->tx_argv[1]);
|
|
if ((factor <= 0) || (factor >= 20))
|
|
{
|
|
TxError("zoom factor must be between 0 and 20.\n");
|
|
return;
|
|
}
|
|
|
|
WindZoom(w, factor);
|
|
}
|