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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tix/] [generic/] [tixNBFrame.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
 * tixNBFrame.c --
3
 *
4
 *      This module implements "tixNoteBookFrame" widgets.
5
 *
6
 * Copyright (c) 1996, Expert Interface Technologies
7
 *
8
 * See the file "license.terms" for information on usage and redistribution
9
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10
 *
11
 *
12
 */
13
 
14
#include <tixPort.h>
15
#include <tixInt.h>
16
#include <tixDef.h>
17
 
18
#define NUM_TAB_POINTS 6
19
 
20
/*
21
 * A data structure of the following type is kept for each
22
 * widget managed by this file:
23
 */
24
 
25
typedef struct NoteBookFrameStruct {
26
    Tk_Window tkwin;            /* Window that embodies the widget.  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 button's widget command. */
32
 
33
    /*
34
     * Information used when displaying widget:
35
     */
36
    int desiredWidth;           /* Desired narrow dimension of scrollbar,
37
                                 * in pixels. */
38
    int width;                  /* total width of the widget */
39
    int height;                 /* total width of the widget */
40
 
41
    /*
42
     * Information used when displaying widget:
43
     */
44
 
45
    /* Border and general drawing */
46
 
47
    int borderWidth;            /* Width of 3-D borders. */
48
    Tk_3DBorder bgBorder;       /* Used for drawing background. */
49
    Tk_3DBorder focusBorder;    /* background of the "focus" tab. */
50
    Tk_3DBorder inActiveBorder; /* background of the "active" tab */
51
    XColor * backPageColorPtr;  /* the color used as the "back page" */
52
    GC backPageGC;              /* GC for drawing text in normal mode. */
53
    int relief;                 /* Indicates whether window as a whole is
54
                                 * raised, sunken, or flat. */
55
    int tabPadx;
56
    int tabPady;
57
 
58
    int isSlave;                /* if is in Slave mode, do not request for
59
                                 * germetry */
60
    /* Text drawing */
61
    TixFont font;               /* Information about text font, or NULL. */
62
    XColor *textColorPtr;       /* Color for drawing text. */
63
    XColor *disabledFg;         /* Foreground color when disabled.  NULL
64
                                 * means use normalFg with a 50% stipple
65
                                 * instead. */
66
    GC textGC;                  /* GC for drawing text in normal mode. */
67
    GC focusGC;                 /* GC for focusing text. */
68
    Pixmap gray;                /* Pixmap for displaying disabled text if
69
                                 * disabledFg is NULL. */
70
    GC disabledGC;              /* Used to produce disabled effect.  If
71
                                 * disabledFg isn't NULL, this GC is used to
72
                                 * draw button text or icon.  Otherwise
73
                                 * text or icon is drawn with normalGC and
74
                                 * this GC is used to stipple background
75
                                 * across it.*/
76
 
77
     Cursor cursor;             /* Current cursor for window, or None. */
78
 
79
    struct _Tab * tabHead;
80
    struct _Tab * tabTail;
81
    struct _Tab * active;
82
    struct _Tab * focus;
83
 
84
    int tabsWidth;              /* total width  of the tabs */
85
    int tabsHeight;             /* total height of the tabs */
86
 
87
    char *takeFocus;            /* Value of -takefocus option;  not used in
88
                                 * the C code, but used by keyboard traversal
89
                                 * scripts.  Malloc'ed, but may be NULL. */
90
 
91
    unsigned int redrawing : 1;
92
    unsigned int gotFocus : 1;
93
 
94
} NoteBookFrame;
95
 
96
typedef struct _Tab {
97
    struct _Tab * next;
98
 
99
    NoteBookFrame * wPtr;
100
    char * name;
101
 
102
    Tk_Uid state;               /* State of Tab's for display purposes:
103
                                 * normal or disabled. */
104
    Tk_Anchor anchor;
105
 
106
    char * text;
107
    int width, height;
108
    int numChars;
109
    Tk_Justify justify;         /* Justification to use for multi-line text. */
110
    int wrapLength;
111
    int underline;              /* Index of character to underline.  < 0 means
112
                                 * don't underline anything. */
113
 
114
    Tk_Image image;
115
    char * imageString;
116
 
117
    Pixmap bitmap;
118
} Tab;
119
 
120
typedef NoteBookFrame   WidgetRecord;
121
typedef NoteBookFrame * WidgetPtr;
122
 
123
/*
124
 * Information used for argv parsing.
125
 */
126
static Tk_ConfigSpec configSpecs[] = {
127
 
128
    {TK_CONFIG_BORDER, "-background", "background", "Background",
129
       DEF_NOTEBOOKFRAME_BG_COLOR, Tk_Offset(WidgetRecord, bgBorder),
130
       TK_CONFIG_COLOR_ONLY},
131
 
132
    {TK_CONFIG_BORDER, "-background", "background", "Background",
133
       DEF_NOTEBOOKFRAME_BG_MONO, Tk_Offset(WidgetRecord, bgBorder),
134
       TK_CONFIG_MONO_ONLY},
135
 
136
    {TK_CONFIG_COLOR, "-backpagecolor", "backPageColor", "BackPageColor",
137
       DEF_NOTEBOOKFRAME_BACKPAGE_COLOR,
138
       Tk_Offset(WidgetRecord, backPageColorPtr),
139
       TK_CONFIG_COLOR_ONLY},
140
 
141
    {TK_CONFIG_COLOR, "-backpagecolor", "backPageColor", "BackPageColor",
142
       DEF_NOTEBOOKFRAME_BACKPAGE_MONO,
143
       Tk_Offset(WidgetRecord, backPageColorPtr),
144
       TK_CONFIG_MONO_ONLY},
145
 
146
    {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
147
       (char *) NULL, 0, 0},
148
 
149
    {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
150
       (char *) NULL, 0, 0},
151
 
152
    {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
153
       DEF_NOTEBOOKFRAME_BORDER_WIDTH, Tk_Offset(WidgetRecord, borderWidth),
154
       0},
155
 
156
    {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
157
       DEF_NOTEBOOKFRAME_CURSOR, Tk_Offset(WidgetRecord, cursor),
158
       TK_CONFIG_NULL_OK},
159
 
160
    {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
161
       "DisabledForeground", DEF_NOTEBOOKFRAME_DISABLED_FG_COLOR,
162
       Tk_Offset(WidgetRecord, disabledFg),
163
       TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
164
 
165
    {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
166
       "DisabledForeground", DEF_NOTEBOOKFRAME_DISABLED_FG_MONO,
167
       Tk_Offset(WidgetRecord, disabledFg),
168
       TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
169
 
170
    {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
171
       (char *) NULL, 0, 0},
172
 
173
    {TK_CONFIG_BORDER, "-focuscolor", "focusColor", "FocusColor",
174
       DEF_NOTEBOOKFRAME_FOCUS_COLOR, Tk_Offset(WidgetRecord, focusBorder),
175
       TK_CONFIG_COLOR_ONLY},
176
 
177
    {TK_CONFIG_BORDER, "-focuscolor", "focusColor", "FocusColor",
178
       DEF_NOTEBOOKFRAME_FOCUS_MONO, Tk_Offset(WidgetRecord, focusBorder),
179
       TK_CONFIG_MONO_ONLY},
180
 
181
    {TK_CONFIG_FONT, "-font", "font", "Font",
182
       DEF_NOTEBOOKFRAME_FONT, Tk_Offset(WidgetRecord, font), 0},
183
 
184
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
185
       DEF_NOTEBOOKFRAME_FG_COLOR, Tk_Offset(WidgetRecord, textColorPtr),
186
       TK_CONFIG_COLOR_ONLY},
187
 
188
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
189
       DEF_NOTEBOOKFRAME_FG_MONO, Tk_Offset(WidgetRecord, textColorPtr),
190
       TK_CONFIG_MONO_ONLY},
191
 
192
    {TK_CONFIG_BORDER, "-inactivebackground", "inactiveBackground",
193
       "Background",
194
       DEF_NOTEBOOKFRAME_INACTIVE_BG_COLOR,
195
       Tk_Offset(WidgetRecord, inActiveBorder),
196
       TK_CONFIG_COLOR_ONLY},
197
 
198
    {TK_CONFIG_BORDER, "-inactivebackground", "inactiveBackground",
199
       "Background",
200
       DEF_NOTEBOOKFRAME_INACTIVE_BG_MONO,
201
       Tk_Offset(WidgetRecord, inActiveBorder),
202
       TK_CONFIG_MONO_ONLY},
203
 
204
    {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
205
       DEF_NOTEBOOKFRAME_RELIEF, Tk_Offset(WidgetRecord, relief), 0},
206
 
207
    {TK_CONFIG_BOOLEAN, "-slave", "slave", "Slave",
208
       DEF_NOTEBOOKFRAME_SLAVE, Tk_Offset(WidgetRecord, isSlave), 0},
209
 
210
    {TK_CONFIG_PIXELS, "-tabpadx", "tabPadX", "Pad",
211
       DEF_NOTEBOOKFRAME_TABPADX, Tk_Offset(WidgetRecord, tabPadx), 0},
212
 
213
    {TK_CONFIG_PIXELS, "-tabpady", "tabPadY", "Pad",
214
       DEF_NOTEBOOKFRAME_TABPADY, Tk_Offset(WidgetRecord, tabPady), 0},
215
 
216
    {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
217
        DEF_NOTEBOOKFRAME_TAKE_FOCUS, Tk_Offset(WidgetRecord, takeFocus),
218
        TK_CONFIG_NULL_OK},
219
 
220
    {TK_CONFIG_PIXELS, "-width", "width", "Width",
221
       DEF_NOTEBOOKFRAME_WIDTH, Tk_Offset(WidgetRecord, desiredWidth), 0},
222
 
223
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
224
        (char *) NULL, 0, 0}
225
};
226
 
