OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkGeometry.c] - Diff between revs 578 and 579

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 578 Rev 579
/*
/*
 * tkGeometry.c --
 * tkGeometry.c --
 *
 *
 *      This file contains generic Tk code for geometry management
 *      This file contains generic Tk code for geometry management
 *      (stuff that's used by all geometry managers).
 *      (stuff that's used by all geometry managers).
 *
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
 *
 *
 * See the file "license.terms" for information on usage and redistribution
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *
 * RCS: @(#) $Id: tkGeometry.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
 * RCS: @(#) $Id: tkGeometry.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
 */
 */
 
 
#include "tkPort.h"
#include "tkPort.h"
#include "tkInt.h"
#include "tkInt.h"
 
 
/*
/*
 * Data structures of the following type are used by Tk_MaintainGeometry.
 * Data structures of the following type are used by Tk_MaintainGeometry.
 * For each slave managed by Tk_MaintainGeometry, there is one of these
 * For each slave managed by Tk_MaintainGeometry, there is one of these
 * structures associated with its master.
 * structures associated with its master.
 */
 */
 
 
typedef struct MaintainSlave {
typedef struct MaintainSlave {
    Tk_Window slave;            /* The slave window being positioned. */
    Tk_Window slave;            /* The slave window being positioned. */
    Tk_Window master;           /* The master that determines slave's
    Tk_Window master;           /* The master that determines slave's
                                 * position; it must be a descendant of
                                 * position; it must be a descendant of
                                 * slave's parent. */
                                 * slave's parent. */
    int x, y;                   /* Desired position of slave relative to
    int x, y;                   /* Desired position of slave relative to
                                 * master. */
                                 * master. */
    int width, height;          /* Desired dimensions of slave. */
    int width, height;          /* Desired dimensions of slave. */
    struct MaintainSlave *nextPtr;
    struct MaintainSlave *nextPtr;
                                /* Next in list of Maintains associated
                                /* Next in list of Maintains associated
                                 * with master. */
                                 * with master. */
} MaintainSlave;
} MaintainSlave;
 
 
/*
/*
 * For each window that has been specified as a master to
 * For each window that has been specified as a master to
 * Tk_MaintainGeometry, there is a structure of the following type:
 * Tk_MaintainGeometry, there is a structure of the following type:
 */
 */
 
 
typedef struct MaintainMaster {
typedef struct MaintainMaster {
    Tk_Window ancestor;         /* The lowest ancestor of this window
    Tk_Window ancestor;         /* The lowest ancestor of this window
                                 * for which we have *not* created a
                                 * for which we have *not* created a
                                 * StructureNotify handler.  May be the
                                 * StructureNotify handler.  May be the
                                 * same as the window itself. */
                                 * same as the window itself. */
    int checkScheduled;         /* Non-zero means that there is already a
    int checkScheduled;         /* Non-zero means that there is already a
                                 * call to MaintainCheckProc scheduled as
                                 * call to MaintainCheckProc scheduled as
                                 * an idle handler. */
                                 * an idle handler. */
    MaintainSlave *slavePtr;    /* First in list of all slaves associated
    MaintainSlave *slavePtr;    /* First in list of all slaves associated
                                 * with this master. */
                                 * with this master. */
} MaintainMaster;
} MaintainMaster;
 
 
/*
/*
 * Hash table that maps from a master's Tk_Window token to a list of
 * Hash table that maps from a master's Tk_Window token to a list of
 * Maintains for that master:
 * Maintains for that master:
 */
 */
 
 
static Tcl_HashTable maintainHashTable;
static Tcl_HashTable maintainHashTable;
 
 
/*
/*
 * Has maintainHashTable been initialized yet?
 * Has maintainHashTable been initialized yet?
 */
 */
 
 
static int initialized = 0;
static int initialized = 0;
 
 
/*
/*
 * Prototypes for static procedures in this file:
 * Prototypes for static procedures in this file:
 */
 */
 
 
static void             MaintainCheckProc _ANSI_ARGS_((ClientData clientData));
static void             MaintainCheckProc _ANSI_ARGS_((ClientData clientData));
static void             MaintainMasterProc _ANSI_ARGS_((ClientData clientData,
static void             MaintainMasterProc _ANSI_ARGS_((ClientData clientData,
                            XEvent *eventPtr));
                            XEvent *eventPtr));
