summaryrefslogtreecommitdiffstats
path: root/tktable/generic/tkTableTag.c
diff options
context:
space:
mode:
Diffstat (limited to 'tktable/generic/tkTableTag.c')
-rw-r--r--tktable/generic/tkTableTag.c1354
1 files changed, 1354 insertions, 0 deletions
diff --git a/tktable/generic/tkTableTag.c b/tktable/generic/tkTableTag.c
new file mode 100644
index 0000000..f3d7ee8
--- /dev/null
+++ b/tktable/generic/tkTableTag.c
@@ -0,0 +1,1354 @@
+/*
+ * tkTableTag.c --
+ *
+ * This module implements tags for table widgets.
+ *
+ * Copyright (c) 1998-2002 Jeffrey Hobbs
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tkTableTag.c,v 1.3 2016/01/27 19:43:23 joye Exp $
+ */
+
+#include "tkTable.h"
+
+static TableTag *TableTagGetEntry _ANSI_ARGS_((Table *tablePtr, char *name,
+ int objc, CONST char **argv));
+static unsigned int TableTagGetPriority _ANSI_ARGS_((Table *tablePtr,
+ TableTag *tagPtr));
+static void TableImageProc _ANSI_ARGS_((ClientData clientData, int x,
+ int y, int width, int height, int imageWidth, int imageHeight));
+static int TableOptionReliefSet _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ CONST84 char *value, char *widgRec, int offset));
+static char * TableOptionReliefGet _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+
+static CONST84 char *tagCmdNames[] = {
+ "celltag", "cget", "coltag", "configure", "delete", "exists",
+ "includes", "lower", "names", "raise", "rowtag", (char *) NULL
+};
+
+enum tagCmd {
+ TAG_CELLTAG, TAG_CGET, TAG_COLTAG, TAG_CONFIGURE, TAG_DELETE, TAG_EXISTS,
+ TAG_INCLUDES, TAG_LOWER, TAG_NAMES, TAG_RAISE, TAG_ROWTAG
+};
+
+static Cmd_Struct tagState_vals[]= {
+ {"unknown", STATE_UNKNOWN},
+ {"normal", STATE_NORMAL},
+ {"disabled", STATE_DISABLED},
+ {"", 0 }
+};
+
+static Tk_CustomOption tagStateOpt =
+{ Cmd_OptionSet, Cmd_OptionGet, (ClientData) (&tagState_vals) };
+static Tk_CustomOption tagBdOpt =
+{ TableOptionBdSet, TableOptionBdGet, (ClientData) BD_TABLE_TAG };
+static Tk_CustomOption tagReliefOpt =
+{ TableOptionReliefSet, TableOptionReliefGet, (ClientData) NULL };
+
+/*
+ * The default specification for configuring tags
+ * Done like this to make the command line parsing easy
+ */
+
+static Tk_ConfigSpec tagConfig[] = {
+ {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", "center",
+ Tk_Offset(TableTag, anchor), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
+ {TK_CONFIG_BORDER, "-background", "background", "Background", NULL,
+ Tk_Offset(TableTag, bg), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
+ {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0, 0},
+ {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
+ {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth", "",
+ 0 /* no offset */,
+ TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK, &tagBdOpt },
+ {TK_CONFIG_STRING, "-ellipsis", "ellipsis", "Ellipsis", "",
+ Tk_Offset(TableTag, ellipsis), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
+ {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground", NULL,
+ Tk_Offset(TableTag, fg), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
+ {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0},
+ {TK_CONFIG_FONT, "-font", "font", "Font", NULL,
+ Tk_Offset(TableTag, tkfont), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
+ {TK_CONFIG_STRING, "-image", "image", "Image", NULL,
+ Tk_Offset(TableTag, imageStr),
+ TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
+ {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify", "left",
+ Tk_Offset(TableTag, justify), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
+ {TK_CONFIG_INT, "-multiline", "multiline", "Multiline", "-1",
+ Tk_Offset(TableTag, multiline), TK_CONFIG_DONT_SET_DEFAULT },
+ {TK_CONFIG_CUSTOM, "-relief", "relief", "Relief", "flat",
+ Tk_Offset(TableTag, relief), TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK,
+ &tagReliefOpt },
+ {TK_CONFIG_INT, "-showtext", "showText", "ShowText", "-1",
+ Tk_Offset(TableTag, showtext), TK_CONFIG_DONT_SET_DEFAULT },
+ {TK_CONFIG_CUSTOM, "-state", "state", "State", "unknown",
+ Tk_Offset(TableTag, state), TK_CONFIG_DONT_SET_DEFAULT, &tagStateOpt },
+ {TK_CONFIG_INT, "-wrap", "wrap", "Wrap", "-1",
+ Tk_Offset(TableTag, wrap), TK_CONFIG_DONT_SET_DEFAULT },
+ {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, 0, 0}
+};
+
+/*
+ * The join tag structure is used to create a combined tag, so it
+ * keeps priority info.
+ */
+typedef struct {
+ TableTag tag; /* must be first */
+ unsigned int magic;
+ unsigned int pbg, pfg, pborders, prelief, ptkfont, panchor, pimage;
+ unsigned int pstate, pjustify, pmultiline, pwrap, pshowtext, pellipsis;
+} TableJoinTag;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableImageProc --
+ * Called when an image associated with a tag is changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Invalidates the whole table.
+ * This should only invalidate affected cells, but that info
+ * is not managed...
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+TableImageProc(ClientData clientData, int x, int y, int width, int height,
+ int imageWidth, int imageHeight)
+{
+ TableInvalidateAll((Table *)clientData, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableNewTag --
+ * ckallocs space for a new tag structure and inits the structure.
+ *
+ * Results:
+ * Returns a pointer to the new structure. Must be freed later.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+TableTag *
+TableNewTag(Table *tablePtr)
+{
+ TableTag *tagPtr;
+
+ /*
+ * If tablePtr is NULL, make a regular tag, otherwise make a join tag.
+ */
+ if (tablePtr == NULL) {
+ tagPtr = (TableTag *) ckalloc(sizeof(TableTag));
+ memset((VOID *) tagPtr, 0, sizeof(TableTag));
+
+ /*
+ * Set the values that aren't 0/NULL by default
+ */
+ tagPtr->anchor = (Tk_Anchor)-1;
+ tagPtr->justify = (Tk_Justify)-1;
+ tagPtr->multiline = -1;
+ tagPtr->relief = -1;
+ tagPtr->showtext = -1;
+ tagPtr->state = STATE_UNKNOWN;
+ tagPtr->wrap = -1;
+ } else {
+ TableJoinTag *jtagPtr = (TableJoinTag *) ckalloc(sizeof(TableJoinTag));
+ memset((VOID *) jtagPtr, 0, sizeof(TableJoinTag));
+ tagPtr = (TableTag *) jtagPtr;
+
+ tagPtr->anchor = (Tk_Anchor)-1;
+ tagPtr->justify = (Tk_Justify)-1;
+ tagPtr->multiline = -1;
+ tagPtr->relief = -1;
+ tagPtr->showtext = -1;
+ tagPtr->state = STATE_UNKNOWN;
+ tagPtr->wrap = -1;
+ jtagPtr->magic = 0x99ABCDEF;
+ jtagPtr->pbg = -1;
+ jtagPtr->pfg = -1;
+ jtagPtr->pborders = -1;
+ jtagPtr->prelief = -1;
+ jtagPtr->ptkfont = -1;
+ jtagPtr->panchor = -1;
+ jtagPtr->pimage = -1;
+ jtagPtr->pstate = -1;
+ jtagPtr->pjustify = -1;
+ jtagPtr->pmultiline = -1;
+ jtagPtr->pwrap = -1;
+ jtagPtr->pshowtext = -1;
+ jtagPtr->pellipsis = -1;
+ }
+
+ return (TableTag *) tagPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableResetTag --
+ * This routine resets a given tag to the table defaults.
+ *
+ * Results:
+ * Tag will have values changed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TableResetTag(Table *tablePtr, TableTag *tagPtr)
+{
+ TableJoinTag *jtagPtr = (TableJoinTag *) tagPtr;
+
+ if (jtagPtr->magic != 0x99ABCDEF) {
+ panic("bad mojo in TableResetTag");
+ }
+
+ memset((VOID *) jtagPtr, 0, sizeof(TableJoinTag));
+
+ tagPtr->anchor = (Tk_Anchor)-1;
+ tagPtr->justify = (Tk_Justify)-1;
+ tagPtr->multiline = -1;
+ tagPtr->relief = -1;
+ tagPtr->showtext = -1;
+ tagPtr->state = STATE_UNKNOWN;
+ tagPtr->wrap = -1;
+ jtagPtr->magic = 0x99ABCDEF;
+ jtagPtr->pbg = -1;
+ jtagPtr->pfg = -1;
+ jtagPtr->pborders = -1;
+ jtagPtr->prelief = -1;
+ jtagPtr->ptkfont = -1;
+ jtagPtr->panchor = -1;
+ jtagPtr->pimage = -1;
+ jtagPtr->pstate = -1;
+ jtagPtr->pjustify = -1;
+ jtagPtr->pmultiline = -1;
+ jtagPtr->pwrap = -1;
+ jtagPtr->pshowtext = -1;
+ jtagPtr->pellipsis = -1;
+
+ /*
+ * Merge in the default tag.
+ */
+ memcpy((VOID *) jtagPtr, (VOID *) &(tablePtr->defaultTag),
+ sizeof(TableTag));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableMergeTag --
+ * This routine merges two tags by adding any fields from the addTag
+ * that are set to the baseTag.
+ *
+ * Results:
+ * baseTag will inherit all set characteristics of addTag
+ * (addTag thus has the priority).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TableMergeTag(Table *tablePtr, TableTag *baseTag, TableTag *addTag)
+{
+ TableJoinTag *jtagPtr = (TableJoinTag *) baseTag;
+ unsigned int prio;
+
+ if (jtagPtr->magic != 0x99ABCDEF) {
+ panic("bad mojo in TableMergeTag");
+ }
+
+#ifndef NO_TAG_PRIORITIES
+ /*
+ * Find priority for the tag to merge
+ */
+ prio = TableTagGetPriority(tablePtr, addTag);
+
+ if ((addTag->anchor != -1) && (prio < jtagPtr->panchor)) {
+ baseTag->anchor = addTag->anchor;
+ jtagPtr->panchor = prio;
+ }
+ if ((addTag->bg != NULL) && (prio < jtagPtr->pbg)) {
+ baseTag->bg = addTag->bg;
+ jtagPtr->pbg = prio;
+ }
+ if ((addTag->fg != NULL) && (prio < jtagPtr->pfg)) {
+ baseTag->fg = addTag->fg;
+ jtagPtr->pfg = prio;
+ }
+ if ((addTag->ellipsis != NULL) && (prio < jtagPtr->pellipsis)) {
+ baseTag->ellipsis = addTag->ellipsis;
+ jtagPtr->pellipsis = prio;
+ }
+ if ((addTag->tkfont != NULL) && (prio < jtagPtr->ptkfont)) {
+ baseTag->tkfont = addTag->tkfont;
+ jtagPtr->ptkfont = prio;
+ }
+ if ((addTag->imageStr != NULL) && (prio < jtagPtr->pimage)) {
+ baseTag->imageStr = addTag->imageStr;
+ baseTag->image = addTag->image;
+ jtagPtr->pimage = prio;
+ }
+ if ((addTag->multiline >= 0) && (prio < jtagPtr->pmultiline)) {
+ baseTag->multiline = addTag->multiline;
+ jtagPtr->pmultiline = prio;
+ }
+ if ((addTag->relief != -1) && (prio < jtagPtr->prelief)) {
+ baseTag->relief = addTag->relief;
+ jtagPtr->prelief = prio;
+ }
+ if ((addTag->showtext >= 0) && (prio < jtagPtr->pshowtext)) {
+ baseTag->showtext = addTag->showtext;
+ jtagPtr->pshowtext = prio;
+ }
+ if ((addTag->state != STATE_UNKNOWN) && (prio < jtagPtr->pstate)) {
+ baseTag->state = addTag->state;
+ jtagPtr->pstate = prio;
+ }
+ if ((addTag->justify != -1) && (prio < jtagPtr->pjustify)) {
+ baseTag->justify = addTag->justify;
+ jtagPtr->pjustify = prio;
+ }
+ if ((addTag->wrap >= 0) && (prio < jtagPtr->pwrap)) {
+ baseTag->wrap = addTag->wrap;
+ jtagPtr->pwrap = prio;
+ }
+ if ((addTag->borders) && (prio < jtagPtr->pborders)) {
+ baseTag->borderStr = addTag->borderStr;
+ baseTag->borders = addTag->borders;
+ baseTag->bd[0] = addTag->bd[0];
+ baseTag->bd[1] = addTag->bd[1];
+ baseTag->bd[2] = addTag->bd[2];
+ baseTag->bd[3] = addTag->bd[3];
+ jtagPtr->pborders = prio;
+ }
+#else
+ if (addTag->anchor != -1) baseTag->anchor = addTag->anchor;
+ if (addTag->bg != NULL) baseTag->bg = addTag->bg;
+ if (addTag->fg != NULL) baseTag->fg = addTag->fg;
+ if (addTag->ellipsis != NULL) baseTag->ellipsis = addTag->ellipsis;
+ if (addTag->tkfont != NULL) baseTag->tkfont = addTag->tkfont;
+ if (addTag->imageStr != NULL) {
+ baseTag->imageStr = addTag->imageStr;
+ baseTag->image = addTag->image;
+ }
+ if (addTag->multiline >= 0) baseTag->multiline = addTag->multiline;
+ if (addTag->relief != -1) baseTag->relief = addTag->relief;
+ if (addTag->showtext >= 0) baseTag->showtext = addTag->showtext;
+ if (addTag->state != STATE_UNKNOWN) baseTag->state = addTag->state;
+ if (addTag->justify != -1) baseTag->justify = addTag->justify;
+ if (addTag->wrap >= 0) baseTag->wrap = addTag->wrap;
+ if (addTag->borders) {
+ baseTag->borderStr = addTag->borderStr;
+ baseTag->borders = addTag->borders;
+ baseTag->bd[0] = addTag->bd[0];
+ baseTag->bd[1] = addTag->bd[1];
+ baseTag->bd[2] = addTag->bd[2];
+ baseTag->bd[3] = addTag->bd[3];
+ }
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableInvertTag --
+ * This routine swaps background and foreground for the selected tag.
+ *
+ * Results:
+ * Inverts fg and bg of tag.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TableInvertTag(TableTag *baseTag)
+{
+ Tk_3DBorder tmpBg;
+
+ tmpBg = baseTag->fg;
+ baseTag->fg = baseTag->bg;
+ baseTag->bg = tmpBg;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableGetTagBorders --
+ * This routine gets the border values based on a tag.
+ *
+ * Results:
+ * It returns the values in the int*'s (if not NULL), and the
+ * total number of defined borders as a result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+TableGetTagBorders(TableTag *tagPtr,
+ int *left, int *right, int *top, int *bottom)
+{
+ switch (tagPtr->borders) {
+ case 0:
+ if (left) { *left = 0; }
+ if (right) { *right = 0; }
+ if (top) { *top = 0; }
+ if (bottom) { *bottom = 0; }
+ break;
+ case 1:
+ if (left) { *left = tagPtr->bd[0]; }
+ if (right) { *right = tagPtr->bd[0]; }
+ if (top) { *top = tagPtr->bd[0]; }
+ if (bottom) { *bottom = tagPtr->bd[0]; }
+ break;
+ case 2:
+ if (left) { *left = tagPtr->bd[0]; }
+ if (right) { *right = tagPtr->bd[1]; }
+ if (top) { *top = 0; }
+ if (bottom) { *bottom = 0; }
+ break;
+ case 4:
+ if (left) { *left = tagPtr->bd[0]; }
+ if (right) { *right = tagPtr->bd[1]; }
+ if (top) { *top = tagPtr->bd[2]; }
+ if (bottom) { *bottom = tagPtr->bd[3]; }
+ break;
+ default:
+ panic("invalid border value '%d'\n", tagPtr->borders);
+ break;
+ }
+ return tagPtr->borders;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableTagGetEntry --
+ * Takes a name and optional args and creates a tag entry in the
+ * table's tag table.
+ *
+ * Results:
+ * A new tag entry will be created and returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static TableTag *
+TableTagGetEntry(Table *tablePtr, char *name, int objc, CONST char **argv)
+{
+ Tcl_HashEntry *entryPtr;
+ TableTag *tagPtr = NULL;
+ int new;
+
+ entryPtr = Tcl_CreateHashEntry(tablePtr->tagTable, name, &new);
+ if (new) {
+ tagPtr = TableNewTag(NULL);
+ Tcl_SetHashValue(entryPtr, (ClientData) tagPtr);
+ if (tablePtr->tagPrioSize >= tablePtr->tagPrioMax) {
+ int i;
+ /*
+ * Increase the priority list size in blocks of 10
+ */
+ tablePtr->tagPrioMax += 10;
+ tablePtr->tagPrioNames = (char **) ckrealloc(
+ (char *) tablePtr->tagPrioNames,
+ sizeof(TableTag *) * tablePtr->tagPrioMax);
+ tablePtr->tagPrios = (TableTag **) ckrealloc(
+ (char *) tablePtr->tagPrios,
+ sizeof(TableTag *) * tablePtr->tagPrioMax);
+ for (i = tablePtr->tagPrioSize; i < tablePtr->tagPrioMax; i++) {
+ tablePtr->tagPrioNames[i] = (char *) NULL;
+ tablePtr->tagPrios[i] = (TableTag *) NULL;
+ }
+ }
+ tablePtr->tagPrioNames[tablePtr->tagPrioSize] =
+ (char *) Tcl_GetHashKey(tablePtr->tagTable, entryPtr);
+ tablePtr->tagPrios[tablePtr->tagPrioSize] = tagPtr;
+ tablePtr->tagPrioSize++;
+ } else {
+ tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr);
+ }
+ if (objc) {
+ Tk_ConfigureWidget(tablePtr->interp, tablePtr->tkwin, tagConfig,
+ objc, (CONST84 char **) argv, (char *)tagPtr,
+ TK_CONFIG_ARGV_ONLY);
+ }
+ return tagPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableTagGetPriority --
+ * Get the priority value for a tag.
+ *
+ * Results:
+ * returns the priority.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static unsigned int
+TableTagGetPriority(Table *tablePtr, TableTag *tagPtr)
+{
+ unsigned int prio = 0;
+ while (tagPtr != tablePtr->tagPrios[prio]) { prio++; }
+ return prio;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableInitTags --
+ * Creates the static table tags.
+ *
+ * Results:
+ * active, sel, title and flash are created as tags.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TableInitTags(Table *tablePtr)
+{
+ static CONST char *activeArgs[] = {"-bg", ACTIVE_BG, "-relief", "flat" };
+ static CONST char *selArgs[] = {"-bg", SELECT_BG, "-fg", SELECT_FG,
+ "-relief", "sunken" };
+ static CONST char *titleArgs[] = {"-bg", DISABLED, "-fg", "white",
+ "-relief", "flat",
+ "-state", "disabled" };
+ static CONST char *flashArgs[] = {"-bg", "red" };
+ /*
+ * The order of creation is important to priority.
+ */
+ TableTagGetEntry(tablePtr, "flash", ARSIZE(flashArgs), flashArgs);
+ TableTagGetEntry(tablePtr, "active", ARSIZE(activeArgs), activeArgs);
+ TableTagGetEntry(tablePtr, "sel", ARSIZE(selArgs), selArgs);
+ TableTagGetEntry(tablePtr, "title", ARSIZE(titleArgs), titleArgs);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindRowColTag --
+ * Finds a row/col tag based on the row/col styles and tagCommand.
+ *
+ * Results:
+ * Returns tag associated with row/col cell, if any.
+ *
+ * Side effects:
+ * Possible side effects from eval of tagCommand.
+ * IMPORTANT: This plays with the interp result object,
+ * so use of resultPtr in prior command may be invalid after
+ * calling this function.
+ *
+ *----------------------------------------------------------------------
+ */
+TableTag *
+FindRowColTag(Table *tablePtr, int cell, int mode)
+{
+ Tcl_HashEntry *entryPtr;
+ TableTag *tagPtr = NULL;
+
+ entryPtr = Tcl_FindHashEntry((mode == ROW) ? tablePtr->rowStyles
+ : tablePtr->colStyles, (char *) cell);
+ if (entryPtr == NULL) {
+ char *cmd = (mode == ROW) ? tablePtr->rowTagCmd : tablePtr->colTagCmd;
+ if (cmd) {
+ register Tcl_Interp *interp = tablePtr->interp;
+ char buf[INDEX_BUFSIZE];
+ /*
+ * Since no specific row/col tag exists, eval the given command
+ * with row/col appended
+ */
+ sprintf(buf, " %d", cell);
+ Tcl_Preserve((ClientData) interp);
+ if (Tcl_VarEval(interp, cmd, buf, (char *)NULL) == TCL_OK) {
+ CONST char *name = Tcl_GetStringResult(interp);
+ if (name && *name) {
+ /*
+ * If a result was returned, check to see if it is
+ * a valid tag.
+ */
+ entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, name);
+ }
+ }
+ Tcl_Release((ClientData) interp);
+ Tcl_ResetResult(interp);
+ }
+ }
+ if (entryPtr != NULL) {
+ /*
+ * This can be either the one in row|colStyles,
+ * or that returned by eval'ing the row|colTagCmd
+ */
+ tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr);
+ }
+ return tagPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableCleanupTag --
+ * Releases the resources used by a tag before it is freed up.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The tag is no longer valid.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TableCleanupTag(Table *tablePtr, TableTag *tagPtr)
+{
+ /*
+ * Free resources that the optionSpec doesn't specifically know about
+ */
+ if (tagPtr->image) {
+ Tk_FreeImage(tagPtr->image);
+ }
+
+ Tk_FreeOptions(tagConfig, (char *) tagPtr, tablePtr->display, 0);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Table_TagCmd --
+ * This procedure is invoked to process the tag method
+ * that corresponds to a widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Table_TagCmd(ClientData clientData, register Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ register Table *tablePtr = (Table *)clientData;
+ int result = TCL_OK, cmdIndex, i, newEntry, value, len;
+ int row, col, tagPrio, refresh = 0;
+ TableTag *tagPtr, *tag2Ptr;
+ Tcl_HashEntry *entryPtr, *scanPtr;
+ Tcl_HashTable *hashTblPtr;
+ Tcl_HashSearch search;
+ Tk_Image image;
+ Tcl_Obj *objPtr, *resultPtr;
+ char buf[INDEX_BUFSIZE], *keybuf, *tagname;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
+ return TCL_ERROR;
+ }
+
+ result = Tcl_GetIndexFromObj(interp, objv[2], tagCmdNames,
+ "tag option", 0, &cmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+ /*
+ * Before using this object, make sure there aren't any calls that
+ * could have changed the interp result, thus freeing the object.
+ */
+ resultPtr = Tcl_GetObjResult(interp);
+
+ switch ((enum tagCmd) cmdIndex) {
+ case TAG_CELLTAG: /* add named tag to a (group of) cell(s) */
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tag ?arg arg ...?");
+ return TCL_ERROR;
+ }
+ tagname = Tcl_GetStringFromObj(objv[3], &len);
+ if (len == 0) {
+ /*
+ * An empty string was specified, so just delete the tag.
+ */
+ tagPtr = NULL;
+ } else {
+ /*
+ * Get the pointer to the tag structure. If it doesn't
+ * exist, it will be created.
+ */
+ tagPtr = TableTagGetEntry(tablePtr, tagname, 0, NULL);
+ }
+
+ if (objc == 4) {
+ /*
+ * The user just wants the cells with this tag returned.
+ * Handle specially tags named: active, flash, sel, title
+ */
+
+ if ((tablePtr->flags & HAS_ACTIVE) &&
+ STREQ(tagname, "active")) {
+ TableMakeArrayIndex(
+ tablePtr->activeRow+tablePtr->rowOffset,
+ tablePtr->activeCol+tablePtr->colOffset, buf);
+ Tcl_SetStringObj(resultPtr, buf, -1);
+ } else if ((tablePtr->flashMode && STREQ(tagname, "flash"))
+ || STREQ(tagname, "sel")) {
+ hashTblPtr = (*tagname == 's') ?
+ tablePtr->selCells : tablePtr->flashCells;
+ for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search);
+ scanPtr != NULL;
+ scanPtr = Tcl_NextHashEntry(&search)) {
+ keybuf = (char *) Tcl_GetHashKey(hashTblPtr, scanPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(keybuf, -1));
+ }
+ } else if (STREQ(tagname, "title") &&
+ (tablePtr->titleRows || tablePtr->titleCols)) {
+ for (row = tablePtr->rowOffset;
+ row < tablePtr->rowOffset+tablePtr->rows; row++) {
+ for (col = tablePtr->colOffset;
+ col < tablePtr->colOffset+tablePtr->titleCols;
+ col++) {
+ TableMakeArrayIndex(row, col, buf);
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(buf, -1));
+ }
+ }
+ for (row = tablePtr->rowOffset;
+ row < tablePtr->rowOffset+tablePtr->titleRows;
+ row++) {
+ for (col = tablePtr->colOffset+tablePtr->titleCols;
+ col < tablePtr->colOffset+tablePtr->cols; col++) {
+ TableMakeArrayIndex(row, col, buf);
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(buf, -1));
+ }
+ }
+ } else {
+ /*
+ * Check this tag pointer amongst all tagged cells
+ */
+ for (scanPtr = Tcl_FirstHashEntry(tablePtr->cellStyles,
+ &search);
+ scanPtr != NULL;
+ scanPtr = Tcl_NextHashEntry(&search)) {
+ if ((TableTag *) Tcl_GetHashValue(scanPtr) == tagPtr) {
+ keybuf = (char *) Tcl_GetHashKey(
+ tablePtr->cellStyles, scanPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewStringObj(keybuf, -1));
+ }
+ }
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * Loop through the arguments and fill in the hash table
+ */
+ for (i = 4; i < objc; i++) {
+ /*
+ * Try and parse the index
+ */
+ if (TableGetIndexObj(tablePtr, objv[i], &row, &col)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Get the hash key ready
+ */
+ TableMakeArrayIndex(row, col, buf);
+
+ if (tagPtr == NULL) {
+ /*
+ * This is a deletion
+ */
+ entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ refresh = 1;
+ }
+ } else {
+ /*
+ * Add a key to the hash table and set it to point to the
+ * Tag structure if it wasn't the same as an existing one
+ */
+ entryPtr = Tcl_CreateHashEntry(tablePtr->cellStyles,
+ buf, &newEntry);
+ if (newEntry || (tagPtr !=
+ (TableTag *) Tcl_GetHashValue(entryPtr))) {
+ Tcl_SetHashValue(entryPtr, (ClientData) tagPtr);
+ refresh = 1;
+ }
+ }
+ /*
+ * Now invalidate this cell for redraw
+ */
+ if (refresh) {
+ TableRefresh(tablePtr, row-tablePtr->rowOffset,
+ col-tablePtr->colOffset, CELL);
+ }
+ }
+ return TCL_OK;
+
+ case TAG_COLTAG:
+ case TAG_ROWTAG: { /* tag a row or a column */
+ int forRows = (cmdIndex == TAG_ROWTAG);
+
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tag ?arg arg ..?");
+ return TCL_ERROR;
+ }
+ tagname = Tcl_GetStringFromObj(objv[3], &len);
+ if (len == 0) {
+ /*
+ * Empty string, so we want to delete this element
+ */
+ tagPtr = NULL;
+ } else {
+ /*
+ * Get the pointer to the tag structure. If it doesn't
+ * exist, it will be created.
+ */
+ tagPtr = TableTagGetEntry(tablePtr, tagname, 0, NULL);
+ }
+
+ /*
+ * Choose the correct hash table based on args
+ */
+ hashTblPtr = forRows ? tablePtr->rowStyles : tablePtr->colStyles;
+
+ if (objc == 4) {
+ /* the user just wants the tagged cells to be returned */
+ /* Special handling for tags: active, flash, sel, title */
+
+ if ((tablePtr->flags & HAS_ACTIVE) &&
+ strcmp(tagname, "active") == 0) {
+ Tcl_SetIntObj(resultPtr,
+ (forRows ?
+ tablePtr->activeRow+tablePtr->rowOffset :
+ tablePtr->activeCol+tablePtr->colOffset));
+ } else if ((tablePtr->flashMode && STREQ(tagname, "flash"))
+ || STREQ(tagname, "sel")) {
+ Tcl_HashTable *cacheTblPtr;
+
+ cacheTblPtr = (Tcl_HashTable *)
+ ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(cacheTblPtr, TCL_ONE_WORD_KEYS);
+
+ hashTblPtr = (*tagname == 's') ?
+ tablePtr->selCells : tablePtr->flashCells;
+ for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search);
+ scanPtr != NULL;
+ scanPtr = Tcl_NextHashEntry(&search)) {
+ TableParseArrayIndex(&row, &col,
+ Tcl_GetHashKey(hashTblPtr, scanPtr));
+ value = forRows ? row : col;
+ entryPtr = Tcl_CreateHashEntry(cacheTblPtr,
+ (char *)value, &newEntry);
+ if (newEntry) {
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewIntObj(value));
+ }
+ }
+
+ Tcl_DeleteHashTable(cacheTblPtr);
+ ckfree((char *) (cacheTblPtr));
+ } else if (STREQ(tagname, "title") &&
+ (forRows?tablePtr->titleRows:tablePtr->titleCols)) {
+ if (forRows) {
+ for (row = tablePtr->rowOffset;
+ row < tablePtr->rowOffset+tablePtr->titleRows;
+ row++) {
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewIntObj(row));
+ }
+ } else {
+ for (col = tablePtr->colOffset;
+ col < tablePtr->colOffset+tablePtr->titleCols;
+ col++) {
+ Tcl_ListObjAppendElement(NULL, resultPtr,
+ Tcl_NewIntObj(col));
+ }
+ }
+ } else {
+ for (scanPtr = Tcl_FirstHashEntry(hashTblPtr, &search);
+ scanPtr != NULL;
+ scanPtr = Tcl_NextHashEntry(&search)) {
+ /* is this the tag pointer on this row */
+ if ((TableTag *) Tcl_GetHashValue(scanPtr) == tagPtr) {
+ objPtr = Tcl_NewIntObj(
+ (int) Tcl_GetHashKey(hashTblPtr, scanPtr));
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * Loop through the arguments and fill in the hash table
+ */
+ for (i = 4; i < objc; i++) {
+ /*
+ * Try and parse the index
+ */
+ if (Tcl_GetIntFromObj(interp, objv[i], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (tagPtr == NULL) {
+ /*
+ * This is a deletion
+ */
+ entryPtr = Tcl_FindHashEntry(hashTblPtr, (char *)value);
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ refresh = 1;
+ }
+ } else {
+ /*
+ * Add a key to the hash table and set it to point to the
+ * Tag structure if it wasn't the same as an existing one
+ */
+ entryPtr = Tcl_CreateHashEntry(hashTblPtr,
+ (char *) value, &newEntry);
+ if (newEntry || (tagPtr !=
+ (TableTag *) Tcl_GetHashValue(entryPtr))) {
+ Tcl_SetHashValue(entryPtr, (ClientData) tagPtr);
+ refresh = 1;
+ }
+ }
+ /* and invalidate the row or column affected */
+ if (refresh) {
+ if (cmdIndex == TAG_ROWTAG) {
+ TableRefresh(tablePtr, value-tablePtr->rowOffset, 0,
+ ROW);
+ } else {
+ TableRefresh(tablePtr, 0, value-tablePtr->colOffset,
+ COL);
+ }
+ }
+ }
+ return TCL_OK; /* COLTAG && ROWTAG */
+ }
+
+ case TAG_CGET:
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName option");
+ return TCL_ERROR;
+ }
+ tagname = Tcl_GetString(objv[3]);
+ entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname);
+ if (entryPtr == NULL) {
+ goto invalidtag;
+ } else {
+ tagPtr = (TableTag *) Tcl_GetHashValue (entryPtr);
+ result = Tk_ConfigureValue(interp, tablePtr->tkwin, tagConfig,
+ (char *) tagPtr, Tcl_GetString(objv[4]), 0);
+ }
+ return result; /* CGET */
+
+ case TAG_CONFIGURE:
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?arg arg ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Get the pointer to the tag structure. If it doesn't
+ * exist, it will be created.
+ */
+ tagPtr = TableTagGetEntry(tablePtr, Tcl_GetString(objv[3]),
+ 0, NULL);
+
+ /*
+ * If there were less than 6 args, we return the configuration
+ * (for all or just one option), even for new tags
+ */
+ if (objc < 6) {
+ result = Tk_ConfigureInfo(interp, tablePtr->tkwin, tagConfig,
+ (char *) tagPtr, (objc == 5) ?
+ Tcl_GetString(objv[4]) : NULL, 0);
+ } else {
+ CONST84 char **argv;
+
+ /* Stringify */
+ argv = (CONST84 char **) ckalloc((objc + 1) * sizeof(char *));
+ for (i = 0; i < objc; i++)
+ argv[i] = Tcl_GetString(objv[i]);
+ argv[objc] = NULL;
+
+ result = Tk_ConfigureWidget(interp, tablePtr->tkwin,
+ tagConfig, objc-4, argv+4, (char *) tagPtr,
+ TK_CONFIG_ARGV_ONLY);
+ ckfree((char *) argv);
+ if (result == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Handle change of image name
+ */
+ if (tagPtr->imageStr) {
+ image = Tk_GetImage(interp, tablePtr->tkwin,
+ tagPtr->imageStr,
+ TableImageProc, (ClientData)tablePtr);
+ if (image == NULL) {
+ result = TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (tagPtr->image) {
+ Tk_FreeImage(tagPtr->image);
+ }
+ tagPtr->image = image;
+
+ /*
+ * We reconfigured, so invalidate the table to redraw
+ */
+ TableInvalidateAll(tablePtr, 0);
+ }
+ return result;
+
+ case TAG_DELETE:
+ /* delete a tag */
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?");
+ return TCL_ERROR;
+ }
+ /* run through the remaining arguments */
+ for (i = 3; i < objc; i++) {
+ tagname = Tcl_GetString(objv[i]);
+ /* cannot delete the title tag */
+ if (STREQ(tagname, "title") ||
+ STREQ(tagname, "sel") ||
+ STREQ(tagname, "flash") ||
+ STREQ(tagname, "active")) {
+ Tcl_AppendStringsToObj(resultPtr, "cannot delete ",
+ tagname, " tag", (char *) NULL);
+ return TCL_ERROR;
+ }
+ entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname);
+ if (entryPtr != NULL) {
+ /* get the tag pointer */
+ tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr);
+
+ /* delete all references to this tag in rows */
+ scanPtr = Tcl_FirstHashEntry(tablePtr->rowStyles, &search);
+ for (; scanPtr != NULL;
+ scanPtr = Tcl_NextHashEntry(&search)) {
+ if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) {
+ Tcl_DeleteHashEntry(scanPtr);
+ refresh = 1;
+ }
+ }
+
+ /* delete all references to this tag in cols */
+ scanPtr = Tcl_FirstHashEntry(tablePtr->colStyles, &search);
+ for (; scanPtr != NULL;
+ scanPtr = Tcl_NextHashEntry(&search)) {
+ if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) {
+ Tcl_DeleteHashEntry(scanPtr);
+ refresh = 1;
+ }
+ }
+
+ /* delete all references to this tag in cells */
+ scanPtr = Tcl_FirstHashEntry(tablePtr->cellStyles,
+ &search);
+ for (; scanPtr != NULL;
+ scanPtr = Tcl_NextHashEntry(&search)) {
+ if ((TableTag *)Tcl_GetHashValue(scanPtr) == tagPtr) {
+ Tcl_DeleteHashEntry(scanPtr);
+ refresh = 1;
+ }
+ }
+
+ /*
+ * Remove the tag from the prio list and collapse
+ * the rest of the tags. We could check for shrinking
+ * the prio list as well.
+ */
+ for (i = 0; i < tablePtr->tagPrioSize; i++) {
+ if (tablePtr->tagPrios[i] == tagPtr) break;
+ }
+ for ( ; i < tablePtr->tagPrioSize; i++) {
+ tablePtr->tagPrioNames[i] =
+ tablePtr->tagPrioNames[i+1];
+ tablePtr->tagPrios[i] = tablePtr->tagPrios[i+1];
+ }
+ tablePtr->tagPrioSize--;
+
+ /* Release the tag structure */
+ TableCleanupTag(tablePtr, tagPtr);
+ ckfree((char *) tagPtr);
+
+ /* And free the hash table entry */
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ }
+ /* since we deleted a tag, redraw the screen */
+ if (refresh) {
+ TableInvalidateAll(tablePtr, 0);
+ }
+ return result;
+
+ case TAG_EXISTS:
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tagName");
+ return TCL_ERROR;
+ }
+ Tcl_SetBooleanObj(resultPtr,
+ (Tcl_FindHashEntry(tablePtr->tagTable,
+ Tcl_GetString(objv[3])) != NULL));
+ return TCL_OK;
+
+ case TAG_INCLUDES:
+ /* does a tag contain a index ? */
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "tag index");
+ return TCL_ERROR;
+ }
+ tagname = Tcl_GetString(objv[3]);
+ /* check to see if the tag actually exists */
+ entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname);
+ if (entryPtr == NULL) {
+ /* Unknown tag, just return 0 */
+ Tcl_SetBooleanObj(resultPtr, 0);
+ return TCL_OK;
+ }
+ /* parse index */
+ if (TableGetIndexObj(tablePtr, objv[4], &row, &col) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* create hash key */
+ TableMakeArrayIndex(row, col, buf);
+
+ if (STREQ(tagname, "active")) {
+ result = (tablePtr->activeRow+tablePtr->rowOffset==row &&
+ tablePtr->activeCol+tablePtr->colOffset==col);
+ } else if (STREQ(tagname, "flash")) {
+ result = (tablePtr->flashMode &&
+ (Tcl_FindHashEntry(tablePtr->flashCells, buf)
+ != NULL));
+ } else if (STREQ(tagname, "sel")) {
+ result = (Tcl_FindHashEntry(tablePtr->selCells, buf) != NULL);
+ } else if (STREQ(tagname, "title")) {
+ result = (row < tablePtr->titleRows+tablePtr->rowOffset ||
+ col < tablePtr->titleCols+tablePtr->colOffset);
+ } else {
+ /* get the pointer to the tag structure */
+ tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr);
+ scanPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf);
+ /*
+ * Look to see if there is a cell, row, or col tag
+ * for this cell
+ */
+ result = ((scanPtr &&
+ (tagPtr == (TableTag *) Tcl_GetHashValue(scanPtr))) ||
+ (tagPtr == FindRowColTag(tablePtr, row, ROW)) ||
+ (tagPtr == FindRowColTag(tablePtr, col, COL)));
+ }
+ /*
+ * Because we may call FindRowColTag above, we can't use
+ * the resultPtr, but this is almost equivalent, and is SAFE
+ */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result));
+ return TCL_OK;
+
+ case TAG_NAMES:
+ /*
+ * Print out the tag names in priority order
+ */
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "?pattern?");
+ return TCL_ERROR;
+ }
+ tagname = (objc == 4) ? Tcl_GetString(objv[3]) : NULL;
+ for (i = 0; i < tablePtr->tagPrioSize; i++) {
+ keybuf = tablePtr->tagPrioNames[i];
+ if (objc == 3 || Tcl_StringMatch(keybuf, tagname)) {
+ objPtr = Tcl_NewStringObj(keybuf, -1);
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return TCL_OK;
+
+ case TAG_LOWER:
+ case TAG_RAISE:
+ /*
+ * Change priority of the named tag
+ */
+ if (objc != 4 && objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, (cmdIndex == TAG_LOWER) ?
+ "tagName ?belowThis?" : "tagName ?aboveThis?");
+ return TCL_ERROR;
+ }
+ tagname = Tcl_GetString(objv[3]);
+ /* check to see if the tag actually exists */
+ entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname);
+ if (entryPtr == NULL) {
+ goto invalidtag;
+ }
+ tagPtr = (TableTag *) Tcl_GetHashValue(entryPtr);
+ tagPrio = TableTagGetPriority(tablePtr, tagPtr);
+ keybuf = tablePtr->tagPrioNames[tagPrio];
+ /*
+ * In the RAISE case, the priority is one higher (-1) because
+ * we want the named tag to move above the other in priority.
+ */
+ if (objc == 5) {
+ tagname = Tcl_GetString(objv[4]);
+ entryPtr = Tcl_FindHashEntry(tablePtr->tagTable, tagname);
+ if (entryPtr == NULL) {
+ goto invalidtag;
+ }
+ tag2Ptr = (TableTag *) Tcl_GetHashValue(entryPtr);
+ if (cmdIndex == TAG_LOWER) {
+ value = TableTagGetPriority(tablePtr, tag2Ptr);
+ } else {
+ value = TableTagGetPriority(tablePtr, tag2Ptr) - 1;
+ }
+ } else {
+ if (cmdIndex == TAG_LOWER) {
+ /*
+ * Lower this tag's priority to the bottom.
+ */
+ value = tablePtr->tagPrioSize - 1;
+ } else {
+ /*
+ * Raise this tag's priority to the top.
+ */
+ value = -1;
+ }
+ }
+ if (value < tagPrio) {
+ /*
+ * Move tag up in priority.
+ */
+ for (i = tagPrio; i > value; i--) {
+ tablePtr->tagPrioNames[i] = tablePtr->tagPrioNames[i-1];
+ tablePtr->tagPrios[i] = tablePtr->tagPrios[i-1];
+ }
+ i++;
+ tablePtr->tagPrioNames[i] = keybuf;
+ tablePtr->tagPrios[i] = tagPtr;
+ refresh = 1;
+ } else if (value > tagPrio) {
+ /*
+ * Move tag down in priority.
+ */
+ for (i = tagPrio; i < value; i++) {
+ tablePtr->tagPrioNames[i] = tablePtr->tagPrioNames[i+1];
+ tablePtr->tagPrios[i] = tablePtr->tagPrios[i+1];
+ }
+ tablePtr->tagPrioNames[i] = keybuf;
+ tablePtr->tagPrios[i] = tagPtr;
+ refresh = 1;
+ }
+ /* since we deleted a tag, redraw the screen */
+ if (refresh) {
+ TableInvalidateAll(tablePtr, 0);
+ }
+ return TCL_OK;
+
+ }
+ return TCL_OK;
+
+ invalidtag:
+ /*
+ * When jumping here, ensure the invalid 'tagname' is set already.
+ */
+ Tcl_AppendStringsToObj(resultPtr, "invalid tag name \"",
+ tagname, "\"", (char *) NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableOptionReliefSet --
+ *
+ * This routine configures the borderwidth value for a tag.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * It may adjust the tag struct values of relief[0..4] and borders.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+TableOptionReliefSet(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* Type of struct being set. */
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing table widget. */
+ CONST84 char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ TableTag *tagPtr = (TableTag *) widgRec;
+
+ if (*value == '\0') {
+ tagPtr->relief = -1;
+ } else {
+ return Tk_GetRelief(interp, value, &(tagPtr->relief));
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TableOptionReliefGet --
+ *
+ * Results:
+ * Value of the tag's -relief option.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+TableOptionReliefGet(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Type of struct being set. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ return (char *) Tk_NameOfRelief(((TableTag *) widgRec)->relief);
+}