OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / blt2.5 / generic / bltTreeViewStyle.c
1
2 /*
3  * bltTreeViewStyle.c --
4  *
5  *      This module implements styles for treeview widget cells.
6  *
7  * Copyright 1998-1999 Lucent Technologies, Inc.
8  *
9  * Permission to use, copy, modify, and distribute this software and
10  * its documentation for any purpose and without fee is hereby
11  * granted, provided that the above copyright notice appear in all
12  * copies and that both that the copyright notice and warranty
13  * disclaimer appear in supporting documentation, and that the names
14  * of Lucent Technologies or any of their entities not be used in
15  * advertising or publicity pertaining to distribution of the software
16  * without specific, written prior permission.
17  *
18  * Lucent Technologies disclaims all warranties with regard to this
19  * software, including all implied warranties of merchantability and
20  * fitness.  In no event shall Lucent Technologies be liable for any
21  * special, indirect or consequential damages or any damages
22  * whatsoever resulting from loss of use, data or profits, whether in
23  * an action of contract, negligence or other tortuous action, arising
24  * out of or in connection with the use or performance of this
25  * software.
26  *
27  *      The "treeview" widget was created by George A. Howlett.
28  *      Extensive cleanups and enhancements by Peter MacDonald.
29  */
30
31 #include "bltInt.h"
32
33 #ifndef NO_TREEVIEW
34
35 #include "bltTreeView.h"
36 #include "bltList.h"
37 #include <X11/Xutil.h>
38 #include <X11/Xatom.h>
39
40 #define STYLE_GAP               2
41
42 static Blt_OptionParseProc ObjToSticky;
43 static Blt_OptionPrintProc StickyToObj;
44
45 static Blt_OptionParseProc ObjToIcon;
46 static Blt_OptionPrintProc IconToObj;
47 static Blt_OptionFreeProc FreeIcon;
48 Blt_CustomOption bltTreeViewIconOption =
49 {
50     /* Contains a pointer to the widget that's currently being
51      * configured.  This is used in the custom configuration parse
52      * routine for icons.  */
53     ObjToIcon, IconToObj, FreeIcon, NULL,
54 };
55 extern Blt_CustomOption bltTreeViewIconsOption;
56
57
58 #define DEF_STYLE_HIGHLIGHT_BACKGROUND  STD_NORMAL_BACKGROUND
59 #define DEF_STYLE_HIGHLIGHT_FOREGROUND  STD_NORMAL_FOREGROUND
60 #ifdef WIN32
61 #define DEF_STYLE_ACTIVE_BACKGROUND     RGB_GREY85
62 #else
63 #define DEF_STYLE_ACTIVE_BACKGROUND     RGB_GREY95
64 #endif
65 #define DEF_STYLE_ACTIVE_FOREGROUND     STD_ACTIVE_FOREGROUND
66 #define DEF_STYLE_GAP                   "2"
67
68 typedef struct {
69     TREEVIEW_STYLE_COMMON
70
71     /* TextBox-specific fields */
72     Tcl_Obj *formatCmd;
73
74     int iconside;                       /* Position of the text in relation to
75                                  * the icon.  */
76     int side;                   /* Side to anchor cell. */
77
78 } TreeViewTextBox;
79
80 #ifdef WIN32
81 #define DEF_TEXTBOX_CURSOR              "arrow"
82 #else
83 #define DEF_TEXTBOX_CURSOR              "hand2"
84 #endif /*WIN32*/
85 #define DEF_TEXTBOX_SIDE                "left"
86
87 #define CONF_STYLES \
88     {BLT_CONFIG_BORDER, "-activebackground", "activeBackground",  \
89         "ActiveBackground", DEF_STYLE_ACTIVE_BACKGROUND, \
90         Blt_Offset(TreeViewStyle, activeBorder), BLT_CONFIG_NULL_OK}, \
91     {BLT_CONFIG_SYNONYM, "-activebg", (char *)NULL, \
92         (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-activebackground"}, \
93     {BLT_CONFIG_SYNONYM, "-activefg", (char *)NULL, \
94         (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-activeforeground"}, \
95     {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground",  \
96         "ActiveForeground", DEF_STYLE_ACTIVE_FOREGROUND,  \
97         Blt_Offset(TreeViewStyle, activeFgColor), 0}, \
98     {BLT_CONFIG_BORDER, "-background", (char *)NULL, (char *)NULL, \
99         (char *)NULL, Blt_Offset(TreeViewStyle, border), \
100         BLT_CONFIG_NULL_OK|BLT_CONFIG_DONT_SET_DEFAULT}, \
101     {BLT_CONFIG_SYNONYM, "-bg", (char *)NULL, (char *)NULL, (char *)NULL, \
102         0, 0, (ClientData)"-background"}, \
103     {BLT_CONFIG_CURSOR, "-cursor", "cursor", "Cursor", \
104         DEF_TEXTBOX_CURSOR, Blt_Offset(TreeViewStyle, cursor), 0}, \
105     {BLT_CONFIG_BOOLEAN, "-readonly", "readOnly", "ReadOnly", \
106         "False", Blt_Offset(TreeViewStyle, noteditable), \
107         BLT_CONFIG_DONT_SET_DEFAULT},\
108     {BLT_CONFIG_STRING, "-editopts", "editOpts", "EditOpts", \
109         (char *)NULL, Blt_Offset(TreeViewStyle, editOpts), \
110         BLT_CONFIG_NULL_OK}, \
111     {BLT_CONFIG_SYNONYM, "-fg", (char *)NULL, (char *)NULL, (char *)NULL, \
112         0, 0, (ClientData)"-foreground"}, \
113     {BLT_CONFIG_FONT, "-font", (char *)NULL, (char *)NULL, \
114         (char *)NULL, Blt_Offset(TreeViewStyle, font), \
115         BLT_CONFIG_NULL_OK|BLT_CONFIG_DONT_SET_DEFAULT}, \
116     {BLT_CONFIG_COLOR, "-foreground", (char *)NULL, (char *)NULL, \
117         (char *)NULL, Blt_Offset(TreeViewStyle, fgColor), \
118         BLT_CONFIG_NULL_OK|BLT_CONFIG_DONT_SET_DEFAULT }, \
119     {BLT_CONFIG_DISTANCE, "-gap", "gap", "Gap", \
120         DEF_STYLE_GAP, Blt_Offset(TreeViewStyle, gap), \
121         BLT_CONFIG_DONT_SET_DEFAULT}, \
122     {BLT_CONFIG_BOOLEAN, "-hide", (char *)NULL, (char *)NULL, \
123         "False", Blt_Offset(TreeViewStyle, hidden), 0}, \
124     {BLT_CONFIG_BORDER, "-highlightbackground", "highlightBackground", \
125         "HighlightBackground", DEF_STYLE_HIGHLIGHT_BACKGROUND, \
126         Blt_Offset(TreeViewStyle, highlightBorder), \
127         BLT_CONFIG_COLOR_ONLY|BLT_CONFIG_NULL_OK}, \
128     {BLT_CONFIG_COLOR, "-highlightforeground", "highlightForeground", \
129         "HighlightForeground", DEF_STYLE_HIGHLIGHT_FOREGROUND, \
130          Blt_Offset(TreeViewStyle, highlightFgColor), BLT_CONFIG_NULL_OK}, \
131     {BLT_CONFIG_SYNONYM, "-highlightbg",(char *)NULL, \
132         (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-highlightbackground"}, \
133     {BLT_CONFIG_SYNONYM, "-highlightfg", (char *)NULL, \
134         (char *)NULL, (char *)NULL, 0, 0, (ClientData)"-highlightforeground"}, \
135     {BLT_CONFIG_CUSTOM, "-icon", (char *)NULL, (char *)NULL, \
136         (char *)NULL, Blt_Offset(TreeViewStyle, icon), \
137         BLT_CONFIG_NULL_OK, &bltTreeViewIconOption}, \
138     {BLT_CONFIG_INT, "-priority", (char *)NULL, (char *)NULL, \
139         "0", Blt_Offset(TreeViewStyle, priority), 0}, \
140     {BLT_CONFIG_SHADOW, "-shadow", "Shadow", "Shadow", \
141         (char *)NULL, Blt_Offset(TreeViewStyle, shadow), 0}, \
142     {BLT_CONFIG_TILE, "-tile", (char *)NULL, (char *)NULL, \
143         (char *)NULL, Tk_Offset(TreeViewStyle, tile), BLT_CONFIG_NULL_OK, },
144
145 static Blt_ConfigSpec textBoxSpecs[] =
146 {
147     CONF_STYLES
148     {BLT_CONFIG_OBJCMD, "-formatcmd", "formatCmd", "FormatCmd",
149         NULL, Blt_Offset(TreeViewTextBox, formatCmd), 
150         BLT_CONFIG_NULL_OK},
151     {BLT_CONFIG_SIDE, "-side", (char *)NULL, (char *)NULL,
152         DEF_TEXTBOX_SIDE, Tk_Offset(TreeViewTextBox, side),
153         BLT_CONFIG_DONT_SET_DEFAULT},
154     {BLT_CONFIG_SIDE, "-iconside", (char *)NULL, (char *)NULL,
155         DEF_TEXTBOX_SIDE, Tk_Offset(TreeViewTextBox, iconside),
156         BLT_CONFIG_DONT_SET_DEFAULT},
157     {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
158         (char *)NULL, 0, 0}
159 };
160
161 typedef struct {
162     TREEVIEW_STYLE_COMMON
163
164     /* Checkbox specific fields. */
165     int size;                   /* Size of the checkbox. */
166     int showValue;              /* If non-zero, display the on/off value.  */
167     char *onValue;
168     char *offValue;
169     int lineWidth;              /* Linewidth of the surrounding box. */
170     GC bgGC;
171     Tk_3DBorder checkBg;                /* Normal background color of cell. */ \
172
173     XColor *boxColor;           /* Rectangle (box) color (grey). */
174     XColor *fillColor;          /* Fill color (white) */
175     XColor *checkColor;         /* Check color (red). */
176
177     GC boxGC;
178     GC fillGC;                  /* Box fill GC */
179     GC checkGC;
180
181     TextLayout *onPtr, *offPtr;
182     TreeViewIcon *icons;        /* Tk images */
183     int boxX, boxW, boxH;
184     int halo;
185     
186 } TreeViewCheckBox;
187
188 #define DEF_CHECKBOX_BOX_COLOR          "black"
189 #define DEF_CHECKBOX_CHECK_COLOR        "darkblue"
190 #define DEF_CHECKBOX_FILL_COLOR         "white"
191 #define DEF_CHECKBOX_OFFVALUE           "0"
192 #define DEF_CHECKBOX_ONVALUE            "1"
193 #define DEF_CHECKBOX_SHOWVALUE          "yes"
194 #define DEF_CHECKBOX_HALO               "0"
195 #define DEF_CHECKBOX_SIZE               "11"
196 #define DEF_CHECKBOX_LINEWIDTH          "1"
197 #define DEF_CHECKBOX_GAP                "4"
198 #ifdef WIN32
199 #define DEF_CHECKBOX_CURSOR             "arrow"
200 #else
201 #define DEF_CHECKBOX_CURSOR             "hand2"
202 #endif /*WIN32*/
203
204 static Blt_ConfigSpec checkBoxSpecs[] =
205 {
206     CONF_STYLES
207     {BLT_CONFIG_COLOR, "-boxcolor", "boxColor", "BoxColor", 
208         DEF_CHECKBOX_BOX_COLOR, Blt_Offset(TreeViewCheckBox, boxColor), 0},
209     {BLT_CONFIG_DISTANCE, "-boxsize", "boxSize", "BoxSize",
210         DEF_CHECKBOX_SIZE, Blt_Offset(TreeViewCheckBox, size), 
211         BLT_CONFIG_DONT_SET_DEFAULT},
212     {BLT_CONFIG_BORDER, "-checkbg", "checkBg", "checkBg",
213         (char *)NULL, Blt_Offset(TreeViewCheckBox, checkBg), BLT_CONFIG_NULL_OK},
214     {BLT_CONFIG_COLOR, "-checkcolor", "checkColor", "CheckColor", 
215         DEF_CHECKBOX_CHECK_COLOR, Blt_Offset(TreeViewCheckBox, checkColor), 0},
216     {BLT_CONFIG_CUSTOM, "-checkicons", "checkIcons", "CheckIcons",
217         (char *)NULL, Blt_Offset(TreeViewCheckBox, icons),
218         BLT_CONFIG_NULL_OK, &bltTreeViewIconsOption},
219     {BLT_CONFIG_COLOR, "-fillcolor", "fillColor", "FillColor", 
220         DEF_CHECKBOX_FILL_COLOR, Blt_Offset(TreeViewCheckBox, fillColor), 0},
221     {BLT_CONFIG_TILE, "-filltile", "fillTile", "FillTile",
222         (char *)NULL, Blt_Offset(TreeViewCheckBox, fillTile), BLT_CONFIG_NULL_OK, },
223     {BLT_CONFIG_INT, "-halo", "halo", "Halo",
224         DEF_CHECKBOX_HALO, Blt_Offset(TreeViewCheckBox, halo), 
225         0},
226     {BLT_CONFIG_DISTANCE, "-linewidth", "lineWidth", "LineWidth",
227         DEF_CHECKBOX_LINEWIDTH, 
228         Blt_Offset(TreeViewCheckBox, lineWidth),
229         BLT_CONFIG_DONT_SET_DEFAULT},
230     {BLT_CONFIG_STRING, "-offvalue", "offValue", "OffValue",
231         DEF_CHECKBOX_OFFVALUE, Blt_Offset(TreeViewCheckBox, offValue), 
232         BLT_CONFIG_NULL_OK},
233     {BLT_CONFIG_STRING, "-onvalue", "onValue", "OnValue",
234         DEF_CHECKBOX_ONVALUE, Blt_Offset(TreeViewCheckBox, onValue), 
235         BLT_CONFIG_NULL_OK},
236     {BLT_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue",
237         DEF_CHECKBOX_SHOWVALUE, Blt_Offset(TreeViewCheckBox, showValue), 
238         BLT_CONFIG_DONT_SET_DEFAULT},
239     {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
240         (char *)NULL, 0, 0}
241 };
242
243 typedef struct {
244     TREEVIEW_STYLE_COMMON
245
246     /* ComboBox-specific fields */
247
248     int borderWidth;            /* Width of outer border surrounding
249                                  * the entire box. */
250     char *choiceCmd;            /* Command to get list of available choices. */
251     char *choices;              /* List of available choices. */
252     char *choiceKey;            /* Key to get list of available choices. */
253     int scrollWidth;
254     int button;
255     int buttonWidth;
256     int buttonBorderWidth;      /* Border width of button. */
257     int buttonRelief;           /* Normal relief of button. */
258     TreeViewIcon *buttonIcons;
259
260 } TreeViewComboBox;
261
262 #define DEF_COMBOBOX_BORDERWIDTH        "1"
263 #define DEF_COMBOBOX_BUTTON_BORDERWIDTH "1"
264 #define DEF_COMBOBOX_BUTTON_RELIEF      "raised"
265 #define DEF_COMBOBOX_RELIEF             "flat"
266 #ifdef WIN32
267 #define DEF_COMBOBOX_CURSOR             "arrow"
268 #else
269 #define DEF_COMBOBOX_CURSOR             "hand2"
270 #endif /*WIN32*/
271
272
273 static Blt_ConfigSpec comboBoxSpecs[] =
274 {
275     CONF_STYLES
276     {BLT_CONFIG_SYNONYM, "-bd", (char *)NULL, (char *)NULL, (char *)NULL, 0, 
277         0, (ClientData)"-borderwidth"},
278     {BLT_CONFIG_DISTANCE, "-borderwidth", (char *)NULL, (char *)NULL,
279         DEF_COMBOBOX_BORDERWIDTH, Blt_Offset(TreeViewComboBox, borderWidth),
280         BLT_CONFIG_DONT_SET_DEFAULT},
281     {BLT_CONFIG_DISTANCE, "-buttonborderwidth", "buttonBorderWidth", 
282         "ButtonBorderWidth", DEF_COMBOBOX_BUTTON_BORDERWIDTH, 
283         Blt_Offset(TreeViewComboBox, buttonBorderWidth),
284         BLT_CONFIG_DONT_SET_DEFAULT},
285     {BLT_CONFIG_CUSTOM, "-buttonicons", "buttonIcons", "ButtonIcons",
286         (char *)NULL, Blt_Offset(TreeViewComboBox, buttonIcons),
287         BLT_CONFIG_NULL_OK, &bltTreeViewIconsOption},
288     {BLT_CONFIG_RELIEF, "-buttonrelief", "buttonRelief", "ButtonRelief",
289         DEF_COMBOBOX_BUTTON_RELIEF, Blt_Offset(TreeViewComboBox, buttonRelief),
290         BLT_CONFIG_DONT_SET_DEFAULT},
291     {BLT_CONFIG_STRING, "-choicecmd", "choiceCmd", "ChoiceCmd",
292         (char *)NULL, Blt_Offset(TreeViewComboBox, choiceCmd), 
293         BLT_CONFIG_NULL_OK, 0},
294     {BLT_CONFIG_STRING, "-choicekey", "choiceKey", "ChoiceKey",
295         (char *)NULL, Blt_Offset(TreeViewComboBox, choiceKey), 
296         BLT_CONFIG_NULL_OK, 0},
297     {BLT_CONFIG_STRING, "-choices", "choices", "Choices",
298         (char *)NULL, Blt_Offset(TreeViewComboBox, choices), 
299         BLT_CONFIG_NULL_OK, 0},
300     {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
301         (char *)NULL, 0, 0}
302 };
303
304 typedef struct {
305     TREEVIEW_STYLE_COMMON
306
307     int windowHeight;
308     int windowWidth;
309     char *windowCmd;
310     int sticky;
311
312 } TreeViewWindowBox;
313
314 #define STICK_NORTH     (1<<0)
315 #define STICK_EAST      (1<<1)
316 #define STICK_SOUTH     (1<<2)
317 #define STICK_WEST      (1<<3)
318
319 static Blt_CustomOption bltStickyOption = { 
320     ObjToSticky, StickyToObj, NULL, NULL,
321 };
322
323 #define DEF_COMBOBOX_BORDERWIDTH        "1"
324 #define DEF_COMBOBOX_BUTTON_BORDERWIDTH "1"
325 #define DEF_COMBOBOX_BUTTON_RELIEF      "raised"
326 #define DEF_COMBOBOX_RELIEF             "flat"
327 #ifdef WIN32
328 #define DEF_COMBOBOX_CURSOR             "arrow"
329 #else
330 #define DEF_COMBOBOX_CURSOR             "hand2"
331 #endif /*WIN32*/
332
333 static Blt_ConfigSpec windowBoxSpecs[] =
334 {
335     {BLT_CONFIG_STRING, "-windowcmd", "windowCmd", "windowCmd",
336         (char *)NULL, Blt_Offset(TreeViewWindowBox, windowCmd), 
337         BLT_CONFIG_NULL_OK, 0},
338     {BLT_CONFIG_INT, "-minwidth", "WindowWidth", "WindowWidth",
339         "0", Blt_Offset(TreeViewWindowBox, windowWidth), 0},
340     {BLT_CONFIG_INT, "-minheight", "WindowHeight", "WindowHeight",
341         "0", Blt_Offset(TreeViewWindowBox, windowHeight), 0},
342     {BLT_CONFIG_CUSTOM, "-sticky", "sticky", "Sticky",
343         "w", Tk_Offset(TreeViewWindowBox, sticky),
344         0, &bltStickyOption},
345         
346     {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
347         (char *)NULL, 0, 0}
348 };
349
350 typedef struct {
351     TREEVIEW_STYLE_COMMON
352
353     /* Barbox specific fields. */
354     GC bgGC;
355     Tk_3DBorder barBg;          /* Normal background color of cell. */ \
356
357     int showValue;              /* If non-zero, display the on/off value.  */
358     double minValue;
359     double maxValue;
360     int lineWidth;              /* Linewidth of the surrounding box. */
361     Tcl_Obj *formatCmd;
362
363     XColor *boxColor;           /* Rectangle (box) color (grey). */
364     XColor *fillColor;          /* Fill color (white) */
365
366     GC boxGC;
367     GC fillGC;                  /* Box fill GC */
368
369     int barWidth;
370     int barHeight;
371     
372 } TreeViewBarBox;
373
374 #define DEF_BARBOX_BOX_COLOR            "black"
375 #define DEF_BARBOX_FILL_COLOR           "darkgreen"
376 #define DEF_BARBOX_MINVALUE             "0.0"
377 #define DEF_BARBOX_MAXVALUE             "100.0"
378 #define DEF_BARBOX_WIDTH                "80"
379 #define DEF_BARBOX_HEIGHT               "10"
380 #define DEF_BARBOX_SHOWVALUE            "yes"
381 #define DEF_BARBOX_LINEWIDTH            "1"
382 #define DEF_BARBOX_GAP          "4"
383 #ifdef WIN32
384 #define DEF_BARBOX_CURSOR               "arrow"
385 #else
386 #define DEF_BARBOX_CURSOR               "hand2"
387 #endif /*WIN32*/
388
389 static Blt_ConfigSpec barBoxSpecs[] =
390 {
391     CONF_STYLES
392     {BLT_CONFIG_BORDER, "-barbg", "barBg", "BarBg",
393         (char *)NULL, Blt_Offset(TreeViewBarBox, barBg), BLT_CONFIG_NULL_OK},
394     {BLT_CONFIG_COLOR, "-barfg", "barFg", "BarFg", 
395         DEF_BARBOX_FILL_COLOR, Blt_Offset(TreeViewBarBox, fillColor), 0},
396     {BLT_CONFIG_COLOR, "-boxcolor", "boxColor", "BoxColor", 
397         DEF_BARBOX_BOX_COLOR, Blt_Offset(TreeViewBarBox, boxColor), 0},
398     {BLT_CONFIG_INT, "-barwidth", "barWidth", "BarWidth",
399         DEF_BARBOX_WIDTH, Blt_Offset(TreeViewBarBox, barWidth), 0},
400     {BLT_CONFIG_INT, "-barheight", "BarHeight", "BarHeight",
401         DEF_BARBOX_HEIGHT, Blt_Offset(TreeViewBarBox, barHeight), 0},
402     {BLT_CONFIG_TILE, "-filltile", "fillTile", "FillTile",
403         (char *)NULL, Tk_Offset(TreeViewBarBox, fillTile), BLT_CONFIG_NULL_OK, },
404     {BLT_CONFIG_OBJCMD, "-formatcmd", "formatCmd", "FormatCmd",
405         NULL, Blt_Offset(TreeViewBarBox, formatCmd), 
406         BLT_CONFIG_NULL_OK},
407     {BLT_CONFIG_DISTANCE, "-linewidth", "lineWidth", "LineWidth",
408         DEF_BARBOX_LINEWIDTH, 
409         Blt_Offset(TreeViewBarBox, lineWidth),
410         BLT_CONFIG_DONT_SET_DEFAULT},
411     {BLT_CONFIG_DOUBLE, "-maxvalue", "maxValue", "MaxValue",
412         DEF_BARBOX_MAXVALUE, Blt_Offset(TreeViewBarBox, maxValue), 0},
413     {BLT_CONFIG_DOUBLE, "-minvalue", "minValue", "MinValue",
414         DEF_BARBOX_MINVALUE, Blt_Offset(TreeViewBarBox, minValue), 0},
415     {BLT_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue",
416         DEF_BARBOX_SHOWVALUE, Blt_Offset(TreeViewBarBox, showValue), 
417         BLT_CONFIG_DONT_SET_DEFAULT},
418     {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
419         (char *)NULL, 0, 0}
420 };
421
422 typedef union {
423     TreeViewTextBox tb;
424     TreeViewCheckBox cb;
425     TreeViewComboBox cob;
426     TreeViewBarBox bb;
427     TreeViewWindowBox wb;
428 } TreeViewAllStyles;
429
430 typedef TreeViewStyle *(StyleCreateProc) _ANSI_ARGS_((TreeView *tvPtr, 
431         Blt_HashEntry *hPtr));
432
433 static StyleConfigProc ConfigureTextBox, ConfigureCheckBox, ConfigureComboBox, ConfigureWindowBox, ConfigureBarBox;
434 static StyleCreateProc CreateTextBox, CreateCheckBox, CreateComboBox, CreateWindowBox, CreateBarBox;
435 static StyleDrawProc DrawTextBox, DrawCheckBox, DrawComboBox, DrawWindowBox, DrawBarBox;
436 static StyleEditProc EditTextBox, EditCheckBox, EditComboBox, EditWindowBox, EditBarBox;
437 static StyleFreeProc FreeTextBox, FreeCheckBox, FreeComboBox, FreeWindowBox, FreeBarBox;
438 static StyleMeasureProc MeasureTextBox, MeasureCheckBox, MeasureComboBox, MeasureWindowBox, MeasureBarBox;
439 static StylePickProc PickComboBox;
440
441
442 static Tcl_Obj *
443 StickyToObj(clientData, interp, tkwin, widgRec, offset)
444     ClientData clientData;      /* Not used. */
445     Tcl_Interp *interp;
446     Tk_Window tkwin;            /* Not used. */
447     char *widgRec;
448     int offset;
449 {
450     int flags = *(int *)(widgRec + offset);
451
452     int count = 0;
453     char result[10];
454
455     if (flags&STICK_NORTH) result[count++] = 'n';
456     if (flags&STICK_EAST)  result[count++] = 'e';
457     if (flags&STICK_SOUTH) result[count++] = 's';
458     if (flags&STICK_WEST)  result[count++] = 'w';
459
460     result[count] = '\0';
461     return Tcl_NewStringObj(result, -1);
462 }
463
464 static int
465 ObjToSticky(clientData, interp, tkwin, objPtr, widgRec, offset)
466     ClientData clientData;      /* Not used. */
467     Tcl_Interp *interp;         /* Interpreter to send results back to */
468     Tk_Window tkwin;            /* Not used. */
469     Tcl_Obj *objPtr;            /* Tcl_Obj representing the new value. */
470     char *widgRec;
471     int offset;
472 {
473     /* TreeView *tvPtr = clientData; */
474     int *stickyPtr = (int *)(widgRec + offset);
475     int sticky = 0;
476     char c;
477     char *value;
478     
479     value = Tcl_GetString(objPtr);
480
481     while ((c = *value++) != '\0') {
482         switch (c) {
483         case 'n': case 'N': sticky |= STICK_NORTH; break;
484         case 'e': case 'E': sticky |= STICK_EAST;  break;
485         case 's': case 'S': sticky |= STICK_SOUTH; break;
486         case 'w': case 'W': sticky |= STICK_WEST;  break;
487         case ' ': case ',': case '\t': case '\r': case '\n': break;
488         default:
489             Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
490                                    "bad sticky value \"", --value,
491                                    "\": must contain n, s, e or w",
492                                    (char *) NULL);
493             return TCL_ERROR;
494         }
495     }
496     *stickyPtr = sticky;
497     return TCL_OK;
498 }               
499
500
501 /*
502  *----------------------------------------------------------------------
503  *
504  * ObjToIcon --
505  *
506  *      Convert the name of an icon into a Tk image.
507  *
508  * Results:
509  *      If the string is successfully converted, TCL_OK is returned.
510  *      Otherwise, TCL_ERROR is returned and an error message is left in
511  *      interpreter's result field.
512  *
513  *----------------------------------------------------------------------
514  */
515 /*ARGSUSED*/
516 static int
517 ObjToIcon(clientData, interp, tkwin, objPtr, widgRec, offset)
518     ClientData clientData;      /* Not used. */
519     Tcl_Interp *interp;         /* Interpreter to send results back to */
520     Tk_Window tkwin;            /* Not used. */
521     Tcl_Obj *objPtr;            /* Tcl_Obj representing the new value. */
522     char *widgRec;
523     int offset;
524 {
525     TreeView *tvPtr = clientData;
526     TreeViewIcon *iconPtr = (TreeViewIcon *)(widgRec + offset);
527     TreeViewIcon icon;
528
529     icon = Blt_TreeViewGetIcon(tvPtr, Tcl_GetString(objPtr));
530     if (icon == NULL) {
531         return TCL_ERROR;
532     }
533     *iconPtr = icon;
534     return TCL_OK;
535 }
536 /*
537  *----------------------------------------------------------------------
538  *
539  * IconToObj --
540  *
541  *      Converts the icon into its string representation (its name).
542  *
543  * Results:
544  *      The name of the icon is returned.
545  *
546  *----------------------------------------------------------------------
547  */
548 /*ARGSUSED*/
549 static Tcl_Obj *
550 IconToObj(clientData, interp, tkwin, widgRec, offset)
551     ClientData clientData;      /* Not used. */
552     Tcl_Interp *interp;
553     Tk_Window tkwin;            /* Not used. */
554     char *widgRec;
555     int offset;
556 {
557     TreeViewIcon icon = *(TreeViewIcon *)(widgRec + offset);
558
559     return Tcl_NewStringObj(icon?Blt_NameOfImage((icon)->tkImage):"", -1);
560 }
561
562 /*ARGSUSED*/
563 static int
564 FreeIcon(clientData, display, widgRec, offset, oldPtr)
565     ClientData clientData;
566     Display *display;           /* Not used. */
567     char *widgRec;
568     int offset;
569     char *oldPtr;
570 {
571     TreeViewIcon icon = (TreeViewIcon)(oldPtr);
572     TreeView *tvPtr = clientData;
573
574     Blt_TreeViewFreeIcon(tvPtr, icon);
575     return TCL_OK;
576 }
577
578 static TreeViewStyleClass textBoxClass = {
579     "TextBoxStyle",
580     textBoxSpecs,
581     ConfigureTextBox,
582     MeasureTextBox,
583     DrawTextBox,
584     NULL,
585     EditTextBox,
586     FreeTextBox,
587 };
588
589 static TreeViewStyleClass checkBoxClass = {
590     "CheckBoxStyle",
591     checkBoxSpecs,
592     ConfigureCheckBox,
593     MeasureCheckBox,
594     DrawCheckBox,
595     NULL,
596     EditCheckBox,
597     FreeCheckBox,
598 };
599
600 static TreeViewStyleClass comboBoxClass = {
601     "ComboBoxStyle", 
602     comboBoxSpecs,
603     ConfigureComboBox,
604     MeasureComboBox,
605     DrawComboBox,
606     PickComboBox,
607     EditComboBox,
608     FreeComboBox,
609 };
610
611 static TreeViewStyleClass windowBoxClass = {
612     "WindowBoxStyle",
613     windowBoxSpecs,
614     ConfigureWindowBox,
615     MeasureWindowBox,
616     DrawWindowBox,
617     NULL,
618     EditWindowBox,
619     FreeWindowBox,
620 };
621
622 static TreeViewStyleClass barBoxClass = {
623     "BarBoxStyle",
624     barBoxSpecs,
625     ConfigureBarBox,
626     MeasureBarBox,
627     DrawBarBox,
628     NULL,
629     EditBarBox,
630     FreeBarBox,
631 };
632
633 int Blt_TreeViewStyleIsFmt (TreeView *tvPtr,
634     TreeViewStyle *stylePtr)
635 {
636     if (stylePtr->classPtr ==  &textBoxClass) {
637         TreeViewTextBox *tbPtr;
638         tbPtr = (TreeViewTextBox *)stylePtr;
639         if (tbPtr->formatCmd != NULL && strlen(Tcl_GetString(tbPtr->formatCmd))) {
640             return 1;
641         }
642         return 0;
643     }
644     if (stylePtr->classPtr ==  &barBoxClass) {
645         TreeViewBarBox *bbPtr;
646         bbPtr = (TreeViewBarBox *)stylePtr;
647         if (bbPtr->formatCmd != NULL && strlen(Tcl_GetString(bbPtr->formatCmd))) {
648             return 1;
649         }
650         return 0;
651     }
652     return 0;
653 }
654
655 /* Allocate a new style. */
656 static TreeViewStyle *newStyle(TreeView *tvPtr, Blt_HashEntry *hPtr, int size) {
657     TreeViewStyle *stylePtr;
658     stylePtr = Blt_Calloc(1, sizeof(TreeViewAllStyles));
659     /*stylePtr = Blt_Calloc(1, size); */
660     assert(stylePtr);
661     stylePtr->gap = STYLE_GAP;
662     stylePtr->name = Blt_Strdup(Blt_GetHashKey(&tvPtr->styleTable, hPtr));
663     stylePtr->hashPtr = hPtr;
664     stylePtr->refCount = 1;
665     Blt_SetHashValue(hPtr, stylePtr);
666     return stylePtr;
667 }
668 /*
669  *----------------------------------------------------------------------
670  *
671  * CreateTextBox --
672  *
673  *      Creates a "textbox" style.
674  *
675  * Results:
676  *      A pointer to the new style structure.
677  *
678  *----------------------------------------------------------------------
679  */
680 static TreeViewStyle *
681 CreateTextBox(tvPtr, hPtr)
682     TreeView *tvPtr;
683     Blt_HashEntry *hPtr;
684 {
685     TreeViewTextBox *tbPtr;
686
687     tbPtr = (TreeViewTextBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewTextBox));
688     tbPtr->classPtr = &textBoxClass;
689     tbPtr->iconside = SIDE_LEFT;
690     tbPtr->side = SIDE_TOP;
691     tbPtr->flags = STYLE_TEXTBOX;
692     return (TreeViewStyle *)tbPtr;
693 }
694
695 /*
696  *----------------------------------------------------------------------
697  *
698  * ConfigureTextBox --
699  *
700  *      Configures a "textbox" style.  This routine performs 
701  *      generates the GCs required for a textbox style.
702  *
703  * Results:
704  *      None.
705  *
706  * Side Effects:
707  *      GCs are created for the style.
708  *
709  *----------------------------------------------------------------------
710  */
711 static void
712 ConfigureTextBox(tvPtr, stylePtr)
713     TreeView *tvPtr;
714     TreeViewStyle *stylePtr;
715 {
716     GC newGC;
717     XColor *bgColor;
718     XGCValues gcValues;
719     unsigned long gcMask;
720
721     gcMask = GCForeground | GCBackground | GCFont;
722     gcValues.font = Tk_FontId(CHOOSE(tvPtr->font, stylePtr->font));
723     bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, stylePtr->border));
724
725     gcValues.background = bgColor->pixel;
726     gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
727     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
728     if (stylePtr->gc != NULL) {
729         Tk_FreeGC(tvPtr->display, stylePtr->gc);
730     }
731     stylePtr->gc = newGC;
732     if (stylePtr->highlightBorder) {
733         gcValues.background = Tk_3DBorderColor(stylePtr->highlightBorder)->pixel;
734     } else {
735         gcValues.background = bgColor->pixel;
736     }
737     if (stylePtr->highlightFgColor) {
738         gcValues.foreground = stylePtr->highlightFgColor->pixel;
739     } else {
740         gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
741     }
742     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
743     if (stylePtr->highlightGC != NULL) {
744         Tk_FreeGC(tvPtr->display, stylePtr->highlightGC);
745     }
746     stylePtr->highlightGC = newGC;
747
748     if (stylePtr->activeBorder) {
749         gcValues.background = Tk_3DBorderColor(stylePtr->activeBorder)->pixel;
750     } else {
751         gcValues.background = bgColor->pixel;
752     }
753     if (stylePtr->activeFgColor) {
754         gcValues.foreground = stylePtr->activeFgColor->pixel;
755     } else {
756         gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
757     }
758     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
759     if (stylePtr->activeGC != NULL) {
760         Tk_FreeGC(tvPtr->display, stylePtr->activeGC);
761     }
762     stylePtr->activeGC = newGC;
763     stylePtr->flags |= STYLE_DIRTY;
764 }
765
766 /*
767  *----------------------------------------------------------------------
768  *
769  * MeasureTextBox --
770  *
771  *      Determines the space requirements for the "textbox" given
772  *      the value to be displayed.  Depending upon whether an icon
773  *      or text is displayed and their relative placements, this
774  *      routine computes the space needed for the text entry.
775  *
776  * Results:
777  *      None.
778  *
779  * Side Effects:
780  *      The width and height fields of *valuePtr* are set with the
781  *      computed dimensions.
782  *
783  *----------------------------------------------------------------------
784  */
785 static void
786 MeasureTextBox(tvPtr, stylePtr, valuePtr)
787     TreeView *tvPtr;
788     TreeViewStyle *stylePtr;
789     TreeViewValue *valuePtr;
790 {
791     TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
792     TreeViewColumn *columnPtr = valuePtr->columnPtr;
793     int iconWidth, iconHeight;
794     int textWidth, textHeight;
795     int gap;
796     TreeViewIcon icon;
797     int rel = 0;
798
799     textWidth = textHeight = 0;
800     iconWidth = iconHeight = 0;
801     valuePtr->width = valuePtr->height = 0;
802     icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
803     if (icon != NULL && tvPtr->hideStyleIcons == 0) {
804         iconWidth = TreeViewIconWidth(icon);
805         iconHeight = TreeViewIconHeight(icon);
806     } 
807     if (valuePtr->textPtr != NULL) {
808         Blt_Free(valuePtr->textPtr);
809         valuePtr->textPtr = NULL;
810     }
811 #define NotNullObj(p) ((p != NULL && strlen(Tcl_GetString(p))) ? p : NULL)
812
813     if (valuePtr->string != NULL) {
814         /* New string defined. */
815         TextStyle ts;
816         Tcl_Obj *fmtObj;
817         
818         fmtObj = NotNullObj(tbPtr->formatCmd);
819         if (fmtObj == NULL) {
820             fmtObj = NotNullObj(columnPtr->formatCmd);
821         }
822         if (fmtObj == NULL) {
823             fmtObj = NotNullObj(tvPtr->formatCmd);
824         }
825
826         Blt_InitTextStyle(&ts);
827         ts.font = CHOOSE3(tvPtr->font, columnPtr->font , stylePtr->font);
828         ts.anchor = TK_ANCHOR_NW;
829         ts.justify = columnPtr->justify;
830         if (fmtObj != NULL) {
831             Tcl_DString cmdString;
832             char *string;
833             int result;
834             Tcl_Interp *interp = tvPtr->interp;
835
836             Tcl_Preserve(valuePtr->entryPtr);
837             rel = 1;
838             Blt_TreeViewPercentSubst(tvPtr, valuePtr->entryPtr, columnPtr, Tcl_GetString(fmtObj), valuePtr->string, &cmdString);
839             result = Tcl_GlobalEval(interp, Tcl_DStringValue(&cmdString));
840             Blt_TreeViewOptsInit(tvPtr);
841             Tcl_DStringFree(&cmdString);
842             if (result == TCL_OK) {
843                 string = Tcl_GetStringResult(interp);
844                 valuePtr->textPtr = Blt_GetTextLayoutStr(string, &ts);
845             }
846          }
847          if (valuePtr->textPtr == NULL) {
848              valuePtr->textPtr = Blt_GetTextLayoutStr(valuePtr->string, &ts);
849          }
850     } 
851     gap = 0;
852     if (valuePtr->textPtr != NULL && tvPtr->hideStyleText == 0) {
853         textWidth = valuePtr->textPtr->width;
854         textHeight = valuePtr->textPtr->height;
855         if (stylePtr->icon != NULL) {
856             gap = stylePtr->gap;
857         }
858     }
859     if (SIDE_VERTICAL(tbPtr->iconside)) {
860         valuePtr->height = iconHeight + gap + textHeight;
861         valuePtr->width = MAX(textWidth, iconWidth);
862     } else {
863         valuePtr->width = iconWidth + gap + textWidth;
864         valuePtr->height = MAX(textHeight, iconHeight);
865     }
866     if (rel) {
867         Tcl_Release(valuePtr->entryPtr);
868     }
869 }
870
871 /* 
872 * Fill in the bg, fg, font from styles from value, entry, column and tvjj. */
873 static void
874 GetPriorityStyle(
875     TreeView *tvPtr,
876     TreeViewEntry *entryPtr,
877     TreeViewValue *valuePtr,
878     TreeViewStyle *inStylePtr,
879     TreeViewStyle *stylePtr
880     ) {
881     TreeViewStyle *s[4];
882     int i = -1, bgprio = -1, fgprio = -1, fntprio = -1;
883     int disabled = (entryPtr->state == STATE_DISABLED);
884
885     s[0] = valuePtr?valuePtr->stylePtr:NULL;
886     s[1] = entryPtr?entryPtr->stylePtr:NULL;
887     s[2] = valuePtr?valuePtr->columnPtr->stylePtr:NULL;
888     s[3] = tvPtr->stylePtr;
889     /*stylePtr->font = CHOOSE3(tvPtr->font, inStylePtr->font, entryPtr->font); */
890     stylePtr->font = tvPtr->font;
891     if (valuePtr != NULL && valuePtr->columnPtr->font) {
892         stylePtr->font = valuePtr->columnPtr->font;
893         stylePtr->gc = valuePtr->columnPtr->textGC;
894     } else if (inStylePtr->font) {
895         stylePtr->font = inStylePtr->font;
896         stylePtr->gc = stylePtr->gc;
897     }
898     stylePtr->border = CHOOSE3(tvPtr->border, inStylePtr->border, entryPtr->border);
899     if (disabled) {
900         stylePtr->fgColor = tvPtr->disabledColor;
901     } else if (valuePtr != NULL) {
902         stylePtr->fgColor = CHOOSE4(tvPtr->fgColor, valuePtr->columnPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
903     } else {
904         stylePtr->fgColor = CHOOSE3(tvPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
905     }
906     while (++i<4) {
907         if (s[i]) {
908             if (s[i]->border && (s[i]->priority>bgprio||stylePtr->border==NULL)) {
909                 stylePtr->border = s[i]->border;
910                 bgprio = s[i]->priority;
911             } 
912             if (disabled == 0 && s[i]->fgColor && (s[i]->priority>fgprio||stylePtr->fgColor==NULL)) {
913                 stylePtr->fgColor = s[i]->fgColor;
914                 fgprio = s[i]->priority;
915             } 
916             if (s[i]->font && (s[i]->priority>fntprio||stylePtr->font==NULL)) {
917                 stylePtr->font = s[i]->font;
918                 stylePtr->gc = s[i]->gc;
919                 fntprio = s[i]->priority;
920             } 
921         }
922     }
923 }
924
925 /* Fill in stylePtr with font, border, fgColor, etc. UNUSED */
926 void
927 Blt_GetPriorityStyle(
928     TreeViewStyle *stylePtr,  /* Style to fillin. */
929     TreeView *tvPtr,
930     TreeViewColumn *columnPtr,
931     TreeViewEntry *entryPtr,
932     TreeViewValue *valuePtr,
933     TreeViewStyle *inStylePtr,
934     int flags
935 ) {
936     TreeViewStyle *s[20];
937     int n = 0, i = -1;
938     int bgprio = -1, fgprio = -1, fntprio = -1, shadprio = -1, tileprio = -1;
939     int iconprio = -1;
940     int disabled = (entryPtr->state == STATE_DISABLED);
941
942     if ((flags&STYLEFLAG_NOCLEAR) == 0) {
943         memset(stylePtr, 0, sizeof(*stylePtr));
944     }
945     /* Is a sub label */
946     if ((flags&STYLEFLAG_SUBSTYLE) && tvPtr->subStylePtr) {
947         s[n++] = tvPtr->subStylePtr;
948     }
949     /* Is an empty value. */
950     if ((flags&STYLEFLAG_EMPTYSTYLE) && tvPtr->emptyStylePtr) {
951         s[n++] = tvPtr->emptyStylePtr;
952     }
953     /* Is an alt row. */
954     if ((flags&STYLEFLAG_ALTSTYLE) && tvPtr->altStylePtr) {
955         s[n++] = tvPtr->altStylePtr;
956     }
957     /* Is a title. */
958     if ((flags&STYLEFLAG_TITLESTYLE) && columnPtr && columnPtr->titleStylePtr) {
959         s[n++] = columnPtr->titleStylePtr;
960     }
961     if (inStylePtr) s[n++] = inStylePtr;
962     if (valuePtr && valuePtr->stylePtr) s[n++] = valuePtr->stylePtr;
963     if (entryPtr && entryPtr->stylePtr) s[n++] = entryPtr->stylePtr;
964     if (columnPtr && columnPtr->stylePtr) s[n++] = columnPtr->stylePtr;
965     if (tvPtr->stylePtr)  s[n++] = tvPtr->stylePtr;
966     if (inStylePtr == NULL) inStylePtr = tvPtr->stylePtr;
967     /*stylePtr->font = CHOOSE(tvPtr->font,  entryPtr->font); */
968     /*stylePtr->font = tvPtr->font;
969     stylePtr->border = tvPtr->border;
970     stylePtr->fgColor = tvPtr->fgColor;
971     stylePtr->shadow.color = NULL;
972     stylePtr->tile = NULL;
973     stylePtr->icon = NULL;*/
974     stylePtr->gc = (entryPtr?entryPtr->gc:NULL);
975     /* stylePtr->font = tvPtr->font; */
976     if (valuePtr != NULL && valuePtr->columnPtr->font) {
977         stylePtr->font = valuePtr->columnPtr->font;
978         stylePtr->gc = valuePtr->columnPtr->textGC;
979     } else if (inStylePtr->font) {
980         stylePtr->font = inStylePtr->font;
981         stylePtr->gc = stylePtr->gc;
982     } else if (columnPtr && columnPtr->font) {
983         stylePtr->font = columnPtr->font;
984         stylePtr->gc = columnPtr->textGC;
985     }
986     stylePtr->border = CHOOSE3(tvPtr->border, inStylePtr->border, entryPtr->border);
987     if (disabled) {
988         stylePtr->fgColor = tvPtr->disabledColor;
989     } else if (valuePtr != NULL) {
990         stylePtr->fgColor = CHOOSE4(tvPtr->fgColor, valuePtr->columnPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
991     } else {
992         stylePtr->fgColor = CHOOSE3(tvPtr->fgColor, inStylePtr->fgColor, entryPtr->color);
993     }
994     i = -1;
995     while (++i<n) {
996         if (s[i]->border && (s[i]->priority>bgprio||stylePtr->border==NULL)) {
997             stylePtr->border = s[i]->border;
998             bgprio = s[i]->priority;
999         } 
1000         if (disabled == 0 && s[i]->fgColor && (s[i]->priority>fgprio||stylePtr->fgColor==NULL)) {
1001             stylePtr->fgColor = s[i]->fgColor;
1002             fgprio = s[i]->priority;
1003         } 
1004         if (s[i]->font && (s[i]->priority>fntprio||stylePtr->font==NULL)) {
1005             stylePtr->font = s[i]->font;
1006             fntprio = s[i]->priority;
1007             stylePtr->gc = s[i]->gc;
1008         } 
1009         if (s[i]->shadow.color && (s[i]->priority>shadprio||stylePtr->shadow.color==NULL)) {
1010             stylePtr->shadow = s[i]->shadow;
1011             shadprio = s[i]->priority;
1012         } 
1013         if (s[i]->icon && (s[i]->priority>iconprio||stylePtr->icon==NULL)) {
1014             stylePtr->icon = s[i]->icon;
1015             iconprio = s[i]->priority;
1016         } 
1017         if (s[i]->tile && (s[i]->priority>tileprio||stylePtr->tile==NULL)) {
1018             stylePtr->tile = s[i]->tile;
1019             tileprio = s[i]->priority;
1020         } 
1021     }
1022     if (entryPtr == NULL) {
1023         if (stylePtr->font==NULL) stylePtr->font = tvPtr->font;
1024         if (stylePtr->border==NULL) stylePtr->border = tvPtr->border;
1025         if (stylePtr->fgColor==NULL) stylePtr->fgColor = tvPtr->fgColor;
1026     } else {
1027         if (stylePtr->font==NULL) stylePtr->font = CHOOSE3(tvPtr->font,(columnPtr?columnPtr->font:NULL),entryPtr->font);
1028         if (stylePtr->border==NULL) stylePtr->border = CHOOSE(tvPtr->border,entryPtr->border);
1029         if (stylePtr->fgColor==NULL) stylePtr->fgColor = CHOOSE(tvPtr->fgColor,entryPtr->color);
1030         if (stylePtr->shadow.color==NULL) stylePtr->shadow = entryPtr->shadow;
1031     }
1032     if (stylePtr->tile==NULL) stylePtr->tile = tvPtr->tile;
1033 }
1034
1035 #define IFSET(var,val) var = (val?val:var)
1036
1037 /* Fill background. */
1038 /* TODO: return GC for element/style that sets the font!!!! */
1039 /* TODO: lookup font from style for Measure routines. */
1040 void
1041 drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, sRec)
1042     TreeView *tvPtr;
1043     Drawable drawable;
1044     TreeViewEntry *entryPtr;
1045     TreeViewValue *valuePtr;
1046     TreeViewStyle *stylePtr;
1047     TreeViewIcon icon;
1048     int x, y;
1049     TreeViewStyle *sRec;
1050 {
1051     TreeViewColumn *columnPtr;
1052     int altRow = (entryPtr->flags&ENTRY_ALTROW);
1053
1054     columnPtr = valuePtr->columnPtr;
1055     sRec->font = CHOOSE(tvPtr->font, columnPtr->font);
1056     sRec->fgColor = CHOOSE(tvPtr->fgColor, columnPtr->fgColor);
1057     sRec->border = tvPtr->border;
1058     sRec->gc = tvPtr->stylePtr->gc;
1059     GetPriorityStyle(tvPtr, entryPtr, valuePtr, stylePtr, sRec);
1060     /* TODO: fix font/gc bug where altStyle has tile and bg */
1061     if ((tvPtr->activeColumnPtr == valuePtr->columnPtr && tvPtr->actCol) ||
1062         (valuePtr == tvPtr->activeValuePtr) ||
1063         (tvPtr->activeButtonPtr == entryPtr && tvPtr->actEntry) ||
1064         (stylePtr->flags & STYLE_HIGHLIGHT)) {
1065         IFSET(sRec->border, stylePtr->highlightBorder);
1066         IFSET(sRec->fgColor, stylePtr->highlightFgColor);
1067      } else if (valuePtr->stylePtr && valuePtr->stylePtr->border) {
1068          sRec->border = valuePtr->stylePtr->border;
1069      } else if (columnPtr->hasbg) {
1070          sRec->border = columnPtr->border;
1071      /*((tvPtr->tile != NULL || columnPtr->tile != NULL) && stylePtr->tile==NULL)*/
1072      } else if ((Blt_HasTile(tvPtr->tile) || Blt_HasTile(columnPtr->tile)) && Blt_HasTile(stylePtr->tile)==0) {
1073          sRec->border = NULL;
1074      } else if (altRow && tvPtr->altStylePtr &&  Blt_HasTile(tvPtr->altStylePtr->tile)) {
1075          stylePtr = tvPtr->altStylePtr;
1076     }
1077     if (!Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
1078         /*
1079         * Draw the active or normal background color over the entire
1080         * label area.  This includes both the tab's text and image.
1081         * The rectangle should be 2 pixels wider/taller than this
1082         * area. So if the label consists of just an image, we get an
1083         * halo around the image when the tab is active.
1084         */
1085         if (sRec->border != NULL && (altRow==0 ||
1086         (altRow && stylePtr->tile && stylePtr == tvPtr->altStylePtr))) {
1087              Blt_TreeViewFill3DTile(tvPtr, drawable, sRec->border,
1088                x - columnPtr->pad.side1, y - tvPtr->leader/2, 
1089                columnPtr->width, entryPtr->height,
1090                0, TK_RELIEF_FLAT,  entryPtr->gc?NULL:stylePtr->tile, tvPtr->scrollTile, 1);
1091         }
1092     }
1093 }
1094
1095 /*
1096  * Set fg color based on string pattern match
1097  */
1098 static void
1099 GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, fgPtr)
1100     TreeView *tvPtr;
1101     TreeViewEntry *entryPtr;
1102     TreeViewValue *valuePtr;
1103     TreeViewStyle *stylePtr;
1104     XColor **fgPtr;
1105 {
1106     XColor *color = NULL;
1107     Tcl_Interp *interp = tvPtr->interp;
1108     int objc, i;
1109     Tcl_Obj **objv, *objPtr = NULL;
1110     TreeViewColumn *columnPtr = valuePtr->columnPtr;
1111             
1112     if (columnPtr->colorPats != NULL && strlen(Tcl_GetString(columnPtr->colorPats))) {
1113         if (Tcl_ListObjGetElements(NULL, columnPtr->colorPats, &objc, &objv) != TCL_OK) return;
1114         if (objc%2) return;
1115         for (i = 0; i < objc; i += 2) {
1116             if (Tcl_StringMatch(valuePtr->string, Tcl_GetString(objv[i]))) {
1117                 color = Tk_AllocColorFromObj(interp, tvPtr->tkwin, objv[i+1]);
1118                 if (color != NULL) {
1119                     *fgPtr = color;
1120                     return;
1121                 }
1122             }
1123         }
1124     } 
1125     if (columnPtr->colorRegex != NULL && strlen(Tcl_GetString(columnPtr->colorRegex))) {
1126         if (Tcl_ListObjGetElements(NULL, columnPtr->colorRegex, &objc, &objv) != TCL_OK) return;
1127         if (objc%2) return;
1128         for (i = 0; i < objc; i += 2) {
1129             if (objPtr == NULL) {
1130                 objPtr = Tcl_NewStringObj(valuePtr->string,-1);
1131                 Tcl_IncrRefCount(objPtr);
1132             }
1133             if (Tcl_RegExpMatchObj(NULL, objPtr, objv[i]) == 1) {
1134                 color = Tk_AllocColorFromObj(interp, tvPtr->tkwin, objv[i+1]);
1135                 if (color != NULL) {
1136                     *fgPtr = color;
1137                     break;
1138                 }
1139             }
1140         }
1141         if (objPtr != NULL) {
1142             Tcl_DecrRefCount(objPtr);
1143         }
1144     } 
1145 }
1146
1147 /*
1148  *----------------------------------------------------------------------
1149  *
1150  * DrawTextBox --
1151  *
1152  *      Draws the "textbox" given the screen coordinates and the
1153  *      value to be displayed.  
1154  *
1155  * Results:
1156  *      None.
1157  *
1158  * Side Effects:
1159  *      The textbox value is drawn.
1160  *
1161  *----------------------------------------------------------------------
1162  */
1163 static void
1164 DrawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
1165     TreeView *tvPtr;
1166     Drawable drawable;
1167     TreeViewEntry *entryPtr;
1168     TreeViewValue *valuePtr;
1169     TreeViewStyle *stylePtr;
1170     TreeViewIcon icon;
1171     int x, y;
1172 {
1173     GC gc;
1174     TreeViewColumn *columnPtr;
1175     TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
1176     int iconX, iconY, iconWidth, iconHeight;
1177     int textX, textY, textWidth, textHeight;
1178     int gap, columnWidth, ix = x;
1179     TreeViewStyle sRec = *stylePtr;
1180     int valWidth;
1181     TextLayout *layPtr;
1182
1183     layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
1184     columnPtr = valuePtr->columnPtr;
1185     valWidth = (layPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
1186     if (!stylePtr) return;
1187     drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
1188     gc = sRec.gc;
1189     columnWidth = columnPtr->width - 
1190         (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
1191
1192     textX = textY = iconX = iconY = 0;  /* Suppress compiler warning. */
1193     
1194     iconWidth = iconHeight = 0;
1195     if (icon != NULL) {
1196         iconWidth = TreeViewIconWidth(icon);
1197         iconHeight = TreeViewIconHeight(icon);
1198     }
1199     textWidth = textHeight = 0;
1200     if (layPtr != NULL) {
1201         textWidth = layPtr->width;
1202         textHeight = layPtr->height;
1203     }
1204     gap = 0;
1205     if ((icon != NULL) && (layPtr != NULL)) {
1206         gap = stylePtr->gap;
1207     }
1208     if (columnWidth >= valWidth) {
1209         switch(columnPtr->justify) {
1210         case TK_JUSTIFY_RIGHT:
1211             ix = x + columnWidth - iconWidth;
1212             x += (columnWidth - valWidth);
1213             break;
1214         case TK_JUSTIFY_CENTER:
1215             ix = x + (columnWidth - iconWidth)/2;
1216             x += (columnWidth - valWidth) / 2;
1217             break;
1218         case TK_JUSTIFY_LEFT:
1219             break;
1220         }
1221     }
1222
1223     switch (tbPtr->iconside) {
1224     case SIDE_RIGHT:
1225         textX = x;
1226         textY = y + (entryPtr->height - textHeight) / 2;
1227         iconX = textX + textWidth + gap;
1228         iconY = y + (entryPtr->height - iconHeight) / 2;
1229         break;
1230     case SIDE_LEFT:
1231         iconX = x;
1232         iconY = y + (entryPtr->height - iconHeight) / 2;
1233         textX = iconX + iconWidth + gap;
1234         textY = y + (entryPtr->height - textHeight) / 2;
1235         break;
1236     case SIDE_TOP:
1237         iconY = y;
1238         if (tbPtr->side == SIDE_BOTTOM) {
1239             iconY = y + (entryPtr->height - textHeight - iconHeight - gap*2);
1240         }
1241         iconX = ix;
1242         textY = iconY + iconHeight + gap;
1243         textX = x;
1244         if (iconWidth>textWidth) {
1245             textX = x + (iconWidth-textWidth)/2;
1246         }
1247         break;
1248     case SIDE_BOTTOM:
1249         textX = x;
1250         textY = y;
1251         if (tbPtr->side == SIDE_BOTTOM) {
1252             textY = y + (entryPtr->height - textHeight - iconHeight - gap*2);
1253         }
1254         if (iconWidth>textWidth) {
1255             textX = x + (iconWidth-textWidth)/2;
1256         }
1257         iconY = textY + textHeight + gap;
1258         iconX = ix;
1259         break;
1260     }
1261     valuePtr->iX = iconX;
1262     valuePtr->iY = iconY;
1263     valuePtr->iW = iconWidth;
1264     valuePtr->iH = iconHeight;
1265     valuePtr->tX = textX;
1266     valuePtr->tY = textY;
1267     valuePtr->tW = textWidth;
1268     valuePtr->tH = textHeight;
1269     if (icon != NULL) {
1270         if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth, 
1271                        iconHeight, drawable, iconX, iconY) != TCL_OK) return;
1272     }
1273     if (layPtr != NULL) {
1274         TextStyle ts;
1275         XColor *color;
1276         int disabled = (entryPtr->state == STATE_DISABLED);
1277         
1278         if (disabled) {
1279             color = tvPtr->disabledColor;
1280         } else if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
1281             color = SELECT_FG(tvPtr);
1282         } else if (entryPtr->color != NULL) {
1283             color = entryPtr->color;
1284         } else {
1285             color = sRec.fgColor;
1286             GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
1287         }
1288         XSetForeground(tvPtr->display, gc, color->pixel);
1289         Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor,
1290             stylePtr->shadow.color, 0.0, 
1291             TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
1292         Blt_DrawTextLayout(tvPtr->tkwin, drawable, layPtr, 
1293                 &ts, textX, textY);
1294         if (color != sRec.fgColor) {
1295             XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
1296         }
1297      } else {
1298          valuePtr->tW = 0;
1299      }
1300     stylePtr->flags &= ~STYLE_DIRTY;
1301 }
1302
1303 /*
1304  *----------------------------------------------------------------------
1305  *
1306  * EditTextbox --
1307  *
1308  *      Edits the "textbox".
1309  *
1310  * Results:
1311  *      None.
1312  *
1313  * Side Effects:
1314  *      The checkbox value is drawn.
1315  *
1316  *----------------------------------------------------------------------
1317  */
1318 /*ARGSUSED*/
1319 static int
1320 EditTextBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
1321     TreeView *tvPtr;
1322     TreeViewEntry *entryPtr;
1323     TreeViewValue *valuePtr;
1324     TreeViewStyle *stylePtr;    /* Not used. */
1325     int x;
1326     int y;
1327     int *retVal;
1328 {
1329     int isTest = *retVal;
1330     *retVal = 0;
1331     if (isTest) {
1332         return TCL_OK;
1333     }
1334     return Blt_TreeViewTextbox(tvPtr, entryPtr, valuePtr->columnPtr);
1335 }
1336
1337
1338 /*
1339  *----------------------------------------------------------------------
1340  *
1341  * FreeTextBox --
1342  *
1343  *      Releases resources allocated for the textbox. The resources
1344  *      freed by this routine are specific only to the "textbox".   
1345  *      Other resources (common to all styles) are freed in the 
1346  *      Blt_TreeViewFreeStyle routine.
1347  *
1348  * Results:
1349  *      None.
1350  *
1351  * Side Effects:
1352  *      GCs allocated for the textbox are freed.
1353  *
1354  *----------------------------------------------------------------------
1355  */
1356 static void
1357 FreeTextBox(tvPtr, stylePtr)
1358     TreeView *tvPtr;
1359     TreeViewStyle *stylePtr;
1360 {
1361     if (!stylePtr) return;
1362     if (stylePtr->highlightGC != NULL) {
1363         Tk_FreeGC(tvPtr->display, stylePtr->highlightGC);
1364     }
1365     if (stylePtr->activeGC != NULL) {
1366         Tk_FreeGC(tvPtr->display, stylePtr->activeGC);
1367     }
1368     if (stylePtr->gc != NULL) {
1369         Tk_FreeGC(tvPtr->display, stylePtr->gc);
1370     }
1371     if (stylePtr->icon != NULL) {
1372         Blt_TreeViewFreeIcon(tvPtr, stylePtr->icon);
1373     }
1374     
1375 }
1376
1377
1378 /*
1379  *----------------------------------------------------------------------
1380  *
1381  * CreateCheckbox --
1382  *
1383  *      Creates a "checkbox" style.
1384  *
1385  * Results:
1386  *      A pointer to the new style structure.
1387  *
1388  *----------------------------------------------------------------------
1389  */
1390 static TreeViewStyle *
1391 CreateCheckBox(tvPtr, hPtr)
1392     TreeView *tvPtr;
1393     Blt_HashEntry *hPtr;
1394 {
1395     TreeViewCheckBox *cbPtr;
1396
1397     cbPtr = (TreeViewCheckBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewCheckBox));
1398     cbPtr->classPtr = &checkBoxClass;
1399     cbPtr->gap = 4;
1400     cbPtr->size = 11;
1401     cbPtr->lineWidth = 1;
1402     cbPtr->showValue = TRUE;
1403     cbPtr->flags = STYLE_CHECKBOX;
1404     return (TreeViewStyle *)cbPtr;
1405 }
1406
1407 /*
1408  *----------------------------------------------------------------------
1409  *
1410  * ConfigureCheckbox --
1411  *
1412  *      Configures a "checkbox" style.  This routine performs 
1413  *      generates the GCs required for a checkbox style.
1414  *
1415  * Results:
1416  *      None.
1417  *
1418  * Side Effects:
1419  *      GCs are created for the style.
1420  *
1421  *----------------------------------------------------------------------
1422  */
1423 static void
1424 ConfigureCheckBox(tvPtr, stylePtr)
1425     TreeView *tvPtr;
1426     TreeViewStyle *stylePtr;
1427 {
1428     GC newGC;
1429     TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1430     XColor *bgColor;
1431     XGCValues gcValues;
1432     unsigned long gcMask;
1433
1434     bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, stylePtr->border));
1435
1436     gcValues.background = bgColor->pixel;
1437     gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
1438     ConfigureTextBox(tvPtr, stylePtr);
1439     gcMask = GCForeground;
1440     gcValues.foreground = cbPtr->fillColor->pixel;
1441     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1442     if (cbPtr->fillGC != NULL) {
1443         Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
1444     }
1445     cbPtr->fillGC = newGC;
1446
1447     gcMask = GCForeground | GCLineWidth;
1448     gcValues.line_width = cbPtr->lineWidth;
1449     gcValues.foreground = cbPtr->boxColor->pixel;
1450     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1451     if (cbPtr->boxGC != NULL) {
1452         Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
1453     }
1454     cbPtr->boxGC = newGC;
1455
1456     gcMask = GCForeground | GCLineWidth;
1457     gcValues.line_width = 1;
1458     gcValues.foreground = cbPtr->checkColor->pixel;
1459     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1460     if (cbPtr->checkGC != NULL) {
1461         Tk_FreeGC(tvPtr->display, cbPtr->checkGC);
1462     }
1463     cbPtr->checkGC = newGC;
1464     if (cbPtr->checkBg) {
1465         bgColor = Tk_3DBorderColor(cbPtr->checkBg);
1466         gcValues.background = bgColor->pixel;
1467         gcValues.foreground = bgColor->pixel;
1468         newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
1469         if (cbPtr->bgGC != NULL) {
1470             Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
1471         }
1472         cbPtr->bgGC = newGC;
1473     }
1474     stylePtr->flags |= STYLE_DIRTY;
1475 }
1476
1477 /*
1478  *----------------------------------------------------------------------
1479  *
1480  * MeasureCheckbox --
1481  *
1482  *      Determines the space requirements for the "checkbox" given
1483  *      the value to be displayed.  Depending upon whether an icon
1484  *      or text is displayed and their relative placements, this
1485  *      routine computes the space needed for the text entry.
1486  *
1487  * Results:
1488  *      None.
1489  *
1490  * Side Effects:
1491  *      The width and height fields of *valuePtr* are set with the
1492  *      computed dimensions.
1493  *
1494  *----------------------------------------------------------------------
1495  */
1496 static void
1497 MeasureCheckBox(tvPtr, stylePtr, valuePtr)
1498     TreeView *tvPtr;
1499     TreeViewStyle *stylePtr;
1500     TreeViewValue *valuePtr;
1501 {
1502     TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1503     TreeViewColumn *columnPtr = valuePtr->columnPtr;
1504     int iconWidth, iconHeight;
1505     int textWidth, textHeight;
1506     int gap;
1507     int boxWidth, boxHeight;
1508     TreeViewIcon icon;
1509
1510     boxWidth = boxHeight = ODD(cbPtr->size);
1511
1512     if (cbPtr->icons) {
1513         TreeViewIcon mIcon;
1514         int i;
1515         
1516         for (i=0; i<2; i++) {
1517             mIcon = cbPtr->icons[i];
1518             if (mIcon) {
1519                 int mwid = TreeViewIconWidth(mIcon);
1520                 int mhig = TreeViewIconHeight(mIcon);
1521                 if (mwid>boxWidth) { boxWidth = mwid; }
1522                 if (mhig>boxHeight) { boxHeight = mhig; }
1523             }
1524         }
1525     }
1526     textWidth = textHeight = iconWidth = iconHeight = 0;
1527     valuePtr->width = valuePtr->height = 0;
1528     icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
1529     if (icon != NULL && tvPtr->hideStyleIcons == 0) {
1530         iconWidth = TreeViewIconWidth(icon);
1531         iconHeight = TreeViewIconHeight(icon);
1532     } 
1533     if (cbPtr->onPtr != NULL) {
1534         Blt_Free(cbPtr->onPtr);
1535         cbPtr->onPtr = NULL;
1536     }
1537     if (cbPtr->offPtr != NULL) {
1538         Blt_Free(cbPtr->offPtr);
1539         cbPtr->offPtr = NULL;
1540     }
1541     gap = 0;
1542     if (cbPtr->showValue && tvPtr->hideStyleText == 0) {
1543         TextStyle ts;
1544         char *string;
1545
1546         Blt_InitTextStyle(&ts);
1547         ts.font = CHOOSE3(tvPtr->font, columnPtr->font, stylePtr->font);
1548         ts.anchor = TK_ANCHOR_NW;
1549         ts.justify = columnPtr->justify;
1550         string = (cbPtr->onValue != NULL) ? cbPtr->onValue : valuePtr->string;
1551         cbPtr->onPtr = Blt_GetTextLayout(string, &ts);
1552         string = (cbPtr->offValue != NULL) ? cbPtr->offValue : valuePtr->string;
1553         cbPtr->offPtr = Blt_GetTextLayout(string, &ts);
1554         textWidth = MAX(cbPtr->offPtr->width, cbPtr->onPtr->width);
1555         textHeight = MAX(cbPtr->offPtr->height, cbPtr->onPtr->height);
1556         if (stylePtr->icon != NULL) {
1557             gap = stylePtr->gap;
1558         }
1559     }
1560     valuePtr->width = stylePtr->gap * 2 + boxWidth + iconWidth + gap + textWidth;
1561     valuePtr->height = MAX3(boxHeight, textHeight, iconHeight);
1562 }
1563
1564 /*
1565  *----------------------------------------------------------------------
1566  *
1567  * 
1568 box --
1569  *
1570  *      Draws the "checkbox" given the screen coordinates and the
1571  *      value to be displayed.  
1572  *
1573  * Results:
1574  *      None.
1575  *
1576  * Side Effects:
1577  *      The checkbox value is drawn.
1578  *
1579  *----------------------------------------------------------------------
1580  */
1581 static void
1582 DrawCheckBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
1583     TreeView *tvPtr;
1584     Drawable drawable;
1585     TreeViewEntry *entryPtr;
1586     TreeViewValue *valuePtr;
1587     TreeViewStyle *stylePtr;
1588     TreeViewIcon icon;
1589     int x, y;
1590 {
1591     GC gc;
1592     TreeViewColumn *columnPtr;
1593     TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1594     int iconX, iconY, iconWidth, iconHeight;
1595     int textX, textY, textHeight;
1596     int gap, columnWidth, ttlWidth;
1597     int bool;
1598     int borderWidth, relief;
1599     TextLayout *textPtr;
1600     int boxX, boxY, boxWidth, boxHeight;
1601     TreeViewStyle *csPtr, sRec = *stylePtr;
1602     int valWidth = (valuePtr->textPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
1603     TextLayout *layPtr;
1604     int showValue;
1605
1606     layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
1607     showValue = (tvPtr->hideStyleText ? 0 : cbPtr->showValue);
1608
1609     columnPtr = valuePtr->columnPtr;
1610     csPtr = columnPtr->stylePtr;
1611     
1612     drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
1613     gc = sRec.gc;
1614
1615     if (gc != stylePtr->activeGC) {
1616         borderWidth = 0;
1617         relief = TK_RELIEF_FLAT;
1618     } else {
1619         borderWidth = 1;
1620         relief = TK_RELIEF_RAISED;
1621     }
1622
1623     columnWidth = columnPtr->width - PADDING(columnPtr->pad);
1624     if (!valuePtr->string) {
1625         return;
1626     }
1627
1628     if (cbPtr->size) {
1629         boxWidth = boxHeight = ODD(cbPtr->size);
1630     } else {
1631         boxWidth = boxHeight = 0;
1632     }
1633     ttlWidth = ( boxWidth + stylePtr->gap * 2);
1634     if (showValue) {
1635         ttlWidth += (valWidth + stylePtr->gap);
1636     }
1637     if (icon != NULL) {
1638         iconWidth = TreeViewIconWidth(icon);
1639         iconHeight = TreeViewIconHeight(icon);
1640         ttlWidth += iconWidth + stylePtr->gap;
1641     }
1642
1643     if (columnWidth > ttlWidth) {
1644         switch(columnPtr->justify) {
1645             case TK_JUSTIFY_RIGHT:
1646             x += (columnWidth - ttlWidth - stylePtr->gap*2);
1647             break;
1648             case TK_JUSTIFY_CENTER:
1649             x += (columnWidth - ttlWidth) / 2;
1650             break;
1651             case TK_JUSTIFY_LEFT:
1652             break;
1653         }
1654     }
1655
1656     bool = (strcmp(valuePtr->string, cbPtr->onValue) == 0);
1657     textPtr = (bool) ? cbPtr->onPtr : cbPtr->offPtr;
1658
1659     cbPtr->boxW = cbPtr->boxH = 0;
1660     cbPtr->boxX = boxX = x + stylePtr->gap;
1661     boxY = y + (entryPtr->height - boxHeight) / 2;
1662
1663     if (cbPtr->icons != NULL) {
1664         TreeViewIcon mIcon;
1665         mIcon = cbPtr->icons[bool];
1666         if (mIcon) {
1667             int mwid = TreeViewIconWidth(mIcon);
1668             int mhig = TreeViewIconHeight(mIcon);
1669             cbPtr->boxW = mwid;
1670             cbPtr->boxH = mhig;
1671             boxY = y + (entryPtr->height - mhig) / 2;
1672             if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, mIcon, 0, 0, mwid, 
1673                 mhig, drawable, boxX, boxY) != TCL_OK) return;
1674         }
1675         
1676     } else {
1677         /*
1678          * Draw the box and check. 
1679          *
1680          *              +-----------+
1681          *              |           |
1682          *              |         * |
1683          *      |        *  |
1684          *      | *     *   |
1685          *      |  *   *    |
1686          *      |   * *     |
1687          *              |    *      |
1688          *              +-----------+
1689          */
1690          if (boxWidth) {
1691              if (cbPtr->checkBg) {
1692                  XFillRectangle(tvPtr->display, drawable, cbPtr->bgGC, boxX, boxY, 
1693                     boxWidth, boxHeight);
1694              } else {
1695                  if (Blt_HasTile(stylePtr->fillTile)) {
1696                      Blt_SetTileOrigin(tvPtr->tkwin, stylePtr->fillTile, -boxX, -boxY);
1697                      Blt_TileRectangle(tvPtr->tkwin, drawable, stylePtr->fillTile,
1698                          boxX, boxY, boxWidth, boxHeight );
1699                  } else if (csPtr != NULL && Blt_HasTile(csPtr->fillTile)) {
1700                      Blt_SetTileOrigin(tvPtr->tkwin, csPtr->fillTile, -boxX, -boxY);
1701                      Blt_TileRectangle(tvPtr->tkwin, drawable, csPtr->fillTile,
1702                          boxX, boxY, boxWidth, boxHeight );
1703                 } else {
1704                     XFillRectangle(tvPtr->display, drawable, cbPtr->fillGC, boxX, boxY, boxWidth, boxHeight);
1705     
1706                  }
1707             }
1708             cbPtr->boxW = boxWidth;
1709             cbPtr->boxH = boxHeight;
1710             XDrawRectangle(tvPtr->display, drawable, cbPtr->boxGC, boxX, boxY, 
1711                 boxWidth, boxHeight);
1712     
1713             if (bool) {
1714                 int midX, midY;
1715                 int i;
1716     
1717                 for (i = 0; i < 3; i++) {
1718                     midX = boxX + 2 * boxWidth / 5;
1719                     midY = boxY + boxHeight - 5 + i;
1720                     XDrawLine(tvPtr->display, drawable, cbPtr->checkGC, 
1721                     boxX + 2, boxY + boxHeight / 3 + 1 + i, midX, midY);
1722                     XDrawLine(tvPtr->display, drawable, cbPtr->checkGC, 
1723                     midX, midY, boxX + boxWidth - 2, boxY + i + 1);
1724                 }
1725             }
1726         }
1727     }
1728 #ifdef notdef
1729     textX = textY = iconX = iconY = 0;  /* Suppress compiler warning. */
1730 #endif
1731     iconWidth = iconHeight = 0;
1732     if (icon != NULL) {
1733         iconWidth = TreeViewIconWidth(icon);
1734         iconHeight = TreeViewIconHeight(icon);
1735     }
1736     textHeight = 0;
1737     gap = 0;
1738     if (showValue) {
1739         textHeight = textPtr->height;
1740         if (icon != NULL) {
1741             gap = stylePtr->gap;
1742         }
1743     }
1744     x = boxX + boxWidth + stylePtr->gap;
1745
1746     /* The icon sits to the left of the text. */
1747     iconX = x;
1748     iconY = y + (entryPtr->height - iconHeight) / 2;
1749     textX = iconX + iconWidth + gap;
1750     textY = y + (entryPtr->height - textHeight) / 2;
1751
1752     valuePtr->iX = iconX;
1753     valuePtr->iY = iconY;
1754     valuePtr->iW = iconWidth;
1755     valuePtr->iH = iconHeight;
1756     valuePtr->tX = textX;
1757     valuePtr->tY = textY;
1758     valuePtr->tW = (textPtr?textPtr->width:0);
1759     valuePtr->tH = textHeight;
1760     
1761     if (icon != NULL) {
1762         if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth, 
1763                        iconHeight, drawable, iconX, iconY) != TCL_OK) return;
1764     } else {
1765         valuePtr->iW = 0;
1766     }
1767     if ((showValue) && (textPtr != NULL)) {
1768         TextStyle ts;
1769         XColor *color;
1770         
1771          int disabled = (entryPtr->state == STATE_DISABLED);
1772         
1773         if (disabled) {
1774             color = tvPtr->disabledColor;
1775         } else  if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
1776             color = SELECT_FG(tvPtr);
1777         } else if (entryPtr->color != NULL) {
1778             color = entryPtr->color;
1779         } else {
1780             color = sRec.fgColor;
1781             GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
1782          }
1783         XSetForeground(tvPtr->display, gc, color->pixel);
1784         Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor,
1785            stylePtr->shadow.color, 0.0, 
1786            TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
1787         Blt_DrawTextLayout(tvPtr->tkwin, drawable, textPtr, &ts, textX, textY);
1788         if (color != sRec.fgColor) {
1789             XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
1790         }
1791     } else {
1792         valuePtr->tW = 0;
1793     }
1794     stylePtr->flags &= ~STYLE_DIRTY;
1795 }
1796
1797 #if 0
1798 /*
1799  *----------------------------------------------------------------------
1800  *
1801  * PickCheckbox --
1802  *
1803  *      Draws the "checkbox" given the screen coordinates and the
1804  *      value to be displayed.  
1805  *
1806  * Results:
1807  *      None.
1808  *
1809  * Side Effects:
1810  *      The checkbox value is drawn.
1811  *
1812  *----------------------------------------------------------------------
1813  */
1814 static int
1815 PickCheckBox(entryPtr, valuePtr, stylePtr, worldX, worldY)
1816     TreeViewEntry *entryPtr;
1817     TreeViewValue *valuePtr;
1818     TreeViewStyle *stylePtr;
1819     int worldX, worldY;
1820 {
1821     TreeViewColumn *columnPtr;
1822     TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1823     int columnWidth;
1824     int x, y, width, height;
1825
1826     columnPtr = valuePtr->columnPtr;
1827     columnWidth = columnPtr->width - 
1828         (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
1829     if (columnWidth > valuePtr->width) {
1830         switch(columnPtr->justify) {
1831         case TK_JUSTIFY_RIGHT:
1832             worldX += (columnWidth - valuePtr->width);
1833             break;
1834         case TK_JUSTIFY_CENTER:
1835             worldX += (columnWidth - valuePtr->width) / 2;
1836             break;
1837         case TK_JUSTIFY_LEFT:
1838             break;
1839         }
1840     }
1841     width = height = ODD(cbPtr->size) + 2 * cbPtr->lineWidth;
1842     x = columnPtr->worldX + columnPtr->pad.side1 + stylePtr->gap - 
1843         cbPtr->lineWidth;
1844     y = entryPtr->worldY + (entryPtr->height - height) / 2;
1845     if ((worldX >= x) && (worldX < (x + width)) && 
1846         (worldY >= y) && (worldY < (y + height))) {
1847         return TRUE;
1848     }
1849     return FALSE;
1850 }
1851 #endif
1852 /*
1853  *----------------------------------------------------------------------
1854  *
1855  * EditCheckbox --
1856  *
1857  *      Edits the "checkbox".
1858  *
1859  * Results:
1860  *      None.
1861  *
1862  * Side Effects:
1863  *      The checkbox value is drawn.
1864  *
1865  *----------------------------------------------------------------------
1866  */
1867 static int
1868 EditCheckBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
1869     TreeView *tvPtr;
1870     TreeViewEntry *entryPtr;
1871     TreeViewValue *valuePtr;
1872     TreeViewStyle *stylePtr;
1873     int x;
1874     int y;
1875     int *retVal;
1876 {
1877     TreeViewColumn *columnPtr;
1878     TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1879     Tcl_Obj *objPtr;
1880     int boxY, isTest = *retVal;
1881     TreeViewStyle *vsPtr;
1882
1883     *retVal = 1;
1884     columnPtr = valuePtr->columnPtr;
1885     if (Blt_TreeGetValueByKey(tvPtr->interp, tvPtr->tree, 
1886               entryPtr->node, columnPtr->key, &objPtr) != TCL_OK) {
1887         return TCL_ERROR;
1888     }
1889     vsPtr = valuePtr->stylePtr;
1890     if (vsPtr && vsPtr->noteditable) {
1891         *retVal = 0;
1892         return TCL_OK;
1893     }
1894     boxY = SCREENY(tvPtr, entryPtr->worldY) +  (entryPtr->height -cbPtr->boxH) / 2;
1895     if (cbPtr->halo>=0) {
1896         int h = cbPtr->halo;
1897         
1898         if (x < (cbPtr->boxX - h) || x > (cbPtr->boxX + cbPtr->boxW + h) ||
1899             y < (boxY - h) || y > (boxY + cbPtr->boxH + h)) {
1900             *retVal = 0;
1901             return TCL_OK;
1902         }
1903     }
1904     if (isTest) {
1905         return TCL_OK;
1906     }
1907     if (strcmp(Tcl_GetString(objPtr), cbPtr->onValue) == 0) {
1908         objPtr = Tcl_NewStringObj(cbPtr->offValue, -1);
1909     } else {
1910         objPtr = Tcl_NewStringObj(cbPtr->onValue, -1);
1911     }
1912     entryPtr->flags |= ENTRY_DIRTY;
1913     tvPtr->flags |= (TV_DIRTY | TV_LAYOUT | TV_SCROLL | TV_RESORT);
1914     if (Blt_TreeSetValueByKey(tvPtr->interp, tvPtr->tree, 
1915               entryPtr->node, columnPtr->key, objPtr) != TCL_OK) {
1916         return TCL_ERROR;
1917     }
1918     return TCL_OK;
1919 }
1920
1921 /*
1922  *----------------------------------------------------------------------
1923  *
1924  * FreeCheckbox --
1925  *
1926  *      Releases resources allocated for the checkbox. The resources
1927  *      freed by this routine are specific only to the "checkbox".   
1928  *      Other resources (common to all styles) are freed in the 
1929  *      Blt_TreeViewFreeStyle routine.
1930  *
1931  * Results:
1932  *      None.
1933  *
1934  * Side Effects:
1935  *      GCs allocated for the checkbox are freed.
1936  *
1937  *----------------------------------------------------------------------
1938  */
1939 static void
1940 FreeCheckBox(tvPtr, stylePtr)
1941     TreeView *tvPtr;
1942     TreeViewStyle *stylePtr;
1943 {
1944     TreeViewCheckBox *cbPtr = (TreeViewCheckBox *)stylePtr;
1945
1946     FreeTextBox(tvPtr, stylePtr);
1947     if (cbPtr->fillGC != NULL) {
1948         Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
1949     }
1950     if (cbPtr->boxGC != NULL) {
1951         Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
1952     }
1953     if (cbPtr->checkGC != NULL) {
1954         Tk_FreeGC(tvPtr->display, cbPtr->checkGC);
1955     }
1956     if (cbPtr->offPtr != NULL) {
1957         Blt_Free(cbPtr->offPtr);
1958     }
1959     if (cbPtr->onPtr != NULL) {
1960         Blt_Free(cbPtr->onPtr);
1961     }
1962     if (cbPtr->bgGC != NULL) {
1963         Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
1964     }
1965 }
1966
1967 /*
1968  *----------------------------------------------------------------------
1969  *
1970  * CreateComboBox --
1971  *
1972  *      Creates a "combobox" style.
1973  *
1974  * Results:
1975  *      A pointer to the new style structure.
1976  *
1977  *----------------------------------------------------------------------
1978  */
1979 static TreeViewStyle *
1980 CreateComboBox(tvPtr, hPtr)
1981     TreeView *tvPtr;
1982     Blt_HashEntry *hPtr;
1983 {
1984     TreeViewComboBox *cbPtr;
1985
1986     cbPtr = (TreeViewComboBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewComboBox));
1987     cbPtr->classPtr = &comboBoxClass;
1988     cbPtr->buttonRelief = TK_RELIEF_RAISED;
1989     cbPtr->buttonBorderWidth = 1;
1990     cbPtr->borderWidth = 1;
1991     cbPtr->flags = STYLE_COMBOBOX;
1992     return (TreeViewStyle *)cbPtr;
1993 }
1994
1995 /*
1996  *----------------------------------------------------------------------
1997  *
1998  * ConfigureComboBox --
1999  *
2000  *      Configures a "combobox" style.  This routine performs 
2001  *      generates the GCs required for a combobox style.
2002  *
2003  * Results:
2004  *      None.
2005  *
2006  * Side Effects:
2007  *      GCs are created for the style.
2008  *
2009  *----------------------------------------------------------------------
2010  */
2011 static void
2012 ConfigureComboBox(tvPtr, stylePtr)
2013     TreeView *tvPtr;
2014     TreeViewStyle *stylePtr;
2015 {
2016     ConfigureTextBox(tvPtr, stylePtr);
2017 }
2018
2019 /*
2020  *----------------------------------------------------------------------
2021  *
2022  * MeasureComboBox --
2023  *
2024  *      Determines the space requirements for the "combobox" given
2025  *      the value to be displayed.  Depending upon whether an icon
2026  *      or text is displayed and their relative placements, this
2027  *      routine computes the space needed for the text entry.
2028  *
2029  * Results:
2030  *      None.
2031  *
2032  * Side Effects:
2033  *      The width and height fields of *valuePtr* are set with the
2034  *      computed dimensions.
2035  *
2036  *----------------------------------------------------------------------
2037  */
2038 static void
2039 MeasureComboBox(tvPtr, stylePtr, valuePtr)
2040     TreeView *tvPtr;
2041     TreeViewStyle *stylePtr;
2042     TreeViewValue *valuePtr;
2043 {
2044     TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr;
2045     TreeViewColumn *columnPtr = valuePtr->columnPtr;
2046     int iconWidth, iconHeight, biconWidth, biconHeight;
2047     int textWidth, textHeight;
2048     int gap;
2049     Tk_Font font;
2050     TreeViewIcon icon, *butIcons;
2051
2052     textWidth = textHeight = 0;
2053     iconWidth = iconHeight = 0;
2054     valuePtr->width = valuePtr->height = 0;
2055
2056     butIcons = cbPtr->buttonIcons;
2057     icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
2058     if (icon != NULL && tvPtr->hideStyleIcons == 0) {
2059         iconWidth = TreeViewIconWidth(icon);
2060         iconHeight = TreeViewIconHeight(icon);
2061     } 
2062     if (valuePtr->textPtr != NULL) {
2063         Blt_Free(valuePtr->textPtr);
2064         valuePtr->textPtr = NULL;
2065     }
2066     font = CHOOSE3(tvPtr->font, columnPtr->font, stylePtr->font);
2067     if (valuePtr->string != NULL) {     /* New string defined. */
2068         TextStyle ts;
2069
2070         Blt_InitTextStyle(&ts);
2071         ts.font = font;
2072         ts.anchor = TK_ANCHOR_NW;
2073         ts.justify = valuePtr->columnPtr->justify;
2074         valuePtr->textPtr = Blt_GetTextLayoutStr(valuePtr->string, &ts);
2075     } 
2076     gap = 0;
2077     if (valuePtr->textPtr != NULL && tvPtr->hideStyleText == 0) {
2078         textWidth = valuePtr->textPtr->width;
2079         textHeight = valuePtr->textPtr->height;
2080         if (stylePtr->icon != NULL) {
2081             gap = stylePtr->gap;
2082         }
2083     }
2084     if (butIcons != NULL) {
2085         TreeViewIcon mIcon;
2086         int i;
2087         
2088         biconWidth = 0;
2089         biconHeight = 0;
2090         for (i=0; i<2; i++) {
2091             mIcon = butIcons[i];
2092             if (!mIcon) continue;
2093             biconWidth = MAX(biconWidth,TreeViewIconWidth(mIcon));
2094             biconHeight = MAX(biconHeight,TreeViewIconHeight(mIcon));
2095         }
2096         biconHeight = MAX(iconHeight,biconHeight);
2097     } else {
2098         biconWidth = STD_ARROW_WIDTH + 6;
2099         biconHeight = iconHeight;
2100     }
2101     cbPtr->buttonWidth = biconWidth + 2 * cbPtr->buttonBorderWidth;
2102     valuePtr->width = 2 * cbPtr->borderWidth + iconWidth + 4 * gap + 
2103         cbPtr->buttonWidth + textWidth;
2104     valuePtr->height = MAX(textHeight, biconHeight) + 2 * cbPtr->borderWidth;
2105 }
2106
2107 /*
2108  *----------------------------------------------------------------------
2109  *
2110  * DrawComboBox --
2111  *
2112  *      Draws the "combobox" given the screen coordinates and the
2113  *      value to be displayed.  
2114  *
2115  * Results:
2116  *      None.
2117  *
2118  * Side Effects:
2119  *      The combobox value is drawn.
2120  *
2121  *----------------------------------------------------------------------
2122  */
2123 static void
2124 DrawComboBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
2125     TreeView *tvPtr;
2126     Drawable drawable;
2127     TreeViewEntry *entryPtr;
2128     TreeViewValue *valuePtr;
2129     TreeViewStyle *stylePtr;
2130     TreeViewIcon icon;
2131     int x, y;
2132 {
2133     GC gc;
2134     TreeViewColumn *columnPtr;
2135     TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr;
2136     int iconX, iconY, iconWidth, iconHeight;
2137     int textX, textY, textHeight;
2138     int buttonX, buttonY;
2139     int gap, columnWidth;
2140     TreeViewStyle sRec;
2141     int valWidth = (valuePtr->textPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
2142     TextLayout *layPtr;
2143
2144     layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
2145
2146     columnPtr = valuePtr->columnPtr;
2147     drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
2148     gc = sRec.gc;
2149
2150     if (!valuePtr->string) {
2151         return;
2152     }
2153     buttonX = x + columnPtr->width;
2154     buttonX -= columnPtr->pad.side2 + cbPtr->borderWidth  +
2155         cbPtr->buttonWidth + stylePtr->gap;
2156     buttonY = y;
2157
2158     columnWidth = columnPtr->width - 
2159         (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
2160     if (columnWidth > valWidth) {
2161         switch(columnPtr->justify) {
2162         case TK_JUSTIFY_RIGHT:
2163             x += (columnWidth - valWidth);
2164             break;
2165         case TK_JUSTIFY_CENTER:
2166             x += (columnWidth - valWidth) / 2;
2167             break;
2168         case TK_JUSTIFY_LEFT:
2169             break;
2170         }
2171     }
2172
2173 #ifdef notdef
2174     textX = textY = iconX = iconY = 0;  /* Suppress compiler warning. */
2175 #endif
2176     
2177     iconWidth = iconHeight = 0;
2178     if (icon != NULL) {
2179         iconWidth = TreeViewIconWidth(icon);
2180         iconHeight = TreeViewIconHeight(icon);
2181     }
2182     textHeight = 0;
2183     if (layPtr != NULL) {
2184         textHeight = layPtr->height;
2185     }
2186     gap = 0;
2187     if ((icon != NULL) && (layPtr != NULL)) {
2188         gap = stylePtr->gap;
2189     }
2190
2191     iconX = x + gap;
2192     iconY = y + (entryPtr->height - iconHeight) / 2;
2193     textX = iconX + iconWidth + gap;
2194     textY = y + (entryPtr->height - textHeight) / 2;
2195
2196     valuePtr->iX = iconX;
2197     valuePtr->iY = iconY;
2198     valuePtr->iW = iconWidth;
2199     valuePtr->iH = iconHeight;
2200     valuePtr->tX = textX;
2201     valuePtr->tY = textY;
2202     valuePtr->tW = valuePtr->textPtr->width;
2203     valuePtr->tH = textHeight;
2204     if (icon != NULL) {
2205         if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth, 
2206                iconHeight, drawable, iconX, iconY) != TCL_OK) return;
2207     } else {
2208         valuePtr->iW = 0;
2209     }
2210     if (layPtr != NULL) {
2211         TextStyle ts;
2212         XColor *color;
2213
2214         int disabled = (entryPtr->state == STATE_DISABLED);
2215         
2216         if (disabled) {
2217             color = tvPtr->disabledColor;
2218         } else  if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
2219            color = SELECT_FG(tvPtr);
2220         } else if (entryPtr->color != NULL) {
2221             color = entryPtr->color;
2222         } else {
2223             color = sRec.fgColor;
2224             GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
2225          }
2226         XSetForeground(tvPtr->display, gc, color->pixel);
2227         Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor,
2228             stylePtr->shadow.color, 0.0, 
2229             TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
2230         Blt_DrawTextLayout(tvPtr->tkwin, drawable, valuePtr->textPtr, 
2231                 &ts, textX, textY);
2232         if (color != sRec.fgColor) {
2233             XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
2234         }
2235     } else {
2236         valuePtr->tW = 0;
2237     }
2238     if (cbPtr->buttonIcons == NULL) {
2239         if (valuePtr == tvPtr->activeValuePtr) {
2240             Blt_Fill3DRectangle(tvPtr->tkwin, drawable, stylePtr->activeBorder, 
2241                 buttonX, buttonY + cbPtr->borderWidth, cbPtr->buttonWidth, 
2242                 entryPtr->height - 2 * cbPtr->borderWidth, 
2243                 cbPtr->buttonBorderWidth, cbPtr->buttonRelief); 
2244         } else {
2245             Blt_Fill3DRectangle(tvPtr->tkwin, drawable, columnPtr->titleBorder, 
2246                 buttonX, buttonY + cbPtr->borderWidth, cbPtr->buttonWidth, 
2247                 entryPtr->height - 2 * cbPtr->borderWidth, 
2248                 cbPtr->buttonBorderWidth, cbPtr->buttonRelief); 
2249         }
2250         buttonX += cbPtr->buttonWidth / 2;
2251         buttonY += entryPtr->height / 2;
2252         Blt_DrawArrow(tvPtr->display, drawable, gc, buttonX, buttonY, 
2253             STD_ARROW_HEIGHT, ARROW_DOWN);
2254         stylePtr->flags &= ~STYLE_DIRTY;
2255     } else {
2256         TreeViewIcon butIcon;
2257         int biconWidth;
2258         int biconHeight;
2259         if (valuePtr == tvPtr->activeValuePtr && cbPtr->buttonIcons[1]) {
2260             butIcon = cbPtr->buttonIcons[1];
2261         } else {
2262             butIcon = cbPtr->buttonIcons[0];
2263         }
2264         biconWidth = TreeViewIconWidth(butIcon);
2265         biconHeight = MAX(iconHeight,TreeViewIconHeight(butIcon));
2266
2267         buttonY += (entryPtr->height-biconHeight)/2;
2268         Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, butIcon, 0, 0, biconWidth, 
2269             biconHeight, drawable, buttonX, buttonY);
2270     }
2271 }
2272
2273 /*
2274  *----------------------------------------------------------------------
2275  *
2276  * PickCombobox --
2277  *
2278  *      Draws the "checkbox" given the screen coordinates and the
2279  *      value to be displayed.  
2280  *
2281  * Results:
2282  *      None.
2283  *
2284  * Side Effects:
2285  *      The checkbox value is drawn.
2286  *
2287  *----------------------------------------------------------------------
2288  */
2289 static int
2290 PickComboBox(entryPtr, valuePtr, stylePtr, worldX, worldY)
2291     TreeViewEntry *entryPtr;
2292     TreeViewValue *valuePtr;
2293     TreeViewStyle *stylePtr;
2294     int worldX, worldY;
2295 {
2296     TreeViewColumn *columnPtr;
2297     TreeViewComboBox *cbPtr = (TreeViewComboBox *)stylePtr;
2298     int x, y, width, height;
2299
2300     columnPtr = valuePtr->columnPtr;
2301     width = cbPtr->buttonWidth;
2302     height = entryPtr->height - 4;
2303     x = columnPtr->worldX + columnPtr->width - columnPtr->pad.side2 - 
2304         cbPtr->borderWidth - columnPtr->borderWidth - width;
2305     y = entryPtr->worldY + cbPtr->borderWidth;
2306     if ((worldX >= x) && (worldX < (x + width)) && 
2307         (worldY >= y) && (worldY < (y + height))) {
2308         return TRUE;
2309     }
2310     return FALSE;
2311 }
2312
2313 /*
2314  *----------------------------------------------------------------------
2315  *
2316  * EditCombobox --
2317  *
2318  *      Edits the "combobox".
2319  *
2320  * Results:
2321  *      None.
2322  *
2323  * Side Effects:
2324  *      The checkbox value is drawn.
2325  *
2326  *----------------------------------------------------------------------
2327  */
2328 /*ARGSUSED*/
2329 static int
2330 EditComboBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
2331     TreeView *tvPtr;
2332     TreeViewEntry *entryPtr;
2333     TreeViewValue *valuePtr;
2334     TreeViewStyle *stylePtr;    /* Not used. */
2335     int x;
2336     int y;
2337     int *retVal;
2338 {
2339     int isTest = *retVal;
2340     *retVal = 1;
2341     if (isTest) {
2342         return TCL_OK;
2343     }
2344     return Blt_TreeViewTextbox(tvPtr, entryPtr, valuePtr->columnPtr);
2345 }
2346
2347 /*
2348  *----------------------------------------------------------------------
2349  *
2350  * FreeComboBox --
2351  *
2352  *      Releases resources allocated for the combobox. The resources
2353  *      freed by this routine are specific only to the "combobox".   
2354  *      Other resources (common to all styles) are freed in the 
2355  *      Blt_TreeViewFreeStyle routine.
2356  *
2357  * Results:
2358  *      None.
2359  *
2360  * Side Effects:
2361  *      GCs allocated for the combobox are freed.
2362  *
2363  *----------------------------------------------------------------------
2364  */
2365 static void
2366 FreeComboBox(tvPtr, stylePtr)
2367     TreeView *tvPtr;
2368     TreeViewStyle *stylePtr;
2369 {
2370     FreeTextBox(tvPtr, stylePtr);
2371 }
2372
2373 /*
2374  *----------------------------------------------------------------------
2375  *
2376  * CreateBarbox --
2377  *
2378  *      Creates a "checkbox" style.
2379  *
2380  * Results:
2381  *      A pointer to the new style structure.
2382  *
2383  *----------------------------------------------------------------------
2384  */
2385 static TreeViewStyle *
2386 CreateBarBox(tvPtr, hPtr)
2387     TreeView *tvPtr;
2388     Blt_HashEntry *hPtr;
2389 {
2390     TreeViewBarBox *cbPtr;
2391
2392     cbPtr = (TreeViewBarBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewBarBox));
2393     cbPtr->classPtr = &barBoxClass;
2394     cbPtr->gap = 4;
2395     cbPtr->lineWidth = 1;
2396     cbPtr->showValue = TRUE;
2397     cbPtr->flags = STYLE_BARBOX;
2398     return (TreeViewStyle *)cbPtr;
2399 }
2400
2401 /*
2402  *----------------------------------------------------------------------
2403  *
2404  * ConfigureBarbox --
2405  *
2406  *      Configures a "checkbox" style.  This routine performs 
2407  *      generates the GCs required for a checkbox style.
2408  *
2409  * Results:
2410  *      None.
2411  *
2412  * Side Effects:
2413  *      GCs are created for the style.
2414  *
2415  *----------------------------------------------------------------------
2416  */
2417 static void
2418 ConfigureBarBox(tvPtr, stylePtr)
2419     TreeView *tvPtr;
2420     TreeViewStyle *stylePtr;
2421 {
2422     GC newGC;
2423     TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2424     XColor *bgColor;
2425     XGCValues gcValues;
2426     unsigned long gcMask;
2427
2428     bgColor = Tk_3DBorderColor(CHOOSE(tvPtr->border, stylePtr->border));
2429
2430     gcValues.background = bgColor->pixel;
2431     gcValues.foreground = CHOOSE(tvPtr->fgColor, stylePtr->fgColor)->pixel;
2432     ConfigureTextBox(tvPtr, stylePtr);
2433     gcMask = GCForeground;
2434     gcValues.foreground = cbPtr->fillColor->pixel;
2435     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
2436     if (cbPtr->fillGC != NULL) {
2437         Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
2438     }
2439     cbPtr->fillGC = newGC;
2440
2441     gcMask = GCForeground | GCLineWidth;
2442     gcValues.line_width = cbPtr->lineWidth;
2443     gcValues.foreground = cbPtr->boxColor->pixel;
2444     newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
2445     if (cbPtr->boxGC != NULL) {
2446         Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
2447     }
2448     cbPtr->boxGC = newGC;
2449     if (cbPtr->barBg) {
2450         bgColor = Tk_3DBorderColor(cbPtr->barBg);
2451         gcValues.background = bgColor->pixel;
2452         gcValues.foreground = bgColor->pixel;
2453         newGC = Tk_GetGC(tvPtr->tkwin, gcMask, &gcValues);
2454         if (cbPtr->bgGC != NULL) {
2455             Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
2456         }
2457         cbPtr->bgGC = newGC;
2458     }
2459     stylePtr->flags |= STYLE_DIRTY;
2460 }
2461
2462 /*
2463  *----------------------------------------------------------------------
2464  *
2465  * MeasureBarbox --
2466  *
2467  *      Determines the space requirements for the "barbox" given
2468  *      the value to be displayed.  Depending upon whether an icon
2469  *      or text is displayed and their relative placements, this
2470  *      routine computes the space needed for the text entry.
2471  *
2472  * Results:
2473  *      None.
2474  *
2475  * Side Effects:
2476  *      The width and height fields of *valuePtr* are set with the
2477  *      computed dimensions.
2478  *
2479  *----------------------------------------------------------------------
2480  */
2481 static void
2482 MeasureBarBox(tvPtr, stylePtr, valuePtr)
2483     TreeView *tvPtr;
2484     TreeViewStyle *stylePtr;
2485     TreeViewValue *valuePtr;
2486 {
2487     TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2488     TreeViewColumn *columnPtr = valuePtr->columnPtr;
2489     TreeViewEntry *entryPtr;
2490     int iconWidth, iconHeight;
2491     int textWidth, textHeight;
2492     int gap, bGap;
2493     int boxWidth, boxHeight;
2494     TreeViewIcon icon;
2495     int rel = 0;
2496
2497     entryPtr = valuePtr->entryPtr;
2498     bGap = stylePtr->gap;
2499     if (cbPtr->barWidth <= 0) {
2500         boxWidth = 0;
2501         bGap = 0;
2502     } else if (cbPtr->barWidth >= 4000) {
2503         boxWidth = 4000;
2504     } else {
2505         boxWidth = ODD(cbPtr->barWidth);
2506     }
2507     if (cbPtr->barHeight <= 0) {
2508         boxHeight = 0;
2509     } else if (cbPtr->barHeight >= 4000) {
2510         boxHeight = 4000;
2511     } else {
2512         boxHeight = ODD(cbPtr->barHeight);
2513     }
2514
2515     textWidth = textHeight = iconWidth = iconHeight = 0;
2516     valuePtr->width = valuePtr->height = 0;
2517     icon = (stylePtr->icon?stylePtr->icon:(columnPtr->stylePtr?columnPtr->stylePtr->icon:NULL));
2518     if (icon != NULL && tvPtr->hideStyleIcons == 0) {
2519         iconWidth = TreeViewIconWidth(icon);
2520         iconHeight = TreeViewIconHeight(icon);
2521     } 
2522     /* TODO: recalc over/under only on change.*/
2523     gap = 0;
2524     if (cbPtr->showValue) {
2525
2526         if (valuePtr->textPtr != NULL) {
2527             Blt_Free(valuePtr->textPtr);
2528             valuePtr->textPtr = NULL;
2529         }
2530         if (valuePtr->string != NULL) {
2531             /* New string defined. */
2532             TextStyle ts;
2533             Tcl_Obj *fmtObj;
2534         
2535             fmtObj = NotNullObj(cbPtr->formatCmd);
2536             if (fmtObj == NULL) {
2537                 fmtObj = NotNullObj(columnPtr->formatCmd);
2538             }
2539             if (fmtObj == NULL) {
2540                 fmtObj = NotNullObj(tvPtr->formatCmd);
2541             }
2542
2543             Blt_InitTextStyle(&ts);
2544             ts.font = CHOOSE3(tvPtr->font, columnPtr->font, stylePtr->font);
2545             ts.anchor = TK_ANCHOR_NW;
2546             ts.justify = valuePtr->columnPtr->justify;
2547             if (fmtObj) {
2548                 Tcl_DString cmdString;
2549                 char *string;
2550                 int result;
2551                 Tcl_Interp *interp = tvPtr->interp;
2552
2553                 Tcl_Preserve(entryPtr);
2554                 rel = 1;
2555                 Blt_TreeViewPercentSubst(tvPtr, valuePtr->entryPtr, valuePtr->columnPtr, Tcl_GetString(fmtObj), valuePtr->string, &cmdString);
2556                 result = Tcl_GlobalEval(interp, Tcl_DStringValue(&cmdString));
2557                 if ((entryPtr->flags & ENTRY_DELETED) || (tvPtr->flags & TV_DELETED)) {
2558                     Tcl_Release(entryPtr);
2559                     return;
2560                 }
2561                 
2562                 Blt_TreeViewOptsInit(tvPtr);
2563                 Tcl_DStringFree(&cmdString);
2564                 if (result == TCL_OK) {
2565                     string = Tcl_GetStringResult(interp);
2566                     valuePtr->textPtr = Blt_GetTextLayoutStr(string, &ts);
2567                 }
2568             }
2569             if (valuePtr->textPtr == NULL) {
2570                 valuePtr->textPtr = Blt_GetTextLayoutStr(valuePtr->string, &ts);
2571             }
2572         } 
2573         if (valuePtr->textPtr != NULL  && tvPtr->hideStyleText == 0) {
2574             textWidth = valuePtr->textPtr->width;
2575             textHeight = valuePtr->textPtr->height;
2576             if (stylePtr->icon != NULL) {
2577                 gap = stylePtr->gap;
2578             }
2579         }
2580      
2581         if (stylePtr->icon != NULL) {
2582             gap = stylePtr->gap;
2583         }
2584     }
2585     valuePtr->width = stylePtr->gap + bGap + boxWidth + iconWidth + gap + textWidth + 2;
2586     valuePtr->height = MAX3(boxHeight, textHeight, iconHeight);
2587     if (rel) Tcl_Release(entryPtr);
2588 }
2589
2590 /*
2591  *----------------------------------------------------------------------
2592  *
2593  * DrawBarbox --
2594  *
2595  *      Draws the "checkbox" given the screen coordinates and the
2596  *      value to be displayed.  
2597  *
2598  * Results:
2599  *      None.
2600  *
2601  * Side Effects:
2602  *      The checkbox value is drawn.
2603  *
2604  *----------------------------------------------------------------------
2605  */
2606 static void
2607 DrawBarBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
2608     TreeView *tvPtr;
2609     Drawable drawable;
2610     TreeViewEntry *entryPtr;
2611     TreeViewValue *valuePtr;
2612     TreeViewStyle *stylePtr;
2613     TreeViewIcon icon;
2614     int x, y;
2615 {
2616     GC gc;
2617     TreeViewColumn *columnPtr;
2618     TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2619     int iconX, iconY, iconWidth, iconHeight;
2620     int textX, textY, textHeight, ttlWidth, bGap, iGap;
2621     int gap, columnWidth;
2622     TextLayout *textPtr;
2623     int boxX, boxY, boxWidth, boxHeight, bw;
2624     TreeViewStyle *csPtr, sRec = *stylePtr;
2625     int valWidth = (valuePtr->textPtr?valuePtr->width:(icon?TreeViewIconWidth(icon):0));
2626     double curValue;
2627     char *string;
2628     TextStyle ts;
2629     XColor *color;
2630     TextLayout *layPtr;
2631     int showValue = (tvPtr->hideStyleText ? 0 : cbPtr->showValue);
2632
2633     layPtr = (tvPtr->hideStyleText?NULL:valuePtr->textPtr);
2634
2635     string = NULL;
2636     textPtr = NULL;
2637     columnPtr = valuePtr->columnPtr;
2638     csPtr = columnPtr->stylePtr;
2639     
2640     drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
2641     gc = sRec.gc;
2642
2643     columnWidth = columnPtr->width - PADDING(columnPtr->pad);
2644     if (!valuePtr->string) {
2645         return;
2646     }
2647     if (Tcl_GetDouble(NULL, valuePtr->string, &curValue) != TCL_OK) {
2648         if (sscanf(valuePtr->string, "%lg", &curValue) != 1) {
2649             return;
2650         }
2651     }
2652     if (cbPtr->maxValue<=cbPtr->minValue) {
2653         return;
2654     }
2655
2656 #ifdef notdef
2657     textX = textY = iconX = iconY = 0;  /* Suppress compiler warning. */
2658 #endif
2659     iconWidth = iconHeight = 0;
2660     bGap = stylePtr->gap;
2661     iGap = 0;
2662     if (cbPtr->barWidth<=0) {
2663         boxWidth = 0;
2664         bGap = 0;
2665     } else if (cbPtr->barWidth >= 4000) {
2666         boxWidth = 4000;
2667     } else {
2668         boxWidth = ODD(cbPtr->barWidth);
2669     }
2670     if (cbPtr->barHeight<=0) {
2671         boxHeight = 0;
2672     } else if (cbPtr->barHeight >= 4000) {
2673         boxHeight = 4000;
2674     } else {
2675         boxHeight = ODD(cbPtr->barHeight);
2676     }
2677     ttlWidth = ( boxWidth + stylePtr->gap * 2);
2678     if (showValue) {
2679         ttlWidth += (valWidth + stylePtr->gap);
2680         Blt_InitTextStyle(&ts);
2681         ts.font = CHOOSE(tvPtr->font, stylePtr->font);
2682         ts.anchor = TK_ANCHOR_NW;
2683         ts.justify = columnPtr->justify;
2684     }
2685     if (icon != NULL) {
2686         iGap = stylePtr->gap;
2687         iconWidth = TreeViewIconWidth(icon);
2688         iconHeight = TreeViewIconHeight(icon);
2689         ttlWidth += iconWidth + stylePtr->gap;
2690     }
2691
2692     if (columnWidth > ttlWidth) {
2693         switch(columnPtr->justify) {
2694         case TK_JUSTIFY_RIGHT:
2695             x += (columnWidth - ttlWidth - stylePtr->gap*2);
2696             break;
2697         case TK_JUSTIFY_CENTER:
2698             x += (columnWidth - ttlWidth) / 2;
2699             break;
2700         case TK_JUSTIFY_LEFT:
2701             break;
2702         }
2703     }
2704
2705     /*
2706      * Draw the barbox 
2707      */
2708     boxX = x + iGap;
2709     boxY = y + (entryPtr->height - boxHeight) / 2;
2710     if (curValue<cbPtr->minValue) {
2711         bw = 0;
2712     } else if (curValue > cbPtr->maxValue) {
2713         bw = boxWidth;
2714     } else if (cbPtr->minValue >= cbPtr->maxValue) {
2715         bw = 0;
2716     } else {
2717         int diff = (cbPtr->maxValue-cbPtr->minValue);
2718         bw = (int)(boxWidth*(1.0*(curValue-cbPtr->minValue)/diff));
2719     }
2720     if (boxHeight && boxWidth) {
2721         if (cbPtr->barBg) {
2722             XFillRectangle(tvPtr->display, drawable, cbPtr->bgGC, boxX, boxY, boxWidth, boxHeight);
2723         }
2724         if (bw>0) {
2725             if (Blt_HasTile(stylePtr->fillTile)) {
2726                 Blt_SetTileOrigin(tvPtr->tkwin, stylePtr->fillTile, -boxX, -boxY);
2727                 Blt_TileRectangle(tvPtr->tkwin, drawable, stylePtr->fillTile,
2728                     boxX, boxY, bw, boxHeight );
2729             } else if (csPtr != NULL && Blt_HasTile(csPtr->fillTile)) {
2730                 Blt_SetTileOrigin(tvPtr->tkwin, csPtr->fillTile, -boxX, -boxY);
2731                 Blt_TileRectangle(tvPtr->tkwin, drawable, csPtr->fillTile,
2732                     boxX, boxY, bw, boxHeight );
2733             } else {
2734
2735                 XFillRectangle(tvPtr->display, drawable, cbPtr->fillGC, boxX, boxY, bw, boxHeight);
2736             }
2737         }
2738         XDrawRectangle(tvPtr->display, drawable, cbPtr->boxGC, boxX, boxY, 
2739             boxWidth, boxHeight);
2740     }
2741
2742     textHeight = 0;
2743     gap = 0;
2744     if (showValue) {
2745         
2746         int disabled = (entryPtr->state == STATE_DISABLED);
2747         
2748         if (disabled) {
2749             color = tvPtr->disabledColor;
2750         } else if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
2751             color = SELECT_FG(tvPtr);
2752         } else if (entryPtr->color != NULL) {
2753             color = entryPtr->color;
2754         } else {
2755             color = sRec.fgColor;
2756             GetColorPats(tvPtr, entryPtr, valuePtr, stylePtr, &color );
2757         }
2758         Blt_SetDrawTextStyle(&ts, sRec.font, gc, color, sRec.fgColor, stylePtr->shadow.color, 0.0, TK_ANCHOR_NW, columnPtr->justify, 0, stylePtr->shadow.offset);
2759         textPtr = valuePtr->textPtr; // Blt_GetTextLayout(string, &ts);
2760         textHeight = textPtr->height;
2761         if (icon != NULL) {
2762             gap = stylePtr->gap;
2763         }
2764     }
2765     x = boxX + boxWidth + bGap;
2766
2767     /* The icon sits to the left of the text. */
2768     iconX = x;
2769     iconY = y + (entryPtr->height - iconHeight) / 2;
2770     textX = iconX + iconWidth + gap;
2771     textY = y + (entryPtr->height - textHeight) / 2;
2772
2773     valuePtr->iX = iconX;
2774     valuePtr->iY = iconY;
2775     valuePtr->iW = iconWidth;
2776     valuePtr->iH = iconHeight;
2777     valuePtr->tX = textX;
2778     valuePtr->tY = textY;
2779     valuePtr->tW = (textPtr?textPtr->width:0);
2780     valuePtr->tH = textHeight;
2781     
2782     if (icon != NULL) {
2783         if (Blt_TreeViewRedrawIcon(tvPtr, entryPtr, columnPtr, icon, 0, 0, iconWidth, 
2784                        iconHeight, drawable, iconX, iconY) != TCL_OK) return;
2785     } else {
2786         valuePtr->iW = 0;
2787     }
2788     if ((showValue) && (textPtr != NULL)) {
2789         XSetForeground(tvPtr->display, gc, color->pixel);
2790         Blt_DrawTextLayout(tvPtr->tkwin, drawable, textPtr, &ts, textX, textY);
2791         if (color != sRec.fgColor) {
2792             XSetForeground(tvPtr->display, gc, sRec.fgColor->pixel);
2793         }
2794     } else {
2795         valuePtr->tW = 0;
2796     }
2797     stylePtr->flags &= ~STYLE_DIRTY;
2798 }
2799
2800 #if 0
2801 /*
2802  *----------------------------------------------------------------------
2803  *
2804  * PickBarbox --
2805  *
2806  *      Draws the "checkbox" given the screen coordinates and the
2807  *      value to be displayed.  
2808  *
2809  * Results:
2810  *      None.
2811  *
2812  * Side Effects:
2813  *      The checkbox value is drawn.
2814  *
2815  *----------------------------------------------------------------------
2816  */
2817 static int
2818 PickBarBox(entryPtr, valuePtr, stylePtr, worldX, worldY)
2819     TreeViewEntry *entryPtr;
2820     TreeViewValue *valuePtr;
2821     TreeViewStyle *stylePtr;
2822     int worldX, worldY;
2823 {
2824     TreeViewColumn *columnPtr;
2825     TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2826     int columnWidth;
2827     int x, y, width, height;
2828
2829     columnPtr = valuePtr->columnPtr;
2830     columnWidth = columnPtr->width - 
2831         (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
2832     if (columnWidth > valuePtr->width) {
2833         switch(columnPtr->justify) {
2834         case TK_JUSTIFY_RIGHT:
2835             worldX += (columnWidth - valuePtr->width);
2836             break;
2837         case TK_JUSTIFY_CENTER:
2838             worldX += (columnWidth - valuePtr->width) / 2;
2839             break;
2840         case TK_JUSTIFY_LEFT:
2841             break;
2842         }
2843     }
2844     width = ODD(cbPtr->barWidth) + 2 * cbPtr->lineWidth;
2845     height = ODD(cbPtr->barHeight) + 2 * cbPtr->lineWidth;
2846     x = columnPtr->worldX + columnPtr->pad.side1 + cbPtr->gap - 
2847         cbPtr->lineWidth;
2848     y = entryPtr->worldY + (entryPtr->height - height) / 2;
2849     if ((worldX >= x) && (worldX < (x + width)) && 
2850         (worldY >= y) && (worldY < (y + height))) {
2851         return TRUE;
2852     }
2853     return FALSE;
2854 }
2855 #endif
2856 /*
2857  *----------------------------------------------------------------------
2858  *
2859  * EditBarbox --
2860  *
2861  *      Edits the "checkbox".
2862  *
2863  * Results:
2864  *      None.
2865  *
2866  * Side Effects:
2867  *      The checkbox value is drawn.
2868  *
2869  *----------------------------------------------------------------------
2870  */
2871 static int
2872 EditBarBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
2873     TreeView *tvPtr;
2874     TreeViewEntry *entryPtr;
2875     TreeViewValue *valuePtr;
2876     TreeViewStyle *stylePtr;
2877     int x;
2878     int y;
2879     int *retVal;
2880 {
2881     *retVal = 0;
2882     return TCL_OK;
2883 }
2884
2885 /*
2886  *----------------------------------------------------------------------
2887  *
2888  * FreeBarbox --
2889  *
2890  *      Releases resources allocated for the checkbox. The resources
2891  *      freed by this routine are specific only to the "checkbox".   
2892  *      Other resources (common to all styles) are freed in the 
2893  *      Blt_TreeViewFreeStyle routine.
2894  *
2895  * Results:
2896  *      None.
2897  *
2898  * Side Effects:
2899  *      GCs allocated for the checkbox are freed.
2900  *
2901  *----------------------------------------------------------------------
2902  */
2903 static void
2904 FreeBarBox(tvPtr, stylePtr)
2905     TreeView *tvPtr;
2906     TreeViewStyle *stylePtr;
2907 {
2908     TreeViewBarBox *cbPtr = (TreeViewBarBox *)stylePtr;
2909
2910     FreeTextBox(tvPtr, stylePtr);
2911     if (cbPtr->fillGC != NULL) {
2912         Tk_FreeGC(tvPtr->display, cbPtr->fillGC);
2913     }
2914     if (cbPtr->boxGC != NULL) {
2915         Tk_FreeGC(tvPtr->display, cbPtr->boxGC);
2916     }
2917     if (cbPtr->bgGC != NULL) {
2918         Tk_FreeGC(tvPtr->display, cbPtr->bgGC);
2919     }
2920 }
2921
2922 /*
2923  *----------------------------------------------------------------------
2924  *
2925  * CreateWindowBox --
2926  *
2927  *      Creates a "textbox" style.
2928  *
2929  * Results:
2930  *      A pointer to the new style structure.
2931  *
2932  *----------------------------------------------------------------------
2933  */
2934 static TreeViewStyle *
2935 CreateWindowBox(tvPtr, hPtr)
2936     TreeView *tvPtr;
2937     Blt_HashEntry *hPtr;
2938 {
2939     TreeViewWindowBox *tbPtr;
2940
2941     tbPtr = (TreeViewWindowBox *)newStyle(tvPtr, hPtr, sizeof(TreeViewWindowBox));
2942     tbPtr->classPtr = &windowBoxClass;
2943     tbPtr->flags = STYLE_WINDOWBOX;
2944     return (TreeViewStyle *)tbPtr;
2945 }
2946
2947 /*
2948  *----------------------------------------------------------------------
2949  *
2950  * ConfigureWindowBox --
2951  *
2952  *      Configures a "textbox" style.  This routine performs 
2953  *      generates the GCs required for a textbox style.
2954  *
2955  * Results:
2956  *      None.
2957  *
2958  * Side Effects:
2959  *      GCs are created for the style.
2960  *
2961  *----------------------------------------------------------------------
2962  */
2963 static void
2964 ConfigureWindowBox(tvPtr, stylePtr)
2965     TreeView *tvPtr;
2966     TreeViewStyle *stylePtr;
2967 {
2968     TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
2969     tbPtr->flags |= STYLE_DIRTY;
2970 }
2971
2972 /*
2973  *----------------------------------------------------------------------
2974  *
2975  * MeasureWindowBox --
2976  *
2977  *      Determines the space requirements for the "textbox" given
2978  *      the value to be displayed.  Depending upon whether an icon
2979  *      or text is displayed and their relative placements, this
2980  *      routine computes the space needed for the text entry.
2981  *
2982  * Results:
2983  *      None.
2984  *
2985  * Side Effects:
2986  *      The width and height fields of *valuePtr* are set with the
2987  *      computed dimensions.
2988  *
2989  *----------------------------------------------------------------------
2990  */
2991 static void
2992 MeasureWindowBox(tvPtr, stylePtr, valuePtr)
2993     TreeView *tvPtr;
2994     TreeViewStyle *stylePtr;
2995     TreeViewValue *valuePtr;
2996 {
2997     TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
2998     valuePtr->width = tbPtr->windowWidth;
2999     valuePtr->height = tbPtr->windowHeight;
3000 }
3001
3002
3003 typedef struct {
3004     int flags;
3005     char *name;
3006     TreeView *tvPtr;
3007     TreeViewEntry *entryPtr;
3008     TreeViewColumn *columnPtr;
3009     Blt_HashEntry *hPtr;
3010     Tk_Window tkwin;
3011     TreeViewWindowBox *stylePtr;
3012 } WindowCell;
3013
3014 static void EmbWinStructureProc( ClientData clientData, XEvent *eventPtr);
3015
3016 static void
3017 EmbWinRemove(WindowCell *wcPtr) {
3018     Blt_HashEntry *hPtr;
3019     TreeView *tvPtr = wcPtr->tvPtr;
3020     hPtr = Blt_FindHashEntry(&tvPtr->winTable, wcPtr->name);
3021     if (hPtr != NULL && wcPtr == (WindowCell*)Blt_GetHashValue(hPtr)) {
3022         Blt_DeleteHashEntry(&tvPtr->winTable, hPtr);
3023     }
3024     Blt_Free(wcPtr->name);
3025     wcPtr->name = NULL;
3026     if (wcPtr->hPtr) Blt_DeleteHashEntry(&tvPtr->winCellTable, wcPtr->hPtr);
3027     wcPtr->hPtr = NULL;
3028     if (wcPtr->tkwin) {
3029         Tk_DeleteEventHandler(wcPtr->tkwin, StructureNotifyMask,
3030             EmbWinStructureProc, (ClientData) wcPtr);
3031         Tk_ManageGeometry(wcPtr->tkwin, NULL, NULL);
3032         wcPtr->tkwin = NULL;
3033     }
3034     Blt_Free(wcPtr);
3035 }
3036
3037 /* Free all windows on widget delete. */
3038 void
3039 Blt_TreeViewFreeWindows( TreeView *tvPtr)
3040 {
3041     Blt_HashEntry *hPtr;
3042     Blt_HashSearch cursor;
3043     WindowCell *wcPtr;
3044
3045     for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3046         hPtr = Blt_NextHashEntry(&cursor)) {
3047         wcPtr = Blt_GetHashValue(hPtr);
3048         if (wcPtr) {
3049             EmbWinRemove(wcPtr);
3050         }
3051     }
3052 }
3053
3054 static void
3055 EmbWinUnmapNow(Tk_Window ewTkwin, Tk_Window tkwin)
3056 {
3057     if (tkwin != Tk_Parent(ewTkwin)) {
3058         Tk_UnmaintainGeometry(ewTkwin, tkwin);
3059     }
3060     Tk_UnmapWindow(ewTkwin);
3061 }
3062
3063 static void EmbWinRequestProc(ClientData clientData,
3064     Tk_Window tkwin)
3065 {
3066 }
3067     
3068 static void     EmbWinLostSlaveProc(ClientData clientData, Tk_Window tkwin);
3069
3070 static Tk_GeomMgr windowGeomType = {
3071     "treeview",                 /* name */
3072     EmbWinRequestProc,          /* requestProc */
3073     EmbWinLostSlaveProc,        /* lostSlaveProc */
3074 };
3075
3076
3077 void
3078 Blt_TreeViewMarkWindows( TreeView *tvPtr, int flag)
3079 {
3080     Blt_HashEntry *hPtr;
3081     Blt_HashSearch cursor;
3082     WindowCell *wcPtr;
3083
3084     for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3085     hPtr = Blt_NextHashEntry(&cursor)) {
3086         wcPtr = Blt_GetHashValue(hPtr);
3087         if (wcPtr) {
3088             if (flag == TV_WINDOW_CLEAR) {
3089                 /* Clear window drawn flags. */
3090                 wcPtr->flags &= ~TV_WINDOW_DRAW;
3091             } else if (flag == TV_WINDOW_UNMAP && (wcPtr->flags&TV_WINDOW_DRAW)==0) {
3092                 /* Unmapped undrawn window. */
3093                 EmbWinUnmapNow(wcPtr->tkwin, tvPtr->tkwin);
3094             }
3095         }
3096     }
3097 }
3098
3099 static WindowCell *
3100 bltTreeViewFindWindow(TreeViewEntry *entryPtr,
3101     TreeViewColumn *columnPtr)
3102 {
3103     TreeView *tvPtr = columnPtr->tvPtr;
3104     Blt_HashEntry *hPtr;
3105     WindowCell *wcPtr;
3106     Tcl_DString dStr;
3107     char *key;
3108     
3109     Tcl_DStringInit(&dStr);
3110     Tcl_DStringAppendElement(&dStr, columnPtr->key);
3111     Tcl_DStringAppendElement(&dStr, Blt_Itoa(entryPtr->node->inode));
3112     key = Tcl_DStringValue(&dStr);
3113     hPtr = Blt_FindHashEntry(&tvPtr->winCellTable, key);
3114     Tcl_DStringFree(&dStr);
3115     if (hPtr == NULL) return NULL;
3116     wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3117     return wcPtr;
3118 }
3119
3120 static int isValidSubWin( TreeView *tvPtr, Tk_Window tkwin) {
3121     Tk_Window ancestor, parent;
3122     parent = Tk_Parent(tkwin);
3123     for (ancestor = tvPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
3124         if (ancestor == parent) {
3125             break;
3126         }
3127         if (Tk_IsTopLevel(ancestor)) {
3128             return 0;
3129         }
3130     }
3131     if (Tk_IsTopLevel(tkwin) || (tkwin == tvPtr->tkwin)) {
3132         return 0;
3133     }
3134     return 1;
3135 }
3136
3137 static WindowCell *
3138 bltTreeViewWindowMake( TreeView *tvPtr, TreeViewEntry *entryPtr,
3139     TreeViewValue *valuePtr,  TreeViewWindowBox *wbPtr) 
3140 {
3141     char *name, *key;
3142     Blt_HashEntry *hPtr;
3143     WindowCell *wcPtr = NULL, *w2Ptr;
3144     TreeViewColumn *columnPtr = valuePtr->columnPtr;
3145     Tcl_DString dStr;
3146     Tk_Window tkwin;
3147     int result, isNew;
3148     Tcl_Interp *interp;
3149     char *execCmd = wbPtr->windowCmd;
3150
3151     interp = tvPtr->interp;
3152
3153     Tcl_DStringInit(&dStr);
3154     Tcl_DStringAppendElement(&dStr, columnPtr->key);
3155     Tcl_DStringAppendElement(&dStr, Blt_Itoa(entryPtr->node->inode));
3156     key = Tcl_DStringValue(&dStr);
3157     hPtr = Blt_CreateHashEntry(&tvPtr->winCellTable, key, &isNew);
3158     Tcl_DStringFree(&dStr);
3159     Tcl_DStringInit(&dStr);
3160
3161     if (hPtr == NULL) return NULL;
3162     if (!isNew) {
3163         wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3164         if (wcPtr && wcPtr->tkwin == NULL) {
3165             return NULL;
3166         }
3167         return wcPtr;
3168     }
3169     
3170     wcPtr = (WindowCell*)Blt_Calloc(1, sizeof(WindowCell));
3171     Blt_SetHashValue(hPtr, wcPtr);
3172     wcPtr->name = NULL;
3173     wcPtr->tvPtr = tvPtr;
3174     wcPtr->columnPtr = columnPtr;
3175     wcPtr->entryPtr = entryPtr;
3176     wcPtr->hPtr = hPtr;
3177     wcPtr->stylePtr = wbPtr;
3178     wcPtr->flags |= TV_WINDOW_DRAW;
3179     
3180     if (execCmd != NULL) {
3181         Tcl_DString cmdString;
3182
3183         Blt_TreeViewPercentSubst(tvPtr, entryPtr, columnPtr, execCmd, valuePtr->string, &cmdString);
3184         result = Tcl_GlobalEval(interp, Tcl_DStringValue(&cmdString));
3185         Blt_TreeViewOptsInit(tvPtr);
3186         Tcl_DStringFree(&cmdString);
3187         if ((entryPtr->flags & ENTRY_DELETED) || (tvPtr->flags & TV_DELETED)) {
3188             result = TCL_ERROR;
3189         }
3190         if (result != TCL_OK) {
3191             goto error;
3192         }
3193         name = Tcl_GetStringResult(interp);
3194     } else {
3195         name = valuePtr->string;
3196         if (name == NULL) {
3197             goto error;
3198         }
3199         if (name[0] != '.') {
3200             Tcl_DStringAppend(&dStr, Tk_PathName(tvPtr->tkwin), -1);
3201             Tcl_DStringAppend(&dStr, ".", -1);
3202             Tcl_DStringAppend(&dStr, name, -1);
3203             name = Tcl_DStringValue(&dStr);
3204         }
3205     }
3206     tkwin = Tk_NameToWindow(tvPtr->interp, name, tvPtr->tkwin);
3207     if (tkwin == NULL || !isValidSubWin(tvPtr, tkwin)) {
3208         goto error;
3209     }
3210     if (name && name[0]) {
3211
3212         wcPtr->name = Blt_Strdup(name);
3213         hPtr = Blt_CreateHashEntry(&tvPtr->winTable, wcPtr->name, &isNew);
3214         if (hPtr != NULL) {
3215             w2Ptr = (WindowCell*)Blt_GetHashValue(hPtr);
3216             if (w2Ptr && (w2Ptr->flags&TV_WINDOW_DRAW)) {
3217                 goto error;
3218             }
3219             Blt_SetHashValue(hPtr, wcPtr);
3220         }
3221     }
3222     Tcl_DStringFree(&dStr);
3223     if (execCmd == NULL) {
3224         entryPtr->flags |= ENTRY_DATA_WINDOW;
3225     }
3226     entryPtr->flags |= ENTRY_WINDOW;
3227     wcPtr->tkwin = tkwin;
3228     Tk_ManageGeometry(tkwin, &windowGeomType, wcPtr);
3229     Tk_CreateEventHandler(tkwin, StructureNotifyMask,
3230         EmbWinStructureProc, (ClientData) wcPtr);
3231     return wcPtr;
3232
3233 error:
3234     if (wcPtr) {
3235         Blt_DeleteHashEntry(&tvPtr->winCellTable, wcPtr->hPtr);
3236         if (wcPtr->name) Blt_Free(wcPtr->name);
3237         Blt_Free(wcPtr);
3238     }
3239     Tcl_DStringFree(&dStr);
3240     return NULL;
3241 }
3242
3243 /* Some other manager took control. */
3244 static void     EmbWinLostSlaveProc(ClientData clientData, Tk_Window tkwin)
3245 {
3246     register WindowCell *wcPtr = (WindowCell *) clientData;
3247     EmbWinUnmapNow(tkwin, wcPtr->tvPtr->tkwin);
3248     EmbWinRemove(wcPtr);
3249 }
3250
3251 static void
3252 EmbWinStructureProc(clientData, eventPtr)
3253     ClientData clientData;      /* Pointer to record describing window item. */
3254     XEvent *eventPtr;           /* Describes what just happened. */
3255 {
3256     register WindowCell *ewPtr = (WindowCell *) clientData;
3257
3258     if (eventPtr->type != DestroyNotify) {
3259         return;
3260     }
3261     EmbWinRemove(ewPtr);
3262 }
3263
3264 int
3265 Blt_WinResizeAlways(Tk_Window tkwin)
3266 {
3267     while (tkwin != NULL) {
3268 #ifdef Tk_IsResizeYes
3269         if (Tk_IsResizeYes(tkwin)) return 1;
3270 #endif
3271         if (Tk_TopWinHierarchy(tkwin)) break;
3272         tkwin = Tk_Parent(tkwin);
3273     }
3274     return 0;
3275 }
3276
3277 static void
3278 EmbWinDisplay(TreeView *tvPtr, WindowCell *wcPtr,
3279               int x, int y, int width, int height)
3280 {
3281     Tk_Window tkwin = tvPtr->tkwin;
3282     Tk_Window cwTkwin = wcPtr->tkwin;
3283     int diff, reqWidth, reqHeight, sticky, diffx, diffy;
3284
3285
3286     if ((diff = (y-tvPtr->titleHeight- tvPtr->insetY))<0) {
3287         height += diff;
3288         y -= diff;
3289     }
3290     if (width < 2 || height < 2) {
3291         if (wcPtr->flags&TV_WINDOW_DRAW) {
3292             EmbWinUnmapNow(cwTkwin, tkwin);
3293         }
3294         return;
3295     }
3296     reqWidth = Tk_ReqWidth(cwTkwin);
3297     if (reqWidth > width) { reqWidth = width; }
3298     reqHeight = Tk_ReqHeight(cwTkwin);
3299     if (reqHeight > height) { reqHeight = height; }
3300     diffx = width - reqWidth;
3301     diffy = height - reqHeight;
3302     
3303     sticky = wcPtr->stylePtr->sticky;
3304     
3305     if (sticky&STICK_EAST && sticky&STICK_WEST) {
3306         reqWidth += diffx;
3307     }
3308     if (sticky&STICK_NORTH && sticky&STICK_SOUTH) {
3309         reqHeight += diffy;
3310     }
3311     if (!(sticky&STICK_WEST)) {
3312         x += (sticky&STICK_EAST) ? diffx : diffx/2;
3313     }
3314     if (!(sticky&STICK_NORTH)) {
3315         y += (sticky&STICK_SOUTH) ? diffy : diffy/2;
3316     }
3317     width = reqWidth;
3318     height = reqHeight;
3319     if (tkwin == Tk_Parent(cwTkwin)) {
3320         if ((x != Tk_X(cwTkwin)) || (y != Tk_Y(cwTkwin))
3321             || (width != Tk_Width(cwTkwin))
3322             || (height != Tk_Height(cwTkwin))
3323             || Blt_WinResizeAlways(cwTkwin)
3324         ) {
3325             Tk_MoveResizeWindow(cwTkwin, x, y, width, height);
3326         }
3327         Tk_MapWindow(cwTkwin);
3328     } else {
3329         Tk_MaintainGeometry(cwTkwin, tkwin, x, y, width, height);
3330     }
3331     wcPtr->flags |= TV_WINDOW_DRAW;
3332 }
3333
3334 /*
3335  * Called when a cell has a window from data.
3336  */
3337 void
3338 Blt_TreeViewWindowUpdate(TreeViewEntry *entryPtr, TreeViewColumn *columnPtr)
3339 {
3340     TreeViewWindowBox *wbPtr;
3341     WindowCell *wcPtr;
3342     
3343     if (entryPtr->flags & ENTRY_DATA_WINDOW) {
3344         /* Cell may already have a window from data. */
3345
3346     } else if (columnPtr->stylePtr != NULL &&
3347         columnPtr->stylePtr->classPtr->className[0] == 'w') {
3348         wbPtr = (TreeViewWindowBox *)columnPtr->stylePtr;
3349         if (wbPtr->windowCmd != NULL) return;
3350         
3351     } else {
3352         return;
3353     }
3354     wcPtr = bltTreeViewFindWindow(entryPtr, columnPtr);
3355     if (wcPtr == NULL || wcPtr->tkwin == NULL) return;
3356     EmbWinUnmapNow(wcPtr->tkwin, wcPtr->tvPtr->tkwin);
3357     Tk_ManageGeometry(wcPtr->tkwin, NULL, NULL);
3358     EmbWinRemove(wcPtr);
3359 }
3360
3361 void
3362 Blt_TreeViewWindowRelease(TreeViewEntry *entryPtr, TreeViewColumn *columnPtr)
3363 {
3364     Blt_HashEntry *hPtr;
3365     Blt_HashSearch cursor;
3366     WindowCell *wcPtr;
3367     TreeView *tvPtr;
3368     
3369     tvPtr = (columnPtr?columnPtr->tvPtr:entryPtr->tvPtr);
3370
3371     for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3372     hPtr = Blt_NextHashEntry(&cursor)) {
3373         wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3374         if (wcPtr == NULL) continue;
3375         if (entryPtr && entryPtr == wcPtr->entryPtr) {
3376             EmbWinUnmapNow(wcPtr->tkwin, wcPtr->tvPtr->tkwin);
3377             EmbWinRemove(wcPtr);
3378             continue;
3379         }
3380         if (columnPtr && columnPtr == wcPtr->columnPtr) {
3381             EmbWinUnmapNow(wcPtr->tkwin, wcPtr->tvPtr->tkwin);
3382             EmbWinRemove(wcPtr);
3383             continue;
3384         }
3385     }
3386 }
3387 /*
3388  *----------------------------------------------------------------------
3389  *
3390  * DrawWindowBox --
3391  *
3392  *      Draws the "windowbox" given the screen coordinates.
3393  *      The window name is taken from the data value.
3394  *
3395  * Results:
3396  *      None.
3397  *
3398  * Side Effects:
3399  *      The window is drawn.
3400  *
3401  *----------------------------------------------------------------------
3402   */
3403 static void
3404 DrawWindowBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y)
3405     TreeView *tvPtr;
3406     Drawable drawable;
3407     TreeViewEntry *entryPtr;
3408     TreeViewValue *valuePtr;
3409     TreeViewStyle *stylePtr;
3410     TreeViewIcon icon;
3411     int x, y;
3412 {
3413     TreeViewColumn *columnPtr;
3414     TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
3415     Tk_Window tkwin;
3416     int width, height, diff;
3417     WindowCell *wcPtr;
3418     TreeViewStyle sRec = *stylePtr;
3419
3420     columnPtr = valuePtr->columnPtr;
3421     
3422     Tcl_Preserve(entryPtr);
3423     wcPtr = bltTreeViewWindowMake(tvPtr, entryPtr, valuePtr, tbPtr);
3424     if ((entryPtr->flags & ENTRY_DELETED) || (tvPtr->flags & TV_DELETED)) {
3425         Tcl_Release(entryPtr);
3426         return;
3427     }
3428     Tcl_Release(entryPtr);
3429     
3430     drawTextBox(tvPtr, drawable, entryPtr, valuePtr, stylePtr, icon, x, y, &sRec);
3431
3432     if (wcPtr != NULL) {
3433         int columnWidth = columnPtr->width - 
3434             (2 * columnPtr->borderWidth + PADDING(columnPtr->pad));
3435             
3436         tkwin = wcPtr->tkwin;
3437         width = columnWidth;
3438         height = entryPtr->height-1;
3439         if ((diff = (y-tvPtr->titleHeight- tvPtr->insetY))<0) {
3440             height += diff;
3441             y -= diff;
3442         }
3443         EmbWinDisplay(tvPtr, wcPtr, x, y, width, height);
3444     }
3445     stylePtr->flags &= ~STYLE_DIRTY;
3446 }
3447
3448 /*
3449  *----------------------------------------------------------------------
3450  *
3451  * EditWindowbox --
3452  *
3453  *      Edits the "windowbox".
3454  *
3455  * Results:
3456  *      None.
3457  *
3458  *----------------------------------------------------------------------
3459  */
3460 /*ARGSUSED*/
3461 static int
3462 EditWindowBox(tvPtr, entryPtr, valuePtr, stylePtr, x, y, retVal)
3463     TreeView *tvPtr;
3464     TreeViewEntry *entryPtr;
3465     TreeViewValue *valuePtr;
3466     TreeViewStyle *stylePtr;    /* Not used. */
3467     int x;
3468     int y;
3469     int *retVal;
3470 {
3471     return TCL_ERROR;
3472 }
3473
3474 /*
3475  *----------------------------------------------------------------------
3476  *
3477  * FreeWindowBox --
3478  *
3479  *      Releases resources allocated for the textbox. The resources
3480  *      freed by this routine are specific only to the "textbox".   
3481  *      Other resources (common to all styles) are freed in the 
3482  *      Blt_TreeViewFreeStyle routine.
3483  *
3484  * Results:
3485  *      None.
3486  *
3487  * Side Effects:
3488  *      GCs allocated for the textbox are freed.
3489  *
3490  *----------------------------------------------------------------------
3491  */
3492 static void
3493 FreeWindowBox(tvPtr, stylePtr)
3494     TreeView *tvPtr;
3495     TreeViewStyle *stylePtr;
3496 {
3497     TreeViewWindowBox *tbPtr = (TreeViewWindowBox *)stylePtr;
3498     Blt_HashEntry *hPtr;
3499     Blt_HashSearch cursor;
3500     WindowCell *wcPtr;
3501
3502     if (!tbPtr) return;
3503
3504     for (hPtr = Blt_FirstHashEntry(&tvPtr->winCellTable, &cursor); hPtr != NULL;
3505         hPtr = Blt_NextHashEntry(&cursor)) {
3506         wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
3507         if (wcPtr && stylePtr == (TreeViewStyle*)wcPtr->stylePtr) {
3508             EmbWinRemove(wcPtr);
3509         }
3510     }
3511
3512 }
3513
3514 static TreeViewStyle *
3515 GetStyle(interp, tvPtr, styleName)
3516     Tcl_Interp *interp;
3517     TreeView *tvPtr;
3518     char *styleName;
3519 {
3520     Blt_HashEntry *hPtr;
3521
3522     hPtr = Blt_FindHashEntry(&tvPtr->styleTable, styleName);
3523     if (hPtr == NULL) {
3524         if (interp != NULL) {
3525             Tcl_AppendResult(interp, "can't find style \"", styleName, 
3526                 "\"", (char *)NULL);
3527         }
3528         return NULL;
3529     }
3530     return Blt_GetHashValue(hPtr);
3531 }
3532
3533 int
3534 Blt_TreeViewGetStyle(interp, tvPtr, styleName, stylePtrPtr)
3535     Tcl_Interp *interp;
3536     TreeView *tvPtr;
3537     char *styleName;
3538     TreeViewStyle **stylePtrPtr;
3539 {
3540     TreeViewStyle *stylePtr;
3541
3542     stylePtr = GetStyle(interp, tvPtr, styleName);
3543     if (stylePtr == NULL) {
3544         return TCL_ERROR;
3545     }
3546     stylePtr->refCount++;
3547     *stylePtrPtr = stylePtr;
3548     return TCL_OK;
3549 }
3550
3551 int
3552 Blt_TreeViewGetStyleMake(interp, tvPtr, styleName, stylePtrPtr, columnPtr, entryPtr, valuePtr)
3553     Tcl_Interp *interp;
3554     TreeView *tvPtr;
3555     char *styleName;
3556     TreeViewStyle **stylePtrPtr;
3557     TreeViewColumn *columnPtr;
3558     TreeViewEntry *entryPtr;
3559     TreeViewValue *valuePtr;
3560 {
3561     TreeViewStyle *stylePtr = NULL;
3562     Tcl_DString dString;
3563     int result;
3564     
3565     if (strlen(styleName)==0) {
3566         Tcl_AppendResult(interp, "can not use style with empty name", 0);
3567         return TCL_ERROR;
3568     }
3569     if (Blt_TreeViewGetStyle(NULL, tvPtr, styleName, &stylePtr) != TCL_OK) {
3570         if (tvPtr->styleCmd == NULL) {
3571             if (stylePtr == NULL) {
3572                 if (interp != NULL) {
3573                     Tcl_AppendResult(interp, "style not found: ", styleName, 0);
3574                 }
3575                 return TCL_ERROR;
3576             }
3577         } else if (!strcmp(tvPtr->styleCmd, "%W style create textbox %V")) {
3578             stylePtr = Blt_TreeViewCreateStyle(interp, tvPtr, STYLE_TEXTBOX, styleName);
3579             assert(stylePtr);
3580             Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
3581
3582         } else {
3583             Tcl_DStringInit(&dString);
3584             Blt_TreeViewPercentSubst(tvPtr, entryPtr, columnPtr, tvPtr->styleCmd, styleName, &dString);
3585             /* TODO: should save/restore intep state. */
3586             result = Tcl_GlobalEval(tvPtr->interp, Tcl_DStringValue(&dString));
3587             Tcl_DStringFree(&dString);
3588             if ((tvPtr->flags & TV_DELETED)) {
3589                 return TCL_ERROR;
3590             }
3591             if (result != TCL_OK) {
3592                 if (interp != NULL) {
3593                     Tcl_AppendResult(interp, "error in -stylecommand ", tvPtr->styleCmd, " for: ", styleName, 0);
3594                 }
3595                 return TCL_ERROR;
3596             }
3597             result = Blt_TreeViewGetStyle(interp, tvPtr, styleName, &stylePtr);
3598             if (result != TCL_OK) {
3599                 if (interp != NULL) {
3600                     Tcl_AppendResult(interp, "style not found: ", styleName, 0);
3601                 }
3602                 return TCL_ERROR;
3603             }
3604             Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
3605             if (interp != NULL) {
3606                 Tcl_ResetResult(interp);
3607             }
3608         }
3609     }
3610     *stylePtrPtr = stylePtr;
3611     return TCL_OK;
3612 }
3613
3614 static TreeViewStyle *
3615 CreateStyle(interp, tvPtr, type, styleName, objc, objv, create)
3616      Tcl_Interp *interp;
3617      TreeView *tvPtr;           /* TreeView widget. */
3618      int type;                  /* Type of style: either
3619                                  * STYLE_TEXTBOX,
3620                                  * STYLE_COMBOBOX, or
3621                                  * STYLE_CHECKBOX */
3622     char *styleName;            /* Name of the new style. */
3623     int objc;
3624     Tcl_Obj *CONST *objv;
3625     int create;
3626 {    
3627     Blt_HashEntry *hPtr;
3628     int isNew, ref = 1;
3629     TreeViewStyle *stylePtr;
3630     
3631     hPtr = Blt_CreateHashEntry(&tvPtr->styleTable, styleName, &isNew);
3632     if (!isNew) {
3633         /* Don't kick an error unless styleCmd is changed. */
3634         if (create && (tvPtr->styleCmd == NULL || strcmp(tvPtr->styleCmd, "%W style create textbox %V") == 0 || (tvPtr->styleCmd[0] == 0))) {
3635             stylePtr = Blt_GetHashValue(hPtr);
3636             if (type == (stylePtr->flags&STYLE_TYPE)) {
3637                 ref = 0;
3638                 goto doconf;
3639             }
3640         }
3641         if (interp != NULL) {
3642             Tcl_AppendResult(interp, "style \"", styleName, 
3643                              "\" already exists", (char *)NULL);
3644         }
3645         return NULL;
3646     }
3647     /* Create the new marker based upon the given type */
3648     switch (type) {
3649     case STYLE_TEXTBOX:
3650         stylePtr = CreateTextBox(tvPtr, hPtr);
3651         break;
3652     case STYLE_COMBOBOX:
3653         stylePtr = CreateComboBox(tvPtr, hPtr);
3654         break;
3655     case STYLE_CHECKBOX:
3656         stylePtr = CreateCheckBox(tvPtr, hPtr);
3657         break;
3658     case STYLE_WINDOWBOX:
3659         stylePtr = CreateWindowBox(tvPtr, hPtr);
3660         break;
3661     case STYLE_BARBOX:
3662         stylePtr = CreateBarBox(tvPtr, hPtr);
3663         break;
3664     default:
3665         return NULL;
3666     }
3667 doconf:
3668     Blt_TreeViewOptsInit(tvPtr);
3669     if (Blt_ConfigureComponentFromObj(tvPtr->interp, tvPtr->tkwin, styleName, 
3670         stylePtr->classPtr->className, stylePtr->classPtr->specsPtr, 
3671         objc, objv, (char *)stylePtr, 0) != TCL_OK) {
3672         if (ref) {
3673             Blt_TreeViewFreeStyle(tvPtr, stylePtr);
3674         }
3675         return NULL;
3676     }
3677     if (stylePtr->tile != NULL) {
3678         Blt_SetTileChangedProc(stylePtr->tile, Blt_TreeViewTileChangedProc, tvPtr);
3679     }
3680     if (stylePtr->fillTile != NULL) {
3681         Blt_SetTileChangedProc(stylePtr->fillTile, Blt_TreeViewTileChangedProc, tvPtr);
3682     }
3683     stylePtr->refCount += ref;
3684     return stylePtr;
3685 }
3686
3687 void
3688 Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr)
3689     TreeView *tvPtr;
3690     TreeViewStyle *stylePtr;
3691 {
3692     if (tvPtr->font == NULL) return;
3693     (*stylePtr->classPtr->configProc)(tvPtr, stylePtr);
3694     stylePtr->flags |= STYLE_DIRTY;
3695     Blt_TreeViewEventuallyRedraw(tvPtr);
3696 }
3697
3698 void
3699 Blt_TreeViewUpdateStyles(tvPtr)
3700     TreeView *tvPtr;
3701 {
3702     Blt_HashEntry *hPtr;
3703     Blt_HashSearch cursor;
3704     TreeViewStyle *stylePtr;
3705     Blt_TreeViewUpdateStyleGCs(tvPtr, tvPtr->stylePtr);
3706
3707     for (hPtr = Blt_FirstHashEntry(&tvPtr->styleTable, &cursor); hPtr != NULL;
3708         hPtr = Blt_NextHashEntry(&cursor)) {
3709         stylePtr = Blt_GetHashValue(hPtr);
3710         Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
3711     }
3712 }
3713
3714 TreeViewStyle *
3715 Blt_TreeViewCreateStyle(interp, tvPtr, type, styleName)
3716      Tcl_Interp *interp;
3717      TreeView *tvPtr;           /* TreeView widget. */
3718      int type;                  /* Type of style: either
3719                                  * STYLE_TEXTBOX,
3720                                  * STYLE_COMBOBOX, or
3721                                  * STYLE_CHECKBOX */
3722     char *styleName;            /* Name of the new style. */
3723 {    
3724     return CreateStyle(interp, tvPtr, type, styleName, 0, (Tcl_Obj **)NULL, 0);
3725 }
3726
3727 void
3728 Blt_TreeViewFreeStyle(tvPtr, stylePtr)
3729     TreeView *tvPtr;
3730     TreeViewStyle *stylePtr;
3731 {
3732     stylePtr->refCount--;
3733 #ifdef notdef
3734     fprint(f(stderr, "Blt_TreeViewFreeStyle %s count=%d\n", stylePtr->name,
3735             stylePtr->refCount);
3736 #endif
3737     /* Remove the style from the hash table so that it's name can be used.*/
3738     /* If no cell is using the style, remove it.*/
3739     if ((stylePtr->refCount <= 0) && !(stylePtr->flags & STYLE_USER)){
3740 #ifdef notdef
3741         fprintf(stderr, "freeing %s\n", stylePtr->name);
3742 #endif
3743         /*Blt_HashEntry *hPtr;
3744         hPtr = Blt_FindHashEntry(&tvPtr->styleTagTable, stylePtr->name, &isNew);
3745         if (hPtr != NULL) {
3746             Blt_DeleteHashEntry(&tvPtr->styleTagTable, hPtr);
3747         }*/
3748         Blt_TreeViewOptsInit(tvPtr);
3749         Blt_FreeObjOptions(tvPtr->interp,
3750                    stylePtr->classPtr->specsPtr, (char *)stylePtr, 
3751                    tvPtr->display, 0);
3752         (*stylePtr->classPtr->freeProc)(tvPtr, stylePtr); 
3753         if (stylePtr->hashPtr != NULL) {
3754             Blt_DeleteHashEntry(&tvPtr->styleTable, stylePtr->hashPtr);
3755         } 
3756         if (stylePtr->name != NULL) {
3757             Blt_Free(stylePtr->name);
3758         }
3759         if (tvPtr->subStylePtr == stylePtr) { tvPtr->subStylePtr = NULL; }
3760         if (tvPtr->altStylePtr == stylePtr) { tvPtr->altStylePtr = NULL; }
3761         if (tvPtr->emptyStylePtr == stylePtr) { tvPtr->emptyStylePtr = NULL; }
3762         Blt_Free(stylePtr);
3763     } 
3764 }
3765
3766 void
3767 Blt_TreeViewSetStyleIcon(tvPtr, stylePtr, icon)
3768     TreeView *tvPtr;
3769     TreeViewStyle *stylePtr;
3770     TreeViewIcon icon;
3771 {
3772     TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3773
3774     if (tbPtr && tbPtr->icon != NULL) {
3775         Blt_TreeViewFreeIcon(tvPtr, tbPtr->icon);
3776     }
3777     tbPtr->icon = icon;
3778 }
3779
3780 GC
3781 Blt_TreeViewGetStyleGC(tvPtr, stylePtr)
3782     TreeView *tvPtr;
3783     TreeViewStyle *stylePtr;
3784 {
3785     TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3786     return (tbPtr && tbPtr->gc) ? tbPtr->gc : tvPtr->stylePtr->gc;
3787 }
3788
3789 Tk_3DBorder
3790 Blt_TreeViewGetStyleBorder(tvPtr, stylePtr)
3791     TreeView *tvPtr;
3792     TreeViewStyle *stylePtr;
3793 {
3794     TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3795     Tk_3DBorder border;
3796
3797     if (!tbPtr) {
3798         return tvPtr->border;
3799     }
3800     border = (tbPtr->flags & STYLE_HIGHLIGHT) 
3801         ? tbPtr->highlightBorder : tbPtr->border;
3802     return (border != NULL) ? border : tvPtr->border;
3803 }
3804
3805 Tk_Font
3806 Blt_TreeViewGetStyleFont(tvPtr, columnPtr, stylePtr)
3807     TreeView *tvPtr;
3808     TreeViewColumn *columnPtr;
3809     TreeViewStyle *stylePtr;
3810 {
3811     TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3812
3813     if (tbPtr != NULL && tbPtr->font != NULL) {
3814         return tbPtr->font;
3815     }
3816     if (columnPtr != NULL && columnPtr->font != NULL) {
3817         return columnPtr->font;
3818     }
3819     return tvPtr->font;
3820 }
3821
3822 XColor *
3823 Blt_TreeViewGetStyleFg(tvPtr, columnPtr, stylePtr)
3824     TreeView *tvPtr;
3825     TreeViewColumn *columnPtr;
3826     TreeViewStyle *stylePtr;
3827 {
3828     TreeViewTextBox *tbPtr = (TreeViewTextBox *)stylePtr;
3829
3830     if (tbPtr && tbPtr->fgColor != NULL) {
3831         return tbPtr->fgColor;
3832     }
3833     if (columnPtr && columnPtr->fgColor) {
3834         return columnPtr->fgColor;
3835     }
3836     return tvPtr->fgColor;
3837 }
3838
3839 static void
3840 DrawValue(tvPtr, entryPtr, valuePtr)
3841     TreeView *tvPtr;
3842     TreeViewEntry *entryPtr;
3843     TreeViewValue *valuePtr;
3844 {
3845     Drawable drawable;
3846     int sx, sy, dx, dy;
3847     int width, height, ishid;
3848     int left, right, top, bottom;
3849     TreeViewColumn *columnPtr;
3850     TreeViewStyle *stylePtr;
3851     Tk_3DBorder selBorder;
3852
3853     stylePtr = valuePtr->stylePtr;
3854     ishid = (stylePtr?stylePtr->hidden:0);
3855     if (stylePtr == NULL) {
3856         stylePtr = CHOOSE(tvPtr->stylePtr, valuePtr->columnPtr->stylePtr);
3857     }
3858     if (stylePtr->cursor != None) {
3859         if (valuePtr == tvPtr->activeValuePtr) {
3860             Tk_DefineCursor(tvPtr->tkwin, stylePtr->cursor);
3861         } else {
3862             if (tvPtr->cursor != None) {
3863                 Tk_DefineCursor(tvPtr->tkwin, tvPtr->cursor);
3864             } else {
3865                 Tk_UndefineCursor(tvPtr->tkwin);
3866             }
3867         }
3868     }
3869     columnPtr = valuePtr->columnPtr;
3870     dx = SCREENX(tvPtr, columnPtr->worldX) + columnPtr->pad.side1-1;
3871     dy = SCREENY(tvPtr, entryPtr->worldY);
3872     height = entryPtr->height - 1;
3873     width = valuePtr->columnPtr->width - PADDING(columnPtr->pad);
3874
3875     top = tvPtr->titleHeight + tvPtr->insetY;
3876     bottom = Tk_Height(tvPtr->tkwin) - tvPtr->insetY;
3877     left = tvPtr->insetX;
3878     right = Tk_Width(tvPtr->tkwin) - tvPtr->insetX;
3879
3880     if (((dx + width) < left) || (dx > right) ||
3881         ((dy + height) < top) || (dy > bottom)) {
3882         return;                 /* Value is clipped. */
3883     }
3884
3885     drawable = Tk_GetPixmap(tvPtr->display, Tk_WindowId(tvPtr->tkwin), 
3886         width, height, Tk_Depth(tvPtr->tkwin));
3887     /* Draw the background of the value. */
3888
3889     if (Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr)) {
3890         selBorder = SELECT_BORDER(tvPtr);
3891         Blt_Fill3DRectangle(tvPtr->tkwin, drawable, selBorder, 0, 0, width, height,
3892             0, TK_RELIEF_FLAT);
3893     } else if ((valuePtr == tvPtr->activeValuePtr) ||
3894         (!Blt_TreeViewEntryIsSelected(tvPtr, entryPtr, columnPtr))) {
3895         Tk_3DBorder border;
3896
3897         border = Blt_TreeViewGetStyleBorder(tvPtr, tvPtr->stylePtr);
3898         Blt_Fill3DRectangle(tvPtr->tkwin, drawable, border, 0, 0, width, height,
3899                 0, TK_RELIEF_FLAT);
3900     } else if (Blt_HasTile(tvPtr->tile) == 0 && Blt_HasTile(columnPtr->tile) == 0) {
3901
3902         Blt_Draw3DRectangle(tvPtr->tkwin, drawable, SELECT_BORDER(tvPtr), 0, 0, 
3903                 width, height, tvPtr->selBorderWidth, tvPtr->selRelief);
3904     }
3905     Blt_TreeViewDrawValue(tvPtr, entryPtr, valuePtr, drawable, 0, 0, entryPtr->flags & ENTRY_ALTROW, ishid);
3906     
3907     /* Clip the drawable if necessary */
3908     sx = sy = 0;
3909     if (dx < left) {
3910         width -= left - dx;
3911         sx += left - dx;
3912         dx = left;
3913     }
3914     if ((dx + width) >= right) {
3915         width -= (dx + width) - right;
3916     }
3917     if (dy < top) {
3918         height -= top - dy;
3919         sy += top - dy;
3920         dy = top;
3921     }
3922     if ((dy + height) >= bottom) {
3923         height -= (dy + height) - bottom;
3924     }
3925     XCopyArea(tvPtr->display, drawable, Tk_WindowId(tvPtr->tkwin), 
3926       tvPtr->lineGC, sx, sy, width,  height, dx, dy);
3927     Tk_FreePixmap(tvPtr->display, drawable);
3928 }
3929
3930 /*
3931  *----------------------------------------------------------------------
3932  *
3933  * StyleActivateOp --
3934  *
3935  *      Turns on/off highlighting for a particular style.
3936  *
3937  *        .t style activate entry column
3938  *
3939  * Results:
3940  *      A standard Tcl result.  If TCL_ERROR is returned, then
3941  *      interp->result contains an error message.
3942  *
3943  *----------------------------------------------------------------------
3944  */
3945 /*ARGSUSED*/
3946 static int
3947 StyleActivateOp(tvPtr, interp, objc, objv)
3948     TreeView *tvPtr;
3949
3950     Tcl_Interp *interp;
3951     int objc;                   /* Not used. */
3952     Tcl_Obj *CONST *objv;
3953 {
3954     TreeViewEntry *entryPtr;
3955     TreeViewValue *valuePtr, *oldPtr;
3956
3957     oldPtr = tvPtr->activeValuePtr;
3958     if (objc == 3) {
3959         Tcl_Obj *listObjPtr; 
3960
3961         valuePtr = tvPtr->activeValuePtr;
3962         entryPtr = tvPtr->activePtr;
3963         listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
3964         if ((entryPtr != NULL) && (valuePtr != NULL)) {
3965             Tcl_Obj *objPtr; 
3966             objPtr = Tcl_NewIntObj(Blt_TreeNodeId(entryPtr->node));
3967             Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
3968             objPtr = Tcl_NewStringObj(valuePtr->columnPtr->key, -1);
3969             Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
3970         } 
3971         Tcl_SetObjResult(interp, listObjPtr);
3972         return TCL_OK;
3973     } else if (objc == 4) {
3974         tvPtr->activeValuePtr = NULL;
3975         if ((oldPtr != NULL)  && (tvPtr->activePtr != NULL)) {
3976             DrawValue(tvPtr, tvPtr->activePtr, oldPtr);
3977         }
3978     } else {
3979         TreeViewColumn *columnPtr;
3980
3981         if (Blt_TreeViewGetEntry(tvPtr, objv[3], &entryPtr) != TCL_OK) {
3982             return TCL_ERROR;
3983         }
3984
3985         if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr) 
3986             != TCL_OK) {
3987             return TCL_ERROR;
3988         }
3989         valuePtr = Blt_TreeViewFindValue(entryPtr, columnPtr);
3990         if (valuePtr == NULL) {
3991             return TCL_OK;
3992         }
3993         tvPtr->activePtr = entryPtr;
3994         tvPtr->activeColumnPtr = columnPtr;
3995         oldPtr = tvPtr->activeValuePtr;
3996         tvPtr->activeValuePtr = valuePtr;
3997         if (valuePtr != oldPtr) {
3998             if (oldPtr != NULL) {
3999                 DrawValue(tvPtr, entryPtr, oldPtr);
4000             }
4001             if (valuePtr != NULL) {
4002                 DrawValue(tvPtr, entryPtr, valuePtr);
4003             }
4004         }
4005     }
4006     return TCL_OK;
4007 }
4008
4009
4010 /*
4011  *----------------------------------------------------------------------
4012  *
4013  * StyleCgetOp --
4014  *
4015  *        .t style cget "styleName" -background
4016  *
4017  *----------------------------------------------------------------------
4018  */
4019 /*ARGSUSED*/
4020 static int
4021 StyleCgetOp(tvPtr, interp, objc, objv)
4022     TreeView *tvPtr;
4023     Tcl_Interp *interp;
4024     int objc;                   /* Not used. */
4025     Tcl_Obj *CONST *objv;
4026 {
4027     TreeViewStyle *stylePtr;
4028
4029     stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4030     if (stylePtr == NULL) {
4031         return TCL_ERROR;
4032     }
4033     Blt_TreeViewOptsInit(tvPtr);
4034     return Blt_ConfigureValueFromObj(interp, tvPtr->tkwin, 
4035         stylePtr->classPtr->specsPtr, (char *)stylePtr, objv[4], 0);
4036 }
4037
4038 /*
4039  *----------------------------------------------------------------------
4040  *
4041  * StyleCheckBoxOp --
4042  *
4043  *        .t style checkbox "styleName" -background blue
4044  *
4045  *----------------------------------------------------------------------
4046  */
4047 /*ARGSUSED*/
4048 static int
4049 StyleCheckBoxOp(tvPtr, interp, objc, objv)
4050     TreeView *tvPtr;
4051     Tcl_Interp *interp;
4052     int objc;                   /* Not used. */
4053     Tcl_Obj *CONST *objv;
4054 {
4055     TreeViewStyle *stylePtr;
4056
4057     stylePtr = CreateStyle(interp, tvPtr, STYLE_CHECKBOX, 
4058         Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4059     if (stylePtr == NULL) {
4060         return TCL_ERROR;
4061     }
4062     stylePtr->refCount = 0;
4063     stylePtr->flags |= STYLE_USER;
4064     Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4065     Tcl_SetObjResult(interp, objv[3]);
4066     return TCL_OK;
4067 }
4068
4069
4070 /*
4071  *----------------------------------------------------------------------
4072  *
4073  * StyleComboBoxOp --
4074  *
4075  *        .t style combobox "styleName" -background blue
4076  *
4077  *----------------------------------------------------------------------
4078  */
4079 /*ARGSUSED*/
4080 static int
4081 StyleComboBoxOp(tvPtr, interp, objc, objv)
4082     TreeView *tvPtr;
4083     Tcl_Interp *interp;
4084     int objc;                   /* Not used. */
4085     Tcl_Obj *CONST *objv;
4086 {
4087     TreeViewStyle *stylePtr;
4088
4089     stylePtr = CreateStyle(interp, tvPtr, STYLE_COMBOBOX, 
4090         Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4091     if (stylePtr == NULL) {
4092         return TCL_ERROR;
4093     }
4094     stylePtr->refCount = 0;
4095     stylePtr->flags |= STYLE_USER;
4096     Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4097     Tcl_SetObjResult(interp, objv[3]);
4098     return TCL_OK;
4099 }
4100
4101 /*
4102  *----------------------------------------------------------------------
4103  *
4104  * StyleConfigureOp --
4105  *
4106  *      This procedure is called to process a list of configuration
4107  *      options database, in order to reconfigure a style.
4108  *
4109  *        .t style configure "styleName" option value
4110  *
4111  * Results:
4112  *      A standard Tcl result.  If TCL_ERROR is returned, then
4113  *      interp->result contains an error message.
4114  *
4115  * Side effects:
4116  *      Configuration information, such as text string, colors, font,
4117  *      etc. get set for stylePtr; old resources get freed, if there
4118  *      were any.  
4119  *
4120  *----------------------------------------------------------------------
4121  */
4122 static int
4123 StyleConfigureOp(tvPtr, interp, objc, objv)
4124     TreeView *tvPtr;
4125     Tcl_Interp *interp;
4126     int objc;
4127     Tcl_Obj *CONST *objv;
4128 {
4129     TreeViewStyle *stylePtr;
4130
4131     if (Blt_TreeViewGetStyleMake(interp, tvPtr, Tcl_GetString(objv[3]), &stylePtr,
4132         NULL, NULL, NULL) != TCL_OK) {
4133         return TCL_ERROR;
4134     }
4135     stylePtr->refCount--;
4136
4137     Blt_TreeViewOptsInit(tvPtr);
4138     if (objc == 4) {
4139         return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, 
4140             stylePtr->classPtr->specsPtr, (char *)stylePtr, (Tcl_Obj *)NULL, 0);
4141     } else if (objc == 5) {
4142         return Blt_ConfigureInfoFromObj(interp, tvPtr->tkwin, 
4143                 stylePtr->classPtr->specsPtr, (char *)stylePtr, objv[4], 0);
4144     }
4145     if (Blt_ConfigureWidgetFromObj(interp, tvPtr->tkwin, 
4146         stylePtr->classPtr->specsPtr, objc - 4, objv + 4, (char *)stylePtr, 
4147         BLT_CONFIG_OBJV_ONLY, NULL) != TCL_OK) {        
4148         return TCL_ERROR;
4149     }
4150     if (stylePtr->tile != NULL) {
4151         Blt_SetTileChangedProc(stylePtr->tile, Blt_TreeViewTileChangedProc, tvPtr);
4152     }
4153     if (stylePtr->fillTile != NULL) {
4154         Blt_SetTileChangedProc(stylePtr->fillTile, Blt_TreeViewTileChangedProc, tvPtr);
4155     }
4156     (*stylePtr->classPtr->configProc)(tvPtr, stylePtr);
4157     Blt_TreeViewMakeStyleDirty(tvPtr);
4158     Blt_TreeViewEventuallyRedraw(tvPtr);
4159     return TCL_OK;
4160 }
4161
4162 /*
4163  *----------------------------------------------------------------------
4164  *
4165  * StyleForgetOp --
4166  *
4167  *      Eliminates one or more style names whose
4168  *      reference count is zero (i.e. no one else is using it).
4169  *
4170  *        .t style forget "styleName"...
4171  *
4172  * Results:
4173  *      A standard Tcl result.  If TCL_ERROR is returned, then
4174  *      interp->result contains an error message.
4175  *
4176  *----------------------------------------------------------------------
4177  */
4178 static int
4179 StyleForgetOp(tvPtr, interp, objc, objv)
4180     TreeView *tvPtr;
4181
4182     Tcl_Interp *interp;
4183     int objc;
4184     Tcl_Obj *CONST *objv;
4185 {
4186     TreeViewStyle *stylePtr;
4187     int i;
4188
4189     for (i = 3; i < objc; i++) {
4190         stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[i]));
4191         if (stylePtr == NULL) {
4192             return TCL_ERROR;
4193         }
4194         if (stylePtr->refCount > 1 || stylePtr == tvPtr->stylePtr) {
4195             continue;
4196         }
4197         if (stylePtr->hashPtr != NULL) {
4198             Blt_DeleteHashEntry(&tvPtr->styleTable, stylePtr->hashPtr);
4199             stylePtr->hashPtr = NULL;
4200         }
4201         stylePtr->refCount--;
4202         stylePtr->flags &= ~STYLE_USER;
4203         Blt_TreeViewFreeStyle(tvPtr, stylePtr);
4204     }
4205     Blt_TreeViewEventuallyRedraw(tvPtr);
4206     return TCL_OK;
4207 }
4208
4209 static int
4210 StyleUseOp(tvPtr, interp, objc, objv)
4211     TreeView *tvPtr;
4212
4213     Tcl_Interp *interp;
4214     int objc;
4215     Tcl_Obj *CONST *objv;
4216 {
4217     TreeViewStyle *stylePtr;
4218
4219     stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4220     if (stylePtr == NULL) {
4221         return TCL_ERROR;
4222     }
4223     Tcl_SetObjResult(interp, Tcl_NewIntObj(stylePtr->refCount-1));
4224     return TCL_OK;
4225 }
4226
4227
4228 static int StyleLookup(char *string) {
4229     if (!strcmp(string, "combobox")) {
4230         return STYLE_COMBOBOX;
4231     }
4232     if (!strcmp(string, "textbox")) {
4233         return STYLE_TEXTBOX;
4234     }
4235     if (!strcmp(string, "barbox")) {
4236         return STYLE_BARBOX;
4237     }
4238     if (!strcmp(string, "windowbox")) {
4239         return STYLE_WINDOWBOX;
4240     }
4241     if (!strcmp(string, "checkbox")) {
4242         return STYLE_CHECKBOX;
4243     }
4244     return -1;
4245 }
4246
4247 /*
4248  *----------------------------------------------------------------------
4249  *
4250  * StyleTypeOp --
4251  *
4252  *      Return the type of a style.
4253  *
4254  *        .t style type "styleName"...
4255  *
4256  * Results:
4257  *      A standard Tcl result.  If TCL_ERROR is returned, then
4258  *      interp->result contains an error message.
4259  *
4260  *----------------------------------------------------------------------
4261  */
4262 static int
4263 StyleTypeOp(tvPtr, interp, objc, objv)
4264     TreeView *tvPtr;
4265
4266     Tcl_Interp *interp;
4267     int objc;
4268     Tcl_Obj *CONST *objv;
4269 {
4270     TreeViewStyle *stylePtr, *newStylePtr;
4271     TreeViewAllStyles all;
4272     const char *cp;
4273     char *newType;
4274     int nType;
4275     
4276     if (objc == 3) {
4277         cp = "textbox combobox checkbox barbox windowbox";
4278         Tcl_AppendResult(interp, cp, 0);
4279         return TCL_OK;
4280     }
4281     stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4282     if (stylePtr == NULL) {
4283         return TCL_ERROR;
4284     }
4285     if (stylePtr->flags & STYLE_CHECKBOX) {
4286         cp = "checkbox";
4287     } else if (stylePtr->flags & STYLE_COMBOBOX) {
4288         cp = "combobox";
4289     } else if (stylePtr->flags & STYLE_WINDOWBOX) {
4290         cp = "windowbox";
4291     } else if (stylePtr->flags & STYLE_BARBOX) {
4292         cp = "barbox";
4293     } else  {
4294         cp = "textbox";
4295     }
4296
4297     if (objc == 4) {
4298         Tcl_AppendResult(interp, cp, 0);
4299         return TCL_OK;
4300     }
4301     if (!strcmp(stylePtr->name, "text")) {
4302         Tcl_AppendResult(interp, "can not change type of style \"text\"", 0);
4303         return TCL_ERROR;
4304     }
4305     newType = Tcl_GetString(objv[4]);
4306     nType = StyleLookup( newType );
4307     if (nType<0) {
4308         Tcl_AppendResult(interp, "unknown type: ", newType, 0);
4309         return TCL_ERROR;
4310     }
4311     /* if (!strcmp(newType, cp)) {
4312         return TCL_OK;
4313     }*/
4314     /* Change the style */
4315     newStylePtr = CreateStyle(interp, tvPtr, nType, "__%%StyleTypeSet%%_", 0, 0, 0);
4316     if (newStylePtr == NULL) {
4317         return TCL_ERROR;
4318     }
4319     newStylePtr->flags |= STYLE_USER;
4320     memcpy(&all, stylePtr, sizeof(all));
4321     memcpy(stylePtr, newStylePtr, sizeof(all));
4322     memcpy(newStylePtr, &all, sizeof(all));
4323     newStylePtr->refCount = stylePtr->refCount;
4324     stylePtr->refCount = all.tb.refCount ;
4325     newStylePtr->hashPtr = stylePtr->hashPtr;
4326     stylePtr->hashPtr = all.tb.hashPtr ;
4327     newStylePtr->name = stylePtr->name;
4328     stylePtr->name = all.tb.name ;
4329     
4330     newStylePtr->flags &= ~STYLE_USER;
4331     Blt_TreeViewFreeStyle(tvPtr, newStylePtr);
4332     Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4333     tvPtr->flags |= (TV_DIRTY | TV_LAYOUT | TV_SCROLL | TV_UPDATE);
4334     Blt_TreeViewMakeStyleDirty(tvPtr);
4335     Blt_TreeViewEventuallyRedraw(tvPtr);
4336     return TCL_OK;
4337 }
4338
4339 /*
4340  *----------------------------------------------------------------------
4341  *
4342  * StyleHighlightOp --
4343  *
4344  *      Turns on/off highlighting for a particular style.
4345  *
4346  *        .t style highlight styleName ?on|off?
4347  *
4348  * Results:
4349  *      A standard Tcl result.  If TCL_ERROR is returned, then
4350  *      interp->result contains an error message.
4351  *
4352  *----------------------------------------------------------------------
4353  */
4354 /*ARGSUSED*/
4355 static int
4356 StyleHighlightOp(tvPtr, interp, objc, objv)
4357     TreeView *tvPtr;
4358
4359     Tcl_Interp *interp;
4360     int objc;                   /* Not used. */
4361     Tcl_Obj *CONST *objv;
4362 {
4363     TreeViewStyle *stylePtr;
4364     int bool, oldBool;
4365
4366     stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4367     if (stylePtr == NULL) {
4368         return TCL_ERROR;
4369     }
4370     oldBool = ((stylePtr->flags & STYLE_HIGHLIGHT) != 0);
4371     if (objc<=4) {
4372         Tcl_SetObjResult(interp, Tcl_NewIntObj(oldBool));
4373         return TCL_OK;
4374     }
4375     if (Tcl_GetBooleanFromObj(interp, objv[4], &bool) != TCL_OK) {
4376         return TCL_ERROR;
4377     }
4378     if (oldBool != bool) {
4379         if (bool) {
4380             stylePtr->flags |= STYLE_HIGHLIGHT;
4381         } else {
4382             stylePtr->flags &= ~STYLE_HIGHLIGHT;
4383         }
4384         Blt_TreeViewEventuallyRedraw(tvPtr);
4385     }
4386     return TCL_OK;
4387 }
4388
4389 /*
4390  *----------------------------------------------------------------------
4391  *
4392  * StyleNamesOp --
4393  *
4394  *      Lists the names of all the current styles in the treeview widget.
4395  *
4396  *        .t style names
4397  *
4398  * Results:
4399  *      Always TCL_OK.
4400  *
4401  *----------------------------------------------------------------------
4402  */
4403 /*ARGSUSED*/
4404 static int
4405 StyleNamesOp(tvPtr, interp, objc, objv)
4406     TreeView *tvPtr;
4407
4408     Tcl_Interp *interp;
4409     int objc;                   /* Not used. */
4410     Tcl_Obj *CONST *objv;       /* Not used. */
4411 {
4412     Blt_HashEntry *hPtr;
4413     Blt_HashSearch cursor;
4414     Tcl_Obj *listObjPtr, *objPtr;
4415     TreeViewStyle *stylePtr;
4416
4417     listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
4418     for (hPtr = Blt_FirstHashEntry(&tvPtr->styleTable, &cursor); hPtr != NULL;
4419          hPtr = Blt_NextHashEntry(&cursor)) {
4420         stylePtr = Blt_GetHashValue(hPtr);
4421         objPtr = Tcl_NewStringObj(stylePtr->name, -1);
4422         Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4423     }
4424     Tcl_SetObjResult(interp, listObjPtr);
4425     return TCL_OK;
4426 }
4427
4428 static int
4429 StyleSlavesOp(tvPtr, interp, objc, objv)
4430     TreeView *tvPtr;
4431
4432     Tcl_Interp *interp;
4433     int objc;
4434     Tcl_Obj *CONST *objv;
4435 {
4436     Blt_HashEntry *hPtr;
4437     Blt_HashSearch cursor;
4438     char *name, *window = NULL;
4439     Tcl_DString dStr;
4440     TreeViewColumn *columnPtr = NULL;
4441     TreeViewEntry *entryPtr = NULL;
4442     TreeViewStyle *stylePtr = NULL;
4443     int visible;
4444     WindowCell  *wcPtr;
4445     int sub = 0, chkVis = 0;
4446
4447     if (!(objc%2))  {
4448         goto argerr;
4449     }
4450     while (objc>3) {
4451         char *string;
4452
4453         string = Tcl_GetString(objv[3]);
4454         if (string[0] != '-') {
4455 argerr:
4456             Tcl_AppendResult(interp, "expected -col, -id, -style, -visible, or -info", 0);
4457             return TCL_ERROR;
4458         }
4459         if ((strcmp(string, "-col") == 0)) {
4460             if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr) 
4461             != TCL_OK) {
4462                 return TCL_ERROR;
4463             }
4464         } else if ((strcmp(string, "-info") == 0)) {
4465             
4466             window = Tcl_GetString(objv[4]);
4467             
4468         } else if ((strcmp(string, "-id") == 0)) {
4469             if (Blt_TreeViewGetEntry(tvPtr, objv[4], &entryPtr) 
4470             != TCL_OK) {
4471                 return TCL_ERROR;
4472             }
4473         } else if ((strcmp(string, "-visible") == 0)) {
4474             if (Tcl_GetBooleanFromObj(interp, objv[4], &visible) != TCL_OK) {
4475                 return TCL_ERROR;
4476             }
4477             chkVis = 1;
4478         } else if ((strcmp(string, "-style") == 0)) {
4479             stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[4]));
4480             if (stylePtr == NULL) {
4481                 return TCL_ERROR;
4482             }
4483         } else break;
4484         
4485         objc -= 2;
4486         objv += 2;
4487         sub++;
4488     }
4489     if (objc != 3)  {
4490         goto argerr;
4491     }
4492     
4493     
4494     Tcl_DStringInit(&dStr);
4495     for (hPtr = Blt_FirstHashEntry(&tvPtr->winTable, &cursor); hPtr != NULL;
4496         hPtr = Blt_NextHashEntry(&cursor)) {
4497         name = (char*)Blt_GetHashKey(&tvPtr->winTable, hPtr);
4498         if (sub) {
4499             wcPtr = (WindowCell*)Blt_GetHashValue(hPtr);
4500             if (wcPtr == NULL) continue;
4501             if (columnPtr && columnPtr != wcPtr->columnPtr) continue;
4502             if (entryPtr && entryPtr != wcPtr->entryPtr) continue;
4503             if (stylePtr && stylePtr != (TreeViewStyle*)wcPtr->stylePtr) continue;
4504             if (chkVis) {
4505                 if (wcPtr->flags&TV_WINDOW_DRAW) {
4506                     if (!visible) continue;
4507                 } else {
4508                     if (visible) continue;
4509                 }
4510             }
4511             if (window) {
4512                 if (wcPtr->tkwin == NULL) continue;
4513                 if (strcmp(window,Tk_PathName(wcPtr->tkwin))) continue;
4514                 Tcl_DStringAppendElement(&dStr, "-style");
4515                 Tcl_DStringAppendElement(&dStr, wcPtr->stylePtr->name);
4516                 Tcl_DStringAppendElement(&dStr, "-col");
4517                 Tcl_DStringAppendElement(&dStr, wcPtr->columnPtr->key);
4518                 Tcl_DStringAppendElement(&dStr, "-id");
4519                 Tcl_DStringAppendElement(&dStr, Blt_Itoa(Blt_TreeNodeId(wcPtr->entryPtr->node)));
4520                 Tcl_DStringAppendElement(&dStr, "-visible");
4521                 Tcl_DStringAppendElement(&dStr, (wcPtr->flags&TV_WINDOW_DRAW)?"True":"False");
4522                 Tcl_DStringResult(interp, &dStr);
4523                 return TCL_OK;
4524             }
4525         }
4526         if (name != NULL) {
4527             Tcl_DStringAppendElement(&dStr, name);
4528         }
4529     }
4530     Tcl_DStringResult(interp, &dStr);
4531     return TCL_OK;
4532 }
4533
4534 /*
4535  *----------------------------------------------------------------------
4536  *
4537  * StyleSetOp --
4538  *
4539  *      Sets a style for a given key for all the ids given.
4540  *
4541  *        .t style set styleName column node...
4542  *
4543  * Results:
4544  *      A standard Tcl result.  If TCL_ERROR is returned, then
4545  *      interp->result contains an error message.
4546  *
4547  *----------------------------------------------------------------------
4548  */
4549 static int
4550 StyleSetOp(tvPtr, interp, objc, objv)
4551     TreeView *tvPtr;
4552
4553     Tcl_Interp *interp;
4554     int objc;
4555     Tcl_Obj *CONST *objv;
4556 {
4557     TreeViewColumn *columnPtr;
4558     TreeViewEntry *entryPtr;
4559     TreeViewStyle *stylePtr = NULL, *oldStylePtr;
4560     TreeViewTagInfo info = {0};
4561     char *string;
4562     int i, count;
4563
4564     count = 0;
4565     if (Blt_TreeViewGetColumn(interp, tvPtr, objv[4], &columnPtr) != TCL_OK) {
4566         return TCL_ERROR;
4567     }
4568     string = Tcl_GetString(objv[3]);
4569     if (string[0]) {
4570         if (Blt_TreeViewGetStyleMake(interp, tvPtr, string, &stylePtr, columnPtr,
4571             NULL, NULL) != TCL_OK) {
4572             return TCL_ERROR;
4573         }
4574         stylePtr->refCount--;
4575     }
4576     if (stylePtr) {
4577         stylePtr->flags |= STYLE_LAYOUT;
4578     }
4579     for (i = 5; i < objc; i++) {
4580         if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[i], &info) != TCL_OK) {
4581             return TCL_ERROR;
4582         }
4583         for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL; 
4584              entryPtr = Blt_TreeViewNextTaggedEntry(&info)) {
4585             register TreeViewValue *valuePtr;
4586
4587              if (columnPtr == &tvPtr->treeColumn) {
4588                  if (stylePtr == entryPtr->realStylePtr) continue;
4589                  if (stylePtr) stylePtr->refCount++;
4590                  oldStylePtr = entryPtr->realStylePtr;
4591                  entryPtr->realStylePtr = stylePtr;
4592                  if (stylePtr) stylePtr->refCount++;
4593                  if (oldStylePtr != NULL) {
4594                      Blt_TreeViewFreeStyle(tvPtr, oldStylePtr);
4595                  }
4596                  count++;
4597                  continue;
4598              }
4599              
4600              for (valuePtr = entryPtr->values; valuePtr != NULL; 
4601                  valuePtr = valuePtr->nextPtr) {
4602                 if (valuePtr->columnPtr == columnPtr) {
4603                     if (stylePtr == valuePtr->stylePtr) break;
4604                     if (stylePtr) stylePtr->refCount++;
4605                     oldStylePtr = valuePtr->stylePtr;
4606                     valuePtr->stylePtr = stylePtr;
4607                     if (stylePtr) stylePtr->refCount++;
4608                     if (oldStylePtr != NULL) {
4609                         Blt_TreeViewFreeStyle(tvPtr, oldStylePtr);
4610                     }
4611                     count++;
4612                     break;
4613                 }
4614             }
4615         }
4616         Blt_TreeViewDoneTaggedEntries(&info);
4617     }
4618     tvPtr->flags |= (TV_DIRTY | TV_LAYOUT | TV_SCROLL | TV_UPDATE);
4619     Blt_TreeViewMakeStyleDirty(tvPtr);
4620     Blt_TreeViewEventuallyRedraw(tvPtr);
4621     Tcl_SetObjResult(interp, Tcl_NewIntObj(count));
4622     return TCL_OK;
4623 }
4624
4625 /*
4626  *----------------------------------------------------------------------
4627  *
4628  * StyleFindOp --
4629  *
4630  *      Find all entries with the given style.
4631  *      If a column is given, find entries with the given style in that column.
4632  *
4633  *        .t style find styleName ?tagorid? ?column?
4634  *
4635  * Results:
4636  *      A standard Tcl result.  If TCL_ERROR is returned, then
4637  *      interp->result contains an error message.
4638  *
4639  *----------------------------------------------------------------------
4640  */
4641 static int
4642 StyleFindOp(tvPtr, interp, objc, objv)
4643     TreeView *tvPtr;
4644
4645     Tcl_Interp *interp;
4646     int objc;
4647     Tcl_Obj *CONST *objv;
4648 {
4649     TreeViewEntry *entryPtr;
4650     TreeViewStyle *stylePtr;
4651     TreeViewTagInfo info = {0};
4652     TreeViewColumn *columnPtr = NULL;
4653     Tcl_Obj *listObjPtr, *objPtr;
4654
4655     if (tvPtr->styleCmd == NULL || strcmp(tvPtr->styleCmd, "%W style create textbox %V")) {
4656         stylePtr = GetStyle(interp, tvPtr, Tcl_GetString(objv[3]));
4657         if (stylePtr == NULL) {
4658             return TCL_ERROR;
4659         }
4660     } else {
4661         stylePtr = GetStyle(NULL, tvPtr, Tcl_GetString(objv[3]));
4662         if (stylePtr == NULL) {
4663             return TCL_OK;
4664         }
4665     }
4666     if (objc>5) {
4667         if (Blt_TreeViewGetColumn(interp, tvPtr, objv[5], &columnPtr) != TCL_OK) {
4668             return TCL_ERROR;
4669         }
4670     }
4671     if (objc>4) {
4672         if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[4], &info) != TCL_OK) {
4673             return TCL_ERROR;
4674         }
4675     } else {
4676         objPtr = Tcl_NewStringObj("all", -1);
4677         if (Blt_TreeViewFindTaggedEntries(tvPtr, objPtr, &info) != TCL_OK) {
4678             Tcl_DecrRefCount(objPtr);
4679             return TCL_ERROR;
4680         }
4681         Tcl_DecrRefCount(objPtr);
4682     }
4683         
4684     listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
4685     for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL; 
4686         entryPtr = Blt_TreeViewNextTaggedEntry(&info)) {
4687         register TreeViewValue *valuePtr;
4688             
4689         if (columnPtr == NULL || columnPtr == &tvPtr->treeColumn) {
4690             if (entryPtr->realStylePtr == stylePtr) {
4691                 objPtr = Tcl_NewIntObj(Blt_TreeNodeId(entryPtr->node));
4692                 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4693                 continue;
4694             }
4695         }
4696
4697         for (valuePtr = entryPtr->values; valuePtr != NULL; 
4698             valuePtr = valuePtr->nextPtr) {
4699             if (columnPtr && valuePtr->columnPtr != columnPtr) continue;
4700             if (valuePtr->stylePtr != stylePtr) continue;
4701             objPtr = Tcl_NewIntObj(Blt_TreeNodeId(entryPtr->node));
4702             Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4703             break;
4704         }
4705     }
4706     Blt_TreeViewDoneTaggedEntries(&info);
4707     Tcl_SetObjResult(interp, listObjPtr);
4708     return TCL_OK;
4709 }
4710
4711 /*
4712  *----------------------------------------------------------------------
4713  *
4714  * StyleTextBoxOp --
4715  *
4716  *        .t style textbox "styleName" -background blue
4717  *
4718  *----------------------------------------------------------------------
4719  */
4720 /*ARGSUSED*/
4721 static int
4722 StyleTextBoxOp(tvPtr, interp, objc, objv)
4723     TreeView *tvPtr;
4724     Tcl_Interp *interp;
4725     int objc;                   /* Not used. */
4726     Tcl_Obj *CONST *objv;
4727 {
4728     TreeViewStyle *stylePtr;
4729
4730     stylePtr = CreateStyle(interp, tvPtr, STYLE_TEXTBOX, 
4731         Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4732     if (stylePtr == NULL) {
4733         return TCL_ERROR;
4734     }
4735     stylePtr->refCount = 0;
4736     stylePtr->flags |= STYLE_USER;
4737     Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4738     Tcl_SetObjResult(interp, objv[3]);
4739     return TCL_OK;
4740 }
4741
4742 /*
4743  *----------------------------------------------------------------------
4744  *
4745  * StyleWindowBoxOp --
4746  *
4747  *        .t style window "styleName"
4748  *
4749  *----------------------------------------------------------------------
4750  */
4751 /*ARGSUSED*/
4752 static int
4753 StyleWindowBoxOp(tvPtr, interp, objc, objv)
4754     TreeView *tvPtr;
4755     Tcl_Interp *interp;
4756     int objc;                   /* Not used. */
4757     Tcl_Obj *CONST *objv;
4758 {
4759     TreeViewStyle *stylePtr;
4760
4761     stylePtr = CreateStyle(interp, tvPtr, STYLE_WINDOWBOX, 
4762         Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4763     if (stylePtr == NULL) {
4764         return TCL_ERROR;
4765     }
4766     stylePtr->refCount = 0;
4767     stylePtr->flags |= STYLE_USER;
4768     Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4769     Tcl_SetObjResult(interp, objv[3]);
4770     return TCL_OK;
4771 }
4772 /*
4773  *----------------------------------------------------------------------
4774  *
4775  * StyleBarBoxOp --
4776  *
4777  *        .t style textbox "styleName" -background blue
4778  *
4779  *----------------------------------------------------------------------
4780  */
4781 /*ARGSUSED*/
4782 static int
4783 StyleBarBoxOp(tvPtr, interp, objc, objv)
4784     TreeView *tvPtr;
4785     Tcl_Interp *interp;
4786     int objc;                   /* Not used. */
4787     Tcl_Obj *CONST *objv;
4788 {
4789     TreeViewStyle *stylePtr;
4790
4791     stylePtr = CreateStyle(interp, tvPtr, STYLE_BARBOX, 
4792         Tcl_GetString(objv[3]), objc - 4, objv + 4, 1);
4793     if (stylePtr == NULL) {
4794         return TCL_ERROR;
4795     }
4796     stylePtr->refCount = 0;
4797     stylePtr->flags |= STYLE_USER;
4798     Blt_TreeViewUpdateStyleGCs(tvPtr, stylePtr);
4799     Tcl_SetObjResult(interp, objv[3]);
4800     return TCL_OK;
4801 }
4802
4803
4804 /*
4805  *----------------------------------------------------------------------
4806  *
4807  * StyleGetOp --
4808  *
4809  *      Get style set for each given key for the id given.
4810  *
4811  *        .t style get column tagorid
4812  *
4813  * Results:
4814  *      A standard Tcl result.  If TCL_ERROR is returned, then
4815  *      interp->result contains an error message.
4816  *
4817  *----------------------------------------------------------------------
4818  */
4819 static int
4820 StyleGetOp(tvPtr, interp, objc, objv)
4821     TreeView *tvPtr;
4822     Tcl_Interp *interp;
4823     int objc;
4824     Tcl_Obj *CONST *objv;
4825 {
4826     TreeViewColumn *columnPtr;
4827     TreeViewEntry *entryPtr;
4828     TreeViewTagInfo info = {0};
4829     Tcl_Obj *listObjPtr, *objPtr;
4830
4831     if (Blt_TreeViewGetColumn(interp, tvPtr, objv[3], &columnPtr) != TCL_OK) {
4832         return TCL_ERROR;
4833     }
4834
4835     if (Blt_TreeViewFindTaggedEntries(tvPtr, objv[4], &info) != TCL_OK) {
4836         return TCL_ERROR;
4837     }
4838     listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
4839     for (entryPtr = Blt_TreeViewFirstTaggedEntry(&info); entryPtr != NULL; 
4840         entryPtr = Blt_TreeViewNextTaggedEntry(&info)) {
4841         register TreeViewValue *valuePtr;
4842
4843         if (columnPtr == &tvPtr->treeColumn) {
4844             if (entryPtr->realStylePtr != NULL) {
4845                 objPtr = Tcl_NewStringObj(entryPtr->realStylePtr->name, -1);
4846             } else {
4847                 objPtr = Tcl_NewStringObj("",0);
4848             }
4849             Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4850             continue;
4851         }
4852         
4853         for (valuePtr = entryPtr->values; valuePtr != NULL; 
4854             valuePtr = valuePtr->nextPtr) {
4855             if (valuePtr->columnPtr == columnPtr) {
4856                 if (valuePtr->stylePtr != NULL) {
4857                     objPtr = Tcl_NewStringObj(valuePtr->stylePtr->name, -1);
4858                 } else {
4859                     objPtr = Tcl_NewStringObj("",0);
4860                 }
4861                 Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
4862                 break;
4863             }
4864         }
4865     }
4866     Blt_TreeViewDoneTaggedEntries(&info);
4867     Tcl_SetObjResult(interp, listObjPtr);
4868     return TCL_OK;
4869 }
4870
4871 #if 0
4872 /*
4873  *----------------------------------------------------------------------
4874  *
4875  * StylePriorityOp --
4876  *
4877  *      Get style with highest priority for given key for the id given.
4878  *
4879  *        .t style priority column tagorid
4880  *
4881  * Results:
4882  *      A standard Tcl result.  If TCL_ERROR is returned, then
4883  *      interp->result contains an error message.
4884  *
4885  *----------------------------------------------------------------------
4886  */
4887 static int
4888 StylePriorityOp(tvPtr, interp, objc, objv)
4889     TreeView *tvPtr;
4890     Tcl_Interp *interp;
4891     int objc;
4892     Tcl_Obj *CONST *objv;
4893 {
4894     TreeViewColumn *columnPtr;
4895     TreeViewEntry *entryPtr;
4896     TreeViewValue *valuePtr;
4897     TreeViewStyle *s[4];
4898     int i, h = -1, p = -1;
4899
4900     s[3] = tvPtr->stylePtr;
4901     
4902     if (Blt_TreeViewGetColumn(interp, tvPtr, objv[3], &columnPtr) != TCL_OK) {
4903         return TCL_ERROR;
4904     }
4905
4906     if (Blt_TreeViewGetEntry(tvPtr, objv[4], &entryPtr) != TCL_OK) {
4907         return TCL_ERROR;
4908     }
4909
4910     if (columnPtr == &tvPtr->treeColumn) {
4911         s[0] = entryPtr->realStylePtr;
4912     } else {
4913         s[0] = NULL;
4914         for (valuePtr = entryPtr->values; valuePtr != NULL; 
4915             valuePtr = valuePtr->nextPtr) {
4916             if (valuePtr->columnPtr == columnPtr) {
4917                 s[0] = valuePtr->stylePtr;
4918                 break;
4919             }
4920         }
4921     }
4922     s[1] = entryPtr->stylePtr;
4923     s[2] = columnPtr->stylePtr;
4924     for (i=0; i<4; i++) {
4925         if (s[i]==0) continue;
4926         if (h<0) { h = i; }
4927         if (s[i]->priority > p) {
4928             h = i;
4929             p = s[i]->priority;
4930         }
4931     }
4932     Tcl_SetObjResult(interp, Tcl_NewStringObj(s[h]->name, -1));
4933     return TCL_OK;
4934 }
4935 #endif
4936 /*
4937  *----------------------------------------------------------------------
4938  *
4939  * StyleCreateOp --
4940  *
4941  *        .t style create "styleType" "styleName" -background blue
4942  *
4943  *----------------------------------------------------------------------
4944  */
4945 /*ARGSUSED*/
4946 static int
4947 StyleCreateOp(tvPtr, interp, objc, objv)
4948     TreeView *tvPtr;
4949     Tcl_Interp *interp;
4950     int objc;                   /* Not used. */
4951     Tcl_Obj *CONST *objv;
4952 {
4953     char *string;
4954     
4955     string = Tcl_GetString(objv[3]);
4956     if (!strcmp(string, "combobox")) {
4957         return StyleComboBoxOp(tvPtr, interp, objc-1, objv+1);
4958     }
4959     if (!strcmp(string, "textbox")) {
4960         return StyleTextBoxOp(tvPtr, interp, objc-1, objv+1);
4961     }
4962     if (!strcmp(string, "barbox")) {
4963         return StyleBarBoxOp(tvPtr, interp, objc-1, objv+1);
4964     }
4965     if (!strcmp(string, "windowbox")) {
4966         return StyleWindowBoxOp(tvPtr, interp, objc-1, objv+1);
4967     }
4968     if (!strcmp(string, "checkbox")) {
4969         return StyleCheckBoxOp(tvPtr, interp, objc-1, objv+1);
4970     }
4971     Tcl_AppendResult(interp, "bad style type \"", string, "\", should be one of: textbox, barbox, checkbox, combobox, or windowbox", 0);
4972     return TCL_ERROR;
4973 }
4974
4975 /*
4976  *----------------------------------------------------------------------
4977  *
4978  * StyleOp --
4979  *
4980  *      .t style activate $node $column
4981  *      .t style activate 
4982  *      .t style cget "highlight" -foreground
4983  *      .t style configure "highlight" -fg blue -bg green
4984  *      .t style checkbox "highlight"
4985  *      .t style highlight "highlight" on|off
4986  *      .t style combobox "highlight"
4987  *      .t style text "highlight"
4988  *      .t style forget "highlight"
4989  *      .t style get "mtime" $node
4990  *      .t style names
4991  *      .t style set "highlight" "mtime" all
4992  *      .t style unset "mtime" all
4993  *
4994  *---------------------------------------------------------------------- 
4995  */
4996 static Blt_OpSpec styleOps[] = {
4997     {"activate", 1, (Blt_Op)StyleActivateOp, 3, 5,"?entry column?",},
4998     /*{"barbox", 2, (Blt_Op)StyleBarBoxOp, 4, 0, "styleName options...",},*/
4999     {"cget", 2, (Blt_Op)StyleCgetOp, 5, 5, "styleName option",},
5000     /*{"checkbox", 2, (Blt_Op)StyleCheckBoxOp, 4, 0, "styleName options...",},
5001     {"combobox", 3, (Blt_Op)StyleComboBoxOp, 4, 0, "styleName options...",},*/
5002     {"configure", 3, (Blt_Op)StyleConfigureOp, 4, 0, "styleName options...",},
5003     {"create", 2, (Blt_Op)StyleCreateOp, 5, 0, "type styleName options...",},
5004     {"find", 2, (Blt_Op)StyleFindOp, 4, 6, "styleName ?tagOrId? ?column?",},
5005     {"forget", 2, (Blt_Op)StyleForgetOp, 3, 0, "styleName...",},
5006     {"get", 1, (Blt_Op)StyleGetOp, 5, 5, "column tagOrId",},
5007     {"highlight", 1, (Blt_Op)StyleHighlightOp, 4, 5, "styleName ?boolean?",},
5008     {"names", 1, (Blt_Op)StyleNamesOp, 3, 3, "",}, 
5009     /*{"priority", 1, (Blt_Op)StylePriorityOp, 5, 5, "column tagOrId",}, */
5010     {"set", 2, (Blt_Op)StyleSetOp, 6, 0, "styleName column tagOrId ...",},
5011     {"slaves", 2, (Blt_Op)StyleSlavesOp, 3, 0, "?-col col? ?-entry id? ?-style name? ?-visible bool? ?-info win?",},
5012     /*{"textbox", 2, (Blt_Op)StyleTextBoxOp, 4, 0, "styleName options...",}, */
5013     {"type", 2, (Blt_Op)StyleTypeOp, 3, 5, "?styleName? ?newType?",},
5014     {"use", 2, (Blt_Op)StyleUseOp, 4, 4, "styleName",},
5015     /*{"windowbox", 2, (Blt_Op)StyleWindowBoxOp, 4, 0, "styleName options...",},*/
5016 };
5017
5018 static int nStyleOps = sizeof(styleOps) / sizeof(Blt_OpSpec);
5019
5020 int
5021 Blt_TreeViewStyleOp(tvPtr, interp, objc, objv)
5022     TreeView *tvPtr;
5023     Tcl_Interp *interp;
5024     int objc;
5025     Tcl_Obj *CONST *objv;
5026 {
5027     Blt_Op proc;
5028     int result;
5029
5030     proc = Blt_GetOpFromObj(interp, nStyleOps, styleOps, BLT_OP_ARG2, objc, 
5031         objv, 0);
5032     if (proc == NULL) {
5033         return TCL_ERROR;
5034     }
5035     result = (*proc)(tvPtr, interp, objc, objv);
5036     return result;
5037 }
5038 #endif /* NO_TREEVIEW */