~ubuntu-branches/ubuntu/dapper/perl-tk/dapper

« back to all changes in this revision

Viewing changes to pTk/mTk/generic/tkOption.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael C. Schultheiss
  • Date: 2006-01-16 16:54:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060116165402-1ppygm8hh8ahel2x
Tags: 1:804.027-2
* Incorporate changes from NMU (Thanks to Steve Kowalik.
  Closes: #348086)
* debian/control: Update Standards-Version (no changes needed)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
 
1
/*
2
2
 * tkOption.c --
3
3
 *
4
4
 *      This module contains procedures to manage the option
6
6
 *      with windows either by name or by class or both.
7
7
 *
8
8
 * Copyright (c) 1990-1994 The Regents of the University of California.
9
 
 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
 
9
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
10
10
 *
11
11
 * See the file "license.terms" for information on usage and redistribution
12
12
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
13
 *
14
 
 * RCS: @(#) $Id: tkOption.c,v 1.2 1998/09/14 18:23:15 stanton Exp $
 
14
 * RCS: @(#) $Id: tkOption.c,v 1.15 2002/08/05 04:30:40 dgp Exp $
15
15
 */
16
16
 
17
17
#include "tkPort.h"
26
26
 * structures exists for each node or leaf in the option tree.  It is
27
27
 * actually stored as part of the parent node, and describes a particular
28
28
 * child of the parent.
 
29
 *
 
30
 * The structure of the option db tree is a little confusing.  There are
 
31
 * four different kinds of nodes in the tree:
 
32
 *      interior class nodes
 
33
 *      interior name nodes
 
34
 *      leaf class nodes
 
35
 *      leaf name nodes
 
36
 *
 
37
 * All interior nodes refer to _window_ classes and names; all leaf nodes
 
38
 * refer to _option_ classes and names.  When looking for a particular option,
 
39
 * therefore, you must compare interior node values to corresponding window
 
40
 * values, and compare leaf node values to corresponding option values.
 
41
 *
 
42
 * The tree is actually stored in a collection of arrays; there is one each
 
43
 * combination of WILDCARD/EXACT and CLASS/NAME and NODE/LEAF.  The NODE arrays
 
44
 * contain the interior nodes of the tree; each element has a pointer to an
 
45
 * array of elements which are the leaves of the tree.  The LEAF arrays, rather
 
46
 * than holding the leaves of the tree, hold a cached subset of the option
 
47
 * database, consisting of the values of all defined options for a single
 
48
 * window, and some additional information about each ancestor of the window
 
49
 * (since some options may be inherited from a parent), all the way back to the
 
50
 * root window.
 
51
 *
 
52
 * Each time a call is made to Tk_GetOption, Tk will attempt to use the cached
 
53
 * information to satisfy the lookup.  If the call is for a window other than
 
54
 * that for which options are currently cached, the portion of the cache that
 
55
 * contains information for common ancestors of the two windows is retained and
 
56
 * the remainder is discarded and rebuilt with new information for the new
 
57
 * window.
29
58
 */
30
59
 
31
60
typedef struct Element {
141
170
 */
142
171
 
143
172
#define NUM_STACKS 8
144
 
static ElArray *stacks[NUM_STACKS];
145
 
static TkWindow *cachedWindow = NULL;   /* Lowest-level window currently
146
 
                                         * loaded in stacks at present. 
147
 
                                         * NULL means stacks have never
148
 
                                         * been used, or have been
149
 
                                         * invalidated because of a change
150
 
                                         * to the database. */
151
173
 
152
174
/*
153
175
 * One of the following structures is used to keep track of each
163
185
                                 * fields when popping out of a level. */
164
186
} StackLevel;
165
187
 
166
 
/*
167
 
 * Information about all of the stack levels that are currently
168
 
 * active.  This array grows dynamically to become as large as needed.
169
 
 */
 
188
typedef struct ThreadSpecificData {
 
189
    int initialized;            /* 0 means the ThreadSpecific Data structure
 
190
                                 * for the current thread needs to be
 
191
                                 * initialized. */
 
192
    ElArray *stacks[NUM_STACKS];
 
193
    TkWindow *cachedWindow;
 
194
                                /* Lowest-level window currently
 
195
                                 * loaded in stacks at present.
 
196
                                 * NULL means stacks have never
 
197
                                 * been used, or have been
 
198
                                 * invalidated because of a change
 
199
                                 * to the database. */
 
200
    /*
 
201
     * Information about all of the stack levels that are currently
 
202
     * active.  This array grows dynamically to become as large as needed.
 
203
     */
170
204
 
171
 
static StackLevel *levels = NULL;
172
 
                                /* Array describing current stack. */
173
 
static int numLevels = 0;       /* Total space allocated. */
174
 
static int curLevel = -1;       /* Highest level currently in use.  Note:
 
205
    StackLevel *levels;         /* Array describing current stack. */
 
206
    int numLevels;              /* Total space allocated. */
 
207
    int curLevel;               /* Highest level currently in use.  Note:
175
208
                                 * curLevel is never 0!  (I don't remember
176
209
                                 * why anymore...) */
177
 
 
178
 
/*
179
 
 * The variable below is a serial number for all options entered into
180
 
 * the database so far.  It increments on each addition to the option
181
 
 * database.  It is used in computing option priorities, so that the
182
 
 * most recent entry wins when choosing between options at the same
183
 
 * priority level.
184
 
 */
185
 
 
186
 
static int serial = 0;
187
 
 
188
 
/*
189
 
 * Special "no match" Element to use as default for searches.
190
 
 */
191
 
 
192
 
static Element defaultMatch;
 
210
    /*
 
211
     * The variable below is a serial number for all options entered into
 
212
     * the database so far.  It increments on each addition to the option
 
213
     * database.  It is used in computing option priorities, so that the
 
214
     * most recent entry wins when choosing between options at the same
 
215
     * priority level.
 
216
     */
 
217
 
 
218
    int serial;
 
219
    Element defaultMatch;       /* Special "no match" Element to use as
 
220
                                 * default for searches.*/
 
221
} ThreadSpecificData;
 
222
static Tcl_ThreadDataKey dataKey;
193
223
 
194
224
/*
195
225
 * Forward declarations for procedures defined in this file:
203
233
static void             ExtendStacks _ANSI_ARGS_((ElArray *arrayPtr,
204
234
                            int leaf));
205
235
static int              GetDefaultOptions _ANSI_ARGS_((Tcl_Interp *interp,
206
 
                            TkWindow *winPtr)); 
207
 
static ElArray *        NewArray _ANSI_ARGS_((int numEls));     
 
236
                            TkWindow *winPtr));
 
237
static ElArray *        NewArray _ANSI_ARGS_((int numEls));
 
238
static void             OptionThreadExitProc _ANSI_ARGS_((
 
239
                            ClientData clientData));
208
240
static void             OptionInit _ANSI_ARGS_((TkMainInfo *mainPtr));
209
241
static int              ParsePriority _ANSI_ARGS_((Tcl_Interp *interp,
210
242
                            char *string));
211
243
static int              ReadOptionFile _ANSI_ARGS_((Tcl_Interp *interp,
212
244
                            Tk_Window tkwin, char *fileName, int priority));
213
245
static void             SetupStacks _ANSI_ARGS_((TkWindow *winPtr, int leaf));
214
 
 
 
246
 
215
247
/*
216
248
 *--------------------------------------------------------------
217
249
 *
232
264
Tk_AddOption(tkwin, name, value, priority)
233
265
    Tk_Window tkwin;            /* Window token;  option will be associated
234
266
                                 * with main window for this window. */
235
 
    char *name;                 /* Multi-element name of option. */
236
 
    char *value;                /* String value for option. */
 
267
    CONST char *name;           /* Multi-element name of option. */
 
268
    CONST char *value;          /* String value for option. */
237
269
    int priority;               /* Overall priority level to use for
238
270
                                 * this option, such as TK_USER_DEFAULT_PRIO
239
271
                                 * or TK_INTERACTIVE_PRIO.  Must be between
243
275
    register ElArray **arrayPtrPtr;
244
276
    register Element *elPtr;
245
277
    Element newEl;
246
 
    register char *p;
247
 
    char *field;
 
278
    register CONST char *p;
 
279
    CONST char *field;
248
280
    int count, firstField, length;
249
281
#define TMP_SIZE 100
250
282
    char tmp[TMP_SIZE+1];
 
283
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
284
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
251
285
 
252
286
    if (winPtr->mainPtr->optionRootPtr == NULL) {
253
287
        OptionInit(winPtr->mainPtr);
254
288
    }
255
 
    cachedWindow = NULL;        /* Invalidate the cache. */
 
289
    tsdPtr->cachedWindow = NULL;        /* Invalidate the cache. */
256
290
 
257
291
    /*
258
292
     * Compute the priority for the new element, including both the
265
299
    } else if (priority > TK_MAX_PRIO) {
266
300
        priority = TK_MAX_PRIO;
267
301
    }
268
 
    newEl.priority = (priority << 24) + serial;
269
 
    serial++;
 
302
    newEl.priority = (priority << 24) + tsdPtr->serial;
 
303
    tsdPtr->serial++;
270
304
 
271
305
    /*
272
306
     * Parse the option one field at a time.
362
396
        }
363
397
    }
364
398
}
365
 
 
 
399
 
366
400
/*
367
401
 *--------------------------------------------------------------
368
402
 *
388
422
Tk_GetOption(tkwin, name, className)
389
423
    Tk_Window tkwin;            /* Token for window that option is
390
424
                                 * associated with. */
391
 
    char *name;                 /* Name of option. */
392
 
    char *className;            /* Class of option.  NULL means there
 
425
    CONST char *name;           /* Name of option. */
 
426
    CONST char *className;      /* Class of option.  NULL means there
393
427
                                 * is no class for this option:  just
394
428
                                 * check for name. */
395
429
{
396
 
    Tk_Uid nameId, classId;
 
430
    Tk_Uid nameId, classId = NULL;
 
431
    char *masqName;
397
432
    register Element *elPtr, *bestPtr;
398
433
    register int count;
 
434
    StackLevel *levelPtr;
 
435
    int stackDepth[NUM_STACKS];
 
436
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
437
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
399
438
 
400
439
    /*
401
440
     * Note:  no need to call OptionInit here:  it will be done by
402
441
     * the SetupStacks call below (squeeze out those nanoseconds).
403
442
     */
404
443
 
405
 
    if (tkwin != (Tk_Window) cachedWindow) {
 
444
    if (tkwin != (Tk_Window) tsdPtr->cachedWindow) {
406
445
        SetupStacks((TkWindow *) tkwin, 1);
407
446
    }
408
447
 
409
 
    nameId = Tk_GetUid(name);
410
 
    bestPtr = &defaultMatch;
411
 
    for (elPtr = stacks[EXACT_LEAF_NAME]->els,
412
 
            count = stacks[EXACT_LEAF_NAME]->numUsed; count > 0;
413
 
            elPtr++, count--) {
414
 
        if ((elPtr->nameUid == nameId)
415
 
                && (elPtr->priority > bestPtr->priority)) {
416
 
            bestPtr = elPtr;
417
 
        }
418
 
    }
419
 
    for (elPtr = stacks[WILDCARD_LEAF_NAME]->els,
420
 
            count = stacks[WILDCARD_LEAF_NAME]->numUsed; count > 0;
421
 
            elPtr++, count--) {
422
 
        if ((elPtr->nameUid == nameId)
423
 
                && (elPtr->priority > bestPtr->priority)) {
424
 
            bestPtr = elPtr;
425
 
        }
426
 
    }
 
448
    /*
 
449
     * Get a default "best" match.
 
450
     */
 
451
 
 
452
    bestPtr = &tsdPtr->defaultMatch;
 
453
 
 
454
    /*
 
455
     * For megawidget support, we want to have some widget options masquerade
 
456
     * as options for other widgets.  For example, a combobox has a button in
 
457
     * it; this button ought to pick up the *Button.background, etc., options.
 
458
     * But because the class of the widget is Combobox, our normal search
 
459
     * won't get that option.
 
460
     *
 
461
     * To work around this, the option name field syntax was extended to allow
 
462
     * for a "." in the name; if this character occurs in the name, then it
 
463
     * indicates that this name contains a new window class and an option name,
 
464
     * ie, "Button.foreground".  If we see this form in the name field, we
 
465
     * query the option database directly (since the option stacks will not
 
466
     * have the information we need).
 
467
     */
 
468
 
 
469
    masqName = strchr(name, (int)'.');
 
470
    if (masqName != NULL) {
 
471
        /*
 
472
         * This option is masquerading with a different window class.
 
473
         * Search the stack to the depth it was before the current window's
 
474
         * information was pushed (the value for which is stored in the bases
 
475
         * field).
 
476
         */
 
477
        levelPtr = &tsdPtr->levels[tsdPtr->curLevel];
 
478
        nameId = Tk_GetUid(masqName+1);
 
479
        for (count = 0; count < NUM_STACKS; count++) {
 
480
            stackDepth[count] = levelPtr->bases[count];
 
481
        }
 
482
    } else {
 
483
        /*
 
484
         * No option masquerading here.  Just use the current level to get the
 
485
         * stack depths.
 
486
         */
 
487
        nameId = Tk_GetUid(name);
 
488
        for (count = 0; count < NUM_STACKS; count++) {
 
489
            stackDepth[count] = tsdPtr->stacks[count]->numUsed;
 
490
        }
 
491
    }
 
492
 
 
493
    /*
 
494
     * Probe the stacks for matches.
 
495
     */
 
496
 
 
497
    for (elPtr = tsdPtr->stacks[EXACT_LEAF_NAME]->els,
 
498
             count = stackDepth[EXACT_LEAF_NAME]; count > 0;
 
499
         elPtr++, count--) {
 
500
        if ((elPtr->nameUid == nameId)
 
501
                && (elPtr->priority > bestPtr->priority)) {
 
502
            bestPtr = elPtr;
 
503
        }
 
504
    }
 
505
    for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_NAME]->els,
 
506
             count = stackDepth[WILDCARD_LEAF_NAME]; count > 0;
 
507
         elPtr++, count--) {
 
508
        if ((elPtr->nameUid == nameId)
 
509
                && (elPtr->priority > bestPtr->priority)) {
 
510
            bestPtr = elPtr;
 
511
        }
 
512
    }
 
513
 
427
514
    if (className != NULL) {
428
515
        classId = Tk_GetUid(className);
429
 
        for (elPtr = stacks[EXACT_LEAF_CLASS]->els,
430
 
                count = stacks[EXACT_LEAF_CLASS]->numUsed; count > 0;
431
 
                elPtr++, count--) {
432
 
            if ((elPtr->nameUid == classId)
433
 
                    && (elPtr->priority > bestPtr->priority)) {
434
 
                bestPtr = elPtr;
435
 
            }
436
 
        }
437
 
        for (elPtr = stacks[WILDCARD_LEAF_CLASS]->els,
438
 
                count = stacks[WILDCARD_LEAF_CLASS]->numUsed; count > 0;
439
 
                elPtr++, count--) {
440
 
            if ((elPtr->nameUid == classId)
441
 
                    && (elPtr->priority > bestPtr->priority)) {
442
 
                bestPtr = elPtr;
443
 
            }
444
 
        }
445
 
    }
 
516
        for (elPtr = tsdPtr->stacks[EXACT_LEAF_CLASS]->els,
 
517
                 count = stackDepth[EXACT_LEAF_CLASS]; count > 0;
 
518
             elPtr++, count--) {
 
519
            if ((elPtr->nameUid == classId)
 
520
                    && (elPtr->priority > bestPtr->priority)) {
 
521
                bestPtr = elPtr;
 
522
            }
 
523
        }
 
524
        for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_CLASS]->els,
 
