/*
* tkPlace.c --
*
* This file contains code to implement a simple geometry manager
* for Tk based on absolute placement or "rubber-sheet" placement.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tkPlace.c 1.25 96/02/15 18:52:32
*/
#include "tkInt.h"
/*
* Border modes for relative placement:
*
* BM_INSIDE: relative distances computed using area inside
* all borders of master window.
* BM_OUTSIDE: relative distances computed using outside area
* that includes all borders of master.
* BM_IGNORE: border issues are ignored: place relative to
* master's actual window size.
*/
/*
* For each window whose geometry is managed by the placer there is
* a structure of the following type:
*/
typedef struct Slave {
* relative to which tkwin is placed.
* This isn't necessarily the logical
* parent of tkwin. NULL means the
* master was deleted or never assigned. */
* to same master (NULL for end of list). */
/*
* Geometry information for window; where there are both relative
* and absolute values for the same attribute (e.g. x and relX) only
* one of them is actually used, depending on flags.
*/
int x, y; /* X and Y pixel coordinates for tkwin. */
* master. */
* master. */
* given position. */
* definitions. */
} Slave;
/*
* Flag definitions for Slave structures:
*
* CHILD_WIDTH - 1 means -width was specified;
* CHILD_REL_WIDTH - 1 means -relwidth was specified.
* CHILD_HEIGHT - 1 means -height was specified;
* CHILD_REL_HEIGHT - 1 means -relheight was specified.
*/
/*
* For each master window that has a slave managed by the placer there
* is a structure of the following form:
*/
typedef struct Master {
* placed relative to this master. */
} Master;
/*
* Flag definitions for masters:
*
* PARENT_RECONFIG_PENDING - 1 means that a call to RecomputePlacement
* is already pending via a Do_When_Idle handler.
*/
/*
* The hash tables below both use Tk_Window tokens as keys. They map
* from Tk_Windows to Slave and Master structures for windows, if they
* exist.
*/
static int initialized = 0;
/*
* The following structure is the official type record for the
* placer:
*/
"place", /* name */
PlaceRequestProc, /* requestProc */
PlaceLostSlaveProc, /* lostSlaveProc */
};
/*
* Forward declarations for procedures defined later in this file:
*/
/*
*--------------------------------------------------------------
*
* Tk_PlaceCmd --
*
* This procedure is invoked to process the "place" Tcl
* commands. See the user documentation for details on
* what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*--------------------------------------------------------------
*/
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int c;
/*
* Initialize, if that hasn't been done yet.
*/
if (!initialized) {
initialized = 1;
}
if (argc < 3) {
return TCL_ERROR;
}
c = argv[1][0];
/*
* Handle special shortcut where window name is first argument.
*/
if (c == '.') {
return TCL_ERROR;
}
}
/*
* Handle more general case of option followed by window name followed
* by possible additional arguments.
*/
return TCL_ERROR;
}
if (argc < 5) {
argv[0],
" configure pathName option value ?option value ...?\"",
(char *) NULL);
return TCL_ERROR;
}
if (argc != 3) {
return TCL_ERROR;
}
return TCL_OK;
}
}
(ClientData) slavePtr);
if (argc != 3) {
return TCL_ERROR;
}
return TCL_OK;
}
} else {
}
} else {
}
} else {
}
} else {
}
(char *) NULL);
}
}
if (argc != 3) {
return TCL_ERROR;
}
}
}
} else {
"\": must be configure, forget, info, or slaves",
(char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* FindSlave --
*
* Given a Tk_Window token, find the Slave structure corresponding
* to that token (making a new one if necessary).
*
* Results:
* None.
*
* Side effects:
* A new Slave structure may be created.
*
*----------------------------------------------------------------------
*/
static Slave *
{
int new;
if (new) {
(ClientData) slavePtr);
} else {
}
return slavePtr;
}
/*
*----------------------------------------------------------------------
*
* UnlinkSlave --
*
* This procedure removes a slave window from the chain of slaves
* in its master.
*
* Results:
* None.
*
* Side effects:
* The slave list of slavePtr's master changes.
*
*----------------------------------------------------------------------
*/
static void
{
return;
}
} else {
panic("UnlinkSlave couldn't find slave to unlink");
}
break;
}
}
}
}
/*
*----------------------------------------------------------------------
*
* FindMaster --
*
* Given a Tk_Window token, find the Master structure corresponding
* to that token (making a new one if necessary).
*
* Results:
* None.
*
* Side effects:
* A new Master structure may be created.
*
*----------------------------------------------------------------------
*/
static Master *
{
int new;
if (new) {
} else {
}
return masterPtr;
}
/*
*----------------------------------------------------------------------
*
* ConfigureSlave --
*
* reconfigure the placement of a window.
*
* Results:
* A standard Tcl result. If an error occurs then a message is
* left in interp->result.
*
* Side effects:
* Information in slavePtr may change, and slavePtr's master is
* scheduled for reconfiguration.
*
*----------------------------------------------------------------------
*/
static int
* about slave. */
int argc; /* Number of config arguments. */
char **argv; /* String values for arguments. */
{
int c, result;
double d;
(char *) NULL);
return TCL_ERROR;
}
if (argc < 2) {
"\" (option with no value?)", (char *) NULL);
goto done;
}
c = argv[0][1];
goto done;
}
} else if ((c == 'b')
c = argv[1][0];
&& (length >= 2)) {
&& (length >= 2)) {
} else if ((c == 'o')
} else {
"\": must be ignore, inside, or outside",
(char *) NULL);
goto done;
}
if (argv[1][0] == 0) {
} else {
goto done;
}
}
goto done;
}
/*
* Make sure that the new master is either the logical parent
* of the slave or a descendant of that window, and that the
* master and slave aren't the same.
*/
break;
}
if (Tk_IsTopLevel(ancestor)) {
goto done;
}
}
(char *) NULL);
goto done;
}
/*
* Re-using same old master. Nothing to do.
*/
} else {
}
}
&& (length >= 5)) {
if (argv[1][0] == 0) {
} else {
goto done;
}
}
&& (length >= 5)) {
if (argv[1][0] == 0) {
} else {
goto done;
}
}
&& (length >= 5)) {
goto done;
}
&& (length >= 5)) {
goto done;
}
if (argv[1][0] == 0) {
} else {
goto done;
}
}
goto done;
}
goto done;
}
} else {
argv[0], "\": must be -anchor, -bordermode, -height, ",
"-in, -relheight, -relwidth, -relx, -rely, -width, ",
"-x, or -y", (char *) NULL);
goto done;
}
}
/*
* If there's no master specified for this slave, use its Tk_Parent.
* Then arrange for a placement recalculation in the master.
*/
done:
}
}
return result;
}
/*
*----------------------------------------------------------------------
*
* RecomputePlacement --
*
* This procedure is called as a when-idle handler. It recomputes
* the geometries of all the slaves of a given master.
*
* Results:
* None.
*
* Side effects:
* Windows may change size or shape.
*
*----------------------------------------------------------------------
*/
static void
{
/*
* Iterate over all the slaves for the master. Each slave's
* geometry can be computed independently of the other slaves.
*/
/*
* Step 1: compute size and borderwidth of master, taking into
* account desired border mode.
*/
masterBW = 0;
}
/*
* Step 2: compute size of slave (outside dimensions including
* border) and location of anchor point within master.
*/
width = 0;
}
/*
* The code below is a bit tricky. In order to round
* correctly when both relX and relWidth are specified,
* compute the location of the right edge and round that,
* then compute width. If we compute the width and round
* it, rounding errors in relX and relWidth accumulate.
*/
}
} else {
}
height = 0;
}
/*
* See note above for rounding errors in width computation.
*/
}
} else {
}
/*
* Step 3: adjust the x and y positions so that the desired
* anchor point on the slave appears at that position. Also
* adjust for the border mode and master's border.
*/
case TK_ANCHOR_N:
x -= width/2;
break;
case TK_ANCHOR_NE:
x -= width;
break;
case TK_ANCHOR_E:
x -= width;
y -= height/2;
break;
case TK_ANCHOR_SE:
x -= width;
y -= height;
break;
case TK_ANCHOR_S:
x -= width/2;
y -= height;
break;
case TK_ANCHOR_SW:
y -= height;
break;
case TK_ANCHOR_W:
y -= height/2;
break;
case TK_ANCHOR_NW:
break;
case TK_ANCHOR_CENTER:
x -= width/2;
y -= height/2;
break;
}
/*
* Step 4: adjust width and height again to reflect inside dimensions
* of window rather than outside. Also make sure that the width and
* height aren't zero.
*/
if (width <= 0) {
width = 1;
}
if (height <= 0) {
height = 1;
}
/*
* Step 5: reconfigure the window and map it if needed. If the
* slave is a child of the master, we do this ourselves. If the
* slave isn't a child of the master, let Tk_MaintainWindow do
* the work (it will re-adjust things as relevant windows map,
* unmap, and move).
*/
}
/*
* Don't map the slave unless the master is mapped: the slave
* will get mapped later, when the master is mapped.
*/
}
} else {
} else {
}
}
}
}
/*
*----------------------------------------------------------------------
*
* MasterStructureProc --
*
* This procedure is invoked by the Tk event handler when
* StructureNotify events occur for a master window.
*
* Results:
* None.
*
* Side effects:
* Structures get cleaned up if the window was deleted. If the
* window was resized then slave geometries get recomputed.
*
*----------------------------------------------------------------------
*/
static void
* referred to by eventPtr. */
{
}
}
}
/*
* When a master gets mapped, must redo the geometry computation
* so that all of its slaves get remapped.
*/
}
/*
* Unmap all of the slaves when the master gets unmapped,
* so that they don't keep redisplaying themselves.
*/
}
}
}
/*
*----------------------------------------------------------------------
*
* SlaveStructureProc --
*
* This procedure is invoked by the Tk event handler when
* StructureNotify events occur for a slave window.
*
* Results:
* None.
*
* Side effects:
* Structures get cleaned up if the window was deleted.
*
*----------------------------------------------------------------------
*/
static void
* referred to by eventPtr. */
{
}
}
/*
*----------------------------------------------------------------------
*
* PlaceRequestProc --
*
* This procedure is invoked by Tk whenever a slave managed by us
* changes its requested geometry.
*
* Results:
* None.
*
* Side effects:
* The window will get relayed out, if its requested size has
* anything to do with its actual size.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static void
* size. */
{
return;
}
return;
}
}
}
/*
*--------------------------------------------------------------
*
* PlaceLostSlaveProc --
*
* This procedure is invoked by Tk whenever some other geometry
* claims control over a slave that used to be managed by us.
*
* Results:
* None.
*
* Side effects:
* Forgets all placer-related information about the slave.
*
*--------------------------------------------------------------
*/
/* ARGSUSED */
static void
* was stolen away. */
{
}
(ClientData) slavePtr);
}