227
#define DEF_NBF_TAB_ANCHOR              "c"
228
#define DEF_NBF_TAB_BITMAP              ""
229
#define DEF_NBF_TAB_IMAGE               ""
230
#define DEF_NBF_TAB_JUSTIFY             "center"
231
#define DEF_NBF_TAB_TEXT                ""
232
#define DEF_NBF_TAB_STATE               "normal"
233
#define DEF_NBF_TAB_UNDERLINE           "-1"
234
#define DEF_NBF_TAB_WRAPLENGTH          "0"
235
 
236
static Tk_ConfigSpec tabConfigSpecs[] = {
237
    {TK_CONFIG_ANCHOR, "-anchor", (char*)NULL, (char*)NULL,
238
       DEF_NBF_TAB_ANCHOR, Tk_Offset(Tab, anchor), 0},
239
 
240
    {TK_CONFIG_BITMAP, "-bitmap", (char*)NULL, (char*)NULL,
241
       DEF_NBF_TAB_BITMAP, Tk_Offset(Tab, bitmap), TK_CONFIG_NULL_OK},
242
 
243
    {TK_CONFIG_STRING, "-image", (char*)NULL, (char*)NULL,
244
       DEF_NBF_TAB_IMAGE, Tk_Offset(Tab, imageString),
245
       TK_CONFIG_NULL_OK},
246
 
247
    {TK_CONFIG_JUSTIFY, "-justify", (char*)NULL, (char*)NULL,
248
        DEF_NBF_TAB_JUSTIFY, Tk_Offset(Tab, justify), 0},
249
 
250
    {TK_CONFIG_STRING, "-label", (char*)NULL, (char*)NULL,
251
       DEF_NBF_TAB_TEXT, Tk_Offset(Tab, text), TK_CONFIG_NULL_OK},
252
 
253
    {TK_CONFIG_UID, "-state", (char*)NULL, (char*)NULL,
254
       DEF_NBF_TAB_STATE, Tk_Offset(Tab, state), 0},
255
 
256
    {TK_CONFIG_INT, "-underline", (char*)NULL, (char*)NULL,
257
        DEF_NBF_TAB_UNDERLINE, Tk_Offset(Tab, underline), 0},
258
 
259
    {TK_CONFIG_PIXELS, "-wraplength", (char*)NULL, (char*)NULL,
260
       DEF_NBF_TAB_WRAPLENGTH, Tk_Offset(Tab, wrapLength), 0},
261
 
262
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
263
       (char *) NULL, 0, 0}
264
};
265
 
266
/*
267
 * Forward declarations for procedures defined later in this file:
268
 */
269
 
270
        /* These are standard procedures for TK widgets
271
         * implemeted in C
272
         */
273
static void             WidgetCmdDeletedProc _ANSI_ARGS_((
274
                            ClientData clientData));
275
static int              WidgetConfigure _ANSI_ARGS_((Tcl_Interp *interp,
276
                            WidgetPtr wPtr, int argc, char **argv,
277
                            int flags));
278
static int              WidgetCommand _ANSI_ARGS_((ClientData clientData,
279
                            Tcl_Interp *, int argc, char **argv));
280
static void             WidgetComputeGeometry _ANSI_ARGS_((WidgetPtr wPtr));
281
static void             WidgetDestroy _ANSI_ARGS_((ClientData clientData));
282
static void             WidgetDisplay _ANSI_ARGS_((ClientData clientData));
283
static void             WidgetEventProc _ANSI_ARGS_((ClientData clientData,
284
                            XEvent *eventPtr));
285
 
286
        /* Extra procedures for this widget
287
         */
288
static int              AddTab _ANSI_ARGS_((WidgetPtr wPtr, char * name,
289
                            char ** argv, int argc));
290
static void             DeleteTab _ANSI_ARGS_((Tab * tPtr));
291
static void             CancelRedrawWhenIdle _ANSI_ARGS_((WidgetPtr wPtr));
292
static void             ComputeGeometry _ANSI_ARGS_((WidgetPtr wPtr));
293
static void             DrawTab _ANSI_ARGS_((WidgetPtr wPtr,
294
                            Tab * tPtr, int x, int isActive,
295
                            Drawable drawable));
296
static Tab *            FindTab _ANSI_ARGS_((Tcl_Interp *interp,
297
                            WidgetPtr wPtr, char * name));
298
static void             FocusTab _ANSI_ARGS_((WidgetPtr wPtr,
299
                            Tab * tPtr, int x, Drawable drawable));
300
static void             GetTabPoints _ANSI_ARGS_((
301
                            WidgetPtr wPtr, Tab * tPtr,
302
                            int x, XPoint *points));
303
static void             ImageProc _ANSI_ARGS_((ClientData clientData,
304
                            int x, int y, int width, int height,
305
                            int imgWidth, int imgHeight));
306
static void             RedrawWhenIdle _ANSI_ARGS_((WidgetPtr wPtr));
307
static int              TabConfigure _ANSI_ARGS_((WidgetPtr wPtr,
308
                            Tab *tPtr, char ** argv, int argc));
309
 
310
 
311
/*
312
 *--------------------------------------------------------------
313
 *
314
 * Tix_NoteBookFrameCmd --
315
 *
316
 *      This procedure is invoked to process the "tixNoteBookFrame" Tcl
317
 *      command.  It creates a new "TixNoteBookFrame" widget.
318
 *
319
 * Results:
320
 *      A standard Tcl result.
321
 *
322
 * Side effects:
323
 *      A new widget is created and configured.
324
 *
325
 *--------------------------------------------------------------
326
 */
327
int
328
Tix_NoteBookFrameCmd(clientData, interp, argc, argv)
329
    ClientData clientData;      /* Main window associated with
330
                                 * interpreter. */
331
    Tcl_Interp *interp;         /* Current interpreter. */
332
    int argc;                   /* Number of arguments. */
333
    char **argv;                /* Argument strings. */