525
                 count = stackDepth[WILDCARD_LEAF_CLASS]; count > 0;
 
526
             elPtr++, count--) {
 
527
            if ((elPtr->nameUid == classId)
 
528
                    && (elPtr->priority > bestPtr->priority)) {
 
529
                bestPtr = elPtr;
 
530
            }
 
531
        }
 
532
    }
 
533
 
 
534
    /*
 
535
     * If this option was masquerading with a different window class,
 
536
     * probe the option database now.  Note that this will be inefficient
 
537
     * if the option database is densely populated, or if the widget has many
 
538
     * masquerading options.
 
539
     */
 
540
 
 
541
    if (masqName != NULL) {
 
542
        char *masqClass;
 
543
        Tk_Uid nodeId, winClassId, winNameId;
 
544
        unsigned int classNameLength;
 
545
        register Element *nodePtr, *leafPtr;
 
546
        static int searchOrder[] = { EXACT_NODE_NAME,
 
547
                                         WILDCARD_NODE_NAME,
 
548
                                         EXACT_NODE_CLASS,
 
549
                                         WILDCARD_NODE_CLASS,
 
550
                                         -1 };
 
551
        int *currentPtr, currentStack, leafCount;
 
552
 
 
553
        /*
 
554
         * Extract the masquerade class name from the name field.
 
555
         */
 
556
 
 
557
        classNameLength = (unsigned int)(masqName - name);
 
558
        masqClass       = (char *)ckalloc(classNameLength + 1);
 
559
        strncpy(masqClass, name, classNameLength);
 
560
        masqClass[classNameLength] = '\0';
 
561
 
 
562
        winClassId      = Tk_GetUid(masqClass);
 
563
        ckfree(masqClass);
 
564
        winNameId       = ((TkWindow *)tkwin)->nameUid;
 
565
 
 
566
        levelPtr = &tsdPtr->levels[tsdPtr->curLevel];
 
567
 
 
568
        for (currentPtr = searchOrder; *currentPtr != -1; currentPtr++) {
 
569
            currentStack = *currentPtr;
 
570
            nodePtr     = tsdPtr->stacks[currentStack]->els;
 
571
            count       = levelPtr->bases[currentStack];
 
572
 
 
573
            /*
 
574
             * For wildcard stacks, check all entries;  for non-wildcard
 
575
             * stacks, only check things that matched in the parent.
 
576
             */
 
577
 
 
578
            if (!(currentStack & WILDCARD)) {
 
579
                nodePtr += levelPtr[-1].bases[currentStack];
 
580
                count   -= levelPtr[-1].bases[currentStack];
 
581
            }
 
582
 
 
583
            if (currentStack && CLASS) {
 
584
                nodeId = winClassId;
 
585
            } else {
 
586
                nodeId = winNameId;
 
587
            }
 
588
 
 
589
            for ( ; count > 0; nodePtr++, count--) {
 
590
                if (nodePtr->nameUid == nodeId) {
 
591
                    leafPtr     = nodePtr->child.arrayPtr->els;
 
592
                    leafCount   = nodePtr->child.arrayPtr->numUsed;
 
593
                    for ( ; leafCount > 0; leafPtr++, leafCount--) {
 
594
                        if (leafPtr->flags & CLASS && className != NULL) {
 
595
                            if (leafPtr->nameUid == classId &&
 
596
                                    leafPtr->priority > bestPtr->priority) {
 
597
                                bestPtr = leafPtr;
 
598
                            }
 
599
                        } else {
 
600
                            if (leafPtr->nameUid == nameId &&
 
601
                                    leafPtr->priority > bestPtr->priority) {
 
602
                                bestPtr = leafPtr;
 
603
                            }
 
604
                        }
 
605
                    }
 
606
                }
 
607
            }
 
608
        }
 
609
    }
 
