summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkText.c31
-rw-r--r--generic/tkText.h1
-rw-r--r--generic/tkTextDisp.c64
-rw-r--r--tests/text.test106
-rw-r--r--win/nmakehlp.c6
5 files changed, 172 insertions, 36 deletions
diff --git a/generic/tkText.c b/generic/tkText.c
index cb89218..36bb4d4 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -689,15 +689,16 @@ TextWidgetObjCmd(
static const char *optionStrings[] = {
"bbox", "cget", "compare", "configure", "count", "debug", "delete",
"dlineinfo", "dump", "edit", "get", "image", "index", "insert",
- "mark", "peer", "replace", "scan", "search", "see", "tag", "window",
- "xview", "yview", NULL
+ "mark", "peer", "pendingyupdate", "replace", "scan", "search",
+ "see", "tag", "window", "xview", "yupdate", "yview", NULL
};
enum options {
TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT,
TEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT,
TEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK,
- TEXT_PEER, TEXT_REPLACE, TEXT_SCAN, TEXT_SEARCH, TEXT_SEE,
- TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW, TEXT_YVIEW
+ TEXT_PEER, TEXT_PENDINGYUPDATE, TEXT_REPLACE, TEXT_SCAN,
+ TEXT_SEARCH, TEXT_SEE, TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW,
+ TEXT_YUPDATE, TEXT_YVIEW
};
if (objc < 2) {
@@ -1372,6 +1373,18 @@ TextWidgetObjCmd(
case TEXT_PEER:
result = TextPeerCmd(textPtr, interp, objc, objv);
break;
+ case TEXT_PENDINGYUPDATE: {
+ int number;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ number = TkTextPendingyupdate(textPtr);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(number));
+ break;
+ }
case TEXT_REPLACE: {
const TkTextIndex *indexFromPtr, *indexToPtr;
@@ -1494,6 +1507,16 @@ TextWidgetObjCmd(
case TEXT_XVIEW:
result = TkTextXviewCmd(textPtr, interp, objc, objv);
break;
+ case TEXT_YUPDATE: {
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ TkTextUpdateLineMetrics(textPtr, 1,
+ TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1);
+ break;
+ }
case TEXT_YVIEW:
result = TkTextYviewCmd(textPtr, interp, objc, objv);
break;
diff --git a/generic/tkText.h b/generic/tkText.h
index 6f5f153..2d1bcaa 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -1124,6 +1124,7 @@ MODULE_SCOPE int TkTextMarkNameToIndex(TkText *textPtr,
MODULE_SCOPE void TkTextMarkSegToIndex(TkText *textPtr,
TkTextSegment *markPtr, TkTextIndex *indexPtr);
MODULE_SCOPE void TkTextEventuallyRepick(TkText *textPtr);
+MODULE_SCOPE int TkTextPendingyupdate(TkText *textPtr);
MODULE_SCOPE void TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr);
MODULE_SCOPE void TkTextPixelIndex(TkText *textPtr, int x, int y,
TkTextIndex *indexPtr, int *nearest);
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index a275b28..ff90520 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -590,8 +590,7 @@ static int TextGetScrollInfoObj(Tcl_Interp *interp,
Tcl_Obj *CONST objv[], double *dblPtr,
int *intPtr);
static void AsyncUpdateLineMetrics(ClientData clientData);
-static void GenerateMetricsEvent(TkText *textPtr,
- CONST char *eventname);
+static void GenerateTextLineHeightsInvalidEvent(TkText *textPtr);
static void AsyncUpdateYScrollbar(ClientData clientData);
static int IsStartOfNotMergedLine(TkText *textPtr,
CONST TkTextIndex *indexPtr);
@@ -2922,6 +2921,8 @@ AsyncUpdateLineMetrics(
lineNum = TkTextUpdateLineMetrics(textPtr, lineNum,
dInfoPtr->lastMetricUpdateLine, 256);
+ dInfoPtr->currentMetricUpdateLine = lineNum;
+
if (tkTextDebug) {
char buffer[2 * TCL_INTEGER_SPACE + 1];
@@ -2929,6 +2930,8 @@ AsyncUpdateLineMetrics(
LOG("tk_textInvalidateLine", buffer);
}
+ GenerateTextLineHeightsInvalidEvent(textPtr);
+
/*
* If we're not in the middle of a long-line calculation (metricEpoch==-1)
* and we've reached the last line, then we're done.
@@ -2946,10 +2949,8 @@ AsyncUpdateLineMetrics(
if (textPtr->refCount == 0) {
ckfree((char *) textPtr);
}
- GenerateMetricsEvent(textPtr, "MetricsDone");
return;
}
- dInfoPtr->currentMetricUpdateLine = lineNum;
/*
* Re-arm the timer. We already have a refCount on the text widget so no
@@ -2963,45 +2964,37 @@ AsyncUpdateLineMetrics(
/*
*----------------------------------------------------------------------
*
- * GenerateMetricsEvent --
+ * GenerateTextLineHeightsInvalidEvent --
*
- * Send an event related to the text widget metrics asynchronous update
- * Two events are used:
- * - <<MetricsOutdated>>: the asynchronous update of line metrics is
- * currently running
- * - <<MetricsDone>> : the asynchronous update of line metrics is
- * over
+ * Send the <<TextLineHeightsInvalid>> event related to the text widget
+ * line metrics asynchronous update.
* This is equivalent to:
- * event generate $textWidget <<MetricsOutdated>>
- * or
- * event generate $textWidget <<MetricsDone>>
+ * event generate $textWidget <<TextLineHeightsInvalid>> -detail $N
+ * where $N is the number of lines for which the height is outdated.
*
* Results:
* None
*
* Side effects:
- * May force the text window into existence.
* If corresponding bindings are present, they will trigger.
*
*----------------------------------------------------------------------
*/
static void
-GenerateMetricsEvent(
- TkText *textPtr, /* Information about text widget. */
- CONST char *eventname) /* Name of the virtual event to send. */
+GenerateTextLineHeightsInvalidEvent(
+ TkText *textPtr) /* Information about text widget. */
{
union {XEvent general; XVirtualEvent virtual;} event;
- Tk_MakeWindowExist(textPtr->tkwin);
-
memset(&event, 0, sizeof(event));
event.general.xany.type = VirtualEvent;
event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
event.general.xany.send_event = False;
event.general.xany.window = Tk_WindowId(textPtr->tkwin);
event.general.xany.display = Tk_Display(textPtr->tkwin);
- event.virtual.name = Tk_GetUid(eventname);
+ event.virtual.name = Tk_GetUid("TextLineHeightsInvalid");
+ event.virtual.user_data = Tcl_NewIntObj(TkTextPendingyupdate(textPtr));
Tk_HandleEvent(&event.general);
}
@@ -3384,7 +3377,6 @@ TextInvalidateLineMetrics(
textPtr->refCount++;
dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
AsyncUpdateLineMetrics, (ClientData) textPtr);
- GenerateMetricsEvent(textPtr, "MetricsOutdated");
}
}
@@ -5089,7 +5081,6 @@ TkTextRelayoutWindow(
textPtr->refCount++;
dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
AsyncUpdateLineMetrics, (ClientData) textPtr);
- GenerateMetricsEvent(textPtr, "MetricsOutdated");
}
}
}
@@ -6084,6 +6075,33 @@ TkTextYviewCmd(
/*
*--------------------------------------------------------------
*
+ * TkTextPendingyupdate --
+ *
+ * This function computes how many lines are not up-to-date regarding
+ * asynchronous height calculations.
+ *
+ * Results:
+ * Returns a positive integer corresponding to the number of lines for
+ * which the height is outdated.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkTextPendingyupdate(
+ TkText *textPtr) /* Information about text widget. */
+{
+ TextDInfo *dInfoPtr = textPtr->dInfoPtr;
+
+ return (dInfoPtr->lastMetricUpdateLine - dInfoPtr->currentMetricUpdateLine);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* TkTextScanCmd --
*
* This function is invoked to process the "scan" option for the widget
diff --git a/tests/text.test b/tests/text.test
index 7c1731d..7e754e2 100644
--- a/tests/text.test
+++ b/tests/text.test
@@ -153,7 +153,7 @@ test text-3.1 {TextWidgetCmd procedure, basics} {
} {1 {wrong # args: should be ".t option ?arg arg ...?"}}
test text-3.2 {TextWidgetCmd procedure} {
list [catch {.t gorp 1.0 z 1.2} msg] $msg
-} {1 {bad option "gorp": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}
+} {1 {bad option "gorp": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}
test text-4.1 {TextWidgetCmd procedure, "bbox" option} {
list [catch {.t bbox} msg] $msg
@@ -221,7 +221,7 @@ test text-6.13 {TextWidgetCmd procedure, "compare" option} {
} {1 {bad comparison operator "z": must be <, <=, ==, >=, >, or !=}}
test text-6.14 {TextWidgetCmd procedure, "compare" option} {
list [catch {.t co 1.0 z 1.2} msg] $msg
-} {1 {ambiguous option "co": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}
+} {1 {ambiguous option "co": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}
# "configure" option is already covered above
@@ -230,7 +230,7 @@ test text-7.1 {TextWidgetCmd procedure, "debug" option} {
} {1 {wrong # args: should be ".t debug boolean"}}
test text-7.2 {TextWidgetCmd procedure, "debug" option} {
list [catch {.t de 0 1} msg] $msg
-} {1 {ambiguous option "de": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}
+} {1 {ambiguous option "de": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}
test text-7.3 {TextWidgetCmd procedure, "debug" option} {
.t debug true
.t deb
@@ -901,7 +901,7 @@ test text-10.2 {TextWidgetCmd procedure, "index" option} {
} {1 {wrong # args: should be ".t index index"}}
test text-10.3 {TextWidgetCmd procedure, "index" option} {
list [catch {.t in a b} msg] $msg
-} {1 {ambiguous option "in": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}
+} {1 {ambiguous option "in": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingyupdate, replace, scan, search, see, tag, window, xview, yupdate, or yview}}
test text-10.4 {TextWidgetCmd procedure, "index" option} {
list [catch {.t index @xyz} msg] $msg
} {1 {bad text index "@xyz"}}
@@ -960,7 +960,101 @@ test text-11.10 {TextWidgetCmd procedure, "insert" option} {
list [.t get 1.0 1.end] [.t tag ranges bold] [.t tag ranges silly]
} {{First second} {1.0 1.5} {1.5 1.12}}
-# Edit, mark, scan, search, see, tag, window, xview, and yview actions are tested elsewhere.
+test text-11a.1 {TextWidgetCmd procedure, "yupdate" option} {
+ destroy .yt
+ text .yt
+ list [catch {.yt yupdate mytext} msg] $msg
+} {1 {wrong # args: should be ".yt yupdate"}}
+test text-11a.2 {TextWidgetCmd procedure, "yupdate" option} {
+ destroy .top.yt .top
+ toplevel .top
+ pack [text .top.yt]
+ set content {}
+ for {set i 1} {$i < 30} {incr i} {
+ append content [string repeat "$i " 15] \n
+ }
+ .top.yt insert 1.0 $content
+ # wait for end of line metrics calculation to get correct $fraction1
+ # as a reference
+ .top.yt yupdate
+ .top.yt yview moveto 1
+ set fraction1 [lindex [.top.yt yview] 0]
+ set res [expr {$fraction1 > 0}]
+ # first case: do not wait for completion of line metrics calculation
+ .top.yt delete 1.0 end
+ .top.yt insert 1.0 $content
+ .top.yt yview moveto $fraction1
+ set fraction2 [lindex [.top.yt yview] 0]
+ lappend res [expr {$fraction1 == $fraction2}]
+ # second case: wait for completion of line metrics calculation
+ .top.yt delete 1.0 end
+ .top.yt insert 1.0 $content
+ .top.yt yupdate
+ .top.yt yview moveto $fraction1
+ set fraction2 [lindex [.top.yt yview] 0]
+ lappend res [expr {$fraction1 == $fraction2}]
+} {1 0 1}
+test text-11a.11 {TextWidgetCmd procedure, "pendingyupdate" option} {
+ destroy .yt
+ text .yt
+ list [catch {.yt pendingyupdate mytext} msg] $msg
+} {1 {wrong # args: should be ".yt pendingyupdate"}}
+test text-11a.12 {TextWidgetCmd procedure, "pendingyupdate" option} {
+ destroy .top.yt .top
+ toplevel .top
+ pack [text .top.yt]
+ set content {}
+ for {set i 1} {$i < 300} {incr i} {
+ append content [string repeat "$i " 15] \n
+ }
+ .top.yt insert 1.0 $content
+ update
+ # wait for end of line metrics calculation to get correct $fraction1
+ # as a reference
+ while {[.top.yt pendingyupdate]} {update}
+ .top.yt yview moveto 1
+ set fraction1 [lindex [.top.yt yview] 0]
+ set res [expr {$fraction1 > 0}]
+ .top.yt delete 1.0 end
+ .top.yt insert 1.0 $content
+ # ensure the test is relevant
+ lappend res [expr {[.top.yt pendingyupdate] > 0}]
+ # asynchronously wait for completion of line metrics calculation
+ while {[.top.yt pendingyupdate]} {update}
+ .top.yt yview moveto $fraction1
+ set fraction2 [lindex [.top.yt yview] 0]
+ lappend res [expr {$fraction1 == $fraction2}]
+} {1 1 1}
+test text-11a.21 {"<<TextLineHeightsInvalid>>" event} {
+ destroy .top.yt .top
+ toplevel .top
+ pack [text .top.yt]
+ set content {}
+ for {set i 1} {$i < 300} {incr i} {
+ append content [string repeat "$i " 15] \n
+ }
+ .top.yt insert 1.0 $content
+ update
+ bind .top.yt <<TextLineHeightsInvalid>> { if {%d == 0} {set yud(%W) 1} }
+ # wait for end of line metrics calculation to get correct $fraction1
+ # as a reference
+ if {[.top.yt pendingyupdate]} {vwait yud(.top.yt)}
+ .top.yt yview moveto 1
+ set fraction1 [lindex [.top.yt yview] 0]
+ set res [expr {$fraction1 > 0}]
+ .top.yt delete 1.0 end
+ .top.yt insert 1.0 $content
+ # synchronously wait for completion of line metrics calculation
+ # and ensure the test is relevant
+ set waited 0
+ if {[.top.yt pendingyupdate]} {set waited 1 ; vwait yud(.top.yt)}
+ lappend res $waited
+ .top.yt yview moveto $fraction1
+ set fraction2 [lindex [.top.yt yview] 0]
+ lappend res [expr {$fraction1 == $fraction2}]
+} {1 1 1}
+
+# edit, mark, scan, search, see, tag, window, xview and yview actions are tested elsewhere.
test text-12.1 {ConfigureText procedure} {
list [catch {.t2 configure -state foobar} msg] $msg
@@ -3698,7 +3792,7 @@ test text-31.2 {TextWidgetCmd procedure, "peer" option} {
list [catch {.t peer names foo} msg] $msg
} {1 {wrong # args: should be ".t peer names"}}
test text-31.3 {TextWidgetCmd procedure, "peer" option} {
- list [catch {.t p names} msg] $msg
+ list [catch {.t pee names} msg] $msg
} {0 {}}
test text-31.4 {TextWidgetCmd procedure, "peer" option} {
.t peer names
diff --git a/win/nmakehlp.c b/win/nmakehlp.c
index b1a1517..84cf75c 100644
--- a/win/nmakehlp.c
+++ b/win/nmakehlp.c
@@ -606,8 +606,8 @@ SubstituteFile(
sp = fopen(substitutions, "rt");
if (sp != NULL) {
while (fgets(szBuffer, cbBuffer, sp) != NULL) {
- char *ks, *ke, *vs, *ve;
- ks = szBuffer;
+ unsigned char *ks, *ke, *vs, *ve;
+ ks = (unsigned char*)szBuffer;
while (ks && *ks && isspace(*ks)) ++ks;
ke = ks;
while (ke && *ke && !isspace(*ke)) ++ke;
@@ -616,7 +616,7 @@ SubstituteFile(
ve = vs;
while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
*ke = 0, *ve = 0;
- list_insert(&substPtr, ks, vs);
+ list_insert(&substPtr, (char*)ks, (char*)vs);
}
fclose(sp);
}