334
{
335
    Tk_Window main = (Tk_Window) clientData;
336
    WidgetPtr wPtr;
337
    Tk_Window tkwin;
338
 
339
    if (argc < 2) {
340
        Tcl_AppendResult(interp, "wrong # args:  should be \"",
341
                argv[0], " pathName ?options?\"", (char *) NULL);
342
        return TCL_ERROR;
343
    }
344
 
345
    tkwin = Tk_CreateWindowFromPath(interp, main, argv[1], (char *) NULL);
346
    if (tkwin == NULL) {
347
        return TCL_ERROR;
348
    }
349
 
350
    Tk_SetClass(tkwin, "TixNoteBookFrame");
351
 
352
    /*
353
     * Allocate and initialize the widget record.
354
     */
355
    wPtr = (WidgetPtr) ckalloc(sizeof(WidgetRecord));
356
    wPtr->tkwin                 = tkwin;
357
    wPtr->display               = Tk_Display(tkwin);
358
    wPtr->interp                = interp;
359
    wPtr->isSlave               = 1;
360
    wPtr->desiredWidth          = 0;
361
    wPtr->interp                = interp;
362
    wPtr->width                 = 0;
363
    wPtr->borderWidth           = 0;
364
    wPtr->bgBorder              = NULL;
365
    wPtr->backPageGC            = None;
366
    wPtr->backPageColorPtr      = NULL;
367
    wPtr->disabledFg            = NULL;
368
    wPtr->gray                  = None;
369
    wPtr->disabledGC            = None;
370
    wPtr->inActiveBorder        = NULL;
371
    wPtr->focusBorder           = NULL;
372
    wPtr->font          = NULL;
373
    wPtr->textColorPtr          = NULL;
374
    wPtr->textGC                = None;
375
    wPtr->focusGC               = None;
376
    wPtr->relief                = TK_RELIEF_FLAT;
377
    wPtr->cursor                = None;
378
 
379
    wPtr->tabHead               = 0;
380
    wPtr->tabTail               = 0;
381
    wPtr->tabPadx               = 0;
382
    wPtr->tabPady               = 0;
383
    wPtr->active                = 0;
384
    wPtr->focus                 = 0;
385
    wPtr->takeFocus             = 0;
386
    wPtr->redrawing             = 0;
387
    wPtr->gotFocus              = 0;
388
 
389
    Tk_CreateEventHandler(wPtr->tkwin,
390
        ExposureMask|StructureNotifyMask|FocusChangeMask,
391
        WidgetEventProc, (ClientData) wPtr);
392
    wPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(wPtr->tkwin),
393
        WidgetCommand, (ClientData) wPtr, WidgetCmdDeletedProc);
394
    if (WidgetConfigure(interp, wPtr, argc-2, argv+2, 0) != TCL_OK) {
395
        Tk_DestroyWindow(wPtr->tkwin);
396
        return TCL_ERROR;
397
    }
398
 
399
    interp->result = Tk_PathName(wPtr->tkwin);
400
    return TCL_OK;
401
}
402
 
403
/*
404
 *--------------------------------------------------------------
405
 *
406
 * WidgetCommand --
407
 *
408
 *      This procedure is invoked to process the Tcl command
409
 *      that corresponds to a widget managed by this module.
410
 *      See the user documentation for details on what it does.
411
 *
412
 * Results:
413
 *      A standard Tcl result.
414
 *
415
 * Side effects:
416
 *      See the user documentation.
417
 *
418
 *--------------------------------------------------------------
419
 */
420
 
421
static int
422
WidgetCommand(clientData, interp, argc, argv)
423
    ClientData clientData;              /* Information about the widget. */
424
    Tcl_Interp *interp;                 /* Current interpreter. */
425
    int argc;                           /* Number of arguments. */
426
    char **argv;                        /* Argument strings. */
427
{
428
    WidgetPtr wPtr = (WidgetPtr) clientData;
429
    int result = TCL_OK;
430
    int length;
431
    char c;
432
 
433
    if (argc < 2) {
434
        Tcl_AppendResult(interp, "wrong # args: should be \"",
435
                argv[0], " option ?arg arg ...?\"", (char *) NULL);
436
        return TCL_ERROR;
437
    }
438
    Tk_Preserve((ClientData) wPtr);
439
    c = argv[1][0];
440
    length = strlen(argv[1]);
441
 
442
    if (((c == 'a') && (strncmp(argv[1], "activate", length) == 0))||
443
        ((c == 'f') && (strncmp(argv[1], "focus", length) == 0))){
444
        if (argc != 3) {
445
            Tcl_AppendResult(interp, "wrong # args: should be \"",
446
                argv[0], " ", argv[1], " name\"", (char *) NULL);
447
            goto error;
448
        }
449
        else {
450
            if (strcmp(argv[2], "")==0) {
451
                if (c == 'a') {
452
                    wPtr->active = 0;
453
                    wPtr->focus  = 0;
454
                }
455
                else {
456
                    wPtr->focus  = 0;
457
                }
458
                RedrawWhenIdle(wPtr);
459
            }
460
            else {
461
                Tab * tPtr;
462
 
463
                for (tPtr=wPtr->tabHead; tPtr; tPtr=tPtr->next) {
464
                    if (strcmp(argv[2], tPtr->name) == 0) {
465
                        if (c == 'a') {
466
                            wPtr->active = tPtr;
467
                            wPtr->focus  = tPtr;
468
                        }
469
                        else {
470
                            wPtr->focus  = tPtr;
471
                        }
472
                        RedrawWhenIdle(wPtr);
473
                        goto done;
474
                    }
475
                }
476
 
477
                Tcl_AppendResult(interp, "unknown tab \"",
478
                    argv[0], "\"", (char *) NULL);
479
                goto error;
480
            }
481
        }
482
    }
483
    else if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)) {
484
        if (argc < 3) {
485
            Tcl_AppendResult(interp, "wrong # args: should be ",
486
                argv[0], " add name ?options?", (char *) NULL);
487
            goto error;
488
        }
489
        else {
490
            if (AddTab(wPtr, argv[2], argv+3, argc-3)!= TCL_OK) {
491
                goto error;
492
            } else {
493
                WidgetComputeGeometry(wPtr);
494
                RedrawWhenIdle(wPtr);
495
            }
496
        }
497
    }
498
    else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)) {
499
        if (argc == 3) {
500
            result = Tk_ConfigureValue(interp, wPtr->tkwin, configSpecs,
501
                (char *)wPtr, argv[2], 0);
502
        } else {
503
            result = Tix_ArgcError(interp, argc, argv, 2, "option");
504
        }
505
    }
506
    else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) {
507
        if (argc == 2) {
508
            result = Tk_ConfigureInfo(interp, wPtr->tkwin, configSpecs,
509
                    (char *) wPtr, (char *) NULL, 0);
510
        } else if (argc == 3) {
511
            result = Tk_ConfigureInfo(interp, wPtr->tkwin, configSpecs,
512
                    (char *) wPtr, argv[2], 0);
513
        } else {
514
            result = WidgetConfigure(interp, wPtr, argc-2, argv+2,
515
                    TK_CONFIG_ARGV_ONLY);
516
        }
517
    }
518
    else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
519
        Tab * tPtr, * prev ;
520
 
521
        if (argc != 3) {
522
            Tix_ArgcError(interp, argc, argv, 2, "page");
523
            goto error;
524
        }
525
 
526
        /* Find the tab from the list */
527
        for (prev=tPtr=wPtr->tabHead; tPtr; prev=tPtr,tPtr=tPtr->next) {
528
            if (strcmp(tPtr->name, argv[2])==0) {
529
                break;
530
            }
531
        }
532
        if (tPtr == NULL) {
533
            Tcl_AppendResult(wPtr->interp,
534
                "Unknown tab \"", argv[2], "\"", (char*) NULL);
535
            goto error;
536
        }
537
        if (tPtr == prev) {
538
            if (wPtr->tabHead == wPtr->tabTail) {
539
                wPtr->tabHead = wPtr->tabTail = NULL;
540
            } else {
541
                wPtr->tabHead = tPtr->next;
542
            }
543
        } else {
544
            if (tPtr == wPtr->tabTail) {
545
                wPtr->tabTail = prev;
546
            }
547
            prev->next = tPtr->next;
548
        }