610
 
446
611
    return bestPtr->child.valueUid;
447
612
}
448
 
 
 
613
 
449
614
/*
450
615
 *--------------------------------------------------------------
451
616
 *
452
 
 * Tk_OptionCmd --
 
617
 * Tk_OptionObjCmd --
453
618
 *
454
619
 *      This procedure is invoked to process the "option" Tcl command.
455
620
 *      See the user documentation for details on what it does.
464
629
 */
465
630
 
466
631
int
467
 
Tk_OptionCmd(clientData, interp, argc, argv)
 
632
Tk_OptionObjCmd(clientData, interp, objc, objv)
468
633
    ClientData clientData;      /* Main window associated with
469
634
                                 * interpreter. */
470
635
    Tcl_Interp *interp;         /* Current interpreter. */
471
 
    int argc;                   /* Number of arguments. */
472
 
    char **argv;                /* Argument strings. */
 
636
    int objc;                   /* Number of Tcl_Obj arguments. */
 
637
    Tcl_Obj *CONST objv[];      /* Tcl_Obj arguments. */
473
638
{
474
639
    Tk_Window tkwin = (Tk_Window) clientData;
475
 
    size_t length;
476
 
    char c;
477
 
 
478
 
    if (argc < 2) {
479
 
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
480
 
                " cmd arg ?arg ...?\"", (char *) NULL);
481
 
        return TCL_ERROR;
482
 
    }
