1/* 2 * tkTableTag.c -- 3 * 4 * This module implements tags for table widgets. 5 * 6 * Copyright (c) 1998-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: tkTableTag.c,v 1.15 2008/11/14 22:46:57 hobbs Exp $ 12 */ 13 14#include "tkTable.h" 15 16static TableTag *TableTagGetEntry _ANSI_ARGS_((Table *tablePtr, char *name, 17 int objc, CONST char **argv)); 18static unsigned int TableTagGetPriority _ANSI_ARGS_((Table *tablePtr, 19 TableTag *tagPtr)); 20static void TableImageProc _ANSI_ARGS_((ClientData clientData, int x, 21 int y, int width, int height, int imageWidth, int imageHeight)); 22static int TableOptionReliefSet _ANSI_ARGS_((ClientData clientData, 23 Tcl_Interp *interp, Tk_Window tkwin, 24 CONST84 char *value, char *widgRec, int offset)); 25static char * TableOptionReliefGet _ANSI_ARGS_((ClientData clientData, 26 Tk_Window tkwin, char *widgRec, int offset, 27 Tcl_FreeProc **freeProcPtr)); 28 29static CONST84 char *tagCmdNames[] = { 30 "celltag", "cget", "coltag", "configure", "delete", "exists", 31 "includes", "lower", "names", "raise", "rowtag", (char *) NULL 32}; 33 34enum tagCmd { 35 TAG_CELLTAG, TAG_CGET, TAG_COLTAG, TAG_CONFIGURE, TAG_DELETE, TAG_EXISTS, 36 TAG_INCLUDES, TAG_LOWER, TAG_NAMES, TAG_RAISE, TAG_ROWTAG 37}; 38 39static Cmd_Struct tagState_vals[]= { 40 {"unknown", STATE_UNKNOWN}, 41 {"normal", STATE_NORMAL}, 42 {"disabled", STATE_DISABLED}, 43 {"", 0 } 44}; 45 46static Tk_CustomOption tagStateOpt = 47{ Cmd_OptionSet, Cmd_OptionGet, (ClientData) (&tagState_vals) }; 48static Tk_CustomOption tagBdOpt = 49{ TableOptionBdSet, TableOptionBdGet, (ClientData) BD_TABLE_TAG }; 50static Tk_CustomOption tagReliefOpt = 51{ TableOptionReliefSet, TableOptionReliefGet, (ClientData) NULL }; 52 53/* 54 * The default specification for configuring tags 55 * Done like this to make the command line parsing easy 56 */ 57 58static Tk_ConfigSpec tagConfig[] = { 59 {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", "center", 60 Tk_Offset(TableTag, anchor), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, 61 {TK_CONFIG_BORDER, "-background", "background", "Background", NULL, 62 Tk_Offset(TableTag, bg), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, 63 {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0, 0}, 64 {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, 65 {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth", "", 66 0 /* no offset */, 67 TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK, &tagBdOpt }, 68 {TK_CONFIG_STRING, "-ellipsis", "ellipsis", "Ellipsis", "", 69 Tk_Offset(TableTag, ellipsis), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, 70 {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground", NULL, 71 Tk_Offset(TableTag, fg), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, 72 {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0}, 73 {TK_CONFIG_FONT, "-font", "font", "Font", NULL, 74 Tk_Offset(TableTag, tkfont), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, 75 {TK_CONFIG_STRING, "-image", "image", "Image", NULL, 76 Tk_Offset(TableTag, imageStr), 77 TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, 78 {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify", "left", 79 Tk_Offset(TableTag, justify), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK }, 80 {TK_CONFIG_INT, "-multiline", "multiline", "Multiline", "-1", 81 Tk_Offset(TableTag, multiline), TK_CONFIG_DONT_SET_DEFAULT }, 82 {TK_CONFIG_CUSTOM, "-relief", "relief", "Relief", "flat", 83 Tk_Offset(TableTag, relief), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK, 84 &tagReliefOpt }, 85 {TK_CONFIG_INT, "-showtext", "showText", "ShowText", "-1", 86 Tk_Offset(TableTag, showtext), TK_CONFIG_DONT_SET_DEFAULT }, 87 {TK_CONFIG_CUSTOM, "-state", "state", "State", "unknown", 88 Tk_Offset(TableTag, state), TK_CONFIG_DONT_SET_DEFAULT, &tagStateOpt }, 89 {TK_CONFIG_INT, "-wrap", "wrap", "Wrap", "-1", 90 Tk_Offset(TableTag, wrap), TK_CONFIG_DONT_SET_DEFAULT }, 91 {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, 0, 0} 92}; 93 94/* 95 * The join tag structure is used to create a combined tag, so it 96 * keeps priority info. 97 */ 98typedef struct { 99 TableTag tag; /* must be first */ 100 unsigned int magic; 101 unsigned int pbg, pfg, pborders, prelief, ptkfont, panchor, pimage; 102 unsigned int pstate, pjustify, pmultiline, pwrap, pshowtext, pellipsis; 103} TableJoinTag; 104 105/* 106 *---------------------------------------------------------------------- 107 * 108 * TableImageProc -- 109 * Called when an image associated with a tag is changed. 110 * 111 * Results: 112 * None. 113 * 114 * Side effects: 115 * Invalidates the whole table. 116 * This should only invalidate affected cells, but that info 117 * is not managed... 118 * 119 *---------------------------------------------------------------------- 120 */ 121static void 122TableImageProc(ClientData clientData, int x, int y, int width, int height, 123 int imageWidth, int imageHeight) 124{ 125 TableInvalidateAll((Table *)clientData, 0); 126} 127 128/* 129 *---------------------------------------------------------------------- 130 * 131 * TableNewTag -- 132 * ckallocs space for a new tag structure and inits the structure. 133 * 134 * Results: 135 * Returns a pointer to the new structure. Must be freed later. 136 * 137 * Side effects: 138 * None. 139 * 140 *---------------------------------------------------------------------- 141 */ 142TableTag * 143TableNewTag(Table *tablePtr) 144{ 145 TableTag *tagPtr; 146 147 /* 148 * If tablePtr is NULL, make a regular tag, otherwise make a join tag. 149 */ 150 if (tablePtr == NULL) { 151 tagPtr = (TableTag *) ckalloc(sizeof(TableTag)); 152 memset((VOID *) tagPtr, 0, sizeof(TableTag)); 153 154 /* 155 * Set the values that aren't 0/NULL by default 156 */ 157 tagPtr->anchor = (Tk_Anchor)-1; 158 tagPtr->justify = (Tk_Justify)-1; 159 tagPtr->multiline = -1; 160 tagPtr->relief = -1; 161 tagPtr->showtext = -1; 162 tagPtr->state = STATE_UNKNOWN; 163 tagPtr->wrap = -1; 164 } else { 165 TableJoinTag *jtagPtr = (TableJoinTag *) ckalloc(sizeof(TableJoinTag)); 166 memset((VOID *) jtagPtr, 0, sizeof(TableJoinTag)); 167 tagPtr = (TableTag *) jtagPtr; 168 169 tagPtr->anchor = (Tk_Anchor)-1; 170 tagPtr->justify = (Tk_Justify)-1; 171 tagPtr->multiline = -1; 172 tagPtr->relief = -1; 173 tagPtr->showtext = -1; 174 tagPtr->state = STATE_UNKNOWN; 175 tagPtr->wrap = -1; 176 jtagPtr->magic = 0x99ABCDEF; 177 jtagPtr->pbg = -1; 178 jtagPtr->pfg = -1; 179 jtagPtr->pborders = -1; 180 jtagPtr->prelief = -1; 181 jtagPtr->ptkfont = -1; 182 jtagPtr->panchor = -1; 183 jtagPtr->pimage = -1; 184 jtagPtr->pstate = -1; 185 jtagPtr->pjustify = -1; 186 jtagPtr->pmultiline = -1; 187 jtagPtr->pwrap = -1; 188 jtagPtr->pshowtext = -1; 189 jtagPtr->pellipsis = -1; 190 } 191 192 return (TableTag *) tagPtr; 193} 194 195/* 196 *---------------------------------------------------------------------- 197 * 198 * TableResetTag -- 199 * This routine resets a given tag to the table defaults. 200 * 201 * Results: 202 * Tag will have values changed. 203 * 204 * Side effects: 205 * None. 206 * 207 *---------------------------------------------------------------------- 208 */ 209void 210TableResetTag(Table *tablePtr, TableTag *tagPtr) 211{ 212 TableJoinTag *jtagPtr = (TableJoinTag *) tagPtr; 213 214 if (jtagPtr->magic != 0x99ABCDEF) { 215 panic("bad mojo in TableResetTag"); 216 } 217 218 memset((VOID *) jtagPtr, 0, sizeof(TableJoinTag)); 219 220 tagPtr->anchor = (Tk_Anchor)-1; 221 tagPtr->justify = (Tk_Justify)-1; 222 tagPtr->multiline = -1; 223 tagPtr->relief = -1; 224 tagPtr->showtext = -1; 225 tagPtr->state = STATE_UNKNOWN; 226 tagPtr->wrap = -1; 227 jtagPtr->magic = 0x99ABCDEF; 228 jtagPtr->pbg = -1; 229 jtagPtr->pfg = -1; 230 jtagPtr->pborders = -1; 231 jtagPtr->prelief = -1; 232 jtagPtr->ptkfont = -1; 233 jtagPtr->panchor = -1; 234 jtagPtr->pimage = -1; 235 jtagPtr->pstate = -1; 236 jtagPtr->pjustify = -1; 237 jtagPtr->pmultiline = -1; 238 jtagPtr->pwrap = -1; 239 jtagPtr->pshowtext = -1; 240 jtagPtr->pellipsis = -1; 241 242 /* 243 * Merge in the default tag. 244 */ 245 memcpy((VOID *) jtagPtr, (VOID *) &(tablePtr->defaultTag), 246 sizeof(TableTag)); 247} 248 249/* 250 *---------------------------------------------------------------------- 251 * 252 * TableMergeTag -- 253 * This routine merges two tags by adding any fields from the addTag 254 * that are set to the baseTag. 255 * 256 * Results: 257 * baseTag will inherit all set characteristics of addTag 258 * (addTag thus has the priority). 259 * 260 * Side effects: 261 * None. 262 * 263 *---------------------------------------------------------------------- 264 */ 265void 266TableMergeTag(Table *tablePtr, TableTag *baseTag, TableTag *addTag) 267{ 268 TableJoinTag *jtagPtr = (TableJoinTag *) baseTag; 269 unsigned int prio; 270 271 if (jtagPtr->magic != 0x99ABCDEF) { 272 panic("bad mojo in TableMergeTag"); 273 } 274 275#ifndef NO_TAG_PRIORITIES 276 /* 277 * Find priority for the tag to merge 278 */ 279 prio = TableTagGetPriority(tablePtr, addTag); 280 281 if ((addTag->anchor != -1) && (prio < jtagPtr->panchor)) { 282 baseTag->anchor = addTag->anchor; 283 jtagPtr->panchor = prio; 284 } 285 if ((addTag->bg != NULL) && (prio < jtagPtr->pbg)) { 286 baseTag->bg = addTag->bg; 287 jtagPtr->pbg = prio; 288 } 289 if ((addTag->fg != NULL) && (prio < jtagPtr->pfg)) { 290 baseTag->fg = addTag->fg; 291 jtagPtr->pfg = prio; 292 } 293 if ((addTag->ellipsis != NULL) && (prio < jtagPtr->pellipsis)) { 294 baseTag->ellipsis = addTag->ellipsis; 295 jtagPtr->pellipsis = prio; 296 } 297 if ((addTag->tkfont != NULL) && (prio < jtagPtr->ptkfont)) { 298 baseTag->tkfont = addTag->tkfont; 299 jtagPtr->ptkfont = prio; 300 } 301 if ((addTag->imageStr != NULL) && (prio < jtagPtr->pimage)) { 302 baseTag->imageStr = addTag->imageStr; 303 baseTag->image = addTag->image; 304 jtagPtr->pimage = prio; 305 } 306 if ((addTag->multiline >= 0) && (prio < jtagPtr->pmultiline)) { 307 baseTag->multiline = addTag->multiline; 308 jtagPtr->pmultiline = prio; 309 } 310 if ((addTag->relief != -1) && (prio < jtagPtr->prelief)) { 311 baseTag->relief = addTag->relief; 312 jtagPtr->prelief = prio; 313 } 314 if ((addTag->showtext >= 0) && (prio < jtagPtr->pshowtext)) { 315 baseTag->showtext = addTag->showtext; 316 jtagPtr->pshowtext = prio; 317 } 318 if ((addTag->state != STATE_UNKNOWN) && (prio < jtagPtr->pstate)) { 319 baseTag->state = addTag->state; 320 jtagPtr->pstate = prio; 321 } 322 if ((addTag->justify != -1) && (prio < jtagPtr->pjustify)) { 323 baseTag->justify = addTag->justify; 324 jtagPtr->pjustify = prio; 325 } 326 if ((addTag->wrap >= 0) && (prio < jtagPtr->pwrap)) { 327 baseTag->wrap = addTag->wrap; 328 jtagPtr->pwrap = prio; 329 } 330 if ((addTag->borders) && (prio < jtagPtr->pborders)) { 331 baseTag->borderStr = addTag->borderStr; 332 baseTag->borders = addTag->borders; 333 baseTag->bd[0] = addTag->bd[0]; 334 baseTag->bd[1] = addTag->bd[1]; 335 baseTag->bd[2] = addTag->bd[2]; 336 baseTag->bd[3] = addTag->bd[3]; 337 jtagPtr->pborders = prio; 338 } 339#else 340 if (addTag->anchor != -1) baseTag->anchor = addTag->anchor; 341 if (addTag->bg != NULL) baseTag->bg = addTag->bg; 342 if (addTag->fg != NULL) baseTag->fg = addTag->fg; 343 if (addTag->ellipsis != NULL) baseTag->ellipsis = addTag->ellipsis; 344 if (addTag->tkfont != NULL) baseTag->tkfont = addTag->tkfont; 345 if (addTag->imageStr != NULL) { 346 baseTag->imageStr = addTag->imageStr; 347 baseTag->image = addTag->image; 348 } 349 if (addTag->multiline >= 0) baseTag->multiline = addTag->multiline; 350 if (addTag->relief != -1) baseTag->relief = addTag->relief; 351 if (addTag->showtext >= 0) baseTag->showtext = addTag->showtext; 352 if (addTag->state != STATE_UNKNOWN) baseTag->state = addTag->state; 353 if (addTag->justify != -1) baseTag->justify = addTag->justify; 354 if (addTag->wrap >= 0) baseTag->wrap = addTag->wrap; 355 if (addTag->borders) { 356 baseTag->borderStr = addTag->borderStr; 357 baseTag->borders = addTag->borders; 358 baseTag->bd[0] = addTag->bd[0]; 359 baseTag->bd[1] = addTag->bd[1]; 360 baseTag->bd[2] = addTag->bd[2]; 361 baseTag->bd[3] = addTag->bd[3]; 362 } 363#endif 364} 365 366/* 367 *---------------------------------------------------------------------- 368 * 369 * TableInvertTag -- 370 * This routine swaps background and foreground for the selected tag. 371 * 372 * Results: 373 * Inverts fg and bg of tag. 374 * 375 * Side effects: 376 * None. 377 * 378 *---------------------------------------------------------------------- 379 */ 380void 381TableInvertTag(TableTag *baseTag) 382{ 383 Tk_3DBorder tmpBg; 384 385 tmpBg = baseTag->fg; 386 baseTag->fg = baseTag->bg; 387 baseTag->bg = tmpBg; 388} 389 390/* 391 *---------------------------------------------------------------------- 392 * 393 * TableGetTagBorders -- 394 * This routine gets the border values based on a tag. 395 * 396 * Results: 397 * It returns the values in the int*'s (if not NULL), and the 398 * total number of defined borders as a result. 399 * 400 * Side effects: 401 * None. 402 * 403 *---------------------------------------------------------------------- 404 */ 405int 406TableGetTagBorders(TableTag *tagPtr, 407 int *left, int *right, int *top, int *bottom) 408{ 409 switch (tagPtr->borders) { 410 case 0: 411 if (left) { *left = 0; } 412 if (right) { *right = 0; } 413 if (top) { *top = 0; } 414 if (bottom) { *bottom = 0; } 415 break; 416 case 1: 417 if (left) { *left = tagPtr->bd[0]; } 418 if (right) { *right = tagPtr->bd[0]; } 419 if (top) { *top = tagPtr->bd[0]; } 420 if (bottom) { *bottom = tagPtr->bd[0]; } 421 break; 422 case 2: 423 if (left) { *left = tagPtr->bd[0]; } 424 if (right) { *right = tagPtr->bd[1]; } 425 if (top) { *top = 0; } 426 if (bottom) { *bottom = 0; } 427 break; 428 case 4: 429 if (left) { *left = tagPtr->bd[0]; } 430 if (right) { *right = tagPtr->bd[1]; } 431 if (top) { *top = tagPtr->bd[2]; } 432 if (bottom) { *bottom = tagPtr->bd[3]; } 433 break; 434 default: 435 panic("invalid border value '%d'\n", tagPtr->borders); 436 break; 437 } 438 return tagPtr->borders; 439} 440 441/* 442 *---------------------------------------------------------------------- 443 * 444 * TableTagGetEntry -- 445 * Takes a name and optional args and creates a tag entry in the 446 * table's tag table. 447 * 448 * Results: 449 * A new tag entry will be created and returned. 450 * 451 * Side effects: 452 * None. 453 * 454 *---------------------------------------------------------------------- 455 */ 456static TableTag * 457TableTagGetEntry(Table *tablePtr, char *name, int objc, CONST char **argv) 458{ 459 Tcl_HashEntry *entryPtr; 460 TableTag *tagPtr = NULL; 461 int new; 462 463 entryPtr = Tcl_CreateHashEntry(tablePtr->tagTable, name, &new); 464 if (new) { 465 tagPtr = TableNewTag(NULL); 466 Tcl_SetHashValue(entryPtr, (ClientData) tagPtr); 467 if (tablePtr->tagPrioSize >= tablePtr->tagPrioMax) { 468 int i; 469 /* 470 * Increase the priority list size in blocks of 10 471 */ 472 tablePtr->tagPrioMax += 10; 473 tablePtr->tagPrioNames = (char **) ckrealloc( 474 (char *) tablePtr->tagPrioNames, 475 sizeof(TableTag *) * tablePtr->tagPrioMax); 476 tablePtr->tagPrios = (TableTag **) ckrealloc( 477 (char *) tablePtr->tagPrios, 478 sizeof(TableTag *) * tablePtr->tagPrioMax); 479 for (i = tablePtr->tagPrioSize; i < tablePtr->tagPrioMax; i++) { 480 tablePtr->tagPrioNames[i] = (char *) NULL; 481 tablePtr->tagPrios[i] = (TableTag *) NULL; 482 } 483 } 484 tablePtr->tagPrioNames[tablePtr->tagPrioSize] = 485 (char *) Tcl_GetHashKey(tablePtr->tagTable, entryPtr); 486 tablePtr->tagPrios[tablePtr->tagPrioSize] = tagPtr; 487 tablePtr->tagPrioSize++; 488 } else { 489 tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); 490 } 491 if (objc) { 492 Tk_ConfigureWidget(tablePtr->interp, tablePtr->tkwin, tagConfig, 493 objc, (CONST84 char **) argv, (char *)tagPtr, 494 TK_CONFIG_ARGV_ONLY); 495 } 496 return tagPtr; 497} 498 499/* 500 *---------------------------------------------------------------------- 501 * 502 * TableTagGetPriority -- 503 * Get the priority value for a tag. 504 * 505 * Results: 506 * returns the priority. 507 * 508 * Side effects: 509 * None. 510 * 511 *---------------------------------------------------------------------- 512 */ 513static unsigned int 514TableTagGetPriority(Table *tablePtr, TableTag *tagPtr) 515{ 516 unsigned int prio = 0; 517 while (tagPtr != tablePtr->tagPrios[prio]) { prio++; } 518 return prio; 519} 520 521/* 522 *---------------------------------------------------------------------- 523 * 524 * TableInitTags -- 525 * Creates the static table tags. 526 * 527 * Results: 528 * active, sel, title and flash are created as tags. 529 * 530 * Side effects: 531 * None. 532 * 533 *---------------------------------------------------------------------- 534 */ 535void 536TableInitTags(Table *tablePtr) 537{ 538 static CONST char *activeArgs[] = {"-bg", ACTIVE_BG, "-relief", "flat" }; 539 static CONST char *selArgs[] = {"-bg", SELECT_BG, "-fg", SELECT_FG, 540 "-relief", "sunken" }; 541 static CONST char *titleArgs[] = {"-bg", DISABLED, "-fg", "white", 542 "-relief", "flat", 543 "-state", "disabled" }; 544 static CONST char *flashArgs[] = {"-bg", "red" }; 545 /* 546 * The order of creation is important to priority. 547 */ 548 TableTagGetEntry(tablePtr, "flash", ARSIZE(flashArgs), flashArgs); 549 TableTagGetEntry(tablePtr, "active", ARSIZE(activeArgs), activeArgs); 550 TableTagGetEntry(tablePtr, "sel", ARSIZE(selArgs), selArgs); 551 TableTagGetEntry(tablePtr, "title", ARSIZE(titleArgs), titleArgs); 552} 553 554/* 555 *---------------------------------------------------------------------- 556 * 557 * FindRowColTag -- 558 * Finds a row/col tag based on the row/col styles and tagCommand. 559 * 560 * Results: 561 * Returns tag associated with row/col cell, if any. 562 * 563 * Side effects: 564 * Possible side effects from eval of tagCommand. 565 * IMPORTANT: This plays with the interp result object, 566 * so use of resultPtr in prior command may be invalid after 567 * calling this function. 568 * 569 *---------------------------------------------------------------------- 570 */ 571TableTag * 572FindRowColTag(Table *tablePtr, int cell, int mode) 573{ 574 Tcl_HashEntry *entryPtr; 575 TableTag *tagPtr = NULL; 576 577 entryPtr = Tcl_FindHashEntry((mode == ROW) ? tablePtr->rowStyles 578 : tablePtr->colStyles, (char *) cell); 579 if (entryPtr == NULL) { 580 char *cmd = (mode == ROW) ? tablePtr->rowTagCmd : tablePtr->colTagCmd; 581 if (cmd) { 582 register Tcl_Interp *interp = tablePtr->interp; 583 char buf[INDEX_BUFSIZE]; 584 /* 585 * Since no specific row/col tag exists, eval the given command 586 * with row/col appended 587 */ 588 sprintf(buf, " %d", cell); 589 Tcl_Preserve((ClientData) interp); 590 if (Tcl_VarEval(interp, cmd, buf, (char *)NULL) == TCL_OK) { 591 CONST char *name = Tcl_GetStringResult(interp); 592 if (name && *name) { 593 /* 594 * If a result was returned, check to see if it is 595 * a valid tag. 596 */ 597 entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, name); 598 } 599 } 600 Tcl_Release((ClientData) interp); 601 Tcl_ResetResult(interp); 602 } 603 } 604 if (entryPtr != NULL) { 605 /* 606 * This can be either the one in row|colStyles, 607 * or that returned by eval'ing the row|colTagCmd 608 */ 609 tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); 610 } 611 return tagPtr; 612} 613 614/* 615 *---------------------------------------------------------------------- 616 * 617 * TableCleanupTag -- 618 * Releases the resources used by a tag before it is freed up. 619 * 620 * Results: 621 * None. 622 * 623 * Side effects: 624 * The tag is no longer valid. 625 * 626 *---------------------------------------------------------------------- 627 */ 628void 629TableCleanupTag(Table *tablePtr, TableTag *tagPtr) 630{ 631 /* 632 * Free resources that the optionSpec doesn't specifically know about 633 */ 634 if (tagPtr->image) { 635 Tk_FreeImage(tagPtr->image); 636 } 637 638 Tk_FreeOptions(tagConfig, (char *) tagPtr, tablePtr->display, 0); 639} 640 641/* 642 *-------------------------------------------------------------- 643 * 644 * Table_TagCmd -- 645 * This procedure is invoked to process the tag method 646 * that corresponds to a widget managed by this module. 647 * See the user documentation for details on what it does. 648 * 649 * Results: 650 * A standard Tcl result. 651 * 652 * Side effects: 653 * See the user documentation. 654 * 655 *-------------------------------------------------------------- 656 */ 657int 658Table_TagCmd(ClientData clientData, register Tcl_Interp *interp, 659 int objc, Tcl_Obj *CONST objv[]) 660{ 661 register Table *tablePtr = (Table *)clientData; 662 int result = TCL_OK, cmdIndex, i, newEntry, value, len; 663 int row, col, tagPrio, refresh = 0; 664 TableTag *tagPtr, *tag2Ptr; 665 Tcl_HashEntry *entryPtr, *scanPtr; 666 Tcl_HashTable *hashTblPtr; 667 Tcl_HashSearch search; 668 Tk_Image image; 669 Tcl_Obj *objPtr, *resultPtr; 670 char buf[INDEX_BUFSIZE], *keybuf, *tagname; 671 672 if (objc < 3) { 673 Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); 674 return TCL_ERROR; 675 } 676 677 result = Tcl_GetIndexFromObj(interp, objv[2], tagCmdNames, 678 "tag option", 0, &cmdIndex); 679 if (result != TCL_OK) { 680 return result; 681 } 682 /* 683 * Before using this object, make sure there aren't any calls that 684 * could have changed the interp result, thus freeing the object. 685 */ 686 resultPtr = Tcl_GetObjResult(interp); 687 688 switch ((enum tagCmd) cmdIndex) { 689 case TAG_CELLTAG: /* add named tag to a (group of) cell(s) */ 690 if (objc < 4) { 691 Tcl_WrongNumArgs(interp, 3, objv, "tag ?arg arg ...?"); 692 return TCL_ERROR; 693 } 694 tagname = Tcl_GetStringFromObj(objv[3], &len); 695 if (len == 0) { 696 /* 697 * An empty string was specified, so just delete the tag. 698 */ 699 tagPtr = NULL; 700 } else { 701 /* 702 * Get the pointer to the tag structure. If it doesn't 703 * exist, it will be created. 704 */ 705 tagPtr = TableTagGetEntry(tablePtr, tagname, 0, NULL); 706 } 707 708 if (objc == 4) { 709 /* 710 * The user just wants the cells with this tag returned. 711 * Handle specially tags named: active, flash, sel, title 712 */ 713 714 if ((tablePtr->flags & HAS_ACTIVE) && 715 STREQ(tagname, "active")) { 716 TableMakeArrayIndex( 717 tablePtr->activeRow+tablePtr->rowOffset, 718 tablePtr->activeCol+tablePtr->colOffset, buf); 719 Tcl_SetStringObj(resultPtr, buf, -1); 720 } else if ((tablePtr->flashMode && STREQ(tagname, "flash")) 721 || STREQ(tagname, "sel")) { 722 hashTblPtr = (*tagname == 's') ? 723 tablePtr->selCells : tablePtr->flashCells; 724 for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search); 725 scanPtr != NULL; 726 scanPtr = Tcl_NextHashEntry(&search)) { 727 keybuf = (char *) Tcl_GetHashKey(hashTblPtr, scanPtr); 728 Tcl_ListObjAppendElement(NULL, resultPtr, 729 Tcl_NewStringObj(keybuf, -1)); 730 } 731 } else if (STREQ(tagname, "title") && 732 (tablePtr->titleRows || tablePtr->titleCols)) { 733 for (row = tablePtr->rowOffset; 734 row < tablePtr->rowOffset+tablePtr->rows; row++) { 735 for (col = tablePtr->colOffset; 736 col < tablePtr->colOffset+tablePtr->titleCols; 737 col++) { 738 TableMakeArrayIndex(row, col, buf); 739 Tcl_ListObjAppendElement(NULL, resultPtr, 740 Tcl_NewStringObj(buf, -1)); 741 } 742 } 743 for (row = tablePtr->rowOffset; 744 row < tablePtr->rowOffset+tablePtr->titleRows; 745 row++) { 746 for (col = tablePtr->colOffset+tablePtr->titleCols; 747 col < tablePtr->colOffset+tablePtr->cols; col++) { 748 TableMakeArrayIndex(row, col, buf); 749 Tcl_ListObjAppendElement(NULL, resultPtr, 750 Tcl_NewStringObj(buf, -1)); 751 } 752 } 753 } else { 754 /* 755 * Check this tag pointer amongst all tagged cells 756 */ 757 for (scanPtr = Tcl_FirstHashEntry(tablePtr->cellStyles, 758 &search); 759 scanPtr != NULL; 760 scanPtr = Tcl_NextHashEntry(&search)) { 761 if ((TableTag *) Tcl_GetHashValue(scanPtr) == tagPtr) { 762 keybuf = (char *) Tcl_GetHashKey( 763 tablePtr->cellStyles, scanPtr); 764 Tcl_ListObjAppendElement(NULL, resultPtr, 765 Tcl_NewStringObj(keybuf, -1)); 766 } 767 } 768 } 769 return TCL_OK; 770 } 771 772 /* 773 * Loop through the arguments and fill in the hash table 774 */ 775 for (i = 4; i < objc; i++) { 776 /* 777 * Try and parse the index 778 */ 779 if (TableGetIndexObj(tablePtr, objv[i], &row, &col) 780 != TCL_OK) { 781 return TCL_ERROR; 782 } 783 /* 784 * Get the hash key ready 785 */ 786 TableMakeArrayIndex(row, col, buf); 787 788 if (tagPtr == NULL) { 789 /* 790 * This is a deletion 791 */ 792 entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf); 793 if (entryPtr != NULL) { 794 Tcl_DeleteHashEntry(entryPtr); 795 refresh = 1; 796 } 797 } else { 798 /* 799 * Add a key to the hash table and set it to point to the 800 * Tag structure if it wasn't the same as an existing one 801 */ 802 entryPtr = Tcl_CreateHashEntry(tablePtr->cellStyles, 803 buf, &newEntry); 804 if (newEntry || (tagPtr != 805 (TableTag *) Tcl_GetHashValue(entryPtr))) { 806 Tcl_SetHashValue(entryPtr, (ClientData) tagPtr); 807 refresh = 1; 808 } 809 } 810 /* 811 * Now invalidate this cell for redraw 812 */ 813 if (refresh) { 814 TableRefresh(tablePtr, row-tablePtr->rowOffset, 815 col-tablePtr->colOffset, CELL); 816 } 817 } 818 return TCL_OK; 819 820 case TAG_COLTAG: 821 case TAG_ROWTAG: { /* tag a row or a column */ 822 int forRows = (cmdIndex == TAG_ROWTAG); 823 824 if (objc < 4) { 825 Tcl_WrongNumArgs(interp, 3, objv, "tag ?arg arg ..?"); 826 return TCL_ERROR; 827 } 828 tagname = Tcl_GetStringFromObj(objv[3], &len); 829 if (len == 0) { 830 /* 831 * Empty string, so we want to delete this element 832 */ 833 tagPtr = NULL; 834 } else { 835 /* 836 * Get the pointer to the tag structure. If it doesn't 837 * exist, it will be created. 838 */ 839 tagPtr = TableTagGetEntry(tablePtr, tagname, 0, NULL); 840 } 841 842 /* 843 * Choose the correct hash table based on args 844 */ 845 hashTblPtr = forRows ? tablePtr->rowStyles : tablePtr->colStyles; 846 847 if (objc == 4) { 848 /* the user just wants the tagged cells to be returned */ 849 /* Special handling for tags: active, flash, sel, title */ 850 851 if ((tablePtr->flags & HAS_ACTIVE) && 852 strcmp(tagname, "active") == 0) { 853 Tcl_SetIntObj(resultPtr, 854 (forRows ? 855 tablePtr->activeRow+tablePtr->rowOffset : 856 tablePtr->activeCol+tablePtr->colOffset)); 857 } else if ((tablePtr->flashMode && STREQ(tagname, "flash")) 858 || STREQ(tagname, "sel")) { 859 Tcl_HashTable *cacheTblPtr; 860 861 cacheTblPtr = (Tcl_HashTable *) 862 ckalloc(sizeof(Tcl_HashTable)); 863 Tcl_InitHashTable(cacheTblPtr, TCL_ONE_WORD_KEYS); 864 865 hashTblPtr = (*tagname == 's') ? 866 tablePtr->selCells : tablePtr->flashCells; 867 for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search); 868 scanPtr != NULL; 869 scanPtr = Tcl_NextHashEntry(&search)) { 870 TableParseArrayIndex(&row, &col, 871 Tcl_GetHashKey(hashTblPtr, scanPtr)); 872 value = forRows ? row : col; 873 entryPtr = Tcl_CreateHashEntry(cacheTblPtr, 874 (char *)value, &newEntry); 875 if (newEntry) { 876 Tcl_ListObjAppendElement(NULL, resultPtr, 877 Tcl_NewIntObj(value)); 878 } 879 } 880 881 Tcl_DeleteHashTable(cacheTblPtr); 882 ckfree((char *) (cacheTblPtr)); 883 } else if (STREQ(tagname, "title") && 884 (forRows?tablePtr->titleRows:tablePtr->titleCols)) { 885 if (forRows) { 886 for (row = tablePtr->rowOffset; 887 row < tablePtr->rowOffset+tablePtr->titleRows; 888 row++) { 889 Tcl_ListObjAppendElement(NULL, resultPtr, 890 Tcl_NewIntObj(row)); 891 } 892 } else { 893 for (col = tablePtr->colOffset; 894 col < tablePtr->colOffset+tablePtr->titleCols; 895 col++) { 896 Tcl_ListObjAppendElement(NULL, resultPtr, 897 Tcl_NewIntObj(col)); 898 } 899 } 900 } else { 901 for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search); 902 scanPtr != NULL; 903 scanPtr = Tcl_NextHashEntry(&search)) { 904 /* is this the tag pointer on this row */ 905 if ((TableTag *) Tcl_GetHashValue(scanPtr) == tagPtr) { 906 objPtr = Tcl_NewIntObj( 907 (int) Tcl_GetHashKey(hashTblPtr, scanPtr)); 908 Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); 909 } 910 } 911 } 912 return TCL_OK; 913 } 914 915 /* 916 * Loop through the arguments and fill in the hash table 917 */ 918 for (i = 4; i < objc; i++) { 919 /* 920 * Try and parse the index 921 */ 922 if (Tcl_GetIntFromObj(interp, objv[i], &value) != TCL_OK) { 923 return TCL_ERROR; 924 } 925 if (tagPtr == NULL) { 926 /* 927 * This is a deletion 928 */ 929 entryPtr = Tcl_FindHashEntry(hashTblPtr, (char *)value); 930 if (entryPtr != NULL) { 931 Tcl_DeleteHashEntry(entryPtr); 932 refresh = 1; 933 } 934 } else { 935 /* 936 * Add a key to the hash table and set it to point to the 937 * Tag structure if it wasn't the same as an existing one 938 */ 939 entryPtr = Tcl_CreateHashEntry(hashTblPtr, 940 (char *) value, &newEntry); 941 if (newEntry || (tagPtr != 942 (TableTag *) Tcl_GetHashValue(entryPtr))) { 943 Tcl_SetHashValue(entryPtr, (ClientData) tagPtr); 944 refresh = 1; 945 } 946 } 947 /* and invalidate the row or column affected */ 948 if (refresh) { 949 if (cmdIndex == TAG_ROWTAG) { 950 TableRefresh(tablePtr, value-tablePtr->rowOffset, 0, 951 ROW); 952 } else { 953 TableRefresh(tablePtr, 0, value-tablePtr->colOffset, 954 COL); 955 } 956 } 957 } 958 return TCL_OK; /* COLTAG && ROWTAG */ 959 } 960 961 case TAG_CGET: 962 if (objc != 5) { 963 Tcl_WrongNumArgs(interp, 3, objv, "tagName option"); 964 return TCL_ERROR; 965 } 966 tagname = Tcl_GetString(objv[3]); 967 entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); 968 if (entryPtr == NULL) { 969 goto invalidtag; 970 } else { 971 tagPtr = (TableTag *) Tcl_GetHashValue (entryPtr); 972 result = Tk_ConfigureValue(interp, tablePtr->tkwin, tagConfig, 973 (char *) tagPtr, Tcl_GetString(objv[4]), 0); 974 } 975 return result; /* CGET */ 976 977 case TAG_CONFIGURE: 978 if (objc < 4) { 979 Tcl_WrongNumArgs(interp, 3, objv, "tagName ?arg arg ...?"); 980 return TCL_ERROR; 981 } 982 983 /* 984 * Get the pointer to the tag structure. If it doesn't 985 * exist, it will be created. 986 */ 987 tagPtr = TableTagGetEntry(tablePtr, Tcl_GetString(objv[3]), 988 0, NULL); 989 990 /* 991 * If there were less than 6 args, we return the configuration 992 * (for all or just one option), even for new tags 993 */ 994 if (objc < 6) { 995 result = Tk_ConfigureInfo(interp, tablePtr->tkwin, tagConfig, 996 (char *) tagPtr, (objc == 5) ? 997 Tcl_GetString(objv[4]) : NULL, 0); 998 } else { 999 CONST84 char **argv; 1000 1001 /* Stringify */ 1002 argv = (CONST84 char **) ckalloc((objc + 1) * sizeof(char *)); 1003 for (i = 0; i < objc; i++) 1004 argv[i] = Tcl_GetString(objv[i]); 1005 argv[objc] = NULL; 1006 1007 result = Tk_ConfigureWidget(interp, tablePtr->tkwin, 1008 tagConfig, objc-4, argv+4, (char *) tagPtr, 1009 TK_CONFIG_ARGV_ONLY); 1010 ckfree((char *) argv); 1011 if (result == TCL_ERROR) { 1012 return TCL_ERROR; 1013 } 1014 1015 /* 1016 * Handle change of image name 1017 */ 1018 if (tagPtr->imageStr) { 1019 image = Tk_GetImage(interp, tablePtr->tkwin, 1020 tagPtr->imageStr, 1021 TableImageProc, (ClientData)tablePtr); 1022 if (image == NULL) { 1023 result = TCL_ERROR; 1024 } 1025 } else { 1026 image = NULL; 1027 } 1028 if (tagPtr->image) { 1029 Tk_FreeImage(tagPtr->image); 1030 } 1031 tagPtr->image = image; 1032 1033 /* 1034 * We reconfigured, so invalidate the table to redraw 1035 */ 1036 TableInvalidateAll(tablePtr, 0); 1037 } 1038 return result; 1039 1040 case TAG_DELETE: 1041 /* delete a tag */ 1042 if (objc < 4) { 1043 Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?"); 1044 return TCL_ERROR; 1045 } 1046 /* run through the remaining arguments */ 1047 for (i = 3; i < objc; i++) { 1048 tagname = Tcl_GetString(objv[i]); 1049 /* cannot delete the title tag */ 1050 if (STREQ(tagname, "title") || 1051 STREQ(tagname, "sel") || 1052 STREQ(tagname, "flash") || 1053 STREQ(tagname, "active")) { 1054 Tcl_AppendStringsToObj(resultPtr, "cannot delete ", 1055 tagname, " tag", (char *) NULL); 1056 return TCL_ERROR; 1057 } 1058 entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); 1059 if (entryPtr != NULL) { 1060 /* get the tag pointer */ 1061 tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); 1062 1063 /* delete all references to this tag in rows */ 1064 scanPtr = Tcl_FirstHashEntry(tablePtr->rowStyles, &search); 1065 for (; scanPtr != NULL; 1066 scanPtr = Tcl_NextHashEntry(&search)) { 1067 if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) { 1068 Tcl_DeleteHashEntry(scanPtr); 1069 refresh = 1; 1070 } 1071 } 1072 1073 /* delete all references to this tag in cols */ 1074 scanPtr = Tcl_FirstHashEntry(tablePtr->colStyles, &search); 1075 for (; scanPtr != NULL; 1076 scanPtr = Tcl_NextHashEntry(&search)) { 1077 if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) { 1078 Tcl_DeleteHashEntry(scanPtr); 1079 refresh = 1; 1080 } 1081 } 1082 1083 /* delete all references to this tag in cells */ 1084 scanPtr = Tcl_FirstHashEntry(tablePtr->cellStyles, 1085 &search); 1086 for (; scanPtr != NULL; 1087 scanPtr = Tcl_NextHashEntry(&search)) { 1088 if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) { 1089 Tcl_DeleteHashEntry(scanPtr); 1090 refresh = 1; 1091 } 1092 } 1093 1094 /* 1095 * Remove the tag from the prio list and collapse 1096 * the rest of the tags. We could check for shrinking 1097 * the prio list as well. 1098 */ 1099 for (i = 0; i < tablePtr->tagPrioSize; i++) { 1100 if (tablePtr->tagPrios[i] == tagPtr) break; 1101 } 1102 for ( ; i < tablePtr->tagPrioSize; i++) { 1103 tablePtr->tagPrioNames[i] = 1104 tablePtr->tagPrioNames[i+1]; 1105 tablePtr->tagPrios[i] = tablePtr->tagPrios[i+1]; 1106 } 1107 tablePtr->tagPrioSize--; 1108 1109 /* Release the tag structure */ 1110 TableCleanupTag(tablePtr, tagPtr); 1111 ckfree((char *) tagPtr); 1112 1113 /* And free the hash table entry */ 1114 Tcl_DeleteHashEntry(entryPtr); 1115 } 1116 } 1117 /* since we deleted a tag, redraw the screen */ 1118 if (refresh) { 1119 TableInvalidateAll(tablePtr, 0); 1120 } 1121 return result; 1122 1123 case TAG_EXISTS: 1124 if (objc != 4) { 1125 Tcl_WrongNumArgs(interp, 3, objv, "tagName"); 1126 return TCL_ERROR; 1127 } 1128 Tcl_SetBooleanObj(resultPtr, 1129 (Tcl_FindHashEntry(tablePtr->tagTable, 1130 Tcl_GetString(objv[3])) != NULL)); 1131 return TCL_OK; 1132 1133 case TAG_INCLUDES: 1134 /* does a tag contain a index ? */ 1135 if (objc != 5) { 1136 Tcl_WrongNumArgs(interp, 3, objv, "tag index"); 1137 return TCL_ERROR; 1138 } 1139 tagname = Tcl_GetString(objv[3]); 1140 /* check to see if the tag actually exists */ 1141 entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); 1142 if (entryPtr == NULL) { 1143 /* Unknown tag, just return 0 */ 1144 Tcl_SetBooleanObj(resultPtr, 0); 1145 return TCL_OK; 1146 } 1147 /* parse index */ 1148 if (TableGetIndexObj(tablePtr, objv[4], &row, &col) != TCL_OK) { 1149 return TCL_ERROR; 1150 } 1151 /* create hash key */ 1152 TableMakeArrayIndex(row, col, buf); 1153 1154 if (STREQ(tagname, "active")) { 1155 result = (tablePtr->activeRow+tablePtr->rowOffset==row && 1156 tablePtr->activeCol+tablePtr->colOffset==col); 1157 } else if (STREQ(tagname, "flash")) { 1158 result = (tablePtr->flashMode && 1159 (Tcl_FindHashEntry(tablePtr->flashCells, buf) 1160 != NULL)); 1161 } else if (STREQ(tagname, "sel")) { 1162 result = (Tcl_FindHashEntry(tablePtr->selCells, buf) != NULL); 1163 } else if (STREQ(tagname, "title")) { 1164 result = (row < tablePtr->titleRows+tablePtr->rowOffset || 1165 col < tablePtr->titleCols+tablePtr->colOffset); 1166 } else { 1167 /* get the pointer to the tag structure */ 1168 tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); 1169 scanPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf); 1170 /* 1171 * Look to see if there is a cell, row, or col tag 1172 * for this cell 1173 */ 1174 result = ((scanPtr && 1175 (tagPtr == (TableTag *) Tcl_GetHashValue(scanPtr))) || 1176 (tagPtr == FindRowColTag(tablePtr, row, ROW)) || 1177 (tagPtr == FindRowColTag(tablePtr, col, COL))); 1178 } 1179 /* 1180 * Because we may call FindRowColTag above, we can't use 1181 * the resultPtr, but this is almost equivalent, and is SAFE 1182 */ 1183 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); 1184 return TCL_OK; 1185 1186 case TAG_NAMES: 1187 /* 1188 * Print out the tag names in priority order 1189 */ 1190 if (objc < 3 || objc > 4) { 1191 Tcl_WrongNumArgs(interp, 3, objv, "?pattern?"); 1192 return TCL_ERROR; 1193 } 1194 tagname = (objc == 4) ? Tcl_GetString(objv[3]) : NULL; 1195 for (i = 0; i < tablePtr->tagPrioSize; i++) { 1196 keybuf = tablePtr->tagPrioNames[i]; 1197 if (objc == 3 || Tcl_StringMatch(keybuf, tagname)) { 1198 objPtr = Tcl_NewStringObj(keybuf, -1); 1199 Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); 1200 } 1201 } 1202 return TCL_OK; 1203 1204 case TAG_LOWER: 1205 case TAG_RAISE: 1206 /* 1207 * Change priority of the named tag 1208 */ 1209 if (objc != 4 && objc != 5) { 1210 Tcl_WrongNumArgs(interp, 3, objv, (cmdIndex == TAG_LOWER) ? 1211 "tagName ?belowThis?" : "tagName ?aboveThis?"); 1212 return TCL_ERROR; 1213 } 1214 tagname = Tcl_GetString(objv[3]); 1215 /* check to see if the tag actually exists */ 1216 entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); 1217 if (entryPtr == NULL) { 1218 goto invalidtag; 1219 } 1220 tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr); 1221 tagPrio = TableTagGetPriority(tablePtr, tagPtr); 1222 keybuf = tablePtr->tagPrioNames[tagPrio]; 1223 /* 1224 * In the RAISE case, the priority is one higher (-1) because 1225 * we want the named tag to move above the other in priority. 1226 */ 1227 if (objc == 5) { 1228 tagname = Tcl_GetString(objv[4]); 1229 entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname); 1230 if (entryPtr == NULL) { 1231 goto invalidtag; 1232 } 1233 tag2Ptr = (TableTag *) Tcl_GetHashValue(entryPtr); 1234 if (cmdIndex == TAG_LOWER) { 1235 value = TableTagGetPriority(tablePtr, tag2Ptr); 1236 } else { 1237 value = TableTagGetPriority(tablePtr, tag2Ptr) - 1; 1238 } 1239 } else { 1240 if (cmdIndex == TAG_LOWER) { 1241 /* 1242 * Lower this tag's priority to the bottom. 1243 */ 1244 value = tablePtr->tagPrioSize - 1; 1245 } else { 1246 /* 1247 * Raise this tag's priority to the top. 1248 */ 1249 value = -1; 1250 } 1251 } 1252 if (value < tagPrio) { 1253 /* 1254 * Move tag up in priority. 1255 */ 1256 for (i = tagPrio; i > value; i--) { 1257 tablePtr->tagPrioNames[i] = tablePtr->tagPrioNames[i-1]; 1258 tablePtr->tagPrios[i] = tablePtr->tagPrios[i-1]; 1259 } 1260 i++; 1261 tablePtr->tagPrioNames[i] = keybuf; 1262 tablePtr->tagPrios[i] = tagPtr; 1263 refresh = 1; 1264 } else if (value > tagPrio) { 1265 /* 1266 * Move tag down in priority. 1267 */ 1268 for (i = tagPrio; i < value; i++) { 1269 tablePtr->tagPrioNames[i] = tablePtr->tagPrioNames[i+1]; 1270 tablePtr->tagPrios[i] = tablePtr->tagPrios[i+1]; 1271 } 1272 tablePtr->tagPrioNames[i] = keybuf; 1273 tablePtr->tagPrios[i] = tagPtr; 1274 refresh = 1; 1275 } 1276 /* since we deleted a tag, redraw the screen */ 1277 if (refresh) { 1278 TableInvalidateAll(tablePtr, 0); 1279 } 1280 return TCL_OK; 1281 1282 } 1283 return TCL_OK; 1284 1285 invalidtag: 1286 /* 1287 * When jumping here, ensure the invalid 'tagname' is set already. 1288 */ 1289 Tcl_AppendStringsToObj(resultPtr, "invalid tag name \"", 1290 tagname, "\"", (char *) NULL); 1291 return TCL_ERROR; 1292} 1293 1294/* 1295 *---------------------------------------------------------------------- 1296 * 1297 * TableOptionReliefSet -- 1298 * 1299 * This routine configures the borderwidth value for a tag. 1300 * 1301 * Results: 1302 * A standard Tcl result. 1303 * 1304 * Side effects: 1305 * It may adjust the tag struct values of relief[0..4] and borders. 1306 * 1307 *---------------------------------------------------------------------- 1308 */ 1309 1310static int 1311TableOptionReliefSet(clientData, interp, tkwin, value, widgRec, offset) 1312 ClientData clientData; /* Type of struct being set. */ 1313 Tcl_Interp *interp; /* Used for reporting errors. */ 1314 Tk_Window tkwin; /* Window containing table widget. */ 1315 CONST84 char *value; /* Value of option. */ 1316 char *widgRec; /* Pointer to record for item. */ 1317 int offset; /* Offset into item. */ 1318{ 1319 TableTag *tagPtr = (TableTag *) widgRec; 1320 1321 if (*value == '\0') { 1322 tagPtr->relief = -1; 1323 } else { 1324 return Tk_GetRelief(interp, value, &(tagPtr->relief)); 1325 } 1326 return TCL_OK; 1327} 1328 1329/* 1330 *---------------------------------------------------------------------- 1331 * 1332 * TableOptionReliefGet -- 1333 * 1334 * Results: 1335 * Value of the tag's -relief option. 1336 * 1337 * Side effects: 1338 * None. 1339 * 1340 *---------------------------------------------------------------------- 1341 */ 1342 1343static char * 1344TableOptionReliefGet(clientData, tkwin, widgRec, offset, freeProcPtr) 1345 ClientData clientData; /* Type of struct being set. */ 1346 Tk_Window tkwin; /* Window containing canvas widget. */ 1347 char *widgRec; /* Pointer to record for item. */ 1348 int offset; /* Offset into item. */ 1349 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with 1350 * information about how to reclaim 1351 * storage for return string. */ 1352{ 1353 return (char *) Tk_NameOfRelief(((TableTag *) widgRec)->relief); 1354} 1355