summaryrefslogtreecommitdiffstats
path: root/generic/tkTreeItem.c
diff options
context:
space:
mode:
authortreectrl <treectrl>2007-11-12 04:02:59 (GMT)
committertreectrl <treectrl>2007-11-12 04:02:59 (GMT)
commitc768d05c5deb9d404d6290cf216a4198789f5110 (patch)
tree688a0dc5288da5dcae48e5325bd174825a3055b9 /generic/tkTreeItem.c
parentec190b42ca9fbc4db9c6ea5ba10c853671e59ef0 (diff)
downloadtktreectrl-c768d05c5deb9d404d6290cf216a4198789f5110.zip
tktreectrl-c768d05c5deb9d404d6290cf216a4198789f5110.tar.gz
tktreectrl-c768d05c5deb9d404d6290cf216a4198789f5110.tar.bz2
The new option -itemtagexpr is checked to disable tag expressions in item descriptions.
Changed the [item sort] code to be a "stable" sort. This means that the pre-sort order of two equal items is used as a tie-breaker. [Request 1782405]
Diffstat (limited to 'generic/tkTreeItem.c')
-rw-r--r--generic/tkTreeItem.c106
1 files changed, 89 insertions, 17 deletions
diff --git a/generic/tkTreeItem.c b/generic/tkTreeItem.c
index a989e89..6207e95 100644
--- a/generic/tkTreeItem.c
+++ b/generic/tkTreeItem.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2002-2006 Tim Baker
*
- * RCS: @(#) $Id: tkTreeItem.c,v 1.101 2007/04/21 21:34:01 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeItem.c,v 1.102 2007/11/12 04:02:59 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -1469,6 +1469,44 @@ TreeItem_ToIndex(
if (indexVis != NULL) (*indexVis) = item->indexVis;
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * ItemHasTag --
+ *
+ * Checks whether an item has a certain tag.
+ *
+ * Results:
+ * Returns TRUE if the item has the given tag.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ItemHasTag(
+ TreeItem item, /* The item to test. */
+ Tk_Uid tag /* Tag to look for. */
+ )
+{
+ TagInfo *tagInfo = item->tagInfo;
+ Tk_Uid *tagPtr;
+ int count;
+
+ if (tagInfo == NULL)
+ return 0;
+
+ for (tagPtr = tagInfo->tagPtr, count = tagInfo->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == tag) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
typedef struct Qualifiers {
TreeCtrl *tree;
int visible; /* 1 if the item must be ReallyVisible(),
@@ -1478,6 +1516,7 @@ typedef struct Qualifiers {
TagExpr expr; /* Tag expression. */
int exprOK; /* TRUE if expr is valid. */
int depth; /* >= 0 for depth, -1 for unspecified */
+ Tk_Uid tag; /* Tag (without operators) or NULL. */
} Qualifiers;
/*
@@ -1507,6 +1546,7 @@ Qualifiers_Init(
q->states[0] = q->states[1] = q->states[2] = 0;
q->exprOK = FALSE;
q->depth = -1;
+ q->tag = NULL;
}
/*
@@ -1574,11 +1614,15 @@ Qualifiers_Scan(
break;
}
case QUAL_TAG: {
- if (q->exprOK)
- TagExpr_Free(&q->expr);
- if (TagExpr_Init(tree, objv[j + 1], &q->expr) != TCL_OK)
- return TCL_ERROR;
- q->exprOK = TRUE;
+ if (tree->itemTagExpr) {
+ if (q->exprOK)
+ TagExpr_Free(&q->expr);
+ if (TagExpr_Init(tree, objv[j + 1], &q->expr) != TCL_OK)
+ return TCL_ERROR;
+ q->exprOK = TRUE;
+ } else {
+ q->tag = Tk_GetUid(Tcl_GetString(objv[j + 1]));
+ }
break;
}
case QUAL_VISIBLE: {
@@ -1640,6 +1684,8 @@ Qualifies(
return 0;
if ((q->depth >= 0) && (item->depth + 1 != q->depth))
return 0;
+ if ((q->tag != NULL) && !ItemHasTag(item, q->tag))
+ return 0;
return 1;
}
@@ -2010,24 +2056,36 @@ TreeItemList_FromObj(
goto gotFirstPart;
}
- /* Try a tag expression. */
+ /* Try a tag or tag expression followed by qualifiers. */
if (objc > 1) {
if (Qualifiers_Scan(&q, objc, objv, listIndex + 1,
&qualArgsTotal) != TCL_OK) {
goto errorExit;
}
}
- if (TagExpr_Init(tree, elemPtr, &expr) != TCL_OK)
- goto errorExit;
- hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search);
- while (hPtr != NULL) {
- item = (TreeItem) Tcl_GetHashValue(hPtr);
- if (TagExpr_Eval(&expr, item->tagInfo) && Qualifies(&q, item)) {
- TreeItemList_Append(items, item);
+ if (tree->itemTagExpr) {
+ if (TagExpr_Init(tree, elemPtr, &expr) != TCL_OK)
+ goto errorExit;
+ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search);
+ while (hPtr != NULL) {
+ item = (TreeItem) Tcl_GetHashValue(hPtr);
+ if (TagExpr_Eval(&expr, item->tagInfo) && Qualifies(&q, item)) {
+ TreeItemList_Append(items, item);
+ }
+ hPtr = Tcl_NextHashEntry(&search);
+ }
+ TagExpr_Free(&expr);
+ } else {
+ Tk_Uid tag = Tk_GetUid(Tcl_GetString(elemPtr));
+ hPtr = Tcl_FirstHashEntry(&tree->itemHash, &search);
+ while (hPtr != NULL) {
+ item = (TreeItem) Tcl_GetHashValue(hPtr);
+ if (ItemHasTag(item, tag) && Qualifies(&q, item)) {
+ TreeItemList_Append(items, item);
+ }
+ hPtr = Tcl_NextHashEntry(&search);
}
- hPtr = Tcl_NextHashEntry(&search);
}
- TagExpr_Free(&expr);
item = NULL;
listIndex += 1 + qualArgsTotal;
}
@@ -5607,6 +5665,11 @@ doneSET:
return result;
}
+/* Quicksort is not a "stable" sorting algorithm, but it can become a
+ * stable sort by using the pre-sort order of two items as a tie-breaker
+ * for items that would otherwise be considered equal. */
+#define STABLE_SORT
+
/* one per column per SortItem */
struct SortItem1
{
@@ -5621,6 +5684,9 @@ struct SortItem
TreeItem item;
struct SortItem1 *item1;
Tcl_Obj *obj; /* TreeItem_ToObj() */
+#ifdef STABLE_SORT
+ int index; /* The pre-sort order of the item */
+#endif
};
typedef struct SortData SortData;
@@ -5897,7 +5963,11 @@ CompareProc(
return v;
}
}
+#ifdef STABLE_SORT
+ return (a->index < b->index) ? -1 : 1;
+#else
return 0;
+#endif
}
/* BEGIN custom quicksort() */
@@ -6353,6 +6423,9 @@ ItemSortCmd(
struct SortItem *sortItem = &sortData.items[index];
sortItem->item = walk;
+#ifdef STABLE_SORT
+ sortItem->index = index;
+#endif
if (sawCmd) {
Tcl_Obj *obj = TreeItem_ToObj(tree, walk);
Tcl_IncrRefCount(obj);
@@ -6460,7 +6533,6 @@ ItemSortCmd(
Tcl_SetObjResult(interp, listObj);
goto done;
}
-
first = first->prevSibling;
last = last->nextSibling;