static void             MaintainSlaveProc _ANSI_ARGS_((ClientData clientData,
static void             MaintainSlaveProc _ANSI_ARGS_((ClientData clientData,
                            XEvent *eventPtr));
                            XEvent *eventPtr));


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_ManageGeometry --
 * Tk_ManageGeometry --
 *
 *
 *      Arrange for a particular procedure to manage the geometry
 *      Arrange for a particular procedure to manage the geometry
 *      of a given slave window.
 *      of a given slave window.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Proc becomes the new geometry manager for tkwin, replacing
 *      Proc becomes the new geometry manager for tkwin, replacing
 *      any previous geometry manager.  The geometry manager will
 *      any previous geometry manager.  The geometry manager will
 *      be notified (by calling procedures in *mgrPtr) when interesting
 *      be notified (by calling procedures in *mgrPtr) when interesting
 *      things happen in the future.  If there was an existing geometry
 *      things happen in the future.  If there was an existing geometry
 *      manager for tkwin different from the new one, it is notified
 *      manager for tkwin different from the new one, it is notified
 *      by calling its lostSlaveProc.
 *      by calling its lostSlaveProc.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_ManageGeometry(tkwin, mgrPtr, clientData)
Tk_ManageGeometry(tkwin, mgrPtr, clientData)
    Tk_Window tkwin;            /* Window whose geometry is to
    Tk_Window tkwin;            /* Window whose geometry is to
                                 * be managed by proc.  */
                                 * be managed by proc.  */
    Tk_GeomMgr *mgrPtr;         /* Static structure describing the
    Tk_GeomMgr *mgrPtr;         /* Static structure describing the
                                 * geometry manager.  This structure
                                 * geometry manager.  This structure
                                 * must never go away. */
                                 * must never go away. */
    ClientData clientData;      /* Arbitrary one-word argument to
    ClientData clientData;      /* Arbitrary one-word argument to
                                 * pass to geometry manager procedures. */
                                 * pass to geometry manager procedures. */
{
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    register TkWindow *winPtr = (TkWindow *) tkwin;
 
 
    if ((winPtr->geomMgrPtr != NULL) && (mgrPtr != NULL)
    if ((winPtr->geomMgrPtr != NULL) && (mgrPtr != NULL)
            && ((winPtr->geomMgrPtr != mgrPtr)
            && ((winPtr->geomMgrPtr != mgrPtr)
                || (winPtr->geomData != clientData))
                || (winPtr->geomData != clientData))
            && (winPtr->geomMgrPtr->lostSlaveProc != NULL)) {
            && (winPtr->geomMgrPtr->lostSlaveProc != NULL)) {
        (*winPtr->geomMgrPtr->lostSlaveProc)(winPtr->geomData, tkwin);
        (*winPtr->geomMgrPtr->lostSlaveProc)(winPtr->geomData, tkwin);
    }
    }
 
 
    winPtr->geomMgrPtr = mgrPtr;
    winPtr->geomMgrPtr = mgrPtr;
    winPtr->geomData = clientData;
    winPtr->geomData = clientData;
}
}


/*
/*
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 *
 *
 * Tk_GeometryRequest --
 * Tk_GeometryRequest --
 *
 *
 *      This procedure is invoked by widget code to indicate
 *      This procedure is invoked by widget code to indicate
 *      its preferences about the size of a window it manages.
 *      its preferences about the size of a window it manages.
 *      In general, widget code should call this procedure
 *      In general, widget code should call this procedure
 *      rather than Tk_ResizeWindow.
 *      rather than Tk_ResizeWindow.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      The geometry manager for tkwin (if any) is invoked to
 *      The geometry manager for tkwin (if any) is invoked to
 *      handle the request.  If possible, it will reconfigure
 *      handle the request.  If possible, it will reconfigure
 *      tkwin and/or other windows to satisfy the request.  The
 *      tkwin and/or other windows to satisfy the request.  The
 *      caller gets no indication of success or failure, but it
 *      caller gets no indication of success or failure, but it
 *      will get X events if the window size was actually
 *      will get X events if the window size was actually
 *      changed.
 *      changed.
 *
 *
 *--------------------------------------------------------------
 *--------------------------------------------------------------
 */
 */
 
 
