Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tip-438 Excluding Merge-Ins
This is equivalent to a diff from 3736983e to 9f400abe
2016-01-13
| ||
17:56 | TIP #438 (Ensure Line Metrics are Up-to-Date) accepted by vote check-in: 15b7aa7e user: fvogel tags: trunk | |
2016-01-07
| ||
17:20 | Prefix "system" of all Windows System Colors was documented check-in: 28b2e86a user: oehhar tags: trunk | |
13:08 | rebase "tip-438" branch to latest trunk. Closed-Leaf check-in: 9f400abe user: jan.nijtmans tags: tip-438 | |
2016-01-06
| ||
20:30 | Fixed bug [3102228] - <<ListboxSelect>> doesn't fire when selection lost check-in: 3736983e user: fvogel tags: trunk | |
20:28 | Fixed bug [3102228] - <<ListboxSelect>> doesn't fire when selection lost check-in: 142932e3 user: fvogel tags: core-8-5-branch | |
20:18 | Fixed bug [1288433] - LisboxSelect event triggers when listbox state is disabled check-in: 087e635d user: fvogel tags: trunk | |
2016-01-05
| ||
17:00 | Harmonized use of NULL for textPtr->afterSyncCmd check-in: 0eb8f1f5 user: fvogel tags: tip-438 | |
Changes to doc/text.n.
︙ | ︙ | |||
913 914 915 916 917 918 919 920 921 922 923 924 925 926 | Note that peers are really peers. Deleting the .QW original text widget will not cause any other peers to be deleted, or otherwise affected. .PP See below for the \fIpathName \fBpeer\fR widget command that controls the creation of peer widgets. .SH "WIDGET COMMAND" .PP The \fBtext\fR command creates a new Tcl command whose name is the same as the path name of the text's window. This command may be used to invoke various operations on the widget. It has the following general form: .CS \fIpathName option \fR?\fIarg arg ...\fR? | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 | Note that peers are really peers. Deleting the .QW original text widget will not cause any other peers to be deleted, or otherwise affected. .PP See below for the \fIpathName \fBpeer\fR widget command that controls the creation of peer widgets. .SH "ASYNCHRONOUS UPDATE OF LINE HEIGHTS" .PP In order to maintain a responsive user-experience, the text widget calculates lines metrics (line heights in pixels) asynchronously. Because of this, some commands of the text widget may return wrong results if the asynchronous calculations are not finished at the time of calling. This applies to \fIpathName \fBcount -ypixels\fR and \fIpathName \fByview\fR. .PP Again for performance reasons, it would not be appropriate to let these commands always wait for the end of the update calculation each time they are called. In most use cases of these commands a more or less inaccurate result does not really matter compared to execution speed. .PP In case accurate result is needed (and if the text widget is managed by a geometry manager), one can resort to \fIpathName \fBsync\fR and \fIpathName \fBpendingsync\fR to control the synchronization of the view of text widgets. .PP The \fB<<WidgetViewSync>>\fR virtual event fires when the line heights of the text widget becomes obsolete (due to some editing command or configuration change), and again when the internal data of the text widget are back in sync with the widget view. The detail field (%d substitution) is either true (when the widget is in sync) or false (when it is not). .PP \fIpathName \fBsync\fR, \fIpathName \fBpendingsync\fR and \fB<<WidgetViewSync>>\fR apply to each text widget independently of its peers. .PP Examples of use: .CS ## Example 1: # immediately complete line metrics at any cost (GUI unresponsive) $w sync $w yview moveto $fraction ## Example 2: # synchronously wait for up-to-date line metrics (GUI responsive) # before executing the scheduled command, but don't block execution flow $w sync -command [list $w yview moveto $fraction] ## Example 3: # init set yud($w) 0 proc updateaction w { \&set ::yud($w) 1 \&# any other update action here... } # runtime, synchronously wait for up-to-date line metrics (GUI responsive) $w sync -command [list updateaction $w] vwait yud($w) $w yview moveto $fraction ## Example 4: # init set todo($w) {} proc updateaction w { \&foreach cmd $::todo($w) {uplevel #0 $cmd} \&set todo($w) {} } # runtime lappend todo($w) [list $w yview moveto $fraction] $w sync -command [list updateaction $w] ## Example 5: # init set todo($w) {} bind $w <<WidgetViewSync>> { \&if {%d} { \&\&foreach cmd $todo(%W) {eval $cmd} \&\&set todo(%W) {} \&} } # runtime if {![$w pendingsync]} { \&$w yview moveto $fraction } else { \&lappend todo($w) [list $w yview moveto $fraction] } .CE .SH "WIDGET COMMAND" .PP The \fBtext\fR command creates a new Tcl command whose name is the same as the path name of the text's window. This command may be used to invoke various operations on the widget. It has the following general form: .CS \fIpathName option \fR?\fIarg arg ...\fR? |
︙ | ︙ | |||
977 978 979 980 981 982 983 | \fB\-indices\fR, \fB\-lines\fR, \fB\-xpixels\fR and \fB\-ypixels\fR. The default value, if no option is specified, is \fB\-indices\fR. There is an additional possible option \fB\-update\fR which is a modifier. If given (and if the text widget is managed by a geometry manager), then all subsequent options ensure that any possible out of date information is recalculated. This currently only has any effect for the \fB\-ypixels\fR count (which, if \fB\-update\fR is not given, will use the text widget's current cached value | > > | | 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 | \fB\-indices\fR, \fB\-lines\fR, \fB\-xpixels\fR and \fB\-ypixels\fR. The default value, if no option is specified, is \fB\-indices\fR. There is an additional possible option \fB\-update\fR which is a modifier. If given (and if the text widget is managed by a geometry manager), then all subsequent options ensure that any possible out of date information is recalculated. This currently only has any effect for the \fB\-ypixels\fR count (which, if \fB\-update\fR is not given, will use the text widget's current cached value for each line). This \fB\-update\fR option is obsoleted by \fIpathName \fBsync\fR, \fIpathName \fBpendingsync\fR and \fB<<WidgetViewSync>>\fR. The count options are interpreted as follows: .RS .IP \fB\-chars\fR count all characters, whether elided or not. Do not count embedded windows or images. .IP \fB\-displaychars\fR count all non-elided characters. .IP \fB\-displayindices\fR |
︙ | ︙ | |||
1340 1341 1342 1343 1344 1345 1346 | .TP \fIpathName \fBpeer names\fR . Returns a list of peers of this widget (this does not include the widget itself). The order within this list is undefined. .RE .TP | | > | > | | | > | | | 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 | .TP \fIpathName \fBpeer names\fR . Returns a list of peers of this widget (this does not include the widget itself). The order within this list is undefined. .RE .TP \fIpathName \fBpendingsync\fR Returns 1 if the line heights calculations are not up-to-date, 0 otherwise. .TP \fIpathName \fBreplace\fR \fIindex1 index2 chars\fR ?\fItagList chars tagList ...\fR? Replaces the range of characters between \fIindex1\fR and \fIindex2\fR with the given characters and tags. See the section on \fIpathName \fBinsert\fR for an explanation of the handling of the \fItagList...\fR arguments, and the section on \fIpathName \fBdelete\fR for an explanation of the handling of the indices. If \fIindex2\fR corresponds to an index earlier in the text than \fIindex1\fR, an error will be generated. .RS .PP The deletion and insertion are arranged so that no unnecessary scrolling of the window or movement of insertion cursor occurs. In addition the undo/redo stack are correctly modified, if undo operations are active in the text widget. The command returns an empty string. |
︙ | ︙ | |||
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 | . Adjusts the view in the window so that the character given by \fIindex\fR is completely visible. If \fIindex\fR is already visible then the command does nothing. If \fIindex\fR is a short distance out of view, the command adjusts the view just enough to make \fIindex\fR visible at the edge of the window. If \fIindex\fR is far out of view, then the command centers \fIindex\fR in the window. .TP \fIpathName \fBtag \fIoption \fR?\fIarg arg ...\fR? . This command is used to manipulate tags. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBtag\fR argument. The following forms of the command are currently supported: .RS | > > > > > > > > > > > > > > > > > | 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 | . Adjusts the view in the window so that the character given by \fIindex\fR is completely visible. If \fIindex\fR is already visible then the command does nothing. If \fIindex\fR is a short distance out of view, the command adjusts the view just enough to make \fIindex\fR visible at the edge of the window. If \fIindex\fR is far out of view, then the command centers \fIindex\fR in the window. .TP \fIpathName \fBsync\fR ?\fB-command \fIcommand\fR? Controls the synchronization of the view of the text widget. .RS .TP \fIpathName \fBsync\fR Immediately brings the line metrics up-to-date by forcing computation of any outdated line heights. The command returns immediately if there is no such outdated line heights, otherwise it returns only at the end of the computation. The command returns an empty string. .TP \fIpathName \fBsync -command \fIcommand\fR Schedules \fIcommand\fR to be executed (by the event loop) exactly once as soon as all line heights are up-to-date. If there are no pending line metrics calculations, the scheduling is immediate. The command returns the empty string. \fBbgerror\fR is called on \fIcommand\fR failure. .RE .TP \fIpathName \fBtag \fIoption \fR?\fIarg arg ...\fR? . This command is used to manipulate tags. The exact behavior of the command depends on the \fIoption\fR argument that follows the \fBtag\fR argument. The following forms of the command are currently supported: .RS |
︙ | ︙ |
Changes to generic/tkText.c.
︙ | ︙ | |||
398 399 400 401 402 403 404 405 406 407 408 409 410 411 | static int TextEditUndo(TkText *textPtr); static int TextEditRedo(TkText *textPtr); static Tcl_Obj * TextGetText(const TkText *textPtr, const TkTextIndex *index1, const TkTextIndex *index2, int visibleOnly); static void GenerateModifiedEvent(TkText *textPtr); static void UpdateDirtyFlag(TkSharedText *sharedPtr); static void TextPushUndoAction(TkText *textPtr, Tcl_Obj *undoString, int insert, const TkTextIndex *index1Ptr, const TkTextIndex *index2Ptr); static int TextSearchIndexInLine(const SearchSpec *searchSpecPtr, TkTextLine *linePtr, int byteIndex); static int TextPeerCmd(TkText *textPtr, Tcl_Interp *interp, | > | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | static int TextEditUndo(TkText *textPtr); static int TextEditRedo(TkText *textPtr); static Tcl_Obj * TextGetText(const TkText *textPtr, const TkTextIndex *index1, const TkTextIndex *index2, int visibleOnly); static void GenerateModifiedEvent(TkText *textPtr); static void UpdateDirtyFlag(TkSharedText *sharedPtr); static void RunAfterSyncCmd(ClientData clientData); static void TextPushUndoAction(TkText *textPtr, Tcl_Obj *undoString, int insert, const TkTextIndex *index1Ptr, const TkTextIndex *index2Ptr); static int TextSearchIndexInLine(const SearchSpec *searchSpecPtr, TkTextLine *linePtr, int byteIndex); static int TextPeerCmd(TkText *textPtr, Tcl_Interp *interp, |
︙ | ︙ | |||
698 699 700 701 702 703 704 | register TkText *textPtr = clientData; int result = TCL_OK; int index; static const char *const optionStrings[] = { "bbox", "cget", "compare", "configure", "count", "debug", "delete", "dlineinfo", "dump", "edit", "get", "image", "index", "insert", | | | > | | | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 | register TkText *textPtr = clientData; int result = TCL_OK; int index; static const char *const optionStrings[] = { "bbox", "cget", "compare", "configure", "count", "debug", "delete", "dlineinfo", "dump", "edit", "get", "image", "index", "insert", "mark", "peer", "pendingsync", "replace", "scan", "search", "see", "sync", "tag", "window", "xview", "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_PENDINGSYNC, TEXT_REPLACE, TEXT_SCAN, TEXT_SEARCH, TEXT_SEE, TEXT_SYNC, TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW, TEXT_YVIEW }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } |
︙ | ︙ | |||
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 | } case TEXT_MARK: result = TkTextMarkCmd(textPtr, interp, objc, objv); break; case TEXT_PEER: result = TextPeerCmd(textPtr, interp, objc, objv); break; case TEXT_REPLACE: { const TkTextIndex *indexFromPtr, *indexToPtr; if (objc < 5) { Tcl_WrongNumArgs(interp, 2, objv, "index1 index2 chars ?tagList chars tagList ...?"); result = TCL_ERROR; | > > > > > > > > > > | 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 | } case TEXT_MARK: result = TkTextMarkCmd(textPtr, interp, objc, objv); break; case TEXT_PEER: result = TextPeerCmd(textPtr, interp, objc, objv); break; case TEXT_PENDINGSYNC: { if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); result = TCL_ERROR; goto done; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(TkTextPendingsync(textPtr))); break; } case TEXT_REPLACE: { const TkTextIndex *indexFromPtr, *indexToPtr; if (objc < 5) { Tcl_WrongNumArgs(interp, 2, objv, "index1 index2 chars ?tagList chars tagList ...?"); result = TCL_ERROR; |
︙ | ︙ | |||
1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 | break; case TEXT_SEARCH: result = TextSearchCmd(textPtr, interp, objc, objv); break; case TEXT_SEE: result = TkTextSeeCmd(textPtr, interp, objc, objv); break; case TEXT_TAG: result = TkTextTagCmd(textPtr, interp, objc, objv); break; case TEXT_WINDOW: result = TkTextWindowCmd(textPtr, interp, objc, objv); break; case TEXT_XVIEW: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 | break; case TEXT_SEARCH: result = TextSearchCmd(textPtr, interp, objc, objv); break; case TEXT_SEE: result = TkTextSeeCmd(textPtr, interp, objc, objv); break; case TEXT_SYNC: { if (objc == 4) { Tcl_Obj *cmd = objv[3]; const char *option = Tcl_GetString(objv[2]); if (strncmp(option, "-command", objv[2]->length)) { Tcl_AppendResult(interp, "wrong option \"", option, "\": should be \"-command\"", NULL); result = TCL_ERROR; goto done; } Tcl_IncrRefCount(cmd); if (TkTextPendingsync(textPtr)) { if (textPtr->afterSyncCmd) { Tcl_DecrRefCount(textPtr->afterSyncCmd); } textPtr->afterSyncCmd = cmd; } else { textPtr->afterSyncCmd = cmd; Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr); } break; } else if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, "?-command command?"); result = TCL_ERROR; goto done; } if (textPtr->afterSyncCmd) { Tcl_DecrRefCount(textPtr->afterSyncCmd); } textPtr->afterSyncCmd = NULL; TkTextUpdateLineMetrics(textPtr, 1, TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1); break; } case TEXT_TAG: result = TkTextTagCmd(textPtr, interp, objc, objv); break; case TEXT_WINDOW: result = TkTextWindowCmd(textPtr, interp, objc, objv); break; case TEXT_XVIEW: |
︙ | ︙ | |||
1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 | if (textPtr->insertBlinkHandler != NULL) { Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler); } textPtr->tkwin = NULL; textPtr->refCount--; Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd); if (textPtr->refCount == 0) { ckfree(textPtr); } } /* *---------------------------------------------------------------------- | > > > > | 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 | if (textPtr->insertBlinkHandler != NULL) { Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler); } textPtr->tkwin = NULL; textPtr->refCount--; Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd); if (textPtr->afterSyncCmd){ Tcl_DecrRefCount(textPtr->afterSyncCmd); textPtr->afterSyncCmd = NULL; } if (textPtr->refCount == 0) { ckfree(textPtr); } } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 | if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) { for (textPtr = sharedTextPtr->peers; textPtr != NULL; textPtr = textPtr->next) { GenerateModifiedEvent(textPtr); } } } /* *---------------------------------------------------------------------- * * SearchPerform -- * * Overall control of search process. Is given a pattern, a starting | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 | if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) { for (textPtr = sharedTextPtr->peers; textPtr != NULL; textPtr = textPtr->next) { GenerateModifiedEvent(textPtr); } } } /* *---------------------------------------------------------------------- * * RunAfterSyncCmd -- * * This function is called by the event loop and executes the command * scheduled by [.text sync -command $cmd]. * * Results: * None. * * Side effects: * Anything may happen, depending on $cmd contents. * *---------------------------------------------------------------------- */ static void RunAfterSyncCmd( ClientData clientData) /* Information about text widget. */ { register TkText *textPtr = (TkText *) clientData; int code; if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { /* * The widget has been deleted. Don't do anything. */ if (--textPtr->refCount == 0) { ckfree((char *) textPtr); } return; } Tcl_Preserve((ClientData) textPtr->interp); code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL); if (code == TCL_ERROR) { Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); Tcl_BackgroundError(textPtr->interp); } Tcl_Release((ClientData) textPtr->interp); Tcl_DecrRefCount(textPtr->afterSyncCmd); textPtr->afterSyncCmd = NULL; } /* *---------------------------------------------------------------------- * * SearchPerform -- * * Overall control of search process. Is given a pattern, a starting |
︙ | ︙ |
Changes to generic/tkText.h.
︙ | ︙ | |||
781 782 783 784 785 786 787 788 789 790 791 792 793 794 | int undo; /* Non-zero means the undo/redo behaviour is * enabled. */ int maxUndo; /* The maximum depth of the undo stack * expressed as the maximum number of compound * statements. */ int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ } TkText; /* * Flag values for TkText records: * * GOT_SELECTION: Non-zero means we've already claimed the * selection. | > > | 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 | int undo; /* Non-zero means the undo/redo behaviour is * enabled. */ int maxUndo; /* The maximum depth of the undo stack * expressed as the maximum number of compound * statements. */ int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ Tcl_Obj *afterSyncCmd; /* Command to be executed when lines are up to * date */ } TkText; /* * Flag values for TkText records: * * GOT_SELECTION: Non-zero means we've already claimed the * selection. |
︙ | ︙ | |||
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 | MODULE_SCOPE int TkTextMarkCmd(TkText *textPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TkTextMarkNameToIndex(TkText *textPtr, const char *name, TkTextIndex *indexPtr); MODULE_SCOPE void TkTextMarkSegToIndex(TkText *textPtr, TkTextSegment *markPtr, TkTextIndex *indexPtr); MODULE_SCOPE void TkTextEventuallyRepick(TkText *textPtr); MODULE_SCOPE void TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr); MODULE_SCOPE void TkTextPixelIndex(TkText *textPtr, int x, int y, TkTextIndex *indexPtr, int *nearest); MODULE_SCOPE Tcl_Obj * TkTextNewIndexObj(TkText *textPtr, const TkTextIndex *indexPtr); MODULE_SCOPE void TkTextRedrawRegion(TkText *textPtr, int x, int y, int width, int height); | > | 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 | MODULE_SCOPE int TkTextMarkCmd(TkText *textPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TkTextMarkNameToIndex(TkText *textPtr, const char *name, TkTextIndex *indexPtr); MODULE_SCOPE void TkTextMarkSegToIndex(TkText *textPtr, TkTextSegment *markPtr, TkTextIndex *indexPtr); MODULE_SCOPE void TkTextEventuallyRepick(TkText *textPtr); MODULE_SCOPE Bool TkTextPendingsync(TkText *textPtr); MODULE_SCOPE void TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr); MODULE_SCOPE void TkTextPixelIndex(TkText *textPtr, int x, int y, TkTextIndex *indexPtr, int *nearest); MODULE_SCOPE Tcl_Obj * TkTextNewIndexObj(TkText *textPtr, const TkTextIndex *indexPtr); MODULE_SCOPE void TkTextRedrawRegion(TkText *textPtr, int x, int y, int width, int height); |
︙ | ︙ |
Changes to generic/tkTextDisp.c.
︙ | ︙ | |||
587 588 589 590 591 592 593 594 595 596 597 598 599 600 | static int DlineXOfIndex(TkText *textPtr, DLine *dlPtr, int byteIndex); static int TextGetScrollInfoObj(Tcl_Interp *interp, TkText *textPtr, int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr); static void AsyncUpdateLineMetrics(ClientData clientData); static void AsyncUpdateYScrollbar(ClientData clientData); static int IsStartOfNotMergedLine(TkText *textPtr, CONST TkTextIndex *indexPtr); /* * Result values returned by TextGetScrollInfoObj: */ | > | 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | static int DlineXOfIndex(TkText *textPtr, DLine *dlPtr, int byteIndex); static int TextGetScrollInfoObj(Tcl_Interp *interp, TkText *textPtr, int objc, Tcl_Obj *const objv[], double *dblPtr, int *intPtr); static void AsyncUpdateLineMetrics(ClientData clientData); static void GenerateWidgetViewSyncEvent(TkText *textPtr, Bool InSync); static void AsyncUpdateYScrollbar(ClientData clientData); static int IsStartOfNotMergedLine(TkText *textPtr, CONST TkTextIndex *indexPtr); /* * Result values returned by TextGetScrollInfoObj: */ |
︙ | ︙ | |||
2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 | * Update the lines in blocks of about 24 recalculations, or 250+ lines * examined, so we pass in 256 for 'doThisMuch'. */ lineNum = TkTextUpdateLineMetrics(textPtr, lineNum, dInfoPtr->lastMetricUpdateLine, 256); if (tkTextDebug) { char buffer[2 * TCL_INTEGER_SPACE + 1]; sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine); LOG("tk_textInvalidateLine", buffer); } /* * 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. */ if (dInfoPtr->metricEpoch == -1 && lineNum == dInfoPtr->lastMetricUpdateLine) { /* * We have looped over all lines, so we're done. We must release our * refCount on the widget (the timer token was already set to NULL | > > | > > > > > > > > > > > > > > > > > > > > > > < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 | * Update the lines in blocks of about 24 recalculations, or 250+ lines * examined, so we pass in 256 for 'doThisMuch'. */ lineNum = TkTextUpdateLineMetrics(textPtr, lineNum, dInfoPtr->lastMetricUpdateLine, 256); dInfoPtr->currentMetricUpdateLine = lineNum; if (tkTextDebug) { char buffer[2 * TCL_INTEGER_SPACE + 1]; sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine); LOG("tk_textInvalidateLine", buffer); } /* * 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. */ if (dInfoPtr->metricEpoch == -1 && lineNum == dInfoPtr->lastMetricUpdateLine) { /* * We have looped over all lines, so we're done. We must release our * refCount on the widget (the timer token was already set to NULL * above). If there is a registered aftersync command, run that first. */ if (textPtr->afterSyncCmd) { int code; Tcl_Preserve((ClientData) textPtr->interp); code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL); if (code == TCL_ERROR) { Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)"); Tcl_BackgroundError(textPtr->interp); } Tcl_Release((ClientData) textPtr->interp); Tcl_DecrRefCount(textPtr->afterSyncCmd); textPtr->afterSyncCmd = NULL; } /* * Fire the <<WidgetViewSync>> event since the widget view is in sync * with its internal data (actually it will be after the next trip * through the event loop, because the widget redraws at idle-time). */ GenerateWidgetViewSyncEvent(textPtr, 1); textPtr->refCount--; if (textPtr->refCount == 0) { ckfree(textPtr); } return; } /* * Re-arm the timer. We already have a refCount on the text widget so no * need to adjust that. */ dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); } /* *---------------------------------------------------------------------- * * GenerateWidgetViewSyncEvent -- * * Send the <<WidgetViewSync>> event related to the text widget * line metrics asynchronous update. * This is equivalent to: * event generate $textWidget <<WidgetViewSync>> -detail $s * where $s is the sync status: true (when the widget view is in * sync with its internal data) or false (when it is not). * * Results: * None * * Side effects: * If corresponding bindings are present, they will trigger. * *---------------------------------------------------------------------- */ static void GenerateWidgetViewSyncEvent( TkText *textPtr, /* Information about text widget. */ Bool InSync) /* True if in sync, false otherwise */ { union {XEvent general; XVirtualEvent virtual;} event; 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("WidgetViewSync"); event.virtual.user_data = Tcl_NewBooleanObj(InSync); Tk_HandleEvent(&event.general); } /* *---------------------------------------------------------------------- * * TkTextUpdateLineMetrics -- * * This function updates the pixel height calculations of a range of |
︙ | ︙ | |||
3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 | * Now re-set the current update calculations. */ if (dInfoPtr->lineUpdateTimer == NULL) { textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); } } /* *---------------------------------------------------------------------- * * TkTextFindDisplayLineEnd -- | > | 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 | * Now re-set the current update calculations. */ if (dInfoPtr->lineUpdateTimer == NULL) { textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); GenerateWidgetViewSyncEvent(textPtr, 0); } } /* *---------------------------------------------------------------------- * * TkTextFindDisplayLineEnd -- |
︙ | ︙ | |||
5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 | dInfoPtr->metricEpoch = -1; if (dInfoPtr->lineUpdateTimer == NULL) { textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); } } } /* *---------------------------------------------------------------------- * | > | 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 | dInfoPtr->metricEpoch = -1; if (dInfoPtr->lineUpdateTimer == NULL) { textPtr->refCount++; dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, AsyncUpdateLineMetrics, textPtr); GenerateWidgetViewSyncEvent(textPtr, 0); } } } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 | break; case TKTEXT_SCROLL_UNITS: YScrollByLines(textPtr, count); break; } return TCL_OK; } /* *-------------------------------------------------------------- * * TkTextScanCmd -- * * This function is invoked to process the "scan" option for the widget | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 | break; case TKTEXT_SCROLL_UNITS: YScrollByLines(textPtr, count); break; } return TCL_OK; } /* *-------------------------------------------------------------- * * TkTextPendingsync -- * * This function checks if any line heights are not up-to-date. * * Results: * Returns a boolean true if it is the case, or false if all line * heights are up-to-date. * * Side effects: * None. * *-------------------------------------------------------------- */ Bool TkTextPendingsync( TkText *textPtr) /* Information about text widget. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; return ( ((dInfoPtr->metricEpoch == -1) && (dInfoPtr->lastMetricUpdateLine == dInfoPtr->currentMetricUpdateLine)) ? 0 : 1); } /* *-------------------------------------------------------------- * * TkTextScanCmd -- * * This function is invoked to process the "scan" option for the widget |
︙ | ︙ |
Changes to tests/text.test.
︙ | ︙ | |||
921 922 923 924 925 926 927 | } -returnCodes {error} -result {wrong # args: should be ".t option ?arg ...?"} test text-3.2 {TextWidgetCmd procedure} -setup { text .t } -body { .t gorp 1.0 z 1.2 } -cleanup { destroy .t | | | 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 | } -returnCodes {error} -result {wrong # args: should be ".t option ?arg ...?"} test text-3.2 {TextWidgetCmd procedure} -setup { text .t } -body { .t gorp 1.0 z 1.2 } -cleanup { destroy .t } -returnCodes {error} -result {bad option "gorp": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview} test text-4.1 {TextWidgetCmd procedure, "bbox" option} -setup { text .t } -body { .t bbox } -cleanup { destroy .t |
︙ | ︙ | |||
1143 1144 1145 1146 1147 1148 1149 | Line 4 bOy GIrl .#@? x_yz !@#$% Line 7" .t co 1.0 z 1.2 } -cleanup { destroy .t | | | | 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 | Line 4 bOy GIrl .#@? x_yz !@#$% Line 7" .t co 1.0 z 1.2 } -cleanup { destroy .t } -returnCodes {error} -result {ambiguous option "co": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview} # "configure" option is already covered above test text-7.1 {TextWidgetCmd procedure, "debug" option} -setup { text .t } -body { .t debug 0 1 } -cleanup { destroy .t } -returnCodes {error} -result {wrong # args: should be ".t debug boolean"} test text-7.2 {TextWidgetCmd procedure, "debug" option} -setup { text .t } -body { .t de 0 1 } -cleanup { destroy .t } -returnCodes {error} -result {ambiguous option "de": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview} test text-7.3 {TextWidgetCmd procedure, "debug" option} -setup { text .t } -body { .t debug true .t deb } -cleanup { destroy .t |
︙ | ︙ | |||
2682 2683 2684 2685 2686 2687 2688 | } .t tag configure hidden -elide true .t tag add hidden 5.7 11.0 update # next line to be fully sure that asynchronous line heights calculation is # up-to-date otherwise this test may fail (depending on the computer # performance), especially when the . toplevel has small height | | | 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 | } .t tag configure hidden -elide true .t tag add hidden 5.7 11.0 update # next line to be fully sure that asynchronous line heights calculation is # up-to-date otherwise this test may fail (depending on the computer # performance), especially when the . toplevel has small height .t sync set y1 [lindex [.t yview] 1] .t count -displaylines 5.0 11.0 set y2 [lindex [.t yview] 1] .t count -displaylines 5.0 12.0 set y3 [lindex [.t yview] 1] list [expr {$y1 == $y2}] [expr {$y1 == $y3}] } -cleanup { |
︙ | ︙ | |||
2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 | lappend res [.t index "end -2 indices"] lappend res [.t index "end -2 display indices"] lappend res [.t index "end -2 display chars"] } -cleanup { destroy .t } -result {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} test text-12.1 {TextWidgetCmd procedure, "index" option} -setup { text .t } -body { .t index } -cleanup { destroy .t | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 | lappend res [.t index "end -2 indices"] lappend res [.t index "end -2 display indices"] lappend res [.t index "end -2 display chars"] } -cleanup { destroy .t } -result {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} test text-11a.1 {TextWidgetCmd procedure, "pendingsync" option} -setup { destroy .yt } -body { text .yt list [catch {.yt pendingsync mytext} msg] $msg } -cleanup { destroy .yt } -result {1 {wrong # args: should be ".yt pendingsync"}} test text-11a.2 {TextWidgetCmd procedure, "pendingsync" option} -setup { destroy .top.yt .top } -body { 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 # wait for end of line metrics calculation to get correct $fraction1 # as a reference while {[.top.yt pendingsync]} {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 [.top.yt pendingsync] # asynchronously wait for completion of line metrics calculation while {[.top.yt pendingsync]} {update} .top.yt yview moveto $fraction1 set fraction2 [lindex [.top.yt yview] 0] lappend res [expr {$fraction1 == $fraction2}] } -cleanup { destroy .top.yt .top } -result {1 1 1} test text-11a.11 {TextWidgetCmd procedure, "sync" option} -setup { destroy .yt } -body { text .yt list [catch {.yt sync mytext} msg] $msg } -cleanup { destroy .yt } -result {1 {wrong # args: should be ".yt sync ?-command command?"}} test text-11a.12 {TextWidgetCmd procedure, "sync" option} -setup { destroy .top.yt .top } -body { 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 sync .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 sync .top.yt yview moveto $fraction1 set fraction2 [lindex [.top.yt yview] 0] lappend res [expr {$fraction1 == $fraction2}] } -cleanup { destroy .top.yt .top } -result {1 0 1} test text-11a.21 {TextWidgetCmd procedure, "sync" option with -command} -setup { destroy .yt } -body { text .yt list [catch {.yt sync -comx foo} msg] $msg } -cleanup { destroy .yt } -result {1 {wrong option "-comx": should be "-command"}} test text-11a.22 {TextWidgetCmd procedure, "sync" option with -command} -setup { destroy .top.yt .top } -body { set res {} set ::x 0 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 # first case: line metrics calculation still running when launching 'sync -command' lappend res [.top.yt pendingsync] .top.yt sync -command [list set ::x 1] lappend res $::x # now finish line metrics calculations while {[.top.yt pendingsync]} {update} lappend res [.top.yt pendingsync] $::x # second case: line metrics calculation completed when launching 'sync -command' .top.yt sync -command [list set ::x 2] lappend res $::x vwait ::x lappend res $::x } -cleanup { destroy .top.yt .top } -result {1 0 0 1 1 2} test text-11a.31 {"<<WidgetViewSync>>" event} -setup { destroy .top.yt .top } -body { 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 <<WidgetViewSync>> { if {%d} {set yud(%W) 1} } # wait for end of line metrics calculation to get correct $fraction1 # as a reference if {[.top.yt pendingsync]} {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 pendingsync]} {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}] } -cleanup { destroy .top.yt .top } -result {1 1 1} test text-11a.41 {"sync" "pendingsync" and <<WidgetViewSync>>} -setup { destroy .top.yt .top } -body { set res {} toplevel .top pack [text .top.yt] set content {} for {set i 1} {$i < 300} {incr i} { append content [string repeat "$i " 50] \n } bind .top.yt <<WidgetViewSync>> {lappend res Sync:%d} .top.yt insert 1.0 $content vwait res ; # event dealt with by the event loop, with %d==0 i.e. we're out of sync # ensure the test is relevant lappend res "Pending:[.top.yt pendingsync]" # - <<WidgetViewSync>> fires when sync returns if there was pending syncs # - there is no more any pending sync after running 'sync' .top.yt sync vwait res ; # event dealt with by the event loop, with %d==1 i.e. we're in sync again lappend res "Pending:[.top.yt pendingsync]" set res } -cleanup { destroy .top.yt .top } -result {Sync:0 Pending:1 Sync:1 Pending:0} test text-12.1 {TextWidgetCmd procedure, "index" option} -setup { text .t } -body { .t index } -cleanup { destroy .t |
︙ | ︙ | |||
2899 2900 2901 2902 2903 2904 2905 | } -returnCodes {error} -result {wrong # args: should be ".t index index"} test text-12.3 {TextWidgetCmd procedure, "index" option} -setup { text .t } -body { .t in a b } -cleanup { destroy .t | | | 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 | } -returnCodes {error} -result {wrong # args: should be ".t index index"} test text-12.3 {TextWidgetCmd procedure, "index" option} -setup { text .t } -body { .t in a b } -cleanup { destroy .t } -returnCodes {error} -result {ambiguous option "in": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, pendingsync, replace, scan, search, see, sync, tag, window, xview, or yview} test text-12.4 {TextWidgetCmd procedure, "index" option} -setup { text .t } -body { .t index @xyz } -cleanup { destroy .t } -returnCodes {error} -result {bad text index "@xyz"} |
︙ | ︙ | |||
6706 6707 6708 6709 6710 6711 6712 | .t peer names foo } -cleanup { destroy .t } -returnCodes {error} -result {wrong # args: should be ".t peer names"} test text-33.3 {TextWidgetCmd procedure, "peer" option} -setup { text .t } -body { | | | 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 | .t peer names foo } -cleanup { destroy .t } -returnCodes {error} -result {wrong # args: should be ".t peer names"} test text-33.3 {TextWidgetCmd procedure, "peer" option} -setup { text .t } -body { .t pee names } -cleanup { destroy .t } -returnCodes {ok} -result {} test text-33.4 {TextWidgetCmd procedure, "peer" option} -setup { text .t } -body { .t peer names |
︙ | ︙ |
Changes to tests/textDisp.test.
︙ | ︙ | |||
4193 4194 4195 4196 4197 4198 4199 | set result "italic font has much too much space" } else { set result "italic font measurement ok" } } {italic font measurement ok} destroy .tt | | | < < < | | | > > > < | | > > > > > > > > | < < | | | | 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 | set result "italic font has much too much space" } else { set result "italic font measurement ok" } } {italic font measurement ok} destroy .tt test textDisp-34.1 {Line heights recalculation problem: bug 2677890} -setup { pack [text .t1] -expand 1 -fill both set txt "" for {set i 1} {$i < 100} {incr i} { append txt "Line $i\n" } set result {} } -body { .t1 insert end $txt .t1 debug 1 set ge [winfo geometry .] scan $ge "%dx%d+%d+%d" width height left top update .t1 sync set negative 0 bind .t1 <<WidgetViewSync>> { if {%d < 0} {set negative 1} } # Without the fix for bug 2677890, changing the width of the toplevel # will launch recomputation of the line heights, but will produce negative # number of still remaining outdated lines, which is obviously wrong. # Thus we use this way to check for regression regarding bug 2677890, # i.e. to check that the fix for this bug really is still in. wm geometry . "[expr {$width * 2}]x$height+$left+$top" update .t1 sync set negative } -cleanup { destroy .t1 } -result {0} test textDisp-35.1 {Init value of charHeight - Dancing scrollbar bug 1499165} -setup { pack [text .t1] -fill both -expand y -side left .t insert end "[string repeat a\nb\nc\n 500000]THE END\n" set res {} } -body { .t see 10000.0 |
︙ | ︙ |