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.4 2002/10/16 07:31:48 hobbs Exp $ 12 */ 13 14#include "tkTable.h" 15 16static char * Cmd_GetName _ANSI_ARGS_((const Cmd_Struct *cmds, int val)); 17static int Cmd_GetValue _ANSI_ARGS_((const Cmd_Struct *cmds, 18 const char *arg)); 19static void Cmd_GetError _ANSI_ARGS_((Tcl_Interp *interp, 20 const Cmd_Struct *cmds, const char *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 */ 40void 41Table_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 72int 73TableOptionBdSet(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 CONST84 char *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 CONST84 char **argv; 87 88 if ((type == BD_TABLE) && (value[0] == '\0')) { 89 /* 90 * NULL strings aren't allowed for the table global -bd 91 */ 92 Tcl_AppendResult(interp, "borderwidth value may not be empty", 93 (char *) NULL); 94 return TCL_ERROR; 95 } 96 97 if ((type == BD_TABLE) || (type == BD_TABLE_TAG)) { 98 TableTag *tagPtr = (TableTag *) (widgRec + offset); 99 borderStr = &(tagPtr->borderStr); 100 bordersPtr = &(tagPtr->borders); 101 bdPtr = tagPtr->bd; 102 } else if (type == BD_TABLE_WIN) { 103 TableEmbWindow *tagPtr = (TableEmbWindow *) widgRec; 104 borderStr = &(tagPtr->borderStr); 105 bordersPtr = &(tagPtr->borders); 106 bdPtr = tagPtr->bd; 107 } else { 108 panic("invalid type given to TableOptionBdSet\n"); 109 return TCL_ERROR; /* lint */ 110 } 111 112 result = Tcl_SplitList(interp, value, &argc, &argv); 113 if (result == TCL_OK) { 114 int i, bd[4]; 115 116 if (((type == BD_TABLE) && (argc == 0)) || (argc == 3) || (argc > 4)) { 117 Tcl_AppendResult(interp, 118 "1, 2 or 4 values must be specified for borderwidth", 119 (char *) NULL); 120 result = TCL_ERROR; 121 } else { 122 /* 123 * We use the shadow bd array first, in case we have an error 124 * parsing arguments half way through. 125 */ 126 for (i = 0; i < argc; i++) { 127 if (Tk_GetPixels(interp, tkwin, argv[i], &(bd[i])) != TCL_OK) { 128 result = TCL_ERROR; 129 break; 130 } 131 } 132 /* 133 * If everything is OK, store the parsed and given values for 134 * easy retrieval. 135 */ 136 if (result == TCL_OK) { 137 for (i = 0; i < argc; i++) { 138 bdPtr[i] = MAX(0, bd[i]); 139 } 140 if (*borderStr) { 141 ckfree(*borderStr); 142 } 143 if (value) { 144 *borderStr = (char *) ckalloc(strlen(value) + 1); 145 strcpy(*borderStr, value); 146 } else { 147 *borderStr = NULL; 148 } 149 *bordersPtr = argc; 150 } 151 } 152 ckfree ((char *) argv); 153 } 154 155 return result; 156} 157 158/* 159 *---------------------------------------------------------------------- 160 * 161 * TableOptionBdGet -- 162 * 163 * Results: 164 * Value of the -bd option. 165 * 166 * Side effects: 167 * None. 168 * 169 *---------------------------------------------------------------------- 170 */ 171 172char * 173TableOptionBdGet(clientData, tkwin, widgRec, offset, freeProcPtr) 174 ClientData clientData; /* Type of struct being set. */ 175 Tk_Window tkwin; /* Window containing canvas widget. */ 176 char *widgRec; /* Pointer to record for item. */ 177 int offset; /* Offset into item. */ 178 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with 179 * information about how to reclaim 180 * storage for return string. */ 181{ 182 register int type = (int) clientData; 183 184 if (type == BD_TABLE) { 185 return ((TableTag *) (widgRec + offset))->borderStr; 186 } else if (type == BD_TABLE_TAG) { 187 return ((TableTag *) widgRec)->borderStr; 188 } else if (type == BD_TABLE_WIN) { 189 return ((TableEmbWindow *) widgRec)->borderStr; 190 } else { 191 panic("invalid type given to TableOptionBdSet\n"); 192 return NULL; /* lint */ 193 } 194} 195 196/* 197 *---------------------------------------------------------------------- 198 * 199 * TableTagConfigureBd -- 200 * This routine configures the border values based on a tag. 201 * The previous value of the bd string (oldValue) is assumed to 202 * be a valid value for this tag. 203 * 204 * Results: 205 * A standard Tcl result. 206 * 207 * Side effects: 208 * It may adjust the value used by -bd. 209 * 210 *---------------------------------------------------------------------- 211 */ 212 213int 214TableTagConfigureBd(Table *tablePtr, TableTag *tagPtr, 215 char *oldValue, int nullOK) 216{ 217 int i, argc, result = TCL_OK; 218 CONST84 char **argv; 219 220 /* 221 * First check to see if the value really changed. 222 */ 223 if (strcmp(tagPtr->borderStr ? tagPtr->borderStr : "", 224 oldValue ? oldValue : "") == 0) { 225 return TCL_OK; 226 } 227 228 tagPtr->borders = 0; 229 if (!nullOK && ((tagPtr->borderStr == NULL) 230 || (*(tagPtr->borderStr) == '\0'))) { 231 /* 232 * NULL strings aren't allowed for this tag 233 */ 234 result = TCL_ERROR; 235 } else if (tagPtr->borderStr) { 236 result = Tcl_SplitList(tablePtr->interp, tagPtr->borderStr, 237 &argc, &argv); 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 argv[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(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_SplitList(tablePtr->interp, oldValue, &argc, &argv); 271 for (i = 0; i < argc; i++) { 272 Tk_GetPixels(tablePtr->interp, tablePtr->tkwin, 273 argv[i], &(tagPtr->bd[i])); 274 } 275 ckfree ((char *) argv); 276 tagPtr->borders = argc; 277 tagPtr->borderStr = (char *) ckalloc(length); 278 memcpy(tagPtr->borderStr, 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 303int 304Cmd_OptionSet(ClientData clientData, Tcl_Interp *interp, 305 Tk_Window unused, CONST84 char *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 332char * 333Cmd_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 Cmd_GetName(p,mode); 339} 340 341/* 342 * simple Cmd_Struct lookup functions 343 */ 344 345char * 346Cmd_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 354int 355Cmd_GetValue(const Cmd_Struct *cmds, const char *arg) 356{ 357 unsigned int len = strlen(arg); 358 for(;cmds->name && cmds->name[0];cmds++) { 359 if (!strncmp(cmds->name, arg, len)) return cmds->value; 360 } 361 return 0; 362} 363 364void 365Cmd_GetError(Tcl_Interp *interp, const Cmd_Struct *cmds, const char *arg) 366{ 367 int i; 368 Tcl_AppendResult(interp, "bad option \"", arg, "\" must be ", (char *) 0); 369 for(i=0;cmds->name && cmds->name[0];cmds++,i++) { 370 Tcl_AppendResult(interp, (i?", ":""), cmds->name, (char *) 0); 371 } 372} 373