549
 
550
        DeleteTab(tPtr);
551
        ComputeGeometry(wPtr);
552
        RedrawWhenIdle(wPtr);
553
    }
554
    else if ((c == 'g') && (strncmp(argv[1], "geometryinfo", length) == 0)) {
555
        char buff[20];
556
 
557
        ComputeGeometry(wPtr);
558
        sprintf(buff, "%d %d", wPtr->width, wPtr->height);
559
 
560
        Tcl_AppendResult(interp, buff, NULL);
561
    }
562
    else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) {
563
        if (argc != 4) {
564
            Tcl_AppendResult(interp, "wrong # args: should be \"",
565
                argv[0], " identify x y\"", (char *) NULL);
566
            goto error;
567
        }
568
        else {
569
            int x, y, left, right;
570
            Tab * tPtr;
571
 
572
            if (Tcl_GetInt(interp, argv[2], &x) != TCL_OK) {
573
                goto error;
574
            }
575
            if (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) {
576
                goto error;
577
            }
578
 
579
            if (y < wPtr->tabsHeight) {
580
                left = 0;
581
                for (tPtr=wPtr->tabHead; tPtr; tPtr=tPtr->next) {
582
                    right = left + (wPtr->borderWidth +  wPtr->tabPadx) * 2
583
                      + tPtr->width;
584
 
585
                    if (x >= left && x <= right && tPtr->state ==tixNormalUid){
586
                        Tcl_AppendResult(interp, tPtr->name, NULL);
587
                        goto done;
588
                    }
589
                    left = right;
590
                }
591
            }
592
 
593
            /*
594
             * An empty string is returned to indicate "nothing selected"
595
             */
596
            Tcl_ResetResult(interp);
597
        }
598
    }
599
    else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) {
600
        Tcl_ResetResult(interp);
601
 
602
        if (argc == 3 && strcmp(argv[2], "pages")==0 ) {
603
            Tab * tPtr;
604
 
605
            for (tPtr=wPtr->tabHead; tPtr; tPtr=tPtr->next) {
606
                Tcl_AppendElement(interp, tPtr->name);
607
            }
608
        }
609
        else if (argc == 3 && strcmp(argv[2], "active")==0 ) {
610
            if (wPtr->active) {
611
                Tcl_AppendResult(interp, wPtr->active->name, NULL);
612
            }
613
        }
614
        else if (argc == 3 && strcmp(argv[2], "focus")==0 ) {
615
            if (wPtr->focus) {
616
                Tcl_AppendResult(interp, wPtr->focus->name, NULL);
617
            }
618
        }
619
        else if (argc == 3 && strcmp(argv[2], "focusnext")==0 ) {
620
            Tab * next;
621
            if (wPtr->focus) {
622
                if (wPtr->focus->next) {
623
                    next = wPtr->focus->next;
624
                } else {
625
                    next = wPtr->tabHead;
626
                }
627
                Tcl_AppendResult(interp, next->name, NULL);
628
            }
629
        }
630
        else if (argc == 3 && strcmp(argv[2], "focusprev")==0 ) {
631
            Tab * prev, *tPtr;
632
 
633
            if (wPtr->focus==wPtr->tabHead) {
634
                prev = wPtr->tabTail;
635
            }
636
            else {
637
                for (prev=tPtr=wPtr->tabHead;tPtr; prev=tPtr,tPtr=tPtr->next) {
638
                    if (tPtr == wPtr->focus) {
639
                        break;
640
                    }
641
                }
642
            }
643
 
644
            if (prev) {
645
                Tcl_AppendResult(interp, prev->name, NULL);
646
            }
647
        }
648
        else {
649
            Tcl_AppendResult(interp, "wrong number of arguments or ",
650
                "unknown option", NULL);
651
            goto error;
652
        }
653
    }
654
    else if ((c == 'm') && (strncmp(argv[1], "move", length) == 0)) {
655
 
656
    }
657
    else if ((c == 'p') && (strncmp(argv[1], "pagecget", length) == 0)) {
658
        Tab * tPtr;
659
 
660
        if (argc != 4) {
661
            Tix_ArgcError(interp, argc, argv, 2, "option");
662
            goto error;
663
        }
664
        if ((tPtr=FindTab(interp, wPtr, argv[2])) == NULL) {
665
            goto error;
666
        }
667
        result = Tk_ConfigureValue(interp, wPtr->tkwin, tabConfigSpecs,
668
            (char *)tPtr, argv[3], 0);
669
    }
670
    else if ((c == 'p') && (strncmp(argv[1], "pageconfigure", length) == 0)) {
671
        Tab * tPtr;
672
 
673
        if (argc < 3) {
674
            Tix_ArgcError(interp, argc, argv, 2,
675
                "page ?option value ...?");
676
            goto error;
677
        }
678
        if ((tPtr=FindTab(interp, wPtr, argv[2])) == NULL) {
679
            goto error;
680
        }
681
        if (argc == 3) {
682
            result = Tk_ConfigureInfo(interp, wPtr->tkwin, tabConfigSpecs,
683
                (char *)tPtr, (char *) NULL, 0);
684
        } else if (argc == 4) {
685
            result = Tk_ConfigureInfo(interp, wPtr->tkwin, tabConfigSpecs,
686
                (char *)tPtr, argv[3], 0);
687
        } else {
688
            result = TabConfigure(wPtr, tPtr, argv+3, argc-3);
689
        }
690
    }
691
    else {
692
        Tcl_AppendResult(interp, "bad option \"", argv[1],
693
            "\":  must be activate, add, configure, delete, ",
694
            "geometryinfo, identify, move, pagecget or ",
695
            "pageconfigure", (char *) NULL);
696
        goto error;
697
    }
698
 
699
  done:
700
    Tk_Release((ClientData) wPtr);
701
    return result;
702
 
703
  error:
704
    Tk_Release((ClientData) wPtr);
705
    return TCL_ERROR;
706
}
707
 
708
/*
709
 *----------------------------------------------------------------------
710
 *
711
 * WidgetConfigure --
712
 *
713
 *      This procedure is called to process an argv/argc list in
714
 *      conjunction with the Tk option database to configure (or
715
 *      reconfigure) a Notebookframe widget.
716
 *
717
 * Results:
718
 *      The return value is a standard Tcl result.  If TCL_ERROR is
719
 *      returned, then interp->result contains an error message.
720
 *
721
 * Side effects:
722
 *      Configuration information, such as colors, border width,
723
 *      etc. get set for wPtr;  old resources get freed,
724
 *      if there were any.
725
 *
726
 *----------------------------------------------------------------------
727
 */
728
static int
729
WidgetConfigure(interp, wPtr, argc, argv, flags)
730
    Tcl_Interp *interp;                 /* Used for error reporting. */
731
    WidgetPtr wPtr;                     /* Information about widget. */
732
    int argc;                           /* Number of valid entries in argv. */
733
    char **argv;                        /* Arguments. */
734
    int flags;                          /* Flags to pass to
735
                                         * Tk_ConfigureWidget. */