483
 
    c = argv[1][0];
484
 
    length = strlen(argv[1]);
485
 
    if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)) {
486
 
        int priority;
487
 
 
488
 
        if ((argc != 4) && (argc != 5)) {
489
 
            Tcl_AppendResult(interp, "wrong # args: should be \"",
490
 
                    argv[0], " add pattern value ?priority?\"", (char *) NULL);
491
 
            return TCL_ERROR;
492
 
        }
493
 
        if (argc == 4) {
494
 
            priority = TK_INTERACTIVE_PRIO;
495
 
        } else {
496
 
            priority = ParsePriority(interp, argv[4]);
497
 
            if (priority < 0) {
498
 
                return TCL_ERROR;
499
 
            }
500
 
        }
501
 
        Tk_AddOption(tkwin, argv[2], argv[3], priority);
502
 
        return TCL_OK;
503
 
    } else if ((c == 'c') && (strncmp(argv[1], "clear", length) == 0)) {
504
 
        TkMainInfo *mainPtr;
505
 
 
506
 
        if (argc != 2) {
507
 
            Tcl_AppendResult(interp, "wrong # args: should be \"",
508
 
                    argv[0], " clear\"", (char *) NULL);
509
 
            return TCL_ERROR;
510
 
        }
511
 
        mainPtr = ((TkWindow *) tkwin)->mainPtr;
512
 
        if (mainPtr->optionRootPtr != NULL) {
513
 
            ClearOptionTree(mainPtr->optionRootPtr);
514
 
            mainPtr->optionRootPtr = NULL;
515
 
        }
516
 
        cachedWindow = NULL;
517
 
        return TCL_OK;
518
 
    } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
519
 
        Tk_Window window;
520
 
        Tk_Uid value;
521
 
 
522
 
        if (argc != 5) {
523
 
            Tcl_AppendResult(interp, "wrong # args: should be \"",
524
 
                    argv[0], " get window name class\"", (char *) NULL);
525
 
            return TCL_ERROR;
526
 
        }
527
 
        window = Tk_NameToWindow(interp, argv[2], tkwin);
528
 
        if (window == NULL) {
529
 
            return TCL_ERROR;
530
 
        }
531
 
        value = Tk_GetOption(window, argv[3], argv[4]);
532
 
        if (value != NULL) {
533
 
            interp->result = value;
534
 
        }
535
 
        return TCL_OK;
536
 
    } else if ((c == 'r') && (strncmp(argv[1], "readfile", length) == 0)) {
537
 
        int priority;
538
 
 
539
 
        if ((argc != 3) && (argc != 4)) {
540
 
            Tcl_AppendResult(interp, "wrong # args: should be \"",
541
 
                    argv[0], " readfile fileName ?priority?\"",
542
 
                    (char *) NULL);
543
 
            return TCL_ERROR;
544
 
        }
545
 
        if (argc == 4) {
546
 
            priority = ParsePriority(interp, argv[3]);
547
 
            if (priority < 0) {
548
 
                return TCL_ERROR;
549
 
            }
550
 
        } else {
551
 
            priority = TK_INTERACTIVE_PRIO;
552
 
        }
553
 
        return ReadOptionFile(interp, tkwin, argv[2], priority);
554
 
    } else {
555
 
        Tcl_AppendResult(interp, "bad option \"", argv[1],
556
 
                "\": must be add, clear, get, or readfile", (char *) NULL);
557
 
        return TCL_ERROR;
558
 
    }
 
640
    int index, result;
 
641
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
642
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
 
643
 
 
644
    static CONST char *optionCmds[] = {
 
645
        "add", "clear", "get", "readfile", NULL
 
646
    };
 
647
 
 
648
    enum optionVals {
 
649
        OPTION_ADD, OPTION_CLEAR, OPTION_GET, OPTION_READFILE
 
650
    };
 