void
void
Tk_GeometryRequest(tkwin, reqWidth, reqHeight)
Tk_GeometryRequest(tkwin, reqWidth, reqHeight)
    Tk_Window tkwin;            /* Window that geometry information
    Tk_Window tkwin;            /* Window that geometry information
                                 * pertains to. */
                                 * pertains to. */
    int reqWidth, reqHeight;    /* Minimum desired dimensions for
    int reqWidth, reqHeight;    /* Minimum desired dimensions for
                                 * window, in pixels. */
                                 * window, in pixels. */
{
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    register TkWindow *winPtr = (TkWindow *) tkwin;
 
 
    /*
    /*
     * X gets very upset if a window requests a width or height of
     * X gets very upset if a window requests a width or height of
     * zero, so rounds requested sizes up to at least 1.
     * zero, so rounds requested sizes up to at least 1.
     */
     */
 
 
    if (reqWidth <= 0) {
    if (reqWidth <= 0) {
        reqWidth = 1;
        reqWidth = 1;
    }
    }
    if (reqHeight <= 0) {
    if (reqHeight <= 0) {
        reqHeight = 1;
        reqHeight = 1;
    }
    }
    if ((reqWidth == winPtr->reqWidth) && (reqHeight == winPtr->reqHeight)) {
    if ((reqWidth == winPtr->reqWidth) && (reqHeight == winPtr->reqHeight)) {
        return;
        return;
    }
    }
    winPtr->reqWidth = reqWidth;
    winPtr->reqWidth = reqWidth;
    winPtr->reqHeight = reqHeight;
    winPtr->reqHeight = reqHeight;
    if ((winPtr->geomMgrPtr != NULL)
    if ((winPtr->geomMgrPtr != NULL)
            && (winPtr->geomMgrPtr->requestProc != NULL)) {
            && (winPtr->geomMgrPtr->requestProc != NULL)) {
        (*winPtr->geomMgrPtr->requestProc)(winPtr->geomData, tkwin);
        (*winPtr->geomMgrPtr->requestProc)(winPtr->geomData, tkwin);
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * Tk_SetInternalBorder --
 * Tk_SetInternalBorder --
 *
 *
 *      Notify relevant geometry managers that a window has an internal
 *      Notify relevant geometry managers that a window has an internal
 *      border of a given width and that child windows should not be
 *      border of a given width and that child windows should not be
 *      placed on that border.
 *      placed on that border.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      The border width is recorded for the window, and all geometry
 *      The border width is recorded for the window, and all geometry
 *      managers of all children are notified so that can re-layout, if
 *      managers of all children are notified so that can re-layout, if
 *      necessary.
 *      necessary.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
void
void
Tk_SetInternalBorder(tkwin, width)
Tk_SetInternalBorder(tkwin, width)
    Tk_Window tkwin;            /* Window that will have internal border. */
    Tk_Window tkwin;            /* Window that will have internal border. */
    int width;                  /* Width of internal border, in pixels. */
    int width;                  /* Width of internal border, in pixels. */
{
{
    register TkWindow *winPtr = (TkWindow *) tkwin;
    register TkWindow *winPtr = (TkWindow *) tkwin;
 
 
    if (width == winPtr->internalBorderWidth) {
    if (width == winPtr->internalBorderWidth) {
        return;
        return;
    }
    }
    if (width < 0) {
    if (width < 0) {
        width = 0;
        width = 0;
    }
    }
    winPtr->internalBorderWidth = width;
    winPtr->internalBorderWidth = width;
 
 
    /*
    /*
     * All the slaves for which this is the master window must now be
     * All the slaves for which this is the master window must now be
     * repositioned to take account of the new internal border width.
     * repositioned to take account of the new internal border width.
     * To signal all the geometry managers to do this, just resize the
     * To signal all the geometry managers to do this, just resize the
     * window to its current size.  The ConfigureNotify event will
     * window to its current size.  The ConfigureNotify event will
     * cause geometry managers to recompute everything.
     * cause geometry managers to recompute everything.
     */
     */
 
 
    Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));
    Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * Tk_MaintainGeometry --
 * Tk_MaintainGeometry --
 *
 *
 *      This procedure is invoked by geometry managers to handle slaves
 *      This procedure is invoked by geometry managers to handle slaves
 *      whose master's are not their parents.  It translates the desired
 *      whose master's are not their parents.  It translates the desired
 *      geometry for the slave into the coordinate system of the parent
 *      geometry for the slave into the coordinate system of the parent
 *      and respositions the slave if it isn't already at the right place.
 *      and respositions the slave if it isn't already at the right place.
 *      Furthermore, it sets up event handlers so that if the master (or
 *      Furthermore, it sets up event handlers so that if the master (or
 *      any of its ancestors up to the slave's parent) is mapped, unmapped,
 *      any of its ancestors up to the slave's parent) is mapped, unmapped,
 *      or moved, then the slave will be adjusted to match.
 *      or moved, then the slave will be adjusted to match.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Event handlers are created and state is allocated to keep track
 *      Event handlers are created and state is allocated to keep track
 *      of slave.  Note:  if slave was already managed for master by
 *      of slave.  Note:  if slave was already managed for master by
 *      Tk_MaintainGeometry, then the previous information is replaced
 *      Tk_MaintainGeometry, then the previous information is replaced
 *      with the new information.  The caller must eventually call
 *      with the new information.  The caller must eventually call
 *      Tk_UnmaintainGeometry to eliminate the correspondence (or, the
 *      Tk_UnmaintainGeometry to eliminate the correspondence (or, the
 *      state is automatically freed when either window is destroyed).
 *      state is automatically freed when either window is destroyed).
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
void
void
Tk_MaintainGeometry(slave, master, x, y, width, height)
Tk_MaintainGeometry(slave, master, x, y, width, height)
    Tk_Window slave;            /* Slave for geometry management. */
    Tk_Window slave;            /* Slave for geometry management. */
    Tk_Window master;           /* Master for slave; must be a descendant
    Tk_Window master;           /* Master for slave; must be a descendant
                                 * of slave's parent. */
                                 * of slave's parent. */
    int x, y;                   /* Desired position of slave within master. */
    int x, y;                   /* Desired position of slave within master. */
    int width, height;          /* Desired dimensions for slave. */
    int width, height;          /* Desired dimensions for slave. */
{
{
    Tcl_HashEntry *hPtr;
    Tcl_HashEntry *hPtr;
    MaintainMaster *masterPtr;
    MaintainMaster *masterPtr;
    register MaintainSlave *slavePtr;
    register MaintainSlave *slavePtr;
    int new, map;
    int new, map;
    Tk_Window ancestor, parent;
    Tk_Window ancestor, parent;
 
 
    if (!initialized) {
    if (!initialized) {
        initialized = 1;
        initialized = 1;
        Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS);
        Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS);
    }
    }
 
 
    /*
    /*
     * See if there is already a MaintainMaster structure for the master;
     * See if there is already a MaintainMaster structure for the master;
     * if not, then create one.
     * if not, then create one.
     */
     */
 
 
    parent = Tk_Parent(slave);
    parent = Tk_Parent(slave);
    hPtr = Tcl_CreateHashEntry(&maintainHashTable, (char *) master, &new);
    hPtr = Tcl_CreateHashEntry(&maintainHashTable, (char *) master, &new);
    if (!new) {
    if (!new) {
        masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr);
        masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr);
    } else {
    } else {
        masterPtr = (MaintainMaster *) ckalloc(sizeof(MaintainMaster));
        masterPtr = (MaintainMaster *) ckalloc(sizeof(MaintainMaster));
        masterPtr->ancestor = master;
        masterPtr->ancestor = master;
        masterPtr->checkScheduled = 0;
        masterPtr->checkScheduled = 0;
        masterPtr->slavePtr = NULL;
        masterPtr->slavePtr = NULL;
        Tcl_SetHashValue(hPtr, masterPtr);
        Tcl_SetHashValue(hPtr, masterPtr);
    }
    }
 
 
    /*
    /*
     * Create a MaintainSlave structure for the slave if there isn't
     * Create a MaintainSlave structure for the slave if there isn't
     * already one.
     * already one.
     */
     */
 
 
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
            slavePtr = slavePtr->nextPtr) {
            slavePtr = slavePtr->nextPtr) {
        if (slavePtr->slave == slave) {
        if (slavePtr->slave == slave) {
            goto gotSlave;
            goto gotSlave;
        }
        }
    }
    }
    slavePtr = (MaintainSlave *) ckalloc(sizeof(MaintainSlave));
    slavePtr = (MaintainSlave *) ckalloc(sizeof(MaintainSlave));
    slavePtr->slave = slave;
    slavePtr->slave = slave;
    slavePtr->master = master;
    slavePtr->master = master;
    slavePtr->nextPtr = masterPtr->slavePtr;
    slavePtr->nextPtr = masterPtr->slavePtr;
    masterPtr->slavePtr = slavePtr;
    masterPtr->slavePtr = slavePtr;
    Tk_CreateEventHandler(slave, StructureNotifyMask, MaintainSlaveProc,
    Tk_CreateEventHandler(slave, StructureNotifyMask, MaintainSlaveProc,
            (ClientData) slavePtr);
            (ClientData) slavePtr);
 
 
    /*
    /*
     * Make sure that there are event handlers registered for all
     * Make sure that there are event handlers registered for all
     * the windows between master and slave's parent (including master
     * the windows between master and slave's parent (including master
     * but not slave's parent).  There may already be handlers for master
     * but not slave's parent).  There may already be handlers for master
     * and some of its ancestors (masterPtr->ancestor tells how many).
     * and some of its ancestors (masterPtr->ancestor tells how many).
     */
     */
 
 
    for (ancestor = master; ancestor != parent;
    for (ancestor = master; ancestor != parent;
            ancestor = Tk_Parent(ancestor)) {
            ancestor = Tk_Parent(ancestor)) {
        if (ancestor == masterPtr->ancestor) {
        if (ancestor == masterPtr->ancestor) {
            Tk_CreateEventHandler(ancestor, StructureNotifyMask,
            Tk_CreateEventHandler(ancestor, StructureNotifyMask,
                    MaintainMasterProc, (ClientData) masterPtr);
                    MaintainMasterProc, (ClientData) masterPtr);
            masterPtr->ancestor = Tk_Parent(ancestor);
            masterPtr->ancestor = Tk_Parent(ancestor);
        }
        }
    }
    }
 
 
    /*
    /*
     * Fill in up-to-date information in the structure, then update the
     * Fill in up-to-date information in the structure, then update the
     * window if it's not currently in the right place or state.
     * window if it's not currently in the right place or state.
     */
     */
 
 
    gotSlave:
    gotSlave:
    slavePtr->x = x;
    slavePtr->x = x;
    slavePtr->y = y;
    slavePtr->y = y;
    slavePtr->width = width;
    slavePtr->width = width;
    slavePtr->height = height;
    slavePtr->height = height;
    map = 1;
    map = 1;
    for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
    for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
        if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
        if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
            map = 0;
            map = 0;
        }
        }
        if (ancestor == parent) {
        if (ancestor == parent) {
            if ((x != Tk_X(slavePtr->slave))
            if ((x != Tk_X(slavePtr->slave))
                    || (y != Tk_Y(slavePtr->slave))
                    || (y != Tk_Y(slavePtr->slave))
                    || (width != Tk_Width(slavePtr->slave))
                    || (width != Tk_Width(slavePtr->slave))
                    || (height != Tk_Height(slavePtr->slave))) {
                    || (height != Tk_Height(slavePtr->slave))) {
                Tk_MoveResizeWindow(slavePtr->slave, x, y, width, height);
                Tk_MoveResizeWindow(slavePtr->slave, x, y, width, height);
            }
            }
            if (map) {
            if (map) {
                Tk_MapWindow(slavePtr->slave);
                Tk_MapWindow(slavePtr->slave);
            } else {
            } else {
                Tk_UnmapWindow(slavePtr->slave);
                Tk_UnmapWindow(slavePtr->slave);
            }
            }
            break;
            break;
        }
        }
        x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
        x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
        y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
        y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * Tk_UnmaintainGeometry --
 * Tk_UnmaintainGeometry --
 *
 *
 *      This procedure cancels a previous Tk_MaintainGeometry call,
 *      This procedure cancels a previous Tk_MaintainGeometry call,
 *      so that the relationship between slave and master is no longer
 *      so that the relationship between slave and master is no longer
 *      maintained.
 *      maintained.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      The slave is unmapped and state is released, so that slave won't
 *      The slave is unmapped and state is released, so that slave won't
 *      track master any more.  If we weren't previously managing slave
 *      track master any more.  If we weren't previously managing slave
 *      relative to master, then this procedure has no effect.
 *      relative to master, then this procedure has no effect.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