736
{
737
    XGCValues gcValues;
738
    GC newGC;
739
    int mask;
740
 
741
    if (Tk_ConfigureWidget(interp, wPtr->tkwin, configSpecs,
742
            argc, argv, (char *) wPtr, flags) != TCL_OK) {
743
        return TCL_ERROR;
744
    }
745
 
746
    if (wPtr->tabPadx < 3) {
747
        wPtr->tabPadx = 3;
748
    }
749
    if (wPtr->tabPady < 2) {
750
        wPtr->tabPady = 2;
751
    }
752
 
753
    Tk_SetBackgroundFromBorder(wPtr->tkwin, wPtr->bgBorder);
754
 
755
    /*
756
     * Get the back page GC
757
     */
758
    gcValues.foreground = wPtr->backPageColorPtr->pixel;
759
    gcValues.graphics_exposures = False;
760
    newGC = Tk_GetGC(wPtr->tkwin, GCForeground|GCGraphicsExposures,
761
            &gcValues);
762
    if (wPtr->backPageGC != None) {
763
        Tk_FreeGC(wPtr->display, wPtr->backPageGC);
764
    }
765
    wPtr->backPageGC = newGC;
766
 
767
    /*
768
     * Get the text GC
769
     */
770
    gcValues.foreground = wPtr->textColorPtr->pixel;
771
    gcValues.background = Tk_3DBorderColor(wPtr->bgBorder)->pixel;
772
    gcValues.font = TixFontId(wPtr->font);
773
    gcValues.graphics_exposures = False;
774
    newGC = Tk_GetGC(wPtr->tkwin,
775
         GCBackground|GCForeground|GCFont|GCGraphicsExposures,
776
         &gcValues);
777
    if (wPtr->textGC != None) {
778
        Tk_FreeGC(wPtr->display, wPtr->textGC);
779
    }
780
    wPtr->textGC = newGC;
781
 
782
    /*
783
     * Get the disabled GC
784
     */
785
    if (wPtr->disabledFg != NULL) {
786
        gcValues.foreground = wPtr->disabledFg->pixel;
787
        gcValues.background = Tk_3DBorderColor(wPtr->bgBorder)->pixel;
788
        mask = GCForeground|GCBackground|GCFont;
789
    } else {
790
        gcValues.foreground = Tk_3DBorderColor(wPtr->bgBorder)->pixel;
791
        if (wPtr->gray == None) {
792
            wPtr->gray = Tk_GetBitmap(interp, wPtr->tkwin,
793
                        Tk_GetUid("gray50"));
794
            if (wPtr->gray == None) {
795
                return TCL_ERROR;
796
            }
797
        }
798
        gcValues.fill_style = FillStippled;
799
        gcValues.stipple = wPtr->gray;
800
        mask = GCForeground|GCFillStyle|GCFont|GCStipple;
801
    }
802
    gcValues.font = TixFontId(wPtr->font);
803
    newGC = Tk_GetGC(wPtr->tkwin, mask, &gcValues);
804
    if (wPtr->disabledGC != None) {
805
        Tk_FreeGC(wPtr->display, wPtr->disabledGC);
806
    }
807
    wPtr->disabledGC = newGC;
808
 
809
    /*
810
     * Get the focus GC
811
     */
812
    gcValues.foreground         = wPtr->textColorPtr->pixel;
813
    gcValues.background         = Tk_3DBorderColor(wPtr->bgBorder)->pixel;
814
    gcValues.graphics_exposures = False;
815
    gcValues.line_style         = LineDoubleDash;
816
    gcValues.dashes             = 2;
817
    newGC = Tk_GetGC(wPtr->tkwin,
818
        GCForeground|GCBackground|GCGraphicsExposures|GCLineStyle|GCDashList,
819
        &gcValues);
820
    if (wPtr->focusGC != None) {
821
        Tk_FreeGC(wPtr->display, wPtr->focusGC);
822
    }
823
    wPtr->focusGC = newGC;
824
 
825
    WidgetComputeGeometry(wPtr);
826
    RedrawWhenIdle(wPtr);
827
 
828
    return TCL_OK;
829
}
830
 
831
/*
832
 *--------------------------------------------------------------
833
 *
834
 * WidgetEventProc --
835
 *
836
 *      This procedure is invoked by the Tk dispatcher for various
837
 *      events on Notebookframes.
838
 *
839
 * Results:
840
 *      None.
841
 *
842
 * Side effects:
843
 *      When the window gets deleted, internal structures get
844
 *      cleaned up.  When it gets exposed, it is redisplayed.
845
 *
846
 *--------------------------------------------------------------
847
 */
848
 
849
static void
850
WidgetEventProc(clientData, eventPtr)
851
    ClientData clientData;      /* Information about window. */
852
    XEvent *eventPtr;           /* Information about event. */
853
{
854
    WidgetPtr wPtr = (WidgetPtr) clientData;
855
 
856
    switch (eventPtr->type ) {
857
      case DestroyNotify:
858
        if (wPtr->tkwin != NULL) {
859
            wPtr->tkwin = NULL;
860
            Tcl_DeleteCommand(wPtr->interp,
861
                Tcl_GetCommandName(wPtr->interp, wPtr->widgetCmd));
862
        }
863
        CancelRedrawWhenIdle(wPtr);
864
        Tk_EventuallyFree((ClientData) wPtr, (Tix_FreeProc*)WidgetDestroy);
865
        break;
866
 
867
      case Expose:
868
      case ConfigureNotify:
869
        RedrawWhenIdle(wPtr);
870
        break;
871
 
872
      case FocusIn:
873
        if (eventPtr->xfocus.detail != NotifyVirtual) {
874
            wPtr->gotFocus = 1;
875
            if (wPtr->focus == NULL) {
876
                wPtr->focus = wPtr->active;
877
            }
878
            RedrawWhenIdle(wPtr);
879
        }
880
        break;
881
 
882
      case FocusOut:
883
        if (eventPtr->xfocus.detail != NotifyVirtual) {
884
            wPtr->gotFocus = 0;
885
            RedrawWhenIdle(wPtr);
886
        }
887
        break;
888
    }
889
}
890
 
891
/*
892
 *----------------------------------------------------------------------
893
 *
894
 * WidgetDestroy --
895
 *
896
 *      This procedure is invoked by Tk_EventuallyFree or Tk_Release
897
 *      to clean up the internal structure of a Notebookframe at a safe time
898
 *      (when no-one is using it anymore).
899
 *
900
 * Results:
901
 *      None.
902
 *
903
 * Side effects:
904
 *      Everything associated with the Notebookframe is freed up.
905
 *
906
 *----------------------------------------------------------------------
907
 */
908
 
909
static void
910
WidgetDestroy(clientData)
911
    ClientData clientData;      /* Info about my widget. */
912
{
913
    WidgetPtr wPtr = (WidgetPtr) clientData;
914
    Tab * tPtr;
915
 
916
    for (tPtr=wPtr->tabHead; tPtr;) {
917
        Tab * toDelete;
918
 
919
        toDelete = tPtr;
920
        tPtr=tPtr->next;
921
 
922
        DeleteTab(toDelete);
923
    }
924
 
925
    if (wPtr->backPageGC != None) {
926
        Tk_FreeGC(wPtr->display, wPtr->backPageGC);
927
    }
928
    if (wPtr->textGC != None) {
929
        Tk_FreeGC(wPtr->display, wPtr->textGC);
930
    }
931
    if (wPtr->focusGC != None) {
932
        Tk_FreeGC(wPtr->display, wPtr->focusGC);
933
    }
934
    if (wPtr->gray != None) {
935
        Tk_FreeBitmap(wPtr->display, wPtr->gray);
936
    }
937
    if (wPtr->disabledGC != None) {
938
        Tk_FreeGC(wPtr->display, wPtr->disabledGC);
939
    }
940
    Tk_FreeOptions(configSpecs, (char *) wPtr, wPtr->display, 0);
941
    ckfree((char *) wPtr);
942
}
943
 
944
/*
945
 *----------------------------------------------------------------------
946
 *
947
 * WidgetCmdDeletedProc --
948
 *
949
 *      This procedure is invoked when a widget command is deleted.  If
950
 *      the widget isn't already in the process of being destroyed,
951
 *      this command destroys it.
952
 *
953
 * Results:
954
 *      None.
955
 *
956
 * Side effects:
957
 *      The widget is destroyed.
958
 *
959
 *----------------------------------------------------------------------
960
 */
961
static void
962
WidgetCmdDeletedProc(clientData)
963
    ClientData clientData;      /* Pointer to widget record for widget. */