651
 
 
652
    if (objc < 2) {
 
653
        Tcl_WrongNumArgs(interp, 1, objv, "cmd arg ?arg ...?");
 
654
        return TCL_ERROR;
 
655
    }
 
656
 
 
657
    result = Tcl_GetIndexFromObj(interp, objv[1], optionCmds, "option", 0,
 
658
            &index);
 
659
    if (result != TCL_OK) {
 
660
        return result;
 
661
    }
 
662
 
 
663
    result = TCL_OK;
 
664
    switch ((enum optionVals) index) {
 
665
        case OPTION_ADD: {
 
666
            int priority;
 
667
            if ((objc != 4) && (objc != 5)) {
 
668
                Tcl_WrongNumArgs(interp, 2, objv, "pattern value ?priority?");
 
669
                return TCL_ERROR;
 
670
            }
 
671
 
 
672
            if (objc == 4) {
 
673
                priority = TK_INTERACTIVE_PRIO;
 
674
            } else {
 
675
                priority = ParsePriority(interp, Tcl_GetString(objv[4]));
 
676
                if (priority < 0) {
 
677
                    return TCL_ERROR;
 
678
                }
 
679
            }
 
680
            Tk_AddOption(tkwin, Tcl_GetString(objv[2]),
 
681
                    Tcl_GetString(objv[3]), priority);
 
682
            break;
 
683
        }
 
684
 
 
685
        case OPTION_CLEAR: {
 
686
            TkMainInfo *mainPtr;
 
687
 
 
688
            if (objc != 2) {
 
689
                Tcl_WrongNumArgs(interp, 2, objv, "");
 
690
                return TCL_ERROR;
 
691
            }
 
692
            mainPtr = ((TkWindow *) tkwin)->mainPtr;
 
693
            if (mainPtr->optionRootPtr != NULL) {
 
694
                ClearOptionTree(mainPtr->optionRootPtr);
 
695
                mainPtr->optionRootPtr = NULL;
 
696
            }
 
697
            tsdPtr->cachedWindow = NULL;
 
698
            break;
 
699
        }
 
700
 
 
701
        case OPTION_GET: {
 
702
            Tk_Window window;
 
703
            Tk_Uid value;
 
704
 
 
705
            if (objc != 5) {
 
706
                Tcl_WrongNumArgs(interp, 2, objv, "window name class");
 
707
                return TCL_ERROR;
 
708
            }
 
709
            window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
 
710
            if (window == NULL) {
 
711
                return TCL_ERROR;
 
712
            }
 
713
            value = Tk_GetOption(window, Tcl_GetString(objv[3]),
 
714
                    Tcl_GetString(objv[4]));
 
715
            if (value != NULL) {
 
716
                Tcl_SetResult(interp, (char *)value, TCL_STATIC);
 
717
            }
 
718
            break;
 
719
        }
 
720
 
 
721
        case OPTION_READFILE: {
 
722
            int priority;
 
723
 
 
724
            if ((objc != 3) && (objc != 4)) {
 
725
                Tcl_WrongNumArgs(interp, 2, objv, "fileName ?priority?");
 
726
                return TCL_ERROR;
 
727
            }
 
728
 
 
729
            if (objc == 4) {
 
730
                priority = ParsePriority(interp, Tcl_GetString(objv[3]));
 
731
                if (priority < 0) {
 
732
                    return TCL_ERROR;
 
733
                }
 
734
            } else {
 
735
                priority = TK_INTERACTIVE_PRIO;
 
736
            }
 
737
            result = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]),
 
738
                    priority);
 
739
            break;
 
740
        }
 
741
    }
 
742
    return result;
559
743
}
560
 
 
 
744
 
561
745
/*
562
746
 *--------------------------------------------------------------
563
747
 *
581
765
TkOptionDeadWindow(winPtr)
582
766
    register TkWindow *winPtr;          /* Window to be cleaned up. */
