~ubuntu-branches/ubuntu/dapper/tk8.0/dapper-updates

« back to all changes in this revision

Viewing changes to generic/tkSquare.c

  • Committer: Bazaar Package Importer
  • Author(s): Mike Markley
  • Date: 2001-07-24 21:57:40 UTC
  • Revision ID: james.westby@ubuntu.com-20010724215740-r70t25rtmbqjil2h
Tags: upstream-8.0.5
ImportĀ upstreamĀ versionĀ 8.0.5

Show diffs side-by-side

added added

removed removed

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