964
{
965
    WidgetPtr wPtr = (WidgetPtr) clientData;
966
 
967
    /*
968
     * This procedure could be invoked either because the window was
969
     * destroyed and the command was then deleted (in which case tkwin
970
     * is NULL) or because the command was deleted, and then this procedure
971
     * destroys the widget.
972
     */
973
    if (wPtr->tkwin != NULL) {
974
        Tk_Window tkwin = wPtr->tkwin;
975
        wPtr->tkwin = NULL;
976
        Tk_DestroyWindow(tkwin);
977
    }
978
}
979
 
980
/*
981
 *----------------------------------------------------------------------
982
 *
983
 * FindTab --
984
 *
985
 *      Seraches for the Tab is the widget's tab list
986
 *----------------------------------------------------------------------
987
 */
988
static Tab * FindTab(interp, wPtr, name)
989
    Tcl_Interp * interp;
990
    WidgetPtr wPtr;
991
    char * name;
992
{
993
    Tab *tPtr;
994
 
995
    for (tPtr=wPtr->tabHead; tPtr; tPtr=tPtr->next) {
996
        if (strcmp(tPtr->name, name) == 0) {
997
            return tPtr;
998
        }
999
    }
1000
 
1001
    Tcl_AppendResult(interp, "Unknown tab \"", name, "\"", (char*) NULL);
1002
    return NULL;
1003
}
1004
 
1005
 
1006
static int TabConfigure(wPtr, tPtr, argv, argc)
1007
    WidgetPtr wPtr;
1008
    Tab *tPtr;
1009
    char ** argv;
1010
    int argc;
1011
{
1012
    if (Tk_ConfigureWidget(wPtr->interp, wPtr->tkwin, tabConfigSpecs,
1013
        argc, argv, (char *)tPtr, TK_CONFIG_ARGV_ONLY) != TCL_OK) {
1014
        return TCL_ERROR;
1015
    }
1016
 
1017
    /*
1018
     * Free the old images for the widget, if there were any.
1019
     */
1020
    if (tPtr->image != NULL) {
1021
        Tk_FreeImage(tPtr->image);
1022
        tPtr->image = NULL;
1023
    }
1024
 
1025
    if (tPtr->imageString != NULL) {
1026
        tPtr->image = Tk_GetImage(wPtr->interp, wPtr->tkwin,
1027
            tPtr->imageString, ImageProc, (ClientData) tPtr);
1028
        if (tPtr->image == NULL) {
1029
            return TCL_ERROR;
1030
        }
1031
    }
1032
 
1033
    if (tPtr->text != NULL) {
1034
        tPtr->numChars = strlen(tPtr->text);
1035
        TixComputeTextGeometry(wPtr->font, tPtr->text, tPtr->numChars,
1036
            tPtr->wrapLength, &tPtr->width, &tPtr->height);
1037
    }
1038
    else if (tPtr->image != NULL) {
1039
        Tk_SizeOfImage(tPtr->image, &tPtr->width, &tPtr->height);
1040
    }
1041
    else if (tPtr->bitmap != None) {
1042
        Tk_SizeOfBitmap(wPtr->display, tPtr->bitmap, &tPtr->width,
1043
            &tPtr->height);
1044
    }
1045
    else {
1046
        tPtr->width = 0;
1047
        tPtr->height = 0;
1048
    }
1049
 
1050
    WidgetComputeGeometry(wPtr);
1051
    RedrawWhenIdle(wPtr);
1052
 
1053
    return TCL_OK;
1054
}
1055
 
1056
/*
1057
 *----------------------------------------------------------------------
1058
 *
1059
 * AddTab --
1060
 *
1061
 *      Adds a new tab into the list of tabs.
1062
 *
1063
 * Results:
1064
 *      The return value is a standard Tcl result.  If TCL_ERROR is
1065
 *      returned, then interp->result contains an error message.
1066
 *
1067
 * Side effects:
1068
 *      Configuration information, such as colors, border width,
1069
 *      etc. get set for wPtr;  old resources get freed,
1070
 *      if there were any.
1071
 *
1072
 *----------------------------------------------------------------------
1073
 */
1074
static int
1075
AddTab(wPtr, name, argv, argc)
1076
    WidgetPtr wPtr;                     /* Information about widget. */
1077
    char * name;                        /* Arguments. */
1078
    char ** argv;
1079
    int argc;
1080
{
1081
    Tab * tPtr;
1082
 
1083
    tPtr = (Tab*)ckalloc(sizeof(Tab));
1084
 
1085
    tPtr->next = NULL;
1086
    tPtr->wPtr = wPtr;
1087
    tPtr->name = (char*)tixStrDup(name);
1088
    tPtr->state = tixNormalUid;
1089
    tPtr->text = NULL;
1090
    tPtr->width = 0;
1091
    tPtr->height = 0;
1092
    tPtr->numChars = 0;
1093
    tPtr->justify = TK_JUSTIFY_CENTER;
1094
    tPtr->wrapLength = 0;
1095
    tPtr->underline = -1;
1096
    tPtr->image = NULL;
1097
    tPtr->imageString = NULL;
1098
    tPtr->bitmap = None;
1099
    tPtr->anchor = TK_ANCHOR_CENTER;
1100
 
1101
    if (TabConfigure(wPtr, tPtr, argv, argc) != TCL_OK) {
1102
        return TCL_ERROR;
1103
    }
1104
 
1105
    /* Append the tab to the end of the list */
1106
 
1107
    if (wPtr->tabHead == 0) {
1108
        wPtr->tabHead = wPtr->tabTail = tPtr;
1109
    }
1110
    else {
1111
        /* Insert right after the tail */
1112
        wPtr->tabTail->next = tPtr;
1113
        wPtr->tabTail = tPtr;
1114
    }
1115
 
1116
    return TCL_OK;
1117
}
1118
 
1119
static void DeleteTab(tPtr)
1120
    Tab * tPtr;
1121
{
1122
    if (tPtr->wPtr->focus == tPtr) {
1123
        tPtr->wPtr->focus = 0;
1124
    }
1125
    if (tPtr->wPtr->active == tPtr) {
1126
        tPtr->wPtr->active = 0;
1127
    }
1128
    if (tPtr->name) {
1129
        ckfree(tPtr->name);
1130
    }
1131
    if (tPtr->image) {
1132
        Tk_FreeImage(tPtr->image);
1133
    }
1134
 
1135
    if (tPtr->wPtr->tkwin) {
1136
        Tk_FreeOptions(tabConfigSpecs, (char *)tPtr,
1137
            Tk_Display(tPtr->wPtr->tkwin), 0);
1138
    }
1139
    ckfree((char*)tPtr);
1140
}
1141
 
1142
/*
1143
 *----------------------------------------------------------------------
1144
 *
1145
 * RedrawWhenIdle --
1146
 *
1147
 *      Redraw this widget when idle
1148
 *
1149
 * Results:
1150
 *
1151
 * Side effects:
1152
 *
1153
 *----------------------------------------------------------------------
1154
 */
1155
static void
1156
RedrawWhenIdle(wPtr)
1157
    WidgetPtr wPtr;                     /* Information about widget. */
1158
{
1159
    if (! wPtr->redrawing && Tk_IsMapped(wPtr->tkwin)) {
1160
        wPtr->redrawing = 1;
1161
        Tk_DoWhenIdle(WidgetDisplay, (ClientData)wPtr);
1162
    }
1163
}
1164
 
1165
/*
1166
 *----------------------------------------------------------------------
1167
 *
1168
 * CancelRedrawWhenIdle --
1169
 *
1170
 *      Redraw this widget when idle
1171
 *
1172
 * Results:
1173
 *
1174
 * Side effects:
1175
 *
1176
 *----------------------------------------------------------------------
1177
 */
1178
static void
1179
CancelRedrawWhenIdle(wPtr)
1180
    WidgetPtr wPtr;                     /* Information about widget. */
1181
{
1182
    if (wPtr->redrawing) {
1183
        wPtr->redrawing = 0;
1184
        Tk_CancelIdleCall(WidgetDisplay, (ClientData)wPtr);
1185
    }
1186
}
1187
 
