summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2019-11-22 08:54:22 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2019-11-22 08:54:22 (GMT)
commit20a005ef0c7ab42b7f4f703572c56ac2af790137 (patch)
tree295f11b07b62234a45581c7e7e7d58a8a02c01d3
parent371daa9f78b7f888ce06ec270477e2dc174a54a1 (diff)
parent8e65c4de1acc5309017fcc308dc64b435509e719 (diff)
downloadtk-20a005ef0c7ab42b7f4f703572c56ac2af790137.zip
tk-20a005ef0c7ab42b7f4f703572c56ac2af790137.tar.gz
tk-20a005ef0c7ab42b7f4f703572c56ac2af790137.tar.bz2
Merge trunk
-rw-r--r--doc/ttk_button.n2
-rw-r--r--doc/ttk_checkbutton.n2
-rw-r--r--doc/ttk_label.n2
-rw-r--r--doc/ttk_menubutton.n2
-rw-r--r--doc/ttk_notebook.n2
-rw-r--r--doc/ttk_radiobutton.n2
-rw-r--r--doc/ttk_treeview.n2
-rw-r--r--generic/ks_names.h6
-rwxr-xr-xgeneric/nanosvg.h8
-rw-r--r--generic/tkFocus.c3
-rw-r--r--generic/tkFont.c15
-rw-r--r--generic/ttk/ttkButton.c5
-rw-r--r--generic/ttk/ttkNotebook.c4
-rw-r--r--generic/ttk/ttkTreeview.c24
-rw-r--r--library/demos/unicodeout.tcl9
-rw-r--r--library/entry.tcl24
-rw-r--r--library/iconlist.tcl6
-rw-r--r--library/listbox.tcl4
-rw-r--r--library/text.tcl27
-rw-r--r--library/tk.tcl8
-rw-r--r--library/ttk/aquaTheme.tcl27
-rw-r--r--library/ttk/entry.tcl26
-rw-r--r--library/ttk/treeview.tcl12
-rw-r--r--macosx/README6
-rw-r--r--macosx/tkMacOSXClipboard.c23
-rw-r--r--macosx/tkMacOSXDraw.c37
-rw-r--r--macosx/tkMacOSXFont.c29
-rw-r--r--macosx/tkMacOSXInit.c6
-rw-r--r--macosx/tkMacOSXKeyEvent.c301
-rw-r--r--macosx/tkMacOSXKeyboard.c9
-rw-r--r--macosx/tkMacOSXMenus.c2
-rw-r--r--macosx/tkMacOSXMouseEvent.c32
-rw-r--r--macosx/tkMacOSXPrivate.h12
-rw-r--r--macosx/tkMacOSXScrlbr.c12
-rw-r--r--macosx/tkMacOSXServices.c131
-rw-r--r--macosx/tkMacOSXTest.c30
-rw-r--r--macosx/tkMacOSXWindowEvent.c22
-rw-r--r--macosx/tkMacOSXWm.c88
-rw-r--r--macosx/ttkMacOSXTheme.c19
-rw-r--r--tests/bind.test23
-rw-r--r--tests/canvImg.test1
-rw-r--r--tests/ttk/notebook.test2
-rw-r--r--tests/ttk/treeview.test4
-rw-r--r--tests/unixEmbed.test52
-rw-r--r--tests/wm.test20
-rwxr-xr-xunix/configure20
-rw-r--r--unix/configure.ac6
-rwxr-xr-xunix/installManPage10
-rw-r--r--unix/tcl.m411
-rw-r--r--unix/tkUnixFont.c2
-rw-r--r--unix/tkUnixKey.c2
-rw-r--r--unix/tkUnixRFont.c15
-rw-r--r--unix/tkUnixWm.c9
-rwxr-xr-xwin/configure9
-rw-r--r--win/makefile.vc2
-rw-r--r--win/rules.vc17
-rw-r--r--win/tcl.m42
-rw-r--r--win/tkWinFont.c2
-rw-r--r--win/tkWinKey.c2
-rw-r--r--win/tkWinPointer.c4
-rw-r--r--win/tkWinWm.c28
-rw-r--r--xlib/X11/Xlib.h4
62 files changed, 775 insertions, 453 deletions
diff --git a/doc/ttk_button.n b/doc/ttk_button.n
index 2b091ad..eb40d9d 100644
--- a/doc/ttk_button.n
+++ b/doc/ttk_button.n
@@ -72,6 +72,8 @@ are:
.br
\fB\-bordercolor\fP \fIcolor\fP
.br
+\fB\-compound\fP \fIcompound\fP
+.br
\fB\-darkcolor\fP \fIcolor\fP
.br
\fB\-foreground\fP \fIcolor\fP
diff --git a/doc/ttk_checkbutton.n b/doc/ttk_checkbutton.n
index a18a886..c78dc0e 100644
--- a/doc/ttk_checkbutton.n
+++ b/doc/ttk_checkbutton.n
@@ -80,6 +80,8 @@ are:
.PP
\fB\-background\fP \fIcolor\fP
.br
+\fB\-compound\fP \fIcompound\fP
+.br
\fB\-foreground\fP \fIcolor\fP
.br
\fB\-indicatorbackground\fP \fIcolor\fP
diff --git a/doc/ttk_label.n b/doc/ttk_label.n
index 8553a08..1b25f9f 100644
--- a/doc/ttk_label.n
+++ b/doc/ttk_label.n
@@ -56,6 +56,8 @@ are:
.PP
\fB\-background\fP \fIcolor\fP
.br
+\fB\-compound\fP \fIcompound\fP
+.br
\fB\-foreground\fP \fIcolor\fP
.br
\fB\-font\fP \fIfont\fP
diff --git a/doc/ttk_menubutton.n b/doc/ttk_menubutton.n
index 76d3829..0d80c1e 100644
--- a/doc/ttk_menubutton.n
+++ b/doc/ttk_menubutton.n
@@ -58,6 +58,8 @@ are:
.br
\fB\-background\fP \fIcolor\fP
.br
+\fB\-compound\fP \fIcompound\fP
+.br
\fB\-foreground\fP \fIcolor\fP
.br
\fB\-font\fP \fIfont\fP
diff --git a/doc/ttk_notebook.n b/doc/ttk_notebook.n
index 19416b5..ae32a44 100644
--- a/doc/ttk_notebook.n
+++ b/doc/ttk_notebook.n
@@ -242,6 +242,8 @@ are:
.br
\fB\-bordercolor\fP \fIcolor\fP
.br
+\fB\-compound\fP \fIcompound\fP
+.br
\fB\-expand\fP \fIpadding\fP
.RS
Defines how much the tab grows in size. Usually used with the
diff --git a/doc/ttk_radiobutton.n b/doc/ttk_radiobutton.n
index 1344ae2..2dc84be 100644
--- a/doc/ttk_radiobutton.n
+++ b/doc/ttk_radiobutton.n
@@ -77,6 +77,8 @@ are:
.PP
\fB\-background\fP \fIcolor\fP
.br
+\fB\-compound\fP \fIcompound\fP
+.br
\fB\-foreground\fP \fIcolor\fP
.br
\fB\-indicatorbackground\fP \fIcolor\fP
diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n
index 125cc78..2deb5b5 100644
--- a/doc/ttk_treeview.n
+++ b/doc/ttk_treeview.n
@@ -235,7 +235,7 @@ A data cell.
Returns the item ID of the item at position \fIy\fR.
.TP
\fIpathname \fBidentify column \fIx y\fR
-Returns the data column identifier of the cell at position \fIx\fR.
+Returns the display column identifier of the cell at position \fIx\fR.
The tree column has ID \fB#0\fR.
.TP
\fIpathname \fBidentify element \fIx y\fR
diff --git a/generic/ks_names.h b/generic/ks_names.h
index b4c185f..a21b02b 100644
--- a/generic/ks_names.h
+++ b/generic/ks_names.h
@@ -521,7 +521,9 @@
{ "Odiaeresis", 0xD6 },
{ "multiply", 0xD7 },
{ "Oslash", 0xD8 },
+#ifndef TK_NO_DEPRECATED
{ "Ooblique", 0xD8 },
+#endif
{ "Ugrave", 0xD9 },
{ "Uacute", 0xDA },
{ "Ucircumflex", 0xDB },
@@ -555,7 +557,9 @@
{ "odiaeresis", 0xF6 },
{ "division", 0xF7 },
{ "oslash", 0xF8 },
+#ifndef TK_NO_DEPRECATED
{ "ooblique", 0xF8 },
+#endif
{ "ugrave", 0xF9 },
{ "uacute", 0xFA },
{ "ucircumflex", 0xFB },
@@ -960,9 +964,11 @@
{ "Greek_IOTAaccent", 0x7A4 },
{ "Greek_IOTAdieresis", 0x7A5 },
{ "Greek_IOTAdiaeresis", 0x7A5 },
+{ "Greek_IOTAaccentdiaeresis", 0x7A6 },
{ "Greek_OMICRONaccent", 0x7A7 },
{ "Greek_UPSILONaccent", 0x7A8 },
{ "Greek_UPSILONdieresis", 0x7A9 },
+{ "Greek_UPSILONaccentdieresis", 0x7AA },
{ "Greek_OMEGAaccent", 0x7AB },
{ "Greek_accentdieresis", 0x7AE },
{ "Greek_horizbar", 0x7AF },
diff --git a/generic/nanosvg.h b/generic/nanosvg.h
index b449dc2..5377ae0 100755
--- a/generic/nanosvg.h
+++ b/generic/nanosvg.h
@@ -704,10 +704,10 @@ static void nsvg__deleteStyles(NSVGstyles* style) {
while (style) {
NSVGstyles *next = style->next;
if (style->name!= NULL)
- free(style->name);
+ NANOSVG_free(style->name);
if (style->description != NULL)
- free(style->description);
- free(style);
+ NANOSVG_free(style->description);
+ NANOSVG_free(style);
style = next;
}
}
@@ -2843,7 +2843,7 @@ static void nsvg__content(void* ud, const char* s)
if (state == 1) {
NSVGstyles* next = p->styles;
- p->styles = (NSVGstyles*)malloc(sizeof(NSVGstyles));
+ p->styles = (NSVGstyles*)NANOSVG_malloc(sizeof(NSVGstyles));
p->styles->next = next;
p->styles->name = nsvg__strndup(start, (size_t)(s - start));
start = s + 1;
diff --git a/generic/tkFocus.c b/generic/tkFocus.c
index 7a4bdbc..7b5acfb 100644
--- a/generic/tkFocus.c
+++ b/generic/tkFocus.c
@@ -629,7 +629,8 @@ TkSetFocusWin(
}
tlFocusPtr->focusWinPtr = winPtr;
- if (topLevelPtr->flags & TK_EMBEDDED) {
+ if (topLevelPtr->flags & TK_EMBEDDED &&
+ (displayFocusPtr->focusWinPtr == NULL)) {
/*
* We are assigning focus to an embedded toplevel. The platform
diff --git a/generic/tkFont.c b/generic/tkFont.c
index cc7861f..44e2aad 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -13,7 +13,9 @@
#include "tkInt.h"
#include "tkFont.h"
-
+#if defined(MAC_OSX_TK)
+#include "tkMacOSXInt.h"
+#endif
/*
* The following structure is used to keep track of all the fonts that exist
* in the current application. It must be stored in the TkMainInfo for the
@@ -873,7 +875,18 @@ TheWorldHasChanged(
ClientData clientData) /* Info about application's fonts. */
{
TkFontInfo *fiPtr = clientData;
+#if defined(MAC_OSX_TK)
+
+ /*
+ * On macOS it is catastrophic to recompute all widgets while the
+ * [NSView drawRect] method is drawing. The best that we can do in
+ * that situation is to abort the recomputation and hope for the best.
+ */
+ if (TkpAppIsDrawing()) {
+ return;
+ }
+#endif
fiPtr->updatePending = 0;
RecomputeWidgets(fiPtr->mainPtr->winPtr);
}
diff --git a/generic/ttk/ttkButton.c b/generic/ttk/ttkButton.c
index d05a514..47e704c 100644
--- a/generic/ttk/ttkButton.c
+++ b/generic/ttk/ttkButton.c
@@ -84,8 +84,9 @@ static Tk_OptionSpec BaseOptionSpecs[] =
* Compound base/image options
*/
{TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
- "none", offsetof(Base,base.compoundObj), -1,
- 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
+ NULL, offsetof(Base,base.compoundObj), -1,
+ TK_OPTION_NULL_OK,(ClientData)ttkCompoundStrings,
+ GEOMETRY_CHANGED },
{TK_OPTION_STRING, "-padding", "padding", "Pad",
NULL, offsetof(Base,base.paddingObj), -1,
TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED},
diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c
index 159a88d..e167374 100644
--- a/generic/ttk/ttkNotebook.c
+++ b/generic/ttk/ttkNotebook.c
@@ -65,8 +65,8 @@ static Tk_OptionSpec TabOptionSpecs[] =
{TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/,
offsetof(Tab,imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
{TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
- "none", offsetof(Tab,compoundObj), -1,
- 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
+ NULL, offsetof(Tab,compoundObj), -1,
+ TK_OPTION_NULL_OK,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
{TK_OPTION_INT, "-underline", "underline", "Underline", "-1",
offsetof(Tab,underlineObj), -1, 0,0,GEOMETRY_CHANGED },
{TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 }
diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c
index 5e5c2f6..a11389b 100644
--- a/generic/ttk/ttkTreeview.c
+++ b/generic/ttk/ttkTreeview.c
@@ -2886,28 +2886,8 @@ static int TreeviewDragCommand(
TreeColumn *c = tv->tree.displayColumns[i];
int right = left + c->width;
if (c == column) {
- /* The limit not to exceed at the right is given by the tree width
- minus the sum of the min widths of the columns at the right of
- the one being resized (and don't forget possible x scrolling!).
- For stretchable columns, this min width really is the minWidth,
- for non-stretchable columns, this is the column width.
- */
- int newxRightLimit = tv->tree.treeArea.x - tv->tree.xscroll.first
- + tv->tree.treeArea.width;
- int j = i + 1;
- while (j < tv->tree.nDisplayColumns) {
- TreeColumn *cr = tv->tree.displayColumns[j];
- if (cr->stretch) {
- newxRightLimit -= cr->minWidth;
- } else {
- newxRightLimit -= cr->width;
- }
- ++j;
- }
- if (newx <= newxRightLimit) {
- DragColumn(tv, i, newx - right);
- TtkRedisplayWidget(&tv->core);
- }
+ DragColumn(tv, i, newx - right);
+ TtkRedisplayWidget(&tv->core);
return TCL_OK;
}
left = right;
diff --git a/library/demos/unicodeout.tcl b/library/demos/unicodeout.tcl
index 9cd3661..25ee932 100644
--- a/library/demos/unicodeout.tcl
+++ b/library/demos/unicodeout.tcl
@@ -131,8 +131,13 @@ addSample $w Japanese \
addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00"
addSample $w Russian \
"\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A"
-addSample $w Emoji \
- "\U1F600\U1F4A9\U1F44D\U1F1F3\U1F1F1"
+if {[package vsatisfies [package provide Tcl] 8.7-]} {
+ addSample $w Emoji \
+ "\U1F600\U1F4A9\U1F44D\U1F1F3\U1F1F1"
+} elseif {([tk windowingsystem] ne "x11") || (![catch {tk::pkgconfig get fontsystem} fs] && ($fs eq "xft"))} {
+ addSample $w Emoji \
+ "\uD83D\uDE00\uD83D\uDCA9\uD83D\uDC4D\uD83C\uDDF3\uD83C\uDDF1"
+}
## We're done processing, so change things back to normal running...
destroy $w.wait
diff --git a/library/entry.tcl b/library/entry.tcl
index 0cc9ffb..2aab934 100644
--- a/library/entry.tcl
+++ b/library/entry.tcl
@@ -74,11 +74,6 @@ bind Entry <<TraverseIn>> {
# Standard Motif bindings:
-bind Entry <Map> {
- if {[tk windowingsystem] eq "aqua"} {
- ::tk::RegisterServiceWidget %W
- }
-}
bind Entry <1> {
tk::EntryButton1 %W %x
%W selection clear
@@ -277,6 +272,25 @@ bind Entry <Meta-Delete> {
}
}
+# Bindings for IME text input and accents.
+
+bind Entry <<TkStartIMEMarkedText>> {
+ dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
+}
+bind Entry <<TkEndIMEMarkedText>> {
+ if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } {
+ bell
+ } else {
+ %W selection range $mark insert
+ }
+}
+bind Entry <<TkClearIMEMarkedText>> {
+ %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert]
+}
+bind Entry <<TkAccentBackspace>> {
+ tk::EntryBackspace %W
+}
+
# A few additional bindings of my own.
bind Entry <2> {
diff --git a/library/iconlist.tcl b/library/iconlist.tcl
index 2095ad6..753f183 100644
--- a/library/iconlist.tcl
+++ b/library/iconlist.tcl
@@ -447,10 +447,10 @@ package require Tk 8.6
bind $canvas <Shift-B1-Motion> [namespace code {my ShiftMotion1 %x %y}]
if {[tk windowingsystem] eq "aqua"} {
- bind $canvas <Shift-MouseWheel> [namespace code {my MouseWheel [expr {40 * (%W)}]}]
- bind $canvas <Option-Shift-MouseWheel> [namespace code {my MouseWheel [expr {400 * (%W)}]}]
+ bind $canvas <Shift-MouseWheel> [namespace code {my MouseWheel [expr {40 * (%D)}]}]
+ bind $canvas <Option-Shift-MouseWheel> [namespace code {my MouseWheel [expr {400 * (%D)}]}]
} else {
- bind $canvas <Shift-MouseWheel> [namespace code {my MouseWheel %W}]
+ bind $canvas <Shift-MouseWheel> [namespace code {my MouseWheel %D}]
}
if {[tk windowingsystem] eq "x11"} {
bind $canvas <Shift-4> [namespace code {my MouseWheel 120}]
diff --git a/library/listbox.tcl b/library/listbox.tcl
index f057151..3802223 100644
--- a/library/listbox.tcl
+++ b/library/listbox.tcl
@@ -204,14 +204,14 @@ if {[tk windowingsystem] eq "aqua"} {
if {%D >= 0} {
%W yview scroll [expr {-%D/30}] units
} else {
- %W yview scroll [expr {29-%D/30}] units
+ %W yview scroll [expr {(29-%D)/30}] units
}
}
bind Listbox <Shift-MouseWheel> {
if {%D >= 0} {
%W xview scroll [expr {-%D/30}] units
} else {
- %W xview scroll [expr {29-%D/30}] units
+ %W xview scroll [expr {(29-%D)/30}] units
}
}
}
diff --git a/library/text.tcl b/library/text.tcl
index ddc0490..96ab6d2 100644
--- a/library/text.tcl
+++ b/library/text.tcl
@@ -42,12 +42,6 @@
# Standard Motif bindings:
-bind Text <Map> {
- if {[tk windowingsystem] eq "aqua"} {
- ::tk::RegisterServiceWidget %W
- }
-}
-
bind Text <1> {
tk::TextButton1 %W %x %y
%W tag remove sel 0.0 end
@@ -397,6 +391,26 @@ bind Text <Meta-Delete> {
}
}
+# Bindings for IME text input.
+
+bind Text <<TkStartIMEMarkedText>> {
+ dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
+}
+bind Text <<TkEndIMEMarkedText>> {
+ if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } {
+ bell
+ } else {
+ %W tag add IMEmarkedtext $mark insert
+ %W tag configure IMEmarkedtext -underline on
+ }
+}
+bind Text <<TkClearIMEMarkedText>> {
+ %W delete IMEmarkedtext.first IMEmarkedtext.last
+}
+bind Text <<TkAccentBackspace>> {
+ %W delete insert-1c
+}
+
# Macintosh only bindings:
if {[tk windowingsystem] eq "aqua"} {
@@ -1223,7 +1237,6 @@ proc ::tk::TextScanDrag {w x y} {
$w scan dragto $x $y
}
}
-
# ::tk::TextUndoRedoProcessMarks --
#
# This proc is executed after an undo or redo action.
diff --git a/library/tk.tcl b/library/tk.tcl
index fcc987d..75574ca 100644
--- a/library/tk.tcl
+++ b/library/tk.tcl
@@ -687,11 +687,6 @@ if {[tk windowingsystem] eq "aqua"} {
if {[tk windowingsystem] eq "aqua"} {
- #register to send data to macOS Services
- proc ::tk::RegisterServiceWidget {w} {
- ::tk::mac::registerServiceWidget $w
- }
-
#stub procedures to respond to "do script" Apple Events
proc ::tk::mac::DoScriptFile {file} {
source $file
@@ -701,7 +696,10 @@ if {[tk windowingsystem] eq "aqua"} {
}
}
+# Create a dictionary to store the starting index of the IME marked
+# text in an Entry or Text widget.
+set ::tk::Priv(IMETextMark) [dict create]
# Run the Ttk themed widget set initialization
if {$::ttk::library ne ""} {
diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl
index 15e13ce..8bba226 100644
--- a/library/ttk/aquaTheme.tcl
+++ b/library/ttk/aquaTheme.tcl
@@ -9,8 +9,8 @@ namespace eval ttk::theme::aqua {
-font TkDefaultFont \
-background systemWindowBackgroundColor \
-foreground systemLabelColor \
- -selectbackground systemHighlight \
- -selectforeground systemLabelColor \
+ -selectbackground systemSelectedTextBackgroundColor \
+ -selectforeground systemSelectedTextColor \
-selectborderwidth 0 \
-insertwidth 1
@@ -38,7 +38,18 @@ namespace eval ttk::theme::aqua {
# Entry
ttk::style configure TEntry \
-foreground systemTextColor \
- -background systemTextBackgroundColor \
+ -background systemTextBackgroundColor
+ ttk::style map TEntry \
+ -foreground {
+ disabled systemDisabledControlTextColor
+ } \
+ -selectforeground {
+ background systemTextColor
+ } \
+ -selectbackground {
+ background systemTextBackgroundColor
+ }
+
# Workaround for #1100117:
# Actually, on Aqua we probably shouldn't stipple images in
@@ -59,20 +70,16 @@ namespace eval ttk::theme::aqua {
# Combobox:
ttk::style configure TCombobox \
-foreground systemTextColor \
- -background systemTransparent \
- -selectforeground systemSelectedTextColor \
- -selectbackground systemSelectedTextBackgroundColor
+ -background systemTransparent
ttk::style map TCombobox \
-foreground {
disabled systemDisabledControlTextColor
} \
-selectforeground {
- !active systemTextColor
+ background systemTextColor
} \
-selectbackground {
- !active systemTextBackgroundColor
- !focus systemTextBackgroundColor
- focus systemSelectedTextBackgroundColor
+ background systemTransparent
}
# Spinbox
diff --git a/library/ttk/entry.tcl b/library/ttk/entry.tcl
index 471df28..e2920a0 100644
--- a/library/ttk/entry.tcl
+++ b/library/ttk/entry.tcl
@@ -58,13 +58,6 @@ option add *TEntry.cursor [ttk::cursor text] widgetDefault
# and I'll put it back.
#
-##Bindings to register with macOS Services API.
-bind T.Entry <Map> {
- if {[tk windowingsystem] eq "aqua"} {
- ::tk::RegisterServiceWidget %W
- }
-}
-
## Clipboard events:
#
bind TEntry <<Cut>> { ttk::entry::Cut %W }
@@ -152,6 +145,25 @@ bind TEntry <Control-d> { ttk::entry::Delete %W }
bind TEntry <Control-h> { ttk::entry::Backspace %W }
bind TEntry <Control-k> { %W delete insert end }
+# Bindings for IME text input.
+
+bind TEntry <<TkStartIMEMarkedText>> {
+ dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
+}
+bind TEntry <<TkEndIMEMarkedText>> {
+ if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } {
+ bell
+ } else {
+ %W selection range $mark insert
+ }
+}
+bind TEntry <<TkClearIMEMarkedText>> {
+ %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert]
+}
+bind TEntry <<TkAccentBackspace>> {
+ ttk::entry::Backspace %W
+}
+
### Clipboard procedures.
#
diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl
index 39273ed..ebf1451 100644
--- a/library/ttk/treeview.tcl
+++ b/library/ttk/treeview.tcl
@@ -121,7 +121,17 @@ proc ttk::treeview::ActivateHeading {w heading} {
if {$w != $State(activeWidget) || $heading != $State(activeHeading)} {
if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} {
- $State(activeWidget) heading $State(activeHeading) state !active
+ # It may happen that $State(activeHeading) no longer corresponds
+ # to an existing display column. This happens for instance when
+ # changing -displaycolumns in a bound script when this change
+ # triggers a <Leave> event. A proc checking if the display column
+ # $State(activeHeading) is really still present or not could be
+ # written but it would need to check several special cases:
+ # a. -displaycolumns "#all" or being an explicit columns list
+ # b. column #0 display is not governed by the -displaycolumn
+ # list but by the value of the -show option
+ # --> Let's rather catch the following line.
+ catch {$State(activeWidget) heading $State(activeHeading) state !active}
}
if {$heading != {}} {
$w heading $heading state active
diff --git a/macosx/README b/macosx/README
index c2dabae..4989ec7 100644
--- a/macosx/README
+++ b/macosx/README
@@ -49,8 +49,8 @@ brings up the Tk console window at startup. This is the case when double
clicking Wish in the Finder (or using 'open Wish.app' from the Terminal).
- Tcl extensions can be installed in any of:
- $HOME/Library/Tcl /Library/Tcl /System/Library/Tcl
- $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
+ $HOME/Library/Tcl /Library/Tcl
+ $HOME/Library/Frameworks /Library/Frameworks
(searched in that order).
Given a potential package directory $pkg, Tcl on OSX checks for the file
$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
@@ -65,7 +65,7 @@ No nroff manpages are installed by default by the GNUmakefile.
- The Tcl and Tk frameworks can be installed in any of the system's standard
framework directories:
- $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
+ $HOME/Library/Frameworks /Library/Frameworks
- ${prefix}/bin/wish8.x is a script that calls a copy of 'Wish' contained in
Tk.framework/Resources
diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c
index 452b32f..6717afa 100644
--- a/macosx/tkMacOSXClipboard.c
+++ b/macosx/tkMacOSXClipboard.c
@@ -130,6 +130,7 @@ TkSelGetSelection(
&& selection == dispPtr->clipboardAtom
&& (target == XA_STRING || target == dispPtr->utf8Atom)) {
NSString *string = nil;
+ NSString *clean;
NSPasteboard *pb = [NSPasteboard generalPasteboard];
NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject:
NSStringPboardType]];
@@ -137,7 +138,27 @@ TkSelGetSelection(
if (type) {
string = [pb stringForType:type];
}
- result = proc(clientData, interp, string ? [string UTF8String] : "");
+ if (string) {
+ /*
+ * Replace all non-BMP characters by the replacement character 0xfffd.
+ * This is a workaround until Tcl supports TCL_UTF_MAX > 3.
+ */
+ int i, j, len = [string length];
+ CFRange all = CFRangeMake(0, len);
+ UniChar *buffer = ckalloc(len*sizeof(UniChar));
+ CFStringGetCharacters((CFStringRef) string, all, buffer);
+ for (i = 0, j = 0 ; j < len ; i++, j++) {
+ if (CFStringIsSurrogateHighCharacter(buffer[j])) {
+ buffer[i] = 0xfffd;
+ j++;
+ } else {
+ buffer[i] = buffer[j];
+ }
+ }
+ clean = (NSString *)CFStringCreateWithCharacters(NULL, buffer, i);
+ ckfree(buffer);
+ result = proc(clientData, interp, [clean UTF8String]);
+ }
} else {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s selection doesn't exist or form \"%s\" not defined",
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index af0cc05..724f637 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -501,9 +501,12 @@ TkMacOSXGetNSImageWithTkImage(
int width,
int height)
{
- Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
+ Pixmap pixmap;
NSImage *nsImage;
-
+ if (width == 0 || height == 0) {
+ return nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0,0)];
+ }
+ pixmap = Tk_GetPixmap(display, None, width, height, 0);
Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
nsImage = CreateNSImageWithPixmap(pixmap, width, height);
Tk_FreePixmap(display, pixmap);
@@ -1611,16 +1614,36 @@ TkMacOSXSetupDrawingContext(
* a view's drawRect or setFrame methods. The isDrawing attribute
* tells us whether we are being called from one of those methods.
*
- * If the CGContext is not valid, or belongs to a different View, then
- * we mark our view as needing display and return failure. It should
- * get drawn in a later call to drawRect.
+ * If the CGContext is not valid then we mark our view as needing
+ * display in the bounding rectangle of the clipping region and
+ * return failure. That rectangle should get drawn in a later call
+ * to drawRect.
+ *
+ * As an exception to the above, if mouse buttons are pressed at the
+ * moment when we fail to obtain a valid context we schedule the entire
+ * view for a redraw rather than just the clipping region. The purpose
+ * of this is to make sure that scrollbars get updated correctly.
*/
- if (view != [NSView focusView]) {
- [view setNeedsDisplay:YES];
+ if (![NSApp isDrawing] || view != [NSView focusView]) {
+ NSRect bounds = [view bounds];
+ NSRect dirtyNS = bounds;
+ if ([NSEvent pressedMouseButtons]) {
+ [view setNeedsDisplay:YES];
+ } else {
+ CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
+ .ty = dirtyNS.size.height};
+ if (dc.clipRgn) {
+ CGRect dirtyCG = NSRectToCGRect(dirtyNS);
+ HIShapeGetBounds(dc.clipRgn, &dirtyCG);
+ dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
+ }
+ [view setNeedsDisplayInRect:dirtyNS];
+ }
canDraw = false;
goto end;
}
+
dc.view = view;
dc.context = GET_CGCONTEXT;
dc.portBounds = NSRectToCGRect([view bounds]);
diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c
index 7659163..41da390 100644
--- a/macosx/tkMacOSXFont.c
+++ b/macosx/tkMacOSXFont.c
@@ -128,11 +128,11 @@ GetTkFontAttributesForNSFont(
{
NSFontTraitMask traits = [[NSFontManager sharedFontManager]
traitsOfFont:nsFont];
-
faPtr->family = Tk_GetUid([[nsFont familyName] UTF8String]);
faPtr->size = [nsFont pointSize];
faPtr->weight = (traits & NSBoldFontMask ? TK_FW_BOLD : TK_FW_NORMAL);
faPtr->slant = (traits & NSItalicFontMask ? TK_FS_ITALIC : TK_FS_ROMAN);
+
}
/*
@@ -176,6 +176,18 @@ FindNSFont(
size = [defaultFont pointSize];
}
nsFont = [fm fontWithFamily:family traits:traits weight:weight size:size];
+
+ /*
+ * A second bug in NSFontManager that Apple created for the Catalina OS
+ * causes requests as above to sometimes return fonts with additional
+ * traits that were not requested, even though fonts without those unwanted
+ * traits exist on the system. See bug [90d555e088]. As a workaround
+ * we ask the font manager to remove any unrequested traits.
+ */
+
+ if (nsFont) {
+ nsFont = [fm convertFont:nsFont toNotHaveTrait:~traits];
+ }
if (!nsFont) {
NSArray *availableFamilies = [fm availableFontFamilies];
NSString *caseFamily = nil;
@@ -394,10 +406,25 @@ TkpFontPkgInit(
systemFont++;
}
TkInitFontAttributes(&fa);
+#if 0
+
+ /*
+ * In macOS 10.15.1 Apple introduced a bug in NSFontManager which caused
+ * it to not recognize the familyName ".SF NSMono" which is the familyName
+ * of the default fixed pitch system fault on that system. See bug [855049e799].
+ * As a workaround we call [NSFont userFixedPitchFontOfSize:11] instead.
+ * This returns a user font in the "Menlo" family.
+ */
+
nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);
+#else
+ nsFont = [NSFont userFixedPitchFontOfSize:11];
+#endif
if (nsFont) {
GetTkFontAttributesForNSFont(nsFont, &fa);
+#if 0
CFRelease(nsFont);
+#endif
} else {
fa.family = Tk_GetUid("Monaco");
fa.size = 11;
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index a787e13..3d15442 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -413,8 +413,7 @@ TkpInit(
/*
* Initialize the NSServices object here. Apple's docs say to do this
* in applicationDidFinishLaunching, but the Tcl interpreter is not
- * initialized until this function call. Only the main interpreter
- * is allowed to provide services.
+ * initialized until this function call.
*/
TkMacOSXServices_Init(interp);
@@ -435,9 +434,6 @@ TkpInit(
TkMacOSXIconBitmapObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath",
TkMacOSXGetAppPathCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "::tk::mac::registerServiceWidget",
- TkMacOSXRegisterServiceWidgetObjCmd, NULL, NULL);
-
return TCL_OK;
}
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index b1c1689..e3aed98 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -7,7 +7,7 @@
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2012 Adrian Robert.
- * Copyright 2015 Marc Culler.
+ * Copyright 2015-2019 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -31,13 +31,12 @@ static NSWindow *keyboardGrabNSWindow = nil;
* window. */
static NSModalSession modalSession = nil;
static BOOL processingCompose = NO;
-static BOOL finishedCompose = NO;
+static Tk_Window composeWin = NULL;
static int caret_x = 0, caret_y = 0, caret_height = 0;
-static void setupXEvent(XEvent *xEvent, NSWindow *w,
- unsigned int state);
-static unsigned isFunctionKey(unsigned int code);
+static unsigned short releaseCode;
-unsigned short releaseCode;
+static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state);
+static unsigned isFunctionKey(unsigned int code);
#pragma mark TKApplication(TKKeyEvent)
@@ -137,9 +136,9 @@ unsigned short releaseCode;
}
/*
- * Events are only received for the front Window on the Macintosh. So
+ * Key events are only received for the front Window on the Macintosh. So
* to build an XEvent we look up the Tk window associated to the Front
- * window. If a different window has a local grab we ignore the event.
+ * window.
*/
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
@@ -148,11 +147,18 @@ unsigned short releaseCode;
if (tkwin) {
TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
- if (grabWinPtr
- && grabWinPtr != winPtr
- && !winPtr->dispPtr->grabFlags /* this means the grab is local. */
- && grabWinPtr->mainPtr == winPtr->mainPtr) {
- return theEvent;
+ /*
+ * If a local grab is in effect, key events for windows in the
+ * grabber's application are redirected to the grabber. Key events
+ * for other applications are delivered normally. If a global
+ * grab is in effect all key events are redirected to the grabber.
+ */
+
+ if (grabWinPtr) {
+ if (winPtr->dispPtr->grabFlags || /* global grab */
+ grabWinPtr->mainPtr == winPtr->mainPtr){ /* same appl. */
+ tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ }
}
} else {
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
@@ -202,18 +208,6 @@ unsigned short releaseCode;
xEvent.xany.type = KeyPress;
}
- /*
- * For command key, take input manager's word so things like
- * dvorak / qwerty layout work.
- */
-
- if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask
- && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask
- && len > 0 && !isFunctionKey(code)) {
- // head off keycode-based translation in tkMacOSXKeyboard.c
- xEvent.xkey.nbytes = [characters length]; //len
- }
-
if ([characters length] > 0) {
xEvent.xkey.keycode = (keyCode << 16) |
(UInt16) [characters characterAtIndex:0];
@@ -235,7 +229,7 @@ unsigned short releaseCode;
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
savedModifiers = modifiers;
return theEvent;
- } /* if send straight to TK */
+ } /* if this is a function key or has modifiers */
} /* if not processing compose */
if (type == NSKeyDown) {
@@ -243,12 +237,29 @@ unsigned short releaseCode;
TKLog(@"keyDown: %s compose sequence.\n",
processingCompose == YES ? "Continue" : "Begin");
}
- processingCompose = YES;
- [nsEvArray addObject: theEvent];
- [[w contentView] interpretKeyEvents: nsEvArray];
- [nsEvArray removeObject: theEvent];
- }
+ /*
+ * Call the interpretKeyEvents method to interpret composition key
+ * strokes. When it detects a complete composition sequence it will
+ * call our implementation of insertText: replacementRange, which
+ * generates a key down XEvent with the appropriate character. In IME
+ * when multiple characters have the same composition sequence and the
+ * chosen character is not the default it may be necessary to hit the
+ * enter key multiple times before the character is accepted and
+ * rendered. We send enter key events until inputText has cleared
+ * the processingCompose flag.
+ */
+
+ processingCompose = YES;
+ while(processingCompose) {
+ [nsEvArray addObject: theEvent];
+ [[w contentView] interpretKeyEvents: nsEvArray];
+ [nsEvArray removeObject: theEvent];
+ if ([theEvent keyCode] != 36) {
+ break;
+ }
+ }
+ }
savedModifiers = modifiers;
return theEvent;
}
@@ -265,25 +276,34 @@ unsigned short releaseCode;
return self;
}
-/* <NSTextInput> implementation (called through interpretKeyEvents:]). */
+/*
+ * Implementation of the NSTextInputClient protocol.
+ */
-/* <NSTextInput>: called when done composing;
- NOTE: also called when we delete over working text, followed immed.
- by doCommandBySelector: deleteBackward: */
+/* [NSTextInputClient inputText: replacementRange:] is called by
+ * interpretKeyEvents when a composition sequence is complete. It is also
+ * called when we delete over working text. In that case the call is followed
+ * immediately by doCommandBySelector: deleteBackward:
+ */
- (void)insertText: (id)aString
+ replacementRange: (NSRange)repRange
{
- int i, len = [(NSString *) aString length];
+ int i, len;
XEvent xEvent;
+ NSString *str;
+
+ str = ([aString isKindOfClass: [NSAttributedString class]]) ?
+ [aString string] : aString;
+ len = [str length];
if (NS_KEYLOG) {
TKLog(@"insertText '%@'\tlen = %d", aString, len);
}
processingCompose = NO;
- finishedCompose = YES;
/*
- * First, clear any working text.
+ * Clear any working text.
*/
if (privateWorkingText != nil) {
@@ -291,32 +311,104 @@ unsigned short releaseCode;
}
/*
- * Now insert the string as keystrokes.
+ * Insert the string as a sequence of keystrokes.
*/
setupXEvent(&xEvent, [self window], 0);
xEvent.xany.type = KeyPress;
- for (i =0; i<len; i++) {
- xEvent.xkey.keycode = (UInt16) [aString characterAtIndex: i];
- [[aString substringWithRange: NSMakeRange(i,1)]
- getCString: xEvent.xkey.trans_chars
- maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
- xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
+ /*
+ * Apple evidently sets location to 0 to signal that an accented letter has
+ * been selected from the accent menu. An unaccented letter has already
+ * been displayed and we need to erase it before displaying the accented
+ * letter.
+ */
+
+ if (repRange.location == 0) {
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
+ }
+
+ /*
+ * NSString represents a non-BMP character as a string of length 2 where
+ * the first character is the high surrogate and the second character is
+ * the low surrogate. We could record this in the XEvent by setting the
+ * keycode to the unicode code point and setting the trans_chars to the
+ * 4-byte UTF-8 string. However, that will not help as long as TCL_UTF_MAX
+ * is set to 3. Until that changes, we just replace non-BMP characters by
+ * the "replacement character" U+FFFD.
+ */
+
+ for (i = 0; i < len; i++) {
+ UniChar nextChar = [str characterAtIndex: i];
+ if (CFStringIsSurrogateHighCharacter(nextChar)) {
+#if 0
+ UniChar lowChar = [str characterAtIndex: ++i];
+ xEvent.xkey.keycode = CFStringGetLongCharacterForSurrogatePair(
+ nextChar, lowChar);
+ xEvent.xkey.nbytes = TkUniCharToUtf(xEvent.xkey.keycode,
+ &xEvent.xkey.trans_chars);
+#else
+ i++;
+ xEvent.xkey.keycode = 0xfffd;
+ strcpy(xEvent.xkey.trans_chars, "\xef\xbf\xbd");
+ xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
+#endif
+ } else {
+ xEvent.xkey.keycode = (int) nextChar;
+ [[str substringWithRange: NSMakeRange(i,1)]
+ getCString: xEvent.xkey.trans_chars
+ maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
+ xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
+ }
xEvent.xany.type = KeyPress;
- releaseCode = (UInt16) [aString characterAtIndex: 0];
+ releaseCode = (UInt16) nextChar;
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
}
- releaseCode = (UInt16) [aString characterAtIndex: 0];
+ releaseCode = (UInt16) [str characterAtIndex: 0];
+}
+
+/*
+ * This required method is allowed to return nil.
+ */
+
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange
+ actualRange:(NSRangePointer)thePointer
+{
+ return nil;
}
+/*
+ * This method is supposed to insert (or replace selected text with) the string
+ * argument. If the argument is an NSString, it should be displayed with a
+ * distinguishing appearance, e.g underlined.
+ */
-/* <NSTextInput>: inserts display of composing characters */
-- (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
+- (void)setMarkedText: (id)aString
+ selectedRange: (NSRange)selRange
+ replacementRange: (NSRange)repRange
{
- NSString *str = [aString respondsToSelector: @selector (string)] ?
- [aString string] : aString;
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ NSString *temp;
+ NSString *str;
+
+ str = ([aString isKindOfClass: [NSAttributedString class]]) ?
+ [aString string] : aString;
+
+ if (focusWin) {
+
+ /*
+ * Remember the widget where the composition is happening, in case it
+ * gets defocussed during the composition.
+ */
+
+ composeWin = focusWin;
+ } else {
+ return;
+ }
if (NS_KEYLOG) {
TKLog(@"setMarkedText '%@' len =%lu range %lu from %lu", str,
(unsigned long) [str length], (unsigned long) selRange.length,
@@ -326,17 +418,23 @@ unsigned short releaseCode;
if (privateWorkingText != nil) {
[self deleteWorkingText];
}
+
if ([str length] == 0) {
return;
}
- processingCompose = YES;
- privateWorkingText = [str copy];
+ /*
+ * Use our insertText method to display the marked text.
+ */
- //PENDING: insert workingText underlined
+ TkSendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
+ temp = [str copy];
+ [self insertText: temp replacementRange:repRange];
+ privateWorkingText = temp;
+ processingCompose = YES;
+ TkSendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
}
-
- (BOOL)hasMarkedText
{
return privateWorkingText != nil;
@@ -355,23 +453,35 @@ unsigned short releaseCode;
return rng;
}
+- (void)cancelComposingText
+{
+ if (NS_KEYLOG) {
+ TKLog(@"cancelComposingText");
+ }
+ [self deleteWorkingText];
+ processingCompose = NO;
+}
- (void)unmarkText
{
if (NS_KEYLOG) {
- TKLog(@"unmark (accept) text");
+ TKLog(@"unmarkText");
}
[self deleteWorkingText];
processingCompose = NO;
}
-/* used to position char selection windows, etc. */
+/*
+ * Called by the system to get a position for popup character selection windows
+ * such as a Character Palette, or a selection menu for IME.
+ */
+
- (NSRect)firstRectForCharacterRange: (NSRange)theRange
+ actualRange: (NSRangePointer)thePointer
{
NSRect rect;
NSPoint pt;
-
pt.x = caret_x;
pt.y = caret_y;
@@ -380,18 +490,16 @@ unsigned short releaseCode;
pt.y -= caret_height;
rect.origin = pt;
- rect.size.width = caret_height;
+ rect.size.width = 0;
rect.size.height = caret_height;
return rect;
}
-
- (NSInteger)conversationIdentifier
{
return (NSInteger) self;
}
-
- (void)doCommandBySelector: (SEL)aSelector
{
if (NS_KEYLOG) {
@@ -399,54 +507,41 @@ unsigned short releaseCode;
}
processingCompose = NO;
if (aSelector == @selector (deleteBackward:)) {
- /*
- * Happens when user backspaces over an ongoing composition:
- * throw a 'delete' into the event queue.
- */
-
- XEvent xEvent;
-
- setupXEvent(&xEvent, [self window], 0);
- xEvent.xany.type = KeyPress;
- xEvent.xkey.nbytes = 1;
- xEvent.xkey.keycode = (0x33 << 16) | 0x7F;
- xEvent.xkey.trans_chars[0] = 0x7F;
- xEvent.xkey.trans_chars[1] = 0x0;
- Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
}
}
-
- (NSArray *)validAttributesForMarkedText
{
static NSArray *arr = nil;
-
if (arr == nil) {
- arr = [NSArray new];
+ arr = [[NSArray alloc] initWithObjects:
+ NSUnderlineStyleAttributeName,
+ NSUnderlineColorAttributeName,
+ nil];
+ [arr retain];
}
- /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
return arr;
}
-
- (NSRange)selectedRange
{
if (NS_KEYLOG) {
TKLog(@"selectedRange request");
}
- return NSMakeRange(NSNotFound, 0);
+ return NSMakeRange(0, 0);
}
-
- (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
{
if (NS_KEYLOG) {
TKLog(@"characterIndexForPoint request");
}
- return 0;
+ return NSNotFound;
}
-
- (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
{
static NSAttributedString *str = nil;
@@ -458,34 +553,44 @@ unsigned short releaseCode;
}
return str;
}
-/* End <NSTextInput> impl. */
+/* End of NSTextInputClient implementation. */
@synthesize needsRedisplay = _needsRedisplay;
@end
@implementation TKContentView(TKKeyEvent)
-/* delete display of composing characters [not in <NSTextInput>] */
+
+/*
+ * Tell the widget to erase the displayed composing characters. This
+ * is not part of the NSTextInputClient protocol.
+ */
+
- (void)deleteWorkingText
{
if (privateWorkingText == nil) {
return;
- }
- if (NS_KEYLOG) {
- TKLog(@"deleteWorkingText len = %lu\n",
- (unsigned long)[privateWorkingText length]);
- }
- [privateWorkingText release];
- privateWorkingText = nil;
- processingCompose = NO;
+ } else {
- //PENDING: delete working text
+ if (NS_KEYLOG) {
+ TKLog(@"deleteWorkingText len = %lu\n",
+ (unsigned long)[privateWorkingText length]);
+ }
+
+ [privateWorkingText release];
+ privateWorkingText = nil;
+ processingCompose = NO;
+ if (composeWin) {
+ TkSendVirtualEvent(composeWin, "TkClearIMEMarkedText", NULL);
+ }
+ }
}
@end
/*
* Set up basic fields in xevent for keyboard input.
*/
+
static void
setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
{
@@ -498,17 +603,15 @@ setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
memset(xEvent, 0, sizeof(XEvent));
xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
- xEvent->xany.send_event = false;
xEvent->xany.display = Tk_Display(tkwin);
xEvent->xany.window = Tk_WindowId(tkwin);
xEvent->xkey.root = XRootWindow(Tk_Display(tkwin), 0);
- xEvent->xkey.subwindow = None;
xEvent->xkey.time = TkpGetMS();
xEvent->xkey.state = state;
xEvent->xkey.same_screen = true;
- xEvent->xkey.trans_chars[0] = 0;
- xEvent->xkey.nbytes = 0;
+ /* No need to initialize other fields implicitly here,
+ * because of the memset() above. */
}
#pragma mark -
diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c
index 3272657..e91dfe2 100644
--- a/macosx/tkMacOSXKeyboard.c
+++ b/macosx/tkMacOSXKeyboard.c
@@ -443,8 +443,11 @@ TkpGetString(
* result. */
{
(void) winPtr; /*unused*/
+ int ch;
+
Tcl_DStringInit(dsPtr);
- return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
+ return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars,
+ TkUtfToUniChar(eventPtr->xkey.trans_chars, &ch));
}
/*
@@ -717,7 +720,7 @@ TkpSetKeycodeAndState(
}
if (keysym <= LATIN1_MAX) {
- int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars);
+ int done = TkUniCharToUtf(keysym, eventPtr->xkey.trans_chars);
eventPtr->xkey.trans_chars[done] = 0;
} else {
@@ -803,7 +806,7 @@ TkpGetKeySym(
/* If nbytes has been set, it's not a function key, but a regular key that
has been translated in tkMacOSXKeyEvent.c; just use that. */
if (eventPtr->xkey.nbytes) {
- return eventPtr->xkey.keycode & 0xFFFF;
+ return eventPtr->xkey.keycode;
}
/*
diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c
index 99c1191..82bcda7 100644
--- a/macosx/tkMacOSXMenus.c
+++ b/macosx/tkMacOSXMenus.c
@@ -70,7 +70,7 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
[NSMenuItem itemWithTitle:
[NSString stringWithFormat:@"About %@", aboutName]
action:@selector(orderFrontStandardAboutPanel:)] atIndex:0];
- _defaultFileMenuItems =
+ _defaultFileMenuItems =
[[NSArray arrayWithObjects:
[NSMenuItem itemWithTitle:
[NSString stringWithFormat:@"Source%C", 0x2026]
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 89cdf1b..b18b4ef 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -130,7 +130,8 @@ enum {
}
/*
- * Make sure tkwin is the toplevel which should receive the event.
+ * If we still don't have a window, try using the toplevel that
+ * manages the NSWindow.
*/
if (!tkwin) {
@@ -138,10 +139,15 @@ enum {
tkwin = (Tk_Window) winPtr;
}
if (!tkwin) {
+
+ /*
+ * We can't find a window for this event. We have to ignore it.
+ */
+
#ifdef TK_MAC_DEBUG_EVENTS
TkMacOSXDbgMsg("tkwin == NULL");
#endif
- return theEvent; /* Give up. No window for this event. */
+ return theEvent;
}
/*
@@ -174,13 +180,25 @@ enum {
* coordinates.
*/
- local.x -= winPtr->wmInfoPtr->xInParent;
- local.y -= winPtr->wmInfoPtr->yInParent;
+ if (Tk_IsEmbedded(winPtr)) {
+ TkWindow *contPtr = TkpGetOtherWindow(winPtr);
+ if (Tk_IsTopLevel(contPtr)) {
+ local.x -= contPtr->wmInfoPtr->xInParent;
+ local.y -= contPtr->wmInfoPtr->yInParent;
+ } else {
+ TkWindow *topPtr = TkMacOSXGetHostToplevel(winPtr)->winPtr;
+ local.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);
+ local.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);
+ }
+ } else {
+ local.x -= winPtr->wmInfoPtr->xInParent;
+ local.y -= winPtr->wmInfoPtr->yInParent;
+ }
/*
- * Find the containing Tk window, and convert local into the coordinates
- * of the Tk window. (The converted local coordinates are only needed
- * for scrollwheel events.)
+ * Use the toplevel coordinates to find the containing Tk window. Then
+ * convert local into the coordinates of that window. (The converted
+ * local coordinates are only needed for scrollwheel events.)
*/
int win_x, win_y;
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index cb80dd8..7aa6840 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -340,7 +340,12 @@ VISIBILITY_HIDDEN
@end
VISIBILITY_HIDDEN
-@interface TKContentView : NSView <NSTextInput>
+/*
+ * Subclass TKContentView from NSTextInputClient to enable composition and
+ * input from the Character Palette.
+ */
+
+@interface TKContentView : NSView <NSTextInputClient>
{
@private
NSString *privateWorkingText;
@@ -354,13 +359,8 @@ VISIBILITY_HIDDEN
@end
@interface TKContentView(TKWindowEvent)
-- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIShapeRef) shape;
- (void) tkToolbarButton: (id) sender;
-- (BOOL) isOpaque;
-- (BOOL) wantsDefaultClipping;
-- (BOOL) acceptsFirstResponder;
-- (void) keyDown: (NSEvent *) theEvent;
@end
@interface NSWindow(TKWm)
diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c
index 66619c2..dff6cc9 100644
--- a/macosx/tkMacOSXScrlbr.c
+++ b/macosx/tkMacOSXScrlbr.c
@@ -214,12 +214,20 @@ static void drawMacScrollbar(
CGContextStrokeLineSegments(context, outer, 2);
/*
- * Do not display the thumb unless scrolling is possible.
+ * Do not display the thumb unless scrolling is possible, in accordance
+ * with macOS behavior.
+ *
+ * Native scrollbars and Ttk scrollbars are always 15 pixels wide, but we
+ * allow Tk scrollbars to have any width, even if it looks bad. To prevent
+ * sporadic assertion errors when drawing skinny thumbs we must make sure
+ * the radius is at most half the width.
*/
if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) {
CGRect thumbBounds = {thumbOrigin, thumbSize};
- path = CGPathCreateWithRoundedRect(thumbBounds, 4, 4, NULL);
+ int width = scrollPtr->vertical ? thumbSize.width : thumbSize.height;
+ int radius = width >= 8 ? 4 : width >> 1;
+ path = CGPathCreateWithRoundedRect(thumbBounds, radius, radius, NULL);
CGContextBeginPath(context);
CGContextAddPath(context, path);
if (msPtr->info.trackInfo.scrollbar.pressState != 0) {
diff --git a/macosx/tkMacOSXServices.c b/macosx/tkMacOSXServices.c
index f1e5951..e92158f 100644
--- a/macosx/tkMacOSXServices.c
+++ b/macosx/tkMacOSXServices.c
@@ -4,20 +4,18 @@
* This file allows the integration of Tk and the Cocoa NSServices API.
*
* Copyright (c) 2010-2019 Kevin Walzer/WordTech Communications LLC.
+ * Copyright (c) 2019 Marc Culler.
* Copyright (c) 2010 Adrian Robert.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include <CoreServices/CoreServices.h>
#include <tkInt.h>
#include <tkMacOSXInt.h>
-static Tcl_Interp *ServicesInterp;
-
/*
- * Event proc which calls the PerformService procedure
+ * Event proc which calls the PerformService procedure.
*/
static int
@@ -25,22 +23,28 @@ ServicesEventProc(
Tcl_Event *event,
int flags)
{
- Tcl_GlobalEval(ServicesInterp, "::tk::mac::PerformService");
+ TkMainInfo *info = TkGetMainInfoList();
+ Tcl_GlobalEval(info->interp, "::tk::mac::PerformService");
return 1;
}
/*
- * Class declarations for TkService class.
+ * The Wish application can send the current selection in the Tk clipboard
+ * to other applications which accept messages of type NSString. The TkService
+ * object provides this service via its provideService method. (The method
+ * must be specified in the application's Info.plist file for this to work.)
*/
-@interface TkService : NSView {
+@interface TkService : NSObject {
}
+ (void) initialize;
-- (void)provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error;
-- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType;
-- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types;
+- (void) provideService:(NSPasteboard *)pboard
+ userData:(NSString *)data
+ error:(NSString **)error;
+- (BOOL) writeSelectionToPasteboard:(NSPasteboard *)pboard
+ types:(NSArray *)types;
@end
@@ -57,32 +61,8 @@ ServicesEventProc(
return;
}
-
-- (id)validRequestorForSendType:(NSString *)sendType
- returnType:(NSString *)returnType
-{
- if ([sendType isEqualToString:@"NSStringPboardType"] ||
- [sendType isEqualToString:@"NSPasteboardTypeString"]) {
- return self;
- }
- return [super validRequestorForSendType:sendType returnType:returnType];
-}
-
-/*
- * Make sure the view accepts events.
- */
-
-- (BOOL)acceptsFirstResponder
-{
- return YES;
-}
-- (BOOL)becomeFirstResponder
-{
- return YES;
-}
-
/*
- * Get selected text, copy to pasteboard.
+ * Get the current Tk selection and copy it to the system pasteboard.
*/
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
@@ -90,6 +70,7 @@ ServicesEventProc(
{
NSArray *typesDeclared = nil;
NSString *pboardType = nil;
+ TkMainInfo *info = TkGetMainInfoList();
for (NSString *typeString in types) {
if ([typeString isEqualToString:@"NSStringPboardType"] ||
@@ -102,9 +83,9 @@ ServicesEventProc(
if (!typesDeclared) {
return NO;
}
- Tcl_Eval(ServicesInterp, "selection get");
+ Tcl_Eval(info->interp, "selection get");
- char *copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp));
+ char *copystring = Tcl_GetString(Tcl_GetObjResult(info->interp));
NSString *writestring = [NSString stringWithUTF8String:copystring];
[pboard declareTypes:typesDeclared owner:nil];
@@ -112,8 +93,8 @@ ServicesEventProc(
}
/*
- * This is the method that actually calls the Tk service; this is the method
- * that must be defined in info.plist.
+ * This is the method that actually calls the Tk service; it must be specified
+ * in Info.plist.
*/
- (void)provideService:(NSPasteboard *)pboard
@@ -125,8 +106,8 @@ ServicesEventProc(
Tcl_Event *event;
/*
- * Get string from private pasteboard, write to general pasteboard to make
- * available to Tcl service.
+ * Get a string from the private pasteboard and copy it to the general
+ * pasteboard to make it available to other applications.
*/
for (NSString *typeString in types) {
@@ -150,69 +131,9 @@ ServicesEventProc(
@end
/*
- * Register a specific widget to access the Services menu.
- */
-
-int
-TkMacOSXRegisterServiceWidgetObjCmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const objv[])
-{
- /*
- * Need proper number of args.
- */
-
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "path?");
- return TCL_ERROR;
- }
- /*
- * Get the object that holds this Tk Window...
- */
-
- Rect bounds;
- NSRect frame;
- Tk_Window path = Tk_NameToWindow(interp,
- Tcl_GetString(objv[1]), Tk_MainWindow(interp));
-
- if (path == NULL) {
- return TCL_ERROR;
- }
-
- Tk_MakeWindowExist(path);
- Tk_MapWindow(path);
- Drawable d = Tk_WindowId(path);
-
- /*
- * Get NSView from Tk window and add subview.
- */
-
- TkService *serviceview = [[TkService alloc] init];
- NSView *view = TkMacOSXGetRootControl(d);
-
- if ([serviceview superview] != view) {
- [view addSubview:serviceview];
- }
- TkMacOSXWinBounds((TkWindow*)path, &bounds);
-
- /*
- * Hack to make sure subview is set to take up entire geometry of window.
- */
-
- frame = NSMakeRect(bounds.left, bounds.top, 100000, 100000);
- frame.origin.y = 0;
- if (!NSEqualRects(frame, [serviceview frame])) {
- [serviceview setFrame:frame];
- }
- [serviceview release];
- return TCL_OK;
-}
-
-/*
- * Initalize the package in the Tcl interpreter, create Tcl commands.
+ * Instantiate a TkService object and register it with the NSApplication.
+ * This is called exactly one time from TkpInit.
*/
int
@@ -220,12 +141,10 @@ TkMacOSXServices_Init(
Tcl_Interp *interp)
{
/*
- * Initialize instance of TclServices to provide service functionality.
+ * Initialize an instance of TkService and register it with the NSApp.
*/
TkService *service = [[TkService alloc] init];
-
- ServicesInterp = interp;
[NSApp setServicesProvider:service];
return TCL_OK;
}
diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c
index 09736e6..c353efe 100644
--- a/macosx/tkMacOSXTest.c
+++ b/macosx/tkMacOSXTest.c
@@ -161,7 +161,7 @@ PressButtonObjCmd(
if (screens && [screens count]) {
ScreenHeight = [[screens objectAtIndex:0] frame].size.height;
}
-
+
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "x y");
return TCL_ERROR;
@@ -186,34 +186,34 @@ PressButtonObjCmd(
loc.y = ScreenHeight - y;
wNum = 0;
CGWarpMouseCursorPosition(pt);
- motion = [NSEvent mouseEventWithType:NSMouseMoved
+ motion = [NSEvent mouseEventWithType:NSMouseMoved
location:loc
- modifierFlags:0
- timestamp:GetCurrentEventTime()
+ modifierFlags:0
+ timestamp:GetCurrentEventTime()
windowNumber:wNum
- context:nil
+ context:nil
eventNumber:0
- clickCount:1
+ clickCount:1
pressure:0.0];
[NSApp postEvent:motion atStart:NO];
- press = [NSEvent mouseEventWithType:NSLeftMouseDown
+ press = [NSEvent mouseEventWithType:NSLeftMouseDown
location:loc
- modifierFlags:0
- timestamp:GetCurrentEventTime()
+ modifierFlags:0
+ timestamp:GetCurrentEventTime()
windowNumber:wNum
- context:nil
+ context:nil
eventNumber:1
- clickCount:1
+ clickCount:1
pressure:0.0];
[NSApp postEvent:press atStart:NO];
release = [NSEvent mouseEventWithType:NSLeftMouseUp
location:loc
- modifierFlags:0
- timestamp:GetCurrentEventTime()
+ modifierFlags:0
+ timestamp:GetCurrentEventTime()
windowNumber:wNum
- context:nil
+ context:nil
eventNumber:2
- clickCount:1
+ clickCount:1
pressure:0.0];
[NSApp postEvent:release atStart:NO];
return TCL_OK;
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 2666939..fe6981d 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -1186,6 +1186,11 @@ RedisplayView(
return YES;
}
+/*
+ * This keyDown method does nothing, which is a huge improvement over the
+ * default keyDown method which beeps every time a key is pressed.
+ */
+
- (void) keyDown: (NSEvent *) theEvent
{
#ifdef TK_MAC_DEBUG_EVENTS
@@ -1193,6 +1198,23 @@ RedisplayView(
#endif
}
+/*
+ * When the services menu is opened this is called for each Responder in
+ * the Responder chain until a service provider is found. The TkContentView
+ * should be the first (and generally only) Responder in the chain. We
+ * return the TkServices object that was created in TkpInit.
+ */
+
+- (id)validRequestorForSendType:(NSString *)sendType
+ returnType:(NSString *)returnType
+{
+ if ([sendType isEqualToString:@"NSStringPboardType"] ||
+ [sendType isEqualToString:@"NSPasteboardTypeString"]) {
+ return [NSApp servicesProvider];
+ }
+ return [super validRequestorForSendType:sendType returnType:returnType];
+}
+
@end
/*
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index 70e9cd9..4e53282 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -2518,6 +2518,7 @@ WmIconphotoCmd(
{
Tk_Image tk_icon;
int width, height, isDefault = 0;
+ NSImage *newIcon = NULL;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv,
@@ -2563,12 +2564,16 @@ WmIconphotoCmd(
return TCL_ERROR;
}
- NSImage *newIcon;
Tk_SizeOfImage(tk_icon, &width, &height);
- newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
- width, height);
+ if (width != 0 && height != 0) {
+ newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
+ width, height);
+ }
Tk_FreeImage(tk_icon);
if (newIcon == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "failed to create an iconphoto with image \"%s\"", icon));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
return TCL_ERROR;
}
[NSApp setApplicationIconImage: newIcon];
@@ -3311,18 +3316,18 @@ WmStackorderCmd(
if (objc == 3) {
windows = TkWmStackorderToplevel(winPtr);
- if (windows == NULL) {
- Tcl_Panic("TkWmStackorderToplevel failed");
- }
-
- resultObj = Tcl_NewObj();
- for (windowPtr = windows; *windowPtr ; windowPtr++) {
- Tcl_ListObjAppendElement(NULL, resultObj,
+ if (windows != NULL) {
+ resultObj = Tcl_NewObj();
+ for (windowPtr = windows; *windowPtr ; windowPtr++) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
TkNewWindowObj((Tk_Window) *windowPtr));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ ckfree(windows);
+ return TCL_OK;
+ } else {
+ return TCL_ERROR;
}
- Tcl_SetObjResult(interp, resultObj);
- ckfree(windows);
- return TCL_OK;
} else {
TkWindow *winPtr2;
int index1 = -1, index2 = -1, result;
@@ -6623,7 +6628,7 @@ WmStackorderToplevelWrapperMap(
Tcl_HashEntry *hPtr;
int newEntry;
- if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr)
+ if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)
&& (winPtr->display == display)) {
hPtr = Tcl_CreateHashEntry(table,
(char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry);
@@ -6644,8 +6649,8 @@ WmStackorderToplevelWrapperMap(
* This procedure returns the stack order of toplevel windows.
*
* Results:
- * An array of pointers to tk window objects in stacking order or else
- * NULL if there was an error.
+ * A NULL terminated array of pointers to tk window objects in stacking
+ * order or else NULL if there was an error.
*
* Side effects:
* None.
@@ -6660,57 +6665,24 @@ TkWmStackorderToplevel(
TkWindow *childWinPtr, **windows, **windowPtr;
Tcl_HashTable table;
Tcl_HashEntry *hPtr;
- Tcl_HashSearch search;
-
- /*
- * Map mac windows to a TkWindow of the wrapped toplevel.
- */
-
- Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
- WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
-
- windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
-
- /*
- * Special cases: If zero or one toplevels were mapped there is no need to
- * enumerate Windows.
- */
-
- switch (table.numEntries) {
- case 0:
- windows[0] = NULL;
- goto done;
- case 1:
- hPtr = Tcl_FirstHashEntry(&table, &search);
- windows[0] = Tcl_GetHashValue(hPtr);
- windows[1] = NULL;
- goto done;
- }
-
NSArray *macWindows = [NSApp orderedWindows];
+ NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects];
NSInteger windowCount = [macWindows count];
- if (!windowCount) {
- ckfree(windows);
- windows = NULL;
- } else {
- windowPtr = windows + table.numEntries;
- *windowPtr-- = NULL;
- for (NSWindow *w in macWindows) {
+ windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *));
+ if (windows != NULL) {
+ Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
+ WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
+ for (NSWindow *w in backToFront) {
hPtr = Tcl_FindHashEntry(&table, (char*) w);
if (hPtr != NULL) {
childWinPtr = Tcl_GetHashValue(hPtr);
- *windowPtr-- = childWinPtr;
+ *windowPtr++ = childWinPtr;
}
}
- if (windowPtr != windows-1) {
- Tcl_Panic("num matched toplevel windows does not equal num "
- "children");
- }
+ *windowPtr = NULL;
+ Tcl_DeleteHashTable(&table);
}
-
- done:
- Tcl_DeleteHashTable(&table);
return windows;
}
diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c
index 3d88ef7..52534ce 100644
--- a/macosx/ttkMacOSXTheme.c
+++ b/macosx/ttkMacOSXTheme.c
@@ -1409,8 +1409,10 @@ static void ButtonElementDraw(
} else if (info.kind == kThemePushButton &&
(state & TTK_STATE_PRESSED)) {
bounds.size.height += 2;
- GradientFillRoundedRectangle(dc.context, bounds, 4,
- pressedPushButtonGradient, 2);
+ if ([NSApp macMinorVersion] > 8) {
+ GradientFillRoundedRectangle(dc.context, bounds, 4,
+ pressedPushButtonGradient, 2);
+ }
} else {
/*
@@ -1859,18 +1861,17 @@ static void ComboboxElementDraw(
BEGIN_DRAWING(d)
bounds.origin.y += 1;
if (TkMacOSXInDarkMode(tkwin)) {
- bounds.size.height += 1;
+ bounds.size.height += 1;
DrawDarkButton(bounds, info.kind, state, dc.context);
- } else if ([NSApp macMinorVersion] > 8) {
- if ((state & TTK_STATE_BACKGROUND) &&
- !(state & TTK_STATE_DISABLED)) {
+ } else if ([NSApp macMinorVersion] > 8) {
+ if ((state & TTK_STATE_BACKGROUND) &&
+ !(state & TTK_STATE_DISABLED)) {
NSColor *background = [NSColor textBackgroundColor];
CGRect innerBounds = CGRectInset(bounds, 1, 2);
SolidFillRoundedRectangle(dc.context, innerBounds, 4, background);
}
- ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
- NULL);
}
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
END_DRAWING
}
@@ -2095,7 +2096,7 @@ static void TrackElementDraw(
Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from);
Tcl_GetDoubleFromObj(NULL, elem->toObj, &to);
Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value);
- factor = RangeToFactor(to - from);
+ factor = RangeToFactor(to);
HIThemeTrackDrawInfo info = {
.version = 0,
diff --git a/tests/bind.test b/tests/bind.test
index 1b01685..c657dd5 100644
--- a/tests/bind.test
+++ b/tests/bind.test
@@ -6743,11 +6743,13 @@ test bind-34.1 {-warp works relatively to a window} -setup {
update
event generate .top <Motion> -x 20 -y 20 -warp 1
update idletasks ; # DoWarp is an idle callback
+ after 50 ; # Win specific - wait for SendInput to be executed
set pointerPos1 [winfo pointerxy .t]
wm geometry .top +600+600
update
event generate .top <Motion> -x 20 -y 20 -warp 1
update idletasks ; # DoWarp is an idle callback
+ after 50 ; # Win specific - wait for SendInput to be executed
set pointerPos2 [winfo pointerxy .t]
# from the first warped position to the second one, the mouse
# pointer should have moved the same amount as the window moved
@@ -6766,12 +6768,33 @@ test bind-34.2 {-warp works relatively to the screen} -setup {
# Contrary to bind-34.1, we're directly checking screen coordinates
event generate {} <Motion> -x 20 -y 20 -warp 1
update idletasks ; # DoWarp is an idle callback
+ after 50 ; # Win specific - wait for SendInput to be executed
set res [winfo pointerxy .]
event generate {} <Motion> -x 200 -y 200 -warp 1
update idletasks ; # DoWarp is an idle callback
+ after 50 ; # Win specific - wait for SendInput to be executed
lappend res {*}[winfo pointerxy .]
} -cleanup {
} -result {20 20 200 200}
+test bind-34.3 {-warp works with null or negative coordinates} -setup {
+} -body {
+ event generate {} <Motion> -x 0 -y 0 -warp 1
+ update idletasks ; # DoWarp is an idle callback
+ after 50 ; # Win specific - wait for SendInput to be executed
+ set res [winfo pointerxy .]
+ event generate {} <Motion> -x -1 -y -1 -warp 1
+ update idletasks ; # DoWarp is an idle callback
+ after 50 ; # Win specific - wait for SendInput to be executed
+ foreach dim [winfo pointerxy .] {
+ if {$dim <= 0} {
+ lappend res ok
+ } else {
+ lappend res $dim
+ }
+ }
+ set res
+} -cleanup {
+} -result {0 0 ok ok}
# cleanup
cleanupTests
diff --git a/tests/canvImg.test b/tests/canvImg.test
index c0b91f8..bd9edb5 100644
--- a/tests/canvImg.test
+++ b/tests/canvImg.test
@@ -803,6 +803,7 @@ test canvImg-11.3 {ImageChangedProc procedure} -constraints {
foo2 changed 0 0 0 0 80 60
.c create image 50 100 -image foo -tags image -anchor nw
.c create image 70 110 -image foo2 -anchor nw
+ update
set z {}
set timer [after 500 {lappend z "timed out"}]
image create test foo -variable x
diff --git a/tests/ttk/notebook.test b/tests/ttk/notebook.test
index 3a2a6ff..ac63088 100644
--- a/tests/ttk/notebook.test
+++ b/tests/ttk/notebook.test
@@ -69,7 +69,7 @@ test notebook-2.5 "tab - get all options" -body {
.nb tab .nb.foo
} -result [list \
-padding 0 -sticky nsew \
- -state normal -text "Changed Foo" -image "" -compound none -underline -1]
+ -state normal -text "Changed Foo" -image "" -compound {} -underline -1]
test notebook-4.1 "Test .nb index end" -body {
.nb index end
diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test
index 9c24998..65ae55e 100644
--- a/tests/ttk/treeview.test
+++ b/tests/ttk/treeview.test
@@ -692,7 +692,7 @@ test treeview-368fa4561e "indicators cannot be clicked on leafs" -setup {
destroy .tv
} -result {0 0 0}
-test treeview-ce470f20fd-1 "dragging further than the right edge of the treeview is forbidden" -setup {
+test treeview-ce470f20fd-1 "dragging further than the right edge of the treeview is allowed" -setup {
pack [ttk::treeview .tv]
.tv heading #0 -text "Drag my right edge -->"
update
@@ -702,7 +702,7 @@ test treeview-ce470f20fd-1 "dragging further than the right edge of the treeview
lappend res [expr {[.tv column #0 -width] > $res}]
} -cleanup {
destroy .tv
-} -result {200 0}
+} -result {200 1}
proc nostretch {tv} {
foreach col [$tv cget -columns] {
diff --git a/tests/unixEmbed.test b/tests/unixEmbed.test
index 7d26fbf..2ebf9c2 100644
--- a/tests/unixEmbed.test
+++ b/tests/unixEmbed.test
@@ -85,6 +85,8 @@ proc colorsFree {w {red 31} {green 245} {blue 192}} {
&& ([lindex $vals 2]/256 == $blue)
}
+testConstraint pressbutton [llength [info commands pressbutton]]
+
test unixEmbed-1.1 {TkpUseWindow procedure, bad window identifier} -constraints {
unix
} -setup {
@@ -1263,6 +1265,56 @@ test unixEmbed-10.2 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -con
deleteWindows
} -result {70x300+0+0}
+test unixEmbed-11.1 {focus -force works for embedded toplevels} -constraints {
+ unix
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .t
+ pack [frame .t.f -container 1 -width 200 -height 200] -fill both
+ update idletasks
+ toplevel .embed -use [winfo id .t.f] -bg green
+ update idletasks
+ focus -force .t
+ focus -force .embed
+ focus
+} -cleanup {
+ deleteWindows
+} -result .embed
+test unixEmbed-11.2 {mouse coordinates in embedded toplevels} -constraints {
+ unix pressbutton
+} -setup {
+ deleteWindows
+} -body {
+ toplevel .main
+ set result {}
+ pack [button .main.b -text "Main Button" \
+ -command {lappend result ".main.b"}] -padx 30 -pady 30
+ pack [frame .main.f -container 1 -width 200 -height 200] -fill both
+ update idletasks
+ toplevel .embed -use [winfo id .main.f] -bg green
+ pack [button .embed.b -text "Emb Button" \
+ -command {lappend result ".embed.b"}] -padx 30 -pady 30
+ wm geometry .main 200x400+100+100
+ update idletasks
+ focus -force .main
+ set x [expr {[winfo x .main ] + [winfo x .main.b] + 40}]
+ set y [expr {[winfo y .main ] + [winfo y .main.b] + 38}]
+ lappend result [winfo containing $x $y]
+ after 200
+ pressbutton $x $y
+ update
+ set y [expr {$y + 80}]
+ lappend result [winfo containing $x $y]
+ after 200
+ pressbutton $x $y
+ update
+ set result
+} -cleanup {
+ deleteWindows
+} -result {.main.b .main.b .embed.b .embed.b}
+
+
# cleanup
deleteWindows
cleanupbg
diff --git a/tests/wm.test b/tests/wm.test
index df8d325..2978c1b 100644
--- a/tests/wm.test
+++ b/tests/wm.test
@@ -873,6 +873,12 @@ test wm-iconphoto-1.4 {usage} -returnCodes error -body {
# we currently have no return info
wm iconphoto . -default
} -result {wrong # args: should be "wm iconphoto window ?-default? image1 ?image2 ...?"}
+test wm-iconphoto-1.5.1 {usage} -constraints aquaOrWin32 -returnCodes error -body {
+ wm iconphoto . -default [image create photo -file {}]
+} -match {glob} -result {failed to create an iconphoto with image *}
+test wm-iconphoto-1.5.2 {usage} -constraints x11 -body {
+ wm iconphoto . -default [image create photo -file {}]
+} -result {}
# All other iconphoto tests are platform specific
@@ -1553,8 +1559,8 @@ test wm-stackorder-5.3 {An overrideredirect window\
destroy .t
} -result 1
-test wm-stackorder-6.1 {An embedded toplevel does not\
- appear in the stacking order on unix or win} -constraints notAqua -body {
+test wm-stackorder-6.1 {An embedded toplevel does not appear in the \
+ stacking order} -body {
toplevel .real -container 1
toplevel .embd -bg blue -use [winfo id .real]
update
@@ -1562,16 +1568,6 @@ test wm-stackorder-6.1 {An embedded toplevel does not\
} -cleanup {
deleteWindows
} -result {. .real}
-test wm-stackorder-6.1.1 {An embedded toplevel does\
- appear in the stacking order on macOS} -constraints aqua -body {
- toplevel .real -container 1
- toplevel .embd -bg blue -use [winfo id .real]
- update
- wm stackorder .
-} -cleanup {
- deleteWindows
-} -result {. .embd}
-
stdWindow
diff --git a/unix/configure b/unix/configure
index 5c46bac..70a5bef 100755
--- a/unix/configure
+++ b/unix/configure
@@ -2360,7 +2360,6 @@ $as_echo "$as_me: WARNING: --with-tcl argument should refer to directory contain
for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
`ls -d /Library/Frameworks 2>/dev/null` \
`ls -d /Network/Library/Frameworks 2>/dev/null` \
- `ls -d /System/Library/Frameworks 2>/dev/null` \
; do
if test -f "$i/Tcl.framework/tclConfig.sh" ; then
ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
@@ -2377,6 +2376,7 @@ $as_echo "$as_me: WARNING: --with-tcl argument should refer to directory contain
`ls -d /usr/local/lib 2>/dev/null` \
`ls -d /usr/contrib/lib 2>/dev/null` \
`ls -d /usr/pkg/lib 2>/dev/null` \
+ `ls -d /usr/lib/tcl8.7 2>/dev/null` \
`ls -d /usr/lib 2>/dev/null` \
`ls -d /usr/lib64 2>/dev/null` \
`ls -d /usr/local/lib/tcl8.7 2>/dev/null` \
@@ -4169,6 +4169,9 @@ $as_echo "$as_me: WARNING: can't find uname command" >&2;}
if test "`uname -s`" = "AIX" ; then
tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
fi
+ if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
+ tcl_cv_sys_version=NetBSD-Debian
+ fi
fi
fi
@@ -5882,6 +5885,15 @@ $as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h
fi
+ ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdbool_h" = xyes; then :
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+
+
# FIXME: This subst was left in only because the TCL_DL_LIBS
# entry in tclConfig.sh uses it. It is not clear why someone
# would use TCL_DL_LIBS instead of TCL_LIBS.
@@ -7650,8 +7662,8 @@ $as_echo "$enable_xft" >&6; }
XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
if test "$found_xft" = "no" ; then
found_xft=yes
- XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
- XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
+ XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
+ XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_xft" >&5
$as_echo "$found_xft" >&6; }
@@ -8141,7 +8153,7 @@ if test "${SHARED_BUILD}" = "1" -a "${SHLIB_SUFFIX}" != ""; then
TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
fi
-TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
+test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'
TK_PKG_DIR='tk$(VERSION)'
diff --git a/unix/configure.ac b/unix/configure.ac
index c485652..0853809 100644
--- a/unix/configure.ac
+++ b/unix/configure.ac
@@ -456,8 +456,8 @@ if test $tk_aqua = no; then
XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
if test "$found_xft" = "no" ; then
found_xft=yes
- XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
- XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
+ XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
+ XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
fi
AC_MSG_RESULT([$found_xft])
dnl make sure that compiling against Xft header file doesn't bomb
@@ -649,7 +649,7 @@ if test "${SHARED_BUILD}" = "1" -a "${SHLIB_SUFFIX}" != ""; then
TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
fi
-TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
+test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
PRIVATE_INCLUDE_DIR='$(includedir)'
HTML_DIR='$(DISTDIR)/html'
TK_PKG_DIR='tk$(VERSION)'
diff --git a/unix/installManPage b/unix/installManPage
index 4d615bf..935bbcd 100755
--- a/unix/installManPage
+++ b/unix/installManPage
@@ -92,12 +92,20 @@ case $ManPage in
exit 2 ;;
esac
+Name=`basename $ManPage .$Section`
SrcDir=`dirname $ManPage`
########################################################################
### Process Page to Create Target Pages
###
+Specials="FindPhoto FontId MeasureChar"
+for n in $Specials; do
+ if [ "$Name" = "$n" ] ; then
+ Names="$n $Names"
+ fi
+done
+
First=""
for Target in $Names; do
Target=$Target.$Section$Suffix
@@ -106,7 +114,7 @@ for Target in $Names; do
First=$Target
sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
$ManPage > $Dir/$First
- chmod 444 $Dir/$First
+ chmod 644 $Dir/$First
$Gzip $Dir/$First
else
ln $SymOrLoc$First$Gz $Dir/$Target$Gz
diff --git a/unix/tcl.m4 b/unix/tcl.m4
index 93efb49..d617259 100644
--- a/unix/tcl.m4
+++ b/unix/tcl.m4
@@ -77,7 +77,6 @@ AC_DEFUN([SC_PATH_TCLCONFIG], [
for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
`ls -d /Library/Frameworks 2>/dev/null` \
`ls -d /Network/Library/Frameworks 2>/dev/null` \
- `ls -d /System/Library/Frameworks 2>/dev/null` \
; do
if test -f "$i/Tcl.framework/tclConfig.sh" ; then
ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
@@ -94,6 +93,7 @@ AC_DEFUN([SC_PATH_TCLCONFIG], [
`ls -d /usr/local/lib 2>/dev/null` \
`ls -d /usr/contrib/lib 2>/dev/null` \
`ls -d /usr/pkg/lib 2>/dev/null` \
+ `ls -d /usr/lib/tcl8.7 2>/dev/null` \
`ls -d /usr/lib 2>/dev/null` \
`ls -d /usr/lib64 2>/dev/null` \
`ls -d /usr/local/lib/tcl8.7 2>/dev/null` \
@@ -210,7 +210,6 @@ AC_DEFUN([SC_PATH_TKCONFIG], [
for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
`ls -d /Library/Frameworks 2>/dev/null` \
`ls -d /Network/Library/Frameworks 2>/dev/null` \
- `ls -d /System/Library/Frameworks 2>/dev/null` \
; do
if test -f "$i/Tk.framework/tkConfig.sh" ; then
ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
@@ -227,6 +226,7 @@ AC_DEFUN([SC_PATH_TKCONFIG], [
`ls -d /usr/local/lib 2>/dev/null` \
`ls -d /usr/contrib/lib 2>/dev/null` \
`ls -d /usr/pkg/lib 2>/dev/null` \
+ `ls -d /usr/lib/tk8.7 2>/dev/null` \
`ls -d /usr/lib 2>/dev/null` \
`ls -d /usr/lib64 2>/dev/null` \
`ls -d /usr/local/lib/tk8.7 2>/dev/null` \
@@ -814,6 +814,9 @@ AC_DEFUN([SC_CONFIG_SYSTEM], [
if test "`uname -s`" = "AIX" ; then
tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
fi
+ if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
+ tcl_cv_sys_version=NetBSD-Debian
+ fi
fi
fi
])
@@ -1870,6 +1873,8 @@ dnl # preprocessing tests use only CPPFLAGS.
[Defined when compiler supports casting to union type.])
fi
+ AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)
+
# FIXME: This subst was left in only because the TCL_DL_LIBS
# entry in tclConfig.sh uses it. It is not clear why someone
# would use TCL_DL_LIBS instead of TCL_LIBS.
@@ -1930,7 +1935,7 @@ dnl # preprocessing tests use only CPPFLAGS.
# NO_SYS_WAIT_H
# NO_DLFCN_H
# HAVE_SYS_PARAM_H
-#
+# HAVE_STDBOOL_H
# HAVE_STRING_H ?
#
#--------------------------------------------------------------------
diff --git a/unix/tkUnixFont.c b/unix/tkUnixFont.c
index 3c1ce65..9a8d1f7 100644
--- a/unix/tkUnixFont.c
+++ b/unix/tkUnixFont.c
@@ -63,7 +63,7 @@ typedef struct FontFamily {
/* Two-level sparse table used to determine
* quickly if the specified character exists.
* As characters are encountered, more pages
- * in this table are dynamically alloced. The
+ * in this table are dynamically allocated. The
* contents of each page is a bitmask
* consisting of FONTMAP_BITSPERPAGE bits,
* representing whether this font can be used
diff --git a/unix/tkUnixKey.c b/unix/tkUnixKey.c
index cbba7bb..fa93edc 100644
--- a/unix/tkUnixKey.c
+++ b/unix/tkUnixKey.c
@@ -208,7 +208,7 @@ TkpGetString(
Tcl_DStringValue(&buf)[len] = '\0';
if (len == 1) {
- len = Tcl_UniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0],
+ len = TkUniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0],
Tcl_DStringValue(dsPtr));
Tcl_DStringSetLength(dsPtr, len);
} else {
diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c
index bca193a..e69dab0 100644
--- a/unix/tkUnixRFont.c
+++ b/unix/tkUnixRFont.c
@@ -74,6 +74,15 @@ static Tcl_ThreadDataKey dataKey;
*-------------------------------------------------------------------------
*/
+
+static int utf8ToUcs4(const char *source, FcChar32 *c, int numBytes)
+{
+ if (numBytes >= 6) {
+ return TkUtfToUniChar(source, (int *)c);
+ }
+ return FcUtf8ToUcs4((const FcChar8 *)source, c, numBytes);
+}
+
void
TkpFontPkgInit(
TkMainInfo *mainPtr) /* The application being created. */
@@ -897,7 +906,7 @@ Tk_DrawChars(
XftFont *ftFont;
FcChar32 c;
- clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
+ clen = utf8ToUcs4(source, &c, numBytes);
if (clen <= 0) {
/*
* This should not happen, but it can.
@@ -1037,7 +1046,7 @@ TkDrawAngledChars(
XftFont *ftFont;
FcChar32 c;
- clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
+ clen = utf8ToUcs4(source, &c, numBytes);
if (clen <= 0) {
/*
* This should not happen, but it can.
@@ -1141,7 +1150,7 @@ TkDrawAngledChars(
XftFont *ftFont, *ft0Font;
FcChar32 c;
- clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes);
+ clen = utf8ToUcs4(source, &c, numBytes);
if (clen <= 0) {
/*
* This should not happen, but it can.
diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c
index f9cf4e7..490a1ea 100644
--- a/unix/tkUnixWm.c
+++ b/unix/tkUnixWm.c
@@ -2444,6 +2444,10 @@ WmIconphotoCmd(
photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));
if (photo == NULL) {
ckfree((char *) iconPropertyData);
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "failed to create an iconphoto with image \"%s\"",
+ Tcl_GetString(objv[i])));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
return TCL_ERROR;
}
Tk_PhotoGetSize(photo, &width, &height);
@@ -3265,6 +3269,8 @@ WmStackorderCmd(
ckfree(windows);
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
+ } else {
+ return TCL_ERROR;
}
} else {
Tk_Window relWin;
@@ -6428,6 +6434,9 @@ TkWmStackorderToplevel(
TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
window_ptr = windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
+ if (windows == NULL) {
+ return NULL;
+ }
/*
* Special cases: If zero or one toplevels were mapped there is no need to
diff --git a/win/configure b/win/configure
index 7e63a81..3bb8570 100755
--- a/win/configure
+++ b/win/configure
@@ -4664,6 +4664,15 @@ $as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h
fi
+ ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdbool_h" = xyes; then :
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+
+
# See if the compiler supports casting to a union type.
# This is used to stop gcc from printing a compiler
# warning when initializing a union member.
diff --git a/win/makefile.vc b/win/makefile.vc
index 99aa6c1..311be18 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -316,7 +316,7 @@ PRJ_INCLUDES = -I"$(BITMAPDIR)" -I"$(XLIBDIR)"
CONFIG_DEFS =/DSTDC_HEADERS=1 /DHAVE_SYS_TYPES_H=1 /DHAVE_SYS_STAT_H=1 \
/DHAVE_STRING_H=1 /DHAVE_MEMORY_H=1 \
- /DHAVE_STRINGS_H=1 /DHAVE_INTTYPES_H=1 /DHAVE_STDINT_H=1 \
+ /DHAVE_STRINGS_H=1 /DHAVE_INTTYPES_H=1 \
/DSUPPORT_CONFIG_EMBEDDED /DUNICODE /D_UNICODE \
!if $(HAVE_UXTHEME_H)
/DHAVE_UXTHEME_H=1 \
diff --git a/win/rules.vc b/win/rules.vc
index 2b11b01..50911d4 100644
--- a/win/rules.vc
+++ b/win/rules.vc
@@ -24,7 +24,7 @@ _RULES_VC = 1
# For modifications that are not backward-compatible, you *must* change
# the major version.
RULES_VERSION_MAJOR = 1
-RULES_VERSION_MINOR = 4
+RULES_VERSION_MINOR = 5
# The PROJECT macro must be defined by parent makefile.
!if "$(PROJECT)" == ""
@@ -976,6 +976,19 @@ VERSION = $(DOTVERSION:.=)
!endif # $(DOING_TCL) ... etc.
+# Windows RC files have 3 version components. Ensure this irrespective
+# of how many components the package has specified. Basically, ensure
+# minimum 4 components by appending 4 0's and then pick out the first 4.
+# Also take care of the fact that DOTVERSION may have "a" or "b" instead
+# of "." separating the version components.
+DOTSEPARATED=$(DOTVERSION:a=.)
+DOTSEPARATED=$(DOTSEPARATED:b=.)
+!if [echo RCCOMMAVERSION = \> versions.vc] \
+ || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc]
+!error *** Could not generate RCCOMMAVERSION ***
+!endif
+!include versions.vc
+
################################################################
# 10. Construct output directory and file paths
# Figure-out how to name our intermediate and output directories.
@@ -1490,7 +1503,7 @@ GUIEXECMD = $(link32) $(guilflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)
RESCMD = $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \
$(TCL_INCLUDES) \
/DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
- /DCOMMAVERSION=$(DOTVERSION:.=,),0 \
+ /DCOMMAVERSION=$(RCCOMMAVERSION) \
/DDOTVERSION=\"$(DOTVERSION)\" \
/DVERSION=\"$(VERSION)\" \
/DSUFX=\"$(SUFX:t=)\" \
diff --git a/win/tcl.m4 b/win/tcl.m4
index c0dd539..d3d94ef 100644
--- a/win/tcl.m4
+++ b/win/tcl.m4
@@ -948,6 +948,8 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [
[Defined when cygwin/mingw ignores VOID define in winnt.h])
fi
+ AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)
+
# See if the compiler supports casting to a union type.
# This is used to stop gcc from printing a compiler
# warning when initializing a union member.
diff --git a/win/tkWinFont.c b/win/tkWinFont.c
index 11385ed..e4f0624 100644
--- a/win/tkWinFont.c
+++ b/win/tkWinFont.c
@@ -2232,7 +2232,7 @@ FontMapLoadPage(
end = (row + 1) << FONTMAP_SHIFT;
for (i = row << FONTMAP_SHIFT; i < end; i++) {
if (Tcl_UtfToExternal(NULL, encoding, src,
- Tcl_UniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,
+ TkUniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,
buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) {
continue;
}
diff --git a/win/tkWinKey.c b/win/tkWinKey.c
index c3816bf..8a83874 100644
--- a/win/tkWinKey.c
+++ b/win/tkWinKey.c
@@ -124,7 +124,7 @@ TkpGetString(
if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))
|| (keysym == XK_Return) || (keysym == XK_Tab)) {
- len = Tcl_UniCharToUtf(keysym & 255, buf);
+ len = TkUniCharToUtf(keysym & 255, buf);
Tcl_DStringAppend(dsPtr, buf, len);
}
}
diff --git a/win/tkWinPointer.c b/win/tkWinPointer.c
index 2b8656b..e7e041f 100644
--- a/win/tkWinPointer.c
+++ b/win/tkWinPointer.c
@@ -362,8 +362,8 @@ void TkSetCursorPos(
int y)
{
INPUT input;
- unsigned xscreen = (GetSystemMetrics(SM_CXSCREEN) - 1);
- unsigned yscreen = (GetSystemMetrics(SM_CYSCREEN) - 1);
+ int xscreen = (int)(GetSystemMetrics(SM_CXSCREEN) - 1);
+ int yscreen = (int)(GetSystemMetrics(SM_CYSCREEN) - 1);
input.type = INPUT_MOUSE;
input.mi.dx = (x * 65535 + xscreen/2) / xscreen;
diff --git a/win/tkWinWm.c b/win/tkWinWm.c
index d273b4c..e6a0a4b 100644
--- a/win/tkWinWm.c
+++ b/win/tkWinWm.c
@@ -4379,9 +4379,9 @@ WmIconphotoCmd(
if (!iconInfo.hbmColor) {
ckfree(lpIR);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "failed to create color bitmap for \"%s\"",
+ "failed to create an iconphoto with image \"%s\"",
Tcl_GetString(objv[i])));
- Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "BITMAP", NULL);
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
return TCL_ERROR;
}
@@ -5189,18 +5189,18 @@ WmStackorderCmd(
if (objc == 3) {
windows = TkWmStackorderToplevel(winPtr);
- if (windows == NULL) {
- Tcl_Panic("TkWmStackorderToplevel failed");
- }
-
- resultObj = Tcl_NewObj();
- for (windowPtr = windows; *windowPtr ; windowPtr++) {
- Tcl_ListObjAppendElement(NULL, resultObj,
- TkNewWindowObj((Tk_Window) *windowPtr));
+ if (windows != NULL) {
+ resultObj = Tcl_NewObj();
+ for (windowPtr = windows; *windowPtr ; windowPtr++) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
+ TkNewWindowObj((Tk_Window) *windowPtr));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ ckfree(windows);
+ return TCL_OK;
+ } else {
+ return TCL_ERROR;
}
- Tcl_SetObjResult(interp, resultObj);
- ckfree(windows);
- return TCL_OK;
} else {
TkWindow *winPtr2, **winPtr2Ptr = &winPtr2;
int index1 = -1, index2 = -1, result;
@@ -6807,8 +6807,6 @@ TkWmStackorderToplevel(
(LPARAM) &pair) == 0) {
ckfree(windows);
windows = NULL;
- } else if (pair.windowPtr != (windows-1)) {
- Tcl_Panic("num matched toplevel windows does not equal num children");
}
done:
diff --git a/xlib/X11/Xlib.h b/xlib/X11/Xlib.h
index e1ae7f1..44f556f 100644
--- a/xlib/X11/Xlib.h
+++ b/xlib/X11/Xlib.h
@@ -589,7 +589,7 @@ typedef struct _XDisplay {
#endif
#ifndef _XEVENT_
-#define XMaxTransChars 4
+#define XMaxTransChars 7
/*
* Definitions of specific events.
@@ -610,7 +610,7 @@ typedef struct {
Bool same_screen; /* same screen flag */
char trans_chars[XMaxTransChars];
/* translated characters */
- int nbytes;
+ unsigned char nbytes;
} XKeyEvent;
typedef XKeyEvent XKeyPressedEvent;
typedef XKeyEvent XKeyReleasedEvent;