diff options
author | fvogel <fvogelnew1@free.fr> | 2022-04-03 10:43:56 (GMT) |
---|---|---|
committer | fvogel <fvogelnew1@free.fr> | 2022-04-03 10:43:56 (GMT) |
commit | b1f5acd445e52aadf8ad909c78535aeaab0f60fe (patch) | |
tree | 02ff54d16a18a86049984d6ae5ed1f4c30c16725 | |
parent | 4d7dd5c1d1a545bed4de7e4b6627e1302796b0f0 (diff) | |
parent | febcba8fc330403fb595f58acc3570f3d29fe1ed (diff) | |
download | tk-b1f5acd445e52aadf8ad909c78535aeaab0f60fe.zip tk-b1f5acd445e52aadf8ad909c78535aeaab0f60fe.tar.gz tk-b1f5acd445e52aadf8ad909c78535aeaab0f60fe.tar.bz2 |
merge 8.6
61 files changed, 1073 insertions, 441 deletions
diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 2600858..629efdf 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -106,7 +106,7 @@ jobs: - name: Configure (symbols=${{ matrix.symbols }} ${{matrix.options }}) # Note that macOS is always a 64 bit platform run: | - ./configure --enable-64bit ${CFGOPT} "--prefix=$HOME/install dir" || { + ./configure --enable-64bit ${CFGOPT} "--prefix=$HOME/install dir" --disable-xft || { cat config.log echo "::error::Failure during Configure" exit 1 diff --git a/doc/SetOptions.3 b/doc/SetOptions.3 index a35522f..b77f8d0 100644 --- a/doc/SetOptions.3 +++ b/doc/SetOptions.3 @@ -429,8 +429,8 @@ internal representation is set to zero. The value must be standard relief such as \fBraised\fR. The internal form is an integer relief value such as \fBTK_RELIEF_RAISED\fR. This option type supports the \fBTK_OPTION_NULL_OK\fR -flag; if the empty string is specified as the value for the option, -the integer relief value is set to \fBTK_RELIEF_NULL\fR. +flag; if a NULL value is set, the internal representation is set to +\fBTK_RELIEF_NULL\fR. .TP \fBTK_OPTION_STRING\fR The value may be any string. The internal form is a (char *) pointer @@ -847,6 +847,9 @@ characters in the text. .IP [4] Whenever the \fBsel\fR tag range changes a virtual event \fB<<Selection>>\fR is generated. +It might also be generated when selection is affected but not actually changed. +Further, multiple selection changes could happen before events can be processed +leading to multiple events with the same visible selection. .PP The \fBsel\fR tag is automatically defined when a text widget is created, and it may not be deleted with the diff --git a/doc/ttk_style.n b/doc/ttk_style.n index 5d7b5d1..f4ff6a7 100644 --- a/doc/ttk_style.n +++ b/doc/ttk_style.n @@ -15,7 +15,7 @@ ttk::style \- Manipulate style database .SH NOTES .PP See also the Tcl'2004 conference presentation, -available at https://tktable.sourceforge.net/tile/tile-tcl2004.pdf +available at http://tktable.sourceforge.net/tile/tile-tcl2004.pdf .SH DEFINITIONS .PP Each widget is assigned a \fIstyle\fR, diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n index 2deb5b5..8494dad 100644 --- a/doc/ttk_treeview.n +++ b/doc/ttk_treeview.n @@ -472,6 +472,9 @@ Again, \fBcolumn #0 always refers to the tree column\fR. The treeview widget generates the following virtual events. .IP <<TreeviewSelect>> Generated whenever the selection changes. +It might also be generated when selection is affected but not actually changed. +Further, multiple selection changes could happen before events can be processed +leading to multiple events with the same visible selection. .IP <<TreeviewOpen>> Generated just before setting the focus item to \fB\-open true\fR. .IP <<TreeviewClose>> diff --git a/generic/tk.decls b/generic/tk.decls index 77cad19..2ade6a1 100644 --- a/generic/tk.decls +++ b/generic/tk.decls @@ -1068,7 +1068,7 @@ declare 272 { declare 273 { void Tk_CreateOldPhotoImageFormat(const Tk_PhotoImageFormat *formatPtr) } -declare 280 { +declare 290 { void TkUnusedStubEntry(void) } diff --git a/generic/tkBind.c b/generic/tkBind.c index 7873d29..e8db70b 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -332,7 +332,7 @@ typedef struct PatSeq { /* * Constants that define how close together two events must be in milliseconds - * or pixels to meet the PAT_NEARBY constraint: + * or pixels to be considered close in space or time. */ #define NEARBY_PIXELS 5 diff --git a/generic/tkCanvPs.c b/generic/tkCanvPs.c index 1a8b3d3..fc3a772 100644 --- a/generic/tkCanvPs.c +++ b/generic/tkCanvPs.c @@ -904,6 +904,18 @@ PostscriptBitmap( imagePtr = XGetImage(Tk_Display(tkwin), bitmap, 0, 0, totalWidth, totalHeight, 1, XYPixmap); + + if (!imagePtr) { + /* + * The XGetImage() function is apparently not implemented on this + * system. Just skip the pixels, the Postscript will still be + * syntactically correct. + */ + + Tcl_AppendToObj(psObj, "<>", -1); + return; + } + Tcl_AppendToObj(psObj, "<", -1); mask = 0x80; value = 0; diff --git a/generic/tkCanvText.c b/generic/tkCanvText.c index 656c421..c0783ad 100644 --- a/generic/tkCanvText.c +++ b/generic/tkCanvText.c @@ -629,7 +629,7 @@ ComputeTextBbox( TextItem *textPtr) /* Item whose bbox is to be recomputed. */ { Tk_CanvasTextInfo *textInfoPtr; - int leftX, topY, width, height, fudge, i; + int width, height, fudge, i; Tk_State state = textPtr->header.state; double x[4], y[4], dx[4], dy[4], sinA, cosA, tmp; @@ -651,8 +651,6 @@ ComputeTextBbox( * bounding box for the text item. */ - leftX = ROUND(textPtr->x); - topY = ROUND(textPtr->y); for (i=0 ; i<4 ; i++) { dx[i] = dy[i] = 0.0; } @@ -662,23 +660,19 @@ ComputeTextBbox( case TK_ANCHOR_NE: break; - case TK_ANCHOR_W: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_E: - topY -= height / 2; - for (i=0 ; i<4 ; i++) { - dy[i] = -height / 2; - } - break; - case TK_ANCHOR_SW: case TK_ANCHOR_S: case TK_ANCHOR_SE: - topY -= height; for (i=0 ; i<4 ; i++) { dy[i] = -height; } break; + + default: + for (i=0 ; i<4 ; i++) { + dy[i] = -height / 2; + } + break; } switch (textPtr->anchor) { case TK_ANCHOR_NW: @@ -686,23 +680,19 @@ ComputeTextBbox( case TK_ANCHOR_SW: break; - case TK_ANCHOR_N: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_S: - leftX -= width / 2; - for (i=0 ; i<4 ; i++) { - dx[i] = -width / 2; - } - break; - case TK_ANCHOR_NE: case TK_ANCHOR_E: case TK_ANCHOR_SE: - leftX -= width; for (i=0 ; i<4 ; i++) { dx[i] = -width; } break; + + default: + for (i=0 ; i<4 ; i++) { + dx[i] = -width / 2; + } + break; } textPtr->actualWidth = width; @@ -1608,6 +1598,7 @@ TextToPostscript( } switch (textPtr->anchor) { + case TK_ANCHOR_NW: x = 0; y = 0; break; case TK_ANCHOR_N: x = 1; y = 0; break; case TK_ANCHOR_NE: x = 2; y = 0; break; case TK_ANCHOR_E: x = 2; y = 1; break; @@ -1615,8 +1606,7 @@ TextToPostscript( case TK_ANCHOR_S: x = 1; y = 2; break; case TK_ANCHOR_SW: x = 0; y = 2; break; case TK_ANCHOR_W: x = 0; y = 1; break; - case TK_ANCHOR_CENTER: x = 1; y = 1; break; - default: x = 0; y = 0; break; + default: x = 1; y = 1; break; } switch (textPtr->justify) { case TK_JUSTIFY_CENTER: justify = "0.5"; break; diff --git a/generic/tkCanvWind.c b/generic/tkCanvWind.c index 4047b0f..a041589 100644 --- a/generic/tkCanvWind.c +++ b/generic/tkCanvWind.c @@ -571,6 +571,9 @@ DisplayWinItem( if (winItemPtr->tkwin == NULL) { return; } + + Tcl_Preserve(canvas); + if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } @@ -585,6 +588,7 @@ DisplayWinItem( } else { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } + Tcl_Release(canvas); return; } Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1, @@ -606,6 +610,7 @@ DisplayWinItem( } else { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } + Tcl_Release(canvas); return; } @@ -620,11 +625,16 @@ DisplayWinItem( || (height != Tk_Height(winItemPtr->tkwin))) { Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height); } - Tk_MapWindow(winItemPtr->tkwin); + + if (winItemPtr->tkwin) { + Tk_MapWindow(winItemPtr->tkwin); + } + } else { Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y, width, height); } + Tcl_Release(canvas); } /* diff --git a/generic/tkDecls.h b/generic/tkDecls.h index 56af6d3..6663d16 100644 --- a/generic/tkDecls.h +++ b/generic/tkDecls.h @@ -870,7 +870,17 @@ EXTERN void Tk_CreateOldPhotoImageFormat( /* Slot 277 is reserved */ /* Slot 278 is reserved */ /* Slot 279 is reserved */ -/* 280 */ +/* Slot 280 is reserved */ +/* Slot 281 is reserved */ +/* Slot 282 is reserved */ +/* Slot 283 is reserved */ +/* Slot 284 is reserved */ +/* Slot 285 is reserved */ +/* Slot 286 is reserved */ +/* Slot 287 is reserved */ +/* Slot 288 is reserved */ +/* Slot 289 is reserved */ +/* 290 */ EXTERN void TkUnusedStubEntry(void); typedef struct { @@ -1164,7 +1174,17 @@ typedef struct TkStubs { void (*reserved277)(void); void (*reserved278)(void); void (*reserved279)(void); - void (*tkUnusedStubEntry) (void); /* 280 */ + void (*reserved280)(void); + void (*reserved281)(void); + void (*reserved282)(void); + void (*reserved283)(void); + void (*reserved284)(void); + void (*reserved285)(void); + void (*reserved286)(void); + void (*reserved287)(void); + void (*reserved288)(void); + void (*reserved289)(void); + void (*tkUnusedStubEntry) (void); /* 290 */ } TkStubs; extern const TkStubs *tkStubsPtr; @@ -1731,8 +1751,18 @@ extern const TkStubs *tkStubsPtr; /* Slot 277 is reserved */ /* Slot 278 is reserved */ /* Slot 279 is reserved */ +/* Slot 280 is reserved */ +/* Slot 281 is reserved */ +/* Slot 282 is reserved */ +/* Slot 283 is reserved */ +/* Slot 284 is reserved */ +/* Slot 285 is reserved */ +/* Slot 286 is reserved */ +/* Slot 287 is reserved */ +/* Slot 288 is reserved */ +/* Slot 289 is reserved */ #define TkUnusedStubEntry \ - (tkStubsPtr->tkUnusedStubEntry) /* 280 */ + (tkStubsPtr->tkUnusedStubEntry) /* 290 */ #endif /* defined(USE_TK_STUBS) */ diff --git a/generic/tkFocus.c b/generic/tkFocus.c index 9b3b2dc..9bf31d4 100644 --- a/generic/tkFocus.c +++ b/generic/tkFocus.c @@ -813,6 +813,7 @@ TkFocusDeadWindow( ToplevelFocusInfo *tlFocusPtr, *prevPtr; DisplayFocusInfo *displayFocusPtr; TkDisplay *dispPtr = winPtr->dispPtr; + int noMatch = 1; /* * Certain special windows like those used for send and clipboard have no @@ -856,6 +857,7 @@ TkFocusDeadWindow( prevPtr->nextPtr = tlFocusPtr->nextPtr; } ckfree(tlFocusPtr); + noMatch = 0; break; } else if (winPtr == tlFocusPtr->focusWinPtr) { /* @@ -873,6 +875,7 @@ TkFocusDeadWindow( displayFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr; dispPtr->focusPtr = tlFocusPtr->topLevelPtr; } + noMatch = 0; break; } } @@ -890,6 +893,15 @@ TkFocusDeadWindow( if (displayFocusPtr->focusOnMapPtr == winPtr) { displayFocusPtr->focusOnMapPtr = NULL; } + + /* + * It may happen that the search above for focus records that refer + * to this window did not find any match. In such a case, when the + * dead window had the focus, release it. + */ + if (noMatch && (dispPtr->focusPtr == winPtr)) { + dispPtr->focusPtr = NULL; + } } /* diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 785bc7f..ac6b59b 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -2811,6 +2811,9 @@ DestroyGrid( { Gridder *gridPtr = (Gridder *)memPtr; + if (gridPtr->flags & REQUESTED_RELAYOUT) { + Tcl_CancelIdleCall(ArrangeGrid, gridPtr); + } if (gridPtr->containerDataPtr != NULL) { if (gridPtr->containerDataPtr->rowPtr != NULL) { ckfree(gridPtr->containerDataPtr -> rowPtr); diff --git a/generic/tkImgPNG.c b/generic/tkImgPNG.c index 03bb4f8..86e2748 100644 --- a/generic/tkImgPNG.c +++ b/generic/tkImgPNG.c @@ -12,8 +12,8 @@ #include "tkInt.h" -#define PNG_INT32(a,b,c,d) \ - (((long)(a) << 24) | ((long)(b) << 16) | ((long)(c) << 8) | (long)(d)) +#define PNG_UINT32(a,b,c,d) \ + (((unsigned long)(a) << 24) | ((unsigned long)(b) << 16) | ((unsigned long)(c) << 8) | (unsigned long)(d)) #define PNG_BLOCK_SZ 1024 /* Process up to 1k at a time. */ #define PNG_MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -45,35 +45,35 @@ static const int startLine[8] = { * are officially deprecated). */ -#define CHUNK_IDAT PNG_INT32('I','D','A','T') /* Pixel data. */ -#define CHUNK_IEND PNG_INT32('I','E','N','D') /* End of Image. */ -#define CHUNK_IHDR PNG_INT32('I','H','D','R') /* Header. */ -#define CHUNK_PLTE PNG_INT32('P','L','T','E') /* Palette. */ - -#define CHUNK_bKGD PNG_INT32('b','K','G','D') /* Background Color */ -#define CHUNK_cHRM PNG_INT32('c','H','R','M') /* Chroma values. */ -#define CHUNK_gAMA PNG_INT32('g','A','M','A') /* Gamma. */ -#define CHUNK_hIST PNG_INT32('h','I','S','T') /* Histogram. */ -#define CHUNK_iCCP PNG_INT32('i','C','C','P') /* Color profile. */ -#define CHUNK_iTXt PNG_INT32('i','T','X','t') /* Internationalized +#define CHUNK_IDAT PNG_UINT32('I','D','A','T') /* Pixel data. */ +#define CHUNK_IEND PNG_UINT32('I','E','N','D') /* End of Image. */ +#define CHUNK_IHDR PNG_UINT32('I','H','D','R') /* Header. */ +#define CHUNK_PLTE PNG_UINT32('P','L','T','E') /* Palette. */ + +#define CHUNK_bKGD PNG_UINT32('b','K','G','D') /* Background Color */ +#define CHUNK_cHRM PNG_UINT32('c','H','R','M') /* Chroma values. */ +#define CHUNK_gAMA PNG_UINT32('g','A','M','A') /* Gamma. */ +#define CHUNK_hIST PNG_UINT32('h','I','S','T') /* Histogram. */ +#define CHUNK_iCCP PNG_UINT32('i','C','C','P') /* Color profile. */ +#define CHUNK_iTXt PNG_UINT32('i','T','X','t') /* Internationalized * text (comments, * etc.) */ -#define CHUNK_oFFs PNG_INT32('o','F','F','s') /* Image offset. */ -#define CHUNK_pCAL PNG_INT32('p','C','A','L') /* Pixel calibration +#define CHUNK_oFFs PNG_UINT32('o','F','F','s') /* Image offset. */ +#define CHUNK_pCAL PNG_UINT32('p','C','A','L') /* Pixel calibration * data. */ -#define CHUNK_pHYs PNG_INT32('p','H','Y','s') /* Physical pixel +#define CHUNK_pHYs PNG_UINT32('p','H','Y','s') /* Physical pixel * dimensions. */ -#define CHUNK_sBIT PNG_INT32('s','B','I','T') /* Significant bits */ -#define CHUNK_sCAL PNG_INT32('s','C','A','L') /* Physical scale. */ -#define CHUNK_sPLT PNG_INT32('s','P','L','T') /* Suggested +#define CHUNK_sBIT PNG_UINT32('s','B','I','T') /* Significant bits */ +#define CHUNK_sCAL PNG_UINT32('s','C','A','L') /* Physical scale. */ +#define CHUNK_sPLT PNG_UINT32('s','P','L','T') /* Suggested * palette. */ -#define CHUNK_sRGB PNG_INT32('s','R','G','B') /* Standard RGB space +#define CHUNK_sRGB PNG_UINT32('s','R','G','B') /* Standard RGB space * declaration. */ -#define CHUNK_tEXt PNG_INT32('t','E','X','t') /* Plain Latin-1 +#define CHUNK_tEXt PNG_UINT32('t','E','X','t') /* Plain Latin-1 * text. */ -#define CHUNK_tIME PNG_INT32('t','I','M','E') /* Time stamp. */ -#define CHUNK_tRNS PNG_INT32('t','R','N','S') /* Transparency. */ -#define CHUNK_zTXt PNG_INT32('z','T','X','t') /* Compressed Latin-1 +#define CHUNK_tIME PNG_UINT32('t','I','M','E') /* Time stamp. */ +#define CHUNK_tRNS PNG_UINT32('t','R','N','S') /* Transparency. */ +#define CHUNK_zTXt PNG_UINT32('z','T','X','t') /* Compressed Latin-1 * text. */ /* @@ -694,7 +694,7 @@ ReadInt32( return TCL_ERROR; } - *resultPtr = PNG_INT32(p[0], p[1], p[2], p[3]); + *resultPtr = PNG_UINT32(p[0], p[1], p[2], p[3]); return TCL_OK; } @@ -886,7 +886,7 @@ ReadChunkHeader( return TCL_ERROR; } - temp = PNG_INT32(pc[0], pc[1], pc[2], pc[3]); + temp = PNG_UINT32(pc[0], pc[1], pc[2], pc[3]); if (temp > INT_MAX) { Tcl_SetObjResult(interp, Tcl_NewStringObj( @@ -911,7 +911,7 @@ ReadChunkHeader( * Convert it to a host-order integer for simple comparison. */ - chunkType = PNG_INT32(pc[0], pc[1], pc[2], pc[3]); + chunkType = PNG_UINT32(pc[0], pc[1], pc[2], pc[3]); /* * Check to see if this is a known/supported chunk type. Note that the @@ -976,7 +976,7 @@ ReadChunkHeader( */ if (!(chunkType & PNG_CF_ANCILLARY)) { - if (chunkType & PNG_INT32(128,128,128,128)) { + if (chunkType & PNG_UINT32(128,128,128,128)) { /* * No nice ASCII conversion; shouldn't happen either, but * we'll be doubly careful. diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 95350f4..d385a7c 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -3616,8 +3616,10 @@ Tk_PhotoBlank( * arrays for each instance. */ - memset(modelPtr->pix32, 0, - ((size_t)modelPtr->width * modelPtr->height * 4)); + if (modelPtr->pix32) { + memset(modelPtr->pix32, 0, + ((size_t)modelPtr->width * modelPtr->height * 4)); + } for (instancePtr = modelPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { TkImgResetDither(instancePtr); diff --git a/generic/tkInt.h b/generic/tkInt.h index fe8f16e..21df17d 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -368,8 +368,14 @@ typedef struct TkDisplay { * by that container. */ int geomInit; -#define TkGetContainer(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ - ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr) + /* + * Information used by tkGrid.c, tkPack.c, tkPlace.c, tkPointer.c, + * and ttkMacOSXTheme.c: + */ + +#define TkGetContainer(tkwin) (Tk_TopWinHierarchy((TkWindow *)tkwin) ? NULL : \ + (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ + ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr)) /* * Information used by tkGet.c only: diff --git a/generic/tkMain.c b/generic/tkMain.c index 953a54f..2dd1095 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -25,11 +25,10 @@ extern int TkCygwinMainEx(int, char **, Tcl_AppInitProc *, Tcl_Interp *); static const char DEFAULT_PRIMARY_PROMPT[] = "% "; /* - * This file can be compiled on Windows in UNICODE mode, as well as - * on all other platforms using the native encoding. This is done - * by using the normal Windows functions like _tcscmp, but on - * platforms which don't have <tchar.h> we have to translate that - * to strcmp here. + * This file can be compiled on Windows in UNICODE mode, as well as on all + * other platforms using the native encoding. This is done by using the normal + * Windows functions like _tcscmp, but on platforms which don't have <tchar.h> + * we have to translate that to strcmp here. */ #ifdef _WIN32 #ifdef __cplusplus @@ -72,7 +71,7 @@ NewNativeObj( Tcl_DStringInit(&ds); Tcl_WCharToUtfDString(string, wcslen(string), &ds); #else - Tcl_ExternalToUtfDString(NULL, (char *) string, -1, &ds); + Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds); #endif obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); Tcl_DStringFree(&ds); @@ -118,7 +117,7 @@ static int WinIsTty(int fd) { extern int isatty(int fd); #endif -typedef struct InteractiveState { +typedef struct { Tcl_Channel input; /* The standard input channel from which lines * are read. */ int tty; /* Non-zero means standard input is a @@ -251,19 +250,19 @@ Tk_MainEx( */ if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1])) - && (TEXT('-') != argv[3][0])) { + && ('-' != argv[3][0])) { Tcl_Obj *value = NewNativeObj(argv[2]); Tcl_SetStartupScript(NewNativeObj(argv[3]), Tcl_GetString(value)); Tcl_DecrRefCount(value); argc -= 3; argv += 3; - } else if ((argc > 1) && (TEXT('-') != argv[1][0])) { + } else if ((argc > 1) && ('-' != argv[1][0])) { Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL); argc--; argv++; } else if ((argc > 2) && (length = _tcslen(argv[1])) && (length > 1) && (0 == _tcsncmp(TEXT("-file"), argv[1], length)) - && (TEXT('-') != argv[2][0])) { + && ('-' != argv[2][0])) { Tcl_SetStartupScript(NewNativeObj(argv[2]), NULL); argc -= 2; argv += 2; @@ -407,15 +406,15 @@ StdinProc( { char *cmd; int code; - int count; + int length; InteractiveState *isPtr = (InteractiveState *)clientData; Tcl_Channel chan = isPtr->input; Tcl_Interp *interp = isPtr->interp; (void)mask; - count = Tcl_Gets(chan, &isPtr->line); + length = Tcl_Gets(chan, &isPtr->line); - if ((count == -1) && !isPtr->gotPartial) { + if ((length < 0) && !isPtr->gotPartial) { if (isPtr->tty) { Tcl_Exit(0); } else { diff --git a/generic/tkPack.c b/generic/tkPack.c index 67267e7..126bb68 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -1394,6 +1394,9 @@ DestroyPacker( { Packer *packPtr = (Packer *)memPtr; + if (packPtr->flags & REQUESTED_REPACK) { + Tcl_CancelIdleCall(ArrangePacking, packPtr); + } ckfree(packPtr); } diff --git a/generic/tkPlace.c b/generic/tkPlace.c index 47ceee2..3212a58 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -426,6 +426,9 @@ static void FreeContent( Content *contentPtr) { + if (contentPtr->containerPtr && (contentPtr->containerPtr->flags & PARENT_RECONFIG_PENDING)) { + Tcl_CancelIdleCall(RecomputePlacement, contentPtr->containerPtr); + } Tk_FreeConfigOptions((char *) contentPtr, contentPtr->optionTable, contentPtr->tkwin); ckfree(contentPtr); diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index ef418e7..8d3588a 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -1334,7 +1334,17 @@ const TkStubs tkStubs = { 0, /* 277 */ 0, /* 278 */ 0, /* 279 */ - TkUnusedStubEntry, /* 280 */ + 0, /* 280 */ + 0, /* 281 */ + 0, /* 282 */ + 0, /* 283 */ + 0, /* 284 */ + 0, /* 285 */ + 0, /* 286 */ + 0, /* 287 */ + 0, /* 288 */ + 0, /* 289 */ + TkUnusedStubEntry, /* 290 */ }; /* !END!: Do not edit above this line. */ diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 6645912..cf1cb1b 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -2566,6 +2566,13 @@ DisplayDLine( display, pixmap, dlPtr->y + dlPtr->spaceAbove); } + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { + /* + * A displayProc called in the loop above invoked a binding + * that caused the widget to be deleted. Don't do anything. + */ + return; + } if (dInfoPtr->dLinesInvalidated) { return; } @@ -4221,7 +4228,7 @@ DisplayText( /* * Choose a new current item if that is needed (this could cause event - * handlers to be invoked, hence the preserve/release calls and the loop, + * handlers to be invoked, hence the refcount management and the loop, * since the handlers could conceivably necessitate yet another current * item calculation). The tkwin check is because the whole window could go * away in the Tcl_Release call. @@ -4500,11 +4507,18 @@ DisplayText( LOG("tk_textRedraw", string); } DisplayDLine(textPtr, dlPtr, prevPtr, pixmap); + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { + /* + * DisplayDLine called a displayProc which invoked a binding + * that caused the widget to be deleted. Don't do anything. + */ + goto end; + } if (dInfoPtr->dLinesInvalidated) { #ifndef TK_NO_DOUBLE_BUFFERING Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap); #endif /* TK_NO_DOUBLE_BUFFERING */ - return; + goto end; } dlPtr->oldY = dlPtr->y; dlPtr->flags &= ~(NEW_LAYOUT | OLD_Y_INVALID); diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c index bd15cc9..46f84b0 100644 --- a/generic/tkTextWind.c +++ b/generic/tkTextWind.c @@ -526,7 +526,6 @@ EmbWinStructureProc( { TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData; TkTextSegment *ewPtr = client->parent; - TkTextIndex index; Tcl_HashEntry *hPtr; if (eventPtr->type != DestroyNotify) { @@ -545,12 +544,7 @@ EmbWinStructureProc( ewPtr->body.ew.tkwin = NULL; client->tkwin = NULL; - index.tree = ewPtr->body.ew.sharedTextPtr->tree; - index.linePtr = ewPtr->body.ew.linePtr; - index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr); - TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index); - TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL, - index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); + EmbWinRequestProc(client, NULL); } /* @@ -574,7 +568,7 @@ EmbWinStructureProc( static void EmbWinRequestProc( ClientData clientData, /* Pointer to record for window item. */ - TCL_UNUSED(Tk_Window)) /* Window that changed its desired size. */ + TCL_UNUSED(Tk_Window)) /* Window that changed its desired size. */ { TkTextEmbWindowClient *client = (TkTextEmbWindowClient *)clientData; TkTextSegment *ewPtr = client->parent; @@ -582,7 +576,15 @@ EmbWinRequestProc( index.tree = ewPtr->body.ew.sharedTextPtr->tree; index.linePtr = ewPtr->body.ew.linePtr; - index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr); + + /* + * ewPtr->body.ew.tkwin == NULL means the embedded window is already + * destroyed. The ewPtr segment is no longer linked, TkTextSegToOffset + * cannot find it within the line pointed by ewPtr->body.ew.linePtr. + */ + + index.byteIndex = ewPtr->body.ew.tkwin ? + TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr) : 0; TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index); TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL, index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); @@ -1129,6 +1131,16 @@ TkTextEmbWinDisplayProc( &lineX, &windowY, &width, &height); windowX = lineX - chunkPtr->x + x; + /* + * Mark the window as displayed so that it won't get unmapped. + * This needs to be done before the next instruction block because + * Tk_MaintainGeometry/Tk_MapWindow will run event handlers, in + * particular for the <Map> event, and if the bound script deletes + * the embedded window its clients will get freed. + */ + + client->displayed = 1; + if (textPtr->tkwin == Tk_Parent(tkwin)) { if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin)) || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin)) @@ -1140,16 +1152,6 @@ TkTextEmbWinDisplayProc( Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY, width, height); } - - /* - * Mark the window as displayed so that it won't get unmapped. - * <TODO>: Tk_MaintainGeometry/Tk_MapWindow may run event handlers, - * in particular for the <Map> event. If the bound script - * deletes the embedded window or the text widget we will - * soon crash. - */ - - client->displayed = 1; } /* diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index 1d8137b..025a0f6 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -143,12 +143,12 @@ typedef struct { /* * Default option values: */ -#define DEF_SELECT_BG "#000000" -#define DEF_SELECT_FG "#ffffff" -#define DEF_INSERT_BG "black" -#define DEF_ENTRY_WIDTH "20" -#define DEF_ENTRY_FONT "TkTextFont" -#define DEF_LIST_HEIGHT "10" +#define DEF_SELECT_BG "#000000" +#define DEF_SELECT_FG "#FFFFFF" +#define DEF_INSERT_BG "black" +#define DEF_ENTRY_WIDTH "20" +#define DEF_ENTRY_FONT "TkTextFont" +#define DEF_LIST_HEIGHT "10" static Tk_OptionSpec EntryOptionSpecs[] = { {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", @@ -174,7 +174,7 @@ static Tk_OptionSpec EntryOptionSpecs[] = { TK_OPTION_NULL_OK,0,TEXTVAR_CHANGED}, {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", "none", -1, Tk_Offset(Entry, entry.validate), - 0, (ClientData) validateStrings, 0}, + 0, (void *) validateStrings, 0}, {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand", NULL, -1, Tk_Offset(Entry, entry.validateCmd), TK_OPTION_NULL_OK, 0, 0}, @@ -283,7 +283,7 @@ static char *EntryDisplayString(const char *showChar, int numChars) TkUtfToUniChar(showChar, &ch); size = TkUniCharToUtf(ch, buf); - p = displayString = ckalloc(numChars * size + 1); + p = displayString = (char *)ckalloc(numChars * size + 1); while (numChars--) { memcpy(p, buf, size); @@ -328,7 +328,7 @@ static int EntryFetchSelection( ClientData clientData, int offset, char *buffer, int maxBytes) { - Entry *entryPtr = (Entry *) clientData; + Entry *entryPtr = (Entry *)clientData; int byteCount; const char *string; const char *selStart, *selEnd; @@ -361,7 +361,7 @@ EntryFetchSelection( */ static void EntryLostSelection(ClientData clientData) { - Entry *entryPtr = (Entry *) clientData; + Entry *entryPtr = (Entry *)clientData; entryPtr->core.flags &= ~GOT_SELECTION; entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1; TtkRedisplayWidget(&entryPtr->core); @@ -377,7 +377,7 @@ static void EntryOwnSelection(Entry *entryPtr) && (!Tcl_IsSafe(entryPtr->core.interp)) && !(entryPtr->core.flags & GOT_SELECTION)) { Tk_OwnSelection(entryPtr->core.tkwin, XA_PRIMARY, EntryLostSelection, - (ClientData) entryPtr); + entryPtr); entryPtr->core.flags |= GOT_SELECTION; } } @@ -393,8 +393,8 @@ static void EntryOwnSelection(Entry *entryPtr) static void ExpandPercents( Entry *entryPtr, /* Entry that needs validation. */ - const char *template, /* Script template */ - const char *new, /* Potential new value of entry string */ + const char *templ, /* Script template */ + const char *newValue, /* Potential new value of entry string */ int index, /* index of insert/delete */ int count, /* #changed characters */ VREASON reason, /* Reason for change */ @@ -407,28 +407,28 @@ ExpandPercents( int ch; char numStorage[2*TCL_INTEGER_SPACE]; - while (*template) { + while (*templ) { /* Find everything up to the next % character and append it * to the result string. */ - string = Tcl_UtfFindFirst(template, '%'); + string = Tcl_UtfFindFirst(templ, '%'); if (string == NULL) { /* No more %-sequences to expand. * Copy the rest of the template. */ - Tcl_DStringAppend(dsPtr, template, -1); + Tcl_DStringAppend(dsPtr, templ, -1); return; } - if (string != template) { - Tcl_DStringAppend(dsPtr, template, string - template); - template = string; + if (string != templ) { + Tcl_DStringAppend(dsPtr, templ, string - templ); + templ = string; } /* There's a percent sequence here. Process it. */ - ++template; /* skip over % */ - if (*template != '\0') { - template += TkUtfToUniChar(template, &ch); + ++templ; /* skip over % */ + if (*templ != '\0') { + templ += TkUtfToUniChar(templ, &ch); } else { ch = '%'; } @@ -451,14 +451,14 @@ ExpandPercents( string = numStorage; break; case 'P': /* 'Peeked' new value of the string */ - string = new; + string = newValue; break; case 's': /* Current string value */ string = entryPtr->entry.string; break; case 'S': /* string to be inserted/deleted, if any */ if (reason == VALIDATE_INSERT) { - string = TkUtfAtIndex(new, index); + string = TkUtfAtIndex(newValue, index); stringLength = TkUtfAtIndex(string, count) - string; } else if (reason == VALIDATE_DELETE) { string = TkUtfAtIndex(entryPtr->entry.string, index); @@ -502,9 +502,9 @@ ExpandPercents( static int RunValidationScript( Tcl_Interp *interp, /* Interpreter to use */ Entry *entryPtr, /* Entry being validated */ - const char *template, /* Script template */ + const char *templ, /* Script template */ const char *optionName, /* "-validatecommand", "-invalidcommand" */ - const char *new, /* Potential new value of entry string */ + const char *newValue, /* Potential new value of entry string */ int index, /* index of insert/delete */ int count, /* #changed characters */ VREASON reason) /* Reason for change */ @@ -513,7 +513,7 @@ static int RunValidationScript( int code; Tcl_DStringInit(&script); - ExpandPercents(entryPtr, template, new, index, count, reason, &script); + ExpandPercents(entryPtr, templ, newValue, index, count, reason, &script); code = Tcl_EvalEx(interp, Tcl_DStringValue(&script), Tcl_DStringLength(&script), TCL_EVAL_GLOBAL); @@ -574,9 +574,9 @@ EntryValidateChange( VMODE vmode = entryPtr->entry.validate; int code, change_ok; - if ( (entryPtr->entry.validateCmd == NULL) + if ((entryPtr->entry.validateCmd == NULL) || (entryPtr->core.flags & VALIDATING) - || !EntryNeedsValidation(vmode, reason) ) + || !EntryNeedsValidation(vmode, reason)) { return TCL_OK; } @@ -630,7 +630,10 @@ done: * Returns: * TCL_OK if valid, TCL_BREAK if invalid, TCL_ERROR on error. */ -static int EntryRevalidate(Tcl_Interp *interp, Entry *entryPtr, VREASON reason) +static int EntryRevalidate( + TCL_UNUSED(Tcl_Interp *), + Entry *entryPtr, + VREASON reason) { int code = EntryValidateChange( entryPtr, entryPtr->entry.string, -1,0, reason); @@ -725,7 +728,7 @@ EntryStoreValue(Entry *entryPtr, const char *value) /* Store new value: */ - entryPtr->entry.string = ckalloc(numBytes + 1); + entryPtr->entry.string = (char *)ckalloc(numBytes + 1); strcpy(entryPtr->entry.string, value); entryPtr->entry.numBytes = numBytes; entryPtr->entry.numChars = numChars; @@ -782,7 +785,7 @@ static int EntrySetValue(Entry *entryPtr, const char *value) */ static void EntryTextVariableTrace(void *recordPtr, const char *value) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (WidgetDestroyed(&entryPtr->core)) { return; @@ -816,29 +819,29 @@ InsertChars( size_t byteCount = strlen(value); int charsAdded = Tcl_NumUtfChars(value, byteCount); size_t newByteCount = entryPtr->entry.numBytes + byteCount + 1; - char *new; + char *newBytes; int code; if (byteCount == 0) { return TCL_OK; } - new = ckalloc(newByteCount); - memcpy(new, string, byteIndex); - strcpy(new + byteIndex, value); - strcpy(new + byteIndex + byteCount, string + byteIndex); + newBytes = (char *)ckalloc(newByteCount); + memcpy(newBytes, string, byteIndex); + strcpy(newBytes + byteIndex, value); + strcpy(newBytes + byteIndex + byteCount, string + byteIndex); code = EntryValidateChange( - entryPtr, new, index, charsAdded, VALIDATE_INSERT); + entryPtr, newBytes, index, charsAdded, VALIDATE_INSERT); if (code == TCL_OK) { AdjustIndices(entryPtr, index, charsAdded); - code = EntrySetValue(entryPtr, new); + code = EntrySetValue(entryPtr, newBytes); } else if (code == TCL_BREAK) { code = TCL_OK; } - ckfree(new); + ckfree(newBytes); return code; } @@ -853,13 +856,13 @@ DeleteChars( { char *string = entryPtr->entry.string; size_t byteIndex, byteCount, newByteCount; - char *new; + char *newBytes; int code; if (index < 0) { index = 0; } - if (count > entryPtr->entry.numChars - index) { + if (count + index > entryPtr->entry.numChars) { count = entryPtr->entry.numChars - index; } if (count <= 0) { @@ -870,20 +873,20 @@ DeleteChars( byteCount = TkUtfAtIndex(string+byteIndex, count) - (string+byteIndex); newByteCount = entryPtr->entry.numBytes + 1 - byteCount; - new = ckalloc(newByteCount); - memcpy(new, string, byteIndex); - strcpy(new + byteIndex, string + byteIndex + byteCount); + newBytes = (char *)ckalloc(newByteCount); + memcpy(newBytes, string, byteIndex); + strcpy(newBytes + byteIndex, string + byteIndex + byteCount); code = EntryValidateChange( - entryPtr, new, index, count, VALIDATE_DELETE); + entryPtr, newBytes, index, count, VALIDATE_DELETE); if (code == TCL_OK) { AdjustIndices(entryPtr, index, -count); - code = EntrySetValue(entryPtr, new); + code = EntrySetValue(entryPtr, newBytes); } else if (code == TCL_BREAK) { code = TCL_OK; } - ckfree(new); + ckfree(newBytes); return code; } @@ -900,7 +903,7 @@ DeleteChars( static void EntryEventProc(ClientData clientData, XEvent *eventPtr) { - Entry *entryPtr = (Entry *) clientData; + Entry *entryPtr = (Entry *)clientData; Tcl_Preserve(clientData); switch (eventPtr->type) { @@ -923,17 +926,19 @@ EntryEventProc(ClientData clientData, XEvent *eventPtr) */ static void -EntryInitialize(Tcl_Interp *interp, void *recordPtr) +EntryInitialize( + TCL_UNUSED(Tcl_Interp *), + void *recordPtr) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; Tk_CreateEventHandler( entryPtr->core.tkwin, EntryEventMask, EntryEventProc, entryPtr); Tk_CreateSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING, - EntryFetchSelection, (ClientData) entryPtr, XA_STRING); + EntryFetchSelection, entryPtr, XA_STRING); TtkBlinkCursor(&entryPtr->core); - entryPtr->entry.string = ckalloc(1); + entryPtr->entry.string = (char *)ckalloc(1); *entryPtr->entry.string = '\0'; entryPtr->entry.displayString = entryPtr->entry.string; entryPtr->entry.textVariableTrace = 0; @@ -952,7 +957,7 @@ EntryInitialize(Tcl_Interp *interp, void *recordPtr) static void EntryCleanup(void *recordPtr) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (entryPtr->entry.textVariableTrace) Ttk_UntraceVariable(entryPtr->entry.textVariableTrace); @@ -974,7 +979,7 @@ EntryCleanup(void *recordPtr) */ static int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; Tcl_Obj *textVarName = entryPtr->entry.textVariableObj; Ttk_TraceHandle *vt = 0; @@ -1038,9 +1043,12 @@ static int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask) /* EntryPostConfigure -- * Post-configuration hook for entry widgets. */ -static int EntryPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +static int EntryPostConfigure( + TCL_UNUSED(Tcl_Interp *), + void *recordPtr, + int mask) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; int status = TCL_OK; if ((mask & TEXTVAR_CHANGED) && entryPtr->entry.textVariableTrace != NULL) { @@ -1079,7 +1087,7 @@ EntryCharPosition(Entry *entryPtr, int index) static void EntryDoLayout(void *recordPtr) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; WidgetCore *corePtr = &entryPtr->core; Tk_TextLayout textLayout = entryPtr->entry.textLayout; int leftIndex = entryPtr->entry.xscroll.first; @@ -1166,7 +1174,7 @@ static GC EntryGetGC(Entry *entryPtr, Tcl_Obj *colorObj, TkRegion clip) */ static void EntryDisplay(void *clientData, Drawable d) { - Entry *entryPtr = clientData; + Entry *entryPtr = (Entry *)clientData; Tk_Window tkwin = entryPtr->core.tkwin; int leftIndex = entryPtr->entry.xscroll.first, rightIndex = entryPtr->entry.xscroll.last + 1, @@ -1428,7 +1436,7 @@ static int EntryBBoxCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; Ttk_Box b; int index; @@ -1458,7 +1466,7 @@ static int EntryDeleteCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; int first, last; if ((objc < 3) || (objc > 4)) { @@ -1487,7 +1495,7 @@ static int EntryGetCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; @@ -1503,7 +1511,7 @@ static int EntryICursorCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "pos"); return TCL_ERROR; @@ -1523,7 +1531,7 @@ static int EntryIndexCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; int index; if (objc != 3) { @@ -1545,7 +1553,7 @@ static int EntryInsertCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; int index; if (objc != 4) { @@ -1567,7 +1575,7 @@ EntryInsertCommand( static int EntrySelectionClearCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); @@ -1584,7 +1592,7 @@ static int EntrySelectionClearCommand( static int EntrySelectionPresentCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; @@ -1600,13 +1608,13 @@ static int EntrySelectionPresentCommand( static int EntrySelectionRangeCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; int start, end; if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "start end"); return TCL_ERROR; } - if ( EntryIndex(interp, entryPtr, objv[3], &start) != TCL_OK + if (EntryIndex(interp, entryPtr, objv[3], &start) != TCL_OK || EntryIndex(interp, entryPtr, objv[4], &end) != TCL_OK) { return TCL_ERROR; } @@ -1638,7 +1646,7 @@ static const Ttk_Ensemble EntrySelectionCommands[] = { static int EntrySetCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "value"); return TCL_ERROR; @@ -1654,7 +1662,7 @@ static int EntrySetCommand( static int EntryValidateCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; int code; if (objc != 2) { @@ -1676,7 +1684,7 @@ static int EntryValidateCommand( static int EntryXViewCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Entry *entryPtr = recordPtr; + Entry *entryPtr = (Entry *)recordPtr; if (objc == 3) { int newFirst; if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) { @@ -1743,7 +1751,7 @@ typedef struct { Tcl_Obj *postCommandObj; Tcl_Obj *valuesObj; Tcl_Obj *heightObj; - int currentIndex; + int currentIndex; } ComboboxPart; typedef struct { @@ -1771,7 +1779,7 @@ static Tk_OptionSpec ComboboxOptionSpecs[] = { static void ComboboxInitialize(Tcl_Interp *interp, void *recordPtr) { - Combobox *cb = recordPtr; + Combobox *cb = (Combobox *)recordPtr; cb->combobox.currentIndex = -1; TtkTrackElementState(&cb->core); @@ -1784,7 +1792,7 @@ ComboboxInitialize(Tcl_Interp *interp, void *recordPtr) static int ComboboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask) { - Combobox *cbPtr = recordPtr; + Combobox *cbPtr = (Combobox *)recordPtr; int unused; /* Make sure -values is a valid list: @@ -1804,13 +1812,13 @@ ComboboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask) static int ComboboxCurrentCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { - Combobox *cbPtr = recordPtr; + Combobox *cbPtr = (Combobox *)recordPtr; int currentIndex = cbPtr->combobox.currentIndex; const char *currentValue = cbPtr->entry.string; int nValues; Tcl_Obj **values; - Tcl_ListObjGetElements(interp,cbPtr->combobox.valuesObj,&nValues,&values); + Tcl_ListObjGetElements(interp, cbPtr->combobox.valuesObj, &nValues, &values); if (objc == 2) { /* Check if currentIndex still valid: @@ -1849,10 +1857,19 @@ static int ComboboxCurrentCommand( switch (index) { case INDEX_END: /* "end" index */ + if (nValues <= 0) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "index \"end\" out of range")); + Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL); + return TCL_ERROR; + } currentIndex = nValues - 1; break; + default: + Tcl_Panic("Unknown named index"); + return TCL_ERROR; } - } else { + } else { /* * The index should be just an integer. @@ -1977,7 +1994,7 @@ static Tk_OptionSpec SpinboxOptionSpecs[] = { static void SpinboxInitialize(Tcl_Interp *interp, void *recordPtr) { - Spinbox *sb = recordPtr; + Spinbox *sb = (Spinbox *)recordPtr; TtkTrackElementState(&sb->core); EntryInitialize(interp, recordPtr); } @@ -1988,7 +2005,7 @@ SpinboxInitialize(Tcl_Interp *interp, void *recordPtr) static int SpinboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask) { - Spinbox *sb = recordPtr; + Spinbox *sb = (Spinbox *)recordPtr; int unused; /* Make sure -values is a valid list: @@ -2050,14 +2067,18 @@ static Ttk_ElementOptionSpec TextareaElementOptions[] = { Tk_Offset(TextareaElement,fontObj), DEF_ENTRY_FONT }, { "-width", TK_OPTION_INT, Tk_Offset(TextareaElement,widthObj), "20" }, - { NULL, 0, 0, NULL } + { NULL, TK_OPTION_BOOLEAN, 0, NULL } }; static void TextareaElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + TCL_UNUSED(void *), + void *elementRecord, + Tk_Window tkwin, + int *widthPtr, + int *heightPtr, + TCL_UNUSED(Ttk_Padding *)) { - TextareaElement *textarea = elementRecord; + TextareaElement *textarea = (TextareaElement *)elementRecord; Tk_Font font = Tk_GetFontFromObj(tkwin, textarea->fontObj); int avgWidth = Tk_TextWidth(font, "0", 1); Tk_FontMetrics fm; diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index 7fd1442..1bb0482 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -2985,30 +2985,16 @@ static int TreeviewSelectionCommand( switch (selop) { case SELECTION_SET: + /* Clear */ for (item=tv->tree.root; item; item=NextPreorder(item)) { - int inSetList = 0; - - for (i=0; items[i]; ++i) { - if (item == items[i]) { - inSetList = 1; - if (!(item->state & TTK_STATE_SELECTED)) { - /* Item newly selected */ - selChange = 1; - } - break; - } - } - if (!inSetList && (item->state & TTK_STATE_SELECTED)) { - /* Item newly deselected */ + if (item->state & TTK_STATE_SELECTED) { + item->state &= ~TTK_STATE_SELECTED; selChange = 1; } - if (selChange) break; - } - for (item=tv->tree.root; item; item=NextPreorder(item)) { - item->state &= ~TTK_STATE_SELECTED; } for (i=0; items[i]; ++i) { items[i]->state |= TTK_STATE_SELECTED; + selChange = 1; } break; case SELECTION_ADD: diff --git a/library/demos/images/earth.gif b/library/demos/images/earth.gif Binary files differindex 2c229eb..d667244 100644 --- a/library/demos/images/earth.gif +++ b/library/demos/images/earth.gif diff --git a/library/fontchooser.tcl b/library/fontchooser.tcl index fb6c6d3..27c8def 100644 --- a/library/fontchooser.tcl +++ b/library/fontchooser.tcl @@ -12,34 +12,48 @@ namespace eval ::tk::fontchooser { variable S set S(W) .__tk__fontchooser - set S(fonts) [lsort -dictionary [font families]] + set S(fonts) [lsort -dictionary -unique [font families]] set S(styles) [list \ - [::msgcat::mc "Regular"] \ - [::msgcat::mc "Italic"] \ - [::msgcat::mc "Bold"] \ - [::msgcat::mc "Bold Italic"] \ + [::msgcat::mc Regular] \ + [::msgcat::mc Italic] \ + [::msgcat::mc Bold] \ + [::msgcat::mc {Bold Italic}] \ ] - set S(sizes) {8 9 10 11 12 14 16 18 20 22 24 26 28 36 48 72} set S(strike) 0 set S(under) 0 set S(first) 1 - set S(sampletext) [::msgcat::mc "AaBbYyZz01"] set S(-parent) . - set S(-title) [::msgcat::mc "Font"] + set S(-title) {} set S(-command) "" set S(-font) TkDefaultFont + set S(bad) [list ] } -proc ::tk::fontchooser::Setup {} { +proc ::tk::fontchooser::Canonical {} { variable S + foreach style $S(styles) { + lappend S(styles,lcase) [string tolower $style] + } + set S(sizes,lcase) $S(sizes) + set S(sampletext) [::msgcat::mc "AaBbYyZz01"] + # Canonical versions of font families, styles, etc. for easier searching set S(fonts,lcase) {} - foreach font $S(fonts) {lappend S(fonts,lcase) [string tolower $font]} + foreach font $S(fonts) { + lappend S(fonts,lcase) [string tolower $font] + } set S(styles,lcase) {} - foreach style $S(styles) {lappend S(styles,lcase) [string tolower $style]} - set S(sizes,lcase) $S(sizes) + foreach style $S(styles) { + lappend S(styles,lcase) [string tolower $style] + } +} + +proc ::tk::fontchooser::Setup {} { + variable S + + Canonical ::ttk::style layout FontchooserFrame { Entry.field -sticky news -border true -children { @@ -47,8 +61,8 @@ proc ::tk::fontchooser::Setup {} { } } bind [winfo class .] <<ThemeChanged>> \ - [list +ttk::style layout FontchooserFrame \ - [ttk::style layout FontchooserFrame]] + [list +ttk::style layout FontchooserFrame \ + [ttk::style layout FontchooserFrame]] namespace ensemble create -map { show ::tk::fontchooser::Show @@ -60,14 +74,24 @@ proc ::tk::fontchooser::Setup {} { proc ::tk::fontchooser::Show {} { variable S + + Canonical + if {![winfo exists $S(W)]} { Create wm transient $S(W) [winfo toplevel $S(-parent)] tk::PlaceWindow $S(W) widget $S(-parent) + if {[string trim $S(-title)] eq ""} { + wm title $S(W) [::msgcat::mc "Font"] + } else { + wm title $S(W) $S(-title) + } } - set S(fonts) [lsort -dictionary [font families]] + set S(fonts) [lsort -dictionary -unique [font families]] set S(fonts,lcase) {} - foreach font $S(fonts) { lappend S(fonts,lcase) [string tolower $font]} + foreach font $S(fonts) { + lappend S(fonts,lcase) [string tolower $font] + } wm deiconify $S(W) } @@ -91,10 +115,10 @@ proc ::tk::fontchooser::Configure {args} { foreach spec $specs { foreach {name xx yy default} $spec break lappend result $name \ - [expr {[info exists S($name)] ? $S($name) : $default}] + [expr {[info exists S($name)] ? $S($name) : $default}] } lappend result -visible \ - [expr {[winfo exists $S(W)] && [winfo ismapped $S(W)]}] + [expr {[winfo exists $S(W)] && [winfo ismapped $S(W)]}] return $result } if {[llength $args] == 1} { @@ -105,25 +129,32 @@ proc ::tk::fontchooser::Configure {args} { return $S($option) } return -code error -errorcode [list TK LOOKUP OPTION $option] \ - "bad option \"$option\": must be\ - -command, -font, -parent, -title or -visible" + "bad option \"$option\": must be\ + -command, -font, -parent, -title or -visible" } - set cache [dict create -parent $S(-parent) -title $S(-title) \ - -font $S(-font) -command $S(-command)] + -font $S(-font) -command $S(-command)] set r [tclParseConfigSpec [namespace which -variable S] $specs DONTSETDEFAULTS $args] if {![winfo exists $S(-parent)]} { - set code [list TK LOOKUP WINDOW $S(-parent)] + set code [list TK LOOKUP WINDOW $S(-parent)] set err "bad window path name \"$S(-parent)\"" array set S $cache return -code error -errorcode $code $err } - if {[string trim $S(-title)] eq ""} { - set S(-title) [::msgcat::mc "Font"] - } - if {[winfo exists $S(W)] && ("-font" in $args)} { - Init $S(-font) - event generate $S(-parent) <<TkFontchooserFontChanged>> + + if {[winfo exists $S(W)]} { + if {{-font} in $args} { + Init $S(-font) + event generate $S(-parent) <<TkFontchooserFontChanged>> + } + + if {[string trim $S(-title)] eq {}} { + wm title $S(W) [::msgcat::mc Font] + } else { + wm title $S(W) $S(-title) + } + $S(W).ok configure -state $S(nstate) + $S(W).apply configure -state $S(nstate) } return $r } @@ -140,7 +171,9 @@ proc ::tk::fontchooser::Create {} { # Now build the dialog if {![winfo exists $S(W)]} { toplevel $S(W) -class TkFontDialog - if {[package provide tcltest] ne {}} {set ::tk_dialog $S(W)} + if {[package provide tcltest] ne {}} { + set ::tk_dialog $S(W) + } wm withdraw $S(W) wm title $S(W) $S(-title) wm transient $S(W) [winfo toplevel $S(-parent)] @@ -153,40 +186,40 @@ proc ::tk::fontchooser::Create {} { ::tk::AmpWidget ::ttk::label $S(W).style -text [::msgcat::mc "Font st&yle:"] ::tk::AmpWidget ::ttk::label $S(W).size -text [::msgcat::mc "&Size:"] -width $sizeWidth ttk::entry $S(W).efont -width 18 \ - -textvariable [namespace which -variable S](font) + -textvariable [namespace which -variable S](font) ttk::entry $S(W).estyle -width 10 \ - -textvariable [namespace which -variable S](style) + -textvariable [namespace which -variable S](style) ttk::entry $S(W).esize -textvariable [namespace which -variable S](size) \ - -width 3 -validate key -validatecommand {string is double %P} + -width 3 -validate key -validatecommand {regexp -- {^-*[0-9]*$} %P} ttk_slistbox $S(W).lfonts -height 7 -exportselection 0 \ - -selectmode browse -activestyle none \ - -listvariable [namespace which -variable S](fonts) + -selectmode browse -activestyle none \ + -listvariable [namespace which -variable S](fonts) ttk_slistbox $S(W).lstyles -width 5 -height 7 -exportselection 0 \ - -selectmode browse -activestyle none \ - -listvariable [namespace which -variable S](styles) + -selectmode browse -activestyle none \ + -listvariable [namespace which -variable S](styles) ttk_slistbox $S(W).lsizes -width 4 -height 7 -exportselection 0 \ - -selectmode browse -activestyle none \ - -listvariable [namespace which -variable S](sizes) + -selectmode browse -activestyle none \ + -listvariable [namespace which -variable S](sizes) set WE $S(W).effects ::ttk::labelframe $WE -text [::msgcat::mc "Effects"] ::tk::AmpWidget ::ttk::checkbutton $WE.strike \ - -variable [namespace which -variable S](strike) \ - -text [::msgcat::mc "Stri&keout"] \ - -command [namespace code [list Click strike]] + -variable [namespace which -variable S](strike) \ + -text [::msgcat::mc "Stri&keout"] \ + -command [namespace code [list Click strike]] ::tk::AmpWidget ::ttk::checkbutton $WE.under \ - -variable [namespace which -variable S](under) \ - -text [::msgcat::mc "&Underline"] \ - -command [namespace code [list Click under]] + -variable [namespace which -variable S](under) \ + -text [::msgcat::mc "&Underline"] \ + -command [namespace code [list Click under]] set bbox [::ttk::frame $S(W).bbox] ::ttk::button $S(W).ok -text [::msgcat::mc OK] -default active\ - -command [namespace code [list Done 1]] + -command [namespace code [list Done 1]] ::ttk::button $S(W).cancel -text [::msgcat::mc Cancel] \ - -command [namespace code [list Done 0]] + -command [namespace code [list Done 0]] ::tk::AmpWidget ::ttk::button $S(W).apply -text [::msgcat::mc "&Apply"] \ - -command [namespace code [list Apply]] + -command [namespace code [list Apply]] wm protocol $S(W) WM_DELETE_WINDOW [namespace code [list Done 0]] # Calculate minimum sizes @@ -196,13 +229,15 @@ proc ::tk::fontchooser::Create {} { set minsize(gap) 10 set minsize(bbox) [winfo reqwidth $S(W).ok] set minsize(fonts) \ - [expr {[font measure TkDefaultFont "Helvetica"] + $scroll_width}] + [expr {[font measure TkDefaultFont "Helvetica"] + $scroll_width}] set minsize(styles) \ - [expr {[font measure TkDefaultFont "Bold Italic"] + $scroll_width}] + [expr {[font measure TkDefaultFont "Bold Italic"] + $scroll_width}] set minsize(sizes) \ - [expr {[font measure TkDefaultFont "-99"] + $scroll_width}] + [expr {[font measure TkDefaultFont "-99"] + $scroll_width}] set min [expr {$minsize(gap) * 4}] - foreach {what width} [array get minsize] {incr min $width} + foreach {what width} [array get minsize] { + incr min $width + } wm minsize $S(W) $min 260 bind $S(W) <Return> [namespace code [list Done 1]] @@ -224,7 +259,7 @@ proc ::tk::fontchooser::Create {} { set WS $S(W).sample ::ttk::labelframe $WS -text [::msgcat::mc "Sample"] ::ttk::label $WS.sample -relief sunken -anchor center \ - -textvariable [namespace which -variable S](sampletext) + -textvariable [namespace which -variable S](sampletext) set S(sample) $WS.sample grid $WS.sample -sticky news -padx 6 -pady 4 grid rowconfigure $WS 0 -weight 1 @@ -233,9 +268,7 @@ proc ::tk::fontchooser::Create {} { grid $S(W).ok -in $bbox -sticky new -pady {0 2} grid $S(W).cancel -in $bbox -sticky new -pady 2 - if {$S(-command) ne ""} { - grid $S(W).apply -in $bbox -sticky new -pady 2 - } + grid $S(W).apply -in $bbox -sticky new -pady 2 grid columnconfigure $bbox 0 -weight 1 grid $WE.strike -sticky w -padx 10 @@ -262,15 +295,19 @@ proc ::tk::fontchooser::Create {} { Init $S(-font) trace add variable [namespace which -variable S](size) \ - write [namespace code [list Tracer]] + write [namespace code [list Tracer]] trace add variable [namespace which -variable S](style) \ - write [namespace code [list Tracer]] + write [namespace code [list Tracer]] trace add variable [namespace which -variable S](font) \ - write [namespace code [list Tracer]] - } else { - Init $S(-font) + write [namespace code [list Tracer]] + trace add variable [namespace which -variable S](strike) \ + write [namespace code [list Tracer]] + trace add variable [namespace which -variable S](under) \ + write [namespace code [list Tracer]] } + Init $S(-font) + return } @@ -290,9 +327,14 @@ proc ::tk::fontchooser::Done {ok} { trace vdelete S(size) w [namespace code [list Tracer]] trace vdelete S(style) w [namespace code [list Tracer]] trace vdelete S(font) w [namespace code [list Tracer]] + trace vdelete S(strike) w [namespace code [list Tracer]] + trace vdelete S(under) w [namespace code [list Tracer]] destroy $S(W) - if {$ok && $S(-command) ne ""} { - uplevel #0 $S(-command) [list $S(result)] + if {$ok} { + if {$S(-command) ne ""} { + uplevel #0 $S(-command) [list $S(result)] + } + event generate $S(-parent) <<TkFontchooserFontChanged>> } } @@ -322,16 +364,17 @@ proc ::tk::fontchooser::Init {{defaultFont ""}} { variable S if {$S(first) || $defaultFont ne ""} { + Canonical if {$defaultFont eq ""} { set defaultFont [[entry .___e] cget -font] destroy .___e } array set F [font actual $defaultFont] set S(font) $F(-family) + set S(style) [::msgcat::mc "Regular"] set S(size) $F(-size) set S(strike) $F(-overstrike) set S(under) $F(-underline) - set S(style) [::msgcat::mc "Regular"] if {$F(-weight) eq "bold" && $F(-slant) eq "italic"} { set S(style) [::msgcat::mc "Bold Italic"] } elseif {$F(-weight) eq "bold"} { @@ -339,12 +382,8 @@ proc ::tk::fontchooser::Init {{defaultFont ""}} { } elseif {$F(-slant) eq "italic"} { set S(style) [::msgcat::mc "Italic"] } - set S(first) 0 } - - Tracer a b c - Update } # ::tk::fontchooser::Click -- @@ -356,7 +395,6 @@ proc ::tk::fontchooser::Init {{defaultFont ""}} { # proc ::tk::fontchooser::Click {who} { variable S - if {$who eq "font"} { set S(font) [$S(W).lfonts get [$S(W).lfonts curselection]] } elseif {$who eq "style"} { @@ -364,7 +402,6 @@ proc ::tk::fontchooser::Click {who} { } elseif {$who eq "size"} { set S(size) [$S(W).lsizes get [$S(W).lsizes curselection]] } - Update } # ::tk::fontchooser::Tracer -- @@ -376,32 +413,43 @@ proc ::tk::fontchooser::Click {who} { # proc ::tk::fontchooser::Tracer {var1 var2 op} { variable S - - set bad 0 - set nstate normal - # Make selection in each listbox - foreach var {font style size} { - set value [string tolower $S($var)] - $S(W).l${var}s selection clear 0 end - set n [lsearch -exact $S(${var}s,lcase) $value] - $S(W).l${var}s selection set $n + # We don't need to process strike and under + if {$var2 ni [list strike under]} { + # Make selection in listbox + set value [string tolower $S($var2)] + $S(W).l${var2}s selection clear 0 end + set n [lsearch -exact $S(${var2}s,lcase) $value] + $S(W).l${var2}s selection set $n if {$n >= 0} { - set S($var) [lindex $S(${var}s) $n] - $S(W).e$var icursor end - $S(W).e$var selection clear - } else { ;# No match, try prefix - # Size is weird: valid numbers are legal but don't display - # unless in the font size list - set n [lsearch -glob $S(${var}s,lcase) "$value*"] - set bad 1 - if {$var ne "size" || ! [string is double -strict $value]} { - set nstate disabled + set S($var2) [lindex $S(${var2}s) $n] + $S(W).e$var2 icursor end + $S(W).e$var2 selection clear + if {[set i [lsearch $S(bad) $var2]] >= 0} { + set S(bad) [lreplace $S(bad) $i $i] + } + } else { + # No match, try prefix + set n [lsearch -glob $S(${var2}s,lcase) "$value*"] + if {$var2 ne "size" || !([regexp -- {^(-[0-9]+|[0-9]+)$} $value] && $value >= -4096 && $value <= 4096)} { + if {[lsearch $S(bad) $var2] < 0} { + lappend S(bad) $var2 + } + } else { + if {[set i [lsearch $S(bad) $var2]] >= 0} { + set S(bad) [lreplace $S(bad) $i $i] + } } } - $S(W).l${var}s see $n + $S(W).l${var2}s see $n + } + if {[llength $S(bad)] == 0} { + set S(nstate) normal + Update + } else { + set S(nstate) disabled } - if {!$bad} {Update} - $S(W).ok configure -state $nstate + $S(W).ok configure -state $S(nstate) + $S(W).apply configure -state $S(nstate) } # ::tk::fontchooser::Update -- @@ -412,13 +460,24 @@ proc ::tk::fontchooser::Update {} { variable S set S(result) [list $S(font) $S(size)] - if {$S(style) eq [::msgcat::mc "Bold"]} {lappend S(result) bold} - if {$S(style) eq [::msgcat::mc "Italic"]} {lappend S(result) italic} - if {$S(style) eq [::msgcat::mc "Bold Italic"]} {lappend S(result) bold italic} - if {$S(strike)} {lappend S(result) overstrike} - if {$S(under)} {lappend S(result) underline} + if {$S(style) eq [::msgcat::mc "Bold"]} { + lappend S(result) bold + } + if {$S(style) eq [::msgcat::mc "Italic"]} { + lappend S(result) italic + } + if {$S(style) eq [::msgcat::mc "Bold Italic"]} { + lappend S(result) bold italic + } + if {$S(strike)} { + lappend S(result) overstrike + } + if {$S(under)} { + lappend S(result) underline + } $S(sample) configure -font $S(result) + set S(-font) $S(result) } # ::tk::fontchooser::Visibility -- @@ -432,7 +491,7 @@ proc ::tk::fontchooser::Visibility {w visible} { } } -# ::tk::fontchooser::ttk_listbox -- +# ::tk::fontchooser::ttk_slistbox -- # # Create a properly themed scrolled listbox. # This is exactly right on XP but may need adjusting on other platforms. diff --git a/library/msgs/fi.msg b/library/msgs/fi.msg new file mode 100644 index 0000000..e014cce --- /dev/null +++ b/library/msgs/fi.msg @@ -0,0 +1,89 @@ +namespace eval ::tk { + ::msgcat::mcset fi "&Abort" "&Keskeyt\u00e4" + ::msgcat::mcset fi "&About..." "&Tietoja..." + ::msgcat::mcset fi "All Files" "Kaikki tiedostot" + ::msgcat::mcset fi "Application Error" "Ohjelmavirhe" + ::msgcat::mcset fi "&Apply" "K\u00e4&yt\u00e4" + ::msgcat::mcset fi "Bold" "Lihavoitu" + ::msgcat::mcset fi "Bold Italic" "Lihavoitu, kursivoitu" + ::msgcat::mcset fi "&Blue" "&Sininen" + ::msgcat::mcset fi "Cancel" "Peruuta" + ::msgcat::mcset fi "&Cancel" "&Peruuta" + ::msgcat::mcset fi "Cannot change to the directory \"%1\$s\".\nPermission denied." "Ei voitu vaihtaa hakemistoon \"%1\$s\".\nLupa ev\u00e4tty." + ::msgcat::mcset fi "Choose Directory" "Valitse hakemisto" + ::msgcat::mcset fi "Cl&ear" "&Tyhjenn\u00e4" + ::msgcat::mcset fi "&Clear Console" "&Tyhjenn\u00e4 konsoli" + ::msgcat::mcset fi "Color" "V\u00e4ri" + ::msgcat::mcset fi "Console" "Konsoli" + ::msgcat::mcset fi "&Copy" "K&opioi" + ::msgcat::mcset fi "Cu&t" "&Leikkaa" + ::msgcat::mcset fi "&Delete" "&Poista" + ::msgcat::mcset fi "Details >>" "Lis\u00e4tiedot >>" + ::msgcat::mcset fi "Directory \"%1\$s\" does not exist." "Hakemistoa \"%1\$s\" ei ole olemassa." + ::msgcat::mcset fi "&Directory:" "&Hakemisto:" + ::msgcat::mcset fi "&Edit" "&Muokkaa" + ::msgcat::mcset fi "Effects" "Tehosteet" + ::msgcat::mcset fi "Error: %1\$s" "Virhe: %1\$s" + ::msgcat::mcset fi "E&xit" "&Lopeta" + ::msgcat::mcset fi "&File" "&Tiedosto" + ::msgcat::mcset fi "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "Tiedosto \"%1\$s\" on jo olemassa.\nHaluatko korvata sen?" + ::msgcat::mcset fi "File \"%1\$s\" already exists.\n\n" "Tiedosto \"%1\$s\" on jo olemassa.\n\n" + ::msgcat::mcset fi "File \"%1\$s\" does not exist." "Tiedostoa \"%1\$s\" ei ole olemassa." + ::msgcat::mcset fi "File &name:" "Tiedosto&nimi:" + ::msgcat::mcset fi "File &names:" "Tiedosto&nimet:" + ::msgcat::mcset fi "Files of &type:" "T&yyppi:" + ::msgcat::mcset fi "Fi&les:" "Ti&edostot:" + ::msgcat::mcset fi "&Filter" "&Suodata" + ::msgcat::mcset fi "Fil&ter:" "Suo&data:" + ::msgcat::mcset fi "Font" "Kirjasin" + ::msgcat::mcset fi "&Font:" "&Kirjasin:" + ::msgcat::mcset fi "Font st&yle:" "Kirjasint&yyli:" + ::msgcat::mcset fi "&Green" "&Vihre\u00e4" + ::msgcat::mcset fi "&Help" "&Ohje" + ::msgcat::mcset fi "Hi" "Hei" + ::msgcat::mcset fi "&Hide Console" "P&iilota konsoli" + ::msgcat::mcset fi "&Ignore" "&Ohita" + ::msgcat::mcset fi "Invalid file name \"%1\$s\"." "Virheellinen tiedostonimi \"%1\$s\"." + ::msgcat::mcset fi "Italic" "Kursivoitu" + ::msgcat::mcset fi "Log Files" "Lokitiedostot" + ::msgcat::mcset fi "&No" "&Ei" + ::msgcat::mcset fi "&OK" + ::msgcat::mcset fi "OK" + ::msgcat::mcset fi "Ok" "OK" + ::msgcat::mcset fi "Open" "Avaa" + ::msgcat::mcset fi "&Open" "&Avaa" + ::msgcat::mcset fi "Open Multiple Files" "Avaa monta tiedostoa" + ::msgcat::mcset fi "P&aste" "L&iit\u00e4" + ::msgcat::mcset fi "&Quit" "&Lopeta" + ::msgcat::mcset fi "&Red" "&Punainen" + ::msgcat::mcset fi "Regular" "Tavallinen" + ::msgcat::mcset fi "Replace existing file?" "Korvataanko olemassaoleva tiedosto?" + ::msgcat::mcset fi "&Retry" "&Yrit\u00e4 uudelleen" + ::msgcat::mcset fi "Sample" "Malli" + ::msgcat::mcset fi "&Save" "&Tallenna" + ::msgcat::mcset fi "Save As" "Tallenna nimell\u00e4" + ::msgcat::mcset fi "Save To Log" "Tallenna lokiin" + ::msgcat::mcset fi "Select Log File" "Valitse lokitiedosto" + ::msgcat::mcset fi "Select a file to source" "Valitse l\u00e4hdetiedosto" + ::msgcat::mcset fi "&Selection:" "&Valinta:" + ::msgcat::mcset fi "&Size:" "K&oko:" + ::msgcat::mcset fi "Skip Messages" "J\u00e4t\u00e4 viestit huomiotta" + ::msgcat::mcset fi "&Source..." "L&\u00e4hde..." + ::msgcat::mcset fi "Stri&keout" "&Yliviivaa" + ::msgcat::mcset fi "Tcl Scripts" "Tcl-skriptit" + ::msgcat::mcset fi "Tcl for Windows" "Tcl Windowsille" + ::msgcat::mcset fi "Text Files" "Tekstitiedostot" + ::msgcat::mcset fi "&Underline" "&Alleviivaa" + ::msgcat::mcset fi "&Yes" "&Kyll\u00e4" + ::msgcat::mcset fi "abort" "keskeyt\u00e4" + ::msgcat::mcset fi "blue" "sininen" + ::msgcat::mcset fi "cancel" "peruuta" + ::msgcat::mcset fi "extension" "lis\u00e4osa" + ::msgcat::mcset fi "extensions" "lis\u00e4osat" + ::msgcat::mcset fi "green" "vihre\u00e4" + ::msgcat::mcset fi "ignore" "ohita" + ::msgcat::mcset fi "ok" + ::msgcat::mcset fi "red" "punainen" + ::msgcat::mcset fi "retry" "yrit\u00e4 uudelleen" + ::msgcat::mcset fi "yes" "kyll\u00e4" +} diff --git a/library/msgs/zh_cn.msg b/library/msgs/zh_cn.msg new file mode 100644 index 0000000..9a728b7 --- /dev/null +++ b/library/msgs/zh_cn.msg @@ -0,0 +1,92 @@ +namespace eval ::tk { + ::msgcat::mcset zh_cn "&Abort" "&中止" + ::msgcat::mcset zh_cn "&About..." "&关于……" + ::msgcat::mcset zh_cn "All Files" "所有文件" + ::msgcat::mcset zh_cn "Application Error" "应用程序错误" + ::msgcat::mcset zh_cn "&Apply" "&添加" + ::msgcat::mcset zh_cn "Bold" "粗体" + ::msgcat::mcset zh_cn "Bold Italic" "加粗斜体" + ::msgcat::mcset zh_cn "&Blue" "&蓝色" + ::msgcat::mcset zh_cn "Cancel" "取消" + ::msgcat::mcset zh_cn "&Cancel" "&取消" + ::msgcat::mcset zh_cn "Cannot change to the directory \"%1\$s\".\nPermission denied." "无法更改目录 \"%1\$s\"。\n访问被拒绝。" + ::msgcat::mcset zh_cn "Choose Directory" "选择文件夹" + ::msgcat::mcset zh_cn "Cl&ear" "清&除" + ::msgcat::mcset zh_cn "&Clear Console" "&清除终端" + ::msgcat::mcset zh_cn "Color" "颜色" + ::msgcat::mcset zh_cn "Console" "终端" + ::msgcat::mcset zh_cn "&Copy" "&复制" + ::msgcat::mcset zh_cn "Cu&t" "剪&切" + ::msgcat::mcset zh_cn "&Delete" "&删除" + ::msgcat::mcset zh_cn "Details >>" "详细信息 >>" + ::msgcat::mcset zh_cn "Directory \"%1\$s\" does not exist." "目录 \"%1\$s\" 不存在。" + ::msgcat::mcset zh_cn "&Directory:" "&目录:" + ::msgcat::mcset zh_cn "&Edit" "&编辑" + ::msgcat::mcset zh_cn "Effects" "效果" + ::msgcat::mcset zh_cn "Error: %1\$s" "错误: %1\$s" + ::msgcat::mcset zh_cn "E&xit" "退&出" + ::msgcat::mcset zh_cn "&File" "&文件" + ::msgcat::mcset zh_cn "File \"%1\$s\" already exists.\nDo you want to overwrite it?" "文件 \"%1\$s\" 已经存在。\n您想要覆盖它吗?" + ::msgcat::mcset zh_cn "File \"%1\$s\" already exists.\n\n" "文件 \"%1\$s\" 已经存在。\n\n" + ::msgcat::mcset zh_cn "File \"%1\$s\" does not exist." "文件 \"%1\$s\" 不存在。" + ::msgcat::mcset zh_cn "File &name:" "文件&名:" + ::msgcat::mcset zh_cn "File &names:" "文件&名:" + ::msgcat::mcset zh_cn "Files of &type:" "文件&类型:" + ::msgcat::mcset zh_cn "Fi&les:" "文&件:" + ::msgcat::mcset zh_cn "&Filter" "&过滤" + ::msgcat::mcset zh_cn "Fil&ter:" "过&滤:" + ::msgcat::mcset zh_cn "Font" "字体" + ::msgcat::mcset zh_cn "&Font:" "&字体:" + ::msgcat::mcset zh_cn "Font st&yle:" "字体&样式:" + ::msgcat::mcset zh_cn "&Green" "&绿色" + ::msgcat::mcset zh_cn "&Help" "&帮助" + ::msgcat::mcset zh_cn "Hi" "你好" + ::msgcat::mcset zh_cn "&Hide Console" "&隐藏终端" + ::msgcat::mcset zh_cn "&Ignore" "&忽略" + ::msgcat::mcset zh_cn "Invalid file name \"%1\$s\"." "无效的文件名 \"%1\$s\"。" + ::msgcat::mcset zh_cn "Italic" "斜体" + ::msgcat::mcset zh_cn "Log Files" "日志文件" + ::msgcat::mcset zh_cn "&No" "&取消" + ::msgcat::mcset zh_cn "&OK" "&确定" + ::msgcat::mcset zh_cn "OK" "确定" + ::msgcat::mcset zh_cn "Ok" "确定" + ::msgcat::mcset zh_cn "Open" "打开" + ::msgcat::mcset zh_cn "&Open" "&打开" + ::msgcat::mcset zh_cn "Open Multiple Files" "打开多个文件" + ::msgcat::mcset zh_cn "P&aste" "粘&贴" + ::msgcat::mcset zh_cn "&Quit" "&退出" + ::msgcat::mcset zh_cn "&Red" "红色" + ::msgcat::mcset zh_cn "Regular" "规则" + ::msgcat::mcset zh_cn "Replace existing file?" "替换已有文件?" + ::msgcat::mcset zh_cn "&Retry" "&重试" + ::msgcat::mcset zh_cn "Sample" "样式" + ::msgcat::mcset zh_cn "&Save" "&保存" + ::msgcat::mcset zh_cn "Save As" "另存为" + ::msgcat::mcset zh_cn "Save To Log" "保存到日志" + ::msgcat::mcset zh_cn "Select Log File" "选择日志文件" + ::msgcat::mcset zh_cn "Select a file to source" "选择一个源文件" + ::msgcat::mcset zh_cn "&Selection:" "&选择:" + ::msgcat::mcset zh_cn "&Size:" "&大小:" + ::msgcat::mcset zh_cn "Show &Hidden Directories" "显示&隐藏目录" + ::msgcat::mcset zh_cn "Show &Hidden Files and Directories" "显示&隐藏文件和目录" + ::msgcat::mcset zh_cn "Skip Messages" "跳过信息" + ::msgcat::mcset zh_cn "&Source..." "&来源……" + ::msgcat::mcset zh_cn "Stri&keout" "删&除线" + ::msgcat::mcset zh_cn "Tcl Scripts" "Tcl脚本" + ::msgcat::mcset zh_cn "Tcl for Windows" "适用于Windows的Tcl" + ::msgcat::mcset zh_cn "Text Files" "文本文档" + ::msgcat::mcset zh_cn "&Underline" "&下划线" + ::msgcat::mcset zh_cn "&Yes" "&确定" + ::msgcat::mcset zh_cn "abort" "中止" + ::msgcat::mcset zh_cn "blue" "蓝色" + ::msgcat::mcset zh_cn "cancel" "取消" + ::msgcat::mcset zh_cn "extension" "拓展" + ::msgcat::mcset zh_cn "extensions" "拓展" + ::msgcat::mcset zh_cn "green" "绿色" + ::msgcat::mcset zh_cn "ignore" "忽略" + ::msgcat::mcset zh_cn "ok" "确定" + ::msgcat::mcset zh_cn "red" "红色" + ::msgcat::mcset zh_cn "retry" "重试" + ::msgcat::mcset zh_cn "yes" "确认" +} + diff --git a/library/ttk/utils.tcl b/library/ttk/utils.tcl index 2571914..3d90880 100644 --- a/library/ttk/utils.tcl +++ b/library/ttk/utils.tcl @@ -236,8 +236,8 @@ proc ttk::Repeatedly {args} { after cancel $Repeat(timer) set script [uplevel 1 [list namespace code $args]] set Repeat(script) $script - uplevel #0 $script set Repeat(timer) [after $Repeat(delay) ttk::Repeat] + uplevel #0 $script } ## Repeat -- @@ -245,8 +245,8 @@ proc ttk::Repeatedly {args} { # proc ttk::Repeat {} { variable Repeat - uplevel #0 $Repeat(script) set Repeat(timer) [after $Repeat(interval) ttk::Repeat] + uplevel #0 $Repeat(script) } ## ttk::CancelRepeat -- diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 9a1ea45..fc0ffdf 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -144,25 +144,28 @@ TkMacOSXCreateCGImageWithXImage( bitsPerComponent = 1; bitsPerPixel = 1; - if (image->bitmap_bit_order != MSBFirst) { - char *srcPtr = image->data + image->xoffset; - char *endPtr = srcPtr + len; - char *destPtr = (data = (char *)ckalloc(len)); + data = (char *)ckalloc(len); + if (data) { + if (image->bitmap_bit_order != MSBFirst) { + char *srcPtr = image->data + image->xoffset; + char *endPtr = srcPtr + len; + char *destPtr = data; - while (srcPtr < endPtr) { - *destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))]; + while (srcPtr < endPtr) { + *destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))]; + } + } else { + memcpy(data, image->data + image->xoffset, len); } - } else { - data = (char *)memcpy(ckalloc(len), image->data + image->xoffset, len); - } - if (data) { provider = CGDataProviderCreateWithData(data, data, len, releaseData); - } - if (provider) { + if (!provider) { + ckfree(data); + } img = CGImageMaskCreate(image->width, image->height, bitsPerComponent, bitsPerPixel, image->bytes_per_line, provider, decode, 0); + CGDataProviderRelease(provider); } } else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) { @@ -170,8 +173,6 @@ TkMacOSXCreateCGImageWithXImage( * Color image */ - CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); - if (image->width == 0 && image->height == 0) { /* @@ -180,19 +181,22 @@ TkMacOSXCreateCGImageWithXImage( return NULL; } + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = kCGBitmapByteOrder32Big | alphaInfo; - data = (char *)memcpy(ckalloc(len), image->data + image->xoffset, len); + data = (char *)ckalloc(len); if (data) { + memcpy(data, image->data + image->xoffset, len); provider = CGDataProviderCreateWithData(data, data, len, releaseData); - } - if (provider) { + if (!provider) { + ckfree(data); + } img = CGImageCreate(image->width, image->height, bitsPerComponent, bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo, provider, decode, 0, kCGRenderingIntentDefault); - CFRelease(provider); + CGDataProviderRelease(provider); } if (colorspace) { CFRelease(colorspace); @@ -650,6 +654,7 @@ CreateCGImageFromDrawableRect( CGImageRef cg_image = NULL, result = NULL; if (mac_drawable->flags & TK_IS_PIXMAP) { cg_context = TkMacOSXGetCGContextForDrawable(drawable); + CGContextRetain(cg_context); } else { NSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable); if (view == nil) { diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c index 9aca9e1..fe2991e 100644 --- a/macosx/tkMacOSXKeyboard.c +++ b/macosx/tkMacOSXKeyboard.c @@ -273,9 +273,9 @@ UpdateKeymaps() for (virt = 0; virt < 128; virt++) { MacKeycode macKC; macKC.v = (keycode_v) {.virt = virt, .o_s = index, .keychar = 0}; - int modifiers = INDEX2CARBON(index), result; + int modifiers = INDEX2CARBON(index); UniChar keychar = 0; - result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, virt, + KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, virt, modifiers, NULL); if (keychar == 0x10) { diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 09d91f0..89ca315 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -1369,7 +1369,7 @@ TkpComputeStandardMenuGeometry( { NSSize menuSize; Tk_Font tkfont, menuFont; - Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; + Tk_FontMetrics menuMetrics, entryMetrics; int modifierCharWidth, menuModifierCharWidth; int x, y, modifierWidth, labelWidth, indicatorSpace; int windowWidth, windowHeight, accelWidth; @@ -1424,12 +1424,10 @@ TkpComputeStandardMenuGeometry( } if (mePtr->fontPtr == NULL) { tkfont = menuFont; - fmPtr = &menuMetrics; modifierCharWidth = menuModifierCharWidth; } else { tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); Tk_GetFontMetrics(tkfont, &entryMetrics); - fmPtr = &entryMetrics; modifierCharWidth = ModifierCharWidth(tkfont); } accelWidth = modifierWidth = indicatorSpace = 0; diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index 6291596..03709ce 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -375,7 +375,6 @@ DrawMenuButtonImageAndText( Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; int haveImage = 0, haveText = 0; - int imageWidth = 0, imageHeight = 0; int imageXOffset = 0, imageYOffset = 0; int textXOffset = 0, textYOffset = 0; int width = 0, height = 0; @@ -396,9 +395,6 @@ DrawMenuButtonImageAndText( haveImage = 1; } - imageWidth = width; - imageHeight = height; - haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { int x = 0, y = 0; diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 83edca3..fd9bbc1 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -4,7 +4,7 @@ * This file implements functions that decode & handle mouse events on * MacOS X. * - * Copyright 2001-2009, Apple Inc. + * Copyright (c) 2001-2009, Apple Inc. * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net> * * See the file "license.terms" for information on usage and redistribution of @@ -396,12 +396,15 @@ enum { target = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y); } + + grabWinPtr = winPtr->dispPtr->grabWinPtr; + /* * Ignore the event if a local grab is in effect and the Tk window is * not in the grabber's subtree. */ - grabWinPtr = winPtr->dispPtr->grabWinPtr; + if (grabWinPtr && /* There is a grab in effect ... */ !winPtr->dispPtr->grabFlags && /* and it is a local grab ... */ grabWinPtr->mainPtr == winPtr->mainPtr){ /* in the same application. */ @@ -420,6 +423,29 @@ enum { } /* + * Ignore the event if a global grab is in effect and the Tk window is + * not in the grabber's subtree. + */ + + if (grabWinPtr && /* There is a grab in effect ... */ + winPtr->dispPtr->grabFlags && /* and it is a global grab ... */ + grabWinPtr->mainPtr == winPtr->mainPtr) { /* in the same application. */ + Tk_Window w; + if (!target) { + return theEvent; + } + for (w = target; !Tk_IsTopLevel(w); w = Tk_Parent(w)) { + if (w == (Tk_Window)grabWinPtr) { + break; + } + } + if (w != (Tk_Window)grabWinPtr) { + /* Force the focus back to the grab window. */ + TkpChangeFocus(grabWinPtr, 1); + } + } + + /* * Translate the current button state into Tk's format. */ @@ -608,10 +634,10 @@ TkMacOSXButtonKeyState(void) Bool XQueryPointer( - Display *display, + TCL_UNUSED(Display *), Window w, - Window *root_return, - Window *child_return, + TCL_UNUSED(Window *), + TCL_UNUSED(Window *), int *root_x_return, int *root_y_return, int *win_x_return, @@ -768,7 +794,7 @@ GenerateButtonEvent( int dummy; TkDisplay *dispPtr; -#if UNUSED +#ifdef UNUSED /* * ButtonDown events will always occur in the front window. ButtonUp diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index b6e3298..5cb8e03 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -592,7 +592,7 @@ UpdateControlValues( MacDrawable *macWin = (MacDrawable *)Tk_WindowId(scrollPtr->tkwin); double dViewSize; HIRect contrlRect; - short width, height; + short height; NSView *view = TkMacOSXGetNSViewForDrawable(macWin); CGFloat viewHeight = [view bounds].size.height; @@ -606,7 +606,6 @@ UpdateControlValues( contrlRect = NSRectToCGRect(frame); msPtr->info.bounds = contrlRect; - width = contrlRect.size.width; height = contrlRect.size.height - scrollPtr->arrowLength; /* diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 7b06200..1bf62d9 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1122,6 +1122,13 @@ TkWmDeadWindow( * preventing zombies is to set the key window to nil. */ + + /* + * Fix bug 5692042764: + * set tkEventTarget to NULL when there is no window to send Tk events to. + */ + TkWindow *newTkEventTarget = NULL; + for (NSWindow *w in [NSApp orderedWindows]) { TkWindow *winPtr2 = TkMacOSXGetTkWindow(w); BOOL isOnScreen; @@ -1134,11 +1141,13 @@ TkWmDeadWindow( wmPtr2->hints.initial_state != WithdrawnState); if (w != deadNSWindow && isOnScreen && [w canBecomeKeyWindow]) { [w makeKeyAndOrderFront:NSApp]; - [NSApp setTkEventTarget:TkMacOSXGetTkWindow(w)]; + newTkEventTarget = TkMacOSXGetTkWindow(w); break; } } + [NSApp setTkEventTarget:newTkEventTarget]; + /* * Prevent zombies on systems with a TouchBar. */ @@ -1149,7 +1158,6 @@ TkWmDeadWindow( } [deadNSWindow close]; [deadNSWindow release]; - [NSApp _resetAutoreleasePool]; #if DEBUG_ZOMBIES > 1 fprintf(stderr, "================= Pool dump ===================\n"); @@ -4848,14 +4856,12 @@ Tk_TopCoordsToWindow( TkWindow *nextPtr; /* Coordinates of highest child found so far * that contains point. */ int x, y; /* Coordinates in winPtr. */ - Window *children; /* Children of winPtr, or NULL. */ winPtr = (TkWindow *)tkwin; x = rootX; y = rootY; while (1) { nextPtr = NULL; - children = NULL; /* * Container windows cannot have children. So if it is a container, diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 52880ef..ddaa226 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1188,6 +1188,7 @@ static void DrawDarkFocusRing( CGPathRef path = CGPathCreateWithRoundedRect(insetBounds, 4, 4, NULL); CGContextBeginPath(context); CGContextAddPath(context, path); + CGPathRelease(path); CGContextAddRect(context, bounds); CGContextEOFillPath(context); CGContextRestoreGState(context); diff --git a/tests/canvPs.test b/tests/canvPs.test index eb09af9..6e24661 100644 --- a/tests/canvPs.test +++ b/tests/canvPs.test @@ -184,6 +184,24 @@ test canvPs-4.1 {test ps generation with single-point uncolored poly, bug 734498 } -returnCodes ok -match glob -result * +test canvPs-5.1 {test ps generation with bitmap, bug 424773a00c} -body { + pack [canvas .c] + update + .c create bitmap 50 50 -bitmap questhead + .c postscript ; # was crashing on macOS +} -cleanup { + destroy .c +} -returnCodes ok -match glob -result * +test canvPs-5.2 {test ps generation with image} -body { + pack [canvas .c] + update + .c create image 50 50 -image ::tk::icons::information + .c postscript +} -cleanup { + destroy .c +} -returnCodes ok -match glob -result * + + # cleanup unset -nocomplain foo bar imageFinish diff --git a/tests/canvWind.test b/tests/canvWind.test index 436ee2c..750321e 100644 --- a/tests/canvWind.test +++ b/tests/canvWind.test @@ -139,6 +139,22 @@ test canvWind-1.4 {DisplayWinItem, windows off-screen horizontally} -setup { destroy .t } -result {{1 3} {1 -79} {0 -79} {1 255} {0 255}} +test canvWind-2.1 {DisplayWinItem, window gets destroyed during <Configure>} -setup { + destroy .t +} -body { + toplevel .t + canvas .t.c + pack .t.c + frame .t.c.f -width 50 -height 50 -background red + set id [.t.c create window 50 50 -window .t.c.f] + update + bind .t.c.f <Configure> {destroy .t.c.f} + .t.c coords $id 60 60 ; # was crashing + update +} -cleanup { + destroy .t +} -result {} + # cleanup cleanupTests return diff --git a/tests/earth.gif b/tests/earth.gif Binary files differindex 2c229eb..d667244 100644 --- a/tests/earth.gif +++ b/tests/earth.gif diff --git a/tests/event.test b/tests/event.test index f0e2311..c521b25 100644 --- a/tests/event.test +++ b/tests/event.test @@ -892,6 +892,60 @@ test event-9 {no <Enter> event is generated for the container window when its } } -result {.top .top.f} +test event-9.1 {enter . window by destroying a toplevel - bug b1d115fa60} -setup { + set EnterBind [bind . <Enter>] +} -body { + wm geometry . 200x200+300+300 + wm deiconify . + _pause 200 + toplevel .top2 -width 200 -height 200 + wm geometry .top2 +[expr {[winfo rootx .]+50}]+[expr {[winfo rooty .]+50}] + wm deiconify .top2 + raise .top2 + _pause 400 + event generate .top2 <Motion> -warp 1 -x 50 -y 50 + _pause 100 + bind . <Enter> {lappend res %W} + set res [list ] + destroy .top2 + _pause 200 + set res +} -cleanup { + deleteWindows + bind . <Enter> $EnterBind +} -result {.} +test event-9.2 {enter toplevel window by destroying a toplevel - bug b1d115fa60} -setup { + set iconified false + if {[winfo ismapped .]} { + wm iconify . + update + set iconified true + } +} -body { + toplevel .top1 + wm geometry .top1 200x200+300+300 + wm deiconify .top1 + _pause 200 + toplevel .top2 -width 200 -height 200 + wm geometry .top2 +[expr {[winfo rootx .top1]+50}]+[expr {[winfo rooty .top1]+50}] + wm deiconify .top2 + raise .top2 + _pause 400 + event generate .top2 <Motion> -warp 1 -x 50 -y 50 + _pause 100 + bind .top1 <Enter> {lappend res %W} + set res [list ] + destroy .top2 + _pause 200 + set res +} -cleanup { + deleteWindows ; # destroy all children of ".", this already includes .top1 + if {$iconified} { + wm deiconify . + update + } +} -result {.top1} + # cleanup update unset -nocomplain keypress_lookup diff --git a/tests/filebox.test b/tests/filebox.test index fdb5614..3c48846 100644 --- a/tests/filebox.test +++ b/tests/filebox.test @@ -74,7 +74,6 @@ proc EnterFileByKey {parent fileName fileDir} { } proc SendButtonPress {parent btn type} { - global tk_strictMotif if {$parent == "."} { set w .__tk_filedialog } else { @@ -210,7 +209,6 @@ foreach mode $modes { # set verylongstring $verylongstring$verylongstring # set verylongstring $verylongstring$verylongstring - set color #404040 test filebox-2.1-$mode "tk_getOpenFile command" nonUnixUserInteraction { ToPressButton $parent cancel tk_getOpenFile -title "Press Cancel ($verylongstring)" -parent $parent @@ -281,9 +279,6 @@ foreach mode $modes { catch {unset tv} catch {unset typeName} ToPressButton $parent ok - if {[info exists tv]} { - } else { - } set choice [tk_getOpenFile -title "Press Ok" \ -filetypes $filters($x) -parent $parent \ -initialfile $fileName -initialdir $fileDir \ @@ -337,20 +332,6 @@ foreach mode $modes { [info commands ::tk::dialog::file::] eq "" }] - set parent . - - set verylongstring longstring: - set verylongstring $verylongstring$verylongstring - set verylongstring $verylongstring$verylongstring - set verylongstring $verylongstring$verylongstring - set verylongstring $verylongstring$verylongstring - # set verylongstring $verylongstring$verylongstring - # set verylongstring $verylongstring$verylongstring - # set verylongstring $verylongstring$verylongstring - # set verylongstring $verylongstring$verylongstring - # set verylongstring $verylongstring$verylongstring - - set color #404040 test filebox-5.1-$mode "tk_getSaveFile command" nonUnixUserInteraction { ToPressButton $parent cancel tk_getSaveFile -title "Press Cancel ($verylongstring)" -parent $parent diff --git a/tests/textBTree.test b/tests/textBTree.test index fd97afa..b1f232c 100644 --- a/tests/textBTree.test +++ b/tests/textBTree.test @@ -257,6 +257,68 @@ test btree-2.21 {deleting with negative range} -body { .t delete 3.2 3.2 .t get 1.0 1000000.0 } -result "Line 1\nLine 2\nLine 3\n" +test btree-2.22 {deleting into beginning of elided range} -setup { + .t delete 1.0 end +} -body { + for {set n 1} {$n <= 10} {incr n} { + .t insert end "Line $n\n" + } + .t tag configure Elided -elide 1 + .t tag add Elided 6.0 end + .t delete 5.0 "5.0 + 8 chars" + .t get 4.0 7.0 +} -cleanup { + .t tag delete Elided + .t delete 1.0 end +} -result "Line 4\nine 6\nLine 7\n" +test btree-2.23 {deleting from within elided range} -body { + for {set n 1} {$n <= 10} {incr n} { + .t insert end "Line $n\n" + } + .t tag configure Elided -elide 1 + .t tag add Elided 6.0 8.0 + .t delete 7.0 9.0 + .t get 6.0 8.0 +} -cleanup { + .t tag delete Elided + .t delete 1.0 end +} -result "Line 6\nLine 9\n" +test btree-2.24 {deleting whole elided range} -body { + for {set n 1} {$n <= 10} {incr n} { + .t insert end "Line $n\n" + } + .t tag configure Elided -elide 1 + .t tag add Elided 6.0 8.0 + .t delete 5.0 9.0 + .t get 4.0 6.0 +} -cleanup { + .t tag delete Elided + .t delete 1.0 end +} -result "Line 4\nLine 9\n" +test btree-2.25 {deleting several elided ranges} -body { + for {set n 1} {$n <= 10} {incr n} { + .t insert end "Line $n\n" + } + .t tag configure Elided -elide 1 + .t tag add Elided 6.0 6.2 6.4 6.5 7.2 7.6 + .t delete 5.0 9.0 + .t get 4.0 7.0 +} -cleanup { + .t tag delete Elided + .t delete 1.0 end +} -result "Line 4\nLine 9\nLine 10\n" +test btree-2.26 {deleting first char of elided range} -body { + for {set n 1} {$n <= 10} {incr n} { + .t insert end "Line $n\n" + } + .t tag configure Elided -elide 1 + .t tag add Elided 6.0 end + .t delete 6.0 6.1 + .t get 5.0 7.0 +} -cleanup { + .t tag delete Elided + .t delete 1.0 end +} -result "Line 5\nine 6\n" test btree-3.1 {inserting with tags} -body { diff --git a/tests/textDisp.test b/tests/textDisp.test index 7310124..6e72c50 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -4755,6 +4755,20 @@ test textDisp-32.3 "NULL undisplayProc problems: #1791052" -setup { image delete $img destroy .tt } +test textDisp-32.4 {Button-1 click with elided lines - Bug 18371b7ce7} -setup { + pack [text .tt -borderwidth 0 -highlightthickness 0] + for {set n 1} {$n <= 5} {incr n} { + .tt insert end "Line $n\n" + } + .tt tag configure Elided -elide 1 + .tt tag add Elided 1.2 4.0 + update +} -body { + event generate .tt <Button-1> -x 1 -y 1 + .tt index insert +} -cleanup { + destroy .tt +} -result {1.0} test textDisp-33.0 {one line longer than fits in the widget} { pack [text .tt -wrap char] diff --git a/tests/textWind.test b/tests/textWind.test index 0b9bd51..bf9ed41 100644 --- a/tests/textWind.test +++ b/tests/textWind.test @@ -1601,7 +1601,7 @@ test textWind-17.10 {peer widget window configuration} -setup { destroy .tt .t } -result {.t.f {} {} .t.f .tt.t.f {} .t.f .tt.t.f .t.f .tt.t.f} -test textWind-18.1 {embedded window deletion triggered by a script bound to <Map>} -constraints knownBug -setup { +test textWind-18.1 {embedded window deletion triggered by a script bound to <Map>} -setup { catch {destroy .t .f .f2} } -body { pack [text .t] @@ -1613,11 +1613,45 @@ test textWind-18.1 {embedded window deletion triggered by a script bound to <Map # this shall not crash (bug 1501749) after 100 {.t yview end} tkwait visibility .f2 + after 200 updateText } -cleanup { destroy .t .f .f2 } -result {} +test textWind-18.2 {text widget deletion triggered by a script bound to embedded window mapping} -setup { + catch {destroy .t .f} +} -body { + pack [text .t] + for {set i 1} {$i < 100} {incr i} {.t insert end "Line $i\n"} + .t window create end -window [frame .f -background red -width 80 -height 80] + bind .f <Map> {destroy .t} + updateText + # this shall not crash (bug 1501749) + after 100 {.t yview end} + tkwait window .t +} -cleanup { + destroy .t .f +} -result {} + +test textWind-18.3 {embedded window destruction in cascade} -setup { + catch {destroy .t .f} + set x 0 +} -body { + pack [text .t] + button .t.b1 + .t window create 1.0 -window .t.b1 + bind .t.b1 <Destroy> {destroy .t.b2 ; set x 1} + button .t.b2 + .t window create 2.0 -window .t.b2 + updateText + # this shall not crash (bug 54fe7a5e71) + after 100 {.t delete 1.0 end} + tkwait variable x +} -cleanup { + destroy .t .f +} -result {} + option clear # cleanup diff --git a/tests/ttk/combobox.test b/tests/ttk/combobox.test index eee0622..bd2dce6 100644 --- a/tests/ttk/combobox.test +++ b/tests/ttk/combobox.test @@ -60,6 +60,11 @@ test combobox-2.7 {current -- set to 0 index when empty [bug 924835c36d]} -body .cb current 0 } -returnCodes error -result {Index 0 out of range} +test combobox-2.8 "current -- set to end index in an empty combobox" -body { + .cb configure -values {} + .cb current end +} -returnCodes error -result {index "end" out of range} + test combobox-2.end "Cleanup" -body { destroy .cb } test combobox-3 "Read postoffset value dynamically from current style" -body { diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test index 3ecbddc..6a1964b 100644 --- a/tests/ttk/treeview.test +++ b/tests/ttk/treeview.test @@ -490,8 +490,9 @@ test treeview-8.8 "<<TreeviewSelect>> when setting the selection" -body { set val 2 .tv selection set myItem1 ; # <<TreeviewSelect>> triggers update + # Current implementation generates an event for this case set val 3 - .tv selection set myItem1 ; # no <<TreeviewSelect>> (already selected) + .tv selection set myItem1 ; # (already selected) update set val 4 .tv selection set {myItem1 myItem2} ; # <<TreeviewSelect>> triggers @@ -500,7 +501,9 @@ test treeview-8.8 "<<TreeviewSelect>> when setting the selection" -body { .tv selection set {myItem2} ; # <<TreeviewSelect>> triggers update set res -} -result {2 4 5} +} -cleanup { + bind .tv <<TreeviewSelect>> {} +} -result {2 3 4 5} test treeview-8.9 "<<TreeviewSelect>> when removing items from the selection" -body { .tv delete [.tv children {}] @@ -519,6 +522,8 @@ test treeview-8.9 "<<TreeviewSelect>> when removing items from the selection" -b .tv selection remove myItem1 ; # no <<TreeviewSelect>> (selection unchanged) update set res +} -cleanup { + bind .tv <<TreeviewSelect>> {} } -result {2} test treeview-8.10 "<<TreeviewSelect>> when adding items in the selection" -body { @@ -539,6 +544,8 @@ test treeview-8.10 "<<TreeviewSelect>> when adding items in the selection" -body .tv selection add myItem3 ; # <<TreeviewSelect>> triggers update set res +} -cleanup { + bind .tv <<TreeviewSelect>> {} } -result {1 3} test treeview-8.11 "<<TreeviewSelect>> when toggling" -body { @@ -562,6 +569,8 @@ test treeview-8.11 "<<TreeviewSelect>> when toggling" -body { .tv selection toggle {myItem3 myItem2} ; # <<TreeviewSelect>> triggers update set res +} -cleanup { + bind .tv <<TreeviewSelect>> {} } -result {2 3 4} ### NEED: more tests for see/yview/scrolling diff --git a/unix/configure b/unix/configure index 0df5407..6fe6752 100755 --- a/unix/configure +++ b/unix/configure @@ -5973,11 +5973,11 @@ fi SHLIB_CFLAGS="" if test "$SHARED_BUILD" = 1; then - SHLIB_LD='ld -shared -expect_unresolved "*"' + SHLIB_LD='${CC} -shared' else - SHLIB_LD='ld -non_shared -expect_unresolved "*"' + SHLIB_LD='${CC} -non_shared' fi diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 6305ef7..739dce3 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1684,9 +1684,9 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ # Digital OSF/1 SHLIB_CFLAGS="" AS_IF([test "$SHARED_BUILD" = 1], [ - SHLIB_LD='ld -shared -expect_unresolved "*"' + SHLIB_LD='${CC} -shared' ], [ - SHLIB_LD='ld -non_shared -expect_unresolved "*"' + SHLIB_LD='${CC} -non_shared' ]) SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" diff --git a/win/configure b/win/configure index 5ff16a4..71fd218 100755 --- a/win/configure +++ b/win/configure @@ -3408,7 +3408,7 @@ fi SHLIB_SUFFIX=".dll" # MACHINE is IX86 for LINK, but this is used by the manifest, - # which requires x86|amd64|ia64. + # which requires x86|amd64|arm64|ia64. MACHINE="X86" if test "$GCC" = "yes"; then @@ -3481,6 +3481,13 @@ echo "${ECHO_T}$ac_cv_cross" >&6 RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; + arm64|aarch64) + CC="aarch64-w64-mingw32-clang" + LD="aarch64-w64-mingw32-ld" + AR="aarch64-w64-mingw32-ar" + RANLIB="aarch64-w64-mingw32-ranlib" + RC="aarch64-w64-mingw32-windres" + ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" @@ -3599,6 +3606,9 @@ echo "${ECHO_T}$ac_cv_win32" >&6 echo "$as_me: error: ${CC} cannot produce win32 executables." >&2;} { (exit 1); exit 1; }; } fi + if test "$do64bit" != "arm64"; then + extra_cflags="$extra_cflags -DHAVE_CPUID=1" + fi hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain" echo "$as_me:$LINENO: checking for working -municode linker flag" >&5 @@ -3892,10 +3902,15 @@ echo "$as_me: error: ${CC} does not support the -shared option. echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 ;; + arm64|aarch64) + MACHINE="ARM64" + echo "$as_me:$LINENO: result: Using ARM64 $MACHINE mode" >&5 +echo "${ECHO_T} Using ARM64 $MACHINE mode" >&6 + ;; ia64) MACHINE="IA64" - echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 -echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 + echo "$as_me:$LINENO: result: Using IA64 $MACHINE mode" >&5 +echo "${ECHO_T} Using IA64 $MACHINE mode" >&6 ;; *) cat >conftest.$ac_ext <<_ACEOF @@ -3949,9 +3964,9 @@ tcl_win_64bit=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "$tcl_win_64bit" = "yes" ; then - do64bit=amd64 - MACHINE="AMD64" - echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 + do64bit=amd64 + MACHINE="AMD64" + echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 fi ;; @@ -3992,6 +4007,9 @@ echo "${ECHO_T}using shared flags" >&6 amd64|x64|yes) MACHINE="AMD64" ; # assume AMD64 as default 64-bit build ;; + arm64|aarch64) + MACHINE="ARM64" + ;; ia64) MACHINE="IA64" ;; @@ -4013,8 +4031,7 @@ echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 if test "$do64bit" != "no" ; then RC="rc" CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d" - # Do not use -O2 for Win64 - this has proved buggy in code gen. - CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}" + CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}" lflags="${lflags} -nologo -MACHINE:${MACHINE}" LINKBIN="link" # Avoid 'unresolved external symbol __security_cookie' errors. diff --git a/win/rules-ext.vc b/win/rules-ext.vc index 6da5689..6d31a03 100644 --- a/win/rules-ext.vc +++ b/win/rules-ext.vc @@ -31,8 +31,13 @@ macro to the name of the project makefile. # We extract version numbers using the nmakehlp program. For now use
# the local copy of nmakehlp. Once we locate Tcl, we will use that
# one if it is newer.
+!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
!if [$(CC) -nologo -DNDEBUG "nmakehlp.c" -link -subsystem:console > nul]
!endif
+!else
+!if [copy x86_64-w64-mingw32-nmakehlp.exe nmakehlp.exe >NUL]
+!endif
+!endif
# First locate the Tcl directory that we are working with.
!if "$(TCLDIR)" != ""
diff --git a/win/rules.vc b/win/rules.vc index c24fce3..372d70a 100644 --- a/win/rules.vc +++ b/win/rules.vc @@ -24,7 +24,7 @@ _RULES_VC = 1 # For modifications that are not backward-compatible, you *must* change
# the major version.
RULES_VERSION_MAJOR = 1
-RULES_VERSION_MINOR = 9
+RULES_VERSION_MINOR = 10
# The PROJECT macro must be defined by parent makefile.
!if "$(PROJECT)" == ""
@@ -411,8 +411,8 @@ _INSTALLDIR=$(_INSTALLDIR)\lib # compiler version 1200. This is kept only for legacy reasons as it
# does not make sense for recent Microsoft compilers. Only used for
# output directory names.
-# ARCH - set to IX86 or AMD64 depending on 32- or 64-bit target
-# NATIVE_ARCH - set to IX86 or AMD64 for the host machine
+# ARCH - set to IX86, ARM64 or AMD64 depending on 32- or 64-bit target
+# NATIVE_ARCH - set to IX86, ARM64 or AMD64 for the host machine
# MACHINE - same as $(ARCH) - legacy
# _VC_MANIFEST_EMBED_{DLL,EXE} - commands for embedding a manifest if needed
@@ -435,6 +435,8 @@ VCVER=0 && ![echo ARCH=IX86 >> vercl.x] \
&& ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
&& ![echo ARCH=AMD64 >> vercl.x] \
+ && ![echo $(_HASH)elif defined(_M_ARM64) >> vercl.x] \
+ && ![echo ARCH=ARM64 >> vercl.x] \
&& ![echo $(_HASH)endif >> vercl.x] \
&& ![$(cc32) -nologo -TC -P vercl.x 2>NUL]
!include vercl.i
@@ -459,6 +461,9 @@ VCVER = $(VCVERSION) !if "$(MACHINE)" == "x86"
!undef MACHINE
MACHINE = IX86
+!elseif "$(MACHINE)" == "arm64"
+!undef MACHINE
+MACHINE = ARM64
!elseif "$(MACHINE)" == "x64"
!undef MACHINE
MACHINE = AMD64
@@ -475,6 +480,8 @@ MACHINE=$(ARCH) # the Tcl platform::identify command
!if "$(MACHINE)" == "AMD64"
PLATFORM_IDENTIFY = win32-x86_64
+!elseif "$(MACHINE)" == "ARM64"
+PLATFORM_IDENTIFY = win32-arm
!else
PLATFORM_IDENTIFY = win32-ix86
!endif
@@ -490,6 +497,8 @@ MULTIPLATFORM_INSTALL = 0 !if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86]
NATIVE_ARCH=IX86
+!elseif ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i ARM | findstr /i 64-bit]
+NATIVE_ARCH=ARM64
!else
NATIVE_ARCH=AMD64
!endif
@@ -541,8 +550,13 @@ NMAKEHLPC = $(_TCLDIR)\win\nmakehlp.c # We always build nmakehlp even if it exists since we do not know
# what source it was built from.
+!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
!if [$(cc32) -nologo "$(NMAKEHLPC)" -link -subsystem:console > nul]
!endif
+!else
+!if [copy $(NMAKEHLPC:nmakehlp.c=x86_64-w64-mingw32-nmakehlp.exe) nmakehlp.exe >NUL]
+!endif
+!endif
################################################################
# 5. Test for compiler features
@@ -1344,7 +1358,7 @@ INCLUDE_INSTALL_DIR = $(_INSTALLDIR)\..\include # baselibs - minimum Windows libraries required. Parent makefile can
# define PRJ_LIBS before including rules.rc if additional libs are needed
-OPTDEFINES = /DSTDC_HEADERS
+OPTDEFINES = /DSTDC_HEADERS /DUSE_NMAKE=1
!if $(VCVERSION) > 1600
OPTDEFINES = $(OPTDEFINES) /DHAVE_STDINT_H=1
!else
@@ -1370,7 +1384,7 @@ OPTDEFINES = $(OPTDEFINES) /DUSE_THREAD_ALLOC=1 OPTDEFINES = $(OPTDEFINES) /DSTATIC_BUILD
!elseif $(TCL_VERSION) > 86
OPTDEFINES = $(OPTDEFINES) /DTCL_WITH_EXTERNAL_TOMMATH
-!if "$(MACHINE)" == "AMD64"
+!if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64"
OPTDEFINES = $(OPTDEFINES) /DMP_64BIT
!endif
!endif
@@ -1398,7 +1412,7 @@ OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_OPTIMIZED !if $(PROFILE)
OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_PROFILED
!endif
-!if "$(MACHINE)" == "AMD64"
+!if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64"
OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_DO64BIT
!endif
!if $(VCVERSION) < 1300
@@ -1460,7 +1474,7 @@ cdebug = $(cdebug) -Zi # cwarn includes default warning levels.
cwarn = $(WARNINGS)
-!if "$(MACHINE)" == "AMD64"
+!if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64"
# Disable pointer<->int warnings related to cast between different sizes
# There are a gadzillion of these due to use of ClientData and
# clutter up compiler
@@ -1476,6 +1490,11 @@ carch = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE carch =
!endif
+# cpuid is only available on intel machines
+!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "AMD64"
+carch = $(carch) /DHAVE_CPUID=1
+!endif
+
!if $(DEBUG)
# Turn warnings into errors
cwarn = $(cwarn) -WX
diff --git a/win/targets.vc b/win/targets.vc index 6bfebc7..077e8f7 100644 --- a/win/targets.vc +++ b/win/targets.vc @@ -4,7 +4,7 @@ # Part of the nmake based build system for Tcl and its extensions.
# This file defines some standard targets for the convenience of extensions
# and can be optionally included by the extension makefile.
-# See TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md) for docs.
+# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for docs.
$(PROJECT): setup pkgindex $(PRJLIB)
@@ -30,7 +30,7 @@ AC_DEFUN([SC_PATH_TCLCONFIG], [ AC_ARG_WITH(tcl, AS_HELP_STRING([--with-tcl], [directory containing tcl configuration (tclConfig.sh)]), - with_tclconfig="${withval}") + [with_tclconfig="${withval}"]) AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ @@ -148,7 +148,7 @@ AC_DEFUN([SC_PATH_TKCONFIG], [ AC_ARG_WITH(tk, AS_HELP_STRING([--with-tk], [directory containing tk configuration (tkConfig.sh)]), - with_tkconfig="${withval}") + [with_tkconfig="${withval}"]) AC_MSG_CHECKING([for Tk configuration]) AC_CACHE_VAL(ac_cv_c_tkconfig,[ @@ -557,7 +557,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ SHLIB_SUFFIX=".dll" # MACHINE is IX86 for LINK, but this is used by the manifest, - # which requires x86|amd64|ia64. + # which requires x86|amd64|arm64|ia64. MACHINE="X86" if test "$GCC" = "yes"; then @@ -582,6 +582,13 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; + arm64|aarch64) + CC="aarch64-w64-mingw32-clang" + LD="aarch64-w64-mingw32-ld" + AR="aarch64-w64-mingw32-ar" + RANLIB="aarch64-w64-mingw32-ranlib" + RC="aarch64-w64-mingw32-windres" + ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" @@ -642,6 +649,9 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ if test "$ac_cv_win32" != "yes"; then AC_MSG_ERROR([${CC} cannot produce win32 executables.]) fi + if test "$do64bit" != "arm64"; then + extra_cflags="$extra_cflags -DHAVE_CPUID=1" + fi hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain" AC_CACHE_CHECK(for working -municode linker flag, @@ -783,9 +793,13 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ MACHINE="AMD64" ; # assume AMD64 as default 64-bit build AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) ;; + arm64|aarch64) + MACHINE="ARM64" + AC_MSG_RESULT([ Using ARM64 $MACHINE mode]) + ;; ia64) MACHINE="IA64" - AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) + AC_MSG_RESULT([ Using IA64 $MACHINE mode]) ;; *) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @@ -797,9 +811,9 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ [tcl_win_64bit=no] ) if test "$tcl_win_64bit" = "yes" ; then - do64bit=amd64 - MACHINE="AMD64" - AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) + do64bit=amd64 + MACHINE="AMD64" + AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) fi ;; esac @@ -837,6 +851,9 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ amd64|x64|yes) MACHINE="AMD64" ; # assume AMD64 as default 64-bit build ;; + arm64|aarch64) + MACHINE="ARM64" + ;; ia64) MACHINE="IA64" ;; @@ -857,8 +874,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ if test "$do64bit" != "no" ; then RC="rc" CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d" - # Do not use -O2 for Win64 - this has proved buggy in code gen. - CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}" + CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}" lflags="${lflags} -nologo -MACHINE:${MACHINE}" LINKBIN="link" # Avoid 'unresolved external symbol __security_cookie' errors. diff --git a/win/tkWin32Dll.c b/win/tkWin32Dll.c index 802b1f3..5161333 100644 --- a/win/tkWin32Dll.c +++ b/win/tkWin32Dll.c @@ -101,7 +101,7 @@ DllMain( DWORD reason, LPVOID reserved) { -#ifdef HAVE_NO_SEH +#if defined(HAVE_NO_SEH) && !defined(__aarch64__) TCLEXCEPTION_REGISTRATION registration; #endif @@ -123,7 +123,9 @@ DllMain( */ #ifdef HAVE_NO_SEH -# ifdef _WIN64 +# if defined(__aarch64__) + /* Don't run TkFinalize(NULL) on mingw-w64 for ARM64, since we don't have corresponding assembler-code. */ +# elif defined(_WIN64) __asm__ __volatile__ ( /* diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index bcea1c1..840938d 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -55,16 +55,16 @@ TkSelGetSelection( Tcl_Encoding encoding; int result, locale, noBackslash = 0; + if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD")) + || (target != XA_STRING)) { + goto error; + } if (!OpenClipboard(NULL)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "clipboard cannot be opened, another application grabbed it")); Tcl_SetErrorCode(interp, "TK", "CLIPBOARD", "BUSY", NULL); return TCL_ERROR; } - if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD")) - || (target != XA_STRING)) { - goto error; - } /* * Attempt to get the data in Unicode form if available as this is less diff --git a/win/tkWinColor.c b/win/tkWinColor.c index fa3f233..1312bcb 100644 --- a/win/tkWinColor.c +++ b/win/tkWinColor.c @@ -173,7 +173,7 @@ TkpGetColor( && FindSystemColor(name+6, &color, &index)) || TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name, &color)) { - winColPtr = ckalloc(sizeof(WinColor)); + winColPtr = (WinColor *)ckalloc(sizeof(WinColor)); winColPtr->info.color = color; winColPtr->index = index; @@ -211,7 +211,7 @@ TkpGetColorByValue( XColor *colorPtr) /* Red, green, and blue fields indicate * desired color. */ { - WinColor *tkColPtr = ckalloc(sizeof(WinColor)); + WinColor *tkColPtr = (WinColor *)ckalloc(sizeof(WinColor)); tkColPtr->info.color.red = colorPtr->red; tkColPtr->info.color.green = colorPtr->green; @@ -274,7 +274,7 @@ int TkWinIndexOfColor( XColor *colorPtr) { - register WinColor *winColPtr = (WinColor *) colorPtr; + WinColor *winColPtr = (WinColor *) colorPtr; if (winColPtr->info.magic == COLOR_MAGIC) { return winColPtr->index; } @@ -300,7 +300,7 @@ TkWinIndexOfColor( int XAllocColor( - Display *display, + TCL_UNUSED(Display *), Colormap colormap, XColor *color) { @@ -316,7 +316,7 @@ XAllocColor( if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) { unsigned long sizePalette = GetDeviceCaps(dc, SIZEPALETTE); UINT newPixel, closePixel; - int new; + int isNew; size_t refCount; Tcl_HashEntry *entryPtr; UINT index; @@ -358,13 +358,13 @@ XAllocColor( color->pixel = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue); entryPtr = Tcl_CreateHashEntry(&cmap->refCounts, - INT2PTR(color->pixel), &new); - if (new) { + INT2PTR(color->pixel), &isNew); + if (isNew) { refCount = 1; } else { refCount = (size_t)Tcl_GetHashValue(entryPtr) + 1; } - Tcl_SetHashValue(entryPtr, (void *)refCount); + Tcl_SetHashValue(entryPtr, INT2PTR(refCount)); } else { /* * Determine what color will actually be used on non-colormap systems. @@ -400,11 +400,11 @@ XAllocColor( int XFreeColors( - Display *display, + TCL_UNUSED(Display *), Colormap colormap, unsigned long *pixels, int npixels, - unsigned long planes) + TCL_UNUSED(unsigned long)) { TkWinColormap *cmap = (TkWinColormap *) colormap; COLORREF cref; @@ -436,7 +436,7 @@ XFreeColors( GetPaletteEntries(cmap->palette, index, 1, &entry); if (cref == RGB(entry.peRed, entry.peGreen, entry.peBlue)) { count = cmap->size - index; - entries = ckalloc(sizeof(PALETTEENTRY) * count); + entries = (PALETTEENTRY *)ckalloc(sizeof(PALETTEENTRY) * count); GetPaletteEntries(cmap->palette, index+1, count, entries); SetPaletteEntries(cmap->palette, index, count, entries); ckfree(entries); @@ -446,7 +446,7 @@ XFreeColors( } Tcl_DeleteHashEntry(entryPtr); } else { - Tcl_SetHashValue(entryPtr, (size_t)refCount); + Tcl_SetHashValue(entryPtr, INT2PTR(refCount)); } } } @@ -472,17 +472,17 @@ XFreeColors( Colormap XCreateColormap( - Display *display, - Window w, - Visual *visual, - int alloc) + TCL_UNUSED(Display *), + TCL_UNUSED(Window), + TCL_UNUSED(Visual *), + TCL_UNUSED(int)) { char logPalBuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)]; LOGPALETTE *logPalettePtr; PALETTEENTRY *entryPtr; TkWinColormap *cmap; Tcl_HashEntry *hashPtr; - int new; + int isNew; UINT i; HPALETTE sysPal; @@ -496,7 +496,7 @@ XCreateColormap( logPalettePtr->palNumEntries = GetPaletteEntries(sysPal, 0, 256, logPalettePtr->palPalEntry); - cmap = ckalloc(sizeof(TkWinColormap)); + cmap = (TkWinColormap *)ckalloc(sizeof(TkWinColormap)); cmap->size = logPalettePtr->palNumEntries; cmap->stale = 0; cmap->palette = CreatePalette(logPalettePtr); @@ -509,7 +509,7 @@ XCreateColormap( for (i = 0; i < logPalettePtr->palNumEntries; i++) { entryPtr = logPalettePtr->palPalEntry + i; hashPtr = Tcl_CreateHashEntry(&cmap->refCounts, INT2PTR(PALETTERGB( - entryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue)), &new); + entryPtr->peRed, entryPtr->peGreen, entryPtr->peBlue)), &isNew); Tcl_SetHashValue(hashPtr, INT2PTR(1)); } @@ -535,7 +535,7 @@ XCreateColormap( int XFreeColormap( - Display *display, + TCL_UNUSED(Display *), Colormap colormap) { TkWinColormap *cmap = (TkWinColormap *) colormap; diff --git a/win/tkWinKey.c b/win/tkWinKey.c index 0cd086c..e1ec558 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -90,7 +90,7 @@ static KeySym KeycodeToKeysym(unsigned int keycode, const char * TkpGetString( - TkWindow *winPtr, /* Window where event occurred: needed to get + TCL_UNUSED(TkWindow *), /* Window where event occurred: needed to get * input context. */ XEvent *eventPtr, /* X keyboard event. */ Tcl_DString *dsPtr) /* Uninitialized or empty string to hold @@ -151,7 +151,7 @@ TkpGetString( KeySym XKeycodeToKeysym( - Display *display, + TCL_UNUSED(Display *), unsigned int keycode, int index) { @@ -505,7 +505,7 @@ TkpInitKeymapInfo( } dispPtr->numModKeyCodes = 0; arraySize = KEYCODE_ARRAY_SIZE; - dispPtr->modKeyCodes = ckalloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode)); + dispPtr->modKeyCodes = (KeyCode *)ckalloc(KEYCODE_ARRAY_SIZE * sizeof(KeyCode)); for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) { if (*codePtr == 0) { continue; @@ -521,18 +521,18 @@ TkpInitKeymapInfo( } } if (dispPtr->numModKeyCodes >= arraySize) { - KeyCode *new; + KeyCode *newKey; /* * Ran out of space in the array; grow it. */ arraySize *= 2; - new = ckalloc(arraySize * sizeof(KeyCode)); - memcpy(new, dispPtr->modKeyCodes, + newKey = (KeyCode *)ckalloc(arraySize * sizeof(KeyCode)); + memcpy(newKey, dispPtr->modKeyCodes, dispPtr->numModKeyCodes * sizeof(KeyCode)); ckfree(dispPtr->modKeyCodes); - dispPtr->modKeyCodes = new; + dispPtr->modKeyCodes = newKey; } dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr; dispPtr->numModKeyCodes++; @@ -549,7 +549,7 @@ TkpInitKeymapInfo( void TkpSetKeycodeAndState( - Tk_Window tkwin, + TCL_UNUSED(Tk_Window), KeySym keySym, XEvent *eventPtr) { @@ -607,7 +607,7 @@ TkpSetKeycodeAndState( KeyCode XKeysymToKeycode( - Display *display, + TCL_UNUSED(Display *), KeySym keysym) { int i; @@ -655,12 +655,12 @@ XKeysymToKeycode( XModifierKeymap * XGetModifierMapping( - Display *display) + TCL_UNUSED(Display *)) { - XModifierKeymap *map = ckalloc(sizeof(XModifierKeymap)); + XModifierKeymap *map = (XModifierKeymap *)ckalloc(sizeof(XModifierKeymap)); map->max_keypermod = 1; - map->modifiermap = ckalloc(sizeof(KeyCode) * 8); + map->modifiermap = (KeyCode *)ckalloc(sizeof(KeyCode) * 8); map->modifiermap[ShiftMapIndex] = VK_SHIFT; map->modifiermap[LockMapIndex] = VK_CAPITAL; map->modifiermap[ControlMapIndex] = VK_CONTROL; @@ -716,7 +716,7 @@ XFreeModifiermap( KeySym XStringToKeysym( - _Xconst char *string) + TCL_UNUSED(_Xconst char *)) { return NoSymbol; } @@ -739,7 +739,7 @@ XStringToKeysym( char * XKeysymToString( - KeySym keysym) + TCL_UNUSED(KeySym)) { return NULL; } diff --git a/win/tkWinTest.c b/win/tkWinTest.c index a202ba5..8a292b3 100644 --- a/win/tkWinTest.c +++ b/win/tkWinTest.c @@ -301,7 +301,7 @@ TestwineventObjCmd( if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), "debug") == 0)) { int b; - if (Tcl_GetBoolean(interp, Tcl_GetString(objv[2]), &b) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, objv[2], &b) != TCL_OK) { return TCL_ERROR; } TkWinDialogDebug(b); diff --git a/win/tkWinWindow.c b/win/tkWinWindow.c index 56fc87c..e5990e5 100644 --- a/win/tkWinWindow.c +++ b/win/tkWinWindow.c @@ -49,7 +49,7 @@ Tk_AttachHWND( Tk_Window tkwin, HWND hwnd) { - int new; + int isNew; Tcl_HashEntry *entryPtr; TkWinDrawable *twdPtr = (TkWinDrawable *) Tk_WindowId(tkwin); ThreadSpecificData *tsdPtr = (ThreadSpecificData *) @@ -66,12 +66,12 @@ Tk_AttachHWND( */ if (twdPtr == NULL) { - twdPtr = ckalloc(sizeof(TkWinDrawable)); + twdPtr = (TkWinDrawable *)ckalloc(sizeof(TkWinDrawable)); twdPtr->type = TWD_WINDOW; twdPtr->window.winPtr = (TkWindow *) tkwin; } else if (twdPtr->window.handle != NULL) { entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, - (char *)twdPtr->window.handle); + twdPtr->window.handle); Tcl_DeleteHashEntry(entryPtr); } @@ -80,7 +80,7 @@ Tk_AttachHWND( */ twdPtr->window.handle = hwnd; - entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &new); + entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &isNew); Tcl_SetHashValue(entryPtr, tkwin); return (Window)twdPtr; @@ -115,7 +115,7 @@ Tk_HWNDToWindow( Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS); tsdPtr->initialized = 1; } - entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char *) hwnd); + entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, hwnd); if (entryPtr != NULL) { return (Tk_Window) Tcl_GetHashValue(entryPtr); } @@ -314,7 +314,7 @@ XDestroyWindow( TkPointerDeadWindow(winPtr); - entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char*)hwnd); + entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, hwnd); if (entryPtr != NULL) { Tcl_DeleteHashEntry(entryPtr); } diff --git a/win/x86_64-w64-mingw32-nmakehlp.exe b/win/x86_64-w64-mingw32-nmakehlp.exe Binary files differnew file mode 100755 index 0000000..2564ec9 --- /dev/null +++ b/win/x86_64-w64-mingw32-nmakehlp.exe |