void
void
Tk_UnmaintainGeometry(slave, master)
Tk_UnmaintainGeometry(slave, master)
    Tk_Window slave;            /* Slave for geometry management. */
    Tk_Window slave;            /* Slave for geometry management. */
    Tk_Window master;           /* Master for slave; must be a descendant
    Tk_Window master;           /* Master for slave; must be a descendant
                                 * of slave's parent. */
                                 * of slave's parent. */
{
{
    Tcl_HashEntry *hPtr;
    Tcl_HashEntry *hPtr;
    MaintainMaster *masterPtr;
    MaintainMaster *masterPtr;
    register MaintainSlave *slavePtr, *prevPtr;
    register MaintainSlave *slavePtr, *prevPtr;
    Tk_Window ancestor;
    Tk_Window ancestor;
 
 
    if (!initialized) {
    if (!initialized) {
        initialized = 1;
        initialized = 1;
        Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS);
        Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS);
    }
    }
 
 
    if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) {
    if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) {
        Tk_UnmapWindow(slave);
        Tk_UnmapWindow(slave);
    }
    }
    hPtr = Tcl_FindHashEntry(&maintainHashTable, (char *) master);
    hPtr = Tcl_FindHashEntry(&maintainHashTable, (char *) master);
    if (hPtr == NULL) {
    if (hPtr == NULL) {
        return;
        return;
    }
    }
    masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr);
    masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr);
    slavePtr = masterPtr->slavePtr;
    slavePtr = masterPtr->slavePtr;
    if (slavePtr->slave == slave) {
    if (slavePtr->slave == slave) {
        masterPtr->slavePtr = slavePtr->nextPtr;
        masterPtr->slavePtr = slavePtr->nextPtr;
    } else {
    } else {
        for (prevPtr = slavePtr, slavePtr = slavePtr->nextPtr; ;
        for (prevPtr = slavePtr, slavePtr = slavePtr->nextPtr; ;
                prevPtr = slavePtr, slavePtr = slavePtr->nextPtr) {
                prevPtr = slavePtr, slavePtr = slavePtr->nextPtr) {
            if (slavePtr == NULL) {
            if (slavePtr == NULL) {
                return;
                return;
            }
            }
            if (slavePtr->slave == slave) {
            if (slavePtr->slave == slave) {
                prevPtr->nextPtr = slavePtr->nextPtr;
                prevPtr->nextPtr = slavePtr->nextPtr;
                break;
                break;
            }
            }
        }
        }
    }
    }
    Tk_DeleteEventHandler(slavePtr->slave, StructureNotifyMask,
    Tk_DeleteEventHandler(slavePtr->slave, StructureNotifyMask,
            MaintainSlaveProc, (ClientData) slavePtr);
            MaintainSlaveProc, (ClientData) slavePtr);
    ckfree((char *) slavePtr);
    ckfree((char *) slavePtr);
    if (masterPtr->slavePtr == NULL) {
    if (masterPtr->slavePtr == NULL) {
        if (masterPtr->ancestor != NULL) {
        if (masterPtr->ancestor != NULL) {
            for (ancestor = master; ; ancestor = Tk_Parent(ancestor)) {
            for (ancestor = master; ; ancestor = Tk_Parent(ancestor)) {
                Tk_DeleteEventHandler(ancestor, StructureNotifyMask,
                Tk_DeleteEventHandler(ancestor, StructureNotifyMask,
                        MaintainMasterProc, (ClientData) masterPtr);
                        MaintainMasterProc, (ClientData) masterPtr);
                if (ancestor == masterPtr->ancestor) {
                if (ancestor == masterPtr->ancestor) {
                    break;
                    break;
                }
                }
            }
            }
        }
        }
        if (masterPtr->checkScheduled) {
        if (masterPtr->checkScheduled) {
            Tcl_CancelIdleCall(MaintainCheckProc, (ClientData) masterPtr);
            Tcl_CancelIdleCall(MaintainCheckProc, (ClientData) masterPtr);
        }
        }
        Tcl_DeleteHashEntry(hPtr);
        Tcl_DeleteHashEntry(hPtr);
        ckfree((char *) masterPtr);
        ckfree((char *) masterPtr);
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * MaintainMasterProc --
 * MaintainMasterProc --
 *
 *
 *      This procedure is invoked by the Tk event dispatcher in
 *      This procedure is invoked by the Tk event dispatcher in
 *      response to StructureNotify events on the master or one
 *      response to StructureNotify events on the master or one
 *      of its ancestors, on behalf of Tk_MaintainGeometry.
 *      of its ancestors, on behalf of Tk_MaintainGeometry.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      It schedules a call to MaintainCheckProc, which will eventually
 *      It schedules a call to MaintainCheckProc, which will eventually
 *      caused the postions and mapped states to be recalculated for all
 *      caused the postions and mapped states to be recalculated for all
 *      the maintained slaves of the master.  Or, if the master window is
 *      the maintained slaves of the master.  Or, if the master window is
 *      being deleted then state is cleaned up.
 *      being deleted then state is cleaned up.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
MaintainMasterProc(clientData, eventPtr)
MaintainMasterProc(clientData, eventPtr)
    ClientData clientData;              /* Pointer to MaintainMaster structure
    ClientData clientData;              /* Pointer to MaintainMaster structure
                                         * for the master window. */
                                         * for the master window. */
    XEvent *eventPtr;                   /* Describes what just happened. */
    XEvent *eventPtr;                   /* Describes what just happened. */
{
{
    MaintainMaster *masterPtr = (MaintainMaster *) clientData;
    MaintainMaster *masterPtr = (MaintainMaster *) clientData;
    MaintainSlave *slavePtr;
    MaintainSlave *slavePtr;
    int done;
    int done;
 
 
    if ((eventPtr->type == ConfigureNotify)
    if ((eventPtr->type == ConfigureNotify)
            || (eventPtr->type == MapNotify)
            || (eventPtr->type == MapNotify)
            || (eventPtr->type == UnmapNotify)) {
            || (eventPtr->type == UnmapNotify)) {
        if (!masterPtr->checkScheduled) {
        if (!masterPtr->checkScheduled) {
            masterPtr->checkScheduled = 1;
            masterPtr->checkScheduled = 1;
            Tcl_DoWhenIdle(MaintainCheckProc, (ClientData) masterPtr);
            Tcl_DoWhenIdle(MaintainCheckProc, (ClientData) masterPtr);
        }
        }
    } else if (eventPtr->type == DestroyNotify) {
    } else if (eventPtr->type == DestroyNotify) {
        /*
        /*
         * Delete all of the state associated with this master, but
         * Delete all of the state associated with this master, but
         * be careful not to use masterPtr after the last slave is
         * be careful not to use masterPtr after the last slave is
         * deleted, since its memory will have been freed.
         * deleted, since its memory will have been freed.
         */
         */
 
 
        done = 0;
        done = 0;
        do {
        do {
            slavePtr = masterPtr->slavePtr;
            slavePtr = masterPtr->slavePtr;
            if (slavePtr->nextPtr == NULL) {
            if (slavePtr->nextPtr == NULL) {
                done = 1;
                done = 1;
            }
            }
            Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
            Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
        } while (!done);
        } while (!done);
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * MaintainSlaveProc --
 * MaintainSlaveProc --
 *
 *
 *      This procedure is invoked by the Tk event dispatcher in
 *      This procedure is invoked by the Tk event dispatcher in
 *      response to StructureNotify events on a slave being managed
 *      response to StructureNotify events on a slave being managed
 *      by Tk_MaintainGeometry.
 *      by Tk_MaintainGeometry.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      If the event is a DestroyNotify event then the Maintain state
 *      If the event is a DestroyNotify event then the Maintain state
 *      and event handlers for this slave are deleted.
 *      and event handlers for this slave are deleted.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
MaintainSlaveProc(clientData, eventPtr)
MaintainSlaveProc(clientData, eventPtr)
    ClientData clientData;              /* Pointer to MaintainSlave structure
    ClientData clientData;              /* Pointer to MaintainSlave structure
                                         * for master-slave pair. */
                                         * for master-slave pair. */
    XEvent *eventPtr;                   /* Describes what just happened. */
    XEvent *eventPtr;                   /* Describes what just happened. */
{
{
    MaintainSlave *slavePtr = (MaintainSlave *) clientData;
    MaintainSlave *slavePtr = (MaintainSlave *) clientData;
 
 
    if (eventPtr->type == DestroyNotify) {
    if (eventPtr->type == DestroyNotify) {
        Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
        Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * MaintainCheckProc --
 * MaintainCheckProc --
 *
 *
 *      This procedure is invoked by the Tk event dispatcher as an
 *      This procedure is invoked by the Tk event dispatcher as an
 *      idle handler, when a master or one of its ancestors has been
 *      idle handler, when a master or one of its ancestors has been
 *      reconfigured, mapped, or unmapped.  Its job is to scan all of
 *      reconfigured, mapped, or unmapped.  Its job is to scan all of
 *      the slaves for the master and reposition them, map them, or
 *      the slaves for the master and reposition them, map them, or
 *      unmap them as needed to maintain their geometry relative to
 *      unmap them as needed to maintain their geometry relative to
 *      the master.
 *      the master.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Slaves can get repositioned, mapped, or unmapped.
 *      Slaves can get repositioned, mapped, or unmapped.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
MaintainCheckProc(clientData)
MaintainCheckProc(clientData)
    ClientData clientData;              /* Pointer to MaintainMaster structure
    ClientData clientData;              /* Pointer to MaintainMaster structure
                                         * for the master window. */
                                         * for the master window. */
{
{
    MaintainMaster *masterPtr = (MaintainMaster *) clientData;
    MaintainMaster *masterPtr = (MaintainMaster *) clientData;
    MaintainSlave *slavePtr;
    MaintainSlave *slavePtr;
    Tk_Window ancestor, parent;
    Tk_Window ancestor, parent;
    int x, y, map;
    int x, y, map;
 
 
    masterPtr->checkScheduled = 0;
    masterPtr->checkScheduled = 0;
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
            slavePtr = slavePtr->nextPtr) {
            slavePtr = slavePtr->nextPtr) {
        parent = Tk_Parent(slavePtr->slave);
        parent = Tk_Parent(slavePtr->slave);
        x = slavePtr->x;
        x = slavePtr->x;
        y = slavePtr->y;
        y = slavePtr->y;
        map = 1;
        map = 1;
        for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
        for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
            if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
            if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
                map = 0;
                map = 0;
            }
            }
            if (ancestor == parent) {
            if (ancestor == parent) {
                if ((x != Tk_X(slavePtr->slave))
                if ((x != Tk_X(slavePtr->slave))
                        || (y != Tk_Y(slavePtr->slave))) {
                        || (y != Tk_Y(slavePtr->slave))) {
                    Tk_MoveWindow(slavePtr->slave, x, y);
                    Tk_MoveWindow(slavePtr->slave, x, y);
                }
                }
                if (map) {
                if (map) {
                    Tk_MapWindow(slavePtr->slave);
                    Tk_MapWindow(slavePtr->slave);
                } else {
                } else {
                    Tk_UnmapWindow(slavePtr->slave);
                    Tk_UnmapWindow(slavePtr->slave);
                }
                }
                break;
                break;
            }
            }
            x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
            x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
            y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
            y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
        }
        }
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.