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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkSquare.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
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.1.1.1 2002-01-16 10:25:52 markom 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
}

powered by: WebSVN 2.1.0

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