tkStyle.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:44k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkStyle.c --
  3.  *
  4.  * This file implements the widget styles and themes support.
  5.  *
  6.  * Copyright (c) 1990-1993 The Regents of the University of California.
  7.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkStyle.c,v 1.3 2002/08/05 04:30:40 dgp Exp $
  13.  */
  14. #include "tkInt.h"
  15. /*
  16.  * The following structure is used to cache widget option specs matching an 
  17.  * element's required options defined by Tk_ElementOptionSpecs. It also holds
  18.  * information behind Tk_StyledElement opaque tokens.
  19.  */
  20. typedef struct StyledWidgetSpec {
  21.     struct StyledElement *elementPtr; /* Pointer to the element holding this
  22.  * structure. */
  23.     Tk_OptionTable optionTable; /* Option table for the widget class 
  24.  * using the element. */
  25.     CONST Tk_OptionSpec **optionsPtr; /* Table of option spec pointers, 
  26.  * matching the option list provided 
  27.  * during element registration. 
  28.  * Malloc'd. */
  29. } StyledWidgetSpec;
  30. /*
  31.  * Elements are declared using static templates. But static
  32.  * information must be completed by dynamic information only
  33.  * accessible at runtime. For each registered element, an instance of
  34.  * the following structure is stored in each style engine and used to
  35.  * cache information about the widget types (identified by their
  36.  * optionTable) that use the given element.
  37.  */
  38. typedef struct StyledElement {
  39.     struct Tk_ElementSpec *specPtr;
  40. /* Filled with template provided during 
  41.  * registration. NULL means no implementation 
  42.  * is available for the current engine. */ 
  43.     int nbWidgetSpecs; /* Size of the array below. Number of distinct 
  44.  * widget classes (actually, distinct option 
  45.  * tables) that used the element so far. */
  46.     StyledWidgetSpec *widgetSpecs;
  47. /* See above for the structure definition.
  48.  * Table grows dynamically as new widgets
  49.  * use the element. Malloc'd. */
  50. } StyledElement;
  51. /*
  52.  * The following structure holds information behind Tk_StyleEngine opaque 
  53.  * tokens.
  54.  */
  55. typedef struct StyleEngine {
  56.     CONST char *name; /* Name of engine. Points to a hash key. */
  57.     StyledElement *elements; /* Table of widget element descriptors. Each 
  58.  * element is indexed by a unique system-wide 
  59.  * ID. Table grows dynamically as new elements 
  60.  * are registered. Malloc'd*/
  61.     struct StyleEngine *parentPtr;
  62. /* Parent engine. Engines may be layered to form
  63.  * a fallback chain, terminated by the default 
  64.  * system engine. */
  65. } StyleEngine;
  66. /*
  67.  * Styles are instances of style engines. The following structure holds 
  68.  * information behind Tk_Style opaque tokens.
  69.  */
  70. typedef struct Style {
  71.     int refCount; /* Number of active uses of this style.
  72.  * If this count is 0, then this Style
  73.  * structure is no longer valid. */
  74.     Tcl_HashEntry *hashPtr; /* Entry in style table for this structure,
  75.  * used when deleting it. */
  76.     CONST char *name; /* Name of style. Points to a hash key. */
  77.     StyleEngine *enginePtr; /* Style engine of which the style is an 
  78.  * instance. */
  79.     ClientData clientData; /* Data provided during registration. */
  80. } Style;
  81. /*
  82.  * Each registered element uses an instance of the following structure. 
  83.  */
  84. typedef struct Element {
  85.     CONST char *name; /* Name of element. Points to a hash key. */
  86.     int id; /* Id of element. */
  87.     int genericId; /* Id of generic element. */
  88.     int created; /* Boolean, whether the element was created 
  89.  * explicitly (was registered) or implicitly 
  90.  * (by a derived element). */
  91. } Element;
  92. /*
  93.  * Thread-local data.
  94.  */
  95. typedef struct ThreadSpecificData {
  96.     int nbInit; /* Number of calls to the init proc. */
  97.     Tcl_HashTable engineTable; /* Map a name to a style engine. Keys are 
  98.  * strings, values are Tk_StyleEngine 
  99.  * pointers. */
  100.     StyleEngine *defaultEnginePtr;
  101. /* Default, core-defined style engine. Global 
  102.  * fallback for all engines. */
  103.     Tcl_HashTable styleTable; /* Map a name to a style. Keys are strings, 
  104.  * values are Tk_Style pointers.*/
  105.     int nbElements; /* Size of the below tables. */
  106.     Tcl_HashTable elementTable; /* Map a name to an element Id. Keys are 
  107.  * strings, values are integer element IDs. */
  108.     Element *elements; /* Array of Elements. */
  109. } ThreadSpecificData;
  110. static Tcl_ThreadDataKey dataKey;
  111. /*
  112.  * Forward declarations for procedures defined later in this file:
  113.  */
  114. /* TODO: sort alpha. */
  115. static int CreateElement _ANSI_ARGS_((CONST char *name,
  116.     int create));
  117. static void DupStyleObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,
  118.     Tcl_Obj *dupObjPtr));
  119. static void FreeElement _ANSI_ARGS_((Element *elementPtr));
  120. static void FreeStyle _ANSI_ARGS_((Style *stylePtr));
  121. static void FreeStyledElement _ANSI_ARGS_((
  122.     StyledElement *elementPtr));
  123. static void FreeStyleEngine _ANSI_ARGS_((
  124.     StyleEngine *enginePtr));
  125. static void FreeStyleObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));
  126. static void FreeWidgetSpec _ANSI_ARGS_((
  127.     StyledWidgetSpec *widgetSpecPtr));
  128. static StyledElement * GetStyledElement _ANSI_ARGS_((
  129.     StyleEngine *enginePtr, int elementId));
  130. static StyledWidgetSpec * GetWidgetSpec _ANSI_ARGS_((StyledElement *elementPtr,
  131.     Tk_OptionTable optionTable));
  132. static void InitElement _ANSI_ARGS_((Element *elementPtr, 
  133.     CONST char *name, int id, int genericId, 
  134.     int created));
  135. static void InitStyle _ANSI_ARGS_((Style *stylePtr, 
  136.     Tcl_HashEntry *hashPtr, CONST char *name, 
  137.     StyleEngine *enginePtr, ClientData clientData));
  138. static void InitStyledElement _ANSI_ARGS_((
  139.     StyledElement *elementPtr));
  140. static void InitStyleEngine _ANSI_ARGS_((StyleEngine *enginePtr,
  141.     CONST char *name, StyleEngine *parentPtr));
  142. static void InitWidgetSpec _ANSI_ARGS_((
  143.     StyledWidgetSpec *widgetSpecPtr, 
  144.     StyledElement *elementPtr, 
  145.     Tk_OptionTable optionTable));
  146. static int SetStyleFromAny _ANSI_ARGS_((Tcl_Interp *interp,
  147.     Tcl_Obj *objPtr));
  148. /*
  149.  * The following structure defines the implementation of the "style" Tcl
  150.  * object, used for drawing. The internalRep.otherValuePtr field of
  151.  * each style object points to the Style structure for the stylefont, or
  152.  * NULL.
  153.  */
  154. static Tcl_ObjType styleObjType = {
  155.     "style", /* name */
  156.     FreeStyleObjProc, /* freeIntRepProc */
  157.     DupStyleObjProc, /* dupIntRepProc */
  158.     NULL, /* updateStringProc */
  159.     SetStyleFromAny /* setFromAnyProc */
  160. };
  161. /*
  162.  *---------------------------------------------------------------------------
  163.  *
  164.  * TkStylePkgInit --
  165.  *
  166.  * This procedure is called when an application is created.  It
  167.  * initializes all the structures that are used by the style
  168.  * package on a per application basis.
  169.  *
  170.  * Results:
  171.  * Stores data in thread-local storage.
  172.  *
  173.  * Side effects:
  174.  * Memory allocated.
  175.  *
  176.  *---------------------------------------------------------------------------
  177.  */
  178. void
  179. TkStylePkgInit(mainPtr)
  180.     TkMainInfo *mainPtr; /* The application being created. */
  181. {
  182.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  183.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  184.     if (tsdPtr->nbInit != 0) return;
  185.     /*
  186.      * Initialize tables.
  187.      */
  188.     Tcl_InitHashTable(&tsdPtr->engineTable, TCL_STRING_KEYS);
  189.     Tcl_InitHashTable(&tsdPtr->styleTable, TCL_STRING_KEYS);
  190.     Tcl_InitHashTable(&tsdPtr->elementTable, TCL_STRING_KEYS);
  191.     tsdPtr->nbElements = 0;
  192.     tsdPtr->elements = NULL;
  193.     /*
  194.      * Create the default system engine.
  195.      */
  196.     
  197.     tsdPtr->defaultEnginePtr = 
  198.     (StyleEngine *) Tk_RegisterStyleEngine(NULL, NULL);
  199.     /*
  200.      * Create the default system style.
  201.      */
  202.     Tk_CreateStyle(NULL, (Tk_StyleEngine) tsdPtr->defaultEnginePtr, 
  203.     (ClientData) 0);
  204.     tsdPtr->nbInit++;
  205. }
  206. /*
  207.  *---------------------------------------------------------------------------
  208.  *
  209.  * TkStylePkgFree --
  210.  *
  211.  * This procedure is called when an application is deleted.  It
  212.  * deletes all the structures that were used by the style package
  213.  * for this application.
  214.  *
  215.  * Results:
  216.  * None.
  217.  *
  218.  * Side effects:
  219.  * Memory freed.
  220.  *
  221.  *---------------------------------------------------------------------------
  222.  */
  223. void
  224. TkStylePkgFree(mainPtr)
  225.     TkMainInfo *mainPtr; /* The application being deleted. */
  226. {
  227.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  228.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  229.     Tcl_HashSearch search;
  230.     Tcl_HashEntry *entryPtr;
  231.     StyleEngine *enginePtr;
  232.     int i;
  233.     tsdPtr->nbInit--;
  234.     if (tsdPtr->nbInit != 0) return;
  235.     /*
  236.      * Free styles.
  237.      */
  238.     entryPtr = Tcl_FirstHashEntry(&tsdPtr->styleTable, &search);
  239.     while (entryPtr != NULL) {
  240. ckfree((char *) Tcl_GetHashValue(entryPtr));
  241. entryPtr = Tcl_NextHashEntry(&search);
  242.     }
  243.     Tcl_DeleteHashTable(&tsdPtr->styleTable);
  244.     /*
  245.      * Free engines.
  246.      */
  247.     entryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);
  248.     while (entryPtr != NULL) {
  249. enginePtr = (StyleEngine *) Tcl_GetHashValue(entryPtr);
  250. FreeStyleEngine(enginePtr);
  251. ckfree((char *) enginePtr);
  252. entryPtr = Tcl_NextHashEntry(&search);
  253.     }
  254.     Tcl_DeleteHashTable(&tsdPtr->engineTable);
  255.     /*
  256.      * Free elements.
  257.      */
  258.     for (i = 0; i < tsdPtr->nbElements; i++) {
  259. FreeElement(tsdPtr->elements+i);
  260.     }
  261.     Tcl_DeleteHashTable(&tsdPtr->elementTable);
  262.     ckfree((char *) tsdPtr->elements);
  263. }
  264. /*
  265.  *---------------------------------------------------------------------------
  266.  *
  267.  * Tk_RegisterStyleEngine --
  268.  *
  269.  * This procedure is called to register a new style engine. Style engines
  270.  * are stored in thread-local space.
  271.  *
  272.  * Results:
  273.  * The newly allocated engine.
  274.  *
  275.  * Side effects:
  276.  * Memory allocated. Data added to thread-local table.
  277.  *
  278.  *---------------------------------------------------------------------------
  279.  */
  280. Tk_StyleEngine
  281. Tk_RegisterStyleEngine(name, parent)
  282.     CONST char *name; /* Name of the engine to create. NULL or empty
  283.  * means the default system engine. */
  284.     Tk_StyleEngine parent; /* The engine's parent. NULL means the default 
  285.  * system engine. */
  286. {
  287.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  288.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  289.     Tcl_HashEntry *entryPtr;
  290.     int newEntry;
  291.     StyleEngine *enginePtr;
  292.     /*
  293.      * Attempt to create a new entry in the engine table. 
  294.      */
  295.     entryPtr = Tcl_CreateHashEntry(&tsdPtr->engineTable, (name?name:""), 
  296.     &newEntry);
  297.     if (!newEntry) {
  298. /*
  299.  * An engine was already registered by that name.
  300.  */
  301. return NULL;
  302.     }
  303.     /*
  304.      * Allocate and intitialize a new engine.
  305.      */
  306.     enginePtr = (StyleEngine *) ckalloc(sizeof(StyleEngine));
  307.     InitStyleEngine(enginePtr, Tcl_GetHashKey(&tsdPtr->engineTable, entryPtr),
  308.     (StyleEngine *) parent);
  309.     Tcl_SetHashValue(entryPtr, (ClientData) enginePtr);
  310.     return (Tk_StyleEngine) enginePtr;
  311. }
  312. /*
  313.  *---------------------------------------------------------------------------
  314.  *
  315.  * InitStyleEngine --
  316.  *
  317.  * Initialize a newly allocated style engine.
  318.  *
  319.  * Results:
  320.  * None.
  321.  *
  322.  * Side effects:
  323.  * Memory allocated.
  324.  *
  325.  *---------------------------------------------------------------------------
  326.  */
  327. static void
  328. InitStyleEngine(enginePtr, name, parentPtr)
  329.     StyleEngine *enginePtr; /* Points to an uninitialized engine. */
  330.     CONST char *name; /* Name of the registered engine. NULL or empty
  331.  * means the default system engine. Usually
  332.  * points to the hash key. */
  333.     StyleEngine *parentPtr; /* The engine's parent. NULL means the default 
  334.  * system engine. */
  335. {
  336.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  337.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  338.     int elementId;
  339.     if (name == NULL || *name == '') {
  340. /*
  341.  * This is the default style engine.
  342.  */
  343. enginePtr->parentPtr = NULL;
  344.     } else if (parentPtr == NULL) {
  345. /*
  346.  * The default style engine is the parent.
  347.  */
  348. enginePtr->parentPtr = tsdPtr->defaultEnginePtr;
  349.     } else {
  350. enginePtr->parentPtr = parentPtr;
  351.     }
  352.     /* 
  353.      * Allocate and initialize elements array. 
  354.      */
  355.     if (tsdPtr->nbElements > 0) {
  356. enginePtr->elements = (StyledElement *) ckalloc(
  357. sizeof(StyledElement) * tsdPtr->nbElements);
  358. for (elementId = 0; elementId < tsdPtr->nbElements; elementId++) {
  359.     InitStyledElement(enginePtr->elements+elementId);
  360. }
  361.     } else {
  362. enginePtr->elements = NULL;
  363.     }
  364. }
  365. /*
  366.  *---------------------------------------------------------------------------
  367.  *
  368.  * FreeStyleEngine --
  369.  *
  370.  * Free an engine and its associated data.
  371.  *
  372.  * Results:
  373.  * None
  374.  *
  375.  * Side effects:
  376.  * Memory freed.
  377.  *
  378.  *---------------------------------------------------------------------------
  379.  */
  380. static void
  381. FreeStyleEngine(enginePtr)
  382.     StyleEngine *enginePtr; /* The style engine to free. */
  383. {
  384.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  385.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  386.     int elementId;
  387.     /*
  388.      * Free allocated elements.
  389.      */
  390.     for (elementId = 0; elementId < tsdPtr->nbElements; elementId++) {
  391. FreeStyledElement(enginePtr->elements+elementId);
  392.     }
  393.     ckfree((char *) enginePtr->elements);
  394. }
  395. /*
  396.  *---------------------------------------------------------------------------
  397.  *
  398.  * Tk_GetStyleEngine --
  399.  *
  400.  * Retrieve a registered style engine by its name.
  401.  *
  402.  * Results:
  403.  * A pointer to the style engine, or NULL if none found.
  404.  *
  405.  * Side effects:
  406.  * None.
  407.  *
  408.  *---------------------------------------------------------------------------
  409.  */
  410. Tk_StyleEngine
  411. Tk_GetStyleEngine(name)
  412.     CONST char *name; /* Name of the engine to retrieve. NULL or
  413.  * empty means the default system engine. */
  414. {
  415.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  416.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  417.     Tcl_HashEntry *entryPtr;
  418.     if (name == NULL) {
  419. return (Tk_StyleEngine) tsdPtr->defaultEnginePtr;
  420.     }
  421.     entryPtr = Tcl_FindHashEntry(&tsdPtr->engineTable, (name?name:""));
  422.     if (!entryPtr) {
  423. return NULL;
  424.     }
  425.     return (Tk_StyleEngine) Tcl_GetHashValue(entryPtr);
  426. }
  427. /*
  428.  *---------------------------------------------------------------------------
  429.  *
  430.  * InitElement --
  431.  *
  432.  * Initialize a newly allocated element.
  433.  *
  434.  * Results:
  435.  * None.
  436.  *
  437.  * Side effects:
  438.  * None.
  439.  *
  440.  *---------------------------------------------------------------------------
  441.  */
  442. static void
  443. InitElement(elementPtr, name, id, genericId, created)
  444.     Element *elementPtr; /* Points to an uninitialized element.*/
  445.     CONST char *name; /* Name of the registered element. Usually
  446.  * points to the hash key. */
  447.     int id; /* Unique element ID. */
  448.     int genericId; /* ID of generic element. -1 means none. */
  449.     int created; /* Boolean, whether the element was created 
  450.  * explicitly (was registered) or implicitly 
  451.  * (by a derived element). */
  452. {
  453.     elementPtr->name = name;
  454.     elementPtr->id = id;
  455.     elementPtr->genericId = genericId;
  456.     elementPtr->created = (created?1:0);
  457. }
  458. /*
  459.  *---------------------------------------------------------------------------
  460.  *
  461.  * FreeElement --
  462.  *
  463.  * Free an element and its associated data.
  464.  *
  465.  * Results:
  466.  * None.
  467.  *
  468.  * Side effects:
  469.  * Memory freed.
  470.  *
  471.  *---------------------------------------------------------------------------
  472.  */
  473. static void
  474. FreeElement(elementPtr)
  475.     Element *elementPtr; /* The element to free. */
  476. {
  477.     /* Nothing to do. */
  478. }
  479. /*
  480.  *---------------------------------------------------------------------------
  481.  *
  482.  * InitStyledElement --
  483.  *
  484.  * Initialize a newly allocated styled element.
  485.  *
  486.  * Results:
  487.  * None.
  488.  *
  489.  * Side effects:
  490.  * None.
  491.  *
  492.  *---------------------------------------------------------------------------
  493.  */
  494. static void
  495. InitStyledElement(elementPtr)
  496.     StyledElement *elementPtr; /* Points to an uninitialized element.*/
  497. {
  498.     memset(elementPtr, 0, sizeof(StyledElement));
  499. }
  500. /*
  501.  *---------------------------------------------------------------------------
  502.  *
  503.  * FreeStyledElement --
  504.  *
  505.  * Free a styled element and its associated data.
  506.  *
  507.  * Results:
  508.  * None.
  509.  *
  510.  * Side effects:
  511.  * Memory freed.
  512.  *
  513.  *---------------------------------------------------------------------------
  514.  */
  515. static void
  516. FreeStyledElement(elementPtr)
  517.     StyledElement *elementPtr; /* The styled element to free. */
  518. {
  519.     int i;
  520.     /*
  521.      * Free allocated widget specs.
  522.      */
  523.     for (i = 0; i < elementPtr->nbWidgetSpecs; i++) {
  524. FreeWidgetSpec(elementPtr->widgetSpecs+i);
  525.     }
  526.     ckfree((char *) elementPtr->widgetSpecs);
  527. }
  528. /*
  529.  *---------------------------------------------------------------------------
  530.  *
  531.  * CreateElement --
  532.  *
  533.  * Find an existing or create a new element.
  534.  *
  535.  * Results:
  536.  * The unique ID for the created or found element.
  537.  *
  538.  * Side effects:
  539.  * Memory allocated.
  540.  *
  541.  *---------------------------------------------------------------------------
  542.  */
  543. static int
  544. CreateElement(name, create)
  545.     CONST char *name; /* Name of the element. */
  546.     int create; /* Boolean, whether the element is being created 
  547.  * explicitly (being registered) or implicitly (by a 
  548.  * derived element). */
  549. {
  550.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  551.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  552.     Tcl_HashEntry *entryPtr, *engineEntryPtr;
  553.     Tcl_HashSearch search;
  554.     int newEntry;
  555.     int elementId, genericId = -1;
  556.     char *dot;
  557.     StyleEngine *enginePtr;
  558.     /*
  559.      * Find or create the element.
  560.      */
  561.     entryPtr = Tcl_CreateHashEntry(&tsdPtr->elementTable, name, &newEntry);
  562.     if (!newEntry) {
  563. elementId = (int) Tcl_GetHashValue(entryPtr);
  564. if (create) {
  565.     tsdPtr->elements[elementId].created = 1;
  566. }
  567. return elementId;
  568.     }
  569.     /*
  570.      * The element didn't exist. If it's a derived element, find or
  571.      * create its generic element ID.
  572.      */
  573.     dot = strchr(name, '.');
  574.     if (dot) {
  575. genericId = CreateElement(dot+1, 0);
  576.     }
  577.     elementId = tsdPtr->nbElements++;
  578.     Tcl_SetHashValue(entryPtr, (ClientData) elementId);
  579.     /*
  580.      * Reallocate element table.
  581.      */
  582.     tsdPtr->elements = (Element *) ckrealloc((char *) tsdPtr->elements, 
  583.     sizeof(Element) * tsdPtr->nbElements);
  584.     InitElement(tsdPtr->elements+elementId, 
  585.     Tcl_GetHashKey(&tsdPtr->elementTable, entryPtr), elementId,
  586.     genericId, create);
  587.     /*
  588.      * Reallocate style engines' element table.
  589.      */
  590.     engineEntryPtr = Tcl_FirstHashEntry(&tsdPtr->engineTable, &search);
  591.     while (engineEntryPtr != NULL) {
  592. enginePtr = (StyleEngine *) Tcl_GetHashValue(engineEntryPtr);
  593. enginePtr->elements = (StyledElement *) ckrealloc(
  594. (char *) enginePtr->elements, 
  595. sizeof(StyledElement) * tsdPtr->nbElements);
  596. InitStyledElement(enginePtr->elements+elementId);
  597. engineEntryPtr = Tcl_NextHashEntry(&search);
  598.     }
  599.     return elementId;
  600. }
  601. /*
  602.  *---------------------------------------------------------------------------
  603.  *
  604.  * Tk_GetElementId --
  605.  *
  606.  * Find an existing element.
  607.  *
  608.  * Results:
  609.  * The unique ID for the found element, or -1 if not found.
  610.  *
  611.  * Side effects:
  612.  * Generic elements may be created.
  613.  *
  614.  *---------------------------------------------------------------------------
  615.  */
  616. int
  617. Tk_GetElementId(name)
  618.     CONST char *name; /* Name of the element. */
  619. {
  620.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  621.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  622.     Tcl_HashEntry *entryPtr;
  623.     int genericId = -1;
  624.     char *dot;
  625.     /*
  626.      * Find the element Id.
  627.      */
  628.     entryPtr = Tcl_FindHashEntry(&tsdPtr->elementTable, name);
  629.     if (entryPtr) {
  630. return (int) Tcl_GetHashValue(entryPtr);
  631.     }
  632.     /*
  633.      * Element not found. If the given name was derived, then first search for 
  634.      * the generic element. If found, create the new derived element.
  635.      */
  636.     dot = strchr(name, '.');
  637.     if (!dot) {
  638. return -1;
  639.     }
  640.     genericId = Tk_GetElementId(dot+1);
  641.     if (genericId == -1) {
  642. return -1;
  643.     }
  644.     if (!tsdPtr->elements[genericId].created) {
  645. /* 
  646.  * The generic element was created implicitly and thus has no real
  647.  * existence.
  648.  */
  649. return -1;
  650.     } else {
  651. /*
  652.  * The generic element was created explicitly. Create the derived
  653.  * element.
  654.  */
  655. return CreateElement(name, 1);
  656.     }
  657. }
  658. /*
  659.  *---------------------------------------------------------------------------
  660.  *
  661.  * Tk_RegisterStyledElement --
  662.  *
  663.  * Register an implementation of a new or existing element for the
  664.  * given style engine.
  665.  *
  666.  * Results:
  667.  * The unique ID for the created or found element.
  668.  *
  669.  * Side effects:
  670.  * Elements may be created. Memory allocated.
  671.  *
  672.  *---------------------------------------------------------------------------
  673.  */
  674. int
  675. Tk_RegisterStyledElement(engine, templatePtr)
  676.     Tk_StyleEngine engine; /* Style engine providing the
  677.  * implementation. */
  678.     Tk_ElementSpec *templatePtr; /* Static template information about
  679.  * the element. */
  680. {
  681.     int elementId;
  682.     StyledElement *elementPtr;
  683.     Tk_ElementSpec *specPtr;
  684.     int nbOptions;
  685.     register Tk_ElementOptionSpec *srcOptions, *dstOptions;
  686.     if (templatePtr->version != TK_STYLE_VERSION_1) {
  687. /*
  688.  * Version mismatch. Do nothing.
  689.  */
  690. return -1;
  691.     }
  692.     if (engine == NULL) {
  693. engine = Tk_GetStyleEngine(NULL);
  694.     }
  695.     /*
  696.      * Register the element, allocating storage in the various engines if 
  697.      * necessary.
  698.      */
  699.     elementId = CreateElement(templatePtr->name, 1);
  700.     /*
  701.      * Initialize the styled element.
  702.      */
  703.     elementPtr = ((StyleEngine *) engine)->elements+elementId;
  704.     specPtr = (Tk_ElementSpec *) ckalloc(sizeof(Tk_ElementSpec));
  705.     specPtr->version = templatePtr->version;
  706.     specPtr->name = ckalloc(strlen(templatePtr->name)+1);
  707.     strcpy(specPtr->name, templatePtr->name);
  708.     nbOptions = 0;
  709.     for (nbOptions = 0, srcOptions = templatePtr->options;
  710.  srcOptions->name != NULL;
  711.  nbOptions++, srcOptions++);
  712.     specPtr->options = (Tk_ElementOptionSpec *) ckalloc(
  713.     sizeof(Tk_ElementOptionSpec) * (nbOptions+1));
  714.     for (srcOptions = templatePtr->options, dstOptions = specPtr->options;
  715.  /* End condition within loop */;
  716.  srcOptions++, dstOptions++) {
  717. if (srcOptions->name == NULL) {
  718.     dstOptions->name = NULL;
  719.     break;
  720. }
  721. dstOptions->name = ckalloc(strlen(srcOptions->name)+1);
  722. strcpy(dstOptions->name, srcOptions->name);
  723. dstOptions->type = srcOptions->type;
  724.     }
  725.     specPtr->getSize = templatePtr->getSize;
  726.     specPtr->getBox = templatePtr->getBox;
  727.     specPtr->getBorderWidth = templatePtr->getBorderWidth;
  728.     specPtr->draw = templatePtr->draw;
  729.     elementPtr->specPtr = specPtr;
  730.     elementPtr->nbWidgetSpecs = 0;
  731.     elementPtr->widgetSpecs = NULL;
  732.     return elementId;
  733. }
  734. /*
  735.  *---------------------------------------------------------------------------
  736.  *
  737.  * GetStyledElement --
  738.  *
  739.  * Get a registered implementation of an existing element for the
  740.  * given style engine.
  741.  *
  742.  * Results:
  743.  * The styled element descriptor, or NULL if not found.
  744.  *
  745.  * Side effects:
  746.  * None.
  747.  *
  748.  *---------------------------------------------------------------------------
  749.  */
  750. static StyledElement *
  751. GetStyledElement(enginePtr, elementId)
  752.     StyleEngine *enginePtr; /* Style engine providing the implementation. 
  753.  * NULL means the default system engine. */
  754.     int elementId; /* Unique element ID */{
  755.     StyledElement *elementPtr;
  756.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  757.     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  758.     StyleEngine *enginePtr2;
  759.     if (enginePtr == NULL) {
  760. enginePtr = tsdPtr->defaultEnginePtr;
  761.     }
  762.     while (elementId >= 0 && elementId < tsdPtr->nbElements) {
  763. /*
  764.  * Look for an implemented element through the engine chain.
  765.  */
  766. enginePtr2 = enginePtr;
  767. do {
  768.     elementPtr = enginePtr2->elements+elementId;
  769.     if (elementPtr->specPtr != NULL) {
  770. return elementPtr;
  771.     }
  772.     enginePtr2 = enginePtr2->parentPtr;
  773. } while (enginePtr2 != NULL);
  774. /*
  775.  * None found, try with the generic element.
  776.  */
  777. elementId = tsdPtr->elements[elementId].genericId;
  778.     }
  779.     /*
  780.      * No matching element found.
  781.      */
  782.     return NULL;
  783. }
  784. /*
  785.  *---------------------------------------------------------------------------
  786.  *
  787.  * InitWidgetSpec --
  788.  *
  789.  * Initialize a newly allocated widget spec.
  790.  *
  791.  * Results:
  792.  * None.
  793.  *
  794.  * Side effects:
  795.  * Memory allocated.
  796.  *
  797.  *---------------------------------------------------------------------------
  798.  */
  799. static void
  800. InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable)
  801.     StyledWidgetSpec *widgetSpecPtr; /* Points to an uninitialized widget
  802.  * spec. */
  803.     StyledElement *elementPtr; /* Styled element descriptor. */
  804.     Tk_OptionTable optionTable; /* The widget's option table. */
  805. {
  806.     int i, nbOptions;
  807.     Tk_ElementOptionSpec *elementOptionPtr;
  808.     CONST Tk_OptionSpec *widgetOptionPtr;
  809.     widgetSpecPtr->elementPtr = elementPtr;
  810.     widgetSpecPtr->optionTable = optionTable;
  811.     
  812.     /*
  813.      * Count the number of options.
  814.      */
  815.     for (nbOptions = 0, elementOptionPtr = elementPtr->specPtr->options; 
  816.     elementOptionPtr->name != NULL;
  817.     nbOptions++, elementOptionPtr++) {
  818.     }
  819.     /*
  820.      * Build the widget option list.
  821.      */
  822.     widgetSpecPtr->optionsPtr = (CONST Tk_OptionSpec **) ckalloc(
  823.     sizeof(Tk_OptionSpec *) * nbOptions);
  824.     for (i = 0, elementOptionPtr = elementPtr->specPtr->options; 
  825.     i < nbOptions;
  826.     i++, elementOptionPtr++) {
  827. widgetOptionPtr = TkGetOptionSpec(elementOptionPtr->name, optionTable);
  828. /*
  829.  * Check that the widget option type is compatible with one of the 
  830.  * element's required types.
  831.  */
  832. if (   elementOptionPtr->type == TK_OPTION_END
  833.     || elementOptionPtr->type == widgetOptionPtr->type) {
  834.     widgetSpecPtr->optionsPtr[i] = widgetOptionPtr;
  835. } else {
  836.     widgetSpecPtr->optionsPtr[i] = NULL;
  837. }
  838.     }
  839. }
  840. /*
  841.  *---------------------------------------------------------------------------
  842.  *
  843.  * FreeWidgetSpec --
  844.  *
  845.  * Free a widget spec and its associated data.
  846.  *
  847.  * Results:
  848.  * None
  849.  *
  850.  * Side effects:
  851.  * Memory freed.
  852.  *
  853.  *---------------------------------------------------------------------------
  854.  */
  855. static void
  856. FreeWidgetSpec(widgetSpecPtr)
  857.     StyledWidgetSpec *widgetSpecPtr; /* The widget spec to free. */
  858. {
  859.     ckfree((char *) widgetSpecPtr->optionsPtr);
  860. }
  861. /*
  862.  *---------------------------------------------------------------------------
  863.  *
  864.  * GetWidgetSpec --
  865.  *
  866.  * Return a new or existing widget spec for the given element and
  867.  * widget type (identified by its option table).
  868.  *
  869.  * Results:
  870.  * A pointer to the matching widget spec.
  871.  *
  872.  * Side effects:
  873.  * Memory may be allocated.
  874.  *
  875.  *---------------------------------------------------------------------------
  876.  */
  877. static StyledWidgetSpec *
  878. GetWidgetSpec(elementPtr, optionTable)
  879.     StyledElement *elementPtr; /* Styled element descriptor. */
  880.     Tk_OptionTable optionTable; /* The widget's option table. */
  881. {
  882.     StyledWidgetSpec *widgetSpecPtr;
  883.     int i;
  884.     /*
  885.      * Try to find an existing widget spec.
  886.      */
  887.     for (i = 0; i < elementPtr->nbWidgetSpecs; i++) {
  888. widgetSpecPtr = elementPtr->widgetSpecs+i;
  889. if (widgetSpecPtr->optionTable == optionTable) {
  890.     return widgetSpecPtr;
  891. }
  892.     }
  893.     /*
  894.      * Create and initialize a new widget spec.
  895.      */
  896.     i = elementPtr->nbWidgetSpecs++;
  897.     elementPtr->widgetSpecs = (StyledWidgetSpec *) ckrealloc(
  898.     (char *) elementPtr->widgetSpecs, 
  899.     sizeof(StyledWidgetSpec) * elementPtr->nbWidgetSpecs);
  900.     widgetSpecPtr = elementPtr->widgetSpecs+i;
  901.     InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable);
  902.     return widgetSpecPtr;
  903. }
  904. /*
  905.  *---------------------------------------------------------------------------
  906.  *
  907.  * Tk_GetStyledElement --
  908.  *
  909.  * This procedure returns a styled instance of the given element.
  910.  *
  911.  * Results:
  912.  * None.
  913.  *
  914.  * Side effects:
  915.  * Cached data may be allocated or updated.
  916.  *
  917.  *---------------------------------------------------------------------------
  918.  */
  919. Tk_StyledElement
  920. Tk_GetStyledElement(style, elementId, optionTable)
  921.     Tk_Style style; /* The widget style. */
  922.     int elementId; /* Unique element ID. */
  923.     Tk_OptionTable optionTable; /* Option table for the widget. */
  924. {
  925.     Style *stylePtr = (Style *) style;
  926.     StyledElement *elementPtr;
  927.     /*
  928.      * Get an element implementation and call corresponding hook.
  929.      */
  930.     elementPtr = GetStyledElement((stylePtr?stylePtr->enginePtr:NULL), 
  931.     elementId);
  932.     if (!elementPtr) {
  933. return NULL;
  934.     }
  935.     return (Tk_StyledElement) GetWidgetSpec(elementPtr, optionTable);
  936. }
  937. /*
  938.  *---------------------------------------------------------------------------
  939.  *
  940.  * Tk_GetElementSize --
  941.  *
  942.  * This procedure computes the size of the given widget element according
  943.  * to its style.
  944.  *
  945.  * Results:
  946.  * None.
  947.  *
  948.  * Side effects:
  949.  * Cached data may be allocated or updated.
  950.  *
  951.  *---------------------------------------------------------------------------
  952.  */
  953. void
  954. Tk_GetElementSize(style, element, recordPtr, tkwin, width, height, inner, widthPtr, 
  955. heightPtr)
  956.     Tk_Style style; /* The widget style. */
  957.     Tk_StyledElement element; /* The styled element, previously
  958.  * returned by Tk_GetStyledElement. */
  959.     char *recordPtr; /* The widget record. */
  960.     Tk_Window tkwin; /* The widget window. */
  961.     int width, height; /* Requested size. */
  962.     int inner; /* Boolean. If TRUE, compute the outer
  963.  * size according to the requested
  964.  * minimum inner size. If FALSE, compute
  965.  * the inner size according to the 
  966.  * requested maximum outer size. */
  967.     int *widthPtr, *heightPtr; /* Returned size. */
  968. {
  969.     Style *stylePtr = (Style *) style;
  970.     StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
  971.     widgetSpecPtr->elementPtr->specPtr->getSize(stylePtr->clientData, 
  972.     recordPtr, widgetSpecPtr->optionsPtr, tkwin, width, height, inner, 
  973.     widthPtr, heightPtr);
  974. }
  975. /*
  976.  *---------------------------------------------------------------------------
  977.  *
  978.  * Tk_GetElementBox --
  979.  *
  980.  * This procedure computes the bounding or inscribed box coordinates
  981.  * of the given widget element according to its style and within the
  982.  * given limits.
  983.  *
  984.  * Results:
  985.  * None.
  986.  *
  987.  * Side effects:
  988.  * Cached data may be allocated or updated.
  989.  *
  990.  *---------------------------------------------------------------------------
  991.  */
  992. void
  993. Tk_GetElementBox(style, element, recordPtr, tkwin, x, y, width, height, inner, 
  994. xPtr, yPtr, widthPtr, heightPtr)
  995.     Tk_Style style; /* The widget style. */
  996.     Tk_StyledElement element; /* The styled element, previously
  997.  * returned by Tk_GetStyledElement. */
  998.     char *recordPtr; /* The widget record. */
  999.     Tk_Window tkwin; /* The widget window. */
  1000.     int x, y; /* Top left corner of available area. */
  1001.     int width, height; /* Size of available area. */
  1002.     int inner; /* Boolean. If TRUE, compute the 
  1003.  * bounding box according to the 
  1004.  * requested inscribed box size. If 
  1005.  * FALSE, compute the inscribed box 
  1006.  * according to the requested bounding
  1007.  * box. */
  1008.     int *xPtr, *yPtr; /* Returned top left corner. */
  1009.     int *widthPtr, *heightPtr; /* Returned size. */
  1010. {
  1011.     Style *stylePtr = (Style *) style;
  1012.     StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
  1013.     widgetSpecPtr->elementPtr->specPtr->getBox(stylePtr->clientData, 
  1014.     recordPtr, widgetSpecPtr->optionsPtr, tkwin, x, y, width, height, 
  1015.     inner, xPtr, yPtr, widthPtr, heightPtr);
  1016. }
  1017. /*
  1018.  *---------------------------------------------------------------------------
  1019.  *
  1020.  * Tk_GetElementBorderWidth --
  1021.  *
  1022.  * This procedure computes the border widthof the given widget element 
  1023.  * according to its style and within the given limits.
  1024.  *
  1025.  * Results:
  1026.  * Border width in pixels. This value is uniform for all four sides.
  1027.  *
  1028.  * Side effects:
  1029.  * Cached data may be allocated or updated.
  1030.  *
  1031.  *---------------------------------------------------------------------------
  1032.  */
  1033. int
  1034. Tk_GetElementBorderWidth(style, element, recordPtr, tkwin)
  1035.     Tk_Style style; /* The widget style. */
  1036.     Tk_StyledElement element; /* The styled element, previously
  1037.  * returned by Tk_GetStyledElement. */
  1038.     char *recordPtr; /* The widget record. */
  1039.     Tk_Window tkwin; /* The widget window. */
  1040. {
  1041.     Style *stylePtr = (Style *) style;
  1042.     StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
  1043.     return widgetSpecPtr->elementPtr->specPtr->getBorderWidth(
  1044.     stylePtr->clientData, recordPtr, widgetSpecPtr->optionsPtr, tkwin);
  1045. }
  1046. /*
  1047.  *---------------------------------------------------------------------------
  1048.  *
  1049.  * Tk_DrawElement --
  1050.  *
  1051.  * This procedure draw the given widget element in a given drawable area.
  1052.  *
  1053.  * Results:
  1054.  * None
  1055.  *
  1056.  * Side effects:
  1057.  * Cached data may be allocated or updated.
  1058.  *
  1059.  *---------------------------------------------------------------------------
  1060.  */
  1061. void
  1062. Tk_DrawElement(style, element, recordPtr, tkwin, d, x, y, width, height, state)
  1063.     Tk_Style style; /* The widget style. */
  1064.     Tk_StyledElement element; /* The styled element, previously
  1065.  * returned by Tk_GetStyledElement. */
  1066.     char *recordPtr; /* The widget record. */
  1067.     Tk_Window tkwin; /* The widget window. */
  1068.     Drawable d; /* Where to draw element. */
  1069.     int x, y; /* Top left corner of element. */
  1070.     int width, height; /* Size of element. */
  1071.     int state; /* Drawing state flags. */
  1072. {
  1073.     Style *stylePtr = (Style *) style;
  1074.     StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element;
  1075.     widgetSpecPtr->elementPtr->specPtr->draw(stylePtr->clientData, 
  1076.     recordPtr, widgetSpecPtr->optionsPtr, tkwin, d, x, y, width, 
  1077.     height, state);
  1078. }
  1079. /*
  1080.  *---------------------------------------------------------------------------
  1081.  *
  1082.  * Tk_CreateStyle --
  1083.  *
  1084.  * This procedure is called to create a new style as an instance of the
  1085.  * given engine. Styles are stored in thread-local space.
  1086.  *
  1087.  * Results:
  1088.  * The newly allocated style.
  1089.  *
  1090.  * Side effects:
  1091.  * Memory allocated. Data added to thread-local table. The style's
  1092.  * refCount is incremented.
  1093.  *
  1094.  *---------------------------------------------------------------------------
  1095.  */
  1096. Tk_Style
  1097. Tk_CreateStyle(name, engine, clientData)
  1098.     CONST char *name; /* Name of the style to create. NULL or empty
  1099.  * means the default system style. */
  1100.     Tk_StyleEngine engine; /* The style engine. */
  1101.     ClientData clientData; /* Private data passed as is to engine code. */
  1102. {
  1103.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  1104.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  1105.     Tcl_HashEntry *entryPtr;
  1106.     int newEntry;
  1107.     Style *stylePtr;
  1108.     /*
  1109.      * Attempt to create a new entry in the style table. 
  1110.      */
  1111.     entryPtr = Tcl_CreateHashEntry(&tsdPtr->styleTable, (name?name:""), 
  1112.     &newEntry);
  1113.     if (!newEntry) {
  1114. /*
  1115.  * A style was already registered by that name.
  1116.  */
  1117. return NULL;
  1118.     }
  1119.     /*
  1120.      * Allocate and intitialize a new style.
  1121.      */
  1122.     stylePtr = (Style *) ckalloc(sizeof(Style));
  1123.     InitStyle(stylePtr, entryPtr, Tcl_GetHashKey(&tsdPtr->styleTable, entryPtr),
  1124.     (engine?(StyleEngine *) engine:tsdPtr->defaultEnginePtr), clientData);
  1125.     Tcl_SetHashValue(entryPtr, (ClientData) stylePtr);
  1126.     stylePtr->refCount++;
  1127.     return (Tk_Style) stylePtr;
  1128. }
  1129. /*
  1130.  *---------------------------------------------------------------------------
  1131.  *
  1132.  * Tk_NameOfStyle --
  1133.  *
  1134.  * Given a style, return its registered name.
  1135.  *
  1136.  * Results:
  1137.  * The return value is the name that was passed to Tk_CreateStyle() to 
  1138.  * create the style.  The storage for the returned string is private
  1139.  * (it points to the corresponding hash key) The caller should not modify 
  1140.  * this string.
  1141.  *
  1142.  * Side effects:
  1143.  * None.
  1144.  *
  1145.  *---------------------------------------------------------------------------
  1146.  */
  1147. CONST char *
  1148. Tk_NameOfStyle(style)
  1149.     Tk_Style style; /* Style whose name is desired. */
  1150. {
  1151.     Style *stylePtr = (Style *) style;
  1152.     return stylePtr->name;
  1153. }
  1154. /*
  1155.  *---------------------------------------------------------------------------
  1156.  *
  1157.  * InitStyle --
  1158.  *
  1159.  * Initialize a newly allocated style.
  1160.  *
  1161.  * Results:
  1162.  * None.
  1163.  *
  1164.  * Side effects:
  1165.  * None.
  1166.  *
  1167.  *---------------------------------------------------------------------------
  1168.  */
  1169. static void
  1170. InitStyle(stylePtr, hashPtr, name, enginePtr, clientData)
  1171.     Style *stylePtr; /* Points to an uninitialized style. */
  1172.     Tcl_HashEntry *hashPtr; /* Hash entry for the registered style. */
  1173.     CONST char *name; /* Name of the registered style. NULL or empty
  1174.  * means the default system style. Usually
  1175.  * points to the hash key. */
  1176.     StyleEngine *enginePtr; /* The style engine. */
  1177.     ClientData clientData; /* Private data passed as is to engine code. */
  1178. {
  1179.     stylePtr->refCount = 0;
  1180.     stylePtr->hashPtr = hashPtr;
  1181.     stylePtr->name = name;
  1182.     stylePtr->enginePtr = enginePtr;
  1183.     stylePtr->clientData = clientData;
  1184. }
  1185. /*
  1186.  *---------------------------------------------------------------------------
  1187.  *
  1188.  * FreeStyle --
  1189.  *
  1190.  * Free a style and its associated data.
  1191.  *
  1192.  * Results:
  1193.  * None
  1194.  *
  1195.  * Side effects:
  1196.  * None.
  1197.  *
  1198.  *---------------------------------------------------------------------------
  1199.  */
  1200. static void
  1201. FreeStyle(stylePtr)
  1202.     Style *stylePtr; /* The style to free. */
  1203. {
  1204.     /* Nothing to do. */
  1205. }
  1206. /*
  1207.  *---------------------------------------------------------------------------
  1208.  *
  1209.  * Tk_GetStyle --
  1210.  *
  1211.  * Retrieve a registered style by its name.
  1212.  *
  1213.  * Results:
  1214.  * A pointer to the style engine, or NULL if none found.  In the latter
  1215.  * case and if the interp is not NULL, an error message is left in the 
  1216.  * interp's result.
  1217.  *
  1218.  * Side effects:
  1219.  * None.
  1220.  *
  1221.  *---------------------------------------------------------------------------
  1222.  */
  1223. Tk_Style
  1224. Tk_GetStyle(interp, name)
  1225.     Tcl_Interp *interp; /* Interp for error return. */
  1226.     CONST char *name; /* Name of the style to retrieve. NULL or empty
  1227.  * means the default system style. */
  1228. {
  1229.     ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
  1230.             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
  1231.     Tcl_HashEntry *entryPtr;
  1232.     Style *stylePtr;
  1233.     /*
  1234.      * Search for a corresponding entry in the style table. 
  1235.      */
  1236.     entryPtr = Tcl_FindHashEntry(&tsdPtr->styleTable, (name?name:""));
  1237.     if (entryPtr == NULL) {
  1238. if (interp != NULL) {
  1239.     Tcl_AppendResult(interp, "style "", name, "" doesn't exist", NULL);
  1240. }
  1241. return (Tk_Style) NULL;
  1242.     }
  1243.     stylePtr = (Style *) Tcl_GetHashValue(entryPtr);
  1244.     stylePtr->refCount++;
  1245.     return (Tk_Style) stylePtr;
  1246. }
  1247. /*
  1248.  *---------------------------------------------------------------------------
  1249.  *
  1250.  * Tk_FreeStyle --
  1251.  *
  1252.  * Free a style previously created by Tk_CreateStyle.
  1253.  *
  1254.  * Results:
  1255.  * None
  1256.  *
  1257.  * Side effects:
  1258.  * The style's refCount is decremented. If it reaches zero, the style
  1259.  * is freed.
  1260.  *
  1261.  *---------------------------------------------------------------------------
  1262.  */
  1263. void 
  1264. Tk_FreeStyle(style)
  1265.     Tk_Style style; /* The style to free. */
  1266. {
  1267.     Style *stylePtr = (Style *) style;
  1268.     if (stylePtr == NULL) {
  1269. return;
  1270.     }
  1271.     stylePtr->refCount--;
  1272.     if (stylePtr->refCount > 0) {
  1273. return;
  1274.     }
  1275.     
  1276.     /*
  1277.      * Keep the default style alive.
  1278.      */
  1279.     if (*stylePtr->name == '') {
  1280. stylePtr->refCount = 1;
  1281. return;
  1282.     }
  1283.     Tcl_DeleteHashEntry(stylePtr->hashPtr);
  1284.     FreeStyle(stylePtr);
  1285.     ckfree((char *) stylePtr);
  1286. }
  1287. /*
  1288.  *---------------------------------------------------------------------------
  1289.  *
  1290.  * Tk_AllocStyleFromObj -- 
  1291.  *
  1292.  * Map the string name of a style to a corresponding Tk_Style. The style 
  1293.  * must have already been created by Tk_CreateStyle.
  1294.  *
  1295.  * Results:
  1296.  * The return value is a token for the style that matches objPtr, or 
  1297.  * NULL if none found.  If NULL is returned, an error message will be 
  1298.  * left in interp's result object.
  1299.  *
  1300.  * Side effects:
  1301.  *  The style's reference count is incremented. For each call to this 
  1302.  * procedure, there should eventually be a call to Tk_FreeStyle() or 
  1303.  * Tk_FreeStyleFromObj() so that the database is cleaned up when styles
  1304.  * aren't in use anymore.
  1305.  *
  1306.  *---------------------------------------------------------------------------
  1307.  */
  1308. Tk_Style
  1309. Tk_AllocStyleFromObj(interp, objPtr)
  1310.     Tcl_Interp *interp; /* Interp for error return. */
  1311.     Tcl_Obj *objPtr; /* Object containing name of the style to
  1312.  * retrieve. */
  1313. {
  1314.     Style *stylePtr;
  1315.     if (objPtr->typePtr != &styleObjType) {
  1316. SetStyleFromAny(interp, objPtr);
  1317. stylePtr = (Style *) objPtr->internalRep.otherValuePtr;
  1318.     } else {
  1319. stylePtr = (Style *) objPtr->internalRep.otherValuePtr;
  1320. stylePtr->refCount++;
  1321.     }
  1322.     return (Tk_Style) stylePtr;
  1323. }
  1324. /*
  1325.  *----------------------------------------------------------------------
  1326.  *
  1327.  * Tk_GetStyleFromObj --
  1328.  *
  1329.  * Find the style that corresponds to a given object.  The style must
  1330.  * have already been created by Tk_CreateStyle.
  1331.  *
  1332.  * Results:
  1333.  * The return value is a token for the style that matches objPtr, or 
  1334.  * NULL if none found.
  1335.  *
  1336.  * Side effects:
  1337.  * If the object is not already a style ref, the conversion will free
  1338.  * any old internal representation. 
  1339.  *
  1340.  *----------------------------------------------------------------------
  1341.  */
  1342. Tk_Style
  1343. Tk_GetStyleFromObj(objPtr)
  1344.     Tcl_Obj *objPtr; /* The object from which to get the style. */
  1345. {
  1346.     if (objPtr->typePtr != &styleObjType) {
  1347. SetStyleFromAny((Tcl_Interp *) NULL, objPtr);
  1348.     }
  1349.     return (Tk_Style) objPtr->internalRep.otherValuePtr;
  1350. }
  1351. /*
  1352.  *---------------------------------------------------------------------------
  1353.  *
  1354.  * Tk_FreeStyleFromObj -- 
  1355.  *
  1356.  * Called to release a style inside a Tcl_Obj *.
  1357.  *
  1358.  * Results:
  1359.  * None.
  1360.  *
  1361.  * Side effects:
  1362.  * If the object is a style ref, the conversion will free its 
  1363.  * internal representation. 
  1364.  *
  1365.  *---------------------------------------------------------------------------
  1366.  */
  1367. void
  1368. Tk_FreeStyleFromObj(objPtr)
  1369.     Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */
  1370. {
  1371.     if (objPtr->typePtr == &styleObjType) {
  1372. FreeStyleObjProc(objPtr);
  1373.     }
  1374. }
  1375. /*
  1376.  *----------------------------------------------------------------------
  1377.  *
  1378.  * SetStyleFromAny --
  1379.  *
  1380.  * Convert the internal representation of a Tcl object to the
  1381.  * style internal form.
  1382.  *
  1383.  * Results:
  1384.  * Always returns TCL_OK.  If an error occurs is returned (e.g. the
  1385.  * style doesn't exist), an error message will be left in interp's 
  1386.  * result.
  1387.  *
  1388.  * Side effects:
  1389.  * The object is left with its typePtr pointing to styleObjType.
  1390.  * The reference count is incremented (in Tk_GetStyle()).
  1391.  *
  1392.  *----------------------------------------------------------------------
  1393.  */
  1394. static int
  1395. SetStyleFromAny(interp, objPtr)
  1396.     Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  1397.     Tcl_Obj *objPtr; /* The object to convert. */
  1398. {
  1399.     Tcl_ObjType *typePtr;
  1400.     char *name;
  1401.     /*
  1402.      * Free the old internalRep before setting the new one. 
  1403.      */
  1404.     name = Tcl_GetString(objPtr);
  1405.     typePtr = objPtr->typePtr;
  1406.     if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
  1407. (*typePtr->freeIntRepProc)(objPtr);
  1408.     }
  1409.     objPtr->typePtr = &styleObjType;
  1410.     objPtr->internalRep.otherValuePtr = (VOID *) Tk_GetStyle(interp, name);
  1411.     return TCL_OK;
  1412. }
  1413. /*
  1414.  *---------------------------------------------------------------------------
  1415.  *
  1416.  * FreeStyleObjProc -- 
  1417.  *
  1418.  * This proc is called to release an object reference to a style.
  1419.  * Called when the object's internal rep is released.
  1420.  *
  1421.  * Results:
  1422.  * None.
  1423.  *
  1424.  * Side effects:
  1425.  * The reference count is decremented (in Tk_FreeStyle()).
  1426.  *
  1427.  *---------------------------------------------------------------------------
  1428.  */
  1429. static void
  1430. FreeStyleObjProc(objPtr)
  1431.     Tcl_Obj *objPtr; /* The object we are releasing. */
  1432. {
  1433.     Style *stylePtr = (Style *) objPtr->internalRep.otherValuePtr;
  1434.     if (stylePtr != NULL) {
  1435. Tk_FreeStyle((Tk_Style) stylePtr);
  1436. objPtr->internalRep.otherValuePtr = NULL;
  1437.     }
  1438. }
  1439. /*
  1440.  *---------------------------------------------------------------------------
  1441.  *
  1442.  * DupStyleObjProc -- 
  1443.  *
  1444.  * When a cached style object is duplicated, this is called to
  1445.  * update the internal reps.
  1446.  *
  1447.  * Results:
  1448.  * None.
  1449.  *
  1450.  * Side effects:
  1451.  * The style's refCount is incremented and the internal rep of the copy 
  1452.  * is set to point to it.
  1453.  *
  1454.  *---------------------------------------------------------------------------
  1455.  */
  1456. static void
  1457. DupStyleObjProc(srcObjPtr, dupObjPtr)
  1458.     Tcl_Obj *srcObjPtr; /* The object we are copying from. */
  1459.     Tcl_Obj *dupObjPtr; /* The object we are copying to. */
  1460. {
  1461.     Style *stylePtr = (Style *) srcObjPtr->internalRep.otherValuePtr;
  1462.     
  1463.     dupObjPtr->typePtr = srcObjPtr->typePtr;
  1464.     dupObjPtr->internalRep.otherValuePtr = (VOID *) stylePtr;
  1465.     if (stylePtr != NULL) {
  1466. stylePtr->refCount++;
  1467.     }
  1468. }