/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkconfig.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkconfig.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkconfig.c revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkconfig.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkConfig.c --   * tkConfig.c --
5   *   *
6   *      This file contains procedures that manage configuration options   *      This file contains procedures that manage configuration options
7   *      for widgets and other things.   *      for widgets and other things.
8   *   *
9   * Copyright (c) 1997-1998 Sun Microsystems, Inc.   * Copyright (c) 1997-1998 Sun Microsystems, Inc.
10   *   *
11   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
12   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13   *   *
14   * RCS: @(#) $Id: tkconfig.c,v 1.1.1.1 2001/06/13 04:58:49 dtashley Exp $   * RCS: @(#) $Id: tkconfig.c,v 1.1.1.1 2001/06/13 04:58:49 dtashley Exp $
15   */   */
16    
17  /*  /*
18   * Temporary flag for working on new config package.   * Temporary flag for working on new config package.
19   */   */
20    
21  #if 0  #if 0
22    
23  /*  /*
24   * used only for removing the old config code   * used only for removing the old config code
25   */   */
26    
27  #define __NO_OLD_CONFIG  #define __NO_OLD_CONFIG
28  #endif  #endif
29    
30  #include "tk.h"  #include "tk.h"
31  #include "tkInt.h"  #include "tkInt.h"
32  #include "tkPort.h"  #include "tkPort.h"
33  #include "tkFont.h"  #include "tkFont.h"
34    
35  /*  /*
36   * The following definition is an AssocData key used to keep track of   * The following definition is an AssocData key used to keep track of
37   * all of the option tables that have been created for an interpreter.   * all of the option tables that have been created for an interpreter.
38   */   */
39    
40  #define OPTION_HASH_KEY "TkOptionTable"  #define OPTION_HASH_KEY "TkOptionTable"
41    
42  /*  /*
43   * The following two structures are used along with Tk_OptionSpec   * The following two structures are used along with Tk_OptionSpec
44   * structures to manage configuration options.  Tk_OptionSpec is   * structures to manage configuration options.  Tk_OptionSpec is
45   * static templates that are compiled into the code of a widget   * static templates that are compiled into the code of a widget
46   * or other object manager.  However, to look up options efficiently   * or other object manager.  However, to look up options efficiently
47   * we need to supplement the static information with additional   * we need to supplement the static information with additional
48   * dynamic information, and this dynamic information may be different   * dynamic information, and this dynamic information may be different
49   * for each application.  Thus we create structures of the following   * for each application.  Thus we create structures of the following
50   * two types to hold all of the dynamic information; this is done   * two types to hold all of the dynamic information; this is done
51   * by Tk_CreateOptionTable.   * by Tk_CreateOptionTable.
52   *   *
53   * One of the following structures corresponds to each Tk_OptionSpec.   * One of the following structures corresponds to each Tk_OptionSpec.
54   * These structures exist as arrays inside TkOptionTable structures.   * These structures exist as arrays inside TkOptionTable structures.
55   */   */
56    
57  typedef struct TkOption {  typedef struct TkOption {
58      CONST Tk_OptionSpec *specPtr;       /* The original spec from the template      CONST Tk_OptionSpec *specPtr;       /* The original spec from the template
59                                           * passed to Tk_CreateOptionTable.*/                                           * passed to Tk_CreateOptionTable.*/
60      Tk_Uid dbNameUID;                   /* The Uid form of the option database      Tk_Uid dbNameUID;                   /* The Uid form of the option database
61                                           * name. */                                           * name. */
62      Tk_Uid dbClassUID;                  /* The Uid form of the option database      Tk_Uid dbClassUID;                  /* The Uid form of the option database
63                                           * class name. */                                           * class name. */
64      Tcl_Obj *defaultPtr;                /* Default value for this option. */      Tcl_Obj *defaultPtr;                /* Default value for this option. */
65      union {      union {
66          Tcl_Obj *monoColorPtr;          /* For color and border options, this          Tcl_Obj *monoColorPtr;          /* For color and border options, this
67                                           * is an alternate default value to                                           * is an alternate default value to
68                                           * use on monochrome displays. */                                           * use on monochrome displays. */
69          struct TkOption *synonymPtr;    /* For synonym options, this points to          struct TkOption *synonymPtr;    /* For synonym options, this points to
70                                           * the master entry. */                                           * the master entry. */
71      } extra;      } extra;
72      int flags;                          /* Miscellaneous flag values; see      int flags;                          /* Miscellaneous flag values; see
73                                           * below for definitions. */                                           * below for definitions. */
74  } Option;  } Option;
75    
76  /*  /*
77   * Flag bits defined for Option structures:   * Flag bits defined for Option structures:
78   *   *
79   * OPTION_NEEDS_FREEING -       1 means that FreeResources must be   * OPTION_NEEDS_FREEING -       1 means that FreeResources must be
80   *                              invoke to free resources associated with   *                              invoke to free resources associated with
81   *                              the option when it is no longer needed.   *                              the option when it is no longer needed.
82   */   */
83    
84  #define OPTION_NEEDS_FREEING            1  #define OPTION_NEEDS_FREEING            1
85    
86  /*  /*
87   * One of the following exists for each Tk_OptionSpec array that has   * One of the following exists for each Tk_OptionSpec array that has
88   * been passed to Tk_CreateOptionTable.   * been passed to Tk_CreateOptionTable.
89   */   */
90    
91  typedef struct OptionTable {  typedef struct OptionTable {
92      int refCount;                       /* Counts the number of uses of this      int refCount;                       /* Counts the number of uses of this
93                                           * table (the number of times                                           * table (the number of times
94                                           * Tk_CreateOptionTable has returned                                           * Tk_CreateOptionTable has returned
95                                           * it).  This can be greater than 1 if                                           * it).  This can be greater than 1 if
96                                           * it is shared along several option                                           * it is shared along several option
97                                           * table  chains, or if the same table                                           * table  chains, or if the same table
98                                           * is used for multiple purposes. */                                           * is used for multiple purposes. */
99      Tcl_HashEntry *hashEntryPtr;        /* Hash table entry that refers to this      Tcl_HashEntry *hashEntryPtr;        /* Hash table entry that refers to this
100                                           * table; used to delete the entry. */                                           * table; used to delete the entry. */
101      struct OptionTable *nextPtr;        /* If templatePtr was part of a chain      struct OptionTable *nextPtr;        /* If templatePtr was part of a chain
102                                           * of templates, this points to the                                           * of templates, this points to the
103                                           * table corresponding to the next                                           * table corresponding to the next
104                                           * template in the chain. */                                           * template in the chain. */
105      int numOptions;                     /* The number of items in the options      int numOptions;                     /* The number of items in the options
106                                           * array below. */                                           * array below. */
107      Option options[1];                  /* Information about the individual      Option options[1];                  /* Information about the individual
108                                           * options in the table.  This must be                                           * options in the table.  This must be
109                                           * the last field in the structure:                                           * the last field in the structure:
110                                           * the actual size of the array will                                           * the actual size of the array will
111                                           * be numOptions, not 1. */                                           * be numOptions, not 1. */
112  } OptionTable;  } OptionTable;
113    
114  /*  /*
115   * Forward declarations for procedures defined later in this file:   * Forward declarations for procedures defined later in this file:
116   */   */
117    
118  static int              DoObjConfig _ANSI_ARGS_((Tcl_Interp *interp,  static int              DoObjConfig _ANSI_ARGS_((Tcl_Interp *interp,
119                              char *recordPtr, Option *optionPtr,                              char *recordPtr, Option *optionPtr,
120                              Tcl_Obj *valuePtr, Tk_Window tkwin,                              Tcl_Obj *valuePtr, Tk_Window tkwin,
121                              Tk_SavedOption *savePtr));                              Tk_SavedOption *savePtr));
122  static void             DestroyOptionHashTable _ANSI_ARGS_((  static void             DestroyOptionHashTable _ANSI_ARGS_((
123                              ClientData clientData, Tcl_Interp *interp));                              ClientData clientData, Tcl_Interp *interp));
124  static void             FreeResources _ANSI_ARGS_((Option *optionPtr,  static void             FreeResources _ANSI_ARGS_((Option *optionPtr,
125                              Tcl_Obj *objPtr, char *internalPtr,                              Tcl_Obj *objPtr, char *internalPtr,
126                              Tk_Window tkwin));                              Tk_Window tkwin));
127  static Tcl_Obj *        GetConfigList _ANSI_ARGS_((char *recordPtr,  static Tcl_Obj *        GetConfigList _ANSI_ARGS_((char *recordPtr,
128                              Option *optionPtr, Tk_Window tkwin));                              Option *optionPtr, Tk_Window tkwin));
129  static Tcl_Obj *        GetObjectForOption _ANSI_ARGS_((char *recordPtr,  static Tcl_Obj *        GetObjectForOption _ANSI_ARGS_((char *recordPtr,
130                              Option *optionPtr, Tk_Window tkwin));                              Option *optionPtr, Tk_Window tkwin));
131  static Option *         GetOptionFromObj _ANSI_ARGS_((Tcl_Interp *interp,  static Option *         GetOptionFromObj _ANSI_ARGS_((Tcl_Interp *interp,
132                              Tcl_Obj *objPtr, OptionTable *tablePtr));                              Tcl_Obj *objPtr, OptionTable *tablePtr));
133  static int              ObjectIsEmpty _ANSI_ARGS_((Tcl_Obj *objPtr));  static int              ObjectIsEmpty _ANSI_ARGS_((Tcl_Obj *objPtr));
134  static int              SetOptionFromAny _ANSI_ARGS_((Tcl_Interp *interp,  static int              SetOptionFromAny _ANSI_ARGS_((Tcl_Interp *interp,
135                              Tcl_Obj *objPtr));                              Tcl_Obj *objPtr));
136    
137  /*  /*
138   * The structure below defines an object type that is used to cache the   * The structure below defines an object type that is used to cache the
139   * result of looking up an option name.  If an object has this type, then   * result of looking up an option name.  If an object has this type, then
140   * its internalPtr1 field points to the OptionTable in which it was looked up,   * its internalPtr1 field points to the OptionTable in which it was looked up,
141   * and the internalPtr2 field points to the entry that matched.   * and the internalPtr2 field points to the entry that matched.
142   */   */
143    
144  Tcl_ObjType optionType = {  Tcl_ObjType optionType = {
145      "option",                           /* name */      "option",                           /* name */
146      (Tcl_FreeInternalRepProc *) NULL,   /* freeIntRepProc */      (Tcl_FreeInternalRepProc *) NULL,   /* freeIntRepProc */
147      (Tcl_DupInternalRepProc *) NULL,    /* dupIntRepProc */      (Tcl_DupInternalRepProc *) NULL,    /* dupIntRepProc */
148      (Tcl_UpdateStringProc *) NULL,      /* updateStringProc */      (Tcl_UpdateStringProc *) NULL,      /* updateStringProc */
149      SetOptionFromAny                    /* setFromAnyProc */      SetOptionFromAny                    /* setFromAnyProc */
150  };  };
151    
152  /*  /*
153   *--------------------------------------------------------------   *--------------------------------------------------------------
154   *   *
155   * Tk_CreateOptionTable --   * Tk_CreateOptionTable --
156   *   *
157   *      Given a template for configuration options, this procedure   *      Given a template for configuration options, this procedure
158   *      creates a table that may be used to look up options efficiently.   *      creates a table that may be used to look up options efficiently.
159   *   *
160   * Results:   * Results:
161   *      Returns a token to a structure that can be passed to procedures   *      Returns a token to a structure that can be passed to procedures
162   *      such as Tk_InitOptions, Tk_SetOptions, and Tk_FreeConfigOptions.   *      such as Tk_InitOptions, Tk_SetOptions, and Tk_FreeConfigOptions.
163   *   *
164   * Side effects:   * Side effects:
165   *      Storage is allocated.   *      Storage is allocated.
166   *   *
167   *--------------------------------------------------------------   *--------------------------------------------------------------
168   */   */
169    
170  Tk_OptionTable  Tk_OptionTable
171  Tk_CreateOptionTable(interp, templatePtr)  Tk_CreateOptionTable(interp, templatePtr)
172      Tcl_Interp *interp;                 /* Interpreter associated with the      Tcl_Interp *interp;                 /* Interpreter associated with the
173                                           * application in which this table                                           * application in which this table
174                                           * will be used. */                                           * will be used. */
175      CONST Tk_OptionSpec *templatePtr;   /* Static information about the      CONST Tk_OptionSpec *templatePtr;   /* Static information about the
176                                           * configuration options. */                                           * configuration options. */
177  {  {
178      Tcl_HashTable *hashTablePtr;      Tcl_HashTable *hashTablePtr;
179      Tcl_HashEntry *hashEntryPtr;      Tcl_HashEntry *hashEntryPtr;
180      int newEntry;      int newEntry;
181      OptionTable *tablePtr;      OptionTable *tablePtr;
182      CONST Tk_OptionSpec *specPtr, *specPtr2;      CONST Tk_OptionSpec *specPtr, *specPtr2;
183      Option *optionPtr;      Option *optionPtr;
184      int numOptions, i;      int numOptions, i;
185    
186      /*      /*
187       * We use an AssocData value in the interpreter to keep a hash       * We use an AssocData value in the interpreter to keep a hash
188       * table of all the option tables we've created for this application.       * table of all the option tables we've created for this application.
189       * This is used for two purposes.  First, it allows us to share the       * This is used for two purposes.  First, it allows us to share the
190       * tables (e.g. in several chains) and second, we use the deletion       * tables (e.g. in several chains) and second, we use the deletion
191       * callback for the AssocData to delete all the option tables when       * callback for the AssocData to delete all the option tables when
192       * the interpreter is deleted.  The code below finds the hash table       * the interpreter is deleted.  The code below finds the hash table
193       * or creates a new one if it doesn't already exist.       * or creates a new one if it doesn't already exist.
194       */       */
195    
196      hashTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, OPTION_HASH_KEY,      hashTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, OPTION_HASH_KEY,
197              NULL);              NULL);
198      if (hashTablePtr == NULL) {      if (hashTablePtr == NULL) {
199          hashTablePtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));          hashTablePtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
200          Tcl_InitHashTable(hashTablePtr, TCL_ONE_WORD_KEYS);          Tcl_InitHashTable(hashTablePtr, TCL_ONE_WORD_KEYS);
201          Tcl_SetAssocData(interp, OPTION_HASH_KEY, DestroyOptionHashTable,          Tcl_SetAssocData(interp, OPTION_HASH_KEY, DestroyOptionHashTable,
202                  (ClientData) hashTablePtr);                  (ClientData) hashTablePtr);
203      }      }
204    
205      /*      /*
206       * See if a table has already been created for this template.  If       * See if a table has already been created for this template.  If
207       * so, just reuse the existing table.       * so, just reuse the existing table.
208       */       */
209    
210      hashEntryPtr = Tcl_CreateHashEntry(hashTablePtr, (char *) templatePtr,      hashEntryPtr = Tcl_CreateHashEntry(hashTablePtr, (char *) templatePtr,
211              &newEntry);              &newEntry);
212      if (!newEntry) {      if (!newEntry) {
213          tablePtr = (OptionTable *) Tcl_GetHashValue(hashEntryPtr);          tablePtr = (OptionTable *) Tcl_GetHashValue(hashEntryPtr);
214          tablePtr->refCount++;          tablePtr->refCount++;
215          return (Tk_OptionTable) tablePtr;          return (Tk_OptionTable) tablePtr;
216      }      }
217    
218      /*      /*
219       * Count the number of options in the template, then create the       * Count the number of options in the template, then create the
220       * table structure.       * table structure.
221       */       */
222    
223      numOptions = 0;      numOptions = 0;
224      for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) {      for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) {
225          numOptions++;          numOptions++;
226      }      }
227      tablePtr = (OptionTable *) (ckalloc(sizeof(OptionTable)      tablePtr = (OptionTable *) (ckalloc(sizeof(OptionTable)
228              + ((numOptions - 1)  * sizeof(Option))));              + ((numOptions - 1)  * sizeof(Option))));
229      tablePtr->refCount = 1;      tablePtr->refCount = 1;
230      tablePtr->hashEntryPtr = hashEntryPtr;      tablePtr->hashEntryPtr = hashEntryPtr;
231      tablePtr->nextPtr = NULL;      tablePtr->nextPtr = NULL;
232      tablePtr->numOptions = numOptions;      tablePtr->numOptions = numOptions;
233    
234      /*      /*
235       * Initialize all of the Option structures in the table.       * Initialize all of the Option structures in the table.
236       */       */
237    
238      for (specPtr = templatePtr, optionPtr = tablePtr->options;      for (specPtr = templatePtr, optionPtr = tablePtr->options;
239              specPtr->type != TK_OPTION_END; specPtr++, optionPtr++) {              specPtr->type != TK_OPTION_END; specPtr++, optionPtr++) {
240          optionPtr->specPtr = specPtr;          optionPtr->specPtr = specPtr;
241          optionPtr->dbNameUID = NULL;          optionPtr->dbNameUID = NULL;
242          optionPtr->dbClassUID = NULL;          optionPtr->dbClassUID = NULL;
243          optionPtr->defaultPtr = NULL;          optionPtr->defaultPtr = NULL;
244          optionPtr->extra.monoColorPtr = NULL;          optionPtr->extra.monoColorPtr = NULL;
245          optionPtr->flags = 0;          optionPtr->flags = 0;
246    
247          if (specPtr->type == TK_OPTION_SYNONYM) {          if (specPtr->type == TK_OPTION_SYNONYM) {
248              /*              /*
249               * This is a synonym option; find the master option that it               * This is a synonym option; find the master option that it
250               * refers to and create a pointer from the synonym to the               * refers to and create a pointer from the synonym to the
251               * master.               * master.
252               */               */
253    
254              for (specPtr2 = templatePtr, i = 0; ; specPtr2++, i++) {              for (specPtr2 = templatePtr, i = 0; ; specPtr2++, i++) {
255                  if (specPtr2->type == TK_OPTION_END) {                  if (specPtr2->type == TK_OPTION_END) {
256                      panic("Tk_CreateOptionTable couldn't find synonym");                      panic("Tk_CreateOptionTable couldn't find synonym");
257                  }                  }
258                  if (strcmp(specPtr2->optionName,                  if (strcmp(specPtr2->optionName,
259                          (char *) specPtr->clientData) == 0) {                          (char *) specPtr->clientData) == 0) {
260                      optionPtr->extra.synonymPtr = tablePtr->options + i;                      optionPtr->extra.synonymPtr = tablePtr->options + i;
261                      break;                      break;
262                  }                  }
263              }              }
264          } else {          } else {
265              if (specPtr->dbName != NULL) {              if (specPtr->dbName != NULL) {
266                  optionPtr->dbNameUID = Tk_GetUid(specPtr->dbName);                  optionPtr->dbNameUID = Tk_GetUid(specPtr->dbName);
267              }              }
268              if (specPtr->dbClass != NULL) {              if (specPtr->dbClass != NULL) {
269                  optionPtr->dbClassUID =                  optionPtr->dbClassUID =
270                          Tk_GetUid(specPtr->dbClass);                          Tk_GetUid(specPtr->dbClass);
271              }              }
272              if (specPtr->defValue != NULL) {              if (specPtr->defValue != NULL) {
273                  optionPtr->defaultPtr =                  optionPtr->defaultPtr =
274                          Tcl_NewStringObj(specPtr->defValue, -1);                          Tcl_NewStringObj(specPtr->defValue, -1);
275                  Tcl_IncrRefCount(optionPtr->defaultPtr);                  Tcl_IncrRefCount(optionPtr->defaultPtr);
276              }              }
277              if (((specPtr->type == TK_OPTION_COLOR)              if (((specPtr->type == TK_OPTION_COLOR)
278                      || (specPtr->type == TK_OPTION_BORDER))                      || (specPtr->type == TK_OPTION_BORDER))
279                      && (specPtr->clientData != NULL)) {                      && (specPtr->clientData != NULL)) {
280                  optionPtr->extra.monoColorPtr =                  optionPtr->extra.monoColorPtr =
281                          Tcl_NewStringObj((char *) specPtr->clientData, -1);                          Tcl_NewStringObj((char *) specPtr->clientData, -1);
282                  Tcl_IncrRefCount(optionPtr->extra.monoColorPtr);                  Tcl_IncrRefCount(optionPtr->extra.monoColorPtr);
283              }              }
284          }          }
285          if (((specPtr->type == TK_OPTION_STRING)          if (((specPtr->type == TK_OPTION_STRING)
286                  && (specPtr->internalOffset >= 0))                  && (specPtr->internalOffset >= 0))
287                  || (specPtr->type == TK_OPTION_COLOR)                  || (specPtr->type == TK_OPTION_COLOR)
288                  || (specPtr->type == TK_OPTION_FONT)                  || (specPtr->type == TK_OPTION_FONT)
289                  || (specPtr->type == TK_OPTION_BITMAP)                  || (specPtr->type == TK_OPTION_BITMAP)
290                  || (specPtr->type == TK_OPTION_BORDER)                  || (specPtr->type == TK_OPTION_BORDER)
291                  || (specPtr->type == TK_OPTION_CURSOR)) {                  || (specPtr->type == TK_OPTION_CURSOR)) {
292              optionPtr->flags |= OPTION_NEEDS_FREEING;              optionPtr->flags |= OPTION_NEEDS_FREEING;
293          }          }
294      }      }
295      tablePtr->hashEntryPtr = hashEntryPtr;      tablePtr->hashEntryPtr = hashEntryPtr;
296      Tcl_SetHashValue(hashEntryPtr, tablePtr);      Tcl_SetHashValue(hashEntryPtr, tablePtr);
297    
298      /*      /*
299       * Finally, check to see if this template chains to another template       * Finally, check to see if this template chains to another template
300       * with additional options.  If so, call ourselves recursively to       * with additional options.  If so, call ourselves recursively to
301       * create the next table(s).       * create the next table(s).
302       */       */
303    
304      if (specPtr->clientData != NULL) {      if (specPtr->clientData != NULL) {
305          tablePtr->nextPtr = (OptionTable *) Tk_CreateOptionTable(interp,          tablePtr->nextPtr = (OptionTable *) Tk_CreateOptionTable(interp,
306                  (Tk_OptionSpec *) specPtr->clientData);                  (Tk_OptionSpec *) specPtr->clientData);
307      }      }
308    
309      return (Tk_OptionTable) tablePtr;      return (Tk_OptionTable) tablePtr;
310  }  }
311    
312  /*  /*
313   *----------------------------------------------------------------------   *----------------------------------------------------------------------
314   *   *
315   * Tk_DeleteOptionTable --   * Tk_DeleteOptionTable --
316   *   *
317   *      Called to release resources used by an option table when   *      Called to release resources used by an option table when
318   *      the table is no longer needed.   *      the table is no longer needed.
319   *   *
320   * Results:   * Results:
321   *      None.   *      None.
322   *   *
323   * Side effects:   * Side effects:
324   *      The option table and associated resources (such as additional   *      The option table and associated resources (such as additional
325   *      option tables chained off it) are destroyed.   *      option tables chained off it) are destroyed.
326   *   *
327   *----------------------------------------------------------------------   *----------------------------------------------------------------------
328   */   */
329    
330  void  void
331  Tk_DeleteOptionTable(optionTable)  Tk_DeleteOptionTable(optionTable)
332      Tk_OptionTable optionTable;         /* The option table to delete. */      Tk_OptionTable optionTable;         /* The option table to delete. */
333  {  {
334      OptionTable *tablePtr = (OptionTable *) optionTable;      OptionTable *tablePtr = (OptionTable *) optionTable;
335      Option *optionPtr;      Option *optionPtr;
336      int count;      int count;
337    
338      tablePtr->refCount--;      tablePtr->refCount--;
339      if (tablePtr->refCount > 0) {      if (tablePtr->refCount > 0) {
340          return;          return;
341      }      }
342    
343      if (tablePtr->nextPtr != NULL) {      if (tablePtr->nextPtr != NULL) {
344          Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr);          Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr);
345      }      }
346    
347      for (count = tablePtr->numOptions - 1, optionPtr = tablePtr->options;      for (count = tablePtr->numOptions - 1, optionPtr = tablePtr->options;
348              count > 0;  count--, optionPtr++) {              count > 0;  count--, optionPtr++) {
349          if (optionPtr->defaultPtr != NULL) {          if (optionPtr->defaultPtr != NULL) {
350              Tcl_DecrRefCount(optionPtr->defaultPtr);              Tcl_DecrRefCount(optionPtr->defaultPtr);
351          }          }
352          if (((optionPtr->specPtr->type == TK_OPTION_COLOR)          if (((optionPtr->specPtr->type == TK_OPTION_COLOR)
353                  || (optionPtr->specPtr->type == TK_OPTION_BORDER))                  || (optionPtr->specPtr->type == TK_OPTION_BORDER))
354                  && (optionPtr->extra.monoColorPtr != NULL)) {                  && (optionPtr->extra.monoColorPtr != NULL)) {
355              Tcl_DecrRefCount(optionPtr->extra.monoColorPtr);              Tcl_DecrRefCount(optionPtr->extra.monoColorPtr);
356          }          }
357      }      }
358      Tcl_DeleteHashEntry(tablePtr->hashEntryPtr);      Tcl_DeleteHashEntry(tablePtr->hashEntryPtr);
359      ckfree((char *) tablePtr);      ckfree((char *) tablePtr);
360  }  }
361    
362  /*  /*
363   *----------------------------------------------------------------------   *----------------------------------------------------------------------
364   *   *
365   * DestroyOptionHashTable --   * DestroyOptionHashTable --
366   *   *
367   *      This procedure is the deletion callback associated with the   *      This procedure is the deletion callback associated with the
368   *      AssocData entry created by Tk_CreateOptionTable.  It is   *      AssocData entry created by Tk_CreateOptionTable.  It is
369   *      invoked when an interpreter is deleted, and deletes all of   *      invoked when an interpreter is deleted, and deletes all of
370   *      the option tables associated with that interpreter.   *      the option tables associated with that interpreter.
371   *   *
372   * Results:   * Results:
373   *      None.   *      None.
374   *   *
375   * Side effects:   * Side effects:
376   *      The option hash table is destroyed along with all of the   *      The option hash table is destroyed along with all of the
377   *      OptionTable structures that it refers to.   *      OptionTable structures that it refers to.
378   *   *
379   *----------------------------------------------------------------------   *----------------------------------------------------------------------
380   */   */
381    
382  static void  static void
383  DestroyOptionHashTable(clientData, interp)  DestroyOptionHashTable(clientData, interp)
384      ClientData clientData;      /* The hash table we are destroying */      ClientData clientData;      /* The hash table we are destroying */
385      Tcl_Interp *interp;         /* The interpreter we are destroying */      Tcl_Interp *interp;         /* The interpreter we are destroying */
386  {  {
387      Tcl_HashTable *hashTablePtr = (Tcl_HashTable *) clientData;      Tcl_HashTable *hashTablePtr = (Tcl_HashTable *) clientData;
388      Tcl_HashSearch search;      Tcl_HashSearch search;
389      Tcl_HashEntry *hashEntryPtr;      Tcl_HashEntry *hashEntryPtr;
390      OptionTable *tablePtr;      OptionTable *tablePtr;
391    
392      for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search);      for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search);
393              hashEntryPtr != NULL;              hashEntryPtr != NULL;
394              hashEntryPtr = Tcl_NextHashEntry(&search)) {              hashEntryPtr = Tcl_NextHashEntry(&search)) {
395          tablePtr = (OptionTable *) Tcl_GetHashValue(hashEntryPtr);          tablePtr = (OptionTable *) Tcl_GetHashValue(hashEntryPtr);
396    
397          /*          /*
398           * The following statements do two tricky things:           * The following statements do two tricky things:
399           * 1. They ensure that the option table is deleted, even if           * 1. They ensure that the option table is deleted, even if
400           *    there are outstanding references to it.           *    there are outstanding references to it.
401           * 2. They ensure that Tk_DeleteOptionTable doesn't delete           * 2. They ensure that Tk_DeleteOptionTable doesn't delete
402           *    other tables chained from this one; we'll do it when           *    other tables chained from this one; we'll do it when
403           *    we come across the hash table entry for the chained           *    we come across the hash table entry for the chained
404           *    table (in fact, the chained table may already have           *    table (in fact, the chained table may already have
405           *    been deleted).           *    been deleted).
406           */           */
407    
408          tablePtr->refCount = 1;          tablePtr->refCount = 1;
409          tablePtr->nextPtr = NULL;          tablePtr->nextPtr = NULL;
410          Tk_DeleteOptionTable((Tk_OptionTable) tablePtr);          Tk_DeleteOptionTable((Tk_OptionTable) tablePtr);
411      }      }
412      Tcl_DeleteHashTable(hashTablePtr);      Tcl_DeleteHashTable(hashTablePtr);
413      ckfree((char *) hashTablePtr);      ckfree((char *) hashTablePtr);
414  }  }
415    
416  /*  /*
417   *--------------------------------------------------------------   *--------------------------------------------------------------
418   *   *
419   * Tk_InitOptions --   * Tk_InitOptions --
420   *   *
421   *      This procedure is invoked when an object such as a widget   *      This procedure is invoked when an object such as a widget
422   *      is created.  It supplies an initial value for each configuration   *      is created.  It supplies an initial value for each configuration
423   *      option (the value may come from the option database, a system   *      option (the value may come from the option database, a system
424   *      default, or the default in the option table).   *      default, or the default in the option table).
425   *   *
426   * Results:   * Results:
427   *      The return value is TCL_OK if the procedure completed   *      The return value is TCL_OK if the procedure completed
428   *      successfully, and TCL_ERROR if one of the initial values was   *      successfully, and TCL_ERROR if one of the initial values was
429   *      bogus.  If an error occurs and interp isn't NULL, then an   *      bogus.  If an error occurs and interp isn't NULL, then an
430   *      error message will be left in its result.   *      error message will be left in its result.
431   *   *
432   * Side effects:   * Side effects:
433   *      Fields of recordPtr are filled in with initial values.   *      Fields of recordPtr are filled in with initial values.
434   *   *
435   *--------------------------------------------------------------   *--------------------------------------------------------------
436   */   */
437    
438  int  int
439  Tk_InitOptions(interp, recordPtr, optionTable, tkwin)  Tk_InitOptions(interp, recordPtr, optionTable, tkwin)
440      Tcl_Interp *interp;         /* Interpreter for error reporting.    NULL      Tcl_Interp *interp;         /* Interpreter for error reporting.    NULL
441                                   * means don't leave an error message. */                                   * means don't leave an error message. */
442      char *recordPtr;            /* Pointer to the record to configure.      char *recordPtr;            /* Pointer to the record to configure.
443                                   * Note: the caller should have properly                                   * Note: the caller should have properly
444                                   * initialized the record with NULL                                   * initialized the record with NULL
445                                   * pointers for each option value. */                                   * pointers for each option value. */
446      Tk_OptionTable optionTable; /* The token which matches the config      Tk_OptionTable optionTable; /* The token which matches the config
447                                   * specs for the widget in question. */                                   * specs for the widget in question. */
448      Tk_Window tkwin;            /* Certain options types (such as      Tk_Window tkwin;            /* Certain options types (such as
449                                   * TK_OPTION_COLOR) need fields out                                   * TK_OPTION_COLOR) need fields out
450                                   * of the window they are used in to                                   * of the window they are used in to
451                                   * be able to calculate their values.                                   * be able to calculate their values.
452                                   * Not needed unless one of these                                   * Not needed unless one of these
453                                   * options is in the configSpecs record. */                                   * options is in the configSpecs record. */
454  {  {
455      OptionTable *tablePtr = (OptionTable *) optionTable;      OptionTable *tablePtr = (OptionTable *) optionTable;
456      Option *optionPtr;      Option *optionPtr;
457      int count;      int count;
458      char *value;      char *value;
459      Tcl_Obj *valuePtr;      Tcl_Obj *valuePtr;
460      enum {      enum {
461          OPTION_DATABASE, SYSTEM_DEFAULT, TABLE_DEFAULT          OPTION_DATABASE, SYSTEM_DEFAULT, TABLE_DEFAULT
462      } source;      } source;
463    
464      /*      /*
465       * If this table chains to other tables, handle their initialization       * If this table chains to other tables, handle their initialization
466       * first.  That way, if both tables refer to the same field of the       * first.  That way, if both tables refer to the same field of the
467       * record, the value in the first table will win.       * record, the value in the first table will win.
468       */       */
469    
470      if (tablePtr->nextPtr != NULL) {      if (tablePtr->nextPtr != NULL) {
471          if (Tk_InitOptions(interp, recordPtr,          if (Tk_InitOptions(interp, recordPtr,
472                  (Tk_OptionTable) tablePtr->nextPtr, tkwin) != TCL_OK) {                  (Tk_OptionTable) tablePtr->nextPtr, tkwin) != TCL_OK) {
473              return TCL_ERROR;              return TCL_ERROR;
474          }          }
475      }      }
476    
477      /*      /*
478       * Iterate over all of the options in the table, initializing each in       * Iterate over all of the options in the table, initializing each in
479       * turn.       * turn.
480       */       */
481    
482      for (optionPtr = tablePtr->options, count = tablePtr->numOptions;      for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
483              count > 0; optionPtr++, count--) {              count > 0; optionPtr++, count--) {
484    
485          /*          /*
486           * If we specify TK_OPTION_DONT_SET_DEFAULT, then the user has           * If we specify TK_OPTION_DONT_SET_DEFAULT, then the user has
487           * processed and set a default for this already.           * processed and set a default for this already.
488           */           */
489          if ((optionPtr->specPtr->type == TK_OPTION_SYNONYM) ||          if ((optionPtr->specPtr->type == TK_OPTION_SYNONYM) ||
490                  (optionPtr->specPtr->flags & TK_OPTION_DONT_SET_DEFAULT)) {                  (optionPtr->specPtr->flags & TK_OPTION_DONT_SET_DEFAULT)) {
491              continue;              continue;
492          }          }
493          source = TABLE_DEFAULT;          source = TABLE_DEFAULT;
494    
495          /*          /*
496           * We look in three places for the initial value, using the first           * We look in three places for the initial value, using the first
497           * non-NULL value that we find.  First, check the option database.           * non-NULL value that we find.  First, check the option database.
498           */           */
499    
500          valuePtr = NULL;          valuePtr = NULL;
501          if (optionPtr->dbNameUID != NULL) {          if (optionPtr->dbNameUID != NULL) {
502              value = Tk_GetOption(tkwin, optionPtr->dbNameUID,              value = Tk_GetOption(tkwin, optionPtr->dbNameUID,
503                      optionPtr->dbClassUID);                      optionPtr->dbClassUID);
504              if (value != NULL) {              if (value != NULL) {
505                  valuePtr = Tcl_NewStringObj(value, -1);                  valuePtr = Tcl_NewStringObj(value, -1);
506                  source = OPTION_DATABASE;                  source = OPTION_DATABASE;
507              }              }
508          }          }
509    
510          /*          /*
511           * Second, check for a system-specific default value.           * Second, check for a system-specific default value.
512           */           */
513          if ((valuePtr == NULL)          if ((valuePtr == NULL)
514                  && (optionPtr->dbNameUID != NULL)) {                  && (optionPtr->dbNameUID != NULL)) {
515              valuePtr = TkpGetSystemDefault(tkwin, optionPtr->dbNameUID,              valuePtr = TkpGetSystemDefault(tkwin, optionPtr->dbNameUID,
516                      optionPtr->dbClassUID);                      optionPtr->dbClassUID);
517              if (valuePtr != NULL) {              if (valuePtr != NULL) {
518                  source = SYSTEM_DEFAULT;                  source = SYSTEM_DEFAULT;
519              }              }
520          }          }
521    
522          /*          /*
523           * Third and last, use the default value supplied by the option           * Third and last, use the default value supplied by the option
524           * table.  In the case of color objects, we pick one of two           * table.  In the case of color objects, we pick one of two
525           * values depending on whether the screen is mono or color.           * values depending on whether the screen is mono or color.
526           */           */
527    
528          if (valuePtr == NULL) {          if (valuePtr == NULL) {
529              if ((tkwin != NULL)              if ((tkwin != NULL)
530                      && ((optionPtr->specPtr->type == TK_OPTION_COLOR)                      && ((optionPtr->specPtr->type == TK_OPTION_COLOR)
531                      || (optionPtr->specPtr->type == TK_OPTION_BORDER))                      || (optionPtr->specPtr->type == TK_OPTION_BORDER))
532                      && (Tk_Depth(tkwin) <= 1)                      && (Tk_Depth(tkwin) <= 1)
533                      && (optionPtr->extra.monoColorPtr != NULL)) {                      && (optionPtr->extra.monoColorPtr != NULL)) {
534                  valuePtr = optionPtr->extra.monoColorPtr;                  valuePtr = optionPtr->extra.monoColorPtr;
535              } else {              } else {
536                  valuePtr = optionPtr->defaultPtr;                  valuePtr = optionPtr->defaultPtr;
537              }              }
538          }          }
539    
540          if (valuePtr == NULL) {          if (valuePtr == NULL) {
541              continue;              continue;
542          }          }
543    
544          if (DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin,          if (DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin,
545                  (Tk_SavedOption *) NULL) != TCL_OK) {                  (Tk_SavedOption *) NULL) != TCL_OK) {
546              if (interp != NULL) {              if (interp != NULL) {
547                  char msg[200];                  char msg[200];
548            
549                  switch (source) {                  switch (source) {
550                      case OPTION_DATABASE:                      case OPTION_DATABASE:
551                          sprintf(msg, "\n    (database entry for \"%.50s\")",                          sprintf(msg, "\n    (database entry for \"%.50s\")",
552                                  optionPtr->specPtr->optionName);                                  optionPtr->specPtr->optionName);
553                          break;                          break;
554                      case SYSTEM_DEFAULT:                      case SYSTEM_DEFAULT:
555                          sprintf(msg, "\n    (system default for \"%.50s\")",                          sprintf(msg, "\n    (system default for \"%.50s\")",
556                                  optionPtr->specPtr->optionName);                                  optionPtr->specPtr->optionName);
557                          break;                          break;
558                      case TABLE_DEFAULT:                      case TABLE_DEFAULT:
559                          sprintf(msg, "\n    (default value for \"%.50s\")",                          sprintf(msg, "\n    (default value for \"%.50s\")",
560                                  optionPtr->specPtr->optionName);                                  optionPtr->specPtr->optionName);
561                  }                  }
562                  if (tkwin != NULL) {                  if (tkwin != NULL) {
563                      sprintf(msg + strlen(msg) - 1, " in widget \"%.50s\")",                      sprintf(msg + strlen(msg) - 1, " in widget \"%.50s\")",
564                              Tk_PathName(tkwin));                              Tk_PathName(tkwin));
565                  }                  }
566                  Tcl_AddErrorInfo(interp, msg);                  Tcl_AddErrorInfo(interp, msg);
567              }              }
568              return TCL_ERROR;              return TCL_ERROR;
569          }          }
570      }      }
571      return TCL_OK;      return TCL_OK;
572  }  }
573    
574  /*  /*
575   *--------------------------------------------------------------   *--------------------------------------------------------------
576   *   *
577   * DoObjConfig --   * DoObjConfig --
578   *   *
579   *      This procedure applies a new value for a configuration option   *      This procedure applies a new value for a configuration option
580   *      to the record being configured.   *      to the record being configured.
581   *   *
582   * Results:   * Results:
583   *      The return value is TCL_OK if the procedure completed   *      The return value is TCL_OK if the procedure completed
584   *      successfully.  If an error occurred then TCL_ERROR is   *      successfully.  If an error occurred then TCL_ERROR is
585   *      returned and an error message is left in interp's result, if   *      returned and an error message is left in interp's result, if
586   *      interp isn't NULL.  In addition, if oldValuePtrPtr isn't   *      interp isn't NULL.  In addition, if oldValuePtrPtr isn't
587   *      NULL then it *oldValuePtrPtr is filled in with a pointer   *      NULL then it *oldValuePtrPtr is filled in with a pointer
588   *      to the option's old value.   *      to the option's old value.
589   *   *
590   * Side effects:   * Side effects:
591   *      RecordPtr gets modified to hold the new value in the form of   *      RecordPtr gets modified to hold the new value in the form of
592   *      a Tcl_Obj, an internal representation, or both.  The old   *      a Tcl_Obj, an internal representation, or both.  The old
593   *      value is freed if oldValuePtrPtr is NULL.   *      value is freed if oldValuePtrPtr is NULL.
594   *   *
595   *--------------------------------------------------------------   *--------------------------------------------------------------
596   */   */
597    
598  static int  static int
599  DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr)  DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr)
600      Tcl_Interp *interp;         /* Interpreter for error reporting.  If      Tcl_Interp *interp;         /* Interpreter for error reporting.  If
601                                   * NULL, then no message is left if an error                                   * NULL, then no message is left if an error
602                                   * occurs. */                                   * occurs. */
603      char *recordPtr;            /* The record to modify to hold the new      char *recordPtr;            /* The record to modify to hold the new
604                                   * option value. */                                   * option value. */
605      Option *optionPtr;          /* Pointer to information about the      Option *optionPtr;          /* Pointer to information about the
606                                   * option. */                                   * option. */
607      Tcl_Obj *valuePtr;          /* New value for option. */      Tcl_Obj *valuePtr;          /* New value for option. */
608      Tk_Window tkwin;            /* Window in which option will be used (needed      Tk_Window tkwin;            /* Window in which option will be used (needed
609                                   * to allocate resources for some options).                                   * to allocate resources for some options).
610                                   * May be NULL if the option doesn't                                   * May be NULL if the option doesn't
611                                   * require window-related resources. */                                   * require window-related resources. */
612      Tk_SavedOption *savedOptionPtr;      Tk_SavedOption *savedOptionPtr;
613                                  /* If NULL, the old value for the option will                                  /* If NULL, the old value for the option will
614                                   * be freed. If non-NULL, the old value will                                   * be freed. If non-NULL, the old value will
615                                   * be stored here, and it becomes the property                                   * be stored here, and it becomes the property
616                                   * of the caller (the caller must eventually                                   * of the caller (the caller must eventually
617                                   * free the old value). */                                   * free the old value). */
618  {  {
619      Tcl_Obj **slotPtrPtr, *oldPtr;      Tcl_Obj **slotPtrPtr, *oldPtr;
620      char *internalPtr;          /* Points to location in record where      char *internalPtr;          /* Points to location in record where
621                                   * internal representation of value should                                   * internal representation of value should
622                                   * be stored, or NULL. */                                   * be stored, or NULL. */
623      char *oldInternalPtr;       /* Points to location in which to save old      char *oldInternalPtr;       /* Points to location in which to save old
624                                   * internal representation of value. */                                   * internal representation of value. */
625      Tk_SavedOption internal;    /* Used to save the old internal representation      Tk_SavedOption internal;    /* Used to save the old internal representation
626                                   * of the value if savedOptionPtr is NULL. */                                   * of the value if savedOptionPtr is NULL. */
627      CONST Tk_OptionSpec *specPtr;      CONST Tk_OptionSpec *specPtr;
628      int nullOK;      int nullOK;
629    
630      /*      /*
631       * Save the old object form for the value, if there is one.       * Save the old object form for the value, if there is one.
632       */       */
633    
634      specPtr = optionPtr->specPtr;      specPtr = optionPtr->specPtr;
635      if (specPtr->objOffset >= 0) {      if (specPtr->objOffset >= 0) {
636          slotPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);          slotPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
637          oldPtr = *slotPtrPtr;          oldPtr = *slotPtrPtr;
638      } else {      } else {
639          slotPtrPtr = NULL;          slotPtrPtr = NULL;
640          oldPtr = NULL;          oldPtr = NULL;
641      }      }
642    
643      /*      /*
644       * Apply the new value in a type-specific way.  Also remember the       * Apply the new value in a type-specific way.  Also remember the
645       * old object and internal forms, if they exist.       * old object and internal forms, if they exist.
646       */       */
647    
648      if (specPtr->internalOffset >= 0) {      if (specPtr->internalOffset >= 0) {
649          internalPtr = recordPtr + specPtr->internalOffset;          internalPtr = recordPtr + specPtr->internalOffset;
650      } else {      } else {
651          internalPtr = NULL;          internalPtr = NULL;
652      }      }
653      if (savedOptionPtr != NULL) {      if (savedOptionPtr != NULL) {
654          savedOptionPtr->optionPtr = optionPtr;          savedOptionPtr->optionPtr = optionPtr;
655          savedOptionPtr->valuePtr = oldPtr;          savedOptionPtr->valuePtr = oldPtr;
656          oldInternalPtr = (char *) &savedOptionPtr->internalForm;          oldInternalPtr = (char *) &savedOptionPtr->internalForm;
657      } else {      } else {
658          oldInternalPtr = (char *) &internal.internalForm;          oldInternalPtr = (char *) &internal.internalForm;
659      }      }
660      nullOK = (optionPtr->specPtr->flags & TK_OPTION_NULL_OK);      nullOK = (optionPtr->specPtr->flags & TK_OPTION_NULL_OK);
661      switch (optionPtr->specPtr->type) {      switch (optionPtr->specPtr->type) {
662          case TK_OPTION_BOOLEAN: {          case TK_OPTION_BOOLEAN: {
663              int new;              int new;
664    
665              if (Tcl_GetBooleanFromObj(interp, valuePtr, &new)              if (Tcl_GetBooleanFromObj(interp, valuePtr, &new)
666                      != TCL_OK) {                      != TCL_OK) {
667                  return TCL_ERROR;                  return TCL_ERROR;
668              }              }
669              if (internalPtr != NULL) {              if (internalPtr != NULL) {
670                  *((int *) oldInternalPtr) = *((int *) internalPtr);                  *((int *) oldInternalPtr) = *((int *) internalPtr);
671                  *((int *) internalPtr) = new;                  *((int *) internalPtr) = new;
672              }              }
673              break;              break;
674          }          }
675          case TK_OPTION_INT: {          case TK_OPTION_INT: {
676              int new;              int new;
677                            
678              if (Tcl_GetIntFromObj(interp, valuePtr, &new) != TCL_OK) {              if (Tcl_GetIntFromObj(interp, valuePtr, &new) != TCL_OK) {
679                  return TCL_ERROR;                  return TCL_ERROR;
680              }              }
681              if (internalPtr != NULL) {              if (internalPtr != NULL) {
682                  *((int *) oldInternalPtr) = *((int *) internalPtr);                  *((int *) oldInternalPtr) = *((int *) internalPtr);
683                  *((int *) internalPtr) = new;                  *((int *) internalPtr) = new;
684              }              }
685              break;              break;
686          }          }
687          case TK_OPTION_DOUBLE: {          case TK_OPTION_DOUBLE: {
688              double new;              double new;
689                            
690              if (Tcl_GetDoubleFromObj(interp, valuePtr, &new)              if (Tcl_GetDoubleFromObj(interp, valuePtr, &new)
691                      != TCL_OK) {                      != TCL_OK) {
692                  return TCL_ERROR;                  return TCL_ERROR;
693              }              }
694              if (internalPtr != NULL) {              if (internalPtr != NULL) {
695                  *((double *) oldInternalPtr) = *((double *) internalPtr);                  *((double *) oldInternalPtr) = *((double *) internalPtr);
696                  *((double *) internalPtr) = new;                  *((double *) internalPtr) = new;
697              }              }
698              break;              break;
699          }          }
700          case TK_OPTION_STRING: {          case TK_OPTION_STRING: {
701              char *new, *value;              char *new, *value;
702              int length;              int length;
703    
704              if (nullOK && ObjectIsEmpty(valuePtr)) {              if (nullOK && ObjectIsEmpty(valuePtr)) {
705                  valuePtr = NULL;                  valuePtr = NULL;
706              }              }
707              if (internalPtr != NULL) {              if (internalPtr != NULL) {
708                  if (valuePtr != NULL) {                  if (valuePtr != NULL) {
709                      value = Tcl_GetStringFromObj(valuePtr, &length);                      value = Tcl_GetStringFromObj(valuePtr, &length);
710                      new = ckalloc((unsigned) (length + 1));                      new = ckalloc((unsigned) (length + 1));
711                      strcpy(new, value);                      strcpy(new, value);
712                  } else {                  } else {
713                      new = NULL;                      new = NULL;
714                  }                  }
715                  *((char **) oldInternalPtr) = *((char **) internalPtr);                  *((char **) oldInternalPtr) = *((char **) internalPtr);
716                  *((char **) internalPtr) = new;                  *((char **) internalPtr) = new;
717              }              }
718              break;              break;
719          }          }
720          case TK_OPTION_STRING_TABLE: {          case TK_OPTION_STRING_TABLE: {
721              int new;              int new;
722    
723              if (Tcl_GetIndexFromObj(interp, valuePtr,              if (Tcl_GetIndexFromObj(interp, valuePtr,
724                      (char **) optionPtr->specPtr->clientData,                      (char **) optionPtr->specPtr->clientData,
725                      optionPtr->specPtr->optionName+1, 0, &new) != TCL_OK) {                      optionPtr->specPtr->optionName+1, 0, &new) != TCL_OK) {
726                  return TCL_ERROR;                  return TCL_ERROR;
727              }              }
728              if (internalPtr != NULL) {              if (internalPtr != NULL) {
729                  *((int *) oldInternalPtr) = *((int *) internalPtr);                  *((int *) oldInternalPtr) = *((int *) internalPtr);
730                  *((int *) internalPtr) = new;                  *((int *) internalPtr) = new;
731              }              }
732              break;              break;
733          }          }
734          case TK_OPTION_COLOR: {          case TK_OPTION_COLOR: {
735              XColor *newPtr;              XColor *newPtr;
736    
737              if (nullOK && ObjectIsEmpty(valuePtr)) {              if (nullOK && ObjectIsEmpty(valuePtr)) {
738                  valuePtr = NULL;                  valuePtr = NULL;
739                  newPtr = NULL;                  newPtr = NULL;
740              } else {              } else {
741                  newPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr);                  newPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr);
742                  if (newPtr == NULL) {                  if (newPtr == NULL) {
743                      return TCL_ERROR;                      return TCL_ERROR;
744                  }                  }
745              }              }
746              if (internalPtr != NULL) {              if (internalPtr != NULL) {
747                  *((XColor **) oldInternalPtr) = *((XColor **) internalPtr);                  *((XColor **) oldInternalPtr) = *((XColor **) internalPtr);
748                  *((XColor **) internalPtr) = newPtr;                  *((XColor **) internalPtr) = newPtr;
749              }              }
750              break;              break;
751          }          }
752          case TK_OPTION_FONT: {          case TK_OPTION_FONT: {
753              Tk_Font new;              Tk_Font new;
754    
755              if (nullOK && ObjectIsEmpty(valuePtr)) {              if (nullOK && ObjectIsEmpty(valuePtr)) {
756                  valuePtr = NULL;                  valuePtr = NULL;
757                  new = NULL;                  new = NULL;
758              } else {              } else {
759                  new = Tk_AllocFontFromObj(interp, tkwin, valuePtr);                  new = Tk_AllocFontFromObj(interp, tkwin, valuePtr);
760                  if (new == NULL) {                  if (new == NULL) {
761                      return TCL_ERROR;                      return TCL_ERROR;
762                  }                  }
763              }              }
764              if (internalPtr != NULL) {              if (internalPtr != NULL) {
765                  *((Tk_Font *) oldInternalPtr) = *((Tk_Font *) internalPtr);                  *((Tk_Font *) oldInternalPtr) = *((Tk_Font *) internalPtr);
766                  *((Tk_Font *) internalPtr) = new;                  *((Tk_Font *) internalPtr) = new;
767              }              }
768              break;              break;
769          }          }
770          case TK_OPTION_BITMAP: {          case TK_OPTION_BITMAP: {
771              Pixmap new;              Pixmap new;
772    
773              if (nullOK && ObjectIsEmpty(valuePtr)) {              if (nullOK && ObjectIsEmpty(valuePtr)) {
774                  valuePtr = NULL;                  valuePtr = NULL;
775                  new = None;                  new = None;
776              } else {              } else {
777                  new = Tk_AllocBitmapFromObj(interp, tkwin, valuePtr);                  new = Tk_AllocBitmapFromObj(interp, tkwin, valuePtr);
778                  if (new == None) {                  if (new == None) {
779                      return TCL_ERROR;                      return TCL_ERROR;
780                  }                  }
781              }              }
782              if (internalPtr != NULL) {              if (internalPtr != NULL) {
783                  *((Pixmap *) oldInternalPtr) = *((Pixmap *) internalPtr);                  *((Pixmap *) oldInternalPtr) = *((Pixmap *) internalPtr);
784                  *((Pixmap *) internalPtr) = new;                  *((Pixmap *) internalPtr) = new;
785              }              }
786              break;              break;
787          }          }
788          case TK_OPTION_BORDER: {          case TK_OPTION_BORDER: {
789              Tk_3DBorder new;              Tk_3DBorder new;
790    
791              if (nullOK && ObjectIsEmpty(valuePtr)) {              if (nullOK && ObjectIsEmpty(valuePtr)) {
792                  valuePtr = NULL;                  valuePtr = NULL;
793                  new = NULL;                  new = NULL;
794              } else {              } else {
795                  new = Tk_Alloc3DBorderFromObj(interp, tkwin, valuePtr);                  new = Tk_Alloc3DBorderFromObj(interp, tkwin, valuePtr);
796                  if (new == NULL) {                  if (new == NULL) {
797                      return TCL_ERROR;                      return TCL_ERROR;
798                  }                  }
799              }              }
800              if (internalPtr != NULL) {              if (internalPtr != NULL) {
801                  *((Tk_3DBorder *) oldInternalPtr) =                  *((Tk_3DBorder *) oldInternalPtr) =
802                          *((Tk_3DBorder *) internalPtr);                          *((Tk_3DBorder *) internalPtr);
803                  *((Tk_3DBorder *) internalPtr) = new;                  *((Tk_3DBorder *) internalPtr) = new;
804              }              }
805              break;              break;
806          }          }
807          case TK_OPTION_RELIEF: {          case TK_OPTION_RELIEF: {
808              int new;              int new;
809    
810              if (Tk_GetReliefFromObj(interp, valuePtr, &new) != TCL_OK) {              if (Tk_GetReliefFromObj(interp, valuePtr, &new) != TCL_OK) {
811                  return TCL_ERROR;                  return TCL_ERROR;
812              }              }
813              if (internalPtr != NULL) {              if (internalPtr != NULL) {
814                  *((int *) oldInternalPtr) = *((int *) internalPtr);                  *((int *) oldInternalPtr) = *((int *) internalPtr);
815                  *((int *) internalPtr) = new;                  *((int *) internalPtr) = new;
816              }              }
817              break;              break;
818          }          }
819          case TK_OPTION_CURSOR: {          case TK_OPTION_CURSOR: {
820              Tk_Cursor new;              Tk_Cursor new;
821    
822              if (nullOK && ObjectIsEmpty(valuePtr)) {              if (nullOK && ObjectIsEmpty(valuePtr)) {
823                  new = None;                  new = None;
824                  valuePtr = NULL;                  valuePtr = NULL;
825              } else {              } else {
826                  new = Tk_AllocCursorFromObj(interp, tkwin, valuePtr);                  new = Tk_AllocCursorFromObj(interp, tkwin, valuePtr);
827                  if (new == None) {                  if (new == None) {
828                      return TCL_ERROR;                      return TCL_ERROR;
829                  }                  }
830              }              }
831              if (internalPtr != NULL) {              if (internalPtr != NULL) {
832                  *((Tk_Cursor *) oldInternalPtr) = *((Tk_Cursor *) internalPtr);                  *((Tk_Cursor *) oldInternalPtr) = *((Tk_Cursor *) internalPtr);
833                  *((Tk_Cursor *) internalPtr) = new;                  *((Tk_Cursor *) internalPtr) = new;
834              }              }
835              Tk_DefineCursor(tkwin, new);              Tk_DefineCursor(tkwin, new);
836              break;              break;
837          }          }
838          case TK_OPTION_JUSTIFY: {          case TK_OPTION_JUSTIFY: {
839              Tk_Justify new;              Tk_Justify new;
840    
841              if (Tk_GetJustifyFromObj(interp, valuePtr, &new) != TCL_OK) {              if (Tk_GetJustifyFromObj(interp, valuePtr, &new) != TCL_OK) {
842                  return TCL_ERROR;                  return TCL_ERROR;
843              }              }
844              if (internalPtr != NULL) {              if (internalPtr != NULL) {
845                  *((Tk_Justify *) oldInternalPtr)                  *((Tk_Justify *) oldInternalPtr)
846                          = *((Tk_Justify *) internalPtr);                          = *((Tk_Justify *) internalPtr);
847                  *((Tk_Justify *) internalPtr) = new;                  *((Tk_Justify *) internalPtr) = new;
848              }              }
849              break;              break;
850          }          }
851          case TK_OPTION_ANCHOR: {          case TK_OPTION_ANCHOR: {
852              Tk_Anchor new;              Tk_Anchor new;
853    
854              if (Tk_GetAnchorFromObj(interp, valuePtr, &new) != TCL_OK) {              if (Tk_GetAnchorFromObj(interp, valuePtr, &new) != TCL_OK) {
855                  return TCL_ERROR;                  return TCL_ERROR;
856              }              }
857              if (internalPtr != NULL) {              if (internalPtr != NULL) {
858                  *((Tk_Anchor *) oldInternalPtr)                  *((Tk_Anchor *) oldInternalPtr)
859                          = *((Tk_Anchor *) internalPtr);                          = *((Tk_Anchor *) internalPtr);
860                  *((Tk_Anchor *) internalPtr) = new;                  *((Tk_Anchor *) internalPtr) = new;
861              }              }
862              break;              break;
863          }          }
864          case TK_OPTION_PIXELS: {          case TK_OPTION_PIXELS: {
865              int new;              int new;
866                            
867              if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr,              if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr,
868                      &new) != TCL_OK) {                      &new) != TCL_OK) {
869                  return TCL_ERROR;                  return TCL_ERROR;
870              }              }
871              if (internalPtr != NULL) {              if (internalPtr != NULL) {
872                  *((int *) oldInternalPtr) = *((int *) internalPtr);                  *((int *) oldInternalPtr) = *((int *) internalPtr);
873                  *((int *) internalPtr) = new;                  *((int *) internalPtr) = new;
874              }              }
875              break;              break;
876          }          }
877          case TK_OPTION_WINDOW: {          case TK_OPTION_WINDOW: {
878              Tk_Window new;              Tk_Window new;
879    
880              if (nullOK && ObjectIsEmpty(valuePtr)) {              if (nullOK && ObjectIsEmpty(valuePtr)) {
881                  valuePtr = NULL;                  valuePtr = NULL;
882                  new = None;                  new = None;
883              } else {              } else {
884                  if (TkGetWindowFromObj(interp, tkwin, valuePtr, &new)                  if (TkGetWindowFromObj(interp, tkwin, valuePtr, &new)
885                          != TCL_OK) {                          != TCL_OK) {
886                      return TCL_ERROR;                      return TCL_ERROR;
887                  }                  }
888              }              }
889              if (internalPtr != NULL) {              if (internalPtr != NULL) {
890                  *((Tk_Window *) oldInternalPtr) = *((Tk_Window *) internalPtr);                  *((Tk_Window *) oldInternalPtr) = *((Tk_Window *) internalPtr);
891                  *((Tk_Window *) internalPtr) = new;                  *((Tk_Window *) internalPtr) = new;
892              }              }
893              break;              break;
894          }          }
895          default: {          default: {
896              char buf[40+TCL_INTEGER_SPACE];              char buf[40+TCL_INTEGER_SPACE];
897              sprintf(buf, "bad config table: unknown type %d",              sprintf(buf, "bad config table: unknown type %d",
898                      optionPtr->specPtr->type);                      optionPtr->specPtr->type);
899              Tcl_SetResult(interp, buf, TCL_VOLATILE);              Tcl_SetResult(interp, buf, TCL_VOLATILE);
900              return TCL_ERROR;              return TCL_ERROR;
901          }          }
902      }      }
903    
904      /*      /*
905       * Release resources associated with the old value, if we're not       * Release resources associated with the old value, if we're not
906       * returning it to the caller, then install the new object value into       * returning it to the caller, then install the new object value into
907       * the record.       * the record.
908       */       */
909    
910      if (savedOptionPtr == NULL) {      if (savedOptionPtr == NULL) {
911          if (optionPtr->flags & OPTION_NEEDS_FREEING) {          if (optionPtr->flags & OPTION_NEEDS_FREEING) {
912              FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);              FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);
913          }          }
914          if (oldPtr != NULL) {          if (oldPtr != NULL) {
915              Tcl_DecrRefCount(oldPtr);              Tcl_DecrRefCount(oldPtr);
916          }          }
917      }      }
918      if (slotPtrPtr != NULL) {      if (slotPtrPtr != NULL) {
919          *slotPtrPtr = valuePtr;          *slotPtrPtr = valuePtr;
920          if (valuePtr != NULL) {          if (valuePtr != NULL) {
921              Tcl_IncrRefCount(valuePtr);              Tcl_IncrRefCount(valuePtr);
922          }          }
923      }      }
924      return TCL_OK;      return TCL_OK;
925  }  }
926    
927  /*  /*
928   *----------------------------------------------------------------------   *----------------------------------------------------------------------
929   *   *
930   * ObjectIsEmpty --   * ObjectIsEmpty --
931   *   *
932   *      This procedure tests whether the string value of an object is   *      This procedure tests whether the string value of an object is
933   *      empty.   *      empty.
934   *   *
935   * Results:   * Results:
936   *      The return value is 1 if the string value of objPtr has length   *      The return value is 1 if the string value of objPtr has length
937   *      zero, and 0 otherwise.   *      zero, and 0 otherwise.
938   *   *
939   * Side effects:   * Side effects:
940   *      None.   *      None.
941   *   *
942   *----------------------------------------------------------------------   *----------------------------------------------------------------------
943   */   */
944    
945  static int  static int
946  ObjectIsEmpty(objPtr)  ObjectIsEmpty(objPtr)
947      Tcl_Obj *objPtr;            /* Object to test.  May be NULL. */      Tcl_Obj *objPtr;            /* Object to test.  May be NULL. */
948  {  {
949      int length;      int length;
950    
951      if (objPtr == NULL) {      if (objPtr == NULL) {
952          return 1;          return 1;
953      }      }
954      if (objPtr->bytes != NULL) {      if (objPtr->bytes != NULL) {
955          return (objPtr->length == 0);          return (objPtr->length == 0);
956      }      }
957      Tcl_GetStringFromObj(objPtr, &length);      Tcl_GetStringFromObj(objPtr, &length);
958      return (length == 0);      return (length == 0);
959  }  }
960    
961  /*  /*
962   *----------------------------------------------------------------------   *----------------------------------------------------------------------
963   *   *
964   * GetOptionFromObj --   * GetOptionFromObj --
965   *   *
966   *      This procedure searches through a chained option table to find   *      This procedure searches through a chained option table to find
967   *      the entry for a particular option name.   *      the entry for a particular option name.
968   *   *
969   * Results:   * Results:
970   *      The return value is a pointer to the matching entry, or NULL   *      The return value is a pointer to the matching entry, or NULL
971   *      if no matching entry could be found.  If NULL is returned and   *      if no matching entry could be found.  If NULL is returned and
972   *      interp is not NULL than an error message is left in its result.   *      interp is not NULL than an error message is left in its result.
973   *      Note: if the matching entry is a synonym then this procedure   *      Note: if the matching entry is a synonym then this procedure
974   *      returns a pointer to the synonym entry, *not* the "real" entry   *      returns a pointer to the synonym entry, *not* the "real" entry
975   *      that the synonym refers to.   *      that the synonym refers to.
976   *   *
977   * Side effects:   * Side effects:
978   *      Information about the matching entry is cached in the object   *      Information about the matching entry is cached in the object
979   *      containing the name, so that future lookups can proceed more   *      containing the name, so that future lookups can proceed more
980   *      quickly.   *      quickly.
981   *   *
982   *----------------------------------------------------------------------   *----------------------------------------------------------------------
983   */   */
984    
985  static Option *  static Option *
986  GetOptionFromObj(interp, objPtr, tablePtr)  GetOptionFromObj(interp, objPtr, tablePtr)
987      Tcl_Interp *interp;         /* Used only for error reporting; if NULL      Tcl_Interp *interp;         /* Used only for error reporting; if NULL
988                                   * no message is left after an error. */                                   * no message is left after an error. */
989      Tcl_Obj *objPtr;            /* Object whose string value is to be      Tcl_Obj *objPtr;            /* Object whose string value is to be
990                                   * looked up in the option table. */                                   * looked up in the option table. */
991      OptionTable *tablePtr;      /* Table in which to look up objPtr. */      OptionTable *tablePtr;      /* Table in which to look up objPtr. */
992  {  {
993      Option *bestPtr, *optionPtr;      Option *bestPtr, *optionPtr;
994      OptionTable *tablePtr2;      OptionTable *tablePtr2;
995      char *p1, *p2, *name;      char *p1, *p2, *name;
996      int count;      int count;
997    
998      /*      /*
999       * First, check to see if the object already has the answer cached.       * First, check to see if the object already has the answer cached.
1000       */       */
1001    
1002      if (objPtr->typePtr == &optionType) {      if (objPtr->typePtr == &optionType) {
1003          if (objPtr->internalRep.twoPtrValue.ptr1 == (VOID *) tablePtr) {          if (objPtr->internalRep.twoPtrValue.ptr1 == (VOID *) tablePtr) {
1004              return (Option *) objPtr->internalRep.twoPtrValue.ptr2;              return (Option *) objPtr->internalRep.twoPtrValue.ptr2;
1005          }          }
1006      }      }
1007    
1008      /*      /*
1009       * The answer isn't cached.  Search through all of the option tables       * The answer isn't cached.  Search through all of the option tables
1010       * in the chain to find the best match.  Some tricky aspects:       * in the chain to find the best match.  Some tricky aspects:
1011       *       *
1012       * 1. We have to accept unique abbreviations.       * 1. We have to accept unique abbreviations.
1013       * 2. The same name could appear in different tables in the chain.       * 2. The same name could appear in different tables in the chain.
1014       *    If this happens, we use the entry from the first table. We       *    If this happens, we use the entry from the first table. We
1015       *    have to be careful to distinguish this case from an ambiguous       *    have to be careful to distinguish this case from an ambiguous
1016       *    abbreviation.       *    abbreviation.
1017       */       */
1018    
1019      bestPtr = NULL;      bestPtr = NULL;
1020      name = Tcl_GetStringFromObj(objPtr, (int *) NULL);      name = Tcl_GetStringFromObj(objPtr, (int *) NULL);
1021      for (tablePtr2 = tablePtr; tablePtr2 != NULL;      for (tablePtr2 = tablePtr; tablePtr2 != NULL;
1022              tablePtr2 = tablePtr2->nextPtr) {              tablePtr2 = tablePtr2->nextPtr) {
1023          for (optionPtr = tablePtr2->options, count = tablePtr2->numOptions;          for (optionPtr = tablePtr2->options, count = tablePtr2->numOptions;
1024                  count > 0; optionPtr++, count--) {                  count > 0; optionPtr++, count--) {
1025              for (p1 = name, p2 = optionPtr->specPtr->optionName;              for (p1 = name, p2 = optionPtr->specPtr->optionName;
1026                      *p1 == *p2; p1++, p2++) {                      *p1 == *p2; p1++, p2++) {
1027                  if (*p1 == 0) {                  if (*p1 == 0) {
1028                      /*                      /*
1029                       * This is an exact match.  We're done.                       * This is an exact match.  We're done.
1030                       */                       */
1031    
1032                      bestPtr = optionPtr;                      bestPtr = optionPtr;
1033                      goto done;                      goto done;
1034                  }                  }
1035              }              }
1036              if (*p1 == 0) {              if (*p1 == 0) {
1037                  /*                  /*
1038                   * The name is an abbreviation for this option.  Keep                   * The name is an abbreviation for this option.  Keep
1039                   * to make sure that the abbreviation only matches one                   * to make sure that the abbreviation only matches one
1040                   * option name.  If we've already found a match in the                   * option name.  If we've already found a match in the
1041                   * past, then it is an error unless the full names for                   * past, then it is an error unless the full names for
1042                   * the two options are identical; in this case, the first                   * the two options are identical; in this case, the first
1043                   * option overrides the second.                   * option overrides the second.
1044                   */                   */
1045    
1046                  if (bestPtr == NULL) {                  if (bestPtr == NULL) {
1047                      bestPtr = optionPtr;                      bestPtr = optionPtr;
1048                  } else {                  } else {
1049                      if (strcmp(bestPtr->specPtr->optionName,                      if (strcmp(bestPtr->specPtr->optionName,
1050                              optionPtr->specPtr->optionName) != 0) {                              optionPtr->specPtr->optionName) != 0) {
1051                          goto error;                          goto error;
1052                      }                      }
1053                  }                  }
1054              }              }
1055          }          }
1056      }      }
1057      if (bestPtr == NULL) {      if (bestPtr == NULL) {
1058          goto error;          goto error;
1059      }      }
1060    
1061      done:      done:
1062      if ((objPtr->typePtr != NULL)      if ((objPtr->typePtr != NULL)
1063              && (objPtr->typePtr->freeIntRepProc != NULL)) {              && (objPtr->typePtr->freeIntRepProc != NULL)) {
1064          objPtr->typePtr->freeIntRepProc(objPtr);          objPtr->typePtr->freeIntRepProc(objPtr);
1065      }      }
1066      objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tablePtr;      objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tablePtr;
1067      objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) bestPtr;      objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) bestPtr;
1068      objPtr->typePtr = &optionType;      objPtr->typePtr = &optionType;
1069      return bestPtr;      return bestPtr;
1070    
1071      error:      error:
1072      if (interp != NULL) {      if (interp != NULL) {
1073          Tcl_AppendResult(interp, "unknown option \"", name,          Tcl_AppendResult(interp, "unknown option \"", name,
1074                  "\"", (char *) NULL);                  "\"", (char *) NULL);
1075      }      }
1076      return NULL;      return NULL;
1077  }  }
1078    
1079  /*  /*
1080   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1081   *   *
1082   * SetOptionFromAny --   * SetOptionFromAny --
1083   *   *
1084   *      This procedure is called to convert a Tcl object to option   *      This procedure is called to convert a Tcl object to option
1085   *      internal form. However, this doesn't make sense (need to have a   *      internal form. However, this doesn't make sense (need to have a
1086   *      table of options in order to do the conversion) so the   *      table of options in order to do the conversion) so the
1087   *      procedure always generates an error.   *      procedure always generates an error.
1088   *   *
1089   * Results:   * Results:
1090   *      The return value is always TCL_ERROR, and an error message is   *      The return value is always TCL_ERROR, and an error message is
1091   *      left in interp's result if interp isn't NULL.   *      left in interp's result if interp isn't NULL.
1092   *   *
1093   * Side effects:   * Side effects:
1094   *      None.   *      None.
1095   *   *
1096   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1097   */   */
1098    
1099  static int  static int
1100  SetOptionFromAny(interp, objPtr)  SetOptionFromAny(interp, objPtr)
1101      Tcl_Interp *interp;         /* Used for error reporting if not NULL. */      Tcl_Interp *interp;         /* Used for error reporting if not NULL. */
1102      register Tcl_Obj *objPtr;   /* The object to convert. */      register Tcl_Obj *objPtr;   /* The object to convert. */
1103  {  {
1104      Tcl_AppendToObj(Tcl_GetObjResult(interp),      Tcl_AppendToObj(Tcl_GetObjResult(interp),
1105              "can't convert value to option except via GetOptionFromObj API",              "can't convert value to option except via GetOptionFromObj API",
1106              -1);              -1);
1107      return TCL_ERROR;      return TCL_ERROR;
1108  }  }
1109    
1110  /*  /*
1111   *--------------------------------------------------------------   *--------------------------------------------------------------
1112   *   *
1113   * Tk_SetOptions --   * Tk_SetOptions --
1114   *   *
1115   *      Process one or more name-value pairs for configuration options   *      Process one or more name-value pairs for configuration options
1116   *      and fill in fields of a record with new values.   *      and fill in fields of a record with new values.
1117   *   *
1118   * Results:   * Results:
1119   *      If all goes well then TCL_OK is returned and the old values of   *      If all goes well then TCL_OK is returned and the old values of
1120   *      any modified objects are saved in *savePtr, if it isn't NULL (the   *      any modified objects are saved in *savePtr, if it isn't NULL (the
1121   *      caller must eventually call Tk_RestoreSavedOptions or   *      caller must eventually call Tk_RestoreSavedOptions or
1122   *      Tk_FreeSavedOptions to free the contents of *savePtr).  In   *      Tk_FreeSavedOptions to free the contents of *savePtr).  In
1123   *      addition, if maskPtr isn't NULL then *maskPtr is filled in with   *      addition, if maskPtr isn't NULL then *maskPtr is filled in with
1124   *      the OR of the typeMask bits from all modified options.  If an   *      the OR of the typeMask bits from all modified options.  If an
1125   *      error occurs then TCL_ERROR is returned and a message   *      error occurs then TCL_ERROR is returned and a message
1126   *      is left in interp's result unless interp is NULL; nothing is   *      is left in interp's result unless interp is NULL; nothing is
1127   *      saved in *savePtr or *maskPtr in this case.   *      saved in *savePtr or *maskPtr in this case.
1128   *   *
1129   * Side effects:   * Side effects:
1130   *      The fields of recordPtr get filled in with object pointers   *      The fields of recordPtr get filled in with object pointers
1131   *      from objc/objv.  Old information in widgRec's fields gets   *      from objc/objv.  Old information in widgRec's fields gets
1132   *      recycled.  Information may be left at *savePtr.   *      recycled.  Information may be left at *savePtr.
1133   *   *
1134   *--------------------------------------------------------------   *--------------------------------------------------------------
1135   */   */
1136    
1137  int  int
1138  Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr,  Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr,
1139          maskPtr)          maskPtr)
1140      Tcl_Interp *interp;                 /* Interpreter for error reporting.      Tcl_Interp *interp;                 /* Interpreter for error reporting.
1141                                           * If NULL, then no error message is                                           * If NULL, then no error message is
1142                                           * returned.*/                                           * returned.*/
1143      char *recordPtr;                    /* The record to configure. */      char *recordPtr;                    /* The record to configure. */
1144      Tk_OptionTable optionTable;         /* Describes valid options. */      Tk_OptionTable optionTable;         /* Describes valid options. */
1145      int objc;                           /* The number of elements in objv. */      int objc;                           /* The number of elements in objv. */
1146      Tcl_Obj *CONST objv[];              /* Contains one or more name-value      Tcl_Obj *CONST objv[];              /* Contains one or more name-value
1147                                           * pairs. */                                           * pairs. */
1148      Tk_Window tkwin;                    /* Window associated with the thing      Tk_Window tkwin;                    /* Window associated with the thing
1149                                           * being configured; needed for some                                           * being configured; needed for some
1150                                           * options (such as colors). */                                           * options (such as colors). */
1151      Tk_SavedOptions *savePtr;           /* If non-NULL, the old values of      Tk_SavedOptions *savePtr;           /* If non-NULL, the old values of
1152                                           * modified options are saved here                                           * modified options are saved here
1153                                           * so that they can be restored                                           * so that they can be restored
1154                                           * after an error. */                                           * after an error. */
1155      int *maskPtr;                       /* It non-NULL, this word is modified      int *maskPtr;                       /* It non-NULL, this word is modified
1156                                           * on a successful return to hold the                                           * on a successful return to hold the
1157                                           * bit-wise OR of the typeMask fields                                           * bit-wise OR of the typeMask fields
1158                                           * of all options that were modified                                           * of all options that were modified
1159                                           * by this call.  Used by the caller                                           * by this call.  Used by the caller
1160                                           * to figure out which options                                           * to figure out which options
1161                                           * actually changed. */                                           * actually changed. */
1162  {  {
1163      OptionTable *tablePtr = (OptionTable *) optionTable;      OptionTable *tablePtr = (OptionTable *) optionTable;
1164      Option *optionPtr;      Option *optionPtr;
1165      Tk_SavedOptions *lastSavePtr, *newSavePtr;      Tk_SavedOptions *lastSavePtr, *newSavePtr;
1166      int mask;      int mask;
1167    
1168      if (savePtr != NULL) {      if (savePtr != NULL) {
1169          savePtr->recordPtr = recordPtr;          savePtr->recordPtr = recordPtr;
1170          savePtr->tkwin = tkwin;          savePtr->tkwin = tkwin;
1171          savePtr->numItems = 0;          savePtr->numItems = 0;
1172          savePtr->nextPtr = NULL;          savePtr->nextPtr = NULL;
1173      }      }
1174      lastSavePtr = savePtr;      lastSavePtr = savePtr;
1175    
1176      /*      /*
1177       * Scan through all of the arguments, processing those       * Scan through all of the arguments, processing those
1178       * that match entries in the option table.       * that match entries in the option table.
1179       */       */
1180    
1181      mask = 0;      mask = 0;
1182      for ( ; objc > 0; objc -= 2, objv += 2) {      for ( ; objc > 0; objc -= 2, objv += 2) {
1183          optionPtr = GetOptionFromObj(interp, objv[0], tablePtr);          optionPtr = GetOptionFromObj(interp, objv[0], tablePtr);
1184          if (optionPtr == NULL) {          if (optionPtr == NULL) {
1185              goto error;              goto error;
1186          }          }
1187          if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {          if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
1188              optionPtr = optionPtr->extra.synonymPtr;              optionPtr = optionPtr->extra.synonymPtr;
1189          }          }
1190    
1191          if (objc < 2) {          if (objc < 2) {
1192              if (interp != NULL) {              if (interp != NULL) {
1193                  Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),                  Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
1194                          "value for \"", Tcl_GetStringFromObj(*objv, NULL),                          "value for \"", Tcl_GetStringFromObj(*objv, NULL),
1195                          "\" missing", (char *) NULL);                          "\" missing", (char *) NULL);
1196                  goto error;                  goto error;
1197              }              }
1198          }          }
1199          if ((savePtr != NULL)          if ((savePtr != NULL)
1200                  && (lastSavePtr->numItems >= TK_NUM_SAVED_OPTIONS)) {                  && (lastSavePtr->numItems >= TK_NUM_SAVED_OPTIONS)) {
1201              /*              /*
1202               * We've run out of space for saving old option values.  Allocate               * We've run out of space for saving old option values.  Allocate
1203               * more space.               * more space.
1204               */               */
1205    
1206              newSavePtr = (Tk_SavedOptions *) ckalloc(sizeof(              newSavePtr = (Tk_SavedOptions *) ckalloc(sizeof(
1207                      Tk_SavedOptions));                      Tk_SavedOptions));
1208              newSavePtr->recordPtr = recordPtr;              newSavePtr->recordPtr = recordPtr;
1209              newSavePtr->tkwin = tkwin;              newSavePtr->tkwin = tkwin;
1210              newSavePtr->numItems = 0;              newSavePtr->numItems = 0;
1211              newSavePtr->nextPtr = NULL;              newSavePtr->nextPtr = NULL;
1212              lastSavePtr->nextPtr = newSavePtr;              lastSavePtr->nextPtr = newSavePtr;
1213              lastSavePtr = newSavePtr;              lastSavePtr = newSavePtr;
1214          }          }
1215          if (DoObjConfig(interp, recordPtr, optionPtr, objv[1], tkwin,          if (DoObjConfig(interp, recordPtr, optionPtr, objv[1], tkwin,
1216                  (savePtr != NULL) ? &lastSavePtr->items[lastSavePtr->numItems]                  (savePtr != NULL) ? &lastSavePtr->items[lastSavePtr->numItems]
1217                  : (Tk_SavedOption *) NULL) != TCL_OK) {                  : (Tk_SavedOption *) NULL) != TCL_OK) {
1218              char msg[100];              char msg[100];
1219    
1220              sprintf(msg, "\n    (processing \"%.40s\" option)",              sprintf(msg, "\n    (processing \"%.40s\" option)",
1221                      Tcl_GetStringFromObj(*objv, NULL));                      Tcl_GetStringFromObj(*objv, NULL));
1222              Tcl_AddErrorInfo(interp, msg);              Tcl_AddErrorInfo(interp, msg);
1223              goto error;              goto error;
1224          }          }
1225          if (savePtr != NULL) {          if (savePtr != NULL) {
1226              lastSavePtr->numItems++;              lastSavePtr->numItems++;
1227          }          }
1228          mask |= optionPtr->specPtr->typeMask;          mask |= optionPtr->specPtr->typeMask;
1229      }      }
1230      if (maskPtr != NULL) {      if (maskPtr != NULL) {
1231          *maskPtr = mask;          *maskPtr = mask;
1232      }      }
1233      return TCL_OK;      return TCL_OK;
1234    
1235      error:      error:
1236      if (savePtr != NULL) {      if (savePtr != NULL) {
1237          Tk_RestoreSavedOptions(savePtr);          Tk_RestoreSavedOptions(savePtr);
1238      }      }
1239      return TCL_ERROR;      return TCL_ERROR;
1240  }  }
1241    
1242  /*  /*
1243   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1244   *   *
1245   * Tk_RestoreSavedOptions --   * Tk_RestoreSavedOptions --
1246   *   *
1247   *      This procedure undoes the effect of a previous call to   *      This procedure undoes the effect of a previous call to
1248   *      Tk_SetOptions by restoring all of the options to their value   *      Tk_SetOptions by restoring all of the options to their value
1249   *      before the call to Tk_SetOptions.   *      before the call to Tk_SetOptions.
1250   *   *
1251   * Results:   * Results:
1252   *      None.   *      None.
1253   *   *
1254   * Side effects:   * Side effects:
1255   *      The configutation record is restored and all the information   *      The configutation record is restored and all the information
1256   *      stored in savePtr is freed.   *      stored in savePtr is freed.
1257   *   *
1258   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1259   */   */
1260    
1261  void  void
1262  Tk_RestoreSavedOptions(savePtr)  Tk_RestoreSavedOptions(savePtr)
1263      Tk_SavedOptions *savePtr;   /* Holds saved option information; must      Tk_SavedOptions *savePtr;   /* Holds saved option information; must
1264                                   * have been passed to Tk_SetOptions. */                                   * have been passed to Tk_SetOptions. */
1265  {  {
1266      int i;      int i;
1267      Option *optionPtr;      Option *optionPtr;
1268      Tcl_Obj *newPtr;            /* New object value of option, which we      Tcl_Obj *newPtr;            /* New object value of option, which we
1269                                   * replace with old value and free.  Taken                                   * replace with old value and free.  Taken
1270                                   * from record. */                                   * from record. */
1271      char *internalPtr;          /* Points to internal value of option in      char *internalPtr;          /* Points to internal value of option in
1272                                   * record. */                                   * record. */
1273      CONST Tk_OptionSpec *specPtr;      CONST Tk_OptionSpec *specPtr;
1274    
1275      /*      /*
1276       * Be sure to restore the options in the opposite order they were       * Be sure to restore the options in the opposite order they were
1277       * set.  This is important because it's possible that the same       * set.  This is important because it's possible that the same
1278       * option name was used twice in a single call to Tk_SetOptions.       * option name was used twice in a single call to Tk_SetOptions.
1279       */       */
1280    
1281      if (savePtr->nextPtr != NULL) {      if (savePtr->nextPtr != NULL) {
1282          Tk_RestoreSavedOptions(savePtr->nextPtr);          Tk_RestoreSavedOptions(savePtr->nextPtr);
1283          ckfree((char *) savePtr->nextPtr);          ckfree((char *) savePtr->nextPtr);
1284          savePtr->nextPtr = NULL;          savePtr->nextPtr = NULL;
1285      }      }
1286      for (i = savePtr->numItems - 1; i >= 0; i--) {      for (i = savePtr->numItems - 1; i >= 0; i--) {
1287          optionPtr = savePtr->items[i].optionPtr;          optionPtr = savePtr->items[i].optionPtr;
1288          specPtr = optionPtr->specPtr;          specPtr = optionPtr->specPtr;
1289    
1290          /*          /*
1291           * First free the new value of the option, which is currently           * First free the new value of the option, which is currently
1292           * in the record.           * in the record.
1293           */           */
1294    
1295          if (specPtr->objOffset >= 0) {          if (specPtr->objOffset >= 0) {
1296              newPtr = *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset));              newPtr = *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset));
1297          } else {          } else {
1298              newPtr = NULL;              newPtr = NULL;
1299          }          }
1300          if (specPtr->internalOffset >= 0) {          if (specPtr->internalOffset >= 0) {
1301              internalPtr = savePtr->recordPtr + specPtr->internalOffset;              internalPtr = savePtr->recordPtr + specPtr->internalOffset;
1302          } else {          } else {
1303              internalPtr = NULL;              internalPtr = NULL;
1304          }          }
1305          if (optionPtr->flags & OPTION_NEEDS_FREEING) {          if (optionPtr->flags & OPTION_NEEDS_FREEING) {
1306              FreeResources(optionPtr, newPtr, internalPtr, savePtr->tkwin);              FreeResources(optionPtr, newPtr, internalPtr, savePtr->tkwin);
1307          }          }
1308          if (newPtr != NULL) {          if (newPtr != NULL) {
1309              Tcl_DecrRefCount(newPtr);              Tcl_DecrRefCount(newPtr);
1310          }          }
1311    
1312          /*          /*
1313           * Now restore the old value of the option.           * Now restore the old value of the option.
1314           */           */
1315    
1316          if (specPtr->objOffset >= 0) {          if (specPtr->objOffset >= 0) {
1317              *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset))              *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset))
1318                      = savePtr->items[i].valuePtr;                      = savePtr->items[i].valuePtr;
1319          }          }
1320          if (specPtr->internalOffset >= 0) {          if (specPtr->internalOffset >= 0) {
1321              switch (specPtr->type) {              switch (specPtr->type) {
1322                  case TK_OPTION_BOOLEAN: {                  case TK_OPTION_BOOLEAN: {
1323                      *((int *) internalPtr)                      *((int *) internalPtr)
1324                              = *((int *) &savePtr->items[i].internalForm);                              = *((int *) &savePtr->items[i].internalForm);
1325                      break;                      break;
1326                  }                  }
1327                  case TK_OPTION_INT: {                  case TK_OPTION_INT: {
1328                      *((int *) internalPtr)                      *((int *) internalPtr)
1329                              = *((int *) &savePtr->items[i].internalForm);                              = *((int *) &savePtr->items[i].internalForm);
1330                      break;                      break;
1331                  }                  }
1332                  case TK_OPTION_DOUBLE: {                  case TK_OPTION_DOUBLE: {
1333                      *((double *) internalPtr)                      *((double *) internalPtr)
1334                              = *((double *) &savePtr->items[i].internalForm);                              = *((double *) &savePtr->items[i].internalForm);
1335                      break;                      break;
1336                  }                  }
1337                  case TK_OPTION_STRING: {                  case TK_OPTION_STRING: {
1338                      *((char **) internalPtr)                      *((char **) internalPtr)
1339                              = *((char **) &savePtr->items[i].internalForm);                              = *((char **) &savePtr->items[i].internalForm);
1340                      break;                      break;
1341                  }                  }
1342                  case TK_OPTION_STRING_TABLE: {                  case TK_OPTION_STRING_TABLE: {
1343                      *((int *) internalPtr)                      *((int *) internalPtr)
1344                              = *((int *) &savePtr->items[i].internalForm);                              = *((int *) &savePtr->items[i].internalForm);
1345                      break;                      break;
1346                  }                  }
1347                  case TK_OPTION_COLOR: {                  case TK_OPTION_COLOR: {
1348                      *((XColor **) internalPtr)                      *((XColor **) internalPtr)
1349                              = *((XColor **) &savePtr->items[i].internalForm);                              = *((XColor **) &savePtr->items[i].internalForm);
1350                      break;                      break;
1351                  }                  }
1352                  case TK_OPTION_FONT: {                  case TK_OPTION_FONT: {
1353                      *((Tk_Font *) internalPtr)                      *((Tk_Font *) internalPtr)
1354                              = *((Tk_Font *) &savePtr->items[i].internalForm);                              = *((Tk_Font *) &savePtr->items[i].internalForm);
1355                      break;                      break;
1356                  }                  }
1357                  case TK_OPTION_BITMAP: {                  case TK_OPTION_BITMAP: {
1358                      *((Pixmap *) internalPtr)                      *((Pixmap *) internalPtr)
1359                              = *((Pixmap *) &savePtr->items[i].internalForm);                              = *((Pixmap *) &savePtr->items[i].internalForm);
1360                      break;                      break;
1361                  }                  }
1362                  case TK_OPTION_BORDER: {                  case TK_OPTION_BORDER: {
1363                      *((Tk_3DBorder *) internalPtr)                      *((Tk_3DBorder *) internalPtr)
1364                              = *((Tk_3DBorder *) &savePtr->items[i].internalForm);                              = *((Tk_3DBorder *) &savePtr->items[i].internalForm);
1365                      break;                      break;
1366                  }                  }
1367                  case TK_OPTION_RELIEF: {                  case TK_OPTION_RELIEF: {
1368                      *((int *) internalPtr)                      *((int *) internalPtr)
1369                              = *((int *) &savePtr->items[i].internalForm);                              = *((int *) &savePtr->items[i].internalForm);
1370                      break;                      break;
1371                  }                  }
1372                  case TK_OPTION_CURSOR: {                  case TK_OPTION_CURSOR: {
1373                      *((Tk_Cursor *) internalPtr)                      *((Tk_Cursor *) internalPtr)
1374                              = *((Tk_Cursor *) &savePtr->items[i].internalForm);                              = *((Tk_Cursor *) &savePtr->items[i].internalForm);
1375                      Tk_DefineCursor(savePtr->tkwin,                      Tk_DefineCursor(savePtr->tkwin,
1376                              *((Tk_Cursor *) internalPtr));                              *((Tk_Cursor *) internalPtr));
1377                      break;                      break;
1378                  }                  }
1379                  case TK_OPTION_JUSTIFY: {                  case TK_OPTION_JUSTIFY: {
1380                      *((Tk_Justify *) internalPtr)                      *((Tk_Justify *) internalPtr)
1381                              = *((Tk_Justify *) &savePtr->items[i].internalForm);                              = *((Tk_Justify *) &savePtr->items[i].internalForm);
1382                      break;                      break;
1383                  }                  }
1384                  case TK_OPTION_ANCHOR: {                  case TK_OPTION_ANCHOR: {
1385                      *((Tk_Anchor *) internalPtr)                      *((Tk_Anchor *) internalPtr)
1386                              = *((Tk_Anchor *) &savePtr->items[i].internalForm);                              = *((Tk_Anchor *) &savePtr->items[i].internalForm);
1387                      break;                      break;
1388                  }                  }
1389                  case TK_OPTION_PIXELS: {                  case TK_OPTION_PIXELS: {
1390                      *((int *) internalPtr)                      *((int *) internalPtr)
1391                              = *((int *) &savePtr->items[i].internalForm);                              = *((int *) &savePtr->items[i].internalForm);
1392                      break;                      break;
1393                  }                  }
1394                  case TK_OPTION_WINDOW: {                  case TK_OPTION_WINDOW: {
1395                      *((Tk_Window *) internalPtr)                      *((Tk_Window *) internalPtr)
1396                              = *((Tk_Window *) &savePtr->items[i].internalForm);                              = *((Tk_Window *) &savePtr->items[i].internalForm);
1397                      break;                      break;
1398                  }                  }
1399                  default: {                  default: {
1400                      panic("bad option type in Tk_RestoreSavedOptions");                      panic("bad option type in Tk_RestoreSavedOptions");
1401                  }                  }
1402              }              }
1403          }          }
1404      }      }
1405      savePtr->numItems = 0;      savePtr->numItems = 0;
1406  }  }
1407    
1408  /*  /*
1409   *--------------------------------------------------------------   *--------------------------------------------------------------
1410   *   *
1411   * Tk_FreeSavedOptions --   * Tk_FreeSavedOptions --
1412   *   *
1413   *      Free all of the saved configuration option values from a   *      Free all of the saved configuration option values from a
1414   *      previous call to Tk_SetOptions.   *      previous call to Tk_SetOptions.
1415   *   *
1416   * Results:   * Results:
1417   *      None.   *      None.
1418   *   *
1419   * Side effects:   * Side effects:
1420   *      Storage and system resources are freed.   *      Storage and system resources are freed.
1421   *   *
1422   *--------------------------------------------------------------   *--------------------------------------------------------------
1423   */   */
1424    
1425  void  void
1426  Tk_FreeSavedOptions(savePtr)  Tk_FreeSavedOptions(savePtr)
1427      Tk_SavedOptions *savePtr;   /* Contains options saved in a previous      Tk_SavedOptions *savePtr;   /* Contains options saved in a previous
1428                                   * call to Tk_SetOptions. */                                   * call to Tk_SetOptions. */
1429  {  {
1430      int count;      int count;
1431      Tk_SavedOption *savedOptionPtr;      Tk_SavedOption *savedOptionPtr;
1432    
1433      if (savePtr->nextPtr != NULL) {      if (savePtr->nextPtr != NULL) {
1434          Tk_FreeSavedOptions(savePtr->nextPtr);          Tk_FreeSavedOptions(savePtr->nextPtr);
1435          ckfree((char *) savePtr->nextPtr);          ckfree((char *) savePtr->nextPtr);
1436      }      }
1437      for (count = savePtr->numItems,      for (count = savePtr->numItems,
1438              savedOptionPtr = &savePtr->items[savePtr->numItems-1];              savedOptionPtr = &savePtr->items[savePtr->numItems-1];
1439              count > 0;  count--, savedOptionPtr--) {              count > 0;  count--, savedOptionPtr--) {
1440          if (savedOptionPtr->optionPtr->flags & OPTION_NEEDS_FREEING) {          if (savedOptionPtr->optionPtr->flags & OPTION_NEEDS_FREEING) {
1441              FreeResources(savedOptionPtr->optionPtr, savedOptionPtr->valuePtr,              FreeResources(savedOptionPtr->optionPtr, savedOptionPtr->valuePtr,
1442                      (char *) &savedOptionPtr->internalForm, savePtr->tkwin);                      (char *) &savedOptionPtr->internalForm, savePtr->tkwin);
1443          }          }
1444          if (savedOptionPtr->valuePtr != NULL) {          if (savedOptionPtr->valuePtr != NULL) {
1445              Tcl_DecrRefCount(savedOptionPtr->valuePtr);              Tcl_DecrRefCount(savedOptionPtr->valuePtr);
1446          }          }
1447      }      }
1448  }  }
1449    
1450  /*  /*
1451   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1452   *   *
1453   * Tk_FreeConfigOptions --   * Tk_FreeConfigOptions --
1454   *   *
1455   *      Free all resources associated with configuration options.   *      Free all resources associated with configuration options.
1456   *   *
1457   * Results:   * Results:
1458   *      None.   *      None.
1459   *   *
1460   * Side effects:   * Side effects:
1461   *      All of the Tcl_Obj's in recordPtr that are controlled by   *      All of the Tcl_Obj's in recordPtr that are controlled by
1462   *      configuration options in optionTable are freed.   *      configuration options in optionTable are freed.
1463   *   *
1464   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1465   */   */
1466    
1467          /* ARGSUSED */          /* ARGSUSED */
1468  void  void
1469  Tk_FreeConfigOptions(recordPtr, optionTable, tkwin)  Tk_FreeConfigOptions(recordPtr, optionTable, tkwin)
1470      char *recordPtr;            /* Record whose fields contain current      char *recordPtr;            /* Record whose fields contain current
1471                                   * values for options. */                                   * values for options. */
1472      Tk_OptionTable optionTable; /* Describes legal options. */      Tk_OptionTable optionTable; /* Describes legal options. */
1473      Tk_Window tkwin;            /* Window associated with recordPtr; needed      Tk_Window tkwin;            /* Window associated with recordPtr; needed
1474                                   * for freeing some options. */                                   * for freeing some options. */
1475  {  {
1476      OptionTable *tablePtr;      OptionTable *tablePtr;
1477      Option *optionPtr;      Option *optionPtr;
1478      int count;      int count;
1479      Tcl_Obj **oldPtrPtr, *oldPtr;      Tcl_Obj **oldPtrPtr, *oldPtr;
1480      char *oldInternalPtr;      char *oldInternalPtr;
1481      CONST Tk_OptionSpec *specPtr;      CONST Tk_OptionSpec *specPtr;
1482    
1483      for (tablePtr = (OptionTable *) optionTable; tablePtr != NULL;      for (tablePtr = (OptionTable *) optionTable; tablePtr != NULL;
1484              tablePtr = tablePtr->nextPtr) {              tablePtr = tablePtr->nextPtr) {
1485          for (optionPtr = tablePtr->options, count = tablePtr->numOptions;          for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
1486                  count > 0; optionPtr++, count--) {                  count > 0; optionPtr++, count--) {
1487              specPtr = optionPtr->specPtr;              specPtr = optionPtr->specPtr;
1488              if (specPtr->type == TK_OPTION_SYNONYM) {              if (specPtr->type == TK_OPTION_SYNONYM) {
1489                  continue;                  continue;
1490              }              }
1491              if (specPtr->objOffset >= 0) {              if (specPtr->objOffset >= 0) {
1492                  oldPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);                  oldPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
1493                  oldPtr = *oldPtrPtr;                  oldPtr = *oldPtrPtr;
1494                  *oldPtrPtr = NULL;                  *oldPtrPtr = NULL;
1495              } else {              } else {
1496                  oldPtr = NULL;                  oldPtr = NULL;
1497              }              }
1498              if (specPtr->internalOffset >= 0) {              if (specPtr->internalOffset >= 0) {
1499                  oldInternalPtr = recordPtr + specPtr->internalOffset;                  oldInternalPtr = recordPtr + specPtr->internalOffset;
1500              } else {              } else {
1501                  oldInternalPtr = NULL;                  oldInternalPtr = NULL;
1502              }              }
1503              if (optionPtr->flags & OPTION_NEEDS_FREEING) {              if (optionPtr->flags & OPTION_NEEDS_FREEING) {
1504                  FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);                  FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);
1505              }              }
1506              if (oldPtr != NULL) {              if (oldPtr != NULL) {
1507                  Tcl_DecrRefCount(oldPtr);                  Tcl_DecrRefCount(oldPtr);
1508              }              }
1509          }          }
1510      }      }
1511  }  }
1512    
1513  /*  /*
1514   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1515   *   *
1516   * FreeResources --   * FreeResources --
1517   *   *
1518   *      Free system resources associated with a configuration option,   *      Free system resources associated with a configuration option,
1519   *      such as colors or fonts.   *      such as colors or fonts.
1520   *   *
1521   * Results:   * Results:
1522   *      None.   *      None.
1523   *   *
1524   * Side effects:   * Side effects:
1525   *      Any system resources associated with objPtr are released.  However,   *      Any system resources associated with objPtr are released.  However,
1526   *      objPtr itself is not freed.   *      objPtr itself is not freed.
1527   *   *
1528   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1529   */   */
1530    
1531  static void  static void
1532  FreeResources(optionPtr, objPtr, internalPtr, tkwin)  FreeResources(optionPtr, objPtr, internalPtr, tkwin)
1533      Option *optionPtr;          /* Description of the configuration option. */      Option *optionPtr;          /* Description of the configuration option. */
1534      Tcl_Obj *objPtr;            /* The current value of the option, specified      Tcl_Obj *objPtr;            /* The current value of the option, specified
1535                                   * as an object. */                                   * as an object. */
1536      char *internalPtr;          /* A pointer to an internal representation for      char *internalPtr;          /* A pointer to an internal representation for
1537                                   * the option's value, such as an int or                                   * the option's value, such as an int or
1538                                   * (XColor *).  Only valid if                                   * (XColor *).  Only valid if
1539                                   * optionPtr->specPtr->internalOffset >= 0. */                                   * optionPtr->specPtr->internalOffset >= 0. */
1540      Tk_Window tkwin;            /* The window in which this option is used. */      Tk_Window tkwin;            /* The window in which this option is used. */
1541  {  {
1542      int internalFormExists;      int internalFormExists;
1543    
1544      /*      /*
1545       * If there exists an internal form for the value, use it to free       * If there exists an internal form for the value, use it to free
1546       * resources (also zero out the internal form).  If there is no       * resources (also zero out the internal form).  If there is no
1547       * internal form, then use the object form.       * internal form, then use the object form.
1548       */       */
1549    
1550      internalFormExists = optionPtr->specPtr->internalOffset >= 0;      internalFormExists = optionPtr->specPtr->internalOffset >= 0;
1551      switch (optionPtr->specPtr->type) {      switch (optionPtr->specPtr->type) {
1552          case TK_OPTION_STRING:          case TK_OPTION_STRING:
1553              if (internalFormExists) {              if (internalFormExists) {
1554                  if (*((char **) internalPtr) != NULL) {                  if (*((char **) internalPtr) != NULL) {
1555                      ckfree(*((char **) internalPtr));                      ckfree(*((char **) internalPtr));
1556                      *((char **) internalPtr) = NULL;                      *((char **) internalPtr) = NULL;
1557                  }                  }
1558              }              }
1559              break;              break;
1560          case TK_OPTION_COLOR:          case TK_OPTION_COLOR:
1561              if (internalFormExists) {              if (internalFormExists) {
1562                  if (*((XColor **) internalPtr) != NULL) {                  if (*((XColor **) internalPtr) != NULL) {
1563                      Tk_FreeColor(*((XColor **) internalPtr));                      Tk_FreeColor(*((XColor **) internalPtr));
1564                      *((XColor **) internalPtr) = NULL;                      *((XColor **) internalPtr) = NULL;
1565                  }                  }
1566              } else if (objPtr != NULL) {              } else if (objPtr != NULL) {
1567                  Tk_FreeColorFromObj(tkwin, objPtr);                  Tk_FreeColorFromObj(tkwin, objPtr);
1568              }              }
1569              break;              break;
1570          case TK_OPTION_FONT:          case TK_OPTION_FONT:
1571              if (internalFormExists) {              if (internalFormExists) {
1572                  Tk_FreeFont(*((Tk_Font *) internalPtr));                  Tk_FreeFont(*((Tk_Font *) internalPtr));
1573                  *((Tk_Font *) internalPtr) = NULL;                  *((Tk_Font *) internalPtr) = NULL;
1574              } else if (objPtr != NULL) {              } else if (objPtr != NULL) {
1575                  Tk_FreeFontFromObj(tkwin, objPtr);                  Tk_FreeFontFromObj(tkwin, objPtr);
1576              }              }
1577              break;              break;
1578          case TK_OPTION_BITMAP:          case TK_OPTION_BITMAP:
1579              if (internalFormExists) {              if (internalFormExists) {
1580                  if (*((Pixmap *) internalPtr) != None) {                  if (*((Pixmap *) internalPtr) != None) {
1581                      Tk_FreeBitmap(Tk_Display(tkwin), *((Pixmap *) internalPtr));                      Tk_FreeBitmap(Tk_Display(tkwin), *((Pixmap *) internalPtr));
1582                      *((Pixmap *) internalPtr) = None;                      *((Pixmap *) internalPtr) = None;
1583                  }                  }
1584              } else if (objPtr != NULL) {              } else if (objPtr != NULL) {
1585                  Tk_FreeBitmapFromObj(tkwin, objPtr);                  Tk_FreeBitmapFromObj(tkwin, objPtr);
1586              }              }
1587              break;              break;
1588          case TK_OPTION_BORDER:          case TK_OPTION_BORDER:
1589              if (internalFormExists) {              if (internalFormExists) {
1590                  if (*((Tk_3DBorder *) internalPtr) != NULL) {                  if (*((Tk_3DBorder *) internalPtr) != NULL) {
1591                      Tk_Free3DBorder(*((Tk_3DBorder *) internalPtr));                      Tk_Free3DBorder(*((Tk_3DBorder *) internalPtr));
1592                      *((Tk_3DBorder *) internalPtr) = NULL;                      *((Tk_3DBorder *) internalPtr) = NULL;
1593                  }                  }
1594              } else if (objPtr != NULL) {              } else if (objPtr != NULL) {
1595                  Tk_Free3DBorderFromObj(tkwin, objPtr);                  Tk_Free3DBorderFromObj(tkwin, objPtr);
1596              }              }
1597              break;              break;
1598          case TK_OPTION_CURSOR:          case TK_OPTION_CURSOR:
1599              if (internalFormExists) {              if (internalFormExists) {
1600                  if (*((Tk_Cursor *) internalPtr) != None) {                  if (*((Tk_Cursor *) internalPtr) != None) {
1601                      Tk_FreeCursor(Tk_Display(tkwin),                      Tk_FreeCursor(Tk_Display(tkwin),
1602                              *((Tk_Cursor *) internalPtr));                              *((Tk_Cursor *) internalPtr));
1603                      *((Tk_Cursor *) internalPtr) = None;                      *((Tk_Cursor *) internalPtr) = None;
1604                  }                  }
1605              } else if (objPtr != NULL) {              } else if (objPtr != NULL) {
1606                  Tk_FreeCursorFromObj(tkwin, objPtr);                  Tk_FreeCursorFromObj(tkwin, objPtr);
1607              }              }
1608              break;              break;
1609          default:          default:
1610              break;              break;
1611      }      }
1612  }  }
1613    
1614  /*  /*
1615   *--------------------------------------------------------------   *--------------------------------------------------------------
1616   *   *
1617   * Tk_GetOptionInfo --   * Tk_GetOptionInfo --
1618   *   *
1619   *      Returns a list object containing complete information about   *      Returns a list object containing complete information about
1620   *      either a single option or all the configuration options in a   *      either a single option or all the configuration options in a
1621   *      table.   *      table.
1622   *   *
1623   * Results:   * Results:
1624   *      This procedure normally returns a pointer to an object.   *      This procedure normally returns a pointer to an object.
1625   *      If namePtr isn't NULL, then the result object is a list with   *      If namePtr isn't NULL, then the result object is a list with
1626   *      five elements: the option's name, its database name, database   *      five elements: the option's name, its database name, database
1627   *      class, default value, and current value.  If the option is a   *      class, default value, and current value.  If the option is a
1628   *      synonym then the list will contain only two values: the option   *      synonym then the list will contain only two values: the option
1629   *      name and the name of the option it refers to.  If namePtr is   *      name and the name of the option it refers to.  If namePtr is
1630   *      NULL, then information is returned for every option in the   *      NULL, then information is returned for every option in the
1631   *      option table: the result will have one sub-list (in the form   *      option table: the result will have one sub-list (in the form
1632   *      described above) for each option in the table.  If an error   *      described above) for each option in the table.  If an error
1633   *      occurs (e.g. because namePtr isn't valid) then NULL is returned   *      occurs (e.g. because namePtr isn't valid) then NULL is returned
1634   *      and an error message will be left in interp's result unless   *      and an error message will be left in interp's result unless
1635   *      interp is NULL.   *      interp is NULL.
1636   *   *
1637   * Side effects:   * Side effects:
1638   *      None.   *      None.
1639   *   *
1640   *--------------------------------------------------------------   *--------------------------------------------------------------
1641   */   */
1642    
1643  Tcl_Obj *  Tcl_Obj *
1644  Tk_GetOptionInfo(interp, recordPtr, optionTable, namePtr, tkwin)  Tk_GetOptionInfo(interp, recordPtr, optionTable, namePtr, tkwin)
1645      Tcl_Interp *interp;         /* Interpreter for error reporting.  If      Tcl_Interp *interp;         /* Interpreter for error reporting.  If
1646                                   * NULL, then no error message is created. */                                   * NULL, then no error message is created. */
1647      char *recordPtr;            /* Record whose fields contain current      char *recordPtr;            /* Record whose fields contain current
1648                                   * values for options. */                                   * values for options. */
1649      Tk_OptionTable optionTable; /* Describes all the legal options. */      Tk_OptionTable optionTable; /* Describes all the legal options. */
1650      Tcl_Obj *namePtr;           /* If non-NULL, the string value selects      Tcl_Obj *namePtr;           /* If non-NULL, the string value selects
1651                                   * a single option whose info is to be                                   * a single option whose info is to be
1652                                   * returned.  Otherwise info is returned for                                   * returned.  Otherwise info is returned for
1653                                   * all options in optionTable. */                                   * all options in optionTable. */
1654      Tk_Window tkwin;            /* Window associated with recordPtr; needed      Tk_Window tkwin;            /* Window associated with recordPtr; needed
1655                                   * to compute correct default value for some                                   * to compute correct default value for some
1656                                   * options. */                                   * options. */
1657  {  {
1658      Tcl_Obj *resultPtr;      Tcl_Obj *resultPtr;
1659      OptionTable *tablePtr = (OptionTable *) optionTable;      OptionTable *tablePtr = (OptionTable *) optionTable;
1660      Option *optionPtr;      Option *optionPtr;
1661      int count;      int count;
1662    
1663      /*      /*
1664       * If information is only wanted for a single configuration       * If information is only wanted for a single configuration
1665       * spec, then handle that one spec specially.       * spec, then handle that one spec specially.
1666       */       */
1667    
1668      if (namePtr != NULL) {      if (namePtr != NULL) {
1669          optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);          optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);
1670          if (optionPtr == NULL) {          if (optionPtr == NULL) {
1671              return (Tcl_Obj *) NULL;              return (Tcl_Obj *) NULL;
1672          }          }
1673          if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {          if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
1674              optionPtr = optionPtr->extra.synonymPtr;              optionPtr = optionPtr->extra.synonymPtr;
1675          }          }
1676          return GetConfigList(recordPtr, optionPtr, tkwin);          return GetConfigList(recordPtr, optionPtr, tkwin);
1677      }      }
1678    
1679      /*      /*
1680       * Loop through all the specs, creating a big list with all       * Loop through all the specs, creating a big list with all
1681       * their information.       * their information.
1682       */       */
1683    
1684      resultPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);      resultPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
1685      for (; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {      for (; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {
1686          for (optionPtr = tablePtr->options, count = tablePtr->numOptions;          for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
1687                  count > 0; optionPtr++, count--) {                  count > 0; optionPtr++, count--) {
1688              Tcl_ListObjAppendElement(interp, resultPtr,              Tcl_ListObjAppendElement(interp, resultPtr,
1689                      GetConfigList(recordPtr, optionPtr, tkwin));                      GetConfigList(recordPtr, optionPtr, tkwin));
1690          }          }
1691      }      }
1692      return resultPtr;      return resultPtr;
1693  }  }
1694    
1695  /*  /*
1696   *--------------------------------------------------------------   *--------------------------------------------------------------
1697   *   *
1698   * GetConfigList --   * GetConfigList --
1699   *   *
1700   *      Create a valid Tcl list holding the configuration information   *      Create a valid Tcl list holding the configuration information
1701   *      for a single configuration option.   *      for a single configuration option.
1702   *   *
1703   * Results:   * Results:
1704   *      A Tcl list, dynamically allocated.  The caller is expected to   *      A Tcl list, dynamically allocated.  The caller is expected to
1705   *      arrange for this list to be freed eventually.   *      arrange for this list to be freed eventually.
1706   *   *
1707   * Side effects:   * Side effects:
1708   *      Memory is allocated.   *      Memory is allocated.
1709   *   *
1710   *--------------------------------------------------------------   *--------------------------------------------------------------
1711   */   */
1712    
1713  static Tcl_Obj *  static Tcl_Obj *
1714  GetConfigList(recordPtr, optionPtr, tkwin)  GetConfigList(recordPtr, optionPtr, tkwin)
1715      char *recordPtr;            /* Pointer to record holding current      char *recordPtr;            /* Pointer to record holding current
1716                                   * values of configuration options. */                                   * values of configuration options. */
1717      Option *optionPtr;          /* Pointer to information describing a      Option *optionPtr;          /* Pointer to information describing a
1718                                   * particular option. */                                   * particular option. */
1719      Tk_Window tkwin;            /* Window corresponding to recordPtr. */      Tk_Window tkwin;            /* Window corresponding to recordPtr. */
1720  {  {
1721      Tcl_Obj *listPtr, *elementPtr;      Tcl_Obj *listPtr, *elementPtr;
1722    
1723      listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);      listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
1724      Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr,      Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr,
1725              Tcl_NewStringObj(optionPtr->specPtr->optionName, -1));              Tcl_NewStringObj(optionPtr->specPtr->optionName, -1));
1726    
1727      if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {      if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
1728          elementPtr = Tcl_NewStringObj(          elementPtr = Tcl_NewStringObj(
1729                  optionPtr->extra.synonymPtr->specPtr->optionName, -1);                  optionPtr->extra.synonymPtr->specPtr->optionName, -1);
1730          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
1731      } else {      } else {
1732          if (optionPtr->dbNameUID == NULL) {          if (optionPtr->dbNameUID == NULL) {
1733              elementPtr = Tcl_NewObj();              elementPtr = Tcl_NewObj();
1734          } else {          } else {
1735              elementPtr = Tcl_NewStringObj(optionPtr->dbNameUID, -1);              elementPtr = Tcl_NewStringObj(optionPtr->dbNameUID, -1);
1736          }          }
1737          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
1738    
1739          if (optionPtr->dbClassUID == NULL) {          if (optionPtr->dbClassUID == NULL) {
1740              elementPtr = Tcl_NewObj();              elementPtr = Tcl_NewObj();
1741          } else {          } else {
1742              elementPtr = Tcl_NewStringObj(optionPtr->dbClassUID, -1);              elementPtr = Tcl_NewStringObj(optionPtr->dbClassUID, -1);
1743          }          }
1744          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
1745    
1746          if ((tkwin != NULL) && ((optionPtr->specPtr->type == TK_OPTION_COLOR)          if ((tkwin != NULL) && ((optionPtr->specPtr->type == TK_OPTION_COLOR)
1747                  || (optionPtr->specPtr->type == TK_OPTION_BORDER))                  || (optionPtr->specPtr->type == TK_OPTION_BORDER))
1748                  && (Tk_Depth(tkwin) <= 1)                  && (Tk_Depth(tkwin) <= 1)
1749                  && (optionPtr->extra.monoColorPtr != NULL)) {                  && (optionPtr->extra.monoColorPtr != NULL)) {
1750              elementPtr = optionPtr->extra.monoColorPtr;              elementPtr = optionPtr->extra.monoColorPtr;
1751          } else if (optionPtr->defaultPtr != NULL) {          } else if (optionPtr->defaultPtr != NULL) {
1752              elementPtr = optionPtr->defaultPtr;              elementPtr = optionPtr->defaultPtr;
1753          } else {          } else {
1754              elementPtr = Tcl_NewObj();              elementPtr = Tcl_NewObj();
1755          }          }
1756          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
1757    
1758          if (optionPtr->specPtr->objOffset >= 0) {          if (optionPtr->specPtr->objOffset >= 0) {
1759              elementPtr = *((Tcl_Obj **) (recordPtr              elementPtr = *((Tcl_Obj **) (recordPtr
1760                      + optionPtr->specPtr->objOffset));                      + optionPtr->specPtr->objOffset));
1761              if (elementPtr == NULL) {              if (elementPtr == NULL) {
1762                  elementPtr = Tcl_NewObj();                  elementPtr = Tcl_NewObj();
1763              }              }
1764          } else {          } else {
1765              elementPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);              elementPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);
1766          }          }
1767          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);          Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
1768      }      }
1769      return listPtr;      return listPtr;
1770  }  }
1771    
1772  /*  /*
1773   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1774   *   *
1775   * GetObjectForOption --   * GetObjectForOption --
1776   *   *
1777   *      This procedure is called to create an object that contains the   *      This procedure is called to create an object that contains the
1778   *      value for an option.  It is invoked by GetConfigList and   *      value for an option.  It is invoked by GetConfigList and
1779   *      Tk_GetOptionValue when only the internal form of an option is   *      Tk_GetOptionValue when only the internal form of an option is
1780   *      stored in the record.   *      stored in the record.
1781   *   *
1782   * Results:   * Results:
1783   *      The return value is a pointer to a Tcl object.  The caller   *      The return value is a pointer to a Tcl object.  The caller
1784   *      must call Tcl_IncrRefCount on this object to preserve it.   *      must call Tcl_IncrRefCount on this object to preserve it.
1785   *   *
1786   * Side effects:   * Side effects:
1787   *      None.   *      None.
1788   *   *
1789   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1790   */   */
1791    
1792  static Tcl_Obj *  static Tcl_Obj *
1793  GetObjectForOption(recordPtr, optionPtr, tkwin)  GetObjectForOption(recordPtr, optionPtr, tkwin)
1794      char *recordPtr;            /* Pointer to record holding current      char *recordPtr;            /* Pointer to record holding current
1795                                   * values of configuration options. */                                   * values of configuration options. */
1796      Option *optionPtr;          /* Pointer to information describing an      Option *optionPtr;          /* Pointer to information describing an
1797                                   * option whose internal value is stored                                   * option whose internal value is stored
1798                                   * in *recordPtr. */                                   * in *recordPtr. */
1799      Tk_Window tkwin;            /* Window corresponding to recordPtr. */      Tk_Window tkwin;            /* Window corresponding to recordPtr. */
1800  {  {
1801      Tcl_Obj *objPtr;      Tcl_Obj *objPtr;
1802      char *internalPtr;          /* Points to internal value of option in      char *internalPtr;          /* Points to internal value of option in
1803                                   * record. */                                   * record. */
1804    
1805      internalPtr = recordPtr + optionPtr->specPtr->internalOffset;      internalPtr = recordPtr + optionPtr->specPtr->internalOffset;
1806      objPtr = NULL;      objPtr = NULL;
1807      switch (optionPtr->specPtr->type) {      switch (optionPtr->specPtr->type) {
1808          case TK_OPTION_BOOLEAN: {          case TK_OPTION_BOOLEAN: {
1809              objPtr = Tcl_NewIntObj(*((int *) internalPtr));              objPtr = Tcl_NewIntObj(*((int *) internalPtr));
1810              break;              break;
1811          }          }
1812          case TK_OPTION_INT: {          case TK_OPTION_INT: {
1813              objPtr = Tcl_NewIntObj(*((int *) internalPtr));              objPtr = Tcl_NewIntObj(*((int *) internalPtr));
1814              break;              break;
1815          }          }
1816          case TK_OPTION_DOUBLE: {          case TK_OPTION_DOUBLE: {
1817              objPtr = Tcl_NewDoubleObj(*((double *) internalPtr));              objPtr = Tcl_NewDoubleObj(*((double *) internalPtr));
1818              break;              break;
1819          }          }
1820          case TK_OPTION_STRING: {          case TK_OPTION_STRING: {
1821              objPtr = Tcl_NewStringObj(*((char **) internalPtr), -1);              objPtr = Tcl_NewStringObj(*((char **) internalPtr), -1);
1822              break;              break;
1823          }          }
1824          case TK_OPTION_STRING_TABLE: {          case TK_OPTION_STRING_TABLE: {
1825              objPtr = Tcl_NewStringObj(              objPtr = Tcl_NewStringObj(
1826                      ((char **) optionPtr->specPtr->clientData)[                      ((char **) optionPtr->specPtr->clientData)[
1827                      *((int *) internalPtr)], -1);                      *((int *) internalPtr)], -1);
1828              break;              break;
1829          }          }
1830          case TK_OPTION_COLOR: {          case TK_OPTION_COLOR: {
1831              XColor *colorPtr = *((XColor **) internalPtr);              XColor *colorPtr = *((XColor **) internalPtr);
1832              if (colorPtr != NULL) {              if (colorPtr != NULL) {
1833                  objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1);                  objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1);
1834              }              }
1835              break;              break;
1836          }          }
1837          case TK_OPTION_FONT: {          case TK_OPTION_FONT: {
1838              Tk_Font tkfont = *((Tk_Font *) internalPtr);              Tk_Font tkfont = *((Tk_Font *) internalPtr);
1839              if (tkfont != NULL) {              if (tkfont != NULL) {
1840                  objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1);                  objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1);
1841              }              }
1842              break;              break;
1843          }          }
1844          case TK_OPTION_BITMAP: {          case TK_OPTION_BITMAP: {
1845              Pixmap pixmap = *((Pixmap *) internalPtr);              Pixmap pixmap = *((Pixmap *) internalPtr);
1846              if (pixmap != None) {              if (pixmap != None) {
1847                  objPtr = Tcl_NewStringObj(Tk_NameOfBitmap(Tk_Display(tkwin),                  objPtr = Tcl_NewStringObj(Tk_NameOfBitmap(Tk_Display(tkwin),
1848                          pixmap), -1);                          pixmap), -1);
1849              }              }
1850              break;              break;
1851          }          }
1852          case TK_OPTION_BORDER: {          case TK_OPTION_BORDER: {
1853              Tk_3DBorder border = *((Tk_3DBorder *) internalPtr);              Tk_3DBorder border = *((Tk_3DBorder *) internalPtr);
1854              if (border != NULL) {              if (border != NULL) {
1855                  objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1);                  objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1);
1856              }              }
1857              break;              break;
1858          }          }
1859          case TK_OPTION_RELIEF: {          case TK_OPTION_RELIEF: {
1860              objPtr = Tcl_NewStringObj(Tk_NameOfRelief(              objPtr = Tcl_NewStringObj(Tk_NameOfRelief(
1861                      *((int *) internalPtr)), -1);                      *((int *) internalPtr)), -1);
1862              break;              break;
1863          }          }
1864          case TK_OPTION_CURSOR: {          case TK_OPTION_CURSOR: {
1865              Tk_Cursor cursor = *((Tk_Cursor *) internalPtr);              Tk_Cursor cursor = *((Tk_Cursor *) internalPtr);
1866              if (cursor != None) {              if (cursor != None) {
1867                  objPtr = Tcl_NewStringObj(                  objPtr = Tcl_NewStringObj(
1868                          Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1);                          Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1);
1869              }              }
1870              break;              break;
1871          }          }
1872          case TK_OPTION_JUSTIFY: {          case TK_OPTION_JUSTIFY: {
1873              objPtr = Tcl_NewStringObj(Tk_NameOfJustify(              objPtr = Tcl_NewStringObj(Tk_NameOfJustify(
1874                      *((Tk_Justify *) internalPtr)), -1);                      *((Tk_Justify *) internalPtr)), -1);
1875              break;              break;
1876          }          }
1877          case TK_OPTION_ANCHOR: {          case TK_OPTION_ANCHOR: {
1878              objPtr = Tcl_NewStringObj(Tk_NameOfAnchor(              objPtr = Tcl_NewStringObj(Tk_NameOfAnchor(
1879                      *((Tk_Anchor *) internalPtr)), -1);                      *((Tk_Anchor *) internalPtr)), -1);
1880              break;              break;
1881          }          }
1882          case TK_OPTION_PIXELS: {          case TK_OPTION_PIXELS: {
1883              objPtr = Tcl_NewIntObj(*((int *) internalPtr));              objPtr = Tcl_NewIntObj(*((int *) internalPtr));
1884              break;              break;
1885          }          }
1886          case TK_OPTION_WINDOW: {          case TK_OPTION_WINDOW: {
1887              Tk_Window tkwin = *((Tk_Window *) internalPtr);              Tk_Window tkwin = *((Tk_Window *) internalPtr);
1888              if (tkwin != NULL) {              if (tkwin != NULL) {
1889                  objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);                  objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);
1890              }              }
1891              break;              break;
1892          }          }
1893          default: {          default: {
1894              panic("bad option type in GetObjectForOption");              panic("bad option type in GetObjectForOption");
1895          }          }
1896      }      }
1897      if (objPtr == NULL) {      if (objPtr == NULL) {
1898          objPtr = Tcl_NewObj();          objPtr = Tcl_NewObj();
1899      }      }
1900      return objPtr;      return objPtr;
1901  }  }
1902    
1903  /*  /*
1904   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1905   *   *
1906   * Tk_GetOptionValue --   * Tk_GetOptionValue --
1907   *   *
1908   *      This procedure returns the current value of a configuration   *      This procedure returns the current value of a configuration
1909   *      option.   *      option.
1910   *   *
1911   * Results:   * Results:
1912   *      The return value is the object holding the current value of   *      The return value is the object holding the current value of
1913   *      the option given by namePtr.  If no such option exists, then   *      the option given by namePtr.  If no such option exists, then
1914   *      the return value is NULL and an error message is left in   *      the return value is NULL and an error message is left in
1915   *      interp's result (if interp isn't NULL).   *      interp's result (if interp isn't NULL).
1916   *   *
1917   * Side effects:   * Side effects:
1918   *      None.   *      None.
1919   *   *
1920   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1921   */   */
1922    
1923  Tcl_Obj *  Tcl_Obj *
1924  Tk_GetOptionValue(interp, recordPtr, optionTable, namePtr, tkwin)  Tk_GetOptionValue(interp, recordPtr, optionTable, namePtr, tkwin)
1925      Tcl_Interp *interp;         /* Interpreter for error reporting.  If      Tcl_Interp *interp;         /* Interpreter for error reporting.  If
1926                                   * NULL then no messages are provided for                                   * NULL then no messages are provided for
1927                                   * errors. */                                   * errors. */
1928      char *recordPtr;            /* Record whose fields contain current      char *recordPtr;            /* Record whose fields contain current
1929                                   * values for options. */                                   * values for options. */
1930      Tk_OptionTable optionTable; /* Describes legal options. */      Tk_OptionTable optionTable; /* Describes legal options. */
1931      Tcl_Obj *namePtr;           /* Gives the command-line name for the      Tcl_Obj *namePtr;           /* Gives the command-line name for the
1932                                   * option whose value is to be returned. */                                   * option whose value is to be returned. */
1933      Tk_Window tkwin;            /* Window corresponding to recordPtr. */      Tk_Window tkwin;            /* Window corresponding to recordPtr. */
1934  {  {
1935      OptionTable *tablePtr = (OptionTable *) optionTable;      OptionTable *tablePtr = (OptionTable *) optionTable;
1936      Option *optionPtr;      Option *optionPtr;
1937      Tcl_Obj *resultPtr;      Tcl_Obj *resultPtr;
1938    
1939      optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);      optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);
1940      if (optionPtr == NULL) {      if (optionPtr == NULL) {
1941          return NULL;          return NULL;
1942      }      }
1943      if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {      if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
1944          optionPtr = optionPtr->extra.synonymPtr;          optionPtr = optionPtr->extra.synonymPtr;
1945      }      }
1946      if (optionPtr->specPtr->objOffset >= 0) {      if (optionPtr->specPtr->objOffset >= 0) {
1947          resultPtr = *((Tcl_Obj **) (recordPtr + optionPtr->specPtr->objOffset));          resultPtr = *((Tcl_Obj **) (recordPtr + optionPtr->specPtr->objOffset));
1948          if (resultPtr == NULL) {          if (resultPtr == NULL) {
1949              /*              /*
1950               * This option has a null value and is represented by a null               * This option has a null value and is represented by a null
1951               * object pointer.  We can't return the null pointer, since that               * object pointer.  We can't return the null pointer, since that
1952               * would indicate an error.  Instead, return a new empty object.               * would indicate an error.  Instead, return a new empty object.
1953               */               */
1954            
1955              resultPtr = Tcl_NewObj();              resultPtr = Tcl_NewObj();
1956          }          }
1957      } else {      } else {
1958          resultPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);          resultPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);
1959      }      }
1960      return resultPtr;      return resultPtr;
1961  }  }
1962    
1963  /*  /*
1964   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1965   *   *
1966   * TkDebugConfig --   * TkDebugConfig --
1967   *   *
1968   *      This is a debugging procedure that returns information about   *      This is a debugging procedure that returns information about
1969   *      one of the configuration tables that currently exists for an   *      one of the configuration tables that currently exists for an
1970   *      interpreter.   *      interpreter.
1971   *   *
1972   * Results:   * Results:
1973   *      If the specified table exists in the given interpreter, then a   *      If the specified table exists in the given interpreter, then a
1974   *      list is returned describing the table and any other tables that   *      list is returned describing the table and any other tables that
1975   *      it chains to: for each table there will be three list elements   *      it chains to: for each table there will be three list elements
1976   *      giving the reference count for the table, the number of elements   *      giving the reference count for the table, the number of elements
1977   *      in the table, and the command-line name for the first option   *      in the table, and the command-line name for the first option
1978   *      in the table.  If the table doesn't exist in the interpreter   *      in the table.  If the table doesn't exist in the interpreter
1979   *      then an empty object is returned.  The reference count for the   *      then an empty object is returned.  The reference count for the
1980   *      returned object is 0.   *      returned object is 0.
1981   *   *
1982   * Side effects:   * Side effects:
1983   *      None.   *      None.
1984   *   *
1985   *----------------------------------------------------------------------   *----------------------------------------------------------------------
1986   */   */
1987    
1988  Tcl_Obj *  Tcl_Obj *
1989  TkDebugConfig(interp, table)  TkDebugConfig(interp, table)
1990      Tcl_Interp *interp;                 /* Interpreter in which the table is      Tcl_Interp *interp;                 /* Interpreter in which the table is
1991                                           * defined. */                                           * defined. */
1992      Tk_OptionTable table;               /* Table about which information is to      Tk_OptionTable table;               /* Table about which information is to
1993                                           * be returned.  May not necessarily                                           * be returned.  May not necessarily
1994                                           * exist in the interpreter anymore. */                                           * exist in the interpreter anymore. */
1995  {  {
1996      OptionTable *tablePtr = (OptionTable *) table;      OptionTable *tablePtr = (OptionTable *) table;
1997      Tcl_HashTable *hashTablePtr;      Tcl_HashTable *hashTablePtr;
1998      Tcl_HashEntry *hashEntryPtr;      Tcl_HashEntry *hashEntryPtr;
1999      Tcl_HashSearch search;      Tcl_HashSearch search;
2000      Tcl_Obj *objPtr;      Tcl_Obj *objPtr;
2001    
2002      objPtr = Tcl_NewObj();      objPtr = Tcl_NewObj();
2003      hashTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, OPTION_HASH_KEY,      hashTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, OPTION_HASH_KEY,
2004              NULL);              NULL);
2005      if (hashTablePtr == NULL) {      if (hashTablePtr == NULL) {
2006          return objPtr;          return objPtr;
2007      }      }
2008    
2009      /*      /*
2010       * Scan all the tables for this interpreter to make sure that the       * Scan all the tables for this interpreter to make sure that the
2011       * one we want still is valid.       * one we want still is valid.
2012       */       */
2013    
2014      for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search);      for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search);
2015              hashEntryPtr != NULL;              hashEntryPtr != NULL;
2016              hashEntryPtr = Tcl_NextHashEntry(&search)) {              hashEntryPtr = Tcl_NextHashEntry(&search)) {
2017          if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) {          if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) {
2018              for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {              for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {
2019                  Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,                  Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
2020                          Tcl_NewIntObj(tablePtr->refCount));                          Tcl_NewIntObj(tablePtr->refCount));
2021                  Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,                  Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
2022                          Tcl_NewIntObj(tablePtr->numOptions));                          Tcl_NewIntObj(tablePtr->numOptions));
2023                  Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,                  Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
2024                          Tcl_NewStringObj(                          Tcl_NewStringObj(
2025                                  tablePtr->options[0].specPtr->optionName,                                  tablePtr->options[0].specPtr->optionName,
2026                          -1));                          -1));
2027              }              }
2028              break;              break;
2029          }          }
2030      }      }
2031      return objPtr;      return objPtr;
2032  }  }
2033    
2034  /* End of tkconfig.c */  /* End of tkconfig.c */

Legend:
Removed from v.69  
changed lines
  Added in v.98

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25