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 *
StickyToObj(clientData,interp,tkwin,widgRec,offset)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
ObjToSticky(clientData,interp,tkwin,objPtr,widgRec,offset)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
ObjToIcon(clientData,interp,tkwin,objPtr,widgRec,offset)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 *
IconToObj(clientData,interp,tkwin,widgRec,offset)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
FreeIcon(clientData,display,widgRec,offset,oldPtr)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 
Blt_TreeViewStyleIsFmt(TreeView * tvPtr,TreeViewStyle * stylePtr)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. */
newStyle(TreeView * tvPtr,Blt_HashEntry * hPtr,int size)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 *
CreateTextBox(tvPtr,hPtr)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
ConfigureTextBox(tvPtr,stylePtr)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
MeasureTextBox(tvPtr,stylePtr,valuePtr)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
GetPriorityStyle(TreeView * tvPtr,TreeViewEntry * entryPtr,TreeViewValue * valuePtr,TreeViewStyle * inStylePtr,TreeViewStyle * stylePtr)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
Blt_GetPriorityStyle(TreeViewStyle * stylePtr,TreeView * tvPtr,TreeViewColumn * columnPtr,TreeViewEntry * entryPtr,TreeViewValue * valuePtr,TreeViewStyle * inStylePtr,int flags)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
drawTextBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y,sRec)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
GetColorPats(tvPtr,entryPtr,valuePtr,stylePtr,fgPtr)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
DrawTextBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)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
EditTextBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)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
FreeTextBox(tvPtr,stylePtr)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 *
CreateCheckBox(tvPtr,hPtr)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
ConfigureCheckBox(tvPtr,stylePtr)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
MeasureCheckBox(tvPtr,stylePtr,valuePtr)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
DrawCheckBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)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
PickCheckBox(entryPtr,valuePtr,stylePtr,worldX,worldY)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
EditCheckBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)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
FreeCheckBox(tvPtr,stylePtr)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 *
CreateComboBox(tvPtr,hPtr)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
ConfigureComboBox(tvPtr,stylePtr)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
MeasureComboBox(tvPtr,stylePtr,valuePtr)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
DrawComboBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)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
PickComboBox(entryPtr,valuePtr,stylePtr,worldX,worldY)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
EditComboBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)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
FreeComboBox(tvPtr,stylePtr)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 *
CreateBarBox(tvPtr,hPtr)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
ConfigureBarBox(tvPtr,stylePtr)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
MeasureBarBox(tvPtr,stylePtr,valuePtr)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
DrawBarBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)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
PickBarBox(entryPtr,valuePtr,stylePtr,worldX,worldY)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
EditBarBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)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
FreeBarBox(tvPtr,stylePtr)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 *
CreateWindowBox(tvPtr,hPtr)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
ConfigureWindowBox(tvPtr,stylePtr)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
MeasureWindowBox(tvPtr,stylePtr,valuePtr)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
EmbWinRemove(WindowCell * wcPtr)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
Blt_TreeViewFreeWindows(TreeView * tvPtr)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
EmbWinUnmapNow(Tk_Window ewTkwin,Tk_Window tkwin)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 
EmbWinRequestProc(ClientData clientData,Tk_Window tkwin)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
Blt_TreeViewMarkWindows(TreeView * tvPtr,int flag)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 *
bltTreeViewFindWindow(TreeViewEntry * entryPtr,TreeViewColumn * columnPtr)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 
isValidSubWin(TreeView * tvPtr,Tk_Window tkwin)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 *
bltTreeViewWindowMake(TreeView * tvPtr,TreeViewEntry * entryPtr,TreeViewValue * valuePtr,TreeViewWindowBox * wbPtr)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. */
EmbWinLostSlaveProc(ClientData clientData,Tk_Window tkwin)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
EmbWinStructureProc(clientData,eventPtr)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
Blt_WinResizeAlways(Tk_Window tkwin)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
EmbWinDisplay(TreeView * tvPtr,WindowCell * wcPtr,int x,int y,int width,int height)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
Blt_TreeViewWindowUpdate(TreeViewEntry * entryPtr,TreeViewColumn * columnPtr)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
Blt_TreeViewWindowRelease(TreeViewEntry * entryPtr,TreeViewColumn * columnPtr)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
DrawWindowBox(tvPtr,drawable,entryPtr,valuePtr,stylePtr,icon,x,y)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
EditWindowBox(tvPtr,entryPtr,valuePtr,stylePtr,x,y,retVal)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
FreeWindowBox(tvPtr,stylePtr)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 *
GetStyle(interp,tvPtr,styleName)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
Blt_TreeViewGetStyle(interp,tvPtr,styleName,stylePtrPtr)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
Blt_TreeViewGetStyleMake(interp,tvPtr,styleName,stylePtrPtr,columnPtr,entryPtr,valuePtr)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 *
CreateStyle(interp,tvPtr,type,styleName,objc,objv,create)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
Blt_TreeViewUpdateStyleGCs(tvPtr,stylePtr)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
Blt_TreeViewUpdateStyles(tvPtr)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 *
Blt_TreeViewCreateStyle(interp,tvPtr,type,styleName)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
Blt_TreeViewFreeStyle(tvPtr,stylePtr)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 */
5039