583
767
{
 
768
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
769
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
 
770
 
584
771
    /*
585
772
     * If this window is in the option stacks, then clear the stacks.
586
773
     */
588
775
    if (winPtr->optionLevel != -1) {
589
776
        int i;
590
777
 
591
 
        for (i = 1; i <= curLevel; i++) {
592
 
            levels[i].winPtr->optionLevel = -1;
 
778
        for (i = 1; i <= tsdPtr->curLevel; i++) {
 
779
            tsdPtr->levels[i].winPtr->optionLevel = -1;
593
780
        }
594
 
        curLevel = -1;
595
 
        cachedWindow = NULL;
 
781
        tsdPtr->curLevel = -1;
 
782
        tsdPtr->cachedWindow = NULL;
596
783
    }
597
784
 
598
785
    /*
600
787
     * database.
601
788
     */
602
789
 
603
 
    if ((winPtr->mainPtr->winPtr == winPtr)
 
790
    if ((winPtr->mainPtr != NULL) && (winPtr->mainPtr->winPtr == winPtr)
604
791
            && (winPtr->mainPtr->optionRootPtr != NULL)) {
605
792
        ClearOptionTree(winPtr->mainPtr->optionRootPtr);
606
793
        winPtr->mainPtr->optionRootPtr = NULL;
607
794
    }
608
795
}
609
 
 
 
796
 
610
797
/*
611
798
 *----------------------------------------------------------------------
612
799
 *
632
819
{
633
820
    int i, j, *basePtr;
634
821
    ElArray *arrayPtr;
 
822
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
823
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
635
824
 
636
825
    if (winPtr->optionLevel == -1) {
637
826
        return;
642
831
     * flush all of the levels above the matching one.
643
832
     */
644
833
 
645
 
    for (i = 1; i <= curLevel; i++) {
646
 
        if (levels[i].winPtr == winPtr) {
647
 
            for (j = i; j <= curLevel; j++) {
648
 
                levels[j].winPtr->optionLevel = -1;
 
834
    for (i = 1; i <= tsdPtr->curLevel; i++) {
 
835
        if (tsdPtr->levels[i].winPtr == winPtr) {
 
836
            for (j = i; j <= tsdPtr->curLevel; j++) {
 
837
                tsdPtr->levels[j].winPtr->optionLevel = -1;
649
838
            }
650
 
            curLevel = i-1;
651
 
            basePtr = levels[i].bases;
 
839
            tsdPtr->curLevel = i-1;
 
840
            basePtr = tsdPtr->levels[i].bases;
652
841
            for (j = 0; j < NUM_STACKS; j++) {
653
 
                arrayPtr = stacks[j];
 
842
                arrayPtr = tsdPtr->stacks[j];
654
843
                arrayPtr->numUsed = basePtr[j];
655
844
                arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
656
845
            }
657
 
            if (curLevel <= 0) {
658
 
                cachedWindow = NULL;
 
846
            if (tsdPtr->curLevel <= 0) {
 
847
                tsdPtr->cachedWindow = NULL;
659
848
            } else {
660
 
                cachedWindow = levels[curLevel].winPtr;
 
849
                tsdPtr->cachedWindow = tsdPtr->levels[tsdPtr->curLevel].winPtr;
661
850
            }
662
851
            break;
663
852
        }
664
853
    }
665
854
}
666
 
 
 
855
 
667
856
/*
668
857
 *----------------------------------------------------------------------
669
858
 *
674
863
 * Results:
675
864
 *      The return value is the integer priority level corresponding
676
865
 *      to string, or -1 if string doesn't point to a valid priority level.
677
 
 *      In this case, an error message is left in interp->result.
 
866
 *      In this case, an error message is left in the interp's result.
678
867
 *
679
868
 * Side effects:
680
869
 *      None.
720
909
    }
721
910
    return priority;
722
911
}
723
 
 
 
912
 
724
913
/*
725
914
 *----------------------------------------------------------------------
726
915
 *
734
923
 * Results:
735
924
 *      The return value is a standard Tcl return code.  In the case of
736
925
 *      an error in parsing string, TCL_ERROR will be returned and an
737
 
 *      error message will be left in interp->result.  The memory at
 
926
 *      error message will be left in the interp's result.  The memory at
738
927
 *      string is totally trashed by this procedure.  If you care about
739
928
 *      its contents, make a copy before calling here.
740
929
 *
784
973
            src++;
785
974
            lineNum++;
786
975
            continue;
787
 
        } 
 
976
        }
788
977
        if (*src == '\0') {
789
978
            break;
790
979
        }
797
986
        dst = name = src;
798
987
        while (*src != ':') {
799
988
            if ((*src == '\0') || (*src == '\n')) {
800
 
                sprintf(interp->result, "missing colon on line %d",
801
 
                        lineNum);
 
989
                char buf[32 + TCL_INTEGER_SPACE];
 
990
 
 
991
                sprintf(buf, "missing colon on line %d", lineNum);
 
992
                Tcl_SetResult(interp, buf, TCL_VOLATILE);
802
993
                return TCL_ERROR;
803
994
            }
804
995
            if ((src[0] == '\\') && (src[1] == '\n')) {
830
1021
            src++;
831
1022
        }
832
1023
        if (*src == '\0') {
833
 
            sprintf(interp->result, "missing value on line %d", lineNum);
 
1024
            char buf[32 + TCL_INTEGER_SPACE];
 
1025
 
 
1026
            sprintf(buf, "missing value on line %d", lineNum);
 
1027
            Tcl_SetResult(interp, buf, TCL_VOLATILE);
834
1028
            return TCL_ERROR;
835
1029
        }
836
1030
 
842
1036
        dst = value = src;
843
1037
        while (*src != '\n') {
844
1038
            if (*src == '\0') {
845
 
                sprintf(interp->result, "missing newline on line %d",
846
 
                        lineNum);
 
1039
                char buf[32 + TCL_INTEGER_SPACE];
 
1040
 
 
1041
                sprintf(buf, "missing newline on line %d", lineNum);
 
1042
                Tcl_SetResult(interp, buf, TCL_VOLATILE);
847
1043
                return TCL_ERROR;
848
1044
            }
849
1045
            if ((src[0] == '\\') && (src[1] == '\n')) {
867
1063
    }
868
1064
    return TCL_OK;
869
1065
}
870
 
 
 
1066
 
871
1067
/*
872
1068
 *----------------------------------------------------------------------
873
1069
 *
879
1075
 * Results:
880
1076
 *      The return value is a standard Tcl return code.  In the case of
881
1077
 *      an error in parsing string, TCL_ERROR will be returned and an
882
 
 *      error message will be left in interp->result.
 
1078
 *      error message will be left in the interp's result.
883
1079
 *
884
1080
 * Side effects:
885
1081
 *      None.
898
1094
                                 * or TK_INTERACTIVE_PRIO.  Must be between
899
1095
                                 * 0 and TK_MAX_PRIO. */
900
1096
{
901
 
    char *realName, *buffer;
 
1097
    CONST char *realName;
 
1098
    char *buffer;
902
1099
    int result, bufferSize;
903
1100
    Tcl_Channel chan;
904
1101
    Tcl_DString newName;
906
1103
    /*
907
1104
     * Prevent file system access in a safe interpreter.
908
1105
     */
909
 
    
 
1106
 
910
1107
    if (Tcl_IsSafe(interp)) {
911
1108
        Tcl_AppendResult(interp, "can't read options from a file in a",
912
1109
                " safe interpreter", (char *) NULL);
913
1110
        return TCL_ERROR;
914
1111
    }
915
 
    
 
1112
 
916
1113
    realName = Tcl_TranslateFileName(interp, fileName, &newName);
917
1114
    if (realName == NULL) {
918
1115
        return TCL_ERROR;
930
1127
     * Compute size of file by seeking to the end of the file.  This will
931
1128
     * overallocate if we are performing CRLF translation.
932
1129
     */
933
 
    
934
 
    bufferSize = Tcl_Seek(chan, 0L, SEEK_END);
935
 
    (void) Tcl_Seek(chan, 0L, SEEK_SET);
 
1130
 
 
1131
    bufferSize = (int) Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_END);
 
1132
    (void) Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_SET);
936
1133
 
937
1134
    if (bufferSize < 0) {
938
1135
        Tcl_AppendResult(interp, "error seeking to end of file \"",
955
1152
    ckfree(buffer);
956
1153
    return result;
957
1154
}
958
 
 
 
1155
 
959
1156
/*
960
1157
 *--------------------------------------------------------------
961
1158
 *
986
1183
    arrayPtr->nextToUse = arrayPtr->els;
987
1184
    return arrayPtr;
988
1185
}
989
 
 
 
1186
 
990
1187
/*
991
1188
 *--------------------------------------------------------------
992
1189
 *
1032
1229
    arrayPtr->numUsed++;
1033
1230
    return arrayPtr;
1034
1231
}
1035
 
 
 
1232
 
1036
1233
/*
1037
1234
 *--------------------------------------------------------------
1038
1235
 *
1062
1259
    int level, i, *iPtr;
1063
1260
    register StackLevel *levelPtr;
1064
1261
    register ElArray *arrayPtr;
 
1262
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
1263
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1065
1264
 
1066
1265
    /*
1067
1266
     * The following array defines the order in which the current
1086
1285
 
1087
1286
    if (winPtr->parentPtr != NULL) {
1088
1287
        level = winPtr->parentPtr->optionLevel;
1089
 
        if ((level == -1) || (cachedWindow == NULL)) {
 
1288
        if ((level == -1) || (tsdPtr->cachedWindow == NULL)) {
1090
1289
            SetupStacks(winPtr->parentPtr, 0);
1091
1290
            level = winPtr->parentPtr->optionLevel;
1092
1291
        }
1100
1299
     * mark those windows as no longer having cached information.
1101
1300
     */
1102
1301
 
1103
 
    if (curLevel >= level) {
1104
 
        while (curLevel >= level) {
1105
 
            levels[curLevel].winPtr->optionLevel = -1;
1106
 
            curLevel--;
 
1302
    if (tsdPtr->curLevel >= level) {
 
1303
        while (tsdPtr->curLevel >= level) {
 
1304
            tsdPtr->levels[tsdPtr->curLevel].winPtr->optionLevel = -1;
 
1305
            tsdPtr->curLevel--;
1107
1306
        }
1108
 
        levelPtr = &levels[level];
 
1307
        levelPtr = &tsdPtr->levels[level];
1109
1308
        for (i = 0; i < NUM_STACKS; i++) {
1110
 
            arrayPtr = stacks[i];
 
1309
            arrayPtr = tsdPtr->stacks[i];
1111
1310
            arrayPtr->numUsed = levelPtr->bases[i];
1112
1311
            arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
1113
1312
        }
1114
1313
    }
1115
 
    curLevel = winPtr->optionLevel = level;
 
1314
    tsdPtr->curLevel = winPtr->optionLevel = level;
1116
1315
 
1117
1316
    /*
1118
1317
     * Step 3:  if the root database information isn't loaded or
1120
1319
     * database root (this only happens if winPtr is a main window).
1121
1320
     */
1122
1321
 
1123
 
    if ((curLevel == 1)
1124
 
            && ((cachedWindow == NULL)
1125
 
            || (cachedWindow->mainPtr != winPtr->mainPtr))) {
 
1322
    if ((tsdPtr->curLevel == 1)
 
1323
            && ((tsdPtr->cachedWindow == NULL)
 
1324
            || (tsdPtr->cachedWindow->mainPtr != winPtr->mainPtr))) {
1126
1325
        for (i = 0; i < NUM_STACKS; i++) {
1127
 
            arrayPtr = stacks[i];
 
1326
            arrayPtr = tsdPtr->stacks[i];
1128
1327
            arrayPtr->numUsed = 0;
1129
1328
            arrayPtr->nextToUse = arrayPtr->els;
1130
1329
        }
1138
1337
     * any more).
1139
1338
     */
1140
1339
 
1141
 
    if (curLevel >= numLevels) {
 
1340
    if (tsdPtr->curLevel >= tsdPtr->numLevels) {
1142
1341
        StackLevel *newLevels;
1143
1342
 
1144
1343
        newLevels = (StackLevel *) ckalloc((unsigned)
1145
 
                (numLevels*2*sizeof(StackLevel)));
1146
 
        memcpy((VOID *) newLevels, (VOID *) levels,
1147
 
                (numLevels*sizeof(StackLevel)));
1148
 
        ckfree((char *) levels);
1149
 
        numLevels *= 2;
1150
 
        levels = newLevels;
 
1344
                (tsdPtr->numLevels*2*sizeof(StackLevel)));
 
1345
        memcpy((VOID *) newLevels, (VOID *) tsdPtr->levels,
 
1346
                (tsdPtr->numLevels*sizeof(StackLevel)));
 
1347
        ckfree((char *) tsdPtr->levels);
 
1348
        tsdPtr->numLevels *= 2;
 
1349
        tsdPtr->levels = newLevels;
1151
1350
    }
1152
 
    levelPtr = &levels[curLevel];
 
1351
    levelPtr = &tsdPtr->levels[tsdPtr->curLevel];
1153
1352
    levelPtr->winPtr = winPtr;
1154
 
    arrayPtr = stacks[EXACT_LEAF_NAME];
1155
 
    arrayPtr->numUsed = 0;
1156
 
    arrayPtr->nextToUse = arrayPtr->els;
1157
 
    arrayPtr = stacks[EXACT_LEAF_CLASS];
1158
 
    arrayPtr->numUsed = 0;
1159
 
    arrayPtr->nextToUse = arrayPtr->els;
1160
 
    levelPtr->bases[EXACT_LEAF_NAME] = stacks[EXACT_LEAF_NAME]->numUsed;
1161
 
    levelPtr->bases[EXACT_LEAF_CLASS] = stacks[EXACT_LEAF_CLASS]->numUsed;
1162
 
    levelPtr->bases[EXACT_NODE_NAME] = stacks[EXACT_NODE_NAME]->numUsed;
1163
 
    levelPtr->bases[EXACT_NODE_CLASS] = stacks[EXACT_NODE_CLASS]->numUsed;
1164
 
    levelPtr->bases[WILDCARD_LEAF_NAME] = stacks[WILDCARD_LEAF_NAME]->numUsed;
1165
 
    levelPtr->bases[WILDCARD_LEAF_CLASS] = stacks[WILDCARD_LEAF_CLASS]->numUsed;
1166
 
    levelPtr->bases[WILDCARD_NODE_NAME] = stacks[WILDCARD_NODE_NAME]->numUsed;
1167
 
    levelPtr->bases[WILDCARD_NODE_CLASS] = stacks[WILDCARD_NODE_CLASS]->numUsed;
1168
 
 
1169
 
 
 
1353
    arrayPtr = tsdPtr->stacks[EXACT_LEAF_NAME];
 
1354
    arrayPtr->numUsed = 0;
 
1355
    arrayPtr->nextToUse = arrayPtr->els;
 
1356
    arrayPtr = tsdPtr->stacks[EXACT_LEAF_CLASS];
 
1357
    arrayPtr->numUsed = 0;
 
1358
    arrayPtr->nextToUse = arrayPtr->els;
 
1359
    for (i = 0; i < NUM_STACKS; i++) {
 
1360
        levelPtr->bases[i] = tsdPtr->stacks[i]->numUsed;
 
1361
    }
1170
1362
    /*
1171
1363
     * Step 5: scan the current stack level looking for matches to this
1172
1364
     * window's name or class;  where found, add new information to the
1184
1376
        } else {
1185
1377
            id = winPtr->nameUid;
1186
1378
        }
1187
 
        elPtr = stacks[i]->els;
 
1379
        elPtr = tsdPtr->stacks[i]->els;
1188
1380
        count = levelPtr->bases[i];
1189
1381
 
1190
1382
        /*
1203
1395
            ExtendStacks(elPtr->child.arrayPtr, leaf);
1204
1396
        }
1205
1397
    }
1206
 
    cachedWindow = winPtr;
 
1398
    tsdPtr->cachedWindow = winPtr;
1207
1399
}
1208
 
 
 
1400
 
1209
1401
/*
1210
1402
 *--------------------------------------------------------------
1211
1403
 *
1232
1424
{
1233
1425
    register int count;
1234
1426
    register Element *elPtr;
 
1427
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
1428
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1235
1429
 
1236
1430
    for (elPtr = arrayPtr->els, count = arrayPtr->numUsed;
1237
1431
            count > 0; elPtr++, count--) {
1238
1432
        if (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) {
1239
1433
            continue;
1240
1434
        }
1241
 
        stacks[elPtr->flags] = ExtendArray(stacks[elPtr->flags], elPtr);
1242
 
    }
1243
 
}
1244
 
 
 
1435
        tsdPtr->stacks[elPtr->flags] = ExtendArray(
 
1436
                tsdPtr->stacks[elPtr->flags], elPtr);
 
1437
    }
 
1438
}
 
1439
 
 
1440
/*
 
1441
 *--------------------------------------------------------------
 
1442
 *
 
1443
 * OptionThreadExitProc --
 
1444
 *
 
1445
 *      Free data structures for option handling.
 
1446
 *
 
1447
 * Results:
 
1448
 *      None.
 
1449
 *
 
1450
 * Side effects:
 
1451
 *      Option-related data structures get freed.
 
1452
 *
 
1453
 *--------------------------------------------------------------
 
1454
 */
 
1455
 
 
1456
static void
 
1457
OptionThreadExitProc(clientData)
 
1458
    ClientData clientData;      /* not used */
 
1459
{
 
1460
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
1461
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
 
1462
 
 
1463
    if (tsdPtr->initialized) {
 
1464
        int i;
 
1465
        for (i = 0; i < NUM_STACKS; i++) {
 
1466
            ckfree((char *) tsdPtr->stacks[i]);
 
1467
        }
 
1468
        ckfree((char *) tsdPtr->levels);
 
1469
        tsdPtr->initialized = 0;
 
1470
    }
 
1471
}
 
1472
 
1245
1473
/*
1246
1474
 *--------------------------------------------------------------
1247
1475
 *
1266
1494
{
1267
1495
    int i;
1268
1496
    Tcl_Interp *interp;
 
1497
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
 
1498
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
 
1499
    Element *defaultMatchPtr = &tsdPtr->defaultMatch;
1269
1500
 
1270
1501
    /*
1271
1502
     * First, once-only initialization.
1272
1503
     */
1273
1504
 
1274
 
    if (numLevels == 0) {
 
1505
    if (tsdPtr->initialized == 0) {
 
1506
        tsdPtr->initialized = 1;
 
1507
        tsdPtr->cachedWindow = NULL;
 
1508
        tsdPtr->numLevels = 5;
 
1509
        tsdPtr->curLevel = -1;
 
1510
        tsdPtr->serial = 0;
1275
1511
 
1276
 
        numLevels = 5;
1277
 
        levels = (StackLevel *) ckalloc((unsigned) (5*sizeof(StackLevel)));
 
1512
        tsdPtr->levels = (StackLevel *) ckalloc((unsigned)
 
1513
                (5*sizeof(StackLevel)));
1278
1514
        for (i = 0; i < NUM_STACKS; i++) {
1279
 
            stacks[i] = NewArray(10);
1280
 
            levels[0].bases[i] = 0;
 
1515
            tsdPtr->stacks[i] = NewArray(10);
 
1516
            tsdPtr->levels[0].bases[i] = 0;
1281
1517
        }
1282
 
    
1283
 
        defaultMatch.nameUid = NULL;
1284
 
        defaultMatch.child.valueUid = NULL;
1285
 
        defaultMatch.priority = -1;
1286
 
        defaultMatch.flags = 0;
 
1518
 
 
1519
        defaultMatchPtr->nameUid = NULL;
 
1520
        defaultMatchPtr->child.valueUid = NULL;
 
1521
        defaultMatchPtr->priority = -1;
 
1522
        defaultMatchPtr->flags = 0;
 
1523
        Tcl_CreateThreadExitHandler(OptionThreadExitProc, NULL);
1287
1524
    }
1288
1525
 
1289
1526
    /*
1296
1533
    (void) GetDefaultOptions(interp, mainPtr->winPtr);
1297
1534
    Tcl_DeleteInterp(interp);
1298
1535
}
1299
 
 
 
1536
 
1300
1537
/*
1301
1538
 *--------------------------------------------------------------
1302
1539
 *
1332
1569
    }
1333
1570
    ckfree((char *) arrayPtr);
1334
1571
}
1335
 
 
 
1572
 
1336
1573
/*
1337
1574
 *--------------------------------------------------------------
1338
1575
 *