📄 tkpack.c
字号:
/* * tkPack.c -- * * This file contains code to implement the "packer" * geometry manager for Tk. * * Copyright (c) 1990-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: @(#) tkPack.c 1.64 96/05/03 10:51:52 */#include "tkPort.h"#include "tkInt.h"typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side;/* For each window that the packer cares about (either because * the window is managed by the packer or because the window * has slaves that are managed by the packer), there is a * structure of the following type: */typedef struct Packer { Tk_Window tkwin; /* Tk token for window. NULL means that * the window has been deleted, but the * packet hasn't had a chance to clean up * yet because the structure is still in * use. */ struct Packer *masterPtr; /* Master window within which this window * is packed (NULL means this window * isn't managed by the packer). */ struct Packer *nextPtr; /* Next window packed within same * parent. List is priority-ordered: * first on list gets packed first. */ struct Packer *slavePtr; /* First in list of slaves packed * inside this window (NULL means * no packed slaves). */ Side side; /* Side of parent against which * this window is packed. */ Tk_Anchor anchor; /* If frame allocated for window is larger * than window needs, this indicates how * where to position window in frame. */ int padX, padY; /* Total additional pixels to leave around the * window (half of this space is left on each * side). This is space *outside* the window: * we'll allocate extra space in frame but * won't enlarge window). */ int iPadX, iPadY; /* Total extra pixels to allocate inside the * window (half this amount will appear on * each side). */ int doubleBw; /* Twice the window's last known border * width. If this changes, the window * must be repacked within its parent. */ int *abortPtr; /* If non-NULL, it means that there is a nested * call to ArrangePacking already working on * this window. *abortPtr may be set to 1 to * abort that nested call. This happens, for * example, if tkwin or any of its slaves * is deleted. */ int flags; /* Miscellaneous flags; see below * for definitions. */} Packer;/* * Flag values for Packer structures: * * REQUESTED_REPACK: 1 means a Tcl_DoWhenIdle request * has already been made to repack * all the slaves of this window. * FILLX: 1 means if frame allocated for window * is wider than window needs, expand window * to fill frame. 0 means don't make window * any larger than needed. * FILLY: Same as FILLX, except for height. * EXPAND: 1 means this window's frame will absorb any * extra space in the parent window. * OLD_STYLE: 1 means this window is being managed with * the old-style packer algorithms (before * Tk version 3.3). The main difference is * that padding and filling are done differently. * DONT_PROPAGATE: 1 means don't set this window's requested * size. 0 means if this window is a master * then Tk will set its requested size to fit * the needs of its slaves. */#define REQUESTED_REPACK 1#define FILLX 2#define FILLY 4#define EXPAND 8#define OLD_STYLE 16#define DONT_PROPAGATE 32/* * Hash table used to map from Tk_Window tokens to corresponding * Packer structures: */static Tcl_HashTable packerHashTable;/* * Have statics in this module been initialized? */static int initialized = 0;/* * The following structure is the official type record for the * packer: */static void PackReqProc _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin));static void PackLostSlaveProc _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin));static Tk_GeomMgr packerType = { "pack", /* name */ PackReqProc, /* requestProc */ PackLostSlaveProc, /* lostSlaveProc */};/* * Forward declarations for procedures defined later in this file: */static void ArrangePacking _ANSI_ARGS_((ClientData clientData));static int ConfigureSlaves _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, int argc, char *argv[]));static void DestroyPacker _ANSI_ARGS_((char *memPtr));static Packer * GetPacker _ANSI_ARGS_((Tk_Window tkwin));static int PackAfter _ANSI_ARGS_((Tcl_Interp *interp, Packer *prevPtr, Packer *masterPtr, int argc, char **argv));static void PackReqProc _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin));static void PackStructureProc _ANSI_ARGS_((ClientData clientData, XEvent *eventPtr));static void Unlink _ANSI_ARGS_((Packer *packPtr));static int XExpansion _ANSI_ARGS_((Packer *slavePtr, int cavityWidth));static int YExpansion _ANSI_ARGS_((Packer *slavePtr, int cavityHeight));/* *-------------------------------------------------------------- * * Tk_PackCmd -- * * This procedure is invoked to process the "pack" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */intTk_PackCmd(clientData, interp, argc, argv) ClientData clientData; /* Main window associated with * interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ Tk_Window tkwin = (Tk_Window) clientData; size_t length; int c; if ((argc >= 2) && (argv[1][0] == '.')) { return ConfigureSlaves(interp, tkwin, argc-1, argv+1); } if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option arg ?arg ...?\"", (char *) NULL); return TCL_ERROR; } c = argv[1][0]; length = strlen(argv[1]); if ((c == 'a') && (length >= 2) && (strncmp(argv[1], "after", length) == 0)) { Packer *prevPtr; Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(interp, argv[2], tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } prevPtr = GetPacker(tkwin2); if (prevPtr->masterPtr == NULL) { Tcl_AppendResult(interp, "window \"", argv[2], "\" isn't packed", (char *) NULL); return TCL_ERROR; } return PackAfter(interp, prevPtr, prevPtr->masterPtr, argc-3, argv+3); } else if ((c == 'a') && (length >= 2) && (strncmp(argv[1], "append", length) == 0)) { Packer *masterPtr; register Packer *prevPtr; Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(interp, argv[2], tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } masterPtr = GetPacker(tkwin2); prevPtr = masterPtr->slavePtr; if (prevPtr != NULL) { while (prevPtr->nextPtr != NULL) { prevPtr = prevPtr->nextPtr; } } return PackAfter(interp, prevPtr, masterPtr, argc-3, argv+3); } else if ((c == 'b') && (strncmp(argv[1], "before", length) == 0)) { Packer *packPtr, *masterPtr; register Packer *prevPtr; Tk_Window tkwin2; tkwin2 = Tk_NameToWindow(interp, argv[2], tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } packPtr = GetPacker(tkwin2); if (packPtr->masterPtr == NULL) { Tcl_AppendResult(interp, "window \"", argv[2], "\" isn't packed", (char *) NULL); return TCL_ERROR; } masterPtr = packPtr->masterPtr; prevPtr = masterPtr->slavePtr; if (prevPtr == packPtr) { prevPtr = NULL; } else { for ( ; ; prevPtr = prevPtr->nextPtr) { if (prevPtr == NULL) { panic("\"pack before\" couldn't find predecessor"); } if (prevPtr->nextPtr == packPtr) { break; } } } return PackAfter(interp, prevPtr, masterPtr, argc-3, argv+3); } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) { if (argv[2][0] != '.') { Tcl_AppendResult(interp, "bad argument \"", argv[2], "\": must be name of window", (char *) NULL); return TCL_ERROR; } return ConfigureSlaves(interp, tkwin, argc-2, argv+2); } else if ((c == 'f') && (strncmp(argv[1], "forget", length) == 0)) { Tk_Window slave; Packer *slavePtr; int i; for (i = 2; i < argc; i++) { slave = Tk_NameToWindow(interp, argv[i], tkwin); if (slave == NULL) { continue; } slavePtr = GetPacker(slave); if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) { Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, (ClientData) NULL); if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } Unlink(slavePtr); Tk_UnmapWindow(slavePtr->tkwin); } } } else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) { register Packer *slavePtr; Tk_Window slave; char buffer[300]; static char *sideNames[] = {"top", "bottom", "left", "right"}; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " info window\"", (char *) NULL); return TCL_ERROR; } slave = Tk_NameToWindow(interp, argv[2], tkwin); if (slave == NULL) { return TCL_ERROR; } slavePtr = GetPacker(slave); if (slavePtr->masterPtr == NULL) { Tcl_AppendResult(interp, "window \"", argv[2], "\" isn't packed", (char *) NULL); return TCL_ERROR; } Tcl_AppendElement(interp, "-in"); Tcl_AppendElement(interp, Tk_PathName(slavePtr->masterPtr->tkwin)); Tcl_AppendElement(interp, "-anchor"); Tcl_AppendElement(interp, Tk_NameOfAnchor(slavePtr->anchor)); Tcl_AppendResult(interp, " -expand ", (slavePtr->flags & EXPAND) ? "1" : "0", " -fill ", (char *) NULL); switch (slavePtr->flags & (FILLX|FILLY)) { case 0: Tcl_AppendResult(interp, "none", (char *) NULL); break; case FILLX: Tcl_AppendResult(interp, "x", (char *) NULL); break; case FILLY: Tcl_AppendResult(interp, "y", (char *) NULL); break; case FILLX|FILLY: Tcl_AppendResult(interp, "both", (char *) NULL); break; } sprintf(buffer, " -ipadx %d -ipady %d -padx %d -pady %d", slavePtr->iPadX/2, slavePtr->iPadY/2, slavePtr->padX/2, slavePtr->padY/2); Tcl_AppendResult(interp, buffer, " -side ", sideNames[slavePtr->side], (char *) NULL); } else if ((c == 'p') && (strncmp(argv[1], "propagate", length) == 0)) { Tk_Window master; Packer *masterPtr; int propagate; if (argc > 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " propagate window ?boolean?\"", (char *) NULL); return TCL_ERROR; } master = Tk_NameToWindow(interp, argv[2], tkwin); if (master == NULL) { return TCL_ERROR; } masterPtr = GetPacker(master); if (argc == 3) { if (masterPtr->flags & DONT_PROPAGATE) { interp->result = "0"; } else { interp->result = "1"; } return TCL_OK; } if (Tcl_GetBoolean(interp, argv[3], &propagate) != TCL_OK) { return TCL_ERROR; } if (propagate) { masterPtr->flags &= ~DONT_PROPAGATE; /* * Repack the master to allow new geometry information to * propagate upwards to the master's master. */ if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } if (!(masterPtr->flags & REQUESTED_REPACK)) { masterPtr->flags |= REQUESTED_REPACK; Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); } } else { masterPtr->flags |= DONT_PROPAGATE; } } else if ((c == 's') && (strncmp(argv[1], "slaves", length) == 0)) { Tk_Window master; Packer *masterPtr, *slavePtr; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " slaves window\"", (char *) NULL); return TCL_ERROR; } master = Tk_NameToWindow(interp, argv[2], tkwin); if (master == NULL) { return TCL_ERROR; } masterPtr = GetPacker(master); for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { Tcl_AppendElement(interp, Tk_PathName(slavePtr->tkwin)); } } else if ((c == 'u') && (strncmp(argv[1], "unpack", length) == 0)) { Tk_Window tkwin2; Packer *packPtr; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " unpack window\"", (char *) NULL); return TCL_ERROR; } tkwin2 = Tk_NameToWindow(interp, argv[2], tkwin); if (tkwin2 == NULL) { return TCL_ERROR; } packPtr = GetPacker(tkwin2); if ((packPtr != NULL) && (packPtr->masterPtr != NULL)) { Tk_ManageGeometry(tkwin2, (Tk_GeomMgr *) NULL, (ClientData) NULL); if (packPtr->masterPtr->tkwin != Tk_Parent(packPtr->tkwin)) { Tk_UnmaintainGeometry(packPtr->tkwin, packPtr->masterPtr->tkwin); } Unlink(packPtr); Tk_UnmapWindow(packPtr->tkwin); } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be configure, forget, info, ", "propagate, or slaves", (char *) NULL); return TCL_ERROR; } return TCL_OK;}/* *-------------------------------------------------------------- * * PackReqProc -- * * This procedure is invoked by Tk_GeometryRequest for * windows managed by the packer. * * Results: * None.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -