1 /*
2 * tkTableUtil.c --
3 *
4 * This module contains utility functions for table widgets.
5 *
6 * Copyright (c) 2000-2002 Jeffrey Hobbs
7 *
8 * See the file "license.terms" for information on usage and redistribution
9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10 *
11 * RCS: @(#) $Id: tkTableUtil.c,v 1.2 2004/02/08 03:09:48 cerney Exp $
12 */
13
14 #include "tkTable.h"
15
16 static char * Cmd_GetName _ANSI_ARGS_((const Cmd_Struct *cmds, int val));
17 static int Cmd_GetValue _ANSI_ARGS_((const Cmd_Struct *cmds,
18 Arg arg));
19 static void Cmd_GetError _ANSI_ARGS_((Tcl_Interp *interp,
20 const Cmd_Struct *cmds, Arg arg));
21
22 /*
23 *--------------------------------------------------------------
24 *
25 * Table_ClearHashTable --
26 * This procedure is invoked to clear a STRING_KEY hash table,
27 * freeing the string entries and then deleting the hash table.
28 * The hash table cannot be used after calling this, except to
29 * be freed or reinitialized.
30 *
31 * Results:
32 * Cached info will be lost.
33 *
34 * Side effects:
35 * Can cause redraw.
36 * See the user documentation.
37 *
38 *--------------------------------------------------------------
39 */
40 void
Table_ClearHashTable(Tcl_HashTable * hashTblPtr)41 Table_ClearHashTable(Tcl_HashTable *hashTblPtr)
42 {
43 Tcl_HashEntry *entryPtr;
44 Tcl_HashSearch search;
45 char *value;
46
47 for (entryPtr = Tcl_FirstHashEntry(hashTblPtr, &search);
48 entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
49 value = (char *) Tcl_GetHashValue(entryPtr);
50 if (value != NULL) ckfree(value);
51 }
52
53 Tcl_DeleteHashTable(hashTblPtr);
54 }
55
56 /*
57 *----------------------------------------------------------------------
58 *
59 * TableOptionBdSet --
60 *
61 * This routine configures the borderwidth value for a tag.
62 *
63 * Results:
64 * A standard Tcl result.
65 *
66 * Side effects:
67 * It may adjust the tag struct values of bd[0..4] and borders.
68 *
69 *----------------------------------------------------------------------
70 */
71
72 int
TableOptionBdSet(clientData,interp,tkwin,value,widgRec,offset)73 TableOptionBdSet(clientData, interp, tkwin, value, widgRec, offset)
74 ClientData clientData; /* Type of struct being set. */
75 Tcl_Interp *interp; /* Used for reporting errors. */
76 Tk_Window tkwin; /* Window containing table widget. */
77 Arg value; /* Value of option. */
78 char *widgRec; /* Pointer to record for item. */
79 int offset; /* Offset into item. */
80 {
81 char **borderStr;
82 int *bordersPtr, *bdPtr;
83 int type = (int) clientData;
84 int result = TCL_OK;
85 int argc;
86 Arg *args;
87
88
89 if ((type == BD_TABLE) && (STREQ(LangString(value),"") )) {
90 /*
91 * NULL strings aren't allowed for the table global -bd
92 */
93 Tcl_AppendResult(interp, "borderwidth value may not be empty",
94 (char *) NULL);
95 return TCL_ERROR;
96 }
97
98 if ((type == BD_TABLE) || (type == BD_TABLE_TAG)) {
99 TableTag *tagPtr = (TableTag *) (widgRec + offset);
100 borderStr = &(tagPtr->borderStr);
101 bordersPtr = &(tagPtr->borders);
102 bdPtr = tagPtr->bd;
103 } else if (type == BD_TABLE_WIN) {
104 TableEmbWindow *tagPtr = (TableEmbWindow *) widgRec;
105 borderStr = &(tagPtr->borderStr);
106 bordersPtr = &(tagPtr->borders);
107 bdPtr = tagPtr->bd;
108 } else {
109 panic("invalid type given to TableOptionBdSet\n");
110 return TCL_ERROR; /* lint */
111 }
112
113 result = Tcl_ListObjGetElements(interp, value, &argc, &args);
114 if (result == TCL_OK) {
115 int i, bd[4];
116
117 if (((type == BD_TABLE) && (argc == 0)) || (argc == 3) || (argc > 4)) {
118 Tcl_AppendResult(interp,
119 "1, 2 or 4 values must be specified for borderwidth",
120 (char *) NULL);
121 result = TCL_ERROR;
122 } else {
123 /*
124 * We use the shadow bd array first, in case we have an error
125 * parsing arguments half way through.
126 */
127 for (i = 0; i < argc; i++) {
128 if (Tk_GetPixels(interp, tkwin, LangString(args[i]), &(bd[i])) != TCL_OK) {
129 result = TCL_ERROR;
130 break;
131 }
132 }
133 /*
134 * If everything is OK, store the parsed and given values for
135 * easy retrieval.
136 */
137 if (result == TCL_OK) {
138 for (i = 0; i < argc; i++) {
139 bdPtr[i] = MAX(0, bd[i]);
140 }
141 if (*borderStr) {
142 ckfree(*borderStr);
143 }
144 if (value) {
145 *borderStr = (char *) ckalloc( strlen( LangString(value) ) + 1);
146 strcpy(*borderStr, LangString(value));
147 } else {
148 *borderStr = NULL;
149 }
150 *bordersPtr = argc;
151 }
152 }
153 /*ckfree ((char *) argv);*/
154 }
155
156 return result;
157 }
158
159 /*
160 *----------------------------------------------------------------------
161 *
162 * TableOptionBdGet --
163 *
164 * Results:
165 * Value of the -bd option.
166 *
167 * Side effects:
168 * None.
169 *
170 *----------------------------------------------------------------------
171 */
172
173 Arg
TableOptionBdGet(clientData,tkwin,widgRec,offset,freeProcPtr)174 TableOptionBdGet(clientData, tkwin, widgRec, offset, freeProcPtr)
175 ClientData clientData; /* Type of struct being set. */
176 Tk_Window tkwin; /* Window containing canvas widget. */
177 char *widgRec; /* Pointer to record for item. */
178 int offset; /* Offset into item. */
179 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
180 * information about how to reclaim
181 * storage for return string. */
182 {
183 register int type = (int) clientData;
184
185 if (type == BD_TABLE) {
186 return LangStringArg( ((TableTag *) (widgRec + offset))->borderStr);
187 } else if (type == BD_TABLE_TAG) {
188 return LangStringArg( ((TableTag *) widgRec)->borderStr);
189 } else if (type == BD_TABLE_WIN) {
190 return LangStringArg( ((TableEmbWindow *) widgRec)->borderStr);
191 } else {
192 panic("invalid type given to TableOptionBdSet\n");
193 return NULL; /* lint */
194 }
195 }
196
197 /*
198 *----------------------------------------------------------------------
199 *
200 * TableTagConfigureBd --
201 * This routine configures the border values based on a tag.
202 * The previous value of the bd string (oldValue) is assumed to
203 * be a valid value for this tag.
204 *
205 * Results:
206 * A standard Tcl result.
207 *
208 * Side effects:
209 * It may adjust the value used by -bd.
210 *
211 *----------------------------------------------------------------------
212 */
213
214 int
TableTagConfigureBd(Table * tablePtr,TableTag * tagPtr,Arg oldValue,int nullOK)215 TableTagConfigureBd(Table *tablePtr, TableTag *tagPtr,
216 Arg oldValue, int nullOK)
217 {
218 int i, argc, result = TCL_OK;
219 Arg *args;
220
221 /*
222 * First check to see if the value really changed.
223 */
224 if (strcmp(tagPtr->borderStr ? tagPtr->borderStr : "",
225 LangString(oldValue) ? LangString(oldValue) : "") == 0) {
226 return TCL_OK;
227 }
228
229 tagPtr->borders = 0;
230 if (!nullOK && ((tagPtr->borderStr == NULL)
231 || (*(tagPtr->borderStr) == '\0'))) {
232 /*
233 * NULL strings aren't allowed for this tag
234 */
235 result = TCL_ERROR;
236 } else if (tagPtr->borderStr) {
237 result = Tcl_ListObjGetElements(tablePtr->interp, LangStringArg(tagPtr->borderStr), &argc, &args);
238 if (result == TCL_OK) {
239 if ((!nullOK && (argc == 0)) || (argc == 3) || (argc > 4)) {
240 Tcl_SetResult(tablePtr->interp,
241 "1, 2 or 4 values must be specified to -borderwidth",
242 TCL_STATIC);
243 result = TCL_ERROR;
244 } else {
245 for (i = 0; i < argc; i++) {
246 if (Tk_GetPixels(tablePtr->interp, tablePtr->tkwin,
247 LangString(args[i]), &(tagPtr->bd[i])) != TCL_OK) {
248 result = TCL_ERROR;
249 break;
250 }
251 tagPtr->bd[i] = MAX(0, tagPtr->bd[i]);
252 }
253 tagPtr->borders = argc;
254 }
255 /* ckfree ((char *) argv); */
256 }
257 }
258
259 if (result != TCL_OK) {
260 if (tagPtr->borderStr) {
261 ckfree ((char *) tagPtr->borderStr);
262 }
263 if (oldValue != NULL) {
264 size_t length = strlen(LangString(oldValue)) + 1;
265 /*
266 * We are making the assumption that oldValue is correct.
267 * We have to reparse in case the bad new value had a couple
268 * of correct args before failing on a bad pixel value.
269 */
270 Tcl_ListObjGetElements(tablePtr->interp, oldValue, &argc, &args);
271 for (i = 0; i < argc; i++) {
272 Tk_GetPixels(tablePtr->interp, tablePtr->tkwin,
273 LangString(args[i]), &(tagPtr->bd[i]));
274 }
275 /* ckfree ((char *) argv); */
276 tagPtr->borders = argc;
277 tagPtr->borderStr = (char *) ckalloc(length);
278 memcpy(tagPtr->borderStr, LangString(oldValue), length);
279 } else {
280 tagPtr->borders = 0;
281 tagPtr->borderStr = (char *) NULL;
282 }
283 }
284
285 return result;
286 }
287
288 /*
289 *----------------------------------------------------------------------
290 *
291 * Cmd_OptionSet --
292 *
293 *
294 * Results:
295 * A standard Tcl result.
296 *
297 * Side effects:
298 * None.
299 *
300 *----------------------------------------------------------------------
301 */
302
303 int
Cmd_OptionSet(ClientData clientData,Tcl_Interp * interp,Tk_Window unused,Arg value,char * widgRec,int offset)304 Cmd_OptionSet(ClientData clientData, Tcl_Interp *interp,
305 Tk_Window unused, Arg value, char *widgRec, int offset)
306 {
307 Cmd_Struct *p = (Cmd_Struct *)clientData;
308 int mode = Cmd_GetValue(p,value);
309 if (!mode) {
310 Cmd_GetError(interp,p,value);
311 return TCL_ERROR;
312 }
313 *((int*)(widgRec+offset)) = mode;
314 return TCL_OK;
315 }
316
317 /*
318 *----------------------------------------------------------------------
319 *
320 * Cmd_OptionGet --
321 *
322 *
323 * Results:
324 * Value of the option.
325 *
326 * Side effects:
327 * None.
328 *
329 *----------------------------------------------------------------------
330 */
331
332 Arg
Cmd_OptionGet(ClientData clientData,Tk_Window unused,char * widgRec,int offset,Tcl_FreeProc ** freeProcPtr)333 Cmd_OptionGet(ClientData clientData, Tk_Window unused,
334 char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
335 {
336 Cmd_Struct *p = (Cmd_Struct *)clientData;
337 int mode = *((int*)(widgRec+offset));
338 return LangStringArg(Cmd_GetName(p,mode));
339 }
340
341 /*
342 * simple Cmd_Struct lookup functions
343 */
344
345 char *
Cmd_GetName(const Cmd_Struct * cmds,int val)346 Cmd_GetName(const Cmd_Struct *cmds, int val)
347 {
348 for(;cmds->name && cmds->name[0];cmds++) {
349 if (cmds->value==val) return cmds->name;
350 }
351 return NULL;
352 }
353
354 int
Cmd_GetValue(const Cmd_Struct * cmds,Arg arg)355 Cmd_GetValue(const Cmd_Struct *cmds, Arg arg)
356 {
357 unsigned int len = strlen(LangString(arg));
358 for(;cmds->name && cmds->name[0];cmds++) {
359 if (!strncmp(cmds->name, LangString(arg), len)) return cmds->value;
360 }
361 return 0;
362 }
363
364 void
Cmd_GetError(Tcl_Interp * interp,const Cmd_Struct * cmds,Arg arg)365 Cmd_GetError(Tcl_Interp *interp, const Cmd_Struct *cmds, Arg arg)
366 {
367 int i;
368 char *argstring = LangString(arg);
369 Tcl_AppendResult(interp, "bad option \"", argstring, "\" must be ", (char *) 0);
370 for(i=0;cmds->name && cmds->name[0];cmds++,i++) {
371 Tcl_AppendResult(interp, (i?", ":""), cmds->name, (char *) 0);
372 }
373 }
374