summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvincentdarley <vincentdarley>2003-11-08 17:22:45 (GMT)
committervincentdarley <vincentdarley>2003-11-08 17:22:45 (GMT)
commitf1ed0750bc8ef3f269f20750e44a0d58e9677082 (patch)
treed3be8a33f1d8bfc5c803dad0b85a7b30184743b9
parent70578fe7b3c2b20b549a09800b88fcba2a1e0cd8 (diff)
downloadtk-f1ed0750bc8ef3f269f20750e44a0d58e9677082.zip
tk-f1ed0750bc8ef3f269f20750e44a0d58e9677082.tar.gz
tk-f1ed0750bc8ef3f269f20750e44a0d58e9677082.tar.bz2
elide tag handling, once more
-rw-r--r--ChangeLog11
-rw-r--r--generic/tkText.h17
-rw-r--r--generic/tkTextBTree.c25
-rw-r--r--generic/tkTextDisp.c57
-rw-r--r--generic/tkTextIndex.c171
-rw-r--r--tests/text.test26
-rw-r--r--tests/textDisp.test16
7 files changed, 241 insertions, 82 deletions
diff --git a/ChangeLog b/ChangeLog
index cbc26a8..83bbd55 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2003-11-08 Vince Darley <vincentdarley@users.sourceforge.net>
+
+ * tests/textDisp.test:
+ * tests/text.test:
+ * generic/tkText.h:
+ * generic/tkTextIndex.c:
+ * generic/tkTextBTree.c:
+ * generic/tkTextDisp.c: fix to another version of [Bug 833627]
+ (crash in tkchat), adding more tests. I believe the handling of
+ nested elide tags of all types is now correct!
+
2003-11-07 Vince Darley <vincentdarley@users.sourceforge.net>
* tests/textDisp.test:
diff --git a/generic/tkText.h b/generic/tkText.h
index 89e4f7b..16e617a 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkText.h,v 1.18 2003/11/07 15:36:26 vincentdarley Exp $
+ * RCS: @(#) $Id: tkText.h,v 1.19 2003/11/08 17:22:46 vincentdarley Exp $
*/
#ifndef _TKTEXT
@@ -827,13 +827,16 @@ typedef int TkTextCountType;
#define LOTSA_TAGS 1000
typedef struct TkTextElideInfo {
- int numTags;
- int elide;
- int elidePriority;
- int deftagCnts[LOTSA_TAGS];
+ int numTags; /* Total tags in widget */
+ int elide; /* Is the state currently elided */
+ int elidePriority; /* Tag priority controlling elide state */
+ TkTextSegment *segPtr; /* Segment to look at next */
+ int deftagCnts[LOTSA_TAGS];
TkTextTag *deftagPtrs[LOTSA_TAGS];
- int *tagCnts;
- TkTextTag **tagPtrs;
+ int *tagCnts; /* 0 or 1 depending if the tag with
+ * that priority is on or off */
+ TkTextTag **tagPtrs; /* Only filled with a tagPtr if the
+ * corresponding tagCnt is 1 */
} TkTextElideInfo;
/*
diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c
index 7be9e7d..22d91c7 100644
--- a/generic/tkTextBTree.c
+++ b/generic/tkTextBTree.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextBTree.c,v 1.9 2003/11/07 15:36:26 vincentdarley Exp $
+ * RCS: @(#) $Id: tkTextBTree.c,v 1.10 2003/11/08 17:22:46 vincentdarley Exp $
*/
#include "tkInt.h"
@@ -2682,13 +2682,22 @@ TkBTreeGetTags(indexPtr, numTagsPtr)
* TkTextIsElided --
*
* Special case to just return information about elided attribute.
- * Specialized from TkBTreeGetTags(indexPtr, numTagsPtr)
- * and GetStyle(textPtr, indexPtr).
- * Just need to keep track of invisibility settings for each priority,
- * pick highest one active at end
+ * Specialized from TkBTreeGetTags(indexPtr, numTagsPtr) and
+ * GetStyle(textPtr, indexPtr). Just need to keep track of
+ * invisibility settings for each priority, pick highest one active
+ * at end.
+ *
+ * Note that this returns all elide information up to and including
+ * the given index (quite obviously). However, this does mean that
+ * indexPtr is a line-start and one then iterates from the beginning
+ * of that line forwards, one will actually revisit the segPtrs of
+ * size zero (for tag toggling, for example) which have already been
+ * seen here.
*
* Results:
* Returns whether this text should be elided or not.
+ *
+ * Optionally returns more detailed information in elideInfo.
*
* Side effects:
* None.
@@ -2754,6 +2763,11 @@ TkTextIsElided(textPtr, indexPtr, elideInfo)
}
}
}
+ /*
+ * Store the first segPtr we haven't examined completely
+ * so that our caller knows where to start.
+ */
+ infoPtr->segPtr = segPtr;
/*
* Record toggles for tags in lines that are predecessors of
@@ -2817,6 +2831,7 @@ TkTextIsElided(textPtr, indexPtr, elideInfo)
}
#endif
infoPtr->elide = infoPtr->tagPtrs[i]->elide;
+ /* Note: i == infoPtr->tagPtrs[i]->priority */
infoPtr->elidePriority = i;
break;
}
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index 324b3ab..85a160d 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextDisp.c,v 1.24 2003/11/07 15:36:26 vincentdarley Exp $
+ * RCS: @(#) $Id: tkTextDisp.c,v 1.25 2003/11/08 17:22:46 vincentdarley Exp $
*/
#include "tkPort.h"
@@ -957,9 +957,7 @@ LayoutDLine(textPtr, indexPtr)
elide = TkTextIsElided(textPtr, indexPtr, &info);
if (elide && indexPtr->byteIndex==0) {
maxBytes = 0;
- for (segPtr = indexPtr->linePtr->segPtr;
- segPtr != NULL;
- segPtr = segPtr->nextPtr) {
+ for (segPtr = info.segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {
if (segPtr->size > 0) {
if (elide == 0) {
/*
@@ -977,19 +975,45 @@ LayoutDLine(textPtr, indexPtr)
} else if ((segPtr->typePtr == &tkTextToggleOffType)
|| (segPtr->typePtr == &tkTextToggleOnType)) {
TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
- if (tagPtr->elideString != NULL
- && (tagPtr->priority >= info.elidePriority)) {
- elide = ((segPtr->typePtr == &tkTextToggleOffType)
- ^ tagPtr->elide);
- if (!elide && tagPtr->priority == info.elidePriority) {
- /* Find previous elide tag, if any */
- while (--info.elidePriority > 0) {
- if (info.tagCnts[info.elidePriority] & 1) {
- break;
+ /*
+ * The elide state only changes if this tag is
+ * either the current highest priority tag
+ * (and is therefore being toggled off), or it's
+ * a new tag with higher priority.
+ */
+ if (tagPtr->elideString != NULL) {
+ info.tagCnts[tagPtr->priority]++;
+ if (info.tagCnts[tagPtr->priority] & 1) {
+ info.tagPtrs[tagPtr->priority] = tagPtr;
+ }
+ if (tagPtr->priority >= info.elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOffType) {
+ /*
+ * If it is being toggled off, and it has
+ * an elide string, it must actually be the
+ * current highest priority tag, so this
+ * check is redundant:
+ */
+ if (tagPtr->priority != info.elidePriority) {
+ panic("Bad tag priority being toggled off");
+ }
+
+ /*
+ * Find previous elide tag, if any (if not
+ * then elide will be zero, of course).
+ */
+ elide = 0;
+ while (--info.elidePriority > 0) {
+ if (info.tagCnts[info.elidePriority] & 1) {
+ elide = info.tagPtrs[info.elidePriority]
+ ->elide;
+ break;
+ }
}
+ } else {
+ elide = tagPtr->elide;
+ info.elidePriority = tagPtr->priority;
}
- } else {
- info.elidePriority = tagPtr->priority;
}
}
}
@@ -5223,7 +5247,8 @@ GetXView(interp, textPtr, report)
dInfoPtr->xScrollLast = last;
if (textPtr->xScrollCmd != NULL) {
listObj = Tcl_NewStringObj(textPtr->xScrollCmd, -1);
- code = Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(first));
+ code = Tcl_ListObjAppendElement(interp, listObj,
+ Tcl_NewDoubleObj(first));
if (code == TCL_OK) {
Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(last));
code = Tcl_EvalObjEx(interp, listObj,
diff --git a/generic/tkTextIndex.c b/generic/tkTextIndex.c
index 123fb01..c5ef481 100644
--- a/generic/tkTextIndex.c
+++ b/generic/tkTextIndex.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextIndex.c,v 1.10 2003/11/07 15:36:26 vincentdarley Exp $
+ * RCS: @(#) $Id: tkTextIndex.c,v 1.11 2003/11/08 17:22:46 vincentdarley Exp $
*/
#include "default.h"
@@ -1385,25 +1385,46 @@ TkTextIndexForwChars(textPtr, srcPtr, charCount, dstPtr, type)
if ((segPtr->typePtr == &tkTextToggleOffType)
|| (segPtr->typePtr == &tkTextToggleOnType)) {
TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
- if (tagPtr->elideString != NULL
- && (tagPtr->priority >= infoPtr->elidePriority)) {
- if (elide) {
- elide = ((segPtr->typePtr == &tkTextToggleOffType)
- & !tagPtr->elide);
- } else {
- elide = ((segPtr->typePtr == &tkTextToggleOnType)
- & tagPtr->elide);
+ /*
+ * The elide state only changes if this tag is
+ * either the current highest priority tag
+ * (and is therefore being toggled off), or it's
+ * a new tag with higher priority.
+ */
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagCnts[tagPtr->priority]++;
+ if (infoPtr->tagCnts[tagPtr->priority] & 1) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
}
- if (!elide && tagPtr->priority
- == infoPtr->elidePriority) {
- /* Find previous elide tag, if any */
- while (--infoPtr->elidePriority > 0) {
- if (infoPtr->tagCnts[infoPtr->elidePriority] & 1) {
- break;
+ if (tagPtr->priority >= infoPtr->elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOffType) {
+ /*
+ * If it is being toggled off, and it has
+ * an elide string, it must actually be the
+ * current highest priority tag, so this
+ * check is redundant:
+ */
+ if (tagPtr->priority != infoPtr->elidePriority) {
+ panic("Bad tag priority being toggled off");
+ }
+
+ /*
+ * Find previous elide tag, if any (if not
+ * then elide will be zero, of course).
+ */
+ elide = 0;
+ while (--infoPtr->elidePriority > 0) {
+ if (infoPtr->tagCnts[infoPtr->elidePriority]
+ & 1) {
+ elide = infoPtr->tagPtrs
+ [infoPtr->elidePriority]->elide;
+ break;
+ }
}
+ } else {
+ elide = tagPtr->elide;
+ infoPtr->elidePriority = tagPtr->priority;
}
- } else {
- infoPtr->elidePriority = tagPtr->priority;
}
}
}
@@ -1529,33 +1550,54 @@ TkTextIndexCount(textPtr, indexPtr1, indexPtr2, type)
*/
if (checkElided) {
if ((segPtr->typePtr == &tkTextToggleOffType)
- || (segPtr->typePtr == &tkTextToggleOnType)) {
+ || (segPtr->typePtr == &tkTextToggleOnType)) {
TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
- if (tagPtr->elideString != NULL
- && (tagPtr->priority >= infoPtr->elidePriority)) {
- if (elide) {
- elide = ((segPtr->typePtr == &tkTextToggleOffType)
- & !tagPtr->elide);
- } else {
- elide = ((segPtr->typePtr == &tkTextToggleOnType)
- & tagPtr->elide);
+ /*
+ * The elide state only changes if this tag is
+ * either the current highest priority tag
+ * (and is therefore being toggled off), or it's
+ * a new tag with higher priority.
+ */
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagCnts[tagPtr->priority]++;
+ if (infoPtr->tagCnts[tagPtr->priority] & 1) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
}
- if (!elide && tagPtr->priority
- == infoPtr->elidePriority) {
- /* Find previous elide tag, if any */
- while (--infoPtr->elidePriority > 0) {
- if (infoPtr->tagCnts[infoPtr->elidePriority] & 1) {
- break;
+ if (tagPtr->priority >= infoPtr->elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOffType) {
+ /*
+ * If it is being toggled off, and it has
+ * an elide string, it must actually be the
+ * current highest priority tag, so this
+ * check is redundant:
+ */
+ if (tagPtr->priority != infoPtr->elidePriority) {
+ panic("Bad tag priority being toggled off");
+ }
+
+ /*
+ * Find previous elide tag, if any (if not
+ * then elide will be zero, of course).
+ */
+ elide = 0;
+ while (--infoPtr->elidePriority > 0) {
+ if (infoPtr->tagCnts[infoPtr->elidePriority]
+ & 1) {
+ elide = infoPtr->tagPtrs
+ [infoPtr->elidePriority]->elide;
+ break;
+ }
}
+ } else {
+ elide = tagPtr->elide;
+ infoPtr->elidePriority = tagPtr->priority;
}
- } else {
- infoPtr->elidePriority = tagPtr->priority;
}
}
}
if (elide) {
if (segPtr == seg2Ptr) {
- return count;
+ goto countDone;
}
byteOffset = 0;
continue;
@@ -1601,7 +1643,7 @@ TkTextIndexCount(textPtr, indexPtr1, indexPtr2, type)
}
}
if (segPtr == seg2Ptr) {
- return count;
+ goto countDone;
}
byteOffset = 0;
}
@@ -1618,6 +1660,11 @@ TkTextIndexCount(textPtr, indexPtr1, indexPtr2, type)
}
segPtr = linePtr1->segPtr;
}
+ countDone:
+ if (infoPtr != NULL) {
+ ckfree((char*) infoPtr);
+ }
+ return count;
}
/*
@@ -1761,25 +1808,45 @@ TkTextIndexBackChars(textPtr, srcPtr, charCount, dstPtr, type)
if ((segPtr->typePtr == &tkTextToggleOffType)
|| (segPtr->typePtr == &tkTextToggleOnType)) {
TkTextTag *tagPtr = segPtr->body.toggle.tagPtr;
- if (tagPtr->elideString != NULL
- && (tagPtr->priority >= infoPtr->elidePriority)) {
- if (elide) {
- elide = ((segPtr->typePtr == &tkTextToggleOnType)
- & !tagPtr->elide);
- } else {
- elide = ((segPtr->typePtr == &tkTextToggleOffType)
- & tagPtr->elide);
+ /*
+ * The elide state only changes if this tag is
+ * either the current highest priority tag
+ * (and is therefore being toggled off), or it's
+ * a new tag with higher priority.
+ */
+ if (tagPtr->elideString != NULL) {
+ infoPtr->tagCnts[tagPtr->priority]++;
+ if (infoPtr->tagCnts[tagPtr->priority] & 1) {
+ infoPtr->tagPtrs[tagPtr->priority] = tagPtr;
}
- if (!elide && tagPtr->priority
- == infoPtr->elidePriority) {
- /* Find previous elide tag, if any */
- while (--infoPtr->elidePriority > 0) {
- if (infoPtr->tagCnts[infoPtr->elidePriority] & 1) {
- break;
+ if (tagPtr->priority >= infoPtr->elidePriority) {
+ if (segPtr->typePtr == &tkTextToggleOnType) {
+ /*
+ * If it is being toggled on, and it has
+ * an elide string, it must actually be the
+ * current highest priority tag, so this
+ * check is redundant:
+ */
+ if (tagPtr->priority != infoPtr->elidePriority) {
+ panic("Bad tag priority being toggled on");
}
+
+ /*
+ * Find previous elide tag, if any (if not
+ * then elide will be zero, of course).
+ */
+ elide = 0;
+ while (--infoPtr->elidePriority > 0) {
+ if (infoPtr->tagCnts[infoPtr->elidePriority] & 1) {
+ elide = infoPtr->tagPtrs
+ [infoPtr->elidePriority]->elide;
+ break;
+ }
+ }
+ } else {
+ elide = tagPtr->elide;
+ infoPtr->elidePriority = tagPtr->priority;
}
- } else {
- infoPtr->elidePriority = tagPtr->priority;
}
}
}
diff --git a/tests/text.test b/tests/text.test
index 6e32ffd..9e85c8b 100644
--- a/tests/text.test
+++ b/tests/text.test
@@ -6,7 +6,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: text.test,v 1.24 2003/11/07 15:36:27 vincentdarley Exp $
+# RCS: @(#) $Id: text.test,v 1.25 2003/11/08 17:22:46 vincentdarley Exp $
package require tcltest 2.1
eval tcltest::configure $argv
@@ -706,6 +706,30 @@ test text-0.2.50 {counting with tag priority eliding} {
lappend res [.t count -displaychars 1.2 1.5]
lappend res [.t count -displaychars 1.3 1.5]
} {0 0 0 0 3 2 1 1}
+test text-0.2.51 {counting with tag priority eliding} {
+ set res {}
+ .t delete 1.0 end
+ .t tag configure WELCOME -elide 1
+ .t tag configure SYSTEM -elide 0
+ .t tag configure TRAFFIC -elide 1
+ .t insert end "\n" {SYSTEM TRAFFIC}
+ .t insert end "\n" WELCOME
+ lappend res [.t count -displaychars 1.0 end]
+ lappend res [.t count -displaychars 1.0 end-1c]
+ lappend res [.t count -displaychars 1.0 1.2]
+ lappend res [.t count -displaychars 2.0 end]
+ lappend res [.t count -displaychars 2.0 end-1c]
+ lappend res [.t index "1.0 +1 indices"]
+ lappend res [.t index "1.0 +1 display indices"]
+ lappend res [.t index "1.0 +1 display chars"]
+ lappend res [.t index end]
+ lappend res [.t index "end -1 indices"]
+ lappend res [.t index "end -1 display indices"]
+ lappend res [.t index "end -1 display chars"]
+ lappend res [.t index "end -2 indices"]
+ lappend res [.t index "end -2 display indices"]
+ lappend res [.t index "end -2 display chars"]
+} {1 0 0 1 0 2.0 4.0 4.0 4.0 3.0 3.0 3.0 2.0 1.0 1.0}
.t delete 1.0 end
.t insert end $current
diff --git a/tests/textDisp.test b/tests/textDisp.test
index abf1d2a..61ba27a 100644
--- a/tests/textDisp.test
+++ b/tests/textDisp.test
@@ -6,7 +6,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: textDisp.test,v 1.15 2003/11/07 12:06:47 vincentdarley Exp $
+# RCS: @(#) $Id: textDisp.test,v 1.16 2003/11/08 17:22:46 vincentdarley Exp $
package require tcltest 2.1
eval tcltest::configure $argv
@@ -186,6 +186,20 @@ test textDisp-0.4 {double tag elide transition} {
destroy .txt
} {}
+test textDisp-0.5 {double tag elide transition} {
+ catch {destroy .txt}
+ pack [text .txt]
+ .txt tag configure WELCOME -elide 1
+ .txt tag configure SYSTEM -elide 0
+ .txt tag configure TRAFFIC -elide 1
+
+ .txt insert end "\n" {SYSTEM TRAFFIC}
+ .txt insert end "\n" WELCOME
+ # Crash was here.
+ update
+ destroy .txt
+} {}
+
test textDisp-1.1 {GetStyle procedure, priorities and tab stops} {
.t delete 1.0 end
.t insert 1.0 "x\ty"