diff options
-rw-r--r-- | doc/FindPhoto.3 | 57 | ||||
-rw-r--r-- | doc/ttk_button.n | 1 | ||||
-rw-r--r-- | doc/ttk_frame.n | 6 | ||||
-rw-r--r-- | doc/ttk_image.n | 20 | ||||
-rw-r--r-- | doc/ttk_label.n | 10 | ||||
-rw-r--r-- | doc/ttk_labelframe.n | 6 | ||||
-rw-r--r-- | doc/ttk_notebook.n | 6 | ||||
-rw-r--r-- | doc/ttk_panedwindow.n | 3 | ||||
-rw-r--r-- | doc/ttk_treeview.n | 5 | ||||
-rw-r--r-- | doc/ttk_vsapi.n | 7 | ||||
-rw-r--r-- | doc/ttk_widget.n | 47 | ||||
-rw-r--r-- | generic/tkBind.c | 25 | ||||
-rw-r--r-- | generic/tkImgPhInstance.c | 2 | ||||
-rw-r--r-- | generic/tkImgPhoto.c | 166 | ||||
-rw-r--r-- | generic/tkTextBTree.c | 6 | ||||
-rw-r--r-- | generic/ttk/ttkNotebook.c | 27 | ||||
-rw-r--r-- | macosx/tkMacOSXDialog.c | 80 | ||||
-rw-r--r-- | macosx/tkMacOSXScrlbr.c | 81 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 5 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.h | 4 | ||||
-rw-r--r-- | tests/color.test | 24 | ||||
-rw-r--r-- | tests/imgBmap.test | 3 | ||||
-rw-r--r-- | tests/imgPhoto.test | 117 | ||||
-rw-r--r-- | xlib/xcolors.c | 10 | ||||
-rw-r--r-- | xlib/xgc.c | 2 |
25 files changed, 521 insertions, 199 deletions
diff --git a/doc/FindPhoto.3 b/doc/FindPhoto.3 index e4d83f0..dc218bf 100644 --- a/doc/FindPhoto.3 +++ b/doc/FindPhoto.3 @@ -4,7 +4,7 @@ '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" '\" Author: Paul Mackerras (paulus@cs.anu.edu.au), '\" Department of Computer Science, '\" Australian National University. @@ -99,8 +99,8 @@ being written to the photo image. particular photo image to the other procedures. The parameter is the name of the image, that is, the name specified to the \fBimage create photo\fR command, or assigned by that command if no name was specified. -If \fIimageName\fR does not exist or is not a photo image, -\fBTk_FindPhoto\fR returns NULL. +If \fIimageName\fR does not exist or is not a photo image, +\fBTk_FindPhoto\fR returns NULL. .PP \fBTk_PhotoPutBlock\fR is used to supply blocks of image data to be displayed. The call affects an area of the image of size @@ -130,14 +130,23 @@ The \fIpixelPtr\fR field points to the first pixel, that is, the top-left pixel in the block. The \fIwidth\fR and \fIheight\fR fields specify the dimensions of the block of pixels. The \fIpixelSize\fR field specifies the address -difference between two horizontally adjacent pixels. Often it is 3 -or 4, but it can have any value. The \fIpitch\fR field specifies the +difference between two horizontally adjacent pixels. It should be 4 for +RGB and 2 for grayscale image data. Other values are possible, if the +offsets in the \fIoffset\fR array are adjusted accordingly (e.g. for +red, green and blue data stored in different planes). Using such a +layout is strongly discouraged, though. Due to a bug, it might not work +correctly if an alpha channel is provided. (see the \fBBUGS\fR section +below). The \fIpitch\fR field specifies the address difference between two vertically adjacent pixels. The \fIoffset\fR array contains the offsets from the address of a pixel to the addresses of the bytes containing the red, green, blue and alpha -(transparency) components. These are normally 0, 1, 2 and 3, but can -have other values, e.g., for images that are stored as separate red, -green and blue planes. +(transparency) components. If the offsets for red, green and blue are +equal, the image is interpreted as grayscale. If they differ, RGB data +is assumed. Normally the offsets will be 0, 1, 2, 3 for RGB data +and 0, 0, 0, 1 for grayscale. It is possible to provide image data +without an alpha channel by setting the offset for alpha to a negative +value and adjusting the \fIpixelSize\fR field accordingly. This use is +discouraged, though (see the \fBBUGS\fR section below). .PP The \fIcompRule\fR parameter to \fBTk_PhotoPutBlock\fR specifies a compositing rule that says what to do with transparent pixels. The @@ -184,16 +193,16 @@ that describe the address and layout of the image data that the photo image has stored internally. The values are valid until the image is destroyed or its size is changed. .PP -It is possible to modify an image by writing directly to the data +It is possible to modify an image by writing directly to the data the \fIpixelPtr\fR field points to. The size of the image cannot be changed this way, though. -Also, changes made by writing directly to \fIpixelPtr\fR will not be -immediately visible, but only after a call to -\fBTk_ImageChanged\fR or after an event that causes the interested +Also, changes made by writing directly to \fIpixelPtr\fR will not be +immediately visible, but only after a call to +\fBTk_ImageChanged\fR or after an event that causes the interested widgets to redraw themselves. -For these reasons usually it is preferable to make changes to -a copy of the image data and write it back with -\fBTk_PhotoPutBlock\fR or \fBTk_PhotoPutZoomedBlock\fR. +For these reasons usually it is preferable to make changes to +a copy of the image data and write it back with +\fBTk_PhotoPutBlock\fR or \fBTk_PhotoPutZoomedBlock\fR. .PP \fBTk_PhotoGetImage\fR returns 1 for compatibility with the corresponding procedure in the old photo widget. @@ -248,6 +257,24 @@ memory was available for an image, Tk would panic. This behaviour is still supported if you compile your extension with the additional flag -DUSE_PANIC_ON_PHOTO_ALLOC_FAILURE. Code linked using Stubs against older versions of Tk will continue to work. +.SH BUGS +The \fBTk_PhotoImageBlock\fR structure used to provide image data to +\fBTk_PhotoPutBlock\fR promises great flexibility in the layout of the +data (e.g. separate planes for the red, green, blue and alpha +channels). Unfortunately, the implementation fails to hold this +promise. The problem is that the \fIpixelSize\fR field is +(incorrectly) used to determine whether the image has an alpha channel. +Currently, if the offset for the alpha channel is greater or equal than +\fIpixelSize\fR, \fBtk_PhotoPutblock\fR assumes no alpha data is +present and makes the image fully opaque. This means that for layouts +where the channels are separate (or any other exotic layout where +\fIpixelSize\fR has to be smaller than the alpha offset), the alpha +channel will not be read correctly. In order to be on the safe side +if this issue will be corrected in a future release, it is strongly +recommended you always provide alpha data - even if the image has no +transparency - and only use the "standard" layout with a +\fIpixelSize\fR of 2 for grayscale and 4 for RGB data with +\fIoffset\fRs of 0, 0, 0, 1 or 0, 1, 2, 3 respectively. .SH CREDITS .PP The code for the photo image type was developed by Paul Mackerras, diff --git a/doc/ttk_button.n b/doc/ttk_button.n index 62ebe47..b84ca48 100644 --- a/doc/ttk_button.n +++ b/doc/ttk_button.n @@ -51,7 +51,6 @@ in the style. .\" .OP \-foreground foreground Foreground .\" .OP \-font font Font .\" .OP \-anchor anchor Anchor -.\" .OP \-padding padding Padding .\" .OP \-relief relief Relief .SH "WIDGET COMMAND" .PP diff --git a/doc/ttk_frame.n b/doc/ttk_frame.n index b54ce96..d2bd745 100644 --- a/doc/ttk_frame.n +++ b/doc/ttk_frame.n @@ -17,8 +17,8 @@ ttk::frame \- Simple container widget A \fBttk::frame\fR widget is a container, used to group other widgets together. .SO ttk_widget -\-class \-cursor \-takefocus -\-style +\-class \-cursor \-padding \-style +\-takefocus .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-borderwidth borderWidth BorderWidth @@ -28,8 +28,6 @@ One of the standard Tk border styles: \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, \fBsolid\fR, or \fBsunken\fR. Defaults to \fBflat\fR. -.OP \-padding padding Padding -Additional padding to include inside the border. .OP \-width width Width If specified, the widget's requested width in pixels. .OP \-height height Height diff --git a/doc/ttk_image.n b/doc/ttk_image.n index 4985c20..bc1dd3f 100644 --- a/doc/ttk_image.n +++ b/doc/ttk_image.n @@ -29,6 +29,13 @@ Valid \fIoptions\fR are: \fB\-border\fR \fIpadding\fR \fIpadding\fR is a list of up to four integers, specifying the left, top, right, and bottom borders, respectively. +If fewer than four elements are specified, +\fIbottom\fR defaults to \fItop\fR, +\fIright\fR defaults to \fIleft\fR, and +\fItop\fR defaults to \fIleft\fR. +In other words, a list of three numbers specify the left, vertical, and right border; +a list of two numbers specify the horizontal and the vertical border; +a single number specifies the same border all the way around the element. See \fBIMAGE STRETCHING\fR, below. .TP \fB\-height \fIheight\fR @@ -36,8 +43,17 @@ Specifies a minimum height for the element. If less than zero, the base image's height is used as a default. .TP \fB\-padding\fR \fIpadding\fR -Specifies the element's interior padding. Defaults to -\fB\-border\fR if not specified. +Specifies the element's interior padding. +The padding is a list of up to four length specifications +\fIleft top right bottom\fR. +If fewer than four elements are specified, +\fIbottom\fR defaults to \fItop\fR, +\fIright\fR defaults to \fIleft\fR, and +\fItop\fR defaults to \fIleft\fR. +In other words, a list of three numbers specify the left, vertical, and right padding; +a list of two numbers specify the horizontal and the vertical padding; +a single number specifies the same padding all the way around the widget. +Defaults to \fB\-border\fR if not specified. .TP \fB\-sticky\fR \fIspec\fR Specifies how the image is placed within the final parcel. diff --git a/doc/ttk_label.n b/doc/ttk_label.n index 6781b47..9c28d7c 100644 --- a/doc/ttk_label.n +++ b/doc/ttk_label.n @@ -19,7 +19,7 @@ The label may be linked to a Tcl variable to automatically change the displayed text. .SO ttk_widget \-class \-compound \-cursor -\-image \-style \-takefocus +\-image \-padding \-style \-takefocus \-text \-textvariable \-underline \-width .SE @@ -43,14 +43,6 @@ If there are multiple lines of text, specifies how the lines are laid out relative to one another. One of \fBleft\fR, \fBcenter\fR, or \fBright\fR. See also \fB\-anchor\fR. -.OP \-padding padding Padding -Specifies the amount of extra space to allocate for the widget. -The padding is a list of up to four length specifications -\fIleft top right bottom\fR. -If fewer than four elements are specified, -\fIbottom\fR defaults to \fItop\fR, -\fIright\fR defaults to \fIleft\fR, and -\fItop\fR defaults to \fIleft\fR. .OP \-relief relief Relief .\" Rewrite this: Specifies the 3-D effect desired for the widget border. diff --git a/doc/ttk_labelframe.n b/doc/ttk_labelframe.n index 64edf6a..4c2c8d5 100644 --- a/doc/ttk_labelframe.n +++ b/doc/ttk_labelframe.n @@ -18,8 +18,8 @@ A \fBttk::labelframe\fR widget is a container used to group other widgets together. It has an optional label, which may be a plain text string or another widget. .SO ttk_widget -\-class \-cursor \-takefocus -\-style +\-class \-cursor \-padding \-style +\-takefocus .SE .SH "WIDGET-SPECIFIC OPTIONS" .\" XXX: Currently included, but may go away: @@ -48,8 +48,6 @@ underline in the text string. The underlined character is used for mnemonic activation. Mnemonic activation for a \fBttk::labelframe\fR sets the keyboard focus to the first child of the \fBttk::labelframe\fR widget. -.OP \-padding padding Padding -Additional padding to include inside the border. .OP \-labelwidget labelWidget LabelWidget The name of a widget to use for the label. If set, overrides the \fB\-text\fR option. diff --git a/doc/ttk_notebook.n b/doc/ttk_notebook.n index 4d1b789..e2ae137 100644 --- a/doc/ttk_notebook.n +++ b/doc/ttk_notebook.n @@ -41,6 +41,9 @@ If fewer than four elements are specified, \fIbottom\fR defaults to \fItop\fR, \fIright\fR defaults to \fIleft\fR, and \fItop\fR defaults to \fIleft\fR. +In other words, a list of three numbers specify the left, vertical, and right padding; +a list of two numbers specify the horizontal and the vertical padding; +a single number specifies the same padding all the way around the widget. .OP \-width width Width If present and greater than zero, specifies the desired width of the pane area @@ -171,7 +174,8 @@ Otherwise, sets the \fI\-option\fRs to the corresponding \fIvalue\fRs. See \fBTAB OPTIONS\fR for the available options. .TP \fIpathname \fBtabs\fR -Returns the list of windows managed by the notebook. +Returns the list of windows managed by the notebook, in the index order of +their associated tabs. .SH "KEYBOARD TRAVERSAL" To enable keyboard traversal for a toplevel window containing a notebook widget \fI$nb\fR, call: diff --git a/doc/ttk_panedwindow.n b/doc/ttk_panedwindow.n index 29fca1d..4ba42bc 100644 --- a/doc/ttk_panedwindow.n +++ b/doc/ttk_panedwindow.n @@ -91,7 +91,8 @@ If one \fI\-option\fR is specified, returns the value of that \fIoption\fR. Otherwise, sets the \fI\-option\fRs to the corresponding \fIvalue\fRs. .TP \fIpathname \fBpanes\fR -Returns the list of all windows managed by the widget. +Returns the list of all windows managed by the widget, in the index order of +their associated panes. .TP \fIpathname \fBsashpos \fIindex\fR ?\fInewpos\fR? If \fInewpos\fR is specified, sets the position diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n index 660b076..8399a09 100644 --- a/doc/ttk_treeview.n +++ b/doc/ttk_treeview.n @@ -45,6 +45,7 @@ and [\fBxy\fR]\fBview\fR widget commands. .SO ttk_widget \-class \-cursor \-takefocus \-style \-xscrollcommand \-yscrollcommand +\-padding .SE .SH "WIDGET-SPECIFIC OPTIONS" .OP \-columns columns Columns @@ -63,10 +64,6 @@ all columns are shown in the order given. Specifies the number of rows which should be visible. Note: the requested width is determined from the sum of the column widths. -.OP \-padding padding Padding -Specifies the internal padding for the widget. -The padding is a list of up to four length specifications; -see \fBTtk_GetPaddingFromObj()\fR for details. .OP \-selectmode selectMode SelectMode Controls how the built-in class bindings manage the selection. One of \fBextended\fR, \fBbrowse\fR, or \fBnone\fR. diff --git a/doc/ttk_vsapi.n b/doc/ttk_vsapi.n index 4d5c3eb..af63c39 100644 --- a/doc/ttk_vsapi.n +++ b/doc/ttk_vsapi.n @@ -34,6 +34,13 @@ Valid \fIoptions\fR are: Specify the element's interior padding. \fIpadding\fR is a list of up to four integers specifying the left, top, right and bottom padding quantities respectively. +If fewer than four elements are specified, +\fIbottom\fR defaults to \fItop\fR, +\fIright\fR defaults to \fIleft\fR, and +\fItop\fR defaults to \fIleft\fR. +In other words, a list of three numbers specify the left, vertical, and right padding; +a list of two numbers specify the horizontal and the vertical padding; +a single number specifies the same padding all the way around the widget. This option may not be mixed with any other options. .TP \fB\-margins \fIpadding\fR diff --git a/doc/ttk_widget.n b/doc/ttk_widget.n index 2ecc29f..d362bba 100644 --- a/doc/ttk_widget.n +++ b/doc/ttk_widget.n @@ -71,24 +71,6 @@ See the description of \fB\-xscrollcommand\fR above for details. .SH "LABEL OPTIONS" The following options are supported by labels, buttons, and other button-like widgets: -.OP \-text text Text -Specifies a text string to be displayed inside the widget -(unless overridden by \fB\-textvariable\fR). -.OP \-textvariable textVariable Variable -Specifies the name of a global variable whose value will be used -in place of the \fB\-text\fR resource. -.OP \-underline underline Underline -If set, specifies the integer index (0-based) of a character to underline -in the text string. -The underlined character is used for mnemonic activation. -.OP \-image image Image -Specifies an image to display. -This is a list of 1 or more elements. -The first element is the default image name. -The rest of the list is a sequence of \fIstatespec / value\fR pairs -as per \fBstyle map\fR, specifying different images to use when -the widget is in a particular state or combination of states. -All images in the list should have the same size. .OP \-compound compound Compound Specifies how to display the image relative to the text, in the case both \fB\-text\fR and \fB\-image\fR are present. @@ -108,6 +90,35 @@ Display image above, below, left of, or right of the text, respectively. .IP none The default; display the image if present, otherwise the text. .RE +.OP \-image image Image +Specifies an image to display. +This is a list of 1 or more elements. +The first element is the default image name. +The rest of the list is a sequence of \fIstatespec / value\fR pairs +as per \fBstyle map\fR, specifying different images to use when +the widget is in a particular state or combination of states. +All images in the list should have the same size. +.OP \-padding padding Padding +Specifies the internal padding for the widget. +The padding is a list of up to four length specifications +\fIleft top right bottom\fR. +If fewer than four elements are specified, +\fIbottom\fR defaults to \fItop\fR, +\fIright\fR defaults to \fIleft\fR, and +\fItop\fR defaults to \fIleft\fR. +In other words, a list of three numbers specify the left, vertical, and right padding; +a list of two numbers specify the horizontal and the vertical padding; +a single number specifies the same padding all the way around the widget. +.OP \-text text Text +Specifies a text string to be displayed inside the widget +(unless overridden by \fB\-textvariable\fR). +.OP \-textvariable textVariable Variable +Specifies the name of a global variable whose value will be used +in place of the \fB\-text\fR resource. +.OP \-underline underline Underline +If set, specifies the integer index (0-based) of a character to underline +in the text string. +The underlined character is used for mnemonic activation. .OP \-width width Width If greater than zero, specifies how much space, in character widths, to allocate for the text label. diff --git a/generic/tkBind.c b/generic/tkBind.c index 567c51f..61b44df 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -3466,12 +3466,28 @@ HandleEventGenerate( if ((warp != 0) && Tk_IsMapped(tkwin)) { TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display); + /* + * TODO: No protection is in place to handle dispPtr destruction + * before DoWarp is called back. + */ + + Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display, + event.general.xmotion.window); + if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) { Tcl_DoWhenIdle(DoWarp, dispPtr); dispPtr->flags |= TK_DISPLAY_IN_WARP; } - dispPtr->warpWindow = Tk_IdToWindow(dispPtr->display, - event.general.xmotion.window); + + if (warpWindow != dispPtr->warpWindow) { + if (warpWindow) { + Tcl_Preserve(warpWindow); + } + if (dispPtr->warpWindow) { + Tcl_Release(dispPtr->warpWindow); + } + dispPtr->warpWindow = warpWindow; + } dispPtr->warpMainwin = mainWin; dispPtr->warpX = event.general.xmotion.x; dispPtr->warpY = event.general.xmotion.y; @@ -3559,6 +3575,11 @@ DoWarp( TkpWarpPointer(dispPtr); XForceScreenSaver(dispPtr->display, ScreenSaverReset); } + + if (dispPtr->warpWindow) { + Tcl_Release(dispPtr->warpWindow); + dispPtr->warpWindow = None; + } dispPtr->flags &= ~TK_DISPLAY_IN_WARP; } diff --git a/generic/tkImgPhInstance.c b/generic/tkImgPhInstance.c index 98aaeab..fd98c6e 100644 --- a/generic/tkImgPhInstance.c +++ b/generic/tkImgPhInstance.c @@ -1261,7 +1261,7 @@ AllocateColors( } } else { /* - * Monochrome display - allocate the shades of grey we want. + * Monochrome display - allocate the shades of gray we want. */ for (i = 0; i < numColors; ++i) { diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 1bd0142..1fec208 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -2698,7 +2698,7 @@ Tk_PhotoPutBlock( * messages, or NULL. */ Tk_PhotoHandle handle, /* Opaque handle for the photo image to be * updated. */ - register Tk_PhotoImageBlock *blockPtr, + Tk_PhotoImageBlock *blockPtr, /* Pointer to a structure describing the pixel * data to be copied into the image. */ int x, int y, /* Coordinates of the top-left pixel to be @@ -2709,6 +2709,8 @@ Tk_PhotoPutBlock( * transparent pixels. */ { register PhotoMaster *masterPtr = (PhotoMaster *) handle; + Tk_PhotoImageBlock sourceBlock; + unsigned char *memToFree; int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; int wLeft, hLeft, wCopy, hCopy, pitch; unsigned char *srcPtr, *srcLinePtr, *destPtr, *destLinePtr; @@ -2736,11 +2738,43 @@ Tk_PhotoPutBlock( return TCL_OK; } + /* + * Fix for bug e4336bef5d: + * + * Make a local copy of *blockPtr, as we might have to change some + * of its fields and don't want to interfere with the caller's data. + * + * If source and destination are the same image, create a copy of the + * source data in our local sourceBlock. + * + * To find out, just comparing the pointers is not enough - they might have + * different values and still point to the same block of memory. (e.g. + * if the -from option was passed to [imageName copy]) + */ + sourceBlock = *blockPtr; + memToFree = NULL; + if (sourceBlock.pixelPtr >= masterPtr->pix32 + && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width + * masterPtr->height * 4) { + sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height + * sourceBlock.pitch); + if (sourceBlock.pixelPtr == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); + Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); + } + return TCL_ERROR; + } + memToFree = sourceBlock.pixelPtr; + memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height + * sourceBlock.pitch); + } + + xEnd = x + width; yEnd = y + height; if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) { - int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32); - if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width), MAX(yEnd, masterPtr->height)) == TCL_ERROR) { if (interp != NULL) { @@ -2748,11 +2782,7 @@ Tk_PhotoPutBlock( TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); } - return TCL_ERROR; - } - if (sameSrc) { - blockPtr->pixelPtr = masterPtr->pix32; - blockPtr->pitch = masterPtr->width * 4; + goto errorExit; } } @@ -2771,14 +2801,14 @@ Tk_PhotoPutBlock( * components, mark it as a color image. */ - greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; - blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; - alphaOffset = blockPtr->offset[3]; - if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) { + greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0]; + blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0]; + alphaOffset = sourceBlock.offset[3]; + if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) { alphaOffset = 0; sourceIsSimplePhoto = 1; } else { - alphaOffset -= blockPtr->offset[0]; + alphaOffset -= sourceBlock.offset[0]; } if ((greenOffset != 0) || (blueOffset != 0)) { masterPtr->flags |= COLOR_IMAGE; @@ -2798,13 +2828,13 @@ Tk_PhotoPutBlock( * pixelSize == 3 and alphaOffset == 0. Maybe other cases too. */ - if ((blockPtr->pixelSize == 4) + if ((sourceBlock.pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) - && (width <= blockPtr->width) && (height <= blockPtr->height) + && (width <= sourceBlock.width) && (height <= sourceBlock.height) && ((height == 1) || ((x == 0) && (width == masterPtr->width) - && (blockPtr->pitch == pitch))) + && (sourceBlock.pitch == pitch))) && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memmove(destLinePtr, blockPtr->pixelPtr + blockPtr->offset[0], + memmove(destLinePtr, sourceBlock.pixelPtr + sourceBlock.offset[0], ((size_t)height * width * 4)); /* @@ -2820,11 +2850,11 @@ Tk_PhotoPutBlock( */ for (hLeft = height; hLeft > 0;) { - int pixelSize = blockPtr->pixelSize; + int pixelSize = sourceBlock.pixelSize; int compRuleSet = (compRule == TK_PHOTO_COMPOSITE_SET); - srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0]; - hCopy = MIN(hLeft, blockPtr->height); + srcLinePtr = sourceBlock.pixelPtr + sourceBlock.offset[0]; + hCopy = MIN(hLeft, sourceBlock.height); hLeft -= hCopy; for (; hCopy > 0; --hCopy) { /* @@ -2835,10 +2865,10 @@ Tk_PhotoPutBlock( if ((pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) - && (width <= blockPtr->width) + && (width <= sourceBlock.width) && compRuleSet) { memcpy(destLinePtr, srcLinePtr, ((size_t)width * 4)); - srcLinePtr += blockPtr->pitch; + srcLinePtr += sourceBlock.pitch; destLinePtr += pitch; continue; } @@ -2849,7 +2879,7 @@ Tk_PhotoPutBlock( destPtr = destLinePtr; for (wLeft = width; wLeft > 0;) { - wCopy = MIN(wLeft, blockPtr->width); + wCopy = MIN(wLeft, sourceBlock.width); wLeft -= wCopy; srcPtr = srcLinePtr; @@ -2939,7 +2969,7 @@ Tk_PhotoPutBlock( destPtr += 4; } } - srcLinePtr += blockPtr->pitch; + srcLinePtr += sourceBlock.pitch; destLinePtr += pitch; } } @@ -3055,7 +3085,15 @@ Tk_PhotoPutBlock( Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, masterPtr->height); + + if (memToFree) ckfree(memToFree); + return TCL_OK; + + errorExit: + if (memToFree) ckfree(memToFree); + + return TCL_ERROR; } /* @@ -3082,7 +3120,7 @@ Tk_PhotoPutZoomedBlock( * messages, or NULL. */ Tk_PhotoHandle handle, /* Opaque handle for the photo image to be * updated. */ - register Tk_PhotoImageBlock *blockPtr, + Tk_PhotoImageBlock *blockPtr, /* Pointer to a structure describing the pixel * data to be copied into the image. */ int x, int y, /* Coordinates of the top-left pixel to be @@ -3097,6 +3135,8 @@ Tk_PhotoPutZoomedBlock( * transparent pixels. */ { register PhotoMaster *masterPtr = (PhotoMaster *) handle; + register Tk_PhotoImageBlock sourceBlock; + unsigned char *memToFree; int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; int wLeft, hLeft, wCopy, hCopy, blockWid, blockHt; unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr, *destPtr, *destLinePtr; @@ -3133,11 +3173,41 @@ Tk_PhotoPutZoomedBlock( return TCL_OK; } + /* + * Fix for Bug e4336bef5d: + * Make a local copy of *blockPtr, as we might have to change some + * of its fields and don't want to interfere with the caller's data. + * + * If source and destination are the same image, create a copy of the + * source data in our local sourceBlock. + * + * To find out, just comparing the pointers is not enough - they might have + * different values and still point to the same block of memory. (e.g. + * if the -from option was passed to [imageName copy]) + */ + sourceBlock = *blockPtr; + memToFree = NULL; + if (sourceBlock.pixelPtr >= masterPtr->pix32 + && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width + * masterPtr->height * 4) { + sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height + * sourceBlock.pitch); + if (sourceBlock.pixelPtr == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); + Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); + } + return TCL_ERROR; + } + memToFree = sourceBlock.pixelPtr; + memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height + * sourceBlock.pitch); + } + xEnd = x + width; yEnd = y + height; if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) { - int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32); - if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width), MAX(yEnd, masterPtr->height)) == TCL_ERROR) { if (interp != NULL) { @@ -3145,11 +3215,7 @@ Tk_PhotoPutZoomedBlock( TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); } - return TCL_ERROR; - } - if (sameSrc) { - blockPtr->pixelPtr = masterPtr->pix32; - blockPtr->pitch = masterPtr->width * 4; + goto errorExit; } } @@ -3168,14 +3234,14 @@ Tk_PhotoPutZoomedBlock( * components, mark it as a color image. */ - greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; - blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; - alphaOffset = blockPtr->offset[3]; - if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) { + greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0]; + blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0]; + alphaOffset = sourceBlock.offset[3]; + if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) { alphaOffset = 0; sourceIsSimplePhoto = 1; } else { - alphaOffset -= blockPtr->offset[0]; + alphaOffset -= sourceBlock.offset[0]; } if ((greenOffset != 0) || (blueOffset != 0)) { masterPtr->flags |= COLOR_IMAGE; @@ -3186,21 +3252,21 @@ Tk_PhotoPutZoomedBlock( * subsampling and zooming. */ - blockXSkip = subsampleX * blockPtr->pixelSize; - blockYSkip = subsampleY * blockPtr->pitch; + blockXSkip = subsampleX * sourceBlock.pixelSize; + blockYSkip = subsampleY * sourceBlock.pitch; if (subsampleX > 0) { - blockWid = ((blockPtr->width + subsampleX - 1) / subsampleX) * zoomX; + blockWid = ((sourceBlock.width + subsampleX - 1) / subsampleX) * zoomX; } else if (subsampleX == 0) { blockWid = width; } else { - blockWid = ((blockPtr->width - subsampleX - 1) / -subsampleX) * zoomX; + blockWid = ((sourceBlock.width - subsampleX - 1) / -subsampleX) * zoomX; } if (subsampleY > 0) { - blockHt = ((blockPtr->height + subsampleY - 1) / subsampleY) * zoomY; + blockHt = ((sourceBlock.height + subsampleY - 1) / subsampleY) * zoomY; } else if (subsampleY == 0) { blockHt = height; } else { - blockHt = ((blockPtr->height - subsampleY - 1) / -subsampleY) * zoomY; + blockHt = ((sourceBlock.height - subsampleY - 1) / -subsampleY) * zoomY; } /* @@ -3208,12 +3274,12 @@ Tk_PhotoPutZoomedBlock( */ destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; - srcOrigPtr = blockPtr->pixelPtr + blockPtr->offset[0]; + srcOrigPtr = sourceBlock.pixelPtr + sourceBlock.offset[0]; if (subsampleX < 0) { - srcOrigPtr += (blockPtr->width - 1) * blockPtr->pixelSize; + srcOrigPtr += (sourceBlock.width - 1) * sourceBlock.pixelSize; } if (subsampleY < 0) { - srcOrigPtr += (blockPtr->height - 1) * blockPtr->pitch; + srcOrigPtr += (sourceBlock.height - 1) * sourceBlock.pitch; } pitch = masterPtr->width * 4; @@ -3363,7 +3429,15 @@ Tk_PhotoPutZoomedBlock( Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, masterPtr->height); + + if (memToFree) ckfree(memToFree); + return TCL_OK; + + errorExit: + if (memToFree) ckfree(memToFree); + + return TCL_ERROR; } /* diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c index db0d71a..c20c546 100644 --- a/generic/tkTextBTree.c +++ b/generic/tkTextBTree.c @@ -1439,7 +1439,7 @@ TkBTreeDeleteIndexRange( prevNodePtr->nextPtr = curNodePtr->nextPtr; } parentPtr->numChildren--; - ckfree(curNodePtr->numPixels); + ckfree(curNodePtr->numPixels); ckfree(curNodePtr); curNodePtr = parentPtr; } @@ -4186,7 +4186,7 @@ Rebalance( treePtr->rootPtr = nodePtr->children.nodePtr; treePtr->rootPtr->parentPtr = NULL; DeleteSummaries(nodePtr->summaryPtr); - ckfree(nodePtr->numPixels); + ckfree(nodePtr->numPixels); ckfree(nodePtr); } return; @@ -4276,7 +4276,7 @@ Rebalance( nodePtr->nextPtr = otherPtr->nextPtr; nodePtr->parentPtr->numChildren--; DeleteSummaries(otherPtr->summaryPtr); - ckfree(otherPtr->numPixels); + ckfree(otherPtr->numPixels); ckfree(otherPtr); continue; } diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c index 389d520..83d7db9 100644 --- a/generic/ttk/ttkNotebook.c +++ b/generic/ttk/ttkNotebook.c @@ -288,13 +288,14 @@ static void ActivateTab(Notebook *nb, int index) * TabState -- * Return the state of the specified tab, based on * notebook state, currentIndex, activeIndex, and user-specified tab state. - * The USER1 bit is set for the leftmost tab, and USER2 - * is set for the rightmost tab. + * The USER1 bit is set for the leftmost visible tab, and USER2 + * is set for the rightmost visible tab. */ static Ttk_State TabState(Notebook *nb, int index) { Ttk_State state = nb->core.state; Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index); + int i = 0; if (index == nb->notebook.currentIndex) { state |= TTK_STATE_SELECTED; @@ -305,11 +306,25 @@ static Ttk_State TabState(Notebook *nb, int index) if (index == nb->notebook.activeIndex) { state |= TTK_STATE_ACTIVE; } - if (index == 0) { - state |= TTK_STATE_USER1; + for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + if (tab->state == TAB_STATE_HIDDEN) { + continue; + } + if (index == i) { + state |= TTK_STATE_USER1; + } + break; } - if (index == Ttk_NumberSlaves(nb->notebook.mgr) - 1) { - state |= TTK_STATE_USER2; + for (i = Ttk_NumberSlaves(nb->notebook.mgr) - 1; i >= 0; --i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + if (tab->state == TAB_STATE_HIDDEN) { + continue; + } + if (index == i) { + state |= TTK_STATE_USER2; + } + break; } if (tab->state == TAB_STATE_DISABLED) { state |= TTK_STATE_DISABLED; diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index 80a7a11..cd289d2 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -24,6 +24,9 @@ #define modalOther -1 #define modalError -2 +/*Vars for filtering in "open file" dialog.*/ +NSMutableArray *openFileTypes; +NSOpenPanel *openpanel; static const char *const colorOptionStrings[] = { "-initialcolor", "-parent", "-title", NULL @@ -212,6 +215,7 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { } } + - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo { @@ -247,6 +251,17 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { ckfree(callbackInfo); } } + +- (void)selectFormat:(id)sender { + NSPopUpButton *button = (NSPopUpButton *)sender; + NSInteger selectedItemIndex = [button indexOfSelectedItem]; + openFileTypes = nil; + openFileTypes = [NSMutableArray array]; + [openFileTypes addObject:[button titleOfSelectedItem]]; + [openpanel setAllowedFileTypes:openFileTypes]; + +} + @end #pragma mark - @@ -395,8 +410,8 @@ Tk_GetOpenFileObjCmd( NSString *directory = nil, *filename = nil; NSString *message, *title, *type; NSWindow *parent; - NSMutableArray *fileTypes = nil; - NSOpenPanel *panel = [NSOpenPanel openPanel]; + // NSOpenPanel *panel = [NSOpenPanel openPanel]; + openpanel = [NSOpenPanel openPanel]; NSInteger modalReturnCode = modalError; BOOL parentIsKey = NO; @@ -432,12 +447,13 @@ Tk_GetOpenFileObjCmd( if (len) { filename = [[[NSString alloc] initWithUTF8String:str] autorelease]; + [openpanel setNameFieldStringValue:filename]; } break; case OPEN_MESSAGE: message = [[NSString alloc] initWithUTF8String: Tcl_GetString(objv[i + 1])]; - [panel setMessage:message]; + [openpanel setMessage:message]; [message release]; break; case OPEN_MULTIPLE: @@ -457,7 +473,7 @@ Tk_GetOpenFileObjCmd( case OPEN_TITLE: title = [[NSString alloc] initWithUTF8String: Tcl_GetString(objv[i + 1])]; - [panel setTitle:title]; + [openpanel setTitle:title]; [title release]; break; case OPEN_TYPEVARIABLE: @@ -468,9 +484,9 @@ Tk_GetOpenFileObjCmd( break; } } - [panel setAllowsMultipleSelection:multiple]; + [openpanel setAllowsMultipleSelection:multiple]; if (fl.filters) { - fileTypes = [NSMutableArray array]; + openFileTypes = [NSMutableArray array]; for (FileFilter *filterPtr = fl.filters; filterPtr; filterPtr = filterPtr->next) { for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; @@ -483,8 +499,8 @@ Tk_GetOpenFileObjCmd( } if (*str) { type = [[NSString alloc] initWithUTF8String:str]; - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; + if (![openFileTypes containsObject:type]) { + [openFileTypes addObject:type]; } [type release]; } @@ -493,15 +509,33 @@ Tk_GetOpenFileObjCmd( mfPtr = mfPtr->next) { if (mfPtr->type) { type = NSFileTypeForHFSTypeCode(mfPtr->type); - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; + if (![openFileTypes containsObject:type]) { + /*Do nothing here, type and creator codes now ignored on macOS.*/ } } } } } } - [panel setAllowedFileTypes:fileTypes]; + + /*Accessory view for file filtering. Adapted from http://codefromabove.com/2015/01/nssavepanel-adding-an-accessory-view/ */ + NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200, 32.0)]; + NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; + [label setStringValue:@"Enable:"]; + [label setBordered:NO]; + [label setBezeled:NO]; + [label setDrawsBackground:NO]; + + NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:openFileTypes]; + [popupButton setAction:@selector(selectFormat:)]; + + [accessoryView addSubview:label]; + [accessoryView addSubview:popupButton]; + [openpanel setAllowedFileTypes:openFileTypes]; + + [openpanel setAccessoryView:accessoryView]; if (cmdObj) { callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { @@ -516,33 +550,33 @@ Tk_GetOpenFileObjCmd( if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - [panel beginSheetForDirectory:directory + [openpanel beginSheetForDirectory:directory file:filename - types:fileTypes + types:openFileTypes modalForWindow:parent modalDelegate:NSApp didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; #else - [panel setAllowedFileTypes:fileTypes]; - [panel setDirectoryURL:getFileURL(directory, filename)]; - [panel beginSheetModalForWindow:parent + [openpanel setAllowedFileTypes:openFileTypes]; + [openpanel setDirectoryURL:getFileURL(directory, filename)]; + [openpanel beginSheetModalForWindow:parent completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:panel + { [NSApp tkFilePanelDidEnd:openpanel returnCode:returnCode contextInfo:callbackInfo ]; } ]; #endif - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:openpanel]; } else { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - modalReturnCode = [panel runModalForDirectory:directory + modalReturnCode = [openpanel runModalForDirectory:directory file:filename]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; - modalReturnCode = [panel runModal]; + [openpanel setDirectoryURL:getFileURL(directory, filename)]; + modalReturnCode = [openpanel runModal]; #endif - [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode + [NSApp tkFilePanelDidEnd:openpanel returnCode:modalReturnCode contextInfo:callbackInfo]; } result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; @@ -562,6 +596,7 @@ Tk_GetOpenFileObjCmd( TkFreeFileFilters(&fl); return result; } + /* *---------------------------------------------------------------------- @@ -643,6 +678,7 @@ Tk_GetSaveFileObjCmd( if (len) { filename = [[[NSString alloc] initWithUTF8String:str] autorelease]; + [panel setNameFieldStringValue:filename]; } break; case SAVE_MESSAGE: diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 91cf112..49ba999 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -19,6 +19,13 @@ #define MIN_SCROLLBAR_VALUE 0 +/* + * Minimum slider length, in pixels (designed to make sure that the slider is + * always easy to grab with the mouse). + */ + +#define MIN_SLIDER_LENGTH 5 + /*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling of scrollbar values.*/ #ifdef __LP64__ #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) @@ -60,16 +67,14 @@ typedef struct ScrollbarMetrics { } ScrollbarMetrics; static ScrollbarMetrics metrics[2] = { - {15, 54, 26, 14, 14, NSRegularControlSize}, /* kThemeScrollBarMedium */ - {11, 40, 20, 10, 10, NSSmallControlSize}, /* kThemeScrollBarSmall */ + {15, 54, 26, 14, 14, kControlSizeNormal}, /* kThemeScrollBarMedium */ + {11, 40, 20, 10, 10, kControlSizeSmall}, /* kThemeScrollBarSmall */ }; - HIThemeTrackDrawInfo info = { .version = 0, .min = 0.0, .max = 100.0, .attributes = kThemeTrackShowThumb, - .kind = kThemeScrollBarMedium, }; @@ -107,7 +112,7 @@ TkpCreateScrollbar( scrollPtr->troughGC = None; scrollPtr->copyGC = None; - Tk_CreateEventHandler(tkwin,ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask|VisibilityChangeMask, ScrollbarEventProc, scrollPtr); + Tk_CreateEventHandler(tkwin,ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask|ButtonReleaseMask|EnterWindowMask|LeaveWindowMask|VisibilityChangeMask, ScrollbarEventProc, scrollPtr); return (TkScrollbar *) scrollPtr; } @@ -212,7 +217,8 @@ TkpDisplayScrollbar( *---------------------------------------------------------------------- */ -extern void + + extern void TkpComputeScrollbarGeometry( register TkScrollbar *scrollPtr) /* Scrollbar whose geometry may have @@ -259,14 +265,12 @@ TkpComputeScrollbarGeometry( if (scrollPtr->sliderLast > fieldLength) { scrollPtr->sliderLast = fieldLength; } - if (!(MOUNTAIN_LION_STYLE)) { - scrollPtr->sliderFirst += scrollPtr->inset + - metrics[variant].topArrowHeight; - scrollPtr->sliderLast += scrollPtr->inset + - metrics[variant].bottomArrowHeight; - } - /* - * Register the desired geometry for the window (leave enough space + + scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset; + scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset; + + + /* Register the desired geometry for the window (leave enough space * for the two arrows plus a minimum-size slider, plus border around * the whole window, if any). Then arrange for the window to be * redisplayed. @@ -281,6 +285,9 @@ TkpComputeScrollbarGeometry( } + + + /* *---------------------------------------------------------------------- * @@ -376,21 +383,22 @@ TkpScrollbarPosition( register const int arrowSize = scrollPtr->arrowLength + inset; if (scrollPtr->vertical) { - length = Tk_Height(scrollPtr->tkwin); - fieldlength = length - 2 * arrowSize; - width = Tk_Width(scrollPtr->tkwin); + length = Tk_Height(scrollPtr->tkwin); + fieldlength = length - 2 * arrowSize; + width = Tk_Width(scrollPtr->tkwin); } else { - tmp = x; - x = y; - y = tmp; - length = Tk_Width(scrollPtr->tkwin); - fieldlength = length - 2 * arrowSize; - width = Tk_Height(scrollPtr->tkwin); + tmp = x; + x = y; + y = tmp; + length = Tk_Width(scrollPtr->tkwin); + fieldlength = length - 2 * arrowSize; + width = Tk_Height(scrollPtr->tkwin); } + fieldlength = fieldlength < 0 ? 0 : fieldlength; if (x<inset || x>=width-inset || y<inset || y>=length-inset) { - return OUTSIDE; + return OUTSIDE; } /* @@ -399,18 +407,19 @@ TkpScrollbarPosition( */ if (y < scrollPtr->sliderFirst) { - return TOP_GAP; + return TOP_GAP; } if (y < scrollPtr->sliderLast) { - return SLIDER; + return SLIDER; } if (y < fieldlength){ - return BOTTOM_GAP; + return BOTTOM_GAP; } if (y < fieldlength + arrowSize) { - return TOP_ARROW; + return TOP_ARROW; } return BOTTOM_ARROW; + } /* @@ -458,7 +467,7 @@ UpdateControlValues( width = contrlRect.size.width; height = contrlRect.size.height; - variant = contrlRect.size.width < metrics[0].width ? 1 : 0; + variant = contrlRect.size.width < metrics[0].width ? 1 : 0; /* * Ensure we set scrollbar control bounds only once all size adjustments @@ -514,8 +523,8 @@ UpdateControlValues( * * ScrollbarPress -- * - * This procedure is invoked in response to <ButtonPress> events. - * Enters a modal loop to handle scrollbar interactions. + * This procedure is invoked in response to <ButtonPress>, <ButtonRelease>, + * <EnterNotify>, and <LeaveNotify> events. Scrollbar appearance is modified. * *-------------------------------------------------------------- */ @@ -526,6 +535,13 @@ ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr) if (eventPtr->type == ButtonPress) { UpdateControlValues(scrollPtr); + info.trackInfo.scrollbar.pressState = 1; + } + if (eventPtr->type == EnterNotify) { + info.trackInfo.scrollbar.pressState = 1; + } + if (eventPtr->type == ButtonRelease || eventPtr->type == LeaveNotify) { + info.trackInfo.scrollbar.pressState = 0; } return TCL_OK; } @@ -566,6 +582,9 @@ ScrollbarEventProc( TkScrollbarEventuallyRedraw(scrollPtr); break; case ButtonPress: + case ButtonRelease: + case EnterNotify: + case LeaveNotify: ScrollbarPress(clientData, eventPtr); break; default: diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 39990e6..75473bf 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -2893,17 +2893,20 @@ WmProtocolCmd( } else { prevPtr->nextPtr = protPtr->nextPtr; } + if (protPtr->command) + ckfree(protPtr->command); Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); break; } } cmd = Tcl_GetStringFromObj(objv[4], &cmdLength); if (cmdLength > 0) { - protPtr = ckalloc(HANDLER_SIZE(cmdLength)); + protPtr = ckalloc(sizeof(ProtocolHandler)); protPtr->protocol = protocol; protPtr->nextPtr = wmPtr->protPtr; wmPtr->protPtr = protPtr; protPtr->interp = interp; + protPtr->command = ckalloc(cmdLength+1); strcpy(protPtr->command, cmd); } return TCL_OK; diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h index d98010f..e904f50 100644 --- a/macosx/tkMacOSXWm.h +++ b/macosx/tkMacOSXWm.h @@ -29,15 +29,13 @@ typedef struct ProtocolHandler { * same top-level window, or NULL for end of * list. */ Tcl_Interp *interp; /* Interpreter in which to invoke command. */ - char command[4]; /* Tcl command to invoke when a client message + char* command; /* Tcl command to invoke when a client message * for this protocol arrives. The actual size * of the structure varies to accommodate the * needs of the actual command. THIS MUST BE * THE LAST FIELD OF THE STRUCTURE. */ } ProtocolHandler; -#define HANDLER_SIZE(cmdLength) \ -((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength)) /* * A data structure of the following type holds window-manager-related diff --git a/tests/color.test b/tests/color.test index a7ed1f8..aa20099 100644 --- a/tests/color.test +++ b/tests/color.test @@ -90,7 +90,17 @@ proc colorsFree {w {red 31} {green 245} {blue 192}} { && ([lindex $vals 2]/256 == $blue) } -if {[testConstraint psuedocolor8]} { +# -- WARNING (SB, 6.4.2017) -- +# +# The if block below looks _very_ outdated. It didn't get any +# substantial changes as far back as the fossil history goes. It might +# be from a time, when 256 color was the best you could get! :-o. +# +# The problem is, on machines with a fancy 24 truecolor display, the +# 'colorsFree' constraint doesn't get set, turning off pretty much every test +# in this file. + +if {[testConstraint pseudocolor8]} { toplevel .t -visual {pseudocolor 8} -colormap new wm geom .t +0+0 mkColors .t.c 40 6 0 0 0 0 6 0 0 0 40 @@ -185,6 +195,18 @@ test color-2.6 {Tk_GetColor procedure} {colorsFree nonPortable} { test color-2.7 {Tk_GetColor procedure} colorsFree { winfo rgb .t #ff0000 } {65535 0 0} +test color-2.8 {Tk_GetColor, invalid char after 3 valid hex digits} -body { + winfo rgb . #abcg +} -returnCodes error -result {invalid color name "#abcg"} +test color-2.9 {Tk_GetColor, invalid char after 6 vaild hex digits} -body { + winfo rgb . #aabbccz +} -returnCodes error -result {invalid color name "#aabbccz"} +test color-2.10 {Tk_GetColor, 3 hex digits, last one invalid} -body { + winfo rgb . #abz +} -returnCodes error -result {invalid color name "#abz"} +test color-2.11 {Tk_GetColor, 6 hex digits, last one invalid} -body { + winfo rgb . #12345g +} -returnCodes error -result {invalid color name "#12345g"} test color-3.1 {Tk_FreeColor procedure, reference counting} colorsFree { eval destroy [winfo child .t] diff --git a/tests/imgBmap.test b/tests/imgBmap.test index 5ffd7c4..e7f2c7e 100644 --- a/tests/imgBmap.test +++ b/tests/imgBmap.test @@ -380,7 +380,8 @@ test imageBmap-7.9 {ImgBmapCmd procedure} -body { test imageBmap-7.10 {ImgBmapCmd procedure} -body { i1 gorp } -returnCodes error -result {bad option "gorp": must be cget or configure} - +# Clean it up after use!! +imageCleanup test imageBmap-8.1 {ImgBmapGet/Free procedures, shared instances} -setup { destroy .c diff --git a/tests/imgPhoto.test b/tests/imgPhoto.test index e93dab4..86da23d 100644 --- a/tests/imgPhoto.test +++ b/tests/imgPhoto.test @@ -134,7 +134,7 @@ test imgPhoto-2.2 {ImgPhotoCreate procedure} -setup { # } {couldn't open "bogus.img": no such file or directory} test imgPhoto-3.1 {ImgPhotoConfigureMaster procedure} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -body { image create photo photo1 -file $teapotPhotoFile photo1 configure -file $teapotPhotoFile @@ -142,7 +142,7 @@ test imgPhoto-3.1 {ImgPhotoConfigureMaster procedure} -constraints { image delete photo1 } -result {} test imgPhoto-3.2 {ImgPhotoConfigureMaster procedure} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -body { image create photo photo1 -file $teapotPhotoFile list [catch {photo1 configure -file bogus} err] [string tolower $err] \ @@ -151,7 +151,7 @@ test imgPhoto-3.2 {ImgPhotoConfigureMaster procedure} -constraints { image delete photo1 } -result {1 {couldn't open "bogus": no such file or directory} 256 256} test imgPhoto-3.3 {ImgPhotoConfigureMaster procedure} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { destroy .c pack [canvas .c] @@ -235,7 +235,7 @@ test imgPhoto-4.9 {ImgPhotoCmd procedure: configure option} -setup { image delete photo1 } -returnCodes error -result {value for "-gamma" missing} test imgPhoto-4.10 {ImgPhotoCmd procedure: copy option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 image create photo photo2 -width 25 -height 30 @@ -278,7 +278,7 @@ test imgPhoto-4.14 {ImgPhotoCmd procedure: copy option} -setup { image delete photo1 photo2 } -result {the "-from" option requires one to four integer values} test imgPhoto-4.15 {ImgPhotoCmd procedure: copy option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 image create photo photo2 -file $teapotPhotoFile @@ -290,7 +290,7 @@ test imgPhoto-4.15 {ImgPhotoCmd procedure: copy option} -constraints { image delete photo1 photo2 } -result {60 50 {215 154 120}} test imgPhoto-4.16 {ImgPhotoCmd procedure: copy option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 image create photo photo2 -file $teapotPhotoFile @@ -301,7 +301,7 @@ test imgPhoto-4.16 {ImgPhotoCmd procedure: copy option} -constraints { image delete photo1 photo2 } -result {80 100 {19 92 192}} test imgPhoto-4.17 {ImgPhotoCmd procedure: copy option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 image create photo photo2 -file $teapotPhotoFile @@ -312,7 +312,7 @@ test imgPhoto-4.17 {ImgPhotoCmd procedure: copy option} -constraints { image delete photo1 photo2 } -result {100 100 {215 154 120}} test imgPhoto-4.18 {ImgPhotoCmd procedure: copy option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 image create photo photo2 -file $teapotPhotoFile @@ -334,7 +334,7 @@ test imgPhoto-4.19 {ImgPhotoCmd procedure: copy option} -constraints { image delete photo1 photo2 } -result {120 100 {169 99 47}} test imgPhoto-4.20 {ImgPhotoCmd procedure: copy option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 image create photo photo2 -file $teapotPhotoFile @@ -345,7 +345,7 @@ test imgPhoto-4.20 {ImgPhotoCmd procedure: copy option} -constraints { image delete photo1 photo2 } -result {90 80 {207 146 112}} test imgPhoto-4.21 {ImgPhotoCmd procedure: copy option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 image create photo photo2 -file $teapotPhotoFile @@ -368,7 +368,7 @@ test imgPhoto-4.21 {ImgPhotoCmd procedure: copy option} -constraints { image delete photo1 photo2 } -result {256 256 49 51 49 51 49 51 10 51 10 10} test imgPhoto-4.22 {ImgPhotoCmd procedure: get option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 } -body { @@ -435,7 +435,7 @@ test imgPhoto-4.30 {ImgPhotoCmd procedure: read option} -setup { image delete photo1 } -result {wrong # args: should be "photo1 read fileName ?-option value ...?"} test imgPhoto-4.31 {ImgPhotoCmd procedure: read option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 } -body { @@ -451,7 +451,7 @@ test imgPhoto-4.32 {ImgPhotoCmd procedure: read option} -setup { image delete photo1 } -result {1 {couldn't open "bogus": no such file or directory}} test imgPhoto-4.33 {ImgPhotoCmd procedure: read option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 } -body { @@ -467,7 +467,7 @@ test imgPhoto-4.34 {ImgPhotoCmd procedure: read option} -setup { image delete photo1 } -result [subst {couldn't recognize data in image file "$README"}] test imgPhoto-4.35 {ImgPhotoCmd procedure: read option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 } -body { @@ -477,7 +477,7 @@ test imgPhoto-4.35 {ImgPhotoCmd procedure: read option} -constraints { image delete photo1 } -result {256 256 {161 109 82}} test imgPhoto-4.36 {ImgPhotoCmd procedure: read option} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { image create photo photo1 } -body { @@ -805,7 +805,7 @@ test imgPhoto-4.74 {ImgPhotoCmd procedure: put option error handling} -setup { image delete photo1 } -returnCodes 1 -result {wrong # args: should be "photo1 put data ?-option value ...?"} test imgPhoto-4.75 {<photo> read command: filename starting with '-'} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -body { file copy -force $teapotPhotoFile -teapotPhotoFile image create photo photo1 @@ -816,7 +816,7 @@ test imgPhoto-4.75 {<photo> read command: filename starting with '-'} -constrain } -result {} test imgPhoto-5.1 {ImgPhotoGet/Free procedures, shared instances} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { destroy .c pack [canvas .c] @@ -853,7 +853,7 @@ test imgPhoto-6.1 {ImgPhotoDisplay procedure, blank display} -setup { } -result {} test imgPhoto-7.1 {ImgPhotoFree procedure, resource freeing} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { destroy .c pack [canvas .c] @@ -868,7 +868,7 @@ test imgPhoto-7.1 {ImgPhotoFree procedure, resource freeing} -constraints { destroy .c } -result {} test imgPhoto-7.2 {ImgPhotoFree procedures, unlinking} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { deleteWindows imageCleanup @@ -893,7 +893,7 @@ test imgPhoto-7.2 {ImgPhotoFree procedures, unlinking} -constraints { image delete photo1 } -result {} test imgPhoto-7.3 {ImgPhotoFree procedures, multiple visuals} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { deleteWindows imageCleanup @@ -918,7 +918,7 @@ test imgPhoto-8.1 {ImgPhotoDelete procedure} -constraints hasTeapotPhoto -body { image delete photo2 } -result {} test imgPhoto-8.2 {ImgPhotoDelete procedure} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -setup { set x {} } -body { @@ -938,7 +938,7 @@ test imgPhoto-8.3 {ImgPhotoDelete procedure, name cleanup} -body { } -result {image "photo2" doesn't exist or is not a photo image} test imgPhoto-9.1 {ImgPhotoCmdDeletedProc procedure} -constraints { - hasTeapotPhoto + hasTeapotPhoto } -body { image create photo photo2 -file $teapotPhotoFile rename photo2 {} @@ -953,6 +953,44 @@ test imgPhoto-10.1 {Tk_ImgPhotoPutBlock procedure} -setup { photo1 put "{#00ff00 #00ff00}" -to 2 0 list [photo1 get 2 0] [photo1 get 3 0] [photo1 get 4 0] } -result {{0 255 0} {0 255 0} {255 0 0}} +test imgPhoto-10.2 {Tk_ImgPhotoPutBlock, same source and dest img} -constraints { + hasTeapotPhoto +} -setup { + imageCleanup +} -body { + # Test for bug e4336bef5d + image create photo photo1 -file $teapotPhotoFile + image create photo photo2 -file $teapotPhotoFile + photo2 copy photo1 -to 1 2 + photo1 copy photo1 -to 1 2 + string equal [photo1 data] [photo2 data] +} -cleanup { + imageCleanup +} -result {1} +test imgPhoto-10.3 {Tk_ImgPhotoPutBlock, same source and dest img} -constraints { + hasTeapotPhoto +} -setup { + imageCleanup +} -body { + # Test for bug e4336bef5d + image create photo photo1 -file $teapotPhotoFile + image create photo photo2 -file $teapotPhotoFile + photo2 copy photo1 -from 2 1 -to 4 5 300 300 + photo1 copy photo1 -from 2 1 -to 4 5 300 300 + string equal [photo1 data] [photo2 data] +} -cleanup { + imageCleanup +} -result {1} +test imgPhoto-10.4 {Tk_ImgPhotoPutBlock, empty image} -setup { + imageCleanup +} -body { + image create photo photo1 + photo1 copy photo1 -to 0 5 10 20 + list [image width photo1] [image height photo1] +} -cleanup { + imageCleanup +} -result {0 0} + test imgPhoto-11.1 {Tk_FindPhoto} -setup { imageCleanup @@ -972,6 +1010,41 @@ test imgPhoto-12.1 {Tk_PhotoPutZoomedBlock} -constraints hasTeapotPhoto -body { } -cleanup { image delete p3 } -result {{19 92 192} {169 117 90} 512 512 {19 92 192}} +test imgPhoto-12.2 {Tk_ImgPhotoPutZoomedBlock, same source and dest img} -constraints { + hasTeapotPhoto +} -setup { + imageCleanup +} -body { + # Test for bug e4336bef5d + image create photo photo1 -file $teapotPhotoFile + image create photo photo2 -file $teapotPhotoFile + photo2 copy photo1 -to 0 1 200 200 -zoom 2 3 + photo1 copy photo1 -to 0 1 200 200 -zoom 2 3 + string equal [photo1 data] [photo2 data] +} -cleanup { + imageCleanup +} -result {1} +test imgPhoto-12.3 {Tk_ImgPhotoPutZoomedBlock, same source and dest img} -setup { + imageCleanup +} -body { + # Test for bug e4336bef5d + image create photo photo1 -file $teapotPhotoFile + image create photo photo2 -file $teapotPhotoFile + photo2 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2 + photo1 copy photo1 -from 1 0 -to 4 5 300 300 -zoom 1 2 + string equal [photo1 data] [photo2 data] +} -cleanup { + imageCleanup +} -result {1} +test imgPhoto-12.4 {Tk_ImgPhotoPutZoomedBlock, empty image} -setup { + imageCleanup +} -body { + image create photo photo1 + photo1 copy photo1 -to 0 5 10 20 + list [image width photo1] [image height photo1] +} -cleanup { + imageCleanup +} -result {0 0} test imgPhoto-13.1 {check separation of images in different interpreters} -setup { imageCleanup diff --git a/xlib/xcolors.c b/xlib/xcolors.c index b5e45c9..78fd44b 100644 --- a/xlib/xcolors.c +++ b/xlib/xcolors.c @@ -345,6 +345,16 @@ XParseColor( char *p; Tcl_WideInt value = parseHex64bit(++spec, &p); + /* + * If *p does not point to the end of the string, there were invalid + * digits in the spec. Ergo, it is not a vailid color string. + * (Bug f0188aca9e) + */ + + if (*p != '\0') { + return 0; + } + switch ((int)(p-spec)) { case 3: colorPtr->red = US(((value >> 8) & 0xf) * 0x1111); @@ -560,7 +560,7 @@ XDrawSegments( XSegment *segments, int nsegments) { - return Success; + return BadDrawable; } #endif |