summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2016-03-30 07:38:04 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2016-03-30 07:38:04 (GMT)
commitb4f99cb2ddffc2639186270b87d2ff9d85c23088 (patch)
treea2e933a9bd65cffc72a95b4dc6210d3295c48859
parent81f9316af362e614d73f055fed1dd87f736c55bb (diff)
parent32ed623c6a6ea47b434caae5452486b9ed93e197 (diff)
downloadtk-b4f99cb2ddffc2639186270b87d2ff9d85c23088.zip
tk-b4f99cb2ddffc2639186270b87d2ff9d85c23088.tar.gz
tk-b4f99cb2ddffc2639186270b87d2ff9d85c23088.tar.bz2
merge core-8-6-branch
-rw-r--r--doc/text.n40
-rw-r--r--generic/tkText.c19
-rw-r--r--library/entry.tcl10
-rw-r--r--library/spinbox.tcl10
-rw-r--r--library/text.tcl10
-rw-r--r--library/ttk/entry.tcl10
-rw-r--r--sdl/SdlTkInt.c117
-rw-r--r--sdl/SdlTkInt.h2
-rw-r--r--sdl/SdlTkUtils.c22
-rw-r--r--sdl/SdlTkX.c132
-rw-r--r--sdl/tkSDLEvent.c4
-rw-r--r--tests/text.test3
-rw-r--r--tests/textDisp.test8
-rw-r--r--win/tkWinMenu.c12
-rw-r--r--xlib/X11/Xlib.h1
15 files changed, 291 insertions, 109 deletions
diff --git a/doc/text.n b/doc/text.n
index e20b68c..1925f5e 100644
--- a/doc/text.n
+++ b/doc/text.n
@@ -1173,22 +1173,30 @@ test suite.
.TP
\fIpathName \fBdelete \fIindex1 \fR?\fIindex2 ...\fR?
.
-Delete a range of characters from the text. If both \fIindex1\fR and
-\fIindex2\fR are specified, then delete all the characters starting with the
-one given by \fIindex1\fR and stopping just before \fIindex2\fR (i.e. the
-character at \fIindex2\fR is not deleted). If \fIindex2\fR does not specify a
-position later in the text than \fIindex1\fR then no characters are deleted.
-If \fIindex2\fR is not specified then the single character at \fIindex1\fR is
-deleted. It is not allowable to delete characters in a way that would leave
-the text without a newline as the last character. The command returns an empty
-string. If more indices are given, multiple ranges of text will be deleted.
-All indices are first checked for validity before any deletions are made. They
-are sorted and the text is removed from the last range to the first range so
-deleted text does not cause an undesired index shifting side-effects. If
-multiple ranges with the same start index are given, then the longest range is
-used. If overlapping ranges are given, then they will be merged into spans
-that do not cause deletion of text outside the given ranges due to text
-shifted during deletion.
+Delete a range of characters from the text.
+If both \fIindex1\fR and \fIindex2\fR are specified, then delete
+all the characters starting with the one given by \fIindex1\fR
+and stopping just before \fIindex2\fR (i.e. the character at
+\fIindex2\fR is not deleted).
+If \fIindex2\fR does not specify a position later in the text
+than \fIindex1\fR then no characters are deleted.
+If \fIindex2\fR is not specified then the single character at
+\fIindex1\fR is deleted.
+Attempts to delete characters in a way that would leave
+the text without a newline as the last character will be tweaked by the
+text widget to avoid this. In particular, deletion of complete lines of
+text up to the end of the text will also delete the newline character just
+before the deleted block so that it is replaced by the new final newline
+of the text widget.
+The command returns an empty string.
+If more indices are given, multiple ranges of text will be deleted.
+All indices are first checked for validity before any deletions are made.
+They are sorted and the text is removed from the last range to the
+first range so deleted text does not cause an undesired index shifting
+side-effects. If multiple ranges with the same start index are given,
+then the longest range is used. If overlapping ranges are given, then
+they will be merged into spans that do not cause deletion of text
+outside the given ranges due to text shifted during deletion.
.TP
\fIpathName \fBdlineinfo \fIindex\fR
.
diff --git a/generic/tkText.c b/generic/tkText.c
index 76251c0..8b94ab7 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -3089,11 +3089,16 @@ DeleteIndexRange(
* The code below is ugly, but it's needed to make sure there is always a
* dummy empty line at the end of the text. If the final newline of the
* file (just before the dummy line) is being deleted, then back up index
- * to just before the newline. Furthermore, remove any tags that are
- * present on the newline that isn't going to be deleted after all (this
- * simulates deleting the newline and then adding a "clean" one back
- * again). Note that index1 and index2 might now be equal again which
- * means that no text will be deleted but tags might be removed.
+ * to just before the newline. If there is a newline just before the first
+ * character being deleted, then back up the first index too. The idea is
+ * that a deletion involving a range starting at a line start and
+ * including the final \n (i.e. index2 is "end") is an attempt to delete
+ * complete lines, so the \n before the deleted block shall become the new
+ * final \n. Furthermore, remove any tags that are present on the newline
+ * that isn't going to be deleted after all (this simulates deleting the
+ * newline and then adding a "clean" one back again). Note that index1 and
+ * index2 might now be equal again which means that no text will be
+ * deleted but tags might be removed.
*/
line1 = TkBTreeLinesTo(textPtr, index1.linePtr);
@@ -3106,6 +3111,10 @@ DeleteIndexRange(
oldIndex2 = index2;
TkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES);
line2--;
+ if ((index1.byteIndex == 0) && (line1 != 0)) {
+ TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES);
+ line1--;
+ }
arrayPtr = TkBTreeGetTags(&index2, NULL, &arraySize);
if (arrayPtr != NULL) {
for (i = 0; i < arraySize; i++) {
diff --git a/library/entry.tcl b/library/entry.tcl
index 389a9bd..dd83f13 100644
--- a/library/entry.tcl
+++ b/library/entry.tcl
@@ -324,9 +324,13 @@ proc ::tk::EntryButton1 {w x} {
focus $w
if {"readonly" ne [$w cget -state]} {
if {$::tk::sdltk} {
- lassign [$w bbox insert] x y
- incr x [winfo rootx $w]
- incr y [winfo rooty $w]
+ if {[catch {
+ lassign [$w bbox insert] x y
+ incr x [winfo rootx $w]
+ incr y [winfo rooty $w]
+ }]} {
+ lassign [winfo pointerxy $w] x y
+ }
sdltk textinput 1 $x $y
}
}
diff --git a/library/spinbox.tcl b/library/spinbox.tcl
index 54331ed..e30c215 100644
--- a/library/spinbox.tcl
+++ b/library/spinbox.tcl
@@ -398,9 +398,13 @@ proc ::tk::spinbox::ButtonDown {w x y} {
focus $w
if {"readonly" ne [$w cget -state]} {
if {$::tk::sdltk} {
- lassign [$w bbox insert] x y
- incr x [winfo rootx $w]
- incr y [winfo rooty $w]
+ if {[catch {
+ lassign [$w bbox insert] x y
+ incr x [winfo rootx $w]
+ incr y [winfo rooty $w]
+ }]} {
+ lassign [winfo pointerxy $w] x y
+ }
sdltk textinput 1 $x $y
}
}
diff --git a/library/text.tcl b/library/text.tcl
index 4f44f39..ebee20d 100644
--- a/library/text.tcl
+++ b/library/text.tcl
@@ -500,9 +500,13 @@ proc ::tk::TextSetInput {w} {
return
}
if {$::tk::sdltk} {
- lassign [$w bbox insert] x y
- incr x [winfo rootx $w]
- incr y [winfo rooty $w]
+ if {[catch {
+ lassign [$w bbox insert] x y
+ incr x [winfo rootx $w]
+ incr y [winfo rooty $w]
+ }]} {
+ lassign [winfo pointerxy $w] x y
+ }
sdltk textinput 1 $x $y
}
}
diff --git a/library/ttk/entry.tcl b/library/ttk/entry.tcl
index ff919f1..3a2363b 100644
--- a/library/ttk/entry.tcl
+++ b/library/ttk/entry.tcl
@@ -346,9 +346,13 @@ proc ttk::entry::Press {w x} {
focus $w
$w instate !readonly {
if {$::tk::sdltk} {
- lassign [$w bbox insert] xx yy
- incr xx [winfo rootx $w]
- incr yy [winfo rooty $w]
+ if {[catch {
+ lassign [$w bbox insert] xx yy
+ incr xx [winfo rootx $w]
+ incr yy [winfo rooty $w]
+ }]} {
+ lassign [winfo pointerxy $w] xx yy
+ }
sdltk textinput 1 $xx $yy
}
}
diff --git a/sdl/SdlTkInt.c b/sdl/SdlTkInt.c
index 6810917..00b6d86 100644
--- a/sdl/SdlTkInt.c
+++ b/sdl/SdlTkInt.c
@@ -1659,7 +1659,7 @@ doNormalKeyEvent:
}
SdlTkX.mouse_x = x;
SdlTkX.mouse_y = y;
- if (tkwin != NULL) {
+ if ((tkwin != NULL) && (Tk_WindowId(tkwin) != None)) {
SendPointerUpdate(tkwin, x, y, xstate);
}
return 0;
@@ -1712,7 +1712,7 @@ doNormalKeyEvent:
} else if (sdl_event->wheel.y > 0) {
xstate |= Button4Mask;
}
- if (tkwin && xstate) {
+ if ((tkwin != NULL) && (Tk_WindowId(tkwin) != None) && xstate) {
SendPointerUpdate(tkwin, SdlTkX.mouse_x, SdlTkX.mouse_y,
xstate);
SendPointerUpdate(tkwin, SdlTkX.mouse_x, SdlTkX.mouse_y,
@@ -2549,7 +2549,7 @@ SdlTkCalculateVisibleRegion(_Window *_w)
/*
*----------------------------------------------------------------------
*
- * blitMovedWindow --
+ * BlitMovedWindow --
*
* Helper routine for SdlTkVisRgnChanged(). Copies the visible
* pixels of a window from its old location to its new location.
@@ -2565,11 +2565,11 @@ SdlTkCalculateVisibleRegion(_Window *_w)
*/
static void
-blitMovedWindow(_Window *_w, int x, int y)
+BlitMovedWindow(_Window *_w, int x, int y)
{
XGCValues fakeGC;
TkpClipMask clip;
- int xOff, yOff;
+ int xOff, yOff, width, height;
Region parentVisRgn;
/*
@@ -2580,6 +2580,15 @@ blitMovedWindow(_Window *_w, int x, int y)
_w->parent->visRgn = _w->parent->visRgnInParent;
/*
+ * What actually needs to be done is copy pixels inside the
+ * old visRgnInParent to the new location. The copy operation
+ * must be constrained by the parent window, since the
+ * child may be larger.
+ */
+ width = _w->parentWidth;
+ height = _w->parentHeight;
+
+ /*
* This window's visRgnInParent is used as the clip region. Put
* it in the parent's coordinates.
*/
@@ -2592,12 +2601,8 @@ blitMovedWindow(_Window *_w, int x, int y)
fakeGC.clip_x_origin = 0;
fakeGC.clip_y_origin = 0;
- /*
- * What actually needs to be done is copy everything inside the
- * old visRgnInParent to the new location.
- */
SdlTkGfxCopyArea((Drawable) _w->parent, (Drawable) _w->parent, &fakeGC,
- x, y, _w->parentWidth, _w->parentHeight, _w->atts.x, _w->atts.y);
+ x, y, width, height, _w->atts.x, _w->atts.y);
XOffsetRegion(_w->visRgnInParent, -_w->atts.x, -_w->atts.y);
@@ -2642,8 +2647,9 @@ blitMovedWindow(_Window *_w, int x, int y)
static void
SdlTkVisRgnChangedInt(_Window *_w, int flags, int x, int y)
{
- int cleared = 0;
+ Region visRgn = NULL;
Region visRgnInParent = NULL;
+ int clrRgn = 0;
/*
* If this is NOT the window that was mapped/unmapped/moved/
@@ -2651,7 +2657,6 @@ SdlTkVisRgnChangedInt(_Window *_w, int flags, int x, int y)
* visible regions for this window.
*/
if ((flags & VRC_CHANGED) || (_w->atts.map_state != IsUnmapped)) {
- Region visRgn;
/*
* A window obscures part of its parent.
@@ -2672,7 +2677,15 @@ SdlTkVisRgnChangedInt(_Window *_w, int flags, int x, int y)
* pixels to the new location.
*/
if ((flags & VRC_MOVE) && !XEmptyRegion(_w->visRgnInParent)) {
- blitMovedWindow(_w, x, y);
+ Region newRgnInParent, blitRgn = SdlTkRgnPoolGet();
+
+ /* For the pixel copy, intersect old and new regions of parent */
+ newRgnInParent = _w->visRgnInParent;
+ XIntersectRegion(visRgnInParent, newRgnInParent, blitRgn);
+ _w->visRgnInParent = blitRgn;
+ BlitMovedWindow(_w, x, y);
+ _w->visRgnInParent = newRgnInParent;
+ SdlTkRgnPoolFree(blitRgn);
}
if (_w->atts.map_state != IsUnmapped) {
@@ -2685,17 +2698,16 @@ SdlTkVisRgnChangedInt(_Window *_w, int flags, int x, int y)
* decframe or wrapper
*/
if (_w->tkwin != NULL) {
- cleared = SdlTkGfxClearRegion((Window) _w, visRgn);
- if ((cleared && !(flags & VRC_EXPOSE)) ||
- (_w->gl_tex != NULL)) {
- SdlTkGfxExposeRegion((Window) _w, visRgn);
+ if (!XEmptyRegion(visRgn) || (_w->gl_tex != NULL)) {
+ flags |= VRC_EXPOSE;
+ clrRgn = 1;
}
- cleared = 1;
} else if (_w->dec != NULL) {
if (!XEmptyRegion(visRgn)) {
SdlTkDecSetDraw(_w, 1);
+ clrRgn = 1;
}
- cleared = 1;
+ flags |= VRC_EXPOSE;
} else if (IS_ROOT(_w)) {
/*
* Can't erase right away, because it will erase the pixels of
@@ -2708,13 +2720,13 @@ SdlTkVisRgnChangedInt(_Window *_w, int flags, int x, int y)
SdlTkX.screen_dirty_region);
}
}
-
- SdlTkRgnPoolFree(visRgn);
}
- if (flags & VRC_EXPOSE) {
- if (_w->tkwin != NULL) {
+ if ((_w->atts.map_state != IsUnmapped) && (flags & VRC_EXPOSE)) {
+ if ((flags & (VRC_MOVE | VRC_CHANGED)) && XEmptyRegion(visRgn)) {
SdlTkGfxExposeRegion((Window) _w, _w->visRgn);
+ } else {
+ SdlTkGfxExposeRegion((Window) _w, visRgn);
}
}
@@ -2731,22 +2743,22 @@ SdlTkVisRgnChangedInt(_Window *_w, int flags, int x, int y)
* moving a toplevel), don't recalculate the visible
* regions of any descendants.
*/
- if ((flags & VRC_EXPOSE) || cleared ||
+ if ((flags & VRC_EXPOSE) ||
!XEqualRegion(_w->visRgnInParent, visRgnInParent)) {
/*
* We only need to do our first child, because it will do
* its next sibling etc.
*/
if (_w->child != NULL) {
- SdlTkVisRgnChangedInt(_w->child, cleared ? VRC_EXPOSE : 0,
+ SdlTkVisRgnChangedInt(_w->child, flags & VRC_EXPOSE,
0, 0);
}
}
}
- if (visRgnInParent != NULL) {
- SdlTkRgnPoolFree(visRgnInParent);
- visRgnInParent = NULL;
+ if (clrRgn && (visRgn != NULL)) {
+ /* Clear what we <Expose>'d before */
+ SdlTkGfxClearRegion((Window) _w, visRgn);
}
/* A window may obscure siblings lower in the stacking order */
@@ -2759,6 +2771,11 @@ SdlTkVisRgnChangedInt(_Window *_w, int flags, int x, int y)
}
}
+ if (visRgn != NULL) {
+ SdlTkRgnPoolFree(visRgn);
+ visRgn = NULL;
+ }
+
if (visRgnInParent != NULL) {
SdlTkRgnPoolFree(visRgnInParent);
visRgnInParent = NULL;
@@ -4133,6 +4150,49 @@ ScreensaverObjCmd(ClientData clientData, Tcl_Interp *interp,
}
static int
+StatObjCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+{
+ Tk_Window tkwin = (Tk_Window) clientData;
+ Display *display;
+ Tcl_DString ds;
+ char buffer[128];
+ int *rgnCounts;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringInit(&ds);
+ SdlTkLock(NULL);
+ rgnCounts = SdlTkRgnPoolStat();
+ sprintf(buffer, "frame_count %d", SdlTkX.frame_count);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ sprintf(buffer, " time_count %d", SdlTkX.time_count);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ sprintf(buffer, " window_free %d", SdlTkX.nwfree);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ sprintf(buffer, " window_total %d", SdlTkX.nwtotal);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ sprintf(buffer, " region_free %d", rgnCounts[0]);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ sprintf(buffer, " region_total %d", rgnCounts[1]);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ SdlTkUnlock(NULL);
+ display = Tk_Display(tkwin);
+ Tcl_MutexLock((Tcl_Mutex *) &display->qlock);
+ sprintf(buffer, " event_length %d", display->qlen);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ sprintf(buffer, " event_length_max %d", display->qlenmax);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ sprintf(buffer, " event_total %d", display->nqtotal);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ Tcl_MutexUnlock((Tcl_Mutex *) &display->qlock);
+ Tcl_DStringResult(interp, &ds);
+ return TCL_OK;
+}
+
+static int
TextinputObjCmd(ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[])
{
@@ -4360,6 +4420,7 @@ static const TkEnsemble sdltkCmdMap[] = {
{ "restore", RestoreObjCmd, NULL },
{ "root", RootObjCmd, NULL },
{ "screensaver", ScreensaverObjCmd, NULL },
+ { "stat", StatObjCmd, NULL },
{ "textinput", TextinputObjCmd, NULL },
{ "touchtranslate", TouchtranslateObjCmd, NULL },
{ "viewport", ViewportObjCmd, NULL },
diff --git a/sdl/SdlTkInt.h b/sdl/SdlTkInt.h
index 8372f1b..4ceefb5 100644
--- a/sdl/SdlTkInt.h
+++ b/sdl/SdlTkInt.h
@@ -180,6 +180,7 @@ typedef struct SdlTkXInfo {
/* Display/Screen/Window elements */
Display *display;
Screen *screen;
+ int nwfree, nwtotal;
_Window *wfree, *wtail;
/* Geometry of decorative frames */
@@ -376,6 +377,7 @@ extern void SdlTkGfxPutImage(Drawable d, Region r, XImage* image,
/* SdlTkUtils.c */
extern Region SdlTkRgnPoolGet(void);
extern void SdlTkRgnPoolFree(Region r);
+extern int *SdlTkRgnPoolStat(void);
extern char **SdlTkListFonts(const char *xlfd, int *count);
extern Font SdlTkFontLoadXLFD(const char *xlfd);
extern int SdlTkFontInit(Tcl_Interp *interp);
diff --git a/sdl/SdlTkUtils.c b/sdl/SdlTkUtils.c
index 81e64ba..a03358e 100644
--- a/sdl/SdlTkUtils.c
+++ b/sdl/SdlTkUtils.c
@@ -50,6 +50,7 @@ typedef struct RgnEntry {
struct RgnEntry *next;
} RgnEntry;
+static int rgnCounts[2] = { 0, 0 }; /* Statistic counters */
static RgnEntry *rgnPool = NULL; /* Linked list of available Regions */
static RgnEntry *rgnFree = NULL; /* Linked list of free RgnEntrys */
@@ -73,6 +74,7 @@ SdlTkRgnPoolGet(void)
* they don't deallocate memory when getting smaller.
*/
XSetEmptyRegion(r);
+ rgnCounts[0]--;
return r;
}
@@ -91,11 +93,19 @@ SdlTkRgnPoolFree(Region r)
entry = rgnFree;
rgnFree = entry->next;
} else {
- entry = (RgnEntry *) ckalloc(sizeof(RgnEntry));
+ entry = (RgnEntry *) ckalloc(sizeof (RgnEntry));
+ rgnCounts[1]++;
}
entry->r = r;
entry->next = rgnPool;
rgnPool = entry;
+ rgnCounts[0]++;
+}
+
+int *
+SdlTkRgnPoolStat(void)
+{
+ return rgnCounts;
}
/*
@@ -375,7 +385,7 @@ SdlTkFontLoadXLFD(const char *xlfd)
/* TkGetCursorByName() */
if (!strcmp(xlfd, cursorFontName)) {
_f = (_Font *) ckalloc (sizeof (_Font));
- memset(_f, 0, sizeof(_Font));
+ memset(_f, 0, sizeof (_Font));
_f->file = cursorFontName;
_f->refCnt = 1;
FNTLOG("FONTLOAD: '%s' -> '%s'", xlfd, cursorFontName);
@@ -407,7 +417,7 @@ SdlTkFontLoadXLFD(const char *xlfd)
* we were given an XLFD refering to a font already loaded, and we hadn't
* seen the XLFD before (in practice this doesn't seem to happen).
*/
- memset(&ffsKey, '\0', sizeof(ffsKey));
+ memset(&ffsKey, 0, sizeof (ffsKey));
ffsKey.file = XInternAtom(SdlTkX.display, fstorage.file, False);
ffsKey.index = fstorage.index;
ffsKey.size = fstorage.size;
@@ -445,7 +455,7 @@ SdlTkFontLoadXLFD(const char *xlfd)
Tcl_SetHashValue(hPtr, (char *) _f);
/* Reuse existing GlyphIndexHash for this file && face */
- memset(&ffKey, '\0', sizeof(ffKey));
+ memset(&ffKey, 0, sizeof (ffKey));
ffKey.file = XInternAtom(SdlTkX.display, _f->file, False);
ffKey.index = fstorage.index;
hPtr = Tcl_CreateHashEntry(&fileFaceHash, (char *) &ffKey, &isNew);
@@ -1065,7 +1075,7 @@ fonterr:
(face->charmap->encoding != FT_ENCODING_UNICODE)) {
goto nextface;
}
- memset(&ffKey, '\0', sizeof (ffKey));
+ memset(&ffKey, 0, sizeof (ffKey));
ffKey.file = XInternAtom(SdlTkX.display, fname, False);
ffKey.index = k;
hPtr = Tcl_CreateHashEntry(&fileFaceHash, (char *) &ffKey,
@@ -1217,7 +1227,7 @@ SdlTkFontAdd(Tcl_Interp *interp, const char *fname)
(face->charmap->encoding != FT_ENCODING_UNICODE)) {
goto nextface;
}
- memset(&ffKey, '\0', sizeof (ffKey));
+ memset(&ffKey, 0, sizeof (ffKey));
ffKey.file = XInternAtom(SdlTkX.display, fname, False);
ffKey.index = k;
hPtr = Tcl_CreateHashEntry(&fileFaceHash, (char *) &ffKey, &isNew);
diff --git a/sdl/SdlTkX.c b/sdl/SdlTkX.c
index f791bef..1b8d897 100644
--- a/sdl/SdlTkX.c
+++ b/sdl/SdlTkX.c
@@ -752,7 +752,7 @@ XCreateBitmapFromData(Display *display, Drawable d, _Xconst char *data,
SDL_FreePalette(pal);
_p = (_Pixmap *) ckalloc(sizeof (_Pixmap));
- memset(_p, '\0', sizeof (_Pixmap));
+ memset(_p, 0, sizeof (_Pixmap));
_p->type = DT_PIXMAP;
_p->sdl = sdl;
_p->format = SdlTkPixelFormat(sdl);
@@ -815,7 +815,7 @@ XCreateGC(Display *display, Drawable d, unsigned long mask, XGCValues *values)
if (!gp) {
return None;
}
- memset(gp, '\0', sizeof (XGCValues));
+ memset(gp, 0, sizeof (XGCValues));
gp->next = display->gcs;
display->gcs = gp;
gp->function = (mask & GCFunction) ? values->function : GXcopy;
@@ -1133,7 +1133,7 @@ XCreatePixmap(Display *display, Drawable d, unsigned int width,
}
_p = (_Pixmap *) ckalloc(sizeof (_Pixmap));
- memset(_p, '\0', sizeof (_Pixmap));
+ memset(_p, 0, sizeof (_Pixmap));
_p->type = DT_PIXMAP;
_p->sdl = sdl;
_p->format = SdlTkPixelFormat(sdl);
@@ -1167,15 +1167,17 @@ SdlTkCreateWindow(Display *display, Window parent, int x, int y,
_Window *_parent = (_Window *) parent;
_Window *_w;
- _w = SdlTkX.wfree;
+ _w = (SdlTkX.nwfree >= 16) ? SdlTkX.wfree : NULL;
if (_w == NULL) {
_w = (_Window *) ckalloc(sizeof (_Window));
- memset(_w, '\0', sizeof (_Window));
+ memset(_w, 0, sizeof (_Window));
+ SdlTkX.nwtotal++;
} else {
SdlTkX.wfree = _w->next;
if (SdlTkX.wfree == NULL) {
SdlTkX.wtail = NULL;
}
+ SdlTkX.nwfree--;
}
_w->type = DT_WINDOW;
@@ -1380,8 +1382,6 @@ SdlTkDestroyWindow(Display *display, Window w)
SdlTkUnmapWindow(display, w);
}
- display->request++;
-
/* Destroy children recursively */
while (_w->child != NULL) {
SdlTkDestroyWindow(display, (Window) _w->child);
@@ -1423,6 +1423,7 @@ SdlTkDestroyWindow(Display *display, Window w)
SdlTkX.wtail->next = _w;
SdlTkX.wtail = _w;
}
+ SdlTkX.nwfree++;
/*
* Remove properties
@@ -1814,8 +1815,9 @@ SdlTkQueueEvent(XEvent *event)
qevent = display->qfree;
if (qevent == NULL) {
qevent = (_XSQEvent *) ckalloc(sizeof (_XSQEvent));
+ display->nqtotal++;
} else {
- display->qfree = display->qfree->next;
+ display->qfree = qevent->next;
}
qevent->event = *event;
qevent->next = NULL;
@@ -1832,8 +1834,18 @@ SdlTkQueueEvent(XEvent *event)
display->head = qevent;
trigger = 1;
}
+ /* Delay trigger for (Graphics)Expose with count greater zero */
+ if ((event->xany.type == Expose) && (event->xexpose.count > 0)) {
+ trigger = 0;
+ } else if ((event->xany.type == GraphicsExpose) &&
+ (event->xgraphicsexpose.count > 0)) {
+ trigger = 0;
+ }
display->tail = qevent;
display->qlen++;
+ if (display->qlen > display->qlenmax) {
+ display->qlenmax = display->qlen;
+ }
#ifdef _WIN32
if (trigger && ((HANDLE) display->fd != INVALID_HANDLE_VALUE)) {
@@ -2325,7 +2337,7 @@ XGetVisualInfo(Display *display, long vinfo_mask, XVisualInfo *vinfo_template,
{
XVisualInfo *info = (XVisualInfo *)ckalloc(sizeof (XVisualInfo));
- memset(info, '\0', sizeof (XVisualInfo));
+ memset(info, 0, sizeof (XVisualInfo));
info->visual = DefaultVisual(display, 0);
info->visualid = info->visual->visualid;
info->screen = 0;
@@ -3823,7 +3835,7 @@ void
SdlTkMoveWindow(Display *display, Window w, int x, int y)
{
_Window *_w = (_Window *) w;
- int ox, oy;
+ int ox = 0, oy = 0, flags;
if (_w->display == NULL) {
return;
@@ -3835,6 +3847,8 @@ SdlTkMoveWindow(Display *display, Window w, int x, int y)
return;
}
+ flags = VRC_CHANGED | VRC_DO_PARENT;
+
/*
* If the window has a decorative frame, move the decorative frame
* instead of the given window.
@@ -3843,15 +3857,21 @@ SdlTkMoveWindow(Display *display, Window w, int x, int y)
if ((_w->parent != NULL) && (_w->parent->dec != NULL)) {
_Window *wdec = _w->parent;
- ox = wdec->atts.x;
- oy = wdec->atts.y;
- wdec->atts.x = x;
- wdec->atts.y = y;
+ if ((x != wdec->atts.x) || (y != wdec->atts.y)) {
+ ox = wdec->atts.x;
+ oy = wdec->atts.y;
+ flags |= VRC_MOVE | VRC_EXPOSE;
+ wdec->atts.x = x;
+ wdec->atts.y = y;
+ }
} else {
- ox = _w->atts.x;
- oy = _w->atts.y;
- _w->atts.x = x;
- _w->atts.y = y;
+ if ((x != _w->atts.x) || (y != _w->atts.y)) {
+ ox = _w->atts.x;
+ oy = _w->atts.y;
+ flags |= VRC_MOVE | VRC_EXPOSE;
+ _w->atts.x = x;
+ _w->atts.y = y;
+ }
}
if (_w->atts.your_event_mask & StructureNotifyMask) {
@@ -3859,10 +3879,9 @@ SdlTkMoveWindow(Display *display, Window w, int x, int y)
}
if ((_w->parent != NULL) && (_w->parent->dec != NULL)) {
- SdlTkVisRgnChanged(_w->parent,
- VRC_CHANGED | VRC_DO_PARENT | VRC_MOVE, ox, oy);
+ SdlTkVisRgnChanged(_w->parent, flags, ox, oy);
} else {
- SdlTkVisRgnChanged(_w, VRC_CHANGED | VRC_DO_PARENT | VRC_MOVE, ox, oy);
+ SdlTkVisRgnChanged(_w, flags, ox, oy);
}
SdlTkScreenChanged();
@@ -3882,7 +3901,7 @@ SdlTkMoveResizeWindow(Display *display, Window w, int x, int y,
unsigned int width, unsigned int height)
{
_Window *_w = (_Window *) w;
- int ox = 0, oy = 0, flags = VRC_CHANGED | VRC_DO_PARENT;
+ int ox = 0, oy = 0, flags;
if (_w->display == NULL) {
return;
@@ -3901,6 +3920,8 @@ SdlTkMoveResizeWindow(Display *display, Window w, int x, int y,
height = 1;
}
+ flags = VRC_CHANGED | VRC_DO_PARENT;
+
/*
* If this window has a decorative frame, move the decorative frame,
* not the given window
@@ -3912,7 +3933,7 @@ SdlTkMoveResizeWindow(Display *display, Window w, int x, int y,
if ((x != wdec->atts.x) || (y != wdec->atts.y)) {
ox = wdec->atts.x;
oy = wdec->atts.y;
- flags |= VRC_MOVE;
+ flags |= VRC_MOVE | VRC_EXPOSE;
wdec->atts.x = x;
wdec->atts.y = y;
}
@@ -3932,7 +3953,7 @@ SdlTkMoveResizeWindow(Display *display, Window w, int x, int y,
if ((x != _w->atts.x) || (y != _w->atts.y)) {
ox = _w->atts.x;
oy = _w->atts.y;
- flags |= VRC_MOVE;
+ flags |= VRC_MOVE | VRC_EXPOSE;
_w->atts.x = x;
_w->atts.y = y;
}
@@ -3961,6 +3982,9 @@ SdlTkMoveResizeWindow(Display *display, Window w, int x, int y,
wdec->atts.height + 2 * wdec->atts.border_width;
}
+ if ((width > _w->atts.width) || (height > _w->atts.height)) {
+ flags |= VRC_EXPOSE;
+ }
_w->atts.width = width;
_w->atts.height = height;
@@ -4001,7 +4025,7 @@ int
XNextEvent(Display *display, XEvent *event_return)
{
_XSQEvent *qevent;
- int once = 1;
+ int n, once = 1;
again:
Tcl_MutexLock((Tcl_Mutex *) &display->qlock);
@@ -4013,7 +4037,6 @@ again:
if (display->fd >= 0) {
#ifdef HAVE_EVENTFD
long long buffer;
- int n;
n = read(display->fd, &buffer, sizeof (buffer));
if ((n < 0) && (errno != EWOULDBLOCK) && (errno != EAGAIN)) {
@@ -4022,7 +4045,6 @@ again:
}
#else
char buffer[64];
- int n;
for (;;) {
n = read(display->fd, buffer, sizeof (buffer));
@@ -4052,6 +4074,20 @@ again:
qevent->next = display->qfree;
display->qfree = qevent;
display->qlen--;
+ /* Shrink free list down to 4 times initial pre-allocated size */
+ n = 0;
+ while (display->nqtotal > 4 * 128) {
+ qevent = display->qfree;
+ if (qevent == NULL) {
+ break;
+ }
+ display->qfree = qevent->next;
+ display->nqtotal--;
+ ckfree((char *) qevent);
+ if (++n > 16) {
+ break;
+ }
+ }
} else {
Tcl_MutexUnlock((Tcl_Mutex *) &display->qlock);
if (once) {
@@ -5283,17 +5319,16 @@ ctxRetry:
/* From win/tkWinX.c TkpOpenDisplay */
display = (Display *) ckalloc(sizeof (Display));
- memset(display, '\0', sizeof (Display));
+ memset(display, 0, sizeof (Display));
display->display_name = NULL;
display->cursor_font = 1;
display->nscreens = 1;
display->request = 1;
- display->qlen = 0;
screen = (Screen *) ckalloc(sizeof (Screen));
- memset(screen, '\0', sizeof (Screen));
+ memset(screen, 0, sizeof (Screen));
screen->display = display;
screen->white_pixel = SDL_MapRGB(pfmt, 255, 255, 255);
@@ -5393,7 +5428,7 @@ ctxRetry:
screen->root_depth = pfmt->BitsPerPixel;
screen->root_visual = (Visual *) ckalloc(sizeof (Visual));
- memset(screen->root_visual, '\0', sizeof (Visual));
+ memset(screen->root_visual, 0, sizeof (Visual));
screen->root_visual->visualid = 0;
if (pfmt->palette != NULL) {
@@ -5483,6 +5518,7 @@ ctxRetry:
#else
display->fd = -1;
#endif
+ display->ext_number = -1;
SDL_EventState(SDL_JOYDEVICEADDED, SDL_ENABLE);
SDL_EventState(SDL_JOYDEVICEREMOVED, SDL_ENABLE);
SDL_EventState(SDL_JOYBALLMOTION, SDL_ENABLE);
@@ -5563,12 +5599,15 @@ ctxRetry:
/* Pre-allocate some events */
display->head = display->tail = NULL;
display->qfree = NULL;
+ display->qlen = display->qlenmax = 0;
+ display->nqtotal = 0;
for (i = 0; i < 128; i++) {
_XSQEvent *qevent = (_XSQEvent *) ckalloc(sizeof (_XSQEvent));
memset(qevent, 0, sizeof (_XSQEvent));
qevent->next = display->qfree;
display->qfree = qevent;
+ display->nqtotal++;
}
SdlTkX.draw_later &= ~(SDLTKX_SCALED | SDLTKX_RENDCLR);
@@ -5589,6 +5628,21 @@ ctxRetry:
SdlTkX.display = display;
SDL_EnableScreenSaver();
+
+ /* Pre-allocate some _Window structs */
+ for (i = 0; i < 128; i++) {
+ _w = (_Window *) ckalloc(sizeof (_Window));
+ memset(_w, 0, sizeof (_Window));
+ if (SdlTkX.wtail == NULL) {
+ SdlTkX.wtail = SdlTkX.wfree = _w;
+ } else {
+ SdlTkX.wtail->next = _w;
+ SdlTkX.wtail = _w;
+ }
+ SdlTkX.nwtotal++;
+ SdlTkX.nwfree++;
+ }
+
return 1;
}
@@ -5708,6 +5762,7 @@ EventThread(ClientData clientData)
qevent = next;
}
SdlTkX.display->head = SdlTkX.display->tail = NULL;
+ SdlTkX.display->qlen = 0;
Tcl_MutexUnlock((Tcl_Mutex *) &SdlTkX.display->qlock);
}
SDL_RemoveTimer(timerId);
@@ -5760,7 +5815,7 @@ XOpenDisplay(_Xconst char *display_name)
}
display = (Display *) ckalloc(sizeof (Display));
- memset(display, '\0', sizeof (Display));
+ memset(display, 0, sizeof (Display));
display->display_name = (char *) ckalloc(strlen(display_name)+1);
strcpy(display->display_name, display_name);
@@ -5803,12 +5858,15 @@ XOpenDisplay(_Xconst char *display_name)
/* Pre-allocate some events */
display->head = display->tail = NULL;
display->qfree = NULL;
+ display->qlen = display->qlenmax = 0;
+ display->nqtotal = 0;
for (i = 0; i < 128; i++) {
_XSQEvent *qevent = (_XSQEvent *) ckalloc(sizeof (_XSQEvent));
memset(qevent, 0, sizeof (_XSQEvent));
qevent->next = display->qfree;
display->qfree = qevent;
+ display->nqtotal++;
}
/* Inflate event queue mutex */
@@ -6148,6 +6206,7 @@ SdlTkResizeWindow(Display *display, Window w,
unsigned int width, unsigned int height)
{
_Window *_w = (_Window *) w;
+ int flags;
if (_w->display == NULL) {
return;
@@ -6166,6 +6225,8 @@ SdlTkResizeWindow(Display *display, Window w,
height = 1;
}
+ flags = VRC_CHANGED | VRC_DO_PARENT;
+
/* If this window has a decorative frame, resize it */
if ((_w->parent != NULL) && (_w->parent->dec != NULL)) {
_Window *wdec = _w->parent;
@@ -6183,6 +6244,9 @@ SdlTkResizeWindow(Display *display, Window w,
wdec->parentHeight = wdec->atts.height + 2 * wdec->atts.border_width;
}
+ if ((width > _w->atts.width) || (height > _w->atts.height)) {
+ flags |= VRC_EXPOSE;
+ }
_w->atts.width = width;
_w->atts.height = height;
@@ -6199,9 +6263,9 @@ SdlTkResizeWindow(Display *display, Window w,
}
if ((_w->parent != NULL) && (_w->parent->dec != NULL)) {
- SdlTkVisRgnChanged(_w->parent, VRC_CHANGED | VRC_DO_PARENT, 0, 0);
+ SdlTkVisRgnChanged(_w->parent, flags, 0, 0);
} else {
- SdlTkVisRgnChanged(_w, VRC_CHANGED | VRC_DO_PARENT, 0, 0);
+ SdlTkVisRgnChanged(_w, flags, 0, 0);
}
SdlTkScreenChanged();
diff --git a/sdl/tkSDLEvent.c b/sdl/tkSDLEvent.c
index 6e59dfb..e58668c 100644
--- a/sdl/tkSDLEvent.c
+++ b/sdl/tkSDLEvent.c
@@ -291,7 +291,9 @@ TransferXEventsToTcl(
while (numFound > 0) {
memset(&event, 0, sizeof(event));
XNextEvent(display, &event.x);
- Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);
+ if (event.type != PointerUpdate) {
+ Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL);
+ }
numFound--;
}
}
diff --git a/tests/text.test b/tests/text.test
index 9c60925..10fb75f 100644
--- a/tests/text.test
+++ b/tests/text.test
@@ -3673,10 +3673,9 @@ Line 4"
list [.t tag ranges sel] [.t get 1.0 end]
} -cleanup {
destroy .t
-} -result {{1.0 4.0} {Line 1
+} -result {{1.0 3.5} {Line 1
abcde
12345
-
}}
test text-19.9 {DeleteChars procedure} -body {
text .t
diff --git a/tests/textDisp.test b/tests/textDisp.test
index e98f97b..ebaa6d8 100644
--- a/tests/textDisp.test
+++ b/tests/textDisp.test
@@ -657,7 +657,7 @@ test textDisp-4.9 {UpdateDisplayInfo, filling in extra vertical space} {textfont
update
.t delete 15.0 end
list [.t bbox 7.0] [.t bbox 12.0]
-} [list [list [expr {$hlth + $px + $bw}] [expr {$hlth + $py + $bw + $fixedHeight}] $fixedWidth $fixedHeight] [list [expr {$hlth + $px + $bw}] [expr {$hlth + $py + $bw + 6 * $fixedHeight}] $fixedWidth $fixedHeight]]
+} [list [list [expr {$hlth + $px + $bw}] [expr {$hlth + $py + $bw + 2 * $fixedHeight}] $fixedWidth $fixedHeight] [list [expr {$hlth + $px + $bw}] [expr {$hlth + $py + $bw + 7 * $fixedHeight}] $fixedWidth $fixedHeight]]
test textDisp-4.10 {UpdateDisplayInfo, filling in extra vertical space} {
.t delete 1.0 end
.t insert end "1\n2\n3\n4\n5\nLine 6 is such a long line that it wraps around.\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
@@ -666,7 +666,7 @@ test textDisp-4.10 {UpdateDisplayInfo, filling in extra vertical space} {
.t delete 13.0 end
update
list [.t index @0,0] $tk_textRelayout $tk_textRedraw
-} {6.0 {13.0 7.0 6.40 6.20 6.0} {6.0 6.20 6.40 7.0 13.0}}
+} {5.0 {12.0 7.0 6.40 6.20 6.0 5.0} {5.0 6.0 6.20 6.40 7.0 12.0}}
test textDisp-4.11 {UpdateDisplayInfo, filling in extra vertical space} {
.t delete 1.0 end
.t insert end "1\n2\n3\n4\n5\nLine 6 is such a long line that it wraps around, not once but really quite a few times.\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
@@ -675,7 +675,7 @@ test textDisp-4.11 {UpdateDisplayInfo, filling in extra vertical space} {
.t delete 14.0 end
update
list [.t index @0,0] $tk_textRelayout $tk_textRedraw
-} {6.60 {14.0 7.0 6.80 6.60} {6.60 6.80 7.0 14.0}}
+} {6.40 {13.0 7.0 6.80 6.60 6.40} {6.40 6.60 6.80 7.0 13.0}}
test textDisp-4.12 {UpdateDisplayInfo, filling in extra vertical space} {
.t delete 1.0 end
.t insert end "1\n2\n3\n4\n5\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16"
@@ -3697,7 +3697,7 @@ test textDisp-28.1 {"yview" option with bizarre scroll command} {
set result [.t2.t index @0,0]
update
lappend result [.t2.t index @0,0]
-} {6.0 2.0}
+} {6.0 1.0}
test textDisp-29.1 {miscellaneous: lines wrap but are still too long} {textfonts} {
catch {destroy .t2}
diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c
index 180d4f5..41a11bd 100644
--- a/win/tkWinMenu.c
+++ b/win/tkWinMenu.c
@@ -1295,7 +1295,17 @@ TkWinHandleMenuEvent(
if (menuPtr != NULL) {
long entryIndex = LOWORD(*pwParam);
- mePtr = NULL;
+ if ((menuPtr->menuType == MENUBAR) && menuPtr->tearoff) {
+ /*
+ * Windows passes the entry index starting at 0 for
+ * the first menu entry. However this entry #0 is the
+ * tearoff entry for Tk (the menu has -tearoff 1),
+ * which is ignored for MENUBAR menues on Windows.
+ */
+
+ entryIndex++;
+ }
+ mePtr = NULL;
if (flags != 0xFFFF) {
if ((flags&MF_POPUP) && (entryIndex<menuPtr->numEntries)) {
mePtr = menuPtr->entries[entryIndex];
diff --git a/xlib/X11/Xlib.h b/xlib/X11/Xlib.h
index ca5e74c..52a92a0 100644
--- a/xlib/X11/Xlib.h
+++ b/xlib/X11/Xlib.h
@@ -543,6 +543,7 @@ typedef struct _XDisplay {
void *gl_rend;
void *agg2d;
unsigned char agg2d_dummyfb[32];
+ int qlenmax, nqtotal;
void *qlock; /* Tcl_Mutex */
#endif
} Display;