summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--changes85
-rw-r--r--doc/SetOptions.350
-rw-r--r--doc/colors.n26
-rw-r--r--doc/event.n2
-rw-r--r--doc/listbox.n11
-rw-r--r--doc/menu.n15
-rw-r--r--doc/messageBox.n39
-rw-r--r--doc/panedwindow.n10
-rw-r--r--doc/spinbox.n12
-rw-r--r--doc/text.n19
-rw-r--r--doc/tk_mac.n237
-rw-r--r--generic/tk.h4
-rw-r--r--generic/tkEntry.c156
-rw-r--r--generic/tkEvent.c6
-rw-r--r--generic/tkFont.c4
-rw-r--r--generic/tkImgPhoto.c6
-rw-r--r--generic/tkInt.decls2
-rw-r--r--generic/tkIntPlatDecls.h7
-rw-r--r--generic/tkListbox.c46
-rw-r--r--generic/tkMenu.c7
-rw-r--r--generic/tkOldConfig.c6
-rw-r--r--generic/tkOption.c2
-rw-r--r--generic/tkPanedWindow.c19
-rw-r--r--generic/tkScrollbar.c2
-rw-r--r--generic/tkStubInit.c2
-rw-r--r--generic/tkText.c34
-rw-r--r--generic/tkTextBTree.c2
-rw-r--r--generic/tkTextDisp.c152
-rw-r--r--generic/tkTextIndex.c2
-rw-r--r--generic/tkTextTag.c8
-rw-r--r--generic/tkTextWind.c16
-rw-r--r--generic/ttk/ttkButton.c4
-rw-r--r--generic/ttk/ttkNotebook.c2
-rw-r--r--library/entry.tcl10
-rw-r--r--library/listbox.tcl36
-rw-r--r--library/menu.tcl2
-rw-r--r--library/scrlbar.tcl7
-rw-r--r--library/text.tcl40
-rw-r--r--library/tk.tcl3
-rw-r--r--macosx/GNUmakefile2
-rw-r--r--macosx/README61
-rw-r--r--macosx/tkMacOSXButton.c4
-rw-r--r--macosx/tkMacOSXDefault.h1
-rw-r--r--macosx/tkMacOSXDialog.c413
-rw-r--r--macosx/tkMacOSXDraw.c94
-rw-r--r--macosx/tkMacOSXEvent.c5
-rw-r--r--macosx/tkMacOSXFont.c23
-rw-r--r--macosx/tkMacOSXHLEvents.c756
-rw-r--r--macosx/tkMacOSXInit.c70
-rw-r--r--macosx/tkMacOSXKeyEvent.c38
-rw-r--r--macosx/tkMacOSXMenu.c29
-rw-r--r--macosx/tkMacOSXMouseEvent.c80
-rw-r--r--macosx/tkMacOSXNotify.c65
-rw-r--r--macosx/tkMacOSXPrivate.h47
-rw-r--r--macosx/tkMacOSXSubwindows.c13
-rw-r--r--macosx/tkMacOSXWindowEvent.c64
-rw-r--r--macosx/tkMacOSXWm.c257
-rw-r--r--macosx/tkMacOSXXStubs.c61
-rw-r--r--macosx/ttkMacOSXTheme.c2
-rw-r--r--tests/bevel.tcl41
-rw-r--r--tests/entry.test35
-rw-r--r--tests/event.test4
-rw-r--r--tests/font.test3
-rw-r--r--tests/listbox.test39
-rw-r--r--tests/menu.test18
-rw-r--r--tests/panedwindow.test23
-rw-r--r--tests/scrollbar.test30
-rw-r--r--tests/spinbox.test26
-rw-r--r--tests/text.test126
-rw-r--r--tests/textDisp.test82
-rw-r--r--tests/textIndex.test13
-rw-r--r--tests/textWind.test14
-rw-r--r--tests/ttk/notebook.test21
-rw-r--r--tests/ttk/spinbox.test2
-rw-r--r--tests/winButton.test8
-rwxr-xr-xunix/configure6
-rw-r--r--unix/configure.in2
-rw-r--r--unix/tcl.m44
-rw-r--r--unix/tk.spec2
-rw-r--r--unix/tkUnixDefault.h1
-rw-r--r--unix/tkUnixEmbed.c5
-rw-r--r--unix/tkUnixXId.c20
-rwxr-xr-xwin/configure36
-rw-r--r--win/configure.in2
-rw-r--r--win/makefile.vc13
-rw-r--r--win/nmakehlp.c6
-rw-r--r--win/tcl.m429
-rw-r--r--win/tkWinDefault.h1
-rw-r--r--win/tkWinEmbed.c7
-rw-r--r--win/tkWinPort.h7
-rw-r--r--win/tkWinScrlbr.c4
-rw-r--r--win/ttkWinXPTheme.c2
93 files changed, 2557 insertions, 1255 deletions
diff --git a/README b/README
index 6fad4bb..4d1dc24 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
README: Tk
- This is the Tk 8.5.18 source distribution.
+ This is the Tk 8.5.19 source distribution.
http://sourceforge.net/projects/tcl/files/Tcl/
You can get any source release of Tk from the URL above.
diff --git a/changes b/changes
index d9d34a3..a752d10 100644
--- a/changes
+++ b/changes
@@ -6987,3 +6987,88 @@ Tk Cocoa 2.0: App Store enabled (walzer,culler,desmera,owen,nyberg,reincke)
*** POTENTIAL INCOMPATIBILITY ***
--- Released 8.5.18, March 6, 2015 --- http://core.tcl.tk/tk/ for details
+
+2015-03-10 (bug) Cocoa: premature image free crash (walzer)
+
+2015-03-15 (bug) Cocoa: wish launches in front. [focus -force] works (culler)
+
+2015-04-09 (bug)[e4ed00] [$text index "1.0 display wordstart"] crash (vogel)
+
+2015-04-09 (bug)[562118] Unicode support of "wordstart" modifier (vogel)
+
+2015-05-05 (bug)[06c3fc] PNG alpha error corrupted output file (gauthier,porter)
+
+2015-05-24 (bug)[53f8fc] panedwindow geometry management (vogel)
+
+2015-05-26 (bug)[1641721] tk_getOpenFile symlink display doubled (nijtmans)
+
+2015-06-01 (bug)[d7bad5][2368195][3592454][1714535][1292219][3592454]
+ panedwindow fixes (vogel)
+
+2015-06-25 (bug)[805cff] Tk_ConfigureWidget() segfault (aspect,nijtmans)
+
+2015-07-13 (bug)[3f179a] Text widget crash with elided text (vogel)
+
+2015-07-16 (bug)[2886436] Stop [$text delete] acting before start index (vogel)
+
+2015-07-28 (bug)[1236306] TraverseToMenu error bound to toplevel destroy (vogel)
+
+2015-08-20 (bug)[00189c] MSVC 14: semi-static UCRT support (dower,nijtmans)
+
+2015-09-29 (bug)[1501749] Crash embedded window delete bound to <Map> (vogel)
+
+2015-10-08 (new feature)[TIP 437] New panedwindow options (vogel)
+
+2015-10-09 (bug)[1669632] [text] autoseparator placement (nash,vogel)
+
+2015-10-09 (bug)[2262711] [text] RE search Unicode+elided (kaitzschu,vogel)
+
+2015-10-09 (bug)[1815161] [$text count -ypixels] needs management (vogel)
+
+2015-10-22 (bug)[1520118] Document spinbox validate expectations (vogel)
+
+2015-10-22 (bug)[1414025] $entry insertion cursor visibility (vogel)
+
+2015-10-26 (bug) PNG rendering on El Capitan (meier,walzer)
+
+2015-11-08 (bug)[2160206] menubutton panic (vogel)
+
+2015-11-08 (bug)[220854] Display trailing TAB in entry (vogel)
+
+2015-11-08 (bug)[542199] double click on lone char in entry (vogel)
+
+2015-11-08 (bug)[297442d] strict motif binding on <Control-underscore> (vogel)
+
+2015-11-08 (bug)[3601604] $listbox -takefocus (vogel)
+
+2015-11-09 (bug)[5ee8af] X, Win: 64-bit enable embedded windows (vogel)
+
+2015-11-29 (bug)[1997299] [text] tag borderwidth leak (vogel)
+
+2015-12-12 (bug)[1739605] [text see] misbehavior (danckaert)
+
+2015-12-13 (bug)[ff8a1e] Never-mapped [text] performance (danckaert)
+
+2015-12-19 (bug)[1700065] Report errors from -textvariable write trace (vogel)
+
+2015-12-19 (bug)[793909] -textvariable handle undefined namespace (vogel)
+
+2015-12-26 (bug)[2f78c7] crash with [text] and [tablelist] (vogel)
+
+2016-01-06 (bug)[1288433,3102228] <<ListboxSelect>> misfires (vogel)
+
+2016-01-08 (bug)[1510538] initial scrollbar width (vogel,nijtmans)
+
+2016-01-08 (bug)[1305128] event not received by scrollbar (vogel,nijtmans)
+
+2016-01-09 (bug)[1927212] Mousewheel/scrollbar bindings (vogel)
+
+2016-01-11 (bug)[63c354] Cocoa message boxes (culler)
+
+2016-01-12 (bug)[2049429] get more $text options from database (vogel)
+
+2016-01-25 (bug) OBOE in ttk::notebook options parsing (bromley,english)
+
+Tk Cocoa 2.0: More drawing internals refinements (culler,walzer)
+
+--- Released 8.5.19, February 12, 2016 --- http://core.tcl.tk/tk/ for details
diff --git a/doc/SetOptions.3 b/doc/SetOptions.3
index 028467a..f12a00f 100644
--- a/doc/SetOptions.3
+++ b/doc/SetOptions.3
@@ -129,19 +129,21 @@ option table is no longer needed \fBTk_DeleteOptionTable\fR should be
called to free all of its resources. All of the option tables
for a Tcl interpreter are freed automatically if the interpreter is deleted.
.PP
-\fBTk_InitOptions\fR is invoked when a new widget is created to set
-the default values for all of the widget's configuration options.
-\fBTk_InitOptions\fR is passed a token for an option table (\fIoptionTable\fR)
-and a pointer to a widget record (\fIrecordPtr\fR), which is the C
-structure that holds information about this widget. \fBTk_InitOptions\fR
-uses the information in the option table to
-choose an appropriate default for each option, then it stores the default
-value directly into the widget record, overwriting any information that
-was already present in the widget record. \fBTk_InitOptions\fR normally
-returns \fBTCL_OK\fR. If an error occurred while setting the default values
-(e.g., because a default value was erroneous) then \fBTCL_ERROR\fR is returned
-and an error message is left in \fIinterp\fR's result if \fIinterp\fR
-is not NULL.
+\fBTk_InitOptions\fR is invoked when a new widget is created to set the
+default values for all of the widget's configuration options that do not
+have \fBTK_OPTION_DONT_SET_DEFAULT\fR set in their \fIflags\fR field.
+\fBTk_InitOptions\fR is passed a token for an option table
+(\fIoptionTable\fR) and a pointer to a widget record (\fIrecordPtr\fR),
+which is the C structure that holds information about this widget.
+\fBTk_InitOptions\fR uses the information in the option table to choose an
+appropriate default for each option, except those having
+\fBTK_OPTION_DONT_SET_DEFAULT\fR set, then it stores the default value
+directly into the widget record, overwriting any information that was
+already present in the widget record. \fBTk_InitOptions\fR normally
+returns \fBTCL_OK\fR. If an error occurred while setting the default
+values (e.g., because a default value was erroneous) then \fBTCL_ERROR\fR
+is returned and an error message is left in \fIinterp\fR's result if
+\fIinterp\fR is not NULL.
.PP
\fBTk_SetOptions\fR is invoked to modify configuration options based
on information specified in a Tcl command. The command might be one that
@@ -306,19 +308,27 @@ given by \fIinternalOffset\fR. For example, if the option's type is
value is not stored in that form. At least one of the offsets must be
greater than or equal to zero.
.PP
-The \fIflags\fR field consists of one or more bits ORed together. At
-present only a single flag is supported: \fBTK_OPTION_NULL_OK\fR. If
-this bit is set for an option then an empty string will be accepted as
-the value for the option and the resulting internal form will be a
-NULL pointer, a zero value, or \fBNone\fR, depending on the type of
-the option. If the flag is not set then empty strings will result
-in errors.
+The \fIflags\fR field consists of one or more bits ORed together. The
+following flags are supported:
+.TP
+\fBTK_OPTION_NULL_OK\fR
+If this bit is set for an option then an empty string will be accepted as
+the value for the option and the resulting internal form will be a NULL
+pointer, a zero value, or \fBNone\fR, depending on the type of the option.
+If the flag is not set then empty strings will result in errors.
\fBTK_OPTION_NULL_OK\fR is typically used to allow a
feature to be turned off entirely, e.g. set a cursor value to
\fBNone\fR so that a window simply inherits its parent's cursor.
Not all option types support the \fBTK_OPTION_NULL_OK\fR
flag; for those that do, there is an explicit indication of that fact
in the descriptions below.
+.TP
+\fBTK_OPTION_DONT_SET_DEFAULT\fR
+If this bit is set for an option then no default value will be set in
+\fBTk_InitOptions\fR for this option. Neither the option database, nor any
+system default value, nor \fIoptionTable\fR are used to give a default
+value to this option. Instead it is assumed that the caller has already
+supplied a default value in the widget code.
.PP
The \fItype\fR field of each Tk_OptionSpec structure determines
how to parse the value of that configuration option. The
diff --git a/doc/colors.n b/doc/colors.n
index 46c35aa..584e0ca 100644
--- a/doc/colors.n
+++ b/doc/colors.n
@@ -933,19 +933,19 @@ On Windows, the following additional system colors are available
.RS
.DS
.ta 6c
-3dDarkShadow Highlight
-3dLight HighlightText
-ActiveBorder InactiveBorder
-ActiveCaption InactiveCaption
-AppWorkspace InactiveCaptionText
-Background InfoBackground
-ButtonFace InfoText
-ButtonHighlight Menu
-ButtonShadow MenuText
-ButtonText Scrollbar
-CaptionText Window
-DisabledText WindowFrame
-GrayText WindowText
+system3dDarkShadow systemHighlight
+system3dLight systemHighlightText
+systemActiveBorder systemInactiveBorder
+systemActiveCaption systemInactiveCaption
+systemAppWorkspace systemInactiveCaptionText
+systemBackground systemInfoBackground
+systemButtonFace systemInfoText
+systemButtonHighlight systemMenu
+systemButtonShadow systemMenuText
+systemButtonText systemScrollbar
+systemCaptionText systemWindow
+systemDisabledText systemWindowFrame
+systemGrayText systemWindowText
.DE
.RE
.SH "SEE ALSO"
diff --git a/doc/event.n b/doc/event.n
index 0a5ced5..85033e9 100644
--- a/doc/event.n
+++ b/doc/event.n
@@ -424,7 +424,7 @@ the physical event.
.PP
Bindings on a virtual event may be created before the virtual event exists.
Indeed, the virtual event never actually needs to be defined, for instance,
-on platforms where the specific virtual event would meaningless or
+on platforms where the specific virtual event would be meaningless or
ungeneratable.
.PP
When a definition of a virtual event changes at run time, all windows
diff --git a/doc/listbox.n b/doc/listbox.n
index b2e8e38..aecc8e2 100644
--- a/doc/listbox.n
+++ b/doc/listbox.n
@@ -414,7 +414,7 @@ In \fBbrowse\fR mode it is also possible to drag the selection
with button 1.
.VS 8.5
On button 1, the listbox will also take focus if it has a \fBnormal\fR
-state and \fB\-takefocus\fR is true.
+state.
.VE 8.5
.PP
If the selection mode is \fBmultiple\fR or \fBextended\fR,
@@ -431,9 +431,12 @@ Most people will probably want to use \fBbrowse\fR mode for
single selections and \fBextended\fR mode for multiple selections;
the other modes appear to be useful only in special situations.
.PP
-Any time the selection changes in the listbox, the virtual event
-\fB<<ListboxSelect>>\fR will be generated. It is easiest to bind
-to this event to be made aware of any changes to listbox selection.
+Any time the set of selected item(s) in the listbox is updated by the
+user through the keyboard or mouse, the virtual event
+\fB<<ListboxSelect>>\fR will be generated. This virtual event will not
+be generated when adjusting the selection with the \fIpathName
+\fBselection\fR command. It is easiest to bind to this event to be
+made aware of any user changes to listbox selection.
.PP
In addition to the above behavior, the following additional behavior
is defined by the default bindings:
diff --git a/doc/menu.n b/doc/menu.n
index 6d0dc8a..1c943f9 100644
--- a/doc/menu.n
+++ b/doc/menu.n
@@ -285,15 +285,10 @@ operations on the widget. It has the following general form:
determine the exact behavior of the command.
.PP
Many of the widget commands for a menu take as one argument an
-indicator of which entry of the menu to operate on. These
+indicator of which entry of the menu to operate on. These
indicators are called \fIindex\fRes and may be specified in
any of the following forms:
.TP 12
-\fInumber\fR
-Specifies the entry numerically, where 0 corresponds
-to the top-most entry of the menu, 1 to the entry below it, and
-so on.
-.TP 12
\fBactive\fR
Indicates the entry that is currently active. If no entry is
active then this form is equivalent to \fBnone\fR. This form may
@@ -323,6 +318,11 @@ For example,
.QW \fB@0\fR
indicates the top-most entry in the window.
.TP 12
+\fInumber\fR
+Specifies the entry numerically, where 0 corresponds
+to the top-most entry of the menu, 1 to the entry below it, and
+so on.
+.TP 12
\fIpattern\fR
If the index does not satisfy one of the above forms then this
form is used. \fIPattern\fR is pattern-matched against the label of
@@ -330,6 +330,9 @@ each entry in the menu, in order from the top down, until a
matching entry is found. The rules of \fBTcl_StringMatch\fR
are used.
.PP
+If the index could match more than one of the above forms, then
+the form earlier in the above list takes precedence.
+.PP
The following widget commands are possible for menu widgets:
.TP
\fIpathName \fBactivate \fIindex\fR
diff --git a/doc/messageBox.n b/doc/messageBox.n
index bbeffee..5ce1745 100644
--- a/doc/messageBox.n
+++ b/doc/messageBox.n
@@ -3,7 +3,7 @@
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-'\"
+'\"
.TH tk_messageBox n 4.2 Tk "Tk Built-In Commands"
.so man.macros
.BS
@@ -13,7 +13,6 @@ tk_messageBox \- pops up a message window and waits for user response.
.SH SYNOPSIS
\fBtk_messageBox \fR?\fIoption value ...\fR?
.BE
-
.SH DESCRIPTION
.PP
This procedure creates and displays a message window with an
@@ -22,70 +21,84 @@ the buttons in the message window is identified by a unique symbolic
name (see the \fB\-type\fR options). After the message window is
popped up, \fBtk_messageBox\fR waits for the user to select one of the
buttons. Then it returns the symbolic name of the selected button.
-
+.PP
The following option-value pairs are supported:
.TP
\fB\-default\fR \fIname\fR
+.
\fIName\fR gives the symbolic name of the default button for
this message window (
.QW ok ,
.QW cancel ,
-and so on). See \fB\-type\fR
+and so on). See \fB\-type\fR
for a list of the symbolic names. If this option is not specified,
the first button in the dialog will be made the default.
.TP
\fB\-detail\fR \fIstring\fR
-.VS 8.5
+.
Specifies an auxiliary message to the main message given by the
-\fB\-message\fR option. Where supported by the underlying OS, the
-message detail will be presented in a less emphasized font than the
+\fB\-message\fR option. The message detail will be presented beneath the main
+message and, where supported by the OS, in a less emphasized font than the
main message.
-.VE 8.5
.TP
\fB\-icon\fR \fIiconImage\fR
+.
Specifies an icon to display. \fIIconImage\fR must be one of the
following: \fBerror\fR, \fBinfo\fR, \fBquestion\fR or
\fBwarning\fR. If this option is not specified, then the info icon will be
displayed.
.TP
\fB\-message\fR \fIstring\fR
-Specifies the message to display in this message box.
+.
+Specifies the message to display in this message box. The
+default value is an empty string.
.TP
\fB\-parent\fR \fIwindow\fR
+.
Makes \fIwindow\fR the logical parent of the message box. The message
box is displayed on top of its parent window.
.TP
\fB\-title\fR \fItitleString\fR
-Specifies a string to display as the title of the message box. The
-default value is an empty string.
+.
+Specifies a string to display as the title of the message box. This option
+is ignored on Mac OS X, where platform guidelines forbid the use of a title
+on this kind of dialog.
.TP
\fB\-type\fR \fIpredefinedType\fR
+.
Arranges for a predefined set of buttons to be displayed. The
following values are possible for \fIpredefinedType\fR:
.RS
.TP 18
\fBabortretryignore\fR
+.
Displays three buttons whose symbolic names are \fBabort\fR,
\fBretry\fR and \fBignore\fR.
.TP 18
\fBok\fR
+.
Displays one button whose symbolic name is \fBok\fR.
.TP 18
\fBokcancel\fR
+.
Displays two buttons whose symbolic names are \fBok\fR and \fBcancel\fR.
.TP 18
\fBretrycancel\fR
+.
Displays two buttons whose symbolic names are \fBretry\fR and \fBcancel\fR.
.TP 18
\fByesno\fR
+.
Displays two buttons whose symbolic names are \fByes\fR and \fBno\fR.
.TP 18
\fByesnocancel\fR
+.
Displays three buttons whose symbolic names are \fByes\fR, \fBno\fR
and \fBcancel\fR.
.RE
.PP
.SH EXAMPLE
+.PP
.CS
set answer [\fBtk_messageBox\fR \-message "Really quit?" \e
\-icon question \-type yesno \e
@@ -96,6 +109,8 @@ switch \-\- $answer {
\-type ok}
}
.CE
-
.SH KEYWORDS
message box
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/doc/panedwindow.n b/doc/panedwindow.n
index 53a7238..33e1e12 100644
--- a/doc/panedwindow.n
+++ b/doc/panedwindow.n
@@ -29,6 +29,16 @@ drawn as squares. May be any value accepted by \fBTk_GetPixels\fR.
Specifies a desired height for the overall panedwindow widget. May be any
value accepted by \fBTk_GetPixels\fR. If an empty string, the widget will be
made high enough to allow all contained widgets to have their natural height.
+.OP \-proxybackground proxyBackground ProxyBackground
+Background color to use when drawing the proxy. If an empty string, the
+value of the \fB-background\fR option will be used.
+.OP \-proxyborderwidth proxyBorderWidth ProxyBorderWidth
+Specifies the borderwidth of the proxy. May be any value accepted by
+\fBTk_GetPixels\fR.
+.OP \-proxyrelief proxyRelief ProxyRelief
+Relief to use when drawing the proxy. May be any of the standard Tk
+relief values. If an empty string, the value of the \fB-sashrelief\fR
+option will be used.
.OP \-opaqueresize opaqueResize OpaqueResize
Specifies whether panes should be resized as a sash is moved (true),
or if resizing should be deferred until the sash is placed (false).
diff --git a/doc/spinbox.n b/doc/spinbox.n
index 8ae6161..34b7014 100644
--- a/doc/spinbox.n
+++ b/doc/spinbox.n
@@ -196,7 +196,7 @@ dangerous to mix. Any problems have been overcome so that using the
the spinbox widget. Using the \fBtextVariable\fR for read-only purposes will
never cause problems. The danger comes when you try set the
\fBtextVariable\fR to something that the \fBvalidateCommand\fR would not
-accept, which causes \fBvalidate\fR to become \fInone\fR (the
+accept, which causes \fBvalidate\fR to become \fBnone\fR (the
\fBinvalidCommand\fR will not be triggered). The same happens
when an error occurs evaluating the \fBvalidateCommand\fR.
.PP
@@ -216,6 +216,16 @@ in the \fBvalidateCommand\fR or \fBinvalidCommand\fR (whichever one you
were editing the spinbox widget from). It is also recommended to not set an
associated \fBtextVariable\fR during validation, as that can cause the
spinbox widget to become out of sync with the \fBtextVariable\fR.
+.PP
+Also, the \fBvalidate\fR option will set itself to \fBnone\fR when the
+spinbox value gets changed because of adjustment of \fBfrom\fR or \fBto\fR
+and the \fBvalidateCommand\fR returns false. For instance
+.CS
+ \fIspinbox pathName \-from 1 \-to 10 \-validate all \-vcmd {return 0}\fR
+.CE
+will in fact set the \fBvalidate\fR option to \fBnone\fR because the default
+value for the spinbox gets changed (due to the \fBfrom\fR and \fBto\fR
+options) to a value not accepted by the validation script.
.SH "WIDGET COMMAND"
.PP
The \fBspinbox\fR command creates a new Tcl command whose
diff --git a/doc/text.n b/doc/text.n
index 5b7804a..32019ce 100644
--- a/doc/text.n
+++ b/doc/text.n
@@ -1127,12 +1127,12 @@ each counting option given. Valid counting options are \fB\-chars\fR,
\fB\-displaychars\fR, \fB\-displayindices\fR, \fB\-displaylines\fR,
\fB\-indices\fR, \fB\-lines\fR, \fB\-xpixels\fR and \fB\-ypixels\fR. The
default value, if no option is specified, is \fB\-indices\fR. There is an
-additional possible option \fB\-update\fR which is a modifier. If given,
-then all subsequent options ensure that any possible out of date
-information is recalculated. This currently only has any effect for the
-\fI\-ypixels\fR count (which, if \fB\-update\fR is not given, will use the text
-widget's current cached value for each line). The count options are
-interpreted as follows:
+additional possible option \fB\-update\fR which is a modifier. If given (and
+if the text widget is managed by a geometry manager), then all subsequent
+options ensure that any possible out of date information is recalculated.
+This currently only has any effect for the \fI\-ypixels\fR count (which, if
+\fB\-update\fR is not given, will use the text widget's current cached value
+for each line). The count options are interpreted as follows:
.RS
.IP \fB\-chars\fR
count all characters, whether elided or not. Do not count
@@ -1259,8 +1259,8 @@ information about marks, tags, and embedded windows.
If \fIindex2\fR is not specified, then it defaults to
one character past \fIindex1\fR. The information is returned
in the following format:
-.LP
.RS
+.LP
\fIkey1 value1 index1 key2 value2 index2\fR ...
.LP
The possible \fIkey\fR values are \fBtext\fR, \fBmark\fR,
@@ -2226,9 +2226,8 @@ after copying it to the clipboard.
Control-t reverses the order of the two characters to the right of
the insertion cursor.
.IP [32]
-Control-z (and Control-underscore on UNIX when \fBtk_strictMotif\fR is
-true) undoes the last edit action if the \fB\-undo\fR option is true.
-Does nothing otherwise.
+Control-z (undoes the last edit action if the \fB\-undo\fR option is
+true. Does nothing otherwise.
.IP [33]
Control-Z (or Control-y on Windows) reapplies the last undone edit
action if the \fB\-undo\fR option is true. Does nothing otherwise.
diff --git a/doc/tk_mac.n b/doc/tk_mac.n
new file mode 100644
index 0000000..f29ef2f
--- /dev/null
+++ b/doc/tk_mac.n
@@ -0,0 +1,237 @@
+'\"
+'\" Copyright (c) 2011 Kevin Walzer.
+'\" Copyright (c) 2011 Donal K. Fellows.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+.TH tk::mac n 8.6 Tk "Tk Built-In Commands"
+.so man.macros
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+tk::mac \- Access Mac-Specific Functionality on OS X from Tk
+.SH SYNOPSIS
+.nf
+\fB::tk::mac::ShowPreferences\fR
+\fB::tk::mac::OpenApplication\fR
+\fB::tk::mac::ReopenApplication\fR
+\fB::tk::mac::OpenDocument \fIfile...\fR
+\fB::tk::mac::PrintDocument \fIfile...\fR
+\fB::tk::mac::Quit\fR
+\fB::tk::mac::OnHide\fR
+\fB::tk::mac::OnShow\fR
+\fB::tk::mac::ShowHelp\fR
+
+\fB::tk::mac::standardAboutPanel\fR
+
+\fB::tk::mac::useCompatibilityMetrics \fIboolean\fR
+\fB::tk::mac::CGAntialiasLimit \fIlimit\fR
+\fB::tk::mac::antialiasedtext \fInumber\fR
+\fB::tk::mac::useThemedToplevel \fIboolean\fR
+
+\fB::tk::mac::iconBitmap \fIname width height \-kind value\fR
+.fi
+.BE
+.SH "EVENT HANDLER CALLBACKS"
+.PP
+The Aqua/Mac OS X application environment defines a number of additional
+events that applications should respond to. These events are mapped by Tk to
+calls to commands in the \fB::tk::mac\fR namespace; unless otherwise noted, if
+the command is absent, no action will be taken.
+.TP
+\fB::tk::mac::ShowPreferences\fR
+.
+The default Apple Event handler for kAEShowPreferences,
+.QW pref .
+The application menu
+.QW "Preferences"
+menu item is only enabled when this proc is defined. Typically this command is
+used to wrap a specific own preferences command, which pops up a preferences
+window. Something like:
+.RS
+.PP
+.CS
+proc ::tk::mac::ShowPreferences {} {
+ setPref
+}
+.CE
+.RE
+.TP
+\fB::tk::mac::OpenApplication\fR
+.
+If a proc of this name is defined, this proc fill fire when your application
+is intially opened. It is the default Apple Event handler for
+kAEOpenApplication,
+.QW oapp .
+.TP
+\fB::tk::mac::ReopenApplication\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEReopenApplication,
+.QW rapp ,
+the Apple Event sent when your application is opened when it is already
+running (e.g. by clicking its icon in the Dock). Here is a sample that raises
+a minimized window when the Dock icon is clicked:
+.RS
+.PP
+.CS
+proc ::tk::mac::ReopenApplication {} {
+ if {[wm state .] eq "withdrawn"} {
+ wm state . normal
+ } else {
+ wm deiconify .
+ }
+ raise .
+}
+.CE
+.RE
+.TP
+\fB::tk::mac::OpenDocument \fIfile...\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEOpenDocuments,
+.QW odoc ,
+the Apple Event sent when your application is asked to open one or more
+documents (e.g., by drag & drop onto the app or by opening a document of a
+type associated to the app). The proc should take as arguments paths to the
+files to be opened, like so:
+.RS
+.PP
+.CS
+proc ::tk::mac::OpenDocument {args} {
+ foreach f $args {my_open_document $f}
+}
+.CE
+.RE
+.TP
+\fB::tk::mac::PrintDocument \fIfile...\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEPrintDocuments,
+.QW pdoc ,
+the Apple Event sent when your application is asked to print one or more
+documents (e.g., via the Print menu item in the Finder). It works the same
+way as \fBtk::mac::OpenDocument\fR in terms of arguments.
+.TP
+\fB::tk::mac::Quit\fR
+.
+If a proc of this name is defined it is the default Apple Event handler for
+kAEQuitApplication,
+.QW quit ,
+the Apple Event sent when your application is asked to be quit, e.g. via the
+quit menu item in the application menu, the quit menu item in the Dock menu,
+or during a logout/restart/shutdown etc. If this is not defined, \fBexit\fR is
+called instead.
+.TP
+\fB::tk::mac::OnHide\fR
+.
+If defined, this is called when your application receives a kEventAppHidden
+event, e.g. via the hide menu item in the application or Dock menus.
+.TP
+\fB::tk::mac::OnShow\fR
+.
+If defined, this is called when your application receives a kEventAppShown
+event, e.g. via the show all menu item in the application menu, or by clicking
+the Dock icon of a hidden application.
+.TP
+\fB::tk::mac::ShowHelp\fR
+.
+Customizes behavior of Apple Help menu; if this procedure is not defined, the
+platform-specific standard Help menu item
+.QW "YourApp Help"
+performs the default Cocoa action of showing the Help Book configured in the
+application's Info.plist (or displaying an alert if no Help Book is set).
+.SH "ADDITIONAL DIALOGS"
+.PP
+The Aqua/Mac OS X defines additional dialogs that applications should
+support.
+.TP
+\fB::tk::mac::standardAboutPanel\fR
+.
+Brings the standard Cocoa about panel to the front, with all its information
+filled in from your application bundle files (standard about panel with no
+options specified). See Apple Technote TN2179 and the AppKit documentation for
+-[NSApplication orderFrontStandardAboutPanelWithOptions:] for details on the
+Info.plist keys and app bundle files used by the about panel.
+.SH "SYSTEM CONFIGURATION"
+.PP
+There are a number of additional global configuration options that control the
+details of how Tk renders by default.
+.TP
+\fB::tk::mac::useCompatibilityMetrics \fIboolean\fR
+.
+Preserves compatibility with older Tk/Aqua metrics; set to \fBfalse\fR for
+more native spacing.
+.TP
+\fB::tk::mac::CGAntialiasLimit \fIlimit\fR
+.
+Sets the antialiasing limit; lines thinner that \fIlimit\fR pixels will not be
+antialiased. Integer, set to 0 by default, making all lines be antialiased.
+.TP
+\fB::tk::mac::antialiasedtext \fInumber\fR
+.
+Sets anti-aliased text. Controls text antialiasing, possible values for
+\fInumber\fR are -1 (default, use system default for text AA), 0 (no text AA),
+1 (use text AA).
+.TP
+\fB::tk::mac::useThemedToplevel \fIboolean\fR
+.
+Sets toplevel windows to draw with the modern grayish/ pinstripe Mac
+background. Equivalent to configuring the toplevel with
+.QW "\fB\-background systemWindowHeaderBackground\fR" ,
+or to using a \fBttk::frame\fR.
+.SH "SUPPORT COMMANDS"
+.TP
+\fB::tk::mac::iconBitmap \fIname width height \-kind value\fR
+.
+Renders native icons and bitmaps in Tk applications (including any image file
+readable by NSImage). A native bitmap name is interpreted as follows (in
+order):
+.RS
+.IP \(bu 3
+predefined builtin 32x32 icon name (\fBstop\fR, \fBcaution\fR, \fBdocument\fR,
+etc.)
+.IP \(bu 3
+\fIname\fR, as defined by \fBtk::mac::iconBitmap\fR
+.IP \(bu 3
+NSImage named image name
+.IP \(bu 3
+NSImage url string
+.IP \(bu 3
+4-char OSType of IconServices icon
+.PP
+The \fIwidth\fR and \fIheight\fR arguments to \fBtk::mac::iconBitmap\fR define
+the dimensions of the image to create, and \fI\-kind\fR must be one of:
+.TP
+\fB\-file\fR
+.
+icon of file at given path
+.TP
+\fB\-fileType\fR
+.
+icon of given file type
+.TP
+\fB\-osType\fR
+.
+icon of given 4-char OSType file type
+.TP
+\fB\-systemType\fR
+.
+icon for given IconServices 4-char OSType
+.TP
+\fB\-namedImage\fR
+.
+named NSImage for given name
+.TP
+\fB\-imageFile\fR
+.
+image at given path
+.RE
+.SH "SEE ALSO"
+bind(n), wm(n)
+.SH KEYWORDS
+about dialog, antialiasing, Apple event, icon, NSImage
+'\" Local Variables:
+'\" mode: nroff
+'\" End:
diff --git a/generic/tk.h b/generic/tk.h
index e356ce5..bf43b41 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -59,10 +59,10 @@ extern "C" {
#define TK_MAJOR_VERSION 8
#define TK_MINOR_VERSION 5
#define TK_RELEASE_LEVEL TCL_FINAL_RELEASE
-#define TK_RELEASE_SERIAL 18
+#define TK_RELEASE_SERIAL 19
#define TK_VERSION "8.5"
-#define TK_PATCH_LEVEL "8.5.18"
+#define TK_PATCH_LEVEL "8.5.19"
/*
* A special definition used to allow this header file to be included from
diff --git a/generic/tkEntry.c b/generic/tkEntry.c
index 6683cdc..9f43f90 100644
--- a/generic/tkEntry.c
+++ b/generic/tkEntry.c
@@ -133,7 +133,7 @@ static const Tk_OptionSpec entryOptSpec[] = {
0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0},
{TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
+ TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
{TK_OPTION_STRING, "-show", "show", "Show",
DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar),
TK_OPTION_NULL_OK, 0, 0},
@@ -279,23 +279,23 @@ static const Tk_OptionSpec sbOptSpec[] = {
0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0},
{TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
+ TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
{TK_OPTION_STRING_TABLE, "-state", "state", "State",
DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
0, (ClientData) stateStrings, 0},
{TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
- TK_CONFIG_NULL_OK, 0, 0},
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
- TK_CONFIG_NULL_OK, 0, 0},
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_DOUBLE, "-to", "to", "To",
DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0},
{TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
0, (ClientData) validateStrings, 0},
{TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand",
- NULL, -1, Tk_Offset(Entry, validateCmd), TK_CONFIG_NULL_OK, 0, 0},
+ NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-values", "values", "Values",
DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr),
TK_OPTION_NULL_OK, 0, 0},
@@ -307,7 +307,7 @@ static const Tk_OptionSpec sbOptSpec[] = {
DEF_SPINBOX_WRAP, -1, Tk_Offset(Spinbox, wrap), 0, 0, 0},
{TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
- TK_CONFIG_NULL_OK, 0, 0},
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
};
@@ -390,8 +390,8 @@ static const char *selElementNames[] = {
*/
static int ConfigureEntry(Tcl_Interp *interp, Entry *entryPtr,
- int objc, Tcl_Obj *const objv[], int flags);
-static void DeleteChars(Entry *entryPtr, int index, int count);
+ int objc, Tcl_Obj *const objv[]);
+static int DeleteChars(Entry *entryPtr, int index, int count);
static void DestroyEntry(char *memPtr);
static void DisplayEntry(ClientData clientData);
static void EntryBlinkProc(ClientData clientData);
@@ -417,7 +417,7 @@ static int EntryValidateChange(Entry *entryPtr, char *change,
static void ExpandPercents(Entry *entryPtr, const char *before,
const char *change, const char *newStr, int index,
int type, Tcl_DString *dsPtr);
-static void EntryValueChanged(Entry *entryPtr,
+static int EntryValueChanged(Entry *entryPtr,
const char *newValue);
static void EntryVisibleRange(Entry *entryPtr,
double *firstPtr, double *lastPtr);
@@ -427,7 +427,7 @@ static int EntryWidgetObjCmd(ClientData clientData,
static void EntryWorldChanged(ClientData instanceData);
static int GetEntryIndex(Tcl_Interp *interp, Entry *entryPtr,
char *string, int *indexPtr);
-static void InsertChars(Entry *entryPtr, int index, char *string);
+static int InsertChars(Entry *entryPtr, int index, char *string);
/*
* These forward declarations are the spinbox specific ones:
@@ -553,7 +553,7 @@ Tk_EntryObjCmd(
if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin)
!= TCL_OK) ||
- (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK)) {
+ (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK)) {
Tk_DestroyWindow(entryPtr->tkwin);
return TCL_ERROR;
}
@@ -658,12 +658,12 @@ EntryWidgetObjCmd(
Tcl_SetObjResult(interp, objPtr);
}
} else {
- result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0);
+ result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
}
break;
case COMMAND_DELETE: {
- int first, last;
+ int first, last, code;
if ((objc < 3) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
@@ -680,7 +680,10 @@ EntryWidgetObjCmd(
goto error;
}
if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
- DeleteChars(entryPtr, first, last - first);
+ code = DeleteChars(entryPtr, first, last - first);
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -721,7 +724,7 @@ EntryWidgetObjCmd(
}
case COMMAND_INSERT: {
- int index;
+ int index, code;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "index text");
@@ -732,7 +735,10 @@ EntryWidgetObjCmd(
goto error;
}
if (entryPtr->state == STATE_NORMAL) {
- InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ code = InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -1080,8 +1086,7 @@ ConfigureEntry(
Entry *entryPtr, /* Information about widget; may or may not
* already have values for some fields. */
int objc, /* Number of valid entries in argv. */
- Tcl_Obj *const objv[], /* Argument objects. */
- int flags) /* Flags to pass to Tk_ConfigureWidget. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tk_SavedOptions savedOptions;
Tk_3DBorder border;
@@ -1096,6 +1101,7 @@ ConfigureEntry(
int valuesChanged = 0; /* lint initialization */
double oldFrom = 0.0; /* lint initialization */
double oldTo = 0.0; /* lint initialization */
+ int code;
/*
* Eliminate any existing trace on a variable monitored by the entry.
@@ -1298,6 +1304,17 @@ ConfigureEntry(
value = Tcl_GetVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY);
if (value == NULL) {
+
+ /*
+ * Since any trace on the textvariable was eliminated above,
+ * the only possible reason for EntryValueChanged to return
+ * an error is that the textvariable lives in a namespace
+ * that does not (yet) exist. Indeed, namespaces are not
+ * automatically created as needed. Don't trap this error
+ * here, better do it below when attempting to trace the
+ * variable.
+ */
+
EntryValueChanged(entryPtr, NULL);
} else {
EntrySetValue(entryPtr, value);
@@ -1316,7 +1333,13 @@ ConfigureEntry(
*/
Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr);
- EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
+
+ /*
+ * No check for error return here as well, because any possible
+ * error will be trapped below when attempting tracing.
+ */
+
+ EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
} else if ((sbPtr->valueStr == NULL)
&& !DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)
&& (!DOUBLES_EQ(sbPtr->fromValue, oldFrom)
@@ -1341,6 +1364,12 @@ ConfigureEntry(
}
}
sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);
+
+ /*
+ * No check for error return here as well, because any possible
+ * error will be trapped below when attempting tracing.
+ */
+
EntryValueChanged(entryPtr, sbPtr->formatBuf);
}
}
@@ -1352,10 +1381,13 @@ ConfigureEntry(
if ((entryPtr->textVarName != NULL)
&& !(entryPtr->flags & ENTRY_VAR_TRACED)) {
- Tcl_TraceVar(interp, entryPtr->textVarName,
+ code = Tcl_TraceVar(interp, entryPtr->textVarName,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
EntryTextVarProc, (ClientData) entryPtr);
- entryPtr->flags |= ENTRY_VAR_TRACED;
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ entryPtr->flags |= ENTRY_VAR_TRACED;
}
EntryWorldChanged((ClientData) entryPtr);
@@ -1675,7 +1707,7 @@ DisplayEntry(
Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &cursorX, NULL,
NULL, NULL);
cursorX += entryPtr->layoutX;
- cursorX -= (entryPtr->insertWidth)/2;
+ cursorX -= (entryPtr->insertWidth == 1) ? 1 : (entryPtr->insertWidth)/2;
Tk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent,
fm.ascent + fm.descent);
if (entryPtr->insertPos >= entryPtr->leftIndex && cursorX < xBound) {
@@ -1990,7 +2022,8 @@ EntryComputeGeometry(
* Add new characters to an entry widget.
*
* Results:
- * None.
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
*
* Side effects:
* New information gets added to entryPtr; it will be redisplayed soon,
@@ -1999,7 +2032,7 @@ EntryComputeGeometry(
*----------------------------------------------------------------------
*/
-static void
+static int
InsertChars(
Entry *entryPtr, /* Entry that is to get the new elements. */
int index, /* Add the new elements before this character
@@ -2017,7 +2050,7 @@ InsertChars(
byteIndex = Tcl_UtfAtIndex(string, index) - string;
byteCount = strlen(value);
if (byteCount == 0) {
- return;
+ return TCL_OK;
}
newByteCount = entryPtr->numBytes + byteCount + 1;
@@ -2031,7 +2064,7 @@ InsertChars(
EntryValidateChange(entryPtr, value, newStr, index,
VALIDATE_INSERT) != TCL_OK) {
ckfree(newStr);
- return;
+ return TCL_OK;
}
ckfree((char *)string);
@@ -2079,7 +2112,7 @@ InsertChars(
if (entryPtr->insertPos >= index) {
entryPtr->insertPos += charsAdded;
}
- EntryValueChanged(entryPtr, NULL);
+ return EntryValueChanged(entryPtr, NULL);
}
/*
@@ -2090,7 +2123,8 @@ InsertChars(
* Remove one or more characters from an entry widget.
*
* Results:
- * None.
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
*
* Side effects:
* Memory gets freed, the entry gets modified and (eventually)
@@ -2099,7 +2133,7 @@ InsertChars(
*----------------------------------------------------------------------
*/
-static void
+static int
DeleteChars(
Entry *entryPtr, /* Entry widget to modify. */
int index, /* Index of first character to delete. */
@@ -2113,7 +2147,7 @@ DeleteChars(
count = entryPtr->numChars - index;
}
if (count <= 0) {
- return;
+ return TCL_OK;
}
string = entryPtr->string;
@@ -2135,7 +2169,7 @@ DeleteChars(
VALIDATE_DELETE) != TCL_OK) {
ckfree(newStr);
ckfree(toDelete);
- return;
+ return TCL_OK;
}
ckfree(toDelete);
@@ -2194,7 +2228,7 @@ DeleteChars(
entryPtr->insertPos = index;
}
}
- EntryValueChanged(entryPtr, NULL);
+ return EntryValueChanged(entryPtr, NULL);
}
/*
@@ -2207,7 +2241,8 @@ DeleteChars(
* is one, and does other bookkeeping such as arranging for redisplay.
*
* Results:
- * None.
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
*
* Side effects:
* None.
@@ -2215,7 +2250,7 @@ DeleteChars(
*----------------------------------------------------------------------
*/
-static void
+static int
EntryValueChanged(
Entry *entryPtr, /* Entry whose value just changed. */
const char *newValue) /* If this value is not NULL, we first force
@@ -2229,7 +2264,7 @@ EntryValueChanged(
newValue = NULL;
} else {
newValue = Tcl_SetVar(entryPtr->interp, entryPtr->textVarName,
- entryPtr->string, TCL_GLOBAL_ONLY);
+ entryPtr->string, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
}
if ((newValue != NULL) && (strcmp(newValue, entryPtr->string) != 0)) {
@@ -2251,6 +2286,19 @@ EntryValueChanged(
EntryComputeGeometry(entryPtr);
EventuallyRedraw(entryPtr);
}
+
+ /*
+ * An error may have happened when setting the textvariable in case there
+ * is a trace on that variable and the trace proc triggered an error.
+ * Another possibility is that the textvariable is in a namespace that
+ * does not (yet) exist.
+ * Signal this error.
+ */
+
+ if ((entryPtr->textVarName != NULL) && (newValue == NULL)) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
}
/*
@@ -3588,7 +3636,7 @@ Tk_SpinboxObjCmd(
Tk_DestroyWindow(entryPtr->tkwin);
return TCL_ERROR;
}
- if (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK) {
+ if (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK) {
goto error;
}
@@ -3698,12 +3746,12 @@ SpinboxWidgetObjCmd(
Tcl_SetObjResult(interp, objPtr);
}
} else {
- result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0);
+ result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
}
break;
case SB_CMD_DELETE: {
- int first, last;
+ int first, last, code;
if ((objc < 3) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
@@ -3722,7 +3770,10 @@ SpinboxWidgetObjCmd(
}
}
if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
- DeleteChars(entryPtr, first, last - first);
+ code = DeleteChars(entryPtr, first, last - first);
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -3782,7 +3833,7 @@ SpinboxWidgetObjCmd(
}
case SB_CMD_INSERT: {
- int index;
+ int index, code;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "index text");
@@ -3793,7 +3844,10 @@ SpinboxWidgetObjCmd(
goto error;
}
if (entryPtr->state == STATE_NORMAL) {
- InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ code = InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -4001,16 +4055,22 @@ SpinboxWidgetObjCmd(
break;
}
- case SB_CMD_SET:
+ case SB_CMD_SET: {
+ int code = TCL_OK;
+
if (objc > 3) {
Tcl_WrongNumArgs(interp, 2, objv, "?string?");
goto error;
}
if (objc == 3) {
- EntryValueChanged(entryPtr, Tcl_GetString(objv[2]));
+ code = EntryValueChanged(entryPtr, Tcl_GetString(objv[2]));
+ if (code != TCL_OK) {
+ goto error;
+ }
}
Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1);
break;
+ }
case SB_CMD_VALIDATE: {
int code;
@@ -4151,7 +4211,7 @@ GetSpinboxElement(
* TCL_OK.
*
* Side effects:
- * An background error condition may arise when invoking the callback.
+ * A background error condition may arise when invoking the callback.
* The widget value may change.
*
*--------------------------------------------------------------
@@ -4182,6 +4242,7 @@ SpinboxInvoke(
return TCL_OK;
}
+ code = TCL_OK;
if (fabs(sbPtr->increment) > MIN_DBL_VAL) {
if (sbPtr->listObj != NULL) {
Tcl_Obj *objPtr;
@@ -4227,7 +4288,7 @@ SpinboxInvoke(
}
}
Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr);
- EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
+ code = EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
} else if (!DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)) {
double dvalue;
@@ -4274,9 +4335,12 @@ SpinboxInvoke(
}
}
sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);
- EntryValueChanged(entryPtr, sbPtr->formatBuf);
+ code = EntryValueChanged(entryPtr, sbPtr->formatBuf);
}
}
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
if (sbPtr->command != NULL) {
Tcl_DStringInit(&script);
diff --git a/generic/tkEvent.c b/generic/tkEvent.c
index 03e7283..747555e 100644
--- a/generic/tkEvent.c
+++ b/generic/tkEvent.c
@@ -2047,6 +2047,12 @@ TkFinalize(
{
ExitHandler *exitPtr;
+#if defined(_WIN32) && !defined(STATIC_BUILD)
+ if (!tclStubsPtr) {
+ return;
+ }
+#endif
+
Tcl_DeleteExitHandler(TkFinalize, NULL);
Tcl_MutexLock(&exitMutex);
diff --git a/generic/tkFont.c b/generic/tkFont.c
index 5d2ad43..7ff1ae9 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -2069,14 +2069,14 @@ Tk_ComputeTextLayout(
NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX,
baseline)->numDisplayChars = -1;
start++;
+ curX = newX;
+ flags &= ~TK_AT_LEAST_ONE;
if ((start < end) &&
((wrapLength <= 0) || (newX <= wrapLength))) {
/*
* More chars can still fit on this line.
*/
- curX = newX;
- flags &= ~TK_AT_LEAST_ONE;
continue;
}
} else {
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index 780b0c2..47aa523 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -2454,7 +2454,11 @@ ImgPhotoGet(
}
XFree((char *) visInfoPtr);
- sprintf(buf, ((mono) ? "%d": "%d/%d/%d"), nRed, nGreen, nBlue);
+ if (mono) {
+ sprintf(buf, "%d", nRed);
+ } else {
+ sprintf(buf, "%d/%d/%d", nRed, nGreen, nBlue);
+ }
instancePtr->defaultPalette = Tk_GetUid(buf);
/*
diff --git a/generic/tkInt.decls b/generic/tkInt.decls
index 7921852..f24d48c 100644
--- a/generic/tkInt.decls
+++ b/generic/tkInt.decls
@@ -957,7 +957,7 @@ declare 51 aqua {
void TkGenWMDestroyEvent(Tk_Window tkwin)
}
declare 52 aqua {
- TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag);
+ void TkMacOSXSetDrawingEnabled(TkWindow *winPtr, int flag)
}
# removed duplicate from tkPlat table (tk.decls)
diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h
index 7654b5d..86127fe 100644
--- a/generic/tkIntPlatDecls.h
+++ b/generic/tkIntPlatDecls.h
@@ -723,7 +723,7 @@ typedef struct TkIntPlatStubs {
Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */
void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */
- VOID *reserved52;
+ void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */
unsigned long (*tkpGetMS) (void); /* 53 */
VOID * (*tkMacOSXDrawable) (Drawable drawable); /* 54 */
int (*tkpScanWindowId) (Tcl_Interp *interp, CONST char *string, Window *idPtr); /* 55 */
@@ -1129,7 +1129,10 @@ extern TkIntPlatStubs *tkIntPlatStubsPtr;
#define TkGenWMDestroyEvent \
(tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 51 */
#endif
-/* Slot 52 is reserved */
+#ifndef TkMacOSXSetDrawingEnabled
+#define TkMacOSXSetDrawingEnabled \
+ (tkIntPlatStubsPtr->tkMacOSXSetDrawingEnabled) /* 52 */
+#endif
#ifndef TkpGetMS
#define TkpGetMS \
(tkIntPlatStubsPtr->tkpGetMS) /* 53 */
diff --git a/generic/tkListbox.c b/generic/tkListbox.c
index 248dd7b..86fb671 100644
--- a/generic/tkListbox.c
+++ b/generic/tkListbox.c
@@ -278,7 +278,7 @@ static const Tk_OptionSpec optionSpecs[] = {
Tk_Offset(Listbox, selBorderWidth), 0, 0, 0},
{TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
DEF_LISTBOX_SELECT_FG_COLOR, -1, Tk_Offset(Listbox, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_LISTBOX_SELECT_FG_MONO, 0},
+ TK_OPTION_NULL_OK, (ClientData) DEF_LISTBOX_SELECT_FG_MONO, 0},
{TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode",
DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(Listbox, selectMode),
TK_OPTION_NULL_OK, 0, 0},
@@ -379,7 +379,7 @@ enum indices {
static void ChangeListboxOffset(Listbox *listPtr, int offset);
static void ChangeListboxView(Listbox *listPtr, int index);
static int ConfigureListbox(Tcl_Interp *interp, Listbox *listPtr,
- int objc, Tcl_Obj *const objv[], int flags);
+ int objc, Tcl_Obj *const objv[]);
static int ConfigureListboxItem(Tcl_Interp *interp,
Listbox *listPtr, ItemAttr *attrs, int objc,
Tcl_Obj *const objv[], int index);
@@ -401,6 +401,7 @@ static void ListboxEventProc(ClientData clientData,
static int ListboxFetchSelection(ClientData clientData,
int offset, char *buffer, int maxBytes);
static void ListboxLostSelection(ClientData clientData);
+static void GenerateListboxSelectEvent(Listbox *listPtr);
static void EventuallyRedrawRange(Listbox *listPtr,
int first, int last);
static void ListboxScanTo(Listbox *listPtr, int x, int y);
@@ -563,7 +564,7 @@ Tk_ListboxObjCmd(
return TCL_ERROR;
}
- if (ConfigureListbox(interp, listPtr, objc-2, objv+2, 0) != TCL_OK) {
+ if (ConfigureListbox(interp, listPtr, objc-2, objv+2) != TCL_OK) {
Tk_DestroyWindow(listPtr->tkwin);
return TCL_ERROR;
}
@@ -699,7 +700,7 @@ ListboxWidgetObjCmd(
result = TCL_OK;
}
} else {
- result = ConfigureListbox(interp, listPtr, objc-2, objv+2, 0);
+ result = ConfigureListbox(interp, listPtr, objc-2, objv+2);
}
break;
}
@@ -1543,8 +1544,7 @@ ConfigureListbox(
register Listbox *listPtr, /* Information about widget; may or may not
* already have values for some fields. */
int objc, /* Number of valid entries in argv. */
- Tcl_Obj *const objv[], /* Arguments. */
- int flags) /* Flags to pass to Tk_ConfigureWidget. */
+ Tcl_Obj *const objv[]) /* Arguments. */
{
Tk_SavedOptions savedOptions;
Tcl_Obj *oldListObj = NULL;
@@ -3177,12 +3177,46 @@ ListboxLostSelection(
if ((listPtr->exportSelection) && (listPtr->nElements > 0)) {
ListboxSelect(listPtr, 0, listPtr->nElements-1, 0);
+ GenerateListboxSelectEvent(listPtr);
}
}
/*
*----------------------------------------------------------------------
*
+ * GenerateListboxSelectEvent --
+ *
+ * Send an event that the listbox selection was updated. This is
+ * equivalent to event generate $listboxWidget <<ListboxSelect>>
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Any side effect possible, depending on bindings to this event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateListboxSelectEvent(
+ Listbox *listPtr) /* Information about widget. */
+{
+ union {XEvent general; XVirtualEvent virtual;} event;
+
+ memset(&event, 0, sizeof(event));
+ event.general.xany.type = VirtualEvent;
+ event.general.xany.serial = NextRequest(Tk_Display(listPtr->tkwin));
+ event.general.xany.send_event = False;
+ event.general.xany.window = Tk_WindowId(listPtr->tkwin);
+ event.general.xany.display = Tk_Display(listPtr->tkwin);
+ event.virtual.name = Tk_GetUid("ListboxSelect");
+ Tk_HandleEvent(&event.general);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* EventuallyRedrawRange --
*
* Ensure that a given range of elements is eventually redrawn on the
diff --git a/generic/tkMenu.c b/generic/tkMenu.c
index 49b5935..b35be24 100644
--- a/generic/tkMenu.c
+++ b/generic/tkMenu.c
@@ -934,9 +934,14 @@ MenuWidgetObjCmd(
* Tearoff menus are posted differently on Mac and Windows than
* non-tearoffs. TkpPostMenu does not actually map the menu's window
* on those platforms, and popup menus have to be handled specially.
+ * Also, menubar menues are not intended to be posted (bug 1567681,
+ * 2160206).
*/
- if (menuPtr->menuType != TEAROFF_MENU) {
+ if (menuPtr->menuType == MENUBAR) {
+ Tcl_AppendResult(interp, "a menubar menu cannot be posted", NULL);
+ return TCL_ERROR;
+ } else if (menuPtr->menuType != TEAROFF_MENU) {
result = TkpPostMenu(interp, menuPtr, x, y);
} else {
result = TkPostTearoffMenu(interp, menuPtr, x, y);
diff --git a/generic/tkOldConfig.c b/generic/tkOldConfig.c
index 97ad5cb..d7a33f7 100644
--- a/generic/tkOldConfig.c
+++ b/generic/tkOldConfig.c
@@ -112,6 +112,10 @@ Tk_ConfigureWidget(
specs = GetCachedSpecs(interp, specs);
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;
+ }
+
/*
* Pass one: scan through all of the arguments, processing those that
* match entries in the specs.
@@ -167,7 +171,6 @@ Tk_ConfigureWidget(
if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)
|| (specPtr->argvName == NULL)
|| (specPtr->type == TK_CONFIG_SYNONYM)) {
- specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;
continue;
}
if (((specPtr->specFlags & needFlags) != needFlags)
@@ -1128,7 +1131,6 @@ GetCachedSpecs(
specPtr->defValue = Tk_GetUid(specPtr->defValue);
}
}
- specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED;
}
} else {
cachedSpecs = (Tk_ConfigSpec *) Tcl_GetHashValue(entryPtr);
diff --git a/generic/tkOption.c b/generic/tkOption.c
index 91a6cc0..95b140d 100644
--- a/generic/tkOption.c
+++ b/generic/tkOption.c
@@ -559,7 +559,7 @@ Tk_GetOption(
count -= levelPtr[-1].bases[currentStack];
}
- if (currentStack && CLASS) {
+ if (currentStack & CLASS) {
nodeId = winClassId;
} else {
nodeId = winNameId;
diff --git a/generic/tkPanedWindow.c b/generic/tkPanedWindow.c
index 6a3766b..99ed179 100644
--- a/generic/tkPanedWindow.c
+++ b/generic/tkPanedWindow.c
@@ -147,6 +147,10 @@ typedef struct PanedWindow {
GC gc; /* Graphics context for copying from
* off-screen pixmap onto screen. */
int proxyx, proxyy; /* Proxy x,y coordinates. */
+ Tk_3DBorder proxyBackground;/* Background color used to draw proxy. If NULL, use background. */
+ Tcl_Obj *proxyBorderWidthPtr; /* Tcl_Obj rep for proxyBorderWidth */
+ int proxyBorderWidth; /* Borderwidth used to draw proxy. */
+ int proxyRelief; /* Relief used to draw proxy, if TK_RELIEF_NULL then use relief. */
Slave **slaves; /* Pointer to array of Slaves. */
int numSlaves; /* Number of slaves. */
int sizeofSlaves; /* Number of elements in the slaves array. */
@@ -298,6 +302,15 @@ static const Tk_OptionSpec optionSpecs[] = {
{TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient),
0, (ClientData) orientStrings, GEOMETRY},
+ {TK_OPTION_BORDER, "-proxybackground", "proxyBackground", "ProxyBackground",
+ 0, -1, Tk_Offset(PanedWindow, proxyBackground), TK_OPTION_NULL_OK,
+ (ClientData) DEF_PANEDWINDOW_BG_MONO},
+ {TK_OPTION_PIXELS, "-proxyborderwidth", "proxyBorderWidth", "ProxyBorderWidth",
+ DEF_PANEDWINDOW_PROXYBORDER, Tk_Offset(PanedWindow, proxyBorderWidthPtr),
+ Tk_Offset(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY},
+ {TK_OPTION_RELIEF, "-proxyrelief", "proxyRelief", "Relief",
+ 0, -1, Tk_Offset(PanedWindow, proxyRelief),
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
DEF_PANEDWINDOW_RELIEF, -1, Tk_Offset(PanedWindow, relief), 0, 0, 0},
{TK_OPTION_CURSOR, "-sashcursor", "sashCursor", "Cursor",
@@ -2769,8 +2782,10 @@ DisplayProxyWindow(
* Redraw the widget's background and border.
*/
- Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, 0, 0,
- Tk_Width(tkwin), Tk_Height(tkwin), 2, pwPtr->sashRelief);
+ Tk_Fill3DRectangle(tkwin, pixmap,
+ pwPtr->proxyBackground ? pwPtr->proxyBackground : pwPtr->background,
+ 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), pwPtr->proxyBorderWidth,
+ (pwPtr->proxyRelief != TK_RELIEF_NULL) ? pwPtr->proxyRelief : pwPtr->sashRelief);
#ifndef TK_NO_DOUBLE_BUFFERING
/*
diff --git a/generic/tkScrollbar.c b/generic/tkScrollbar.c
index 3fff58d..ba42c20 100644
--- a/generic/tkScrollbar.c
+++ b/generic/tkScrollbar.c
@@ -627,6 +627,8 @@ TkScrollbarEventProc(
TkScrollbarEventuallyRedraw(scrollPtr);
}
}
+ } else if (eventPtr->type == MapNotify) {
+ TkScrollbarEventuallyRedraw(scrollPtr);
}
}
diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c
index 3ee54dd..90a124f 100644
--- a/generic/tkStubInit.c
+++ b/generic/tkStubInit.c
@@ -588,7 +588,7 @@ TkIntPlatStubs tkIntPlatStubs = {
TkGetTransientMaster, /* 49 */
TkGenerateButtonEvent, /* 50 */
TkGenWMDestroyEvent, /* 51 */
- NULL, /* 52 */
+ TkMacOSXSetDrawingEnabled, /* 52 */
TkpGetMS, /* 53 */
TkMacOSXDrawable, /* 54 */
TkpScanWindowId, /* 55 */
diff --git a/generic/tkText.c b/generic/tkText.c
index eb2d77a..8edf82d 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -197,18 +197,18 @@ static const Tk_OptionSpec optionSpecs[] = {
TK_OPTION_NULL_OK, (ClientData) DEF_TEXT_SELECT_BD_MONO, 0},
{TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
DEF_TEXT_SELECT_FG_COLOR, -1, Tk_Offset(TkText, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_TEXT_SELECT_FG_MONO, 0},
+ TK_OPTION_NULL_OK, (ClientData) DEF_TEXT_SELECT_FG_MONO, 0},
{TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
DEF_TEXT_SET_GRID, -1, Tk_Offset(TkText, setGrid), 0, 0, 0},
{TK_OPTION_PIXELS, "-spacing1", "spacing1", "Spacing",
DEF_TEXT_SPACING1, -1, Tk_Offset(TkText, spacing1),
- TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY },
+ 0, 0 , TK_TEXT_LINE_GEOMETRY },
{TK_OPTION_PIXELS, "-spacing2", "spacing2", "Spacing",
DEF_TEXT_SPACING2, -1, Tk_Offset(TkText, spacing2),
- TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY },
+ 0, 0 , TK_TEXT_LINE_GEOMETRY },
{TK_OPTION_PIXELS, "-spacing3", "spacing3", "Spacing",
DEF_TEXT_SPACING3, -1, Tk_Offset(TkText, spacing3),
- TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY },
+ 0, 0 , TK_TEXT_LINE_GEOMETRY },
{TK_OPTION_CUSTOM, "-startline", NULL, NULL,
NULL, -1, Tk_Offset(TkText, start), TK_OPTION_NULL_OK,
(ClientData) &lineOption, TK_TEXT_LINE_RANGE},
@@ -566,14 +566,6 @@ CreateWidget(
textPtr->end = NULL;
}
- /*
- * Register with the B-tree. In some sense it would be best if we could do
- * this later (after configuration options), so that any changes to
- * start,end do not require a total recalculation.
- */
-
- TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight);
-
textPtr->state = TK_TEXT_STATE_NORMAL;
textPtr->relief = TK_RELIEF_FLAT;
textPtr->cursor = None;
@@ -584,6 +576,14 @@ CreateWidget(
textPtr->prevHeight = Tk_Height(newWin);
/*
+ * Register with the B-tree. In some sense it would be best if we could do
+ * this later (after configuration options), so that any changes to
+ * start,end do not require a total recalculation.
+ */
+
+ TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight);
+
+ /*
* This will add refCounts to textPtr.
*/
@@ -2319,6 +2319,7 @@ TextWorldChanged(
{
Tk_FontMetrics fm;
int border;
+ int oldCharHeight = textPtr->charHeight;
textPtr->charWidth = Tk_TextWidth(textPtr->tkfont, "0", 1);
if (textPtr->charWidth <= 0) {
@@ -2330,6 +2331,9 @@ TextWorldChanged(
if (textPtr->charHeight <= 0) {
textPtr->charHeight = 1;
}
+ if (textPtr->charHeight != oldCharHeight) {
+ TkBTreeClientRangeChanged(textPtr, textPtr->charHeight);
+ }
border = textPtr->borderWidth + textPtr->highlightWidth;
Tk_GeometryRequest(textPtr->tkwin,
textPtr->width * textPtr->charWidth + 2*textPtr->padX + 2*border,
@@ -4205,7 +4209,11 @@ TextSearchFoundMatch(
matchOffset += Tcl_NumUtfChars(segPtr->body.chars, -1);
}
} else {
- leftToScan -= segPtr->size;
+ if (searchSpecPtr->exact) {
+ leftToScan -= segPtr->size;
+ } else {
+ leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1);
+ }
}
curIndex.byteIndex += segPtr->size;
}
diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c
index 36f0ef3..58fc645 100644
--- a/generic/tkTextBTree.c
+++ b/generic/tkTextBTree.c
@@ -1117,7 +1117,7 @@ TkBTreeInsertChars(
/*
* I don't believe it's possible for either of the two lines passed to
* this function to be the last line of text, but the function is robust
- * to that case anyway. (We must never re-calculated the line height of
+ * to that case anyway. (We must never re-calculate the line height of
* the last line).
*/
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index fc7b46b..1f39112 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -658,17 +658,8 @@ TkTextCreateDInfo(
dInfoPtr->metricEpoch = -1;
dInfoPtr->metricIndex.textPtr = NULL;
dInfoPtr->metricIndex.linePtr = NULL;
-
- /*
- * Add a refCount for each of the idle call-backs.
- */
-
- textPtr->refCount++;
- dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(0,
- AsyncUpdateLineMetrics, (ClientData) textPtr);
- textPtr->refCount++;
- dInfoPtr->scrollbarTimer = Tcl_CreateTimerHandler(200,
- AsyncUpdateYScrollbar, (ClientData) textPtr);
+ dInfoPtr->lineUpdateTimer = NULL;
+ dInfoPtr->scrollbarTimer = NULL;
textPtr->dInfoPtr = dInfoPtr;
}
@@ -1647,7 +1638,7 @@ LayoutDLine(
* Make one more pass over the line to recompute various things like its
* height, length, and total number of bytes. Also modify the x-locations
* of chunks to reflect justification. If we're not wrapping, I'm not sure
- * what is the best way to handle left and center justification: should
+ * what is the best way to handle right and center justification: should
* the total length, for purposes of justification, be (a) the window
* width, (b) the length of the longest line in the window, or (c) the
* length of the longest line in the text? (c) isn't available, (b) seems
@@ -2225,7 +2216,7 @@ UpdateDisplayInfo(
* Here's a problem: see the tests textDisp-29.2.1-4
*
* If the widget is being created, but has not yet been configured it will
- * have a maxY of 1 above, and we we won't have examined all the lines
+ * have a maxY of 1 above, and we won't have examined all the lines
* (just the first line, in fact), and so maxOffset will not be a true
* reflection of the widget's lines. Therefore we must not overwrite the
* original newXPixelOffset in this case.
@@ -2540,7 +2531,7 @@ DisplayLineBackground(
* current x coordinate? */
int matchRight; /* Does line's style match its neighbor just
* to the right of the current x-coord? */
- int minX, maxX, xOffset;
+ int minX, maxX, xOffset, bw;
StyleValues *sValuePtr;
Display *display;
#ifndef TK_NO_DOUBLE_BUFFERING
@@ -2611,16 +2602,25 @@ DisplayLineBackground(
rightX = leftX + 32767;
}
+ /*
+ * Prevent the borders from leaking on adjacent characters,
+ * which would happen for too large border width.
+ */
+
+ bw = sValuePtr->borderWidth;
+ if (leftX + sValuePtr->borderWidth > rightX) {
+ bw = rightX - leftX;
+ }
+
XFillRectangle(display, pixmap, chunkPtr->stylePtr->bgGC,
leftX + xOffset, y, (unsigned int) (rightX - leftX),
(unsigned int) dlPtr->height);
if (sValuePtr->relief != TK_RELIEF_FLAT) {
Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- leftX + xOffset, y, sValuePtr->borderWidth,
- dlPtr->height, 1, sValuePtr->relief);
+ leftX + xOffset, y, bw, dlPtr->height, 1,
+ sValuePtr->relief);
Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- rightX - sValuePtr->borderWidth + xOffset,
- y, sValuePtr->borderWidth, dlPtr->height, 0,
+ rightX - bw + xOffset, y, bw, dlPtr->height, 0,
sValuePtr->relief);
}
}
@@ -2717,22 +2717,29 @@ DisplayLineBackground(
matchRight = (nextPtr2 != NULL)
&& SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr);
if (matchLeft && !matchRight) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 - sValuePtr->borderWidth < leftX) {
+ bw = rightX2 - leftX;
+ }
if (sValuePtr->relief != TK_RELIEF_FLAT) {
Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- rightX2 - sValuePtr->borderWidth + xOffset, y,
- sValuePtr->borderWidth, sValuePtr->borderWidth, 0,
- sValuePtr->relief);
+ rightX2 - bw + xOffset, y, bw,
+ sValuePtr->borderWidth, 0, sValuePtr->relief);
}
- leftX = rightX2 - sValuePtr->borderWidth;
+ leftX = rightX2 - bw;
leftXIn = 0;
} else if (!matchLeft && matchRight
&& (sValuePtr->relief != TK_RELIEF_FLAT)) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 + sValuePtr->borderWidth > rightX) {
+ bw = rightX - rightX2;
+ }
Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- rightX2 + xOffset, y, sValuePtr->borderWidth,
- sValuePtr->borderWidth, 1, sValuePtr->relief);
+ rightX2 + xOffset, y, bw, sValuePtr->borderWidth,
+ 1, sValuePtr->relief);
Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- leftX + xOffset, y, rightX2 + sValuePtr->borderWidth -
- leftX, sValuePtr->borderWidth, leftXIn, 0, 1,
+ leftX + xOffset, y, rightX2 + bw - leftX,
+ sValuePtr->borderWidth, leftXIn, 0, 1,
sValuePtr->relief);
}
@@ -2764,7 +2771,7 @@ DisplayLineBackground(
chunkPtr2 = NULL;
if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) {
/*
- * Find the chunk in the previous line that covers leftX.
+ * Find the chunk in the next line that covers leftX.
*/
nextPtr2 = dlPtr->nextPtr->chunkPtr;
@@ -2820,26 +2827,33 @@ DisplayLineBackground(
matchRight = (nextPtr2 != NULL)
&& SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr);
if (matchLeft && !matchRight) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 - sValuePtr->borderWidth < leftX) {
+ bw = rightX2 - leftX;
+ }
if (sValuePtr->relief != TK_RELIEF_FLAT) {
Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- rightX2 - sValuePtr->borderWidth + xOffset,
+ rightX2 - bw + xOffset,
y + dlPtr->height - sValuePtr->borderWidth,
- sValuePtr->borderWidth, sValuePtr->borderWidth, 0,
- sValuePtr->relief);
+ bw, sValuePtr->borderWidth, 0, sValuePtr->relief);
}
- leftX = rightX2 - sValuePtr->borderWidth;
+ leftX = rightX2 - bw;
leftXIn = 1;
} else if (!matchLeft && matchRight
&& (sValuePtr->relief != TK_RELIEF_FLAT)) {
+ bw = sValuePtr->borderWidth;
+ if (rightX2 + sValuePtr->borderWidth > rightX) {
+ bw = rightX - rightX2;
+ }
Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- rightX2 + xOffset, y + dlPtr->height -
- sValuePtr->borderWidth, sValuePtr->borderWidth,
+ rightX2 + xOffset,
+ y + dlPtr->height - sValuePtr->borderWidth, bw,
sValuePtr->borderWidth, 1, sValuePtr->relief);
Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border,
- leftX + xOffset, y + dlPtr->height -
- sValuePtr->borderWidth, rightX2 + sValuePtr->borderWidth -
- leftX, sValuePtr->borderWidth, leftXIn, 1, 0,
- sValuePtr->relief);
+ leftX + xOffset,
+ y + dlPtr->height - sValuePtr->borderWidth,
+ rightX2 + bw - leftX, sValuePtr->borderWidth, leftXIn,
+ 1, 0, sValuePtr->relief);
}
nextChunk2b:
@@ -2889,9 +2903,10 @@ AsyncUpdateLineMetrics(
dInfoPtr->lineUpdateTimer = NULL;
- if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
+ if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)
+ || !Tk_IsMapped(textPtr->tkwin)) {
/*
- * The widget has been deleted. Don't do anything.
+ * The widget has been deleted, or is not mapped. Don't do anything.
*/
if (--textPtr->refCount == 0) {
@@ -5151,7 +5166,10 @@ TkTextSetYView(
dInfoPtr->newTopPixelOffset = 0;
goto scheduleUpdate;
- }
+ }
+ /*
+ * The line is already on screen, with no need to scroll.
+ */
return;
}
}
@@ -5214,6 +5232,15 @@ TkTextSetYView(
}
/*
+ * If the window height is smaller than the line height, prefer to make
+ * the top of the line visible.
+ */
+
+ if (dInfoPtr->maxY - dInfoPtr->y < lineHeight) {
+ bottomY = lineHeight;
+ }
+
+ /*
* Our job now is to arrange the display so that indexPtr appears as low
* on the screen as possible but with its bottom no lower than bottomY.
* BottomY is the bottom of the window if the desired line is just below
@@ -6563,6 +6590,7 @@ FindDLine(
CONST TkTextIndex *indexPtr)/* Index of desired character. */
{
DLine *dlPtrPrev;
+ TkTextIndex indexPtr2;
if (dlPtr == NULL) {
return NULL;
@@ -6587,24 +6615,58 @@ FindDLine(
dlPtrPrev = dlPtr;
dlPtr = dlPtr->nextPtr;
if (dlPtr == NULL) {
- TkTextIndex indexPtr2;
/*
* We're past the last display line, either because the desired
* index lies past the visible text, or because the desired index
- * is on the last display line showing the last logical line.
+ * is on the last display line.
*/
indexPtr2 = dlPtrPrev->index;
TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,
&indexPtr2);
if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {
+ /*
+ * The desired index is on the last display line.
+ * --> return this display line.
+ */
dlPtr = dlPtrPrev;
- break;
} else {
- return NULL;
+ /*
+ * The desired index is past the visible text. There is no
+ * display line displaying something at the desired index.
+ * --> return NULL.
+ */
}
+ break;
}
if (TkTextIndexCmp(&dlPtr->index,indexPtr) > 0) {
- dlPtr = dlPtrPrev;
+ /*
+ * If we're here then we would normally expect that:
+ * dlPtrPrev->index <= indexPtr < dlPtr->index
+ * i.e. we have found the searched display line being dlPtr.
+ * However it is possible that some DLines were unlinked
+ * previously, leading to a situation where going through
+ * the list of display lines skips display lines that did
+ * exist just a moment ago.
+ */
+ indexPtr2 = dlPtrPrev->index;
+ TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,
+ &indexPtr2);
+ if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {
+ /*
+ * Confirmed:
+ * dlPtrPrev->index <= indexPtr < dlPtr->index
+ * --> return dlPtrPrev.
+ */
+ dlPtr = dlPtrPrev;
+ } else {
+ /*
+ * The last (rightmost) index shown by dlPtrPrev is still
+ * before the desired index. This may be because there was
+ * previously a display line between dlPtrPrev and dlPtr
+ * and this display line has been unlinked.
+ * --> return dlPtr.
+ */
+ }
break;
}
}
diff --git a/generic/tkTextIndex.c b/generic/tkTextIndex.c
index 6a60faf..b886975 100644
--- a/generic/tkTextIndex.c
+++ b/generic/tkTextIndex.c
@@ -1695,7 +1695,7 @@ IndexCountBytesOrdered(
byteCount += segPtr->size;
}
- linePtr = indexPtr1->linePtr->nextPtr;
+ linePtr = TkBTreeNextLine(textPtr, indexPtr1->linePtr);
while (linePtr != indexPtr2->linePtr) {
for (segPtr = linePtr->segPtr; segPtr != NULL;
segPtr = segPtr->nextPtr) {
diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c
index dad03bf..a310dd7 100644
--- a/generic/tkTextTag.c
+++ b/generic/tkTextTag.c
@@ -44,11 +44,11 @@ static const Tk_OptionSpec tagOptionSpecs[] = {
{TK_OPTION_BITMAP, "-bgstipple", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_PIXELS, "-borderwidth", NULL, NULL,
- "0", Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth),
- TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0},
+ NULL, Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
{TK_OPTION_STRING, "-elide", NULL, NULL,
- "0", -1, Tk_Offset(TkTextTag, elideString),
- TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0},
+ NULL, -1, Tk_Offset(TkTextTag, elideString),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
{TK_OPTION_BITMAP, "-fgstipple", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_FONT, "-font", NULL, NULL,
diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c
index 8d1f850..5b511d2 100644
--- a/generic/tkTextWind.c
+++ b/generic/tkTextWind.c
@@ -1123,6 +1123,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))
@@ -1134,12 +1144,6 @@ TkTextEmbWinDisplayProc(
Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY,
width, height);
}
-
- /*
- * Mark the window as displayed so that it won't get unmapped.
- */
-
- client->displayed = 1;
}
/*
diff --git a/generic/ttk/ttkButton.c b/generic/ttk/ttkButton.c
index 2954184..bc44f25 100644
--- a/generic/ttk/ttkButton.c
+++ b/generic/ttk/ttkButton.c
@@ -413,8 +413,8 @@ typedef struct
static Tk_OptionSpec CheckbuttonOptionSpecs[] =
{
{TK_OPTION_STRING, "-variable", "variable", "Variable",
- "", Tk_Offset(Checkbutton, checkbutton.variableObj), -1,
- TK_OPTION_DONT_SET_DEFAULT,0,0},
+ NULL, Tk_Offset(Checkbutton, checkbutton.variableObj), -1,
+ TK_OPTION_NULL_OK,0,0},
{TK_OPTION_STRING, "-onvalue", "onValue", "OnValue",
"1", Tk_Offset(Checkbutton, checkbutton.onValueObj), -1,
0,0,0},
diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c
index 551f4a6..dd757cb 100644
--- a/generic/ttk/ttkNotebook.c
+++ b/generic/ttk/ttkNotebook.c
@@ -902,7 +902,7 @@ static int NotebookAddCommand(
if (tab->state == TAB_STATE_HIDDEN) {
tab->state = TAB_STATE_NORMAL;
}
- if (ConfigureTab(interp, nb, tab, slaveWindow, objc-4,objv+4) != TCL_OK) {
+ if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) {
return TCL_ERROR;
}
diff --git a/library/entry.tcl b/library/entry.tcl
index 382cc88..c3e573d 100644
--- a/library/entry.tcl
+++ b/library/entry.tcl
@@ -373,12 +373,18 @@ proc ::tk::EntryMouseSelect {w x} {
}
}
word {
- if {$cur < [$w index anchor]} {
+ if {$cur < $anchor} {
set before [tcl_wordBreakBefore [$w get] $cur]
set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]]
- } else {
+ } elseif {$cur > $anchor} {
set before [tcl_wordBreakBefore [$w get] $anchor]
set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]]
+ } else {
+ if {[$w index @$Priv(pressX)] < $anchor} {
+ incr anchor -1
+ }
+ set before [tcl_wordBreakBefore [$w get] $anchor]
+ set after [tcl_wordBreakAfter [$w get] $anchor]
}
if {$before < 0} {
set before 0
diff --git a/library/listbox.tcl b/library/listbox.tcl
index 2d9af20..5087786 100644
--- a/library/listbox.tcl
+++ b/library/listbox.tcl
@@ -118,7 +118,7 @@ bind Listbox <Control-Home> {
%W see 0
%W selection clear 0 end
%W selection set 0
- event generate %W <<ListboxSelect>>
+ tk::FireListboxSelectEvent %W
}
bind Listbox <Shift-Control-Home> {
tk::ListboxDataExtend %W 0
@@ -128,7 +128,7 @@ bind Listbox <Control-End> {
%W see end
%W selection clear 0 end
%W selection set end
- event generate %W <<ListboxSelect>>
+ tk::FireListboxSelectEvent %W
}
bind Listbox <Shift-Control-End> {
tk::ListboxDataExtend %W [%W index end]
@@ -163,7 +163,7 @@ bind Listbox <Control-slash> {
bind Listbox <Control-backslash> {
if {[%W cget -selectmode] ne "browse"} {
%W selection clear 0 end
- event generate %W <<ListboxSelect>>
+ tk::FireListboxSelectEvent %W
}
}
@@ -243,7 +243,7 @@ proc ::tk::ListboxBeginSelect {w el {focus 1}} {
set Priv(listboxSelection) {}
set Priv(listboxPrev) $el
}
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
# check existence as ListboxSelect may destroy us
if {$focus && [winfo exists $w] && [$w cget -state] eq "normal"} {
focus $w
@@ -271,7 +271,7 @@ proc ::tk::ListboxMotion {w el} {
$w selection clear 0 end
$w selection set $el
set Priv(listboxPrev) $el
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
}
extended {
set i $Priv(listboxPrev)
@@ -302,7 +302,7 @@ proc ::tk::ListboxMotion {w el} {
incr i -1
}
set Priv(listboxPrev) $el
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
}
}
}
@@ -353,7 +353,7 @@ proc ::tk::ListboxBeginToggle {w el} {
} else {
$w selection set $el
}
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
}
}
@@ -405,7 +405,7 @@ proc ::tk::ListboxUpDown {w amount} {
browse {
$w selection clear 0 end
$w selection set active
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
}
extended {
$w selection clear 0 end
@@ -413,7 +413,7 @@ proc ::tk::ListboxUpDown {w amount} {
$w selection anchor active
set Priv(listboxPrev) [$w index active]
set Priv(listboxSelection) {}
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
}
}
}
@@ -501,7 +501,7 @@ proc ::tk::ListboxCancel w {
}
incr first
}
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
}
# ::tk::ListboxSelectAll
@@ -521,5 +521,19 @@ proc ::tk::ListboxSelectAll w {
} else {
$w selection set 0 end
}
- event generate $w <<ListboxSelect>>
+ tk::FireListboxSelectEvent $w
+}
+
+# ::tk::FireListboxSelectEvent
+#
+# Fire the <<ListboxSelect>> event if the listbox is not in disabled
+# state.
+#
+# Arguments:
+# w - The listbox widget.
+
+proc ::tk::FireListboxSelectEvent w {
+ if {[$w cget -state] eq "normal"} {
+ event generate $w <<ListboxSelect>>
+ }
}
diff --git a/library/menu.tcl b/library/menu.tcl
index fd814b3..4875477 100644
--- a/library/menu.tcl
+++ b/library/menu.tcl
@@ -1037,7 +1037,7 @@ proc ::tk::MenuFind {w char} {
proc ::tk::TraverseToMenu {w char} {
variable ::tk::Priv
- if {$char eq ""} {
+ if {![winfo exists $w] || $char eq ""} {
return
}
while {[winfo class $w] eq "Menu"} {
diff --git a/library/scrlbar.tcl b/library/scrlbar.tcl
index 4b25325..43ce4ae 100644
--- a/library/scrlbar.tcl
+++ b/library/scrlbar.tcl
@@ -141,6 +141,13 @@ if {[tk windowingsystem] eq "aqua"} {
bind Scrollbar <Shift-Option-MouseWheel> {
tk::ScrollByUnits %W h [expr {-10 * (%D)}]
}
+} else {
+ bind Scrollbar <MouseWheel> {
+ tk::ScrollByUnits %W v [expr {- (%D /120 ) * 4}]
+ }
+ bind Scrollbar <Shift-MouseWheel> {
+ tk::ScrollByUnits %W h [expr {- (%D /120 ) * 4}]
+ }
}
# tk::ScrollButtonDown --
# This procedure is invoked when a button is pressed in a scrollbar.
diff --git a/library/text.tcl b/library/text.tcl
index 0e43e61..68ca0f5 100644
--- a/library/text.tcl
+++ b/library/text.tcl
@@ -85,7 +85,16 @@ bind Text <ButtonRelease-1> {
}
bind Text <Control-1> {
%W mark set insert @%x,%y
+ # An operation that moves the insert mark without making it
+ # one end of the selection must insert an autoseparator
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
}
+# stop an accidental double click triggering <Double-Button-1>
+bind Text <Double-Control-1> { # nothing }
+# stop an accidental movement triggering <B1-Motion>
+bind Text <Control-B1-Motion> { # nothing }
bind Text <Left> {
tk::TextSetCursor %W insert-1displayindices
}
@@ -241,6 +250,11 @@ bind Text <Control-slash> {
}
bind Text <Control-backslash> {
%W tag remove sel 1.0 end
+ # An operation that clears the selection must insert an autoseparator,
+ # because the selection operation may have moved the insert mark
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
}
bind Text <<Cut>> {
tk_textCut %W
@@ -252,7 +266,15 @@ bind Text <<Paste>> {
tk_textPaste %W
}
bind Text <<Clear>> {
+ # Make <<Clear>> an atomic operation on the Undo stack,
+ # i.e. separate it from other delete operations on either side
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
catch {%W delete sel.first sel.last}
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
}
bind Text <<PasteSelection>> {
if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
@@ -340,7 +362,16 @@ bind Text <Control-t> {
}
bind Text <<Undo>> {
+ # An Undo operation may remove the separator at the top of the Undo stack.
+ # Then the item at the top of the stack gets merged with the subsequent changes.
+ # Place separators before and after Undo to prevent this.
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
catch { %W edit undo }
+ if {[%W cget -autoseparators]} {
+ %W edit separator
+ }
}
bind Text <<Redo>> {
@@ -1054,9 +1085,18 @@ proc ::tk_textCopy w {
proc ::tk_textCut w {
if {![catch {set data [$w get sel.first sel.last]}]} {
+ # make <<Cut>> an atomic operation on the Undo stack,
+ # i.e. separate it from other delete operations on either side
+ set oldSeparator [$w cget -autoseparators]
+ if {$oldSeparator} {
+ $w edit separator
+ }
clipboard clear -displayof $w
clipboard append -displayof $w $data
$w delete sel.first sel.last
+ if {$oldSeparator} {
+ $w edit separator
+ }
}
}
diff --git a/library/tk.tcl b/library/tk.tcl
index a9db8cb..b971329 100644
--- a/library/tk.tcl
+++ b/library/tk.tcl
@@ -15,7 +15,7 @@ package require Tcl 8.5 ;# Guard against [source] in an 8.4- interp before
# Insist on running with compatible version of Tcl
package require Tcl 8.5.0
# Verify that we have Tk binary and script components from the same release
-package require -exact Tk 8.5.18
+package require -exact Tk 8.5.19
# Create a ::tk namespace
namespace eval ::tk {
@@ -308,7 +308,6 @@ proc ::tk::EventMotifBindings {n1 dummy dummy} {
event $op <<Cut>> <Control-Key-w>
event $op <<Copy>> <Meta-Key-w>
event $op <<Paste>> <Control-Key-y>
- event $op <<Undo>> <Control-underscore>
}
#----------------------------------------------------------------------
diff --git a/macosx/GNUmakefile b/macosx/GNUmakefile
index f3299e2..46f76d5 100644
--- a/macosx/GNUmakefile
+++ b/macosx/GNUmakefile
@@ -35,7 +35,7 @@ MANDIR ?= ${PREFIX}/man
TCL_BUILD_DIR ?= ${BUILD_DIR}/tcl/${BUILD_STYLE}
# location of installed tcl, only used if tcl in TCL_BUILD_DIR can't be found
TCL_FRAMEWORK_DIR ?= /Library/Frameworks
-TCLSH_DIR ?= ${PREFIX}
+TCLSH_DIR ?= ${PREFIX}/bin
# set to non-empty value to install manpages in addition to html help:
INSTALL_MANPAGES ?=
diff --git a/macosx/README b/macosx/README
index b992a2e..8940ee6 100644
--- a/macosx/README
+++ b/macosx/README
@@ -386,3 +386,64 @@ make overrides to the tk/macosx GNUmakefile, e.g.
sudo make -C tk${ver}/macosx install \
TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.
+
+4. About the event loop in Tk for Mac OSX
+-----------------------------------------
+
+The main program in a typical OSX application looks like this (see *)
+
+ void NSApplicationMain(int argc, char *argv[]) {
+ [NSApplication sharedApplication];
+ [NSBundle loadNibNamed:@"myMain" owner:NSApp];
+ [NSApp run];
+ }
+
+The run method implements the event loop for the application. There
+are three key steps in the run method. First it calls
+[NSApp finishLaunching], which creates the bouncing application icon
+and does other mysterious things. Second it creates an
+NSAutoreleasePool. Third, it starts an event loop which drains the
+NSAutoreleasePool every time the queue is empty, and replaces the
+drained pool with a new one. This third step is essential to
+preventing memory leaks, since the internal methods of Appkit objects
+all assume that an autorelease pool is in scope and will be drained
+when the event processing cycle ends.
+
+Mac OSX Tk does not call the [NSApp run] method at all. Instead it
+uses the event loop built in to Tk. So we must take care to replicate
+the important features of the method ourselves. Here is how this
+works in outline.
+
+We add a private NSAUtoreleasePool* property to our subclass of
+NSApplication. (The subclass is called TKApplication but can be
+referenced with the global variable NSApp). The TkpInit
+function calls [NSApp _setup] which initializes this property by
+creating an NSAutoreleasePool. A bit later on, TkpInit calls
+[NSAPP _setupEventLoop] which in turn calls the
+[NSApp finishLaunching] method.
+
+Each time that Tcl processes an event in its queue, it calls a
+platform specific function which, in the case of Mac OSX, is named
+TkMacOSXEventsCheckProc. In the unix implementations of Tk, including
+the Mac OSX version, this function collects events from an "event
+source", and transfers them to the Tcl event queue. In Mac OSX the
+event source is the NSApplication event queue. Each NSEvent is
+converted to a Tcl event which is added to the Tcl event queue. The
+NSEvent is also passed to [NSApp sendevent], which sends the event on
+to the application's NSWindows, which send it to their NSViews, etc.
+Since the CheckProc function gets called for every Tk event, it is an
+appropriate place to drain the main NSAutoreleasePool and replace it
+with a new pool. This is done by calling the method
+[NSApp _resetAutoreleasePool], where _resetAutoreleasePool is a method
+which we define for the subclass TKApplication.
+
+One minor caveat is that there are several steps of the Tk
+initialization which precede the call to TkpInit. Notably, the font
+package is initialized first. Since there is no NSAUtoreleasePool in
+scope prior to calling TkpInit, the functions called in these
+preliminary stages need to create and drain their own
+NSAutoreleasePools whenever they call methods of Appkit objects
+(e.g. NSFont).
+
+* https://developer.apple.com/library/mac/documentation/Cocoa/\
+Reference/ApplicationKit/Classes/NSApplication_Class
diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c
index adb78c6..35f4ab5 100644
--- a/macosx/tkMacOSXButton.c
+++ b/macosx/tkMacOSXButton.c
@@ -289,10 +289,10 @@ TkpComputeButtonGeometry(
if ( butPtr->indicatorOn ) {
switch (butPtr->type) {
case TYPE_RADIO_BUTTON:
- GetThemeMetric(kThemeMetricRadioButtonWidth, &butPtr->indicatorDiameter);
+ GetThemeMetric(kThemeMetricRadioButtonWidth, (SInt32 *)&butPtr->indicatorDiameter);
break;
case TYPE_CHECK_BUTTON:
- GetThemeMetric(kThemeMetricCheckBoxWidth, &butPtr->indicatorDiameter);
+ GetThemeMetric(kThemeMetricCheckBoxWidth, (SInt32 *)&butPtr->indicatorDiameter);
break;
default:
break;
diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h
index 0380de9..60d6cda 100644
--- a/macosx/tkMacOSXDefault.h
+++ b/macosx/tkMacOSXDefault.h
@@ -409,6 +409,7 @@
#define DEF_PANEDWINDOW_HEIGHT ""
#define DEF_PANEDWINDOW_OPAQUERESIZE "1"
#define DEF_PANEDWINDOW_ORIENT "horizontal"
+#define DEF_PANEDWINDOW_PROXYBORDER "2"
#define DEF_PANEDWINDOW_RELIEF "flat"
#define DEF_PANEDWINDOW_SASHCURSOR ""
#define DEF_PANEDWINDOW_SASHPAD "0"
diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c
index b5ff48b..84fef94 100644
--- a/macosx/tkMacOSXDialog.c
+++ b/macosx/tkMacOSXDialog.c
@@ -7,24 +7,34 @@
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
#include "tkMacOSXPrivate.h"
#include "tkFileFilter.h"
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+#define modalOK NSOKButton
+#define modalCancel NSCancelButton
+#else
+#define modalOK NSModalResponseOK
+#define modalCancel NSModalResponseCancel
+#endif
+#define modalOther -1
+#define modalError -2
+
static int TkBackgroundEvalObjv(Tcl_Interp *interp, int objc,
Tcl_Obj *const *objv, int flags);
-static const char *colorOptionStrings[] = {
+static const char *const colorOptionStrings[] = {
"-initialcolor", "-parent", "-title", NULL
};
enum colorOptions {
COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE
};
-static const char *openOptionStrings[] = {
+static const char *const openOptionStrings[] = {
"-defaultextension", "-filetypes", "-initialdir", "-initialfile",
"-message", "-multiple", "-parent", "-title", "-typevariable",
"-command", NULL
@@ -34,7 +44,7 @@ enum openOptions {
OPEN_MESSAGE, OPEN_MULTIPLE, OPEN_PARENT, OPEN_TITLE,
OPEN_TYPEVARIABLE, OPEN_COMMAND,
};
-static const char *saveOptionStrings[] = {
+static const char *const saveOptionStrings[] = {
"-defaultextension", "-filetypes", "-initialdir", "-initialfile",
"-message", "-parent", "-title", "-typevariable", "-command",
"-confirmoverwrite", NULL
@@ -44,7 +54,7 @@ enum saveOptions {
SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE, SAVE_TYPEVARIABLE, SAVE_COMMAND,
SAVE_CONFIRMOW
};
-static const char *chooseOptionStrings[] = {
+static const char *const chooseOptionStrings[] = {
"-initialdir", "-message", "-mustexist", "-parent", "-title", "-command",
NULL
};
@@ -58,7 +68,7 @@ typedef struct {
int multiple;
} FilePanelCallbackInfo;
-static const char *alertOptionStrings[] = {
+static const char *const alertOptionStrings[] = {
"-default", "-detail", "-icon", "-message", "-parent", "-title",
"-type", "-command", NULL
};
@@ -71,7 +81,7 @@ typedef struct {
Tcl_Obj *cmdObj;
int typeIndex;
} AlertCallbackInfo;
-static const char *alertTypeStrings[] = {
+static const char *const alertTypeStrings[] = {
"abortretryignore", "ok", "okcancel", "retrycancel", "yesno",
"yesnocancel", NULL
};
@@ -79,13 +89,13 @@ enum alertTypeOptions {
TYPE_ABORTRETRYIGNORE, TYPE_OK, TYPE_OKCANCEL, TYPE_RETRYCANCEL,
TYPE_YESNO, TYPE_YESNOCANCEL
};
-static const char *alertIconStrings[] = {
+static const char *const alertIconStrings[] = {
"error", "info", "question", "warning", NULL
};
enum alertIconOptions {
ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING
};
-static const char *alertButtonStrings[] = {
+static const char *const alertButtonStrings[] = {
"abort", "retry", "ignore", "ok", "cancel", "yes", "no", NULL
};
@@ -105,9 +115,9 @@ static const NSAlertStyle alertStyles[] = {
};
/*
- * Need to map from 'alertButtonStrings' and its corresponding integer,
- * index to the native button index, which is 1, 2, 3, from right to left.
- * This is necessary to do for each separate '-type' of button sets.
+ * Need to map from 'alertButtonStrings' and its corresponding integer, index
+ * to the native button index, which is 1, 2, 3, from right to left. This is
+ * necessary to do for each separate '-type' of button sets.
*/
static const short alertButtonIndexAndTypeToNativeButtonIndex[][7] = {
@@ -134,32 +144,53 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
[TYPE_YESNOCANCEL] = {5, 6, 4},
};
+/*
+ * Construct a file URL from directory and filename. Either may
+ * be nil. If both are nil, returns nil.
+ */
+#if MAC_OS_X_VERSION_MIN_REQUIRED > 1050
+static NSURL *getFileURL(NSString *directory, NSString *filename) {
+ NSURL *url = nil;
+ if (directory) {
+ url = [NSURL fileURLWithPath:directory];
+ }
+ if (filename) {
+ url = [NSURL URLWithString:filename relativeToURL:url];
+ }
+ return url;
+}
+#endif
+
#pragma mark TKApplication(TKDialog)
@interface NSColorPanel(TKDialog)
-- (void)_setUseModalAppearance:(BOOL)flag;
+- (void) _setUseModalAppearance: (BOOL) flag;
@end
@implementation TKApplication(TKDialog)
-- (void)tkFilePanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)returnCode
- contextInfo:(void *)contextInfo {
+
+- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
+ returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
+{
FilePanelCallbackInfo *callbackInfo = contextInfo;
if (returnCode == NSFileHandlingPanelOKButton) {
Tcl_Obj *resultObj;
+
if (callbackInfo->multiple) {
resultObj = Tcl_NewListObj(0, NULL);
- for (NSString *name in [(NSOpenPanel*)panel filenames]) {
+ for (NSURL *url in [(NSOpenPanel*)panel URLs]) {
Tcl_ListObjAppendElement(callbackInfo->interp, resultObj,
- Tcl_NewStringObj([name UTF8String], -1));
+ Tcl_NewStringObj([[url path] UTF8String], -1));
}
} else {
- resultObj = Tcl_NewStringObj([[panel filename] UTF8String], -1);
+ resultObj = Tcl_NewStringObj([[[panel URL]path] UTF8String], -1);
}
if (callbackInfo->cmdObj) {
Tcl_Obj **objv, **tmpv;
int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
callbackInfo->cmdObj, &objc, &objv);
+
if (result == TCL_OK && objc) {
tmpv = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
@@ -179,21 +210,25 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
}
if (callbackInfo->cmdObj) {
Tcl_DecrRefCount(callbackInfo->cmdObj);
- ckfree((char*) callbackInfo);
+ ckfree((char *)callbackInfo);
}
}
-- (void)tkAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode
- contextInfo:(void *)contextInfo {
+
+- (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode
+ contextInfo: (void *) contextInfo
+{
AlertCallbackInfo *callbackInfo = contextInfo;
- if (returnCode != NSAlertErrorReturn) {
+ if (returnCode >= NSAlertFirstButtonReturn) {
Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[
alertNativeButtonIndexAndTypeToButtonIndex[callbackInfo->
typeIndex][returnCode - NSAlertFirstButtonReturn]], -1);
+
if (callbackInfo->cmdObj) {
Tcl_Obj **objv, **tmpv;
int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
callbackInfo->cmdObj, &objc, &objv);
+
if (result == TCL_OK && objc) {
tmpv = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
@@ -211,7 +246,7 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
}
if (callbackInfo->cmdObj) {
Tcl_DecrRefCount(callbackInfo->cmdObj);
- ckfree((char*) callbackInfo);
+ ckfree((char *) callbackInfo);
}
}
@end
@@ -252,43 +287,41 @@ Tk_ChooseColorObjCmd(
for (i = 1; i < objc; i += 2) {
int index;
- const char *option, *value;
+ const char *value;
- if (Tcl_GetIndexFromObj(interp, objv[i], colorOptionStrings, "option",
- TCL_EXACT, &index) != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], colorOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
- option = Tcl_GetString(objv[i]);
- Tcl_AppendResult(interp, "value for \"", option, "\" missing",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "COLORDIALOG", "VALUE", NULL);
goto end;
}
value = Tcl_GetString(objv[i + 1]);
switch (index) {
- case COLOR_INITIAL: {
- XColor *colorPtr;
+ case COLOR_INITIAL: {
+ XColor *colorPtr;
- colorPtr = Tk_GetColor(interp, tkwin, value);
- if (colorPtr == NULL) {
- goto end;
- }
- initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel);
- Tk_FreeColor(colorPtr);
- break;
- }
- case COLOR_PARENT: {
- parent = Tk_NameToWindow(interp, value, tkwin);
- if (parent == NULL) {
- goto end;
- }
- break;
+ colorPtr = Tk_GetColor(interp, tkwin, value);
+ if (colorPtr == NULL) {
+ goto end;
}
- case COLOR_TITLE: {
- title = value;
- break;
+ initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel);
+ Tk_FreeColor(colorPtr);
+ break;
+ }
+ case COLOR_PARENT:
+ parent = Tk_NameToWindow(interp, value, tkwin);
+ if (parent == NULL) {
+ goto end;
}
+ break;
+ case COLOR_TITLE:
+ title = value;
+ break;
}
}
colorPanel = [NSColorPanel sharedColorPanel];
@@ -306,7 +339,7 @@ Tk_ChooseColorObjCmd(
[colorPanel setColor:initialColor];
}
returnCode = [NSApp runModalForWindow:colorPanel];
- if (returnCode == NSOKButton) {
+ if (returnCode == modalOK) {
color = [[colorPanel color] colorUsingColorSpace:
[NSColorSpace genericRGBColorSpace]];
numberOfComponents = [color numberOfComponents];
@@ -325,6 +358,7 @@ Tk_ChooseColorObjCmd(
Tcl_ResetResult(interp);
}
result = TCL_OK;
+
end:
return result;
}
@@ -365,17 +399,19 @@ Tk_GetOpenFileObjCmd(
NSWindow *parent;
NSMutableArray *fileTypes = nil;
NSOpenPanel *panel = [NSOpenPanel openPanel];
- NSInteger returnCode = NSAlertErrorReturn;
+ NSInteger modalReturnCode = modalError;
+ BOOL parentIsKey = NO;
TkInitFileFilters(&fl);
for (i = 1; i < objc; i += 2) {
- if (Tcl_GetIndexFromObj(interp, objv[i], openOptionStrings, "option",
- TCL_EXACT, &index) != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
- str = Tcl_GetString(objv[i]);
- Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -434,6 +470,7 @@ Tk_GetOpenFileObjCmd(
break;
}
}
+ [panel setAllowsMultipleSelection:multiple];
if (fl.filters) {
fileTypes = [NSMutableArray array];
for (FileFilter *filterPtr = fl.filters; filterPtr;
@@ -466,10 +503,9 @@ Tk_GetOpenFileObjCmd(
}
}
}
- [panel setAllowsMultipleSelection:multiple];
+ [panel setAllowedFileTypes:fileTypes];
if (cmdObj) {
- callbackInfo = (FilePanelCallbackInfo *)
- ckalloc(sizeof(FilePanelCallbackInfo));
+ callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -480,28 +516,51 @@ Tk_GetOpenFileObjCmd(
callbackInfo->multiple = multiple;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
- [panel beginSheetForDirectory:directory file:filename types:fileTypes
- modalForWindow:parent modalDelegate:NSApp didEndSelector:
- @selector(tkFilePanelDidEnd:returnCode:contextInfo:)
- contextInfo:callbackInfo];
- returnCode = cmdObj ? NSAlertOtherReturn :
- [NSApp runModalForWindow:panel];
+ parentIsKey = [parent isKeyWindow];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ [panel beginSheetForDirectory:directory
+ file:filename
+ types:fileTypes
+ modalForWindow:parent
+ modalDelegate:NSApp
+ didEndSelector:
+ @selector(tkFilePanelDidEnd:returnCode:contextInfo:)
+ contextInfo:callbackInfo];
+#else
+ [panel setAllowedFileTypes:fileTypes];
+ [panel setDirectoryURL:getFileURL(directory, filename)];
+ [panel beginSheetModalForWindow:parent
+ completionHandler:^(NSInteger returnCode)
+ { [NSApp tkFilePanelDidEnd:panel
+ returnCode:returnCode
+ contextInfo:callbackInfo ]; } ];
+#endif
+ modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
} else {
- returnCode = [panel runModalForDirectory:directory file:filename
- types:fileTypes];
- [NSApp tkFilePanelDidEnd:panel returnCode:returnCode
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ modalReturnCode = [panel runModalForDirectory:directory
+ file:filename];
+#else
+ [panel setDirectoryURL:getFileURL(directory, filename)];
+ modalReturnCode = [panel runModal];
+#endif
+ [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
contextInfo:callbackInfo];
}
- result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
+ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
if (typeVariablePtr && result == TCL_OK) {
/*
* The -typevariable option is not really supported.
*/
- Tcl_SetVar(interp, Tcl_GetString(typeVariablePtr), "",
- TCL_GLOBAL_ONLY);
+ Tcl_SetVar2(interp, Tcl_GetString(typeVariablePtr), NULL,
+ "", TCL_GLOBAL_ONLY);
}
-end:
+
+ end:
TkFreeFileFilters(&fl);
return result;
}
@@ -543,18 +602,19 @@ Tk_GetSaveFileObjCmd(
NSWindow *parent;
NSMutableArray *fileTypes = nil;
NSSavePanel *panel = [NSSavePanel savePanel];
- NSInteger returnCode = NSAlertErrorReturn;
+ NSInteger modalReturnCode = modalError;
+ BOOL parentIsKey = NO;
TkInitFileFilters(&fl);
for (i = 1; i < objc; i += 2) {
- if (Tcl_GetIndexFromObj(interp, objv[i], saveOptionStrings, "option",
- TCL_EXACT, &index) != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
- str = Tcl_GetString(objv[i]);
- Tcl_AppendResult(interp, "value for \"", str, "\" missing",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -614,7 +674,7 @@ Tk_GetSaveFileObjCmd(
break;
case SAVE_CONFIRMOW:
if (Tcl_GetBooleanFromObj(interp, objv[i + 1],
- &confirmOverwrite) != TCL_OK) {
+ &confirmOverwrite) != TCL_OK) {
goto end;
}
break;
@@ -649,8 +709,7 @@ Tk_GetSaveFileObjCmd(
[panel setCanSelectHiddenExtension:YES];
[panel setExtensionHidden:NO];
if (cmdObj) {
- callbackInfo = (FilePanelCallbackInfo *)
- ckalloc(sizeof(FilePanelCallbackInfo));
+ callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -661,19 +720,39 @@ Tk_GetSaveFileObjCmd(
callbackInfo->multiple = 0;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
- [panel beginSheetForDirectory:directory file:filename
- modalForWindow:parent modalDelegate:NSApp didEndSelector:
- @selector(tkFilePanelDidEnd:returnCode:contextInfo:)
- contextInfo:callbackInfo];
- returnCode = cmdObj ? NSAlertOtherReturn :
- [NSApp runModalForWindow:panel];
+ parentIsKey = [parent isKeyWindow];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ [panel beginSheetForDirectory:directory
+ file:filename
+ modalForWindow:parent
+ modalDelegate:NSApp
+ didEndSelector:
+ @selector(tkFilePanelDidEnd:returnCode:contextInfo:)
+ contextInfo:callbackInfo];
+#else
+ [panel setDirectoryURL:getFileURL(directory, filename)];
+ [panel beginSheetModalForWindow:parent
+ completionHandler:^(NSInteger returnCode)
+ { [NSApp tkFilePanelDidEnd:panel
+ returnCode:returnCode
+ contextInfo:callbackInfo ]; } ];
+#endif
+ modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
} else {
- returnCode = [panel runModalForDirectory:directory file:filename];
- [NSApp tkFilePanelDidEnd:panel returnCode:returnCode
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ modalReturnCode = [panel runModalForDirectory:directory file:filename];
+#else
+ [panel setDirectoryURL:getFileURL(directory, filename)];
+ modalReturnCode = [panel runModal];
+#endif
+ [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
contextInfo:callbackInfo];
}
- result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
-end:
+ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
+ end:
TkFreeFileFilters(&fl);
return result;
}
@@ -714,16 +793,18 @@ Tk_ChooseDirectoryObjCmd(
NSString *message, *title;
NSWindow *parent;
NSOpenPanel *panel = [NSOpenPanel openPanel];
- NSInteger returnCode = NSAlertErrorReturn;
+ NSInteger modalReturnCode = modalError;
+ BOOL parentIsKey = NO;
for (i = 1; i < objc; i += 2) {
- if (Tcl_GetIndexFromObj(interp, objv[i], chooseOptionStrings, "option",
- TCL_EXACT, &index) != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
- str = Tcl_GetString(objv[i]);
- Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -770,8 +851,7 @@ Tk_ChooseDirectoryObjCmd(
[panel setCanChooseDirectories:YES];
[panel setCanCreateDirectories:!mustexist];
if (cmdObj) {
- callbackInfo = (FilePanelCallbackInfo *)
- ckalloc(sizeof(FilePanelCallbackInfo));
+ callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -782,19 +862,38 @@ Tk_ChooseDirectoryObjCmd(
callbackInfo->multiple = 0;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
- [panel beginSheetForDirectory:directory file:filename
- modalForWindow:parent modalDelegate:NSApp didEndSelector:
- @selector(tkFilePanelDidEnd:returnCode:contextInfo:)
+ parentIsKey = [parent isKeyWindow];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ [panel beginSheetForDirectory:directory
+ file:filename
+ modalForWindow:parent
+ modalDelegate:NSApp
+ didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
- returnCode = cmdObj ? NSAlertOtherReturn :
- [NSApp runModalForWindow:panel];
+#else
+ [panel setDirectoryURL:getFileURL(directory, filename)];
+ [panel beginSheetModalForWindow:parent
+ completionHandler:^(NSInteger returnCode)
+ { [NSApp tkFilePanelDidEnd:panel
+ returnCode:returnCode
+ contextInfo:callbackInfo ]; } ];
+#endif
+ modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
} else {
- returnCode = [panel runModalForDirectory:directory file:filename];
- [NSApp tkFilePanelDidEnd:panel returnCode:returnCode
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ modalReturnCode = [panel runModalForDirectory:directory file:nil];
+#else
+ [panel setDirectoryURL:getFileURL(directory, filename)];
+ modalReturnCode = [panel runModal];
+#endif
+ [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
contextInfo:callbackInfo];
}
- result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
-end:
+ result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
+ end:
return result;
}
@@ -818,20 +917,29 @@ void
TkAboutDlg(void)
{
NSImage *image;
- NSString *path = [NSApp tkFrameworkImagePath:@"Tk.tiff"];
+ NSString *path = [NSApp tkFrameworkImagePath: @"Tk.tiff"];
+
if (path) {
image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
} else {
image = [NSApp applicationIconImage];
}
+
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:@"Y"];
+
NSString *year = [dateFormatter stringFromDate:[NSDate date]];
+
[dateFormatter release];
- NSMutableParagraphStyle *style = [[[NSParagraphStyle defaultParagraphStyle]
- mutableCopy] autorelease];
+
+ NSMutableParagraphStyle *style =
+ [[[NSParagraphStyle defaultParagraphStyle] mutableCopy]
+ autorelease];
+
[style setAlignment:NSCenterTextAlignment];
+
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"Tcl & Tk", @"ApplicationName",
@"Tcl " TCL_VERSION " & Tk " TK_VERSION, @"ApplicationVersion",
@@ -842,15 +950,15 @@ TkAboutDlg(void)
[[[NSAttributedString alloc] initWithString:
[NSString stringWithFormat:
@"%1$C 1987-%2$@ Tcl Core Team." "\n\n"
- "%1$C 1989-%2$@ Contributors." "\n\n"
+ "%1$C 1989-%2$@ Contributors." "\n\n"
"%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC." "\n\n"
"%1$C 2014-%2$@ Marc Culler." "\n\n"
- "%1$C 2002-%2$@ Daniel A. Steffen." "\n\n"
- "%1$C 2001-2009 Apple Inc." "\n\n"
- "%1$C 2001-2002 Jim Ingham & Ian Reid" "\n\n"
- "%1$C 1998-2000 Jim Ingham & Ray Johnson" "\n\n"
- "%1$C 1998-2000 Scriptics Inc." "\n\n"
- "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] attributes:
+ "%1$C 2002-%2$@ Daniel A. Steffen." "\n\n"
+ "%1$C 2001-2009 Apple Inc." "\n\n"
+ "%1$C 2001-2002 Jim Ingham & Ian Reid" "\n\n"
+ "%1$C 1998-2000 Jim Ingham & Ray Johnson" "\n\n"
+ "%1$C 1998-2000 Scriptics Inc." "\n\n"
+ "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] attributes:
[NSDictionary dictionaryWithObject:style
forKey:NSParagraphStyleAttributeName]] autorelease], @"Credits",
nil];
@@ -884,7 +992,7 @@ TkMacOSXStandardAboutPanelObjCmd(
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
- [NSApp orderFrontStandardAboutPanelWithOptions:nil];
+ [NSApp orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionary]];
return TCL_OK;
}
@@ -922,18 +1030,20 @@ Tk_MessageBoxObjCmd(
NSWindow *parent;
NSArray *buttons;
NSAlert *alert = [NSAlert new];
- NSInteger returnCode = NSAlertErrorReturn;
+ NSInteger modalReturnCode = 1;
+ BOOL parentIsKey = NO;
iconIndex = ICON_INFO;
typeIndex = TYPE_OK;
for (i = 1; i < objc; i += 2) {
- if (Tcl_GetIndexFromObj(interp, objv[i], alertOptionStrings, "option",
- TCL_EXACT, &index) != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i], alertOptionStrings,
+ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
- str = Tcl_GetString(objv[i]);
- Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "value for \"%s\" missing", Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "MSGBOX", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -954,8 +1064,8 @@ Tk_MessageBoxObjCmd(
break;
case ALERT_ICON:
- if (Tcl_GetIndexFromObj(interp, objv[i + 1], alertIconStrings,
- "value", TCL_EXACT, &iconIndex) != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertIconStrings,
+ sizeof(char *), "value", TCL_EXACT, &iconIndex) != TCL_OK) {
goto end;
}
break;
@@ -984,8 +1094,8 @@ Tk_MessageBoxObjCmd(
break;
case ALERT_TYPE:
- if (Tcl_GetIndexFromObj(interp, objv[i + 1], alertTypeStrings,
- "value", TCL_EXACT, &typeIndex) != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertTypeStrings,
+ sizeof(char *), "value", TCL_EXACT, &typeIndex) != TCL_OK) {
goto end;
}
break;
@@ -996,13 +1106,12 @@ Tk_MessageBoxObjCmd(
}
if (indexDefaultOption) {
/*
- * Any '-default' option needs to know the '-type' option, which is why
- * we do this here.
+ * Any '-default' option needs to know the '-type' option, which is
+ * why we do this here.
*/
- if (Tcl_GetIndexFromObj(interp, objv[indexDefaultOption + 1],
- alertButtonStrings, "value", TCL_EXACT, &index)
- != TCL_OK) {
+ if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1],
+ alertButtonStrings, sizeof(char *), "value", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
@@ -1015,6 +1124,7 @@ Tk_MessageBoxObjCmd(
if (!defaultNativeButtonIndex) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Illegal default option", -1));
+ Tcl_SetErrorCode(interp, "TK", "MSGBOX", "DEFAULT", NULL);
goto end;
}
}
@@ -1027,15 +1137,17 @@ Tk_MessageBoxObjCmd(
buttons = [alert buttons];
for (NSButton *b in buttons) {
NSString *ke = [b keyEquivalent];
+
if (([ke isEqualToString:@"\r"] || [ke isEqualToString:@"\033"]) &&
![b keyEquivalentModifierMask]) {
[b setKeyEquivalent:@""];
}
}
- [[buttons objectAtIndex:[buttons count]-1] setKeyEquivalent:@"\033"];
- [[buttons objectAtIndex:defaultNativeButtonIndex-1] setKeyEquivalent:@"\r"];
+ [[buttons objectAtIndex: [buttons count]-1] setKeyEquivalent: @"\033"];
+ [[buttons objectAtIndex: defaultNativeButtonIndex-1]
+ setKeyEquivalent: @"\r"];
if (cmdObj) {
- callbackInfo = (AlertCallbackInfo *) ckalloc(sizeof(AlertCallbackInfo));
+ callbackInfo = (AlertCallbackInfo *)ckalloc(sizeof(AlertCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -1046,19 +1158,32 @@ Tk_MessageBoxObjCmd(
callbackInfo->typeIndex = typeIndex;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
- [alert beginSheetModalForWindow:parent modalDelegate:NSApp
- didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:)
- contextInfo:callbackInfo];
- returnCode = cmdObj ? NSAlertOtherReturn :
- [NSApp runModalForWindow:[alert window]];
+ parentIsKey = [parent isKeyWindow];
+#if MAC_OS_X_VERSION_MIN_REQUIRED > 1090
+ [alert beginSheetModalForWindow:parent
+ completionHandler:^(NSModalResponse returnCode)
+ { [NSApp tkAlertDidEnd:alert
+ returnCode:returnCode
+ contextInfo:callbackInfo ]; } ];
+#else
+ [alert beginSheetModalForWindow:parent
+ modalDelegate:NSApp
+ didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:)
+ contextInfo:callbackInfo];
+#endif
+ modalReturnCode = cmdObj ? 0 :
+ [NSApp runModalForWindow:[alert window]];
} else {
- returnCode = [alert runModal];
- [NSApp tkAlertDidEnd:alert returnCode:returnCode
+ modalReturnCode = [alert runModal];
+ [NSApp tkAlertDidEnd:alert returnCode:modalReturnCode
contextInfo:callbackInfo];
}
- result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
-end:
+ result = (modalReturnCode >= NSAlertFirstButtonReturn) ? TCL_OK : TCL_ERROR;
+ end:
[alert release];
+ if (parentIsKey) {
+ [parent makeKeyWindow];
+ }
return result;
}
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 3f51d00..f376591 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -141,7 +141,7 @@ BitmapRepFromDrawableRect(
if ( mac_drawable->flags & TK_IS_PIXMAP ) {
/*
This means that the MacDrawable is functioning as a Tk Pixmap, so its view
- field is NULL. It's context field should point to a CGImage.
+ field is NULL.
*/
cg_context = GetCGContextForDrawable(drawable);
CGRect image_rect = CGRectMake(x, y, width, height);
@@ -199,10 +199,10 @@ XCopyArea(
Display *display, /* Display. */
Drawable src, /* Source drawable. */
Drawable dst, /* Destination drawable. */
- GC gc, /* GC to use. */
+ GC gc, /* GC to use. */
int src_x, /* X & Y, width & height */
int src_y, /* define the source rectangle */
- unsigned int width, /* that will be copied. */
+ unsigned int width, /* that will be copied. */
unsigned int height,
int dest_x, /* Dest X & Y on dest rect. */
int dest_y)
@@ -282,10 +282,10 @@ XCopyPlane(
Display *display, /* Display. */
Drawable src, /* Source drawable. */
Drawable dst, /* Destination drawable. */
- GC gc, /* GC to use. */
+ GC gc, /* GC to use. */
int src_x, /* X & Y, width & height */
int src_y, /* define the source rectangle */
- unsigned int width, /* that will be copied. */
+ unsigned int width, /* that will be copied. */
unsigned int height,
int dest_x, /* Dest X & Y on dest rect. */
int dest_y,
@@ -293,6 +293,7 @@ XCopyPlane(
{
TkMacOSXDrawingContext dc;
MacDrawable *srcDraw = (MacDrawable *) src;
+ MacDrawable *dstDraw = (MacDrawable *) dst;
display->request++;
if (!width || !height) {
@@ -306,33 +307,47 @@ XCopyPlane(
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
return;
}
- if (dc.context) {
+ CGContextRef context = dc.context;
+ if (context) {
CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
-
if (img) {
TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
unsigned long imageBackground = gc->background;
-
- if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP &&
- clipPtr->value.pixmap == src) {
- imageBackground = TRANSPARENT_PIXEL << 24;
+ if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){
+ CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap);
+ CGRect rect = CGRectMake(dest_x, dest_y, width, height);
+ rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
+ CGContextSaveGState(context);
+ /* Move the origin of the destination to top left. */
+ CGContextTranslateCTM(context, 0, rect.origin.y + CGRectGetMaxY(rect));
+ CGContextScaleCTM(context, 1, -1);
+ /* Fill with the background color, clipping to the mask. */
+ CGContextClipToMask(context, rect, mask);
+ TkMacOSXSetColorInContext(gc, gc->background, dc.context);
+ CGContextFillRect(dc.context, rect);
+ /* Fill with the foreground color, clipping to the intersection of img and mask. */
+ CGContextClipToMask(context, rect, img);
+ TkMacOSXSetColorInContext(gc, gc->foreground, context);
+ CGContextFillRect(context, rect);
+ CGContextRestoreGState(context);
+ CGImageRelease(mask);
+ CGImageRelease(img);
+ } else {
+ DrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground,
+ CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
+ CGRectMake(src_x, src_y, width, height),
+ CGRectMake(dest_x, dest_y, width, height));
+ CGImageRelease(img);
}
- DrawCGImage(dst, gc, dc.context, img, gc->foreground,
- imageBackground, CGRectMake(0, 0,
- srcDraw->size.width, srcDraw->size.height),
- CGRectMake(src_x, src_y, width, height),
- CGRectMake(dest_x, dest_y, width, height));
- CFRelease(img);
- } else {
+ } else { /* no image */
TkMacOSXDbgMsg("Invalid source drawable");
}
} else {
- TkMacOSXDbgMsg("Invalid destination drawable");
+ TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context.");
}
TkMacOSXRestoreDrawingContext(&dc);
- } else {
- XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x,
- dest_y);
+ } else { /* source drawable is a window, not a Pixmap */
+ XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x, dest_y);
}
}
@@ -356,16 +371,16 @@ XCopyPlane(
int
TkPutImage(
unsigned long *colors, /* Unused on Macintosh. */
- int ncolors, /* Unused on Macintosh. */
+ int ncolors, /* Unused on Macintosh. */
Display* display, /* Display. */
Drawable d, /* Drawable to place image on. */
- GC gc, /* GC to use. */
+ GC gc, /* GC to use. */
XImage* image, /* Image to place. */
int src_x, /* Source X & Y. */
int src_y,
int dest_x, /* Destination X & Y. */
int dest_y,
- unsigned int width, /* Same width & height for both */
+ unsigned int width, /* Same width & height for both */
unsigned int height) /* distination and source. */
{
TkMacOSXDrawingContext dc;
@@ -431,11 +446,12 @@ CreateCGImageWithXImage(
* BW image
*/
+ /* Reverses the sense of the bits */
static const CGFloat decodeWB[2] = {1, 0};
+ decode = decodeWB;
bitsPerComponent = 1;
bitsPerPixel = 1;
- decode = decodeWB;
if (image->bitmap_bit_order != MSBFirst) {
char *srcPtr = image->data + image->xoffset;
char *endPtr = srcPtr + len;
@@ -445,16 +461,14 @@ CreateCGImageWithXImage(
*destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
}
} else {
- data = memcpy(ckalloc(len), image->data + image->xoffset,
- len);
+ data = memcpy(ckalloc(len), image->data + image->xoffset, len);
}
if (data) {
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
}
if (provider) {
img = CGImageMaskCreate(image->width, image->height, bitsPerComponent,
- bitsPerPixel, image->bytes_per_line,
- provider, decode, 0);
+ bitsPerPixel, image->bytes_per_line, provider, decode, 0);
}
} else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
/*
@@ -476,6 +490,7 @@ CreateCGImageWithXImage(
img = CGImageCreate(image->width, image->height, bitsPerComponent,
bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,
provider, decode, 0, kCGRenderingIntentDefault);
+ CFRelease(provider);
}
if (colorspace) {
CFRelease(colorspace);
@@ -483,10 +498,6 @@ CreateCGImageWithXImage(
} else {
TkMacOSXDbgMsg("Unsupported image type");
}
- if (provider) {
- CFRelease(provider);
- }
-
return img;
}
@@ -660,12 +671,11 @@ GetCGContextForDrawable(
kCGBitmapByteOrderDefault;
#endif
char *data;
- CGRect bounds = CGRectMake(0, 0, macDraw->size.width,
- macDraw->size.height);
+ CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height);
if (macDraw->flags & TK_IS_BW_PIXMAP) {
bitsPerPixel = 8;
- bitmapInfo = kCGImageAlphaOnly;
+ bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;
} else {
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
bitsPerPixel = 32;
@@ -738,6 +748,7 @@ DrawCGImage(
if (CGImageIsMask(image)) {
/*CGContextSaveGState(context);*/
if (macDraw->flags & TK_IS_BW_PIXMAP) {
+ /* Set fill color to black, background comes from the context, or is transparent. */
if (imageBackground != TRANSPARENT_PIXEL << 24) {
CGContextClearRect(context, dstBounds);
}
@@ -750,6 +761,7 @@ DrawCGImage(
TkMacOSXSetColorInContext(gc, imageForeground, context);
}
}
+
#ifdef TK_MAC_DEBUG_IMAGE_DRAWING
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.0);
@@ -1479,7 +1491,7 @@ TkScrollWindow(
{
Drawable drawable = Tk_WindowId(tkwin);
MacDrawable *macDraw = (MacDrawable *) drawable;
- NSView *view = TkMacOSXDrawableView(macDraw);
+ TKContentView *view = (TKContentView *)TkMacOSXDrawableView(macDraw);
CGRect srcRect, dstRect;
HIShapeRef dmgRgn = NULL, extraRgn = NULL;
NSRect bounds, visRect, scrollSrc, scrollDst;
@@ -1556,7 +1568,6 @@ TkScrollWindow(
/* Belt and suspenders: make the AppKit request a redraw
when it gets control again. */
- [view setNeedsDisplay:YES];
}
} else {
dmgRgn = HIShapeCreateEmpty();
@@ -1817,7 +1828,7 @@ TkMacOSXGetClipRgn(
{
MacDrawable *macDraw = (MacDrawable *) drawable;
HIShapeRef clipRgn = NULL;
-
+
if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
TkMacOSXUpdateClipRgn(macDraw->winPtr);
#ifdef TK_MAC_DEBUG_DRAWING
@@ -1842,7 +1853,6 @@ TkMacOSXGetClipRgn(
} else if (macDraw->visRgn) {
clipRgn = HIShapeCreateCopy(macDraw->visRgn);
}
-
return clipRgn;
}
@@ -1895,7 +1905,7 @@ TkpClipDrawableToRect(
{
MacDrawable *macDraw = (MacDrawable *) d;
NSView *view = TkMacOSXDrawableView(macDraw);
-
+
if (macDraw->drawRgn) {
CFRelease(macDraw->drawRgn);
macDraw->drawRgn = NULL;
diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c
index 6685b80..3c59ac3 100644
--- a/macosx/tkMacOSXEvent.c
+++ b/macosx/tkMacOSXEvent.c
@@ -126,10 +126,6 @@ enum {
MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
- /* This can be called from outside the Appkit event loop,
- * so it needs its own AutoreleasePool.
- */
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSArray *macWindows = [NSApp orderedWindows];
for (NSWindow *w in macWindows) {
@@ -137,7 +133,6 @@ TkMacOSXFlushWindows(void)
[w flushWindow];
}
}
- [pool drain];
}
/*
diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c
index d30da09..f329071 100644
--- a/macosx/tkMacOSXFont.c
+++ b/macosx/tkMacOSXFont.c
@@ -15,6 +15,19 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXFont.h"
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
+#define defaultOrientation kCTFontDefaultOrientation
+#define verticalOrientation kCTFontVerticalOrientation
+#else
+#define defaultOrientation kCTFontOrientationDefault
+#define verticalOrientation kCTFontOrientationVertical
+#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101100
+#define fixedPitch kCTFontUserFixedPitchFontType
+#else
+#define fixedPitch kCTFontUIFontUserFixedPitch
+#endif
+
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_FONTS
@@ -197,6 +210,7 @@ FindNSFont(
nsFont = [fm convertFont:nsFont toSize:size];
nsFont = [fm convertFont:nsFont toHaveTrait:traits];
}
+ [nsFont retain];
#undef defaultFont
return nsFont;
}
@@ -270,7 +284,7 @@ InitFont(
fmPtr->fixed = [nsFont advancementForGlyph:glyphs[0]].width ==
[nsFont advancementForGlyph:glyphs[1]].width;
bounds = NSRectFromCGRect(CTFontGetBoundingRectsForGlyphs((CTFontRef)
- nsFont, kCTFontDefaultOrientation, ch, boundingRects, nCh));
+ nsFont, defaultOrientation, ch, boundingRects, nCh));
kern = [nsFont advancementForGlyph:glyphs[2]].width -
[fontPtr->nsFont advancementForGlyph:glyphs[2]].width;
}
@@ -358,6 +372,7 @@ TkpFontPkgInit(
NSFont *nsFont;
TkFontAttributes fa;
NSMutableCharacterSet *cs;
+ /* Since we called before TkpInit, we need our own autorelease pool. */
NSAutoreleasePool *pool = [NSAutoreleasePool new];
/* force this for now */
@@ -382,8 +397,7 @@ TkpFontPkgInit(
systemFont++;
}
TkInitFontAttributes(&fa);
- nsFont = (NSFont*) CTFontCreateUIFontForLanguage(
- kCTFontUserFixedPitchFontType, 11, NULL);
+ nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);
if (nsFont) {
GetTkFontAttributesForNSFont(nsFont, &fa);
CFRelease(nsFont);
@@ -518,7 +532,7 @@ TkpGetFontFromAttributes(
nsFont = FindNSFont(faPtr->family, traits, weight, points, 1);
}
if (!nsFont) {
- Tcl_Panic("Could not deternmine NSFont from TkFontAttributes");
+ Tcl_Panic("Could not determine NSFont from TkFontAttributes");
}
if (tkFontPtr == NULL) {
fontPtr = (MacFont *) ckalloc(sizeof(MacFont));
@@ -663,7 +677,6 @@ TkpGetFontAttrsForChar(
{
MacFont *fontPtr = (MacFont *) tkfont;
NSFont *nsFont = fontPtr->nsFont;
-
*faPtr = fontPtr->font.fa;
if (nsFont && ![[nsFont coveredCharacterSet] characterIsMember:c]) {
UTF16Char ch = c;
diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c
index 9671ab9..9c0f9d1 100644
--- a/macosx/tkMacOSXHLEvents.c
+++ b/macosx/tkMacOSXHLEvents.c
@@ -7,12 +7,15 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2015 Marc Culler
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tkMacOSXPrivate.h"
+#include <sys/param.h>
+#define URL_MAX_LENGTH (17 + MAXPATHLEN)
/*
* This is a Tcl_Event structure that the Quit AppleEvent handler uses to
@@ -30,154 +33,32 @@ typedef struct KillEvent {
* Static functions used only in this file.
*/
-static OSErr QuitHandler(const AppleEvent *event,
- AppleEvent *reply, SRefCon handlerRefcon);
-static OSErr OappHandler(const AppleEvent *event,
- AppleEvent *reply, SRefCon handlerRefcon);
-static OSErr RappHandler(const AppleEvent *event,
- AppleEvent *reply, SRefCon handlerRefcon);
-static OSErr OdocHandler(const AppleEvent *event,
- AppleEvent *reply, SRefCon handlerRefcon);
-static OSErr PrintHandler(const AppleEvent *event,
- AppleEvent *reply, SRefCon handlerRefcon);
-static OSErr ScriptHandler(const AppleEvent *event,
- AppleEvent *reply, SRefCon handlerRefcon);
-static OSErr PrefsHandler(const AppleEvent *event,
- AppleEvent *reply, SRefCon handlerRefcon);
-static int MissedAnyParameters(const AppleEvent *theEvent);
-static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
-static OSStatus FSRefToDString(const FSRef *fsref, Tcl_DString *ds);
+static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event,
+ NSAppleEventDescriptor* replyEvent,
+ Tcl_Interp *interp,
+ char* procedure);
+static int MissedAnyParameters(const AppleEvent *theEvent);
+static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
#pragma mark TKApplication(TKHLEvents)
@implementation TKApplication(TKHLEvents)
-
-- (void)terminate:(id)sender {
- QuitHandler(NULL, NULL, (SRefCon) _eventInterp);
-}
-
-- (void)preferences:(id)sender {
- PrefsHandler(NULL, NULL, (SRefCon) _eventInterp);
-}
-
-@end
-
-#pragma mark -
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacOSXInitAppleEvents --
- *
- * Initilize the Apple Events on the Macintosh. This registers the core
- * event handlers.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkMacOSXInitAppleEvents(
- Tcl_Interp *interp) /* Interp to handle basic events. */
+- (void) terminate: (id) sender
{
- AEEventHandlerUPP OappHandlerUPP, RappHandlerUPP, OdocHandlerUPP;
- AEEventHandlerUPP PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP;
- AEEventHandlerUPP PrefsHandlerUPP;
- static Boolean initialized = FALSE;
-
- if (!initialized) {
- initialized = TRUE;
-
- /*
- * Install event handlers for the core apple events.
- */
-
- QuitHandlerUPP = NewAEEventHandlerUPP(QuitHandler);
- ChkErr(AEInstallEventHandler, kCoreEventClass, kAEQuitApplication,
- QuitHandlerUPP, (SRefCon) interp, false);
-
- OappHandlerUPP = NewAEEventHandlerUPP(OappHandler);
- ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenApplication,
- OappHandlerUPP, (SRefCon) interp, false);
-
- RappHandlerUPP = NewAEEventHandlerUPP(RappHandler);
- ChkErr(AEInstallEventHandler, kCoreEventClass, kAEReopenApplication,
- RappHandlerUPP, (SRefCon) interp, false);
-
- OdocHandlerUPP = NewAEEventHandlerUPP(OdocHandler);
- ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenDocuments,
- OdocHandlerUPP, (SRefCon) interp, false);
-
- PrintHandlerUPP = NewAEEventHandlerUPP(PrintHandler);
- ChkErr(AEInstallEventHandler, kCoreEventClass, kAEPrintDocuments,
- PrintHandlerUPP, (SRefCon) interp, false);
-
- PrefsHandlerUPP = NewAEEventHandlerUPP(PrefsHandler);
- ChkErr(AEInstallEventHandler, kCoreEventClass, kAEShowPreferences,
- PrefsHandlerUPP, (SRefCon) interp, false);
-
- if (interp) {
- ScriptHandlerUPP = NewAEEventHandlerUPP(ScriptHandler);
- ChkErr(AEInstallEventHandler, kAEMiscStandards, kAEDoScript,
- ScriptHandlerUPP, (SRefCon) interp, false);
- }
- }
+ [self handleQuitApplicationEvent:Nil withReplyEvent:Nil];
}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacOSXDoHLEvent --
- *
- * Dispatch incomming highlevel events.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Depends on the incoming event.
- *
- *----------------------------------------------------------------------
- */
-int
-TkMacOSXDoHLEvent(
- void *theEvent)
+- (void) preferences: (id) sender
{
- return AEProcessAppleEvent((EventRecord *)theEvent);
+ [self handleShowPreferencesEvent:Nil withReplyEvent:Nil];
}
-
-/*
- *----------------------------------------------------------------------
- *
- * QuitHandler --
- *
- * This is the 'quit' core Apple event handler.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static OSErr
-QuitHandler(
- const AppleEvent *event,
- AppleEvent *reply,
- SRefCon handlerRefcon)
+- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
- Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
KillEvent *eventPtr;
- if (interp) {
+ if (_eventInterp) {
/*
* Call the exit command from the event loop, since you are not
* supposed to call ExitToShell in an Apple Event Handler. We put this
@@ -186,289 +67,292 @@ QuitHandler(
* quickly as possible.
*/
- eventPtr = (KillEvent *) ckalloc(sizeof(KillEvent));
+ eventPtr = (KillEvent*)ckalloc(sizeof(KillEvent));
eventPtr->header.proc = ReallyKillMe;
- eventPtr->interp = interp;
+ eventPtr->interp = _eventInterp;
Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);
}
- return noErr;
}
-
-/*
- *----------------------------------------------------------------------
- *
- * OappHandler --
- *
- * This is the 'oapp' core Apple event handler.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static OSErr
-OappHandler(
- const AppleEvent *event,
- AppleEvent *reply,
- SRefCon handlerRefcon)
+- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
- Tcl_CmdInfo dummy;
- Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
+ Tcl_Interp *interp = _eventInterp;
if (interp &&
- Tcl_GetCommandInfo(interp, "::tk::mac::OpenApplication", &dummy)){
- int code = Tcl_EvalEx(interp, "::tk::mac::OpenApplication", -1, TCL_EVAL_GLOBAL);
+ Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){
+ int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication",
+ -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
- Tcl_BackgroundError(interp);
+ Tcl_BackgroundError(_eventInterp);
}
}
- return noErr;
}
-
-/*
- *----------------------------------------------------------------------
- *
- * RappHandler --
- *
- * This is the 'rapp' core Apple event handler.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static OSErr
-RappHandler(
- const AppleEvent *event,
- AppleEvent *reply,
- SRefCon handlerRefcon)
+- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
- Tcl_CmdInfo dummy;
- Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
ProcessSerialNumber thePSN = {0, kCurrentProcess};
- OSStatus err = ChkErr(SetFrontProcess, &thePSN);
-
- if (interp && Tcl_GetCommandInfo(interp,
- "::tk::mac::ReopenApplication", &dummy)) {
- int code = Tcl_EvalEx(interp, "::tk::mac::ReopenApplication", -1, TCL_EVAL_GLOBAL);
+ SetFrontProcess(&thePSN);
+#else
+ [[NSApplication sharedApplication] activateIgnoringOtherApps: YES];
+#endif
+ if (_eventInterp && Tcl_FindCommand(_eventInterp,
+ "::tk::mac::ReopenApplication", NULL, 0)) {
+ int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication",
+ -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK){
- Tcl_BackgroundError(interp);
+ Tcl_BackgroundError(_eventInterp);
}
}
- return err;
}
-
-/*
- *----------------------------------------------------------------------
- *
- * PrefsHandler --
- *
- * This is the 'pref' core Apple event handler. Called when the user
- * selects 'Preferences...' in MacOS X
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static OSErr
-PrefsHandler(
- const AppleEvent *event,
- AppleEvent *reply,
- SRefCon handlerRefcon)
+- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
- Tcl_CmdInfo dummy;
- Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
-
- if (interp &&
- Tcl_GetCommandInfo(interp, "::tk::mac::ShowPreferences", &dummy)){
- int code = Tcl_EvalEx(interp, "::tk::mac::ShowPreferences", -1, TCL_EVAL_GLOBAL);
+ if (_eventInterp &&
+ Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)){
+ int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowPreferences",
+ -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
- Tcl_BackgroundError(interp);
+ Tcl_BackgroundError(_eventInterp);
}
}
- return noErr;
}
-
-/*
- *----------------------------------------------------------------------
- *
- * OdocHandler --
- *
- * This is the 'odoc' core Apple event handler.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static OSErr
-OdocHandler(
- const AppleEvent *event,
- AppleEvent *reply,
- SRefCon handlerRefcon)
+- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
- Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
- AEDescList fileSpecList;
- FSRef file;
- DescType type;
- Size actual;
- long count, index;
- AEKeyword keyword;
- Tcl_DString command, pathName;
- Tcl_CmdInfo dummy;
- int code;
+ tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::OpenDocument");
+}
- /*
- * Don't bother if we don't have an interp or the open document procedure
- * doesn't exist.
- */
+- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::PrintDocument");
+}
- if (!interp ||
- !Tcl_GetCommandInfo(interp, "::tk::mac::OpenDocument", &dummy)) {
- return noErr;
- }
+- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent
+{
+ OSStatus err;
+ const AEDesc *theDesc = nil;
+ DescType type = 0, initialType = 0;
+ Size actual;
+ int tclErr = -1;
+ char URLBuffer[1 + URL_MAX_LENGTH];
+ char errString[128];
+ char typeString[5];
/*
- * If we get any errors while retrieving our parameters we just return with
- * no error.
+ * The DoScript event receives one parameter that should be text data or a
+ * fileURL.
*/
- if (ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList,
- &fileSpecList) != noErr) {
- return noErr;
+ theDesc = [event aeDesc];
+ if (theDesc == nil) {
+ return;
}
- if (MissedAnyParameters(event) != noErr) {
- return noErr;
+
+ err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,
+ NULL, 0, NULL);
+ if (err != noErr) {
+ sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err);
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
+ errString, strlen(errString));
+ return;
}
- if (ChkErr(AECountItems, &fileSpecList, &count) != noErr) {
- return noErr;
+
+ if (MissedAnyParameters((AppleEvent*)theDesc)) {
+ sprintf(errString, "AEDoScriptHandler: extra parameters");
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
+ errString, strlen(errString));
+ return;
}
- /*
- * Convert our parameters into a script to evaluate, skipping things that
- * we can't handle right.
- */
-
- Tcl_DStringInit(&command);
- Tcl_DStringAppend(&command, "::tk::mac::OpenDocument", -1);
- for (index = 1; index <= count; index++) {
- if (ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, &keyword,
- &type, (Ptr) &file, sizeof(FSRef), &actual) != noErr) {
- continue;
+ if (initialType == typeFileURL || initialType == typeAlias) {
+ /*
+ * The descriptor can be coerced to a file url. Source the file, or
+ * pass the path as a string argument to ::tk::mac::DoScriptFile if
+ * that procedure exists.
+ */
+ err = AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
+ (Ptr) URLBuffer, URL_MAX_LENGTH, &actual);
+ if (err == noErr && actual > 0){
+ URLBuffer[actual] = '\0';
+ NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
+ NSURL *fileURL = [NSURL URLWithString:urlString];
+ Tcl_DString command;
+ Tcl_DStringInit(&command);
+ if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)){
+ Tcl_DStringAppend(&command, "::tk::mac::DoScriptFile", -1);
+ } else {
+ Tcl_DStringAppend(&command, "source", -1);
+ }
+ Tcl_DStringAppendElement(&command, [[fileURL path] UTF8String]);
+ tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
+ Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
}
-
- if (ChkErr(FSRefToDString, &file, &pathName) == noErr) {
- Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
- Tcl_DStringFree(&pathName);
+ } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
+ NULL, 0, &actual)) {
+ if (actual > 0) {
+ /*
+ * The descriptor can be coerced to UTF8 text. Evaluate as Tcl, or
+ * or pass the text as a string argument to ::tk::mac::DoScriptText
+ * if that procedure exists.
+ */
+ char *data = ckalloc(actual + 1);
+ if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
+ data, actual, NULL)) {
+ if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", NULL, 0)){
+ Tcl_DString command;
+ Tcl_DStringInit(&command);
+ Tcl_DStringAppend(&command, "::tk::mac::DoScriptText", -1);
+ Tcl_DStringAppendElement(&command, data);
+ tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
+ Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
+ } else {
+ tclErr = Tcl_EvalEx(_eventInterp, data, actual, TCL_EVAL_GLOBAL);
+ }
+ }
+ ckfree(data);
+ }
+ } else {
+ /*
+ * The descriptor can not be coerced to a fileURL or UTF8 text.
+ */
+ for (int i = 0; i < 4; i++) {
+ typeString[i] = ((char*)&initialType)[3-i];
}
+ typeString[4] = '\0';
+ sprintf(errString, "AEDoScriptHandler: invalid script type '%s', "
+ "must be coercable to 'furl' or 'utf8'", typeString);
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, errString,
+ strlen(errString));
}
-
/*
- * Now handle the event by evaluating a script.
+ * If we ran some Tcl code, put the result in the reply.
*/
-
- code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
- Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
- if (code != TCL_OK) {
- Tcl_BackgroundError(interp);
+ if (tclErr >= 0) {
+ int reslen;
+ const char *result =
+ Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen);
+ if (tclErr == TCL_OK) {
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyDirectObject, typeChar,
+ result, reslen);
+ } else {
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
+ result, reslen);
+ AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorNumber, typeSInt32,
+ (Ptr) &tclErr,sizeof(int));
+ }
}
- Tcl_DStringFree(&command);
- return noErr;
+ return;
}
-
+@end
+
+#pragma mark -
+
/*
*----------------------------------------------------------------------
*
- * PrintHandler --
+ * TkMacOSXProcessFiles --
*
- * This is the 'pdoc' core Apple event handler.
+ * Extract a list of fileURLs from an AppleEvent and call the specified
+ * procedure with the file paths as arguments.
*
* Results:
* None.
*
* Side effects:
- * None.
+ * The event is handled by running the procedure.
*
*----------------------------------------------------------------------
*/
-static OSErr
-PrintHandler(
- const AppleEvent * event,
- AppleEvent * reply,
- SRefCon handlerRefcon)
+static void
+tkMacOSXProcessFiles(
+ NSAppleEventDescriptor* event,
+ NSAppleEventDescriptor* replyEvent,
+ Tcl_Interp *interp,
+ char* procedure)
{
- Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
- AEDescList fileSpecList;
- FSRef file;
+ Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8");
+ const AEDesc *fileSpecDesc = nil;
+ AEDesc contents;
+ char URLString[1 + URL_MAX_LENGTH];
+ NSURL *fileURL;
DescType type;
Size actual;
long count, index;
AEKeyword keyword;
Tcl_DString command, pathName;
- Tcl_CmdInfo dummy;
int code;
/*
- * Don't bother if we don't have an interp or the print document procedure
- * doesn't exist.
+ * Do nothing if we don't have an interpreter or the procedure doesn't exist.
*/
- if (!interp ||
- !Tcl_GetCommandInfo(interp, "::tk::mac::PrintDocument", &dummy)) {
- return noErr;
+ if (!interp || !Tcl_FindCommand(interp, procedure, NULL, 0)) {
+ return;
}
-
+
+ fileSpecDesc = [event aeDesc];
+ if (fileSpecDesc == nil ) {
+ return;
+ }
+
/*
- * If we get any errors while retrieving our parameters we just return with
- * no error.
+ * The AppleEvent's descriptor should either contain a value of
+ * typeObjectSpecifier or typeAEList. In the first case, the descriptor
+ * can be treated as a list of size 1 containing a value which can be
+ * coerced into a fileURL. In the second case we want to work with the list
+ * itself. Values in the list will be coerced into fileURL's if possible;
+ * otherwise they will be ignored.
*/
-
- if (ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList,
- &fileSpecList) != noErr) {
- return noErr;
+
+ /* Get a copy of the AppleEvent's descriptor. */
+ AEGetParamDesc(fileSpecDesc, keyDirectObject, typeWildCard, &contents);
+ if (contents.descriptorType == typeAEList) {
+ fileSpecDesc = &contents;
}
- if (ChkErr(MissedAnyParameters, event) != noErr) {
- return noErr;
+
+ if (AECountItems(fileSpecDesc, &count) != noErr) {
+ AEDisposeDesc(&contents);
+ return;
}
- if (ChkErr(AECountItems, &fileSpecList, &count) != noErr) {
- return noErr;
- }
-
+
+ /*
+ * Construct a Tcl command which calls the procedure, passing the
+ * paths contained in the AppleEvent as arguments.
+ */
+
Tcl_DStringInit(&command);
- Tcl_DStringAppend(&command, "::tk::mac::PrintDocument", -1);
+ Tcl_DStringAppend(&command, procedure, -1);
+
for (index = 1; index <= count; index++) {
- if (ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, &keyword,
- &type, (Ptr) &file, sizeof(FSRef), &actual) != noErr) {
+ if (noErr != AEGetNthPtr(fileSpecDesc, index, typeFileURL, &keyword,
+ &type, (Ptr) URLString, URL_MAX_LENGTH, &actual)) {
continue;
}
-
- if (ChkErr(FSRefToDString, &file, &pathName) == noErr) {
- Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
- Tcl_DStringFree(&pathName);
+ if (type != typeFileURL) {
+ continue;
+ }
+ URLString[actual] = '\0';
+ fileURL = [NSURL URLWithString:[NSString stringWithUTF8String:(char*)URLString]];
+ if (fileURL == nil) {
+ continue;
}
+ Tcl_ExternalToUtfDString(utf8, [[fileURL path] UTF8String], -1, &pathName);
+ Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
+ Tcl_DStringFree(&pathName);
}
+ AEDisposeDesc(&contents);
/*
- * Now handle the event by evaluating a script.
+ * Handle the event by evaluating the Tcl expression we constructed.
*/
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
@@ -477,18 +361,19 @@ PrintHandler(
Tcl_BackgroundError(interp);
}
Tcl_DStringFree(&command);
- return noErr;
+ return;
}
/*
*----------------------------------------------------------------------
*
- * ScriptHandler --
+ * TkMacOSXInitAppleEvents --
*
- * This handler process the script event.
+ * Register AppleEvent handlers with the NSAppleEventManager for
+ * this NSApplication.
*
* Results:
- * Schedules the given event to be processed.
+ * None.
*
* Side effects:
* None.
@@ -496,108 +381,91 @@ PrintHandler(
*----------------------------------------------------------------------
*/
-static OSErr
-ScriptHandler(
- const AppleEvent *event,
- AppleEvent *reply,
- SRefCon handlerRefcon)
+void
+TkMacOSXInitAppleEvents(
+ Tcl_Interp *interp) /* not used */
{
- OSStatus theErr;
- AEDescList theDesc;
- Size size;
- int tclErr = -1;
- Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
- char errString[128];
+ NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
+ static Boolean initialized = FALSE;
- /*
- * The do script event receives one parameter that should be data or a
- * file.
- */
+ if (!initialized) {
+ initialized = TRUE;
- theErr = AEGetParamDesc(event, keyDirectObject, typeWildCard,
- &theDesc);
- if (theErr != noErr) {
- sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d",
- (int)theErr);
- theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString,
- strlen(errString));
- } else if (MissedAnyParameters(event)) {
- /*
- * Return error if parameter is missing.
- */
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleQuitApplicationEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
- sprintf(errString, "AEDoScriptHandler: extra parameters");
- AEPutParamPtr(reply, keyErrorString, typeChar, errString,
- strlen(errString));
- theErr = -1771;
- } else if (theDesc.descriptorType == (DescType) typeAlias &&
- AEGetParamPtr(event, keyDirectObject, typeFSRef, NULL, NULL,
- 0, &size) == noErr && size == sizeof(FSRef)) {
- /*
- * We've had a file sent to us. Source it.
- */
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleOpenApplicationEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEOpenApplication];
- FSRef file;
- theErr = AEGetParamPtr(event, keyDirectObject, typeFSRef, NULL, &file,
- size, NULL);
- if (theErr == noErr) {
- Tcl_DString scriptName;
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleReopenApplicationEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEReopenApplication];
- theErr = FSRefToDString(&file, &scriptName);
- if (theErr == noErr) {
- tclErr = Tcl_EvalFile(interp, Tcl_DStringValue(&scriptName));
- Tcl_DStringFree(&scriptName);
- } else {
- sprintf(errString, "AEDoScriptHandler: file not found");
- AEPutParamPtr(reply, keyErrorString, typeChar, errString,
- strlen(errString));
- }
- }
- } else if (AEGetParamPtr(event, keyDirectObject, typeUTF8Text, NULL, NULL,
- 0, &size) == noErr && size) {
- /*
- * We've had some data sent to us. Evaluate it.
- */
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleShowPreferencesEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEShowPreferences];
- char *data = ckalloc(size + 1);
- theErr = AEGetParamPtr(event, keyDirectObject, typeUTF8Text, NULL, data,
- size, NULL);
- if (theErr == noErr) {
- tclErr = Tcl_EvalEx(interp, data, size, TCL_EVAL_GLOBAL);
- }
- } else {
- /*
- * Umm, don't recognize what we've got...
- */
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
- sprintf(errString, "AEDoScriptHandler: invalid script type '%-4.4s', "
- "must be 'alis' or coercable to 'utf8'",
- (char*) &theDesc.descriptorType);
- AEPutParamPtr(reply, keyErrorString, typeChar, errString,
- strlen(errString));
- theErr = -1770;
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEPrintDocuments];
+
+ [aeManager setEventHandler:NSApp
+ andSelector:@selector(handleDoScriptEvent:withReplyEvent:)
+ forEventClass:kAEMiscStandards andEventID:kAEDoScript];
}
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXDoHLEvent --
+ *
+ * Dispatch an AppleEvent.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depend on the AppleEvent.
+ *
+ *----------------------------------------------------------------------
+ */
- /*
- * If we actually go to run Tcl code - put the result in the reply.
+int
+TkMacOSXDoHLEvent(
+ void *theEvent)
+{
+ /* According to the NSAppleEventManager reference:
+ * "The theReply parameter always specifies a reply Apple event, never
+ * nil. However, the handler should not fill out the reply if the
+ * descriptor type for the reply event is typeNull, indicating the sender
+ * does not want a reply."
+ * The specified way to build such a non-nil descriptor is used here. But
+ * on OSX 10.11, the compiler nonetheless generates a warning. I am
+ * supressing the warning here -- maybe the warnings will stop in a future
+ * compiler release.
*/
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+#endif
- if (tclErr >= 0) {
- int reslen;
- const char *result =
- Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &reslen);
+ NSAppleEventDescriptor* theReply = [NSAppleEventDescriptor nullDescriptor];
+ NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
- if (tclErr == TCL_OK) {
- AEPutParamPtr(reply, keyDirectObject, typeChar, result, reslen);
- } else {
- AEPutParamPtr(reply, keyErrorString, typeChar, result, reslen);
- AEPutParamPtr(reply, keyErrorNumber, typeSInt32, (Ptr) &tclErr,
- sizeof(int));
- }
- }
+ return [aeManager dispatchRawAppleEvent:(const AppleEvent*)theEvent
+ withRawReply: (AppleEvent *)theReply
+ handlerRefCon: (SRefCon)0];
- AEDisposeDesc(&theDesc);
- return theErr;
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
}
/*
@@ -616,7 +484,6 @@ ScriptHandler(
*
*----------------------------------------------------------------------
*/
-
static int
ReallyKillMe(
Tcl_Event *eventPtr,
@@ -666,38 +533,7 @@ MissedAnyParameters(
return (err != errAEDescNotFound);
}
-
-/*
- *----------------------------------------------------------------------
- *
- * FSRefToDString --
- *
- * Get a POSIX path from an FSRef.
- *
- * Results:
- * In the parameter ds.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static OSStatus
-FSRefToDString(
- const FSRef *fsref,
- Tcl_DString *ds)
-{
- UInt8 fileName[PATH_MAX+1];
- OSStatus err;
- err = ChkErr(FSRefMakePath, fsref, fileName, sizeof(fileName));
- if (err == noErr) {
- Tcl_ExternalToUtfDString(NULL, (char*) fileName, -1, ds);
- }
- return err;
-}
-
/*
* Local Variables:
* mode: objc
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index 6ba726d..8e353b4 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -59,14 +59,24 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
@end
@implementation TKApplication
+@synthesize poolProtected = _poolProtected;
@end
@implementation TKApplication(TKInit)
+- (void) _resetAutoreleasePool
+{
+ if(![self poolProtected]) {
+ [_mainPool drain];
+ _mainPool = [NSAutoreleasePool new];
+ }
+}
+
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
- (void)_postedNotification:(NSNotification *)notification {
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}
#endif
+
- (void)_setupApplicationNotifications {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#define observe(n, s) [nc addObserver:self selector:@selector(s) name:(n) object:nil]
@@ -81,14 +91,18 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), NULL, &keyboardChanged, kTISNotifySelectedKeyboardInputSourceChanged, NULL, CFNotificationSuspensionBehaviorCoalesce);
#endif
}
-- (void)_setupEventLoop {
- /*Remove private API calls here.*/
+- (void)_setupEventLoop {
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
[self finishLaunching];
[self setWindowsNeedUpdate:YES];
+ [pool drain];
}
+
- (void)_setup:(Tcl_Interp *)interp {
_eventInterp = interp;
+ _mainPool = [NSAutoreleasePool new];
+ [NSApp setPoolProtected:NO];
_defaultMainMenu = nil;
[self _setupMenus];
[self setDelegate:self];
@@ -99,8 +113,10 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
[self _setupWindowNotifications];
[self _setupApplicationNotifications];
}
+
- (NSString *)tkFrameworkImagePath:(NSString*)image {
NSString *path = nil;
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
if (tkLibPath[0] != '\0') {
path = [[NSBundle bundleWithPath:[[NSString stringWithUTF8String:
tkLibPath] stringByAppendingString:@"/../.."]]
@@ -131,6 +147,8 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
}
}
#endif
+ [path retain];
+ [pool drain];
return path;
}
@end
@@ -157,6 +175,7 @@ static void
SetApplicationIcon(
ClientData clientData)
{
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSString *path = [NSApp tkFrameworkImagePath:@"Tk.icns"];
if (path) {
NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];
@@ -165,6 +184,7 @@ SetApplicationIcon(
[image release];
}
}
+ [pool drain];
}
/*
@@ -242,19 +262,19 @@ TkpInit(
}
#endif
- static NSAutoreleasePool *pool = nil;
- if (!pool) {
- pool = [NSAutoreleasePool new];
+ {
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ [[NSUserDefaults standardUserDefaults] registerDefaults:
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES],
+ @"_NSCanWrapButtonTitles",
+ [NSNumber numberWithInt:-1],
+ @"NSStringDrawingTypesetterBehavior",
+ nil]];
+ [TKApplication sharedApplication];
+ [pool drain];
+ [NSApp _setup:interp];
}
- [[NSUserDefaults standardUserDefaults] registerDefaults:
- [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:YES],
- @"_NSCanWrapButtonTitles",
- [NSNumber numberWithInt:-1],
- @"NSStringDrawingTypesetterBehavior",
- nil]];
- [TKApplication sharedApplication];
- [NSApp _setup:interp];
/* Check whether we are a bundled executable: */
bundleRef = CFBundleGetMainBundle();
@@ -311,13 +331,15 @@ TkpInit(
Tcl_DoWhenIdle(SetApplicationIcon, NULL);
}
- [NSApp _setupEventLoop];
- TkMacOSXInitAppleEvents(interp);
- TkMacOSXUseAntialiasedText(interp, -1);
- TkMacOSXInitCGDrawing(interp, TRUE, 0);
- [pool drain];
- pool = [NSAutoreleasePool new];
-
+ {
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ [NSApp _setupEventLoop];
+ TkMacOSXInitAppleEvents(interp);
+ TkMacOSXUseAntialiasedText(interp, -1);
+ TkMacOSXInitCGDrawing(interp, TRUE, 0);
+ [pool drain];
+ }
+
/*
* FIXME: Close stdin & stdout for remote debugging otherwise we will
* fight with gdb for stdin & stdout
@@ -473,9 +495,8 @@ TkpDisplayWarning(
MODULE_SCOPE void
TkMacOSXDefaultStartupScript(void)
{
- CFBundleRef bundleRef;
-
- bundleRef = CFBundleGetMainBundle();
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ CFBundleRef bundleRef = CFBundleGetMainBundle();
if (bundleRef != NULL) {
CFURLRef appMainURL = CFBundleCopyResourceURL(bundleRef,
@@ -499,6 +520,7 @@ TkMacOSXDefaultStartupScript(void)
CFRelease(appMainURL);
}
}
+ [pool drain];
}
/*
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index 8e278f7..da74e60 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -227,7 +227,7 @@ static unsigned isFunctionKey(unsigned int code);
-@implementation TKContentView(TKKeyEvent)
+@implementation TKContentView
/* <NSTextInput> implementation (called through interpretKeyEvents:]). */
/* <NSTextInput>: called when done composing;
@@ -293,22 +293,6 @@ static unsigned isFunctionKey(unsigned int code);
}
-/* delete display of composing characters [not in <NSTextInput>] */
-- (void)deleteWorkingText
-{
- if (privateWorkingText == nil)
- return;
- if (NS_KEYLOG)
- NSLog(@"deleteWorkingText len = %lu\n",
- (unsigned long)[privateWorkingText length]);
- [privateWorkingText release];
- privateWorkingText = nil;
- processingCompose = NO;
-
- //PENDING: delete working text
-}
-
-
- (BOOL)hasMarkedText
{
return privateWorkingText != nil;
@@ -344,7 +328,7 @@ static unsigned isFunctionKey(unsigned int code);
pt.y = caret_y;
pt = [self convertPoint: pt toView: nil];
- pt = [[self window] convertBaseToScreen: pt];
+ pt = [[self window] convertPointToScreen: pt];
pt.y -= caret_height;
rect.origin = pt;
@@ -418,6 +402,24 @@ static unsigned isFunctionKey(unsigned int code);
@end
+@implementation TKContentView(TKKeyEvent)
+/* delete display of composing characters [not in <NSTextInput>] */
+- (void)deleteWorkingText
+{
+ if (privateWorkingText == nil)
+ return;
+ if (NS_KEYLOG)
+ NSLog(@"deleteWorkingText len = %lu\n",
+ (unsigned long)[privateWorkingText length]);
+ [privateWorkingText release];
+ privateWorkingText = nil;
+ processingCompose = NO;
+
+ //PENDING: delete working text
+}
+@end
+
+
/*
* Set up basic fields in xevent for keyboard input.
diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c
index c3121cb..8f20447 100644
--- a/macosx/tkMacOSXMenu.c
+++ b/macosx/tkMacOSXMenu.c
@@ -258,10 +258,10 @@ static int ModifierCharWidth(Tk_Font tkfont);
if (menuPtr && mePtr) {
Tcl_Interp *interp = menuPtr->interp;
- /*Add time for errors to fire if necessary. This is sub-optimal but avoids issues with Tcl/Cocoa event loop integration.*/
+ /*Add time for errors to fire if necessary. This is sub-optimal
+ *but avoids issues with Tcl/Cocoa event loop integration.
+ */
Tcl_Sleep(100);
-
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
Tcl_Preserve(interp);
Tcl_Preserve(menuPtr);
@@ -274,7 +274,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
}
Tcl_Release(menuPtr);
Tcl_Release(interp);
- [pool drain];
}
}
}
@@ -377,13 +376,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
@implementation TKApplication(TKMenu)
-- (void) safeSetMainMenu: (NSMenu *) menu
-{
- NSAutoreleasePool* pool = [NSAutoreleasePool new];
- [self setMainMenu: menu];
- [pool drain];
-}
-
- (void) menuBeginTracking: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
@@ -420,7 +412,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
if (!mePtr || !(mePtr->entryFlags & ENTRY_APPLE_MENU)) {
applicationMenuItem = [NSMenuItem itemWithSubmenu:
- [[_defaultApplicationMenu copy] autorelease]];
+ [_defaultApplicationMenu copy]];
[menu insertItem:applicationMenuItem atIndex:0];
}
[menu setSpecial:tkMainMenu];
@@ -428,7 +420,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
applicationMenu = (TKMenu *)[applicationMenuItem submenu];
if (![applicationMenu isSpecial:tkApplicationMenu]) {
for (NSMenuItem *item in _defaultApplicationMenuItems) {
- [applicationMenu addItem:[[item copy] autorelease]];
+ [applicationMenu addItem:[item copy]];
}
[applicationMenu setSpecial:tkApplicationMenu];
}
@@ -438,15 +430,13 @@ static int ModifierCharWidth(Tk_Font tkfont);
for (NSMenuItem *item in itemArray) {
TkMenuEntry *mePtr = (TkMenuEntry *)[item tag];
TKMenu *submenu = (TKMenu *)[item submenu];
-
if (mePtr && submenu) {
if ((mePtr->entryFlags & ENTRY_WINDOWS_MENU) &&
![submenu isSpecial:tkWindowsMenu]) {
NSInteger index = 0;
for (NSMenuItem *i in _defaultWindowsMenuItems) {
- [submenu insertItem:[[i copy] autorelease] atIndex:
- index++];
+ [submenu insertItem:[i copy] atIndex:index++];
}
[self setWindowsMenu:submenu];
[submenu setSpecial:tkWindowsMenu];
@@ -455,8 +445,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
NSInteger index = 0;
for (NSMenuItem *i in _defaultHelpMenuItems) {
- [submenu insertItem:[[i copy] autorelease] atIndex:
- index++];
+ [submenu insertItem:[i copy] atIndex:index++];
}
[submenu setSpecial:tkHelpMenu];
}
@@ -475,7 +464,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
[servicesMenuItem setSubmenu:_servicesMenu];
}
[self setAppleMenu:applicationMenu];
- [self safeSetMainMenu:menu];
+ [self setMainMenu:menu];
}
@end
@@ -792,7 +781,7 @@ TkpPostMenu(
NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
frame.origin = [view convertPoint:
- [win convertScreenToBase:frame.origin] fromView:nil];
+ [win convertPointFromScreen:frame.origin] fromView:nil];
NSMenu *menu = (NSMenu *) menuPtr->platformData;
NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 10a615e..cd3eac1 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -26,7 +26,7 @@ typedef struct {
static int GenerateButtonEvent(MouseEventData *medPtr);
static unsigned int ButtonModifiers2State(UInt32 buttonState,
- UInt32 keyModifiers);
+ UInt32 keyModifiers);
#pragma mark TKApplication(TKMouseEvent)
@@ -34,26 +34,41 @@ enum {
NSWindowWillMoveEventType = 20
};
+/*
+ * In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil
+ * window attribute pointing to the active window. As of 10.8 this behavior
+ * had changed. The new behavior was that if the mouse were ever moved outside
+ * of a window, all subsequent NSMouseMoved NSEvents would have a Nil window
+ * attribute. To work around this the TKApplication remembers the last non-Nil
+ * window that it received in a mouse event. If it receives an NSEvent with a
+ * Nil window attribute then the saved window is used.
+ */
+
@implementation TKApplication(TKMouseEvent)
- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent {
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
- id win;
- NSEventType type = [theEvent type];
+ NSWindow* eventWindow = [theEvent window];
+ NSEventType eventType = [theEvent type];
#if 0
NSTrackingArea *trackingArea = nil;
NSInteger eventNumber, clickCount, buttonNumber;
#endif
- switch (type) {
+ switch (eventType) {
case NSMouseEntered:
+ /* Remember which window has the mouse. */
+ if (_windowWithMouse) {
+ [_windowWithMouse release];
+ }
+ _windowWithMouse = [theEvent window];
+ if (_windowWithMouse) {
+ [_windowWithMouse retain];
+ }
+ break;
case NSMouseExited:
case NSCursorUpdate:
-#if 0
- trackingArea = [theEvent trackingArea];
- /* fall through */
-#endif
case NSLeftMouseDown:
case NSLeftMouseUp:
case NSRightMouseDown:
@@ -75,24 +90,39 @@ enum {
case NSTabletProximity:
case NSScrollWheel:
break;
-
default: /* Unrecognized mouse event. */
return theEvent;
}
+ /* Remember the window in case we need it next time. */
+ if (eventWindow && eventWindow != _windowWithMouse) {
+ if (_windowWithMouse) {
+ [_windowWithMouse release];
+ }
+ _windowWithMouse = eventWindow;
+ [_windowWithMouse retain];
+ }
+
/* Create an Xevent to add to the Tk queue. */
- win = [theEvent window];
NSPoint global, local = [theEvent locationInWindow];
- if (win) {
- global = [win convertBaseToScreen:local];
- local.y = [win frame].size.height - local.y;
+ if (eventWindow) { /* local will be in window coordinates. */
+ global = [eventWindow convertPointToScreen: local];
+ local.y = [eventWindow frame].size.height - local.y;
global.y = tkMacOSXZeroScreenHeight - global.y;
- } else {
- local.y = tkMacOSXZeroScreenHeight - local.y;
- global = local;
+ } else { /* local will be in screen coordinates. */
+ if (_windowWithMouse ) {
+ eventWindow = _windowWithMouse;
+ global = local;
+ local = [eventWindow convertPointFromScreen: local];
+ local.y = [eventWindow frame].size.height - local.y;
+ global.y = tkMacOSXZeroScreenHeight - global.y;
+ } else { /* We have no window. Use the screen???*/
+ local.y = tkMacOSXZeroScreenHeight - local.y;
+ global = local;
+ }
}
- Window window = TkMacOSXGetXWindow(win);
+ Window window = TkMacOSXGetXWindow(eventWindow);
Tk_Window tkwin = window ? Tk_IdToWindow(TkGetDisplayList()->display,
window) : NULL;
if (!tkwin) {
@@ -120,7 +150,7 @@ enum {
state |= (buttons & ((1<<5) - 1)) << 8;
} else {
if (button < 5) {
- switch (type) {
+ switch (eventType) {
case NSLeftMouseDown:
case NSRightMouseDown:
case NSLeftMouseDragged:
@@ -157,12 +187,12 @@ enum {
state |= Mod4Mask;
}
- if (type != NSScrollWheel) {
+ if (eventType != NSScrollWheel) {
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state);
#endif
Tk_UpdatePointer(tkwin, global.x, global.y, state);
- } else {
+ } else { /* handle scroll wheel event */
CGFloat delta;
int coarseDelta;
XEvent xEvent;
@@ -178,7 +208,8 @@ enum {
delta = [theEvent deltaY];
if (delta != 0.0) {
- coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta);
+ coarseDelta = (delta > -1.0 && delta < 1.0) ?
+ (signbit(delta) ? -1 : 1) : lround(delta);
xEvent.xbutton.state = state;
xEvent.xkey.keycode = coarseDelta;
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
@@ -186,7 +217,8 @@ enum {
}
delta = [theEvent deltaX];
if (delta != 0.0) {
- coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta);
+ coarseDelta = (delta > -1.0 && delta < 1.0) ?
+ (signbit(delta) ? -1 : 1) : lround(delta);
xEvent.xbutton.state = state | ShiftMask;
xEvent.xkey.keycode = coarseDelta;
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
@@ -357,7 +389,7 @@ XQueryPointer(
if (win) {
NSPoint local;
- local = [win convertScreenToBase:global];
+ local = [win convertPointFromScreen:global];
local.y = [win frame].size.height - local.y;
if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
local.x -= macWin->winPtr->wmInfoPtr->xInParent;
@@ -455,7 +487,7 @@ TkGenerateButtonEvent(
if (win) {
NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
- local = [win convertScreenToBase:local];
+ local = [win convertPointFromScreen:local];
local.y = [win frame].size.height - local.y;
if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
local.x -= macWin->winPtr->wmInfoPtr->xInParent;
diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c
index 4cfb5a9..fa359f0 100644
--- a/macosx/tkMacOSXNotify.c
+++ b/macosx/tkMacOSXNotify.c
@@ -49,7 +49,7 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
@end
@implementation TKApplication(TKNotify)
-/* Call super then redisplay all of our windows. */
+/* Display all windows each time an event is removed from the queue.*/
- (NSEvent *)nextEventMatchingMask:(NSUInteger)mask
untilDate:(NSDate *)expiration inMode:(NSString *)mode
dequeue:(BOOL)deqFlag {
@@ -57,9 +57,9 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
untilDate:expiration
inMode:mode
dequeue:deqFlag];
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ /* Retain this event for later use. Must be released.*/
+ [event retain];
[NSApp makeWindowsPerform:@selector(tkDisplayIfNeeded) inOrder:NO];
- [pool drain];
return event;
}
@@ -67,10 +67,8 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
* Call super then check the pasteboard.
*/
- (void)sendEvent:(NSEvent *)theEvent {
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
[super sendEvent:theEvent];
[NSApp tkCheckPasteboard];
- [pool drain];
}
@end
@@ -191,7 +189,7 @@ TkMacOSXNotifyExitHandler(
* TkMacOSXEventsSetupProc --
*
* This procedure implements the setup part of the MacOSX event
- * source. It is invoked by Tcl_DoOneEvent before calling
+ * source. It is invoked by Tcl_DoOneEvent before calling
* TkMacOSXEventsProc to process all queued NSEvents. In our
* case, all we need to do is to set the Tcl MaxBlockTime to
* 0 before starting the loop to process all queued NSEvents.
@@ -200,7 +198,7 @@ TkMacOSXNotifyExitHandler(
* None.
*
* Side effects:
- *
+ *
* If NSEvents are queued, then the maximum block time will be set
* to 0 to ensure that control returns immediately to Tcl.
*
@@ -212,16 +210,20 @@ TkMacOSXEventsSetupProc(
ClientData clientData,
int flags)
{
- if (flags & TCL_WINDOW_EVENTS &&
- ![[NSRunLoop currentRunLoop] currentMode]) {
+ NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
+ /* runloopMode will be nil if we are in the Tcl event loop. */
+ if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
static Tcl_Time zeroBlockTime = { 0, 0 };
- /* Call this with dequeue=NO -- just checking if the queue is empty. */
+ /* Call this with dequeue=NO -- just checking if the queue is empty. */
NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantPast]
- inMode:GetRunLoopMode(TkMacOSXGetModalSession())
- dequeue:NO];
- if (currentEvent && currentEvent.type > 0) {
- Tcl_SetMaxBlockTime(&zeroBlockTime);
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(TkMacOSXGetModalSession())
+ dequeue:NO];
+ if (currentEvent) {
+ if (currentEvent.type > 0) {
+ Tcl_SetMaxBlockTime(&zeroBlockTime);
+ }
+ [currentEvent release];
}
}
}
@@ -249,13 +251,14 @@ TkMacOSXEventsCheckProc(
int flags)
{
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
+ /* runloopMode will be nil if we are in the Tcl event loop. */
if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
-
NSEvent *currentEvent = nil;
NSEvent *testEvent = nil;
NSModalSession modalSession;
do {
+ [NSApp _resetAutoreleasePool];
modalSession = TkMacOSXGetModalSession();
testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
@@ -270,25 +273,25 @@ TkMacOSXEventsCheckProc(
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(modalSession)
dequeue:YES];
- if (!currentEvent) {
- break; /* No events are available. */
- }
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
- /* Generate Xevents. */
- int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
- Tcl_SetServiceMode(oldServiceMode);
- if (processedEvent) { /* Should always be non-NULL. */
+ if (currentEvent) {
+ /* Generate Xevents. */
+ int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
+ Tcl_SetServiceMode(oldServiceMode);
+ if (processedEvent) { /* Should always be non-NULL. */
#ifdef TK_MAC_DEBUG_EVENTS
- TKLog(@" event: %@", currentEvent);
+ TKLog(@" event: %@", currentEvent);
#endif
- if (modalSession) {
- [NSApp _modalSession:modalSession sendEvent:currentEvent];
- } else {
- [NSApp sendEvent:currentEvent];
+ if (modalSession) {
+ [NSApp _modalSession:modalSession sendEvent:currentEvent];
+ } else {
+ [NSApp sendEvent:currentEvent];
+ }
}
+ [currentEvent release];
+ } else {
+ break;
}
- [pool drain];
} while (1);
}
}
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index b93fa18..d892f4e 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -272,10 +272,17 @@ VISIBILITY_HIDDEN
TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
NSArray *_defaultHelpMenuItems;
+ NSWindow *_windowWithMouse;
+ NSAutoreleasePool *_mainPool;
+#ifdef __i386__
+ BOOL _poolProtected;
+#endif
}
+@property BOOL poolProtected;
@end
@interface TKApplication(TKInit)
- (NSString *)tkFrameworkImagePath:(NSString*)image;
+- (void)_resetAutoreleasePool;
@end
@interface TKApplication(TKEvent)
- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
@@ -293,15 +300,33 @@ VISIBILITY_HIDDEN
- (void)tkProvidePasteboard:(TkDisplay *)dispPtr;
- (void)tkCheckPasteboard;
@end
+@interface TKApplication(TKHLEvents)
+- (void) terminate: (id) sender;
+- (void) preferences: (id) sender;
+- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
+ withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
+@end
VISIBILITY_HIDDEN
@interface TKContentView : NSView <NSTextInput> {
@private
/*Remove private API calls.*/
- #if 0
+#if 0
id _savedSubviews;
BOOL _subviewsSetAside;
- #endif
+#endif
NSString *privateWorkingText;
}
@end
@@ -310,10 +335,27 @@ VISIBILITY_HIDDEN
- (void) deleteWorkingText;
@end
+@interface TKContentView(TKWindowEvent)
+- (void) drawRect: (NSRect) rect;
+- (void) generateExposeEvents: (HIShapeRef) shape;
+- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly;
+- (void) viewDidEndLiveResize;
+- (void) tkToolbarButton: (id) sender;
+- (BOOL) isOpaque;
+- (BOOL) wantsDefaultClipping;
+- (BOOL) acceptsFirstResponder;
+- (void) keyDown: (NSEvent *) theEvent;
+@end
+
VISIBILITY_HIDDEN
@interface TKWindow : NSWindow
@end
+@interface NSWindow(TKWm)
+- (NSPoint) convertPointToScreen:(NSPoint)point;
+- (NSPoint) convertPointFromScreen:(NSPoint)point;
+@end
+
#pragma mark NSMenu & NSMenuItem Utilities
@interface NSMenu(TKUtils)
@@ -342,5 +384,4 @@ VISIBILITY_HIDDEN
keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;
@end
-
#endif /* _TKMACPRIV */
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index 2f500fa..c1f16f3 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -131,11 +131,6 @@ XMapWindow(
{
MacDrawable *macWin = (MacDrawable *) window;
XEvent event;
- /*
- * This function can be called from outside the AppKit event
- * loop, so it needs its own AutoreleasePool.
- */
- NSAutoreleasePool* pool = [NSAutoreleasePool new];
/*
* Under certain situations it's possible for this function to be called
@@ -158,6 +153,7 @@ XMapWindow(
if ( [win canBecomeKeyWindow] ) {
[win makeKeyAndOrderFront:NSApp];
}
+ /* Why do we need this? (It is used by Carbon)*/
[win windowRef];
TkMacOSXApplyWindowAttributes(macWin->winPtr, win);
}
@@ -194,7 +190,6 @@ XMapWindow(
event.xvisibility.type = VisibilityNotify;
event.xvisibility.state = VisibilityUnobscured;
NotifyVisibility(macWin->winPtr, &event);
- [pool drain];
}
/*
@@ -318,7 +313,6 @@ XResizeWindow(
unsigned int height)
{
MacDrawable *macWin = (MacDrawable *) window;
-
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
@@ -365,7 +359,6 @@ XMoveResizeWindow(
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
-
if (w) {
NSRect r = NSMakeRect(x + macWin->winPtr->wmInfoPtr->xInParent,
tkMacOSXZeroScreenHeight - (y +
@@ -406,7 +399,6 @@ XMoveWindow(
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
-
if (w) {
[w setFrameTopLeftPoint:NSMakePoint(x, tkMacOSXZeroScreenHeight - y)];
}
@@ -805,9 +797,6 @@ TkMacOSXUpdateClipRgn(
/*
* TODO: Here we should handle out of process embedding.
*/
- } else if (winPtr->wmInfoPtr->attributes &
- kWindowResizableAttribute) {
- NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
}
macWin->aboveVisRgn = HIShapeCreateCopy(rgn);
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index ef3c86b..fce3801 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -165,6 +165,10 @@ extern BOOL opaqueTag;
if (winPtr) {
TkGenWMDestroyEvent((Tk_Window) winPtr);
+ if (_windowWithMouse == w) {
+ _windowWithMouse = nil;
+ [w release];
+ }
}
/*
@@ -747,15 +751,16 @@ TkWmProtocolEventProc(
int
Tk_MacOSXIsAppInFront(void)
{
- OSStatus err;
- ProcessSerialNumber frontPsn, ourPsn = {0, kCurrentProcess};
Boolean isFrontProcess = true;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ ProcessSerialNumber frontPsn, ourPsn = {0, kCurrentProcess};
- err = ChkErr(GetFrontProcess, &frontPsn);
- if (err == noErr) {
- ChkErr(SameProcess, &frontPsn, &ourPsn, &isFrontProcess);
+ if (noErr == GetFrontProcess(&frontPsn)){
+ SameProcess(&frontPsn, &ourPsn, &isFrontProcess);
}
-
+#else
+ isFrontProcess = [NSRunningApplication currentApplication].active;
+#endif
return (isFrontProcess == true);
}
@@ -782,21 +787,6 @@ Tk_MacOSXIsAppInFront(void)
*
*/
-@interface TKContentView(TKWindowEvent)
-- (void) drawRect: (NSRect) rect;
-- (void) generateExposeEvents: (HIShapeRef) shape;
-- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly;
-- (void) viewDidEndLiveResize;
-- (void) tkToolbarButton: (id) sender;
-- (BOOL) isOpaque;
-- (BOOL) wantsDefaultClipping;
-- (BOOL) acceptsFirstResponder;
-- (void) keyDown: (NSEvent *) theEvent;
-@end
-
-@implementation TKContentView
-@end
-
/*Restrict event processing to Expose events.*/
static Tk_RestrictAction
ExposeRestrictProc(
@@ -822,7 +812,7 @@ ConfigureRestrictProc(
{
const NSRect *rectsBeingDrawn;
NSInteger rectsBeingDrawnCount;
-
+
[self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount];
#ifdef TK_MAC_DEBUG_DRAWING
@@ -858,7 +848,8 @@ ConfigureRestrictProc(
-(void) setFrameSize: (NSSize)newsize
{
- if ( [self inLiveResize] ) {
+ [super setFrameSize: newsize];
+ if ([self inLiveResize]) {
NSWindow *w = [self window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
@@ -867,17 +858,26 @@ ConfigureRestrictProc(
ClientData oldArg;
Tk_RestrictProc *oldProc;
- /* Resize the NSView */
- [super setFrameSize: newsize];
-
- /* Disable drawing until the window has been completely configured.*/
+ /* This can be called from outside the Tk event loop.
+ * Since it calls Tcl_DoOneEvent, we need to make sure we
+ * don't clobber the AutoreleasePool set up by the caller.
+ */
+ [NSApp setPoolProtected:YES];
+
+ /*
+ * Try to prevent flickers and flashes.
+ */
+ [w disableFlushWindow];
+ NSDisableScreenUpdates();
+
+ /* Disable Tk drawing until the window has been completely configured.*/
TkMacOSXSetDrawingEnabled(winPtr, 0);
/* Generate and handle a ConfigureNotify event for the new size.*/
TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
- while ( Tk_DoOneEvent(TK_X_EVENTS|TK_DONT_WAIT) ) {}
+ while (Tk_DoOneEvent(TK_X_EVENTS|TK_DONT_WAIT)) {}
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
/* Now that Tk has configured all subwindows we can create the clip regions. */
@@ -889,9 +889,11 @@ ConfigureRestrictProc(
HIRect bounds = NSRectToCGRect([self bounds]);
HIShapeRef shape = HIShapeCreateWithRect(&bounds);
[self generateExposeEvents: shape];
- while ( Tk_DoOneEvent(TK_ALL_EVENTS|TK_DONT_WAIT) ) {}
- } else {
- [super setFrameSize: newsize];
+ while (Tk_DoOneEvent(TK_ALL_EVENTS|TK_DONT_WAIT)) {}
+ [w enableFlushWindow];
+ [w flushWindowIfNeeded];
+ NSEnableScreenUpdates();
+ [NSApp setPoolProtected:NO];
}
}
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index 37a1d25..be7bf47 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -24,8 +24,6 @@
#define DEBUG_ZOMBIES 0
-#define DEBUG_ZOMBIES 0
-
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_WINDOWS
@@ -200,6 +198,48 @@ static int tkMacOSXWmAttrNotifyVal = 0;
static Tcl_HashTable windowTable;
static int windowHashInit = false;
+
+
+#pragma mark NSWindow(TKWm)
+
+/*
+ * Conversion of coordinates between window and screen.
+ */
+
+@implementation NSWindow(TKWm)
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+- (NSPoint) convertPointToScreen: (NSPoint) point
+{
+ return [self convertBaseToScreen:point];
+}
+- (NSPoint) convertPointFromScreen: (NSPoint)point
+{
+ return [self convertScreenToBase:point];
+}
+@end
+#else
+- (NSPoint) convertPointToScreen: (NSPoint) point
+{
+ NSRect pointrect;
+ pointrect.origin = point;
+ pointrect.size.width = 0;
+ pointrect.size.height = 0;
+ return [self convertRectToScreen:pointrect].origin;
+}
+- (NSPoint) convertPointFromScreen: (NSPoint)point
+{
+ NSRect pointrect;
+ pointrect.origin = point;
+ pointrect.size.width = 0;
+ pointrect.size.height = 0;
+ return [self convertRectFromScreen:pointrect].origin;
+}
+@end
+#endif
+
+#pragma mark -
+
+
/*
* Forward declarations for procedures defined in this file:
*/
@@ -348,6 +388,7 @@ static void RemapWindows(TkWindow *winPtr,
@end
@implementation TKWindow(TKWm)
+
- (BOOL) canBecomeKeyWindow
{
TkWindow *winPtr = TkMacOSXGetTkWindow(self);
@@ -357,16 +398,58 @@ static void RemapWindows(TkWindow *winPtr,
kWindowNoActivatesAttribute)) ? NO : YES;
}
+#if DEBUG_ZOMBIES
- (id) retain
{
-#if DEBUG_ZOMBIES
+ id result = [super retain];
const char *title = [[self title] UTF8String];
- if (title != NULL) {
- printf("Retaining %s with count %lu\n", title, [self retainCount]);
+ if (title == nil) {
+ title = "unnamed window";
}
-#endif
- return [super retain];
+ if (DEBUG_ZOMBIES > 1){
+ printf("Retained <%s>. Count is: %lu\n", title, [self retainCount]);
+ }
+ return result;
+}
+
+- (id) autorelease
+{
+ static int xcount = 0;
+ id result = [super autorelease];
+ const char *title = [[self title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ if (DEBUG_ZOMBIES > 1){
+ printf("Autoreleased <%s>. Count is %lu\n", title, [self retainCount]);
+ }
+ return result;
+}
+
+- (oneway void) release {
+ const char *title = [[self title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ if (DEBUG_ZOMBIES > 1){
+ printf("Releasing <%s>. Count is %lu\n", title, [self retainCount]);
+ }
+ [super release];
+}
+
+- (void) dealloc {
+ const char *title = [[self title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ if (DEBUG_ZOMBIES > 0){
+ printf(">>>> Freeing <%s>. Count is %lu\n", title, [self retainCount]);
+ }
+ [super dealloc];
}
+
+
+#endif
@end
#pragma mark -
@@ -479,7 +562,6 @@ FrontWindowAtPoint(
int x, int y)
{
NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSArray *windows = [NSApp orderedWindows];
TkWindow *front = NULL;
@@ -489,7 +571,6 @@ FrontWindowAtPoint(
break;
}
}
- [pool drain];
return front;
}
@@ -795,7 +876,6 @@ TkWmDeadWindow(
NSWindow *window = wmPtr->window;
if (window && !Tk_IsEmbedded(winPtr) ) {
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSWindow *parent = [window parentWindow];
if (parent) {
[parent removeChildWindow:window];
@@ -805,19 +885,34 @@ TkWmDeadWindow(
if (winPtr->window) {
((MacDrawable *) winPtr->window)->view = nil;
}
+#if DEBUG_ZOMBIES > 0
+ {
+ const char *title = [[window title] UTF8String];
+ if (title == nil) {
+ title = "unnamed window";
+ }
+ printf(">>>> Closing <%s>. Count is: %lu\n", title, [window retainCount]);
+ }
+#endif
[window release];
wmPtr->window = NULL;
- /* Activate the highest window left on the screen. */
- NSArray *windows = [NSApp orderedWindows];
- if ( [windows count] > 0 ) {
- NSWindow *front = [windows objectAtIndex:0];
- if ( front && [front canBecomeKeyWindow] ) {
- [front makeKeyAndOrderFront:NSApp];
- }
- }
- [pool drain];
- }
- ckfree(wmPtr);
+
+ /* Activate the highest window left on the screen. */
+ NSArray *windows = [NSApp orderedWindows];
+ if ( [windows count] > 0 ) {
+ NSWindow *front = [windows objectAtIndex:0];
+ if ( front && [front canBecomeKeyWindow] ) {
+ [front makeKeyAndOrderFront:NSApp];
+ }
+ }
+ [NSApp _resetAutoreleasePool];
+
+#if DEBUG_ZOMBIES > 0
+ fprintf(stderr, "================= Pool dump ===================\n");
+ [NSAutoreleasePool showPools];
+#endif
+ }
+ ckfree((char *)wmPtr);
winPtr->wmInfoPtr = NULL;
}
@@ -5017,7 +5112,7 @@ TkUnsupported1ObjCmd(
};
Tk_Window tkwin = clientData;
TkWindow *winPtr;
- int index;
+ int index, i;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
@@ -5026,56 +5121,40 @@ TkUnsupported1ObjCmd(
/* Iterate through objc/objv to set correct background color and toggle opacity of window. */
- int i;
for (i= 0; i < objc; i++) {
-
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*black*") == 1) {
- colorName = [NSColor blackColor]; // use #000000 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*dark*") == 1) {
+ if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*black*")) {
+ colorName = [NSColor blackColor]; // use #000000 in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*dark*")) {
colorName = [NSColor darkGrayColor]; //use #545454 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*light*") == 1) {
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*light*")) {
colorName = [NSColor lightGrayColor]; //use #ababab in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*white*")) {
+ colorName = [NSColor whiteColor]; //use #ffffff in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "gray*")) {
+ colorName = [NSColor grayColor]; //use #7f7f7f in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*red*")) {
+ colorName = [NSColor redColor]; //use #ff0000 in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*green*")) {
+ colorName = [NSColor greenColor]; //use #00ff00 in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*blue*")) {
+ colorName = [NSColor blueColor]; //use #0000ff in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*cyan*")) {
+ colorName = [NSColor cyanColor]; //use #00ffff in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*yellow*")) {
+ colorName = [NSColor yellowColor]; //use #ffff00 in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*magenta*")) {
+ colorName = [NSColor magentaColor]; //use #ff00ff in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*orange*")) {
+ colorName = [NSColor orangeColor]; //use #ff8000 in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*purple*")) {
+ colorName = [NSColor purpleColor]; //use #800080 in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*brown*")){
+ colorName = [NSColor brownColor]; //use #996633 in Tk scripts to match
+ } else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*clear*")) {
+ colorName = [NSColor clearColor]; //use systemTransparent in Tk scripts to match
}
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*white*") == 1) {
- colorName = [NSColor whiteColor]; //use #ffffff in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "gray*") == 1) {
- colorName = [NSColor grayColor]; //use #7f7f7f in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*red*") == 1) {
- colorName = [NSColor redColor]; //use #ff0000 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*green*") == 1) {
- colorName = [NSColor greenColor]; //use #00ff00 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*blue*") == 1) {
- colorName = [NSColor blueColor]; //use #0000ff in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*cyan*") == 1) {
- colorName = [NSColor cyanColor]; //use #00ffff in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*yellow*") == 1) {
- colorName = [NSColor yellowColor]; //use #ffff00 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*magenta*") == 1) {
- colorName = [NSColor magentaColor]; //use #ff00ff in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*orange*") == 1) {
- colorName = [NSColor orangeColor]; //use #ff8000 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*purple*") == 1) {
- colorName = [NSColor purpleColor]; //use #800080 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*brown*") == 1){
- colorName = [NSColor brownColor]; //use #996633 in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*clear*") == 1) {
- colorName = [NSColor clearColor]; //use systemTransparent in Tk scripts to match
- }
- if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*opacity*") == 1) {
- opaqueTag=YES;
+ if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*opacity*")) {
+ opaqueTag = YES;
}
}
@@ -5194,22 +5273,22 @@ WmWinStyle(
{ "moveToActiveSpace", tkMoveToActiveSpaceAttribute },
{ "nonActivating", tkNonactivatingPanelAttribute },
{ "hud", tkHUDWindowAttribute },
- { "black", NULL },
- { "dark", NULL },
- { "light", NULL },
- { "gray", NULL },
- { "red", NULL },
- { "green", NULL },
- { "blue", NULL },
- { "cyan", NULL },
- { "yellow", NULL },
- { "magenta", NULL },
- { "orange", NULL },
- { "purple", NULL },
- { "brown", NULL },
- { "clear", NULL },
- { "opacity", NULL },
- { "fullscreen", NULL },
+ { "black", 0 },
+ { "dark", 0 },
+ { "light", 0 },
+ { "gray", 0 },
+ { "red", 0 },
+ { "green", 0 },
+ { "blue", 0 },
+ { "cyan", 0 },
+ { "yellow", 0 },
+ { "magenta", 0 },
+ { "orange", 0 },
+ { "purple", 0 },
+ { "brown", 0 },
+ { "clear", 0 },
+ { "opacity", 0 },
+ { "fullscreen", 0 },
{ NULL }
};
@@ -5404,7 +5483,6 @@ TkMacOSXMakeRealWindowExist(
* TODO: Here we should handle out of process embedding.
*/
}
-
WindowClass macClass = wmPtr->macClass;
wmPtr->attributes &= (tkAlwaysValidAttributes |
macClassAttrs[macClass].validAttrs);
@@ -5438,10 +5516,10 @@ TkMacOSXMakeRealWindowExist(
NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
if (!window) {
- Tcl_Panic("couldn't allocate new Mac window");
+ Tcl_Panic("couldn't allocate new Mac window");
}
TKContentView *contentView = [[TKContentView alloc]
- initWithFrame:NSZeroRect];
+ initWithFrame:NSZeroRect];
[window setContentView:contentView];
[contentView release];
[window setDelegate:NSApp];
@@ -5476,7 +5554,7 @@ TkMacOSXMakeRealWindowExist(
[window setDocumentEdited:NO];
wmPtr->window = window;
- macWin->view = contentView;
+ macWin->view = window.contentView;
TkMacOSXApplyWindowAttributes(winPtr, window);
NSRect geometry = InitialWindowBounds(winPtr, window);
@@ -5485,7 +5563,6 @@ TkMacOSXMakeRealWindowExist(
geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y +
geometry.size.height);
[window setFrame:geometry display:NO];
-
TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
macWin->flags |= TK_HOST_EXISTS;
}
@@ -5880,7 +5957,6 @@ TkpChangeFocus(
if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) ){
NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
TkWmRestackToplevel(winPtr, Above, NULL);
if (force ) {
[NSApp activateIgnoringOtherApps:YES];
@@ -5888,7 +5964,6 @@ TkpChangeFocus(
if ( win && [win canBecomeKeyWindow] ) {
[win makeKeyAndOrderFront:NSApp];
}
- [pool drain];
}
/*
diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c
index 0be5416..a16daa8 100644
--- a/macosx/tkMacOSXXStubs.c
+++ b/macosx/tkMacOSXXStubs.c
@@ -142,7 +142,7 @@ TkpOpenDisplay(
static NSRect maxBounds = {{0, 0}, {0, 0}};
static char vendor[25] = "";
NSArray *cgVers;
- NSAutoreleasePool *pool;
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
if (gMacDisplay != NULL) {
if (strcmp(gMacDisplay->display->display_name, display_name) == 0) {
@@ -166,7 +166,6 @@ TkpOpenDisplay(
display->default_screen = 0;
display->display_name = (char *) macScreenName;
- pool = [NSAutoreleasePool new];
cgVers = [[[NSBundle bundleWithIdentifier:@"com.apple.CoreGraphics"]
objectForInfoDictionaryKey:@"CFBundleShortVersionString"]
componentsSeparatedByString:@"."];
@@ -181,7 +180,21 @@ TkpOpenDisplay(
NSAppKitVersionNumber);
}
display->vendor = vendor;
- Gestalt(gestaltSystemVersion, (SInt32 *) &display->release);
+ {
+ int major, minor, patch;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 10100
+ Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
+ Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
+ Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
+#else
+ NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
+ major = systemVersion.majorVersion;
+ minor = systemVersion.minorVersion;
+ patch = systemVersion.patchVersion;
+#endif
+ display->release = major << 16 | minor << 8 | patch;
+ }
/*
* These screen bits never change
@@ -890,6 +903,7 @@ XGetImage(
int format)
{
NSBitmapImageRep *bitmap_rep;
+ NSUInteger bitmap_fmt;
XImage * imagePtr = NULL;
char * bitmap = NULL;
char * image_data=NULL;
@@ -908,10 +922,11 @@ XGetImage(
}
bitmap_rep = BitmapRepFromDrawableRect(d, x, y,width, height);
+ bitmap_fmt = [bitmap_rep bitmapFormat];
- if ( bitmap_rep == Nil ||
- [bitmap_rep bitmapFormat] != 0 ||
- [bitmap_rep samplesPerPixel] != 4 ||
+ if ( bitmap_rep == Nil ||
+ (bitmap_fmt != 0 && bitmap_fmt != 1) ||
+ [bitmap_rep samplesPerPixel] != 4 ||
[bitmap_rep isPlanar] != 0 ) {
TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
return NULL;
@@ -920,10 +935,9 @@ XGetImage(
NSSize image_size = NSMakeSize(width, height);
NSImage* ns_image = [[NSImage alloc]initWithSize:image_size];
[ns_image addRepresentation:bitmap_rep];
-
- /* Assume premultiplied nonplanar data with 4 bytes per pixel and alpha last.*/
- if ( [bitmap_rep bitmapFormat] == 0 &&
- [bitmap_rep isPlanar ] == 0 &&
+
+ /* Assume premultiplied nonplanar data with 4 bytes per pixel.*/
+ if ( [bitmap_rep isPlanar ] == 0 &&
[bitmap_rep samplesPerPixel] == 4 ) {
bytes_per_row = [bitmap_rep bytesPerRow];
size = bytes_per_row*height;
@@ -933,14 +947,27 @@ XGetImage(
bitmap = ckalloc(size);
/*
Oddly enough, the bitmap has the top row at the beginning,
- and the pixels are in BGRA format.
+ and the pixels are in BGRA or ABGR format.
*/
- for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
- for (m=n; m<n+bytes_per_row; m+=4) {
- *(bitmap+m) = *(image_data+m+2);
- *(bitmap+m+1) = *(image_data+m+1);
- *(bitmap+m+2) = *(image_data+m);
- *(bitmap+m+3) = *(image_data+m+3);
+ if (bitmap_fmt == 0) {
+ /* BGRA */
+ for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
+ for (m=n; m<n+bytes_per_row; m+=4) {
+ *(bitmap+m) = *(image_data+m+2);
+ *(bitmap+m+1) = *(image_data+m+1);
+ *(bitmap+m+2) = *(image_data+m);
+ *(bitmap+m+3) = *(image_data+m+3);
+ }
+ }
+ } else {
+ /* ABGR */
+ for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
+ for (m=n; m<n+bytes_per_row; m+=4) {
+ *(bitmap+m) = *(image_data+m+3);
+ *(bitmap+m+1) = *(image_data+m+2);
+ *(bitmap+m+2) = *(image_data+m+1);
+ *(bitmap+m+3) = *(image_data+m);
+ }
}
}
}
diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c
index 87ec4c2..1997370 100644
--- a/macosx/ttkMacOSXTheme.c
+++ b/macosx/ttkMacOSXTheme.c
@@ -299,7 +299,7 @@ static void TabElementSize(
void *clientData, void *elementRecord, Tk_Window tkwin,
int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
- *heightPtr = GetThemeMetric(kThemeMetricLargeTabHeight, heightPtr);
+ GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *)heightPtr);
*paddingPtr = Ttk_MakePadding(0, 0, 0, 2);
}
diff --git a/tests/bevel.tcl b/tests/bevel.tcl
index 950b714..4af60f3 100644
--- a/tests/bevel.tcl
+++ b/tests/bevel.tcl
@@ -42,6 +42,7 @@ significance:
r - should appear raised
u - should appear raised and also slightly offset vertically
s - should appear sunken
+S - should appear solid
n - preceding relief should extend right to end of line.
* - should appear "normal"
x - extra long lines to allow horizontal scrolling.
@@ -125,15 +126,33 @@ foreach i {1 2 3} {
.t.t insert end *****
.t.t insert end rrr r1
-
-
-
-
-
-
-
-
-
-
-
+font configure TkFixedFont -size 20
+.t.t tag configure sol100 -relief solid -borderwidth 100 \
+ -foreground red -font TkFixedFont
+.t.t tag configure sol12 -relief solid -borderwidth 12 \
+ -foreground red -font TkFixedFont
+.t.t tag configure big -font TkFixedFont
+set ind [.t.t index end]
+
+.t.t insert end "\n\nBorders do not leak on the neighbour chars"
+.t.t insert end "\nOnly \"S\" is on dark background"
+.t.t insert end {
+ xxx
+ x} {} S sol100 {x
+ xxx}
+
+.t.t insert end "\n\nA very thick border grows toward the inside of the tagged area only"
+.t.t insert end "\nOnly \"S\" is on dark background"
+.t.t insert end {
+ xxxx} {} SSSSS sol100 {xxxx
+ x} {} SSSSSSSSSSSSSSSSSS sol100 {x
+ xxx} {} SSSSSSSSS sol100 xxxx {}
+
+.t.t insert end "\n\nA thinner border is continuous"
+.t.t insert end {
+ xxxx} {} SSSSS sol12 {xxxx
+ x} {} SSSSSSSSSSSSSSSSSS sol12 {x
+ xxx} {} SSSSSSSSS sol12 xxxx {}
+
+.t.t tag add big $ind end
diff --git a/tests/entry.test b/tests/entry.test
index ffdbf45..da3637d 100644
--- a/tests/entry.test
+++ b/tests/entry.test
@@ -778,6 +778,14 @@ test entry-6.11 {EntryComputeGeometry procedure} win {
[expr 8+5*[font measure {helvetica 12} .]] \
[expr 8+5*[font measure {helvetica 12} X]] \
[expr 8+[font measure {helvetica 12} 12345]]]
+test entry-6.12 {EntryComputeGeometry procedure} {fonts} {
+ catch {destroy .e}
+ entry .e -font $fixed -bd 2 -relief raised -width 20
+ pack .e
+ .e insert end "012\t456\t"
+ update
+ list [.e index @81] [.e index @82] [.e index @116] [.e index @117]
+} {6 7 7 8}
catch {destroy .e}
entry .e -width 10 -font $fixed -textvariable contents -xscrollcommand scroll
@@ -1613,13 +1621,32 @@ test entry-22.1 {lost namespaced textvar} {
namespace eval test { variable foo {a b} }
entry .e -textvariable ::test::foo
namespace delete test
- .e insert end "more stuff"
- .e delete 5 end
- catch {set ::test::foo} result
- list [.e get] [.e cget -textvar] $result
+ catch {.e insert end "more stuff"} result1
+ catch {.e delete 5 end} result2
+ catch {set ::test::foo} result3
+ list [.e get] [.e cget -textvar] $result1 $result2 $result3
} [list "a bmo" ::test::foo \
+ {can't set "::test::foo": parent namespace doesn't exist} \
+ {can't set "::test::foo": parent namespace doesn't exist} \
{can't read "::test::foo": no such variable}]
+test entry-23.1 {error in trace proc attached to the textvariable} {
+ destroy .e
+ trace variable myvar w traceit
+ proc traceit args {error "Intentional error here!"}
+ entry .e -textvariable myvar
+ catch {.e insert end mystring} result1
+ catch {.e delete 0} result2
+ list $result1 $result2
+} [list {can't set "myvar": Intentional error here!} \
+ {can't set "myvar": Intentional error here!}]
+
+test entry-24.1 {textvariable lives in a non-existing namespace} {
+ destroy .e
+ catch {entry .e -textvariable thisnsdoesntexist::myvar} result1
+ set result1
+} {can't trace "thisnsdoesntexist::myvar": parent namespace doesn't exist}
+
destroy .e
# XXX Still need to write tests for EntryBlinkProc, EntryFocusProc,
diff --git a/tests/event.test b/tests/event.test
index fa75610..95be5f4 100644
--- a/tests/event.test
+++ b/tests/event.test
@@ -705,7 +705,7 @@ test event-7.1(double-click) {A double click on a lone character
set result
} {1.3 A 1.3 A}
test event-7.2(double-click) {A double click on a lone character\
- in an entry widget should select that character} {knownBug} {
+ in an entry widget should select that character} {
destroy .t
set t [toplevel .t]
set e [entry $t.e]
@@ -766,7 +766,7 @@ test event-7.2(double-click) {A double click on a lone character\
lappend result [_get_selection $e]
set result
-} {3 A 4 A}
+} {4 A 4 A}
# cleanup
diff --git a/tests/font.test b/tests/font.test
index a02cc2e..2defb29 100644
--- a/tests/font.test
+++ b/tests/font.test
@@ -829,7 +829,7 @@ test font-24.10 {Tk_ComputeTextLayout: tab caused break} {
lappend x [getsize]
.b.l config -wrap 0
set x
-} "{[expr $ax*3] $ay} {[expr $ax*3] [expr $ay*2]}"
+} "{[expr $ax*8] $ay} {[expr $ax*8] [expr $ay*2]}"
test font-24.11 {Tk_ComputeTextLayout: absorb spaces at eol} {
set x {}
.b.l config -text "000 000" -wrap [expr $ax*5]
@@ -1162,6 +1162,7 @@ test font-33.1 {Tk_TextWidth procedure} {
test font-34.1 {ConfigAttributesObj procedure: arguments} {
# (Tcl_GetIndexFromObj() != TCL_OK)
+ set x {}
setup
list [catch {font create xyz -xyz} msg] $msg
} {1 {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}}
diff --git a/tests/listbox.test b/tests/listbox.test
index b4046b6..62b8cc1 100644
--- a/tests/listbox.test
+++ b/tests/listbox.test
@@ -2169,6 +2169,45 @@ test listbox-30.1 {Bug 3607326} -setup {
unset -nocomplain a
} -result * -match glob -returnCodes error
+test listbox-31.1 {<<ListboxSelect>> event} -setup {
+ destroy .l
+ unset -nocomplain res
+} -body {
+ pack [listbox .l -state normal]
+ update
+ bind .l <<ListboxSelect>> {lappend res [%W curselection]}
+ .l insert end a b c
+ focus -force .l
+ event generate .l <1> -x 5 -y 5 ; # <<ListboxSelect>> fires
+ .l configure -state disabled
+ focus -force .l
+ event generate .l <Control-Home> ; # <<ListboxSelect>> does NOT fire
+ .l configure -state normal
+ focus -force .l
+ event generate .l <Control-End> ; # <<ListboxSelect>> fires
+ .l selection clear 0 end ; # <<ListboxSelect>> does NOT fire
+ .l selection set 1 1 ; # <<ListboxSelect>> does NOT fire
+ lappend res [.l curselection]
+} -cleanup {
+ destroy .l
+ unset -nocomplain res
+} -result {0 2 1}
+
+test listbox-31.2 {<<ListboxSelect>> event on lost selection} -setup {
+ destroy .l
+} -body {
+ pack [listbox .l -exportselection true]
+ update
+ bind .l <<ListboxSelect>> {lappend res [list [selection own] [%W curselection]]}
+ .l insert end a b c
+ focus -force .l
+ event generate .l <1> -x 5 -y 5 ; # <<ListboxSelect>> fires
+ selection clear ; # <<ListboxSelect>> fires again
+ set res
+} -cleanup {
+ destroy .l
+} -result {{.l 0} {{} {}}}
+
resetGridInfo
deleteWindows
option clear
diff --git a/tests/menu.test b/tests/menu.test
index 3cb47c3..c797281 100644
--- a/tests/menu.test
+++ b/tests/menu.test
@@ -754,8 +754,13 @@ test menu-3.41 {MenuWidgetCmd procedure, "index" option} {
catch {destroy .m1}
menu .m1
.m1 add command -label "test"
- list [catch {.m1 index "test"} msg] $msg [destroy .m1]
-} {0 1 {}}
+ .m1 add command -label "3"
+ .m1 add command -label "another label"
+ .m1 add command -label "end"
+ .m1 add command -label "3a"
+ .m1 add command -label "final entry"
+ list [.m1 index "test"] [.m1 index "3"] [.m1 index "3a"] [.m1 index "end"] [destroy .m1]
+} {1 3 5 6 {}}
test menu-3.42 {MenuWidgetCmd procedure, "insert" option} {
catch {destroy .m1}
menu .m1
@@ -2561,6 +2566,15 @@ test menu-36.1 {menu -underline string overruns Bug 1599877} {} {
tk::TraverseToMenu . "e"
} {}
+test menu-37.1 {menubar menues cannot be posted - bug 2160206} {} {
+ # On Linux the following used to panic
+ # It now returns an error (on all platforms)
+ catch {destroy .m}
+ menu .m -type menubar
+ list [catch ".m post 1 1" msg] $msg
+} {1 {a menubar menu cannot be posted}}
+
+
# cleanup
deleteWindows
cleanupTests
diff --git a/tests/panedwindow.test b/tests/panedwindow.test
index 724b40d..b075e18 100644
--- a/tests/panedwindow.test
+++ b/tests/panedwindow.test
@@ -29,24 +29,31 @@ foreach {testName testData} {
20 20 badValue {bad screen distance "badValue"}}
panedwindow-1.8 {-opaqueresize
true 1 foo {expected boolean value but got "foo"}}
- panedwindow-1.9 {-orient
+ panedwindow-1.9 {-proxybackground
+ "#f0a0a0" "#f0a0a0" non-existent {unknown color name "non-existent"}}
+ panedwindow-1.10 {-proxyborderwidth
+ 1.3 1.3 badValue {bad screen distance "badValue"}}
+ panedwindow-1.11 {-proxyrelief
+ groove groove
+ 1.5 {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}}
+ panedwindow-1.12 {-orient
horizontal horizontal
badValue {bad orient "badValue": must be horizontal or vertical}}
- panedwindow-1.10 {-relief
+ panedwindow-1.13 {-relief
groove groove
1.5 {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}}
- panedwindow-1.11 {-sashcursor
+ panedwindow-1.14 {-sashcursor
arrow arrow badValue {bad cursor spec "badValue"}}
- panedwindow-1.12 {-sashpad
+ panedwindow-1.15 {-sashpad
1.3 1 badValue {bad screen distance "badValue"}}
- panedwindow-1.13 {-sashrelief
+ panedwindow-1.16 {-sashrelief
groove groove
1.5 {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}}
- panedwindow-1.14 {-sashwidth
+ panedwindow-1.17 {-sashwidth
10 10 badValue {bad screen distance "badValue"}}
- panedwindow-1.15 {-showhandle
+ panedwindow-1.18 {-showhandle
true 1 foo {expected boolean value but got "foo"}}
- panedwindow-1.16 {-width
+ panedwindow-1.19 {-width
402 402 badValue {bad screen distance "badValue"}}
} {
lassign $testData optionName goodIn goodOut badIn badOut
diff --git a/tests/scrollbar.test b/tests/scrollbar.test
index 5d4334f..35f48bd 100644
--- a/tests/scrollbar.test
+++ b/tests/scrollbar.test
@@ -632,6 +632,36 @@ test scrollbar-9.1 {scrollbar widget vs hidden commands} {
list [winfo children .] [interp hidden]
} [list {} $l]
+test scrollbar-10.1 {<MouseWheel> event on scrollbar} -constraints {win|unix} -setup {
+ destroy .t .s
+} -body {
+ pack [text .t -yscrollcommand {.s set}] -side left
+ for {set i 1} {$i < 100} {incr i} {.t insert end "Line $i\n"}
+ pack [scrollbar .s -command {.t yview}] -fill y -expand 1 -side left
+ update
+ focus -force .s
+ event generate .s <MouseWheel> -delta -120
+ after 200 {set eventprocessed 1} ; vwait eventprocessed
+ .t index @0,0
+} -cleanup {
+ destroy .t .s
+} -result {5.0}
+
+test scrollbar-10.2 {<MouseWheel> event on scrollbar} -constraints {win|unix} -setup {
+ destroy .t .s
+} -body {
+ pack [text .t -xscrollcommand {.s set} -wrap none] -side top
+ for {set i 1} {$i < 100} {incr i} {.t insert end "Char $i "}
+ pack [scrollbar .s -command {.t xview} -orient horizontal] -fill x -expand 1 -side top
+ update
+ focus -force .s
+ event generate .s <Shift-MouseWheel> -delta -120
+ after 200 {set eventprocessed 1} ; vwait eventprocessed
+ .t index @0,0
+} -cleanup {
+ destroy .t .s
+} -result {1.4}
+
catch {destroy .s}
catch {destroy .t}
diff --git a/tests/spinbox.test b/tests/spinbox.test
index 430e176..68c6fae 100644
--- a/tests/spinbox.test
+++ b/tests/spinbox.test
@@ -1568,9 +1568,9 @@ test spinbox-22.3 {spinbox config, -from changes SF bug 559078} {
set val
} {6}
-test entry-23.1 {selection present while disabled, bug 637828} {
+test spinbox-23.1 {selection present while disabled, bug 637828} {
destroy .e
- entry .e
+ spinbox .e
.e insert end 0123456789
.e select from 3
.e select to 6
@@ -1583,6 +1583,28 @@ test entry-23.1 {selection present while disabled, bug 637828} {
} {1 1 345}
destroy .e
+
+test spinbox-24.1 {error in trace proc attached to the textvariable} {
+ destroy .s
+ trace variable myvar w traceit
+ proc traceit args {error "Intentional error here!"}
+ spinbox .s -textvariable myvar -from 1 -to 10
+ catch {.s set mystring} result1
+ catch {.s insert 0 mystring} result2
+ catch {.s delete 0} result3
+ catch {.s invoke buttonup} result4
+ list $result1 $result2 $result3 $result4
+} [list {can't set "myvar": Intentional error here!} \
+ {can't set "myvar": Intentional error here!} \
+ {can't set "myvar": Intentional error here!} \
+ {can't set "myvar": Intentional error here!}]
+
+test spinbox-25.1 {textvariable lives in a non-existing namespace} {
+ destroy .s
+ catch {spinbox .s -textvariable thisnsdoesntexist::myvar} result1
+ set result1
+} {can't trace "thisnsdoesntexist::myvar": parent namespace doesn't exist}
+
catch {unset ::e ::vVals}
##
diff --git a/tests/text.test b/tests/text.test
index e75f38a..2ca5d54 100644
--- a/tests/text.test
+++ b/tests/text.test
@@ -714,22 +714,23 @@ test text-9.2.45 {TextWidgetCmd procedure, "count" option} -setup {
} -result {0}
test text-9.2.46 {TextWidgetCmd procedure, "count" option} -setup {
toplevel .mytop
- pack [text .mytop.t]
- wm geometry .mytop 100x300+0+0
+ pack [text .mytop.t -font TkFixedFont -bd 0 -padx 0 -wrap char]
+ set spec [font measure TkFixedFont "Line 1+++Line 1---Li"] ; # 20 chars
+ append spec x300+0+0
+ wm geometry .mytop $spec
.mytop.t delete 1.0 end
update
set res {}
} -body {
for {set i 1} {$i < 5} {incr i} {
- # 0 1 2 3 4
- # 012345 678901234 567890123 456789012 34567890123456789
+ # 0 1 2 3 4
+ # 012345 678901234 567890123 456789012 34567890123456789
.mytop.t insert end "Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr 64+$i]]\n"
}
.mytop.t tag configure hidden -elide true
- .mytop.t tag add hidden 2.15 3.10
- .mytop.t configure -wrap char
+ .mytop.t tag add hidden 2.30 3.10
lappend res [.mytop.t count -displaylines 2.0 3.0]
- lappend res [.mytop.t count -displaylines 2.0 3.40]
+ lappend res [.mytop.t count -displaylines 2.0 3.50]
} -cleanup {
destroy .mytop
} -result {1 3}
@@ -744,6 +745,10 @@ test text-9.2.47 {TextWidgetCmd procedure, "count" option} -setup {
.t tag configure hidden -elide true
.t tag add hidden 5.7 11.0
update
+ # next line to be fully sure that asynchronous line heights calculation is
+ # up-to-date otherwise this test may fail (depending on the computer
+ # performance), especially when the . toplevel has small height
+ .t count -update -ypixels 1.0 end
set y1 [lindex [.t yview] 1]
.t count -displaylines 5.0 11.0
set y2 [lindex [.t yview] 1]
@@ -2780,6 +2785,24 @@ test text-20.185 {TextSearchCmd, elide up to match} {
lappend res [.t2 search -regexp bc 1.0]
lappend res [.t2 search -regexp c 1.0]
} {{} {} 1.0 2.1 2.0 3.1 2.0 3.0}
+test text-20.185.1 {TextSearchCmd, elide up to match, with UTF-8 chars before the match} {
+ deleteWindows
+ pack [text .t2]
+ .t2 tag configure e -elide 0
+ .t2 insert end A {} xyz e bb\n
+ .t2 insert end \u00c4 {} xyz e bb
+ set res {}
+ lappend res [.t2 search bb 1.0 "1.0 lineend"]
+ lappend res [.t2 search bb 2.0 "2.0 lineend"]
+ lappend res [.t2 search -regexp bb 1.0 "1.0 lineend"]
+ lappend res [.t2 search -regexp bb 2.0 "2.0 lineend"]
+ .t2 tag configure e -elide 1
+ lappend res [.t2 search bb 1.0 "1.0 lineend"]
+ lappend res [.t2 search bb 2.0 "2.0 lineend"]
+ lappend res [.t2 search -regexp bb 1.0 "1.0 lineend"]
+ lappend res [.t2 search -regexp -elide bb 2.0 "2.0 lineend"]
+ lappend res [.t2 search -regexp bb 2.0 "2.0 lineend"]
+} {1.4 2.4 1.4 2.4 1.4 2.4 1.4 2.4 2.4}
test text-20.186 {TextSearchCmd, strict limits} {
deleteWindows
pack [text .t2]
@@ -3204,6 +3227,95 @@ test text-25.18 {patch 1469210 - inserting after undo} -setup {
} -cleanup {
destroy .t
} -result 1
+test text-25.19 {patch 1669632 (i) - undo after <Control-1>} -setup {
+ destroy .t
+} -body {
+ text .t -undo 1
+ .t insert end foo\nbar
+ .t edit reset
+ .t insert 2.2 WORLD
+ event generate .t <Control-1> -x 1 -y 1
+ .t insert insert HELLO
+ .t edit undo
+ .t get 2.2 2.7
+} -cleanup {
+ destroy .t
+} -result WORLD
+test text-25.20 {patch 1669632 (iv) - undo after <Control-backslash>} -setup {
+ destroy .t
+} -body {
+ toplevel .top
+ pack [text .top.t -undo 1]
+ .top.t insert end "This is an example text"
+ .top.t edit reset
+ .top.t mark set insert 1.5
+ .top.t insert 1.5 HELLO
+ .top.t tag add sel 1.10 1.12
+ update
+ focus -force .top.t
+ event generate .top.t <Control-backslash>
+ .top.t insert insert " WORLD "
+ .top.t edit undo
+ .top.t get 1.5 1.10
+} -cleanup {
+ destroy .top.t .top
+} -result HELLO
+test text-25.21 {patch 1669632 (vii) - <<Undo>> shall not remove separators} -setup {
+ destroy .t
+} -body {
+ text .t -undo 1
+ .t insert end "This is an example text"
+ .t edit reset
+ .t insert 1.5 "WORLD "
+ event generate .t <Control-1> -x 1 -y 1
+ .t insert insert HELLO
+ event generate .t <<Undo>>
+ .t insert insert E
+ event generate .t <<Undo>>
+ .t get 1.0 "1.0 lineend"
+} -cleanup {
+ destroy .t
+} -result "This WORLD is an example text"
+test text-25.22 {patch 1669632 (v) - <<Clear>> is atomic} -setup {
+ destroy .t
+} -body {
+ toplevel .top
+ pack [text .top.t -undo 1]
+ .top.t insert end "This is an example text"
+ .top.t edit reset
+ .top.t mark set insert 1.5
+ .top.t insert 1.5 "A"
+ update
+ focus -force .top.t
+ event generate .top.t <Delete>
+ event generate .top.t <Shift-Right>
+ event generate .top.t <<Clear>>
+ event generate .top.t <Delete>
+ event generate .top.t <<Undo>>
+ .top.t get 1.0 "1.0 lineend"
+} -cleanup {
+ destroy .top.t .top
+} -result "This A an example text"
+ test text-25.23 {patch 1669632 (v) - <<Cut>> is atomic} -setup {
+ destroy .t
+} -body {
+ toplevel .top
+ pack [text .top.t -undo 1]
+ .top.t insert end "This is an example text"
+ .top.t edit reset
+ .top.t mark set insert 1.5
+ .top.t insert 1.5 "A"
+ update
+ focus -force .top.t
+ event generate .top.t <Delete>
+ event generate .top.t <Shift-Right>
+ event generate .top.t <<Cut>>
+ event generate .top.t <Delete>
+ event generate .top.t <<Undo>>
+ .top.t get 1.0 "1.0 lineend"
+} -cleanup {
+ destroy .top.t .top
+} -result "This A an example text"
test text-26.1 {bug fix - 624372, ControlUtfProc long lines} {
destroy .t
diff --git a/tests/textDisp.test b/tests/textDisp.test
index aed842c..bb009ad 100644
--- a/tests/textDisp.test
+++ b/tests/textDisp.test
@@ -615,6 +615,10 @@ catch {destroy .f2}
.t configure -borderwidth 0 -wrap char
wm geom . {}
update
+set bw [.t cget -borderwidth]
+set px [.t cget -padx]
+set py [.t cget -pady]
+set hlth [.t cget -highlightthickness]
test textDisp-4.7 {UpdateDisplayInfo, filling in extra vertical space} {
# This test was failing on Windows because the title bar on .
# was a certain minimum size and it was interfering with the size
@@ -653,7 +657,7 @@ test textDisp-4.9 {UpdateDisplayInfo, filling in extra vertical space} {textfont
update
.t delete 15.0 end
list [.t bbox 7.0] [.t bbox 12.0]
-} [list [list 3 [expr {2*$fixedDiff + 29}] 7 $fixedHeight] [list 3 [expr {7*$fixedDiff + 94}] 7 $fixedHeight]]
+} [list [list [expr {$hlth + $px + $bw}] [expr {$hlth + $py + $bw + 2 * $fixedHeight}] $fixedWidth $fixedHeight] [list [expr {$hlth + $px + $bw}] [expr {$hlth + $py + $bw + 7 * $fixedHeight}] $fixedWidth $fixedHeight]]
test textDisp-4.10 {UpdateDisplayInfo, filling in extra vertical space} {
.t delete 1.0 end
.t insert end "1\n2\n3\n4\n5\nLine 6 is such a long line that it wraps around.\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
@@ -1177,16 +1181,15 @@ test textDisp-8.12 {TkTextChanged, moving the insert cursor redraws only past an
.t mark set insert 3.8 ; # within the same line
update
lappend res $tk_textRedraw
- # This last one is tricky: correct result really is {2.0 3.0} when
- # calling .t mark set insert, two calls to TkTextChanged are done:
- # (a) to redraw the line of the past position of the cursor
- # (b) to redraw the line of the new position of the cursor
- # During (a) the display line showing the cursor gets unlinked,
- # which leads TkTextChanged in (b) to schedule a redraw starting
- # one line _before_ the line containing the insert cursor. This is
- # because during (b) findDLine cannot return the display line the
- # cursor is in since this display line was just unlinked in (a).
-} {{8.0 9.0} {8.0 12.0} {8.0 12.0} {3.0 8.0} {2.0 3.0}}
+} {{8.0 9.0} {8.0 12.0} {8.0 12.0} {3.0 8.0} {3.0 4.0}}
+test textDisp-8.13 {TkTextChanged, used to crash, see [06c1433906]} {
+ .t delete 1.0 end
+ .t insert 1.0 \nLine2\nLine3\n
+ update
+ .t insert 3.0 ""
+ .t delete 1.0 2.0
+ update idletasks
+} {}
test textDisp-9.1 {TkTextRedrawTag} {
.t configure -wrap char
@@ -1329,6 +1332,30 @@ test textDisp-9.13 {TkTextRedrawTag} {
update
list $tk_textRelayout $tk_textRedraw
} {{2.0 6.0 7.0} {2.0 6.0 7.0}}
+test textDisp-9.14 {TkTextRedrawTag} {
+ pack [text .tnocrash]
+ for {set i 1} {$i < 6} {incr i} {
+ .tnocrash insert end \nfoo$i
+ }
+ .tnocrash tag configure mytag1 -relief raised
+ .tnocrash tag configure mytag2 -relief solid
+ update
+ proc doit {} {
+ .tnocrash tag add mytag1 4.0 5.0
+ .tnocrash tag add mytag2 4.0 5.0
+ after idle {
+ .tnocrash tag remove mytag1 1.0 end
+ .tnocrash tag remove mytag2 1.0 end
+ }
+ .tnocrash delete 1.0 2.0
+ }
+ doit ; # must not crash
+ after 500 {
+ destroy .tnocrash
+ set done 1
+ }
+ vwait done
+} {}
test textDisp-10.1 {TkTextRelayoutWindow} {
.t configure -wrap char
@@ -1570,6 +1597,17 @@ test textDisp-11.20 {TkTextSetYView, see in elided lines} {
# this shall not crash (null chunkPtr in TkTextSeeCmd is tested)
.top.t see 3.0
} {}
+test textDisp-11.21 {TkTextSetYView, window height smaller than the line height} {
+ .top.t delete 1.0 end
+ for {set i 1} {$i <= 10} {incr i} {
+ .top.t insert end "Line $i\n"
+ }
+ set lineheight [font metrics [.top.t cget -font] -linespace]
+ wm geometry .top 200x[expr {$lineheight / 2}]
+ update
+ .top.t see 1.0
+ .top.t index @0,[expr {$lineheight - 2}]
+} {1.0}
.t configure -wrap word
.t delete 50.0 51.0
@@ -2006,9 +2044,9 @@ test textDisp-16.18 {TkTextYviewCmd procedure, "moveto" roundoff} {textfonts} {
wm geometry .top1 +0+0
text .top1.t -height 3 -width 4 -wrap none -setgrid 1 -padx 6 \
-spacing3 6
- .top1.t insert end "1\n2\n3\n4\n5\n6"
pack .top1.t
update
+ .top1.t insert end "1\n2\n3\n4\n5\n6"
.top1.t yview moveto 0.3333
set result [.top1.t yview]
destroy .top1
@@ -4100,7 +4138,7 @@ test textDisp-33.2 {one line longer than fits in the widget} {
.tt debug 1
set tk_textHeightCalc ""
.tt insert 1.0 [string repeat "more wrap + " 1]
- after 100 ; update
+ after 100 ; update idletasks
# Nothing should have been recalculated.
set tk_textHeightCalc
} {}
@@ -4180,7 +4218,23 @@ test textDisp-34.1 {Text widgets multi-scrolling problem: Bug 2677890} -setup {
return $result
} -cleanup {
destroy .t1 .sy
-} -result {{0.0 1.0} {0.0 1.0} {0.0 1.0} {0.0 0.24}}
+} -result {{0.0 0.24} {0.0 0.24} {0.0 0.24} {0.0 0.24}}
+
+test textDisp-35.1 {Init value of charHeight - Dancing scrollbar bug 1499165} -setup {
+ pack [text .t1] -fill both -expand y -side left
+ .t insert end "[string repeat a\nb\nc\n 500000]THE END\n"
+ set res {}
+} -body {
+ .t see 10000.0
+ after 300 {set fr1 [.t yview] ; set done 1}
+ vwait done
+ after 300 {set fr2 [.t yview] ; set done 1}
+ vwait done
+ lappend res [expr {[lindex $fr1 0] == [lindex $fr2 0]}]
+ lappend res [expr {[lindex $fr1 1] == [lindex $fr2 1]}]
+} -cleanup {
+ destroy .t1
+} -result {1 1}
deleteWindows
option clear
diff --git a/tests/textIndex.test b/tests/textIndex.test
index abed3d4..e78e54b 100644
--- a/tests/textIndex.test
+++ b/tests/textIndex.test
@@ -943,6 +943,19 @@ test textIndex-24.1 {text mark prev} {
set res
} {1.0}
+test textIndex-25.1 {IndexCountBytesOrdered, bug [3f1f79abcf]} {
+ pack [text .t2]
+ .t2 tag configure elided -elide 1
+ .t2 insert end "01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n"
+ .t2 insert end "11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n"
+ .t2 insert end "21\n22\n23\n25\n26\n27\n28\n29\n30\n31"
+ .t2 insert end "32\n33\n34\n36\n37\n38\n39" elided
+ # then this used to crash Tk:
+ .t2 see end
+ focus -force .t2 ; # to see the cursor blink
+ destroy .t2
+} {}
+
# cleanup
rename textimage {}
catch {destroy .t}
diff --git a/tests/textWind.test b/tests/textWind.test
index 79dca50..2e16f7b 100644
--- a/tests/textWind.test
+++ b/tests/textWind.test
@@ -1023,6 +1023,20 @@ test textWind-17.9 {peer widget window configuration} {
set res
} {{-window {} {} {} {}} {-window {} {} {} {}} {-window {} {} {} .t.f} {-window {} {} {} .tt.t.f}}
+test textWind-18.1 {embedded window deletion triggered by a script bound to <Map>} {
+ catch {destroy .t .f}
+ 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]
+ .t window create end -window [frame .f2 -background blue -width 80 -height 80]
+ bind .f <Map> {.t delete .f}
+ update
+ # this shall not crash (bug 1501749)
+ after 100 {.t yview end}
+ tkwait visibility .f2
+ update
+} {}
+
catch {destroy .t}
option clear
diff --git a/tests/ttk/notebook.test b/tests/ttk/notebook.test
index cdce020..3a2a6ff 100644
--- a/tests/ttk/notebook.test
+++ b/tests/ttk/notebook.test
@@ -468,6 +468,27 @@ test notebook-1817596-3 "insert/configure" -body {
} -result [list [list .nb.l2 .nb.l0 .nb.l1] L2 L0 L1] -cleanup { destroy .nb }
+test notebook-readd-1 "add same widget twice" -body {
+ pack [ttk::notebook .nb]
+ .nb add [ttk::button .nb.b1] -text "Button"
+ .nb add .nb.b1
+ .nb tabs
+} -result [list .nb.b1] -cleanup { destroy .nb }
+
+test notebook-readd-2 "add same widget twice, with options" -body {
+ pack [ttk::notebook .nb]
+ .nb add [ttk::button .nb.b1] -text "Tab label"
+ .nb add .nb.b1 -text "Changed tab label"
+ .nb tabs
+} -result [list .nb.b1] -cleanup { destroy .nb }
+
+test notebook-readd-3 "insert same widget twice, with options" -body {
+ pack [ttk::notebook .nb]
+ .nb insert end [ttk::button .nb.b1] -text "Tab label"
+ .nb insert end .nb.b1 -text "Changed tab label"
+ .nb tabs
+} -result [list .nb.b1] -cleanup { destroy .nb }
+
# See #1343984
test notebook-1343984-1 "don't autoselect on destroy - setup" -body {
diff --git a/tests/ttk/spinbox.test b/tests/ttk/spinbox.test
index f7741c6..32b77af 100644
--- a/tests/ttk/spinbox.test
+++ b/tests/ttk/spinbox.test
@@ -143,7 +143,7 @@ test spinbox-1.8.4 "-validate option: " -setup {
.sb configure -validate all -validatecommand {lappend ::spinbox_test %P}
pack .sb
.sb set 50
- focus .sb
+ focus -force .sb
after 500 {set ::spinbox_wait 1} ; vwait ::spinbox_wait
set ::spinbox_test
} -cleanup {
diff --git a/tests/winButton.test b/tests/winButton.test
index 5bf6867..5e3dcfb 100644
--- a/tests/winButton.test
+++ b/tests/winButton.test
@@ -29,7 +29,9 @@ radiobutton .r -text Radiobutton
pack .l .b .c .r
update
-test winbutton-1.1 {TkpComputeButtonGeometry procedure} {testImageType win} {
+test winbutton-1.1 {TkpComputeButtonGeometry procedure} {testImageType win nonPortable} {
+ # nonPortable because of [3e3e25f483]: on Win7 first started with a high DPI screen
+ # the smallest size (i.e. 8) is not available for "MS Sans Serif" font
deleteWindows
image create test image1
image1 changed 0 0 0 0 60 40
@@ -46,7 +48,9 @@ test winbutton-1.1 {TkpComputeButtonGeometry procedure} {testImageType win} {
[winfo reqwidth .b3] [winfo reqheight .b3] \
[winfo reqwidth .b4] [winfo reqheight .b4]
} {68 48 70 50 90 52 90 52}
-test winbutton-1.2 {TkpComputeButtonGeometry procedure} win {
+test winbutton-1.2 {TkpComputeButtonGeometry procedure} {win nonPortable} {
+ # nonPortable because of [3e3e25f483]: on Win7 first started with a high DPI screen
+ # the smallest size (i.e. 8) is not available for "MS Sans Serif" font
deleteWindows
label .b1 -bitmap question -bd 3 -padx 0 -pady 2
button .b2 -bitmap question -bd 3 -padx 0 -pady 2
diff --git a/unix/configure b/unix/configure
index 824d3b4..f6c4ff7 100755
--- a/unix/configure
+++ b/unix/configure
@@ -1338,7 +1338,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
TK_VERSION=8.5
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=5
-TK_PATCH_LEVEL=".18"
+TK_PATCH_LEVEL=".19"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
@@ -5783,7 +5783,7 @@ fi
;;
*)
case "$arch" in
- alpha|sparc64)
+ alpha|sparc|sparc64)
SHLIB_CFLAGS="-fPIC"
;;
*)
@@ -7086,7 +7086,7 @@ fi
MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
if test "${SHLIB_SUFFIX}" = ".dll"; then
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
else
diff --git a/unix/configure.in b/unix/configure.in
index bab5d8a..d4a8c28 100644
--- a/unix/configure.in
+++ b/unix/configure.in
@@ -25,7 +25,7 @@ m4_ifdef([SC_USE_CONFIG_HEADERS], [
TK_VERSION=8.5
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=5
-TK_PATCH_LEVEL=".18"
+TK_PATCH_LEVEL=".19"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
diff --git a/unix/tcl.m4 b/unix/tcl.m4
index b9f4896..3005321 100644
--- a/unix/tcl.m4
+++ b/unix/tcl.m4
@@ -1500,7 +1500,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
;;
*)
case "$arch" in
- alpha|sparc64)
+ alpha|sparc|sparc64)
SHLIB_CFLAGS="-fPIC"
;;
*)
@@ -2069,7 +2069,7 @@ dnl # preprocessing tests use only CPPFLAGS.
LIB_SUFFIX=${SHARED_LIB_SUFFIX}
MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [
- INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"'
+ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
], [
INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
diff --git a/unix/tk.spec b/unix/tk.spec
index fd51c52..02bb625 100644
--- a/unix/tk.spec
+++ b/unix/tk.spec
@@ -4,7 +4,7 @@
Name: tk
Summary: Tk graphical toolkit for the Tcl scripting language.
-Version: 8.5.18
+Version: 8.5.19
Release: 2
License: BSD
Group: Development/Languages
diff --git a/unix/tkUnixDefault.h b/unix/tkUnixDefault.h
index 4eb8778..a8ecdc1 100644
--- a/unix/tkUnixDefault.h
+++ b/unix/tkUnixDefault.h
@@ -367,6 +367,7 @@
#define DEF_PANEDWINDOW_HEIGHT ""
#define DEF_PANEDWINDOW_OPAQUERESIZE "1"
#define DEF_PANEDWINDOW_ORIENT "horizontal"
+#define DEF_PANEDWINDOW_PROXYBORDER "2"
#define DEF_PANEDWINDOW_RELIEF "flat"
#define DEF_PANEDWINDOW_SASHCURSOR ""
#define DEF_PANEDWINDOW_SASHPAD "0"
diff --git a/unix/tkUnixEmbed.c b/unix/tkUnixEmbed.c
index 5b5f486..119bc67 100644
--- a/unix/tkUnixEmbed.c
+++ b/unix/tkUnixEmbed.c
@@ -100,7 +100,7 @@ TkpUseWindow(
{
TkWindow *winPtr = (TkWindow *) tkwin;
TkWindow *usePtr;
- int id, anyError;
+ int anyError;
Window parent;
Tk_ErrorHandler handler;
Container *containerPtr;
@@ -113,10 +113,9 @@ TkpUseWindow(
"can't modify container after widget is created", NULL);
return TCL_ERROR;
}
- if (Tcl_GetInt(interp, string, &id) != TCL_OK) {
+ if (TkpScanWindowId(interp, string, &parent) != TCL_OK) {
return TCL_ERROR;
}
- parent = (Window) id;
usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, parent);
if (usePtr != NULL) {
diff --git a/unix/tkUnixXId.c b/unix/tkUnixXId.c
index ca2eb33..444be30 100644
--- a/unix/tkUnixXId.c
+++ b/unix/tkUnixXId.c
@@ -586,13 +586,23 @@ TkpScanWindowId(
CONST char *string,
Window *idPtr)
{
- int value;
+ int code;
+ Tcl_Obj obj;
- if (Tcl_GetInt(interp, string, &value) != TCL_OK) {
- return TCL_ERROR;
+ obj.refCount = 1;
+ obj.bytes = (char *) string; /* DANGER?! */
+ obj.length = strlen(string);
+ obj.typePtr = NULL;
+
+ code = Tcl_GetLongFromObj(interp, &obj, (long *)idPtr);
+
+ if (obj.refCount > 1) {
+ Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
+ }
+ if (obj.typePtr && obj.typePtr->freeIntRepProc) {
+ obj.typePtr->freeIntRepProc(&obj);
}
- *idPtr = (Window) value;
- return TCL_OK;
+ return code;
}
/*
diff --git a/win/configure b/win/configure
index 35f57ca..3d4bf2f 100755
--- a/win/configure
+++ b/win/configure
@@ -1312,7 +1312,7 @@ SHELL=/bin/sh
TK_VERSION=8.5
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=5
-TK_PATCH_LEVEL=".18"
+TK_PATCH_LEVEL=".19"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
#------------------------------------------------------------------------
@@ -3425,7 +3425,7 @@ do
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CYGPATH="cygpath -w"
+ ac_cv_prog_CYGPATH="cygpath -m"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
@@ -3827,6 +3827,13 @@ echo "${ECHO_T}using shared flags" >&6
EXESUFFIX="\${DBGX}.exe"
LIBRARIES="\${SHARED_LIBRARIES}"
SHLIB_LD_LIBS='${LIBS}'
+ case "x`echo \${VisualStudioVersion}`" in
+ x1[4-9]*)
+ lflags="${lflags} -nodefaultlib:libucrt.lib"
+ ;;
+ *)
+ ;;
+ esac
fi
# DLLSUFFIX is separate because it is the building block for
# users of tclConfig.sh that may build shared or static.
@@ -3852,18 +3859,23 @@ echo "${ECHO_T}using shared flags" >&6
;;
esac
if test ! -d "${PATH64}" ; then
- { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5
-echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;}
- { echo "$as_me:$LINENO: WARNING: Ensure latest Platform SDK is installed" >&5
-echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;}
- do64bit="no"
- else
- echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5
-echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6
+ { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK" >&5
+echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK" >&2;}
fi
+ echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5
+echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6
fi
LIBS="user32.lib advapi32.lib ws2_32.lib"
+
+ case "x`echo \${VisualStudioVersion}`" in
+ x1[4-9]*)
+ LIBS="$LIBS ucrt.lib"
+ ;;
+ *)
+ ;;
+ esac
+
if test "$do64bit" != "no" ; then
# The space-based-path will work for the Makefile, but will
# not work if AC_TRY_COMPILE is called. TEA has the
@@ -3938,7 +3950,7 @@ fi
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}"
- lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
+ lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
LINKBIN="\"${PATH64}/link.exe\""
# Avoid 'unresolved external symbol __security_cookie' errors.
# c.f. http://support.microsoft.com/?id=894573
@@ -3950,7 +3962,7 @@ fi
CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
# -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
- lflags="-nologo"
+ lflags="${lflags} -nologo"
LINKBIN="link"
fi
diff --git a/win/configure.in b/win/configure.in
index 4634bb6..9dd7fb8 100644
--- a/win/configure.in
+++ b/win/configure.in
@@ -14,7 +14,7 @@ SHELL=/bin/sh
TK_VERSION=8.5
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=5
-TK_PATCH_LEVEL=".18"
+TK_PATCH_LEVEL=".19"
VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
#------------------------------------------------------------------------
diff --git a/win/makefile.vc b/win/makefile.vc
index 4b9475f..d2795c9 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -42,7 +42,7 @@ the build instructions.
# turn on the 64-bit compiler, if your SDK has it.
#
# 3) Targets are:
-# release -- Builds the core, the shell. (default)
+# release -- Builds the core, the shell and the dlls. (default)
# dlls -- Just builds the windows extensions.
# shell -- Just builds the shell and the core.
# core -- Only builds the core [tkXX.(dll|lib)].
@@ -443,7 +443,7 @@ cdebug = $(OPTIMIZATIONS)
cdebug =
!endif
!if $(SYMBOLS)
-cdebug = $(cdebug) -Zi
+cdebug = $(cdebug) -Zi
!endif
!else if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64"
### Warnings are too many, can't support warnings into errors.
@@ -476,6 +476,7 @@ CON_CFLAGS = $(cdebug) $(cflags) $(crt) -DCONSOLE
WISH_CFLAGS = $(BASE_CFLAGS) $(TK_DEFINES)
STUB_CFLAGS = $(cflags) $(cdebug) $(TK_DEFINES)
+
#---------------------------------------------------------------------
# Link flags
#---------------------------------------------------------------------
@@ -496,6 +497,10 @@ lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)
lflags = $(lflags) -profile
!endif
+!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
+lflags = $(lflags) -nodefaultlib:libucrt.lib
+!endif
+
!if $(ALIGN98_HACK) && !$(STATIC_BUILD)
### Align sections for PE size savings.
lflags = $(lflags) -opt:nowin98
@@ -520,6 +525,10 @@ baselibs = kernel32.lib user32.lib
baselibs = $(baselibs) bufferoverflowU.lib
!endif
!endif
+!if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
+baselibs = $(baselibs) ucrt.lib
+!endif
+
guilibs = $(baselibs) gdi32.lib
diff --git a/win/nmakehlp.c b/win/nmakehlp.c
index b1a1517..84cf75c 100644
--- a/win/nmakehlp.c
+++ b/win/nmakehlp.c
@@ -606,8 +606,8 @@ SubstituteFile(
sp = fopen(substitutions, "rt");
if (sp != NULL) {
while (fgets(szBuffer, cbBuffer, sp) != NULL) {
- char *ks, *ke, *vs, *ve;
- ks = szBuffer;
+ unsigned char *ks, *ke, *vs, *ve;
+ ks = (unsigned char*)szBuffer;
while (ks && *ks && isspace(*ks)) ++ks;
ke = ks;
while (ke && *ke && !isspace(*ke)) ++ke;
@@ -616,7 +616,7 @@ SubstituteFile(
ve = vs;
while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
*ke = 0, *ve = 0;
- list_insert(&substPtr, ks, vs);
+ list_insert(&substPtr, (char*)ks, (char*)vs);
}
fclose(sp);
}
diff --git a/win/tcl.m4 b/win/tcl.m4
index 44fd47e..006778c 100644
--- a/win/tcl.m4
+++ b/win/tcl.m4
@@ -558,7 +558,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
# Set some defaults (may get changed below)
EXTRA_CFLAGS=""
- AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
+ AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo)
SHLIB_SUFFIX=".dll"
@@ -783,6 +783,13 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
EXESUFFIX="\${DBGX}.exe"
LIBRARIES="\${SHARED_LIBRARIES}"
SHLIB_LD_LIBS='${LIBS}'
+ case "x`echo \${VisualStudioVersion}`" in
+ x1[[4-9]]*)
+ lflags="${lflags} -nodefaultlib:libucrt.lib"
+ ;;
+ *)
+ ;;
+ esac
fi
# DLLSUFFIX is separate because it is the building block for
# users of tclConfig.sh that may build shared or static.
@@ -808,15 +815,21 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
;;
esac
if test ! -d "${PATH64}" ; then
- AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode])
- AC_MSG_WARN([Ensure latest Platform SDK is installed])
- do64bit="no"
- else
- AC_MSG_RESULT([ Using 64-bit $MACHINE mode])
+ AC_MSG_WARN([Could not find 64-bit $MACHINE SDK])
fi
+ AC_MSG_RESULT([ Using 64-bit $MACHINE mode])
fi
LIBS="user32.lib advapi32.lib ws2_32.lib"
+
+ case "x`echo \${VisualStudioVersion}`" in
+ x1[[4-9]]*)
+ LIBS="$LIBS ucrt.lib"
+ ;;
+ *)
+ ;;
+ esac
+
if test "$do64bit" != "no" ; then
# The space-based-path will work for the Makefile, but will
# not work if AC_TRY_COMPILE is called. TEA has the
@@ -831,7 +844,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
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}"
- lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
+ lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
LINKBIN="\"${PATH64}/link.exe\""
# Avoid 'unresolved external symbol __security_cookie' errors.
# c.f. http://support.microsoft.com/?id=894573
@@ -843,7 +856,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d"
# -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy)
CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}"
- lflags="-nologo"
+ lflags="${lflags} -nologo"
LINKBIN="link"
fi
diff --git a/win/tkWinDefault.h b/win/tkWinDefault.h
index a1a76c7..d0bae8f 100644
--- a/win/tkWinDefault.h
+++ b/win/tkWinDefault.h
@@ -370,6 +370,7 @@
#define DEF_PANEDWINDOW_HEIGHT ""
#define DEF_PANEDWINDOW_OPAQUERESIZE "1"
#define DEF_PANEDWINDOW_ORIENT "horizontal"
+#define DEF_PANEDWINDOW_PROXYBORDER "2"
#define DEF_PANEDWINDOW_RELIEF "flat"
#define DEF_PANEDWINDOW_SASHCURSOR ""
#define DEF_PANEDWINDOW_SASHPAD "0"
diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c
index b7f5085..a0670cc 100644
--- a/win/tkWinEmbed.c
+++ b/win/tkWinEmbed.c
@@ -256,10 +256,13 @@ TkpUseWindow(
return TCL_OK;
}
- if (Tcl_GetInt(interp, string, &id) != TCL_OK) {
+ if (
+#ifdef _WIN64
+ (sscanf(string, "0x%p", &hwnd) != 1) &&
+#endif
+ Tcl_GetInt(interp, string, (int *) &hwnd) != TCL_OK) {
return TCL_ERROR;
}
- hwnd = (HWND) INT2PTR(id);
if ((HWND)winPtr->privatePtr == hwnd) {
return TCL_OK;
}
diff --git a/win/tkWinPort.h b/win/tkWinPort.h
index 8d7778c..b94628e 100644
--- a/win/tkWinPort.h
+++ b/win/tkWinPort.h
@@ -80,6 +80,13 @@
#define REDO_KEYSYM_LOOKUP
/*
+ * See ticket [916c1095438eae56]: GetVersionExW triggers warnings
+ */
+#if defined(_MSC_VER)
+# pragma warning(disable:4996)
+#endif
+
+/*
* The following macro checks to see whether there is buffered
* input data available for a stdio FILE.
*/
diff --git a/win/tkWinScrlbr.c b/win/tkWinScrlbr.c
index 46aad58..fc9685d 100644
--- a/win/tkWinScrlbr.c
+++ b/win/tkWinScrlbr.c
@@ -218,10 +218,10 @@ CreateProc(
if (scrollPtr->info.vertical) {
style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
- | SBS_VERT | SBS_RIGHTALIGN;
+ | SBS_VERT;
} else {
style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
- | SBS_HORZ | SBS_BOTTOMALIGN;
+ | SBS_HORZ;
}
scrollPtr->hwnd = CreateWindow("SCROLLBAR", NULL, style,
diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c
index 80b616d..6359891 100644
--- a/win/ttkWinXPTheme.c
+++ b/win/ttkWinXPTheme.c
@@ -25,7 +25,7 @@ int TtkXPTheme_Init(Tcl_Interp *interp, HWND hwnd) { return TCL_OK; }
#include <windows.h>
#include <uxtheme.h>
-#ifdef HAVE_VSSYM32_H
+#if defined(HAVE_VSSYM32_H) || _MSC_VER > 1500
# include <vssym32.h>
#else
# include <tmschema.h>