tkSquare.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:18k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkSquare.c --
  3.  *
  4.  * This module implements "square" widgets that are object
  5.  * based.  A "square" is a widget that displays a single square that can 
  6.  * be moved around and resized.  This file is intended as an example
  7.  * of how to build a widget;  it isn't included in the
  8.  * normal wish, but it is included in "tktest".
  9.  *
  10.  * Copyright (c) 1997 Sun Microsystems, Inc.
  11.  *
  12.  * See the file "license.terms" for information on usage and redistribution
  13.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14.  *
  15.  * RCS: @(#) $Id: tkSquare.c,v 1.5 2002/01/17 23:33:53 dgp Exp $
  16.  */
  17. #include "tkPort.h"
  18. #define __NO_OLD_CONFIG
  19. #include "tk.h"
  20. #include "tkInt.h"
  21. /*
  22.  * A data structure of the following type is kept for each square
  23.  * widget managed by this file:
  24.  */
  25. typedef struct {
  26.     Tk_Window tkwin; /* Window that embodies the square.  NULL
  27.  * means window has been deleted but
  28.  * widget record hasn't been cleaned up yet. */
  29.     Display *display; /* X's token for the window's display. */
  30.     Tcl_Interp *interp; /* Interpreter associated with widget. */
  31.     Tcl_Command widgetCmd; /* Token for square's widget command. */
  32.     Tk_OptionTable optionTable; /* Token representing the configuration
  33.  * specifications. */
  34.     Tcl_Obj *xPtr, *yPtr; /* Position of square's upper-left corner
  35.  * within widget. */
  36.     int x, y;
  37.     Tcl_Obj *sizeObjPtr; /* Width and height of square. */
  38.     /*
  39.      * Information used when displaying widget:
  40.      */
  41.     Tcl_Obj *borderWidthPtr; /* Width of 3-D border around whole widget. */
  42.     Tcl_Obj *bgBorderPtr;
  43.     Tcl_Obj *fgBorderPtr;
  44.     Tcl_Obj *reliefPtr;
  45.     GC gc; /* Graphics context for copying from
  46.  * off-screen pixmap onto screen. */
  47.     Tcl_Obj *doubleBufferPtr; /* Non-zero means double-buffer redisplay
  48.  * with pixmap;  zero means draw straight
  49.  * onto the display. */
  50.     int updatePending; /* Non-zero means a call to SquareDisplay
  51.  * has already been scheduled. */
  52. } Square;
  53. /*
  54.  * Information used for argv parsing.
  55.  */
  56. static Tk_OptionSpec optionSpecs[] = {
  57.     {TK_OPTION_BORDER, "-background", "background", "Background",
  58.     "#d9d9d9", Tk_Offset(Square, bgBorderPtr), -1, 0,
  59.     (ClientData) "white"},
  60.     {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
  61.     (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"},
  62.     {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
  63.     (char *) NULL, 0, -1, 0, (ClientData) "-background"},
  64.     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
  65.     "2", Tk_Offset(Square, borderWidthPtr), -1},
  66.     {TK_OPTION_BOOLEAN, "-dbl", "doubleBuffer", "DoubleBuffer",
  67.     "1", Tk_Offset(Square, doubleBufferPtr), -1},
  68.     {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL,
  69.     (char *) NULL, 0, -1, 0, (ClientData) "-foreground"},
  70.     {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground",
  71.     "#b03060", Tk_Offset(Square, fgBorderPtr), -1, 0,
  72.     (ClientData) "black"},
  73.     {TK_OPTION_PIXELS, "-posx", "posx", "PosX", "0",
  74.     Tk_Offset(Square, xPtr), -1},
  75.     {TK_OPTION_PIXELS, "-posy", "posy", "PosY", "0",
  76.     Tk_Offset(Square, yPtr), -1},
  77.     {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
  78.     "raised", Tk_Offset(Square, reliefPtr), -1},
  79.     {TK_OPTION_PIXELS, "-size", "size", "Size", "20",
  80.     Tk_Offset(Square, sizeObjPtr), -1},
  81.     {TK_OPTION_END}
  82. };
  83. /*
  84.  * Forward declarations for procedures defined later in this file:
  85.  */
  86. int SquareObjCmd _ANSI_ARGS_((ClientData clientData,
  87.     Tcl_Interp *interp, int objc, 
  88.     Tcl_Obj * CONST objv[]));
  89. static void SquareDeletedProc _ANSI_ARGS_((
  90.     ClientData clientData));
  91. static int SquareConfigure _ANSI_ARGS_((Tcl_Interp *interp,
  92.     Square *squarePtr));
  93. static void SquareDestroy _ANSI_ARGS_((char *memPtr));
  94. static void SquareDisplay _ANSI_ARGS_((ClientData clientData));
  95. static void KeepInWindow _ANSI_ARGS_((Square *squarePtr));
  96. static void SquareObjEventProc _ANSI_ARGS_((ClientData clientData,
  97.     XEvent *eventPtr));
  98. static int SquareWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
  99.     Tcl_Interp *, int objc, Tcl_Obj * CONST objv[]));
  100. /*
  101.  *--------------------------------------------------------------
  102.  *
  103.  * SquareCmd --
  104.  *
  105.  * This procedure is invoked to process the "square" Tcl
  106.  * command.  It creates a new "square" widget.
  107.  *
  108.  * Results:
  109.  * A standard Tcl result.
  110.  *
  111.  * Side effects:
  112.  * A new widget is created and configured.
  113.  *
  114.  *--------------------------------------------------------------
  115.  */
  116. int
  117. SquareObjCmd(clientData, interp, objc, objv)
  118.     ClientData clientData; /* NULL. */
  119.     Tcl_Interp *interp; /* Current interpreter. */
  120.     int objc; /* Number of arguments. */
  121.     Tcl_Obj * CONST objv[]; /* Argument objects. */
  122. {
  123.     Square *squarePtr;
  124.     Tk_Window tkwin;
  125.     Tk_OptionTable optionTable;
  126.     if (objc < 2) {
  127. Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
  128. return TCL_ERROR;
  129.     }
  130.     tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), 
  131.     Tcl_GetStringFromObj(objv[1], NULL), (char *) NULL);
  132.     if (tkwin == NULL) {
  133. return TCL_ERROR;
  134.     }
  135.     Tk_SetClass(tkwin, "Square");
  136.     /*
  137.      * Create the option table for this widget class.  If it has
  138.      * already been created, the refcount will get bumped and just
  139.      * the pointer will be returned.  The refcount getting bumped
  140.      * does not concern us, because Tk will ensure the table is
  141.      * deleted when the interpreter is destroyed.
  142.      */
  143.     optionTable = Tk_CreateOptionTable(interp, optionSpecs);
  144.     /*
  145.      * Allocate and initialize the widget record.  The memset allows
  146.      * us to set just the non-NULL/0 items.
  147.      */
  148.     squarePtr = (Square *) ckalloc(sizeof(Square));
  149.     memset((void *) squarePtr, 0, (sizeof(Square)));
  150.     squarePtr->tkwin = tkwin;
  151.     squarePtr->display = Tk_Display(tkwin);
  152.     squarePtr->interp = interp;
  153.     squarePtr->widgetCmd = Tcl_CreateObjCommand(interp,
  154.     Tk_PathName(squarePtr->tkwin), SquareWidgetObjCmd,
  155.     (ClientData) squarePtr, SquareDeletedProc);
  156.     squarePtr->gc = None;
  157.     squarePtr->optionTable = optionTable;
  158.     if (Tk_InitOptions(interp, (char *) squarePtr, optionTable, tkwin)
  159.     != TCL_OK) {
  160. Tk_DestroyWindow(squarePtr->tkwin);
  161. ckfree((char *) squarePtr);
  162. return TCL_ERROR;
  163.     }
  164.     Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask,
  165.     SquareObjEventProc, (ClientData) squarePtr);
  166.     if (Tk_SetOptions(interp, (char *) squarePtr, optionTable, objc - 2,
  167.     objv + 2, tkwin, NULL, (int *) NULL) != TCL_OK) {
  168. goto error;
  169.     }
  170.     if (SquareConfigure(interp, squarePtr) != TCL_OK) {
  171. goto error;
  172.     }
  173.     Tcl_SetObjResult(interp,
  174.     Tcl_NewStringObj(Tk_PathName(squarePtr->tkwin), -1));
  175.     return TCL_OK;
  176. error:
  177.     Tk_DestroyWindow(squarePtr->tkwin);
  178.     return TCL_ERROR;
  179. }
  180. /*
  181.  *--------------------------------------------------------------
  182.  *
  183.  * SquareWidgetObjCmd --
  184.  *
  185.  * This procedure is invoked to process the Tcl command
  186.  * that corresponds to a widget managed by this module.
  187.  * See the user documentation for details on what it does.
  188.  *
  189.  * Results:
  190.  * A standard Tcl result.
  191.  *
  192.  * Side effects:
  193.  * See the user documentation.
  194.  *
  195.  *--------------------------------------------------------------
  196.  */
  197. static int
  198. SquareWidgetObjCmd(clientData, interp, objc, objv)
  199.     ClientData clientData; /* Information about square widget. */
  200.     Tcl_Interp *interp; /* Current interpreter. */
  201.     int objc; /* Number of arguments. */
  202.     Tcl_Obj * CONST objv[]; /* Argument objects. */
  203. {
  204.     Square *squarePtr = (Square *) clientData;
  205.     int result = TCL_OK;
  206.     static CONST char *squareOptions[] = {"cget", "configure", (char *) NULL};
  207.     enum {
  208. SQUARE_CGET, SQUARE_CONFIGURE
  209.     };
  210.     Tcl_Obj *resultObjPtr;
  211.     int index;
  212.     if (objc < 2) {
  213. Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
  214. return TCL_ERROR;
  215.     }
  216.     if (Tcl_GetIndexFromObj(interp, objv[1], squareOptions, "command",
  217.     0, &index) != TCL_OK) {
  218. return TCL_ERROR;
  219.     }
  220.     Tcl_Preserve((ClientData) squarePtr);
  221.     
  222.     switch (index) {
  223. case SQUARE_CGET: {
  224.     if (objc != 3) {
  225. Tcl_WrongNumArgs(interp, 2, objv, "option");
  226. goto error;
  227.     }
  228.     resultObjPtr = Tk_GetOptionValue(interp, (char *) squarePtr,
  229.     squarePtr->optionTable, objv[2], squarePtr->tkwin);
  230.     if (resultObjPtr == NULL) {
  231. result = TCL_ERROR;
  232.     } else {
  233. Tcl_SetObjResult(interp, resultObjPtr);
  234.     }
  235.     break;
  236. }
  237. case SQUARE_CONFIGURE: {
  238.     resultObjPtr = NULL;
  239.     if (objc == 2) {
  240. resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr,
  241. squarePtr->optionTable, (Tcl_Obj *) NULL,
  242. squarePtr->tkwin);
  243. if (resultObjPtr == NULL) {
  244.     result = TCL_ERROR;
  245. }
  246.     } else if (objc == 3) {
  247. resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr,
  248. squarePtr->optionTable, objv[2], squarePtr->tkwin);
  249. if (resultObjPtr == NULL) {
  250.     result = TCL_ERROR;
  251. }
  252.     } else {
  253. result = Tk_SetOptions(interp, (char *) squarePtr,
  254. squarePtr->optionTable, objc - 2, objv + 2,
  255. squarePtr->tkwin, NULL, (int *) NULL);
  256. if (result == TCL_OK) {
  257.     result = SquareConfigure(interp, squarePtr);
  258. }
  259. if (!squarePtr->updatePending) {
  260.     Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr);
  261.     squarePtr->updatePending = 1;
  262. }
  263.     }
  264.     if (resultObjPtr != NULL) {
  265. Tcl_SetObjResult(interp, resultObjPtr);
  266.     }
  267. }
  268.     }
  269.     Tcl_Release((ClientData) squarePtr);
  270.     return result;
  271.     error:
  272.     Tcl_Release((ClientData) squarePtr);
  273.     return TCL_ERROR;
  274. }
  275. /*
  276.  *----------------------------------------------------------------------
  277.  *
  278.  * SquareConfigure --
  279.  *
  280.  * This procedure is called to process an argv/argc list in
  281.  * conjunction with the Tk option database to configure (or
  282.  * reconfigure) a square widget.
  283.  *
  284.  * Results:
  285.  * The return value is a standard Tcl result.  If TCL_ERROR is
  286.  * returned, then the interp's result contains an error message.
  287.  *
  288.  * Side effects:
  289.  * Configuration information, such as colors, border width,
  290.  * etc. get set for squarePtr;  old resources get freed,
  291.  * if there were any.
  292.  *
  293.  *----------------------------------------------------------------------
  294.  */
  295. static int
  296. SquareConfigure(interp, squarePtr)
  297.     Tcl_Interp *interp; /* Used for error reporting. */
  298.     Square *squarePtr; /* Information about widget. */
  299. {
  300.     int borderWidth;
  301.     Tk_3DBorder bgBorder;
  302.     int doubleBuffer;
  303.     /*
  304.      * Set the background for the window and create a graphics context
  305.      * for use during redisplay.
  306.      */
  307.     bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, 
  308.     squarePtr->bgBorderPtr);
  309.     Tk_SetWindowBackground(squarePtr->tkwin,
  310.     Tk_3DBorderColor(bgBorder)->pixel);
  311.     Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
  312.     if ((squarePtr->gc == None) && (doubleBuffer)) {
  313. XGCValues gcValues;
  314. gcValues.function = GXcopy;
  315. gcValues.graphics_exposures = False;
  316. squarePtr->gc = Tk_GetGC(squarePtr->tkwin,
  317. GCFunction|GCGraphicsExposures, &gcValues);
  318.     }
  319.     /*
  320.      * Register the desired geometry for the window.  Then arrange for
  321.      * the window to be redisplayed.
  322.      */
  323.     Tk_GeometryRequest(squarePtr->tkwin, 200, 150);
  324.     Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
  325.     &borderWidth);
  326.     Tk_SetInternalBorder(squarePtr->tkwin, borderWidth);
  327.     if (!squarePtr->updatePending) {
  328. Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr);
  329. squarePtr->updatePending = 1;
  330.     }
  331.     KeepInWindow(squarePtr);
  332.     return TCL_OK;
  333. }
  334. /*
  335.  *--------------------------------------------------------------
  336.  *
  337.  * SquareObjEventProc --
  338.  *
  339.  * This procedure is invoked by the Tk dispatcher for various
  340.  * events on squares.
  341.  *
  342.  * Results:
  343.  * None.
  344.  *
  345.  * Side effects:
  346.  * When the window gets deleted, internal structures get
  347.  * cleaned up.  When it gets exposed, it is redisplayed.
  348.  *
  349.  *--------------------------------------------------------------
  350.  */
  351. static void
  352. SquareObjEventProc(clientData, eventPtr)
  353.     ClientData clientData; /* Information about window. */
  354.     XEvent *eventPtr; /* Information about event. */
  355. {
  356.     Square *squarePtr = (Square *) clientData;
  357.     if (eventPtr->type == Expose) {
  358. if (!squarePtr->updatePending) {
  359.     Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr);
  360.     squarePtr->updatePending = 1;
  361. }
  362.     } else if (eventPtr->type == ConfigureNotify) {
  363. KeepInWindow(squarePtr);
  364. if (!squarePtr->updatePending) {
  365.     Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr);
  366.     squarePtr->updatePending = 1;
  367. }
  368.     } else if (eventPtr->type == DestroyNotify) {
  369. if (squarePtr->tkwin != NULL) {
  370.     Tk_FreeConfigOptions((char *) squarePtr, squarePtr->optionTable,
  371.     squarePtr->tkwin);
  372.     if (squarePtr->gc != None) {
  373. Tk_FreeGC(squarePtr->display, squarePtr->gc);
  374.     }
  375.     squarePtr->tkwin = NULL;
  376.     Tcl_DeleteCommandFromToken(squarePtr->interp,
  377.     squarePtr->widgetCmd);
  378. }
  379. if (squarePtr->updatePending) {
  380.     Tcl_CancelIdleCall(SquareDisplay, (ClientData) squarePtr);
  381. }
  382. Tcl_EventuallyFree((ClientData) squarePtr, SquareDestroy);
  383.     }
  384. }
  385. /*
  386.  *----------------------------------------------------------------------
  387.  *
  388.  * SquareDeletedProc --
  389.  *
  390.  * This procedure is invoked when a widget command is deleted.  If
  391.  * the widget isn't already in the process of being destroyed,
  392.  * this command destroys it.
  393.  *
  394.  * Results:
  395.  * None.
  396.  *
  397.  * Side effects:
  398.  * The widget is destroyed.
  399.  *
  400.  *----------------------------------------------------------------------
  401.  */
  402. static void
  403. SquareDeletedProc(clientData)
  404.     ClientData clientData; /* Pointer to widget record for widget. */
  405. {
  406.     Square *squarePtr = (Square *) clientData;
  407.     Tk_Window tkwin = squarePtr->tkwin;
  408.     /*
  409.      * This procedure could be invoked either because the window was
  410.      * destroyed and the command was then deleted (in which case tkwin
  411.      * is NULL) or because the command was deleted, and then this procedure
  412.      * destroys the widget.
  413.      */
  414.     if (tkwin != NULL) {
  415. Tk_DestroyWindow(tkwin);
  416.     }
  417. }
  418. /*
  419.  *--------------------------------------------------------------
  420.  *
  421.  * SquareDisplay --
  422.  *
  423.  * This procedure redraws the contents of a square window.
  424.  * It is invoked as a do-when-idle handler, so it only runs
  425.  * when there's nothing else for the application to do.
  426.  *
  427.  * Results:
  428.  * None.
  429.  *
  430.  * Side effects:
  431.  * Information appears on the screen.
  432.  *
  433.  *--------------------------------------------------------------
  434.  */
  435. static void
  436. SquareDisplay(clientData)
  437.     ClientData clientData; /* Information about window. */
  438. {
  439.     Square *squarePtr = (Square *) clientData;
  440.     Tk_Window tkwin = squarePtr->tkwin;
  441.     Pixmap pm = None;
  442.     Drawable d;
  443.     int borderWidth, size, relief;
  444.     Tk_3DBorder bgBorder, fgBorder;
  445.     int doubleBuffer;
  446.     squarePtr->updatePending = 0;
  447.     if (!Tk_IsMapped(tkwin)) {
  448. return;
  449.     }
  450.     /*
  451.      * Create a pixmap for double-buffering, if necessary.
  452.      */
  453.     Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
  454.     if (doubleBuffer) {
  455. pm = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
  456. Tk_Width(tkwin), Tk_Height(tkwin),
  457. DefaultDepthOfScreen(Tk_Screen(tkwin)));
  458. d = pm;
  459.     } else {
  460. d = Tk_WindowId(tkwin);
  461.     }
  462.     /*
  463.      * Redraw the widget's background and border.
  464.      */
  465.     Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
  466.     &borderWidth);
  467.     bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, 
  468.     squarePtr->bgBorderPtr);
  469.     Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);
  470.     Tk_Fill3DRectangle(tkwin, d, bgBorder, 0, 0, Tk_Width(tkwin),
  471.     Tk_Height(tkwin), borderWidth, relief);
  472.     /*
  473.      * Display the square.
  474.      */
  475.     Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);
  476.     fgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, 
  477.     squarePtr->fgBorderPtr);
  478.     Tk_Fill3DRectangle(tkwin, d, fgBorder, squarePtr->x, squarePtr->y, size, 
  479.     size, borderWidth, TK_RELIEF_RAISED);
  480.     /*
  481.      * If double-buffered, copy to the screen and release the pixmap.
  482.      */
  483.     if (doubleBuffer) {
  484. XCopyArea(Tk_Display(tkwin), pm, Tk_WindowId(tkwin), squarePtr->gc,
  485. 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
  486. 0, 0);
  487. Tk_FreePixmap(Tk_Display(tkwin), pm);
  488.     }
  489. }
  490. /*
  491.  *----------------------------------------------------------------------
  492.  *
  493.  * SquareDestroy --
  494.  *
  495.  * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
  496.  * to clean up the internal structure of a square at a safe time
  497.  * (when no-one is using it anymore).
  498.  *
  499.  * Results:
  500.  * None.
  501.  *
  502.  * Side effects:
  503.  * Everything associated with the square is freed up.
  504.  *
  505.  *----------------------------------------------------------------------
  506.  */
  507. static void
  508. SquareDestroy(memPtr)
  509.     char *memPtr; /* Info about square widget. */
  510. {
  511.     Square *squarePtr = (Square *) memPtr;
  512.     
  513.     ckfree((char *) squarePtr);
  514. }
  515. /*
  516.  *----------------------------------------------------------------------
  517.  *
  518.  * KeepInWindow --
  519.  *
  520.  * Adjust the position of the square if necessary to keep it in
  521.  * the widget's window.
  522.  *
  523.  * Results:
  524.  * None.
  525.  *
  526.  * Side effects:
  527.  * The x and y position of the square are adjusted if necessary
  528.  * to keep the square in the window.
  529.  *
  530.  *----------------------------------------------------------------------
  531.  */
  532. static void
  533. KeepInWindow(squarePtr)
  534.     register Square *squarePtr; /* Pointer to widget record. */
  535. {
  536.     int i, bd, relief;
  537.     int borderWidth, size;
  538.     Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
  539.     &borderWidth);
  540.     Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->xPtr, 
  541.     &squarePtr->x);
  542.     Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->yPtr, 
  543.     &squarePtr->y);
  544.     Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);
  545.     Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);
  546.     bd = 0;
  547.     if (relief != TK_RELIEF_FLAT) {
  548. bd = borderWidth;
  549.     }
  550.     i = (Tk_Width(squarePtr->tkwin) - bd) - (squarePtr->x + size);
  551.     if (i < 0) {
  552. squarePtr->x += i;
  553.     }
  554.     i = (Tk_Height(squarePtr->tkwin) - bd) - (squarePtr->y + size);
  555.     if (i < 0) {
  556. squarePtr->y += i;
  557.     }
  558.     if (squarePtr->x < bd) {
  559. squarePtr->x = bd;
  560.     }
  561.     if (squarePtr->y < bd) {
  562. squarePtr->y = bd;
  563.     }
  564. }