1188
static void GetTabPoints(wPtr, tPtr, x, points)
1189
    WidgetPtr wPtr;
1190
    Tab * tPtr;
1191
    int x;
1192
    XPoint *points;
1193
{
1194
    points[0].x = x + wPtr->borderWidth;
1195
    points[0].y = wPtr->tabsHeight;
1196
    points[1].x = points[0].x;
1197
    points[1].y = wPtr->borderWidth * 2;
1198
    points[2].x = x + wPtr->borderWidth * 2;
1199
    points[2].y = wPtr->borderWidth;
1200
 
1201
    points[3].x = x + tPtr->width + wPtr->tabPadx*2;
1202
    points[3].y = points[2].y;
1203
    points[4].x = points[3].x + wPtr->borderWidth;
1204
    points[4].y = points[1].y;
1205
    points[5].x = points[4].x;
1206
    points[5].y = points[0].y;
1207
}
1208
 
1209
/*
1210
 *----------------------------------------------------------------------
1211
 *
1212
 * DrawTab --
1213
 *
1214
 *      Draws one tab according to its position and text
1215
 *
1216
 * Results:
1217
 *
1218
 * Side effects:
1219
 *
1220
 *----------------------------------------------------------------------
1221
 */
1222
static void DrawTab(wPtr, tPtr, x, isActive, drawable)
1223
    WidgetPtr wPtr;
1224
    Tab * tPtr;
1225
    int x;
1226
    int isActive;
1227
    Drawable drawable;
1228
{
1229
    Tk_3DBorder border;
1230
    XPoint points[NUM_TAB_POINTS];
1231
    int drawX, drawY, extraH;
1232
 
1233
    if (isActive) {
1234
        border = wPtr->bgBorder;
1235
    } else {
1236
        border = wPtr->inActiveBorder;
1237
    }
1238
 
1239
    GetTabPoints(wPtr, tPtr, x, points);
1240
    drawX = x + wPtr->borderWidth + wPtr->tabPadx;
1241
    drawY = wPtr->borderWidth + wPtr->tabPady;
1242
    extraH = wPtr->tabsHeight - tPtr->height -
1243
      wPtr->borderWidth - wPtr->tabPady *2;
1244
 
1245
    if (extraH > 0) {
1246
        switch (tPtr->anchor) {
1247
          case TK_ANCHOR_SW: case TK_ANCHOR_S: case TK_ANCHOR_SE:
1248
            drawY += extraH;
1249
            break;
1250
          case TK_ANCHOR_W: case TK_ANCHOR_CENTER: case TK_ANCHOR_E:
1251
            drawY += extraH/2;
1252
            break;
1253
          case TK_ANCHOR_N: case TK_ANCHOR_NE: case TK_ANCHOR_NW:
1254
            /*
1255
             * Do nothing.
1256
             */
1257
            break;
1258
        }
1259
    }
1260
 
1261
    Tk_Fill3DPolygon(wPtr->tkwin, drawable,
1262
        border, points, NUM_TAB_POINTS,
1263
        wPtr->borderWidth, TK_RELIEF_SUNKEN);
1264
 
1265
    if (tPtr->text != NULL) {
1266
        if (tPtr->state == tixNormalUid) {
1267
            TixDisplayText(wPtr->display, drawable, wPtr->font,
1268
                tPtr->text, tPtr->numChars,
1269
                drawX, drawY,
1270
                tPtr->width,
1271
                tPtr->justify,
1272
                tPtr->underline,
1273
                wPtr->textGC);
1274
        } else {
1275
            TixDisplayText(wPtr->display, drawable, wPtr->font,
1276
                tPtr->text, tPtr->numChars,
1277
                drawX, drawY,
1278
                tPtr->width,
1279
                tPtr->justify,
1280
                tPtr->underline,
1281
                wPtr->disabledGC);
1282
        }
1283
    }
1284
    else if (tPtr->image != NULL) {
1285
        Tk_RedrawImage(tPtr->image, 0, 0, tPtr->width, tPtr->height,
1286
            drawable, drawX, drawY);
1287
    }
1288
    else if (tPtr->bitmap != None) {
1289
        GC gc;
1290
 
1291
        if (tPtr->state == tixNormalUid) {
1292
            gc = wPtr->textGC;
1293
        } else {
1294
            gc = wPtr->disabledGC;
1295
        }
1296
        XSetClipOrigin(wPtr->display, gc, drawX, drawY);
1297
        XCopyPlane(wPtr->display, tPtr->bitmap, drawable,
1298
                gc, 0, 0, tPtr->width, tPtr->height,
1299
                drawX, drawY, 1);
1300
        XSetClipOrigin(wPtr->display, gc, 0, 0);
1301
    }
1302
 
1303
#if 0
1304
    if (wPtr->gotFocus && tPtr == wPtr->focus) {
1305
        XDrawLine(Tk_Display(wPtr->tkwin), drawable, wPtr->focusGC,
1306
            drawX,
1307
            drawY + tPtr->height + 1,
1308
            drawX + tPtr->width,
1309
            drawY + tPtr->height + 1);
1310
    }
1311
#endif
1312
}
1313
/*
1314
 *----------------------------------------------------------------------
1315
 *
1316
 * FocusTab --
1317
 *
1318
 *      Draws focus highlight on a tab.
1319
 *
1320
 * Results:
1321
 *
1322
 * Side effects:
1323
 *
1324
 *----------------------------------------------------------------------
1325
 */
1326
static void FocusTab(wPtr, tPtr, x, drawable)
1327
    WidgetPtr wPtr;
1328
    Tab * tPtr;
1329
    int x;
1330
    Drawable drawable;
1331
{
1332
    Tk_3DBorder border;
1333
 
1334
    XPoint points[NUM_TAB_POINTS];
1335
 
1336
    if (wPtr->active == tPtr) {
1337
        border = wPtr->bgBorder;
1338
    } else {
1339
        border = wPtr->inActiveBorder;
1340
    }
1341
 
1342
    GetTabPoints(wPtr, tPtr, x, points);
1343
    Tk_Draw3DPolygon(wPtr->tkwin, drawable,
1344
        wPtr->focusBorder, points, NUM_TAB_POINTS,
1345
        wPtr->borderWidth, TK_RELIEF_SUNKEN);
1346
 
1347
    if (wPtr->active == tPtr) {
1348
        Tk_Draw3DPolygon(wPtr->tkwin, drawable,
1349
            border, points, NUM_TAB_POINTS,
1350
            wPtr->borderWidth/2, TK_RELIEF_SUNKEN);
1351
    }
1352
}
1353
 
1354
/*
1355
 *----------------------------------------------------------------------
1356
 *
1357
 * WidgetDisplay --
1358
 *
1359
 *      Redraw this widget
1360
 *
1361
 * Results:
1362
 *
1363
 * Side effects:
1364
 *
1365
 *----------------------------------------------------------------------
1366
 */
1367
static void
1368
WidgetDisplay(clientData)
1369
    ClientData clientData;                      /* Information about widget. */
