diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2016-03-30 07:38:04 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2016-03-30 07:38:04 (GMT) |
commit | b4f99cb2ddffc2639186270b87d2ff9d85c23088 (patch) | |
tree | a2e933a9bd65cffc72a95b4dc6210d3295c48859 | |
parent | 81f9316af362e614d73f055fed1dd87f736c55bb (diff) | |
parent | 32ed623c6a6ea47b434caae5452486b9ed93e197 (diff) | |
download | tk-b4f99cb2ddffc2639186270b87d2ff9d85c23088.zip tk-b4f99cb2ddffc2639186270b87d2ff9d85c23088.tar.gz tk-b4f99cb2ddffc2639186270b87d2ff9d85c23088.tar.bz2 |
merge core-8-6-branch
-rw-r--r-- | doc/text.n | 40 | ||||
-rw-r--r-- | generic/tkText.c | 19 | ||||
-rw-r--r-- | library/entry.tcl | 10 | ||||
-rw-r--r-- | library/spinbox.tcl | 10 | ||||
-rw-r--r-- | library/text.tcl | 10 | ||||
-rw-r--r-- | library/ttk/entry.tcl | 10 | ||||
-rw-r--r-- | sdl/SdlTkInt.c | 117 | ||||
-rw-r--r-- | sdl/SdlTkInt.h | 2 | ||||
-rw-r--r-- | sdl/SdlTkUtils.c | 22 | ||||
-rw-r--r-- | sdl/SdlTkX.c | 132 | ||||
-rw-r--r-- | sdl/tkSDLEvent.c | 4 | ||||
-rw-r--r-- | tests/text.test | 3 | ||||
-rw-r--r-- | tests/textDisp.test | 8 | ||||
-rw-r--r-- | win/tkWinMenu.c | 12 | ||||
-rw-r--r-- | xlib/X11/Xlib.h | 1 |
15 files changed, 291 insertions, 109 deletions
@@ -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; |