1370
{
1371
    WidgetPtr wPtr = (WidgetPtr) clientData;
1372
    Tab * tPtr;
1373
    int width, height;
1374
    Drawable buffer;
1375
 
1376
    /* Now let's redraw */
1377
    if (wPtr->tabHead == NULL) {
1378
        /*
1379
         * no tabs to redraw: just draw the border
1380
         */
1381
        if ((wPtr->bgBorder != NULL) && (wPtr->relief != TK_RELIEF_FLAT)) {
1382
            Tk_Fill3DRectangle(wPtr->tkwin, Tk_WindowId(wPtr->tkwin),
1383
                wPtr->bgBorder, 0, 0,
1384
                Tk_Width(wPtr->tkwin), Tk_Height(wPtr->tkwin),
1385
                wPtr->borderWidth, wPtr->relief);
1386
        }
1387
    }
1388
    else {
1389
        int x, y, activex;
1390
 
1391
        buffer = Tix_GetRenderBuffer(wPtr->display, Tk_WindowId(wPtr->tkwin),
1392
            Tk_Width(wPtr->tkwin), Tk_Height(wPtr->tkwin),
1393
            Tk_Depth(wPtr->tkwin));
1394
        XFillRectangle(Tk_Display(wPtr->tkwin), buffer, wPtr->backPageGC,
1395
            0, 0, Tk_Width(wPtr->tkwin), Tk_Height(wPtr->tkwin));
1396
 
1397
        Tk_Fill3DRectangle(wPtr->tkwin, buffer,
1398
                wPtr->bgBorder, 0, wPtr->tabsHeight,
1399
                Tk_Width(wPtr->tkwin),
1400
                Tk_Height(wPtr->tkwin) - wPtr->tabsHeight,
1401
                wPtr->borderWidth, wPtr->relief);
1402
 
1403
        /* Draw the tabs */
1404
        x = 0;
1405
        for (tPtr=wPtr->tabHead; tPtr; tPtr=tPtr->next) {
1406
            if (tPtr == wPtr->active) {
1407
                activex = x;
1408
                DrawTab(wPtr, tPtr, x, 1, buffer);
1409
            }
1410
            else {
1411
                DrawTab(wPtr, tPtr, x, 0, buffer);
1412
            }
1413
            if (tPtr == wPtr->focus && wPtr->gotFocus) {
1414
                FocusTab(wPtr, tPtr, x, buffer);
1415
            }
1416
 
1417
            x += (wPtr->borderWidth +  wPtr->tabPadx) * 2;
1418
            x += tPtr->width;
1419
        }
1420
 
1421
        /* Draw the box */
1422
        Tk_Draw3DRectangle(wPtr->tkwin, buffer,
1423
                wPtr->bgBorder, 0, wPtr->tabsHeight,
1424
                Tk_Width(wPtr->tkwin),
1425
                Tk_Height(wPtr->tkwin) - wPtr->tabsHeight,
1426
                wPtr->borderWidth, wPtr->relief);
1427
 
1428
        if (wPtr->active != NULL) {
1429
            /*
1430
             * Fill up the gap between the active tab and the box
1431
             */
1432
            x = activex + wPtr->borderWidth;
1433
            y = wPtr->tabsHeight;
1434
            height = wPtr->borderWidth;
1435
            width = wPtr->active->width + wPtr->tabPadx*2;
1436
 
1437
            XFillRectangle(wPtr->display, buffer,
1438
                Tk_3DBorderGC(wPtr->tkwin, wPtr->bgBorder, TK_3D_FLAT_GC),
1439
                x, y, width, height);
1440
        }
1441
 
1442
        if (buffer != Tk_WindowId(wPtr->tkwin)) {
1443
            XCopyArea(wPtr->display, buffer, Tk_WindowId(wPtr->tkwin),
1444
                wPtr->textGC, 0, 0, Tk_Width(wPtr->tkwin),
1445
                Tk_Height(wPtr->tkwin), 0, 0);
1446
            Tk_FreePixmap(wPtr->display, buffer);
1447
        }
1448
    }
1449
 
1450
    wPtr->redrawing = 0;
1451
}
1452
 
1453
/*
1454
 *--------------------------------------------------------------
1455
 *
1456
 * ComputeGeometry --
1457
 *
1458
 *
1459
 * Results:
1460
 *      A standard Tcl result.
1461
 *
1462
 * Side effects:
1463
 *      See the user documentation.
1464
 *
1465
 *--------------------------------------------------------------
1466
 */
1467
static void
1468
ComputeGeometry(wPtr)
1469
    WidgetPtr wPtr;
1470
{
1471
    Tab * tPtr;
1472
 
1473
    /* Calculate the requested size of the widget */
1474
    if (wPtr->tabHead == NULL) {
1475
        wPtr->width  = wPtr->borderWidth * 2;
1476
        wPtr->height = wPtr->borderWidth * 2;
1477
 
1478
        wPtr->tabsWidth  = 0;
1479
        wPtr->tabsHeight = 0;
1480
    } else {
1481
        wPtr->tabsWidth  = 0;
1482
        wPtr->tabsHeight = 0;
1483
        for (tPtr=wPtr->tabHead; tPtr; tPtr=tPtr->next) {
1484
 
1485
            if (tPtr->text != NULL) {
1486
                tPtr->numChars = strlen(tPtr->text);
1487
                TixComputeTextGeometry(wPtr->font, tPtr->text,
1488
                    tPtr->numChars, tPtr->wrapLength,
1489
                    &tPtr->width, &tPtr->height);
1490
            }
1491
            else if (tPtr->image != NULL) {
1492
                Tk_SizeOfImage(tPtr->image, &tPtr->width, &tPtr->height);
1493
            }
1494
            else if (tPtr->bitmap != None) {
1495
                Tk_SizeOfBitmap(wPtr->display, tPtr->bitmap, &tPtr->width,
1496
                    &tPtr->height);
1497
            }
1498
            else {
1499
                tPtr->width = 0;
1500
                tPtr->height = 0;
1501
            }
1502
 
1503
            wPtr->tabsWidth += (wPtr->borderWidth + wPtr->tabPadx) * 2;
1504
            wPtr->tabsWidth += tPtr->width;
1505
 
1506
            if (tPtr->height > wPtr->tabsHeight) {
1507
                wPtr->tabsHeight = tPtr->height;
1508
            }
1509
        }
1510
        wPtr->tabsHeight += wPtr->tabPady*2 + wPtr->borderWidth;
1511
 
1512
        wPtr->width  = wPtr->tabsWidth;
1513
        wPtr->height = wPtr->tabsHeight + wPtr->borderWidth*2;
1514
    }
1515
}
1516
 
1517
/*
1518
 *--------------------------------------------------------------
1519
 *
1520
 * WidgetComputeGeometry --
1521
 *
1522
 *      This procedure is invoked to process the Tcl command
1523
 *      that corresponds to a widget managed by this module.
1524
 *      See the user documentation for details on what it does.
1525
 *
1526
 * Results:
1527
 *      A standard Tcl result.
1528
 *
1529
 * Side effects:
1530
 *      See the user documentation.
1531
 *
1532
 *--------------------------------------------------------------
1533
 */
1534
static void
1535
WidgetComputeGeometry(wPtr)
1536
    WidgetPtr wPtr;
1537
{
1538
    int width;
1539
 
1540
    ComputeGeometry(wPtr);
1541
 
1542
    if (!wPtr->isSlave) {
1543
        if (wPtr->desiredWidth > 0) {
1544
            width = wPtr->desiredWidth;
1545
        } else {
1546
            width = wPtr->width;
1547
        }
1548
        Tk_GeometryRequest(wPtr->tkwin, width, wPtr->height);
1549
    }
1550
}
1551
 
1552
/*
1553
 *----------------------------------------------------------------------
1554
 *
1555
 * ImageProc --
1556
 *
1557
 *      This procedure is invoked by the image code whenever the manager
1558
 *      for an image does something that affects the size of contents
1559
 *      of an image displayed in this widget.
1560
 *
1561
 * Results:
1562
 *      None.
1563
 *
1564
 * Side effects:
1565
 *      Arranges for the HList to get redisplayed.
1566
 *
1567
 *----------------------------------------------------------------------
1568
 */
1569
static void
1570
ImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
1571
    ClientData clientData;              /* Pointer to widget record. */
1572
    int x, y;                           /* Upper left pixel (within image)
1573
                                         * that must be redisplayed. */
1574
    int width, height;                  /* Dimensions of area to redisplay
1575
                                         * (may be <= 0). */
1576
    int imgWidth, imgHeight;            /* New dimensions of image. */
1577
{
1578
    Tab * tPtr;
1579
 
1580
    tPtr = (Tab *)clientData;
1581
 
1582
    WidgetComputeGeometry(tPtr->wPtr);
1583
    RedrawWhenIdle(tPtr->wPtr);
1584
}

powered by: WebSVN 2.1.0

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