Codebase list tk8.6 / 805edcb
Update upstream source from tag 'upstream/8.6.10' Update to upstream version '8.6.10' with Debian dir 15367f51c037410e2311a0183ff96085ae9362f2 Sergei Golovan 4 years ago
364 changed file(s) with 24932 addition(s) and 13439 deletion(s). Raw diff Collapse all Expand all
00 A NOTE ON THE CHANGELOG:
11 Starting in early 2011, Tk source code has been under the management of
2 fossil, hosted at http://core.tcl-lang.org/tk/ . Fossil presents a "Timeline"
2 fossil, hosted at https://core.tcl-lang.org/tk/ . Fossil presents a "Timeline"
33 view of changes made that is superior in every way to a hand edited log file.
44 Because of this, many Tk developers are now out of the habit of maintaining
55 this log file. You may still find useful things in it, but the Timeline is
52175217 2000-05-31 Eric Melski <ericm@scriptics.com>
52185218
52195219 * library/bgerror.tcl: Improved bgerror based on work by Donal
5220 K. Fellows; no longer dependant on tk_dialog; features a
5220 K. Fellows; no longer dependent on tk_dialog; features a
52215221 Windows-esque "Details" button, and a customizable extra function
52225222 button that allows the user to (for example) save the stack trace
52235223 to a file.
+0
-41
README less more
0 README: Tk
1 This is the Tk 8.6.9 source distribution.
2 http://sourceforge.net/projects/tcl/files/Tcl/
3 You can get any source release of Tk from the URL above.
4
5 1. Introduction
6 ---------------
7
8 This directory contains the sources and documentation for Tk, an X11
9 toolkit implemented with the Tcl scripting language.
10
11 For details on features, incompatibilities, and potential problems with
12 this release, see the Tcl/Tk 8.6 Web page at
13
14 http://www.tcl-lang.org/software/tcltk/8.6.html
15
16 or refer to the "changes" file in this directory, which contains a
17 historical record of all changes to Tk.
18
19 Tk is maintained, enhanced, and distributed freely by the Tcl community.
20 Source code development and tracking of bug reports and feature requests
21 takes place at:
22
23 http://core.tcl-lang.org/tk/
24
25 with the Tcl Developer Xchange at:
26
27 http://www.tcl-lang.org/
28
29 Tk is a freely available open source package. You can do virtually
30 anything you like with it, such as modifying it, redistributing it,
31 and selling it either in whole or in part. See the file
32 "license.terms" for complete information.
33
34 2. See Tcl README
35 -----------------
36
37 Please see the README file that comes with the associated Tcl release
38 for more information. There are pointers there to extensive
39 documentation. In addition, there are additional README files
40 in the subdirectories of this distribution.
0 # README: Tk
1
2 This is the **Tk 8.6.10** source distribution.
3
4 You can get any source release of Tk from [our distribution
5 site](https://sourceforge.net/projects/tcl/files/Tcl/).
6
7
8 ## <a id="intro">1.</a> Introduction
9
10 This directory contains the sources and documentation for Tk, a
11 cross-platform GUI toolkit implemented with the Tcl scripting language.
12
13 For details on features, incompatibilities, and potential problems with
14 this release, see [the Tcl/Tk 8.6 Web page](https://www.tcl.tk/software/tcltk/8.6.html)
15 or refer to the "changes" file in this directory, which contains a
16 historical record of all changes to Tk.
17
18 Tk is maintained, enhanced, and distributed freely by the Tcl community.
19 Source code development and tracking of bug reports and feature requests
20 takes place at [core.tcl-lang.org](https://core.tcl-lang.org/).
21 Tcl/Tk release and mailing list services are [hosted by
22 SourceForge](https://sourceforge.net/projects/tcl/)
23 with the Tcl Developer Xchange hosted at
24 [www.tcl-lang.org](https://www.tcl-lang.org).
25
26 Tk is a freely available open source package. You can do virtually
27 anything you like with it, such as modifying it, redistributing it,
28 and selling it either in whole or in part. See the file
29 `license.terms` for complete information.
30
31 ## <a id="tcl">2.</a> See Tcl README.md
32
33 Please see the README.md file that comes with the associated Tcl release
34 for more information. There are pointers there to extensive
35 documentation. In addition, there are additional README files
36 in the subdirectories of this distribution.
70717071
70727072 2013-08-25 (bug fix)[3016181] Cocoa: [destroy $scrollbar] => crash (goddard)
70737073
7074 --- Released 8.6.1, September 19, 2013 --- http://core.tcl.tk/tk/ for details
7074 --- Released 8.6.1, September 19, 2013 --- https://core.tcl-lang.org/tk/ for details
70757075
70767076 2013-10-27 (bug fix) OSX drawing lags (deily,steffen,walzer)
70777077
71197119
71207120 2014-08-01 (bug fix) OSX font config crash (rob@bitkeeper)
71217121
7122 --- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tk/ for details
7122 --- Released 8.6.2, August 27, 2014 --- https://core.tcl-lang.org/tk/ for details
71237123
71247124 2014-08-27 (bug) Cocoa: Crash after [$button destroy] (walzer)
71257125
71437143
71447144 2014-11-07 (bug)[3529885] [scale] handling of negative resolution (vogel)
71457145
7146 --- Released 8.6.3, November 12, 2014 --- http://core.tcl.tk/tk/ for details
7146 --- Released 8.6.3, November 12, 2014 --- https://core.tcl-lang.org/tk/ for details
71477147
71487148 2014-11-14 (bug)[d43a10] shimmer-related crash in [tk_getOpenFile] (nadkarni)
71497149
71657165 Tk Cocoa 2.0: App Store enabled (walzer,culler,desmera,owen,nyberg,reincke)
71667166 *** POTENTIAL INCOMPATIBILITY ***
71677167
7168 --- Released 8.6.4, March 12, 2015 --- http://core.tcl.tk/tk/ for details
7168 --- Released 8.6.4, March 12, 2015 --- https://core.tcl-lang.org/tk/ for details
71697169
71707170 2015-03-10 (bug) Cocoa: premature image free crash (walzer)
71717171
72647264
72657265 Tk Cocoa 2.0: More drawing internals refinements (culler,walzer)
72667266
7267 --- Released 8.6.5, February 29, 2016 --- http://core.tcl.tk/tk/ for details
7267 --- Released 8.6.5, February 29, 2016 --- https://core.tcl-lang.org/tk/ for details
72687268
72697269 2016-03-07 (bug)[3137232] spinbox teardown hygiene (vogel)
72707270
73117311
73127312 2016-07-21 (bug)[450bb0] Aqua: memory corruption from [tk busy] (porter)
73137313
7314 --- Released 8.6.6, July 27, 2016 --- http://core.tcl.tk/tk/ for details
7314 --- Released 8.6.6, July 27, 2016 --- https://core.tcl-lang.org/tk/ for details
73157315
73167316 2016-08-23 (bug)[a2abc4] Wrong warp cursor position on 2nd display (vogel)
73177317
74137413
74147414 2017-08-08 (bug)[4966ca] Scidb race in notebook tab selection (cramer)
74157415
7416 --- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tk/ for details
7416 --- Released 8.6.7, August 9, 2017 --- https://core.tcl-lang.org/tk/ for details
74177417
74187418 2017-08-24 (bug)[f1a3ca] Memory leak in [text] B-tree (edhume3)
74197419
74937493
74947494 2017-12-18 (bug)[b77626] Make [tk busy -cursor] silent no-op on macOS (vogel)
74957495
7496 --- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tk/ for details
7496 --- Released 8.6.8, December 22, 2017 --- https://core.tcl-lang.org/tk/ for details
74977497
74987498 2017-12-31 (bug)[aa7679] crash using window after master destroyed (vogel)
74997499
75677567
75687568 2018-11-04 (bug)[6b22d4] [treeview] binding fix (ohagan)
75697569
7570 - Released 8.6.9, November 16, 2018 - http://core.tcl-lang.org/tk/ for details -
7570 - Released 8.6.9, November 16, 2018 - https://core.tcl-lang.org/tk/ for details
7571
7572 2018-11-19 (bug)[0a9c91] crash in text-11a.22 (vogel)
7573
7574 2018-11-20 (bug)[9705d1] crash activating "Alt" theme (culler)
7575
7576 2018-11-24 (bug)[e3b954] cursor offset at full screen display (culler)
7577
7578 2019-01-04 (bug)[18a4ba] cross-platform [winfo containing] (culler)
7579
7580 2019-01-08 (feature) local grab on Mac OSX (culler)
7581
7582 2019-01-10 (build) 'None', 'ControlMask' symbol conflicts (nijtmans)
7583
7584 2019-01-20 (bug)[509caf] [treeview tag configure] regression (mcdonald,vogel)
7585
7586 2019-01-26 (bug)[3003895] [scale] res rounds and -from (tischler,pieper,vogel)
7587
7588 2019-02-02 (new)[TIP 533] [$mb post x y idx] (culler,vogel)
7589
7590 2019-02-08 (bug)[1529659] embed toplevel blocks outer menu (culler)
7591
7592 2019-02-10 (bug)[8814bd] crash in [NSMenu size] (culler)
7593
7594 2019-02-13 (bug)[b389df] Aqua: mouse position on dual screen (culler)
7595
7596 2019-02-23 (bug)[56a182] Aqua: [tk_getOpenFile] causes off-screen toplevels (culler,walzer)
7597
7598 2019-02-23 (bug)[9771ae] Aqua: workaround incompatible transient window models (culler,walzer)
7599
7600 2019-03-01 (bug)[1951ab] Prevent transient window cycles (crashed on Aqua) (culler,vogel)
7601 *** POTENTIAL INCOMPATIBILITY ***
7602
7603 2019-03-04 (bug)[4da219] Incomplete read of multi-image GIF (oehlmann)
7604
7605 2019-03-14 (bug)[609e00] Aqua: wrong coords from MouseWheel binding (vogel,culler)
7606
7607 2019-03-25 (bug)[48c394] Aqua: recompute text layout for empty string (culler)
7608
7609 2019-03-31 (new)[TIP 535] Precision of ::scale widget tick mark values (vogel)
7610 *** POTENTIAL INCOMPATIBILITY ***
7611
7612 2019-03-31 (bug)[da3914] [$treeview identify element] failure (ulfalizer,vogel)
7613
7614 2019-04-06 (bug)[897ffe] Prevent cross-manager loops of geom management (culler,vogel)
7615
7616 2019-04-11 (new) Apple Dark Mode support (culler)
7617
7618 2019-04-14 (new) Aqua: Use color names consistent with NSColor (culler)
7619 *** POTENTIAL INCOMPATIBILITY ***
7620
7621 2019-04-14 (new) Aqua: [tk::unsupported::MacWindowStyle isdark] (culler)
7622
7623 2019-04-19 (bug)[368fa4] Prevent toggle of hidden treeview indicators (ulfalizer,vogel)
7624
7625 2019-04-24 (bug)[4d2e8d] Aqua: notebook pane redraws (culler)
7626
7627 2019-04-24 (bug)[928652] Apply TIP 533 for ttk::menubutton (culler,vogel)
7628
7629 2019-04-24 (bug)[1001070] X-platform rework of label options -highlight* (seal,culler,vogel)
7630
7631 2019-04-28 (bug)[6286fd] checkbutton handling of -selectcolor (ralfixx)
7632
7633 2019-04-30 (bug)[4f9a99] Win: crash in [style element create] (oehlman,vogel)
7634
7635 2019-05-08 (bug) Ttk scrolling bugs, see tests treeview-9.1, entry-3.[3-6] (vogel)
7636
7637 2019-05-08 (bug)[51b4b1] Aqua: combobox use native ttk scrollbar (bll,vogel)
7638 *** POTENTIAL INCOMPATIBILITY ***
7639
7640 2019-05-18 (new)[eb2996] Win: support for horizontal scrolling (chavez,vogel)
7641
7642 2019-05-26 (new)[TIP 541] [combobox current] support "end" index (vogel)
7643
7644 2019-05-26 (bug)[2a6c62] <<TreeviewSelect>> trigger on item delete (vogel)
7645
7646 2019-06-05 (bug)[9ebc6f] Aqua: fix incorrect reports of mouse coords (chavez, culler)
7647
7648 2019-06-14 (bug)[436ad6] Corrected Aqua regressions in [wm manage] (walzer, culler)
7649
7650 2019-06-15 (bug)[75b8fb] Crash with some [event generate]d <ButtonRelease> (leunissen,vogel)
7651
7652 2019-06-15 (new)[TIP 536] New tk::mac::* commands for IPC on Mac OSX (walzer)
7653
7654 2019-07-13 (bug)[4566e2] Aqua: Make default background color of Tk and Ttk agree (walzer,culler)
7655 *** POTENTIAL INCOMPATIBILITY ***
7656
7657 2019-07-16 (bug)[5ddeca] Stop app switching exposing withdrawn windows as zombies (culler)
7658
7659 2019-07-25 (new)[1fb7af] Win support for buttons 4 and 5 (chavez,vogel,nijtmans)
7660
7661 2019-08-18 (new) Refactor all MouseWheel bindings (nijtmans)
7662 *** POTENTIAL INCOMPATIBILITY ***
7663
7664 2019-08-21 (bug)[c8ccd1] up array key in [text] takes to index 1.0 (ulfalizer,vogel)
7665
7666 2019-08-28 (new)[TIP 532] Tk event loop rewrite to prevent ring overflow (cramer)
7667 *** POTENTIAL INCOMPATIBILITY ***
7668
7669 2019-08-28 (bug)[943d5e] Win: embedded widget destruction cancels window resize (nemethi,vogel,nijtmans)
7670
7671 2019-09-12 (bug)[2834776] Stop disabled spinbox from generating <<Increment>> & <<Decrement>> (vogel)
7672
7673 2019-09-24 (bug)[96bce5] Aqua: Prevent crash drawing 1x1 rounded rectangles (bll,culler)
7674
7675 2019-10-03 (bug)[3ed5b6] Win: root window position with highlightthickness>0 (leunissem,vogel,nijtmans)
7676
7677 2019-10-09 (bug)[a01b6f7] Workaround XWayland bug reporting screen width (werner,nijtmans)
7678
7679 2019-10-10 (bug) Aqua: Prevent crash deactivating menu during menu deletion (culler)
7680
7681 2019-10-21 (bug)[aea00b] Aqua: Better handling of resolution changes (chavez, culler)
7682
7683 2019-10-25 (bug)[b82bd4] Fix [style configure -compound] (culler,vogel)
7684
7685 2019-10-27 (bug)[f7a4f7] Aqua: embedded toplevel, forced focus and mouse coords (naaus,culler)
7686
7687 2019-11-13 (new) Win: keycodes Mail, AudioMedia, Launch0, Launch1 (nijtmans)
7688
7689 2019-11-15 (bug)[69b48f] failing test textTag-18.1 (vogel)
7690
7691 2019-11-17 (bug)[c4abd2] panic in stackorder command (culler)
7692
7693 2019-11-17 (bug)[53d280] [wm iconphoto] crash on empty image (culler)
7694
7695 2019-11-17 [90d555] workaround NSFontManager bad selections (culler)
7696
7697 2019-11-19 (new) Partial Emoji support in text displays (nijtmans,culler)
7698
7699 - Released 8.6.10, Nov 21, 2019 - https://core.tcl-lang.org/tk/ for details
143143 .PP
144144 .CS
145145 static const Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
146 Tk_CanvasTagsPrintProc, (ClientData) NULL
146 Tk_CanvasTagsPrintProc, NULL
147147 };
148148
149149 static const Tk_ConfigSpec configSpecs[] = {
3030 The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR;
3131 this mechanism only works in programs that dispatch events
3232 through \fBTk_HandleEvent\fR (or through other Tk procedures that
33 call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or
33 call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or
3434 \fBTk_MainLoop\fR).
3535 .PP
3636 \fIProc\fR should have arguments and result that match the
3737 The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR;
3838 this mechanism only works in programs that dispatch events
3939 through \fBTk_HandleEvent\fR (or through other Tk procedures that
40 call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or
40 call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or
4141 \fBTk_MainLoop\fR).
4242 .PP
4343 \fIProc\fR should have arguments and result that match the
3737 The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR;
3838 this mechanism only works in programs that dispatch events
3939 through \fBTk_HandleEvent\fR (or through other Tk procedures that
40 call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or
40 call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or
4141 \fBTk_MainLoop\fR).
4242 .PP
4343 \fIProc\fR should have arguments and result that match the
1414 \fB#include <tk.h>\fR
1515 .sp
1616 int
17 \fBTk_GetScrollInfoObj(\fIinterp, objc, objv, dblPtr, intPtr\fB)\fR
17 \fBTk_GetScrollInfoObj(\fIinterp, objc, objv, fractionPtr, stepsPtr\fB)\fR
1818 .sp
1919 int
20 \fBTk_GetScrollInfo(\fIinterp, argc, argv, dblPtr, intPtr\fB)\fR
20 \fBTk_GetScrollInfo(\fIinterp, argc, argv, fractionPtr, stepsPtr\fB)\fR
2121 .SH ARGUMENTS
2222 .AS "Tcl_Interp" *fractionPtr
2323 .AP Tcl_Interp *interp in
2424 .PP
2525 \fBTk_HandleEvent\fR is a lower-level procedure that deals with window
2626 events. It is called by \fBTcl_ServiceEvent\fR (and indirectly by
27 \fBTk_DoOneEvent\fR), and in a few other cases within Tk.
27 \fBTcl_DoOneEvent\fR), and in a few other cases within Tk.
2828 It makes callbacks to any window event
2929 handlers (created by calls to \fBTk_CreateEventHandler\fR)
3030 that match \fIeventPtr\fR and then returns. In some cases
4545 When \fBTk_MoveToplevelWindow\fR is called it does not immediately
4646 pass on the new desired location to the window manager; it defers
4747 this action until all other outstanding work has been completed,
48 using the \fBTk_DoWhenIdle\fR mechanism.
48 using the \fBTcl_DoWhenIdle\fR mechanism.
4949 .SH KEYWORDS
5050 position, top-level window, window manager
22 '\"
33 '\" See the file "license.terms" for information on usage and redistribution
44 '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
5 '\"
5 '\"
66 .TH Tk_NameOfImage 3 4.0 Tk "Tk Library Procedures"
77 .so man.macros
88 .BS
1313 \fB#include <tk.h>\fR
1414 .sp
1515 const char *
16 \fBTk_NameOfImage\fR(\fItypePtr\fR)
16 \fBTk_NameOfImage\fR(\fIimageMaster\fR)
1717 .SH ARGUMENTS
18 .AS Tk_ImageMaster *masterPtr
19 .AP Tk_ImageMaster *masterPtr in
18 .AS Tk_ImageMaster imageMaster
19 .AP Tk_ImageMaster imageMaster in
2020 Token for image, which was passed to image manager's \fIcreateProc\fR when
2121 the image was created.
2222 .BE
313313 Tk_ArgvInfo argTable[] = {
314314 {"\-X", TK_ARGV_CONSTANT, (char *) 1, (char *) &debugFlag,
315315 "Turn on debugging printfs"},
316 {"\-N", TK_ARGV_INT, (char *) NULL, (char *) &numReps,
316 {"\-N", TK_ARGV_INT, NULL, (char *) &numReps,
317317 "Number of repetitions"},
318 {"\-of", TK_ARGV_STRING, (char *) NULL, (char *) &fileName,
318 {"\-of", TK_ARGV_STRING, NULL, (char *) &fileName,
319319 "Name of file for output"},
320 {"x", TK_ARGV_REST, (char *) NULL, (char *) &exec,
320 {"x", TK_ARGV_REST, NULL, (char *) &exec,
321321 "File to exec, followed by any arguments (must be last argument)."},
322 {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,
323 (char *) NULL}
322 {NULL, TK_ARGV_END, NULL, NULL,
323 NULL}
324324 };
325325
326326 main(argc, argv)
2929 .PP
3030 This procedure is useful in certain situations where applications
3131 are only prepared to receive certain X events. After
32 \fBTk_RestrictEvents\fR is called, \fBTk_DoOneEvent\fR (and
32 \fBTk_RestrictEvents\fR is called, \fBTcl_DoOneEvent\fR (and
3333 hence \fBTk_MainLoop\fR) will filter X input events through
3434 \fIproc\fR. \fIProc\fR indicates whether a
3535 given event is to be processed immediately, deferred until some
4747 information it needs to filter events. The \fIeventPtr\fR points to
4848 an event under consideration. \fIProc\fR returns a restrict action
4949 (enumerated type \fBTk_RestrictAction\fR) that indicates what
50 \fBTk_DoOneEvent\fR should do with the event. If the return value is
50 \fBTcl_DoOneEvent\fR should do with the event. If the return value is
5151 \fBTK_PROCESS_EVENT\fR, then the event will be handled immediately.
5252 If the return value is \fBTK_DEFER_EVENT\fR, then the event will be
5353 left on the event queue for later processing. If the return value is
7373 \fBXWindowEvent\fR, but these procedures cannot be used because
7474 Tk keeps its own event queue that is separate from the X event
7575 queue. Instead, call \fBTk_RestrictEvents\fR to set up a filter,
76 then call \fBTk_DoOneEvent\fR to retrieve the desired event(s).
76 then call \fBTcl_DoOneEvent\fR to retrieve the desired event(s).
7777 .SH KEYWORDS
7878 delay, event, filter, restriction
5555 will be identical to the \fIinstanceData\fR parameter passed to
5656 \fBTk_SetClassProcs\fR.
5757 .PP
58 \fIcreateProc\fR is used to create platform-dependant windows. It is
58 \fIcreateProc\fR is used to create platform-dependent windows. It is
5959 invoked by \fBTk_MakeWindowExist\fR. \fIcreateProc\fR should have
6060 arguments and results that match the type \fBTk_ClassCreateProc\fR:
6161 .CS
44 '\"
55 '\" See the file "license.terms" for information on usage and redistribution
66 '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
7 '\"
7 '\"
88 .TH bind n 8.0 Tk "Tk Built-In Commands"
99 .so man.macros
1010 .BS
565565 If a virtual-root window manager is being used then the substituted
566566 values are the corresponding x-coordinate and y-coordinate in the virtual root.
567567 Valid only for
568 \fBButtonPress\fR, \fBButtonRelease\fR, \fBKeyPress\fR, \fBKeyRelease\fR,
569 and \fBMotion\fR events.
568 \fBButtonPress\fR, \fBButtonRelease\fR, \fBEnter\fR, \fBKeyPress\fR,
569 \fBKeyRelease\fR, \fBLeave\fR and \fBMotion\fR events.
570570 Same meaning as \fB%x\fR and \fB%y\fR, except relative to the (virtual) root
571571 window.
572572 .LP
637637 .IP (c)
638638 if the modifiers specified in one pattern are a subset of the
639639 modifiers in another pattern, then the pattern with more modifiers
640 is more specific.
640 is more specific;
641641 .IP (d)
642642 a virtual event whose physical pattern matches the sequence is less
643643 specific than the same physical pattern that is not associated with a
644 virtual event.
644 virtual event;
645645 .IP (e)
646646 given a sequence that matches two or more virtual events, one
647647 of the virtual events will be chosen, but the order is undefined.
12181218 Specifies the color to be used to fill item's area.
12191219 in its normal, active, and disabled states,
12201220 \fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR.
1221 If \fIcolor\fR is an empty string (the default),
1222 then the item will not be filled.
12231221 For the line item, it specifies the color of the line drawn.
12241222 For the text item, it specifies the foreground color of the text.
1223 If \fIcolor\fR is an empty string (the default for all canvas items
1224 except line and text), then the item will not be filled.
12251225 .TP
12261226 \fB\-outline \fIcolor\fR
12271227 .TP
12321232 This option specifies the color that should be used to draw the
12331233 outline of the item in its normal, active and disabled states.
12341234 \fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR.
1235 This option defaults to \fBblack\fR. If \fIcolor\fR is specified
1236 as an empty string then no outline is drawn for the item.
1235 If \fIcolor\fR is specified as an empty string then no outline is drawn
1236 for the item.
12371237 .TP
12381238 \fB\-offset \fIoffset\fR
12391239 .
14411441 Specifies the color to use for each of the bitmap's
14421442 .QW 1
14431443 valued pixels in its normal, active and disabled states.
1444 \fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR and
1445 defaults to \fBblack\fR.
1444 \fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR.
14461445 .SS "IMAGE ITEMS"
14471446 .PP
14481447 Items of type \fBimage\fR are used to display images on a
783783 .TP
784784 \fBMac OS X\fR
785785 .
786 On Mac OS X, the following additional system colors are available
787 (note that the actual color values depend on the currently active OS theme,
788 and typically many of these will in fact be patterns rather than pure colors):
786 On macOS, the following additional system colors are available.
787 This first group contains all colors available in the HIToolbox library.
788 (Note that in some cases the actual color values may depend on the
789 current Appearance.)
789790 .RS
790791 .DS
791792 systemActiveAreaFill
899900 systemScrollBarDelimiterInactive
900901 systemSecondaryGroupBoxBackground
901902 systemSecondaryHighlightColor
903 systemSelectedTabTextColor
902904 systemSheetBackground
903905 systemSheetBackgroundOpaque
904906 systemSheetBackgroundTransparent
924926 systemWindowHeaderInactiveText
925927 .DE
926928 .RE
929 .
930 The second group of MacOS colors below are based on Apple's "semantic"
931 NScolors. On OSX 10.14 (Mojave) and later these colors change value
932 when Dark Mode is enabled. However, the change is only observable
933 when the Apple window manager is drawing to the screen. So the
934 \fBwinfo rgb\fR command will return the color coordinates used in the
935 standard Aqua mode, even if Dark Mode has been selected in the system
936 preferences. The numbered systemWindowBackgroundColors are used in
937 the \fBttk::notebook\fR and \fBttk::labelframe\fR widgets to provide a
938 contrasting background. Each numbered color constrasts with its
939 predecessor.
940 .RS
941 .DS
942 systemControlAccentColor
943 systemControlTextColor
944 systemDisabledControlTextColor
945 systemLabelColor
946 systemSelectedTextBackgroundColor
947 systemSelectedTextColor
948 systemTextBackgroundColor
949 systemTextColor
950 systemWindowBackgroundColor
951 systemWindowBackgroundColor1
952 systemWindowBackgroundColor2
953 systemWindowBackgroundColor3
954 systemWindowBackgroundColor4
955 systemWindowBackgroundColor5
956 systemWindowBackgroundColor6
957 systemWindowBackgroundColor7
958 .DE
959 .RE
927960 .TP
961
962
928963 \fBWindows\fR
929964 .
930965 On Windows, the following additional system colors are available
238238 .TP
239239 \fB\-time\fI integer\fR
240240 \fIInteger\fR must be an integer value; it specifies the \fItime\fR field
241 for the event.
241 for the event. Additonally the special value \fBcurrent\fR is allowed,
242 this value will be substituted by the current event time.
242243 Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR,
243244 \fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, \fBMotion\fR,
244245 and \fBProperty\fR events.
9898 name is the same as the path name of the frame's window. This
9999 command may be used to invoke various
100100 operations on the widget. It has the following general form:
101 .PP
101102 .CS
102103 \fIpathName option \fR?\fIarg arg ...\fR?
103104 .CE
105 .PP
104106 \fIPathName\fR is the name of the command, which is the same as
105107 the frame widget's path name. \fIOption\fR and the \fIarg\fRs
106108 determine the exact behavior of the command. The following
107109 commands are possible for frame widgets:
108110 .TP
109111 \fIpathName \fBcget\fR \fIoption\fR
112 .
110113 Returns the current value of the configuration option given
111114 by \fIoption\fR.
112115 \fIOption\fR may have any of the values accepted by the \fBframe\fR
113116 command.
114117 .TP
115118 \fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR?
119 .
116120 Query or modify the configuration options of the widget.
117121 If no \fIoption\fR is specified, returns a list describing all of
118122 the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
5959 The \fBfocus\fR command is still used to determine which window in the
6060 application receives the keyboard events.
6161 The keyboard grab is released when the grab is released.
62 .PP
63 On macOS a global grab affects all windows created by one Tk process.
64 No window in that process other than the grab window can even be
65 focused, hence no other window receives key or mouse events. A local
66 grab on macOS affects all windows created by one Tcl interpreter. It
67 is possible to focus any window belonging to the Tk process during a
68 local grab but the grab window is the only window created by its
69 interpreter which receives key or mouse events. Windows belonging to the
70 same process but created by different interpreters continue to receive
71 key and mouse events normally.
6272 .PP
6373 Grabs apply to particular displays. If an application has windows
6474 on multiple displays then it can establish a separate grab on each
440440 .PP
441441 .CS
442442 button .b \-text "Foo"
443 entry .e \-variable foo
443 entry .e \-textvariable foo ; set foo "Hello World!"
444444 label .l \-text "This is a fairly long piece of text"
445445
446446 \fBgrid\fR .b .e .l \-sticky ew
1717 be valid on all platforms, and some keysyms are also available on
1818 platforms that have a different native name for that key.
1919 For example, on Unix systems, the presence
20 of a particular keysym is dependant on the configuration of the
20 of a particular keysym is dependent on the configuration of the
2121 keyboard modifier map. This list shows keysyms along with their
2222 decimal and hexadecimal values.
2323 .PP
2424 .CS
25 space 32 0x0020
26 exclam 33 0x0021
27 quotedbl 34 0x0022
28 numbersign 35 0x0023
29 dollar 36 0x0024
30 percent 37 0x0025
31 ampersand 38 0x0026
32 quoteright 39 0x0027
33 parenleft 40 0x0028
34 parenright 41 0x0029
35 asterisk 42 0x002a
36 plus 43 0x002b
37 comma 44 0x002c
38 minus 45 0x002d
39 period 46 0x002e
40 slash 47 0x002f
41 0 48 0x0030
42 1 49 0x0031
43 2 50 0x0032
44 3 51 0x0033
45 4 52 0x0034
46 5 53 0x0035
47 6 54 0x0036
48 7 55 0x0037
49 8 56 0x0038
50 9 57 0x0039
51 colon 58 0x003a
52 semicolon 59 0x003b
53 less 60 0x003c
54 equal 61 0x003d
55 greater 62 0x003e
56 question 63 0x003f
57 at 64 0x0040
58 A 65 0x0041
59 B 66 0x0042
60 C 67 0x0043
61 D 68 0x0044
62 E 69 0x0045
63 F 70 0x0046
64 G 71 0x0047
65 H 72 0x0048
66 I 73 0x0049
67 J 74 0x004a
68 K 75 0x004b
69 L 76 0x004c
70 M 77 0x004d
71 N 78 0x004e
72 O 79 0x004f
73 P 80 0x0050
74 Q 81 0x0051
75 R 82 0x0052
76 S 83 0x0053
77 T 84 0x0054
78 U 85 0x0055
79 V 86 0x0056
80 W 87 0x0057
81 X 88 0x0058
82 Y 89 0x0059
83 Z 90 0x005a
84 bracketleft 91 0x005b
85 backslash 92 0x005c
86 bracketright 93 0x005d
87 asciicircum 94 0x005e
88 underscore 95 0x005f
89 quoteleft 96 0x0060
90 a 97 0x0061
91 b 98 0x0062
92 c 99 0x0063
93 d 100 0x0064
94 e 101 0x0065
95 f 102 0x0066
96 g 103 0x0067
97 h 104 0x0068
98 i 105 0x0069
99 j 106 0x006a
100 k 107 0x006b
101 l 108 0x006c
102 m 109 0x006d
103 n 110 0x006e
104 o 111 0x006f
105 p 112 0x0070
106 q 113 0x0071
107 r 114 0x0072
108 s 115 0x0073
109 t 116 0x0074
110 u 117 0x0075
111 v 118 0x0076
112 w 119 0x0077
113 x 120 0x0078
114 y 121 0x0079
115 z 122 0x007a
116 braceleft 123 0x007b
117 bar 124 0x007c
118 braceright 125 0x007d
119 asciitilde 126 0x007e
120 nobreakspace 160 0x00a0
121 exclamdown 161 0x00a1
122 cent 162 0x00a2
123 sterling 163 0x00a3
124 currency 164 0x00a4
125 yen 165 0x00a5
126 brokenbar 166 0x00a6
127 section 167 0x00a7
128 diaeresis 168 0x00a8
129 copyright 169 0x00a9
130 ordfeminine 170 0x00aa
131 guillemotleft 171 0x00ab
132 notsign 172 0x00ac
133 hyphen 173 0x00ad
134 registered 174 0x00ae
135 macron 175 0x00af
136 degree 176 0x00b0
137 plusminus 177 0x00b1
138 twosuperior 178 0x00b2
139 threesuperior 179 0x00b3
140 acute 180 0x00b4
141 mu 181 0x00b5
142 paragraph 182 0x00b6
143 periodcentered 183 0x00b7
144 cedilla 184 0x00b8
145 onesuperior 185 0x00b9
146 masculine 186 0x00ba
147 guillemotright 187 0x00bb
148 onequarter 188 0x00bc
149 onehalf 189 0x00bd
150 threequarters 190 0x00be
151 questiondown 191 0x00bf
152 Agrave 192 0x00c0
153 Aacute 193 0x00c1
154 Acircumflex 194 0x00c2
155 Atilde 195 0x00c3
156 Adiaeresis 196 0x00c4
157 Aring 197 0x00c5
158 AE 198 0x00c6
159 Ccedilla 199 0x00c7
160 Egrave 200 0x00c8
161 Eacute 201 0x00c9
162 Ecircumflex 202 0x00ca
163 Ediaeresis 203 0x00cb
164 Igrave 204 0x00cc
165 Iacute 205 0x00cd
166 Icircumflex 206 0x00ce
167 Idiaeresis 207 0x00cf
168 Eth 208 0x00d0
169 Ntilde 209 0x00d1
170 Ograve 210 0x00d2
171 Oacute 211 0x00d3
172 Ocircumflex 212 0x00d4
173 Otilde 213 0x00d5
174 Odiaeresis 214 0x00d6
175 multiply 215 0x00d7
176 Ooblique 216 0x00d8
177 Ugrave 217 0x00d9
178 Uacute 218 0x00da
179 Ucircumflex 219 0x00db
180 Udiaeresis 220 0x00dc
181 Yacute 221 0x00dd
182 Thorn 222 0x00de
183 ssharp 223 0x00df
184 agrave 224 0x00e0
185 aacute 225 0x00e1
186 acircumflex 226 0x00e2
187 atilde 227 0x00e3
188 adiaeresis 228 0x00e4
189 aring 229 0x00e5
190 ae 230 0x00e6
191 ccedilla 231 0x00e7
192 egrave 232 0x00e8
193 eacute 233 0x00e9
194 ecircumflex 234 0x00ea
195 ediaeresis 235 0x00eb
196 igrave 236 0x00ec
197 iacute 237 0x00ed
198 icircumflex 238 0x00ee
199 idiaeresis 239 0x00ef
200 eth 240 0x00f0
201 ntilde 241 0x00f1
202 ograve 242 0x00f2
203 oacute 243 0x00f3
204 ocircumflex 244 0x00f4
205 otilde 245 0x00f5
206 odiaeresis 246 0x00f6
207 division 247 0x00f7
208 oslash 248 0x00f8
209 ugrave 249 0x00f9
210 uacute 250 0x00fa
211 ucircumflex 251 0x00fb
212 udiaeresis 252 0x00fc
213 yacute 253 0x00fd
214 thorn 254 0x00fe
215 ydiaeresis 255 0x00ff
216 Aogonek 417 0x01a1
217 breve 418 0x01a2
218 Lstroke 419 0x01a3
219 Lcaron 421 0x01a5
220 Sacute 422 0x01a6
221 Scaron 425 0x01a9
222 Scedilla 426 0x01aa
223 Tcaron 427 0x01ab
224 Zacute 428 0x01ac
25 space 32 0x20
26 exclam 33 0x21
27 quotedbl 34 0x22
28 numbersign 35 0x23
29 dollar 36 0x24
30 percent 37 0x25
31 ampersand 38 0x26
32 apostrophe 39 0x27
33 parenleft 40 0x28
34 parenright 41 0x29
35 asterisk 42 0x2A
36 plus 43 0x2B
37 comma 44 0x2C
38 minus 45 0x2D
39 period 46 0x2E
40 slash 47 0x2F
41 0 48 0x30
42 1 49 0x31
43 2 50 0x32
44 3 51 0x33
45 4 52 0x34
46 5 53 0x35
47 6 54 0x36
48 7 55 0x37
49 8 56 0x38
50 9 57 0x39
51 colon 58 0x3A
52 semicolon 59 0x3B
53 less 60 0x3C
54 equal 61 0x3D
55 greater 62 0x3E
56 question 63 0x3F
57 at 64 0x40
58 A 65 0x41
59 B 66 0x42
60 C 67 0x43
61 D 68 0x44
62 E 69 0x45
63 F 70 0x46
64 G 71 0x47
65 H 72 0x48
66 I 73 0x49
67 J 74 0x4A
68 K 75 0x4B
69 L 76 0x4C
70 M 77 0x4D
71 N 78 0x4E
72 O 79 0x4F
73 P 80 0x50
74 Q 81 0x51
75 R 82 0x52
76 S 83 0x53
77 T 84 0x54
78 U 85 0x55
79 V 86 0x56
80 W 87 0x57
81 X 88 0x58
82 Y 89 0x59
83 Z 90 0x5A
84 bracketleft 91 0x5B
85 backslash 92 0x5C
86 bracketright 93 0x5D
87 asciicircum 94 0x5E
88 underscore 95 0x5F
89 grave 96 0x60
90 a 97 0x61
91 b 98 0x62
92 c 99 0x63
93 d 100 0x64
94 e 101 0x65
95 f 102 0x66
96 g 103 0x67
97 h 104 0x68
98 i 105 0x69
99 j 106 0x6A
100 k 107 0x6B
101 l 108 0x6C
102 m 109 0x6D
103 n 110 0x6E
104 o 111 0x6F
105 p 112 0x70
106 q 113 0x71
107 r 114 0x72
108 s 115 0x73
109 t 116 0x74
110 u 117 0x75
111 v 118 0x76
112 w 119 0x77
113 x 120 0x78
114 y 121 0x79
115 z 122 0x7A
116 braceleft 123 0x7B
117 bar 124 0x7C
118 braceright 125 0x7D
119 asciitilde 126 0x7E
120 nobreakspace 160 0xA0
121 exclamdown 161 0xA1
122 cent 162 0xA2
123 sterling 163 0xA3
124 currency 164 0xA4
125 yen 165 0xA5
126 brokenbar 166 0xA6
127 section 167 0xA7
128 diaeresis 168 0xA8
129 copyright 169 0xA9
130 ordfeminine 170 0xAA
131 guillemotleft 171 0xAB
132 notsign 172 0xAC
133 hyphen 173 0xAD
134 registered 174 0xAE
135 macron 175 0xAF
136 degree 176 0xB0
137 plusminus 177 0xB1
138 twosuperior 178 0xB2
139 threesuperior 179 0xB3
140 acute 180 0xB4
141 mu 181 0xB5
142 paragraph 182 0xB6
143 periodcentered 183 0xB7
144 cedilla 184 0xB8
145 onesuperior 185 0xB9
146 masculine 186 0xBA
147 guillemotright 187 0xBB
148 onequarter 188 0xBC
149 onehalf 189 0xBD
150 threequarters 190 0xBE
151 questiondown 191 0xBF
152 Agrave 192 0xC0
153 Aacute 193 0xC1
154 Acircumflex 194 0xC2
155 Atilde 195 0xC3
156 Adiaeresis 196 0xC4
157 Aring 197 0xC5
158 AE 198 0xC6
159 Ccedilla 199 0xC7
160 Egrave 200 0xC8
161 Eacute 201 0xC9
162 Ecircumflex 202 0xCA
163 Ediaeresis 203 0xCB
164 Igrave 204 0xCC
165 Iacute 205 0xCD
166 Icircumflex 206 0xCE
167 Idiaeresis 207 0xCF
168 ETH 208 0xD0
169 Ntilde 209 0xD1
170 Ograve 210 0xD2
171 Oacute 211 0xD3
172 Ocircumflex 212 0xD4
173 Otilde 213 0xD5
174 Odiaeresis 214 0xD6
175 multiply 215 0xD7
176 Oslash 216 0xD8
177 Ugrave 217 0xD9
178 Uacute 218 0xDA
179 Ucircumflex 219 0xDB
180 Udiaeresis 220 0xDC
181 Yacute 221 0xDD
182 THORN 222 0xDE
183 ssharp 223 0xDF
184 agrave 224 0xE0
185 aacute 225 0xE1
186 acircumflex 226 0xE2
187 atilde 227 0xE3
188 adiaeresis 228 0xE4
189 aring 229 0xE5
190 ae 230 0xE6
191 ccedilla 231 0xE7
192 egrave 232 0xE8
193 eacute 233 0xE9
194 ecircumflex 234 0xEA
195 ediaeresis 235 0xEB
196 igrave 236 0xEC
197 iacute 237 0xED
198 icircumflex 238 0xEE
199 idiaeresis 239 0xEF
200 eth 240 0xF0
201 ntilde 241 0xF1
202 ograve 242 0xF2
203 oacute 243 0xF3
204 ocircumflex 244 0xF4
205 otilde 245 0xF5
206 odiaeresis 246 0xF6
207 division 247 0xF7
208 oslash 248 0xF8
209 ugrave 249 0xF9
210 uacute 250 0xFA
211 ucircumflex 251 0xFB
212 udiaeresis 252 0xFC
213 yacute 253 0xFD
214 thorn 254 0xFE
215 ydiaeresis 255 0xFF
216 Aogonek 417 0x1A1
217 breve 418 0x1A2
218 Lstroke 419 0x1A3
219 Lcaron 421 0x1A5
220 Sacute 422 0x1A6
221 Scaron 425 0x1A9
222 Scedilla 426 0x1AA
223 Tcaron 427 0x1AB
224 Zacute 428 0x1AC
225225 .CE
226226 .CS
227 Zcaron 430 0x01ae
228 Zabovedot 431 0x01af
229 aogonek 433 0x01b1
230 ogonek 434 0x01b2
231 lstroke 435 0x01b3
232 lcaron 437 0x01b5
233 sacute 438 0x01b6
234 caron 439 0x01b7
235 scaron 441 0x01b9
236 scedilla 442 0x01ba
237 tcaron 443 0x01bb
238 zacute 444 0x01bc
239 doubleacute 445 0x01bd
240 zcaron 446 0x01be
241 zabovedot 447 0x01bf
242 Racute 448 0x01c0
243 Abreve 451 0x01c3
244 Cacute 454 0x01c6
245 Ccaron 456 0x01c8
246 Eogonek 458 0x01ca
247 Ecaron 460 0x01cc
248 Dcaron 463 0x01cf
249 Nacute 465 0x01d1
250 Ncaron 466 0x01d2
251 Odoubleacute 469 0x01d5
252 Rcaron 472 0x01d8
253 Uring 473 0x01d9
254 Udoubleacute 475 0x01db
255 Tcedilla 478 0x01de
256 racute 480 0x01e0
257 abreve 483 0x01e3
258 cacute 486 0x01e6
259 ccaron 488 0x01e8
260 eogonek 490 0x01ea
261 ecaron 492 0x01ec
262 dcaron 495 0x01ef
263 nacute 497 0x01f1
264 ncaron 498 0x01f2
265 odoubleacute 501 0x01f5
266 rcaron 504 0x01f8
267 uring 505 0x01f9
268 udoubleacute 507 0x01fb
269 tcedilla 510 0x01fe
270 abovedot 511 0x01ff
271 Hstroke 673 0x02a1
272 Hcircumflex 678 0x02a6
273 Iabovedot 681 0x02a9
274 Gbreve 683 0x02ab
275 Jcircumflex 684 0x02ac
276 hstroke 689 0x02b1
277 hcircumflex 694 0x02b6
278 idotless 697 0x02b9
279 gbreve 699 0x02bb
280 jcircumflex 700 0x02bc
281 Cabovedot 709 0x02c5
282 Ccircumflex 710 0x02c6
283 Gabovedot 725 0x02d5
284 Gcircumflex 728 0x02d8
285 Ubreve 733 0x02dd
286 Scircumflex 734 0x02de
287 cabovedot 741 0x02e5
288 ccircumflex 742 0x02e6
289 gabovedot 757 0x02f5
290 gcircumflex 760 0x02f8
291 ubreve 765 0x02fd
292 scircumflex 766 0x02fe
293 kappa 930 0x03a2
294 Rcedilla 931 0x03a3
295 Itilde 933 0x03a5
296 Lcedilla 934 0x03a6
297 Emacron 938 0x03aa
298 Gcedilla 939 0x03ab
299 Tslash 940 0x03ac
300 rcedilla 947 0x03b3
301 itilde 949 0x03b5
302 lcedilla 950 0x03b6
303 emacron 954 0x03ba
304 gacute 955 0x03bb
305 tslash 956 0x03bc
306 ENG 957 0x03bd
307 eng 959 0x03bf
308 Amacron 960 0x03c0
309 Iogonek 967 0x03c7
310 Eabovedot 972 0x03cc
311 Imacron 975 0x03cf
312 Ncedilla 977 0x03d1
313 Omacron 978 0x03d2
314 Kcedilla 979 0x03d3
315 Uogonek 985 0x03d9
316 Utilde 989 0x03dd
317 Umacron 990 0x03de
318 amacron 992 0x03e0
319 iogonek 999 0x03e7
320 eabovedot 1004 0x03ec
321 imacron 1007 0x03ef
322 ncedilla 1009 0x03f1
323 omacron 1010 0x03f2
324 kcedilla 1011 0x03f3
325 uogonek 1017 0x03f9
326 utilde 1021 0x03fd
327 umacron 1022 0x03fe
328 overline 1150 0x047e
329 kana_fullstop 1185 0x04a1
330 kana_openingbracket 1186 0x04a2
331 kana_closingbracket 1187 0x04a3
332 kana_comma 1188 0x04a4
333 kana_middledot 1189 0x04a5
334 kana_WO 1190 0x04a6
335 kana_a 1191 0x04a7
336 kana_i 1192 0x04a8
337 kana_u 1193 0x04a9
338 kana_e 1194 0x04aa
339 kana_o 1195 0x04ab
340 kana_ya 1196 0x04ac
341 kana_yu 1197 0x04ad
342 kana_yo 1198 0x04ae
343 kana_tu 1199 0x04af
344 prolongedsound 1200 0x04b0
345 kana_A 1201 0x04b1
346 kana_I 1202 0x04b2
347 kana_U 1203 0x04b3
348 kana_E 1204 0x04b4
349 kana_O 1205 0x04b5
350 kana_KA 1206 0x04b6
351 kana_KI 1207 0x04b7
352 kana_KU 1208 0x04b8
353 kana_KE 1209 0x04b9
354 kana_KO 1210 0x04ba
355 kana_SA 1211 0x04bb
356 kana_SHI 1212 0x04bc
357 kana_SU 1213 0x04bd
358 kana_SE 1214 0x04be
359 kana_SO 1215 0x04bf
360 kana_TA 1216 0x04c0
361 kana_TI 1217 0x04c1
362 kana_TU 1218 0x04c2
363 kana_TE 1219 0x04c3
364 kana_TO 1220 0x04c4
365 kana_NA 1221 0x04c5
366 kana_NI 1222 0x04c6
367 kana_NU 1223 0x04c7
368 kana_NE 1224 0x04c8
369 kana_NO 1225 0x04c9
370 kana_HA 1226 0x04ca
371 kana_HI 1227 0x04cb
372 kana_HU 1228 0x04cc
373 kana_HE 1229 0x04cd
374 kana_HO 1230 0x04ce
375 kana_MA 1231 0x04cf
376 kana_MI 1232 0x04d0
377 kana_MU 1233 0x04d1
378 kana_ME 1234 0x04d2
379 kana_MO 1235 0x04d3
380 kana_YA 1236 0x04d4
381 kana_YU 1237 0x04d5
382 kana_YO 1238 0x04d6
383 kana_RA 1239 0x04d7
384 kana_RI 1240 0x04d8
385 kana_RU 1241 0x04d9
386 kana_RE 1242 0x04da
387 kana_RO 1243 0x04db
388 kana_WA 1244 0x04dc
389 kana_N 1245 0x04dd
390 voicedsound 1246 0x04de
391 semivoicedsound 1247 0x04df
392 Arabic_comma 1452 0x05ac
393 Arabic_semicolon 1467 0x05bb
394 Arabic_question_mark 1471 0x05bf
395 Arabic_hamza 1473 0x05c1
396 Arabic_maddaonalef 1474 0x05c2
397 Arabic_hamzaonalef 1475 0x05c3
398 Arabic_hamzaonwaw 1476 0x05c4
399 Arabic_hamzaunderalef 1477 0x05c5
400 Arabic_hamzaonyeh 1478 0x05c6
401 Arabic_alef 1479 0x05c7
402 Arabic_beh 1480 0x05c8
403 Arabic_tehmarbuta 1481 0x05c9
404 Arabic_teh 1482 0x05ca
405 Arabic_theh 1483 0x05cb
406 Arabic_jeem 1484 0x05cc
407 Arabic_hah 1485 0x05cd
408 Arabic_khah 1486 0x05ce
409 Arabic_dal 1487 0x05cf
410 Arabic_thal 1488 0x05d0
411 Arabic_ra 1489 0x05d1
412 Arabic_zain 1490 0x05d2
413 Arabic_seen 1491 0x05d3
414 Arabic_sheen 1492 0x05d4
415 Arabic_sad 1493 0x05d5
416 Arabic_dad 1494 0x05d6
417 Arabic_tah 1495 0x05d7
418 Arabic_zah 1496 0x05d8
419 Arabic_ain 1497 0x05d9
420 Arabic_ghain 1498 0x05da
421 Arabic_tatweel 1504 0x05e0
422 Arabic_feh 1505 0x05e1
423 Arabic_qaf 1506 0x05e2
424 Arabic_kaf 1507 0x05e3
425 Arabic_lam 1508 0x05e4
426 Arabic_meem 1509 0x05e5
227 Zcaron 430 0x1AE
228 Zabovedot 431 0x1AF
229 aogonek 433 0x1B1
230 ogonek 434 0x1B2
231 lstroke 435 0x1B3
232 lcaron 437 0x1B5
233 sacute 438 0x1B6
234 caron 439 0x1B7
235 scaron 441 0x1B9
236 scedilla 442 0x1BA
237 tcaron 443 0x1BB
238 zacute 444 0x1BC
239 doubleacute 445 0x1BD
240 zcaron 446 0x1BE
241 zabovedot 447 0x1BF
242 Racute 448 0x1C0
243 Abreve 451 0x1C3
244 Lacute 453 0x1C5
245 Cacute 454 0x1C6
246 Ccaron 456 0x1C8
247 Eogonek 458 0x1CA
248 Ecaron 460 0x1CC
249 Dcaron 463 0x1CF
250 Dstroke 464 0x1D0
251 Nacute 465 0x1D1
252 Ncaron 466 0x1D2
253 Odoubleacute 469 0x1D5
254 Rcaron 472 0x1D8
255 Uring 473 0x1D9
256 Udoubleacute 475 0x1DB
257 Tcedilla 478 0x1DE
258 racute 480 0x1E0
259 abreve 483 0x1E3
260 lacute 485 0x1E5
261 cacute 486 0x1E6
262 ccaron 488 0x1E8
263 eogonek 490 0x1EA
264 ecaron 492 0x1EC
265 dcaron 495 0x1EF
266 dstroke 496 0x1F0
267 nacute 497 0x1F1
268 ncaron 498 0x1F2
269 odoubleacute 501 0x1F5
270 rcaron 504 0x1F8
271 uring 505 0x1F9
272 udoubleacute 507 0x1FB
273 tcedilla 510 0x1FE
274 abovedot 511 0x1FF
275 Hstroke 673 0x2A1
276 Hcircumflex 678 0x2A6
277 Iabovedot 681 0x2A9
278 Gbreve 683 0x2AB
279 Jcircumflex 684 0x2AC
280 hstroke 689 0x2B1
281 hcircumflex 694 0x2B6
282 idotless 697 0x2B9
283 gbreve 699 0x2BB
284 jcircumflex 700 0x2BC
285 Cabovedot 709 0x2C5
286 Ccircumflex 710 0x2C6
287 Gabovedot 725 0x2D5
288 Gcircumflex 728 0x2D8
289 Ubreve 733 0x2DD
290 Scircumflex 734 0x2DE
291 cabovedot 741 0x2E5
292 ccircumflex 742 0x2E6
293 gabovedot 757 0x2F5
294 gcircumflex 760 0x2F8
295 ubreve 765 0x2FD
296 scircumflex 766 0x2FE
297 kra 930 0x3A2
298 Rcedilla 931 0x3A3
299 Itilde 933 0x3A5
300 Lcedilla 934 0x3A6
301 Emacron 938 0x3AA
302 Gcedilla 939 0x3AB
303 Tslash 940 0x3AC
304 rcedilla 947 0x3B3
305 itilde 949 0x3B5
306 lcedilla 950 0x3B6
307 emacron 954 0x3BA
308 gcedilla 955 0x3BB
309 tslash 956 0x3BC
310 ENG 957 0x3BD
311 eng 959 0x3BF
312 Amacron 960 0x3C0
313 Iogonek 967 0x3C7
314 Eabovedot 972 0x3CC
315 Imacron 975 0x3CF
316 Ncedilla 977 0x3D1
317 Omacron 978 0x3D2
318 Kcedilla 979 0x3D3
319 Uogonek 985 0x3D9
320 Utilde 989 0x3DD
321 Umacron 990 0x3DE
322 amacron 992 0x3E0
323 iogonek 999 0x3E7
324 eabovedot 1004 0x3EC
325 imacron 1007 0x3EF
326 ncedilla 1009 0x3F1
327 omacron 1010 0x3F2
328 kcedilla 1011 0x3F3
329 uogonek 1017 0x3F9
330 utilde 1021 0x3FD
331 umacron 1022 0x3FE
332 overline 1150 0x47E
333 kana_fullstop 1185 0x4A1
334 kana_openingbracket 1186 0x4A2
335 kana_closingbracket 1187 0x4A3
336 kana_comma 1188 0x4A4
337 kana_conjunctive 1189 0x4A5
338 kana_WO 1190 0x4A6
339 kana_a 1191 0x4A7
340 kana_i 1192 0x4A8
341 kana_u 1193 0x4A9
342 kana_e 1194 0x4AA
343 kana_o 1195 0x4AB
344 kana_ya 1196 0x4AC
345 kana_yu 1197 0x4AD
346 kana_yo 1198 0x4AE
347 kana_tsu 1199 0x4AF
348 prolongedsound 1200 0x4B0
349 kana_A 1201 0x4B1
350 kana_I 1202 0x4B2
351 kana_U 1203 0x4B3
352 kana_E 1204 0x4B4
353 kana_O 1205 0x4B5
354 kana_KA 1206 0x4B6
355 kana_KI 1207 0x4B7
356 kana_KU 1208 0x4B8
357 kana_KE 1209 0x4B9
358 kana_KO 1210 0x4BA
359 kana_SA 1211 0x4BB
360 kana_SHI 1212 0x4BC
361 kana_SU 1213 0x4BD
362 kana_SE 1214 0x4BE
363 kana_SO 1215 0x4BF
364 kana_TA 1216 0x4C0
365 kana_CHI 1217 0x4C1
366 kana_TSU 1218 0x4C2
367 kana_TE 1219 0x4C3
368 kana_TO 1220 0x4C4
369 kana_NA 1221 0x4C5
370 kana_NI 1222 0x4C6
371 kana_NU 1223 0x4C7
372 kana_NE 1224 0x4C8
373 kana_NO 1225 0x4C9
374 kana_HA 1226 0x4CA
375 kana_HI 1227 0x4CB
376 kana_FU 1228 0x4CC
377 kana_HE 1229 0x4CD
378 kana_HO 1230 0x4CE
379 kana_MA 1231 0x4CF
380 kana_MI 1232 0x4D0
381 kana_MU 1233 0x4D1
382 kana_ME 1234 0x4D2
383 kana_MO 1235 0x4D3
384 kana_YA 1236 0x4D4
385 kana_YU 1237 0x4D5
386 kana_YO 1238 0x4D6
387 kana_RA 1239 0x4D7
388 kana_RI 1240 0x4D8
389 kana_RU 1241 0x4D9
390 kana_RE 1242 0x4DA
391 kana_RO 1243 0x4DB
392 kana_WA 1244 0x4DC
393 kana_N 1245 0x4DD
394 voicedsound 1246 0x4DE
395 semivoicedsound 1247 0x4DF
396 Arabic_comma 1452 0x5AC
397 Arabic_semicolon 1467 0x5BB
398 Arabic_question_mark 1471 0x5BF
399 Arabic_hamza 1473 0x5C1
400 Arabic_maddaonalef 1474 0x5C2
401 Arabic_hamzaonalef 1475 0x5C3
402 Arabic_hamzaonwaw 1476 0x5C4
403 Arabic_hamzaunderalef 1477 0x5C5
404 Arabic_hamzaonyeh 1478 0x5C6
405 Arabic_alef 1479 0x5C7
406 Arabic_beh 1480 0x5C8
407 Arabic_tehmarbuta 1481 0x5C9
408 Arabic_teh 1482 0x5CA
409 Arabic_theh 1483 0x5CB
410 Arabic_jeem 1484 0x5CC
411 Arabic_hah 1485 0x5CD
412 Arabic_khah 1486 0x5CE
413 Arabic_dal 1487 0x5CF
414 Arabic_thal 1488 0x5D0
415 Arabic_ra 1489 0x5D1
416 Arabic_zain 1490 0x5D2
417 Arabic_seen 1491 0x5D3
418 Arabic_sheen 1492 0x5D4
419 Arabic_sad 1493 0x5D5
420 Arabic_dad 1494 0x5D6
421 Arabic_tah 1495 0x5D7
422 Arabic_zah 1496 0x5D8
423 Arabic_ain 1497 0x5D9
424 Arabic_ghain 1498 0x5DA
425 Arabic_tatweel 1504 0x5E0
426 Arabic_feh 1505 0x5E1
427 Arabic_qaf 1506 0x5E2
428 Arabic_kaf 1507 0x5E3
429 Arabic_lam 1508 0x5E4
430 Arabic_meem 1509 0x5E5
427431 .CE
428432 .CS
429 Arabic_noon 1510 0x05e6
430 Arabic_heh 1511 0x05e7
431 Arabic_waw 1512 0x05e8
432 Arabic_alefmaksura 1513 0x05e9
433 Arabic_yeh 1514 0x05ea
434 Arabic_fathatan 1515 0x05eb
435 Arabic_dammatan 1516 0x05ec
436 Arabic_kasratan 1517 0x05ed
437 Arabic_fatha 1518 0x05ee
438 Arabic_damma 1519 0x05ef
439 Arabic_kasra 1520 0x05f0
440 Arabic_shadda 1521 0x05f1
441 Arabic_sukun 1522 0x05f2
442 Serbian_dje 1697 0x06a1
443 Macedonia_gje 1698 0x06a2
444 Cyrillic_io 1699 0x06a3
445 Ukranian_je 1700 0x06a4
446 Macedonia_dse 1701 0x06a5
447 Ukranian_i 1702 0x06a6
448 Ukranian_yi 1703 0x06a7
449 Serbian_je 1704 0x06a8
450 Serbian_lje 1705 0x06a9
451 Serbian_nje 1706 0x06aa
452 Serbian_tshe 1707 0x06ab
453 Macedonia_kje 1708 0x06ac
454 Byelorussian_shortu 1710 0x06ae
455 Serbian_dze 1711 0x06af
456 numerosign 1712 0x06b0
457 Serbian_DJE 1713 0x06b1
458 Macedonia_GJE 1714 0x06b2
459 Cyrillic_IO 1715 0x06b3
460 Ukranian_JE 1716 0x06b4
461 Macedonia_DSE 1717 0x06b5
462 Ukranian_I 1718 0x06b6
463 Ukranian_YI 1719 0x06b7
464 Serbian_JE 1720 0x06b8
465 Serbian_LJE 1721 0x06b9
466 Serbian_NJE 1722 0x06ba
467 Serbian_TSHE 1723 0x06bb
468 Macedonia_KJE 1724 0x06bc
469 Byelorussian_SHORTU 1726 0x06be
470 Serbian_DZE 1727 0x06bf
471 Cyrillic_yu 1728 0x06c0
472 Cyrillic_a 1729 0x06c1
473 Cyrillic_be 1730 0x06c2
474 Cyrillic_tse 1731 0x06c3
475 Cyrillic_de 1732 0x06c4
476 Cyrillic_ie 1733 0x06c5
477 Cyrillic_ef 1734 0x06c6
478 Cyrillic_ghe 1735 0x06c7
479 Cyrillic_ha 1736 0x06c8
480 Cyrillic_i 1737 0x06c9
481 Cyrillic_shorti 1738 0x06ca
482 Cyrillic_ka 1739 0x06cb
483 Cyrillic_el 1740 0x06cc
484 Cyrillic_em 1741 0x06cd
485 Cyrillic_en 1742 0x06ce
486 Cyrillic_o 1743 0x06cf
487 Cyrillic_pe 1744 0x06d0
488 Cyrillic_ya 1745 0x06d1
489 Cyrillic_er 1746 0x06d2
490 Cyrillic_es 1747 0x06d3
491 Cyrillic_te 1748 0x06d4
492 Cyrillic_u 1749 0x06d5
493 Cyrillic_zhe 1750 0x06d6
494 Cyrillic_ve 1751 0x06d7
495 Cyrillic_softsign 1752 0x06d8
496 Cyrillic_yeru 1753 0x06d9
497 Cyrillic_ze 1754 0x06da
498 Cyrillic_sha 1755 0x06db
499 Cyrillic_e 1756 0x06dc
500 Cyrillic_shcha 1757 0x06dd
501 Cyrillic_che 1758 0x06de
502 Cyrillic_hardsign 1759 0x06df
503 Cyrillic_YU 1760 0x06e0
504 Cyrillic_A 1761 0x06e1
505 Cyrillic_BE 1762 0x06e2
506 Cyrillic_TSE 1763 0x06e3
507 Cyrillic_DE 1764 0x06e4
508 Cyrillic_IE 1765 0x06e5
509 Cyrillic_EF 1766 0x06e6
510 Cyrillic_GHE 1767 0x06e7
511 Cyrillic_HA 1768 0x06e8
512 Cyrillic_I 1769 0x06e9
513 Cyrillic_SHORTI 1770 0x06ea
514 Cyrillic_KA 1771 0x06eb
515 Cyrillic_EL 1772 0x06ec
516 Cyrillic_EM 1773 0x06ed
517 Cyrillic_EN 1774 0x06ee
518 Cyrillic_O 1775 0x06ef
519 Cyrillic_PE 1776 0x06f0
520 Cyrillic_YA 1777 0x06f1
521 Cyrillic_ER 1778 0x06f2
522 Cyrillic_ES 1779 0x06f3
523 Cyrillic_TE 1780 0x06f4
524 Cyrillic_U 1781 0x06f5
525 Cyrillic_ZHE 1782 0x06f6
526 Cyrillic_VE 1783 0x06f7
527 Cyrillic_SOFTSIGN 1784 0x06f8
528 Cyrillic_YERU 1785 0x06f9
529 Cyrillic_ZE 1786 0x06fa
530 Cyrillic_SHA 1787 0x06fb
531 Cyrillic_E 1788 0x06fc
532 Cyrillic_SHCHA 1789 0x06fd
533 Cyrillic_CHE 1790 0x06fe
534 Cyrillic_HARDSIGN 1791 0x06ff
535 Greek_ALPHAaccent 1953 0x07a1
536 Greek_EPSILONaccent 1954 0x07a2
537 Greek_ETAaccent 1955 0x07a3
538 Greek_IOTAaccent 1956 0x07a4
539 Greek_IOTAdiaeresis 1957 0x07a5
540 Greek_IOTAaccentdiaeresis 1958 0x07a6
541 Greek_OMICRONaccent 1959 0x07a7
542 Greek_UPSILONaccent 1960 0x07a8
543 Greek_UPSILONdieresis 1961 0x07a9
544 Greek_UPSILONaccentdieresis 1962 0x07aa
545 Greek_OMEGAaccent 1963 0x07ab
546 Greek_alphaaccent 1969 0x07b1
547 Greek_epsilonaccent 1970 0x07b2
548 Greek_etaaccent 1971 0x07b3
549 Greek_iotaaccent 1972 0x07b4
550 Greek_iotadieresis 1973 0x07b5
551 Greek_iotaaccentdieresis 1974 0x07b6
552 Greek_omicronaccent 1975 0x07b7
553 Greek_upsilonaccent 1976 0x07b8
554 Greek_upsilondieresis 1977 0x07b9
555 Greek_upsilonaccentdieresis 1978 0x07ba
556 Greek_omegaaccent 1979 0x07bb
557 Greek_ALPHA 1985 0x07c1
558 Greek_BETA 1986 0x07c2
559 Greek_GAMMA 1987 0x07c3
560 Greek_DELTA 1988 0x07c4
561 Greek_EPSILON 1989 0x07c5
562 Greek_ZETA 1990 0x07c6
563 Greek_ETA 1991 0x07c7
564 Greek_THETA 1992 0x07c8
565 Greek_IOTA 1993 0x07c9
566 Greek_KAPPA 1994 0x07ca
567 Greek_LAMBDA 1995 0x07cb
568 Greek_MU 1996 0x07cc
569 Greek_NU 1997 0x07cd
570 Greek_XI 1998 0x07ce
571 Greek_OMICRON 1999 0x07cf
572 Greek_PI 2000 0x07d0
573 Greek_RHO 2001 0x07d1
574 Greek_SIGMA 2002 0x07d2
575 Greek_TAU 2004 0x07d4
576 Greek_UPSILON 2005 0x07d5
577 Greek_PHI 2006 0x07d6
578 Greek_CHI 2007 0x07d7
579 Greek_PSI 2008 0x07d8
580 Greek_OMEGA 2009 0x07d9
581 Greek_alpha 2017 0x07e1
582 Greek_beta 2018 0x07e2
583 Greek_gamma 2019 0x07e3
584 Greek_delta 2020 0x07e4
585 Greek_epsilon 2021 0x07e5
586 Greek_zeta 2022 0x07e6
587 Greek_eta 2023 0x07e7
588 Greek_theta 2024 0x07e8
589 Greek_iota 2025 0x07e9
590 Greek_kappa 2026 0x07ea
591 Greek_lambda 2027 0x07eb
592 Greek_mu 2028 0x07ec
593 Greek_nu 2029 0x07ed
594 Greek_xi 2030 0x07ee
595 Greek_omicron 2031 0x07ef
596 Greek_pi 2032 0x07f0
597 Greek_rho 2033 0x07f1
598 Greek_sigma 2034 0x07f2
599 Greek_finalsmallsigma 2035 0x07f3
600 Greek_tau 2036 0x07f4
601 Greek_upsilon 2037 0x07f5
602 Greek_phi 2038 0x07f6
603 Greek_chi 2039 0x07f7
604 Greek_psi 2040 0x07f8
605 Greek_omega 2041 0x07f9
606 leftradical 2209 0x08a1
607 topleftradical 2210 0x08a2
608 horizconnector 2211 0x08a3
609 topintegral 2212 0x08a4
610 botintegral 2213 0x08a5
611 vertconnector 2214 0x08a6
612 topleftsqbracket 2215 0x08a7
613 botleftsqbracket 2216 0x08a8
614 toprightsqbracket 2217 0x08a9
615 botrightsqbracket 2218 0x08aa
616 topleftparens 2219 0x08ab
617 botleftparens 2220 0x08ac
618 toprightparens 2221 0x08ad
619 botrightparens 2222 0x08ae
620 leftmiddlecurlybrace 2223 0x08af
621 rightmiddlecurlybrace 2224 0x08b0
622 topleftsummation 2225 0x08b1
623 botleftsummation 2226 0x08b2
624 topvertsummationconnector 2227 0x08b3
625 botvertsummationconnector 2228 0x08b4
626 toprightsummation 2229 0x08b5
627 botrightsummation 2230 0x08b6
628 rightmiddlesummation 2231 0x08b7
433 Arabic_noon 1510 0x5E6
434 Arabic_ha 1511 0x5E7
435 Arabic_waw 1512 0x5E8
436 Arabic_alefmaksura 1513 0x5E9
437 Arabic_yeh 1514 0x5EA
438 Arabic_fathatan 1515 0x5EB
439 Arabic_dammatan 1516 0x5EC
440 Arabic_kasratan 1517 0x5ED
441 Arabic_fatha 1518 0x5EE
442 Arabic_damma 1519 0x5EF
443 Arabic_kasra 1520 0x5F0
444 Arabic_shadda 1521 0x5F1
445 Arabic_sukun 1522 0x5F2
446 Serbian_dje 1697 0x6A1
447 Macedonia_gje 1698 0x6A2
448 Cyrillic_io 1699 0x6A3
449 Ukrainian_ie 1700 0x6A4
450 Macedonia_dse 1701 0x6A5
451 Ukrainian_i 1702 0x6A6
452 Ukrainian_yi 1703 0x6A7
453 Cyrillic_je 1704 0x6A8
454 Cyrillic_lje 1705 0x6A9
455 Cyrillic_nje 1706 0x6AA
456 Serbian_tshe 1707 0x6AB
457 Macedonia_kje 1708 0x6AC
458 Byelorussian_shortu 1710 0x6AE
459 Cyrillic_dzhe 1711 0x6AF
460 numerosign 1712 0x6B0
461 Serbian_DJE 1713 0x6B1
462 Macedonia_GJE 1714 0x6B2
463 Cyrillic_IO 1715 0x6B3
464 Ukrainian_IE 1716 0x6B4
465 Macedonia_DSE 1717 0x6B5
466 Ukrainian_I 1718 0x6B6
467 Ukrainian_YI 1719 0x6B7
468 Cyrillic_JE 1720 0x6B8
469 Cyrillic_LJE 1721 0x6B9
470 Cyrillic_NJE 1722 0x6BA
471 Serbian_TSHE 1723 0x6BB
472 Macedonia_KJE 1724 0x6BC
473 Byelorussian_SHORTU 1726 0x6BE
474 Cyrillic_DZHE 1727 0x6BF
475 Cyrillic_yu 1728 0x6C0
476 Cyrillic_a 1729 0x6C1
477 Cyrillic_be 1730 0x6C2
478 Cyrillic_tse 1731 0x6C3
479 Cyrillic_de 1732 0x6C4
480 Cyrillic_ie 1733 0x6C5
481 Cyrillic_ef 1734 0x6C6
482 Cyrillic_ghe 1735 0x6C7
483 Cyrillic_ha 1736 0x6C8
484 Cyrillic_i 1737 0x6C9
485 Cyrillic_shorti 1738 0x6CA
486 Cyrillic_ka 1739 0x6CB
487 Cyrillic_el 1740 0x6CC
488 Cyrillic_em 1741 0x6CD
489 Cyrillic_en 1742 0x6CE
490 Cyrillic_o 1743 0x6CF
491 Cyrillic_pe 1744 0x6D0
492 Cyrillic_ya 1745 0x6D1
493 Cyrillic_er 1746 0x6D2
494 Cyrillic_es 1747 0x6D3
495 Cyrillic_te 1748 0x6D4
496 Cyrillic_u 1749 0x6D5
497 Cyrillic_zhe 1750 0x6D6
498 Cyrillic_ve 1751 0x6D7
499 Cyrillic_softsign 1752 0x6D8
500 Cyrillic_yeru 1753 0x6D9
501 Cyrillic_ze 1754 0x6DA
502 Cyrillic_sha 1755 0x6DB
503 Cyrillic_e 1756 0x6DC
504 Cyrillic_shcha 1757 0x6DD
505 Cyrillic_che 1758 0x6DE
506 Cyrillic_hardsign 1759 0x6DF
507 Cyrillic_YU 1760 0x6E0
508 Cyrillic_A 1761 0x6E1
509 Cyrillic_BE 1762 0x6E2
510 Cyrillic_TSE 1763 0x6E3
511 Cyrillic_DE 1764 0x6E4
512 Cyrillic_IE 1765 0x6E5
513 Cyrillic_EF 1766 0x6E6
514 Cyrillic_GHE 1767 0x6E7
515 Cyrillic_HA 1768 0x6E8
516 Cyrillic_I 1769 0x6E9
517 Cyrillic_SHORTI 1770 0x6EA
518 Cyrillic_KA 1771 0x6EB
519 Cyrillic_EL 1772 0x6EC
520 Cyrillic_EM 1773 0x6ED
521 Cyrillic_EN 1774 0x6EE
522 Cyrillic_O 1775 0x6EF
523 Cyrillic_PE 1776 0x6F0
524 Cyrillic_YA 1777 0x6F1
525 Cyrillic_ER 1778 0x6F2
526 Cyrillic_ES 1779 0x6F3
527 Cyrillic_TE 1780 0x6F4
528 Cyrillic_U 1781 0x6F5
529 Cyrillic_ZHE 1782 0x6F6
530 Cyrillic_VE 1783 0x6F7
531 Cyrillic_SOFTSIGN 1784 0x6F8
532 Cyrillic_YERU 1785 0x6F9
533 Cyrillic_ZE 1786 0x6FA
534 Cyrillic_SHA 1787 0x6FB
535 Cyrillic_E 1788 0x6FC
536 Cyrillic_SHCHA 1789 0x6FD
537 Cyrillic_CHE 1790 0x6FE
538 Cyrillic_HARDSIGN 1791 0x6FF
539 Greek_ALPHAaccent 1953 0x7A1
540 Greek_EPSILONaccent 1954 0x7A2
541 Greek_ETAaccent 1955 0x7A3
542 Greek_IOTAaccent 1956 0x7A4
543 Greek_IOTAdieresis 1957 0x7A5
544 Greek_IOTAaccentdiaeresis 1958 0x7A6
545 Greek_OMICRONaccent 1959 0x7A7
546 Greek_UPSILONaccent 1960 0x7A8
547 Greek_UPSILONdieresis 1961 0x7A9
548 Greek_UPSILONaccentdieresis 1962 0x7AA
549 Greek_OMEGAaccent 1963 0x7AB
550 Greek_accentdieresis 1966 0x7AE
551 Greek_horizbar 1967 0x7AF
552 Greek_alphaaccent 1969 0x7B1
553 Greek_epsilonaccent 1970 0x7B2
554 Greek_etaaccent 1971 0x7B3
555 Greek_iotaaccent 1972 0x7B4
556 Greek_iotadieresis 1973 0x7B5
557 Greek_iotaaccentdieresis 1974 0x7B6
558 Greek_omicronaccent 1975 0x7B7
559 Greek_upsilonaccent 1976 0x7B8
560 Greek_upsilondieresis 1977 0x7B9
561 Greek_upsilonaccentdieresis 1978 0x7BA
562 Greek_omegaaccent 1979 0x7BB
563 Greek_ALPHA 1985 0x7C1
564 Greek_BETA 1986 0x7C2
565 Greek_GAMMA 1987 0x7C3
566 Greek_DELTA 1988 0x7C4
567 Greek_EPSILON 1989 0x7C5
568 Greek_ZETA 1990 0x7C6
569 Greek_ETA 1991 0x7C7
570 Greek_THETA 1992 0x7C8
571 Greek_IOTA 1993 0x7C9
572 Greek_KAPPA 1994 0x7CA
573 Greek_LAMDA 1995 0x7CB
574 Greek_MU 1996 0x7CC
575 Greek_NU 1997 0x7CD
576 Greek_XI 1998 0x7CE
577 Greek_OMICRON 1999 0x7CF
578 Greek_PI 2000 0x7D0
579 Greek_RHO 2001 0x7D1
580 Greek_SIGMA 2002 0x7D2
581 Greek_TAU 2004 0x7D4
582 Greek_UPSILON 2005 0x7D5
583 Greek_PHI 2006 0x7D6
584 Greek_CHI 2007 0x7D7
585 Greek_PSI 2008 0x7D8
586 Greek_OMEGA 2009 0x7D9
587 Greek_alpha 2017 0x7E1
588 Greek_beta 2018 0x7E2
589 Greek_gamma 2019 0x7E3
590 Greek_delta 2020 0x7E4
591 Greek_epsilon 2021 0x7E5
592 Greek_zeta 2022 0x7E6
593 Greek_eta 2023 0x7E7
594 Greek_theta 2024 0x7E8
595 Greek_iota 2025 0x7E9
596 Greek_kappa 2026 0x7EA
597 Greek_lamda 2027 0x7EB
598 Greek_mu 2028 0x7EC
599 Greek_nu 2029 0x7ED
600 Greek_xi 2030 0x7EE
601 Greek_omicron 2031 0x7EF
602 Greek_pi 2032 0x7F0
603 Greek_rho 2033 0x7F1
604 Greek_sigma 2034 0x7F2
605 Greek_finalsmallsigma 2035 0x7F3
606 Greek_tau 2036 0x7F4
607 Greek_upsilon 2037 0x7F5
608 Greek_phi 2038 0x7F6
609 Greek_chi 2039 0x7F7
610 Greek_psi 2040 0x7F8
611 Greek_omega 2041 0x7F9
612 leftradical 2209 0x8A1
613 topleftradical 2210 0x8A2
614 horizconnector 2211 0x8A3
615 topintegral 2212 0x8A4
616 botintegral 2213 0x8A5
617 vertconnector 2214 0x8A6
618 topleftsqbracket 2215 0x8A7
619 botleftsqbracket 2216 0x8A8
620 toprightsqbracket 2217 0x8A9
621 botrightsqbracket 2218 0x8AA
622 topleftparens 2219 0x8AB
623 botleftparens 2220 0x8AC
624 toprightparens 2221 0x8AD
625 botrightparens 2222 0x8AE
626 leftmiddlecurlybrace 2223 0x8AF
627 rightmiddlecurlybrace 2224 0x8B0
628 topleftsummation 2225 0x8B1
629 botleftsummation 2226 0x8B2
630 topvertsummationconnector 2227 0x8B3
631 botvertsummationconnector 2228 0x8B4
632 toprightsummation 2229 0x8B5
633 botrightsummation 2230 0x8B6
634 rightmiddlesummation 2231 0x8B7
629635 .CE
630636 .CS
631 lessthanequal 2236 0x08bc
632 notequal 2237 0x08bd
633 greaterthanequal 2238 0x08be
634 integral 2239 0x08bf
635 therefore 2240 0x08c0
636 variation 2241 0x08c1
637 infinity 2242 0x08c2
638 nabla 2245 0x08c5
639 approximate 2248 0x08c8
640 similarequal 2249 0x08c9
641 ifonlyif 2253 0x08cd
642 implies 2254 0x08ce
643 identical 2255 0x08cf
644 radical 2262 0x08d6
645 includedin 2266 0x08da
646 includes 2267 0x08db
647 intersection 2268 0x08dc
648 union 2269 0x08dd
649 logicaland 2270 0x08de
650 logicalor 2271 0x08df
651 partialderivative 2287 0x08ef
652 function 2294 0x08f6
653 leftarrow 2299 0x08fb
654 uparrow 2300 0x08fc
655 rightarrow 2301 0x08fd
656 downarrow 2302 0x08fe
657 blank 2527 0x09df
658 soliddiamond 2528 0x09e0
659 checkerboard 2529 0x09e1
660 ht 2530 0x09e2
661 ff 2531 0x09e3
662 cr 2532 0x09e4
663 lf 2533 0x09e5
664 nl 2536 0x09e8
665 vt 2537 0x09e9
666 lowrightcorner 2538 0x09ea
667 uprightcorner 2539 0x09eb
668 upleftcorner 2540 0x09ec
669 lowleftcorner 2541 0x09ed
670 crossinglines 2542 0x09ee
671 horizlinescan1 2543 0x09ef
672 horizlinescan3 2544 0x09f0
673 horizlinescan5 2545 0x09f1
674 horizlinescan7 2546 0x09f2
675 horizlinescan9 2547 0x09f3
676 leftt 2548 0x09f4
677 rightt 2549 0x09f5
678 bott 2550 0x09f6
679 topt 2551 0x09f7
680 vertbar 2552 0x09f8
681 emspace 2721 0x0aa1
682 enspace 2722 0x0aa2
683 em3space 2723 0x0aa3
684 em4space 2724 0x0aa4
685 digitspace 2725 0x0aa5
686 punctspace 2726 0x0aa6
687 thinspace 2727 0x0aa7
688 hairspace 2728 0x0aa8
689 emdash 2729 0x0aa9
690 endash 2730 0x0aaa
691 signifblank 2732 0x0aac
692 ellipsis 2734 0x0aae
693 doubbaselinedot 2735 0x0aaf
694 onethird 2736 0x0ab0
695 twothirds 2737 0x0ab1
696 onefifth 2738 0x0ab2
697 twofifths 2739 0x0ab3
698 threefifths 2740 0x0ab4
699 fourfifths 2741 0x0ab5
700 onesixth 2742 0x0ab6
701 fivesixths 2743 0x0ab7
702 careof 2744 0x0ab8
703 figdash 2747 0x0abb
704 leftanglebracket 2748 0x0abc
705 decimalpoint 2749 0x0abd
706 rightanglebracket 2750 0x0abe
707 marker 2751 0x0abf
708 oneeighth 2755 0x0ac3
709 threeeighths 2756 0x0ac4
710 fiveeighths 2757 0x0ac5
711 seveneighths 2758 0x0ac6
712 trademark 2761 0x0ac9
713 signaturemark 2762 0x0aca
714 trademarkincircle 2763 0x0acb
715 leftopentriangle 2764 0x0acc
716 rightopentriangle 2765 0x0acd
717 emopencircle 2766 0x0ace
718 emopenrectangle 2767 0x0acf
719 leftsinglequotemark 2768 0x0ad0
720 rightsinglequotemark 2769 0x0ad1
721 leftdoublequotemark 2770 0x0ad2
722 rightdoublequotemark 2771 0x0ad3
723 prescription 2772 0x0ad4
724 minutes 2774 0x0ad6
725 seconds 2775 0x0ad7
726 latincross 2777 0x0ad9
727 hexagram 2778 0x0ada
728 filledrectbullet 2779 0x0adb
729 filledlefttribullet 2780 0x0adc
730 filledrighttribullet 2781 0x0add
731 emfilledcircle 2782 0x0ade
732 emfilledrect 2783 0x0adf
733 enopencircbullet 2784 0x0ae0
734 enopensquarebullet 2785 0x0ae1
735 openrectbullet 2786 0x0ae2
736 opentribulletup 2787 0x0ae3
737 opentribulletdown 2788 0x0ae4
738 openstar 2789 0x0ae5
739 enfilledcircbullet 2790 0x0ae6
740 enfilledsqbullet 2791 0x0ae7
741 filledtribulletup 2792 0x0ae8
742 filledtribulletdown 2793 0x0ae9
743 leftpointer 2794 0x0aea
744 rightpointer 2795 0x0aeb
745 club 2796 0x0aec
746 diamond 2797 0x0aed
747 heart 2798 0x0aee
748 maltesecross 2800 0x0af0
749 dagger 2801 0x0af1
750 doubledagger 2802 0x0af2
751 checkmark 2803 0x0af3
752 ballotcross 2804 0x0af4
753 musicalsharp 2805 0x0af5
754 musicalflat 2806 0x0af6
755 malesymbol 2807 0x0af7
756 femalesymbol 2808 0x0af8
757 telephone 2809 0x0af9
758 telephonerecorder 2810 0x0afa
759 phonographcopyright 2811 0x0afb
760 caret 2812 0x0afc
761 singlelowquotemark 2813 0x0afd
762 doublelowquotemark 2814 0x0afe
763 cursor 2815 0x0aff
764 leftcaret 2979 0x0ba3
765 rightcaret 2982 0x0ba6
766 downcaret 2984 0x0ba8
767 upcaret 2985 0x0ba9
768 overbar 3008 0x0bc0
769 downtack 3010 0x0bc2
770 upshoe 3011 0x0bc3
771 downstile 3012 0x0bc4
772 underbar 3014 0x0bc6
773 jot 3018 0x0bca
774 quad 3020 0x0bcc
775 uptack 3022 0x0bce
776 circle 3023 0x0bcf
777 upstile 3027 0x0bd3
778 downshoe 3030 0x0bd6
779 rightshoe 3032 0x0bd8
780 leftshoe 3034 0x0bda
781 lefttack 3036 0x0bdc
782 righttack 3068 0x0bfc
783 hebrew_aleph 3296 0x0ce0
784 hebrew_beth 3297 0x0ce1
785 hebrew_gimmel 3298 0x0ce2
786 hebrew_daleth 3299 0x0ce3
787 hebrew_he 3300 0x0ce4
788 hebrew_waw 3301 0x0ce5
789 hebrew_zayin 3302 0x0ce6
790 hebrew_het 3303 0x0ce7
791 hebrew_teth 3304 0x0ce8
792 hebrew_yod 3305 0x0ce9
793 hebrew_finalkaph 3306 0x0cea
794 hebrew_kaph 3307 0x0ceb
795 hebrew_lamed 3308 0x0cec
796 hebrew_finalmem 3309 0x0ced
797 hebrew_mem 3310 0x0cee
798 hebrew_finalnun 3311 0x0cef
799 hebrew_nun 3312 0x0cf0
800 hebrew_samekh 3313 0x0cf1
801 hebrew_ayin 3314 0x0cf2
802 hebrew_finalpe 3315 0x0cf3
803 hebrew_pe 3316 0x0cf4
804 hebrew_finalzadi 3317 0x0cf5
805 hebrew_zadi 3318 0x0cf6
806 hebrew_kuf 3319 0x0cf7
807 hebrew_resh 3320 0x0cf8
808 hebrew_shin 3321 0x0cf9
809 hebrew_taf 3322 0x0cfa
810 BackSpace 65288 0xff08
811 Tab 65289 0xff09
812 Linefeed 65290 0xff0a
813 Clear 65291 0xff0b
814 Return 65293 0xff0d
815 Pause 65299 0xff13
816 Scroll_Lock 65300 0xff14
817 Sys_Req 65301 0xff15
818 Escape 65307 0xff1b
819 Multi_key 65312 0xff20
820 Kanji 65313 0xff21
821 Home 65360 0xff50
822 Left 65361 0xff51
823 Up 65362 0xff52
824 Right 65363 0xff53
825 Down 65364 0xff54
826 Prior 65365 0xff55
827 Next 65366 0xff56
828 End 65367 0xff57
829 Begin 65368 0xff58
830 Win_L 65371 0xff5b
831 Win_R 65372 0xff5c
637 lessthanequal 2236 0x8BC
638 notequal 2237 0x8BD
639 greaterthanequal 2238 0x8BE
640 integral 2239 0x8BF
641 therefore 2240 0x8C0
642 variation 2241 0x8C1
643 infinity 2242 0x8C2
644 nabla 2245 0x8C5
645 approximate 2248 0x8C8
646 similarequal 2249 0x8C9
647 ifonlyif 2253 0x8CD
648 implies 2254 0x8CE
649 identical 2255 0x8CF
650 radical 2262 0x8D6
651 includedin 2266 0x8DA
652 includes 2267 0x8DB
653 intersection 2268 0x8DC
654 union 2269 0x8DD
655 logicaland 2270 0x8DE
656 logicalor 2271 0x8DF
657 partialderivative 2287 0x8EF
658 function 2294 0x8F6
659 leftarrow 2299 0x8FB
660 uparrow 2300 0x8FC
661 rightarrow 2301 0x8FD
662 downarrow 2302 0x8FE
663 blank 2527 0x9DF
664 soliddiamond 2528 0x9E0
665 checkerboard 2529 0x9E1
666 ht 2530 0x9E2
667 ff 2531 0x9E3
668 cr 2532 0x9E4
669 lf 2533 0x9E5
670 nl 2536 0x9E8
671 vt 2537 0x9E9
672 lowrightcorner 2538 0x9EA
673 uprightcorner 2539 0x9EB
674 upleftcorner 2540 0x9EC
675 lowleftcorner 2541 0x9ED
676 crossinglines 2542 0x9EE
677 horizlinescan1 2543 0x9EF
678 horizlinescan3 2544 0x9F0
679 horizlinescan5 2545 0x9F1
680 horizlinescan7 2546 0x9F2
681 horizlinescan9 2547 0x9F3
682 leftt 2548 0x9F4
683 rightt 2549 0x9F5
684 bott 2550 0x9F6
685 topt 2551 0x9F7
686 vertbar 2552 0x9F8
687 emspace 2721 0xAA1
688 enspace 2722 0xAA2
689 em3space 2723 0xAA3
690 em4space 2724 0xAA4
691 digitspace 2725 0xAA5
692 punctspace 2726 0xAA6
693 thinspace 2727 0xAA7
694 hairspace 2728 0xAA8
695 emdash 2729 0xAA9
696 endash 2730 0xAAA
697 signifblank 2732 0xAAC
698 ellipsis 2734 0xAAE
699 doubbaselinedot 2735 0xAAF
700 onethird 2736 0xAB0
701 twothirds 2737 0xAB1
702 onefifth 2738 0xAB2
703 twofifths 2739 0xAB3
704 threefifths 2740 0xAB4
705 fourfifths 2741 0xAB5
706 onesixth 2742 0xAB6
707 fivesixths 2743 0xAB7
708 careof 2744 0xAB8
709 figdash 2747 0xABB
710 leftanglebracket 2748 0xABC
711 decimalpoint 2749 0xABD
712 rightanglebracket 2750 0xABE
713 marker 2751 0xABF
714 oneeighth 2755 0xAC3
715 threeeighths 2756 0xAC4
716 fiveeighths 2757 0xAC5
717 seveneighths 2758 0xAC6
718 trademark 2761 0xAC9
719 signaturemark 2762 0xACA
720 trademarkincircle 2763 0xACB
721 leftopentriangle 2764 0xACC
722 rightopentriangle 2765 0xACD
723 emopencircle 2766 0xACE
724 emopenrectangle 2767 0xACF
725 leftsinglequotemark 2768 0xAD0
726 rightsinglequotemark 2769 0xAD1
727 leftdoublequotemark 2770 0xAD2
728 rightdoublequotemark 2771 0xAD3
729 prescription 2772 0xAD4
730 minutes 2774 0xAD6
731 seconds 2775 0xAD7
732 latincross 2777 0xAD9
733 hexagram 2778 0xADA
734 filledrectbullet 2779 0xADB
735 filledlefttribullet 2780 0xADC
736 filledrighttribullet 2781 0xADD
737 emfilledcircle 2782 0xADE
738 emfilledrect 2783 0xADF
739 enopencircbullet 2784 0xAE0
740 enopensquarebullet 2785 0xAE1
741 openrectbullet 2786 0xAE2
742 opentribulletup 2787 0xAE3
743 opentribulletdown 2788 0xAE4
744 openstar 2789 0xAE5
745 enfilledcircbullet 2790 0xAE6
746 enfilledsqbullet 2791 0xAE7
747 filledtribulletup 2792 0xAE8
748 filledtribulletdown 2793 0xAE9
749 leftpointer 2794 0xAEA
750 rightpointer 2795 0xAEB
751 club 2796 0xAEC
752 diamond 2797 0xAED
753 heart 2798 0xAEE
754 maltesecross 2800 0xAF0
755 dagger 2801 0xAF1
756 doubledagger 2802 0xAF2
757 checkmark 2803 0xAF3
758 ballotcross 2804 0xAF4
759 musicalsharp 2805 0xAF5
760 musicalflat 2806 0xAF6
761 malesymbol 2807 0xAF7
762 femalesymbol 2808 0xAF8
763 telephone 2809 0xAF9
764 telephonerecorder 2810 0xAFA
765 phonographcopyright 2811 0xAFB
766 caret 2812 0xAFC
767 singlelowquotemark 2813 0xAFD
768 doublelowquotemark 2814 0xAFE
769 cursor 2815 0xAFF
770 leftcaret 2979 0xBA3
771 rightcaret 2982 0xBA6
772 downcaret 2984 0xBA8
773 upcaret 2985 0xBA9
774 overbar 3008 0xBC0
775 downtack 3010 0xBC2
776 upshoe 3011 0xBC3
777 downstile 3012 0xBC4
778 underbar 3014 0xBC6
779 jot 3018 0xBCA
780 quad 3020 0xBCC
781 uptack 3022 0xBCE
782 circle 3023 0xBCF
783 upstile 3027 0xBD3
784 downshoe 3030 0xBD6
785 rightshoe 3032 0xBD8
786 leftshoe 3034 0xBDA
787 lefttack 3036 0xBDC
788 righttack 3068 0xBFC
789 hebrew_doublelowline 3295 0xCDF
790 hebrew_aleph 3296 0xCE0
791 hebrew_bet 3297 0xCE1
792 hebrew_gimel 3298 0xCE2
793 hebrew_dalet 3299 0xCE3
794 hebrew_he 3300 0xCE4
795 hebrew_waw 3301 0xCE5
796 hebrew_zain 3302 0xCE6
797 hebrew_chet 3303 0xCE7
798 hebrew_tet 3304 0xCE8
799 hebrew_yod 3305 0xCE9
800 hebrew_finalkaph 3306 0xCEA
801 hebrew_kaph 3307 0xCEB
802 hebrew_lamed 3308 0xCEC
803 hebrew_finalmem 3309 0xCED
804 hebrew_mem 3310 0xCEE
805 hebrew_finalnun 3311 0xCEF
806 hebrew_nun 3312 0xCF0
807 hebrew_samech 3313 0xCF1
808 hebrew_ayin 3314 0xCF2
809 hebrew_finalpe 3315 0xCF3
810 hebrew_pe 3316 0xCF4
811 hebrew_finalzade 3317 0xCF5
812 hebrew_zade 3318 0xCF6
813 hebrew_qoph 3319 0xCF7
814 hebrew_resh 3320 0xCF8
815 hebrew_shin 3321 0xCF9
816 hebrew_taw 3322 0xCFA
817 BackSpace 65288 0xFF08
818 Tab 65289 0xFF09
819 Linefeed 65290 0xFF0A
820 Clear 65291 0xFF0B
821 Return 65293 0xFF0D
822 Pause 65299 0xFF13
823 Scroll_Lock 65300 0xFF14
824 Sys_Req 65301 0xFF15
825 Escape 65307 0xFF1B
826 Multi_key 65312 0xFF20
827 Kanji 65313 0xFF21
828 Muhenkan 65314 0xFF22
829 Henkan_Mode 65315 0xFF23
830 Romaji 65316 0xFF24
831 Hiragana 65317 0xFF25
832 Katakana 65318 0xFF26
833 Hiragana_Katakana 65319 0xFF27
834 Zenkaku 65320 0xFF28
835 Hankaku 65321 0xFF29
836 Zenkaku_Hankaku 65322 0xFF2A
837 Touroku 65323 0xFF2B
838 Massyo 65324 0xFF2C
839 Kana_Lock 65325 0xFF2D
840 Kana_Shift 65326 0xFF2E
841 Eisu_Shift 65327 0xFF2F
842 Eisu_toggle 65328 0xFF30
843 Home 65360 0xFF50
844 Left 65361 0xFF51
845 Up 65362 0xFF52
846 Right 65363 0xFF53
847 Down 65364 0xFF54
848 Prior 65365 0xFF55
849 Next 65366 0xFF56
850 End 65367 0xFF57
851 Begin 65368 0xFF58
852 Win_L 65371 0xFF5B
853 Win_R 65372 0xFF5C
832854 .CE
833855 .CS
834 App 65373 0xff5d
835 Select 65376 0xff60
836 Print 65377 0xff61
837 Execute 65378 0xff62
838 Insert 65379 0xff63
839 Undo 65381 0xff65
840 Redo 65382 0xff66
841 Menu 65383 0xff67
842 Find 65384 0xff68
843 Cancel 65385 0xff69
844 Help 65386 0xff6a
845 Break 65387 0xff6b
846 Hebrew_switch 65406 0xff7e
847 Num_Lock 65407 0xff7f
848 KP_Space 65408 0xff80
849 KP_Tab 65417 0xff89
850 KP_Enter 65421 0xff8d
851 KP_F1 65425 0xff91
852 KP_F2 65426 0xff92
853 KP_F3 65427 0xff93
854 KP_F4 65428 0xff94
855 KP_Multiply 65450 0xffaa
856 KP_Add 65451 0xffab
857 KP_Separator 65452 0xffac
858 KP_Subtract 65453 0xffad
859 KP_Decimal 65454 0xffae
860 KP_Divide 65455 0xffaf
861 KP_0 65456 0xffb0
862 KP_1 65457 0xffb1
863 KP_2 65458 0xffb2
864 KP_3 65459 0xffb3
865 KP_4 65460 0xffb4
866 KP_5 65461 0xffb5
867 KP_6 65462 0xffb6
868 KP_7 65463 0xffb7
869 KP_8 65464 0xffb8
870 KP_9 65465 0xffb9
871 KP_Equal 65469 0xffbd
872 F1 65470 0xffbe
873 F2 65471 0xffbf
874 F3 65472 0xffc0
875 F4 65473 0xffc1
876 F5 65474 0xffc2
877 F6 65475 0xffc3
878 F7 65476 0xffc4
879 F8 65477 0xffc5
880 F9 65478 0xffc6
881 F10 65479 0xffc7
882 L1 65480 0xffc8
883 L2 65481 0xffc9
884 L3 65482 0xffca
885 L4 65483 0xffcb
886 L5 65484 0xffcc
887 L6 65485 0xffcd
888 L7 65486 0xffce
889 L8 65487 0xffcf
890 L9 65488 0xffd0
891 L10 65489 0xffd1
892 R1 65490 0xffd2
893 R2 65491 0xffd3
894 R3 65492 0xffd4
895 R4 65493 0xffd5
896 R5 65494 0xffd6
897 R6 65495 0xffd7
898 R7 65496 0xffd8
899 R8 65497 0xffd9
900 R9 65498 0xffda
901 R10 65499 0xffdb
902 R11 65500 0xffdc
903 R12 65501 0xffdd
904 F33 65502 0xffde
905 R14 65503 0xffdf
906 R15 65504 0xffe0
907 Shift_L 65505 0xffe1
908 Shift_R 65506 0xffe2
909 Control_L 65507 0xffe3
910 Control_R 65508 0xffe4
911 Caps_Lock 65509 0xffe5
912 Shift_Lock 65510 0xffe6
913 Meta_L 65511 0xffe7
914 Meta_R 65512 0xffe8
915 Alt_L 65513 0xffe9
916 Alt_R 65514 0xffea
917 Super_L 65515 0xffeb
918 Super_R 65516 0xffec
919 Hyper_L 65517 0xffed
920 Hyper_R 65518 0xffee
921 Delete 65535 0xffff
856 App 65373 0xFF5D
857 Select 65376 0xFF60
858 Print 65377 0xFF61
859 Execute 65378 0xFF62
860 Insert 65379 0xFF63
861 Undo 65381 0xFF65
862 Redo 65382 0xFF66
863 Menu 65383 0xFF67
864 Find 65384 0xFF68
865 Cancel 65385 0xFF69
866 Help 65386 0xFF6A
867 Break 65387 0xFF6B
868 Mode_switch 65406 0xFF7E
869 Num_Lock 65407 0xFF7F
870 KP_Space 65408 0xFF80
871 KP_Tab 65417 0xFF89
872 KP_Enter 65421 0xFF8D
873 KP_F1 65425 0xFF91
874 KP_F2 65426 0xFF92
875 KP_F3 65427 0xFF93
876 KP_F4 65428 0xFF94
877 KP_Home 65429 0xFF95
878 KP_Left 65430 0xFF96
879 KP_Up 65431 0xFF97
880 KP_Right 65432 0xFF98
881 KP_Down 65433 0xFF99
882 KP_Prior 65434 0xFF9A
883 KP_Next 65435 0xFF9B
884 KP_End 65436 0xFF9C
885 KP_Begin 65437 0xFF9D
886 KP_Insert 65438 0xFF9E
887 KP_Delete 65439 0xFF9F
888 KP_Multiply 65450 0xFFAA
889 KP_Add 65451 0xFFAB
890 KP_Separator 65452 0xFFAC
891 KP_Subtract 65453 0xFFAD
892 KP_Decimal 65454 0xFFAE
893 KP_Divide 65455 0xFFAF
894 KP_0 65456 0xFFB0
895 KP_1 65457 0xFFB1
896 KP_2 65458 0xFFB2
897 KP_3 65459 0xFFB3
898 KP_4 65460 0xFFB4
899 KP_5 65461 0xFFB5
900 KP_6 65462 0xFFB6
901 KP_7 65463 0xFFB7
902 KP_8 65464 0xFFB8
903 KP_9 65465 0xFFB9
904 KP_Equal 65469 0xFFBD
905 F1 65470 0xFFBE
906 F2 65471 0xFFBF
907 F3 65472 0xFFC0
908 F4 65473 0xFFC1
909 F5 65474 0xFFC2
910 F6 65475 0xFFC3
911 F7 65476 0xFFC4
912 F8 65477 0xFFC5
913 F9 65478 0xFFC6
914 F10 65479 0xFFC7
915 F11 65480 0xFFC8
916 F12 65481 0xFFC9
917 F13 65482 0xFFCA
918 F14 65483 0xFFCB
919 F15 65484 0xFFCC
920 F16 65485 0xFFCD
921 F17 65486 0xFFCE
922 F18 65487 0xFFCF
923 F19 65488 0xFFD0
924 F20 65489 0xFFD1
925 F21 65490 0xFFD2
926 F22 65491 0xFFD3
927 F23 65492 0xFFD4
928 F24 65493 0xFFD5
929 F25 65494 0xFFD6
930 F26 65495 0xFFD7
931 F27 65496 0xFFD8
932 F28 65497 0xFFD9
933 F29 65498 0xFFDA
934 F30 65499 0xFFDB
935 F31 65500 0xFFDC
936 F32 65501 0xFFDD
937 F33 65502 0xFFDE
938 F34 65503 0xFFDF
939 F35 65504 0xFFE0
940 Shift_L 65505 0xFFE1
941 Shift_R 65506 0xFFE2
942 Control_L 65507 0xFFE3
943 Control_R 65508 0xFFE4
944 Caps_Lock 65509 0xFFE5
945 Shift_Lock 65510 0xFFE6
946 Meta_L 65511 0xFFE7
947 Meta_R 65512 0xFFE8
948 Alt_L 65513 0xFFE9
949 Alt_R 65514 0xFFEA
950 Super_L 65515 0xFFEB
951 Super_R 65516 0xFFEC
952 Hyper_L 65517 0xFFED
953 Hyper_R 65518 0xFFEE
954 Delete 65535 0xFFFF
922955 XF86AudioLowerVolume 269025041 0x1008FF11
923956 XF86AudioMute 269025042 0x1008FF12
924957 XF86AudioRaiseVolume 269025043 0x1008FF13
263263 menubar whenever the window's menubar is in front. The first items in
264264 the menu are provided by Mac OS X, and the names of the current
265265 toplevels are automatically appended after all the Tk-defined items and
266 a separator.
266 a separator. The Window menu on the Mac also allows toggling the
267 window into a fullscreen state, and managing a tabbed window interface
268 (multiple windows grouped into a single window) if supported by that
269 version of the operating system.
267270 .PP
268271 When Tk sees a .menubar.help menu on the Macintosh, the menu's contents
269272 are appended to the standard Help menu of the user's menubar whenever
466469 bindings normally take care of this before invoking the \fBinvoke\fR
467470 widget command.
468471 .TP
469 \fIpathName \fBpost \fIx y\fR
472 \fIpathName \fBpost \fIx y\fR ?\fIindex\fR?
470473 .
471474 Arrange for the menu to be displayed on the screen at the root-window
472 coordinates given by \fIx\fR and \fIy\fR. These coordinates are
473 adjusted if necessary to guarantee that the entire menu is visible on
474 the screen. This command normally returns an empty string.
475 If the \fB\-postcommand\fR option has been specified, then its value is
476 executed as a Tcl script before posting the menu and the result of
477 that script is returned as the result of the \fBpost\fR widget
478 command.
479 If an error returns while executing the command, then the error is
480 returned without posting the menu.
475 coordinates given by \fIx\fR and \fIy\fR. If an index is specified
476 the menu will be located so that the entry with that index is
477 displayed at the point. These coordinates are adjusted if necessary to
478 guarantee that the entire menu is visible on the screen. This command
479 normally returns an empty string. If the \fB\-postcommand\fR option
480 has been specified, then its value is executed as a Tcl script before
481 posting the menu and the result of that script is returned as the
482 result of the \fBpost\fR widget command. If an error returns while
483 executing the command, then the error is returned without posting the
484 menu.
481485 .TP
482486 \fIpathName \fBpostcascade \fIindex\fR
483487 .
330330 (rightmost or bottommost) pane in the window.
331331 .PP
332332 Unlike slave windows managed by e.g. pack or grid, the panes managed by a
333 panedwindow do not change width or height to accomodate changes in the
333 panedwindow do not change width or height to accommodate changes in the
334334 requested widths or heights of the panes, once these have become mapped.
335335 Therefore it may be advisable, particularly when creating layouts
336336 interactively, to not add a pane to the panedwindow widget until after the
5454 .OP \-resolution resolution Resolution
5555 A real value specifying the resolution for the scale.
5656 If this value is greater than zero then the scale's value will always be
57 rounded to an even multiple of this value, as will tick marks and
57 rounded to an even multiple of this value, as will
5858 the endpoints of the scale. If the value is less than zero then no
5959 rounding occurs. Defaults to 1 (i.e., the value will be integral).
6060 .OP \-showvalue showValue ShowValue
7777 .OP \-tickinterval tickInterval TickInterval
7878 Must be a real value.
7979 Determines the spacing between numerical
80 tick marks displayed below or to the left of the slider.
80 tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval.
8181 If 0, no tick marks will be displayed.
8282 .OP \-to to To
8383 Specifies a real value corresponding
1212 tk::mac \- Access Mac-Specific Functionality on OS X from Tk
1313 .SH SYNOPSIS
1414 .nf
15 \fB::tk::mac::DoScriptFile\fR
16 \fB::tk::mac::DoScriptText\fR
1517 \fB::tk::mac::ShowPreferences\fR
1618 \fB::tk::mac::OpenApplication\fR
1719 \fB::tk::mac::ReopenApplication\fR
2123 \fB::tk::mac::OnHide\fR
2224 \fB::tk::mac::OnShow\fR
2325 \fB::tk::mac::ShowHelp\fR
26 \fB::tk::mac::PerformService\fR
27 \fB::tk::mac::LaunchURL \fIURL...\fR
28 \fB::tk::mac::GetAppPath\fR
2429
2530 \fB::tk::mac::standardAboutPanel\fR
2631
2934 \fB::tk::mac::antialiasedtext \fInumber\fR
3035 \fB::tk::mac::useThemedToplevel \fIboolean\fR
3136
37
3238 \fB::tk::mac::iconBitmap \fIname width height \-kind value\fR
3339 .fi
3440 .BE
3844 events that applications should respond to. These events are mapped by Tk to
3945 calls to commands in the \fB::tk::mac\fR namespace; unless otherwise noted, if
4046 the command is absent, no action will be taken.
47 .TP
48 \fB::tk::mac::DoScriptFile\fR
49 .
50 The default Apple Event handler for AEDoScriptHandler. This command
51 executes a Tcl file when an AppleScript sends a
52 .QW "do script"
53 command to Wish with a file path as a parameter.
54 .TP
55 \fB::tk::mac::DoScriptText\fR
56 .
57 The default Apple Event handler for AEDoScriptHandler. This command
58 executes Tcl code when an AppleScript sends a
59 .QW "do script"
60 command to Wish with Tcl code or a Tcl procedure as a parameter.
4161 .TP
4262 \fB::tk::mac::ShowPreferences\fR
4363 .
6080 \fB::tk::mac::OpenApplication\fR
6181 .
6282 If a proc of this name is defined, this proc fill fire when your application
63 is intially opened. It is the default Apple Event handler for
83 is initially opened. It is the default Apple Event handler for
6484 kAEOpenApplication,
6585 .QW oapp .
6686 .TP
109129 If a proc of this name is defined it is the default Apple Event handler for
110130 kAEPrintDocuments,
111131 .QW pdoc ,
112 the Apple Event sent when your application is asked to print one or more
113 documents (e.g., via the Print menu item in the Finder). It works the same
114 way as \fBtk::mac::OpenDocument\fR in terms of arguments.
132 the Apple Event sent when your application is asked to print a
133 document. It takes a single absolute file path as an argument.
115134 .TP
116135 \fB::tk::mac::Quit\fR
117136 .
140159 platform-specific standard Help menu item
141160 .QW "YourApp Help"
142161 performs the default Cocoa action of showing the Help Book configured in the
143 application's Info.plist (or displaying an alert if no Help Book is set).
162 application's Info.plist (or displaying an alert if no Help Book is
163 set).
164 .TP
165 \fB::tk::mac::PerformService\fR
166 .
167 Executes a Tcl procedure called from the macOS
168 .QW Services
169 menu in the Application menu item. The
170 .QW Services
171 menu item allows for inter-application communication; data from one
172 application, such as selected text, can be sent to another application
173 for processing, for example to Safari as a search item for Google, or
174 to TextEdit to be appended to a file. An example of the proc is below,
175 and should be rewritten in an application script for customization:
176 .RS
177 .PP
178 .CS
179 proc ::tk::mac::PerformService {} {
180 set data [clipboard get]
181 $w insert end $data
182 }
183 .CE
184 .RE
185 Note that the mechanism for retrieving the data is from the clipboard;
186 there is no other supported way to obtain the data. If the Services
187 process is not desired, the NSServices keys can be deleted from
188 the application's Info.plist file. The underlying code supporting this
189 command also allows the text, entry and ttk::entry widgets to access
190 services from other applications via the Services menu. The NSPortName
191 key in Wish's Info.plist file is currently set as
192 .QW "Wish"
193 ; if a developer changes the name of the Wish executable to something
194 else, this key should be modified with the same name.
195 .TP
196 \fB::tk::mac::LaunchURL \fIURL...\fR
197 .
198 If defined, launches a URL within Tk. This would be used if a Tk
199 application wants to handle a URL itself, such as displaying data from
200 an RSS feed, rather than launching a default application to handle the
201 URL, although it can defined as such. Wish includes a stub URL scheme
202 of
203 .QW foo://
204 in the CFBundleURLSchemes key of its Info.plist file; this should be customized for the specific URL
205 scheme the developer wants to support.
206 .TP
207 \fB::tk::mac::GetAppPath\fR
208 .
209 Returns the current applications's file path.
210 .TP
211
212
144213 .SH "ADDITIONAL DIALOGS"
145214 .PP
146215 The Aqua/Mac OS X defines additional dialogs that applications should
103103 and relief. The \fBtoplevel\fR command returns the
104104 path name of the new window.
105105 .PP
106 A toplevel is similar to a frame except that it is created as a
106 A toplevel is similar to a \fBframe\fR except that it is created as a
107107 top-level window: its X parent is the root window of a screen
108 rather than the logical parent from its path name. The primary
108 rather than the logical parent from its Tk path name. The primary
109109 purpose of a toplevel is to serve as a container for dialog boxes
110110 and other collections of widgets. The only visible features
111111 of a toplevel are its background color and an optional 3-D border
116116 name is the same as the path name of the toplevel's window. This
117117 command may be used to invoke various
118118 operations on the widget. It has the following general form:
119 .PP
119120 .CS
120121 \fIpathName option \fR?\fIarg arg ...\fR?
121122 .CE
123 .PP
122124 \fIPathName\fR is the name of the command, which is the same as
123125 the toplevel widget's path name. \fIOption\fR and the \fIarg\fRs
124126 determine the exact behavior of the command. The following
125127 commands are possible for toplevel widgets:
126128 .TP
127129 \fIpathName \fBcget \fIoption\fR
130 .
128131 Returns the current value of the configuration option given
129132 by \fIoption\fR.
130133 \fIOption\fR may have any of the values accepted by the \fBtoplevel\fR
131134 command.
132135 .TP
133136 \fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR?
137 .
134138 Query or modify the configuration options of the widget.
135139 If no \fIoption\fR is specified, returns a list describing all of
136140 the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
147151 .PP
148152 When a new toplevel is created, it has no default event bindings:
149153 toplevels are not intended to be interactive.
154 .PP
155 Be aware that bindings on toplevels may receive events from subwidgets.
150156 .SH "SEE ALSO"
151 frame(n)
157 bind(n), bindtags(n), frame(n), wm(n)
152158 .SH KEYWORDS
153159 toplevel, widget
154160 '\" Local Variables:
211211 .PP
212212 \fBTtk_GetBorderFromObj\fR is the same as \fBTtk_GetPaddingFromObj\fR
213213 except that the lengths are specified as integers
214 (i.e., resolution-dependant values like \fI3m\fR are not allowed).
214 (i.e., resolution-dependent values like \fI3m\fR are not allowed).
215215 .PP
216216 \fBTtk_GetStickyFromObj\fR converts the string in \fIobjPtr\fR
217217 to a \fIsticky\fR bitmask. The string contains zero or more
7171 .br
7272 \fB\-bordercolor\fP \fIcolor\fP
7373 .br
74 \fB\-compound\fP \fIcompound\fP
75 .br
7476 \fB\-darkcolor\fP \fIcolor\fP
7577 .br
7678 \fB\-foreground\fP \fIcolor\fP
7979 .PP
8080 \fB\-background\fP \fIcolor\fP
8181 .br
82 \fB\-compound\fP \fIcompound\fP
83 .br
8284 \fB\-foreground\fP \fIcolor\fP
8385 .br
8486 \fB\-indicatorbackground\fP \fIcolor\fP
6666 .TP
6767 \fIpathName \fBcurrent\fR ?\fInewIndex\fR?
6868 If \fInewIndex\fR is supplied, sets the combobox value
69 to the element at position \fInewIndex\fR in the list of \fB\-values\fR.
69 to the element at position \fInewIndex\fR in the list of \fB\-values\fR
70 (in addition to integers, the \fBend\fR index is supported and indicates
71 the last element of the list).
7072 Otherwise, returns the index of the current value in the list of
7173 \fB\-values\fR or \fB\-1\fR if the current value does not appear in the list.
7274 .TP
123125 .PP
124126 \fB\-arrowcolor\fP \fIcolor\fP
125127 .br
128 \fB\-arrowsize\fP \fIamount\fP
129 .br
126130 \fB\-background\fP \fIcolor\fP
127131 .br
128132 \fB\-bordercolor\fP \fIcolor\fP
221221 Returns 0 if validation fails, 1 if it succeeds.
222222 Sets or clears the \fBinvalid\fR state accordingly.
223223 See \fBVALIDATION\fR below for more details.
224 .TP
225 \fIpathName \fBxview \fIargs\fR
226 This command is used to query and change the horizontal position of the
227 text in the widget's window. It can take any of the following
228 forms:
229 .RS
230 .TP
231 \fIpathName \fBxview\fR
232 Returns a list containing two elements.
233 Each element is a real fraction between 0 and 1; together they describe
234 the horizontal span that is visible in the window.
235 For example, if the first element is .2 and the second element is .6,
236 20% of the entry's text is off-screen to the left, the middle 40% is visible
237 in the window, and 40% of the text is off-screen to the right.
238 These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
239 option.
240 .TP
241 \fIpathName \fBxview\fR \fIindex\fR
242 Adjusts the view in the window so that the character given by \fIindex\fR
243 is displayed at the left edge of the window.
244 .TP
245 \fIpathName \fBxview moveto\fI fraction\fR
246 Adjusts the view in the window so that the character \fIfraction\fR of the
247 way through the text appears at the left edge of the window.
248 \fIFraction\fR must be a fraction between 0 and 1.
249 .TP
250 \fIpathName \fBxview scroll \fInumber what\fR
251 This command shifts the view in the window left or right according to
252 \fInumber\fR and \fIwhat\fR.
253 \fINumber\fR must be an integer.
254 \fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
255 '\" or an abbreviation of one of these, but we don't document that.
256 If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
257 \fInumber\fR average-width characters on the display; if it is
258 \fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
259 If \fInumber\fR is negative then characters farther to the left
260 become visible; if it is positive then characters farther to the right
261 become visible.
262 .RE
263224 .PP
264225 The entry widget also supports the following generic \fBttk::widget\fR
265226 widget subcommands (see \fIttk::widget(n)\fR for details):
266227 .DS
267228 .ta 5.5c 11c
268229 \fBcget\fR \fBconfigure\fR \fBidentify\fR
269 \fBinstate\fR \fBstate\fR
230 \fBinstate\fR \fBstate\fR \fBxview\fR
270231 .DE
271232 .SH VALIDATION
272233 .PP
471432 .PP
472433 \fB\-background\fP \fIcolor\fP
473434 .RS
474 When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP.
435 For backwards compatibility, when using the aqua theme (for macOS), this
436 option behaves as an alias for the \fB\-fieldbackground\fP provided that no
437 value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored.
475438 .RE
476439 \fB\-bordercolor\fP \fIcolor\fP
477440 .br
479442 .br
480443 \fB\-fieldbackground\fP \fIcolor\fP
481444 .RS
482 Does not work with the aqua theme (Mac OS X).
483 .br
484445 Some themes use a graphical background and their field background colors cannot be changed.
485446 .RE
486447 \fB\-foreground\fP \fIcolor\fP
2222 .SH "WIDGET-SPECIFIC OPTIONS"
2323 .OP \-borderwidth borderWidth BorderWidth
2424 The desired width of the widget border. Defaults to 0.
25 May be ignored depending on the theme used.
2526 .OP \-relief relief Relief
2627 One of the standard Tk border styles:
2728 \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR,
5253 are:
5354 .PP
5455 \fB\-background\fP \fIcolor\fP
56 .br
57 \fB\-relief\fP \fIrelief\fP
5558 .PP
5659 Some options are only available for specific themes.
5760 .PP
5861 See the \fBttk::style\fP manual page for information on how to configure
5962 ttk styles.
63 .SH BINDINGS
64 .PP
65 When a new \fBttk::frame\fR is created, it has no default event bindings;
66 \fBttk::frame\fRs are not intended to be interactive.
6067 .SH "SEE ALSO"
6168 ttk::widget(n), ttk::labelframe(n), frame(n)
6269 .SH "KEYWORDS"
1212 .SH "OVERVIEW"
1313 .PP
1414 The Tk themed widget set is based on a revised and enhanced version
15 of TIP #48 (http://tip.tcl.tk/48) specified style engine.
15 of TIP #48 (https://tip.tcl-lang.org/48) specified style engine.
1616 The main concepts are described below.
1717 The basic idea is to separate, to the extent possible,
1818 the code implementing a widget's behavior from
4848 Valid values are
4949 \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, \fBsolid\fR,
5050 and \fBsunken\fR.
51 .OP \-text text Text
52 Specifies a text string to be displayed inside the widget
53 (unless overridden by \fB\-textvariable\fR).
5451 .OP \-wraplength wrapLength WrapLength
5552 Specifies the maximum line length (in pixels).
5653 If this option is less than or equal to zero,
7370 .PP
7471 \fB\-background\fP \fIcolor\fP
7572 .br
73 \fB\-compound\fP \fIcompound\fP
74 .br
7675 \fB\-foreground\fP \fIcolor\fP
7776 .br
7877 \fB\-font\fP \fIfont\fP
2929 .\" XXX: \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR,
3030 .\" XXX: \fBsolid\fR, or \fBsunken\fR.
3131 .\" XXX: Default is theme-dependent.
32 .OP \-height height Height
33 If specified, the widget's requested height in pixels.
34 (See \fIttk::frame(n)\fR for further notes on \fB\-width\fR and
35 \fB\-height\fR).
3236 .OP \-labelanchor labelAnchor LabelAnchor
3337 Specifies where to place the label.
3438 Allowed values are (clockwise from the top upper left corner):
3943 .\" and specifies which side the label should be placed on;
4044 .\" the remaining characters specify how the label is aligned on that side.
4145 .\" NOTE: Now allows other values as well; leave this undocumented for now
46 .OP \-labelwidget labelWidget LabelWidget
47 The name of a widget to use for the label.
48 If set, overrides the \fB\-text\fR option.
49 The \fB\-labelwidget\fR must be a child of the \fBlabelframe\fR widget
50 or one of the \fBlabelframe\fR's ancestors, and must belong to the
51 same top-level widget as the \fBlabelframe\fR.
4252 .OP \-text text Text
4353 Specifies the text of the label.
4454 .OP \-underline underline Underline
4757 The underlined character is used for mnemonic activation.
4858 Mnemonic activation for a \fBttk::labelframe\fR
4959 sets the keyboard focus to the first child of the \fBttk::labelframe\fR widget.
50 .OP \-labelwidget labelWidget LabelWidget
51 The name of a widget to use for the label.
52 If set, overrides the \fB\-text\fR option.
53 The \fB\-labelwidget\fR must be a child of the \fBlabelframe\fR widget
54 or one of the \fBlabelframe\fR's ancestors, and must belong to the
55 same top-level widget as the \fBlabelframe\fR.
5660 .OP \-width width Width
5761 If specified, the widget's requested width in pixels.
58 .OP \-height height Height
59 If specified, the widget's requested height in pixels.
60 (See \fIttk::frame(n)\fR for further notes on \fB\-width\fR and
61 \fB\-height\fR).
6262 .SH "WIDGET COMMAND"
6363 .PP
6464 Supports the standard widget commands
5757 .br
5858 \fB\-background\fP \fIcolor\fP
5959 .br
60 \fB\-compound\fP \fIcompound\fP
61 .br
6062 \fB\-foreground\fP \fIcolor\fP
6163 .br
6264 \fB\-font\fP \fIfont\fP
241241 .br
242242 \fB\-bordercolor\fP \fIcolor\fP
243243 .br
244 \fB\-compound\fP \fIcompound\fP
245 .br
244246 \fB\-expand\fP \fIpadding\fP
245247 .RS
246248 Defines how much the tab grows in size. Usually used with the
4848 that is, the progress bar completes one
4949 .QW cycle
5050 when the \fB\-value\fR increases by \fB\-maximum\fR.
51 If \fB\-variable\fR is set to an existing variable, specifying \fB\-value\fR
52 has no effect (the variable value takes precedence).
5153 .OP \-variable variable Variable
5254 The name of a global Tcl variable which is linked to the \fB\-value\fR.
53 If specified, the \fB\-value\fR of the progress bar is
55 If specified to an existing variable, the \fB\-value\fR of the progress bar is
5456 automatically set to the value of the variable whenever
5557 the latter is modified.
5658 .SH "WIDGET COMMAND"
7676 .PP
7777 \fB\-background\fP \fIcolor\fP
7878 .br
79 \fB\-compound\fP \fIcompound\fP
80 .br
7981 \fB\-foreground\fP \fIcolor\fP
8082 .br
8183 \fB\-indicatorbackground\fP \fIcolor\fP
4141 This value may be either less than or greater than the \fB\-from\fR option.
4242 .OP \-value value Value
4343 Specifies the current floating-point value of the variable.
44 If \fB\-variable\fR is set to an existing variable, specifying \fB\-value\fR
45 has no effect (the variable value takes precedence).
4446 .OP \-variable variable Variable
4547 Specifies the name of a global variable to link to the scale. Whenever the
4648 value of the variable changes, the scale will update to reflect this value.
9294 is omitted.
9395 .SH "STYLING OPTIONS"
9496 .PP
95 The class name for a \fBttk::scale\fP is \fBTProgressbar\fP.
97 The class name for a \fBttk::scale\fP is \fBTScale\fP.
9698 .PP
9799 Dynamic states: \fBactive\fP.
98100 .PP
7575 .SH "INTERNAL COMMANDS"
7676 .PP
7777 The following widget commands are used internally
78 by the TScrollbar widget class bindings.
78 by the \fBTScrollbar\fP widget class bindings.
7979 .TP
8080 \fIpathName \fBdelta \fIdeltaX deltaY\fR
8181 Returns a real number indicating the fractional change in
152152 grid $f.hsb \-row 1 \-column 0 \-sticky nsew
153153 grid columnconfigure $f 0 \-weight 1
154154 grid rowconfigure $f 0 \-weight 1
155 pack $f
155156 .CE
156157 .SH "STYLING OPTIONS"
157158 .PP
159160 .PP
160161 Dynamic states: \fBactive\fP, \fBdisabled\fP.
161162 .PP
162 \fBTScrollbar\fP styling options configurable with \fBttk::style\fP
163 are:
163 \fBTScrollbar\fP (or more specifically \fBVertical.TScrollbar\fP and
164 \fBHorizontal.TScrollbar\fP) styling options that are configurable with
165 \fBttk::style\fP are:
164166 .PP
165167 \fB\-arrowcolor\fP \fIcolor\fP
168 .br
169 \fB\-arrowsize\fP \fIamount\fP
166170 .br
167171 \fB\-background\fP \fIcolor\fP
168172 .br
169173 \fB\-bordercolor\fP \fIcolor\fP
170174 .br
171 \fB\-darkcolor\fP \fIcolor\fP
175 \fB\-darkcolor\fP \fIcolor\fP (color of the dark part of the 3D relief)
172176 .br
173177 \fB\-foreground\fP \fIcolor\fP
174178 .br
175 \fB\-lightcolor\fP \fIcolor\fP
179 \fB\-gripcount\fP \fIcount\fP (number of lines on the thumb)
180 .br
181 \fB\-lightcolor\fP \fIcolor\fP (color of the light part of the 3D relief)
176182 .br
177183 \fB\-troughcolor\fP \fIcolor\fP
178184 .PP
9494 .br
9595 \fB\-background\fP \fIcolor\fP
9696 .RS
97 When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP.
97 For backwards compatibility, when using the aqua theme (for macOS), this
98 option behaves as an alias for the \fB\-fieldbackground\fP provided that no
99 value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored.
98100 .RE
99101 \fB\-bordercolor\fP \fIcolor\fP
100102 .br
101103 \fB\-darkcolor\fP \fIcolor\fP
102104 .br
103105 \fB\-fieldbackground\fP \fIcolor\fP
104 .RS
105 Does not work with the aqua theme (Mac OS X).
106 .RE
106 .br
107107 \fB\-foreground\fP \fIcolor\fP
108108 .br
109109 \fB\-lightcolor\fP \fIcolor\fP
1414 .SH NOTES
1515 .PP
1616 See also the Tcl'2004 conference presentation,
17 available at http://tktable.sourceforge.net/tile/tile-tcl2004.pdf
17 available at https://tktable.sourceforge.net/tile/tile-tcl2004.pdf
1818 .SH DEFINITIONS
1919 .PP
2020 Each widget is assigned a \fIstyle\fR,
132132 For example, [\fI$pathname \fBcolumn #\fIn \fB\-id\fR]
133133 returns the data column associated with display column #\fIn\fR.
134134 .TP
135 \fB\-anchor\fR
135 \fB\-anchor \fIanchor\fR
136136 Specifies how the text in this column should be aligned
137 with respect to the cell. One of
137 with respect to the cell. \fIAnchor\fR is one of
138138 \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR,
139139 \fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR.
140140 .TP
141 \fB\-minwidth\fR
141 \fB\-minwidth \fIminwidth\fR
142142 The minimum width of the column in pixels.
143143 The treeview widget will not make the column any smaller than
144144 \fB\-minwidth\fR when the widget is resized or the user drags a
145 column separator. Default is 20 pixels.
146 .TP
147 \fB\-stretch \fIboolean\fR
148 Specifies whether or not the column width should be adjusted
149 when the widget is resized or the user drags a column separator.
150 \fIBoolean\fR may have any of the forms accepted by \fBTcl_GetBoolean\fR.
151 By default columns are stretchable.
152 .TP
153 \fB\-width \fIwidth\fR
154 The width of the column in pixels. Default is 200 pixels. The specified
155 column width may be changed by Tk in order to honor \fB\-stretch\fR
156 and/or \fB\-minwidth\fR, or when the widget is resized or the user drags a
145157 column separator.
146 .TP
147 \fB\-stretch\fR
148 Specifies whether or not the column's width should be adjusted
149 when the widget is resized.
150 .TP
151 \fB\-width \fIw\fR
152 The width of the column in pixels. Default is something reasonable,
153 probably 200 or so.
154158 .PP
155159 Use \fIpathname column #0\fR to configure the tree column.
156160 .RE
230234 Returns the item ID of the item at position \fIy\fR.
231235 .TP
232236 \fIpathname \fBidentify column \fIx y\fR
233 Returns the data column identifier of the cell at position \fIx\fR.
237 Returns the display column identifier of the cell at position \fIx\fR.
234238 The tree column has ID \fB#0\fR.
235239 .TP
236240 \fIpathname \fBidentify element \fIx y\fR
387391 If \fItag\fR is not present for a particular item,
388392 then the \fB\-tags\fR for that item are unchanged.
389393 .RE
390 .TP
391 \fIpathName \fBxview \fIargs\fR
392 Standard command for horizontal scrolling; see \fIwidget(n)\fR.
393 .TP
394 \fIpathName \fByview \fIargs\fR
395 Standard command for vertical scrolling; see \fIttk::widget(n)\fR.
394 .PP
395 The treeview widget also supports the following generic \fBttk::widget\fR
396 widget subcommands (see \fIttk::widget(n)\fR for details):
397 .DS
398 .ta 5.5c 11c
399 \fBxview\fR \fByview\fR
400 .DE
396401 .SH "ITEM OPTIONS"
397402 .PP
398403 The following item options may be specified for items
433438 Specifies the item image, in case the item's \fB\-image\fR option is empty.
434439 .\" .PP
435440 .\" \fI(@@@ TODO: sort out order of precedence for options)\fR
441 .PP
442 Tag priority is decided by the creation order: tags created first receive
443 higher priority.
436444 .SH "COLUMN IDENTIFIERS"
437445 .PP
438446 Column identifiers take any of the following forms:
191191 If \fIstateSpec\fR is not specified,
192192 returns a list of the currently-enabled state flags.
193193 .RE
194 .TP
195 \fIpathName \fBxview \fIargs\fR
196 This command is used to query and change the horizontal position of the
197 content in the widget's window. It can take any of the following
198 forms:
199 .RS
200 .TP
201 \fIpathName \fBxview\fR
202 Returns a list containing two elements.
203 Each element is a real fraction between 0 and 1; together they describe
204 the horizontal span that is visible in the window.
205 For example, if the first element is .2 and the second element is .6,
206 20% of the widget's content is off-screen to the left, the middle 40% is visible
207 in the window, and 40% of the content is off-screen to the right.
208 These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR
209 option.
210 .TP
211 \fIpathName \fBxview\fR \fIindex\fR
212 Adjusts the view in the window so that the content given by \fIindex\fR
213 is displayed at the left edge of the window.
214 .TP
215 \fIpathName \fBxview moveto\fI fraction\fR
216 Adjusts the view in the window so that the character \fIfraction\fR of the
217 way through the content appears at the left edge of the window.
218 \fIFraction\fR must be a fraction between 0 and 1.
219 .TP
220 \fIpathName \fBxview scroll \fInumber what\fR
221 This command shifts the view in the window left or right according to
222 \fInumber\fR and \fIwhat\fR.
223 \fINumber\fR must be an integer.
224 \fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
225 '\" or an abbreviation of one of these, but we don't document that.
226 If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by
227 \fInumber\fR average-width characters on the display; if it is
228 \fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
229 If \fInumber\fR is negative then characters farther to the left
230 become visible; if it is positive then characters farther to the right
231 become visible.
232 .RE
233 .TP
234 \fIpathName \fByview \fIargs\fR
235 This command is used to query and change the vertical position of the
236 content in the widget's window. It can take any of the following
237 forms:
238 .RS
239 .TP
240 \fIpathName \fByview\fR
241 Returns a list containing two elements.
242 Each element is a real fraction between 0 and 1; together they describe
243 the vertical span that is visible in the window.
244 For example, if the first element is .2 and the second element is .6,
245 20% of the widget's content is off-screen to the top, the middle 40% is visible
246 in the window, and 40% of the content is off-screen to the bottom.
247 These are the same values passed to scrollbars via the \fB\-yscrollcommand\fR
248 option.
249 .TP
250 \fIpathName \fByview\fR \fIindex\fR
251 Adjusts the view in the window so that the content given by \fIindex\fR
252 is displayed at the top edge of the window.
253 .TP
254 \fIpathName \fByview moveto\fI fraction\fR
255 Adjusts the view in the window so that the item \fIfraction\fR of the
256 way through the content appears at the top edge of the window.
257 \fIFraction\fR must be a fraction between 0 and 1.
258 .TP
259 \fIpathName \fByview scroll \fInumber what\fR
260 This command shifts the view in the window up or down according to
261 \fInumber\fR and \fIwhat\fR.
262 \fINumber\fR must be an integer.
263 \fIWhat\fR must be either \fBunits\fR or \fBpages\fR.
264 '\" or an abbreviation of one of these, but we don't document that.
265 If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by
266 \fInumber\fR average-width characters on the display; if it is
267 \fBpages\fR then the view adjusts by \fInumber\fR screenfuls.
268 If \fInumber\fR is negative then items farther to the top
269 become visible; if it is positive then items farther to the bottom
270 become visible.
271 .RE
194272 .SH "WIDGET STATES"
195273 The widget state is a bitmap of independent state flags.
196274 Widget state flags include:
7272 screen of the application's main window.
7373 If no window in this application contains the point then an empty
7474 string is returned.
75 An empty string is also returned if the point lies in the title bar
76 or border of its highest containing toplevel in this application.
77 (Note that with some window managers the borders may be invisible.)
7578 In selecting the containing window, children are given higher priority
7679 than parents and among siblings the highest one in the stacking order is
7780 chosen.
709709 .TP
710710 \fBwm transient \fIwindow\fR ?\fImaster\fR?
711711 .
712 If \fImaster\fR is specified, then the window manager is informed
713 that \fIwindow\fR is a transient window (e.g. pull-down menu) working
714 on behalf of \fImaster\fR (where \fImaster\fR is the
715 path name for a top-level window). If \fImaster\fR
716 is specified as an empty string then \fIwindow\fR is marked as not
717 being a transient window any more. Otherwise the command
718 returns the path name of \fIwindow\fR's current master, or an
719 empty string if \fIwindow\fR is not currently a transient window.
720 A transient window will mirror state changes in the master and
721 inherit the state of the master when initially mapped. It is an
722 error to attempt to make a window a transient of itself.
723 The window manager may also decorate a transient window differently, removing
724 some features normally present (e.g., minimize and maximize buttons) though
725 this is entirely at the discretion of the window manager.
712 If \fImaster\fR is specified, then the window manager is informed that
713 \fIwindow\fR is a transient window (e.g. pull-down menu) working on
714 behalf of \fImaster\fR (where \fImaster\fR is the path name for a
715 top-level window). If \fImaster\fR is specified as an empty string
716 then \fIwindow\fR is marked as not being a transient window any more.
717 Otherwise the command returns the path name of \fIwindow\fR's current
718 master, or an empty string if \fIwindow\fR is not currently a
719 transient window. A transient window will mirror state changes in the
720 master and inherit the state of the master when initially mapped. The
721 directed graph with an edge from each transient to its master must be
722 acyclic. In particular, it is an error to attempt to make a window a
723 transient of itself. The window manager may also decorate a transient
724 window differently, removing some features normally present (e.g.,
725 minimize and maximize buttons) though this is entirely at the
726 discretion of the window manager.
726727 .TP
727728 \fBwm withdraw \fIwindow\fR
728729 .
33 * Note that this should be done manually only, because in some cases
44 * keysymdefs.h defines the same integer for multiple keysyms, e.g.:
55 *
6 * #define XK_Greek_LAMDA 0x7cb
7 * #define XK_Greek_LAMBDA 0x7cb
6 * #define XK_Greek_LAMDA 0x7CB
7 * #define XK_Greek_LAMBDA 0x7CB
88 *
9 * #define XK_Cyrillic_DZHE 0x6bf
10 * #define XK_Serbian_DZE 0x6bf (deprecated)
9 * #define XK_Cyrillic_DZHE 0x6BF
10 * #define XK_Serbian_DZE 0x6BF (deprecated)
1111 *
1212 */
1313 { "BackSpace", 0xFF08 },
2222 { "Delete", 0xFFFF },
2323 { "Multi_key", 0xFF20 },
2424 { "Kanji", 0xFF21 },
25 { "Muhenkan", 0xFF22 },
26 { "Henkan_Mode", 0xFF23 },
27 { "Henkan", 0xFF23 },
28 { "Romaji", 0xFF24 },
29 { "Hiragana", 0xFF25 },
30 { "Katakana", 0xFF26 },
31 { "Hiragana_Katakana", 0xFF27 },
32 { "Zenkaku", 0xFF28 },
33 { "Hankaku", 0xFF29 },
34 { "Zenkaku_Hankaku", 0xFF2A },
35 { "Touroku", 0xFF2B },
36 { "Massyo", 0xFF2C },
37 { "Kana_Lock", 0xFF2D },
38 { "Kana_Shift", 0xFF2E },
39 { "Eisu_Shift", 0xFF2F },
40 { "Eisu_toggle", 0xFF30 },
2541 { "Home", 0xFF50 },
2642 { "Left", 0xFF51 },
2743 { "Up", 0xFF52 },
2844 { "Right", 0xFF53 },
2945 { "Down", 0xFF54 },
3046 { "Prior", 0xFF55 },
47 { "Page_Up", 0xFF55 },
3148 { "Next", 0xFF56 },
49 { "Page_Down", 0xFF56 },
3250 { "End", 0xFF57 },
3351 { "Begin", 0xFF58 },
3452 { "Win_L", 0xFF5B },
5573 { "KP_F2", 0xFF92 },
5674 { "KP_F3", 0xFF93 },
5775 { "KP_F4", 0xFF94 },
76 { "KP_Home", 0xFF95 },
77 { "KP_Left", 0xFF96 },
78 { "KP_Up", 0xFF97 },
79 { "KP_Right", 0xFF98 },
80 { "KP_Down", 0xFF99 },
81 { "KP_Prior", 0xFF9A },
82 { "KP_Page_Up", 0xFF9A },
83 { "KP_Next", 0xFF9B },
84 { "KP_Page_Down", 0xFF9B },
85 { "KP_End", 0xFF9C },
86 { "KP_Begin", 0xFF9D },
87 { "KP_Insert", 0xFF9E },
88 { "KP_Delete", 0xFF9F },
5889 { "KP_Equal", 0xFFBD },
5990 { "KP_Multiply", 0xFFAA },
6091 { "KP_Add", 0xFFAB },
146177 { "Super_R", 0xFFEC },
147178 { "Hyper_L", 0xFFED },
148179 { "Hyper_R", 0xFFEE },
149 { "space", 0x020 },
150 { "exclam", 0x021 },
151 { "quotedbl", 0x022 },
152 { "numbersign", 0x023 },
153 { "dollar", 0x024 },
154 { "percent", 0x025 },
155 { "ampersand", 0x026 },
156 { "quoteright", 0x027 },
157 { "parenleft", 0x028 },
158 { "parenright", 0x029 },
159 { "asterisk", 0x02a },
160 { "plus", 0x02b },
161 { "comma", 0x02c },
162 { "minus", 0x02d },
163 { "period", 0x02e },
164 { "slash", 0x02f },
165 { "0", 0x030 },
166 { "1", 0x031 },
167 { "2", 0x032 },
168 { "3", 0x033 },
169 { "4", 0x034 },
170 { "5", 0x035 },
171 { "6", 0x036 },
172 { "7", 0x037 },
173 { "8", 0x038 },
174 { "9", 0x039 },
175 { "colon", 0x03a },
176 { "semicolon", 0x03b },
177 { "less", 0x03c },
178 { "equal", 0x03d },
179 { "greater", 0x03e },
180 { "question", 0x03f },
181 { "at", 0x040 },
182 { "A", 0x041 },
183 { "B", 0x042 },
184 { "C", 0x043 },
185 { "D", 0x044 },
186 { "E", 0x045 },
187 { "F", 0x046 },
188 { "G", 0x047 },
189 { "H", 0x048 },
190 { "I", 0x049 },
191 { "J", 0x04a },
192 { "K", 0x04b },
193 { "L", 0x04c },
194 { "M", 0x04d },
195 { "N", 0x04e },
196 { "O", 0x04f },
197 { "P", 0x050 },
198 { "Q", 0x051 },
199 { "R", 0x052 },
200 { "S", 0x053 },
201 { "T", 0x054 },
202 { "U", 0x055 },
203 { "V", 0x056 },
204 { "W", 0x057 },
205 { "X", 0x058 },
206 { "Y", 0x059 },
207 { "Z", 0x05a },
208 { "bracketleft", 0x05b },
209 { "backslash", 0x05c },
210 { "bracketright", 0x05d },
211 { "asciicircum", 0x05e },
212 { "underscore", 0x05f },
213 { "quoteleft", 0x060 },
214 { "a", 0x061 },
215 { "b", 0x062 },
216 { "c", 0x063 },
217 { "d", 0x064 },
218 { "e", 0x065 },
219 { "f", 0x066 },
220 { "g", 0x067 },
221 { "h", 0x068 },
222 { "i", 0x069 },
223 { "j", 0x06a },
224 { "k", 0x06b },
225 { "l", 0x06c },
226 { "m", 0x06d },
227 { "n", 0x06e },
228 { "o", 0x06f },
229 { "p", 0x070 },
230 { "q", 0x071 },
231 { "r", 0x072 },
232 { "s", 0x073 },
233 { "t", 0x074 },
234 { "u", 0x075 },
235 { "v", 0x076 },
236 { "w", 0x077 },
237 { "x", 0x078 },
238 { "y", 0x079 },
239 { "z", 0x07a },
240 { "braceleft", 0x07b },
241 { "bar", 0x07c },
242 { "braceright", 0x07d },
243 { "asciitilde", 0x07e },
244 { "nobreakspace", 0x0a0 },
245 { "exclamdown", 0x0a1 },
246 { "cent", 0x0a2 },
247 { "sterling", 0x0a3 },
248 { "currency", 0x0a4 },
249 { "yen", 0x0a5 },
250 { "brokenbar", 0x0a6 },
251 { "section", 0x0a7 },
252 { "diaeresis", 0x0a8 },
253 { "copyright", 0x0a9 },
254 { "ordfeminine", 0x0aa },
255 { "guillemotleft", 0x0ab },
256 { "notsign", 0x0ac },
257 { "hyphen", 0x0ad },
258 { "registered", 0x0ae },
259 { "macron", 0x0af },
260 { "degree", 0x0b0 },
261 { "plusminus", 0x0b1 },
262 { "twosuperior", 0x0b2 },
263 { "threesuperior", 0x0b3 },
264 { "acute", 0x0b4 },
265 { "mu", 0x0b5 },
266 { "paragraph", 0x0b6 },
267 { "periodcentered", 0x0b7 },
268 { "cedilla", 0x0b8 },
269 { "onesuperior", 0x0b9 },
270 { "masculine", 0x0ba },
271 { "guillemotright", 0x0bb },
272 { "onequarter", 0x0bc },
273 { "onehalf", 0x0bd },
274 { "threequarters", 0x0be },
275 { "questiondown", 0x0bf },
276 { "Agrave", 0x0c0 },
277 { "Aacute", 0x0c1 },
278 { "Acircumflex", 0x0c2 },
279 { "Atilde", 0x0c3 },
280 { "Adiaeresis", 0x0c4 },
281 { "Aring", 0x0c5 },
282 { "AE", 0x0c6 },
283 { "Ccedilla", 0x0c7 },
284 { "Egrave", 0x0c8 },
285 { "Eacute", 0x0c9 },
286 { "Ecircumflex", 0x0ca },
287 { "Ediaeresis", 0x0cb },
288 { "Igrave", 0x0cc },
289 { "Iacute", 0x0cd },
290 { "Icircumflex", 0x0ce },
291 { "Idiaeresis", 0x0cf },
292 { "Eth", 0x0d0 },
293 { "Ntilde", 0x0d1 },
294 { "Ograve", 0x0d2 },
295 { "Oacute", 0x0d3 },
296 { "Ocircumflex", 0x0d4 },
297 { "Otilde", 0x0d5 },
298 { "Odiaeresis", 0x0d6 },
299 { "multiply", 0x0d7 },
300 { "Ooblique", 0x0d8 },
301 { "Ugrave", 0x0d9 },
302 { "Uacute", 0x0da },
303 { "Ucircumflex", 0x0db },
304 { "Udiaeresis", 0x0dc },
305 { "Yacute", 0x0dd },
306 { "Thorn", 0x0de },
307 { "ssharp", 0x0df },
308 { "agrave", 0x0e0 },
309 { "aacute", 0x0e1 },
310 { "acircumflex", 0x0e2 },
311 { "atilde", 0x0e3 },
312 { "adiaeresis", 0x0e4 },
313 { "aring", 0x0e5 },
314 { "ae", 0x0e6 },
315 { "ccedilla", 0x0e7 },
316 { "egrave", 0x0e8 },
317 { "eacute", 0x0e9 },
318 { "ecircumflex", 0x0ea },
319 { "ediaeresis", 0x0eb },
320 { "igrave", 0x0ec },
321 { "iacute", 0x0ed },
322 { "icircumflex", 0x0ee },
323 { "idiaeresis", 0x0ef },
324 { "eth", 0x0f0 },
325 { "ntilde", 0x0f1 },
326 { "ograve", 0x0f2 },
327 { "oacute", 0x0f3 },
328 { "ocircumflex", 0x0f4 },
329 { "otilde", 0x0f5 },
330 { "odiaeresis", 0x0f6 },
331 { "division", 0x0f7 },
332 { "oslash", 0x0f8 },
333 { "ugrave", 0x0f9 },
334 { "uacute", 0x0fa },
335 { "ucircumflex", 0x0fb },
336 { "udiaeresis", 0x0fc },
337 { "yacute", 0x0fd },
338 { "thorn", 0x0fe },
339 { "ydiaeresis", 0x0ff },
340 { "Aogonek", 0x1a1 },
341 { "breve", 0x1a2 },
342 { "Lstroke", 0x1a3 },
343 { "Lcaron", 0x1a5 },
344 { "Sacute", 0x1a6 },
345 { "Scaron", 0x1a9 },
346 { "Scedilla", 0x1aa },
347 { "Tcaron", 0x1ab },
348 { "Zacute", 0x1ac },
349 { "Zcaron", 0x1ae },
350 { "Zabovedot", 0x1af },
351 { "aogonek", 0x1b1 },
352 { "ogonek", 0x1b2 },
353 { "lstroke", 0x1b3 },
354 { "lcaron", 0x1b5 },
355 { "sacute", 0x1b6 },
356 { "caron", 0x1b7 },
357 { "scaron", 0x1b9 },
358 { "scedilla", 0x1ba },
359 { "tcaron", 0x1bb },
360 { "zacute", 0x1bc },
361 { "doubleacute", 0x1bd },
362 { "zcaron", 0x1be },
363 { "zabovedot", 0x1bf },
364 { "Racute", 0x1c0 },
365 { "Abreve", 0x1c3 },
366 { "Cacute", 0x1c6 },
367 { "Ccaron", 0x1c8 },
368 { "Eogonek", 0x1ca },
369 { "Ecaron", 0x1cc },
370 { "Dcaron", 0x1cf },
371 { "Nacute", 0x1d1 },
372 { "Ncaron", 0x1d2 },
373 { "Odoubleacute", 0x1d5 },
374 { "Rcaron", 0x1d8 },
375 { "Uring", 0x1d9 },
376 { "Udoubleacute", 0x1db },
377 { "Tcedilla", 0x1de },
378 { "racute", 0x1e0 },
379 { "abreve", 0x1e3 },
380 { "cacute", 0x1e6 },
381 { "ccaron", 0x1e8 },
382 { "eogonek", 0x1ea },
383 { "ecaron", 0x1ec },
384 { "dcaron", 0x1ef },
385 { "nacute", 0x1f1 },
386 { "ncaron", 0x1f2 },
387 { "odoubleacute", 0x1f5 },
388 { "udoubleacute", 0x1fb },
389 { "rcaron", 0x1f8 },
390 { "uring", 0x1f9 },
391 { "tcedilla", 0x1fe },
392 { "abovedot", 0x1ff },
393 { "Hstroke", 0x2a1 },
394 { "Hcircumflex", 0x2a6 },
395 { "Iabovedot", 0x2a9 },
396 { "Gbreve", 0x2ab },
397 { "Jcircumflex", 0x2ac },
398 { "hstroke", 0x2b1 },
399 { "hcircumflex", 0x2b6 },
400 { "idotless", 0x2b9 },
401 { "gbreve", 0x2bb },
402 { "jcircumflex", 0x2bc },
403 { "Cabovedot", 0x2c5 },
404 { "Ccircumflex", 0x2c6 },
405 { "Gabovedot", 0x2d5 },
406 { "Gcircumflex", 0x2d8 },
407 { "Ubreve", 0x2dd },
408 { "Scircumflex", 0x2de },
409 { "cabovedot", 0x2e5 },
410 { "ccircumflex", 0x2e6 },
411 { "gabovedot", 0x2f5 },
412 { "gcircumflex", 0x2f8 },
413 { "ubreve", 0x2fd },
414 { "scircumflex", 0x2fe },
415 { "kappa", 0x3a2 },
416 { "Rcedilla", 0x3a3 },
417 { "Itilde", 0x3a5 },
418 { "Lcedilla", 0x3a6 },
419 { "Emacron", 0x3aa },
420 { "Gcedilla", 0x3ab },
421 { "Tslash", 0x3ac },
422 { "rcedilla", 0x3b3 },
423 { "itilde", 0x3b5 },
424 { "lcedilla", 0x3b6 },
425 { "emacron", 0x3ba },
426 { "gacute", 0x3bb },
427 { "tslash", 0x3bc },
428 { "ENG", 0x3bd },
429 { "eng", 0x3bf },
430 { "Amacron", 0x3c0 },
431 { "Iogonek", 0x3c7 },
432 { "Eabovedot", 0x3cc },
433 { "Imacron", 0x3cf },
434 { "Ncedilla", 0x3d1 },
435 { "Omacron", 0x3d2 },
436 { "Kcedilla", 0x3d3 },
437 { "Uogonek", 0x3d9 },
438 { "Utilde", 0x3dd },
439 { "Umacron", 0x3de },
440 { "amacron", 0x3e0 },
441 { "iogonek", 0x3e7 },
442 { "eabovedot", 0x3ec },
443 { "imacron", 0x3ef },
444 { "ncedilla", 0x3f1 },
445 { "omacron", 0x3f2 },
446 { "kcedilla", 0x3f3 },
447 { "uogonek", 0x3f9 },
448 { "utilde", 0x3fd },
449 { "umacron", 0x3fe },
450 { "overline", 0x47e },
451 { "kana_fullstop", 0x4a1 },
452 { "kana_openingbracket", 0x4a2 },
453 { "kana_closingbracket", 0x4a3 },
454 { "kana_comma", 0x4a4 },
455 { "kana_middledot", 0x4a5 },
456 { "kana_WO", 0x4a6 },
457 { "kana_a", 0x4a7 },
458 { "kana_i", 0x4a8 },
459 { "kana_u", 0x4a9 },
460 { "kana_e", 0x4aa },
461 { "kana_o", 0x4ab },
462 { "kana_ya", 0x4ac },
463 { "kana_yu", 0x4ad },
464 { "kana_yo", 0x4ae },
465 { "kana_tu", 0x4af },
466 { "prolongedsound", 0x4b0 },
467 { "kana_A", 0x4b1 },
468 { "kana_I", 0x4b2 },
469 { "kana_U", 0x4b3 },
470 { "kana_E", 0x4b4 },
471 { "kana_O", 0x4b5 },
472 { "kana_KA", 0x4b6 },
473 { "kana_KI", 0x4b7 },
474 { "kana_KU", 0x4b8 },
475 { "kana_KE", 0x4b9 },
476 { "kana_KO", 0x4ba },
477 { "kana_SA", 0x4bb },
478 { "kana_SHI", 0x4bc },
479 { "kana_SU", 0x4bd },
480 { "kana_SE", 0x4be },
481 { "kana_SO", 0x4bf },
482 { "kana_TA", 0x4c0 },
483 { "kana_TI", 0x4c1 },
484 { "kana_TU", 0x4c2 },
485 { "kana_TE", 0x4c3 },
486 { "kana_TO", 0x4c4 },
487 { "kana_NA", 0x4c5 },
488 { "kana_NI", 0x4c6 },
489 { "kana_NU", 0x4c7 },
490 { "kana_NE", 0x4c8 },
491 { "kana_NO", 0x4c9 },
492 { "kana_HA", 0x4ca },
493 { "kana_HI", 0x4cb },
494 { "kana_HU", 0x4cc },
495 { "kana_HE", 0x4cd },
496 { "kana_HO", 0x4ce },
497 { "kana_MA", 0x4cf },
498 { "kana_MI", 0x4d0 },
499 { "kana_MU", 0x4d1 },
500 { "kana_ME", 0x4d2 },
501 { "kana_MO", 0x4d3 },
502 { "kana_YA", 0x4d4 },
503 { "kana_YU", 0x4d5 },
504 { "kana_YO", 0x4d6 },
505 { "kana_RA", 0x4d7 },
506 { "kana_RI", 0x4d8 },
507 { "kana_RU", 0x4d9 },
508 { "kana_RE", 0x4da },
509 { "kana_RO", 0x4db },
510 { "kana_WA", 0x4dc },
511 { "kana_N", 0x4dd },
512 { "voicedsound", 0x4de },
513 { "semivoicedsound", 0x4df },
180 { "space", 0x20 },
181 { "exclam", 0x21 },
182 { "quotedbl", 0x22 },
183 { "numbersign", 0x23 },
184 { "dollar", 0x24 },
185 { "percent", 0x25 },
186 { "ampersand", 0x26 },
187 { "apostrophe", 0x27 },
188 { "quoteright", 0x27 },
189 { "parenleft", 0x28 },
190 { "parenright", 0x29 },
191 { "asterisk", 0x2A },
192 { "plus", 0x2B },
193 { "comma", 0x2C },
194 { "minus", 0x2D },
195 { "period", 0x2E },
196 { "slash", 0x2F },
197 { "0", 0x30 },
198 { "1", 0x31 },
199 { "2", 0x32 },
200 { "3", 0x33 },
201 { "4", 0x34 },
202 { "5", 0x35 },
203 { "6", 0x36 },
204 { "7", 0x37 },
205 { "8", 0x38 },
206 { "9", 0x39 },
207 { "colon", 0x3A },
208 { "semicolon", 0x3B },
209 { "less", 0x3C },
210 { "equal", 0x3D },
211 { "greater", 0x3E },
212 { "question", 0x3F },
213 { "at", 0x40 },
214 { "A", 0x41 },
215 { "B", 0x42 },
216 { "C", 0x43 },
217 { "D", 0x44 },
218 { "E", 0x45 },
219 { "F", 0x46 },
220 { "G", 0x47 },
221 { "H", 0x48 },
222 { "I", 0x49 },
223 { "J", 0x4A },
224 { "K", 0x4B },
225 { "L", 0x4C },
226 { "M", 0x4D },
227 { "N", 0x4E },
228 { "O", 0x4F },
229 { "P", 0x50 },
230 { "Q", 0x51 },
231 { "R", 0x52 },
232 { "S", 0x53 },
233 { "T", 0x54 },
234 { "U", 0x55 },
235 { "V", 0x56 },
236 { "W", 0x57 },
237 { "X", 0x58 },
238 { "Y", 0x59 },
239 { "Z", 0x5A },
240 { "bracketleft", 0x5B },
241 { "backslash", 0x5C },
242 { "bracketright", 0x5D },
243 { "asciicircum", 0x5E },
244 { "underscore", 0x5F },
245 { "grave", 0x60 },
246 { "quoteleft", 0x60 },
247 { "a", 0x61 },
248 { "b", 0x62 },
249 { "c", 0x63 },
250 { "d", 0x64 },
251 { "e", 0x65 },
252 { "f", 0x66 },
253 { "g", 0x67 },
254 { "h", 0x68 },
255 { "i", 0x69 },
256 { "j", 0x6A },
257 { "k", 0x6B },
258 { "l", 0x6C },
259 { "m", 0x6D },
260 { "n", 0x6E },
261 { "o", 0x6F },
262 { "p", 0x70 },
263 { "q", 0x71 },
264 { "r", 0x72 },
265 { "s", 0x73 },
266 { "t", 0x74 },
267 { "u", 0x75 },
268 { "v", 0x76 },
269 { "w", 0x77 },
270 { "x", 0x78 },
271 { "y", 0x79 },
272 { "z", 0x7A },
273 { "braceleft", 0x7B },
274 { "bar", 0x7C },
275 { "braceright", 0x7D },
276 { "asciitilde", 0x7E },
277 { "nobreakspace", 0xA0 },
278 { "exclamdown", 0xA1 },
279 { "cent", 0xA2 },
280 { "sterling", 0xA3 },
281 { "currency", 0xA4 },
282 { "yen", 0xA5 },
283 { "brokenbar", 0xA6 },
284 { "section", 0xA7 },
285 { "diaeresis", 0xA8 },
286 { "copyright", 0xA9 },
287 { "ordfeminine", 0xAA },
288 { "guillemotleft", 0xAB },
289 { "notsign", 0xAC },
290 { "hyphen", 0xAD },
291 { "registered", 0xAE },
292 { "macron", 0xAF },
293 { "degree", 0xB0 },
294 { "plusminus", 0xB1 },
295 { "twosuperior", 0xB2 },
296 { "threesuperior", 0xB3 },
297 { "acute", 0xB4 },
298 { "mu", 0xB5 },
299 { "paragraph", 0xB6 },
300 { "periodcentered", 0xB7 },
301 { "cedilla", 0xB8 },
302 { "onesuperior", 0xB9 },
303 { "masculine", 0xBA },
304 { "guillemotright", 0xBB },
305 { "onequarter", 0xBC },
306 { "onehalf", 0xBD },
307 { "threequarters", 0xBE },
308 { "questiondown", 0xBF },
309 { "Agrave", 0xC0 },
310 { "Aacute", 0xC1 },
311 { "Acircumflex", 0xC2 },
312 { "Atilde", 0xC3 },
313 { "Adiaeresis", 0xC4 },
314 { "Aring", 0xC5 },
315 { "AE", 0xC6 },
316 { "Ccedilla", 0xC7 },
317 { "Egrave", 0xC8 },
318 { "Eacute", 0xC9 },
319 { "Ecircumflex", 0xCA },
320 { "Ediaeresis", 0xCB },
321 { "Igrave", 0xCC },
322 { "Iacute", 0xCD },
323 { "Icircumflex", 0xCE },
324 { "Idiaeresis", 0xCF },
325 { "ETH", 0xD0 },
326 { "Eth", 0xD0 },
327 { "Ntilde", 0xD1 },
328 { "Ograve", 0xD2 },
329 { "Oacute", 0xD3 },
330 { "Ocircumflex", 0xD4 },
331 { "Otilde", 0xD5 },
332 { "Odiaeresis", 0xD6 },
333 { "multiply", 0xD7 },
334 { "Oslash", 0xD8 },
335 { "Ooblique", 0xD8 },
336 { "Ugrave", 0xD9 },
337 { "Uacute", 0xDA },
338 { "Ucircumflex", 0xDB },
339 { "Udiaeresis", 0xDC },
340 { "Yacute", 0xDD },
341 { "THORN", 0xDE },
342 { "Thorn", 0xDE },
343 { "ssharp", 0xDF },
344 { "agrave", 0xE0 },
345 { "aacute", 0xE1 },
346 { "acircumflex", 0xE2 },
347 { "atilde", 0xE3 },
348 { "adiaeresis", 0xE4 },
349 { "aring", 0xE5 },
350 { "ae", 0xE6 },
351 { "ccedilla", 0xE7 },
352 { "egrave", 0xE8 },
353 { "eacute", 0xE9 },
354 { "ecircumflex", 0xEA },
355 { "ediaeresis", 0xEB },
356 { "igrave", 0xEC },
357 { "iacute", 0xED },
358 { "icircumflex", 0xEE },
359 { "idiaeresis", 0xEF },
360 { "eth", 0xF0 },
361 { "ntilde", 0xF1 },
362 { "ograve", 0xF2 },
363 { "oacute", 0xF3 },
364 { "ocircumflex", 0xF4 },
365 { "otilde", 0xF5 },
366 { "odiaeresis", 0xF6 },
367 { "division", 0xF7 },
368 { "oslash", 0xF8 },
369 { "ugrave", 0xF9 },
370 { "uacute", 0xFA },
371 { "ucircumflex", 0xFB },
372 { "udiaeresis", 0xFC },
373 { "yacute", 0xFD },
374 { "thorn", 0xFE },
375 { "ydiaeresis", 0xFF },
376 { "Aogonek", 0x1A1 },
377 { "breve", 0x1A2 },
378 { "Lstroke", 0x1A3 },
379 { "Lcaron", 0x1A5 },
380 { "Sacute", 0x1A6 },
381 { "Scaron", 0x1A9 },
382 { "Scedilla", 0x1AA },
383 { "Tcaron", 0x1AB },
384 { "Zacute", 0x1AC },
385 { "Zcaron", 0x1AE },
386 { "Zabovedot", 0x1AF },
387 { "aogonek", 0x1B1 },
388 { "ogonek", 0x1B2 },
389 { "lstroke", 0x1B3 },
390 { "lcaron", 0x1B5 },
391 { "sacute", 0x1B6 },
392 { "caron", 0x1B7 },
393 { "scaron", 0x1B9 },
394 { "scedilla", 0x1BA },
395 { "tcaron", 0x1BB },
396 { "zacute", 0x1BC },
397 { "doubleacute", 0x1BD },
398 { "zcaron", 0x1BE },
399 { "zabovedot", 0x1BF },
400 { "Racute", 0x1C0 },
401 { "Abreve", 0x1C3 },
402 { "Lacute", 0x1C5 },
403 { "Cacute", 0x1C6 },
404 { "Ccaron", 0x1C8 },
405 { "Eogonek", 0x1CA },
406 { "Ecaron", 0x1CC },
407 { "Dcaron", 0x1CF },
408 { "Dstroke", 0x1D0 },
409 { "Nacute", 0x1D1 },
410 { "Ncaron", 0x1D2 },
411 { "Odoubleacute", 0x1D5 },
412 { "Rcaron", 0x1D8 },
413 { "Uring", 0x1D9 },
414 { "Udoubleacute", 0x1DB },
415 { "Tcedilla", 0x1DE },
416 { "racute", 0x1E0 },
417 { "abreve", 0x1E3 },
418 { "lacute", 0x1E5 },
419 { "cacute", 0x1E6 },
420 { "ccaron", 0x1E8 },
421 { "eogonek", 0x1EA },
422 { "ecaron", 0x1EC },
423 { "dcaron", 0x1EF },
424 { "dstroke", 0x1F0 },
425 { "nacute", 0x1F1 },
426 { "ncaron", 0x1F2 },
427 { "odoubleacute", 0x1F5 },
428 { "rcaron", 0x1F8 },
429 { "uring", 0x1F9 },
430 { "udoubleacute", 0x1FB },
431 { "tcedilla", 0x1FE },
432 { "abovedot", 0x1FF },
433 { "Hstroke", 0x2A1 },
434 { "Hcircumflex", 0x2A6 },
435 { "Iabovedot", 0x2A9 },
436 { "Gbreve", 0x2AB },
437 { "Jcircumflex", 0x2AC },
438 { "hstroke", 0x2B1 },
439 { "hcircumflex", 0x2B6 },
440 { "idotless", 0x2B9 },
441 { "gbreve", 0x2BB },
442 { "jcircumflex", 0x2BC },
443 { "Cabovedot", 0x2C5 },
444 { "Ccircumflex", 0x2C6 },
445 { "Gabovedot", 0x2D5 },
446 { "Gcircumflex", 0x2D8 },
447 { "Ubreve", 0x2DD },
448 { "Scircumflex", 0x2DE },
449 { "cabovedot", 0x2E5 },
450 { "ccircumflex", 0x2E6 },
451 { "gabovedot", 0x2F5 },
452 { "gcircumflex", 0x2F8 },
453 { "ubreve", 0x2FD },
454 { "scircumflex", 0x2FE },
455 { "kra", 0x3A2 },
456 { "kappa", 0x3A2 },
457 { "Rcedilla", 0x3A3 },
458 { "Itilde", 0x3A5 },
459 { "Lcedilla", 0x3A6 },
460 { "Emacron", 0x3AA },
461 { "Gcedilla", 0x3AB },
462 { "Tslash", 0x3AC },
463 { "rcedilla", 0x3B3 },
464 { "itilde", 0x3B5 },
465 { "lcedilla", 0x3B6 },
466 { "emacron", 0x3BA },
467 { "gcedilla", 0x3BB },
468 { "gacute", 0x3BB },
469 { "tslash", 0x3BC },
470 { "ENG", 0x3BD },
471 { "eng", 0x3BF },
472 { "Amacron", 0x3C0 },
473 { "Iogonek", 0x3C7 },
474 { "Eabovedot", 0x3CC },
475 { "Imacron", 0x3CF },
476 { "Ncedilla", 0x3D1 },
477 { "Omacron", 0x3D2 },
478 { "Kcedilla", 0x3D3 },
479 { "Uogonek", 0x3D9 },
480 { "Utilde", 0x3DD },
481 { "Umacron", 0x3DE },
482 { "amacron", 0x3E0 },
483 { "iogonek", 0x3E7 },
484 { "eabovedot", 0x3EC },
485 { "imacron", 0x3EF },
486 { "ncedilla", 0x3F1 },
487 { "omacron", 0x3F2 },
488 { "kcedilla", 0x3F3 },
489 { "uogonek", 0x3F9 },
490 { "utilde", 0x3FD },
491 { "umacron", 0x3FE },
492 { "overline", 0x47E },
493 { "kana_fullstop", 0x4A1 },
494 { "kana_openingbracket", 0x4A2 },
495 { "kana_closingbracket", 0x4A3 },
496 { "kana_comma", 0x4A4 },
497 { "kana_conjunctive", 0x4A5 },
498 { "kana_middledot", 0x4A5 },
499 { "kana_WO", 0x4A6 },
500 { "kana_a", 0x4A7 },
501 { "kana_i", 0x4A8 },
502 { "kana_u", 0x4A9 },
503 { "kana_e", 0x4AA },
504 { "kana_o", 0x4AB },
505 { "kana_ya", 0x4AC },
506 { "kana_yu", 0x4AD },
507 { "kana_yo", 0x4AE },
508 { "kana_tsu", 0x4AF },
509 { "kana_tu", 0x4AF },
510 { "prolongedsound", 0x4B0 },
511 { "kana_A", 0x4B1 },
512 { "kana_I", 0x4B2 },
513 { "kana_U", 0x4B3 },
514 { "kana_E", 0x4B4 },
515 { "kana_O", 0x4B5 },
516 { "kana_KA", 0x4B6 },
517 { "kana_KI", 0x4B7 },
518 { "kana_KU", 0x4B8 },
519 { "kana_KE", 0x4B9 },
520 { "kana_KO", 0x4BA },
521 { "kana_SA", 0x4BB },
522 { "kana_SHI", 0x4BC },
523 { "kana_SU", 0x4BD },
524 { "kana_SE", 0x4BE },
525 { "kana_SO", 0x4BF },
526 { "kana_TA", 0x4C0 },
527 { "kana_CHI", 0x4C1 },
528 { "kana_TI", 0x4C1 },
529 { "kana_TSU", 0x4C2 },
530 { "kana_TU", 0x4C2 },
531 { "kana_TE", 0x4C3 },
532 { "kana_TO", 0x4C4 },
533 { "kana_NA", 0x4C5 },
534 { "kana_NI", 0x4C6 },
535 { "kana_NU", 0x4C7 },
536 { "kana_NE", 0x4C8 },
537 { "kana_NO", 0x4C9 },
538 { "kana_HA", 0x4CA },
539 { "kana_HI", 0x4CB },
540 { "kana_FU", 0x4CC },
541 { "kana_HU", 0x4CC },
542 { "kana_HE", 0x4CD },
543 { "kana_HO", 0x4CE },
544 { "kana_MA", 0x4CF },
545 { "kana_MI", 0x4D0 },
546 { "kana_MU", 0x4D1 },
547 { "kana_ME", 0x4D2 },
548 { "kana_MO", 0x4D3 },
549 { "kana_YA", 0x4D4 },
550 { "kana_YU", 0x4D5 },
551 { "kana_YO", 0x4D6 },
552 { "kana_RA", 0x4D7 },
553 { "kana_RI", 0x4D8 },
554 { "kana_RU", 0x4D9 },
555 { "kana_RE", 0x4DA },
556 { "kana_RO", 0x4DB },
557 { "kana_WA", 0x4DC },
558 { "kana_N", 0x4DD },
559 { "voicedsound", 0x4DE },
560 { "semivoicedsound", 0x4DF },
514561 { "kana_switch", 0xFF7E },
515 { "Arabic_comma", 0x5ac },
516 { "Arabic_semicolon", 0x5bb },
517 { "Arabic_question_mark", 0x5bf },
518 { "Arabic_hamza", 0x5c1 },
519 { "Arabic_maddaonalef", 0x5c2 },
520 { "Arabic_hamzaonalef", 0x5c3 },
521 { "Arabic_hamzaonwaw", 0x5c4 },
522 { "Arabic_hamzaunderalef", 0x5c5 },
523 { "Arabic_hamzaonyeh", 0x5c6 },
524 { "Arabic_alef", 0x5c7 },
525 { "Arabic_beh", 0x5c8 },
526 { "Arabic_tehmarbuta", 0x5c9 },
527 { "Arabic_teh", 0x5ca },
528 { "Arabic_theh", 0x5cb },
529 { "Arabic_jeem", 0x5cc },
530 { "Arabic_hah", 0x5cd },
531 { "Arabic_khah", 0x5ce },
532 { "Arabic_dal", 0x5cf },
533 { "Arabic_thal", 0x5d0 },
534 { "Arabic_ra", 0x5d1 },
535 { "Arabic_zain", 0x5d2 },
536 { "Arabic_seen", 0x5d3 },
537 { "Arabic_sheen", 0x5d4 },
538 { "Arabic_sad", 0x5d5 },
539 { "Arabic_dad", 0x5d6 },
540 { "Arabic_tah", 0x5d7 },
541 { "Arabic_zah", 0x5d8 },
542 { "Arabic_ain", 0x5d9 },
543 { "Arabic_ghain", 0x5da },
544 { "Arabic_tatweel", 0x5e0 },
545 { "Arabic_feh", 0x5e1 },
546 { "Arabic_qaf", 0x5e2 },
547 { "Arabic_kaf", 0x5e3 },
548 { "Arabic_lam", 0x5e4 },
549 { "Arabic_meem", 0x5e5 },
550 { "Arabic_noon", 0x5e6 },
551 { "Arabic_heh", 0x5e7 },
552 { "Arabic_waw", 0x5e8 },
553 { "Arabic_alefmaksura", 0x5e9 },
554 { "Arabic_yeh", 0x5ea },
555 { "Arabic_fathatan", 0x5eb },
556 { "Arabic_dammatan", 0x5ec },
557 { "Arabic_kasratan", 0x5ed },
558 { "Arabic_fatha", 0x5ee },
559 { "Arabic_damma", 0x5ef },
560 { "Arabic_kasra", 0x5f0 },
561 { "Arabic_shadda", 0x5f1 },
562 { "Arabic_sukun", 0x5f2 },
562 { "Arabic_comma", 0x5AC },
563 { "Arabic_semicolon", 0x5BB },
564 { "Arabic_question_mark", 0x5BF },
565 { "Arabic_hamza", 0x5C1 },
566 { "Arabic_maddaonalef", 0x5C2 },
567 { "Arabic_hamzaonalef", 0x5C3 },
568 { "Arabic_hamzaonwaw", 0x5C4 },
569 { "Arabic_hamzaunderalef", 0x5C5 },
570 { "Arabic_hamzaonyeh", 0x5C6 },
571 { "Arabic_alef", 0x5C7 },
572 { "Arabic_beh", 0x5C8 },
573 { "Arabic_tehmarbuta", 0x5C9 },
574 { "Arabic_teh", 0x5CA },
575 { "Arabic_theh", 0x5CB },
576 { "Arabic_jeem", 0x5CC },
577 { "Arabic_hah", 0x5CD },
578 { "Arabic_khah", 0x5CE },
579 { "Arabic_dal", 0x5CF },
580 { "Arabic_thal", 0x5D0 },
581 { "Arabic_ra", 0x5D1 },
582 { "Arabic_zain", 0x5D2 },
583 { "Arabic_seen", 0x5D3 },
584 { "Arabic_sheen", 0x5D4 },
585 { "Arabic_sad", 0x5D5 },
586 { "Arabic_dad", 0x5D6 },
587 { "Arabic_tah", 0x5D7 },
588 { "Arabic_zah", 0x5D8 },
589 { "Arabic_ain", 0x5D9 },
590 { "Arabic_ghain", 0x5DA },
591 { "Arabic_tatweel", 0x5E0 },
592 { "Arabic_feh", 0x5E1 },
593 { "Arabic_qaf", 0x5E2 },
594 { "Arabic_kaf", 0x5E3 },
595 { "Arabic_lam", 0x5E4 },
596 { "Arabic_meem", 0x5E5 },
597 { "Arabic_noon", 0x5E6 },
598 { "Arabic_ha", 0x5E7 },
599 { "Arabic_heh", 0x5E7 },
600 { "Arabic_waw", 0x5E8 },
601 { "Arabic_alefmaksura", 0x5E9 },
602 { "Arabic_yeh", 0x5EA },
603 { "Arabic_fathatan", 0x5EB },
604 { "Arabic_dammatan", 0x5EC },
605 { "Arabic_kasratan", 0x5ED },
606 { "Arabic_fatha", 0x5EE },
607 { "Arabic_damma", 0x5EF },
608 { "Arabic_kasra", 0x5F0 },
609 { "Arabic_shadda", 0x5F1 },
610 { "Arabic_sukun", 0x5F2 },
563611 { "Arabic_switch", 0xFF7E },
564 { "Serbian_dje", 0x6a1 },
565 { "Macedonia_gje", 0x6a2 },
566 { "Cyrillic_io", 0x6a3 },
567 { "Ukranian_je", 0x6a4 },
568 { "Macedonia_dse", 0x6a5 },
569 { "Ukranian_i", 0x6a6 },
570 { "Ukranian_yi", 0x6a7 },
571 { "Serbian_je", 0x6a8 },
572 { "Serbian_lje", 0x6a9 },
573 { "Serbian_nje", 0x6aa },
574 { "Serbian_tshe", 0x6ab },
575 { "Macedonia_kje", 0x6ac },
576 { "Byelorussian_shortu", 0x6ae },
577 { "Serbian_dze", 0x6af },
578 { "numerosign", 0x6b0 },
579 { "Serbian_DJE", 0x6b1 },
580 { "Macedonia_GJE", 0x6b2 },
581 { "Cyrillic_IO", 0x6b3 },
582 { "Ukranian_JE", 0x6b4 },
583 { "Macedonia_DSE", 0x6b5 },
584 { "Ukranian_I", 0x6b6 },
585 { "Ukranian_YI", 0x6b7 },
586 { "Serbian_JE", 0x6b8 },
587 { "Serbian_LJE", 0x6b9 },
588 { "Serbian_NJE", 0x6ba },
589 { "Serbian_TSHE", 0x6bb },
590 { "Macedonia_KJE", 0x6bc },
591 { "Byelorussian_SHORTU", 0x6be },
592 { "Serbian_DZE", 0x6bf },
593 { "Cyrillic_yu", 0x6c0 },
594 { "Cyrillic_a", 0x6c1 },
595 { "Cyrillic_be", 0x6c2 },
596 { "Cyrillic_tse", 0x6c3 },
597 { "Cyrillic_de", 0x6c4 },
598 { "Cyrillic_ie", 0x6c5 },
599 { "Cyrillic_ef", 0x6c6 },
600 { "Cyrillic_ghe", 0x6c7 },
601 { "Cyrillic_ha", 0x6c8 },
602 { "Cyrillic_i", 0x6c9 },
603 { "Cyrillic_shorti", 0x6ca },
604 { "Cyrillic_ka", 0x6cb },
605 { "Cyrillic_el", 0x6cc },
606 { "Cyrillic_em", 0x6cd },
607 { "Cyrillic_en", 0x6ce },
608 { "Cyrillic_o", 0x6cf },
609 { "Cyrillic_pe", 0x6d0 },
610 { "Cyrillic_ya", 0x6d1 },
611 { "Cyrillic_er", 0x6d2 },
612 { "Cyrillic_es", 0x6d3 },
613 { "Cyrillic_te", 0x6d4 },
614 { "Cyrillic_u", 0x6d5 },
615 { "Cyrillic_zhe", 0x6d6 },
616 { "Cyrillic_ve", 0x6d7 },
617 { "Cyrillic_softsign", 0x6d8 },
618 { "Cyrillic_yeru", 0x6d9 },
619 { "Cyrillic_ze", 0x6da },
620 { "Cyrillic_sha", 0x6db },
621 { "Cyrillic_e", 0x6dc },
622 { "Cyrillic_shcha", 0x6dd },
623 { "Cyrillic_che", 0x6de },
624 { "Cyrillic_hardsign", 0x6df },
625 { "Cyrillic_YU", 0x6e0 },
626 { "Cyrillic_A", 0x6e1 },
627 { "Cyrillic_BE", 0x6e2 },
628 { "Cyrillic_TSE", 0x6e3 },
629 { "Cyrillic_DE", 0x6e4 },
630 { "Cyrillic_IE", 0x6e5 },
631 { "Cyrillic_EF", 0x6e6 },
632 { "Cyrillic_GHE", 0x6e7 },
633 { "Cyrillic_HA", 0x6e8 },
634 { "Cyrillic_I", 0x6e9 },
635 { "Cyrillic_SHORTI", 0x6ea },
636 { "Cyrillic_KA", 0x6eb },
637 { "Cyrillic_EL", 0x6ec },
638 { "Cyrillic_EM", 0x6ed },
639 { "Cyrillic_EN", 0x6ee },
640 { "Cyrillic_O", 0x6ef },
641 { "Cyrillic_PE", 0x6f0 },
642 { "Cyrillic_YA", 0x6f1 },
643 { "Cyrillic_ER", 0x6f2 },
644 { "Cyrillic_ES", 0x6f3 },
645 { "Cyrillic_TE", 0x6f4 },
646 { "Cyrillic_U", 0x6f5 },
647 { "Cyrillic_ZHE", 0x6f6 },
648 { "Cyrillic_VE", 0x6f7 },
649 { "Cyrillic_SOFTSIGN", 0x6f8 },
650 { "Cyrillic_YERU", 0x6f9 },
651 { "Cyrillic_ZE", 0x6fa },
652 { "Cyrillic_SHA", 0x6fb },
653 { "Cyrillic_E", 0x6fc },
654 { "Cyrillic_SHCHA", 0x6fd },
655 { "Cyrillic_CHE", 0x6fe },
656 { "Cyrillic_HARDSIGN", 0x6ff },
657 { "Greek_ALPHAaccent", 0x7a1 },
658 { "Greek_EPSILONaccent", 0x7a2 },
659 { "Greek_ETAaccent", 0x7a3 },
660 { "Greek_IOTAaccent", 0x7a4 },
661 { "Greek_IOTAdiaeresis", 0x7a5 },
662 { "Greek_IOTAaccentdiaeresis", 0x7a6 },
663 { "Greek_OMICRONaccent", 0x7a7 },
664 { "Greek_UPSILONaccent", 0x7a8 },
665 { "Greek_UPSILONdieresis", 0x7a9 },
666 { "Greek_UPSILONaccentdieresis", 0x7aa },
667 { "Greek_OMEGAaccent", 0x7ab },
668 { "Greek_alphaaccent", 0x7b1 },
669 { "Greek_epsilonaccent", 0x7b2 },
670 { "Greek_etaaccent", 0x7b3 },
671 { "Greek_iotaaccent", 0x7b4 },
672 { "Greek_iotadieresis", 0x7b5 },
673 { "Greek_iotaaccentdieresis", 0x7b6 },
674 { "Greek_omicronaccent", 0x7b7 },
675 { "Greek_upsilonaccent", 0x7b8 },
676 { "Greek_upsilondieresis", 0x7b9 },
677 { "Greek_upsilonaccentdieresis", 0x7ba },
678 { "Greek_omegaaccent", 0x7bb },
679 { "Greek_ALPHA", 0x7c1 },
680 { "Greek_BETA", 0x7c2 },
681 { "Greek_GAMMA", 0x7c3 },
682 { "Greek_DELTA", 0x7c4 },
683 { "Greek_EPSILON", 0x7c5 },
684 { "Greek_ZETA", 0x7c6 },
685 { "Greek_ETA", 0x7c7 },
686 { "Greek_THETA", 0x7c8 },
687 { "Greek_IOTA", 0x7c9 },
688 { "Greek_KAPPA", 0x7ca },
689 { "Greek_LAMBDA", 0x7cb },
690 { "Greek_MU", 0x7cc },
691 { "Greek_NU", 0x7cd },
692 { "Greek_XI", 0x7ce },
693 { "Greek_OMICRON", 0x7cf },
694 { "Greek_PI", 0x7d0 },
695 { "Greek_RHO", 0x7d1 },
696 { "Greek_SIGMA", 0x7d2 },
697 { "Greek_TAU", 0x7d4 },
698 { "Greek_UPSILON", 0x7d5 },
699 { "Greek_PHI", 0x7d6 },
700 { "Greek_CHI", 0x7d7 },
701 { "Greek_PSI", 0x7d8 },
702 { "Greek_OMEGA", 0x7d9 },
703 { "Greek_alpha", 0x7e1 },
704 { "Greek_beta", 0x7e2 },
705 { "Greek_gamma", 0x7e3 },
706 { "Greek_delta", 0x7e4 },
707 { "Greek_epsilon", 0x7e5 },
708 { "Greek_zeta", 0x7e6 },
709 { "Greek_eta", 0x7e7 },
710 { "Greek_theta", 0x7e8 },
711 { "Greek_iota", 0x7e9 },
712 { "Greek_kappa", 0x7ea },
713 { "Greek_lambda", 0x7eb },
714 { "Greek_mu", 0x7ec },
715 { "Greek_nu", 0x7ed },
716 { "Greek_xi", 0x7ee },
717 { "Greek_omicron", 0x7ef },
718 { "Greek_pi", 0x7f0 },
719 { "Greek_rho", 0x7f1 },
720 { "Greek_sigma", 0x7f2 },
721 { "Greek_finalsmallsigma", 0x7f3 },
722 { "Greek_tau", 0x7f4 },
723 { "Greek_upsilon", 0x7f5 },
724 { "Greek_phi", 0x7f6 },
725 { "Greek_chi", 0x7f7 },
726 { "Greek_psi", 0x7f8 },
727 { "Greek_omega", 0x7f9 },
612 { "Serbian_dje", 0x6A1 },
613 { "Macedonia_gje", 0x6A2 },
614 { "Cyrillic_io", 0x6A3 },
615 { "Ukrainian_ie", 0x6A4 },
616 { "Ukranian_je", 0x6A4 },
617 { "Macedonia_dse", 0x6A5 },
618 { "Ukrainian_i", 0x6A6 },
619 { "Ukranian_i", 0x6A6 },
620 { "Ukrainian_yi", 0x6A7 },
621 { "Ukranian_yi", 0x6A7 },
622 { "Cyrillic_je", 0x6A8 },
623 { "Serbian_je", 0x6A8 },
624 { "Cyrillic_lje", 0x6A9 },
625 { "Serbian_lje", 0x6A9 },
626 { "Cyrillic_nje", 0x6AA },
627 { "Serbian_nje", 0x6AA },
628 { "Serbian_tshe", 0x6AB },
629 { "Macedonia_kje", 0x6AC },
630 { "Ukrainian_ghe_with_upturn", 0x6AD },
631 { "Byelorussian_shortu", 0x6AE },
632 { "Cyrillic_dzhe", 0x6AF },
633 { "Serbian_dze", 0x6AF },
634 { "numerosign", 0x6B0 },
635 { "Serbian_DJE", 0x6B1 },
636 { "Macedonia_GJE", 0x6B2 },
637 { "Cyrillic_IO", 0x6B3 },
638 { "Ukrainian_IE", 0x6B4 },
639 { "Ukranian_JE", 0x6B4 },
640 { "Macedonia_DSE", 0x6B5 },
641 { "Ukrainian_I", 0x6B6 },
642 { "Ukranian_I", 0x6B6 },
643 { "Ukrainian_YI", 0x6B7 },
644 { "Ukranian_YI", 0x6B7 },
645 { "Cyrillic_JE", 0x6B8 },
646 { "Serbian_JE", 0x6B8 },
647 { "Cyrillic_LJE", 0x6B9 },
648 { "Serbian_LJE", 0x6B9 },
649 { "Cyrillic_NJE", 0x6BA },
650 { "Serbian_NJE", 0x6BA },
651 { "Serbian_TSHE", 0x6BB },
652 { "Macedonia_KJE", 0x6BC },
653 { "Ukrainian_GHE_WITH_UPTURN", 0x6BD },
654 { "Byelorussian_SHORTU", 0x6BE },
655 { "Cyrillic_DZHE", 0x6BF },
656 { "Serbian_DZE", 0x6BF },
657 { "Cyrillic_yu", 0x6C0 },
658 { "Cyrillic_a", 0x6C1 },
659 { "Cyrillic_be", 0x6C2 },
660 { "Cyrillic_tse", 0x6C3 },
661 { "Cyrillic_de", 0x6C4 },
662 { "Cyrillic_ie", 0x6C5 },
663 { "Cyrillic_ef", 0x6C6 },
664 { "Cyrillic_ghe", 0x6C7 },
665 { "Cyrillic_ha", 0x6C8 },
666 { "Cyrillic_i", 0x6C9 },
667 { "Cyrillic_shorti", 0x6CA },
668 { "Cyrillic_ka", 0x6CB },
669 { "Cyrillic_el", 0x6CC },
670 { "Cyrillic_em", 0x6CD },
671 { "Cyrillic_en", 0x6CE },
672 { "Cyrillic_o", 0x6CF },
673 { "Cyrillic_pe", 0x6D0 },
674 { "Cyrillic_ya", 0x6D1 },
675 { "Cyrillic_er", 0x6D2 },
676 { "Cyrillic_es", 0x6D3 },
677 { "Cyrillic_te", 0x6D4 },
678 { "Cyrillic_u", 0x6D5 },
679 { "Cyrillic_zhe", 0x6D6 },
680 { "Cyrillic_ve", 0x6D7 },
681 { "Cyrillic_softsign", 0x6D8 },
682 { "Cyrillic_yeru", 0x6D9 },
683 { "Cyrillic_ze", 0x6DA },
684 { "Cyrillic_sha", 0x6DB },
685 { "Cyrillic_e", 0x6DC },
686 { "Cyrillic_shcha", 0x6DD },
687 { "Cyrillic_che", 0x6DE },
688 { "Cyrillic_hardsign", 0x6DF },
689 { "Cyrillic_YU", 0x6E0 },
690 { "Cyrillic_A", 0x6E1 },
691 { "Cyrillic_BE", 0x6E2 },
692 { "Cyrillic_TSE", 0x6E3 },
693 { "Cyrillic_DE", 0x6E4 },
694 { "Cyrillic_IE", 0x6E5 },
695 { "Cyrillic_EF", 0x6E6 },
696 { "Cyrillic_GHE", 0x6E7 },
697 { "Cyrillic_HA", 0x6E8 },
698 { "Cyrillic_I", 0x6E9 },
699 { "Cyrillic_SHORTI", 0x6EA },
700 { "Cyrillic_KA", 0x6EB },
701 { "Cyrillic_EL", 0x6EC },
702 { "Cyrillic_EM", 0x6ED },
703 { "Cyrillic_EN", 0x6EE },
704 { "Cyrillic_O", 0x6EF },
705 { "Cyrillic_PE", 0x6F0 },
706 { "Cyrillic_YA", 0x6F1 },
707 { "Cyrillic_ER", 0x6F2 },
708 { "Cyrillic_ES", 0x6F3 },
709 { "Cyrillic_TE", 0x6F4 },
710 { "Cyrillic_U", 0x6F5 },
711 { "Cyrillic_ZHE", 0x6F6 },
712 { "Cyrillic_VE", 0x6F7 },
713 { "Cyrillic_SOFTSIGN", 0x6F8 },
714 { "Cyrillic_YERU", 0x6F9 },
715 { "Cyrillic_ZE", 0x6FA },
716 { "Cyrillic_SHA", 0x6FB },
717 { "Cyrillic_E", 0x6FC },
718 { "Cyrillic_SHCHA", 0x6FD },
719 { "Cyrillic_CHE", 0x6FE },
720 { "Cyrillic_HARDSIGN", 0x6FF },
721 { "Greek_ALPHAaccent", 0x7A1 },
722 { "Greek_EPSILONaccent", 0x7A2 },
723 { "Greek_ETAaccent", 0x7A3 },
724 { "Greek_IOTAaccent", 0x7A4 },
725 { "Greek_IOTAdieresis", 0x7A5 },
726 { "Greek_IOTAdiaeresis", 0x7A5 },
727 { "Greek_IOTAaccentdiaeresis", 0x7A6 },
728 { "Greek_OMICRONaccent", 0x7A7 },
729 { "Greek_UPSILONaccent", 0x7A8 },
730 { "Greek_UPSILONdieresis", 0x7A9 },
731 { "Greek_UPSILONaccentdieresis", 0x7AA },
732 { "Greek_OMEGAaccent", 0x7AB },
733 { "Greek_accentdieresis", 0x7AE },
734 { "Greek_horizbar", 0x7AF },
735 { "Greek_alphaaccent", 0x7B1 },
736 { "Greek_epsilonaccent", 0x7B2 },
737 { "Greek_etaaccent", 0x7B3 },
738 { "Greek_iotaaccent", 0x7B4 },
739 { "Greek_iotadieresis", 0x7B5 },
740 { "Greek_iotaaccentdieresis", 0x7B6 },
741 { "Greek_omicronaccent", 0x7B7 },
742 { "Greek_upsilonaccent", 0x7B8 },
743 { "Greek_upsilondieresis", 0x7B9 },
744 { "Greek_upsilonaccentdieresis", 0x7BA },
745 { "Greek_omegaaccent", 0x7BB },
746 { "Greek_ALPHA", 0x7C1 },
747 { "Greek_BETA", 0x7C2 },
748 { "Greek_GAMMA", 0x7C3 },
749 { "Greek_DELTA", 0x7C4 },
750 { "Greek_EPSILON", 0x7C5 },
751 { "Greek_ZETA", 0x7C6 },
752 { "Greek_ETA", 0x7C7 },
753 { "Greek_THETA", 0x7C8 },
754 { "Greek_IOTA", 0x7C9 },
755 { "Greek_KAPPA", 0x7CA },
756 { "Greek_LAMDA", 0x7CB },
757 { "Greek_LAMBDA", 0x7CB },
758 { "Greek_MU", 0x7CC },
759 { "Greek_NU", 0x7CD },
760 { "Greek_XI", 0x7CE },
761 { "Greek_OMICRON", 0x7CF },
762 { "Greek_PI", 0x7D0 },
763 { "Greek_RHO", 0x7D1 },
764 { "Greek_SIGMA", 0x7D2 },
765 { "Greek_TAU", 0x7D4 },
766 { "Greek_UPSILON", 0x7D5 },
767 { "Greek_PHI", 0x7D6 },
768 { "Greek_CHI", 0x7D7 },
769 { "Greek_PSI", 0x7D8 },
770 { "Greek_OMEGA", 0x7D9 },
771 { "Greek_alpha", 0x7E1 },
772 { "Greek_beta", 0x7E2 },
773 { "Greek_gamma", 0x7E3 },
774 { "Greek_delta", 0x7E4 },
775 { "Greek_epsilon", 0x7E5 },
776 { "Greek_zeta", 0x7E6 },
777 { "Greek_eta", 0x7E7 },
778 { "Greek_theta", 0x7E8 },
779 { "Greek_iota", 0x7E9 },
780 { "Greek_kappa", 0x7EA },
781 { "Greek_lamda", 0x7EB },
782 { "Greek_lambda", 0x7EB },
783 { "Greek_mu", 0x7EC },
784 { "Greek_nu", 0x7ED },
785 { "Greek_xi", 0x7EE },
786 { "Greek_omicron", 0x7EF },
787 { "Greek_pi", 0x7F0 },
788 { "Greek_rho", 0x7F1 },
789 { "Greek_sigma", 0x7F2 },
790 { "Greek_finalsmallsigma", 0x7F3 },
791 { "Greek_tau", 0x7F4 },
792 { "Greek_upsilon", 0x7F5 },
793 { "Greek_phi", 0x7F6 },
794 { "Greek_chi", 0x7F7 },
795 { "Greek_psi", 0x7F8 },
796 { "Greek_omega", 0x7F9 },
728797 { "Greek_switch", 0xFF7E },
729 { "leftradical", 0x8a1 },
730 { "topleftradical", 0x8a2 },
731 { "horizconnector", 0x8a3 },
732 { "topintegral", 0x8a4 },
733 { "botintegral", 0x8a5 },
734 { "vertconnector", 0x8a6 },
735 { "topleftsqbracket", 0x8a7 },
736 { "botleftsqbracket", 0x8a8 },
737 { "toprightsqbracket", 0x8a9 },
738 { "botrightsqbracket", 0x8aa },
739 { "topleftparens", 0x8ab },
740 { "botleftparens", 0x8ac },
741 { "toprightparens", 0x8ad },
742 { "botrightparens", 0x8ae },
743 { "leftmiddlecurlybrace", 0x8af },
744 { "rightmiddlecurlybrace", 0x8b0 },
745 { "topleftsummation", 0x8b1 },
746 { "botleftsummation", 0x8b2 },
747 { "topvertsummationconnector", 0x8b3 },
748 { "botvertsummationconnector", 0x8b4 },
749 { "toprightsummation", 0x8b5 },
750 { "botrightsummation", 0x8b6 },
751 { "rightmiddlesummation", 0x8b7 },
752 { "lessthanequal", 0x8bc },
753 { "notequal", 0x8bd },
754 { "greaterthanequal", 0x8be },
755 { "integral", 0x8bf },
756 { "therefore", 0x8c0 },
757 { "variation", 0x8c1 },
758 { "infinity", 0x8c2 },
759 { "nabla", 0x8c5 },
760 { "approximate", 0x8c8 },
761 { "similarequal", 0x8c9 },
762 { "ifonlyif", 0x8cd },
763 { "implies", 0x8ce },
764 { "identical", 0x8cf },
765 { "radical", 0x8d6 },
766 { "includedin", 0x8da },
767 { "includes", 0x8db },
768 { "intersection", 0x8dc },
769 { "union", 0x8dd },
770 { "logicaland", 0x8de },
771 { "logicalor", 0x8df },
772 { "partialderivative", 0x8ef },
773 { "function", 0x8f6 },
774 { "leftarrow", 0x8fb },
775 { "uparrow", 0x8fc },
776 { "rightarrow", 0x8fd },
777 { "downarrow", 0x8fe },
778 { "blank", 0x9df },
779 { "soliddiamond", 0x9e0 },
780 { "checkerboard", 0x9e1 },
781 { "ht", 0x9e2 },
782 { "ff", 0x9e3 },
783 { "cr", 0x9e4 },
784 { "lf", 0x9e5 },
785 { "nl", 0x9e8 },
786 { "vt", 0x9e9 },
787 { "lowrightcorner", 0x9ea },
788 { "uprightcorner", 0x9eb },
789 { "upleftcorner", 0x9ec },
790 { "lowleftcorner", 0x9ed },
791 { "crossinglines", 0x9ee },
792 { "horizlinescan1", 0x9ef },
793 { "horizlinescan3", 0x9f0 },
794 { "horizlinescan5", 0x9f1 },
795 { "horizlinescan7", 0x9f2 },
796 { "horizlinescan9", 0x9f3 },
797 { "leftt", 0x9f4 },
798 { "rightt", 0x9f5 },
799 { "bott", 0x9f6 },
800 { "topt", 0x9f7 },
801 { "vertbar", 0x9f8 },
802 { "emspace", 0xaa1 },
803 { "enspace", 0xaa2 },
804 { "em3space", 0xaa3 },
805 { "em4space", 0xaa4 },
806 { "digitspace", 0xaa5 },
807 { "punctspace", 0xaa6 },
808 { "thinspace", 0xaa7 },
809 { "hairspace", 0xaa8 },
810 { "emdash", 0xaa9 },
811 { "endash", 0xaaa },
812 { "signifblank", 0xaac },
813 { "ellipsis", 0xaae },
814 { "doubbaselinedot", 0xaaf },
815 { "onethird", 0xab0 },
816 { "twothirds", 0xab1 },
817 { "onefifth", 0xab2 },
818 { "twofifths", 0xab3 },
819 { "threefifths", 0xab4 },
820 { "fourfifths", 0xab5 },
821 { "onesixth", 0xab6 },
822 { "fivesixths", 0xab7 },
823 { "careof", 0xab8 },
824 { "figdash", 0xabb },
825 { "leftanglebracket", 0xabc },
826 { "decimalpoint", 0xabd },
827 { "rightanglebracket", 0xabe },
828 { "marker", 0xabf },
829 { "oneeighth", 0xac3 },
830 { "threeeighths", 0xac4 },
831 { "fiveeighths", 0xac5 },
832 { "seveneighths", 0xac6 },
833 { "trademark", 0xac9 },
834 { "signaturemark", 0xaca },
835 { "trademarkincircle", 0xacb },
836 { "leftopentriangle", 0xacc },
837 { "rightopentriangle", 0xacd },
838 { "emopencircle", 0xace },
839 { "emopenrectangle", 0xacf },
840 { "leftsinglequotemark", 0xad0 },
841 { "rightsinglequotemark", 0xad1 },
842 { "leftdoublequotemark", 0xad2 },
843 { "rightdoublequotemark", 0xad3 },
844 { "prescription", 0xad4 },
845 { "minutes", 0xad6 },
846 { "seconds", 0xad7 },
847 { "latincross", 0xad9 },
848 { "hexagram", 0xada },
849 { "filledrectbullet", 0xadb },
850 { "filledlefttribullet", 0xadc },
851 { "filledrighttribullet", 0xadd },
852 { "emfilledcircle", 0xade },
853 { "emfilledrect", 0xadf },
854 { "enopencircbullet", 0xae0 },
855 { "enopensquarebullet", 0xae1 },
856 { "openrectbullet", 0xae2 },
857 { "opentribulletup", 0xae3 },
858 { "opentribulletdown", 0xae4 },
859 { "openstar", 0xae5 },
860 { "enfilledcircbullet", 0xae6 },
861 { "enfilledsqbullet", 0xae7 },
862 { "filledtribulletup", 0xae8 },
863 { "filledtribulletdown", 0xae9 },
864 { "leftpointer", 0xaea },
865 { "rightpointer", 0xaeb },
866 { "club", 0xaec },
867 { "diamond", 0xaed },
868 { "heart", 0xaee },
869 { "maltesecross", 0xaf0 },
870 { "dagger", 0xaf1 },
871 { "doubledagger", 0xaf2 },
872 { "checkmark", 0xaf3 },
873 { "ballotcross", 0xaf4 },
874 { "musicalsharp", 0xaf5 },
875 { "musicalflat", 0xaf6 },
876 { "malesymbol", 0xaf7 },
877 { "femalesymbol", 0xaf8 },
878 { "telephone", 0xaf9 },
879 { "telephonerecorder", 0xafa },
880 { "phonographcopyright", 0xafb },
881 { "caret", 0xafc },
882 { "singlelowquotemark", 0xafd },
883 { "doublelowquotemark", 0xafe },
884 { "cursor", 0xaff },
885 { "leftcaret", 0xba3 },
886 { "rightcaret", 0xba6 },
887 { "downcaret", 0xba8 },
888 { "upcaret", 0xba9 },
889 { "overbar", 0xbc0 },
890 { "downtack", 0xbc2 },
891 { "upshoe", 0xbc3 },
892 { "downstile", 0xbc4 },
893 { "underbar", 0xbc6 },
894 { "jot", 0xbca },
895 { "quad", 0xbcc },
896 { "uptack", 0xbce },
897 { "circle", 0xbcf },
898 { "upstile", 0xbd3 },
899 { "downshoe", 0xbd6 },
900 { "rightshoe", 0xbd8 },
901 { "leftshoe", 0xbda },
902 { "lefttack", 0xbdc },
903 { "righttack", 0xbfc },
904 { "hebrew_aleph", 0xce0 },
905 { "hebrew_beth", 0xce1 },
906 { "hebrew_gimmel", 0xce2 },
907 { "hebrew_daleth", 0xce3 },
908 { "hebrew_he", 0xce4 },
909 { "hebrew_waw", 0xce5 },
910 { "hebrew_zayin", 0xce6 },
911 { "hebrew_het", 0xce7 },
912 { "hebrew_teth", 0xce8 },
913 { "hebrew_yod", 0xce9 },
914 { "hebrew_finalkaph", 0xcea },
915 { "hebrew_kaph", 0xceb },
916 { "hebrew_lamed", 0xcec },
917 { "hebrew_finalmem", 0xced },
918 { "hebrew_mem", 0xcee },
919 { "hebrew_finalnun", 0xcef },
920 { "hebrew_nun", 0xcf0 },
921 { "hebrew_samekh", 0xcf1 },
922 { "hebrew_ayin", 0xcf2 },
923 { "hebrew_finalpe", 0xcf3 },
924 { "hebrew_pe", 0xcf4 },
925 { "hebrew_finalzadi", 0xcf5 },
926 { "hebrew_zadi", 0xcf6 },
927 { "hebrew_kuf", 0xcf7 },
928 { "hebrew_resh", 0xcf8 },
929 { "hebrew_shin", 0xcf9 },
930 { "hebrew_taf", 0xcfa },
798 { "leftradical", 0x8A1 },
799 { "topleftradical", 0x8A2 },
800 { "horizconnector", 0x8A3 },
801 { "topintegral", 0x8A4 },
802 { "botintegral", 0x8A5 },
803 { "vertconnector", 0x8A6 },
804 { "topleftsqbracket", 0x8A7 },
805 { "botleftsqbracket", 0x8A8 },
806 { "toprightsqbracket", 0x8A9 },
807 { "botrightsqbracket", 0x8AA },
808 { "topleftparens", 0x8AB },
809 { "botleftparens", 0x8AC },
810 { "toprightparens", 0x8AD },
811 { "botrightparens", 0x8AE },
812 { "leftmiddlecurlybrace", 0x8AF },
813 { "rightmiddlecurlybrace", 0x8B0 },
814 { "topleftsummation", 0x8B1 },
815 { "botleftsummation", 0x8B2 },
816 { "topvertsummationconnector", 0x8B3 },
817 { "botvertsummationconnector", 0x8B4 },
818 { "toprightsummation", 0x8B5 },
819 { "botrightsummation", 0x8B6 },
820 { "rightmiddlesummation", 0x8B7 },
821 { "lessthanequal", 0x8BC },
822 { "notequal", 0x8BD },
823 { "greaterthanequal", 0x8BE },
824 { "integral", 0x8BF },
825 { "therefore", 0x8C0 },
826 { "variation", 0x8C1 },
827 { "infinity", 0x8C2 },
828 { "nabla", 0x8C5 },
829 { "approximate", 0x8C8 },
830 { "similarequal", 0x8C9 },
831 { "ifonlyif", 0x8CD },
832 { "implies", 0x8CE },
833 { "identical", 0x8CF },
834 { "radical", 0x8D6 },
835 { "includedin", 0x8DA },
836 { "includes", 0x8DB },
837 { "intersection", 0x8DC },
838 { "union", 0x8DD },
839 { "logicaland", 0x8DE },
840 { "logicalor", 0x8DF },
841 { "partialderivative", 0x8EF },
842 { "function", 0x8F6 },
843 { "leftarrow", 0x8FB },
844 { "uparrow", 0x8FC },
845 { "rightarrow", 0x8FD },
846 { "downarrow", 0x8FE },
847 { "blank", 0x9DF },
848 { "soliddiamond", 0x9E0 },
849 { "checkerboard", 0x9E1 },
850 { "ht", 0x9E2 },
851 { "ff", 0x9E3 },
852 { "cr", 0x9E4 },
853 { "lf", 0x9E5 },
854 { "nl", 0x9E8 },
855 { "vt", 0x9E9 },
856 { "lowrightcorner", 0x9EA },
857 { "uprightcorner", 0x9EB },
858 { "upleftcorner", 0x9EC },
859 { "lowleftcorner", 0x9ED },
860 { "crossinglines", 0x9EE },
861 { "horizlinescan1", 0x9EF },
862 { "horizlinescan3", 0x9F0 },
863 { "horizlinescan5", 0x9F1 },
864 { "horizlinescan7", 0x9F2 },
865 { "horizlinescan9", 0x9F3 },
866 { "leftt", 0x9F4 },
867 { "rightt", 0x9F5 },
868 { "bott", 0x9F6 },
869 { "topt", 0x9F7 },
870 { "vertbar", 0x9F8 },
871 { "emspace", 0xAA1 },
872 { "enspace", 0xAA2 },
873 { "em3space", 0xAA3 },
874 { "em4space", 0xAA4 },
875 { "digitspace", 0xAA5 },
876 { "punctspace", 0xAA6 },
877 { "thinspace", 0xAA7 },
878 { "hairspace", 0xAA8 },
879 { "emdash", 0xAA9 },
880 { "endash", 0xAAA },
881 { "signifblank", 0xAAC },
882 { "ellipsis", 0xAAE },
883 { "doubbaselinedot", 0xAAF },
884 { "onethird", 0xAB0 },
885 { "twothirds", 0xAB1 },
886 { "onefifth", 0xAB2 },
887 { "twofifths", 0xAB3 },
888 { "threefifths", 0xAB4 },
889 { "fourfifths", 0xAB5 },
890 { "onesixth", 0xAB6 },
891 { "fivesixths", 0xAB7 },
892 { "careof", 0xAB8 },
893 { "figdash", 0xABB },
894 { "leftanglebracket", 0xABC },
895 { "decimalpoint", 0xABD },
896 { "rightanglebracket", 0xABE },
897 { "marker", 0xABF },
898 { "oneeighth", 0xAC3 },
899 { "threeeighths", 0xAC4 },
900 { "fiveeighths", 0xAC5 },
901 { "seveneighths", 0xAC6 },
902 { "trademark", 0xAC9 },
903 { "signaturemark", 0xACA },
904 { "trademarkincircle", 0xACB },
905 { "leftopentriangle", 0xACC },
906 { "rightopentriangle", 0xACD },
907 { "emopencircle", 0xACE },
908 { "emopenrectangle", 0xACF },
909 { "leftsinglequotemark", 0xAD0 },
910 { "rightsinglequotemark", 0xAD1 },
911 { "leftdoublequotemark", 0xAD2 },
912 { "rightdoublequotemark", 0xAD3 },
913 { "prescription", 0xAD4 },
914 { "permille", 0xAD5 },
915 { "minutes", 0xAD6 },
916 { "seconds", 0xAD7 },
917 { "latincross", 0xAD9 },
918 { "hexagram", 0xADA },
919 { "filledrectbullet", 0xADB },
920 { "filledlefttribullet", 0xADC },
921 { "filledrighttribullet", 0xADD },
922 { "emfilledcircle", 0xADE },
923 { "emfilledrect", 0xADF },
924 { "enopencircbullet", 0xAE0 },
925 { "enopensquarebullet", 0xAE1 },
926 { "openrectbullet", 0xAE2 },
927 { "opentribulletup", 0xAE3 },
928 { "opentribulletdown", 0xAE4 },
929 { "openstar", 0xAE5 },
930 { "enfilledcircbullet", 0xAE6 },
931 { "enfilledsqbullet", 0xAE7 },
932 { "filledtribulletup", 0xAE8 },
933 { "filledtribulletdown", 0xAE9 },
934 { "leftpointer", 0xAEA },
935 { "rightpointer", 0xAEB },
936 { "club", 0xAEC },
937 { "diamond", 0xAED },
938 { "heart", 0xAEE },
939 { "maltesecross", 0xAF0 },
940 { "dagger", 0xAF1 },
941 { "doubledagger", 0xAF2 },
942 { "checkmark", 0xAF3 },
943 { "ballotcross", 0xAF4 },
944 { "musicalsharp", 0xAF5 },
945 { "musicalflat", 0xAF6 },
946 { "malesymbol", 0xAF7 },
947 { "femalesymbol", 0xAF8 },
948 { "telephone", 0xAF9 },
949 { "telephonerecorder", 0xAFA },
950 { "phonographcopyright", 0xAFB },
951 { "caret", 0xAFC },
952 { "singlelowquotemark", 0xAFD },
953 { "doublelowquotemark", 0xAFE },
954 { "cursor", 0xAFF },
955 { "leftcaret", 0xBA3 },
956 { "rightcaret", 0xBA6 },
957 { "downcaret", 0xBA8 },
958 { "upcaret", 0xBA9 },
959 { "overbar", 0xBC0 },
960 { "downtack", 0xBC2 },
961 { "upshoe", 0xBC3 },
962 { "downstile", 0xBC4 },
963 { "underbar", 0xBC6 },
964 { "jot", 0xBCA },
965 { "quad", 0xBCC },
966 { "uptack", 0xBCE },
967 { "circle", 0xBCF },
968 { "upstile", 0xBD3 },
969 { "downshoe", 0xBD6 },
970 { "rightshoe", 0xBD8 },
971 { "leftshoe", 0xBDA },
972 { "lefttack", 0xBDC },
973 { "righttack", 0xBFC },
974 { "hebrew_doublelowline", 0xCDF },
975 { "hebrew_aleph", 0xCE0 },
976 { "hebrew_bet", 0xCE1 },
977 { "hebrew_beth", 0xCE1 },
978 { "hebrew_gimel", 0xCE2 },
979 { "hebrew_gimmel", 0xCE2 },
980 { "hebrew_dalet", 0xCE3 },
981 { "hebrew_daleth", 0xCE3 },
982 { "hebrew_he", 0xCE4 },
983 { "hebrew_waw", 0xCE5 },
984 { "hebrew_zain", 0xCE6 },
985 { "hebrew_zayin", 0xCE6 },
986 { "hebrew_chet", 0xCE7 },
987 { "hebrew_het", 0xCE7 },
988 { "hebrew_tet", 0xCE8 },
989 { "hebrew_teth", 0xCE8 },
990 { "hebrew_yod", 0xCE9 },
991 { "hebrew_finalkaph", 0xCEA },
992 { "hebrew_kaph", 0xCEB },
993 { "hebrew_lamed", 0xCEC },
994 { "hebrew_finalmem", 0xCED },
995 { "hebrew_mem", 0xCEE },
996 { "hebrew_finalnun", 0xCEF },
997 { "hebrew_nun", 0xCF0 },
998 { "hebrew_samech", 0xCF1 },
999 { "hebrew_samekh", 0xCF1 },
1000 { "hebrew_ayin", 0xCF2 },
1001 { "hebrew_finalpe", 0xCF3 },
1002 { "hebrew_pe", 0xCF4 },
1003 { "hebrew_finalzade", 0xCF5 },
1004 { "hebrew_finalzadi", 0xCF5 },
1005 { "hebrew_zade", 0xCF6 },
1006 { "hebrew_zadi", 0xCF6 },
1007 { "hebrew_qoph", 0xCF7 },
1008 { "hebrew_kuf", 0xCF7 },
1009 { "hebrew_resh", 0xCF8 },
1010 { "hebrew_shin", 0xCF9 },
1011 { "hebrew_taw", 0xCFA },
1012 { "hebrew_taf", 0xCFA },
9311013 { "Hebrew_switch", 0xFF7E },
1014 { "XF86ModeLock", 0x1008FF01 },
1015 { "XF86MonBrightnessUp", 0x1008FF02 },
1016 { "XF86MonBrightnessDown", 0x1008FF03 },
1017 { "XF86KbdLightOnOff", 0x1008FF04 },
1018 { "XF86KbdBrightnessUp", 0x1008FF05 },
1019 { "XF86KbdBrightnessDown", 0x1008FF06 },
1020 { "XF86MonBrightnessCycle", 0x1008FF07 },
1021 { "XF86Standby", 0x1008FF10 },
9321022 { "XF86AudioLowerVolume", 0x1008FF11 },
9331023 { "XF86AudioMute", 0x1008FF12 },
9341024 { "XF86AudioRaiseVolume", 0x1008FF13 },
9361026 { "XF86AudioStop", 0x1008FF15 },
9371027 { "XF86AudioPrev", 0x1008FF16 },
9381028 { "XF86AudioNext", 0x1008FF17 },
1029 { "XF86HomePage", 0x1008FF18 },
1030 { "XF86Mail", 0x1008FF19 },
1031 { "XF86Start", 0x1008FF1A },
1032 { "XF86Search", 0x1008FF1B },
1033 { "XF86AudioRecord", 0x1008FF1C },
1034 { "XF86Calculator", 0x1008FF1D },
1035 { "XF86Memo", 0x1008FF1E },
1036 { "XF86ToDoList", 0x1008FF1F },
1037 { "XF86Calendar", 0x1008FF20 },
1038 { "XF86PowerDown", 0x1008FF21 },
1039 { "XF86ContrastAdjust", 0x1008FF22 },
1040 { "XF86RockerUp", 0x1008FF23 },
1041 { "XF86RockerDown", 0x1008FF24 },
1042 { "XF86RockerEnter", 0x1008FF25 },
1043 { "XF86Back", 0x1008FF26 },
1044 { "XF86Forward", 0x1008FF27 },
1045 { "XF86Stop", 0x1008FF28 },
1046 { "XF86Refresh", 0x1008FF29 },
1047 { "XF86PowerOff", 0x1008FF2A },
1048 { "XF86WakeUp", 0x1008FF2B },
1049 { "XF86Eject", 0x1008FF2C },
1050 { "XF86ScreenSaver", 0x1008FF2D },
1051 { "XF86WWW", 0x1008FF2E },
1052 { "XF86Sleep", 0x1008FF2F },
1053 { "XF86Favorites", 0x1008FF30 },
1054 { "XF86AudioPause", 0x1008FF31 },
1055 { "XF86AudioMedia", 0x1008FF32 },
1056 { "XF86MyComputer", 0x1008FF33 },
1057 { "XF86VendorHome", 0x1008FF34 },
1058 { "XF86LightBulb", 0x1008FF35 },
1059 { "XF86Shop", 0x1008FF36 },
1060 { "XF86History", 0x1008FF37 },
1061 { "XF86OpenURL", 0x1008FF38 },
1062 { "XF86AddFavorite", 0x1008FF39 },
1063 { "XF86HotLinks", 0x1008FF3A },
1064 { "XF86BrightnessAdjust", 0x1008FF3B },
1065 { "XF86Finance", 0x1008FF3C },
1066 { "XF86Community", 0x1008FF3D },
1067 { "XF86AudioRewind", 0x1008FF3E },
1068 { "XF86BackForward", 0x1008FF3F },
1069 { "XF86Launch0", 0x1008FF40 },
1070 { "XF86Launch1", 0x1008FF41 },
1071 { "XF86Launch2", 0x1008FF42 },
1072 { "XF86Launch3", 0x1008FF43 },
1073 { "XF86Launch4", 0x1008FF44 },
1074 { "XF86Launch5", 0x1008FF45 },
1075 { "XF86Launch6", 0x1008FF46 },
1076 { "XF86Launch7", 0x1008FF47 },
1077 { "XF86Launch8", 0x1008FF48 },
1078 { "XF86Launch9", 0x1008FF49 },
1079 { "XF86LaunchA", 0x1008FF4A },
1080 { "XF86LaunchB", 0x1008FF4B },
1081 { "XF86LaunchC", 0x1008FF4C },
1082 { "XF86LaunchD", 0x1008FF4D },
1083 { "XF86LaunchE", 0x1008FF4E },
1084 { "XF86LaunchF", 0x1008FF4F },
1085 { "XF86ApplicationLeft", 0x1008FF50 },
1086 { "XF86ApplicationRight", 0x1008FF51 },
1087 { "XF86Book", 0x1008FF52 },
1088 { "XF86CD", 0x1008FF53 },
1089 { "XF86Calculater", 0x1008FF54 },
1090 { "XF86Clear", 0x1008FF55 },
1091 { "XF86Close", 0x1008FF56 },
1092 { "XF86Copy", 0x1008FF57 },
1093 { "XF86Cut", 0x1008FF58 },
1094 { "XF86Display", 0x1008FF59 },
1095 { "XF86DOS", 0x1008FF5A },
1096 { "XF86Documents", 0x1008FF5B },
1097 { "XF86Excel", 0x1008FF5C },
1098 { "XF86Explorer", 0x1008FF5D },
1099 { "XF86Game", 0x1008FF5E },
1100 { "XF86Go", 0x1008FF5F },
1101 { "XF86iTouch", 0x1008FF60 },
1102 { "XF86LogOff", 0x1008FF61 },
1103 { "XF86Market", 0x1008FF62 },
1104 { "XF86Meeting", 0x1008FF63 },
1105 { "XF86MenuKB", 0x1008FF65 },
1106 { "XF86MenuPB", 0x1008FF66 },
1107 { "XF86MySites", 0x1008FF67 },
1108 { "XF86New", 0x1008FF68 },
1109 { "XF86News", 0x1008FF69 },
1110 { "XF86OfficeHome", 0x1008FF6A },
1111 { "XF86Open", 0x1008FF6B },
1112 { "XF86Option", 0x1008FF6C },
1113 { "XF86Paste", 0x1008FF6D },
1114 { "XF86Phone", 0x1008FF6E },
1115 { "XF86Q", 0x1008FF70 },
1116 { "XF86Reply", 0x1008FF72 },
1117 { "XF86Reload", 0x1008FF73 },
1118 { "XF86RotateWindows", 0x1008FF74 },
1119 { "XF86RotationPB", 0x1008FF75 },
1120 { "XF86RotationKB", 0x1008FF76 },
1121 { "XF86Save", 0x1008FF77 },
1122 { "XF86ScrollUp", 0x1008FF78 },
1123 { "XF86ScrollDown", 0x1008FF79 },
1124 { "XF86ScrollClick", 0x1008FF7A },
1125 { "XF86Send", 0x1008FF7B },
1126 { "XF86Spell", 0x1008FF7C },
1127 { "XF86SplitScreen", 0x1008FF7D },
1128 { "XF86Support", 0x1008FF7E },
1129 { "XF86TaskPane", 0x1008FF7F },
1130 { "XF86Terminal", 0x1008FF80 },
1131 { "XF86Tools", 0x1008FF81 },
1132 { "XF86Travel", 0x1008FF82 },
1133 { "XF86UserPB", 0x1008FF84 },
1134 { "XF86User1KB", 0x1008FF85 },
1135 { "XF86User2KB", 0x1008FF86 },
1136 { "XF86Video", 0x1008FF87 },
1137 { "XF86WheelButton", 0x1008FF88 },
1138 { "XF86Word", 0x1008FF89 },
1139 { "XF86Xfer", 0x1008FF8A },
1140 { "XF86ZoomIn", 0x1008FF8B },
1141 { "XF86ZoomOut", 0x1008FF8C },
1142 { "XF86Away", 0x1008FF8D },
1143 { "XF86Messenger", 0x1008FF8E },
1144 { "XF86WebCam", 0x1008FF8F },
1145 { "XF86MailForward", 0x1008FF90 },
1146 { "XF86Pictures", 0x1008FF91 },
1147 { "XF86Music", 0x1008FF92 },
1148 { "XF86Battery", 0x1008FF93 },
1149 { "XF86Bluetooth", 0x1008FF94 },
1150 { "XF86WLAN", 0x1008FF95 },
1151 { "XF86UWB", 0x1008FF96 },
1152 { "XF86AudioForward", 0x1008FF97 },
1153 { "XF86AudioRepeat", 0x1008FF98 },
1154 { "XF86AudioRandomPlay", 0x1008FF99 },
1155 { "XF86Subtitle", 0x1008FF9A },
1156 { "XF86AudioCycleTrack", 0x1008FF9B },
1157 { "XF86CycleAngle", 0x1008FF9C },
1158 { "XF86FrameBack", 0x1008FF9D },
1159 { "XF86FrameForward", 0x1008FF9E },
1160 { "XF86Time", 0x1008FF9F },
1161 { "XF86Select", 0x1008FFA0 },
1162 { "XF86View", 0x1008FFA1 },
1163 { "XF86TopMenu", 0x1008FFA2 },
1164 { "XF86Red", 0x1008FFA3 },
1165 { "XF86Green", 0x1008FFA4 },
1166 { "XF86Yellow", 0x1008FFA5 },
1167 { "XF86Blue", 0x1008FFA6 },
1168 { "XF86Suspend", 0x1008FFA7 },
1169 { "XF86Hibernate", 0x1008FFA8 },
1170 { "XF86TouchpadToggle", 0x1008FFA9 },
1171 { "XF86TouchpadOn", 0x1008FFB0 },
1172 { "XF86TouchpadOff", 0x1008FFB1 },
1173 { "XF86AudioMicMute", 0x1008FFB2 },
1174 { "XF86Keyboard", 0x1008FFB3 },
1175 { "XF86WWAN", 0x1008FFB4 },
1176 { "XF86RFKill", 0x1008FFB5 },
1177 { "XF86AudioPreset", 0x1008FFB6 },
1178 { "XF86RotationLockToggle", 0x1008FFB7 },
1179 { "XF86Switch_VT_1", 0x1008FE01 },
1180 { "XF86Switch_VT_2", 0x1008FE02 },
1181 { "XF86Switch_VT_3", 0x1008FE03 },
1182 { "XF86Switch_VT_4", 0x1008FE04 },
1183 { "XF86Switch_VT_5", 0x1008FE05 },
1184 { "XF86Switch_VT_6", 0x1008FE06 },
1185 { "XF86Switch_VT_7", 0x1008FE07 },
1186 { "XF86Switch_VT_8", 0x1008FE08 },
1187 { "XF86Switch_VT_9", 0x1008FE09 },
1188 { "XF86Switch_VT_10", 0x1008FE0A },
1189 { "XF86Switch_VT_11", 0x1008FE0B },
1190 { "XF86Switch_VT_12", 0x1008FE0C },
1191 { "XF86Ungrab", 0x1008FE20 },
1192 { "XF86ClearGrab", 0x1008FE21 },
1193 { "XF86Next_VMode", 0x1008FE22 },
1194 { "XF86Prev_VMode", 0x1008FE23 },
1195 { "XF86LogWindowTree", 0x1008FE24 },
1196 { "XF86LogGrabInfo", 0x1008FE25 },
7474 #define TK_MAJOR_VERSION 8
7575 #define TK_MINOR_VERSION 6
7676 #define TK_RELEASE_LEVEL TCL_FINAL_RELEASE
77 #define TK_RELEASE_SERIAL 9
77 #define TK_RELEASE_SERIAL 10
7878
7979 #define TK_VERSION "8.6"
80 #define TK_PATCH_LEVEL "8.6.9"
80 #define TK_PATCH_LEVEL "8.6.10"
8181
8282 /*
8383 * A special definition used to allow this header file to be included from
9191
9292 #ifndef RC_INVOKED
9393
94 #ifndef _XLIB_H
94 #if !defined(_XLIB_H) && !defined(_X11_XLIB_H_)
9595 # include <X11/Xlib.h>
9696 # ifdef MAC_OSX_TK
9797 # include <X11/X.h>
9898 # endif
9999 #endif
100 #ifdef __STDC__
100 #if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \
101 || defined(__cplusplus) || defined(_MSC_VER) || defined(__ICC)
101102 # include <stddef.h>
102103 #endif
103104
265266 * Computes number of bytes from beginning of structure to a given field.
266267 */
267268
268 #ifdef offsetof
269269 #define Tk_Offset(type, field) ((int) offsetof(type, field))
270 #else
271 #define Tk_Offset(type, field) ((int) ((char *) &((type *) 0)->field))
270 /* Workaround for platforms missing offsetof(), e.g. VC++ 6.0 */
271 #ifndef offsetof
272 # define offsetof(type, field) ((size_t) ((char *) &((type *) 0)->field))
272273 #endif
273274
274275 /*
675676 * request. */
676677 Display *display; /* Display the event was read from. */
677678 Window event; /* Window on which event was requested. */
678 Window root; /* Root window that the event occured on. */
679 Window root; /* Root window that the event occurred on. */
679680 Window subwindow; /* Child window. */
680681 Time time; /* Milliseconds. */
681682 int x, y; /* Pointer x, y coordinates in event
812813 int internalBorderBottom;
813814 int minReqWidth;
814815 int minReqHeight;
815 char *dummy20; /* geometryMaster */
816816 #ifdef TK_USE_INPUT_METHODS
817 int dummy21;
817 int dummy20;
818818 #endif /* TK_USE_INPUT_METHODS */
819 char *dummy21; /* geomMgrName */
820 Tk_Window dummy22; /* maintainerPtr */
819821 } Tk_FakeWin;
820822
821823 /*
235235 borderPtr->darkColorPtr = NULL;
236236 borderPtr->lightColorPtr = NULL;
237237 borderPtr->shadow = None;
238 borderPtr->bgGC = None;
239 borderPtr->darkGC = None;
240 borderPtr->lightGC = None;
238 borderPtr->bgGC = NULL;
239 borderPtr->darkGC = NULL;
240 borderPtr->lightGC = NULL;
241241 borderPtr->hashPtr = hashPtr;
242242 borderPtr->nextPtr = existingBorderPtr;
243243 Tcl_SetHashValue(hashPtr, borderPtr);
373373 {
374374 TkBorder * borderPtr = (TkBorder *) border;
375375
376 if ((borderPtr->lightGC == None) && (which != TK_3D_FLAT_GC)) {
376 if ((borderPtr->lightGC == NULL) && (which != TK_3D_FLAT_GC)) {
377377 TkpGetShadows(borderPtr, tkwin);
378378 }
379379 if (which == TK_3D_FLAT_GC) {
390390 * compilers happy.
391391 */
392392
393 return (GC) None;
393 return NULL;
394394 }
395395
396396 /*
438438 if (borderPtr->shadow != None) {
439439 Tk_FreeBitmap(display, borderPtr->shadow);
440440 }
441 if (borderPtr->bgGC != None) {
441 if (borderPtr->bgGC != NULL) {
442442 Tk_FreeGC(display, borderPtr->bgGC);
443443 }
444 if (borderPtr->darkGC != None) {
444 if (borderPtr->darkGC != NULL) {
445445 Tk_FreeGC(display, borderPtr->darkGC);
446446 }
447 if (borderPtr->lightGC != None) {
447 if (borderPtr->lightGC != NULL) {
448448 Tk_FreeGC(display, borderPtr->lightGC);
449449 }
450450 if (prevPtr == borderPtr) {
764764 int i, lightOnLeft, dx, dy, parallel, pointsSeen;
765765 Display *display = Tk_Display(tkwin);
766766
767 if (borderPtr->lightGC == None) {
767 if (borderPtr->lightGC == NULL) {
768768 TkpGetShadows(borderPtr, tkwin);
769769 }
770770
13141314 *
13151315 * Side effects:
13161316 * If no error occurs, a blank internal format for a border value is
1317 * intialized. The final form cannot be done without a Tk_Window.
1317 * initialized. The final form cannot be done without a Tk_Window.
13181318 *
13191319 *----------------------------------------------------------------------
13201320 */
5353 GC bgGC; /* Used (if necessary) to draw areas in the
5454 * background color. */
5555 GC darkGC; /* Used to draw darker parts of the border.
56 * None means the shadow colors haven't been
56 * NULL means the shadow colors haven't been
5757 * allocated yet.*/
5858 GC lightGC; /* Used to draw lighter parts of the border.
59 * None means the shadow colors haven't been
59 * NULL means the shadow colors haven't been
6060 * allocated yet. */
6161 Tcl_HashEntry *hashPtr; /* Entry in borderTable (needed in order to
6262 * delete structure). */
0 /*
1 * tkArray.h --
2 *
3 * An array is a sequence of items, stored in a contiguous memory region.
4 * Random access to any item is very fast. New items can be either appended
5 * or prepended. An array may be traversed in the forward or backward direction.
6 *
7 * Copyright (c) 2018-2019 by Gregor Cramer.
8 *
9 * See the file "license.terms" for information on usage and redistribution of
10 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 */
12
13 /*
14 * Note that this file will not be included in header files, it is the purpose
15 * of this file to be included in source files only. Thus we are not using the
16 * prefix "Tk_" here for functions, because all the functions have private scope.
17 */
18
19 /*
20 * -------------------------------------------------------------------------------
21 * Use the array in the following way:
22 * -------------------------------------------------------------------------------
23 * typedef struct { int key, value; } Pair;
24 * TK_PTR_ARRAY_DEFINE(MyArray, Pair);
25 * MyArray *arr = NULL;
26 * if (MyArray_IsEmpty(arr)) {
27 * MyArray_Append(&arr, MakePair(1, 2));
28 * MyArray_Append(&arr, MakePair(2, 3));
29 * for (i = 0; i < MyArray_Size(arr); ++i) {
30 * Pair *p = MyArray_Get(arr, i);
31 * printf("%d -> %d\n", p->key, p->value);
32 * ckfree(p);
33 * }
34 * MyArray_Free(&arr);
35 * assert(arr == NULL);
36 * }
37 * -------------------------------------------------------------------------------
38 * Or with aggregated elements:
39 * -------------------------------------------------------------------------------
40 * typedef struct { int key, value; } Pair;
41 * TK_ARRAY_DEFINE(MyArray, Pair);
42 * Pair p1 = { 1, 2 };
43 * Pair p2 = { 2, 3 };
44 * MyArray *arr = NULL;
45 * if (MyArray_IsEmpty(arr)) {
46 * MyArray_Append(&arr, p1);
47 * MyArray_Append(&arr, p2);
48 * for (i = 0; i < MyArray_Size(arr); ++i) {
49 * const Pair *p = MyArray_Get(arr, i);
50 * printf("%d -> %d\n", p->key, p->value);
51 * }
52 * MyArray_Free(&arr);
53 * assert(arr == NULL);
54 * }
55 * -------------------------------------------------------------------------------
56 */
57
58 /*************************************************************************/
59 /*
60 * Two array types will be provided:
61 * Use TK_ARRAY_DEFINE if your array is aggregating the elements. Use
62 * TK_PTR_ARRAY_DEFINE if your array contains pointers to elements. But
63 * in latter case the array is not responsible for the lifetime of the
64 * elements.
65 */
66 /*************************************************************************/
67 /*
68 * Array_ElemSize: Returns the memory size for one array element.
69 */
70 /*************************************************************************/
71 /*
72 * Array_BufferSize: Returns the memory size for given number of elements.
73 */
74 /*************************************************************************/
75 /*
76 * Array_IsEmpty: Array is empty?
77 */
78 /*************************************************************************/
79 /*
80 * Array_Size: Number of elements in array.
81 */
82 /*************************************************************************/
83 /*
84 * Array_Capacity: Capacity of given array. This is the maximal number of
85 * elements fitting into current array memory without resizing the buffer.
86 */
87 /*************************************************************************/
88 /*
89 * Array_SetSize: Set array size, new size must not exceed the capacity of
90 * the array. This function has to be used with care when increasing the
91 * array size.
92 */
93 /*************************************************************************/
94 /*
95 * Array_First: Returns position of first element in array. Given array
96 * may be NULL.
97 */
98 /*************************************************************************/
99 /*
100 * Array_Last: Returns position after last element in array. Given array
101 * may be empty.
102 */
103 /*************************************************************************/
104 /*
105 * Array_Front: Returns first element in array. Given array must not be
106 * empty.
107 */
108 /*************************************************************************/
109 /*
110 * Array_Back: Returns last element in array. Given array must not be
111 * empty.
112 */
113 /*************************************************************************/
114 /*
115 * Array_Resize: Resize buffer of array for given number of elements. The
116 * array may grow or shrink. Note that this function is not initializing
117 * the increased buffer.
118 */
119 /*************************************************************************/
120 /*
121 * Array_ResizeAndClear: Resize buffer of array for given number of
122 * elements. The array may grow or shrink. The increased memory will be
123 * filled with zeroes.
124 */
125 /*************************************************************************/
126 /*
127 * Array_Clear: Fill specified range with zeroes.
128 */
129 /*************************************************************************/
130 /*
131 * Array_Free: Resize array to size zero. This function will release the
132 * array buffer.
133 */
134 /*************************************************************************/
135 /*
136 * Array_Append: Insert given element after end of array.
137 */
138 /*************************************************************************/
139 /*
140 * Array_PopBack: Shrink array by one element. Given array must not be
141 * empty.
142 */
143 /*************************************************************************/
144 /*
145 * Array_Get: Random access to array element at given position. The given
146 * index must not exceed current array size.
147 */
148 /*************************************************************************/
149 /*
150 * Array_Set: Replace array element at given position with new value. The
151 * given index must not exceed current array size.
152 */
153 /*************************************************************************/
154 /*
155 * Array_Find: Return index position of element which matches given
156 * argument. If not found then -1 will be returned.
157 */
158 /*************************************************************************/
159
160 #ifndef TK_ARRAY_DEFINED
161 #define TK_ARRAY_DEFINED
162
163 #include "tkInt.h"
164
165 #if defined(__GNUC__) || defined(__clang__)
166 # define __TK_ARRAY_UNUSED __attribute__((unused))
167 #else
168 # define __TK_ARRAY_UNUSED
169 #endif
170
171 #define TK_ARRAY_DEFINE(AT, ElemType) /* AT = type of array */ \
172 /* ------------------------------------------------------------------------- */ \
173 typedef struct AT { \
174 size_t size; \
175 size_t capacity; \
176 ElemType buf[1]; \
177 } AT; \
178 \
179 __TK_ARRAY_UNUSED \
180 static void \
181 AT##_Init(AT *arr) \
182 { \
183 assert(arr); \
184 arr->size = 0; \
185 arr->capacity = 0; \
186 } \
187 \
188 __TK_ARRAY_UNUSED \
189 static size_t \
190 AT##_ElemSize() \
191 { \
192 return sizeof(ElemType); \
193 } \
194 \
195 __TK_ARRAY_UNUSED \
196 static size_t \
197 AT##_BufferSize(size_t numElems) \
198 { \
199 return numElems*sizeof(ElemType); \
200 } \
201 \
202 __TK_ARRAY_UNUSED \
203 static int \
204 AT##_IsEmpty(const AT *arr) \
205 { \
206 assert(!arr || arr->size != 0xdeadbeef); \
207 return !arr || arr->size == 0u; \
208 } \
209 \
210 __TK_ARRAY_UNUSED \
211 static size_t \
212 AT##_Size(const AT *arr) \
213 { \
214 assert(!arr || arr->size != 0xdeadbeef); \
215 return arr ? arr->size : 0u; \
216 } \
217 \
218 __TK_ARRAY_UNUSED \
219 static size_t \
220 AT##_Capacity(const AT *arr) \
221 { \
222 assert(!arr || arr->size != 0xdeadbeef); \
223 return arr ? arr->capacity : 0u; \
224 } \
225 \
226 __TK_ARRAY_UNUSED \
227 static ElemType * \
228 AT##_First(AT *arr) \
229 { \
230 assert(!arr || arr->size != 0xdeadbeef); \
231 return arr ? arr->buf : NULL; \
232 } \
233 \
234 __TK_ARRAY_UNUSED \
235 static ElemType * \
236 AT##_Last(AT *arr) \
237 { \
238 assert(!arr || arr->size != 0xdeadbeef); \
239 return arr ? arr->buf + arr->size : NULL; \
240 } \
241 \
242 __TK_ARRAY_UNUSED \
243 static ElemType * \
244 AT##_Front(AT *arr) \
245 { \
246 assert(arr); \
247 assert(arr->size != 0xdeadbeef); \
248 assert(!AT##_IsEmpty(arr)); \
249 return &arr->buf[0]; \
250 } \
251 \
252 __TK_ARRAY_UNUSED \
253 static ElemType * \
254 AT##_Back(AT *arr) \
255 { \
256 assert(arr); \
257 assert(arr->size != 0xdeadbeef); \
258 assert(!AT##_IsEmpty(arr)); \
259 return &arr->buf[arr->size - 1]; \
260 } \
261 \
262 __TK_ARRAY_UNUSED \
263 static void \
264 AT##_Resize(AT **arrp, size_t newSize) \
265 { \
266 assert(arrp); \
267 assert(!*arrp || (*arrp)->size != 0xdeadbeef); \
268 if (newSize == 0) { \
269 assert(!*arrp || ((*arrp)->size = 0xdeadbeef)); \
270 ckfree(*arrp); \
271 *arrp = NULL; \
272 } else { \
273 int init = *arrp == NULL; \
274 size_t memSize = AT##_BufferSize(newSize - 1) + sizeof(AT); \
275 *arrp = ckrealloc(*arrp, memSize); \
276 if (init) { \
277 (*arrp)->size = 0; \
278 } else if (newSize < (*arrp)->size) { \
279 (*arrp)->size = newSize; \
280 } \
281 (*arrp)->capacity = newSize; \
282 } \
283 } \
284 \
285 __TK_ARRAY_UNUSED \
286 static void \
287 AT##_Clear(AT *arr, size_t from, size_t to) \
288 { \
289 assert(arr); \
290 assert(arr->size != 0xdeadbeef); \
291 assert(to <= AT##_Capacity(arr)); \
292 assert(from <= to); \
293 memset(arr->buf + from, 0, AT##_BufferSize(to - from)); \
294 } \
295 \
296 __TK_ARRAY_UNUSED \
297 static void \
298 AT##_ResizeAndClear(AT **arrp, size_t newSize) \
299 { \
300 size_t oldCapacity; \
301 assert(arrp); \
302 oldCapacity = *arrp ? (*arrp)->capacity : 0; \
303 AT##_Resize(arrp, newSize); \
304 if (newSize > oldCapacity) { \
305 AT##_Clear(*arrp, oldCapacity, newSize); \
306 } \
307 } \
308 \
309 __TK_ARRAY_UNUSED \
310 static void \
311 AT##_SetSize(AT *arr, size_t newSize) \
312 { \
313 assert(newSize <= AT##_Capacity(arr)); \
314 assert(!arr || arr->size != 0xdeadbeef); \
315 if (arr) { \
316 arr->size = newSize; \
317 } \
318 } \
319 \
320 __TK_ARRAY_UNUSED \
321 static void \
322 AT##_Append(AT **arrp, ElemType *elem) \
323 { \
324 assert(arrp); \
325 if (!*arrp) { \
326 AT##_Resize(arrp, 1); \
327 } else if ((*arrp)->size == (*arrp)->capacity) { \
328 AT##_Resize(arrp, (*arrp)->capacity + ((*arrp)->capacity + 1)/2); \
329 } \
330 (*arrp)->buf[(*arrp)->size++] = *elem; \
331 } \
332 \
333 __TK_ARRAY_UNUSED \
334 static size_t \
335 AT##_PopBack(AT *arr) \
336 { \
337 assert(!AT##_IsEmpty(arr)); \
338 return arr->size -= 1; \
339 } \
340 \
341 __TK_ARRAY_UNUSED \
342 static ElemType * \
343 AT##_Get(const AT *arr, size_t at) \
344 { \
345 assert(arr); \
346 assert(at < AT##_Size(arr)); \
347 return (ElemType *) &arr->buf[at]; \
348 } \
349 \
350 __TK_ARRAY_UNUSED \
351 static void \
352 AT##_Set(AT *arr, size_t at, ElemType *elem) \
353 { \
354 assert(arr); \
355 assert(at < AT##_Size(arr)); \
356 arr->buf[at] = *elem; \
357 } \
358 \
359 __TK_ARRAY_UNUSED \
360 static void \
361 AT##_Free(AT **arrp) \
362 { \
363 AT##_Resize(arrp, 0); \
364 } \
365 \
366 __TK_ARRAY_UNUSED \
367 static int \
368 AT##_Find(const AT *arr, const ElemType *elem) \
369 { \
370 assert(!arr || arr->size != 0xdeadbeef); \
371 if (arr) { \
372 const ElemType *buf = arr->buf; \
373 size_t i; \
374 for (i = 0; i < arr->size; ++i) { \
375 if (memcmp(&buf[i], elem, sizeof(ElemType)) == 0) { \
376 return (int) i; \
377 } \
378 } \
379 } \
380 return -1; \
381 } \
382 \
383 __TK_ARRAY_UNUSED \
384 static int \
385 AT##_Contains(const AT *arr, const ElemType *elem) \
386 { \
387 return AT##_Find(arr, elem) != -1; \
388 } \
389 /* ------------------------------------------------------------------------- */
390
391 #define TK_PTR_ARRAY_DEFINE(AT, ElemType) /* AT = type of array */ \
392 /* ------------------------------------------------------------------------- */ \
393 typedef struct AT { \
394 size_t size; \
395 size_t capacity; \
396 ElemType *buf[1]; \
397 } AT; \
398 \
399 __TK_ARRAY_UNUSED \
400 static size_t \
401 AT##_ElemSize() \
402 { \
403 return sizeof(ElemType); \
404 } \
405 \
406 __TK_ARRAY_UNUSED \
407 static size_t \
408 AT##_BufferSize(size_t numElems) \
409 { \
410 return numElems*sizeof(ElemType *); \
411 } \
412 \
413 __TK_ARRAY_UNUSED \
414 static int \
415 AT##_IsEmpty(const AT *arr) \
416 { \
417 assert(!arr || arr->size != 0xdeadbeef); \
418 return !arr || arr->size == 0; \
419 } \
420 \
421 __TK_ARRAY_UNUSED \
422 static ElemType ** \
423 AT##_First(AT *arr) \
424 { \
425 assert(!arr || arr->size != 0xdeadbeef); \
426 return arr ? arr->buf : NULL; \
427 } \
428 \
429 __TK_ARRAY_UNUSED \
430 static ElemType ** \
431 AT##_Last(AT *arr) \
432 { \
433 assert(!arr || arr->size != 0xdeadbeef); \
434 return arr ? arr->buf + arr->size : NULL; \
435 } \
436 \
437 __TK_ARRAY_UNUSED \
438 static ElemType * \
439 AT##_Front(AT *arr) \
440 { \
441 assert(arr); \
442 assert(arr->size != 0xdeadbeef); \
443 assert(!AT##_IsEmpty(arr)); \
444 return arr->buf[0]; \
445 } \
446 \
447 __TK_ARRAY_UNUSED \
448 static ElemType * \
449 AT##_Back(AT *arr) \
450 { \
451 assert(arr); \
452 assert(arr->size != 0xdeadbeef); \
453 assert(!AT##_IsEmpty(arr)); \
454 return arr->buf[arr->size - 1]; \
455 } \
456 \
457 __TK_ARRAY_UNUSED \
458 static size_t \
459 AT##_Size(const AT *arr) \
460 { \
461 assert(!arr || arr->size != 0xdeadbeef); \
462 return arr ? arr->size : 0; \
463 } \
464 \
465 __TK_ARRAY_UNUSED \
466 static size_t \
467 AT##_Capacity(const AT *arr) \
468 { \
469 assert(!arr || arr->size != 0xdeadbeef); \
470 return arr ? arr->capacity : 0; \
471 } \
472 \
473 __TK_ARRAY_UNUSED \
474 static void \
475 AT##_Resize(AT **arrp, size_t newCapacity) \
476 { \
477 assert(arrp); \
478 assert(!*arrp || (*arrp)->size != 0xdeadbeef); \
479 if (newCapacity == 0) { \
480 assert(!*arrp || ((*arrp)->size = 0xdeadbeef)); \
481 ckfree(*arrp); \
482 *arrp = NULL; \
483 } else { \
484 int init = *arrp == NULL; \
485 size_t memSize = AT##_BufferSize(newCapacity - 1) + sizeof(AT); \
486 *arrp = ckrealloc(*arrp, memSize); \
487 if (init) { \
488 (*arrp)->size = 0; \
489 } else if (newCapacity < (*arrp)->size) { \
490 (*arrp)->size = newCapacity; \
491 } \
492 (*arrp)->capacity = newCapacity; \
493 } \
494 } \
495 \
496 __TK_ARRAY_UNUSED \
497 static void \
498 AT##_Clear(AT *arr, size_t from, size_t to) \
499 { \
500 assert(arr); \
501 assert(arr->size != 0xdeadbeef); \
502 assert(to <= AT##_Capacity(arr)); \
503 assert(from <= to); \
504 memset(arr->buf + from, 0, AT##_BufferSize(to - from)); \
505 } \
506 \
507 __TK_ARRAY_UNUSED \
508 static void \
509 AT##_ResizeAndClear(AT **arrp, size_t newCapacity) \
510 { \
511 size_t oldCapacity; \
512 assert(arrp); \
513 oldCapacity = *arrp ? (*arrp)->capacity : 0; \
514 AT##_Resize(arrp, newCapacity); \
515 if (newCapacity > oldCapacity) { \
516 AT##_Clear(*arrp, oldCapacity, newCapacity); \
517 } \
518 } \
519 \
520 __TK_ARRAY_UNUSED \
521 static void \
522 AT##_SetSize(AT *arr, size_t newSize) \
523 { \
524 assert(arr); \
525 assert(newSize <= AT##_Capacity(arr)); \
526 arr->size = newSize; \
527 } \
528 \
529 __TK_ARRAY_UNUSED \
530 static void \
531 AT##_Append(AT **arrp, ElemType *elem) \
532 { \
533 assert(arrp); \
534 if (!*arrp) { \
535 AT##_Resize(arrp, 1); \
536 } else if ((*arrp)->size == (*arrp)->capacity) { \
537 AT##_Resize(arrp, (*arrp)->capacity + ((*arrp)->capacity + 1)/2); \
538 } \
539 (*arrp)->buf[(*arrp)->size++] = elem; \
540 } \
541 \
542 __TK_ARRAY_UNUSED \
543 static size_t \
544 AT##_PopBack(AT *arr) \
545 { \
546 assert(!AT##_IsEmpty(arr)); \
547 return arr->size -= 1; \
548 } \
549 \
550 __TK_ARRAY_UNUSED \
551 static ElemType * \
552 AT##_Get(const AT *arr, size_t at) \
553 { \
554 assert(arr); \
555 assert(at < AT##_Size(arr)); \
556 return arr->buf[at]; \
557 } \
558 \
559 __TK_ARRAY_UNUSED \
560 static void \
561 AT##_Set(AT *arr, size_t at, ElemType *elem) \
562 { \
563 assert(arr); \
564 assert(at < AT##_Size(arr)); \
565 arr->buf[at] = elem; \
566 } \
567 \
568 __TK_ARRAY_UNUSED \
569 static void \
570 AT##_Free(AT **arrp) \
571 { \
572 AT##_Resize(arrp, 0); \
573 } \
574 \
575 __TK_ARRAY_UNUSED \
576 static int \
577 AT##_Find(const AT *arr, const ElemType *elem) \
578 { \
579 assert(!arr || arr->size != 0xdeadbeef); \
580 if (arr) { \
581 ElemType *const *buf = arr->buf; \
582 size_t i; \
583 for (i = 0; i < arr->size; ++i) { \
584 if (buf[i] == elem) { \
585 return (int) i; \
586 } \
587 } \
588 } \
589 return -1; \
590 } \
591 \
592 __TK_ARRAY_UNUSED \
593 static int \
594 AT##_Contains(const AT *arr, const ElemType *elem) \
595 { \
596 return AT##_Find(arr, elem) != -1; \
597 } \
598 /* ------------------------------------------------------------------------- */
599
600 #endif /* TK_ARRAY_DEFINED */
601
602 /*
603 * Local Variables:
604 * mode: c
605 * c-basic-offset: 4
606 * fill-column: 105
607 * End:
608 * vi:set ts=8 sw=4:
609 */
66 * Copyright (c) 1989-1994 The Regents of the University of California.
77 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
88 * Copyright (c) 1998 by Scriptics Corporation.
9 * Copyright (c) 2018-2019 by Gregor Cramer.
910 *
1011 * See the file "license.terms" for information on usage and redistribution of
1112 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
1213 */
1314
1415 #include "tkInt.h"
15
16 #ifdef _WIN32
16 #include "tkDList.h"
17 #include "tkArray.h"
18
19 #if defined(_WIN32)
1720 #include "tkWinInt.h"
1821 #elif defined(MAC_OSX_TK)
1922 #include "tkMacOSXInt.h"
20 #else
23 #else /* if defined(__unix__) */
2124 #include "tkUnixInt.h"
2225 #endif
2326
27 #ifdef NDEBUG
28 # define DEBUG(expr)
29 #else
30 # define DEBUG(expr) expr
31 #endif
32
33 #ifdef _MSC_VER
34 /*
35 * Earlier versions of MSVC don't know snprintf, but _snprintf is compatible.
36 * Note that sprintf is deprecated.
37 */
38 # define snprintf _snprintf
39 #endif
40
41 #define SIZE_OF_ARRAY(arr) (sizeof(arr)/sizeof(arr[0]))
42
2443 /*
2544 * File structure:
2645 *
2847 *
2948 * Init/Free this package.
3049 *
31 * Tcl "bind" command (actually located in tkCmds.c) core implementation, plus
32 * helpers.
50 * Tcl "bind" command (actually located in tkCmds.c) core implementation, plus helpers.
3351 *
3452 * Tcl "event" command implementation, plus helpers.
3553 *
3755 *
3856 * Non-package-specific helpers.
3957 */
58
59 /*
60 * In old implementation (the one that used an event ring), <Double-1> and <1><1> were
61 * equivalent sequences. However it is logical to give <Double-1> higher precedence.
62 * This can be achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1.
63 */
64
65 #ifndef PREFER_MOST_SPECIALIZED_EVENT
66 # define PREFER_MOST_SPECIALIZED_EVENT 0
67 #endif
68
69 /*
70 * Traditionally motion events can be combined with buttons in this way: <B1-B2-Motion>.
71 * However it should be allowed to express this as <Motion-1-2> in addition. This can be
72 * achieved by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1.
73 */
74
75 #ifndef SUPPORT_ADDITIONAL_MOTION_SYNTAX
76 # define SUPPORT_ADDITIONAL_MOTION_SYNTAX 0 /* set to 1 if wanted */
77 #endif
78
79 /*
80 * The output for motion events is of the type <B1-Motion>. This can be changed to become
81 * <Motion-1> instead by setting PRINT_SHORT_MOTION_SYNTAX to 1, however this would be a
82 * backwards incompatibility.
83 */
84
85 #ifndef PRINT_SHORT_MOTION_SYNTAX
86 # define PRINT_SHORT_MOTION_SYNTAX 0 /* set to 1 if wanted */
87 #endif
88
89 #if !SUPPORT_ADDITIONAL_MOTION_SYNTAX
90 # undef PRINT_SHORT_MOTION_SYNTAX
91 # define PRINT_SHORT_MOTION_SYNTAX 0
92 #endif
93
94 /*
95 * For debugging only, normally set to zero.
96 */
97
98 #ifdef SUPPORT_DEBUGGING
99 # undef SUPPORT_DEBUGGING
100 #endif
101 #define SUPPORT_DEBUGGING 0
102
103 /*
104 * Test validity of PSEntry items.
105 */
106
107 # define TEST_PSENTRY(psPtr) psPtr->number != 0xdeadbeef
108 # define MARK_PSENTRY(psPtr) psPtr->number = 0xdeadbeef
40109
41110 /*
42111 * The following union is used to hold the detail information from an XEvent
43112 * (including Tk's XVirtualEvent extension).
44113 */
45114
115 typedef KeySym Info;
116
46117 typedef union {
47 KeySym keySym; /* KeySym that corresponds to xkey.keycode. */
48 int button; /* Button that was pressed (xbutton.button). */
49 Tk_Uid name; /* Tk_Uid of virtual event. */
50 ClientData clientData; /* Used when type of Detail is unknown, and to
51 * ensure that all bytes of Detail are
52 * initialized when this structure is used in
53 * a hash key. */
118 Info info; /* This either corresponds to xkey.keycode, or to xbutton.button,
119 * or is meaningless, depending on event type. */
120 Tk_Uid name; /* Tk_Uid of virtual event. */
54121 } Detail;
122
123 /*
124 * We need an extended event definition.
125 */
126
127 typedef struct {
128 XEvent xev; /* The original event from server. */
129 Detail detail; /* Additional information (for hashing). */
130 unsigned countAny; /* Count of multi-events, like multi-clicks, or repeated key pressing,
131 * this count does not depend on detail (keySym or button). */
132 unsigned countDetailed;
133 /* Count of multi-events, like multi-clicks, or repeated key pressing,
134 * this count considers the detail (keySym or button). */
135 } Event;
136
137 /*
138 * We need a structure providing a list of pattern sequences.
139 */
140
141 typedef unsigned EventMask;
142 typedef unsigned long ModMask;
143
144 struct PatSeq; /* forward declaration */
145
146 /* We need this array for bookkeeping the last matching modifier mask per pattern. */
147 TK_ARRAY_DEFINE(PSModMaskArr, ModMask);
148
149 typedef struct PSEntry {
150 TK_DLIST_LINKS(PSEntry); /* Makes this struct a double linked list; must be first entry. */
151 Window window; /* Window of last match. */
152 struct PatSeq* psPtr; /* Pointer to pattern sequence. */
153 PSModMaskArr *lastModMaskArr;
154 /* Last matching modifier mask per pattern (except last pattern).
155 * Only needed if pattern sequence is not single (more than one
156 * pattern), and if one of these patterns contains a non-zero
157 * modifier mask. */
158 unsigned count; /* Only promote to next level if this count has reached count of
159 * pattern. */
160 unsigned expired:1; /* Whether this entry is expired, this means it has to be removed
161 * from promotion list. */
162 unsigned keepIt:1; /* Whether to keep this entry, even if expired. */
163 } PSEntry;
164
165 /* Defining the whole PSList_* stuff (list of PSEntry items). */
166 TK_DLIST_DEFINE(PSList, PSEntry);
167
168 /* Don't keep larger arrays of modifier masks inside PSEntry. */
169 #define MAX_MOD_MASK_ARR_SIZE 8
170
171 /*
172 * Maps and lookup tables from an event to a list of patterns that match that event.
173 */
174
175 typedef struct {
176 Tcl_HashTable patternTable; /* Keys are PatternTableKey structs, values are (PatSeq *). */
177 Tcl_HashTable listTable; /* Keys are PatternTableKey structs, values are (PSList *). */
178 PSList entryPool; /* Contains free (unused) list items. */
179 unsigned number; /* Needed for enumeration of pattern sequences. */
180 } LookupTables;
55181
56182 /*
57183 * The structure below represents a binding table. A binding table represents
64190 * application with separate event bindings for each (for example, each canvas
65191 * widget has a separate binding table for associating events with the items
66192 * in the canvas).
67 *
68 * Note: it is probably a bad idea to reduce EVENT_BUFFER_SIZE much below 30.
69 * To see this, consider a triple mouse button click while the Shift key is
70 * down (and auto-repeating). There may be as many as 3 auto-repeat events
71 * after each mouse button press or release (see the first large comment block
72 * within Tk_BindEvent for more on this), for a total of 20 events to cover
73 * the three button presses and two intervening releases. If you reduce
74 * EVENT_BUFFER_SIZE too much, shift multi-clicks will be lost.
75 */
76
77 /*
78 * NOTE: The changes which were needed to make Tk work on OSX 10.14 (Mojave)
79 * also demand that the event ring be a bit bigger. It might be wise to
80 * augment the current double-click pattern matching by adding a new
81 * DoubleClick modifier bit which could be set based on the clickCount of the
82 * Apple NSEvent object.
83 */
84
85 #ifndef TK_MAC_OSX
86 #define EVENT_BUFFER_SIZE 45
87 #else
88 #define EVENT_BUFFER_SIZE 30
89 #endif
193 */
194
195 /* defining the whole Promotion_* stuff (array of PSList entries) */
196 TK_ARRAY_DEFINE(PromArr, PSList);
90197
91198 typedef struct Tk_BindingTable_ {
92 XEvent eventRing[EVENT_BUFFER_SIZE];
93 /* Circular queue of recent events (higher
94 * indices are for more recent events). */
95 Detail detailRing[EVENT_BUFFER_SIZE];
96 /* "Detail" information (keySym, button,
97 * Tk_Uid, or 0) for each entry in
98 * eventRing. */
99 int curEvent; /* Index in eventRing of most recent event.
100 * Newer events have higher indices. */
101 Tcl_HashTable patternTable; /* Used to map from an event to a list of
102 * patterns that may match that event. Keys
103 * are PatternTableKey structs, values are
104 * (PatSeq *). */
105 Tcl_HashTable objectTable; /* Used to map from an object to a list of
106 * patterns associated with that object. Keys
107 * are ClientData, values are (PatSeq *). */
108 Tcl_Interp *interp; /* Interpreter in which commands are
109 * executed. */
199 Event eventInfo[TK_LASTEVENT];
200 /* Containing the most recent event for every event type. */
201 PromArr *promArr; /* Contains the promoted pattern sequences. */
202 Event *curEvent; /* Pointing to most recent event. */
203 ModMask curModMask; /* Containing the current modifier mask. */
204 LookupTables lookupTables; /* Containing hash tables for fast lookup. */
205 Tcl_HashTable objectTable; /* Used to map from an object to a list of patterns associated with
206 * that object. Keys are ClientData, values are (PatSeq *). */
207 Tcl_Interp *interp; /* Interpreter in which commands are executed. */
110208 } BindingTable;
111209
112210 /*
123221 */
124222
125223 typedef struct {
126 Tcl_HashTable patternTable; /* Used to map from a physical event to a list
127 * of patterns that may match that event. Keys
128 * are PatternTableKey structs, values are
129 * (PatSeq *). */
130 Tcl_HashTable nameTable; /* Used to map a virtual event name to the
131 * array of physical events that can trigger
132 * it. Keys are the Tk_Uid names of the
133 * virtual events, values are PhysicalsOwned
134 * structs. */
224 LookupTables lookupTables; /* Providing fast lookup tables to lists of pattern sequences. */
225 Tcl_HashTable nameTable; /* Used to map a virtual event name to the array of physical events
226 * that can trigger it. Keys are the Tk_Uid names of the virtual
227 * events, values are PhysOwned structs. */
135228 } VirtualEventTable;
136229
137230 /*
150243 */
151244
152245 typedef struct {
153 ClientData object; /* For binding table, identifies the binding
154 * tag of the object (or class of objects)
155 * relative to which the event occurred. For
156 * virtual event table, always NULL. */
157 int type; /* Type of event (from X). */
158 Detail detail; /* Additional information, such as keysym,
159 * button, Tk_Uid, or 0 if nothing
160 * additional. */
246 ClientData object; /* For binding table, identifies the binding tag of the object
247 * (or class of objects) relative to which the event occurred.
248 * For virtual event table, always NULL. */
249 unsigned type; /* Type of event (from X). */
250 Detail detail; /* Additional information, such as keysym, button, Tk_Uid, or zero
251 * if nothing additional. */
161252 } PatternTableKey;
162253
163254 /*
164255 * The following structure defines a pattern, which is matched against X
165256 * events as part of the process of converting X events into Tcl commands.
257 *
258 * For technical reasons we do not use 'union Detail', although this would
259 * be possible, instead 'info' and 'name' are both included.
166260 */
167261
168262 typedef struct {
169 int eventType; /* Type of X event, e.g. ButtonPress. */
170 int needMods; /* Mask of modifiers that must be present (0
171 * means no modifiers are required). */
172 Detail detail; /* Additional information that must match
173 * event. Normally this is 0, meaning no
174 * additional information must match. For
175 * KeyPress and KeyRelease events, a keySym
176 * may be specified to select a particular
177 * keystroke (0 means any keystrokes). For
178 * button events, specifies a particular
179 * button (0 means any buttons are OK). For
180 * virtual events, specifies the Tk_Uid of the
181 * virtual event name (never 0). */
263 unsigned eventType; /* Type of X event, e.g. ButtonPress. */
264 unsigned count; /* Multi-event count, e.g. double-clicks, triple-clicks, etc. */
265 ModMask modMask; /* Mask of modifiers that must be present (zero means no modifiers
266 * are required). */
267 Info info; /* Additional information that must match event. Normally this is zero,
268 * meaning no additional information must match. For KeyPress and
269 * KeyRelease events, it may be specified to select a particular
270 * keystroke (zero means any keystrokes). For button events, specifies
271 * a particular button (zero means any buttons are OK). */
272 Tk_Uid name; /* Specifies the Tk_Uid of the virtual event name. NULL if not a
273 * virtual event. */
182274 } TkPattern;
275
276 /*
277 * The following structure keeps track of all the virtual events that are
278 * associated with a particular physical event. It is pointed to by the 'owners'
279 * field in a PatSeq in the patternTable of a virtual event table.
280 */
281
282 TK_PTR_ARRAY_DEFINE(VirtOwners, Tcl_HashEntry); /* define array of hash entries */
183283
184284 /*
185285 * The following structure defines a pattern sequence, which consists of one
200300 */
201301
202302 typedef struct PatSeq {
203 int numPats; /* Number of patterns in sequence (usually
204 * 1). */
205 char *script; /* Binding script to evaluate when sequence
206 * matches (ckalloc()ed) */
207 int flags; /* Miscellaneous flag values; see below for
208 * definitions. */
209 struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences that
210 * have the same initial pattern. NULL means
211 * end of list. */
212 Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the initial
213 * pattern. This is the head of the list of
214 * which nextSeqPtr forms a part. */
215 struct VirtualOwners *voPtr;/* In a binding table, always NULL. In a
216 * virtual event table, identifies the array
217 * of virtual events that can be triggered by
218 * this event. */
219 struct PatSeq *nextObjPtr; /* In a binding table, next in list of all
220 * pattern sequences for the same object (NULL
221 * for end of list). Needed to implement
222 * Tk_DeleteAllBindings. In a virtual event
223 * table, always NULL. */
224 TkPattern pats[1]; /* Array of "numPats" patterns. Only one
225 * element is declared here but in actuality
226 * enough space will be allocated for
227 * "numPats" patterns. To match, pats[0] must
228 * match event n, pats[1] must match event
229 * n-1, etc. */
303 unsigned numPats; /* Number of patterns in sequence (usually 1). */
304 unsigned count; /* Total number of repetition counts, summed over count in TkPattern. */
305 unsigned number; /* Needed for the decision whether a binding is less recently defined
306 * than another, it is guaranteed that the most recently bound event
307 * has the highest number. */
308 unsigned added:1; /* Is this pattern sequence already added to lookup table? */
309 unsigned modMaskUsed:1; /* Does at least one pattern contain a non-zero modifier mask? */
310 DEBUG(unsigned owned:1;) /* For debugging purposes. */
311 char *script; /* Binding script to evaluate when sequence matches (ckalloc()ed) */
312 Tcl_Obj* object; /* Token for object with which binding is associated. For virtual
313 * event table this is NULL. */
314 struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences that have the same initial
315 * pattern. NULL means end of list. */
316 Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the initial pattern. This is the
317 * head of the list of which nextSeqPtr forms a part. */
318 union {
319 VirtOwners *owners; /* In a binding table it has no meaning. In a virtual event table,
320 * identifies the array of virtual events that can be triggered
321 * by this event. */
322 struct PatSeq *nextObj; /* In a binding table, next in list of all pattern sequences for
323 * the same object (NULL for end of list). Needed to implement
324 * Tk_DeleteAllBindings. In a virtual event table it has no meaning. */
325 } ptr;
326 TkPattern pats[1]; /* Array of "numPats" patterns. Only one element is declared here
327 * but in actuality enough space will be allocated for "numPats"
328 * patterns (but usually 1). */
230329 } PatSeq;
231330
232331 /*
233 * Flag values for PatSeq structures:
234 *
235 * PAT_NEARBY 1 means that all of the events matching this sequence
236 * must occur with nearby X and Y mouse coordinates and
237 * close in time. This is typically used to restrict
238 * multiple button presses.
239 */
240
241 #define PAT_NEARBY 0x1
332 * Compute memory size of struct PatSeq with given pattern size.
333 * The caller must be sure that pattern size is greater than zero.
334 */
335 #define PATSEQ_MEMSIZE(numPats) (sizeof(PatSeq) + (numPats - 1)*sizeof(TkPattern))
242336
243337 /*
244338 * Constants that define how close together two events must be in milliseconds
245339 * or pixels to meet the PAT_NEARBY constraint:
246340 */
247341
248 #define NEARBY_PIXELS 5
249 #define NEARBY_MS 500
250
251 /*
252 * The following structure keeps track of all the virtual events that are
253 * associated with a particular physical event. It is pointed to by the voPtr
254 * field in a PatSeq in the patternTable of a virtual event table.
255 */
256
257 typedef struct VirtualOwners {
258 int numOwners; /* Number of virtual events to trigger. */
259 Tcl_HashEntry *owners[1]; /* Array of pointers to entries in nameTable.
260 * Enough space will actually be allocated for
261 * numOwners hash entries. */
262 } VirtualOwners;
342 #define NEARBY_PIXELS 5
343 #define NEARBY_MS 500
344
345 /*
346 * Needed as "no-number" constant for integers. The value of this constant is
347 * outside of integer range (type "int"). (Unfortunatly current version of
348 * Tcl/Tk does not provide C99 integer support.)
349 */
350
351 #define NO_NUMBER (((Tcl_WideInt) (~ (unsigned) 0)) + 1)
263352
264353 /*
265354 * The following structure is used in the nameTable of a virtual event table
266355 * to associate a virtual event with all the physical events that can trigger
267356 * it.
268357 */
269 typedef struct {
270 int numOwned; /* Number of physical events owned. */
271 PatSeq *patSeqs[1]; /* Array of pointers to physical event
272 * patterns. Enough space will actually be
273 * allocated to hold numOwned. */
274 } PhysicalsOwned;
358
359 TK_PTR_ARRAY_DEFINE(PhysOwned, PatSeq); /* define array of pattern seqs */
275360
276361 /*
277362 * One of the following structures exists for each interpreter. This structure
281366 */
282367
283368 typedef struct {
284 TkDisplay *curDispPtr; /* Display for last binding command invoked in
285 * this application. */
369 TkDisplay *curDispPtr; /* Display for last binding command invoked in this application. */
286370 int curScreenIndex; /* Index of screen for last binding command */
287 int bindingDepth; /* Number of active instances of Tk_BindEvent
288 * in this application. */
371 unsigned bindingDepth; /* Number of active instances of Tk_BindEvent in this application. */
289372 } ScreenInfo;
290373
291374 /*
295378
296379 typedef struct TkBindInfo_ {
297380 VirtualEventTable virtualEventTable;
298 /* The virtual events that exist in this
299 * interpreter. */
300 ScreenInfo screenInfo; /* Keeps track of the current display and
301 * screen, so it can be restored after a
302 * binding has executed. */
303 int deleted; /* 1 the application has been deleted but the
304 * structure has been preserved. */
381 /* The virtual events that exist in this interpreter. */
382 ScreenInfo screenInfo; /* Keeps track of the current display and screen, so it can be
383 * restored after a binding has executed. */
384 int deleted; /* 1 if the application has been deleted but the structure has been
385 * preserved. */
386 Time lastEventTime; /* Needed for time measurement. */
387 Time lastCurrentTime; /* Needed for time measurement. */
305388 } BindInfo;
306389
307390 /*
316399
317400 #ifdef REDO_KEYSYM_LOOKUP
318401 typedef struct {
319 const char *name; /* Name of keysym. */
402 const char *name; /* Name of keysym. */
320403 KeySym value; /* Numeric identifier for keysym. */
321404 } KeySymInfo;
322405 static const KeySymInfo keyArray[] = {
325408 #endif
326409 {NULL, 0}
327410 };
328 static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */
329 static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */
411 static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */
412 static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */
330413 #endif /* REDO_KEYSYM_LOOKUP */
331
332 /*
333 * Set to non-zero when the package-wide static variables have been
334 * initialized.
335 */
336
337 static int initialized = 0;
338 TCL_DECLARE_MUTEX(bindMutex)
339414
340415 /*
341416 * A hash table is kept to map from the string names of event modifiers to
345420 */
346421
347422 typedef struct {
348 const char *name; /* Name of modifier. */
349 int mask; /* Button/modifier mask value, such as
350 * Button1Mask. */
351 int flags; /* Various flags; see below for
352 * definitions. */
423 const char *name; /* Name of modifier. */
424 ModMask mask; /* Button/modifier mask value, such as Button1Mask. */
425 unsigned flags; /* Various flags; see below for definitions. */
353426 } ModInfo;
354427
355428 /*
356429 * Flags for ModInfo structures:
357430 *
358 * DOUBLE - Non-zero means duplicate this event,
359 * e.g. for double-clicks.
360 * TRIPLE - Non-zero means triplicate this event,
361 * e.g. for triple-clicks.
362 * QUADRUPLE - Non-zero means quadruple this event,
363 * e.g. for 4-fold-clicks.
431 * DOUBLE - Non-zero means duplicate this event, e.g. for double-clicks.
432 * TRIPLE - Non-zero means triplicate this event, e.g. for triple-clicks.
433 * QUADRUPLE - Non-zero means quadruple this event, e.g. for 4-fold-clicks.
364434 * MULT_CLICKS - Combination of all of above.
365435 */
366436
367 #define DOUBLE 1
368 #define TRIPLE 2
369 #define QUADRUPLE 4
370 #define MULT_CLICKS 7
437 #define DOUBLE (1<<0)
438 #define TRIPLE (1<<1)
439 #define QUADRUPLE (1<<2)
440 #define MULT_CLICKS (DOUBLE|TRIPLE|QUADRUPLE)
371441
372442 static const ModInfo modArray[] = {
373443 {"Control", ControlMask, 0},
415485
416486 typedef struct {
417487 const char *name; /* Name of event. */
418 int type; /* Event type for X, such as ButtonPress. */
419 int eventMask; /* Mask bits (for XSelectInput) for this event
420 * type. */
488 unsigned type; /* Event type for X, such as ButtonPress. */
489 unsigned eventMask; /* Mask bits (for XSelectInput) for this event type. */
421490 } EventInfo;
422491
423492 /*
433502 {"KeyRelease", KeyRelease, KeyPressMask|KeyReleaseMask},
434503 {"Button", ButtonPress, ButtonPressMask},
435504 {"ButtonPress", ButtonPress, ButtonPressMask},
436 {"ButtonRelease", ButtonRelease,
437 ButtonPressMask|ButtonReleaseMask},
438 {"Motion", MotionNotify,
439 ButtonPressMask|PointerMotionMask},
505 {"ButtonRelease", ButtonRelease, ButtonPressMask|ButtonReleaseMask},
506 {"Motion", MotionNotify, ButtonPressMask|PointerMotionMask},
440507 {"Enter", EnterNotify, EnterWindowMask},
441508 {"Leave", LeaveNotify, LeaveWindowMask},
442509 {"FocusIn", FocusIn, FocusChangeMask},
464531 };
465532 static Tcl_HashTable eventTable;
466533
534 static int eventArrayIndex[TK_LASTEVENT];
535
467536 /*
468537 * The defines and table below are used to classify events into various
469538 * groups. The reason for this is that logically identical fields (e.g.
472541 * information from events.
473542 */
474543
475 #define KEY 0x1
476 #define BUTTON 0x2
477 #define MOTION 0x4
478 #define CROSSING 0x8
479 #define FOCUS 0x10
480 #define EXPOSE 0x20
481 #define VISIBILITY 0x40
482 #define CREATE 0x80
483 #define DESTROY 0x100
484 #define UNMAP 0x200
485 #define MAP 0x400
486 #define REPARENT 0x800
487 #define CONFIG 0x1000
488 #define GRAVITY 0x2000
489 #define CIRC 0x4000
490 #define PROP 0x8000
491 #define COLORMAP 0x10000
492 #define VIRTUAL 0x20000
493 #define ACTIVATE 0x40000
494 #define MAPREQ 0x80000
495 #define CONFIGREQ 0x100000
496 #define RESIZEREQ 0x200000
497 #define CIRCREQ 0x400000
544 #define KEY (1<<0)
545 #define BUTTON (1<<1)
546 #define MOTION (1<<2)
547 #define CROSSING (1<<3)
548 #define FOCUS (1<<4)
549 #define EXPOSE (1<<5)
550 #define VISIBILITY (1<<6)
551 #define CREATE (1<<7)
552 #define DESTROY (1<<8)
553 #define UNMAP (1<<9)
554 #define MAP (1<<10)
555 #define REPARENT (1<<11)
556 #define CONFIG (1<<12)
557 #define GRAVITY (1<<13)
558 #define CIRC (1<<14)
559 #define PROP (1<<15)
560 #define COLORMAP (1<<16)
561 #define VIRTUAL (1<<17)
562 #define ACTIVATE (1<<18)
563 #define MAPREQ (1<<19)
564 #define CONFIGREQ (1<<20)
565 #define RESIZEREQ (1<<21)
566 #define CIRCREQ (1<<22)
498567
499568 #define KEY_BUTTON_MOTION_VIRTUAL (KEY|BUTTON|MOTION|VIRTUAL)
500569 #define KEY_BUTTON_MOTION_CROSSING (KEY|BUTTON|MOTION|VIRTUAL|CROSSING)
547616 */
548617
549618 static const TkStateMap queuePosition[] = {
550 {-1, "now"},
551 {TCL_QUEUE_HEAD, "head"},
552 {TCL_QUEUE_MARK, "mark"},
553 {TCL_QUEUE_TAIL, "tail"},
554 {-2, NULL}
619 {-1, "now"},
620 {TCL_QUEUE_HEAD, "head"},
621 {TCL_QUEUE_MARK, "mark"},
622 {TCL_QUEUE_TAIL, "tail"},
623 {-2, NULL}
555624 };
556625
557626 /*
582651 };
583652
584653 static const TkStateMap circPlace[] = {
585 {PlaceOnTop, "PlaceOnTop"},
586 {PlaceOnBottom, "PlaceOnBottom"},
654 {PlaceOnTop, "PlaceOnTop"},
655 {PlaceOnBottom, "PlaceOnBottom"},
587656 {-1, NULL}
588657 };
589658
595664 };
596665
597666 static const TkStateMap configureRequestDetail[] = {
598 {None, "None"},
599 {Above, "Above"},
600 {Below, "Below"},
601 {BottomIf, "BottomIf"},
602 {TopIf, "TopIf"},
603 {Opposite, "Opposite"},
667 {None, "None"},
668 {Above, "Above"},
669 {Below, "Below"},
670 {BottomIf, "BottomIf"},
671 {TopIf, "TopIf"},
672 {Opposite, "Opposite"},
604673 {-1, NULL}
605674 };
606675
610679 {-1, NULL}
611680 };
612681
682 DEBUG(static int countTableItems = 0;)
683 DEBUG(static int countEntryItems = 0;)
684 DEBUG(static int countListItems = 0;)
685 DEBUG(static int countBindItems = 0;)
686 DEBUG(static int countSeqItems = 0;)
687
613688 /*
614689 * Prototypes for local functions defined in this file:
615690 */
616691
617 static void ChangeScreen(Tcl_Interp *interp, char *dispName,
618 int screenIndex);
619 static int CreateVirtualEvent(Tcl_Interp *interp,
620 VirtualEventTable *vetPtr, char *virtString,
621 const char *eventString);
622 static int DeleteVirtualEvent(Tcl_Interp *interp,
623 VirtualEventTable *vetPtr, char *virtString,
624 const char *eventString);
692 static void ChangeScreen(Tcl_Interp *interp, char *dispName, int screenIndex);
693 static int CreateVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
694 char *virtString, const char *eventString);
695 static int DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
696 char *virtString, const char *eventString);
625697 static void DeleteVirtualEventTable(VirtualEventTable *vetPtr);
626 static void ExpandPercents(TkWindow *winPtr, const char *before,
627 XEvent *eventPtr,KeySym keySym,
628 unsigned int scriptCount, Tcl_DString *dsPtr);
629 static PatSeq * FindSequence(Tcl_Interp *interp,
630 Tcl_HashTable *patternTablePtr, ClientData object,
631 const char *eventString, int create,
632 int allowVirtual, unsigned long *maskPtr);
633 static void GetAllVirtualEvents(Tcl_Interp *interp,
634 VirtualEventTable *vetPtr);
635 static char * GetField(char *p, char *copy, int size);
636 static Tcl_Obj * GetPatternObj(PatSeq *psPtr);
637 static int GetVirtualEvent(Tcl_Interp *interp,
638 VirtualEventTable *vetPtr, Tcl_Obj *virtName);
639 static Tk_Uid GetVirtualEventUid(Tcl_Interp *interp,
640 char *virtString);
698 static void ExpandPercents(TkWindow *winPtr, const char *before, Event *eventPtr,
699 unsigned scriptCount, Tcl_DString *dsPtr);
700 static PatSeq * FindSequence(Tcl_Interp *interp, LookupTables *lookupTables,
701 ClientData object, const char *eventString, int create,
702 int allowVirtual, EventMask *maskPtr);
703 static void GetAllVirtualEvents(Tcl_Interp *interp, VirtualEventTable *vetPtr);
704 static const char * GetField(const char *p, char *copy, unsigned size);
705 static Tcl_Obj * GetPatternObj(const PatSeq *psPtr);
706 static int GetVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
707 Tcl_Obj *virtName);
708 static Tk_Uid GetVirtualEventUid(Tcl_Interp *interp, char *virtString);
641709 static int HandleEventGenerate(Tcl_Interp *interp, Tk_Window main,
642710 int objc, Tcl_Obj *const objv[]);
643711 static void InitVirtualEventTable(VirtualEventTable *vetPtr);
644 static PatSeq * MatchPatterns(TkDisplay *dispPtr,
645 BindingTable *bindPtr, PatSeq *psPtr,
646 PatSeq *bestPtr, ClientData *objectPtr,
647 PatSeq **sourcePtrPtr);
712 static PatSeq * MatchPatterns(TkDisplay *dispPtr, Tk_BindingTable bindPtr, PSList *psList,
713 PSList *psSuccList, unsigned patIndex, const Event *eventPtr,
714 ClientData object, PatSeq **physPtrPtr);
648715 static int NameToWindow(Tcl_Interp *interp, Tk_Window main,
649716 Tcl_Obj *objPtr, Tk_Window *tkwinPtr);
650 static int ParseEventDescription(Tcl_Interp *interp,
651 const char **eventStringPtr, TkPattern *patPtr,
652 unsigned long *eventMaskPtr);
717 static unsigned ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr,
718 TkPattern *patPtr, EventMask *eventMaskPtr);
653719 static void DoWarp(ClientData clientData);
720 static PSList * GetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr,
721 Tcl_Obj *object, int onlyConsiderDetailedEvents);
722 static void ClearLookupTable(LookupTables *lookupTables, ClientData object);
723 static void ClearPromotionLists(Tk_BindingTable bindPtr, ClientData object);
724 static PSEntry * MakeListEntry(PSList *pool, PatSeq *psPtr, int needModMasks);
725 static void RemovePatSeqFromLookup(LookupTables *lookupTables, PatSeq *psPtr);
726 static void RemovePatSeqFromPromotionLists(Tk_BindingTable bindPtr, PatSeq *psPtr);
727 static PatSeq * DeletePatSeq(PatSeq *psPtr);
728 static void InsertPatSeq(LookupTables *lookupTables, PatSeq *psPtr);
729 #if SUPPORT_DEBUGGING
730 void TkpDumpPS(const PatSeq *psPtr);
731 void TkpDumpPSList(const PSList *psList);
732 #endif
733
734 /*
735 * Some useful helper functions.
736 */
737 #ifdef SUPPORT_DEBUGGING
738 static int BindCount = 0;
739 #endif
740
741 static unsigned Max(unsigned a, unsigned b) { return a < b ? b : a; }
742 static int Abs(int n) { return n < 0 ? -n : n; }
743 static int IsOdd(int n) { return n & 1; }
744
745 static int TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; }
746 static int TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; }
747
748 static int
749 IsSubsetOf(
750 ModMask lhsMask, /* this is a subset */
751 ModMask rhsMask) /* of this bit field? */
752 {
753 return (lhsMask & rhsMask) == lhsMask;
754 }
755
756 static const char*
757 SkipSpaces(
758 const char* s)
759 {
760 assert(s);
761 while (isspace(UCHAR(*s)))
762 ++s;
763 return s;
764 }
765
766 static const char*
767 SkipFieldDelims(
768 const char* s)
769 {
770 assert(s);
771 while (*s == '-' || isspace(UCHAR(*s))) {
772 ++s;
773 }
774 return s;
775 }
776
777 static unsigned
778 GetButtonNumber(
779 const char *field)
780 {
781 assert(field);
782 return (field[0] >= '1' && field[0] <= '5' && field[1] == '\0') ? field[0] - '0' : 0;
783 }
784
785 static Time
786 CurrentTimeInMilliSecs()
787 {
788 Tcl_Time now;
789 Tcl_GetTime(&now);
790 return ((Time) now.sec)*1000 + ((Time) now.usec)/1000;
791 }
792
793 static Info
794 GetInfo(
795 const PatSeq *psPtr,
796 unsigned index)
797 {
798 assert(psPtr);
799 assert(index < psPtr->numPats);
800
801 return psPtr->pats[index].info;
802 }
803
804 static unsigned
805 GetCount(
806 const PatSeq *psPtr,
807 unsigned index)
808 {
809 assert(psPtr);
810 assert(index < psPtr->numPats);
811
812 return psPtr->pats[index].count;
813 }
814
815 static int
816 CountSpecialized(
817 const PatSeq *fstMatchPtr,
818 const PatSeq *sndMatchPtr)
819 {
820 int fstCount = 0;
821 int sndCount = 0;
822 unsigned i;
823
824 assert(fstMatchPtr);
825 assert(sndMatchPtr);
826
827 for (i = 0; i < fstMatchPtr->numPats; ++i) {
828 if (GetInfo(fstMatchPtr, i)) { fstCount += GetCount(fstMatchPtr, i); }
829 }
830 for (i = 0; i < sndMatchPtr->numPats; ++i) {
831 if (GetInfo(sndMatchPtr, i)) { sndCount += GetCount(sndMatchPtr, i); }
832 }
833
834 return sndCount - fstCount;
835 }
836
837 static int
838 MatchEventNearby(
839 const XEvent *lhs, /* previous button event */
840 const XEvent *rhs) /* current button event */
841 {
842 assert(lhs);
843 assert(rhs);
844 assert(lhs->type == ButtonPress || lhs->type == ButtonRelease);
845 assert(lhs->type == rhs->type);
846
847 /* assert: lhs->xbutton.time <= rhs->xbutton.time */
848
849 return TestNearbyTime(rhs->xbutton.time, lhs->xbutton.time)
850 && TestNearbyCoords(rhs->xbutton.x_root, lhs->xbutton.x_root)
851 && TestNearbyCoords(rhs->xbutton.y_root, lhs->xbutton.y_root);
852 }
853
854 static int
855 MatchEventRepeat(
856 const XEvent *lhs, /* previous key event */
857 const XEvent *rhs) /* current key event */
858 {
859 assert(lhs);
860 assert(rhs);
861 assert(lhs->type == KeyPress || lhs->type == KeyRelease);
862 assert(lhs->type == rhs->type);
863
864 /* assert: lhs->xkey.time <= rhs->xkey.time */
865 return TestNearbyTime(rhs->xkey.time, lhs->xkey.time);
866 }
867
868 static void
869 FreePatSeq(
870 PatSeq *psPtr)
871 {
872 assert(psPtr);
873 assert(!psPtr->owned);
874 DEBUG(MARK_PSENTRY(psPtr);)
875 ckfree(psPtr->script);
876 if (!psPtr->object) {
877 VirtOwners_Free(&psPtr->ptr.owners);
878 }
879 ckfree(psPtr);
880 DEBUG(countSeqItems -= 1;)
881 }
882
883 static void
884 RemoveListEntry(
885 PSList *pool,
886 PSEntry *psEntry)
887 {
888 assert(pool);
889 assert(psEntry);
890
891 if (PSModMaskArr_Capacity(psEntry->lastModMaskArr) > MAX_MOD_MASK_ARR_SIZE) {
892 PSModMaskArr_Free(&psEntry->lastModMaskArr);
893 }
894 PSList_Remove(psEntry);
895 PSList_Append(pool, psEntry);
896 }
897
898 static void
899 ClearList(
900 PSList *psList,
901 PSList *pool,
902 ClientData object)
903 {
904 assert(psList);
905 assert(pool);
906
907 if (object) {
908 PSEntry *psEntry;
909 PSEntry *psNext;
910
911 for (psEntry = PSList_First(psList); psEntry; psEntry = psNext) {
912 psNext = PSList_Next(psEntry);
913 if (psEntry->psPtr->object == object) {
914 RemoveListEntry(pool, psEntry);
915 }
916 }
917 } else {
918 PSList_Move(pool, psList);
919 }
920 }
921
922 static PSEntry *
923 FreePatSeqEntry(
924 PSList *pool,
925 PSEntry *entry)
926 {
927 PSEntry *next = PSList_Next(entry);
928 PSModMaskArr_Free(&entry->lastModMaskArr);
929 ckfree(entry);
930 return next;
931 }
932
933 static unsigned
934 ResolveModifiers(
935 TkDisplay *dispPtr,
936 unsigned modMask)
937 {
938 assert(dispPtr);
939
940 if (dispPtr->metaModMask) {
941 if (modMask & META_MASK) {
942 modMask &= ~(ModMask)META_MASK;
943 modMask |= dispPtr->metaModMask;
944 }
945 }
946 if (dispPtr->altModMask) {
947 if (modMask & ALT_MASK) {
948 modMask &= ~(ModMask)ALT_MASK;
949 modMask |= dispPtr->altModMask;
950 }
951 }
952
953 return modMask;
954 }
955
956 static int
957 ButtonNumberFromState(
958 unsigned state)
959 {
960 if (!(state & ALL_BUTTONS)) { return 0; }
961 if (state & Button1Mask) { return 1; }
962 if (state & Button2Mask) { return 2; }
963 if (state & Button3Mask) { return 3; }
964 if (state & Button4Mask) { return 4; }
965 return 5;
966 }
967
968 static void
969 SetupPatternKey(
970 PatternTableKey *key,
971 const PatSeq *psPtr)
972 {
973 const TkPattern *patPtr;
974
975 assert(key);
976 assert(psPtr);
977
978 /* otherwise on some systems the key contains uninitialized bytes */
979 memset(key, 0, sizeof(PatternTableKey));
980
981 patPtr = psPtr->pats;
982 assert(!patPtr->info || !patPtr->name);
983
984 key->object = psPtr->object;
985 key->type = patPtr->eventType;
986 if (patPtr->info) {
987 key->detail.info = patPtr->info;
988 } else {
989 key->detail.name = patPtr->name;
990 }
991 }
992
993 /*
994 *--------------------------------------------------------------
995 *
996 * MakeListEntry --
997 *
998 * Makes new entry item for lookup table. We are using a
999 * pool of items, this avoids superfluous memory allocation/
1000 * deallocation.
1001 *
1002 * Results:
1003 * New entry item.
1004 *
1005 * Side effects:
1006 * Memory allocated.
1007 *
1008 *--------------------------------------------------------------
1009 */
1010
1011 static PSEntry *
1012 MakeListEntry(
1013 PSList *pool,
1014 PatSeq *psPtr,
1015 int needModMasks)
1016 {
1017 PSEntry *newEntry = NULL;
1018
1019 assert(pool);
1020 assert(psPtr);
1021 assert(psPtr->numPats > 0);
1022 assert(TEST_PSENTRY(psPtr));
1023
1024 if (PSList_IsEmpty(pool)) {
1025 newEntry = ckalloc(sizeof(PSEntry));
1026 newEntry->lastModMaskArr = NULL;
1027 DEBUG(countEntryItems += 1;)
1028 } else {
1029 newEntry = PSList_First(pool);
1030 PSList_RemoveHead(pool);
1031 }
1032
1033 if (!needModMasks) {
1034 PSModMaskArr_SetSize(newEntry->lastModMaskArr, 0);
1035 } else {
1036 if (PSModMaskArr_Capacity(newEntry->lastModMaskArr) < psPtr->numPats - 1) {
1037 PSModMaskArr_Resize(&newEntry->lastModMaskArr, psPtr->numPats - 1);
1038 }
1039 PSModMaskArr_SetSize(newEntry->lastModMaskArr, psPtr->numPats - 1);
1040 }
1041
1042 newEntry->psPtr = psPtr;
1043 newEntry->window = None;
1044 newEntry->expired = 0;
1045 newEntry->keepIt = 1;
1046 newEntry->count = 1;
1047 DEBUG(psPtr->owned = 0;)
1048
1049 return newEntry;
1050 }
1051
1052 /*
1053 *--------------------------------------------------------------
1054 *
1055 * GetLookupForEvent --
1056 *
1057 * Get specific pattern sequence table for given event.
1058 *
1059 * Results:
1060 * Specific pattern sequence table for given event.
1061 *
1062 * Side effects:
1063 * None.
1064 *
1065 *--------------------------------------------------------------
1066 */
1067
1068 static PSList *
1069 GetLookupForEvent(
1070 LookupTables* lookupTables,
1071 const Event *eventPtr,
1072 Tcl_Obj *object,
1073 int onlyConsiderDetailedEvents)
1074 {
1075 PatternTableKey key;
1076 Tcl_HashEntry *hPtr;
1077
1078 assert(lookupTables);
1079 assert(eventPtr);
1080
1081 /* otherwise on some systems the key contains uninitialized bytes */
1082 memset(&key, 0, sizeof(PatternTableKey));
1083
1084 if (onlyConsiderDetailedEvents) {
1085 switch (eventPtr->xev.type) {
1086 case ButtonPress: /* fallthru */
1087 case ButtonRelease: key.detail.info = eventPtr->xev.xbutton.button; break;
1088 case MotionNotify: key.detail.info = ButtonNumberFromState(eventPtr->xev.xmotion.state); break;
1089 case KeyPress: /* fallthru */
1090 case KeyRelease: key.detail.info = eventPtr->detail.info; break;
1091 case VirtualEvent: key.detail.name = eventPtr->detail.name; break;
1092 }
1093 if (!key.detail.name) {
1094 assert(!key.detail.info);
1095 return NULL;
1096 }
1097 }
1098
1099 key.object = object;
1100 key.type = eventPtr->xev.type;
1101 hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key);
1102 return hPtr ? Tcl_GetHashValue(hPtr) : NULL;
1103 }
1104
1105 /*
1106 *--------------------------------------------------------------
1107 *
1108 * ClearLookupTable --
1109 *
1110 * Clear lookup table in given binding table, but only those
1111 * bindings associated to given object. If object is NULL
1112 * then remove all entries.
1113 *
1114 * Results:
1115 * None.
1116 *
1117 * Side effects:
1118 * None.
1119 *
1120 *--------------------------------------------------------------
1121 */
1122 static void
1123 ClearLookupTable(
1124 LookupTables *lookupTables,
1125 ClientData object)
1126 {
1127 Tcl_HashSearch search;
1128 Tcl_HashEntry *hPtr;
1129 Tcl_HashEntry *nextPtr;
1130 PSList *pool = &lookupTables->entryPool;
1131
1132 assert(lookupTables);
1133
1134 for (hPtr = Tcl_FirstHashEntry(&lookupTables->listTable, &search); hPtr; hPtr = nextPtr) {
1135 PSList *psList;
1136
1137 nextPtr = Tcl_NextHashEntry(&search);
1138
1139 if (object) {
1140 const PatternTableKey *key = Tcl_GetHashKey(&lookupTables->listTable, hPtr);
1141 if (key->object != object) {
1142 continue;
1143 }
1144 Tcl_DeleteHashEntry(hPtr);
1145 }
1146
1147 psList = Tcl_GetHashValue(hPtr);
1148 PSList_Move(pool, psList);
1149 ckfree(psList);
1150 DEBUG(countListItems -= 1;)
1151 }
1152 }
1153
1154 /*
1155 *--------------------------------------------------------------
1156 *
1157 * ClearPromotionLists --
1158 *
1159 * Clear all the lists holding the promoted pattern
1160 * sequences, which belongs to given object. If object
1161 * is NULL then remove all patterns.
1162 *
1163 * Results:
1164 * None.
1165 *
1166 * Side effects:
1167 * None.
1168 *
1169 *--------------------------------------------------------------
1170 */
1171
1172 static void
1173 ClearPromotionLists(
1174 Tk_BindingTable bindPtr,
1175 ClientData object)
1176 {
1177 unsigned newArraySize = 0;
1178 unsigned i;
1179
1180 assert(bindPtr);
1181
1182 for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) {
1183 PSList *psList = PromArr_Get(bindPtr->promArr, i);
1184 ClearList(psList, &bindPtr->lookupTables.entryPool, object);
1185 if (!PSList_IsEmpty(psList)) {
1186 newArraySize = i + 1;
1187 }
1188 }
1189
1190 PromArr_SetSize(bindPtr->promArr, newArraySize);
1191 }
6541192
6551193 /*
6561194 *---------------------------------------------------------------------------
6701208 *---------------------------------------------------------------------------
6711209 */
6721210
1211 /*
1212 * Windoze compiler does not allow the definition of these static variables inside a function,
1213 * otherwise this should belong to function TkBindInit().
1214 */
1215 TCL_DECLARE_MUTEX(bindMutex);
1216 static int initialized = 0;
1217
6731218 void
6741219 TkBindInit(
6751220 TkMainInfo *mainPtr) /* The newly created application. */
6761221 {
6771222 BindInfo *bindInfoPtr;
6781223
679 if (sizeof(XEvent) < sizeof(XVirtualEvent)) {
680 Tcl_Panic("TkBindInit: virtual events can't be supported");
681 }
1224 assert(mainPtr);
1225
1226 /* otherwise virtual events can't be supported */
1227 assert(sizeof(XEvent) >= sizeof(XVirtualEvent));
1228
1229 /* type of TkPattern.info is well defined? */
1230 assert(sizeof(Info) >= sizeof(KeySym));
1231 assert(sizeof(Info) >= sizeof(unsigned));
1232
1233 /* ensure that our matching algorithm is working (when testing detail) */
1234 assert(sizeof(Detail) == sizeof(Tk_Uid));
1235
1236 /* test that constant NO_NUMBER is indeed out of integer range */
1237 assert(sizeof(NO_NUMBER) > sizeof(int));
1238 assert(((int) NO_NUMBER) == 0 && NO_NUMBER != 0);
1239
1240 /* test expected indices of Button1..Button5, otherwise our button handling is not working */
1241 assert(Button1 == 1 && Button2 == 2 && Button3 == 3 && Button4 == 4 && Button5 == 5);
1242 assert(Button2Mask == (Button1Mask << 1));
1243 assert(Button3Mask == (Button1Mask << 2));
1244 assert(Button4Mask == (Button1Mask << 3));
1245 assert(Button5Mask == (Button1Mask << 4));
1246
1247 /* test expected values of button motion masks, otherwise our button handling is not working */
1248 assert(Button1MotionMask == Button1Mask);
1249 assert(Button2MotionMask == Button2Mask);
1250 assert(Button3MotionMask == Button3Mask);
1251 assert(Button4MotionMask == Button4Mask);
1252 assert(Button5MotionMask == Button5Mask);
1253
1254 /* because we expect zero if keySym is empty */
1255 assert(NoSymbol == 0L);
1256
1257 /* this must be a union, not a struct, otherwise comparison with NULL will not work */
1258 assert(Tk_Offset(Detail, name) == Tk_Offset(Detail, info));
1259
1260 /* we use some constraints about X*Event */
1261 assert(Tk_Offset(XButtonEvent, time) == Tk_Offset(XMotionEvent, time));
1262 assert(Tk_Offset(XButtonEvent, x_root) == Tk_Offset(XMotionEvent, x_root));
1263 assert(Tk_Offset(XButtonEvent, y_root) == Tk_Offset(XMotionEvent, y_root));
1264 assert(Tk_Offset(XCreateWindowEvent, border_width) == Tk_Offset(XConfigureEvent, border_width));
1265 assert(Tk_Offset(XCreateWindowEvent, width) == Tk_Offset(XConfigureEvent, width));
1266 assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XCirculateRequestEvent, window));
1267 assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XConfigureEvent, window));
1268 assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XGravityEvent, window));
1269 assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XMapEvent, window));
1270 assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XReparentEvent, window));
1271 assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XUnmapEvent, window));
1272 assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XConfigureEvent, x));
1273 assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XGravityEvent, x));
1274 assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XConfigureEvent, y));
1275 assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XGravityEvent, y));
1276 assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XEnterWindowEvent, time));
1277 assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XLeaveWindowEvent, time));
1278 assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XKeyEvent, time));
1279 assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XButtonEvent, root));
1280 assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XCrossingEvent, root));
1281 assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XMotionEvent, root));
1282 assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XButtonEvent, state));
1283 assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XMotionEvent, state));
1284 assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XButtonEvent, subwindow));
1285 assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XCrossingEvent, subwindow));
1286 assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XMotionEvent, subwindow));
1287 assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XButtonEvent, time));
1288 assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XMotionEvent, time));
1289 assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XButtonEvent, x));
1290 assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XCrossingEvent, x));
1291 assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XMotionEvent, x));
1292 assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XButtonEvent, x_root));
1293 assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XCrossingEvent, x_root));
1294 assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XMotionEvent, x_root));
1295 assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XButtonEvent, y));
1296 assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XCrossingEvent, y));
1297 assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XMotionEvent, y));
1298 assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XButtonEvent, y_root));
1299 assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XCrossingEvent, y_root));
1300 assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XMotionEvent, y_root));
6821301
6831302 /*
6841303 * Initialize the static data structures used by the binding package. They
6921311 const ModInfo *modPtr;
6931312 const EventInfo *eiPtr;
6941313 int newEntry;
1314 unsigned i;
6951315 #ifdef REDO_KEYSYM_LOOKUP
6961316 const KeySymInfo *kPtr;
6971317
6981318 Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS);
6991319 Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS);
700 for (kPtr = keyArray; kPtr->name != NULL; kPtr++) {
1320 for (kPtr = keyArray; kPtr->name; ++kPtr) {
7011321 hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &newEntry);
7021322 Tcl_SetHashValue(hPtr, kPtr->value);
703 hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value,
704 &newEntry);
1323 hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value, &newEntry);
7051324 if (newEntry) {
7061325 Tcl_SetHashValue(hPtr, kPtr->name);
7071326 }
7081327 }
7091328 #endif /* REDO_KEYSYM_LOOKUP */
7101329
1330 for (i = 0; i < SIZE_OF_ARRAY(eventArrayIndex); ++i) {
1331 eventArrayIndex[i] = -1;
1332 }
1333 for (i = 0; i < SIZE_OF_ARRAY(eventArray); ++i) {
1334 unsigned type = eventArray[i].type;
1335 assert(type < TK_LASTEVENT);
1336 assert(type > 0 || i == SIZE_OF_ARRAY(eventArray) - 1);
1337 if (type > 0 && eventArrayIndex[type] == -1) {
1338 eventArrayIndex[type] = i;
1339 }
1340 }
1341
7111342 Tcl_InitHashTable(&modTable, TCL_STRING_KEYS);
712 for (modPtr = modArray; modPtr->name != NULL; modPtr++) {
1343 for (modPtr = modArray; modPtr->name; ++modPtr) {
7131344 hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &newEntry);
7141345 Tcl_SetHashValue(hPtr, modPtr);
7151346 }
7161347
7171348 Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS);
718 for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) {
1349 for (eiPtr = eventArray; eiPtr->name; ++eiPtr) {
7191350 hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &newEntry);
7201351 Tcl_SetHashValue(hPtr, eiPtr);
7211352 }
1353
7221354 initialized = 1;
7231355 }
7241356 Tcl_MutexUnlock(&bindMutex);
7321364 bindInfoPtr->screenInfo.curScreenIndex = -1;
7331365 bindInfoPtr->screenInfo.bindingDepth = 0;
7341366 bindInfoPtr->deleted = 0;
1367 bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();
1368 bindInfoPtr->lastEventTime = 0;
7351369 mainPtr->bindInfo = bindInfoPtr;
1370 DEBUG(countBindItems += 1;)
7361371
7371372 TkpInitializeMenuBindings(mainPtr->interp, mainPtr->bindingTable);
7381373 }
7601395 {
7611396 BindInfo *bindInfoPtr;
7621397
1398 assert(mainPtr);
1399
7631400 Tk_DeleteBindingTable(mainPtr->bindingTable);
7641401 mainPtr->bindingTable = NULL;
765
7661402 bindInfoPtr = mainPtr->bindInfo;
7671403 DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable);
7681404 bindInfoPtr->deleted = 1;
7691405 Tcl_EventuallyFree(bindInfoPtr, TCL_DYNAMIC);
7701406 mainPtr->bindInfo = NULL;
1407
1408 DEBUG(countBindItems -= 1;)
1409 assert(countBindItems > 0 || countTableItems == 0);
1410 assert(countBindItems > 0 || countEntryItems == 0);
1411 assert(countBindItems > 0 || countListItems == 0);
1412 assert(countBindItems > 0 || countSeqItems == 0);
7711413 }
7721414
7731415 /*
7891431
7901432 Tk_BindingTable
7911433 Tk_CreateBindingTable(
792 Tcl_Interp *interp) /* Interpreter to associate with the binding
793 * table: commands are executed in this
794 * interpreter. */
1434 Tcl_Interp *interp) /* Interpreter to associate with the binding table: commands are
1435 * executed in this interpreter. */
7951436 {
7961437 BindingTable *bindPtr = ckalloc(sizeof(BindingTable));
797 int i;
1438 unsigned i;
1439
1440 assert(interp);
1441 DEBUG(countTableItems += 1;)
7981442
7991443 /*
8001444 * Create and initialize a new binding table.
8011445 */
8021446
803 for (i = 0; i < EVENT_BUFFER_SIZE; i++) {
804 bindPtr->eventRing[i].type = -1;
805 }
806 bindPtr->curEvent = 0;
807 Tcl_InitHashTable(&bindPtr->patternTable,
808 sizeof(PatternTableKey)/sizeof(int));
1447 memset(bindPtr, 0, sizeof(BindingTable));
1448 for (i = 0; i < SIZE_OF_ARRAY(bindPtr->eventInfo); ++i) {
1449 bindPtr->eventInfo[i].xev.type = -1;
1450 }
1451 bindPtr->curEvent = bindPtr->eventInfo; /* do not assign NULL */
1452 bindPtr->lookupTables.number = 0;
1453 PromArr_ResizeAndClear(&bindPtr->promArr, 2);
1454 Tcl_InitHashTable(&bindPtr->lookupTables.listTable, sizeof(PatternTableKey)/sizeof(int));
1455 Tcl_InitHashTable(&bindPtr->lookupTables.patternTable, sizeof(PatternTableKey)/sizeof(int));
8091456 Tcl_InitHashTable(&bindPtr->objectTable, TCL_ONE_WORD_KEYS);
8101457 bindPtr->interp = interp;
8111458 return bindPtr;
8321479 Tk_DeleteBindingTable(
8331480 Tk_BindingTable bindPtr) /* Token for the binding table to destroy. */
8341481 {
835 PatSeq *psPtr, *nextPtr;
8361482 Tcl_HashEntry *hPtr;
8371483 Tcl_HashSearch search;
1484
1485 assert(bindPtr);
8381486
8391487 /*
8401488 * Find and delete all of the patterns associated with the binding table.
8411489 */
8421490
843 for (hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search);
844 hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
845 for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = nextPtr) {
1491 hPtr = Tcl_FirstHashEntry(&bindPtr->lookupTables.patternTable, &search);
1492 for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {
1493 PatSeq *nextPtr;
1494 PatSeq *psPtr;
1495
1496 for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
1497 assert(TEST_PSENTRY(psPtr));
8461498 nextPtr = psPtr->nextSeqPtr;
847 ckfree(psPtr->script);
848 ckfree(psPtr);
849 }
850 }
1499 FreePatSeq(psPtr);
1500 }
1501 }
1502
1503 /*
1504 * Don't forget to release lookup elements.
1505 */
1506
1507 ClearLookupTable(&bindPtr->lookupTables, NULL);
1508 ClearPromotionLists(bindPtr, NULL);
1509 PromArr_Free(&bindPtr->promArr);
1510 DEBUG(countEntryItems -= PSList_Size(&bindPtr->lookupTables.entryPool);)
1511 PSList_Traverse(&bindPtr->lookupTables.entryPool, FreePatSeqEntry);
8511512
8521513 /*
8531514 * Clean up the rest of the information associated with the binding table.
8541515 */
8551516
856 Tcl_DeleteHashTable(&bindPtr->patternTable);
1517 Tcl_DeleteHashTable(&bindPtr->lookupTables.patternTable);
1518 Tcl_DeleteHashTable(&bindPtr->lookupTables.listTable);
8571519 Tcl_DeleteHashTable(&bindPtr->objectTable);
1520
8581521 ckfree(bindPtr);
1522 DEBUG(countTableItems -= 1;)
8591523 }
8601524
1525 /*
1526 *--------------------------------------------------------------
1527 *
1528 * InsertPatSeq --
1529 *
1530 * Insert given pattern sequence into lookup table for fast
1531 * access.
1532 *
1533 * Results:
1534 * None.
1535 *
1536 * Side effects:
1537 * Memory allocated.
1538 *
1539 *--------------------------------------------------------------
1540 */
1541
1542 static void
1543 InsertPatSeq(
1544 LookupTables *lookupTables,
1545 PatSeq *psPtr)
1546 {
1547 assert(lookupTables);
1548 assert(psPtr);
1549 assert(TEST_PSENTRY(psPtr));
1550 assert(psPtr->numPats >= 1u);
1551
1552 if (!(psPtr->added)) {
1553 PatternTableKey key;
1554 Tcl_HashEntry *hPtr;
1555 int isNew;
1556 PSList *psList;
1557 PSEntry *psEntry;
1558
1559 SetupPatternKey(&key, psPtr);
1560 hPtr = Tcl_CreateHashEntry(&lookupTables->listTable, (char *) &key, &isNew);
1561
1562 if (isNew) {
1563 psList = ckalloc(sizeof(PSList));
1564 PSList_Init(psList);
1565 Tcl_SetHashValue(hPtr, psList);
1566 DEBUG(countListItems += 1;)
1567 } else {
1568 psList = Tcl_GetHashValue(hPtr);
1569 }
1570
1571 psEntry = MakeListEntry(&lookupTables->entryPool, psPtr, 0);
1572 PSList_Append(psList, psEntry);
1573 psPtr->added = 1;
1574 }
1575 }
8611576 /*
8621577 *--------------------------------------------------------------
8631578 *
8861601 Tk_CreateBinding(
8871602 Tcl_Interp *interp, /* Used for error reporting. */
8881603 Tk_BindingTable bindPtr, /* Table in which to create binding. */
889 ClientData object, /* Token for object with which binding is
890 * associated. */
891 const char *eventString, /* String describing event sequence that
892 * triggers binding. */
893 const char *script, /* Contains Tcl script to execute when
894 * binding triggers. */
895 int append) /* 0 means replace any existing binding for
896 * eventString; 1 means append to that
897 * binding. If the existing binding is for a
898 * callback function and not a Tcl command
899 * string, the existing binding will always be
900 * replaced. */
1604 ClientData object, /* Token for object with which binding is associated. */
1605 const char *eventString, /* String describing event sequence that triggers binding. */
1606 const char *script, /* Contains Tcl script to execute when binding triggers. */
1607 int append) /* 0 means replace any existing binding for eventString;
1608 * 1 means append to that binding. If the existing binding is
1609 * for a callback function and not a Tcl command string, the
1610 * existing binding will always be replaced. */
9011611 {
9021612 PatSeq *psPtr;
903 unsigned long eventMask;
904 char *newStr, *oldStr;
1613 EventMask eventMask;
1614 char *oldStr;
1615 char *newStr;
1616
1617 assert(bindPtr);
1618 assert(object);
1619 assert(eventString);
1620 assert(script);
1621
1622 psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString,
1623 !!*script, 1, &eventMask);
9051624
9061625 if (!*script) {
1626 assert(!psPtr || psPtr->added);
9071627 /* Silently ignore empty scripts -- see SF#3006842 */
908 return 1;
909 }
910 psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString,
911 1, 1, &eventMask);
912 if (psPtr == NULL) {
1628 return eventMask;
1629 }
1630 if (!psPtr) {
9131631 return 0;
9141632 }
915 if (psPtr->script == NULL) {
1633 assert(TEST_PSENTRY(psPtr));
1634
1635 if (psPtr->numPats > PromArr_Capacity(bindPtr->promArr)) {
1636 /*
1637 * We have to increase the size of array containing the lists of promoted sequences.
1638 * Normally the maximal size is 1, only in very seldom cases a bigger size is needed.
1639 * Note that for technical reasons the capacity should be one higher than the expected
1640 * maximal size.
1641 */
1642 PromArr_ResizeAndClear(&bindPtr->promArr, psPtr->numPats);
1643 }
1644
1645 if (!psPtr->script) {
1646 Tcl_HashEntry *hPtr;
9161647 int isNew;
917 Tcl_HashEntry *hPtr;
9181648
9191649 /*
9201650 * This pattern sequence was just created. Link the pattern into the
9221652 * these bindings will all automatically be deleted.
9231653 */
9241654
925 hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object,
926 &isNew);
927 if (isNew) {
928 psPtr->nextObjPtr = NULL;
929 } else {
930 psPtr->nextObjPtr = Tcl_GetHashValue(hPtr);
931 }
1655 hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, &isNew);
1656 psPtr->ptr.nextObj = isNew ? NULL : Tcl_GetHashValue(hPtr);
9321657 Tcl_SetHashValue(hPtr, psPtr);
1658 InsertPatSeq(&bindPtr->lookupTables, psPtr);
9331659 }
9341660
9351661 oldStr = psPtr->script;
936 if ((append != 0) && (oldStr != NULL)) {
937 size_t length1 = strlen(oldStr), length2 = strlen(script);
1662 if (append && oldStr) {
1663 size_t length1 = strlen(oldStr);
1664 size_t length2 = strlen(script);
9381665
9391666 newStr = ckalloc(length1 + length2 + 2);
9401667 memcpy(newStr, oldStr, length1);
9411668 newStr[length1] = '\n';
942 memcpy(newStr+length1+1, script, length2+1);
1669 memcpy(newStr + length1 + 1, script, length2 + 1);
9431670 } else {
9441671 size_t length = strlen(script);
9451672
9461673 newStr = ckalloc(length + 1);
947 memcpy(newStr, script, length+1);
948 }
949 if (oldStr != NULL) {
950 ckfree(oldStr);
951 }
1674 memcpy(newStr, script, length + 1);
1675 }
1676 ckfree(oldStr);
9521677 psPtr->script = newStr;
9531678 return eventMask;
9541679 }
9751700 Tk_DeleteBinding(
9761701 Tcl_Interp *interp, /* Used for error reporting. */
9771702 Tk_BindingTable bindPtr, /* Table in which to delete binding. */
978 ClientData object, /* Token for object with which binding is
979 * associated. */
980 const char *eventString) /* String describing event sequence that
981 * triggers binding. */
982 {
983 PatSeq *psPtr, *prevPtr;
984 unsigned long eventMask;
985 Tcl_HashEntry *hPtr;
986
987 psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString,
988 0, 1, &eventMask);
989 if (psPtr == NULL) {
1703 ClientData object, /* Token for object with which binding is associated. */
1704 const char *eventString) /* String describing event sequence that triggers binding. */
1705 {
1706 PatSeq *psPtr;
1707
1708 assert(bindPtr);
1709 assert(object);
1710 assert(eventString);
1711
1712 psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL);
1713 if (!psPtr) {
9901714 Tcl_ResetResult(interp);
991 return TCL_OK;
992 }
993
994 /*
995 * Unlink the binding from the list for its object, then from the list for
996 * its pattern.
997 */
998
999 hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);
1000 if (hPtr == NULL) {
1001 Tcl_Panic("Tk_DeleteBinding couldn't find object table entry");
1002 }
1003 prevPtr = Tcl_GetHashValue(hPtr);
1004 if (prevPtr == psPtr) {
1005 Tcl_SetHashValue(hPtr, psPtr->nextObjPtr);
10061715 } else {
1007 for ( ; ; prevPtr = prevPtr->nextObjPtr) {
1008 if (prevPtr == NULL) {
1009 Tcl_Panic("Tk_DeleteBinding couldn't find on object list");
1010 }
1011 if (prevPtr->nextObjPtr == psPtr) {
1012 prevPtr->nextObjPtr = psPtr->nextObjPtr;
1013 break;
1014 }
1015 }
1016 }
1017 prevPtr = Tcl_GetHashValue(psPtr->hPtr);
1018 if (prevPtr == psPtr) {
1019 if (psPtr->nextSeqPtr == NULL) {
1020 Tcl_DeleteHashEntry(psPtr->hPtr);
1716 Tcl_HashEntry *hPtr;
1717 PatSeq *prevPtr;
1718
1719 assert(TEST_PSENTRY(psPtr));
1720
1721 /*
1722 * Unlink the binding from the list for its object.
1723 */
1724
1725 if (!(hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) {
1726 Tcl_Panic("Tk_DeleteBinding couldn't find object table entry");
1727 }
1728 prevPtr = Tcl_GetHashValue(hPtr);
1729 if (prevPtr == psPtr) {
1730 Tcl_SetHashValue(hPtr, psPtr->ptr.nextObj);
10211731 } else {
1022 Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr);
1023 }
1024 } else {
1025 for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
1026 if (prevPtr == NULL) {
1027 Tcl_Panic("Tk_DeleteBinding couldn't find on hash chain");
1028 }
1029 if (prevPtr->nextSeqPtr == psPtr) {
1030 prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
1031 break;
1032 }
1033 }
1034 }
1035
1036 ckfree(psPtr->script);
1037 ckfree(psPtr);
1732 for ( ; ; prevPtr = prevPtr->ptr.nextObj) {
1733 if (!prevPtr) {
1734 Tcl_Panic("Tk_DeleteBinding couldn't find on object list");
1735 }
1736 if (prevPtr->ptr.nextObj == psPtr) {
1737 prevPtr->ptr.nextObj = psPtr->ptr.nextObj;
1738 break;
1739 }
1740 }
1741 }
1742
1743 RemovePatSeqFromLookup(&bindPtr->lookupTables, psPtr);
1744 RemovePatSeqFromPromotionLists(bindPtr, psPtr);
1745 DeletePatSeq(psPtr);
1746 }
1747
10381748 return TCL_OK;
10391749 }
10401750
10631773 Tk_GetBinding(
10641774 Tcl_Interp *interp, /* Interpreter for error reporting. */
10651775 Tk_BindingTable bindPtr, /* Table in which to look for binding. */
1066 ClientData object, /* Token for object with which binding is
1067 * associated. */
1068 const char *eventString) /* String describing event sequence that
1069 * triggers binding. */
1070 {
1071 PatSeq *psPtr;
1072 unsigned long eventMask;
1073
1074 psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString,
1075 0, 1, &eventMask);
1076 if (psPtr == NULL) {
1077 return NULL;
1078 }
1079 return psPtr->script;
1776 ClientData object, /* Token for object with which binding is associated. */
1777 const char *eventString) /* String describing event sequence that triggers binding. */
1778 {
1779 const PatSeq *psPtr;
1780
1781 assert(bindPtr);
1782 assert(object);
1783 assert(eventString);
1784
1785 psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL);
1786 assert(!psPtr || TEST_PSENTRY(psPtr));
1787 return psPtr ? psPtr->script : NULL;
10801788 }
10811789
10821790 /*
11051813 Tk_BindingTable bindPtr, /* Table in which to look for bindings. */
11061814 ClientData object) /* Token for object. */
11071815 {
1108 PatSeq *psPtr;
11091816 Tcl_HashEntry *hPtr;
1110 Tcl_Obj *resultObj;
1111
1112 hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);
1113 if (hPtr == NULL) {
1114 return;
1115 }
1116
1117 resultObj = Tcl_NewObj();
1118 for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL;
1119 psPtr = psPtr->nextObjPtr) {
1817
1818 assert(bindPtr);
1819 assert(object);
1820
1821 if ((hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) {
1822 const PatSeq *psPtr;
1823 Tcl_Obj *resultObj = Tcl_NewObj();
1824
11201825 /*
1121 * For each binding, output information about each of the patterns in
1122 * its sequence.
1826 * For each binding, output information about each of the patterns in its sequence.
11231827 */
11241828
1125 Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(psPtr));
1126 }
1127 Tcl_SetObjResult(interp, resultObj);
1829 for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = psPtr->ptr.nextObj) {
1830 assert(TEST_PSENTRY(psPtr));
1831 Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(psPtr));
1832 }
1833 Tcl_SetObjResult(interp, resultObj);
1834 }
1835 }
1836
1837 /*
1838 *--------------------------------------------------------------
1839 *
1840 * RemovePatSeqFromLookup --
1841 *
1842 * Remove given pattern sequence from lookup tables. This
1843 * can be required before deleting the pattern sequence.
1844 *
1845 * Results:
1846 * None.
1847 *
1848 * Side effects:
1849 * None.
1850 *
1851 *--------------------------------------------------------------
1852 */
1853
1854 static void
1855 RemovePatSeqFromLookup(
1856 LookupTables *lookupTables, /* Remove from this lookup tables. */
1857 PatSeq *psPtr) /* Remove this pattern sequence. */
1858 {
1859 PatternTableKey key;
1860 Tcl_HashEntry *hPtr;
1861
1862 assert(lookupTables);
1863 assert(psPtr);
1864
1865 SetupPatternKey(&key, psPtr);
1866
1867 if ((hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key))) {
1868 PSList *psList = Tcl_GetHashValue(hPtr);
1869 PSEntry *psEntry;
1870
1871 TK_DLIST_FOREACH(psEntry, psList) {
1872 if (psEntry->psPtr == psPtr) {
1873 psPtr->added = 0;
1874 RemoveListEntry(&lookupTables->entryPool, psEntry);
1875 return;
1876 }
1877 }
1878 }
1879
1880 assert(!"couldn't find pattern sequence in lookup");
1881 }
1882
1883 /*
1884 *--------------------------------------------------------------
1885 *
1886 * RemovePatSeqFromPromotionLists --
1887 *
1888 * Remove given pattern sequence from promotion lists. This
1889 * can be required before deleting the pattern sequence.
1890 *
1891 * Results:
1892 * None.
1893 *
1894 * Side effects:
1895 * None.
1896 *
1897 *--------------------------------------------------------------
1898 */
1899
1900 static void
1901 RemovePatSeqFromPromotionLists(
1902 Tk_BindingTable bindPtr, /* Table in which to look for bindings. */
1903 PatSeq *psPtr) /* Remove this pattern sequence. */
1904 {
1905 unsigned i;
1906
1907 assert(bindPtr);
1908 assert(psPtr);
1909
1910 for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) {
1911 PSList *psList = PromArr_Get(bindPtr->promArr, i);
1912 PSEntry *psEntry;
1913
1914 TK_DLIST_FOREACH(psEntry, psList) {
1915 if (psEntry->psPtr == psPtr) {
1916 RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);
1917 break;
1918 }
1919 }
1920 }
1921 }
1922
1923 /*
1924 *--------------------------------------------------------------
1925 *
1926 * DeletePatSeq --
1927 *
1928 * Delete given pattern sequence. Possibly it is required
1929 * to invoke RemovePatSeqFromLookup(), and RemovePatSeqFromPromotionLists()
1930 * before.
1931 *
1932 * Results:
1933 * Pointer to succeeding pattern sequence.
1934 *
1935 * Side effects:
1936 * Deallocation of memory.
1937 *
1938 *--------------------------------------------------------------
1939 */
1940
1941 static PatSeq *
1942 DeletePatSeq(
1943 PatSeq *psPtr) /* Delete this pattern sequence. */
1944 {
1945 PatSeq *prevPtr;
1946 PatSeq *nextPtr;
1947
1948 assert(psPtr);
1949 assert(!psPtr->added);
1950 assert(!psPtr->owned);
1951
1952 prevPtr = Tcl_GetHashValue(psPtr->hPtr);
1953 nextPtr = psPtr->ptr.nextObj;
1954
1955 /*
1956 * Be sure to remove each binding from its hash chain in the pattern
1957 * table. If this is the last pattern in the chain, then delete the
1958 * hash entry too.
1959 */
1960
1961 if (prevPtr == psPtr) {
1962 if (!psPtr->nextSeqPtr) {
1963 Tcl_DeleteHashEntry(psPtr->hPtr);
1964 } else {
1965 Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr);
1966 }
1967 } else {
1968 for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
1969 if (!prevPtr) {
1970 Tcl_Panic("DeletePatSeq couldn't find on hash chain");
1971 }
1972 if (prevPtr->nextSeqPtr == psPtr) {
1973 prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
1974 break;
1975 }
1976 }
1977 }
1978
1979 FreePatSeq(psPtr);
1980 return nextPtr;
11281981 }
11291982
11301983 /*
11492002 Tk_BindingTable bindPtr, /* Table in which to delete bindings. */
11502003 ClientData object) /* Token for object. */
11512004 {
1152 PatSeq *psPtr, *prevPtr;
2005 PatSeq *psPtr;
11532006 PatSeq *nextPtr;
11542007 Tcl_HashEntry *hPtr;
11552008
1156 hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);
1157 if (hPtr == NULL) {
2009 assert(bindPtr);
2010 assert(object);
2011
2012 if (!(hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) {
11582013 return;
11592014 }
1160 for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL;
1161 psPtr = nextPtr) {
1162 nextPtr = psPtr->nextObjPtr;
1163
1164 /*
1165 * Be sure to remove each binding from its hash chain in the pattern
1166 * table. If this is the last pattern in the chain, then delete the
1167 * hash entry too.
1168 */
1169
1170 prevPtr = Tcl_GetHashValue(psPtr->hPtr);
1171 if (prevPtr == psPtr) {
1172 if (psPtr->nextSeqPtr == NULL) {
1173 Tcl_DeleteHashEntry(psPtr->hPtr);
1174 } else {
1175 Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr);
1176 }
1177 } else {
1178 for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
1179 if (prevPtr == NULL) {
1180 Tcl_Panic("Tk_DeleteAllBindings couldn't find on hash chain");
1181 }
1182 if (prevPtr->nextSeqPtr == psPtr) {
1183 prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
1184 break;
1185 }
1186 }
1187 }
1188 ckfree(psPtr->script);
1189 ckfree(psPtr);
1190 }
2015
2016 /*
2017 * Don't forget to clear lookup tables.
2018 */
2019
2020 ClearLookupTable(&bindPtr->lookupTables, object);
2021 ClearPromotionLists(bindPtr, object);
2022
2023 for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
2024 assert(TEST_PSENTRY(psPtr));
2025 DEBUG(psPtr->added = 0;)
2026 nextPtr = DeletePatSeq(psPtr);
2027 }
2028
11912029 Tcl_DeleteHashEntry(hPtr);
11922030 }
11932031
12162054 *---------------------------------------------------------------------------
12172055 */
12182056
2057 /* helper function */
2058 static void
2059 ResetCounters(
2060 Event *eventInfo,
2061 unsigned eventType,
2062 Window window)
2063 {
2064 Event *curEvent;
2065
2066 assert(eventInfo);
2067 curEvent = eventInfo + eventType;
2068
2069 if (curEvent->xev.xany.window == window) {
2070 curEvent->xev.xany.window = None;
2071 eventInfo[eventType].countAny = 0;
2072 eventInfo[eventType].countDetailed = 0;
2073 }
2074 }
2075
2076 /* helper function */
2077 static int
2078 IsBetterMatch(
2079 const PatSeq *fstMatchPtr,
2080 const PatSeq *sndMatchPtr) /* this is a better match? */
2081 {
2082 int diff;
2083
2084 if (!sndMatchPtr) { return 0; }
2085 if (!fstMatchPtr) { return 1; }
2086
2087 diff = CountSpecialized(fstMatchPtr, sndMatchPtr);
2088 if (diff > 0) { return 1; }
2089 if (diff < 0) { return 0; }
2090
2091 #if PREFER_MOST_SPECIALIZED_EVENT
2092 { /* local scope */
2093 #define M (Tcl_WideUInt)1000000
2094 static const Tcl_WideUInt weight[5] = { 0, 1, M, M*M, M*M*M };
2095 #undef M
2096 Tcl_WideUInt fstCount = 0;
2097 Tcl_WideUInt sndCount = 0;
2098 unsigned i;
2099
2100 /*
2101 * Count the most high-ordered patterns.
2102 *
2103 * (This computation assumes that a sequence does not contain more than
2104 * 1,000,000 single patterns. It can be precluded that in practice this
2105 * assumption will not be violated.)
2106 */
2107
2108 for (i = 0; i < fstMatchPtr->numPats; ++i) {
2109 assert(GetCount(fstMatchPtr, i) < SIZE_OF_ARRAY(weight));
2110 fstCount += weight[GetCount(fstMatchPtr, i)];
2111 }
2112 for (i = 0; i < sndMatchPtr->numPats; ++i) {
2113 assert(GetCount(sndMatchPtr, i) < SIZE_OF_ARRAY(weight));
2114 sndCount += weight[GetCount(sndMatchPtr, i)];
2115 }
2116 if (sndCount > fstCount) { return 1; }
2117 if (sndCount < fstCount) { return 0; }
2118 }
2119 #endif
2120
2121 return sndMatchPtr->number > fstMatchPtr->number;
2122 }
2123
12192124 void
12202125 Tk_BindEvent(
12212126 Tk_BindingTable bindPtr, /* Table in which to look for bindings. */
12222127 XEvent *eventPtr, /* What actually happened. */
1223 Tk_Window tkwin, /* Window on display where event occurred
1224 * (needed in order to locate display
1225 * information). */
1226 int numObjects, /* Number of objects at *objectPtr. */
1227 ClientData *objectPtr) /* Array of one or more objects to check for a
1228 * matching binding. */
1229 {
2128 Tk_Window tkwin, /* Window on display where event occurred (needed in order to
2129 * locate display information). */
2130 int numObjects, /* Number of objects at *objArr. */
2131 ClientData *objArr) /* Array of one or more objects to check for a matching binding. */
2132 {
2133 Tcl_Interp *interp;
2134 ScreenInfo *screenPtr;
12302135 TkDisplay *dispPtr;
1231 ScreenInfo *screenPtr;
2136 TkDisplay *oldDispPtr;
2137 Event *curEvent;
2138 TkWindow *winPtr = (TkWindow *) tkwin;
12322139 BindInfo *bindInfoPtr;
1233 TkDisplay *oldDispPtr;
1234 XEvent *ringPtr;
1235 PatSeq *vMatchDetailList, *vMatchNoDetailList;
1236 int flags, oldScreen;
1237 unsigned int scriptCount;
1238 Tcl_Interp *interp;
2140 Tcl_InterpState interpState;
2141 LookupTables *physTables;
2142 PatSeq *psPtr[2];
2143 PatSeq *matchPtrBuf[32];
2144 PatSeq **matchPtrArr = matchPtrBuf;
2145 PSList *psl[2];
12392146 Tcl_DString scripts;
1240 Tcl_InterpState interpState;
1241 Detail detail;
1242 char *p, *end;
1243 TkWindow *winPtr = (TkWindow *) tkwin;
1244 PatternTableKey key;
2147 const char *p;
2148 const char *end;
2149 unsigned scriptCount;
2150 int oldScreen;
2151 unsigned flags;
2152 unsigned arraySize;
2153 unsigned newArraySize;
2154 unsigned i, k;
2155
2156 assert(bindPtr);
2157 assert(eventPtr);
2158 assert(tkwin);
2159 assert(numObjects >= 0);
12452160
12462161 /*
12472162 * Ignore events on windows that don't have names: these are windows like
12482163 * wrapper windows that shouldn't be visible to the application.
12492164 */
12502165
1251 if (winPtr->pathName == NULL) {
2166 if (!winPtr->pathName) {
12522167 return;
12532168 }
2169
2170 flags = flagArray[eventPtr->type];
2171
2172 /*
2173 * Ignore event types which are not in flagArray and all zeroes there.
2174 */
2175
2176 if (eventPtr->type >= TK_LASTEVENT || !flags) {
2177 return;
2178 }
2179
2180 if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
2181 bindPtr->curModMask = eventPtr->xkey.state;
2182 } else if (flags & CROSSING) {
2183 bindPtr->curModMask = eventPtr->xcrossing.state;
2184 }
2185
2186 dispPtr = ((TkWindow *) tkwin)->dispPtr;
2187 bindInfoPtr = winPtr->mainPtr->bindInfo;
2188 curEvent = bindPtr->eventInfo + eventPtr->type;
12542189
12552190 /*
12562191 * Ignore the event completely if it is an Enter, Leave, FocusIn, or
12592194 * children to visible to bindings on the parent: this would cause
12602195 * problems for mega-widgets, since the internal structure of a
12612196 * mega-widget isn't supposed to be visible to people watching the parent.
2197 *
2198 * Furthermore we have to compute current time, needed for "event generate".
12622199 */
12632200
1264 if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) {
2201 switch (eventPtr->type) {
2202 case EnterNotify:
2203 case LeaveNotify:
2204 if (eventPtr->xcrossing.time) {
2205 bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();
2206 bindInfoPtr->lastEventTime = eventPtr->xcrossing.time;
2207 }
12652208 if (eventPtr->xcrossing.detail == NotifyInferior) {
12662209 return;
12672210 }
1268 }
1269 if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
2211 break;
2212 case FocusIn:
2213 case FocusOut:
12702214 if (eventPtr->xfocus.detail == NotifyInferior) {
12712215 return;
12722216 }
2217 break;
2218 case KeyPress:
2219 case KeyRelease: {
2220 int reset = 1;
2221
2222 if (eventPtr->xkey.time) {
2223 bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();
2224 bindInfoPtr->lastEventTime = eventPtr->xkey.time;
2225 }
2226 /* modifier keys should not influence button events */
2227 for (i = 0; i < (unsigned) dispPtr->numModKeyCodes; ++i) {
2228 if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {
2229 reset = 0;
2230 }
2231 }
2232 if (reset) {
2233 /* reset repetition count for button events */
2234 bindPtr->eventInfo[ButtonPress].countAny = 0;
2235 bindPtr->eventInfo[ButtonPress].countDetailed = 0;
2236 bindPtr->eventInfo[ButtonRelease].countAny = 0;
2237 bindPtr->eventInfo[ButtonRelease].countDetailed = 0;
2238 }
2239 break;
2240 }
2241 case ButtonPress:
2242 case ButtonRelease:
2243 /* reset repetition count for key events */
2244 bindPtr->eventInfo[KeyPress].countAny = 0;
2245 bindPtr->eventInfo[KeyPress].countDetailed = 0;
2246 bindPtr->eventInfo[KeyRelease].countAny = 0;
2247 bindPtr->eventInfo[KeyRelease].countDetailed = 0;
2248 /* fallthru */
2249 case MotionNotify:
2250 if (eventPtr->xmotion.time) {
2251 bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();
2252 bindInfoPtr->lastEventTime = eventPtr->xmotion.time;
2253 }
2254 break;
2255 case PropertyNotify:
2256 if (eventPtr->xproperty.time) {
2257 bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs();
2258 bindInfoPtr->lastEventTime = eventPtr->xproperty.time;
2259 }
2260 break;
2261 case DestroyNotify:
2262 ResetCounters(bindPtr->eventInfo, KeyPress, eventPtr->xany.window);
2263 ResetCounters(bindPtr->eventInfo, KeyRelease, eventPtr->xany.window);
2264 ResetCounters(bindPtr->eventInfo, ButtonPress, eventPtr->xany.window);
2265 ResetCounters(bindPtr->eventInfo, ButtonRelease, eventPtr->xany.window);
2266 break;
12732267 }
12742268
12752269 /*
1276 * Ignore event types which are not in flagArray and all zeroes there.
1277 * Most notably, NoExpose events can fill the ring buffer and disturb
1278 * (thus masking out) event sequences of interest.
2270 * Now check whether this is a repeating event (multi-click, repeated key press, and so on).
12792271 */
12802272
1281 if ((eventPtr->type >= TK_LASTEVENT) || !flagArray[eventPtr->type]) {
1282 return;
1283 }
1284
1285 dispPtr = ((TkWindow *) tkwin)->dispPtr;
1286 bindInfoPtr = winPtr->mainPtr->bindInfo;
2273 /* NOTE: if curEvent is not yet set, then the following cannot match: */
2274 if (curEvent->xev.xany.window == eventPtr->xany.window) {
2275 switch (eventPtr->type) {
2276 case KeyPress:
2277 case KeyRelease:
2278 if (MatchEventRepeat(&curEvent->xev, eventPtr)) {
2279 if (curEvent->xev.xkey.keycode == eventPtr->xkey.keycode) {
2280 ++curEvent->countDetailed;
2281 } else {
2282 curEvent->countDetailed = 1;
2283 }
2284 ++curEvent->countAny;
2285 } else {
2286 curEvent->countAny = curEvent->countDetailed = 1;
2287 }
2288 break;
2289 case ButtonPress:
2290 case ButtonRelease:
2291 if (MatchEventNearby(&curEvent->xev, eventPtr)) {
2292 if (curEvent->xev.xbutton.button == eventPtr->xbutton.button) {
2293 ++curEvent->countDetailed;
2294 } else {
2295 curEvent->countDetailed = 1;
2296 }
2297 ++curEvent->countAny;
2298 } else {
2299 curEvent->countAny = curEvent->countDetailed = 1;
2300 }
2301 break;
2302 case EnterNotify:
2303 case LeaveNotify:
2304 if (TestNearbyTime(eventPtr->xcrossing.time, curEvent->xev.xcrossing.time)) {
2305 ++curEvent->countAny;
2306 } else {
2307 curEvent->countAny = 1;
2308 }
2309 break;
2310 case PropertyNotify:
2311 if (TestNearbyTime(eventPtr->xproperty.time, curEvent->xev.xproperty.time)) {
2312 ++curEvent->countAny;
2313 } else {
2314 curEvent->countAny = 1;
2315 }
2316 break;
2317 default:
2318 ++curEvent->countAny;
2319 break;
2320 }
2321 } else {
2322 curEvent->countAny = curEvent->countDetailed = 1;
2323 }
12872324
12882325 /*
1289 * Add the new event to the ring of saved events for the binding table.
1290 * Two tricky points:
1291 *
1292 * 1. Combine consecutive MotionNotify events. Do this by putting the new
1293 * event *on top* of the previous event.
1294 * 2. If a modifier key is held down, it auto-repeats to generate
1295 * continuous KeyPress and KeyRelease events. These can flush the event
1296 * ring so that valuable information is lost (such as repeated button
1297 * clicks). To handle this, check for the special case of a modifier
1298 * KeyPress arriving when the previous two events are a KeyRelease and
1299 * KeyPress of the same key. If this happens, mark the most recent
1300 * event (the KeyRelease) invalid and put the new event on top of the
1301 * event before that (the KeyPress).
2326 * Now update the details.
13022327 */
13032328
1304 if ((eventPtr->type == MotionNotify)
1305 && (bindPtr->eventRing[bindPtr->curEvent].type == MotionNotify)) {
1306 /*
1307 * Don't advance the ring pointer.
1308 */
1309 } else if (eventPtr->type == KeyPress) {
1310 int i;
1311
1312 for (i = 0; ; i++) {
1313 if (i >= dispPtr->numModKeyCodes) {
1314 goto advanceRingPointer;
1315 }
1316 if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {
1317 break;
1318 }
1319 }
1320 ringPtr = &bindPtr->eventRing[bindPtr->curEvent];
1321 if ((ringPtr->type != KeyRelease)
1322 || (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) {
1323 goto advanceRingPointer;
1324 }
1325 if (bindPtr->curEvent <= 0) {
1326 i = EVENT_BUFFER_SIZE - 1;
2329 curEvent->xev = *eventPtr;
2330 if (flags & KEY) {
2331 curEvent->detail.info = TkpGetKeySym(dispPtr, eventPtr);
2332 } else if (flags & BUTTON) {
2333 curEvent->detail.info = eventPtr->xbutton.button;
2334 } else if (flags & MOTION) {
2335 curEvent->detail.info = ButtonNumberFromState(eventPtr->xmotion.state);
2336 } else if (flags & VIRTUAL) {
2337 curEvent->detail.name = ((XVirtualEvent *) eventPtr)->name;
2338 }
2339
2340 bindPtr->curEvent = curEvent;
2341 physTables = &bindPtr->lookupTables;
2342 scriptCount = 0;
2343 arraySize = 0;
2344 Tcl_DStringInit(&scripts);
2345
2346 if ((size_t) numObjects > SIZE_OF_ARRAY(matchPtrBuf)) {
2347 /* it's unrealistic that the buffer size is too small, but who knows? */
2348 matchPtrArr = ckalloc(numObjects*sizeof(matchPtrArr[0]));
2349 }
2350 memset(matchPtrArr, 0, numObjects*sizeof(matchPtrArr[0]));
2351
2352 if (!PromArr_IsEmpty(bindPtr->promArr)) {
2353 for (k = 0; k < (unsigned) numObjects; ++k) {
2354 psl[1] = PromArr_Last(bindPtr->promArr);
2355 psl[0] = psl[1] - 1;
2356
2357 /*
2358 * Loop over all promoted bindings, finding the longest matching one.
2359 *
2360 * Note that we must process all lists, because all matching patterns
2361 * have to be promoted. Normally at most one list will be processed, and
2362 * usually this list only contains one or two patterns.
2363 */
2364
2365 for (i = PromArr_Size(bindPtr->promArr); i > 0; --i, --psl[0], --psl[1]) {
2366 psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psl[1], i, curEvent, objArr[k], NULL);
2367
2368 if (IsBetterMatch(matchPtrArr[k], psPtr[0])) {
2369 /* we will process it later, because we still may find a pattern with better match */
2370 matchPtrArr[k] = psPtr[0];
2371 }
2372 if (!PSList_IsEmpty(psl[1])) {
2373 /* we have promoted sequences, adjust array size */
2374 arraySize = Max(i + 1, arraySize);
2375 }
2376 }
2377 }
2378 }
2379
2380 /*
2381 * 1. Look for bindings for the specific detail (button and key events).
2382 * 2. Look for bindings without detail.
2383 */
2384
2385 for (k = 0; k < (unsigned) numObjects; ++k) {
2386 PSList *psSuccList = PromArr_First(bindPtr->promArr);
2387 PatSeq *bestPtr;
2388
2389 psl[0] = GetLookupForEvent(physTables, curEvent, objArr[k], 1);
2390 psl[1] = GetLookupForEvent(physTables, curEvent, objArr[k], 0);
2391
2392 assert(psl[0] == NULL || psl[0] != psl[1]);
2393
2394 psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psSuccList, 0, curEvent, objArr[k], NULL);
2395 psPtr[1] = MatchPatterns(dispPtr, bindPtr, psl[1], psSuccList, 0, curEvent, objArr[k], NULL);
2396
2397 if (!PSList_IsEmpty(psSuccList)) {
2398 /* we have promoted sequences, adjust array size */
2399 arraySize = Max(1u, arraySize);
2400 }
2401
2402 bestPtr = psPtr[0] ? psPtr[0] : psPtr[1];
2403
2404 if (matchPtrArr[k]) {
2405 if (IsBetterMatch(matchPtrArr[k], bestPtr)) {
2406 matchPtrArr[k] = bestPtr;
2407 } else {
2408 /*
2409 * We've already found a higher level match, nevertheless it was required to
2410 * process the level zero patterns because of possible promotions.
2411 */
2412 }
2413 /*
2414 * Now we have to catch up the processing of the script.
2415 */
13272416 } else {
1328 i = bindPtr->curEvent - 1;
1329 }
1330 ringPtr = &bindPtr->eventRing[i];
1331 if ((ringPtr->type != KeyPress)
1332 || (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) {
1333 goto advanceRingPointer;
1334 }
1335 bindPtr->eventRing[bindPtr->curEvent].type = -1;
1336 bindPtr->curEvent = i;
1337 } else {
1338
1339 advanceRingPointer:
1340 bindPtr->curEvent++;
1341 if (bindPtr->curEvent >= EVENT_BUFFER_SIZE) {
1342 bindPtr->curEvent = 0;
1343 }
1344 }
1345 ringPtr = &bindPtr->eventRing[bindPtr->curEvent];
1346 memcpy(ringPtr, eventPtr, sizeof(XEvent));
1347 detail.clientData = 0;
1348 flags = flagArray[ringPtr->type];
1349 if (flags & KEY) {
1350 detail.keySym = TkpGetKeySym(dispPtr, ringPtr);
1351 if (detail.keySym == NoSymbol) {
1352 detail.keySym = 0;
1353 }
1354 } else if (flags & BUTTON) {
1355 detail.button = ringPtr->xbutton.button;
1356 } else if (flags & VIRTUAL) {
1357 detail.name = ((XVirtualEvent *) ringPtr)->name;
1358 }
1359 bindPtr->detailRing[bindPtr->curEvent] = detail;
2417 /*
2418 * We have to look whether we can find a better match in virtual table, provided that we
2419 * don't have a higher level match.
2420 */
2421
2422 matchPtrArr[k] = bestPtr;
2423
2424 if (eventPtr->type != VirtualEvent) {
2425 LookupTables *virtTables = &bindInfoPtr->virtualEventTable.lookupTables;
2426 PatSeq *matchPtr = matchPtrArr[k];
2427 PatSeq *mPtr;
2428 PSList *psl[2];
2429
2430 /*
2431 * Note that virtual events cannot promote.
2432 */
2433
2434 psl[0] = GetLookupForEvent(virtTables, curEvent, NULL, 1);
2435 psl[1] = GetLookupForEvent(virtTables, curEvent, NULL, 0);
2436
2437 assert(psl[0] == NULL || psl[0] != psl[1]);
2438
2439 mPtr = MatchPatterns(dispPtr, bindPtr, psl[0], NULL, 0, curEvent, objArr[k], &matchPtr);
2440 if (mPtr) {
2441 matchPtrArr[k] = matchPtr;
2442 matchPtr = mPtr;
2443 }
2444 if (MatchPatterns(dispPtr, bindPtr, psl[1], NULL, 0, curEvent, objArr[k], &matchPtr)) {
2445 matchPtrArr[k] = matchPtr;
2446 }
2447 }
2448 }
2449
2450 if (matchPtrArr[k]) {
2451 ExpandPercents(winPtr, matchPtrArr[k]->script, curEvent, scriptCount++, &scripts);
2452 /* nul is added to the scripts string to separate the various scripts */
2453 Tcl_DStringAppend(&scripts, "", 1);
2454 }
2455 }
2456
2457 PromArr_SetSize(bindPtr->promArr, arraySize);
13602458
13612459 /*
1362 * Find out if there are any virtual events that correspond to this
1363 * physical event (or sequence of physical events).
2460 * Remove expired pattern sequences.
13642461 */
13652462
1366 vMatchDetailList = NULL;
1367 vMatchNoDetailList = NULL;
1368 memset(&key, 0, sizeof(key));
1369
1370 if (ringPtr->type != VirtualEvent) {
1371 Tcl_HashTable *veptPtr = &bindInfoPtr->virtualEventTable.patternTable;
1372 Tcl_HashEntry *hPtr;
1373
1374 key.object = NULL;
1375 key.type = ringPtr->type;
1376 key.detail = detail;
1377
1378 hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key);
1379 if (hPtr != NULL) {
1380 vMatchDetailList = Tcl_GetHashValue(hPtr);
1381 }
1382
1383 if (key.detail.clientData != 0) {
1384 key.detail.clientData = 0;
1385 hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key);
1386 if (hPtr != NULL) {
1387 vMatchNoDetailList = Tcl_GetHashValue(hPtr);
1388 }
1389 }
1390 }
1391
1392 /*
1393 * Loop over all the binding tags, finding the binding script or callback
1394 * for each one. Append all of the binding scripts, with %-sequences
1395 * expanded, to "scripts", with null characters separating the scripts for
1396 * each object.
1397 */
1398
1399 scriptCount = 0;
1400 Tcl_DStringInit(&scripts);
1401
1402 for ( ; numObjects > 0; numObjects--, objectPtr++) {
1403 PatSeq *matchPtr = NULL, *sourcePtr = NULL;
1404 Tcl_HashEntry *hPtr;
1405
1406 /*
1407 * Match the new event against those recorded in the pattern table,
1408 * saving the longest matching pattern. For events with details
1409 * (button and key events), look for a binding for the specific key or
1410 * button. First see if the event matches a physical event that the
1411 * object is interested in, then look for a virtual event.
1412 */
1413
1414 key.object = *objectPtr;
1415 key.type = ringPtr->type;
1416 key.detail = detail;
1417 hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key);
1418 if (hPtr != NULL) {
1419 matchPtr = MatchPatterns(dispPtr, bindPtr, Tcl_GetHashValue(hPtr),
1420 matchPtr, NULL, &sourcePtr);
1421 }
1422
1423 if (vMatchDetailList != NULL) {
1424 matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchDetailList,
1425 matchPtr, objectPtr, &sourcePtr);
1426 }
1427
1428 /*
1429 * If no match was found, look for a binding for all keys or buttons
1430 * (detail of 0). Again, first match on a virtual event.
1431 */
1432
1433 if ((detail.clientData != 0) && (matchPtr == NULL)) {
1434 key.detail.clientData = 0;
1435 hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key);
1436 if (hPtr != NULL) {
1437 matchPtr = MatchPatterns(dispPtr, bindPtr,
1438 Tcl_GetHashValue(hPtr), matchPtr, NULL, &sourcePtr);
1439 }
1440
1441 if (vMatchNoDetailList != NULL) {
1442 matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchNoDetailList,
1443 matchPtr, objectPtr, &sourcePtr);
1444 }
1445 }
1446
1447 if (matchPtr != NULL) {
1448 ExpandPercents(winPtr, sourcePtr->script, eventPtr,
1449 detail.keySym, scriptCount++, &scripts);
2463 for (i = 0, newArraySize = 0; i < arraySize; ++i) {
2464 PSList *psList = PromArr_Get(bindPtr->promArr, i);
2465 PSEntry *psEntry;
2466 PSEntry *psNext;
2467
2468 for (psEntry = PSList_First(psList); psEntry; psEntry = psNext) {
2469 const TkPattern *patPtr;
2470
2471 assert(i + 1 < psEntry->psPtr->numPats);
2472
2473 psNext = PSList_Next(psEntry);
2474 patPtr = &psEntry->psPtr->pats[i + 1];
14502475
14512476 /*
1452 * A "" is added to the scripts string to separate the various
1453 * scripts that should be invoked.
2477 * We have to remove the following entries from promotion list (but
2478 * only if we don't want to keep it):
2479 * ------------------------------------------------------------------
2480 * 1) It is marked as expired (see MatchPatterns()).
2481 * 2) If we have a Key event, and current entry is matching a Button.
2482 * 3) If we have a Button event, and current entry is matching a Key.
2483 * 4) If we have a detailed event, current entry it is also detailed,
2484 * we have matching event types, but the details are different.
2485 * 5) Current entry has been matched with a different window.
14542486 */
14552487
1456 Tcl_DStringAppend(&scripts, "", 1);
1457 }
1458 }
2488 if (psEntry->keepIt) {
2489 assert(!psEntry->expired);
2490 psEntry->keepIt = 0;
2491 } else if (psEntry->expired
2492 || psEntry->window != curEvent->xev.xany.window
2493 || (patPtr->info
2494 && curEvent->detail.info
2495 && patPtr->eventType == (unsigned) curEvent->xev.type
2496 && patPtr->info != curEvent->detail.info)) {
2497 RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);
2498 } else {
2499 switch (patPtr->eventType) {
2500 case ButtonPress:
2501 case ButtonRelease:
2502 if (curEvent->xev.type == KeyPress || curEvent->xev.type == KeyRelease) {
2503 RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);
2504 }
2505 break;
2506 case KeyPress:
2507 case KeyRelease:
2508 if (curEvent->xev.type == ButtonPress || curEvent->xev.type == ButtonRelease) {
2509 RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry);
2510 }
2511 break;
2512 }
2513 }
2514 }
2515
2516 if (!PSList_IsEmpty(psList)) {
2517 /* we still have promoted sequences, adjust array size */
2518 newArraySize = Max(i + 1, newArraySize);
2519 }
2520 }
2521
2522 PromArr_SetSize(bindPtr->promArr, newArraySize);
2523
2524 if (matchPtrArr != matchPtrBuf) {
2525 ckfree(matchPtrArr);
2526 }
2527
14592528 if (Tcl_DStringLength(&scripts) == 0) {
1460 return;
2529 return; /* nothing to do */
14612530 }
14622531
14632532 /*
14882557 screenPtr = &bindInfoPtr->screenInfo;
14892558 oldDispPtr = screenPtr->curDispPtr;
14902559 oldScreen = screenPtr->curScreenIndex;
1491 if ((dispPtr != screenPtr->curDispPtr)
1492 || (Tk_ScreenNumber(tkwin) != screenPtr->curScreenIndex)) {
2560
2561 if (dispPtr != screenPtr->curDispPtr || Tk_ScreenNumber(tkwin) != screenPtr->curScreenIndex) {
14932562 screenPtr->curDispPtr = dispPtr;
14942563 screenPtr->curScreenIndex = Tk_ScreenNumber(tkwin);
14952564 ChangeScreen(interp, dispPtr->name, screenPtr->curScreenIndex);
14962565 }
1497
1498 p = Tcl_DStringValue(&scripts);
1499 end = p + Tcl_DStringLength(&scripts);
15002566
15012567 /*
15022568 * Be careful when dereferencing screenPtr or bindInfoPtr. If we evaluate
15052571 */
15062572
15072573 Tcl_Preserve(bindInfoPtr);
1508 while (p < end) {
1509 int len = (int) strlen(p);
2574
2575 for (p = Tcl_DStringValue(&scripts), end = p + Tcl_DStringLength(&scripts); p < end; ) {
2576 unsigned len = strlen(p);
15102577 int code;
15112578
15122579 if (!bindInfoPtr->deleted) {
1513 screenPtr->bindingDepth++;
2580 ++screenPtr->bindingDepth;
15142581 }
15152582 Tcl_AllowExceptions(interp);
15162583
15182585 p += len + 1;
15192586
15202587 if (!bindInfoPtr->deleted) {
1521 screenPtr->bindingDepth--;
1522 }
1523 if (code != TCL_OK) {
1524 if (code == TCL_CONTINUE) {
1525 /*
1526 * Do nothing: just go on to the next command.
1527 */
1528 } else if (code == TCL_BREAK) {
1529 break;
1530 } else {
2588 --screenPtr->bindingDepth;
2589 }
2590 if (code != TCL_OK && code != TCL_CONTINUE) {
2591 if (code != TCL_BREAK) {
15312592 Tcl_AddErrorInfo(interp, "\n (command bound to event)");
15322593 Tcl_BackgroundException(interp, code);
1533 break;
1534 }
1535 }
1536 }
1537
1538 if (!bindInfoPtr->deleted && (screenPtr->bindingDepth != 0)
1539 && ((oldDispPtr != screenPtr->curDispPtr)
1540 || (oldScreen != screenPtr->curScreenIndex))) {
2594 }
2595 break;
2596 }
2597 }
2598
2599 if (!bindInfoPtr->deleted
2600 && screenPtr->bindingDepth > 0
2601 && (oldDispPtr != screenPtr->curDispPtr || oldScreen != screenPtr->curScreenIndex)) {
15412602 /*
15422603 * Some other binding script is currently executing, but its screen is
15432604 * no longer current. Change the current display back again.
15442605 */
1545
15462606 screenPtr->curDispPtr = oldDispPtr;
15472607 screenPtr->curScreenIndex = oldScreen;
15482608 ChangeScreen(interp, oldDispPtr->name, oldScreen);
15492609 }
1550 (void) Tcl_RestoreInterpState(interp, interpState);
2610 Tcl_RestoreInterpState(interp, interpState);
15512611 Tcl_DStringFree(&scripts);
1552
15532612 Tcl_Release(bindInfoPtr);
15542613 }
15552614
15582617 *
15592618 * MatchPatterns --
15602619 *
1561 * Given a list of pattern sequences and a list of recent events, return
1562 * the pattern sequence that best matches the event list, if there is
2620 * Given a list of pattern sequences and the recent event, return
2621 * the pattern sequence that best matches this event, if there is
15632622 * one.
15642623 *
1565 * This function is used in two different ways. In the simplest use,
1566 * "object" is NULL and psPtr is a list of pattern sequences, each of
1567 * which corresponds to a binding. In this case, the function finds the
1568 * pattern sequences that match the event list and returns the most
1569 * specific of those, if there is more than one.
1570 *
1571 * In the second case, psPtr is a list of pattern sequences, each of
1572 * which corresponds to a definition for a virtual binding. In order for
1573 * one of these sequences to "match", it must match the events (as above)
1574 * but in addition there must be a binding for its associated virtual
1575 * event on the current object. The "object" argument indicates which
1576 * object the binding must be for.
1577 *
15782624 * Results:
1579
1580 * The return value is NULL if bestPtr is NULL and no pattern matches the
1581 * recent events from bindPtr. Otherwise the return value is the most
1582 * specific pattern sequence among bestPtr and all those at psPtr that
1583 * match the event list and object. If a pattern sequence other than
1584 * bestPtr is returned, then *bestCommandPtr is filled in with a pointer
1585 * to the command from the best sequence.
2625 *
2626 * The return value is NULL if no match is found. Otherwise the
2627 * return value is the most specific pattern sequence among all
2628 * those that match the event table.
15862629 *
15872630 * Side effects:
15882631 * None.
15892632 *
15902633 *----------------------------------------------------------------------
15912634 */
2635
2636 /* helper function */
2637 static int
2638 VirtPatIsBound(
2639 Tk_BindingTable bindPtr, /* Table in which to look for bindings. */
2640 PatSeq *psPtr, /* Test this pattern. */
2641 ClientData object, /* Check for this binding tag. */
2642 PatSeq **physPtrPtr) /* Input: the best physical event.
2643 * Output: the physical event associated with matching virtual event. */
2644 {
2645 PatternTableKey key;
2646 const struct VirtOwners *owners;
2647 unsigned i;
2648
2649 assert(bindPtr);
2650 assert(psPtr);
2651 assert(!psPtr->object);
2652 assert(physPtrPtr);
2653
2654 if (*physPtrPtr) {
2655 const TkPattern *physPatPtr = (*physPtrPtr)->pats;
2656 const TkPattern *virtPatPtr = psPtr->pats;
2657
2658 if (physPatPtr->info || !virtPatPtr->info) {
2659 if (IsSubsetOf(virtPatPtr->modMask, physPatPtr->modMask)) {
2660 return 0; /* we cannot surpass this match */
2661 }
2662 }
2663 }
2664
2665 /* otherwise on some systems the key contains uninitialized bytes */
2666 memset(&key, 0, sizeof(key));
2667
2668 key.object = object;
2669 key.type = VirtualEvent;
2670 owners = psPtr->ptr.owners;
2671
2672 for (i = 0; i < VirtOwners_Size(owners); ++i) {
2673 Tcl_HashEntry *hPtr = VirtOwners_Get(owners, i);
2674
2675 key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr, hPtr);
2676
2677 if ((hPtr = Tcl_FindHashEntry(&bindPtr->lookupTables.patternTable, (char *) &key))) {
2678 /* The physical event matches this virtual event's definition. */
2679 *physPtrPtr = (PatSeq *) Tcl_GetHashValue(hPtr);
2680 return 1;
2681 }
2682 }
2683
2684 return 0;
2685 }
2686
2687 /* helper function */
2688 static int
2689 Compare(
2690 const PatSeq *fstMatchPtr,
2691 const PatSeq *sndMatchPtr) /* most recent match */
2692 {
2693 int diff;
2694
2695 if (!fstMatchPtr) { return +1; }
2696 assert(sndMatchPtr);
2697 diff = CountSpecialized(fstMatchPtr, sndMatchPtr);
2698 return diff ? diff : (int) sndMatchPtr->count - (int) fstMatchPtr->count;
2699 }
2700
2701 /* helper function */
2702 static int
2703 CompareModMasks(
2704 const PSModMaskArr *fstModMaskArr,
2705 const PSModMaskArr *sndModMaskArr,
2706 ModMask fstModMask,
2707 ModMask sndModMask)
2708 {
2709 int fstCount = 0;
2710 int sndCount = 0;
2711 int i;
2712
2713 if (PSModMaskArr_IsEmpty(fstModMaskArr)) {
2714 if (!PSModMaskArr_IsEmpty(sndModMaskArr)) {
2715 for (i = PSModMaskArr_Size(sndModMaskArr) - 1; i >= 0; --i) {
2716 if (*PSModMaskArr_Get(sndModMaskArr, i)) {
2717 ++sndCount;
2718 }
2719 }
2720 }
2721 } else if (PSModMaskArr_IsEmpty(sndModMaskArr)) {
2722 for (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) {
2723 if (*PSModMaskArr_Get(fstModMaskArr, i)) {
2724 ++fstCount;
2725 }
2726 }
2727 } else {
2728 assert(PSModMaskArr_Size(fstModMaskArr) == PSModMaskArr_Size(sndModMaskArr));
2729
2730 for (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) {
2731 ModMask fstModMask = *PSModMaskArr_Get(fstModMaskArr, i);
2732 ModMask sndModMask = *PSModMaskArr_Get(sndModMaskArr, i);
2733
2734 if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
2735 if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; }
2736 }
2737 }
2738
2739 /* Finally compare modifier masks of last pattern. */
2740
2741 if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
2742 if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; }
2743
2744 return fstCount - sndCount;
2745 }
15922746
15932747 static PatSeq *
15942748 MatchPatterns(
15952749 TkDisplay *dispPtr, /* Display from which the event came. */
1596 BindingTable *bindPtr, /* Information about binding table, such as
1597 * ring of recent events. */
1598 PatSeq *psPtr, /* List of pattern sequences. */
1599 PatSeq *bestPtr, /* The best match seen so far, from a previous
1600 * call to this function. NULL means no prior
1601 * best match. */
1602 ClientData *objectPtr, /* If NULL, the sequences at psPtr correspond
1603 * to "normal" bindings. If non-NULL, the
1604 * sequences at psPtr correspond to virtual
1605 * bindings; in order to match each sequence
1606 * must correspond to a virtual binding for
1607 * which a binding exists for object in
1608 * bindPtr. */
1609 PatSeq **sourcePtrPtr) /* Filled with the pattern sequence that
1610 * contains the eventProc and clientData
1611 * associated with the best match. If this
1612 * differs from the return value, it is the
1613 * virtual event that most closely matched the
1614 * return value (a physical event). Not
1615 * modified unless a result other than bestPtr
1616 * is returned. */
1617 {
1618 PatSeq *matchPtr, *bestSourcePtr, *sourcePtr;
1619
1620 bestSourcePtr = *sourcePtrPtr;
1621
1622 /*
1623 * Iterate over all the pattern sequences.
1624 */
1625
1626 for ( ; psPtr != NULL; psPtr = psPtr->nextSeqPtr) {
1627 XEvent *eventPtr = &bindPtr->eventRing[bindPtr->curEvent];
1628 Detail *detailPtr = &bindPtr->detailRing[bindPtr->curEvent];
1629 TkPattern *patPtr = psPtr->pats;
1630 Window window = eventPtr->xany.window;
1631 int patCount, ringCount, flags, state, modMask, i;
1632
1633 /*
1634 * Iterate over all the patterns in a sequence to be sure that they
1635 * all match.
1636 */
1637
1638 patCount = psPtr->numPats;
1639 ringCount = EVENT_BUFFER_SIZE;
1640 while (patCount > 0) {
1641 if (ringCount <= 0) {
1642 goto nextSequence;
1643 }
1644 if (eventPtr->xany.type != patPtr->eventType) {
1645 /*
1646 * Most of the event types are considered superfluous in that
1647 * they are ignored if they occur in the middle of a pattern
1648 * sequence and have mismatching types. The only ones that
1649 * cannot be ignored are ButtonPress and ButtonRelease events
1650 * (if the next event in the pattern is a KeyPress or
1651 * KeyRelease) and KeyPress and KeyRelease events (if the next
1652 * pattern event is a ButtonPress or ButtonRelease). Here are
1653 * some tricky cases to consider:
1654 * 1. Double-Button or Double-Key events.
1655 * 2. Double-ButtonRelease or Double-KeyRelease events.
1656 * 3. The arrival of various events like Enter and Leave and
1657 * FocusIn and GraphicsExpose between two button presses or
1658 * key presses.
1659 * 4. Modifier keys like Shift and Control shouldn't generate
1660 * conflicts with button events.
1661 */
1662
1663 if ((patPtr->eventType == KeyPress)
1664 || (patPtr->eventType == KeyRelease)) {
1665 if ((eventPtr->xany.type == ButtonPress)
1666 || (eventPtr->xany.type == ButtonRelease)) {
1667 goto nextSequence;
1668 }
1669 } else if ((patPtr->eventType == ButtonPress)
1670 || (patPtr->eventType == ButtonRelease)) {
1671 if ((eventPtr->xany.type == KeyPress)
1672 || (eventPtr->xany.type == KeyRelease)) {
2750 Tk_BindingTable bindPtr, /* Table in which to look for bindings. */
2751 PSList *psList, /* List of potentially matching patterns, can be NULL. */
2752 PSList *psSuccList, /* Add all matching higher-level pattern sequences to this list.
2753 * Can be NULL. */
2754 unsigned patIndex, /* Match only this tag in sequence. */
2755 const Event *curEvent, /* Match this event. */
2756 ClientData object, /* Check for this binding tag. */
2757 PatSeq **physPtrPtr) /* Input: the best physical event; NULL if we test physical events.
2758 * Output: the associated physical event for the best matching virtual
2759 * event; NULL when we match physical events. */
2760 {
2761 Window window;
2762 PSEntry *psEntry;
2763 PatSeq *bestPtr;
2764 PatSeq *bestPhysPtr;
2765 ModMask bestModMask;
2766 const PSModMaskArr *bestModMaskArr = NULL;
2767
2768 assert(dispPtr);
2769 assert(bindPtr);
2770 assert(curEvent);
2771
2772 if (!psList) {
2773 return NULL;
2774 }
2775
2776 bestModMask = 0;
2777 bestPtr = NULL;
2778 bestPhysPtr = NULL;
2779 window = curEvent->xev.xany.window;
2780
2781 for (psEntry = PSList_First(psList); psEntry; psEntry = PSList_Next(psEntry)) {
2782 if (patIndex == 0 || psEntry->window == window) {
2783 PatSeq* psPtr = psEntry->psPtr;
2784
2785 assert(TEST_PSENTRY(psPtr));
2786 assert((psPtr->object == NULL) == (physPtrPtr != NULL));
2787 assert(psPtr->object || patIndex == 0);
2788 assert(psPtr->numPats > patIndex);
2789
2790 if (psPtr->object
2791 ? psPtr->object == object
2792 : VirtPatIsBound(bindPtr, psPtr, object, physPtrPtr)) {
2793 TkPattern *patPtr = psPtr->pats + patIndex;
2794
2795 if (patPtr->eventType == (unsigned) curEvent->xev.type
2796 && (curEvent->xev.type != CreateNotify
2797 || curEvent->xev.xcreatewindow.parent == window)
2798 && (!patPtr->name || patPtr->name == curEvent->detail.name)
2799 && (!patPtr->info || patPtr->info == curEvent->detail.info)) {
2800 /*
2801 * Resolve the modifier mask for Alt and Mod keys. Unfortunately this
2802 * cannot be done in ParseEventDescription, otherwise this function would
2803 * be the better place.
2804 */
2805 ModMask modMask = ResolveModifiers(dispPtr, patPtr->modMask);
2806 ModMask curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask);
2807
2808 psEntry->expired = 1; /* remove it from promotion list */
2809
2810 if ((modMask & ~curModMask) == 0) {
2811 unsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny;
2812
2813 if (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) {
2814 PSModMaskArr_Set(psEntry->lastModMaskArr, patIndex, &modMask);
2815 }
2816
16732817 /*
1674 * Ignore key events if they are modifier keys.
2818 * This pattern is finally matching.
16752819 */
16762820
1677 for (i = 0; i < dispPtr->numModKeyCodes; i++) {
1678 if (dispPtr->modKeyCodes[i]
1679 == eventPtr->xkey.keycode) {
2821 if (psPtr->numPats == patIndex + 1) {
2822 if (patPtr->count <= count) {
16802823 /*
1681 * This key is a modifier key, so ignore it.
2824 * This is also a final pattern.
2825 * We always prefer the pattern with better match.
2826 * If completely equal than prefer most recently defined pattern.
16822827 */
16832828
1684 goto nextEvent;
2829 int cmp = Compare(bestPtr, psPtr);
2830
2831 if (cmp == 0) {
2832 cmp = CompareModMasks(psEntry->lastModMaskArr, bestModMaskArr,
2833 modMask, bestModMask);
2834 }
2835
2836 if (cmp > 0 || (cmp == 0 && bestPtr->number < psPtr->number)) {
2837 bestPtr = psPtr;
2838 bestModMask = modMask;
2839 bestModMaskArr = psEntry->lastModMaskArr;
2840 if (physPtrPtr) {
2841 bestPhysPtr = *physPtrPtr;
2842 }
2843 }
2844 } else {
2845 DEBUG(psEntry->expired = 0;)
2846 psEntry->keepIt = 1; /* don't remove it from promotion list */
16852847 }
1686 }
1687 goto nextSequence;
1688 }
1689 }
1690 goto nextEvent;
1691 }
1692 if (eventPtr->xany.type == CreateNotify
1693 && eventPtr->xcreatewindow.parent != window) {
1694 goto nextSequence;
1695 } else if (eventPtr->xany.window != window) {
1696 goto nextSequence;
1697 }
1698
1699 /*
1700 * Note: it's important for the keysym check to go before the
1701 * modifier check, so we can ignore unwanted modifier keys before
1702 * choking on the modifier check.
1703 */
1704
1705 if ((patPtr->detail.clientData != 0)
1706 && (patPtr->detail.clientData != detailPtr->clientData)) {
1707 /*
1708 * The detail appears not to match. However, if the event is a
1709 * KeyPress for a modifier key then just ignore the event.
1710 * Otherwise event sequences like "aD" never match because the
1711 * shift key goes down between the "a" and the "D".
1712 */
1713
1714 if (eventPtr->xany.type == KeyPress) {
1715 for (i = 0; i < dispPtr->numModKeyCodes; i++) {
1716 if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {
1717 goto nextEvent;
2848 } else if (psSuccList) {
2849 /*
2850 * Not a final pattern, but matching, so promote it to next level.
2851 * But do not promote if count of current pattern is not yet reached.
2852 */
2853 if (patPtr->count == psEntry->count) {
2854 PSEntry *psNewEntry;
2855
2856 assert(!patPtr->name);
2857 psNewEntry = MakeListEntry(
2858 &bindPtr->lookupTables.entryPool, psPtr, psPtr->modMaskUsed);
2859 if (!PSModMaskArr_IsEmpty(psNewEntry->lastModMaskArr)) {
2860 PSModMaskArr_Set(psNewEntry->lastModMaskArr, patIndex, &modMask);
2861 }
2862 assert(psNewEntry->keepIt);
2863 assert(psNewEntry->count == 1u);
2864 PSList_Append(psSuccList, psNewEntry);
2865 psNewEntry->window = window; /* bind to current window */
2866 } else {
2867 assert(psEntry->count < patPtr->count);
2868 DEBUG(psEntry->expired = 0;)
2869 psEntry->count += 1;
2870 psEntry->keepIt = 1; /* don't remove it from promotion list */
2871 }
17182872 }
17192873 }
17202874 }
1721 goto nextSequence;
1722 }
1723 flags = flagArray[eventPtr->type];
1724 if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
1725 state = eventPtr->xkey.state;
1726 } else if (flags & CROSSING) {
1727 state = eventPtr->xcrossing.state;
1728 } else {
1729 state = 0;
1730 }
1731 if (patPtr->needMods != 0) {
1732 modMask = patPtr->needMods;
1733 if ((modMask & META_MASK) && (dispPtr->metaModMask != 0)) {
1734 modMask = (modMask & ~META_MASK) | dispPtr->metaModMask;
1735 }
1736 if ((modMask & ALT_MASK) && (dispPtr->altModMask != 0)) {
1737 modMask = (modMask & ~ALT_MASK) | dispPtr->altModMask;
1738 }
1739
1740 if ((state & META_MASK) && (dispPtr->metaModMask != 0)) {
1741 state = (state & ~META_MASK) | dispPtr->metaModMask;
1742 }
1743 if ((state & ALT_MASK) && (dispPtr->altModMask != 0)) {
1744 state = (state & ~ALT_MASK) | dispPtr->altModMask;
1745 }
1746
1747 if ((state & modMask) != modMask) {
1748 goto nextSequence;
1749 }
1750 }
1751 if (psPtr->flags & PAT_NEARBY) {
1752 XEvent *firstPtr = &bindPtr->eventRing[bindPtr->curEvent];
1753 long timeDiff;
1754
1755 timeDiff = ((long)firstPtr->xkey.time -
1756 (long)eventPtr->xkey.time);
1757 if ((firstPtr->xkey.x_root
1758 < (eventPtr->xkey.x_root - NEARBY_PIXELS))
1759 || (firstPtr->xkey.x_root
1760 > (eventPtr->xkey.x_root + NEARBY_PIXELS))
1761 || (firstPtr->xkey.y_root
1762 < (eventPtr->xkey.y_root - NEARBY_PIXELS))
1763 || (firstPtr->xkey.y_root
1764 > (eventPtr->xkey.y_root + NEARBY_PIXELS))
1765 || (timeDiff > NEARBY_MS)) {
1766 goto nextSequence;
1767 }
1768 }
1769 patPtr++;
1770 patCount--;
1771 nextEvent:
1772 if (eventPtr == bindPtr->eventRing) {
1773 eventPtr = &bindPtr->eventRing[EVENT_BUFFER_SIZE-1];
1774 detailPtr = &bindPtr->detailRing[EVENT_BUFFER_SIZE-1];
1775 } else {
1776 eventPtr--;
1777 detailPtr--;
1778 }
1779 ringCount--;
1780 }
1781
1782 matchPtr = psPtr;
1783 sourcePtr = psPtr;
1784
1785 if (objectPtr != NULL) {
1786 int iVirt;
1787 VirtualOwners *voPtr;
1788 PatternTableKey key;
1789
1790 /*
1791 * The sequence matches the physical constraints. Is this object
1792 * interested in any of the virtual events that correspond to this
1793 * sequence?
1794 */
1795
1796 voPtr = psPtr->voPtr;
1797
1798 memset(&key, 0, sizeof(key));
1799 key.object = *objectPtr;
1800 key.type = VirtualEvent;
1801 key.detail.clientData = 0;
1802
1803 for (iVirt = 0; iVirt < voPtr->numOwners; iVirt++) {
1804 Tcl_HashEntry *hPtr = voPtr->owners[iVirt];
1805
1806 key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr,
1807 hPtr);
1808 hPtr = Tcl_FindHashEntry(&bindPtr->patternTable,
1809 (char *) &key);
1810 if (hPtr != NULL) {
1811 /*
1812 * This tag is interested in this virtual event and its
1813 * corresponding physical event is a good match with the
1814 * virtual event's definition.
1815 */
1816
1817 PatSeq *virtMatchPtr = Tcl_GetHashValue(hPtr);
1818
1819 if ((virtMatchPtr->numPats != 1)
1820 || (virtMatchPtr->nextSeqPtr != NULL)) {
1821 Tcl_Panic("MatchPattern: badly constructed virtual event");
1822 }
1823 sourcePtr = virtMatchPtr;
1824 goto match;
1825 }
1826 }
1827
1828 /*
1829 * The physical event matches a virtual event's definition, but
1830 * the tag isn't interested in it.
1831 */
1832
1833 goto nextSequence;
1834 }
1835 match:
1836
1837 /*
1838 * This sequence matches. If we've already got another match, pick
1839 * whichever is most specific. Detail is most important, then
1840 * needMods.
1841 */
1842
1843 if (bestPtr != NULL) {
1844 TkPattern *patPtr2;
1845
1846 if (matchPtr->numPats != bestPtr->numPats) {
1847 if (bestPtr->numPats > matchPtr->numPats) {
1848 goto nextSequence;
1849 } else {
1850 goto newBest;
1851 }
1852 }
1853 for (i = 0, patPtr = matchPtr->pats, patPtr2 = bestPtr->pats;
1854 i < matchPtr->numPats; i++, patPtr++, patPtr2++) {
1855 if (patPtr->detail.clientData != patPtr2->detail.clientData) {
1856 if (patPtr->detail.clientData == 0) {
1857 goto nextSequence;
1858 } else {
1859 goto newBest;
1860 }
1861 }
1862 if (patPtr->needMods != patPtr2->needMods) {
1863 if ((patPtr->needMods & patPtr2->needMods)
1864 == patPtr->needMods) {
1865 goto nextSequence;
1866 } else if ((patPtr->needMods & patPtr2->needMods)
1867 == patPtr2->needMods) {
1868 goto newBest;
1869 }
1870 }
1871 }
1872
1873 /*
1874 * Tie goes to current best pattern.
1875 *
1876 * (1) For virtual vs. virtual, the least recently defined virtual
1877 * wins, because virtuals are examined in order of definition.
1878 * This order is _not_ guaranteed in the documentation.
1879 *
1880 * (2) For virtual vs. physical, the physical wins because all the
1881 * physicals are examined before the virtuals. This order is
1882 * guaranteed in the documentation.
1883 *
1884 * (3) For physical vs. physical pattern, the most recently
1885 * defined physical wins, because physicals are examined in
1886 * reverse order of definition. This order is guaranteed in the
1887 * documentation.
1888 */
1889
1890 goto nextSequence;
1891 }
1892 newBest:
1893 bestPtr = matchPtr;
1894 bestSourcePtr = sourcePtr;
1895
1896 nextSequence:
1897 continue;
1898 }
1899
1900 *sourcePtrPtr = bestSourcePtr;
2875 }
2876 }
2877 }
2878
2879 if (bestPhysPtr) {
2880 assert(physPtrPtr);
2881 *physPtrPtr = bestPhysPtr;
2882 }
19012883 return bestPtr;
19022884 }
19032885
19212903
19222904 static void
19232905 ExpandPercents(
1924 TkWindow *winPtr, /* Window where event occurred: needed to get
1925 * input context. */
1926 const char *before, /* Command containing percent expressions to
1927 * be replaced. */
1928 XEvent *eventPtr, /* X event containing information to be used
1929 * in % replacements. */
1930 KeySym keySym, /* KeySym: only relevant for KeyPress and
1931 * KeyRelease events). */
1932 unsigned int scriptCount, /* The number of script-based binding patterns
1933 * matched so far for this event. */
1934 Tcl_DString *dsPtr) /* Dynamic string in which to append new
1935 * command. */
1936 {
1937 int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl
1938 * list element. */
1939 int number, flags, length;
1940 #define NUM_SIZE 40
1941 const char *string;
2906 TkWindow *winPtr, /* Window where event occurred: needed to get input context. */
2907 const char *before, /* Command containing percent expressions to be replaced. */
2908 Event *eventPtr, /* Event containing information to be used in % replacements. */
2909 unsigned scriptCount, /* The number of script-based binding patterns matched so far for
2910 * this event. */
2911 Tcl_DString *dsPtr) /* Dynamic string in which to append new command. */
2912 {
2913 unsigned flags;
19422914 Tcl_DString buf;
1943 char numStorage[NUM_SIZE+1];
2915 XEvent *evPtr;
2916
2917 assert(winPtr);
2918 assert(before);
2919 assert(eventPtr);
2920 assert(dsPtr);
19442921
19452922 Tcl_DStringInit(&buf);
1946
1947 if (eventPtr->type < TK_LASTEVENT) {
1948 flags = flagArray[eventPtr->type];
1949 } else {
1950 flags = 0;
1951 }
2923 evPtr = &eventPtr->xev;
2924 flags = (evPtr->type < TK_LASTEVENT) ? flagArray[evPtr->type] : 0;
19522925
19532926 while (1) {
2927 char numStorage[TCL_INTEGER_SPACE];
2928 const char *string;
2929 Tcl_WideInt number;
2930
19542931 /*
19552932 * Find everything up to the next % character and append it to the
19562933 * result string.
19572934 */
19582935
1959 for (string = before; (*string != 0) && (*string != '%'); string++) {
1960 /* Empty loop body. */
1961 }
2936 for (string = before; *string && *string != '%'; ++string)
2937 ;
19622938 if (string != before) {
1963 Tcl_DStringAppend(dsPtr, before, (int) (string-before));
2939 Tcl_DStringAppend(dsPtr, before, string - before);
19642940 before = string;
19652941 }
1966 if (*before == 0) {
2942 if (!*before) {
19672943 break;
19682944 }
19692945
19712947 * There's a percent sequence here. Process it.
19722948 */
19732949
1974 number = 0;
2950 number = NO_NUMBER;
19752951 string = "??";
2952
19762953 switch (before[1]) {
19772954 case '#':
1978 number = eventPtr->xany.serial;
1979 goto doNumber;
2955 number = evPtr->xany.serial;
2956 break;
19802957 case 'a':
19812958 if (flags & CONFIG) {
1982 TkpPrintWindowId(numStorage, eventPtr->xconfigure.above);
2959 TkpPrintWindowId(numStorage, evPtr->xconfigure.above);
19832960 string = numStorage;
19842961 }
1985 goto doString;
2962 break;
19862963 case 'b':
19872964 if (flags & BUTTON) {
1988 number = eventPtr->xbutton.button;
1989 goto doNumber;
1990 }
1991 goto doString;
2965 number = evPtr->xbutton.button;
2966 }
2967 break;
19922968 case 'c':
19932969 if (flags & EXPOSE) {
1994 number = eventPtr->xexpose.count;
1995 goto doNumber;
1996 }
1997 goto doString;
2970 number = evPtr->xexpose.count;
2971 }
2972 break;
19982973 case 'd':
19992974 if (flags & (CROSSING|FOCUS)) {
2000 if (flags & FOCUS) {
2001 number = eventPtr->xfocus.detail;
2002 } else {
2003 number = eventPtr->xcrossing.detail;
2004 }
2005 string = TkFindStateString(notifyDetail, number);
2975 int detail = (flags & FOCUS) ? evPtr->xfocus.detail : evPtr->xcrossing.detail;
2976 string = TkFindStateString(notifyDetail, detail);
20062977 } else if (flags & CONFIGREQ) {
2007 if (eventPtr->xconfigurerequest.value_mask & CWStackMode) {
2008 string = TkFindStateString(configureRequestDetail,
2009 eventPtr->xconfigurerequest.detail);
2978 if (evPtr->xconfigurerequest.value_mask & CWStackMode) {
2979 string = TkFindStateString(configureRequestDetail, evPtr->xconfigurerequest.detail);
20102980 } else {
20112981 string = "";
20122982 }
20132983 } else if (flags & VIRTUAL) {
2014 XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr;
2015
2016 if (vePtr->user_data != NULL) {
2017 string = Tcl_GetString(vePtr->user_data);
2018 } else {
2019 string = "";
2020 }
2021 }
2022 goto doString;
2984 XVirtualEvent *vePtr = (XVirtualEvent *) evPtr;
2985 string = vePtr->user_data ? Tcl_GetString(vePtr->user_data) : "";
2986 }
2987 break;
20232988 case 'f':
20242989 if (flags & CROSSING) {
2025 number = eventPtr->xcrossing.focus;
2026 goto doNumber;
2027 }
2028 goto doString;
2990 number = evPtr->xcrossing.focus;
2991 }
2992 break;
20292993 case 'h':
20302994 if (flags & EXPOSE) {
2031 number = eventPtr->xexpose.height;
2995 number = evPtr->xexpose.height;
20322996 } else if (flags & CONFIG) {
2033 number = eventPtr->xconfigure.height;
2997 number = evPtr->xconfigure.height;
20342998 } else if (flags & CREATE) {
2035 number = eventPtr->xcreatewindow.height;
2999 number = evPtr->xcreatewindow.height;
20363000 } else if (flags & CONFIGREQ) {
2037 number = eventPtr->xconfigurerequest.height;
3001 number = evPtr->xconfigurerequest.height;
20383002 } else if (flags & RESIZEREQ) {
2039 number = eventPtr->xresizerequest.height;
2040 } else {
2041 goto doString;
2042 }
2043 goto doNumber;
3003 number = evPtr->xresizerequest.height;
3004 }
3005 break;
20443006 case 'i':
20453007 if (flags & CREATE) {
2046 TkpPrintWindowId(numStorage, eventPtr->xcreatewindow.window);
3008 TkpPrintWindowId(numStorage, evPtr->xcreatewindow.window);
20473009 } else if (flags & CONFIGREQ) {
2048 TkpPrintWindowId(numStorage,
2049 eventPtr->xconfigurerequest.window);
3010 TkpPrintWindowId(numStorage, evPtr->xconfigurerequest.window);
20503011 } else if (flags & MAPREQ) {
2051 TkpPrintWindowId(numStorage, eventPtr->xmaprequest.window);
3012 TkpPrintWindowId(numStorage, evPtr->xmaprequest.window);
20523013 } else {
2053 TkpPrintWindowId(numStorage, eventPtr->xany.window);
3014 TkpPrintWindowId(numStorage, evPtr->xany.window);
20543015 }
20553016 string = numStorage;
2056 goto doString;
3017 break;
20573018 case 'k':
2058 if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
2059 number = eventPtr->xkey.keycode;
2060 goto doNumber;
2061 }
2062 goto doString;
3019 if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
3020 number = evPtr->xkey.keycode;
3021 }
3022 break;
20633023 case 'm':
20643024 if (flags & CROSSING) {
2065 number = eventPtr->xcrossing.mode;
2066 string = TkFindStateString(notifyMode, number);
3025 string = TkFindStateString(notifyMode, evPtr->xcrossing.mode);
20673026 } else if (flags & FOCUS) {
2068 number = eventPtr->xfocus.mode;
2069 string = TkFindStateString(notifyMode, number);
2070 }
2071 goto doString;
3027 string = TkFindStateString(notifyMode, evPtr->xfocus.mode);
3028 }
3029 break;
20723030 case 'o':
20733031 if (flags & CREATE) {
2074 number = eventPtr->xcreatewindow.override_redirect;
3032 number = evPtr->xcreatewindow.override_redirect;
20753033 } else if (flags & MAP) {
2076 number = eventPtr->xmap.override_redirect;
3034 number = evPtr->xmap.override_redirect;
20773035 } else if (flags & REPARENT) {
2078 number = eventPtr->xreparent.override_redirect;
3036 number = evPtr->xreparent.override_redirect;
20793037 } else if (flags & CONFIG) {
2080 number = eventPtr->xconfigure.override_redirect;
2081 } else {
2082 goto doString;
2083 }
2084 goto doNumber;
3038 number = evPtr->xconfigure.override_redirect;
3039 }
3040 break;
20853041 case 'p':
20863042 if (flags & CIRC) {
2087 string = TkFindStateString(circPlace,
2088 eventPtr->xcirculate.place);
3043 string = TkFindStateString(circPlace, evPtr->xcirculate.place);
20893044 } else if (flags & CIRCREQ) {
2090 string = TkFindStateString(circPlace,
2091 eventPtr->xcirculaterequest.place);
2092 }
2093 goto doString;
3045 string = TkFindStateString(circPlace, evPtr->xcirculaterequest.place);
3046 }
3047 break;
20943048 case 's':
20953049 if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
2096 number = eventPtr->xkey.state;
2097 goto doNumber;
3050 number = evPtr->xkey.state;
20983051 } else if (flags & CROSSING) {
2099 number = eventPtr->xcrossing.state;
2100 goto doNumber;
3052 number = evPtr->xcrossing.state;
21013053 } else if (flags & PROP) {
2102 string = TkFindStateString(propNotify,
2103 eventPtr->xproperty.state);
3054 string = TkFindStateString(propNotify, evPtr->xproperty.state);
21043055 } else if (flags & VISIBILITY) {
2105 string = TkFindStateString(visNotify,
2106 eventPtr->xvisibility.state);
2107 }
2108 goto doString;
3056 string = TkFindStateString(visNotify, evPtr->xvisibility.state);
3057 }
3058 break;
21093059 case 't':
21103060 if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
2111 number = (int) eventPtr->xkey.time;
3061 number = (int) evPtr->xkey.time;
21123062 } else if (flags & CROSSING) {
2113 number = (int) eventPtr->xcrossing.time;
3063 number = (int) evPtr->xcrossing.time;
21143064 } else if (flags & PROP) {
2115 number = (int) eventPtr->xproperty.time;
2116 } else {
2117 goto doString;
2118 }
2119 goto doNumber;
3065 number = (int) evPtr->xproperty.time;
3066 }
3067 break;
21203068 case 'v':
2121 number = eventPtr->xconfigurerequest.value_mask;
2122 goto doNumber;
3069 number = evPtr->xconfigurerequest.value_mask;
3070 break;
21233071 case 'w':
21243072 if (flags & EXPOSE) {
2125 number = eventPtr->xexpose.width;
3073 number = evPtr->xexpose.width;
21263074 } else if (flags & CONFIG) {
2127 number = eventPtr->xconfigure.width;
3075 number = evPtr->xconfigure.width;
21283076 } else if (flags & CREATE) {
2129 number = eventPtr->xcreatewindow.width;
3077 number = evPtr->xcreatewindow.width;
21303078 } else if (flags & CONFIGREQ) {
2131 number = eventPtr->xconfigurerequest.width;
3079 number = evPtr->xconfigurerequest.width;
21323080 } else if (flags & RESIZEREQ) {
2133 number = eventPtr->xresizerequest.width;
2134 } else {
2135 goto doString;
2136 }
2137 goto doNumber;
3081 number = evPtr->xresizerequest.width;
3082 }
3083 break;
21383084 case 'x':
21393085 if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
2140 number = eventPtr->xkey.x;
3086 number = evPtr->xkey.x;
21413087 } else if (flags & CROSSING) {
2142 number = eventPtr->xcrossing.x;
3088 number = evPtr->xcrossing.x;
21433089 } else if (flags & EXPOSE) {
2144 number = eventPtr->xexpose.x;
3090 number = evPtr->xexpose.x;
21453091 } else if (flags & (CREATE|CONFIG|GRAVITY)) {
2146 number = eventPtr->xcreatewindow.x;
3092 number = evPtr->xcreatewindow.x;
21473093 } else if (flags & REPARENT) {
2148 number = eventPtr->xreparent.x;
3094 number = evPtr->xreparent.x;
21493095 } else if (flags & CREATE) {
2150 number = eventPtr->xcreatewindow.x;
3096 number = evPtr->xcreatewindow.x;
21513097 } else if (flags & CONFIGREQ) {
2152 number = eventPtr->xconfigurerequest.x;
2153 } else {
2154 goto doString;
2155 }
2156 goto doNumber;
3098 number = evPtr->xconfigurerequest.x;
3099 }
3100 break;
21573101 case 'y':
21583102 if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
2159 number = eventPtr->xkey.y;
3103 number = evPtr->xkey.y;
21603104 } else if (flags & EXPOSE) {
2161 number = eventPtr->xexpose.y;
3105 number = evPtr->xexpose.y;
21623106 } else if (flags & (CREATE|CONFIG|GRAVITY)) {
2163 number = eventPtr->xcreatewindow.y;
3107 number = evPtr->xcreatewindow.y;
21643108 } else if (flags & REPARENT) {
2165 number = eventPtr->xreparent.y;
3109 number = evPtr->xreparent.y;
21663110 } else if (flags & CROSSING) {
2167 number = eventPtr->xcrossing.y;
3111 number = evPtr->xcrossing.y;
21683112 } else if (flags & CREATE) {
2169 number = eventPtr->xcreatewindow.y;
3113 number = evPtr->xcreatewindow.y;
21703114 } else if (flags & CONFIGREQ) {
2171 number = eventPtr->xconfigurerequest.y;
2172 } else {
2173 goto doString;
2174 }
2175 goto doNumber;
3115 number = evPtr->xconfigurerequest.y;
3116 }
3117 break;
21763118 case 'A':
2177 if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
3119 if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
21783120 Tcl_DStringFree(&buf);
2179 string = TkpGetString(winPtr, eventPtr, &buf);
2180 }
2181 goto doString;
3121 string = TkpGetString(winPtr, evPtr, &buf);
3122 }
3123 break;
21823124 case 'B':
21833125 if (flags & CREATE) {
2184 number = eventPtr->xcreatewindow.border_width;
3126 number = evPtr->xcreatewindow.border_width;
21853127 } else if (flags & CONFIGREQ) {
2186 number = eventPtr->xconfigurerequest.border_width;
3128 number = evPtr->xconfigurerequest.border_width;
21873129 } else if (flags & CONFIG) {
2188 number = eventPtr->xconfigure.border_width;
2189 } else {
2190 goto doString;
2191 }
2192 goto doNumber;
3130 number = evPtr->xconfigure.border_width;
3131 }
3132 break;
21933133 case 'D':
21943134 /*
21953135 * This is used only by the MouseWheel event.
21963136 */
2197
2198 if ((flags & KEY) && (eventPtr->type == MouseWheelEvent)) {
2199 number = eventPtr->xkey.keycode;
2200 goto doNumber;
2201 }
2202 goto doString;
3137 if ((flags & KEY) && evPtr->type == MouseWheelEvent) {
3138 number = evPtr->xkey.keycode;
3139 }
3140 break;
22033141 case 'E':
2204 number = (int) eventPtr->xany.send_event;
2205 goto doNumber;
3142 number = (int) evPtr->xany.send_event;
3143 break;
22063144 case 'K':
2207 if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
2208 const char *name = TkKeysymToString(keySym);
2209
2210 if (name != NULL) {
3145 if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
3146 const char *name = TkKeysymToString(eventPtr->detail.info);
3147 if (name) {
22113148 string = name;
22123149 }
22133150 }
2214 goto doString;
3151 break;
22153152 case 'M':
22163153 number = scriptCount;
2217 goto doNumber;
3154 break;
22183155 case 'N':
2219 if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) {
2220 number = (int) keySym;
2221 goto doNumber;
2222 }
2223 goto doString;
3156 if ((flags & KEY) && evPtr->type != MouseWheelEvent) {
3157 number = (int) eventPtr->detail.info;
3158 }
3159 break;
22243160 case 'P':
22253161 if (flags & PROP) {
2226 string = Tk_GetAtomName((Tk_Window) winPtr,
2227 eventPtr->xproperty.atom);
2228 }
2229 goto doString;
3162 string = Tk_GetAtomName((Tk_Window) winPtr, evPtr->xproperty.atom);
3163 }
3164 break;
22303165 case 'R':
22313166 if (flags & KEY_BUTTON_MOTION_CROSSING) {
2232 TkpPrintWindowId(numStorage, eventPtr->xkey.root);
3167 TkpPrintWindowId(numStorage, evPtr->xkey.root);
22333168 string = numStorage;
22343169 }
2235 goto doString;
3170 break;
22363171 case 'S':
22373172 if (flags & KEY_BUTTON_MOTION_CROSSING) {
2238 TkpPrintWindowId(numStorage, eventPtr->xkey.subwindow);
3173 TkpPrintWindowId(numStorage, evPtr->xkey.subwindow);
22393174 string = numStorage;
22403175 }
2241 goto doString;
3176 break;
22423177 case 'T':
2243 number = eventPtr->type;
2244 goto doNumber;
3178 number = evPtr->type;
3179 break;
22453180 case 'W': {
2246 Tk_Window tkwin;
2247
2248 tkwin = Tk_IdToWindow(eventPtr->xany.display,
2249 eventPtr->xany.window);
2250 if (tkwin != NULL) {
3181 Tk_Window tkwin = Tk_IdToWindow(evPtr->xany.display, evPtr->xany.window);
3182 if (tkwin) {
22513183 string = Tk_PathName(tkwin);
2252 } else {
2253 string = "??";
2254 }
2255 goto doString;
3184 }
3185 break;
22563186 }
22573187 case 'X':
22583188 if (flags & KEY_BUTTON_MOTION_CROSSING) {
2259
2260 number = eventPtr->xkey.x_root;
2261 Tk_IdToWindow(eventPtr->xany.display,
2262 eventPtr->xany.window);
2263 goto doNumber;
2264 }
2265 goto doString;
3189 number = evPtr->xkey.x_root;
3190 }
3191 break;
22663192 case 'Y':
22673193 if (flags & KEY_BUTTON_MOTION_CROSSING) {
2268
2269 number = eventPtr->xkey.y_root;
2270 Tk_IdToWindow(eventPtr->xany.display,
2271 eventPtr->xany.window);
2272 goto doNumber;
2273 }
2274 goto doString;
3194 number = evPtr->xkey.y_root;
3195 }
3196 break;
22753197 default:
22763198 numStorage[0] = before[1];
22773199 numStorage[1] = '\0';
22783200 string = numStorage;
2279 goto doString;
2280 }
2281
2282 doNumber:
2283 sprintf(numStorage, "%d", number);
2284 string = numStorage;
2285
2286 doString:
2287 spaceNeeded = Tcl_ScanElement(string, &cvtFlags);
2288 length = Tcl_DStringLength(dsPtr);
2289 Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
2290 spaceNeeded = Tcl_ConvertElement(string,
2291 Tcl_DStringValue(dsPtr) + length,
2292 cvtFlags | TCL_DONT_USE_BRACES);
2293 Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
2294 before += 2;
2295 }
3201 break;
3202 }
3203
3204 if (number != NO_NUMBER) {
3205 snprintf(numStorage, sizeof(numStorage), "%d", (int) number);
3206 string = numStorage;
3207 }
3208 { /* local scope */
3209 int cvtFlags;
3210 unsigned spaceNeeded = Tcl_ScanElement(string, &cvtFlags);
3211 unsigned length = Tcl_DStringLength(dsPtr);
3212
3213 Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
3214 spaceNeeded = Tcl_ConvertElement(
3215 string, Tcl_DStringValue(dsPtr) + length, cvtFlags | TCL_DONT_USE_BRACES);
3216 Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
3217 before += 2;
3218 }
3219 }
3220
22963221 Tcl_DStringFree(&buf);
22973222 }
22983223
23233248 char *dispName, /* Name of new display. */
23243249 int screenIndex) /* Index of new screen. */
23253250 {
2326 Tcl_Obj *cmdObj = Tcl_ObjPrintf("::tk::ScreenChanged %s.%d",
2327 dispName, screenIndex);
3251 Tcl_Obj *cmdObj = Tcl_ObjPrintf("::tk::ScreenChanged %s.%d", dispName, screenIndex);
23283252 int code;
23293253
23303254 Tcl_IncrRefCount(cmdObj);
23313255 code = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL);
23323256 if (code != TCL_OK) {
2333 Tcl_AddErrorInfo(interp,
2334 "\n (changing screen in event binding)");
3257 Tcl_AddErrorInfo(interp, "\n (changing screen in event binding)");
23353258 Tcl_BackgroundException(interp, code);
23363259 }
23373260 Tcl_DecrRefCount(cmdObj);
23643287 int index, i;
23653288 char *name;
23663289 const char *event;
2367 Tk_Window tkwin = clientData;
2368 TkBindInfo bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo;
2369 VirtualEventTable *vetPtr = &bindInfo->virtualEventTable;
2370 static const char *const optionStrings[] = {
2371 "add", "delete", "generate", "info",
2372 NULL
2373 };
2374 enum options {
2375 EVENT_ADD, EVENT_DELETE, EVENT_GENERATE, EVENT_INFO
2376 };
2377
3290 Tk_Window tkwin;
3291 TkBindInfo bindInfo;
3292 VirtualEventTable *vetPtr;
3293
3294 static const char *const optionStrings[] = { "add", "delete", "generate", "info", NULL };
3295 enum options { EVENT_ADD, EVENT_DELETE, EVENT_GENERATE, EVENT_INFO };
3296
3297 assert(clientData);
23783298
23793299 if (objc < 2) {
23803300 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
23813301 return TCL_ERROR;
23823302 }
2383 if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
2384 sizeof(char *), "option", 0, &index) != TCL_OK) {
3303 if (Tcl_GetIndexFromObjStruct(
3304 interp, objv[1], optionStrings, sizeof(char *), "option", 0, &index) != TCL_OK) {
3305 #ifdef SUPPORT_DEBUGGING
3306 if (strcmp(Tcl_GetString(objv[1]), "debug") == 0) {
3307 if (objc < 3) {
3308 Tcl_WrongNumArgs(interp, 1, objv, "debug number");
3309 return TCL_ERROR;
3310 }
3311 Tcl_GetIntFromObj(interp, objv[2], &BindCount);
3312 return TCL_OK;
3313 }
3314 #endif
23853315 return TCL_ERROR;
23863316 }
3317
3318 tkwin = (Tk_Window) clientData;
3319 bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo;
3320 vetPtr = &bindInfo->virtualEventTable;
23873321
23883322 switch ((enum options) index) {
23893323 case EVENT_ADD:
23903324 if (objc < 4) {
2391 Tcl_WrongNumArgs(interp, 2, objv,
2392 "virtual sequence ?sequence ...?");
3325 Tcl_WrongNumArgs(interp, 2, objv, "virtual sequence ?sequence ...?");
23933326 return TCL_ERROR;
23943327 }
23953328 name = Tcl_GetString(objv[2]);
2396 for (i = 3; i < objc; i++) {
3329 for (i = 3; i < objc; ++i) {
23973330 event = Tcl_GetString(objv[i]);
2398 if (CreateVirtualEvent(interp, vetPtr, name, event) != TCL_OK) {
3331 if (!CreateVirtualEvent(interp, vetPtr, name, event)) {
23993332 return TCL_ERROR;
24003333 }
24013334 }
24093342 if (objc == 3) {
24103343 return DeleteVirtualEvent(interp, vetPtr, name, NULL);
24113344 }
2412 for (i = 3; i < objc; i++) {
3345 for (i = 3; i < objc; ++i) {
24133346 event = Tcl_GetString(objv[i]);
24143347 if (DeleteVirtualEvent(interp, vetPtr, name, event) != TCL_OK) {
24153348 return TCL_ERROR;
24183351 break;
24193352 case EVENT_GENERATE:
24203353 if (objc < 4) {
2421 Tcl_WrongNumArgs(interp, 2, objv,
2422 "window event ?-option value ...?");
3354 Tcl_WrongNumArgs(interp, 2, objv, "window event ?-option value ...?");
24233355 return TCL_ERROR;
24243356 }
24253357 return HandleEventGenerate(interp, tkwin, objc - 2, objv + 2);
24273359 if (objc == 2) {
24283360 GetAllVirtualEvents(interp, vetPtr);
24293361 return TCL_OK;
2430 } else if (objc == 3) {
3362 }
3363 if (objc == 3) {
24313364 return GetVirtualEvent(interp, vetPtr, objv[2]);
2432 } else {
2433 Tcl_WrongNumArgs(interp, 2, objv, "?virtual?");
2434 return TCL_ERROR;
2435 }
3365 }
3366 Tcl_WrongNumArgs(interp, 2, objv, "?virtual?");
3367 return TCL_ERROR;
24363368 }
24373369 return TCL_OK;
24383370 }
24563388
24573389 static void
24583390 InitVirtualEventTable(
2459 VirtualEventTable *vetPtr) /* Pointer to virtual event table. Memory is
2460 * supplied by the caller. */
2461 {
2462 Tcl_InitHashTable(&vetPtr->patternTable,
2463 sizeof(PatternTableKey) / sizeof(int));
3391 VirtualEventTable *vetPtr) /* Pointer to virtual event table. Memory is supplied by the caller. */
3392 {
3393 assert(vetPtr);
3394 memset(vetPtr, 0, sizeof(*vetPtr));
3395 Tcl_InitHashTable(&vetPtr->lookupTables.patternTable, sizeof(PatternTableKey)/sizeof(int));
3396 Tcl_InitHashTable(&vetPtr->lookupTables.listTable, sizeof(PatternTableKey)/sizeof(int));
24643397 Tcl_InitHashTable(&vetPtr->nameTable, TCL_ONE_WORD_KEYS);
3398 PSList_Init(&vetPtr->lookupTables.entryPool);
24653399 }
24663400
24673401 /*
24873421 {
24883422 Tcl_HashEntry *hPtr;
24893423 Tcl_HashSearch search;
2490 PatSeq *psPtr, *nextPtr;
2491
2492 hPtr = Tcl_FirstHashEntry(&vetPtr->patternTable, &search);
2493 for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
2494 psPtr = Tcl_GetHashValue(hPtr);
2495 for ( ; psPtr != NULL; psPtr = nextPtr) {
3424
3425 assert(vetPtr);
3426
3427 hPtr = Tcl_FirstHashEntry(&vetPtr->lookupTables.patternTable, &search);
3428 for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {
3429 PatSeq *nextPtr;
3430 PatSeq *psPtr;
3431
3432 for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) {
3433 assert(TEST_PSENTRY(psPtr));
24963434 nextPtr = psPtr->nextSeqPtr;
2497 ckfree(psPtr->voPtr);
2498 ckfree(psPtr);
2499 }
2500 }
2501 Tcl_DeleteHashTable(&vetPtr->patternTable);
3435 DEBUG(psPtr->owned = 0;)
3436 FreePatSeq(psPtr);
3437 }
3438 }
3439 Tcl_DeleteHashTable(&vetPtr->lookupTables.patternTable);
25023440
25033441 hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search);
2504 for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
3442 for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {
25053443 ckfree(Tcl_GetHashValue(hPtr));
25063444 }
25073445 Tcl_DeleteHashTable(&vetPtr->nameTable);
3446 Tcl_DeleteHashTable(&vetPtr->lookupTables.listTable);
3447
3448 ClearLookupTable(&vetPtr->lookupTables, NULL);
3449 DEBUG(countEntryItems -= PSList_Size(&vetPtr->lookupTables.entryPool);)
3450 PSList_Traverse(&vetPtr->lookupTables.entryPool, FreePatSeqEntry);
25083451 }
25093452
25103453 /*
25323475 Tcl_Interp *interp, /* Used for error reporting. */
25333476 VirtualEventTable *vetPtr, /* Table in which to augment virtual event. */
25343477 char *virtString, /* Name of new virtual event. */
2535 const char *eventString) /* String describing physical event that
2536 * triggers virtual event. */
3478 const char *eventString) /* String describing physical event that triggers virtual event. */
25373479 {
25383480 PatSeq *psPtr;
25393481 int dummy;
25403482 Tcl_HashEntry *vhPtr;
2541 unsigned long eventMask;
2542 PhysicalsOwned *poPtr;
2543 VirtualOwners *voPtr;
3483 PhysOwned *owned;
25443484 Tk_Uid virtUid;
25453485
2546 virtUid = GetVirtualEventUid(interp, virtString);
2547 if (virtUid == NULL) {
2548 return TCL_ERROR;
3486 assert(vetPtr);
3487 assert(virtString);
3488 assert(eventString);
3489
3490 if (!(virtUid = GetVirtualEventUid(interp, virtString))) {
3491 return 0;
25493492 }
25503493
25513494 /*
25523495 * Find/create physical event
25533496 */
25543497
2555 psPtr = FindSequence(interp, &vetPtr->patternTable, NULL, eventString,
2556 1, 0, &eventMask);
2557 if (psPtr == NULL) {
2558 return TCL_ERROR;
2559 }
3498 if (!(psPtr = FindSequence(interp, &vetPtr->lookupTables, NULL, eventString, 1, 0, NULL))) {
3499 return 0;
3500 }
3501 assert(TEST_PSENTRY(psPtr));
25603502
25613503 /*
25623504 * Find/create virtual event.
25683510 * Make virtual event own the physical event.
25693511 */
25703512
2571 poPtr = Tcl_GetHashValue(vhPtr);
2572 if (poPtr == NULL) {
2573 poPtr = ckalloc(sizeof(PhysicalsOwned));
2574 poPtr->numOwned = 0;
2575 } else {
2576 /*
2577 * See if this virtual event is already defined for this physical
2578 * event and just return if it is.
2579 */
2580
2581 int i;
2582
2583 for (i = 0; i < poPtr->numOwned; i++) {
2584 if (poPtr->patSeqs[i] == psPtr) {
2585 return TCL_OK;
2586 }
2587 }
2588 poPtr = ckrealloc(poPtr, sizeof(PhysicalsOwned)
2589 + poPtr->numOwned * sizeof(PatSeq *));
2590 }
2591 Tcl_SetHashValue(vhPtr, poPtr);
2592 poPtr->patSeqs[poPtr->numOwned] = psPtr;
2593 poPtr->numOwned++;
2594
2595 /*
2596 * Make physical event so it can trigger the virtual event.
2597 */
2598
2599 voPtr = psPtr->voPtr;
2600 if (voPtr == NULL) {
2601 voPtr = ckalloc(sizeof(VirtualOwners));
2602 voPtr->numOwners = 0;
2603 } else {
2604 voPtr = ckrealloc(voPtr, sizeof(VirtualOwners)
2605 + voPtr->numOwners * sizeof(Tcl_HashEntry *));
2606 }
2607 psPtr->voPtr = voPtr;
2608 voPtr->owners[voPtr->numOwners] = vhPtr;
2609 voPtr->numOwners++;
2610
2611 return TCL_OK;
3513 owned = Tcl_GetHashValue(vhPtr);
3514
3515 if (!PhysOwned_Contains(owned, psPtr)) {
3516 PhysOwned_Append(&owned, psPtr);
3517 Tcl_SetHashValue(vhPtr, owned);
3518 DEBUG(psPtr->owned = 1;)
3519 InsertPatSeq(&vetPtr->lookupTables, psPtr);
3520 /* Make physical event so it can trigger the virtual event. */
3521 VirtOwners_Append(&psPtr->ptr.owners, vhPtr);
3522 }
3523
3524 return 1;
26123525 }
26133526
26143527 /*
26383551 DeleteVirtualEvent(
26393552 Tcl_Interp *interp, /* Used for error reporting. */
26403553 VirtualEventTable *vetPtr, /* Table in which to delete event. */
2641 char *virtString, /* String describing event sequence that
2642 * triggers binding. */
2643 const char *eventString) /* The event sequence that should be deleted,
2644 * or NULL to delete all event sequences for
2645 * the entire virtual event. */
3554 char *virtString, /* String describing event sequence that triggers binding. */
3555 const char *eventString) /* The event sequence that should be deleted, or NULL to delete
3556 * all event sequences for the entire virtual event. */
26463557 {
26473558 int iPhys;
26483559 Tk_Uid virtUid;
26493560 Tcl_HashEntry *vhPtr;
2650 PhysicalsOwned *poPtr;
2651 PatSeq *eventPSPtr;
2652
2653 virtUid = GetVirtualEventUid(interp, virtString);
2654 if (virtUid == NULL) {
3561 PhysOwned *owned;
3562 const PatSeq *eventPSPtr;
3563 PatSeq *lastElemPtr;
3564
3565 assert(vetPtr);
3566 assert(virtString);
3567
3568 if (!(virtUid = GetVirtualEventUid(interp, virtString))) {
26553569 return TCL_ERROR;
26563570 }
26573571
2658 vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid);
2659 if (vhPtr == NULL) {
3572 if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) {
26603573 return TCL_OK;
26613574 }
2662 poPtr = Tcl_GetHashValue(vhPtr);
3575 owned = Tcl_GetHashValue(vhPtr);
26633576
26643577 eventPSPtr = NULL;
2665 if (eventString != NULL) {
2666 unsigned long eventMask;
3578 if (eventString) {
3579 LookupTables *lookupTables = &vetPtr->lookupTables;
26673580
26683581 /*
26693582 * Delete only the specific physical event associated with the virtual
26713584 * event doesn't own that physical event, return w/o doing anything.
26723585 */
26733586
2674 eventPSPtr = FindSequence(interp, &vetPtr->patternTable, NULL,
2675 eventString, 0, 0, &eventMask);
2676 if (eventPSPtr == NULL) {
3587 eventPSPtr = FindSequence(interp, lookupTables, NULL, eventString, 0, 0, NULL);
3588 if (!eventPSPtr) {
26773589 const char *string = Tcl_GetString(Tcl_GetObjResult(interp));
2678
2679 return (string[0] != '\0') ? TCL_ERROR : TCL_OK;
2680 }
2681 }
2682
2683 for (iPhys = poPtr->numOwned; --iPhys >= 0; ) {
2684 PatSeq *psPtr = poPtr->patSeqs[iPhys];
2685
2686 if ((eventPSPtr == NULL) || (psPtr == eventPSPtr)) {
2687 int iVirt;
2688 VirtualOwners *voPtr;
3590 return string[0] ? TCL_ERROR : TCL_OK;
3591 }
3592 }
3593
3594 for (iPhys = PhysOwned_Size(owned); --iPhys >= 0; ) {
3595 PatSeq *psPtr = PhysOwned_Get(owned, iPhys);
3596
3597 assert(TEST_PSENTRY(psPtr));
3598
3599 if (!eventPSPtr || psPtr == eventPSPtr) {
3600 VirtOwners *owners = psPtr->ptr.owners;
3601 int iVirt = VirtOwners_Find(owners, vhPtr);
3602
3603 assert(iVirt != -1); /* otherwise we couldn't find owner, and this should not happen */
26893604
26903605 /*
26913606 * Remove association between this physical event and the given
26923607 * virtual event that it triggers.
26933608 */
26943609
2695 voPtr = psPtr->voPtr;
2696 for (iVirt = 0; iVirt < voPtr->numOwners; iVirt++) {
2697 if (voPtr->owners[iVirt] == vhPtr) {
2698 break;
2699 }
2700 }
2701 if (iVirt == voPtr->numOwners) {
2702 Tcl_Panic("DeleteVirtualEvent: couldn't find owner");
2703 }
2704 voPtr->numOwners--;
2705 if (voPtr->numOwners == 0) {
2706 /*
2707 * Removed last reference to this physical event, so remove it
2708 * from physical->virtual map.
2709 */
2710
2711 PatSeq *prevPtr = Tcl_GetHashValue(psPtr->hPtr);
2712
2713 if (prevPtr == psPtr) {
2714 if (psPtr->nextSeqPtr == NULL) {
2715 Tcl_DeleteHashEntry(psPtr->hPtr);
2716 } else {
2717 Tcl_SetHashValue(psPtr->hPtr,
2718 psPtr->nextSeqPtr);
2719 }
2720 } else {
2721 for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
2722 if (prevPtr == NULL) {
2723 Tcl_Panic("DeleteVirtualEvent couldn't find on hash chain");
2724 }
2725 if (prevPtr->nextSeqPtr == psPtr) {
2726 prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
2727 break;
2728 }
2729 }
2730 }
2731 ckfree(psPtr->voPtr);
2732 ckfree(psPtr);
2733 } else {
3610 if (VirtOwners_Size(owners) > 1) {
27343611 /*
27353612 * This physical event still triggers some other virtual
27363613 * event(s). Consolidate the list of virtual owners for this
27373614 * physical event so it no longer triggers the given virtual
27383615 * event.
27393616 */
2740
2741 voPtr->owners[iVirt] = voPtr->owners[voPtr->numOwners];
3617 VirtOwners_Set(owners, iVirt, VirtOwners_Back(owners));
3618 VirtOwners_PopBack(owners);
3619 } else {
3620 /*
3621 * Removed last reference to this physical event, so remove it
3622 * from lookup table.
3623 */
3624 DEBUG(psPtr->owned = 0;)
3625 RemovePatSeqFromLookup(&vetPtr->lookupTables, psPtr);
3626 DeletePatSeq(psPtr);
27423627 }
27433628
27443629 /*
27453630 * Now delete the virtual event's reference to the physical event.
27463631 */
27473632
2748 poPtr->numOwned--;
2749 if (eventPSPtr != NULL && poPtr->numOwned != 0) {
3633 lastElemPtr = PhysOwned_Back(owned);
3634
3635 if (PhysOwned_PopBack(owned) > 0 && eventPSPtr) {
27503636 /*
27513637 * Just deleting this one physical event. Consolidate list of
27523638 * owned physical events and return.
27533639 */
2754
2755 poPtr->patSeqs[iPhys] = poPtr->patSeqs[poPtr->numOwned];
3640 if ((size_t) iPhys < PhysOwned_Size(owned)) {
3641 PhysOwned_Set(owned, iPhys, lastElemPtr);
3642 }
27563643 return TCL_OK;
27573644 }
27583645 }
27593646 }
27603647
2761 if (poPtr->numOwned == 0) {
3648 if (PhysOwned_IsEmpty(owned)) {
27623649 /*
27633650 * All the physical events for this virtual event were deleted, either
27643651 * because there was only one associated physical event or because the
27653652 * caller was deleting the entire virtual event. Now the virtual event
27663653 * itself should be deleted.
27673654 */
2768
2769 ckfree(poPtr);
3655 PhysOwned_Free(&owned);
27703656 Tcl_DeleteHashEntry(vhPtr);
27713657 }
27723658 return TCL_OK;
28013687 Tcl_Obj *virtName) /* String describing virtual event. */
28023688 {
28033689 Tcl_HashEntry *vhPtr;
2804 int iPhys;
2805 PhysicalsOwned *poPtr;
3690 unsigned iPhys;
3691 const PhysOwned *owned;
28063692 Tk_Uid virtUid;
28073693 Tcl_Obj *resultObj;
28083694
2809 virtUid = GetVirtualEventUid(interp, Tcl_GetString(virtName));
2810 if (virtUid == NULL) {
3695 assert(vetPtr);
3696 assert(virtName);
3697
3698 if (!(virtUid = GetVirtualEventUid(interp, Tcl_GetString(virtName)))) {
28113699 return TCL_ERROR;
28123700 }
28133701
2814 vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid);
2815 if (vhPtr == NULL) {
3702 if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) {
28163703 return TCL_OK;
28173704 }
28183705
28193706 resultObj = Tcl_NewObj();
2820 poPtr = Tcl_GetHashValue(vhPtr);
2821 for (iPhys = 0; iPhys < poPtr->numOwned; iPhys++) {
2822 Tcl_ListObjAppendElement(NULL, resultObj,
2823 GetPatternObj(poPtr->patSeqs[iPhys]));
3707 owned = Tcl_GetHashValue(vhPtr);
3708 for (iPhys = 0; iPhys < PhysOwned_Size(owned); ++iPhys) {
3709 Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(PhysOwned_Get(owned, iPhys)));
28243710 }
28253711 Tcl_SetObjResult(interp, resultObj);
28263712
28543740 Tcl_HashSearch search;
28553741 Tcl_Obj *resultObj;
28563742
3743 assert(vetPtr);
3744
28573745 resultObj = Tcl_NewObj();
28583746 hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search);
2859 for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
2860 Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf(
2861 "<<%s>>", (char *) Tcl_GetHashKey(hPtr->tablePtr, hPtr)));
3747 for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) {
3748 Tcl_Obj* msg = Tcl_ObjPrintf("<<%s>>", (char *) Tcl_GetHashKey(hPtr->tablePtr, hPtr));
3749 Tcl_ListObjAppendElement(NULL, resultObj, msg);
28623750 }
28633751 Tcl_SetObjResult(interp, resultObj);
28643752 }
29053793 int objc, /* Number of arguments. */
29063794 Tcl_Obj *const objv[]) /* Argument objects. */
29073795 {
2908 union {XEvent general; XVirtualEvent virtual;} event;
3796 union { XEvent general; XVirtualEvent virtual; } event;
3797
29093798 const char *p;
2910 const char *name, *windowName;
2911 int count, flags, synch, i, number, warp;
3799 const char *name;
3800 const char *windowName;
29123801 Tcl_QueuePosition pos;
29133802 TkPattern pat;
2914 Tk_Window tkwin, tkwin2;
3803 Tk_Window tkwin;
3804 Tk_Window tkwin2;
29153805 TkWindow *mainPtr;
2916 unsigned long eventMask;
3806 EventMask eventMask;
29173807 Tcl_Obj *userDataObj;
3808 int synch;
3809 int warp;
3810 unsigned count;
3811 unsigned flags;
3812 int number;
3813 unsigned i;
29183814
29193815 static const char *const fieldStrings[] = {
29203816 "-when", "-above", "-borderwidth", "-button",
29243820 "-place", "-root", "-rootx", "-rooty",
29253821 "-sendevent", "-serial", "-state", "-subwindow",
29263822 "-time", "-warp", "-width", "-window",
2927 "-x", "-y", NULL
3823 "-x", "-y", NULL
29283824 };
29293825 enum field {
29303826 EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON,
29373833 EVENT_X, EVENT_Y
29383834 };
29393835
3836 assert(mainWin);
3837
29403838 windowName = Tcl_GetString(objv[0]);
29413839 if (!windowName[0]) {
29423840 tkwin = mainWin;
2943 } else if (NameToWindow(interp, mainWin, objv[0], &tkwin) != TCL_OK) {
3841 } else if (!NameToWindow(interp, mainWin, objv[0], &tkwin)) {
29443842 return TCL_ERROR;
29453843 }
29463844
29473845 mainPtr = (TkWindow *) mainWin;
2948 if ((tkwin == NULL)
2949 || (mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {
3846 if (!tkwin || mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
29503847 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
29513848 "window id \"%s\" doesn't exist in this application",
29523849 Tcl_GetString(objv[0])));
2953 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW",
2954 Tcl_GetString(objv[0]), NULL);
3850 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW", Tcl_GetString(objv[0]), NULL);
29553851 return TCL_ERROR;
29563852 }
29573853
29583854 name = Tcl_GetString(objv[1]);
2959
29603855 p = name;
29613856 eventMask = 0;
29623857 userDataObj = NULL;
2963 count = ParseEventDescription(interp, &p, &pat, &eventMask);
2964 if (count == 0) {
3858 if ((count = ParseEventDescription(interp, &p, &pat, &eventMask)) == 0) {
29653859 return TCL_ERROR;
29663860 }
2967 if (count != 1) {
2968 Tcl_SetObjResult(interp, Tcl_NewStringObj(
2969 "Double or Triple modifier not allowed", -1));
3861 if (count != 1u) {
3862 Tcl_SetObjResult(interp,
3863 Tcl_NewStringObj("Double, Triple, or Quadruple modifier not allowed", -1));
29703864 Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_MODIFIER", NULL);
29713865 return TCL_ERROR;
29723866 }
2973 if (*p != '\0') {
2974 Tcl_SetObjResult(interp, Tcl_NewStringObj(
2975 "only one event specification allowed", -1));
3867 if (*p) {
3868 Tcl_SetObjResult(interp, Tcl_NewStringObj("only one event specification allowed", -1));
29763869 Tcl_SetErrorCode(interp, "TK", "EVENT", "MULTIPLE", NULL);
29773870 return TCL_ERROR;
29783871 }
29803873 memset(&event, 0, sizeof(event));
29813874 event.general.xany.type = pat.eventType;
29823875 event.general.xany.serial = NextRequest(Tk_Display(tkwin));
2983 event.general.xany.send_event = False;
3876 event.general.xany.send_event = 0;
29843877 if (windowName[0]) {
29853878 event.general.xany.window = Tk_WindowId(tkwin);
29863879 } else {
2987 event.general.xany.window =
2988 RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
3880 event.general.xany.window = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
29893881 }
29903882 event.general.xany.display = Tk_Display(tkwin);
29913883
29943886 /*
29953887 * Event DestroyNotify should be generated by destroying the window.
29963888 */
2997
29983889 Tk_DestroyWindow(tkwin);
29993890 return TCL_OK;
30003891 }
30013892 if (flags & KEY_BUTTON_MOTION_VIRTUAL) {
3002 event.general.xkey.state = pat.needMods;
3003 if ((flags & KEY) && (event.general.xany.type != MouseWheelEvent)) {
3004 TkpSetKeycodeAndState(tkwin, pat.detail.keySym, &event.general);
3893 event.general.xkey.state = pat.modMask;
3894 if ((flags & KEY) && event.general.xany.type != MouseWheelEvent) {
3895 TkpSetKeycodeAndState(tkwin, pat.info, &event.general);
30053896 } else if (flags & BUTTON) {
3006 event.general.xbutton.button = pat.detail.button;
3897 event.general.xbutton.button = pat.info;
30073898 } else if (flags & VIRTUAL) {
3008 event.virtual.name = pat.detail.name;
3899 event.virtual.name = pat.name;
30093900 }
30103901 }
30113902 if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) {
30173908 event.general.xkey.y_root = -1;
30183909 }
30193910
3020 if (event.general.xany.type == FocusIn
3021 || event.general.xany.type == FocusOut) {
3911 if (event.general.xany.type == FocusIn || event.general.xany.type == FocusOut) {
30223912 event.general.xany.send_event = GENERATED_FOCUS_EVENT_MAGIC;
30233913 }
30243914
30253915 /*
3026 * Process the remaining arguments to fill in additional fields of the
3027 * event.
3916 * Process the remaining arguments to fill in additional fields of the event.
30283917 */
30293918
30303919 synch = 1;
30313920 warp = 0;
30323921 pos = TCL_QUEUE_TAIL;
3033 for (i = 2; i < objc; i += 2) {
3922
3923 for (i = 2; i < (unsigned) objc; i += 2) {
30343924 Tcl_Obj *optionPtr, *valuePtr;
3925 int badOpt = 0;
30353926 int index;
30363927
30373928 optionPtr = objv[i];
30413932 sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
30423933 return TCL_ERROR;
30433934 }
3044 if (objc & 1) {
3935 if (IsOdd(objc)) {
30453936 /*
30463937 * This test occurs after Tcl_GetIndexFromObj() so that "event
30473938 * generate <Button> -xyz" will return the error message that
30613952 return TCL_ERROR;
30623953 }
30633954 if (!(flags & KEY_BUTTON_MOTION_VIRTUAL)) {
3064 goto badopt;
3955 badOpt = 1;
30653956 }
30663957 break;
30673958 case EVENT_WHEN:
3068 pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr,
3069 queuePosition, valuePtr);
3959 pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr, queuePosition, valuePtr);
30703960 if ((int) pos < -1) {
30713961 return TCL_ERROR;
30723962 }
3073 synch = 0;
3074 if ((int) pos == -1) {
3075 synch = 1;
3076 }
3963 synch = ((int) pos == -1);
30773964 break;
30783965 case EVENT_ABOVE:
3079 if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
3966 if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {
30803967 return TCL_ERROR;
30813968 }
30823969 if (flags & CONFIG) {
30833970 event.general.xconfigure.above = Tk_WindowId(tkwin2);
30843971 } else {
3085 goto badopt;
3972 badOpt = 1;
30863973 }
30873974 break;
30883975 case EVENT_BORDER:
3089 if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
3976 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
30903977 return TCL_ERROR;
30913978 }
30923979 if (flags & (CREATE|CONFIG)) {
30933980 event.general.xcreatewindow.border_width = number;
30943981 } else {
3095 goto badopt;
3982 badOpt = 1;
30963983 }
30973984 break;
30983985 case EVENT_BUTTON:
31023989 if (flags & BUTTON) {
31033990 event.general.xbutton.button = number;
31043991 } else {
3105 goto badopt;
3992 badOpt = 1;
31063993 }
31073994 break;
31083995 case EVENT_COUNT:
31123999 if (flags & EXPOSE) {
31134000 event.general.xexpose.count = number;
31144001 } else {
3115 goto badopt;
4002 badOpt = 1;
31164003 }
31174004 break;
31184005 case EVENT_DATA:
31224009 * completes and we know that the event generation is really
31234010 * going to happen.
31244011 */
3125
31264012 userDataObj = valuePtr;
31274013 } else {
3128 goto badopt;
4014 badOpt = 1;
31294015 }
31304016 break;
31314017 case EVENT_DELTA:
31324018 if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
31334019 return TCL_ERROR;
31344020 }
3135 if ((flags & KEY) && (event.general.xkey.type == MouseWheelEvent)) {
4021 if ((flags & KEY) && event.general.xkey.type == MouseWheelEvent) {
31364022 event.general.xkey.keycode = number;
31374023 } else {
3138 goto badopt;
4024 badOpt = 1;
31394025 }
31404026 break;
31414027 case EVENT_DETAIL:
3142 number = TkFindStateNumObj(interp, optionPtr, notifyDetail,
3143 valuePtr);
4028 number = TkFindStateNumObj(interp, optionPtr, notifyDetail, valuePtr);
31444029 if (number < 0) {
31454030 return TCL_ERROR;
31464031 }
31494034 } else if (flags & CROSSING) {
31504035 event.general.xcrossing.detail = number;
31514036 } else {
3152 goto badopt;
4037 badOpt = 1;
31534038 }
31544039 break;
31554040 case EVENT_FOCUS:
31594044 if (flags & CROSSING) {
31604045 event.general.xcrossing.focus = number;
31614046 } else {
3162 goto badopt;
4047 badOpt = 1;
31634048 }
31644049 break;
31654050 case EVENT_HEIGHT:
3166 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr,
3167 &number) != TCL_OK) {
4051 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
31684052 return TCL_ERROR;
31694053 }
31704054 if (flags & EXPOSE) {
31724056 } else if (flags & CONFIG) {
31734057 event.general.xconfigure.height = number;
31744058 } else {
3175 goto badopt;
4059 badOpt = 1;
31764060 }
31774061 break;
31784062 case EVENT_KEYCODE:
31794063 if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
31804064 return TCL_ERROR;
31814065 }
3182 if ((flags & KEY) && (event.general.xkey.type != MouseWheelEvent)) {
4066 if ((flags & KEY) && event.general.xkey.type != MouseWheelEvent) {
31834067 event.general.xkey.keycode = number;
31844068 } else {
3185 goto badopt;
4069 badOpt = 1;
31864070 }
31874071 break;
31884072 case EVENT_KEYSYM: {
31924076 value = Tcl_GetString(valuePtr);
31934077 keysym = TkStringToKeysym(value);
31944078 if (keysym == NoSymbol) {
3195 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3196 "unknown keysym \"%s\"", value));
3197 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYSYM", value,
3198 NULL);
4079 Tcl_SetObjResult(interp, Tcl_ObjPrintf("unknown keysym \"%s\"", value));
4080 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYSYM", value, NULL);
31994081 return TCL_ERROR;
32004082 }
32014083
32024084 TkpSetKeycodeAndState(tkwin, keysym, &event.general);
32034085 if (event.general.xkey.keycode == 0) {
3204 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3205 "no keycode for keysym \"%s\"", value));
3206 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYCODE", value,
3207 NULL);
4086 Tcl_SetObjResult(interp, Tcl_ObjPrintf("no keycode for keysym \"%s\"", value));
4087 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYCODE", value, NULL);
32084088 return TCL_ERROR;
32094089 }
3210 if (!(flags & KEY)
3211 || (event.general.xkey.type == MouseWheelEvent)) {
3212 goto badopt;
4090 if (!(flags & KEY) || (event.general.xkey.type == MouseWheelEvent)) {
4091 badOpt = 1;
32134092 }
32144093 break;
32154094 }
32164095 case EVENT_MODE:
3217 number = TkFindStateNumObj(interp,optionPtr,notifyMode,valuePtr);
3218 if (number < 0) {
4096 if ((number = TkFindStateNumObj(interp, optionPtr, notifyMode, valuePtr)) < 0) {
32194097 return TCL_ERROR;
32204098 }
32214099 if (flags & CROSSING) {
32234101 } else if (flags & FOCUS) {
32244102 event.general.xfocus.mode = number;
32254103 } else {
3226 goto badopt;
4104 badOpt = 1;
32274105 }
32284106 break;
32294107 case EVENT_OVERRIDE:
32394117 } else if (flags & CONFIG) {
32404118 event.general.xconfigure.override_redirect = number;
32414119 } else {
3242 goto badopt;
4120 badOpt = 1;
32434121 }
32444122 break;
32454123 case EVENT_PLACE:
3246 number = TkFindStateNumObj(interp, optionPtr, circPlace, valuePtr);
3247 if (number < 0) {
4124 if ((number = TkFindStateNumObj(interp, optionPtr, circPlace, valuePtr)) < 0) {
32484125 return TCL_ERROR;
32494126 }
32504127 if (flags & CIRC) {
32514128 event.general.xcirculate.place = number;
32524129 } else {
3253 goto badopt;
4130 badOpt = 1;
32544131 }
32554132 break;
32564133 case EVENT_ROOT:
3257 if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
4134 if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {
32584135 return TCL_ERROR;
32594136 }
32604137 if (flags & KEY_BUTTON_MOTION_CROSSING) {
32614138 event.general.xkey.root = Tk_WindowId(tkwin2);
32624139 } else {
3263 goto badopt;
4140 badOpt = 1;
32644141 }
32654142 break;
32664143 case EVENT_ROOTX:
3267 if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
4144 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
32684145 return TCL_ERROR;
32694146 }
32704147 if (flags & KEY_BUTTON_MOTION_CROSSING) {
32714148 event.general.xkey.x_root = number;
32724149 } else {
3273 goto badopt;
4150 badOpt = 1;
32744151 }
32754152 break;
32764153 case EVENT_ROOTY:
3277 if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
4154 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
32784155 return TCL_ERROR;
32794156 }
32804157 if (flags & KEY_BUTTON_MOTION_CROSSING) {
32814158 event.general.xkey.y_root = number;
32824159 } else {
3283 goto badopt;
4160 badOpt = 1;
32844161 }
32854162 break;
32864163 case EVENT_SEND: {
32924169 * Allow arbitrary integer values for the field; they are
32934170 * needed by a few of the tests in the Tk test suite.
32944171 */
3295
32964172 if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
32974173 return TCL_ERROR;
32984174 }
3299 } else {
3300 if (Tcl_GetBooleanFromObj(interp,valuePtr,&number) != TCL_OK) {
3301 return TCL_ERROR;
4175 if (number) {
4176 /*
4177 * send_event only expects 1 or 0. We cannot allow arbitrary non-zero
4178 * values, otherwise the thing with GENERATED_FOCUS_EVENT_MAGIC will not
4179 * work.
4180 */
4181 number = 1;
33024182 }
3303 }
3304 event.general.xany.send_event = number;
4183 } else if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) {
4184 return TCL_ERROR;
4185 }
4186 event.general.xany.send_event |= number;
33054187 break;
33064188 }
33074189 case EVENT_SERIAL:
33214203 event.general.xcrossing.state = number;
33224204 }
33234205 } else if (flags & VISIBILITY) {
3324 number = TkFindStateNumObj(interp, optionPtr, visNotify,
3325 valuePtr);
3326 if (number < 0) {
4206 if ((number = TkFindStateNumObj(interp, optionPtr, visNotify, valuePtr)) < 0) {
33274207 return TCL_ERROR;
33284208 }
33294209 event.general.xvisibility.state = number;
33304210 } else {
3331 goto badopt;
4211 badOpt = 1;
33324212 }
33334213 break;
33344214 case EVENT_SUBWINDOW:
3335 if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
4215 if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {
33364216 return TCL_ERROR;
33374217 }
33384218 if (flags & KEY_BUTTON_MOTION_CROSSING) {
33394219 event.general.xkey.subwindow = Tk_WindowId(tkwin2);
33404220 } else {
3341 goto badopt;
3342 }
3343 break;
3344 case EVENT_TIME:
3345 if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
4221 badOpt = 1;
4222 }
4223 break;
4224 case EVENT_TIME: {
4225 if (strcmp(Tcl_GetString(valuePtr), "current") == 0) {
4226 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
4227 BindInfo *biPtr = mainPtr->mainPtr->bindInfo;
4228 number = dispPtr->lastEventTime + (CurrentTimeInMilliSecs() - biPtr->lastCurrentTime);
4229 } else if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
33464230 return TCL_ERROR;
33474231 }
33484232 if (flags & KEY_BUTTON_MOTION_CROSSING) {
33504234 } else if (flags & PROP) {
33514235 event.general.xproperty.time = number;
33524236 } else {
3353 goto badopt;
3354 }
3355 break;
4237 badOpt = 1;
4238 }
4239 break;
4240 }
33564241 case EVENT_WIDTH:
3357 if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
4242 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
33584243 return TCL_ERROR;
33594244 }
33604245 if (flags & EXPOSE) {
33624247 } else if (flags & (CREATE|CONFIG)) {
33634248 event.general.xcreatewindow.width = number;
33644249 } else {
3365 goto badopt;
4250 badOpt = 1;
33664251 }
33674252 break;
33684253 case EVENT_WINDOW:
3369 if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
4254 if (!NameToWindow(interp, tkwin, valuePtr, &tkwin2)) {
33704255 return TCL_ERROR;
33714256 }
33724257 if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) {
33734258 event.general.xcreatewindow.window = Tk_WindowId(tkwin2);
33744259 } else {
3375 goto badopt;
4260 badOpt = 1;
33764261 }
33774262 break;
33784263 case EVENT_X:
3379 if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
4264 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
33804265 return TCL_ERROR;
33814266 }
33824267 if (flags & KEY_BUTTON_MOTION_CROSSING) {
33994284 } else if (flags & REPARENT) {
34004285 event.general.xreparent.x = number;
34014286 } else {
3402 goto badopt;
4287 badOpt = 1;
34034288 }
34044289 break;
34054290 case EVENT_Y:
3406 if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) {
4291 if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
34074292 return TCL_ERROR;
34084293 }
34094294 if (flags & KEY_BUTTON_MOTION_CROSSING) {
34264311 } else if (flags & REPARENT) {
34274312 event.general.xreparent.y = number;
34284313 } else {
3429 goto badopt;
3430 }
3431 break;
3432 }
3433 continue;
3434
3435 badopt:
3436 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3437 "%s event doesn't accept \"%s\" option",
3438 name, Tcl_GetString(optionPtr)));
3439 Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_OPTION", NULL);
3440 return TCL_ERROR;
4314 badOpt = 1;
4315 }
4316 break;
4317 }
4318
4319 if (badOpt) {
4320 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
4321 "%s event doesn't accept \"%s\" option", name, Tcl_GetString(optionPtr)));
4322 Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_OPTION", NULL);
4323 return TCL_ERROR;
4324 }
34414325 }
34424326
34434327 /*
34444328 * Don't generate events for windows that don't exist yet.
34454329 */
34464330
3447 if (!event.general.xany.window) {
3448 goto done;
3449 }
3450
3451 if (userDataObj != NULL) {
4331 if (event.general.xany.window) {
4332 if (userDataObj) {
4333 /*
4334 * Must be virtual event to set that variable to non-NULL. Now we want
4335 * to install the object into the event. Note that we must incr the
4336 * refcount before firing it into the low-level event subsystem; the
4337 * refcount will be decremented once the event has been processed.
4338 */
4339 event.virtual.user_data = userDataObj;
4340 Tcl_IncrRefCount(userDataObj);
4341 }
34524342
34534343 /*
3454 * Must be virtual event to set that variable to non-NULL. Now we want
3455 * to install the object into the event. Note that we must incr the
3456 * refcount before firing it into the low-level event subsystem; the
3457 * refcount will be decremented once the event has been processed.
4344 * Now we have constructed the event, inject it into the event handling
4345 * code.
34584346 */
34594347
3460 event.virtual.user_data = userDataObj;
3461 Tcl_IncrRefCount(userDataObj);
3462 }
3463
3464 /*
3465 * Now we have constructed the event, inject it into the event handling
3466 * code.
3467 */
3468
3469 if (synch != 0) {
3470 Tk_HandleEvent(&event.general);
3471 } else {
3472 Tk_QueueWindowEvent(&event.general, pos);
3473 }
3474
3475 /*
3476 * We only allow warping if the window is mapped.
3477 */
3478
3479 if ((warp != 0) && Tk_IsMapped(tkwin)) {
3480 TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display);
3481
3482 Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display,
3483 event.general.xmotion.window);
3484
3485 if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) {
3486 Tcl_DoWhenIdle(DoWarp, dispPtr);
3487 dispPtr->flags |= TK_DISPLAY_IN_WARP;
3488 }
3489
3490 if (warpWindow != dispPtr->warpWindow) {
3491 if (warpWindow) {
3492 Tcl_Preserve(warpWindow);
3493 }
3494 if (dispPtr->warpWindow) {
3495 Tcl_Release(dispPtr->warpWindow);
3496 }
3497 dispPtr->warpWindow = warpWindow;
3498 }
3499 dispPtr->warpMainwin = mainWin;
3500 dispPtr->warpX = event.general.xmotion.x;
3501 dispPtr->warpY = event.general.xmotion.y;
3502 }
3503
3504 done:
4348 if (synch) {
4349 Tk_HandleEvent(&event.general);
4350 } else {
4351 Tk_QueueWindowEvent(&event.general, pos);
4352 }
4353
4354 /*
4355 * We only allow warping if the window is mapped.
4356 */
4357
4358 if (warp && Tk_IsMapped(tkwin)) {
4359 TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display);
4360
4361 Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display, event.general.xmotion.window);
4362
4363 if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) {
4364 Tcl_DoWhenIdle(DoWarp, dispPtr);
4365 dispPtr->flags |= TK_DISPLAY_IN_WARP;
4366 }
4367
4368 if (warpWindow != dispPtr->warpWindow) {
4369 if (warpWindow) {
4370 Tcl_Preserve(warpWindow);
4371 }
4372 if (dispPtr->warpWindow) {
4373 Tcl_Release(dispPtr->warpWindow);
4374 }
4375 dispPtr->warpWindow = warpWindow;
4376 }
4377 dispPtr->warpMainwin = mainWin;
4378 dispPtr->warpX = event.general.xmotion.x;
4379 dispPtr->warpY = event.general.xmotion.y;
4380 }
4381 }
4382
35054383 Tcl_ResetResult(interp);
35064384 return TCL_OK;
35074385 }
4386 /*
4387 *---------------------------------------------------------------------------
4388 *
4389 * NameToWindow --
4390 *
4391 * Helper function for lookup of a window given its path name. Our
4392 * version is able to handle window id's.
4393 *
4394 * Results:
4395 * None.
4396 *
4397 * Side effects:
4398 * None.
4399 *
4400 *---------------------------------------------------------------------------
4401 */
35084402
35094403 static int
35104404 NameToWindow(
35134407 Tcl_Obj *objPtr, /* Contains name or id string of window. */
35144408 Tk_Window *tkwinPtr) /* Filled with token for window. */
35154409 {
3516 const char *name = Tcl_GetString(objPtr);
4410 const char *name;
35174411 Tk_Window tkwin;
35184412
4413 assert(mainWin);
4414 assert(objPtr);
4415 assert(tkwinPtr);
4416
4417 name = Tcl_GetString(objPtr);
4418
35194419 if (name[0] == '.') {
3520 tkwin = Tk_NameToWindow(interp, name, mainWin);
3521 if (tkwin == NULL) {
3522 return TCL_ERROR;
4420 if (!(tkwin = Tk_NameToWindow(interp, name, mainWin))) {
4421 return 0;
35234422 }
35244423 } else {
35254424 Window id;
35264425
4426 tkwin = NULL;
4427
35274428 /*
3528 * Check for the winPtr being valid, even if it looks ok to
4429 * Check for the winPtr being valid, even if it looks okay to
35294430 * TkpScanWindowId. [Bug #411307]
35304431 */
35314432
3532 if (TkpScanWindowId(NULL, name, &id) != TCL_OK) {
3533 goto badWindow;
3534 }
3535 tkwin = Tk_IdToWindow(Tk_Display(mainWin), id);
3536 if (tkwin == NULL) {
3537 goto badWindow;
3538 }
3539 }
4433 if (TkpScanWindowId(NULL, name, &id) == TCL_OK) {
4434 tkwin = Tk_IdToWindow(Tk_Display(mainWin), id);
4435 }
4436
4437 if (!tkwin) {
4438 Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad window name/identifier \"%s\"", name));
4439 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW_ID", name, NULL);
4440 return 0;
4441 }
4442 }
4443
4444 assert(tkwin);
35404445 *tkwinPtr = tkwin;
3541 return TCL_OK;
3542
3543 badWindow:
3544 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3545 "bad window name/identifier \"%s\"", name));
3546 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW_ID", name, NULL);
3547 return TCL_ERROR;
4446 return 1;
35484447 }
35494448
35504449 /*
35684467 ClientData clientData)
35694468 {
35704469 TkDisplay *dispPtr = clientData;
4470
4471 assert(clientData);
35714472
35724473 /*
35734474 * DoWarp was scheduled only if the window was mapped. It needs to be
35774478 * the whole screen.
35784479 */
35794480
3580 if ((dispPtr->warpWindow == NULL) ||
3581 (Tk_IsMapped(dispPtr->warpWindow)
3582 && (Tk_WindowId(dispPtr->warpWindow) != None))) {
4481 if (!dispPtr->warpWindow ||
4482 (Tk_IsMapped(dispPtr->warpWindow) && Tk_WindowId(dispPtr->warpWindow) != None)) {
35834483 TkpWarpPointer(dispPtr);
35844484 XForceScreenSaver(dispPtr->display, ScreenSaverReset);
35854485 }
35864486
35874487 if (dispPtr->warpWindow) {
35884488 Tcl_Release(dispPtr->warpWindow);
3589 dispPtr->warpWindow = None;
4489 dispPtr->warpWindow = NULL;
35904490 }
35914491 dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
35924492 }
36194519 Tk_Uid uid;
36204520 size_t length;
36214521
4522 assert(virtString);
4523
36224524 length = strlen(virtString);
36234525
3624 if (length < 5 || virtString[0] != '<' || virtString[1] != '<' ||
3625 virtString[length - 2] != '>' || virtString[length - 1] != '>') {
3626 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3627 "virtual event \"%s\" is badly formed", virtString));
4526 if (length < 5
4527 || virtString[0] != '<'
4528 || virtString[1] != '<'
4529 || virtString[length - 2] != '>'
4530 || virtString[length - 1] != '>') {
4531 Tcl_SetObjResult(interp, Tcl_ObjPrintf("virtual event \"%s\" is badly formed", virtString));
36284532 Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "MALFORMED", NULL);
36294533 return NULL;
36304534 }
36624566 static PatSeq *
36634567 FindSequence(
36644568 Tcl_Interp *interp, /* Interpreter to use for error reporting. */
3665 Tcl_HashTable *patternTablePtr,
3666 /* Table to use for lookup. */
3667 ClientData object, /* For binding table, token for object with
3668 * which binding is associated. For virtual
3669 * event table, NULL. */
3670 const char *eventString, /* String description of pattern to match on.
3671 * See user documentation for details. */
3672 int create, /* 0 means don't create the entry if it
3673 * doesn't already exist. Non-zero means
3674 * create. */
3675 int allowVirtual, /* 0 means that virtual events are not allowed
3676 * in the sequence. Non-zero otherwise. */
3677 unsigned long *maskPtr) /* *maskPtr is filled in with the event types
3678 * on which this pattern sequence depends. */
3679 {
3680 TkPattern pats[EVENT_BUFFER_SIZE];
3681 int numPats, virtualFound;
3682 const char *p;
4569 LookupTables *lookupTables, /* Tables used for lookup. */
4570 ClientData object, /* For binding table, token for object with which binding is
4571 * associated. For virtual event table, NULL. */
4572 const char *eventString, /* String description of pattern to match on. See user
4573 * documentation for details. */
4574 int create, /* 0 means don't create the entry if it doesn't already exist.
4575 * 1 means create. */
4576 int allowVirtual, /* 0 means that virtual events are not allowed in the sequence.
4577 * 1 otherwise. */
4578 EventMask *maskPtr) /* *maskPtr is filled in with the event types on which this
4579 * pattern sequence depends. */
4580 {
4581 unsigned patsBufSize = 1;
4582 unsigned numPats;
4583 unsigned totalCount = 0;
4584 int virtualFound = 0;
4585 const char *p = eventString;
36834586 TkPattern *patPtr;
36844587 PatSeq *psPtr;
36854588 Tcl_HashEntry *hPtr;
3686 int flags, count, isNew;
3687 size_t sequenceSize;
3688 unsigned long eventMask;
4589 int isNew;
4590 unsigned count;
4591 unsigned maxCount = 0;
4592 EventMask eventMask = 0;
4593 ModMask modMask = 0;
36894594 PatternTableKey key;
36904595
4596 assert(lookupTables);
4597 assert(eventString);
4598
4599 psPtr = ckalloc(PATSEQ_MEMSIZE(patsBufSize));
4600
36914601 /*
3692 *-------------------------------------------------------------
3693 * Step 1: parse the pattern string to produce an array of Patterns. The
3694 * array is generated backwards, so that the lowest-indexed pattern
3695 * corresponds to the last event that must occur.
3696 *-------------------------------------------------------------
4602 *------------------------------------------------------------------
4603 * Step 1: parse the pattern string to produce an array of Patterns.
4604 *------------------------------------------------------------------
36974605 */
36984606
3699 p = eventString;
3700 flags = 0;
3701 eventMask = 0;
3702 virtualFound = 0;
3703
3704 patPtr = &pats[EVENT_BUFFER_SIZE-1];
3705 for (numPats = 0; numPats < EVENT_BUFFER_SIZE; numPats++, patPtr--) {
3706 while (isspace(UCHAR(*p))) {
3707 p++;
3708 }
3709 if (*p == '\0') {
3710 break;
3711 }
3712
3713 count = ParseEventDescription(interp, &p, patPtr, &eventMask);
3714 if (count == 0) {
4607 for (patPtr = psPtr->pats, numPats = 0; *(p = SkipSpaces(p)); ++patPtr, ++numPats) {
4608 if (numPats >= patsBufSize) {
4609 unsigned pos = patPtr - psPtr->pats;
4610 patsBufSize += patsBufSize;
4611 psPtr = ckrealloc(psPtr, PATSEQ_MEMSIZE(patsBufSize));
4612 patPtr = psPtr->pats + pos;
4613 }
4614
4615 if ((count = ParseEventDescription(interp, &p, patPtr, &eventMask)) == 0) {
4616 /* error encountered */
4617 ckfree(psPtr);
37154618 return NULL;
37164619 }
37174620
37184621 if (eventMask & VirtualEventMask) {
3719 if (allowVirtual == 0) {
4622 if (!allowVirtual) {
37204623 Tcl_SetObjResult(interp, Tcl_NewStringObj(
3721 "virtual event not allowed in definition of another virtual event",
3722 -1));
3723 Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "INNER",
3724 NULL);
4624 "virtual event not allowed in definition of another virtual event", -1));
4625 Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "INNER", NULL);
4626 ckfree(psPtr);
37254627 return NULL;
37264628 }
37274629 virtualFound = 1;
37284630 }
37294631
3730 /*
3731 * Replicate events for DOUBLE, TRIPLE, QUADRUPLE.
3732 */
3733
3734 while ((count-- > 1) && (numPats < EVENT_BUFFER_SIZE-1)) {
3735 flags |= PAT_NEARBY;
3736 patPtr[-1] = patPtr[0];
3737 patPtr--;
3738 numPats++;
3739 }
4632 if (count > 1u) {
4633 maxCount = Max(count, maxCount);
4634 }
4635
4636 totalCount += count;
4637 modMask |= patPtr->modMask;
37404638 }
37414639
37424640 /*
3743 *-------------------------------------------------------------
3744 * Step 2: find the sequence in the binding table if it exists, and add a
3745 * new sequence to the table if it doesn't.
3746 *-------------------------------------------------------------
4641 *------------------------------------------------------------------
4642 * Step 2: find the sequence in the binding table if it exists, and
4643 * add a new sequence to the table if it doesn't.
4644 *------------------------------------------------------------------
37474645 */
37484646
37494647 if (numPats == 0) {
3750 Tcl_SetObjResult(interp, Tcl_NewStringObj(
3751 "no events specified in binding", -1));
4648 Tcl_SetObjResult(interp, Tcl_NewStringObj("no events specified in binding", -1));
37524649 Tcl_SetErrorCode(interp, "TK", "EVENT", "NO_EVENTS", NULL);
4650 ckfree(psPtr);
37534651 return NULL;
37544652 }
3755 if ((numPats > 1) && (virtualFound != 0)) {
3756 Tcl_SetObjResult(interp, Tcl_NewStringObj(
3757 "virtual events may not be composed", -1));
3758 Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "COMPOSITION",
3759 NULL);
4653 if (numPats > 1u && virtualFound) {
4654 Tcl_SetObjResult(interp, Tcl_NewStringObj("virtual events may not be composed", -1));
4655 Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "COMPOSITION", NULL);
4656 ckfree(psPtr);
37604657 return NULL;
37614658 }
3762
3763 patPtr = &pats[EVENT_BUFFER_SIZE-numPats];
3764 memset(&key, 0, sizeof(key));
3765 key.object = object;
3766 key.type = patPtr->eventType;
3767 key.detail = patPtr->detail;
3768 hPtr = Tcl_CreateHashEntry(patternTablePtr, (char *) &key, &isNew);
3769 sequenceSize = numPats*sizeof(TkPattern);
4659 if (patsBufSize > numPats) {
4660 psPtr = ckrealloc(psPtr, PATSEQ_MEMSIZE(numPats));
4661 }
4662
4663 patPtr = psPtr->pats;
4664 psPtr->object = object;
4665 SetupPatternKey(&key, psPtr);
4666 hPtr = Tcl_CreateHashEntry(&lookupTables->patternTable, (char *) &key, &isNew);
37704667 if (!isNew) {
3771 for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL;
3772 psPtr = psPtr->nextSeqPtr) {
3773 if ((numPats == psPtr->numPats)
3774 && ((flags & PAT_NEARBY) == (psPtr->flags & PAT_NEARBY))
3775 && (memcmp(patPtr, psPtr->pats, sequenceSize) == 0)) {
3776 goto done;
4668 unsigned sequenceSize = numPats*sizeof(TkPattern);
4669 PatSeq *psPtr2;
4670
4671 for (psPtr2 = Tcl_GetHashValue(hPtr); psPtr2; psPtr2 = psPtr2->nextSeqPtr) {
4672 assert(TEST_PSENTRY(psPtr2));
4673 if (numPats == psPtr2->numPats && memcmp(patPtr, psPtr2->pats, sequenceSize) == 0) {
4674 ckfree(psPtr);
4675 if (maskPtr) {
4676 *maskPtr = eventMask;
4677 }
4678 return psPtr2;
37774679 }
37784680 }
37794681 }
37904692 * silently ignore missing bindings.
37914693 */
37924694
4695 ckfree(psPtr);
37934696 return NULL;
37944697 }
3795 psPtr = ckalloc(sizeof(PatSeq) + (numPats-1)*sizeof(TkPattern));
4698
4699 DEBUG(countSeqItems += 1;)
4700
37964701 psPtr->numPats = numPats;
4702 psPtr->count = totalCount;
4703 psPtr->number = lookupTables->number++;
4704 psPtr->added = 0;
4705 psPtr->modMaskUsed = (modMask != 0);
37974706 psPtr->script = NULL;
3798 psPtr->flags = flags;
37994707 psPtr->nextSeqPtr = Tcl_GetHashValue(hPtr);
38004708 psPtr->hPtr = hPtr;
3801 psPtr->voPtr = NULL;
3802 psPtr->nextObjPtr = NULL;
4709 psPtr->ptr.nextObj = NULL;
4710 assert(psPtr->ptr.owners == NULL);
4711 DEBUG(psPtr->owned = 0;)
38034712 Tcl_SetHashValue(hPtr, psPtr);
38044713
3805 memcpy(psPtr->pats, patPtr, sequenceSize);
3806
3807 done:
3808 *maskPtr = eventMask;
4714 if (maskPtr) {
4715 *maskPtr = eventMask;
4716 }
38094717 return psPtr;
38104718 }
38114719
38304738 *---------------------------------------------------------------------------
38314739 */
38324740
3833 static int
4741 /* helper function */
4742 static unsigned
4743 FinalizeParseEventDescription(
4744 Tcl_Interp *interp,
4745 TkPattern *patPtr,
4746 unsigned count,
4747 Tcl_Obj* errorObj,
4748 const char* errCode)
4749 {
4750 assert(patPtr);
4751 assert(!errorObj == (count > 0));
4752
4753 if (errorObj) {
4754 Tcl_SetObjResult(interp, errorObj);
4755 Tcl_SetErrorCode(interp, "TK", "EVENT", errCode, NULL);
4756 }
4757 patPtr->count = count;
4758 return count;
4759 }
4760
4761 static unsigned
38344762 ParseEventDescription(
38354763 Tcl_Interp *interp, /* For error messages. */
3836 const char **eventStringPtr,/* On input, holds a pointer to start of event
3837 * string. On exit, gets pointer to rest of
3838 * string after parsed event. */
3839 TkPattern *patPtr, /* Filled with the pattern parsed from the
3840 * event string. */
3841 unsigned long *eventMaskPtr)/* Filled with event mask of matched event. */
3842 {
3843 char *p;
3844 unsigned long eventMask;
3845 int count, eventFlags;
3846 #define FIELD_SIZE 48
3847 char field[FIELD_SIZE];
3848 Tcl_HashEntry *hPtr;
3849 Tcl_DString copy;
3850
3851 Tcl_DStringInit(&copy);
3852 p = Tcl_DStringAppend(&copy, *eventStringPtr, -1);
3853
3854 patPtr->eventType = -1;
3855 patPtr->needMods = 0;
3856 patPtr->detail.clientData = 0;
3857
3858 eventMask = 0;
3859 count = 1;
4764 const char **eventStringPtr,/* On input, holds a pointer to start of event string. On exit,
4765 * gets pointer to rest of string after parsed event. */
4766 TkPattern *patPtr, /* Filled with the pattern parsed from the event string. */
4767 EventMask *eventMaskPtr) /* Filled with event mask of matched event. */
4768 {
4769 const char *p;
4770 EventMask eventMask = 0;
4771 unsigned count = 1;
4772
4773 assert(eventStringPtr);
4774 assert(patPtr);
4775 assert(eventMaskPtr);
4776
4777 p = *eventStringPtr;
4778 memset(patPtr, 0, sizeof(TkPattern)); /* otherwise memcmp doesn't work */
38604779
38614780 /*
38624781 * Handle simple ASCII characters.
38684787 patPtr->eventType = KeyPress;
38694788 eventMask = KeyPressMask;
38704789 string[0] = *p;
3871 string[1] = 0;
3872 patPtr->detail.keySym = TkStringToKeysym(string);
3873 if (patPtr->detail.keySym == NoSymbol) {
3874 if (isprint(UCHAR(*p))) {
3875 patPtr->detail.keySym = *p;
3876 } else {
3877 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3878 "bad ASCII character 0x%x", UCHAR(*p)));
3879 Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_CHAR", NULL);
3880 count = 0;
3881 goto done;
3882 }
3883 }
3884 p++;
3885 goto end;
3886 }
3887
3888 /*
3889 * A fancier event description. This can be either a virtual event or a
3890 * physical event.
3891 *
3892 * A virtual event description consists of:
3893 *
3894 * 1. double open angle brackets.
3895 * 2. virtual event name.
3896 * 3. double close angle brackets.
3897 *
3898 * A physical event description consists of:
3899 *
3900 * 1. open angle bracket.
3901 * 2. any number of modifiers, each followed by spaces or dashes.
3902 * 3. an optional event name.
3903 * 4. an option button or keysym name. Either this or item 3 *must* be
3904 * present; if both are present then they are separated by spaces or
3905 * dashes.
3906 * 5. a close angle bracket.
3907 */
3908
3909 p++;
3910 if (*p == '<') {
4790 string[1] = '\0';
4791 patPtr->info = TkStringToKeysym(string);
4792 if (patPtr->info == NoSymbol) {
4793 if (!isprint(UCHAR(*p))) {
4794 return FinalizeParseEventDescription(
4795 interp,
4796 patPtr, 0,
4797 Tcl_ObjPrintf("bad ASCII character 0x%x", UCHAR(*p)), "BAD_CHAR");
4798 }
4799 patPtr->info = *p;
4800 }
4801 ++p;
4802 } else {
39114803 /*
3912 * This is a virtual event: soak up all the characters up to the next
3913 * '>'.
4804 * A fancier event description. This can be either a virtual event or a physical event.
4805 *
4806 * A virtual event description consists of:
4807 *
4808 * 1. double open angle brackets.
4809 * 2. virtual event name.
4810 * 3. double close angle brackets.
4811 *
4812 * A physical event description consists of:
4813 *
4814 * 1. open angle bracket.
4815 * 2. any number of modifiers, each followed by spaces or dashes.
4816 * 3. an optional event name.
4817 * 4. an option button or keysym name. Either this or item 3 *must* be present; if both
4818 * are present then they are separated by spaces or dashes.
4819 * 5. a close angle bracket.
39144820 */
39154821
3916 char *field = p + 1;
3917
3918 p = strchr(field, '>');
3919 if (p == field) {
3920 Tcl_SetObjResult(interp, Tcl_NewStringObj(
3921 "virtual event \"<<>>\" is badly formed", -1));
3922 Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "MALFORMED",
3923 NULL);
3924 count = 0;
3925 goto done;
3926 }
3927 if ((p == NULL) || (p[1] != '>')) {
3928 Tcl_SetObjResult(interp, Tcl_NewStringObj(
3929 "missing \">\" in virtual binding", -1));
3930 Tcl_SetErrorCode(interp, "TK", "EVENT", "VIRTUAL", "MALFORMED",
3931 NULL);
3932 count = 0;
3933 goto done;
3934 }
3935 *p = '\0';
3936 patPtr->eventType = VirtualEvent;
3937 eventMask = VirtualEventMask;
3938 patPtr->detail.name = Tk_GetUid(field);
3939 *p = '>';
3940
3941 p += 2;
3942 goto end;
3943 }
3944
3945 while (1) {
3946 ModInfo *modPtr;
3947
3948 p = GetField(p, field, FIELD_SIZE);
3949 if (*p == '>') {
4822 ++p;
4823 if (*p == '<') {
39504824 /*
3951 * This solves the problem of, e.g., <Control-M> being
3952 * misinterpreted as Control + Meta + missing keysym instead of
3953 * Control + KeyPress + M.
4825 * This is a virtual event: soak up all the characters up to the next '>'.
39544826 */
39554827
3956 break;
3957 }
3958 hPtr = Tcl_FindHashEntry(&modTable, field);
3959 if (hPtr == NULL) {
3960 break;
3961 }
3962 modPtr = Tcl_GetHashValue(hPtr);
3963 patPtr->needMods |= modPtr->mask;
3964 if (modPtr->flags & MULT_CLICKS) {
3965 int i = modPtr->flags & MULT_CLICKS;
3966
3967 count = 2;
3968 while (i >>= 1) {
3969 count++;
3970 }
3971 }
3972 while ((*p == '-') || isspace(UCHAR(*p))) {
3973 p++;
3974 }
3975 }
3976
3977 eventFlags = 0;
3978 hPtr = Tcl_FindHashEntry(&eventTable, field);
3979 if (hPtr != NULL) {
3980 const EventInfo *eiPtr = Tcl_GetHashValue(hPtr);
3981
3982 patPtr->eventType = eiPtr->type;
3983 eventFlags = flagArray[eiPtr->type];
3984 eventMask = eiPtr->eventMask;
3985 while ((*p == '-') || isspace(UCHAR(*p))) {
3986 p++;
3987 }
3988 p = GetField(p, field, FIELD_SIZE);
3989 }
3990 if (*field != '\0') {
3991 if ((*field >= '1') && (*field <= '5') && (field[1] == '\0')) {
3992 if (eventFlags == 0) {
3993 patPtr->eventType = ButtonPress;
3994 eventMask = ButtonPressMask;
3995 } else if (eventFlags & KEY) {
3996 goto getKeysym;
3997 } else if (!(eventFlags & BUTTON)) {
3998 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3999 "specified button \"%s\" for non-button event",
4000 field));
4001 Tcl_SetErrorCode(interp, "TK", "EVENT", "NON_BUTTON", NULL);
4002 count = 0;
4003 goto done;
4004 }
4005 patPtr->detail.button = (*field - '0');
4828 const char *field = p + 1;
4829 char buf[256];
4830 char* bufPtr = buf;
4831 unsigned size;
4832
4833 p = strchr(field, '>');
4834 if (p == field) {
4835 return FinalizeParseEventDescription(
4836 interp,
4837 patPtr, 0,
4838 Tcl_NewStringObj("virtual event \"<<>>\" is badly formed", -1), "MALFORMED");
4839 }
4840 if (!p || p[1] != '>') {
4841 return FinalizeParseEventDescription(
4842 interp,
4843 patPtr, 0,
4844 Tcl_NewStringObj("missing \">\" in virtual binding", -1), "MALFORMED");
4845 }
4846
4847 size = p - field;
4848 if (size >= sizeof(buf)) {
4849 bufPtr = ckalloc(size + 1);
4850 }
4851 strncpy(bufPtr, field, size);
4852 bufPtr[size] = '\0';
4853 eventMask = VirtualEventMask;
4854 patPtr->eventType = VirtualEvent;
4855 patPtr->name = Tk_GetUid(bufPtr);
4856 if (bufPtr != buf) {
4857 ckfree(bufPtr);
4858 }
4859 p += 2;
40064860 } else {
4007
4008 getKeysym:
4009 patPtr->detail.keySym = TkStringToKeysym(field);
4010 if (patPtr->detail.keySym == NoSymbol) {
4011 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
4012 "bad event type or keysym \"%s\"", field));
4013 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "KEYSYM", field,
4014 NULL);
4015 count = 0;
4016 goto done;
4017 }
4018 if (eventFlags == 0) {
4019 patPtr->eventType = KeyPress;
4020 eventMask = KeyPressMask;
4021 } else if (!(eventFlags & KEY)) {
4022 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
4023 "specified keysym \"%s\" for non-key event", field));
4024 Tcl_SetErrorCode(interp, "TK", "EVENT", "NON_KEY", NULL);
4025 count = 0;
4026 goto done;
4027 }
4028 }
4029 } else if (eventFlags == 0) {
4030 Tcl_SetObjResult(interp, Tcl_NewStringObj(
4031 "no event type or button # or keysym", -1));
4032 Tcl_SetErrorCode(interp, "TK", "EVENT", "UNMODIFIABLE", NULL);
4033 count = 0;
4034 goto done;
4035 }
4036
4037 while ((*p == '-') || isspace(UCHAR(*p))) {
4038 p++;
4039 }
4040 if (*p != '>') {
4041 while (*p != '\0') {
4042 p++;
4043 if (*p == '>') {
4044 Tcl_SetObjResult(interp, Tcl_NewStringObj(
4045 "extra characters after detail in binding", -1));
4046 Tcl_SetErrorCode(interp, "TK", "EVENT", "PAST_DETAIL", NULL);
4047 count = 0;
4048 goto done;
4049 }
4050 }
4051 Tcl_SetObjResult(interp, Tcl_NewStringObj(
4052 "missing \">\" in binding", -1));
4053 Tcl_SetErrorCode(interp, "TK", "EVENT", "MALFORMED", NULL);
4054 count = 0;
4055 goto done;
4056 }
4057 p++;
4058
4059 end:
4060 *eventStringPtr += (p - Tcl_DStringValue(&copy));
4861 unsigned eventFlags;
4862 char field[512];
4863 Tcl_HashEntry *hPtr;
4864
4865 while (1) {
4866 ModInfo *modPtr;
4867
4868 p = GetField(p, field, sizeof(field));
4869 if (*p == '>') {
4870 /*
4871 * This solves the problem of, e.g., <Control-M> being
4872 * misinterpreted as Control + Meta + missing keysym instead of
4873 * Control + KeyPress + M.
4874 */
4875
4876 break;
4877 }
4878 if (!(hPtr = Tcl_FindHashEntry(&modTable, field))) {
4879 break;
4880 }
4881 modPtr = Tcl_GetHashValue(hPtr);
4882 patPtr->modMask |= modPtr->mask;
4883 if (modPtr->flags & MULT_CLICKS) {
4884 unsigned i = modPtr->flags & MULT_CLICKS;
4885
4886 count = 2;
4887 while (i >>= 1) {
4888 ++count;
4889 }
4890 }
4891 p = SkipFieldDelims(p);
4892 }
4893
4894 eventFlags = 0;
4895 if ((hPtr = Tcl_FindHashEntry(&eventTable, field))) {
4896 const EventInfo *eiPtr = Tcl_GetHashValue(hPtr);
4897
4898 patPtr->eventType = eiPtr->type;
4899 eventFlags = flagArray[eiPtr->type];
4900 eventMask = eiPtr->eventMask;
4901 p = GetField(SkipFieldDelims(p), field, sizeof(field));
4902 }
4903 if (*field) {
4904 unsigned button = GetButtonNumber(field);
4905
4906 if ((eventFlags & BUTTON)
4907 || (button && eventFlags == 0)
4908 || (SUPPORT_ADDITIONAL_MOTION_SYNTAX && (eventFlags & MOTION) && button == 0)) {
4909 /* This must be a button (or bad motion) event */
4910 if (button == 0) {
4911 return FinalizeParseEventDescription(
4912 interp,
4913 patPtr, 0,
4914 Tcl_ObjPrintf("bad button number \"%s\"", field), "BUTTON");
4915 }
4916 patPtr->info = button;
4917 if (!(eventFlags & BUTTON)) {
4918 patPtr->eventType = ButtonPress;
4919 eventMask = ButtonPressMask;
4920 }
4921 } else if ((eventFlags & KEY) || eventFlags == 0) {
4922 /* This must be a key event */
4923 patPtr->info = TkStringToKeysym(field);
4924 if (patPtr->info == NoSymbol) {
4925 return FinalizeParseEventDescription(
4926 interp,
4927 patPtr, 0,
4928 Tcl_ObjPrintf("bad event type or keysym \"%s\"", field), "KEYSYM");
4929 }
4930 if (!(eventFlags & KEY)) {
4931 patPtr->eventType = KeyPress;
4932 eventMask = KeyPressMask;
4933 }
4934 } else if (button) {
4935 if (!SUPPORT_ADDITIONAL_MOTION_SYNTAX || patPtr->eventType != MotionNotify) {
4936 return FinalizeParseEventDescription(
4937 interp,
4938 patPtr, 0,
4939 Tcl_ObjPrintf("specified button \"%s\" for non-button event", field),
4940 "NON_BUTTON");
4941 }
4942 #if SUPPORT_ADDITIONAL_MOTION_SYNTAX
4943 patPtr->modMask |= TkGetButtonMask(button);
4944 p = SkipFieldDelims(p);
4945 while (*p && *p != '>') {
4946 p = SkipFieldDelims(GetField(p, field, sizeof(field)));
4947 if ((button = GetButtonNumber(field)) == 0) {
4948 return FinalizeParseEventDescription(
4949 interp,
4950 patPtr, 0,
4951 Tcl_ObjPrintf("bad button number \"%s\"", field), "BUTTON");
4952 }
4953 patPtr->modMask |= TkGetButtonMask(button);
4954 }
4955 patPtr->info = ButtonNumberFromState(patPtr->modMask);
4956 #endif
4957 } else {
4958 return FinalizeParseEventDescription(
4959 interp,
4960 patPtr, 0,
4961 Tcl_ObjPrintf("specified keysym \"%s\" for non-key event", field),
4962 "NON_KEY");
4963 }
4964 } else if (eventFlags == 0) {
4965 return FinalizeParseEventDescription(
4966 interp,
4967 patPtr, 0,
4968 Tcl_NewStringObj("no event type or button # or keysym", -1), "UNMODIFIABLE");
4969 } else if (patPtr->eventType == MotionNotify) {
4970 patPtr->info = ButtonNumberFromState(patPtr->modMask);
4971 }
4972
4973 p = SkipFieldDelims(p);
4974
4975 if (*p != '>') {
4976 while (*p) {
4977 ++p;
4978 if (*p == '>') {
4979 return FinalizeParseEventDescription(
4980 interp,
4981 patPtr, 0,
4982 Tcl_NewStringObj("extra characters after detail in binding", -1),
4983 "PAST_DETAIL");
4984 }
4985 }
4986 return FinalizeParseEventDescription(
4987 interp,
4988 patPtr, 0,
4989 Tcl_NewStringObj("missing \">\" in binding", -1), "MALFORMED");
4990 }
4991 ++p;
4992 }
4993 }
4994
4995 *eventStringPtr = p;
40614996 *eventMaskPtr |= eventMask;
4062 done:
4063 Tcl_DStringFree(&copy);
4064 return count;
4997 return FinalizeParseEventDescription(interp, patPtr, count, NULL, NULL);
40654998 }
40664999
40675000 /*
40855018 *----------------------------------------------------------------------
40865019 */
40875020
4088 static char *
5021 static const char *
40895022 GetField(
4090 char *p, /* Pointer to part of pattern. */
4091 char *copy, /* Place to copy field. */
4092 int size) /* Maximum number of characters to copy. */
4093 {
4094 while ((*p != '\0') && !isspace(UCHAR(*p)) && (*p != '>')
4095 && (*p != '-') && (size > 1)) {
4096 *copy = *p;
4097 p++;
4098 copy++;
4099 size--;
5023 const char *p, /* Pointer to part of pattern. */
5024 char *copy, /* Place to copy field. */
5025 unsigned size) /* Maximum number of characters to copy. */
5026 {
5027 assert(p);
5028 assert(copy);
5029
5030 for ( ; *p && !isspace(UCHAR(*p)) && *p != '>' && *p != '-' && size > 1u; --size) {
5031 *copy++ = *p++;
41005032 }
41015033 *copy = '\0';
41025034 return p;
41225054
41235055 static Tcl_Obj *
41245056 GetPatternObj(
4125 PatSeq *psPtr)
4126 {
4127 TkPattern *patPtr;
4128 int patsLeft, needMods;
4129 const ModInfo *modPtr;
4130 const EventInfo *eiPtr;
5057 const PatSeq *psPtr)
5058 {
41315059 Tcl_Obj *patternObj = Tcl_NewObj();
4132
4133 /*
4134 * The order of the patterns in the sequence is backwards from the order
4135 * in which they must be output.
4136 */
4137
4138 for (patsLeft = psPtr->numPats, patPtr = &psPtr->pats[psPtr->numPats - 1];
4139 patsLeft > 0; patsLeft--, patPtr--) {
5060 unsigned i;
5061
5062 assert(psPtr);
5063
5064 for (i = 0; i < psPtr->numPats; ++i) {
5065 const TkPattern *patPtr = psPtr->pats + i;
5066
41405067 /*
41415068 * Check for simple case of an ASCII character.
41425069 */
4143
4144 if ((patPtr->eventType == KeyPress)
4145 && !(psPtr->flags & PAT_NEARBY)
4146 && (patPtr->needMods == 0)
4147 && (patPtr->detail.keySym < 128)
4148 && isprint(UCHAR(patPtr->detail.keySym))
4149 && (patPtr->detail.keySym != '<')
4150 && (patPtr->detail.keySym != ' ')) {
4151 char c = (char) patPtr->detail.keySym;
4152
5070 if (patPtr->eventType == KeyPress
5071 && patPtr->count == 1
5072 && patPtr->modMask == 0
5073 && patPtr->info < 128
5074 && isprint(UCHAR(patPtr->info))
5075 && patPtr->info != '<'
5076 && patPtr->info != ' ') {
5077 char c = (char) patPtr->info;
41535078 Tcl_AppendToObj(patternObj, &c, 1);
4154 continue;
4155 }
4156
4157 /*
4158 * Check for virtual event.
4159 */
4160
4161 if (patPtr->eventType == VirtualEvent) {
4162 Tcl_AppendPrintfToObj(patternObj, "<<%s>>", patPtr->detail.name);
4163 continue;
4164 }
4165
4166 /*
4167 * It's a more general event specification. First check for "Double",
4168 * "Triple", "Quadruple", then modifiers, then event type, then keysym
4169 * or button detail.
4170 */
4171
4172 Tcl_AppendToObj(patternObj, "<", 1);
4173
4174 if ((psPtr->flags & PAT_NEARBY) && (patsLeft > 1)
4175 && (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) {
4176 patsLeft--;
4177 patPtr--;
4178 if ((patsLeft > 1) &&
4179 (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) {
4180 patsLeft--;
4181 patPtr--;
4182 if ((patsLeft > 1) &&
4183 (memcmp(patPtr, patPtr-1, sizeof(TkPattern)) == 0)) {
4184 patsLeft--;
4185 patPtr--;
4186 Tcl_AppendToObj(patternObj, "Quadruple-", 10);
4187 } else {
4188 Tcl_AppendToObj(patternObj, "Triple-", 7);
5079 } else if (patPtr->eventType == VirtualEvent) {
5080 assert(patPtr->name);
5081 Tcl_AppendPrintfToObj(patternObj, "<<%s>>", patPtr->name);
5082 } else {
5083 ModMask modMask;
5084 const ModInfo *modPtr;
5085
5086 /*
5087 * It's a more general event specification. First check for "Double",
5088 * "Triple", "Quadruple", then modifiers, then event type, then keysym
5089 * or button detail.
5090 */
5091
5092 Tcl_AppendToObj(patternObj, "<", 1);
5093
5094 switch (patPtr->count) {
5095 case 2: Tcl_AppendToObj(patternObj, "Double-", 7); break;
5096 case 3: Tcl_AppendToObj(patternObj, "Triple-", 7); break;
5097 case 4: Tcl_AppendToObj(patternObj, "Quadruple-", 10); break;
5098 }
5099
5100 modMask = patPtr->modMask;
5101 #if PRINT_SHORT_MOTION_SYNTAX
5102 if (patPtr->eventType == MotionNotify) {
5103 modMask &= ~(ModMask)ALL_BUTTONS;
5104 }
5105 #endif
5106
5107 for (modPtr = modArray; modMask; ++modPtr) {
5108 if (modPtr->mask & modMask) {
5109 modMask &= ~modPtr->mask;
5110 Tcl_AppendPrintfToObj(patternObj, "%s-", modPtr->name);
41895111 }
4190 } else {
4191 Tcl_AppendToObj(patternObj, "Double-", 7);
4192 }
4193 }
4194
4195 for (needMods = patPtr->needMods, modPtr = modArray;
4196 needMods != 0; modPtr++) {
4197 if (modPtr->mask & needMods) {
4198 needMods &= ~modPtr->mask;
4199 Tcl_AppendPrintfToObj(patternObj, "%s-", modPtr->name);
4200 }
4201 }
4202
4203 for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) {
4204 if (eiPtr->type == patPtr->eventType) {
4205 Tcl_AppendToObj(patternObj, eiPtr->name, -1);
4206 if (patPtr->detail.clientData != 0) {
4207 Tcl_AppendToObj(patternObj, "-", 1);
5112 }
5113
5114 assert(patPtr->eventType < TK_LASTEVENT);
5115 assert(((size_t) eventArrayIndex[patPtr->eventType]) < SIZE_OF_ARRAY(eventArray));
5116 Tcl_AppendToObj(patternObj, eventArray[eventArrayIndex[patPtr->eventType]].name, -1);
5117
5118 if (patPtr->info) {
5119 switch (patPtr->eventType) {
5120 case KeyPress:
5121 case KeyRelease: {
5122 const char *string = TkKeysymToString(patPtr->info);
5123 if (string) {
5124 Tcl_AppendToObj(patternObj, "-", 1);
5125 Tcl_AppendToObj(patternObj, string, -1);
5126 }
5127 break;
42085128 }
4209 break;
4210 }
4211 }
4212
4213 if (patPtr->detail.clientData != 0) {
4214 if ((patPtr->eventType == KeyPress)
4215 || (patPtr->eventType == KeyRelease)) {
4216 const char *string = TkKeysymToString(patPtr->detail.keySym);
4217
4218 if (string != NULL) {
4219 Tcl_AppendToObj(patternObj, string, -1);
5129 case ButtonPress:
5130 case ButtonRelease:
5131 assert(patPtr->info <= Button5);
5132 Tcl_AppendPrintfToObj(patternObj, "-%d", (int) patPtr->info);
5133 break;
5134 #if PRINT_SHORT_MOTION_SYNTAX
5135 case MotionNotify: {
5136 ModMask mask = patPtr->modMask;
5137 while (mask & ALL_BUTTONS) {
5138 unsigned button = ButtonNumberFromState(mask);
5139 Tcl_AppendPrintfToObj(patternObj, "-%u", button);
5140 mask &= ~TkGetButtonMask(button);
5141 }
5142 break;
42205143 }
4221 } else {
4222 Tcl_AppendPrintfToObj(patternObj, "%d", patPtr->detail.button);
4223 }
4224 }
4225
4226 Tcl_AppendToObj(patternObj, ">", 1);
5144 #endif
5145 }
5146 }
5147
5148 Tcl_AppendToObj(patternObj, ">", 1);
5149 }
42275150 }
42285151
42295152 return patternObj;
42535176 #ifdef REDO_KEYSYM_LOOKUP
42545177 Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&keySymTable, name);
42555178
4256 if (hPtr != NULL) {
5179 if (hPtr) {
42575180 return (KeySym) Tcl_GetHashValue(hPtr);
42585181 }
4259 if (strlen(name) == 1) {
5182 assert(name);
5183 if (strlen(name) == 1u) {
42605184 KeySym keysym = (KeySym) (unsigned char) name[0];
42615185
4262 if (TkKeysymToString(keysym) != NULL) {
5186 if (TkKeysymToString(keysym)) {
42635187 return keysym;
42645188 }
42655189 }
42665190 #endif /* REDO_KEYSYM_LOOKUP */
5191 assert(name);
42675192 return XStringToKeysym(name);
42685193 }
42695194
42915216 #ifdef REDO_KEYSYM_LOOKUP
42925217 Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&nameTable, (char *)keysym);
42935218
4294 if (hPtr != NULL) {
5219 if (hPtr) {
42955220 return Tcl_GetHashValue(hPtr);
42965221 }
42975222 #endif /* REDO_KEYSYM_LOOKUP */
42985223
5224 if (keysym > (KeySym)0x1008FFFF) {
5225 return NULL;
5226 }
42995227 return XKeysymToString(keysym);
43005228 }
43015229
43225250 TkpGetBindingXEvent(
43235251 Tcl_Interp *interp) /* Interpreter. */
43245252 {
4325 TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);
4326 BindingTable *bindPtr = winPtr->mainPtr->bindingTable;
4327
4328 return &(bindPtr->eventRing[bindPtr->curEvent]);
5253 TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp);
5254 BindingTable *bindPtr = winPtr->mainPtr->bindingTable;
5255
5256 return &bindPtr->curEvent->xev;
43295257 }
43305258
43315259 /*
43495277 TkpCancelWarp(
43505278 TkDisplay *dispPtr)
43515279 {
5280 assert(dispPtr);
5281
43525282 if (dispPtr->flags & TK_DISPLAY_IN_WARP) {
43535283 Tcl_CancelIdleCall(DoWarp, dispPtr);
43545284 dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
43565286 }
43575287
43585288 /*
5289 *----------------------------------------------------------------------
5290 *
5291 * TkpDumpPS --
5292 *
5293 * Dump given pattern sequence to stdout.
5294 *
5295 * Results:
5296 * None.
5297 *
5298 * Side effects:
5299 * None.
5300 *
5301 *----------------------------------------------------------------------
5302 */
5303
5304 #if SUPPORT_DEBUGGING
5305 void
5306 TkpDumpPS(
5307 const PatSeq *psPtr)
5308 {
5309 if (!psPtr) {
5310 fprintf(stdout, "<null>\n");
5311 } else {
5312 Tcl_Obj* result = GetPatternObj(psPtr);
5313 Tcl_IncrRefCount(result);
5314 fprintf(stdout, "%s", Tcl_GetString(result));
5315 if (psPtr->object) {
5316 fprintf(stdout, " (%s)", (char *) psPtr->object);
5317 }
5318 fprintf(stdout, "\n");
5319 Tcl_DecrRefCount(result);
5320 }
5321 }
5322 #endif
5323
5324 /*
5325 *----------------------------------------------------------------------
5326 *
5327 * TkpDumpPSList --
5328 *
5329 * Dump given pattern sequence list to stdout.
5330 *
5331 * Results:
5332 * None.
5333 *
5334 * Side effects:
5335 * None.
5336 *
5337 *----------------------------------------------------------------------
5338 */
5339
5340 #if SUPPORT_DEBUGGING
5341 void
5342 TkpDumpPSList(
5343 const PSList *psList)
5344 {
5345 if (!psList) {
5346 fprintf(stdout, "<null>\n");
5347 } else {
5348 const PSEntry *psEntry;
5349
5350 fprintf(stdout, "Dump PSList ========================================\n");
5351 TK_DLIST_FOREACH(psEntry, psList) {
5352 TkpDumpPS(psEntry->psPtr);
5353 }
5354 fprintf(stdout, "====================================================\n");
5355 }
5356 }
5357 #endif
5358
5359 /*
43595360 * Local Variables:
43605361 * mode: c
43615362 * c-basic-offset: 4
4362 * fill-column: 78
5363 * fill-column: 105
43635364 * End:
4364 */
5365 * vi:set ts=8 sw=4:
5366 */
8787 int width, height; /* Dimensions of bitmap. */
8888 } DataKey;
8989
90 typedef struct ThreadSpecificData {
90 typedef struct {
9191 int initialized; /* 0 means table below needs initializing. */
9292 Tcl_HashTable predefBitmapTable;
9393 /* Hash table created by Tk_DefineBitmap to
518518 Tk_Window tkRef) /* Window hosting the busy window */
519519 {
520520 Busy *busyPtr;
521 int length, x, y;
521 size_t length;
522 int x, y;
522523 const char *fmt;
523524 char *name;
524525 Tk_Window tkBusy, tkChild, tkParent;
567568 busyPtr->height = Tk_Height(tkRef);
568569 busyPtr->x = Tk_X(tkRef);
569570 busyPtr->y = Tk_Y(tkRef);
570 busyPtr->cursor = None;
571 busyPtr->cursor = NULL;
571572 Tk_SetClass(tkBusy, "Busy");
572573 busyPtr->optionTable = Tk_CreateOptionTable(interp, busyOptionSpecs);
573574 if (Tk_InitOptions(interp, (char *) busyPtr, busyPtr->optionTable,
597598 */
598599
599600 Tk_ManageGeometry(tkBusy, &busyMgrInfo, busyPtr);
600 if (busyPtr->cursor != None) {
601 if (busyPtr->cursor != NULL) {
601602 Tk_DefineCursor(tkBusy, busyPtr->cursor);
602603 }
603604
642643 return TCL_ERROR;
643644 }
644645 if (busyPtr->cursor != oldCursor) {
645 if (busyPtr->cursor == None) {
646 if (busyPtr->cursor == NULL) {
646647 Tk_UndefineCursor(busyPtr->tkBusy);
647648 } else {
648649 Tk_DefineCursor(busyPtr->tkBusy, busyPtr->cursor);
877878 hPtr = Tcl_NextHashEntry(&cursor)) {
878879 busyPtr = Tcl_GetHashValue(hPtr);
879880 if (pattern == NULL ||
880 Tcl_StringMatch(Tk_PathName(busyPtr->tkRef), pattern)) {
881 Tcl_StringCaseMatch(Tk_PathName(busyPtr->tkRef), pattern, 0)) {
881882 Tcl_ListObjAppendElement(interp, objPtr,
882883 TkNewWindowObj(busyPtr->tkRef));
883884 }
1515 #include "tkButton.h"
1616 #include "default.h"
1717
18 typedef struct ThreadSpecificData {
18 typedef struct {
1919 int defaultsInitialized;
2020 } ThreadSpecificData;
2121 static Tcl_ThreadDataKey dataKey;
709709 butPtr->normalFg = NULL;
710710 butPtr->activeFg = NULL;
711711 butPtr->disabledFg = NULL;
712 butPtr->normalTextGC = None;
713 butPtr->activeTextGC = None;
714 butPtr->disabledGC = None;
715 butPtr->stippleGC = None;
712 butPtr->normalTextGC = NULL;
713 butPtr->activeTextGC = NULL;
714 butPtr->disabledGC = NULL;
715 butPtr->stippleGC = NULL;
716716 butPtr->gray = None;
717 butPtr->copyGC = None;
717 butPtr->copyGC = NULL;
718718 butPtr->widthPtr = NULL;
719719 butPtr->width = 0;
720720 butPtr->heightPtr = NULL;
739739 butPtr->onValuePtr = NULL;
740740 butPtr->offValuePtr = NULL;
741741 butPtr->tristateValuePtr = NULL;
742 butPtr->cursor = None;
742 butPtr->cursor = NULL;
743743 butPtr->takeFocusPtr = NULL;
744744 butPtr->commandPtr = NULL;
745745 butPtr->flags = 0;
877877 */
878878
879879 Tcl_CancelIdleCall(TkpDisplayButton, butPtr);
880 XFlush(butPtr->display);
880 (void)XFlush(butPtr->display);
881881 #ifndef MAC_OSX_TK
882882 /*
883883 * On the mac you can not sleep in a display proc, and the
980980 if (butPtr->tristateImage != NULL) {
981981 Tk_FreeImage(butPtr->tristateImage);
982982 }
983 if (butPtr->normalTextGC != None) {
983 if (butPtr->normalTextGC != NULL) {
984984 Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
985985 }
986 if (butPtr->activeTextGC != None) {
986 if (butPtr->activeTextGC != NULL) {
987987 Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
988988 }
989 if (butPtr->disabledGC != None) {
989 if (butPtr->disabledGC != NULL) {
990990 Tk_FreeGC(butPtr->display, butPtr->disabledGC);
991991 }
992 if (butPtr->stippleGC != None) {
992 if (butPtr->stippleGC != NULL) {
993993 Tk_FreeGC(butPtr->display, butPtr->stippleGC);
994994 }
995995 if (butPtr->gray != None) {
996996 Tk_FreeBitmap(butPtr->display, butPtr->gray);
997997 }
998 if (butPtr->copyGC != None) {
998 if (butPtr->copyGC != NULL) {
999999 Tk_FreeGC(butPtr->display, butPtr->copyGC);
10001000 }
10011001 if (butPtr->textLayout != NULL) {
11741174 */
11751175
11761176 if ((butPtr->type == TYPE_RADIO_BUTTON) &&
1177 (*Tcl_GetString(butPtr->onValuePtr) == 0)) {
1177 (*Tcl_GetString(butPtr->onValuePtr) == '\0')) {
11781178 butPtr->flags |= SELECTED;
11791179 }
11801180 }
13661366 gcValues.graphics_exposures = False;
13671367 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
13681368 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1369 if (butPtr->normalTextGC != None) {
1369 if (butPtr->normalTextGC != NULL) {
13701370 Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
13711371 }
13721372 butPtr->normalTextGC = newGC;
13761376 gcValues.background = Tk_3DBorderColor(butPtr->activeBorder)->pixel;
13771377 mask = GCForeground | GCBackground | GCFont;
13781378 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1379 if (butPtr->activeTextGC != None) {
1379 if (butPtr->activeTextGC != NULL) {
13801380 Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
13811381 }
13821382 butPtr->activeTextGC = newGC;
13881388 * Create the GC that can be used for stippling
13891389 */
13901390
1391 if (butPtr->stippleGC == None) {
1391 if (butPtr->stippleGC == NULL) {
13921392 gcValues.foreground = gcValues.background;
13931393 mask = GCForeground;
13941394 if (butPtr->gray == None) {
14141414 gcValues.foreground = gcValues.background;
14151415 }
14161416 newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
1417 if (butPtr->disabledGC != None) {
1417 if (butPtr->disabledGC != NULL) {
14181418 Tk_FreeGC(butPtr->display, butPtr->disabledGC);
14191419 }
14201420 butPtr->disabledGC = newGC;
14211421
1422 if (butPtr->copyGC == None) {
1422 if (butPtr->copyGC == NULL) {
14231423 butPtr->copyGC = Tk_GetGC(butPtr->tkwin, 0, &gcValues);
14241424 }
14251425
16161616 Tcl_Obj *valuePtr;
16171617
16181618 /*
1619 * See ticket [5d991b82].
1620 */
1621
1622 if (butPtr->selVarNamePtr == NULL) {
1623 if (!(flags & TCL_INTERP_DESTROYED)) {
1624 Tcl_UntraceVar2(interp, name1, name2,
1625 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1626 ButtonVarProc, clientData);
1627 }
1628 return NULL;
1629 }
1630
1631 /*
16321619 * If the variable is being unset, then just re-establish the trace unless
16331620 * the whole interpreter is going away.
16341621 */
16351622
16361623 if (flags & TCL_TRACE_UNSETS) {
16371624 butPtr->flags &= ~(SELECTED | TRISTATED);
1638 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1625 if (!Tcl_InterpDeleted(interp)) {
1626 ClientData probe = NULL;
1627
1628 do {
1629 probe = Tcl_VarTraceInfo(interp,
1630 Tcl_GetString(butPtr->selVarNamePtr),
1631 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1632 ButtonVarProc, probe);
1633 if (probe == (ClientData)butPtr) {
1634 break;
1635 }
1636 } while (probe);
1637 if (probe) {
1638 /*
1639 * We were able to fetch the unset trace for our
1640 * selVarNamePtr, which means it is not unset and not
1641 * the cause of this unset trace. Instead some outdated
1642 * former variable must be, and we should ignore it.
1643 */
1644 goto redisplay;
1645 }
16391646 Tcl_TraceVar2(interp, Tcl_GetString(butPtr->selVarNamePtr),
16401647 NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
16411648 ButtonVarProc, clientData);
17101717 ButtonTextVarProc(
17111718 ClientData clientData, /* Information about button. */
17121719 Tcl_Interp *interp, /* Interpreter containing variable. */
1713 const char *name1, /* Name of variable. */
1714 const char *name2, /* Second part of variable name. */
1720 const char *name1, /* Not used. */
1721 const char *name2, /* Not used. */
17151722 int flags) /* Information about what happened. */
17161723 {
17171724 TkButton *butPtr = clientData;
17221729 }
17231730
17241731 /*
1725 * See ticket [5d991b82].
1726 */
1727
1728 if (butPtr->textVarNamePtr == NULL) {
1729 if (!(flags & TCL_INTERP_DESTROYED)) {
1730 Tcl_UntraceVar2(interp, name1, name2,
1731 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1732 ButtonTextVarProc, clientData);
1733 }
1734 return NULL;
1735 }
1736
1737 /*
17381732 * If the variable is unset, then immediately recreate it unless the whole
17391733 * interpreter is going away.
17401734 */
17411735
17421736 if (flags & TCL_TRACE_UNSETS) {
1743 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1737 if (!Tcl_InterpDeleted(interp) && butPtr->textVarNamePtr != NULL) {
1738
1739 /*
1740 * An unset trace on some variable brought us here, but is it
1741 * the variable we have stored in butPtr->textVarNamePtr ?
1742 */
1743
1744 ClientData probe = NULL;
1745
1746 do {
1747 probe = Tcl_VarTraceInfo(interp,
1748 Tcl_GetString(butPtr->textVarNamePtr),
1749 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1750 ButtonTextVarProc, probe);
1751 if (probe == (ClientData)butPtr) {
1752 break;
1753 }
1754 } while (probe);
1755 if (probe) {
1756 /*
1757 * We were able to fetch the unset trace for our
1758 * textVarNamePtr, which means it is not unset and not
1759 * the cause of this unset trace. Instead some outdated
1760 * former textvariable must be, and we should ignore it.
1761 */
1762 return NULL;
1763 }
1764
17441765 Tcl_ObjSetVar2(interp, butPtr->textVarNamePtr, NULL,
17451766 butPtr->textPtr, TCL_GLOBAL_ONLY);
17461767 Tcl_TraceVar2(interp, Tcl_GetString(butPtr->textVarNamePtr),
234234 * Miscellaneous information:
235235 */
236236
237 Tk_Cursor cursor; /* Value of -cursor option: if not None,
237 Tk_Cursor cursor; /* Value of -cursor option: if not NULL,
238238 * specifies current cursor for window. */
239239 Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the
240240 * C code, but used by keyboard traversal
1111
1212 #include "tkInt.h"
1313 #include "tkCanvas.h"
14 #include "default.h"
1415
1516 /*
1617 * The structure below defines the record for each arc item.
143144 "0,0", Tk_Offset(ArcItem, tsoffset),
144145 TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
145146 {TK_CONFIG_COLOR, "-outline", NULL, NULL,
146 "black", Tk_Offset(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL},
147 DEF_CANVITEM_OUTLINE, Tk_Offset(ArcItem, outline.color), TK_CONFIG_NULL_OK, NULL},
147148 {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
148149 "0,0", Tk_Offset(ArcItem, outline.tsoffset),
149150 TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
289290 arcPtr->activeFillStipple = None;
290291 arcPtr->disabledFillStipple = None;
291292 arcPtr->style = PIESLICE_STYLE;
292 arcPtr->fillGC = None;
293 arcPtr->fillGC = NULL;
293294
294295 /*
295296 * Process the arguments to fill in the item record.
477478 mask |= GCCapStyle;
478479 newGC = Tk_GetGC(tkwin, mask, &gcValues);
479480 } else {
480 newGC = None;
481 }
482 if (arcPtr->outline.gc != None) {
481 newGC = NULL;
482 }
483 if (arcPtr->outline.gc != NULL) {
483484 Tk_FreeGC(Tk_Display(tkwin), arcPtr->outline.gc);
484485 }
485486 arcPtr->outline.gc = newGC;
511512 }
512513
513514 if (arcPtr->style == ARC_STYLE) {
514 newGC = None;
515 newGC = NULL;
515516 } else if (color == NULL) {
516 newGC = None;
517 newGC = NULL;
517518 } else {
518519 gcValues.foreground = color->pixel;
519520 if (arcPtr->style == CHORD_STYLE) {
529530 }
530531 newGC = Tk_GetGC(tkwin, mask, &gcValues);
531532 }
532 if (arcPtr->fillGC != None) {
533 if (arcPtr->fillGC != NULL) {
533534 Tk_FreeGC(Tk_Display(tkwin), arcPtr->fillGC);
534535 }
535536 arcPtr->fillGC = newGC;
602603 if (arcPtr->disabledFillStipple != None) {
603604 Tk_FreeBitmap(display, arcPtr->disabledFillStipple);
604605 }
605 if (arcPtr->fillGC != None) {
606 if (arcPtr->fillGC != NULL) {
606607 Tk_FreeGC(display, arcPtr->fillGC);
607608 }
608609 }
733734 * drawn) and add one extra pixel just for safety.
734735 */
735736
736 if (arcPtr->outline.gc == None) {
737 if (arcPtr->outline.gc == NULL) {
737738 tmp = 1;
738739 } else {
739740 tmp = (int) ((width + 1.0)/2.0 + 1);
832833 * window servers to crash and should be a no-op anyway.
833834 */
834835
835 if ((arcPtr->fillGC != None) && (extent != 0)) {
836 if ((arcPtr->fillGC != NULL) && (extent != 0)) {
836837 if (stipple != None) {
837838 int w = 0;
838839 int h = 0;
866867 XSetTSOrigin(display, arcPtr->fillGC, 0, 0);
867868 }
868869 }
869 if (arcPtr->outline.gc != None) {
870 if (arcPtr->outline.gc != NULL) {
870871 Tk_ChangeOutlineGC(canvas, itemPtr, &(arcPtr->outline));
871872
872873 if (extent != 0) {
904905 } else {
905906 if (arcPtr->style == CHORD_STYLE) {
906907 TkFillPolygon(canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
907 display, drawable, arcPtr->outline.gc, None);
908 display, drawable, arcPtr->outline.gc, NULL);
908909 } else if (arcPtr->style == PIESLICE_STYLE) {
909910 TkFillPolygon(canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
910 display, drawable, arcPtr->outline.gc, None);
911 display, drawable, arcPtr->outline.gc, NULL);
911912 TkFillPolygon(canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
912913 PIE_OUTLINE2_PTS, display, drawable,
913 arcPtr->outline.gc, None);
914 arcPtr->outline.gc, NULL);
914915 }
915916 }
916917
10161017 return dist;
10171018 }
10181019
1019 if ((arcPtr->fillGC != None) || (arcPtr->outline.gc == None)) {
1020 if ((arcPtr->fillGC != NULL) || (arcPtr->outline.gc == NULL)) {
10201021 filled = 1;
10211022 } else {
10221023 filled = 0;
10231024 }
1024 if (arcPtr->outline.gc == None) {
1025 if (arcPtr->outline.gc == NULL) {
10251026 width = 0.0;
10261027 }
10271028
11431144 }
11441145 }
11451146
1146 if ((arcPtr->fillGC != None) || (arcPtr->outline.gc == None)) {
1147 if ((arcPtr->fillGC != NULL) || (arcPtr->outline.gc == NULL)) {
11471148 filled = 1;
11481149 } else {
11491150 filled = 0;
11501151 }
1151 if (arcPtr->outline.gc == None) {
1152 if (arcPtr->outline.gc == NULL) {
11521153 width = 0.0;
11531154 }
11541155
18821883 * arc.
18831884 */
18841885
1885 if (arcPtr->fillGC != None) {
1886 if (arcPtr->fillGC != NULL) {
18861887 Tcl_AppendPrintfToObj(psObj,
18871888 "matrix currentmatrix\n"
18881889 "%.15g %.15g translate %.15g %.15g scale\n",
19111912 }
19121913 Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp));
19131914
1914 if (arcPtr->outline.gc != None) {
1915 if (arcPtr->outline.gc != NULL) {
19151916 Tcl_AppendToObj(psObj, "grestore gsave\n", -1);
19161917 }
19171918 } else {
19231924 * If there's an outline for the arc, draw it.
19241925 */
19251926
1926 if (arcPtr->outline.gc != None) {
1927 if (arcPtr->outline.gc != NULL) {
19271928 Tcl_AppendPrintfToObj(psObj,
19281929 "matrix currentmatrix\n"
19291930 "%.15g %.15g translate %.15g %.15g scale\n",
1111
1212 #include "tkInt.h"
1313 #include "tkCanvas.h"
14 #include "default.h"
1415
1516 /*
1617 * The structure below defines the record for each bitmap item.
6970 NULL, Tk_Offset(BitmapItem, disabledFgColor),
7071 TK_CONFIG_NULL_OK, NULL},
7172 {TK_CONFIG_COLOR, "-foreground", NULL, NULL,
72 "black", Tk_Offset(BitmapItem, fgColor), 0, NULL},
73 DEF_CANVBMAP_FG, Tk_Offset(BitmapItem, fgColor), 0, NULL},
7374 {TK_CONFIG_CUSTOM, "-state", NULL, NULL,
7475 NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
7576 &stateOption},
188189 bmapPtr->bgColor = NULL;
189190 bmapPtr->activeBgColor = NULL;
190191 bmapPtr->disabledBgColor = NULL;
191 bmapPtr->gc = None;
192 bmapPtr->gc = NULL;
192193
193194 /*
194195 * Process the arguments to fill in the item record. Only 1 (list) or 2 (x
371372 }
372373
373374 if (bitmap == None) {
374 newGC = None;
375 newGC = NULL;
375376 } else {
376377 gcValues.foreground = fgColor->pixel;
377378 mask = GCForeground;
384385 }
385386 newGC = Tk_GetGC(tkwin, mask, &gcValues);
386387 }
387 if (bmapPtr->gc != None) {
388 if (bmapPtr->gc != NULL) {
388389 Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
389390 }
390391 bmapPtr->gc = newGC;
448448 x = (int) (imgPtr->x + ((imgPtr->x >= 0) ? 0.5 : - 0.5));
449449 y = (int) (imgPtr->y + ((imgPtr->y >= 0) ? 0.5 : - 0.5));
450450
451 if ((state == TK_STATE_HIDDEN) || (image == None)) {
451 if ((state == TK_STATE_HIDDEN) || (image == NULL)) {
452452 imgPtr->header.x1 = imgPtr->header.x2 = x;
453453 imgPtr->header.y1 = imgPtr->header.y2 = y;
454454 return;
1212
1313 #include "tkInt.h"
1414 #include "tkCanvas.h"
15 #include "default.h"
1516
1617 /*
1718 * The structure below defines the record for each line item.
174175 {TK_CONFIG_CAP_STYLE, "-capstyle", NULL, NULL,
175176 "butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
176177 {TK_CONFIG_COLOR, "-fill", NULL, NULL,
177 "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL},
178 DEF_CANVITEM_OUTLINE, Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK, NULL},
178179 {TK_CONFIG_CUSTOM, "-dash", NULL, NULL,
179180 NULL, Tk_Offset(LineItem, outline.dash),
180181 TK_CONFIG_NULL_OK, &dashOption},
295296 linePtr->coordPtr = NULL;
296297 linePtr->capStyle = CapButt;
297298 linePtr->joinStyle = JoinRound;
298 linePtr->arrowGC = None;
299 linePtr->arrowGC = NULL;
299300 linePtr->arrow = ARROWS_NONE;
300301 linePtr->arrowShapeA = (float)8.0;
301302 linePtr->arrowShapeB = (float)10.0;
520521 #endif
521522 arrowGC = Tk_GetGC(tkwin, mask, &gcValues);
522523 } else {
523 newGC = arrowGC = None;
524 }
525 if (linePtr->outline.gc != None) {
524 newGC = arrowGC = NULL;
525 }
526 if (linePtr->outline.gc != NULL) {
526527 Tk_FreeGC(Tk_Display(tkwin), linePtr->outline.gc);
527528 }
528 if (linePtr->arrowGC != None) {
529 if (linePtr->arrowGC != NULL) {
529530 Tk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC);
530531 }
531532 linePtr->outline.gc = newGC;
610611 if (linePtr->coordPtr != NULL) {
611612 ckfree(linePtr->coordPtr);
612613 }
613 if (linePtr->arrowGC != None) {
614 if (linePtr->arrowGC != NULL) {
614615 Tk_FreeGC(display, linePtr->arrowGC);
615616 }
616617 if (linePtr->firstArrowPtr != NULL) {
839840 int numPoints;
840841 Tk_State state = itemPtr->state;
841842
842 if ((!linePtr->numPoints) || (linePtr->outline.gc == None)) {
843 if (!linePtr->numPoints || (linePtr->outline.gc == NULL)) {
843844 return;
844845 }
845846
1212
1313 #include "tkInt.h"
1414 #include "tkCanvas.h"
15 #include "default.h"
1516
1617 /*
1718 * The structure below defines the record for each polygon item.
111112 {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
112113 "0.0", Tk_Offset(PolygonItem, outline.disabledWidth),
113114 TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
115 /* Remark: Default for -fill should be NULL, see [2860519]. Will be fixed in Tk 8.7 */
114116 {TK_CONFIG_COLOR, "-fill", NULL, NULL,
115 "black", Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL},
117 DEF_CANVITEM_OUTLINE, Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK, NULL},
116118 {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL,
117119 "round", Tk_Offset(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT, NULL},
118120 {TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
272274 polyPtr->fillStipple = None;
273275 polyPtr->activeFillStipple = None;
274276 polyPtr->disabledFillStipple = None;
275 polyPtr->fillGC = None;
277 polyPtr->fillGC = NULL;
276278 polyPtr->smooth = NULL;
277279 polyPtr->splineSteps = 12;
278280 polyPtr->autoClosed = 0;
477479 mask |= GCCapStyle|GCJoinStyle;
478480 newGC = Tk_GetGC(tkwin, mask, &gcValues);
479481 } else {
480 newGC = None;
481 }
482 if (polyPtr->outline.gc != None) {
482 newGC = NULL;
483 }
484 if (polyPtr->outline.gc != NULL) {
483485 Tk_FreeGC(Tk_Display(tkwin), polyPtr->outline.gc);
484486 }
485487 polyPtr->outline.gc = newGC;
503505 }
504506
505507 if (color == NULL) {
506 newGC = None;
508 newGC = NULL;
507509 } else {
508510 gcValues.foreground = color->pixel;
509511 mask = GCForeground;
517519 * Mac OS X CG drawing needs access to the outline linewidth
518520 * even for fills (as linewidth controls antialiasing).
519521 */
520 gcValues.line_width = polyPtr->outline.gc != None ?
522 gcValues.line_width = polyPtr->outline.gc != NULL ?
521523 polyPtr->outline.gc->line_width : 0;
522524 mask |= GCLineWidth;
523525 #endif
524526 newGC = Tk_GetGC(tkwin, mask, &gcValues);
525527 }
526 if (polyPtr->fillGC != None) {
528 if (polyPtr->fillGC != NULL) {
527529 Tk_FreeGC(Tk_Display(tkwin), polyPtr->fillGC);
528530 }
529531 polyPtr->fillGC = newGC;
589591 if (polyPtr->disabledFillStipple != None) {
590592 Tk_FreeBitmap(display, polyPtr->disabledFillStipple);
591593 }
592 if (polyPtr->fillGC != None) {
594 if (polyPtr->fillGC != NULL) {
593595 Tk_FreeGC(display, polyPtr->fillGC);
594596 }
595597 }
693695 }
694696 }
695697
696 if (polyPtr->outline.gc != None) {
698 if (polyPtr->outline.gc != NULL) {
697699 tsoffset = &polyPtr->outline.tsoffset;
698700 if (tsoffset) {
699701 if (tsoffset->flags & TK_OFFSET_INDEX) {
835837 * allocated.
836838 */
837839
838 if (gc != None && numPoints > 3) {
840 if (gc != NULL && numPoints > 3) {
839841 XFillPolygon(display, drawable, gc, pointPtr, numPoints, Complex,
840842 CoordModeOrigin);
841843 }
842 if (outlineGC != None) {
844 if (outlineGC != NULL) {
843845 XDrawLines(display, drawable, outlineGC, pointPtr, numPoints,
844846 CoordModeOrigin);
845847 }
880882 Pixmap stipple = polyPtr->fillStipple;
881883 double linewidth = polyPtr->outline.width;
882884
883 if (((polyPtr->fillGC == None) && (polyPtr->outline.gc == None)) ||
885 if (((polyPtr->fillGC == NULL) && (polyPtr->outline.gc == NULL)) ||
884886 (polyPtr->numPoints < 1) ||
885 (polyPtr->numPoints < 3 && polyPtr->outline.gc == None)) {
887 (polyPtr->numPoints < 3 && polyPtr->outline.gc == NULL)) {
886888 return;
887889 }
888890
910912 * reset the offset when done, since the GC is supposed to be read-only.
911913 */
912914
913 if ((stipple != None) && (polyPtr->fillGC != None)) {
915 if ((stipple != None) && (polyPtr->fillGC != NULL)) {
914916 Tk_TSOffset *tsoffset = &polyPtr->tsoffset;
915917 int w = 0, h = 0;
916918 int flags = tsoffset->flags;
972974 }
973975 numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
974976 polyPtr->numPoints, polyPtr->splineSteps, pointPtr, NULL);
975 if (polyPtr->fillGC != None) {
977 if (polyPtr->fillGC != NULL) {
976978 XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr,
977979 numPoints, Complex, CoordModeOrigin);
978980 }
979 if (polyPtr->outline.gc != None) {
981 if (polyPtr->outline.gc != NULL) {
980982 XDrawLines(display, drawable, polyPtr->outline.gc, pointPtr,
981983 numPoints, CoordModeOrigin);
982984 }
985987 }
986988 }
987989 Tk_ResetOutlineGC(canvas, itemPtr, &polyPtr->outline);
988 if ((stipple != None) && (polyPtr->fillGC != None)) {
990 if ((stipple != None) && (polyPtr->fillGC != NULL)) {
989991 XSetTSOrigin(display, polyPtr->fillGC, 0, 0);
990992 }
991993 }
12981300 if (bestDist <= 0.0) {
12991301 goto donepoint;
13001302 }
1301 if ((polyPtr->outline.gc != None) && (polyPtr->joinStyle == JoinRound)) {
1303 if ((polyPtr->outline.gc != NULL) && (polyPtr->joinStyle == JoinRound)) {
13021304 dist = bestDist - radius;
13031305 if (dist <= 0.0) {
13041306 bestDist = 0.0;
13081310 }
13091311 }
13101312
1311 if ((polyPtr->outline.gc == None) || (width <= 1)) {
1313 if ((polyPtr->outline.gc == NULL) || (width <= 1)) {
13121314 goto donepoint;
13131315 }
13141316
15141516 goto donearea;
15151517 }
15161518
1517 if (polyPtr->outline.gc == None) {
1519 if (polyPtr->outline.gc == NULL) {
15181520 goto donearea;
15191521 }
15201522
380380 */
381381
382382 psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName, &mode);
383 if (psInfo.chan == (Tcl_Channel) NULL) {
383 if (psInfo.chan == NULL) {
384384 result = TCL_ERROR;
385385 goto cleanup;
386386 }
12781278 cdata.colors = ckalloc(sizeof(XColor) * ncolors);
12791279 cdata.ncolors = ncolors;
12801280
1281 if (visual->class == DirectColor || visual->class == TrueColor) {
1281 if (visual->c_class == DirectColor || visual->c_class == TrueColor) {
12821282 cdata.separated = 1;
12831283 cdata.red_mask = visual->red_mask;
12841284 cdata.green_mask = visual->green_mask;
13101310 }
13111311 }
13121312
1313 if (visual->class == StaticGray || visual->class == GrayScale) {
1313 if (visual->c_class == StaticGray || visual->c_class == GrayScale) {
13141314 cdata.color = 0;
13151315 } else {
13161316 cdata.color = 1;
106106 {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
107107 NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK, NULL},
108108 {TK_CONFIG_COLOR, "-fill", NULL, NULL,
109 "black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK, NULL},
109 DEF_CANVITEM_OUTLINE, Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK, NULL},
110110 {TK_CONFIG_FONT, "-font", NULL, NULL,
111111 DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0, NULL},
112112 {TK_CONFIG_JUSTIFY, "-justify", NULL, NULL,
268268 textPtr->textLayout = NULL;
269269 textPtr->actualWidth = 0;
270270 textPtr->drawOrigin[0] = textPtr->drawOrigin[1] = 0.0;
271 textPtr->gc = None;
272 textPtr->selTextGC = None;
273 textPtr->cursorOffGC = None;
271 textPtr->gc = NULL;
272 textPtr->selTextGC = NULL;
273 textPtr->cursorOffGC = NULL;
274274 textPtr->sine = 0.0;
275275 textPtr->cosine = 1.0;
276276
446446 }
447447 }
448448
449 newGC = newSelGC = None;
449 newGC = newSelGC = NULL;
450450 if (textPtr->tkfont != NULL) {
451451 gcValues.font = Tk_FontId(textPtr->tkfont);
452452 mask = GCFont;
471471 }
472472 newSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues);
473473 }
474 if (textPtr->gc != None) {
474 if (textPtr->gc != NULL) {
475475 Tk_FreeGC(Tk_Display(tkwin), textPtr->gc);
476476 }
477477 textPtr->gc = newGC;
478 if (textPtr->selTextGC != None) {
478 if (textPtr->selTextGC != NULL) {
479479 Tk_FreeGC(Tk_Display(tkwin), textPtr->selTextGC);
480480 }
481481 textPtr->selTextGC = newSelGC;
490490 }
491491 newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
492492 } else {
493 newGC = None;
494 }
495 if (textPtr->cursorOffGC != None) {
493 newGC = NULL;
494 }
495 if (textPtr->cursorOffGC != NULL) {
496496 Tk_FreeGC(Tk_Display(tkwin), textPtr->cursorOffGC);
497497 }
498498 textPtr->cursorOffGC = newGC;
591591 }
592592
593593 Tk_FreeTextLayout(textPtr->textLayout);
594 if (textPtr->gc != None) {
594 if (textPtr->gc != NULL) {
595595 Tk_FreeGC(display, textPtr->gc);
596596 }
597 if (textPtr->selTextGC != None) {
597 if (textPtr->selTextGC != NULL) {
598598 Tk_FreeGC(display, textPtr->selTextGC);
599599 }
600 if (textPtr->cursorOffGC != None) {
600 if (textPtr->cursorOffGC != NULL) {
601601 Tk_FreeGC(display, textPtr->cursorOffGC);
602602 }
603603 }
819819 }
820820 }
821821
822 if (textPtr->gc == None) {
822 if (textPtr->gc == NULL) {
823823 return;
824824 }
825825
931931 Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,
932932 textInfoPtr->insertBorder, points, 4,
933933 textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);
934 } else if (textPtr->cursorOffGC != None) {
934 } else if (textPtr->cursorOffGC != NULL) {
935935 /*
936936 * Redraw the background over the area of the cursor, even
937937 * though the cursor is turned off. This guarantees that the
1111
1212 #include "tkInt.h"
1313 #include "tkCanvas.h"
14 #include <assert.h>
1514
1615 /*
1716 * Structures defined only in this file.
960959 Tk_CreateOutline(
961960 Tk_Outline *outline) /* Outline structure to be filled in. */
962961 {
963 outline->gc = None;
962 outline->gc = NULL;
964963 outline->width = 1.0;
965964 outline->activeWidth = 0.0;
966965 outline->disabledWidth = 0.0;
10011000 Display *display, /* Display containing window. */
10021001 Tk_Outline *outline)
10031002 {
1004 if (outline->gc != None) {
1003 if (outline->gc != NULL) {
10051004 Tk_FreeGC(display, outline->gc);
10061005 }
10071006 if ((unsigned) ABS(outline->dash.number) > sizeof(char *)) {
677677 canvasPtr->highlightBgColorPtr = NULL;
678678 canvasPtr->highlightColorPtr = NULL;
679679 canvasPtr->inset = 0;
680 canvasPtr->pixmapGC = None;
680 canvasPtr->pixmapGC = NULL;
681681 canvasPtr->width = None;
682682 canvasPtr->height = None;
683683 canvasPtr->confine = 0;
697697 canvasPtr->textInfo.cursorOn = 0;
698698 canvasPtr->insertOnTime = 0;
699699 canvasPtr->insertOffTime = 0;
700 canvasPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
700 canvasPtr->insertBlinkHandler = NULL;
701701 canvasPtr->xOrigin = canvasPtr->yOrigin = 0;
702702 canvasPtr->drawableXOrigin = canvasPtr->drawableYOrigin = 0;
703703 canvasPtr->bindingTable = NULL;
723723 canvasPtr->scanYOrigin = 0;
724724 canvasPtr->hotPtr = NULL;
725725 canvasPtr->hotPrevPtr = NULL;
726 canvasPtr->cursor = None;
726 canvasPtr->cursor = NULL;
727727 canvasPtr->takeFocus = NULL;
728728 canvasPtr->pixelsPerMM = WidthOfScreen(Tk_Screen(newWin));
729729 canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(newWin));
10261026 result = TCL_ERROR;
10271027 goto done;
10281028 }
1029 if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
1029 if (mask & ~(unsigned long)(ButtonMotionMask|Button1MotionMask
10301030 |Button2MotionMask|Button3MotionMask|Button4MotionMask
10311031 |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
10321032 |EnterWindowMask|LeaveWindowMask|KeyPressMask
21882188 */
21892189
21902190 Tcl_DeleteHashTable(&canvasPtr->idTable);
2191 if (canvasPtr->pixmapGC != None) {
2191 if (canvasPtr->pixmapGC != NULL) {
21922192 Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
21932193 }
21942194 #ifndef USE_OLD_TAG_SEARCH
22642264 gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;
22652265 newGC = Tk_GetGC(canvasPtr->tkwin,
22662266 GCFunction|GCGraphicsExposures|GCForeground, &gcValues);
2267 if (canvasPtr->pixmapGC != None) {
2267 if (canvasPtr->pixmapGC != NULL) {
22682268 Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
22692269 }
22702270 canvasPtr->pixmapGC = newGC;
28882888 Tk_Item *itemPtr) /* Item to be redrawn. May be NULL, in which
28892889 * case nothing happens. */
28902890 {
2891 if (itemPtr == NULL) {
2891 if (itemPtr == NULL || canvasPtr->tkwin == NULL) {
28922892 return;
28932893 }
28942894 if ((itemPtr->x1 >= itemPtr->x2) || (itemPtr->y1 >= itemPtr->y2) ||
47464746 XEvent *eventPtr) /* Pointer to X event that just happened. */
47474747 {
47484748 TkCanvas *canvasPtr = clientData;
4749 int mask;
4749 unsigned long mask;
47504750
47514751 Tcl_Preserve(canvasPtr);
47524752
47594759 switch (eventPtr->type) {
47604760 case ButtonPress:
47614761 case ButtonRelease:
4762 switch (eventPtr->xbutton.button) {
4763 case Button1:
4764 mask = Button1Mask;
4765 break;
4766 case Button2:
4767 mask = Button2Mask;
4768 break;
4769 case Button3:
4770 mask = Button3Mask;
4771 break;
4772 case Button4:
4773 mask = Button4Mask;
4774 break;
4775 case Button5:
4776 mask = Button5Mask;
4777 break;
4778 default:
4779 mask = 0;
4780 break;
4781 }
4762 mask = TkGetButtonMask(eventPtr->xbutton.button);
47824763
47834764 /*
47844765 * For button press events, repick the current item using the button
48614842 * ButtonRelease, or MotionNotify. */
48624843 {
48634844 double coords[2];
4864 int buttonDown;
4845 unsigned long buttonDown;
48654846 Tk_Item *prevItemPtr;
48664847 #ifndef USE_OLD_TAG_SEARCH
48674848 SearchUids *searchUids = GetStaticUids();
48744855 * for windows.
48754856 */
48764857
4877 buttonDown = canvasPtr->state
4878 & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
4858 buttonDown = canvasPtr->state & ALL_BUTTONS;
48794859
48804860 /*
48814861 * Save information about this event in the canvas. The event in the
53065286 } else {
53075287 canvasPtr->textInfo.gotFocus = 0;
53085288 canvasPtr->textInfo.cursorOn = 0;
5309 canvasPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
5289 canvasPtr->insertBlinkHandler = NULL;
53105290 }
53115291 EventuallyRedrawItem(canvasPtr, canvasPtr->textInfo.focusItemPtr);
53125292 if (canvasPtr->highlightWidth > 0) {
205205 * Miscellaneous information:
206206 */
207207
208 Tk_Cursor cursor; /* Current cursor for window, or None. */
208 Tk_Cursor cursor; /* Current cursor for window, or NULL. */
209209 char *takeFocus; /* Value of -takefocus option; not used in the
210210 * C code, but used by keyboard traversal
211211 * scripts. Malloc'ed, but may be NULL. */
133133 if (!nice) {
134134 XForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset);
135135 }
136 XFlush(Tk_Display(tkwin));
136 (void)XFlush(Tk_Display(tkwin));
137137 Tk_DeleteErrorHandler(handler);
138138 return TCL_OK;
139139 }
12841284 int objc, /* Number of arguments. */
12851285 Tcl_Obj *const objv[]) /* Argument objects. */
12861286 {
1287 int index, x, y, width, height, useX, useY, class, skip;
1287 int index, x, y, width, height, useX, useY, c_class, skip;
12881288 const char *string;
12891289 TkWindow *winPtr;
12901290 Tk_Window tkwin = clientData;
14951495 Tcl_NewIntObj(WidthMMOfScreen(Tk_Screen(tkwin))));
14961496 break;
14971497 case WIN_SCREENVISUAL:
1498 class = DefaultVisualOfScreen(Tk_Screen(tkwin))->class;
1498 c_class = DefaultVisualOfScreen(Tk_Screen(tkwin))->c_class;
14991499 goto visual;
15001500 case WIN_SERVER:
15011501 TkGetServerInfo(interp, tkwin);
15231523 break;
15241524 }
15251525 case WIN_VISUAL:
1526 class = Tk_Visual(tkwin)->class;
1526 c_class = Tk_Visual(tkwin)->c_class;
15271527
15281528 visual:
1529 string = TkFindStateString(visualMap, class);
1529 string = TkFindStateString(visualMap, c_class);
15301530 if (string == NULL) {
15311531 string = "unknown";
15321532 }
17891789 }
17901790 resultPtr = Tcl_NewObj();
17911791 for (i = 0; i < count; i++) {
1792 string = TkFindStateString(visualMap, visInfoPtr[i].class);
1792 string = TkFindStateString(visualMap, visInfoPtr[i].c_class);
17931793 if (string == NULL) {
17941794 strcpy(buf, "unknown");
17951795 } else {
17961796 sprintf(buf, "%s %d", string, visInfoPtr[i].depth);
17971797 }
17981798 if (includeVisualId) {
1799 sprintf(visualIdString, " 0x%x",
1800 (unsigned) visInfoPtr[i].visualid);
1799 sprintf(visualIdString, " 0x%lx",
1800 (unsigned long) visInfoPtr[i].visualid);
18011801 strcat(buf, visualIdString);
18021802 }
18031803 strPtr = Tcl_NewStringObj(buf, -1);
3030 * The structure below is used to allocate thread-local data.
3131 */
3232
33 typedef struct ThreadSpecificData {
33 typedef struct {
3434 char rgbString[20]; /* */
3535 } ThreadSpecificData;
3636 static Tcl_ThreadDataKey dataKey;
244244 */
245245
246246 tkColPtr->magic = COLOR_MAGIC;
247 tkColPtr->gc = None;
247 tkColPtr->gc = NULL;
248248 tkColPtr->screen = Tk_Screen(tkwin);
249249 tkColPtr->colormap = Tk_Colormap(tkwin);
250250 tkColPtr->visual = Tk_Visual(tkwin);
325325
326326 tkColPtr = TkpGetColorByValue(tkwin, colorPtr);
327327 tkColPtr->magic = COLOR_MAGIC;
328 tkColPtr->gc = None;
328 tkColPtr->gc = NULL;
329329 tkColPtr->screen = Tk_Screen(tkwin);
330330 tkColPtr->colormap = valueKey.colormap;
331331 tkColPtr->visual = Tk_Visual(tkwin);
435435 Tcl_Panic("Tk_GCForColor called with bogus color");
436436 }
437437
438 if (tkColPtr->gc == None) {
438 if (tkColPtr->gc == NULL) {
439439 gcValues.foreground = tkColPtr->color.pixel;
440440 tkColPtr->gc = XCreateGC(DisplayOfScreen(tkColPtr->screen), drawable,
441441 GCForeground, &gcValues);
490490 * longer any objects referencing it.
491491 */
492492
493 if (tkColPtr->gc != None) {
493 if (tkColPtr->gc != NULL) {
494494 XFreeGC(DisplayOfScreen(screen), tkColPtr->gc);
495 tkColPtr->gc = None;
495 tkColPtr->gc = NULL;
496496 }
497497 TkpFreeColor(tkColPtr);
498498
3131 * COLOR_MAGIC. */
3232 GC gc; /* Simple gc with this color as foreground
3333 * color and all other fields defaulted. May
34 * be None. */
34 * be NULL. */
3535 Screen *screen; /* Screen where this color is valid. Used to
3636 * delete it, and to find its display. */
3737 Colormap colormap; /* Colormap from which this entry was
3030 * the option tables that have been created for a thread.
3131 */
3232
33 typedef struct ThreadSpecificData {
33 typedef struct {
3434 int initialized; /* 0 means table below needs initializing. */
3535 Tcl_HashTable hashTable;
3636 } ThreadSpecificData;
799799 Tk_Cursor newCursor;
800800
801801 if (nullOK && ObjectIsEmpty(valuePtr)) {
802 newCursor = None;
802 newCursor = NULL;
803803 valuePtr = NULL;
804804 } else {
805805 newCursor = Tk_AllocCursorFromObj(interp, tkwin, valuePtr);
806 if (newCursor == None) {
806 if (newCursor == NULL) {
807807 return TCL_ERROR;
808808 }
809809 }
861861
862862 if (nullOK && ObjectIsEmpty(valuePtr)) {
863863 valuePtr = NULL;
864 newWin = None;
864 newWin = NULL;
865865 } else {
866866 if (TkGetWindowFromObj(interp, tkwin, valuePtr,
867867 &newWin) != TCL_OK) {
16651665 break;
16661666 case TK_OPTION_CURSOR:
16671667 if (internalFormExists) {
1668 if (*((Tk_Cursor *) internalPtr) != None) {
1668 if (*((Tk_Cursor *) internalPtr) != NULL) {
16691669 Tk_FreeCursor(Tk_Display(tkwin), *((Tk_Cursor *) internalPtr));
1670 *((Tk_Cursor *) internalPtr) = None;
1670 *((Tk_Cursor *) internalPtr) = NULL;
16711671 }
16721672 } else if (objPtr != NULL) {
16731673 Tk_FreeCursorFromObj(tkwin, objPtr);
19381938 case TK_OPTION_CURSOR: {
19391939 Tk_Cursor cursor = *((Tk_Cursor *) internalPtr);
19401940
1941 if (cursor != None) {
1941 if (cursor != NULL) {
19421942 objPtr = Tcl_NewStringObj(
19431943 Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1);
19441944 }
149149 cursorPtr = TkcGetCursor(interp, tkwin, Tcl_GetString(objPtr));
150150 objPtr->internalRep.twoPtrValue.ptr1 = cursorPtr;
151151 if (cursorPtr == NULL) {
152 return None;
152 return NULL;
153153 }
154154 cursorPtr->objRefCount++;
155155 return cursorPtr->cursor;
189189 TkCursor *cursorPtr = TkcGetCursor(interp, tkwin, string);
190190
191191 if (cursorPtr == NULL) {
192 return None;
192 return NULL;
193193 }
194194 return cursorPtr->cursor;
195195 }
387387
388388 error:
389389 Tcl_DeleteHashEntry(dataHashPtr);
390 return None;
390 return NULL;
391391 }
392392
393393 /*
424424
425425 if (!dispPtr->cursorInit) {
426426 printid:
427 sprintf(dispPtr->cursorString, "cursor id %p", cursor);
427 sprintf(dispPtr->cursorString, "cursor id 0x%" TCL_Z_MODIFIER "x", (size_t)cursor);
428428 return dispPtr->cursorString;
429429 }
430430 idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor);
0 /*
1 * tkDList.h --
2 *
3 * A list is headed by pointers to first and last element. The elements
4 * are doubly linked so that an arbitrary element can be removed without
5 * a need to traverse the list. New elements can be added to the list
6 * before or after an existing element or at the head/tail of the list.
7 * A list may be traversed in the forward or backward direction.
8 *
9 * Copyright (c) 2018 by Gregor Cramer.
10 *
11 * See the file "license.terms" for information on usage and redistribution of
12 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 */
14
15 /*
16 * Note that this file will not be included in header files, it is the purpose
17 * of this file to be included in source files only. Thus we are not using the
18 * prefix "Tk_" here for functions, because all the functions have private scope.
19 */
20
21 /*
22 * -------------------------------------------------------------------------------
23 * Use the double linked list in the following way:
24 * -------------------------------------------------------------------------------
25 * typedef struct MyListEntry { TK_DLIST_LINKS(MyListEntry); int value; } MyListEntry;
26 * TK_DLIST_DEFINE(MyList, MyListEntry);
27 * MyList listHdr = TK_DLIST_LIST_INITIALIZER; // or MyList_Init(&listHdr)
28 * MyListEntry *p;
29 * int i = 0;
30 * MyList_Append(&listHdr, ckalloc(sizeof(MyListEntry)));
31 * MyList_Append(&listHdr, ckalloc(sizeof(MyListEntry)));
32 * TK_DLIST_FOREACH(p, &listHdr) { p->value = i++; }
33 * // ...
34 * MyList_RemoveHead(&listHdr);
35 * MyList_RemoveHead(&listHdr);
36 * MyList_Clear(MyListEntry, &listHdr); // invokes ckfree() for each element
37 * -------------------------------------------------------------------------------
38 * IMPORTANT NOTE: TK_DLIST_LINKS must be used at start of struct!
39 */
40
41 #ifndef TK_DLIST_DEFINED
42 #define TK_DLIST_DEFINED
43
44 #include "tkInt.h"
45
46 /*
47 * List definitions.
48 */
49
50 #define TK_DLIST_LINKS(ElemType) \
51 struct { \
52 struct ElemType *prev; /* previous element */ \
53 struct ElemType *next; /* next element */ \
54 } _dl_
55
56 #define TK_DLIST_LIST_INITIALIZER { NULL, NULL }
57 #define TK_DLIST_ELEM_INITIALIZER { NULL, NULL }
58
59 /*************************************************************************/
60 /*
61 * DList_Init: Initialize list header. This can also be used to clear the
62 * list.
63 *
64 * See also: DList_Clear()
65 */
66 /*************************************************************************/
67 /*
68 * DList_ElemInit: Initialize a list element.
69 */
70 /*************************************************************************/
71 /*
72 * DList_InsertAfter: Insert 'elem' after 'listElem'. 'elem' must not
73 * be linked, but 'listElem' must be linked.
74 */
75 /*************************************************************************/
76 /*
77 * DList_InsertBefore: Insert 'elem' before 'listElem'. 'elem' must not
78 * be linked, but 'listElem' must be linked.
79 */
80 /*************************************************************************/
81 /*
82 * DList_Prepend: Insert 'elem' at start of list. This element must not
83 * be linked.
84 *
85 * See also: DList_Append()
86 */
87 /*************************************************************************/
88 /*
89 * DList_Append: Append 'elem' to end of list. This element must not
90 * be linked.
91 *
92 * See also: DList_Prepend()
93 */
94 /*************************************************************************/
95 /*
96 * DList_Move: Append all list items of 'src' to end of 'dst'.
97 */
98 /*************************************************************************/
99 /*
100 * DList_Remove: Remove 'elem' from list. This element must be linked.
101 *
102 * See also: DList_Free()
103 */
104 /*************************************************************************/
105 /*
106 * DList_Free: Remove 'elem' from list and free it. This element must
107 * be linked.
108 *
109 * See also: DList_Remove()
110 */
111 /*************************************************************************/
112 /*
113 * DList_RemoveHead: Remove first element from list. The list must
114 * not be empty.
115 *
116 * See also: DList_FreeHead()
117 */
118 /*************************************************************************/
119 /*
120 * DList_RemoveTail: Remove last element from list. The list must
121 * not be empty.
122 *
123 * See also: DList_FreeTail()
124 */
125 /*************************************************************************/
126 /*
127 * DList_FreeHead: Remove first element from list and free it.
128 * The list must not be empty.
129 *
130 * See also: DList_RemoveHead()
131 */
132 /*************************************************************************/
133 /*
134 * DList_FreeTail: Remove last element from list and free it.
135 * The list must not be empty.
136 *
137 * See also: DList_RemoveTail()
138 */
139 /*************************************************************************/
140 /*
141 * DList_SwapElems: Swap positions of given elements 'lhs' and 'rhs'.
142 * Both elements must be linked, and must belong to same list.
143 */
144 /*************************************************************************/
145 /*
146 * DList_Clear: Clear whole list and free all elements.
147 *
148 * See also: DList_Init
149 */
150 /*************************************************************************/
151 /*
152 * DList_Traverse: Iterate over all elements in list from first to last.
153 * Call given function func(head, elem) for each element. The function has
154 * to return the next element in list to traverse, normally this is
155 * DList_Next(elem).
156 *
157 * See also: TK_DLIST_FOREACH, TK_DLIST_FOREACH_REVERSE
158 */
159 /*************************************************************************/
160 /*
161 * DList_First: Return pointer of first element in list, maybe it's NULL.
162 */
163 /*************************************************************************/
164 /*
165 * DList_Last: Return pointer of last element in list, maybe it's NULL.
166 */
167 /*************************************************************************/
168 /*
169 * DList_Next: Return pointer of next element after 'elem', maybe it's NULL.
170 *
171 * See also: DList_Prev()
172 */
173 /*************************************************************************/
174 /*
175 * DList_Prev: Return pointer of previous element before 'elem', maybe it's
176 * NULL.
177 *
178 * See also: DList_Next()
179 */
180 /*************************************************************************/
181 /*
182 * DList_IsEmpty: Test whether given list is empty.
183 */
184 /*************************************************************************/
185 /*
186 * DList_IsLinked: Test whether given element is linked.
187 */
188 /*************************************************************************/
189 /*
190 * DList_IsFirst: Test whether given element is first element in list.
191 * Note that 'elem' must be linked.
192 *
193 * See also: DList_IsLast(), DList_IsLinked()
194 */
195 /*************************************************************************/
196 /*
197 * DList_IsLast: Test whether given element is last element in list.
198 * Note that 'elem' must be linked.
199 *
200 * See also: DList_IsFirst(), DList_IsLinked()
201 */
202 /*************************************************************************/
203 /*
204 * DList_Size: Count number of elements in given list.
205 */
206 /*************************************************************************/
207 /*
208 * TK_DLIST_FOREACH: Iterate over all elements in list from first to last.
209 * 'var' is the name of the variable which points to current element.
210 *
211 * See also: TK_DLIST_FOREACH_REVERSE, DList_Traverse()
212 */
213 /*************************************************************************/
214 /*
215 * TK_DLIST_FOREACH_REVERSE: Iterate over all elements in list from last
216 * to first (backwards). 'var' is the name of the variable which points to
217 * current element.
218 */
219 /*************************************************************************/
220
221 #if defined(__GNUC__) || defined(__clang__)
222 # define __TK_DLIST_UNUSED __attribute__((unused))
223 #else
224 # define __TK_DLIST_UNUSED
225 #endif
226
227 #define TK_DLIST_DEFINE(LT, ElemType) /* LT = type of head/list */ \
228 /* ------------------------------------------------------------------------- */ \
229 typedef struct LT { \
230 struct ElemType *first; /* first element */ \
231 struct ElemType *last; /* last element */ \
232 } LT; \
233 \
234 typedef struct ElemType *(LT##_Func)(LT *head, struct ElemType *elem); \
235 \
236 __TK_DLIST_UNUSED \
237 static void \
238 LT##_Init(LT *head) \
239 { \
240 assert(head); \
241 head->first = NULL; \
242 head->last = NULL; \
243 } \
244 \
245 __TK_DLIST_UNUSED \
246 static void \
247 LT##_ElemInit(struct ElemType *elem) \
248 { \
249 assert(elem); \
250 elem->_dl_.next = NULL; \
251 elem->_dl_.prev = NULL; \
252 } \
253 \
254 __TK_DLIST_UNUSED \
255 static int \
256 LT##_IsEmpty(LT *head) \
257 { \
258 assert(head); \
259 return head->first == NULL; \
260 } \
261 \
262 __TK_DLIST_UNUSED \
263 static int \
264 LT##_IsLinked(struct ElemType *elem) \
265 { \
266 assert(elem); \
267 return elem->_dl_.next && elem->_dl_.prev; \
268 } \
269 \
270 __TK_DLIST_UNUSED \
271 static int \
272 LT##_IsFirst(struct ElemType *elem) \
273 { \
274 assert(LT##_IsLinked(elem)); \
275 return elem->_dl_.prev->_dl_.prev == elem; \
276 } \
277 \
278 __TK_DLIST_UNUSED \
279 static int \
280 LT##_IsLast(struct ElemType *elem) \
281 { \
282 assert(LT##_IsLinked(elem)); \
283 return elem->_dl_.next->_dl_.next == elem; \
284 } \
285 \
286 __TK_DLIST_UNUSED \
287 static struct ElemType * \
288 LT##_First(LT *head) \
289 { \
290 assert(head); \
291 return head->first; \
292 } \
293 \
294 __TK_DLIST_UNUSED \
295 static struct ElemType * \
296 LT##_Last(LT *head) \
297 { \
298 assert(head); \
299 return head->last; \
300 } \
301 \
302 __TK_DLIST_UNUSED \
303 static struct ElemType * \
304 LT##_Next(struct ElemType *elem) \
305 { \
306 assert(elem); \
307 return LT##_IsLast(elem) ? NULL : elem->_dl_.next; \
308 } \
309 \
310 __TK_DLIST_UNUSED \
311 static struct ElemType * \
312 LT##_Prev(struct ElemType *elem) \
313 { \
314 assert(elem); \
315 return LT##_IsFirst(elem) ? NULL : elem->_dl_.prev; \
316 } \
317 \
318 __TK_DLIST_UNUSED \
319 static unsigned \
320 LT##_Size(const LT *head) \
321 { \
322 const struct ElemType *elem; \
323 unsigned size = 0; \
324 assert(head); \
325 if ((elem = head->first)) { \
326 for ( ; elem != (void *) head; elem = elem->_dl_.next) { \
327 ++size; \
328 } \
329 } \
330 return size; \
331 } \
332 \
333 __TK_DLIST_UNUSED \
334 static void \
335 LT##_InsertAfter(struct ElemType *listElem, struct ElemType *elem) \
336 { \
337 assert(listElem); \
338 assert(elem); \
339 elem->_dl_.next = listElem->_dl_.next; \
340 elem->_dl_.prev = listElem; \
341 listElem->_dl_.next->_dl_.prev = elem; \
342 listElem->_dl_.next = elem; \
343 } \
344 \
345 __TK_DLIST_UNUSED \
346 static void \
347 LT##_InsertBefore(struct ElemType *listElem, struct ElemType *elem) \
348 { \
349 assert(listElem); \
350 assert(elem); \
351 elem->_dl_.next = listElem; \
352 elem->_dl_.prev = listElem->_dl_.prev;; \
353 listElem->_dl_.prev->_dl_.next = elem; \
354 listElem->_dl_.prev = elem; \
355 } \
356 \
357 __TK_DLIST_UNUSED \
358 static void \
359 LT##_Prepend(LT *head, struct ElemType *elem) \
360 { \
361 assert(head); \
362 assert(elem); \
363 elem->_dl_.prev = (void *) head; \
364 if (!head->first) { \
365 elem->_dl_.next = (void *) head; \
366 head->last = elem; \
367 } else { \
368 elem->_dl_.next = head->first; \
369 head->first->_dl_.prev = elem; \
370 } \
371 head->first = elem; \
372 } \
373 \
374 __TK_DLIST_UNUSED \
375 static void \
376 LT##_Append(LT *head, struct ElemType *elem) \
377 { \
378 assert(head); \
379 assert(elem); \
380 elem->_dl_.next = (void *) head; \
381 if (!head->first) { \
382 elem->_dl_.prev = (void *) head; \
383 head->first = elem; \
384 } else { \
385 elem->_dl_.prev = head->last; \
386 head->last->_dl_.next = elem; \
387 } \
388 head->last = elem; \
389 } \
390 \
391 __TK_DLIST_UNUSED \
392 static void \
393 LT##_Move(LT *dst, LT *src) \
394 { \
395 assert(dst); \
396 assert(src); \
397 if (src->first) { \
398 if (dst->first) { \
399 dst->last->_dl_.next = src->first; \
400 src->first->_dl_.prev = dst->last; \
401 dst->last = src->last; \
402 } else { \
403 *dst = *src; \
404 dst->first->_dl_.prev = (void *) dst; \
405 } \
406 dst->last->_dl_.next = (void *) dst; \
407 LT##_Init(src); \
408 } \
409 } \
410 \
411 __TK_DLIST_UNUSED \
412 static void \
413 LT##_Remove(struct ElemType *elem) \
414 { \
415 int isFirst, isLast; \
416 assert(LT##_IsLinked(elem)); \
417 isFirst = LT##_IsFirst(elem); \
418 isLast = LT##_IsLast(elem); \
419 if (isFirst && isLast) { \
420 ((LT *) elem->_dl_.prev)->first = NULL; \
421 ((LT *) elem->_dl_.next)->last = NULL; \
422 } else { \
423 if (isFirst) { \
424 ((LT *) elem->_dl_.prev)->first = elem->_dl_.next; \
425 } else { \
426 elem->_dl_.prev->_dl_.next = elem->_dl_.next; \
427 } \
428 if (isLast) { \
429 ((LT *) elem->_dl_.next)->last = elem->_dl_.prev; \
430 } else { \
431 elem->_dl_.next->_dl_.prev = elem->_dl_.prev; \
432 } \
433 } \
434 LT##_ElemInit(elem); \
435 } \
436 \
437 __TK_DLIST_UNUSED \
438 static void \
439 LT##_Free(struct ElemType *elem) \
440 { \
441 LT##_Remove(elem); \
442 ckfree((void *) elem); \
443 } \
444 \
445 __TK_DLIST_UNUSED \
446 static void \
447 LT##_RemoveHead(LT *head) \
448 { \
449 assert(!LT##_IsEmpty(head)); \
450 LT##_Remove(head->first); \
451 } \
452 \
453 __TK_DLIST_UNUSED \
454 static void \
455 LT##_RemoveTail(LT *head) \
456 { \
457 assert(!LT##_IsEmpty(head)); \
458 LT##_Remove(head->last); \
459 } \
460 \
461 __TK_DLIST_UNUSED \
462 static void \
463 LT##_FreeHead(LT *head) \
464 { \
465 assert(!LT##_IsEmpty(head)); \
466 LT##_Free(head->first); \
467 } \
468 \
469 __TK_DLIST_UNUSED \
470 static void \
471 LT##_FreeTail(LT *head) \
472 { \
473 assert(!LT##_IsEmpty(head)); \
474 LT##_Free(head->last); \
475 } \
476 \
477 __TK_DLIST_UNUSED \
478 static void \
479 LT##_SwapElems(struct ElemType *lhs, struct ElemType *rhs) \
480 { \
481 assert(lhs); \
482 assert(rhs); \
483 if (lhs != rhs) { \
484 struct ElemType tmp; \
485 if (LT##_IsFirst(lhs)) { \
486 ((LT *) lhs->_dl_.prev)->first = rhs; \
487 } else if (LT##_IsFirst(rhs)) { \
488 ((LT *) rhs->_dl_.prev)->first = lhs; \
489 } \
490 if (LT##_IsLast(lhs)) { \
491 ((LT *) lhs->_dl_.next)->last = rhs; \
492 } else if (LT##_IsLast(rhs)) { \
493 ((LT *) rhs->_dl_.next)->last = lhs; \
494 } \
495 tmp._dl_ = lhs->_dl_; \
496 lhs->_dl_ = rhs->_dl_; \
497 rhs->_dl_ = tmp._dl_; \
498 } \
499 } \
500 \
501 __TK_DLIST_UNUSED \
502 static void \
503 LT##_Clear(LT *head) \
504 { \
505 struct ElemType *p; \
506 struct ElemType *next; \
507 assert(head); \
508 for (p = head->first; p; p = next) { \
509 next = LT##_Next(p); \
510 ckfree((void *) p); \
511 } \
512 LT##_Init(head); \
513 } \
514 \
515 __TK_DLIST_UNUSED \
516 static void \
517 LT##_Traverse(LT *head, LT##_Func func) \
518 { \
519 struct ElemType *next; \
520 struct ElemType *p; \
521 assert(head); \
522 for (p = head->first; p; p = next) { \
523 next = func(head, p); \
524 } \
525 } \
526 /* ------------------------------------------------------------------------- */
527
528 #define TK_DLIST_FOREACH(var, head) \
529 assert(head); \
530 for (var = head->first ? head->first : (void *) head; var != (void *) head; var = var->_dl_.next)
531
532 #define TK_DLIST_FOREACH_REVERSE(var, head) \
533 assert(head); \
534 for (var = head->last ? head->last : (void *) head; var != (void *) head; var = var->_dl_.prev)
535
536 #endif /* TK_DLIST_DEFINED */
537
538 /*
539 * Local Variables:
540 * mode: c
541 * c-basic-offset: 4
542 * fill-column: 105
543 * End:
544 * vi:set ts=8 sw=4:
545 */
523523 entryPtr->selectFirst = -1;
524524 entryPtr->selectLast = -1;
525525
526 entryPtr->cursor = None;
526 entryPtr->cursor = NULL;
527527 entryPtr->exportSelection = 1;
528528 entryPtr->justify = TK_JUSTIFY_LEFT;
529529 entryPtr->relief = TK_RELIEF_FLAT;
530530 entryPtr->state = STATE_NORMAL;
531531 entryPtr->displayString = entryPtr->string;
532532 entryPtr->inset = XPAD;
533 entryPtr->textGC = None;
534 entryPtr->selTextGC = None;
535 entryPtr->highlightGC = None;
533 entryPtr->textGC = NULL;
534 entryPtr->selTextGC = NULL;
535 entryPtr->highlightGC = NULL;
536536 entryPtr->avgWidth = 1;
537537 entryPtr->validate = VALIDATE_NONE;
538538
10321032 EntryTextVarProc, entryPtr);
10331033 entryPtr->flags &= ~ENTRY_VAR_TRACED;
10341034 }
1035 if (entryPtr->textGC != None) {
1035 if (entryPtr->textGC != NULL) {
10361036 Tk_FreeGC(entryPtr->display, entryPtr->textGC);
10371037 }
1038 if (entryPtr->selTextGC != None) {
1038 if (entryPtr->selTextGC != NULL) {
10391039 Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
10401040 }
10411041 Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler);
14291429 ClientData instanceData) /* Information about widget. */
14301430 {
14311431 XGCValues gcValues;
1432 GC gc = None;
1432 GC gc = NULL;
14331433 unsigned long mask;
14341434 Tk_3DBorder border;
14351435 XColor *colorPtr;
14811481 gcValues.graphics_exposures = False;
14821482 mask = GCForeground | GCFont | GCGraphicsExposures;
14831483 gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
1484 if (entryPtr->textGC != None) {
1484 if (entryPtr->textGC != NULL) {
14851485 Tk_FreeGC(entryPtr->display, entryPtr->textGC);
14861486 }
14871487 entryPtr->textGC = gc;
14921492 gcValues.font = Tk_FontId(entryPtr->tkfont);
14931493 mask = GCForeground | GCFont;
14941494 gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
1495 if (entryPtr->selTextGC != None) {
1495 if (entryPtr->selTextGC != NULL) {
14961496 Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
14971497 }
14981498 entryPtr->selTextGC = gc;
15121512 *
15131513 * TkpDrawEntryBorderAndFocus --
15141514 *
1515 * This function redraws the border of an entry widget. It overrides the
1516 * generic border drawing code if the entry widget parameters are such
1517 * that the native widget drawing is a good fit. This version just
1518 * returns 0, so platforms that don't do special native drawing don't
1519 * have to implement it.
1515 * Stub function for Tk on platforms other than Aqua
1516 * (Windows and X11), which do not draw native entry borders.
1517 * See macosx/tkMacOSXEntry.c for function definition in Tk Aqua.
15201518 *
15211519 * Results:
1522 * 1 if it has drawn the border, 0 if not.
1520 * Returns 0.
15231521 *
15241522 * Side effects:
1525 * May draw the entry border into pixmap.
1523 * None.
15261524 *
15271525 *--------------------------------------------------------------
15281526 */
15411539 *
15421540 * TkpDrawSpinboxButtons --
15431541 *
1544 * This function redraws the buttons of an spinbox widget. It overrides
1545 * the generic button drawing code if the spinbox widget parameters are
1546 * such that the native widget drawing is a good fit. This version just
1547 * returns 0, so platforms that don't do special native drawing don't
1548 * have to implement it.
1542 * Stub function for Tk on platforms other than Aqua
1543 * (Windows and X11), which do not draw native spinbox buttons.
1544 * See macosx/tkMacOSXEntry.c for function definition in Tk Aqua.
15491545 *
15501546 * Results:
1551 * 1 if it has drawn the border, 0 if not.
1547 * Returns 0.
15521548 *
15531549 * Side effects:
1554 * May draw the entry border into pixmap.
1550 * None.
15551551 *
15561552 *--------------------------------------------------------------
15571553 */
24562452 } else if ((elem == SEL_BUTTONDOWN) || (elem == SEL_BUTTONUP)) {
24572453 cursor = sbPtr->bCursor;
24582454 } else {
2459 cursor = None;
2460 }
2461 if (cursor != None) {
2455 cursor = NULL;
2456 }
2457 if (cursor != NULL) {
24622458 Tk_DefineCursor(entryPtr->tkwin, cursor);
24632459 } else {
24642460 Tk_UndefineCursor(entryPtr->tkwin);
31343130 EntryTextVarProc(
31353131 ClientData clientData, /* Information about button. */
31363132 Tcl_Interp *interp, /* Interpreter containing variable. */
3137 const char *name1, /* Name of variable. */
3138 const char *name2, /* Second part of variable name. */
3133 const char *name1, /* Not used. */
3134 const char *name2, /* Not used. */
31393135 int flags) /* Information about what happened. */
31403136 {
31413137 Entry *entryPtr = clientData;
31493145 }
31503146
31513147 /*
3152 * See ticket [5d991b82].
3153 */
3154
3155 if (entryPtr->textVarName == NULL) {
3156 if (!(flags & TCL_INTERP_DESTROYED)) {
3157 Tcl_UntraceVar2(interp, name1, name2,
3158 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
3159 EntryTextVarProc, clientData);
3160 }
3161 return NULL;
3162 }
3163
3164 /*
31653148 * If the variable is unset, then immediately recreate it unless the whole
31663149 * interpreter is going away.
31673150 */
31683151
31693152 if (flags & TCL_TRACE_UNSETS) {
3170 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
3153 if (!Tcl_InterpDeleted(interp) && entryPtr->textVarName) {
3154 ClientData probe = NULL;
3155
3156 do {
3157 probe = Tcl_VarTraceInfo(interp,
3158 entryPtr->textVarName,
3159 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
3160 EntryTextVarProc, probe);
3161 if (probe == (ClientData)entryPtr) {
3162 break;
3163 }
3164 } while (probe);
3165 if (probe) {
3166 /*
3167 * We were able to fetch the unset trace for our
3168 * textVarName, which means it is not unset and not
3169 * the cause of this unset trace. Instead some outdated
3170 * former variable must be, and we should ignore it.
3171 */
3172 return NULL;
3173 }
31713174 Tcl_SetVar2(interp, entryPtr->textVarName, NULL,
31723175 entryPtr->string, TCL_GLOBAL_ONLY);
31733176 Tcl_TraceVar2(interp, entryPtr->textVarName, NULL,
31743177 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
31753178 EntryTextVarProc, clientData);
31763179 entryPtr->flags |= ENTRY_VAR_TRACED;
3177 }
3180 }
31783181 return NULL;
31793182 }
31803183
36323635 entryPtr->selectFirst = -1;
36333636 entryPtr->selectLast = -1;
36343637
3635 entryPtr->cursor = None;
3638 entryPtr->cursor = NULL;
36363639 entryPtr->exportSelection = 1;
36373640 entryPtr->justify = TK_JUSTIFY_LEFT;
36383641 entryPtr->relief = TK_RELIEF_FLAT;
36393642 entryPtr->state = STATE_NORMAL;
36403643 entryPtr->displayString = entryPtr->string;
36413644 entryPtr->inset = XPAD;
3642 entryPtr->textGC = None;
3643 entryPtr->selTextGC = None;
3644 entryPtr->highlightGC = None;
3645 entryPtr->textGC = NULL;
3646 entryPtr->selTextGC = NULL;
3647 entryPtr->highlightGC = NULL;
36453648 entryPtr->avgWidth = 1;
36463649 entryPtr->validate = VALIDATE_NONE;
36473650
36483651 sbPtr->selElement = SEL_NONE;
36493652 sbPtr->curElement = SEL_NONE;
3650 sbPtr->bCursor = None;
3653 sbPtr->bCursor = NULL;
36513654 sbPtr->repeatDelay = 400;
36523655 sbPtr->repeatInterval = 100;
36533656 sbPtr->fromValue = 0.0;
8181 * in readonly state, plus used for
8282 * background. */
8383 int borderWidth; /* Width of 3-D border around window. */
84 Tk_Cursor cursor; /* Current cursor for window, or None. */
84 Tk_Cursor cursor; /* Current cursor for window, or NULL. */
8585 int exportSelection; /* Non-zero means tie internal entry selection
8686 * to X selection. */
8787 Tk_Font tkfont; /* Information about text font, or NULL. */
191191 Tk_3DBorder activeBorder; /* Used for drawing border around active
192192 * buttons. */
193193 Tk_3DBorder buttonBorder; /* Used for drawing border around buttons. */
194 Tk_Cursor bCursor; /* cursor for buttons, or None. */
194 Tk_Cursor bCursor; /* cursor for buttons, or NULL. */
195195 int bdRelief; /* 3-D effect: TK_RELIEF_RAISED, etc. */
196196 int buRelief; /* 3-D effect: TK_RELIEF_RAISED, etc. */
197197 char *command; /* Command to invoke for spin buttons. NULL
138138 * storage for the current thread.
139139 */
140140
141 typedef struct ThreadSpecificData {
141 typedef struct {
142142 int handlersActive; /* The following variable has a non-zero value
143143 * when a handler is active. */
144144 InProgress *pendingPtr; /* Topmost search in progress, or NULL if
192192
193193 static void CleanUpTkEvent(XEvent *eventPtr);
194194 static void DelayedMotionProc(ClientData clientData);
195 static int GetButtonMask(unsigned int Button);
196195 static unsigned long GetEventMaskFromXEvent(XEvent *eventPtr);
197196 static TkWindow * GetTkWindowFromXEvent(XEvent *eventPtr);
198197 static void InvokeClientMessageHandlers(ThreadSpecificData *tsdPtr,
207206 static int RefreshKeyboardMappingIfNeeded(XEvent *eventPtr);
208207 static int TkXErrorHandler(ClientData clientData,
209208 XErrorEvent *errEventPtr);
210 static void UpdateButtonEventState(XEvent *eventPtr);
211209 static int WindowEventProc(Tcl_Event *evPtr, int flags);
212210 #ifdef TK_USE_INPUT_METHODS
213211 static void CreateXIC(TkWindow *winPtr);
523521 /*
524522 *----------------------------------------------------------------------
525523 *
526 * GetButtonMask --
524 * TkGetButtonMask --
527525 *
528526 * Return the proper Button${n}Mask for the button.
529527 *
536534 *----------------------------------------------------------------------
537535 */
538536
539 static int
540 GetButtonMask(
537 static const unsigned long buttonMasks[] = {
538 0, Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
539 };
540
541 unsigned long
542 TkGetButtonMask(
541543 unsigned int button)
542544 {
543 switch (button) {
544 case 1:
545 return Button1Mask;
546 case 2:
547 return Button2Mask;
548 case 3:
549 return Button3Mask;
550 case 4:
551 return Button4Mask;
552 case 5:
553 return Button5Mask;
554 }
555 return 0;
556 }
557
558 /*
559 *----------------------------------------------------------------------
560 *
561 * UpdateButtonEventState --
562 *
563 * Update the button event state in our TkDisplay using the XEvent
564 * passed. We also may modify the the XEvent passed to fit some aspects
565 * of our TkDisplay.
566 *
567 * Results:
568 * None.
569 *
570 * Side effects:
571 * The TkDisplay's private button state may be modified. The eventPtr's
572 * state may be updated to reflect masks stored in our TkDisplay that the
573 * event doesn't contain. The eventPtr may also be modified to not
574 * contain a button state for the window in which it was not pressed in.
575 *
576 *----------------------------------------------------------------------
577 */
578
579 static void
580 UpdateButtonEventState(
581 XEvent *eventPtr)
582 {
583 TkDisplay *dispPtr;
584 int allButtonsMask = Button1Mask | Button2Mask | Button3Mask
585 | Button4Mask | Button5Mask;
586
587 switch (eventPtr->type) {
588 case ButtonPress:
589 dispPtr = TkGetDisplay(eventPtr->xbutton.display);
590 dispPtr->mouseButtonWindow = eventPtr->xbutton.window;
591 eventPtr->xbutton.state |= dispPtr->mouseButtonState;
592
593 dispPtr->mouseButtonState |= GetButtonMask(eventPtr->xbutton.button);
594 break;
595
596 case ButtonRelease:
597 dispPtr = TkGetDisplay(eventPtr->xbutton.display);
598 dispPtr->mouseButtonWindow = None;
599 dispPtr->mouseButtonState &= ~GetButtonMask(eventPtr->xbutton.button);
600 eventPtr->xbutton.state |= dispPtr->mouseButtonState;
601 break;
602
603 case MotionNotify:
604 dispPtr = TkGetDisplay(eventPtr->xmotion.display);
605 if (dispPtr->mouseButtonState & allButtonsMask) {
606 if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) {
607 /*
608 * This motion event should not be interpreted as a button
609 * press + motion event since this is not the same window the
610 * button was pressed down in.
611 */
612
613 dispPtr->mouseButtonState &= ~allButtonsMask;
614 dispPtr->mouseButtonWindow = None;
615 } else {
616 eventPtr->xmotion.state |= dispPtr->mouseButtonState;
617 }
618 }
619 break;
620 }
545 return (button > Button5) ? 0 : buttonMasks[button];
621546 }
622547
623548 /*
12191144 ThreadSpecificData *tsdPtr =
12201145 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
12211146
1222 UpdateButtonEventState(eventPtr);
1147 #if !defined(MAC_OSX_TK) && !defined(_WIN32)
1148 if (((eventPtr->type == ButtonPress) || (eventPtr->type == ButtonRelease))
1149 && ((eventPtr->xbutton.button - 6) < 2)) {
1150 eventPtr->xbutton.button -= 2;
1151 eventPtr->xbutton.state ^= ShiftMask;
1152 }
1153 #endif
12231154
12241155 /*
12251156 * If the generic handler processed this event we are done and can return.
13671298 * handle CreateNotify events, so we gotta pass 'em through.
13681299 */
13691300
1370 if ((ip.winPtr != None)
1301 if ((ip.winPtr != NULL)
13711302 && ((mask != SubstructureNotifyMask)
13721303 || (eventPtr->type == CreateNotify))) {
13731304 TkBindEventProc(winPtr, eventPtr);
14381369 ipPtr->nextHandler = NULL;
14391370 }
14401371 if (ipPtr->winPtr == winPtr) {
1441 ipPtr->winPtr = None;
1372 ipPtr->winPtr = NULL;
14421373 }
14431374 }
14441375 ckfree(handlerPtr);
278278 * pass the event through to Tk bindings.
279279 */
280280
281 if (eventPtr->xfocus.send_event == GENERATED_FOCUS_EVENT_MAGIC) {
282 eventPtr->xfocus.send_event = 0;
281 if ((eventPtr->xfocus.send_event & GENERATED_FOCUS_EVENT_MAGIC) == GENERATED_FOCUS_EVENT_MAGIC) {
282 eventPtr->xfocus.send_event &= ~GENERATED_FOCUS_EVENT_MAGIC;
283283 return 1;
284284 }
285285
550550 return;
551551 }
552552
553 /*
554 * Get the current focus window with the same display and application
555 * as winPtr.
556 */
557
553558 displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
554559
555560 /*
556 * If force is set, we should make sure we grab the focus regardless of
557 * the current focus window since under Windows, we may need to take
558 * control away from another application.
561 * Do nothing if the window already has focus and force is not set. If
562 * force is set, we need to grab the focus, since under Windows or macOS
563 * this may involve taking control away from another application.
559564 */
560565
561566 if (winPtr == displayFocusPtr->focusWinPtr && !force) {
563568 }
564569
565570 /*
566 * Find the top-level window for winPtr, then find (or create) a record
567 * for the top-level. Also see whether winPtr and all its ancestors are
571 * Find the toplevel window for winPtr, then find (or create) a record
572 * for the toplevel. Also see whether winPtr and all its ancestors are
568573 * mapped.
569574 */
570575
571576 allMapped = 1;
572577 for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) {
573578 if (topLevelPtr == NULL) {
579
574580 /*
575581 * The window is being deleted. No point in worrying about giving
576582 * it the focus.
587593 }
588594
589595 /*
590 * If the new focus window isn't mapped, then we can't focus on it (X will
591 * generate an error, for example). Instead, create an event handler that
592 * will set the focus to this window once it gets mapped. At the same
593 * time, delete any old handler that might be around; it's no longer
594 * relevant.
596 * If any ancestor of the new focus window isn't mapped, then we can't set
597 * focus for it (X will generate an error, for example). Instead, create
598 * an event handler that will set the focus to this window once it gets
599 * mapped. At the same time, delete any old handler that might be around;
600 * it's no longer relevant.
595601 */
596602
597603 if (displayFocusPtr->focusOnMapPtr != NULL) {
622628 }
623629 tlFocusPtr->focusWinPtr = winPtr;
624630
625 /*
626 * Reset the window system's focus window and generate focus events, with
627 * two special cases:
628 *
629 * 1. If the application is embedded and doesn't currently have the focus,
630 * don't set the focus directly. Instead, see if the embedding code can
631 * claim the focus from the enclosing container.
632 * 2. Otherwise, if the application doesn't currently have the focus,
633 * don't change the window system's focus unless it was already in this
634 * application or "force" was specified.
635 */
636
637 if ((topLevelPtr->flags & TK_EMBEDDED)
638 && (displayFocusPtr->focusWinPtr == NULL)) {
631 if (topLevelPtr->flags & TK_EMBEDDED &&
632 (displayFocusPtr->focusWinPtr == NULL)) {
633
634 /*
635 * We are assigning focus to an embedded toplevel. The platform
636 * specific function TkpClaimFocus needs to handle the job of
637 * assigning focus to the container, since we have no way to find the
638 * contaiuner.
639 */
640
639641 TkpClaimFocus(topLevelPtr, force);
640642 } else if ((displayFocusPtr->focusWinPtr != NULL) || force) {
641 /*
642 * Generate events to shift focus between Tk windows. We do this
643 * regardless of what TkpChangeFocus does with the real X focus so
644 * that Tk widgets track focus commands when there is no window
645 * manager. GenerateFocusEvents will set up a serial number marker so
646 * we discard focus events that are triggered by the ChangeFocus.
643
644 /*
645 * If we are forcing removal of focus from a container hosting a
646 * toplevel from a different application, clear the focus in that
647 * application.
648 */
649
650 if (force) {
651 TkWindow *focusPtr = winPtr->dispPtr->focusPtr;
652 if (focusPtr && focusPtr->mainPtr != winPtr->mainPtr) {
653 DisplayFocusInfo *displayFocusPtr2 = FindDisplayFocusInfo(
654 focusPtr->mainPtr, focusPtr->dispPtr);
655 displayFocusPtr2->focusWinPtr = NULL;
656 }
657 }
658
659 /*
660 * Call the platform specific function TkpChangeFocus to move the
661 * window manager's focus to a new toplevel.
647662 */
648663
649664 serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force);
1212
1313 #include "tkInt.h"
1414 #include "tkFont.h"
15
15 #if defined(MAC_OSX_TK)
16 #include "tkMacOSXInt.h"
17 #endif
1618 /*
1719 * The following structure is used to keep track of all the fonts that exist
1820 * in the current application. It must be stored in the TkMainInfo for the
871873 ClientData clientData) /* Info about application's fonts. */
872874 {
873875 TkFontInfo *fiPtr = clientData;
874
876 #if defined(MAC_OSX_TK)
877
878 /*
879 * On macOS it is catastrophic to recompute all widgets while the
880 * [NSView drawRect] method is drawing. The best that we can do in
881 * that situation is to abort the recomputation and hope for the best.
882 */
883
884 if (TkpAppIsDrawing()) {
885 return;
886 }
887 #endif
875888 fiPtr->updatePending = 0;
876889 RecomputeWidgets(fiPtr->mainPtr->winPtr);
877890 }
661661 framePtr->type = type;
662662 framePtr->colormap = colormap;
663663 framePtr->relief = TK_RELIEF_FLAT;
664 framePtr->cursor = None;
664 framePtr->cursor = NULL;
665665
666666 if (framePtr->type == TYPE_LABELFRAME) {
667667 Labelframe *labelframePtr = (Labelframe *) framePtr;
668668
669669 labelframePtr->labelAnchor = LABELANCHOR_NW;
670 labelframePtr->textGC = None;
670 labelframePtr->textGC = NULL;
671671 }
672672
673673 /*
863863
864864 if (framePtr->type == TYPE_LABELFRAME) {
865865 Tk_FreeTextLayout(labelframePtr->textLayout);
866 if (labelframePtr->textGC != None) {
866 if (labelframePtr->textGC != NULL) {
867867 Tk_FreeGC(framePtr->display, labelframePtr->textGC);
868868 }
869869 }
11191119 gcValues.graphics_exposures = False;
11201120 gc = Tk_GetGC(tkwin, GCForeground | GCFont | GCGraphicsExposures,
11211121 &gcValues);
1122 if (labelframePtr->textGC != None) {
1122 if (labelframePtr->textGC != NULL) {
11231123 Tk_FreeGC(framePtr->display, labelframePtr->textGC);
11241124 }
11251125 labelframePtr->textGC = gc;
219219 /*
220220 * All the slaves for which this is the master window must now be
221221 * repositioned to take account of the new internal border width. To
222 * signal all the geometry managers to do this, just resize the window to
223 * its current size. The ConfigureNotify event will cause geometry
224 * managers to recompute everything.
222 * signal all the geometry managers to do this, trigger a ConfigureNotify
223 * event. This will cause geometry managers to recompute everything.
225224 */
226225
227226 if (changed) {
228 Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));
227 TkDoConfigureNotify(winPtr);
229228 }
230229 }
231230
326325 {
327326 register TkWindow *winPtr = (TkWindow *) tkwin;
328327
329 if (winPtr->geometryMaster != NULL &&
330 strcmp(winPtr->geometryMaster, master) == 0) {
328 if (winPtr->geomMgrName != NULL &&
329 strcmp(winPtr->geomMgrName, master) == 0) {
331330 return TCL_OK;
332331 }
333 if (winPtr->geometryMaster != NULL) {
332 if (winPtr->geomMgrName != NULL) {
334333 if (interp != NULL) {
335334 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
336335 "cannot use geometry manager %s inside %s which already"
337336 " has slaves managed by %s",
338 master, Tk_PathName(tkwin), winPtr->geometryMaster));
337 master, Tk_PathName(tkwin), winPtr->geomMgrName));
339338 Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "FIGHT", NULL);
340339 }
341340 return TCL_ERROR;
342341 }
343342
344 winPtr->geometryMaster = ckalloc(strlen(master) + 1);
345 strcpy(winPtr->geometryMaster, master);
343 winPtr->geomMgrName = ckalloc(strlen(master) + 1);
344 strcpy(winPtr->geomMgrName, master);
346345 return TCL_OK;
347346 }
348347
371370 {
372371 register TkWindow *winPtr = (TkWindow *) tkwin;
373372
374 if (winPtr->geometryMaster != NULL &&
375 strcmp(winPtr->geometryMaster, master) != 0) {
373 if (winPtr->geomMgrName != NULL &&
374 strcmp(winPtr->geomMgrName, master) != 0) {
376375 Tcl_Panic("Trying to free %s from geometry manager %s",
377 winPtr->geometryMaster, master);
378 }
379 if (winPtr->geometryMaster != NULL) {
380 ckfree(winPtr->geometryMaster);
381 winPtr->geometryMaster = NULL;
376 winPtr->geomMgrName, master);
377 }
378 if (winPtr->geomMgrName != NULL) {
379 ckfree(winPtr->geomMgrName);
380 winPtr->geomMgrName = NULL;
382381 }
383382 }
384383
424423 Tk_Window ancestor, parent;
425424 TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr;
426425
426 ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master;
427
428 ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master;
427429 if (master == Tk_Parent(slave)) {
428430 /*
429431 * If the slave is a direct descendant of the master, don't bother
569571 Tk_Window ancestor;
570572 TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr;
571573
574 ((TkWindow *)slave)->maintainerPtr = NULL;
575
576 ((TkWindow *)slave)->maintainerPtr = NULL;
572577 if (master == Tk_Parent(slave)) {
573578 /*
574579 * If the slave is a direct descendant of the master,
2121 * the current thread.
2222 */
2323
24 typedef struct ThreadSpecificData {
24 typedef struct {
2525 int initialized;
2626 Tcl_HashTable uidTable;
2727 } ThreadSpecificData;
132132 */
133133
134134 #define GENERATED_GRAB_EVENT_MAGIC ((Bool) 0x147321ac)
135
136 /*
137 * Mask that selects any of the state bits corresponding to buttons, plus
138 * masks that select individual buttons' bits:
139 */
140
141 #define ALL_BUTTONS \
142 (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
143 static const unsigned int buttonStates[] = {
144 Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
145 };
146135
147136 /*
148137 * Forward declarations for functions declared later in this file:
425414 }
426415
427416 Tk_MakeWindowExist(tkwin);
428 #ifndef MAC_OSX_TK
429 if (!grabGlobal)
430 #else
431 if (0)
432 #endif /* MAC_OSX_TK */
433 {
417 if (!grabGlobal) {
434418 Window dummy1, dummy2;
435419 int dummy3, dummy4, dummy5, dummy6;
436420 unsigned int state;
885869 return 1;
886870 }
887871 } else {
888 if ((eventPtr->xbutton.state & ALL_BUTTONS)
889 == buttonStates[eventPtr->xbutton.button - Button1]) {
872 if (eventPtr->xbutton.button != AnyButton &&
873 ((eventPtr->xbutton.state & ALL_BUTTONS)
874 == (unsigned int)TkGetButtonMask(eventPtr->xbutton.button))) {
890875 ReleaseButtonGrab(dispPtr); /* Note 4. */
891876 }
892877 }
13851370 static int
13861371 GrabWinEventProc(
13871372 Tcl_Event *evPtr, /* Event of type NewGrabWinEvent. */
1388 int flags) /* Flags argument to Tk_DoOneEvent: indicates
1373 int flags) /* Flags argument to Tcl_DoOneEvent: indicates
13891374 * what kinds of events are being processed
13901375 * right now. */
13911376 {
19121912 GridLayout *layoutPtr; /* Temporary layout structure. */
19131913 int requiredSize; /* The natural size of the grid (pixels).
19141914 * This is the minimum size needed to
1915 * accomodate all of the slaves at their
1915 * accommodate all of the slaves at their
19161916 * requested sizes. */
19171917 int offset; /* The pixel offset of the right edge of the
19181918 * current slot from the beginning of the
24852485 * Side effects:
24862486 * The width and height arguments are filled in the master data
24872487 * structure. Additional space is allocated for the constraints to
2488 * accomodate the offsets.
2488 * accommodate the offsets.
24892489 *
24902490 *----------------------------------------------------------------------
24912491 */
29372937 Gridder *masterPtr = NULL;
29382938 Gridder *slavePtr;
29392939 Tk_Window other, slave, parent, ancestor;
2940 TkWindow *master;
29402941 int i, j, tmp;
29412942 int numWindows;
29422943 int width;
33513352 }
33523353
33533354 /*
3354 * Try to make sure our master isn't managed by us.
3355 * Check for management loops.
33553356 */
33563357
3357 if (masterPtr->masterPtr == slavePtr) {
3358 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3358 for (master = (TkWindow *)masterPtr->tkwin; master != NULL;
3359 master = (TkWindow *)TkGetGeomMaster(master)) {
3360 if (master == (TkWindow *)slave) {
3361 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
33593362 "can't put %s inside %s, would cause management loop",
3360 Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin)));
3361 Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
3362 Unlink(slavePtr);
3363 return TCL_ERROR;
3364 }
3363 Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin)));
3364 Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
3365 Unlink(slavePtr);
3366 return TCL_ERROR;
3367 }
3368 }
3369 if (masterPtr->tkwin != Tk_Parent(slave)) {
3370 ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin;
3371 }
33653372
33663373 Tk_ManageGeometry(slave, &gridMgrType, slavePtr);
33673374
6565 * when the world is falling apart.) */
6666 } ImageMaster;
6767
68 typedef struct ThreadSpecificData {
68 typedef struct {
6969 Tk_ImageType *imageTypeList;/* First in a list of all known image
7070 * types. */
7171 Tk_ImageType *oldImageTypeList;
774774
775775 gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
776776 newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
777 if (newGC != None) {
777 if (newGC != NULL) {
778778 XFillRectangle(Tk_Display(tkwin), pmap, newGC, 0, 0,
779779 (unsigned) width, (unsigned) height);
780780 Tk_FreeGC(Tk_Display(tkwin), newGC);
426426 }
427427 gc = Tk_GetGC(instancePtr->tkwin, mask, &gcValues);
428428 } else {
429 gc = None;
430 }
431 if (instancePtr->gc != None) {
429 gc = NULL;
430 }
431 if (instancePtr->gc != NULL) {
432432 Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
433433 }
434434 instancePtr->gc = gc;
440440 * it clear that this instance cannot be displayed. Then report the error.
441441 */
442442
443 if (instancePtr->gc != None) {
443 if (instancePtr->gc != NULL) {
444444 Tk_FreeGC(Tk_Display(instancePtr->tkwin), instancePtr->gc);
445445 }
446 instancePtr->gc = None;
446 instancePtr->gc = NULL;
447447 Tcl_AppendObjToErrorInfo(masterPtr->interp, Tcl_ObjPrintf(
448448 "\n (while configuring image \"%s\")", Tk_NameOfImage(
449449 masterPtr->tkMaster)));
847847 instancePtr->bg = NULL;
848848 instancePtr->bitmap = None;
849849 instancePtr->mask = None;
850 instancePtr->gc = None;
850 instancePtr->gc = NULL;
851851 instancePtr->nextPtr = masterPtr->instancePtr;
852852 masterPtr->instancePtr = instancePtr;
853853 ImgBmapConfigureInstance(instancePtr);
901901 * creating the image instance so it can't be displayed.
902902 */
903903
904 if (instancePtr->gc == None) {
904 if (instancePtr->gc == NULL) {
905905 return;
906906 }
907907
972972 if (instancePtr->mask != None) {
973973 Tk_FreePixmap(display, instancePtr->mask);
974974 }
975 if (instancePtr->gc != None) {
975 if (instancePtr->gc != NULL) {
976976 Tk_FreeGC(display, instancePtr->gc);
977977 }
978978 if (instancePtr->masterPtr->instancePtr == instancePtr) {
6262 * Most data in a GIF image is binary and is treated as such. However, a few
6363 * key bits are stashed in ASCII. If we try to compare those pieces to the
6464 * char they represent, it will fail on any non-ASCII (eg, EBCDIC) system. To
65 * accomodate these systems, we test against the numeric value of the ASCII
65 * accommodate these systems, we test against the numeric value of the ASCII
6666 * characters instead of the characters themselves. This is encoding
67 * independant.
67 * independent.
6868 */
6969
7070 static const char GIF87a[] = { /* ASCII GIF87a */
10331033 int transparent)
10341034 {
10351035 unsigned char initialCodeSize;
1036 int xpos = 0, ypos = 0, pass = 0, i;
1036 int xpos = 0, ypos = 0, pass = 0, i, count;
10371037 register unsigned char *pixelPtr;
10381038 static const int interlaceStep[] = { 8, 8, 4, 2 };
10391039 static const int interlaceStart[] = { 0, 4, 2, 1 };
12501250 ypos++;
12511251 }
12521252 pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3);
1253 }
1254
1255 /*
1256 * Now read until the final zero byte.
1257 * It was observed that there might be 1 length blocks
1258 * (test imgPhoto-14.1) which are not read.
1259 *
1260 * The field "stack" is abused for temporary buffer. it has 4096 bytes
1261 * and we need 256.
1262 *
1263 * Loop until we hit a 0 length block which is the end sign.
1264 */
1265 while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack)))
1266 {
1267 if (-1 == count ) {
1268 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1269 "error reading GIF image: %s", Tcl_PosixError(interp)));
1270 return TCL_ERROR;
1271 }
12531272 }
12541273 return TCL_OK;
12551274 }
99 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
1010 */
1111
12 #include "assert.h"
1312 #include "tkInt.h"
1413
1514 #define PNG_INT32(a,b,c,d) \
1818 */
1919
2020 #include "tkImgPhoto.h"
21 #ifdef MAC_OSX_TK
22 #define TKPUTIMAGE_CAN_BLEND
23 #endif
2124
2225 /*
2326 * Declaration for internal Xlib function used here:
2932 * Forward declarations
3033 */
3134
32 #ifndef MAC_OSX_TK
35 #ifndef TKPUTIMAGE_CAN_BLEND
3336 static void BlendComplexAlpha(XImage *bgImg, PhotoInstance *iPtr,
3437 int xOffset, int yOffset, int width, int height);
3538 #endif
305308 nGreen = nBlue = 0;
306309 mono = 1;
307310 instancePtr->visualInfo = *visInfoPtr;
308 switch (visInfoPtr->class) {
311 switch (visInfoPtr->c_class) {
309312 case DirectColor:
310313 case TrueColor:
311314 nRed = 1 << CountBits(visInfoPtr->red_mask);
410413 *
411414 *----------------------------------------------------------------------
412415 */
413 #ifndef MAC_OSX_TK
416 #ifndef TKPUTIMAGE_CAN_BLEND
414417 #ifndef _WIN32
415418 #define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift))
416419 #define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift))
485488 * optimized.
486489 */
487490
488 #if !(defined(_WIN32) || defined(MAC_OSX_TK))
491 #if !defined(_WIN32)
489492 if (bgImg->depth < 24) {
490493 unsigned char red_mlen, green_mlen, blue_mlen;
491494
533536 }
534537 return;
535538 }
536 #endif /* !_WIN32 && !MAC_OSX_TK */
539 #endif /* !_WIN32 */
537540
538541 for (y = 0; y < height; y++) {
539542 line = (y + yOffset) * iPtr->masterPtr->width;
576579 }
577580 #undef ALPHA_BLEND
578581 }
579 #endif /* MAC_OSX_TK */
582 #endif /* TKPUTIMAGE_CAN_BLEND */
580583
581584 /*
582585 *----------------------------------------------------------------------
608611 * to imageX and imageY. */
609612 {
610613 PhotoInstance *instancePtr = clientData;
614 #ifndef TKPUTIMAGE_CAN_BLEND
611615 XVisualInfo visInfo = instancePtr->visualInfo;
616 #endif
612617
613618 /*
614619 * If there's no pixmap, it means that an error occurred while creating
619624 return;
620625 }
621626
622 #ifdef MAC_OSX_TK
623 /*
624 * The Mac version of TkPutImage handles RGBA images directly. There is
627 #ifdef TKPUTIMAGE_CAN_BLEND
628 /*
629 * If TkPutImage can handle RGBA Ximages directly there is
625630 * no need to call XGetImage or to do the Porter-Duff compositing by hand.
626 * We just let the CG graphics library do it, using the graphics hardware.
627 */
631 */
632
628633 unsigned char *rgbaPixels = instancePtr->masterPtr->pix32;
629
630634 XImage *photo = XCreateImage(display, NULL, 32, ZPixmap, 0, (char*)rgbaPixels,
631635 (unsigned int)instancePtr->width,
632636 (unsigned int)instancePtr->height,
637641 photo->data = NULL;
638642 XDestroyImage(photo);
639643 #else
644
640645 if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA)
641646 && visInfo.depth >= 15
642 && (visInfo.class == DirectColor || visInfo.class == TrueColor)) {
647 && (visInfo.c_class == DirectColor || visInfo.c_class == TrueColor)) {
643648 Tk_ErrorHandler handler;
644649 XImage *bgImg = NULL;
645650
694699 XSetClipMask(display, instancePtr->gc, None);
695700 XSetClipOrigin(display, instancePtr->gc, 0, 0);
696701 }
697 XFlush(display);
702 (void)XFlush(display);
698703 #endif
699704 }
700705
942947 mono = 0;
943948 }
944949
945 switch (instancePtr->visualInfo.class) {
950 switch (instancePtr->visualInfo.c_class) {
946951 case DirectColor:
947952 case TrueColor:
948953 if ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask)))
12071212 * store them in *colors.
12081213 */
12091214
1210 if ((colorPtr->visualInfo.class == DirectColor)
1211 || (colorPtr->visualInfo.class == TrueColor)) {
1215 if ((colorPtr->visualInfo.c_class == DirectColor)
1216 || (colorPtr->visualInfo.c_class == TrueColor)) {
12121217
12131218 /*
12141219 * Direct/True Color: allocate shades of red, green, blue
13621367 */
13631368
13641369 #ifndef _WIN32
1365 if ((colorPtr->visualInfo.class != DirectColor)
1366 && (colorPtr->visualInfo.class != TrueColor)) {
1370 if ((colorPtr->visualInfo.c_class != DirectColor)
1371 && (colorPtr->visualInfo.c_class != TrueColor)) {
13671372 colorPtr->flags |= MAP_COLORS;
13681373 }
13691374 #endif /* _WIN32 */
13891394 } else {
13901395 g = (i * (nGreen - 1) + 127) / 255;
13911396 b = (i * (nBlue - 1) + 127) / 255;
1392 if ((colorPtr->visualInfo.class == DirectColor)
1393 || (colorPtr->visualInfo.class == TrueColor)) {
1397 if ((colorPtr->visualInfo.c_class == DirectColor)
1398 || (colorPtr->visualInfo.c_class == TrueColor)) {
13941399 colorPtr->redValues[i] =
13951400 colors[r].pixel & colorPtr->visualInfo.red_mask;
13961401 colorPtr->greenValues[i] =
15841589 if (instancePtr->pixels != None) {
15851590 Tk_FreePixmap(instancePtr->display, instancePtr->pixels);
15861591 }
1587 if (instancePtr->gc != None) {
1592 if (instancePtr->gc != NULL) {
15881593 Tk_FreeGC(instancePtr->display, instancePtr->gc);
15891594 }
15901595 if (instancePtr->imagePtr != NULL) {
16481653 * DirectColor with many colors).
16491654 */
16501655
1651 if ((colorPtr->visualInfo.class == DirectColor)
1652 || (colorPtr->visualInfo.class == TrueColor)) {
1656 if ((colorPtr->visualInfo.c_class == DirectColor)
1657 || (colorPtr->visualInfo.c_class == TrueColor)) {
16531658 int nRed, nGreen, nBlue, result;
16541659
16551660 result = sscanf(colorPtr->id.palette, "%d/%d/%d", &nRed,
124124 NULL
125125 };
126126
127 typedef struct ThreadSpecificData {
127 typedef struct {
128128 Tk_PhotoImageFormat *formatList;
129129 /* Pointer to the first in the list of known
130130 * photo image formats.*/
401401 void TkpMenuThreadInit(void)
402402 }
403403 declare 113 {
404 void TkClipBox(TkRegion rgn, XRectangle *rect_return)
404 int TkClipBox(TkRegion rgn, XRectangle *rect_return)
405405 }
406406 declare 114 {
407407 TkRegion TkCreateRegion(void)
408408 }
409409 declare 115 {
410 void TkDestroyRegion(TkRegion rgn)
410 int TkDestroyRegion(TkRegion rgn)
411411 }
412412 declare 116 {
413 void TkIntersectRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
413 int TkIntersectRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
414414 }
415415 declare 117 {
416416 int TkRectInRegion(TkRegion rgn, int x, int y, unsigned int width,
417417 unsigned int height)
418418 }
419419 declare 118 {
420 void TkSetRegion(Display *display, GC gc, TkRegion rgn)
420 int TkSetRegion(Display *display, GC gc, TkRegion rgn)
421421 }
422422 declare 119 {
423 void TkUnionRectWithRegion(XRectangle *rect,
423 int TkUnionRectWithRegion(XRectangle *rect,
424424 TkRegion src, TkRegion dr_return)
425425 }
426426 declare 121 aqua {
466466 void TkGCCleanup(TkDisplay *dispPtr)
467467 }
468468 declare 145 {
469 void TkSubtractRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
469 int TkSubtractRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return)
470470 }
471471 declare 146 {
472472 void TkStylePkgInit(TkMainInfo *mainPtr)
842842 declare 45 win {
843843 int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
844844 Tcl_Obj *const objv[])
845 }
846 declare 47 win {
847 Tk_Window TkpGetCapture(void)
845848 }
846849
847850 ################################
10081011 Tk_Window TkMacOSXGetCapture(void)
10091012 }
10101013 declare 49 aqua {
1011 Window TkGetTransientMaster(TkWindow *winPtr)
1014 Tk_Window TkGetTransientMaster(TkWindow *winPtr)
10121015 }
10131016 declare 50 aqua {
10141017 int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state)
15431546 int XBell(Display *d, int i)
15441547 }
15451548 declare 14 aqua {
1546 void XChangeProperty(Display *d, Window w, Atom a1, Atom a2, int i1,
1549 int XChangeProperty(Display *d, Window w, Atom a1, Atom a2, int i1,
15471550 int i2, _Xconst unsigned char *c, int i3)
15481551 }
15491552 declare 15 aqua {
1550 void XChangeWindowAttributes(Display *d, Window w, unsigned long ul,
1553 int XChangeWindowAttributes(Display *d, Window w, unsigned long ul,
15511554 XSetWindowAttributes *x)
15521555 }
15531556 declare 16 aqua {
1554 void XConfigureWindow(Display *d, Window w, unsigned int i,
1557 int XConfigureWindow(Display *d, Window w, unsigned int i,
15551558 XWindowChanges *x)
15561559 }
15571560 declare 17 aqua {
1558 void XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
1561 int XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
15591562 int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)
15601563 }
15611564 declare 18 aqua {
1562 void XCopyPlane(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
1565 int XCopyPlane(Display *d, Drawable dr1, Drawable dr2, GC g, int i1,
15631566 int i2, unsigned int ui1,
15641567 unsigned int ui2, int i3, int i4, unsigned long ul)
15651568 }
15711574 int XDefineCursor(Display *d, Window w, Cursor c)
15721575 }
15731576 declare 21 aqua {
1574 void XDestroyWindow(Display *d, Window w)
1577 int XDestroyWindow(Display *d, Window w)
15751578 }
15761579 declare 22 aqua {
1577 void XDrawArc(Display *d, Drawable dr, GC g, int i1, int i2,
1580 int XDrawArc(Display *d, Drawable dr, GC g, int i1, int i2,
15781581 unsigned int ui1, unsigned int ui2, int i3, int i4)
15791582 }
15801583 declare 23 aqua {
15811584 int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)
15821585 }
15831586 declare 24 aqua {
1584 void XDrawRectangle(Display *d, Drawable dr, GC g, int i1, int i2,
1587 int XDrawRectangle(Display *d, Drawable dr, GC g, int i1, int i2,
15851588 unsigned int ui1, unsigned int ui2)
15861589 }
15871590 declare 25 aqua {
1588 void XFillArc(Display *d, Drawable dr, GC g, int i1, int i2,
1591 int XFillArc(Display *d, Drawable dr, GC g, int i1, int i2,
15891592 unsigned int ui1, unsigned int ui2, int i3, int i4)
15901593 }
15911594 declare 26 aqua {
1592 void XFillPolygon(Display *d, Drawable dr, GC g, XPoint *x,
1595 int XFillPolygon(Display *d, Drawable dr, GC g, XPoint *x,
15931596 int i1, int i2, int i3)
15941597 }
15951598 declare 27 aqua {
16261629 KeyCode XKeysymToKeycode(Display *d, KeySym k)
16271630 }
16281631 declare 36 aqua {
1629 void XMapWindow(Display *d, Window w)
1632 int XMapWindow(Display *d, Window w)
16301633 }
16311634 declare 37 aqua {
1632 void XMoveResizeWindow(Display *d, Window w, int i1, int i2,
1635 int XMoveResizeWindow(Display *d, Window w, int i1, int i2,
16331636 unsigned int ui1, unsigned int ui2)
16341637 }
16351638 declare 38 aqua {
1636 void XMoveWindow(Display *d, Window w, int i1, int i2)
1639 int XMoveWindow(Display *d, Window w, int i1, int i2)
16371640 }
16381641 declare 39 aqua {
16391642 Bool XQueryPointer(Display *d, Window w1, Window *w2, Window *w3,
16401643 int *i1, int *i2, int *i3, int *i4, unsigned int *ui)
16411644 }
16421645 declare 40 aqua {
1643 void XRaiseWindow(Display *d, Window w)
1646 int XRaiseWindow(Display *d, Window w)
16441647 }
16451648 declare 41 aqua {
1646 void XRefreshKeyboardMapping(XMappingEvent *x)
1649 int XRefreshKeyboardMapping(XMappingEvent *x)
16471650 }
16481651 declare 42 aqua {
1649 void XResizeWindow(Display *d, Window w, unsigned int ui1,
1652 int XResizeWindow(Display *d, Window w, unsigned int ui1,
16501653 unsigned int ui2)
16511654 }
16521655 declare 43 aqua {
1653 void XSelectInput(Display *d, Window w, long l)
1656 int XSelectInput(Display *d, Window w, long l)
16541657 }
16551658 declare 44 aqua {
16561659 Status XSendEvent(Display *d, Window w, Bool b, long l, XEvent *x)
16571660 }
16581661 declare 45 aqua {
1659 void XSetIconName(Display *d, Window w, _Xconst char *c)
1662 int XSetIconName(Display *d, Window w, _Xconst char *c)
16601663 }
16611664 declare 46 aqua {
1662 void XSetInputFocus(Display *d, Window w, int i, Time t)
1665 int XSetInputFocus(Display *d, Window w, int i, Time t)
16631666 }
16641667 declare 47 aqua {
16651668 int XSetSelectionOwner(Display *d, Atom a, Window w, Time t)
16661669 }
16671670 declare 48 aqua {
1668 void XSetWindowBackground(Display *d, Window w, unsigned long ul)
1671 int XSetWindowBackground(Display *d, Window w, unsigned long ul)
16691672 }
16701673 declare 49 aqua {
1671 void XSetWindowBackgroundPixmap(Display *d, Window w, Pixmap p)
1674 int XSetWindowBackgroundPixmap(Display *d, Window w, Pixmap p)
16721675 }
16731676 declare 50 aqua {
1674 void XSetWindowBorder(Display *d, Window w, unsigned long ul)
1677 int XSetWindowBorder(Display *d, Window w, unsigned long ul)
16751678 }
16761679 declare 51 aqua {
1677 void XSetWindowBorderPixmap(Display *d, Window w, Pixmap p)
1680 int XSetWindowBorderPixmap(Display *d, Window w, Pixmap p)
16781681 }
16791682 declare 52 aqua {
1680 void XSetWindowBorderWidth(Display *d, Window w, unsigned int ui)
1683 int XSetWindowBorderWidth(Display *d, Window w, unsigned int ui)
16811684 }
16821685 declare 53 aqua {
1683 void XSetWindowColormap(Display *d, Window w, Colormap c)
1686 int XSetWindowColormap(Display *d, Window w, Colormap c)
16841687 }
16851688 declare 54 aqua {
1686 void XUngrabKeyboard(Display *d, Time t)
1689 int XUngrabKeyboard(Display *d, Time t)
16871690 }
16881691 declare 55 aqua {
16891692 int XUngrabPointer(Display *d, Time t)
16901693 }
16911694 declare 56 aqua {
1692 void XUnmapWindow(Display *d, Window w)
1695 int XUnmapWindow(Display *d, Window w)
16931696 }
16941697 declare 57 aqua {
16951698 int TkPutImage(unsigned long *colors, int ncolors, Display *display,
17571760 int _XInitImageFuncPtrs(XImage *image)
17581761 }
17591762 declare 76 aqua {
1760 XIC XCreateIC(void)
1763 XIC XCreateIC(XIM xim, ...)
17611764 }
17621765 declare 77 aqua {
17631766 XVisualInfo *XGetVisualInfo(Display *display, long vinfo_mask,
17761779 XSegment *segments, int nsegments)
17771780 }
17781781 declare 81 aqua {
1779 void XForceScreenSaver(Display *display, int mode)
1782 int XForceScreenSaver(Display *display, int mode)
17801783 }
17811784 declare 82 aqua {
17821785 int XDrawLine(Display *d, Drawable dr, GC g, int x1, int y1,
17871790 int x, int y, unsigned int width, unsigned int height)
17881791 }
17891792 declare 84 aqua {
1790 void XClearWindow(Display *d, Window w)
1793 int XClearWindow(Display *d, Window w)
17911794 }
17921795 declare 85 aqua {
17931796 int XDrawPoint(Display *display, Drawable d, GC gc, int x, int y)
18021805 unsigned int src_height, int dest_x, int dest_y)
18031806 }
18041807 declare 88 aqua {
1805 void XQueryColor(Display *display, Colormap colormap, XColor *def_in_out)
1808 int XQueryColor(Display *display, Colormap colormap, XColor *def_in_out)
18061809 }
18071810 declare 89 aqua {
1808 void XQueryColors(Display *display, Colormap colormap,
1811 int XQueryColors(Display *display, Colormap colormap,
18091812 XColor *defs_in_out, int ncolors)
18101813 }
18111814 declare 90 aqua {
18131816 Window **w4, unsigned int *ui)
18141817 }
18151818 declare 91 aqua {
1816 int XSync(Display *display, Bool flag)
1819 int XSync(Display *display, Bool discard)
1820 }
1821 declare 107 aqua {
1822 int XFlush(Display *display)
1823 }
1824 declare 108 aqua {
1825 int XGrabServer(Display *display)
1826 }
1827 declare 109 aqua {
1828 int XUngrabServer(Display *display)
1829 }
1830 declare 110 aqua {
1831 int XFree(void *data)
1832 }
1833 declare 111 aqua {
1834 int XNoOp(Display *display)
1835 }
1836 declare 112 aqua {
1837 XAfterFunction XSynchronize(Display *display, Bool onoff)
1838 }
1839 declare 114 aqua {
1840 VisualID XVisualIDFromVisual(Visual *visual)
1841 }
1842 declare 137 aqua {
1843 int XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
1844 int sx, int sy, int dx, int dy,
1845 unsigned int w, unsigned int h)
18171846 }
18181847
18191848 # Local Variables:
8282 # define PTR2UINT(p) ((unsigned int)(p))
8383 # endif
8484 #endif
85
86 #ifndef TCL_Z_MODIFIER
87 # if defined(_WIN64)
88 # define TCL_Z_MODIFIER "I"
89 # elif defined(__GNUC__) && !defined(_WIN32)
90 # define TCL_Z_MODIFIER "z"
91 # else
92 # define TCL_Z_MODIFIER ""
93 # endif
94 #endif /* !TCL_Z_MODIFIER */
8595
8696 /*
8797 * Opaque type declarations:
321331 * Tk_Window token to a list of slaves managed
322332 * by that master. */
323333 int geomInit;
334
335 #define TkGetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \
336 ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr)
324337
325338 /*
326339 * Information used by tkGet.c only:
488501 */
489502
490503 int mouseButtonState; /* Current mouse button state for this
491 * display. */
504 * display. NOT USED as of 8.6.10 */
492505 Window mouseButtonWindow; /* Window the button state was set in, added
493506 * in Tk 8.4. */
494507 Tk_Window warpWindow;
811824
812825 int minReqWidth; /* Minimum requested width. */
813826 int minReqHeight; /* Minimum requested height. */
814 char *geometryMaster;
815827 #ifdef TK_USE_INPUT_METHODS
816828 int ximGeneration; /* Used to invalidate XIC */
817829 #endif /* TK_USE_INPUT_METHODS */
830 char *geomMgrName; /* Records the name of the geometry manager. */
831 struct TkWindow *maintainerPtr;
832 /* The geometry master for this window. The
833 * value is NULL if the window has no master or
834 * if its master is its parent. */
818835 } TkWindow;
819836
820837 /*
924941 #define EXTENDED_MASK (AnyModifier<<3)
925942
926943 /*
944 * Mask that selects any of the state bits corresponding to buttons, plus
945 * masks that select individual buttons' bits:
946 */
947
948 #define ALL_BUTTONS \
949 (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
950
951
952 MODULE_SCOPE unsigned long TkGetButtonMask(unsigned int);
953
954 /*
927955 * Object types not declared in tkObj.c need to be mentioned here so they can
928956 * be properly registered with Tcl:
929957 */
9761004 void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn));
9771005 #endif
9781006 #if !defined(CLANG_ASSERT)
979 #include <assert.h>
9801007 #define CLANG_ASSERT(x) assert(x)
9811008 #endif
9821009 #elif !defined(CLANG_ASSERT)
12391266 MODULE_SCOPE void TkUnixSetXftClipRegion(TkRegion clipRegion);
12401267 #endif
12411268
1269 #if !defined(__cplusplus) && !defined(c_plusplus)
1270 # define c_class class
1271 #endif
1272
12421273 #if TCL_UTF_MAX > 4
12431274 # define TkUtfToUniChar Tcl_UtfToUniChar
12441275 # define TkUniCharToUtf Tcl_UniCharToUtf
333333 /* 112 */
334334 EXTERN void TkpMenuThreadInit(void);
335335 /* 113 */
336 EXTERN void TkClipBox(TkRegion rgn, XRectangle *rect_return);
336 EXTERN int TkClipBox(TkRegion rgn, XRectangle *rect_return);
337337 /* 114 */
338338 EXTERN TkRegion TkCreateRegion(void);
339339 /* 115 */
340 EXTERN void TkDestroyRegion(TkRegion rgn);
340 EXTERN int TkDestroyRegion(TkRegion rgn);
341341 /* 116 */
342 EXTERN void TkIntersectRegion(TkRegion sra, TkRegion srcb,
342 EXTERN int TkIntersectRegion(TkRegion sra, TkRegion srcb,
343343 TkRegion dr_return);
344344 /* 117 */
345345 EXTERN int TkRectInRegion(TkRegion rgn, int x, int y,
346346 unsigned int width, unsigned int height);
347347 /* 118 */
348 EXTERN void TkSetRegion(Display *display, GC gc, TkRegion rgn);
348 EXTERN int TkSetRegion(Display *display, GC gc, TkRegion rgn);
349349 /* 119 */
350 EXTERN void TkUnionRectWithRegion(XRectangle *rect, TkRegion src,
350 EXTERN int TkUnionRectWithRegion(XRectangle *rect, TkRegion src,
351351 TkRegion dr_return);
352352 /* Slot 120 is reserved */
353353 #ifdef MAC_OSX_TK /* AQUA */
399399 /* 144 */
400400 EXTERN void TkGCCleanup(TkDisplay *dispPtr);
401401 /* 145 */
402 EXTERN void TkSubtractRegion(TkRegion sra, TkRegion srcb,
402 EXTERN int TkSubtractRegion(TkRegion sra, TkRegion srcb,
403403 TkRegion dr_return);
404404 /* 146 */
405405 EXTERN void TkStylePkgInit(TkMainInfo *mainPtr);
667667 void (*tkpGetSubFonts) (Tcl_Interp *interp, Tk_Font tkfont); /* 110 */
668668 Tcl_Obj * (*tkpGetSystemDefault) (Tk_Window tkwin, const char *dbName, const char *className); /* 111 */
669669 void (*tkpMenuThreadInit) (void); /* 112 */
670 void (*tkClipBox) (TkRegion rgn, XRectangle *rect_return); /* 113 */
670 int (*tkClipBox) (TkRegion rgn, XRectangle *rect_return); /* 113 */
671671 TkRegion (*tkCreateRegion) (void); /* 114 */
672 void (*tkDestroyRegion) (TkRegion rgn); /* 115 */
673 void (*tkIntersectRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 116 */
672 int (*tkDestroyRegion) (TkRegion rgn); /* 115 */
673 int (*tkIntersectRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 116 */
674674 int (*tkRectInRegion) (TkRegion rgn, int x, int y, unsigned int width, unsigned int height); /* 117 */
675 void (*tkSetRegion) (Display *display, GC gc, TkRegion rgn); /* 118 */
676 void (*tkUnionRectWithRegion) (XRectangle *rect, TkRegion src, TkRegion dr_return); /* 119 */
675 int (*tkSetRegion) (Display *display, GC gc, TkRegion rgn); /* 118 */
676 int (*tkUnionRectWithRegion) (XRectangle *rect, TkRegion src, TkRegion dr_return); /* 119 */
677677 void (*reserved120)(void);
678678 #if !(defined(_WIN32) || defined(MAC_OSX_TK)) /* X11 */
679679 void (*reserved121)(void);
726726 void (*tkFocusFree) (TkMainInfo *mainPtr); /* 142 */
727727 void (*tkClipCleanup) (TkDisplay *dispPtr); /* 143 */
728728 void (*tkGCCleanup) (TkDisplay *dispPtr); /* 144 */
729 void (*tkSubtractRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 145 */
729 int (*tkSubtractRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 145 */
730730 void (*tkStylePkgInit) (TkMainInfo *mainPtr); /* 146 */
731731 void (*tkStylePkgFree) (TkMainInfo *mainPtr); /* 147 */
732732 Tk_Window (*tkToplevelWindowForCommand) (Tcl_Interp *interp, const char *cmdName); /* 148 */
141141 EXTERN int TkpTestsendCmd(ClientData clientData,
142142 Tcl_Interp *interp, int objc,
143143 Tcl_Obj *const objv[]);
144 /* Slot 46 is reserved */
145 /* 47 */
146 EXTERN Tk_Window TkpGetCapture(void);
144147 #endif /* WIN */
145148 #ifdef MAC_OSX_TK /* AQUA */
146149 /* 0 */
242245 EXTERN Tk_Window TkMacOSXGetCapture(void);
243246 /* Slot 48 is reserved */
244247 /* 49 */
245 EXTERN Window TkGetTransientMaster(TkWindow *winPtr);
248 EXTERN Tk_Window TkGetTransientMaster(TkWindow *winPtr);
246249 /* 50 */
247250 EXTERN int TkGenerateButtonEvent(int x, int y, Window window,
248251 unsigned int state);
340343 void (*tkWmCleanup) (TkDisplay *dispPtr); /* 43 */
341344 void (*tkSendCleanup) (TkDisplay *dispPtr); /* 44 */
342345 int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 45 */
346 void (*reserved46)(void);
347 Tk_Window (*tkpGetCapture) (void); /* 47 */
343348 #endif /* WIN */
344349 #ifdef MAC_OSX_TK /* AQUA */
345350 void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 0 */
391396 int (*tkpIsWindowFloating) (void *window); /* 46 */
392397 Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */
393398 void (*reserved48)(void);
394 Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
399 Tk_Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
395400 int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */
396401 void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */
397402 void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */
521526 (tkIntPlatStubsPtr->tkSendCleanup) /* 44 */
522527 #define TkpTestsendCmd \
523528 (tkIntPlatStubsPtr->tkpTestsendCmd) /* 45 */
529 /* Slot 46 is reserved */
530 #define TkpGetCapture \
531 (tkIntPlatStubsPtr->tkpGetCapture) /* 47 */
524532 #endif /* WIN */
525533 #ifdef MAC_OSX_TK /* AQUA */
526534 #define TkGenerateActivateEvents \
449449 /* 13 */
450450 EXTERN int XBell(Display *d, int i);
451451 /* 14 */
452 EXTERN void XChangeProperty(Display *d, Window w, Atom a1,
452 EXTERN int XChangeProperty(Display *d, Window w, Atom a1,
453453 Atom a2, int i1, int i2,
454454 _Xconst unsigned char *c, int i3);
455455 /* 15 */
456 EXTERN void XChangeWindowAttributes(Display *d, Window w,
456 EXTERN int XChangeWindowAttributes(Display *d, Window w,
457457 unsigned long ul, XSetWindowAttributes *x);
458458 /* 16 */
459 EXTERN void XConfigureWindow(Display *d, Window w,
459 EXTERN int XConfigureWindow(Display *d, Window w,
460460 unsigned int i, XWindowChanges *x);
461461 /* 17 */
462 EXTERN void XCopyArea(Display *d, Drawable dr1, Drawable dr2,
462 EXTERN int XCopyArea(Display *d, Drawable dr1, Drawable dr2,
463463 GC g, int i1, int i2, unsigned int ui1,
464464 unsigned int ui2, int i3, int i4);
465465 /* 18 */
466 EXTERN void XCopyPlane(Display *d, Drawable dr1, Drawable dr2,
466 EXTERN int XCopyPlane(Display *d, Drawable dr1, Drawable dr2,
467467 GC g, int i1, int i2, unsigned int ui1,
468468 unsigned int ui2, int i3, int i4,
469469 unsigned long ul);
474474 /* 20 */
475475 EXTERN int XDefineCursor(Display *d, Window w, Cursor c);
476476 /* 21 */
477 EXTERN void XDestroyWindow(Display *d, Window w);
477 EXTERN int XDestroyWindow(Display *d, Window w);
478478 /* 22 */
479 EXTERN void XDrawArc(Display *d, Drawable dr, GC g, int i1,
479 EXTERN int XDrawArc(Display *d, Drawable dr, GC g, int i1,
480480 int i2, unsigned int ui1, unsigned int ui2,
481481 int i3, int i4);
482482 /* 23 */
483483 EXTERN int XDrawLines(Display *d, Drawable dr, GC g, XPoint *x,
484484 int i1, int i2);
485485 /* 24 */
486 EXTERN void XDrawRectangle(Display *d, Drawable dr, GC g, int i1,
486 EXTERN int XDrawRectangle(Display *d, Drawable dr, GC g, int i1,
487487 int i2, unsigned int ui1, unsigned int ui2);
488488 /* 25 */
489 EXTERN void XFillArc(Display *d, Drawable dr, GC g, int i1,
489 EXTERN int XFillArc(Display *d, Drawable dr, GC g, int i1,
490490 int i2, unsigned int ui1, unsigned int ui2,
491491 int i3, int i4);
492492 /* 26 */
493 EXTERN void XFillPolygon(Display *d, Drawable dr, GC g,
493 EXTERN int XFillPolygon(Display *d, Drawable dr, GC g,
494494 XPoint *x, int i1, int i2, int i3);
495495 /* 27 */
496496 EXTERN int XFillRectangles(Display *d, Drawable dr, GC g,
522522 /* 35 */
523523 EXTERN KeyCode XKeysymToKeycode(Display *d, KeySym k);
524524 /* 36 */
525 EXTERN void XMapWindow(Display *d, Window w);
525 EXTERN int XMapWindow(Display *d, Window w);
526526 /* 37 */
527 EXTERN void XMoveResizeWindow(Display *d, Window w, int i1,
527 EXTERN int XMoveResizeWindow(Display *d, Window w, int i1,
528528 int i2, unsigned int ui1, unsigned int ui2);
529529 /* 38 */
530 EXTERN void XMoveWindow(Display *d, Window w, int i1, int i2);
530 EXTERN int XMoveWindow(Display *d, Window w, int i1, int i2);
531531 /* 39 */
532532 EXTERN Bool XQueryPointer(Display *d, Window w1, Window *w2,
533533 Window *w3, int *i1, int *i2, int *i3,
534534 int *i4, unsigned int *ui);
535535 /* 40 */
536 EXTERN void XRaiseWindow(Display *d, Window w);
536 EXTERN int XRaiseWindow(Display *d, Window w);
537537 /* 41 */
538 EXTERN void XRefreshKeyboardMapping(XMappingEvent *x);
538 EXTERN int XRefreshKeyboardMapping(XMappingEvent *x);
539539 /* 42 */
540 EXTERN void XResizeWindow(Display *d, Window w, unsigned int ui1,
540 EXTERN int XResizeWindow(Display *d, Window w, unsigned int ui1,
541541 unsigned int ui2);
542542 /* 43 */
543 EXTERN void XSelectInput(Display *d, Window w, long l);
543 EXTERN int XSelectInput(Display *d, Window w, long l);
544544 /* 44 */
545545 EXTERN Status XSendEvent(Display *d, Window w, Bool b, long l,
546546 XEvent *x);
547547 /* 45 */
548 EXTERN void XSetIconName(Display *d, Window w, _Xconst char *c);
548 EXTERN int XSetIconName(Display *d, Window w, _Xconst char *c);
549549 /* 46 */
550 EXTERN void XSetInputFocus(Display *d, Window w, int i, Time t);
550 EXTERN int XSetInputFocus(Display *d, Window w, int i, Time t);
551551 /* 47 */
552552 EXTERN int XSetSelectionOwner(Display *d, Atom a, Window w,
553553 Time t);
554554 /* 48 */
555 EXTERN void XSetWindowBackground(Display *d, Window w,
555 EXTERN int XSetWindowBackground(Display *d, Window w,
556556 unsigned long ul);
557557 /* 49 */
558 EXTERN void XSetWindowBackgroundPixmap(Display *d, Window w,
558 EXTERN int XSetWindowBackgroundPixmap(Display *d, Window w,
559559 Pixmap p);
560560 /* 50 */
561 EXTERN void XSetWindowBorder(Display *d, Window w,
561 EXTERN int XSetWindowBorder(Display *d, Window w,
562562 unsigned long ul);
563563 /* 51 */
564 EXTERN void XSetWindowBorderPixmap(Display *d, Window w,
564 EXTERN int XSetWindowBorderPixmap(Display *d, Window w,
565565 Pixmap p);
566566 /* 52 */
567 EXTERN void XSetWindowBorderWidth(Display *d, Window w,
567 EXTERN int XSetWindowBorderWidth(Display *d, Window w,
568568 unsigned int ui);
569569 /* 53 */
570 EXTERN void XSetWindowColormap(Display *d, Window w, Colormap c);
570 EXTERN int XSetWindowColormap(Display *d, Window w, Colormap c);
571571 /* 54 */
572 EXTERN void XUngrabKeyboard(Display *d, Time t);
572 EXTERN int XUngrabKeyboard(Display *d, Time t);
573573 /* 55 */
574574 EXTERN int XUngrabPointer(Display *d, Time t);
575575 /* 56 */
576 EXTERN void XUnmapWindow(Display *d, Window w);
576 EXTERN int XUnmapWindow(Display *d, Window w);
577577 /* 57 */
578578 EXTERN int TkPutImage(unsigned long *colors, int ncolors,
579579 Display *display, Drawable d, GC gc,
628628 /* 75 */
629629 EXTERN int _XInitImageFuncPtrs(XImage *image);
630630 /* 76 */
631 EXTERN XIC XCreateIC(void);
631 EXTERN XIC XCreateIC(XIM xim, ...);
632632 /* 77 */
633633 EXTERN XVisualInfo * XGetVisualInfo(Display *display, long vinfo_mask,
634634 XVisualInfo *vinfo_template,
643643 EXTERN int XDrawSegments(Display *display, Drawable d, GC gc,
644644 XSegment *segments, int nsegments);
645645 /* 81 */
646 EXTERN void XForceScreenSaver(Display *display, int mode);
646 EXTERN int XForceScreenSaver(Display *display, int mode);
647647 /* 82 */
648648 EXTERN int XDrawLine(Display *d, Drawable dr, GC g, int x1,
649649 int y1, int x2, int y2);
652652 int x, int y, unsigned int width,
653653 unsigned int height);
654654 /* 84 */
655 EXTERN void XClearWindow(Display *d, Window w);
655 EXTERN int XClearWindow(Display *d, Window w);
656656 /* 85 */
657657 EXTERN int XDrawPoint(Display *display, Drawable d, GC gc,
658658 int x, int y);
666666 unsigned int src_height, int dest_x,
667667 int dest_y);
668668 /* 88 */
669 EXTERN void XQueryColor(Display *display, Colormap colormap,
669 EXTERN int XQueryColor(Display *display, Colormap colormap,
670670 XColor *def_in_out);
671671 /* 89 */
672 EXTERN void XQueryColors(Display *display, Colormap colormap,
672 EXTERN int XQueryColors(Display *display, Colormap colormap,
673673 XColor *defs_in_out, int ncolors);
674674 /* 90 */
675675 EXTERN Status XQueryTree(Display *d, Window w1, Window *w2,
676676 Window *w3, Window **w4, unsigned int *ui);
677677 /* 91 */
678 EXTERN int XSync(Display *display, Bool flag);
678 EXTERN int XSync(Display *display, Bool discard);
679 /* Slot 92 is reserved */
680 /* Slot 93 is reserved */
681 /* Slot 94 is reserved */
682 /* Slot 95 is reserved */
683 /* Slot 96 is reserved */
684 /* Slot 97 is reserved */
685 /* Slot 98 is reserved */
686 /* Slot 99 is reserved */
687 /* Slot 100 is reserved */
688 /* Slot 101 is reserved */
689 /* Slot 102 is reserved */
690 /* Slot 103 is reserved */
691 /* Slot 104 is reserved */
692 /* Slot 105 is reserved */
693 /* Slot 106 is reserved */
694 /* 107 */
695 EXTERN int XFlush(Display *display);
696 /* 108 */
697 EXTERN int XGrabServer(Display *display);
698 /* 109 */
699 EXTERN int XUngrabServer(Display *display);
700 /* 110 */
701 EXTERN int XFree(void *data);
702 /* 111 */
703 EXTERN int XNoOp(Display *display);
704 /* 112 */
705 EXTERN XAfterFunction XSynchronize(Display *display, Bool onoff);
706 /* Slot 113 is reserved */
707 /* 114 */
708 EXTERN VisualID XVisualIDFromVisual(Visual *visual);
709 /* Slot 115 is reserved */
710 /* Slot 116 is reserved */
711 /* Slot 117 is reserved */
712 /* Slot 118 is reserved */
713 /* Slot 119 is reserved */
714 /* Slot 120 is reserved */
715 /* Slot 121 is reserved */
716 /* Slot 122 is reserved */
717 /* Slot 123 is reserved */
718 /* Slot 124 is reserved */
719 /* Slot 125 is reserved */
720 /* Slot 126 is reserved */
721 /* Slot 127 is reserved */
722 /* Slot 128 is reserved */
723 /* Slot 129 is reserved */
724 /* Slot 130 is reserved */
725 /* Slot 131 is reserved */
726 /* Slot 132 is reserved */
727 /* Slot 133 is reserved */
728 /* Slot 134 is reserved */
729 /* Slot 135 is reserved */
730 /* Slot 136 is reserved */
731 /* 137 */
732 EXTERN int XPutImage(Display *d, Drawable dr, GC gc, XImage *im,
733 int sx, int sy, int dx, int dy,
734 unsigned int w, unsigned int h);
679735 #endif /* AQUA */
680736
681737 typedef struct TkIntXlibStubs {
837893 XErrorHandler (*xSetErrorHandler) (XErrorHandler x); /* 11 */
838894 Status (*xAllocColor) (Display *d, Colormap c, XColor *xp); /* 12 */
839895 int (*xBell) (Display *d, int i); /* 13 */
840 void (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3); /* 14 */
841 void (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 15 */
842 void (*xConfigureWindow) (Display *d, Window w, unsigned int i, XWindowChanges *x); /* 16 */
843 void (*xCopyArea) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 17 */
844 void (*xCopyPlane) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul); /* 18 */
896 int (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3); /* 14 */
897 int (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 15 */
898 int (*xConfigureWindow) (Display *d, Window w, unsigned int i, XWindowChanges *x); /* 16 */
899 int (*xCopyArea) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 17 */
900 int (*xCopyPlane) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul); /* 18 */
845901 Pixmap (*xCreateBitmapFromData) (Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height); /* 19 */
846902 int (*xDefineCursor) (Display *d, Window w, Cursor c); /* 20 */
847 void (*xDestroyWindow) (Display *d, Window w); /* 21 */
848 void (*xDrawArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 22 */
903 int (*xDestroyWindow) (Display *d, Window w); /* 21 */
904 int (*xDrawArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 22 */
849905 int (*xDrawLines) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2); /* 23 */
850 void (*xDrawRectangle) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 24 */
851 void (*xFillArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 25 */
852 void (*xFillPolygon) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3); /* 26 */
906 int (*xDrawRectangle) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 24 */
907 int (*xFillArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 25 */
908 int (*xFillPolygon) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3); /* 26 */
853909 int (*xFillRectangles) (Display *d, Drawable dr, GC g, XRectangle *x, int i); /* 27 */
854910 int (*xFreeColormap) (Display *d, Colormap c); /* 28 */
855911 int (*xFreeColors) (Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul); /* 29 */
859915 int (*xGrabKeyboard) (Display *d, Window w, Bool b, int i1, int i2, Time t); /* 33 */
860916 int (*xGrabPointer) (Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t); /* 34 */
861917 KeyCode (*xKeysymToKeycode) (Display *d, KeySym k); /* 35 */
862 void (*xMapWindow) (Display *d, Window w); /* 36 */
863 void (*xMoveResizeWindow) (Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 37 */
864 void (*xMoveWindow) (Display *d, Window w, int i1, int i2); /* 38 */
918 int (*xMapWindow) (Display *d, Window w); /* 36 */
919 int (*xMoveResizeWindow) (Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 37 */
920 int (*xMoveWindow) (Display *d, Window w, int i1, int i2); /* 38 */
865921 Bool (*xQueryPointer) (Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui); /* 39 */
866 void (*xRaiseWindow) (Display *d, Window w); /* 40 */
867 void (*xRefreshKeyboardMapping) (XMappingEvent *x); /* 41 */
868 void (*xResizeWindow) (Display *d, Window w, unsigned int ui1, unsigned int ui2); /* 42 */
869 void (*xSelectInput) (Display *d, Window w, long l); /* 43 */
922 int (*xRaiseWindow) (Display *d, Window w); /* 40 */
923 int (*xRefreshKeyboardMapping) (XMappingEvent *x); /* 41 */
924 int (*xResizeWindow) (Display *d, Window w, unsigned int ui1, unsigned int ui2); /* 42 */
925 int (*xSelectInput) (Display *d, Window w, long l); /* 43 */
870926 Status (*xSendEvent) (Display *d, Window w, Bool b, long l, XEvent *x); /* 44 */
871 void (*xSetIconName) (Display *d, Window w, _Xconst char *c); /* 45 */
872 void (*xSetInputFocus) (Display *d, Window w, int i, Time t); /* 46 */
927 int (*xSetIconName) (Display *d, Window w, _Xconst char *c); /* 45 */
928 int (*xSetInputFocus) (Display *d, Window w, int i, Time t); /* 46 */
873929 int (*xSetSelectionOwner) (Display *d, Atom a, Window w, Time t); /* 47 */
874 void (*xSetWindowBackground) (Display *d, Window w, unsigned long ul); /* 48 */
875 void (*xSetWindowBackgroundPixmap) (Display *d, Window w, Pixmap p); /* 49 */
876 void (*xSetWindowBorder) (Display *d, Window w, unsigned long ul); /* 50 */
877 void (*xSetWindowBorderPixmap) (Display *d, Window w, Pixmap p); /* 51 */
878 void (*xSetWindowBorderWidth) (Display *d, Window w, unsigned int ui); /* 52 */
879 void (*xSetWindowColormap) (Display *d, Window w, Colormap c); /* 53 */
880 void (*xUngrabKeyboard) (Display *d, Time t); /* 54 */
930 int (*xSetWindowBackground) (Display *d, Window w, unsigned long ul); /* 48 */
931 int (*xSetWindowBackgroundPixmap) (Display *d, Window w, Pixmap p); /* 49 */
932 int (*xSetWindowBorder) (Display *d, Window w, unsigned long ul); /* 50 */
933 int (*xSetWindowBorderPixmap) (Display *d, Window w, Pixmap p); /* 51 */
934 int (*xSetWindowBorderWidth) (Display *d, Window w, unsigned int ui); /* 52 */
935 int (*xSetWindowColormap) (Display *d, Window w, Colormap c); /* 53 */
936 int (*xUngrabKeyboard) (Display *d, Time t); /* 54 */
881937 int (*xUngrabPointer) (Display *d, Time t); /* 55 */
882 void (*xUnmapWindow) (Display *d, Window w); /* 56 */
938 int (*xUnmapWindow) (Display *d, Window w); /* 56 */
883939 int (*tkPutImage) (unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); /* 57 */
884940 Status (*xParseColor) (Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr); /* 58 */
885941 GC (*xCreateGC) (Display *display, Drawable d, unsigned long valuemask, XGCValues *values); /* 59 */
899955 int (*xSetFunction) (Display *display, GC gc, int function); /* 73 */
900956 int (*xSetLineAttributes) (Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style); /* 74 */
901957 int (*_XInitImageFuncPtrs) (XImage *image); /* 75 */
902 XIC (*xCreateIC) (void); /* 76 */
958 XIC (*xCreateIC) (XIM xim, ...); /* 76 */
903959 XVisualInfo * (*xGetVisualInfo) (Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return); /* 77 */
904960 void (*xSetWMClientMachine) (Display *display, Window w, XTextProperty *text_prop); /* 78 */
905961 Status (*xStringListToTextProperty) (char **list, int count, XTextProperty *text_prop_return); /* 79 */
906962 int (*xDrawSegments) (Display *display, Drawable d, GC gc, XSegment *segments, int nsegments); /* 80 */
907 void (*xForceScreenSaver) (Display *display, int mode); /* 81 */
963 int (*xForceScreenSaver) (Display *display, int mode); /* 81 */
908964 int (*xDrawLine) (Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2); /* 82 */
909965 int (*xFillRectangle) (Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height); /* 83 */
910 void (*xClearWindow) (Display *d, Window w); /* 84 */
966 int (*xClearWindow) (Display *d, Window w); /* 84 */
911967 int (*xDrawPoint) (Display *display, Drawable d, GC gc, int x, int y); /* 85 */
912968 int (*xDrawPoints) (Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode); /* 86 */
913969 int (*xWarpPointer) (Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y); /* 87 */
914 void (*xQueryColor) (Display *display, Colormap colormap, XColor *def_in_out); /* 88 */
915 void (*xQueryColors) (Display *display, Colormap colormap, XColor *defs_in_out, int ncolors); /* 89 */
970 int (*xQueryColor) (Display *display, Colormap colormap, XColor *def_in_out); /* 88 */
971 int (*xQueryColors) (Display *display, Colormap colormap, XColor *defs_in_out, int ncolors); /* 89 */
916972 Status (*xQueryTree) (Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui); /* 90 */
917 int (*xSync) (Display *display, Bool flag); /* 91 */
973 int (*xSync) (Display *display, Bool discard); /* 91 */
974 void (*reserved92)(void);
975 void (*reserved93)(void);
976 void (*reserved94)(void);
977 void (*reserved95)(void);
978 void (*reserved96)(void);
979 void (*reserved97)(void);
980 void (*reserved98)(void);
981 void (*reserved99)(void);
982 void (*reserved100)(void);
983 void (*reserved101)(void);
984 void (*reserved102)(void);
985 void (*reserved103)(void);
986 void (*reserved104)(void);
987 void (*reserved105)(void);
988 void (*reserved106)(void);
989 int (*xFlush) (Display *display); /* 107 */
990 int (*xGrabServer) (Display *display); /* 108 */
991 int (*xUngrabServer) (Display *display); /* 109 */
992 int (*xFree) (void *data); /* 110 */
993 int (*xNoOp) (Display *display); /* 111 */
994 XAfterFunction (*xSynchronize) (Display *display, Bool onoff); /* 112 */
995 void (*reserved113)(void);
996 VisualID (*xVisualIDFromVisual) (Visual *visual); /* 114 */
997 void (*reserved115)(void);
998 void (*reserved116)(void);
999 void (*reserved117)(void);
1000 void (*reserved118)(void);
1001 void (*reserved119)(void);
1002 void (*reserved120)(void);
1003 void (*reserved121)(void);
1004 void (*reserved122)(void);
1005 void (*reserved123)(void);
1006 void (*reserved124)(void);
1007 void (*reserved125)(void);
1008 void (*reserved126)(void);
1009 void (*reserved127)(void);
1010 void (*reserved128)(void);
1011 void (*reserved129)(void);
1012 void (*reserved130)(void);
1013 void (*reserved131)(void);
1014 void (*reserved132)(void);
1015 void (*reserved133)(void);
1016 void (*reserved134)(void);
1017 void (*reserved135)(void);
1018 void (*reserved136)(void);
1019 int (*xPutImage) (Display *d, Drawable dr, GC gc, XImage *im, int sx, int sy, int dx, int dy, unsigned int w, unsigned int h); /* 137 */
9181020 #endif /* AQUA */
9191021 } TkIntXlibStubs;
9201022
13811483 (tkIntXlibStubsPtr->xQueryTree) /* 90 */
13821484 #define XSync \
13831485 (tkIntXlibStubsPtr->xSync) /* 91 */
1486 /* Slot 92 is reserved */
1487 /* Slot 93 is reserved */
1488 /* Slot 94 is reserved */
1489 /* Slot 95 is reserved */
1490 /* Slot 96 is reserved */
1491 /* Slot 97 is reserved */
1492 /* Slot 98 is reserved */
1493 /* Slot 99 is reserved */
1494 /* Slot 100 is reserved */
1495 /* Slot 101 is reserved */
1496 /* Slot 102 is reserved */
1497 /* Slot 103 is reserved */
1498 /* Slot 104 is reserved */
1499 /* Slot 105 is reserved */
1500 /* Slot 106 is reserved */
1501 #define XFlush \
1502 (tkIntXlibStubsPtr->xFlush) /* 107 */
1503 #define XGrabServer \
1504 (tkIntXlibStubsPtr->xGrabServer) /* 108 */
1505 #define XUngrabServer \
1506 (tkIntXlibStubsPtr->xUngrabServer) /* 109 */
1507 #define XFree \
1508 (tkIntXlibStubsPtr->xFree) /* 110 */
1509 #define XNoOp \
1510 (tkIntXlibStubsPtr->xNoOp) /* 111 */
1511 #define XSynchronize \
1512 (tkIntXlibStubsPtr->xSynchronize) /* 112 */
1513 /* Slot 113 is reserved */
1514 #define XVisualIDFromVisual \
1515 (tkIntXlibStubsPtr->xVisualIDFromVisual) /* 114 */
1516 /* Slot 115 is reserved */
1517 /* Slot 116 is reserved */
1518 /* Slot 117 is reserved */
1519 /* Slot 118 is reserved */
1520 /* Slot 119 is reserved */
1521 /* Slot 120 is reserved */
1522 /* Slot 121 is reserved */
1523 /* Slot 122 is reserved */
1524 /* Slot 123 is reserved */
1525 /* Slot 124 is reserved */
1526 /* Slot 125 is reserved */
1527 /* Slot 126 is reserved */
1528 /* Slot 127 is reserved */
1529 /* Slot 128 is reserved */
1530 /* Slot 129 is reserved */
1531 /* Slot 130 is reserved */
1532 /* Slot 131 is reserved */
1533 /* Slot 132 is reserved */
1534 /* Slot 133 is reserved */
1535 /* Slot 134 is reserved */
1536 /* Slot 135 is reserved */
1537 /* Slot 136 is reserved */
1538 #define XPutImage \
1539 (tkIntXlibStubsPtr->xPutImage) /* 137 */
13841540 #endif /* AQUA */
13851541
13861542 #endif /* defined(USE_TK_STUBS) */
541541 listPtr->itemAttrTable = ckalloc(sizeof(Tcl_HashTable));
542542 Tcl_InitHashTable(listPtr->itemAttrTable, TCL_ONE_WORD_KEYS);
543543 listPtr->relief = TK_RELIEF_RAISED;
544 listPtr->textGC = None;
545 listPtr->selFgColorPtr = None;
546 listPtr->selTextGC = None;
544 listPtr->textGC = NULL;
545 listPtr->selFgColorPtr = NULL;
546 listPtr->selTextGC = NULL;
547547 listPtr->fullLines = 1;
548548 listPtr->xScrollUnit = 1;
549549 listPtr->exportSelection = 1;
550 listPtr->cursor = None;
550 listPtr->cursor = NULL;
551551 listPtr->state = STATE_NORMAL;
552552 listPtr->gray = None;
553553 listPtr->justify = TK_JUSTIFY_LEFT;
14871487 * Tk_FreeOptions handle all the standard option-related stuff.
14881488 */
14891489
1490 if (listPtr->textGC != None) {
1490 if (listPtr->textGC != NULL) {
14911491 Tk_FreeGC(listPtr->display, listPtr->textGC);
14921492 }
1493 if (listPtr->selTextGC != None) {
1493 if (listPtr->selTextGC != NULL) {
14941494 Tk_FreeGC(listPtr->display, listPtr->selTextGC);
14951495 }
14961496 if (listPtr->gray != None) {
17901790
17911791 gcValues.font = Tk_FontId(listPtr->tkfont);
17921792 gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
1793 if (listPtr->textGC != None) {
1793 if (listPtr->textGC != NULL) {
17941794 Tk_FreeGC(listPtr->display, listPtr->textGC);
17951795 }
17961796 listPtr->textGC = gc;
18011801 gcValues.font = Tk_FontId(listPtr->tkfont);
18021802 mask = GCForeground | GCFont;
18031803 gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
1804 if (listPtr->selTextGC != None) {
1804 if (listPtr->selTextGC != NULL) {
18051805 Tk_FreeGC(listPtr->display, listPtr->selTextGC);
18061806 }
18071807 listPtr->selTextGC = gc;
34303430 ListboxListVarProc(
34313431 ClientData clientData, /* Information about button. */
34323432 Tcl_Interp *interp, /* Interpreter containing variable. */
3433 const char *name1, /* Name of variable. */
3434 const char *name2, /* Second part of variable name. */
3433 const char *name1, /* Not used. */
3434 const char *name2, /* Not used. */
34353435 int flags) /* Information about what happened. */
34363436 {
34373437 Listbox *listPtr = clientData;
34403440 Tcl_HashEntry *entry;
34413441
34423442 /*
3443 * See ticket [5d991b82].
3444 */
3445
3446 if (listPtr->listVarName == NULL) {
3447 if (!(flags & TCL_INTERP_DESTROYED)) {
3448 Tcl_UntraceVar2(interp, name1, name2,
3449 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
3450 ListboxListVarProc, clientData);
3451 }
3452 return NULL;
3453 }
3454
3455 /*
34563443 * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable!
34573444 */
34583445
34593446 if (flags & TCL_TRACE_UNSETS) {
3460 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
3447
3448 if (!Tcl_InterpDeleted(interp) && listPtr->listVarName) {
3449 ClientData probe = NULL;
3450
3451 do {
3452 probe = Tcl_VarTraceInfo(interp,
3453 listPtr->listVarName,
3454 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
3455 ListboxListVarProc, probe);
3456 if (probe == (ClientData)listPtr) {
3457 break;
3458 }
3459 } while (probe);
3460 if (probe) {
3461 /*
3462 * We were able to fetch the unset trace for our
3463 * listVarName, which means it is not unset and not
3464 * the cause of this unset trace. Instead some outdated
3465 * former variable must be, and we should ignore it.
3466 */
3467 return NULL;
3468 }
34613469 Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL,
34623470 listPtr->listObj, TCL_GLOBAL_ONLY);
34633471 Tcl_TraceVar2(interp, listPtr->listVarName,
1212 #include "tkInt.h"
1313 #include "tkMenu.h"
1414
15 typedef struct ThreadSpecificData {
15 typedef struct {
1616 int postCommandGeneration;
1717 } ThreadSpecificData;
1818 static Tcl_ThreadDataKey dataKey;
4444 * The default prompt used when the user has not overridden it.
4545 */
4646
47 #define DEFAULT_PRIMARY_PROMPT "% "
47 static const char DEFAULT_PRIMARY_PROMPT[] = "% ";
4848
4949 /*
5050 * This file can be compiled on Windows in UNICODE mode, as well as
7878 #endif
7979
8080 /*
81 * Further on, in UNICODE mode, we need to use Tcl_NewUnicodeObj,
82 * while otherwise NewNativeObj is needed (which provides proper
83 * conversion from native encoding to UTF-8).
84 */
81 * Further on, in UNICODE mode we just use Tcl_NewUnicodeObj, otherwise
82 * NewNativeObj is needed (which provides proper conversion from native
83 * encoding to UTF-8).
84 */
85
86 static inline Tcl_Obj *
87 NewNativeObj(
88 TCHAR *string)
89 {
90 Tcl_Obj *obj;
91 Tcl_DString ds;
92
8593 #ifdef UNICODE
86 # define NewNativeObj Tcl_NewUnicodeObj
87 #else /* !UNICODE */
88 static Tcl_Obj *NewNativeObj(char *string, int length) {
89 Tcl_Obj *obj;
90 Tcl_DString ds;
91 Tcl_ExternalToUtfDString(NULL, string, length, &ds);
92 obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
93 Tcl_DStringFree(&ds);
94 return obj;
94 Tcl_WinTCharToUtf(string, -1, &ds);
95 #else
96 Tcl_ExternalToUtfDString(NULL, (char *) string, -1, &ds);
97 #endif
98 obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
99 Tcl_DStringFree(&ds);
100 return obj;
95101 }
96 #endif /* !UNICODE */
97102
98103 /*
99104 * Declarations for various library functions and variables (don't want to
234239 is.gotPartial = 0;
235240 Tcl_Preserve(interp);
236241
237 #if defined(_WIN32) && !defined(__CYGWIN__)
242 #if defined(_WIN32)
238243 #if !defined(STATIC_BUILD)
239244 /* If compiled for Win32 but running on Cygwin, don't use console */
240245 if (!tclStubsPtr->reserved9)
268273
269274 if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1]))
270275 && (TEXT('-') != argv[3][0])) {
271 Tcl_Obj *value = NewNativeObj(argv[2], -1);
272 Tcl_SetStartupScript(NewNativeObj(argv[3], -1), Tcl_GetString(value));
276 Tcl_Obj *value = NewNativeObj(argv[2]);
277 Tcl_SetStartupScript(NewNativeObj(argv[3]), Tcl_GetString(value));
273278 Tcl_DecrRefCount(value);
274279 argc -= 3;
275280 argv += 3;
276281 } else if ((argc > 1) && (TEXT('-') != argv[1][0])) {
277 Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL);
282 Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL);
278283 argc--;
279284 argv++;
280285 } else if ((argc > 2) && (length = _tcslen(argv[1]))
281286 && (length > 1) && (0 == _tcsncmp(TEXT("-file"), argv[1], length))
282287 && (TEXT('-') != argv[2][0])) {
283 Tcl_SetStartupScript(NewNativeObj(argv[2], -1), NULL);
288 Tcl_SetStartupScript(NewNativeObj(argv[2]), NULL);
284289 argc -= 2;
285290 argv += 2;
286291 }
288293
289294 path = Tcl_GetStartupScript(&encodingName);
290295 if (path == NULL) {
291 appName = NewNativeObj(argv[0], -1);
296 appName = NewNativeObj(argv[0]);
292297 } else {
293298 appName = path;
294299 }
300305
301306 argvPtr = Tcl_NewListObj(0, NULL);
302307 while (argc--) {
303 Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++, -1));
308 Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++));
304309 }
305310 Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);
306311
430435
431436 count = Tcl_Gets(chan, &isPtr->line);
432437
433 if (count < 0 && !isPtr->gotPartial) {
438 if (count == -1 && !isPtr->gotPartial) {
434439 if (isPtr->tty) {
435440 Tcl_Exit(0);
436441 } else {
518523 chan = Tcl_GetStdChannel(TCL_STDOUT);
519524 if (chan != NULL) {
520525 Tcl_WriteChars(chan, DEFAULT_PRIMARY_PROMPT,
521 strlen(DEFAULT_PRIMARY_PROMPT));
526 sizeof(DEFAULT_PRIMARY_PROMPT) - 1);
522527 }
523528 }
524529 } else {
7676
7777 #define MENU_HASH_KEY "tkMenus"
7878
79 typedef struct ThreadSpecificData {
79 typedef struct {
8080 int menusInitialized; /* Flag indicates whether thread-specific
8181 * elements of the Windows Menu module have
8282 * been initialized. */
8989
9090 /*
9191 * The following flag indicates whether the process-wide state for the Menu
92 * module has been intialized. The Mutex protects access to that flag.
92 * module has been initialized. The Mutex protects access to that flag.
9393 */
9494
9595 static int menusInitialized;
454454 Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd, menuPtr,
455455 MenuCmdDeletedProc);
456456 menuPtr->active = -1;
457 menuPtr->cursorPtr = None;
457 menuPtr->cursorPtr = NULL;
458458 menuPtr->masterMenuPtr = menuPtr;
459459 menuPtr->menuType = UNKNOWN_TYPE;
460460 TkMenuInitializeDrawingFields(menuPtr);
753753
754754 first = 1;
755755 }
756 if ((first < 0) || (last < first)) {
756 if ((first == -1) || (last < first)) {
757757 goto done;
758758 }
759759 DeleteMenuCloneEntries(menuPtr, first, last);
869869 break;
870870 }
871871 case MENU_POST: {
872 int x, y;
873
874 if (objc != 4) {
875 Tcl_WrongNumArgs(interp, 2, objv, "x y");
872 int x, y, index = -1;
873
874 if (objc != 4 && objc != 5) {
875 Tcl_WrongNumArgs(interp, 2, objv, "x y ?index?");
876876 goto error;
877877 }
878878 if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
879879 || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
880880 goto error;
881881 }
882 if (objc == 5) {
883 if (TkGetMenuIndex(interp, menuPtr, objv[4], 0, &index) != TCL_OK) {
884 goto error;
885 }
886 }
882887
883888 /*
884 * Tearoff menus are posted differently on Mac and Windows than
885 * non-tearoffs. TkpPostMenu does not actually map the menu's window
886 * on those platforms, and popup menus have to be handled specially.
887 * Also, menubar menues are not intended to be posted (bug 1567681,
888 * 2160206).
889 * Tearoff menus are the same as ordinary menus on the Mac and are
890 * posted differently on Windows than non-tearoffs. TkpPostMenu
891 * does not actually map the menu's window on those platforms, and
892 * popup menus have to be handled specially. Also, menubar menus are
893 * not intended to be posted (bug 1567681, 2160206).
889894 */
890895
891896 if (menuPtr->menuType == MENUBAR) {
892897 Tcl_AppendResult(interp, "a menubar menu cannot be posted", NULL);
893898 return TCL_ERROR;
894899 } else if (menuPtr->menuType != TEAROFF_MENU) {
895 result = TkpPostMenu(interp, menuPtr, x, y);
900 result = TkpPostMenu(interp, menuPtr, x, y, index);
896901 } else {
897 result = TkPostTearoffMenu(interp, menuPtr, x, y);
902 result = TkpPostTearoffMenu(interp, menuPtr, x, y, index);
898903 }
899904 break;
900905 }
21582163 Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr;
21592164 const char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr);
21602165
2161 if ((label != NULL) && (Tcl_StringMatch(label, string))) {
2166 if ((label != NULL) && (Tcl_StringCaseMatch(label, string, 0))) {
21622167 *indexPtr = i;
21632168 goto success;
21642169 }
24852490 const char *value;
24862491 const char *name, *onValue;
24872492
2488 if (flags & TCL_INTERP_DESTROYED) {
2493 if (Tcl_InterpDeleted(interp) || (mePtr->namePtr == NULL)) {
24892494 /*
2490 * Do nothing if the interpreter is going away.
2495 * Do nothing if the interpreter is going away or we have
2496 * no variable name.
24912497 */
24922498
24932499 return NULL;
24982504 if (menuPtr->menuFlags & MENU_DELETION_PENDING) {
24992505 return NULL;
25002506 }
2501
2502 /*
2503 * See ticket [5d991b82].
2504 */
2505
2506 if (mePtr->namePtr == NULL) {
2507 Tcl_UntraceVar2(interp, name1, name2,
2508 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
2509 MenuVarProc, clientData);
2510 return NULL;
2511 }
25122507
25132508 name = Tcl_GetString(mePtr->namePtr);
25142509
25172512 */
25182513
25192514 if (flags & TCL_TRACE_UNSETS) {
2515 ClientData probe = NULL;
25202516 mePtr->entryFlags &= ~ENTRY_SELECTED;
2521 if (flags & TCL_TRACE_DESTROYED) {
2522 Tcl_TraceVar2(interp, name, NULL,
2523 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
2524 MenuVarProc, clientData);
2525 }
2517
2518 do {
2519 probe = Tcl_VarTraceInfo(interp, name,
2520 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
2521 MenuVarProc, probe);
2522 if (probe == (ClientData)mePtr) {
2523 break;
2524 }
2525 } while (probe);
2526 if (probe) {
2527 /*
2528 * We were able to fetch the unset trace for our
2529 * namePtr, which means it is not unset and not
2530 * the cause of this unset trace. Instead some outdated
2531 * former variable must be, and we should ignore it.
2532 */
2533 return NULL;
2534 }
2535 Tcl_TraceVar2(interp, name, NULL,
2536 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
2537 MenuVarProc, clientData);
25262538 TkpConfigureMenuEntry(mePtr);
25272539 TkEventuallyRedrawMenu(menuPtr, NULL);
25282540 return NULL;
7474 * of character to underline (<0 means don't
7575 * underline anything). */
7676 Tcl_Obj *underlinePtr; /* Index of character to underline. */
77 Tcl_Obj *bitmapPtr; /* Bitmap to display in menu entry, or None.
78 * If not None then label is ignored. */
77 Tcl_Obj *bitmapPtr; /* Bitmap to display in menu entry, or NULL.
78 * If not NULL then label is ignored. */
7979 Tcl_Obj *imagePtr; /* Name of image to display, or NULL. If not
8080 * NULL, bitmap, text, and textVarName are
8181 * ignored. */
119119 * always 0 for tearoff and separator
120120 * entries. */
121121 int hideMargin; /* If this is 0, then the item has enough
122 * margin to accomodate a standard check mark
122 * margin to accommodate a standard check mark
123123 * and a default right margin. If this is 1,
124124 * then the item has no such margins, and
125125 * checkbuttons and radiobuttons with this set
174174 * NULL means use overall disabledGC from menu
175175 * structure. See comments for disabledFg in
176176 * menu structure for more information. */
177 GC indicatorGC; /* For drawing indicators. None means use GC
177 GC indicatorGC; /* For drawing indicators. NULL means use GC
178178 * from menu. */
179179
180180 /*
339339 Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the
340340 * C code, but used by keyboard traversal
341341 * scripts. Malloc'ed, but may be NULL. */
342 Tcl_Obj *cursorPtr; /* Current cursor for window, or None. */
342 Tcl_Obj *cursorPtr; /* Current cursor for window, or NULL. */
343343 Tcl_Obj *postCommandPtr; /* Used to detect cycles in cascade hierarchy
344344 * trees when preprocessing postcommands on
345345 * some platforms. See PostMenu for more
519519 MODULE_SCOPE int TkPostSubmenu(Tcl_Interp *interp, TkMenu *menuPtr,
520520 TkMenuEntry *mePtr);
521521 MODULE_SCOPE int TkPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,
522 int x, int y);
522 int x, int y);
523523 MODULE_SCOPE int TkPreprocessMenu(TkMenu *menuPtr);
524524 MODULE_SCOPE void TkRecomputeMenu(TkMenu *menuPtr);
525525
542542 MODULE_SCOPE int TkpMenuNewEntry(TkMenuEntry *mePtr);
543543 MODULE_SCOPE int TkpNewMenu(TkMenu *menuPtr);
544544 MODULE_SCOPE int TkpPostMenu(Tcl_Interp *interp, TkMenu *menuPtr,
545 int x, int y);
545 int x, int y, int index);
546 MODULE_SCOPE int TkpPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,
547 int x, int y, int index);
546548 MODULE_SCOPE void TkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr);
547549
548550 #endif /* _TKMENU */
4242 TkMenuInitializeDrawingFields(
4343 TkMenu *menuPtr) /* The menu we are initializing. */
4444 {
45 menuPtr->textGC = None;
45 menuPtr->textGC = NULL;
4646 menuPtr->gray = None;
47 menuPtr->disabledGC = None;
48 menuPtr->activeGC = None;
49 menuPtr->indicatorGC = None;
50 menuPtr->disabledImageGC = None;
47 menuPtr->disabledGC = NULL;
48 menuPtr->activeGC = NULL;
49 menuPtr->indicatorGC = NULL;
50 menuPtr->disabledImageGC = NULL;
5151 menuPtr->totalWidth = menuPtr->totalHeight = 0;
5252 }
5353
7878 mePtr->y = 0;
7979 mePtr->indicatorSpace = 0;
8080 mePtr->labelWidth = 0;
81 mePtr->textGC = None;
82 mePtr->activeGC = None;
83 mePtr->disabledGC = None;
84 mePtr->indicatorGC = None;
81 mePtr->textGC = NULL;
82 mePtr->activeGC = NULL;
83 mePtr->disabledGC = NULL;
84 mePtr->indicatorGC = NULL;
8585 }
8686
8787 /*
105105 TkMenuFreeDrawOptions(
106106 TkMenu *menuPtr)
107107 {
108 if (menuPtr->textGC != None) {
108 if (menuPtr->textGC != NULL) {
109109 Tk_FreeGC(menuPtr->display, menuPtr->textGC);
110110 }
111 if (menuPtr->disabledImageGC != None) {
111 if (menuPtr->disabledImageGC != NULL) {
112112 Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);
113113 }
114114 if (menuPtr->gray != None) {
115115 Tk_FreeBitmap(menuPtr->display, menuPtr->gray);
116116 }
117 if (menuPtr->disabledGC != None) {
117 if (menuPtr->disabledGC != NULL) {
118118 Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);
119119 }
120 if (menuPtr->activeGC != None) {
120 if (menuPtr->activeGC != NULL) {
121121 Tk_FreeGC(menuPtr->display, menuPtr->activeGC);
122122 }
123 if (menuPtr->indicatorGC != None) {
123 if (menuPtr->indicatorGC != NULL) {
124124 Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);
125125 }
126126 }
146146 TkMenuEntryFreeDrawOptions(
147147 TkMenuEntry *mePtr)
148148 {
149 if (mePtr->textGC != None) {
149 if (mePtr->textGC != NULL) {
150150 Tk_FreeGC(mePtr->menuPtr->display, mePtr->textGC);
151151 }
152 if (mePtr->disabledGC != None) {
152 if (mePtr->disabledGC != NULL) {
153153 Tk_FreeGC(mePtr->menuPtr->display, mePtr->disabledGC);
154154 }
155 if (mePtr->activeGC != None) {
155 if (mePtr->activeGC != NULL) {
156156 Tk_FreeGC(mePtr->menuPtr->display, mePtr->activeGC);
157157 }
158 if (mePtr->indicatorGC != None) {
158 if (mePtr->indicatorGC != NULL) {
159159 Tk_FreeGC(mePtr->menuPtr->display, mePtr->indicatorGC);
160160 }
161161 }
204204 gcValues.background = Tk_3DBorderColor(border)->pixel;
205205 newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
206206 &gcValues);
207 if (menuPtr->textGC != None) {
207 if (menuPtr->textGC != NULL) {
208208 Tk_FreeGC(menuPtr->display, menuPtr->textGC);
209209 }
210210 menuPtr->textGC = newGC;
232232 }
233233 }
234234 newGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
235 if (menuPtr->disabledGC != None) {
235 if (menuPtr->disabledGC != NULL) {
236236 Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);
237237 }
238238 menuPtr->disabledGC = newGC;
248248 newGC = Tk_GetGC(menuPtr->tkwin,
249249 GCForeground|GCFillStyle|GCStipple, &gcValues);
250250 }
251 if (menuPtr->disabledImageGC != None) {
251 if (menuPtr->disabledImageGC != NULL) {
252252 Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);
253253 }
254254 menuPtr->disabledImageGC = newGC;
261261 gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;
262262 newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
263263 &gcValues);
264 if (menuPtr->activeGC != None) {
264 if (menuPtr->activeGC != NULL) {
265265 Tk_FreeGC(menuPtr->display, menuPtr->activeGC);
266266 }
267267 menuPtr->activeGC = newGC;
272272 gcValues.background = Tk_3DBorderColor(border)->pixel;
273273 newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
274274 &gcValues);
275 if (menuPtr->indicatorGC != None) {
275 if (menuPtr->indicatorGC != NULL) {
276276 Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);
277277 }
278278 menuPtr->indicatorGC = newGC;
384384 GCForeground|GCBackground|GCFont|GCGraphicsExposures,
385385 &gcValues);
386386 } else {
387 newGC = None;
388 newActiveGC = None;
389 newDisabledGC = None;
390 newIndicatorGC = None;
391 }
392 if (mePtr->textGC != None) {
387 newGC = NULL;
388 newActiveGC = NULL;
389 newDisabledGC = NULL;
390 newIndicatorGC = NULL;
391 }
392 if (mePtr->textGC != NULL) {
393393 Tk_FreeGC(menuPtr->display, mePtr->textGC);
394394 }
395395 mePtr->textGC = newGC;
396 if (mePtr->activeGC != None) {
396 if (mePtr->activeGC != NULL) {
397397 Tk_FreeGC(menuPtr->display, mePtr->activeGC);
398398 }
399399 mePtr->activeGC = newActiveGC;
400 if (mePtr->disabledGC != None) {
400 if (mePtr->disabledGC != NULL) {
401401 Tk_FreeGC(menuPtr->display, mePtr->disabledGC);
402402 }
403403 mePtr->disabledGC = newDisabledGC;
404 if (mePtr->indicatorGC != None) {
404 if (mePtr->indicatorGC != NULL) {
405405 Tk_FreeGC(menuPtr->display, mePtr->indicatorGC);
406406 }
407407 mePtr->indicatorGC = newIndicatorGC;
474474 * None.
475475 *
476476 * Side effects:
477 * A when-idle hander is scheduled to do the redisplay, if there isn't
477 * A when-idle handler is scheduled to do the redisplay, if there isn't
478478 * one already scheduled.
479479 *
480480 *----------------------------------------------------------------------
806806 *
807807 * TkPostTearoffMenu --
808808 *
809 * Posts a menu on the screen. Used to post tearoff menus. On Unix, all
810 * menus are posted this way. Adjusts the menu's position so that it fits
811 * on the screen, and maps and raises the menu.
809 * Posts a tearoff menu on the screen. Adjusts the menu's position so
810 * that it fits on the screen, and maps and raises the menu.
812811 *
813812 * Results:
814813 * Returns a standard Tcl Error.
826825 int x, int y) /* The root X,Y coordinates where we are
827826 * posting */
828827 {
829 int vRootX, vRootY, vRootWidth, vRootHeight;
830 int result;
831
832 TkActivateMenuEntry(menuPtr, -1);
833 TkRecomputeMenu(menuPtr);
834 result = TkPostCommand(menuPtr);
835 if (result != TCL_OK) {
836 return result;
837 }
838
839 /*
840 * The post commands could have deleted the menu, which means we are dead
841 * and should go away.
842 */
843
844 if (menuPtr->tkwin == NULL) {
845 return TCL_OK;
846 }
847
848 /*
849 * Adjust the position of the menu if necessary to keep it visible on the
850 * screen. There are two special tricks to make this work right:
851 *
852 * 1. If a virtual root window manager is being used then the coordinates
853 * are in the virtual root window of menuPtr's parent; since the menu
854 * uses override-redirect mode it will be in the *real* root window for
855 * the screen, so we have to map the coordinates from the virtual root
856 * (if any) to the real root. Can't get the virtual root from the menu
857 * itself (it will never be seen by the wm) so use its parent instead
858 * (it would be better to have an an option that names a window to use
859 * for this...).
860 * 2. The menu may not have been mapped yet, so its current size might be
861 * the default 1x1. To compute how much space it needs, use its
862 * requested size, not its actual size.
863 */
864
865 Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
866 &vRootWidth, &vRootHeight);
867 vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
868 if (x > vRootX + vRootWidth) {
869 x = vRootX + vRootWidth;
870 }
871 if (x < vRootX) {
872 x = vRootX;
873 }
874 vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
875 if (y > vRootY + vRootHeight) {
876 y = vRootY + vRootHeight;
877 }
878 if (y < vRootY) {
879 y = vRootY;
880 }
881 Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
882 if (!Tk_IsMapped(menuPtr->tkwin)) {
883 Tk_MapWindow(menuPtr->tkwin);
884 }
885 TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
886 return TCL_OK;
828 return TkpPostTearoffMenu(interp, menuPtr, x, y, -1);
887829 }
888830
889831 /*
278278 mbPtr->normalFg = NULL;
279279 mbPtr->activeFg = NULL;
280280 mbPtr->disabledFg = NULL;
281 mbPtr->normalTextGC = None;
282 mbPtr->activeTextGC = None;
281 mbPtr->normalTextGC = NULL;
282 mbPtr->activeTextGC = NULL;
283283 mbPtr->gray = None;
284 mbPtr->disabledGC = None;
285 mbPtr->stippleGC = None;
284 mbPtr->disabledGC = NULL;
285 mbPtr->stippleGC = NULL;
286286 mbPtr->leftBearing = 0;
287287 mbPtr->rightBearing = 0;
288288 mbPtr->widthString = NULL;
299299 mbPtr->indicatorWidth = 0;
300300 mbPtr->indicatorHeight = 0;
301301 mbPtr->direction = DIRECTION_FLUSH;
302 mbPtr->cursor = None;
302 mbPtr->cursor = NULL;
303303 mbPtr->takeFocus = NULL;
304304 mbPtr->flags = 0;
305305
442442 if (mbPtr->image != NULL) {
443443 Tk_FreeImage(mbPtr->image);
444444 }
445 if (mbPtr->normalTextGC != None) {
445 if (mbPtr->normalTextGC != NULL) {
446446 Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);
447447 }
448 if (mbPtr->activeTextGC != None) {
448 if (mbPtr->activeTextGC != NULL) {
449449 Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
450450 }
451 if (mbPtr->disabledGC != None) {
451 if (mbPtr->disabledGC != NULL) {
452452 Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
453453 }
454 if (mbPtr->stippleGC != None) {
454 if (mbPtr->stippleGC != NULL) {
455455 Tk_FreeGC(mbPtr->display, mbPtr->stippleGC);
456456 }
457457 if (mbPtr->gray != None) {
689689 gcValues.graphics_exposures = False;
690690 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
691691 gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
692 if (mbPtr->normalTextGC != None) {
692 if (mbPtr->normalTextGC != NULL) {
693693 Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);
694694 }
695695 mbPtr->normalTextGC = gc;
698698 gcValues.background = Tk_3DBorderColor(mbPtr->activeBorder)->pixel;
699699 mask = GCForeground | GCBackground | GCFont;
700700 gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
701 if (mbPtr->activeTextGC != None) {
701 if (mbPtr->activeTextGC != NULL) {
702702 Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
703703 }
704704 mbPtr->activeTextGC = gc;
709709 * Create the GC that can be used for stippling
710710 */
711711
712 if (mbPtr->stippleGC == None) {
712 if (mbPtr->stippleGC == NULL) {
713713 gcValues.foreground = gcValues.background;
714714 mask = GCForeground;
715715 if (mbPtr->gray == None) {
735735 gcValues.foreground = gcValues.background;
736736 }
737737 gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
738 if (mbPtr->disabledGC != None) {
738 if (mbPtr->disabledGC != NULL) {
739739 Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
740740 }
741741 mbPtr->disabledGC = gc;
881881 unsigned len;
882882
883883 /*
884 * See ticket [5d991b82].
885 */
886
887 if (mbPtr->textVarName == NULL) {
888 if (!(flags & TCL_INTERP_DESTROYED)) {
889 Tcl_UntraceVar2(interp, name1, name2,
890 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
891 MenuButtonTextVarProc, clientData);
892 }
893 return NULL;
894 }
895
896 /*
897884 * If the variable is unset, then immediately recreate it unless the whole
898885 * interpreter is going away.
899886 */
900887
901888 if (flags & TCL_TRACE_UNSETS) {
902 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
889 if (!Tcl_InterpDeleted(interp) && mbPtr->textVarName) {
890 ClientData probe = NULL;
891
892 do {
893 probe = Tcl_VarTraceInfo(interp,
894 mbPtr->textVarName,
895 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
896 MenuButtonTextVarProc, probe);
897 if (probe == (ClientData)mbPtr) {
898 break;
899 }
900 } while (probe);
901 if (probe) {
902 /*
903 * We were able to fetch the unset trace for our
904 * textVarName, which means it is not unset and not
905 * the cause of this unset trace. Instead some outdated
906 * former variable must be, and we should ignore it.
907 */
908 return NULL;
909 }
903910 Tcl_SetVar2(interp, mbPtr->textVarName, NULL, mbPtr->text,
904911 TCL_GLOBAL_ONLY);
905912 Tcl_TraceVar2(interp, mbPtr->textVarName, NULL,
169169 * "left" and "right" will pop the menu left
170170 * or right, and the active item will be next
171171 * to the button. */
172 Tk_Cursor cursor; /* Current cursor for window, or None. */
172 Tk_Cursor cursor; /* Current cursor for window, or NULL. */
173173 char *takeFocus; /* Value of -takefocus option; not used in the
174174 * C code, but used by keyboard traversal
175175 * scripts. Malloc'ed, but may be NULL. */
255255 MessageCmdDeletedProc);
256256 msgPtr->optionTable = optionTable;
257257 msgPtr->relief = TK_RELIEF_FLAT;
258 msgPtr->textGC = None;
258 msgPtr->textGC = NULL;
259259 msgPtr->anchor = TK_ANCHOR_CENTER;
260260 msgPtr->aspect = 150;
261261 msgPtr->justify = TK_JUSTIFY_LEFT;
262 msgPtr->cursor = None;
262 msgPtr->cursor = NULL;
263263
264264 Tk_SetClass(msgPtr->tkwin, "Message");
265265 Tk_SetClassProcs(msgPtr->tkwin, &messageClass, msgPtr);
397397 * Tk_FreeConfigOptions handle all the standard option-related stuff.
398398 */
399399
400 if (msgPtr->textGC != None) {
400 if (msgPtr->textGC != NULL) {
401401 Tk_FreeGC(msgPtr->display, msgPtr->textGC);
402402 }
403403 if (msgPtr->textLayout != NULL) {
524524 ClientData instanceData) /* Information about widget. */
525525 {
526526 XGCValues gcValues;
527 GC gc = None;
527 GC gc = NULL;
528528 Tk_FontMetrics fm;
529529 Message *msgPtr = instanceData;
530530
535535 gcValues.font = Tk_FontId(msgPtr->tkfont);
536536 gcValues.foreground = msgPtr->fgColorPtr->pixel;
537537 gc = Tk_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues);
538 if (msgPtr->textGC != None) {
538 if (msgPtr->textGC != NULL) {
539539 Tk_FreeGC(msgPtr->display, msgPtr->textGC);
540540 }
541541 msgPtr->textGC = gc;
838838 const char *value;
839839
840840 /*
841 * See ticket [5d991b82].
842 */
843
844 if (msgPtr->textVarName == NULL) {
845 if (!(flags & TCL_INTERP_DESTROYED)) {
846 Tcl_UntraceVar2(interp, name1, name2,
847 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
848 MessageTextVarProc, clientData);
849 }
850 return NULL;
851 }
852
853 /*
854841 * If the variable is unset, then immediately recreate it unless the whole
855842 * interpreter is going away.
856843 */
857844
858845 if (flags & TCL_TRACE_UNSETS) {
859 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
846 if (!Tcl_InterpDeleted(interp) && msgPtr->textVarName) {
847 ClientData probe = NULL;
848
849 do {
850 probe = Tcl_VarTraceInfo(interp,
851 msgPtr->textVarName,
852 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
853 MessageTextVarProc, probe);
854 if (probe == (ClientData)msgPtr) {
855 break;
856 }
857 } while (probe);
858 if (probe) {
859 /*
860 * We were able to fetch the unset trace for our
861 * textVarName, which means it is not unset and not
862 * the cause of this unset trace. Instead some outdated
863 * former variable must be, and we should ignore it.
864 */
865 return NULL;
866 }
860867 Tcl_SetVar2(interp, msgPtr->textVarName, NULL, msgPtr->string,
861868 TCL_GLOBAL_ONLY);
862869 Tcl_TraceVar2(interp, msgPtr->textVarName, NULL,
4646 * thread.
4747 */
4848
49 typedef struct ThreadSpecificData {
49 typedef struct {
5050 const Tcl_ObjType *doubleTypePtr;
5151 const Tcl_ObjType *intTypePtr;
5252 } ThreadSpecificData;
9595 /*
9696 * The following structure defines the implementation of the "pixel" Tcl
9797 * object, used for measuring distances. The pixel object remembers its
98 * initial display-independant settings.
98 * initial display-independent settings.
9999 */
100100
101101 static const Tcl_ObjType pixelObjType = {
109109 /*
110110 * The following structure defines the implementation of the "pixel" Tcl
111111 * object, used for measuring distances. The pixel object remembers its
112 * initial display-independant settings.
112 * initial display-independent settings.
113113 */
114114
115115 static const Tcl_ObjType mmObjType = {
476476 Tk_Cursor newCursor, oldCursor;
477477
478478 if (nullValue) {
479 newCursor = None;
479 newCursor = NULL;
480480 } else {
481481 uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
482482 newCursor = Tk_GetCursor(interp, tkwin, uid);
483 if (newCursor == None) {
483 if (newCursor == NULL) {
484484 return TCL_ERROR;
485485 }
486486 }
487487 oldCursor = *((Tk_Cursor *) ptr);
488 if (oldCursor != None) {
488 if (oldCursor != NULL) {
489489 Tk_FreeCursor(Tk_Display(tkwin), oldCursor);
490490 }
491491 *((Tk_Cursor *) ptr) = newCursor;
836836 case TK_CONFIG_ACTIVE_CURSOR: {
837837 Tk_Cursor cursor = *((Tk_Cursor *) ptr);
838838
839 if (cursor != None) {
839 if (cursor != NULL) {
840840 result = Tk_NameOfCursor(Tk_Display(tkwin), cursor);
841841 }
842842 break;
10211021 break;
10221022 case TK_CONFIG_CURSOR:
10231023 case TK_CONFIG_ACTIVE_CURSOR:
1024 if (*((Tk_Cursor *) ptr) != None) {
1024 if (*((Tk_Cursor *) ptr) != NULL) {
10251025 Tk_FreeCursor(display, *((Tk_Cursor *) ptr));
1026 *((Tk_Cursor *) ptr) = None;
1026 *((Tk_Cursor *) ptr) = NULL;
10271027 }
10281028 }
10291029 }
9090 *
9191 * TkOldTestInit --
9292 *
93 * This function performs intialization for the Tk test suite
93 * This function performs initialization for the Tk test suite
9494 * extensions for testing support for legacy interfaces.
9595 *
9696 * Results:
175175 * of a level. */
176176 } StackLevel;
177177
178 typedef struct ThreadSpecificData {
178 typedef struct {
179179 int initialized; /* 0 means the ThreadSpecific Data structure
180180 * for the current thread needs to be
181181 * initialized. */
15211521 {
15221522 Packer *masterPtr, *slavePtr, *prevPtr, *otherPtr;
15231523 Tk_Window other, slave, parent, ancestor;
1524 TkWindow *master;
15241525 int i, j, numWindows, tmp, positionGiven;
15251526 const char *string;
15261527 static const char *const optionStrings[] = {
17981799 }
17991800
18001801 /*
1802 * Check for management loops.
1803 */
1804
1805 for (master = (TkWindow *)masterPtr->tkwin; master != NULL;
1806 master = (TkWindow *)TkGetGeomMaster(master)) {
1807 if (master == (TkWindow *)slave) {
1808 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1809 "can't put %s inside %s, would cause management loop",
1810 Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin)));
1811 Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
1812 return TCL_ERROR;
1813 }
1814 }
1815 if (masterPtr->tkwin != Tk_Parent(slave)) {
1816 ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin;
1817 }
1818
1819 /*
18011820 * Unpack the slave if it's currently packed, then position it after
18021821 * prevPtr.
18031822 */
303303 0, orientStrings, GEOMETRY},
304304 {TK_OPTION_BORDER, "-proxybackground", "proxyBackground", "ProxyBackground",
305305 0, -1, Tk_Offset(PanedWindow, proxyBackground), TK_OPTION_NULL_OK,
306 (ClientData) DEF_PANEDWINDOW_BG_MONO},
306 (ClientData) DEF_PANEDWINDOW_BG_MONO, 0},
307307 {TK_OPTION_PIXELS, "-proxyborderwidth", "proxyBorderWidth", "ProxyBorderWidth",
308308 DEF_PANEDWINDOW_PROXYBORDER, Tk_Offset(PanedWindow, proxyBorderWidthPtr),
309309 Tk_Offset(PanedWindow, proxyBorderWidth), 0, 0, GEOMETRY},
447447 pwPtr->optionTable = pwOpts->pwOptions;
448448 pwPtr->slaveOpts = pwOpts->slaveOpts;
449449 pwPtr->relief = TK_RELIEF_RAISED;
450 pwPtr->gc = None;
451 pwPtr->cursor = None;
452 pwPtr->sashCursor = None;
450 pwPtr->gc = NULL;
451 pwPtr->cursor = NULL;
452 pwPtr->sashCursor = NULL;
453453
454454 /*
455455 * Keep a hold of the associated tkwin until we destroy the widget,
861861
862862 index = -1;
863863 haveLoc = 0;
864 if (options.after != None) {
864 if (options.after != NULL) {
865865 tkwin = options.after;
866866 haveLoc = 1;
867867 for (i = 0; i < pwPtr->numSlaves; i++) {
870870 break;
871871 }
872872 }
873 } else if (options.before != None) {
873 } else if (options.before != NULL) {
874874 tkwin = options.before;
875875 haveLoc = 1;
876876 for (i = 0; i < pwPtr->numSlaves; i++) {
13031303
13041304 gcValues.background = Tk_3DBorderColor(pwPtr->background)->pixel;
13051305 newGC = Tk_GetGC(pwPtr->tkwin, GCBackground, &gcValues);
1306 if (pwPtr->gc != None) {
1306 if (pwPtr->gc != NULL) {
13071307 Tk_FreeGC(pwPtr->display, pwPtr->gc);
13081308 }
13091309 pwPtr->gc = newGC;
20432043
20442044 for (i = 0; i < masterPtr->numSlaves; i++) {
20452045 if (masterPtr->slaves[i]->before == slavePtr->tkwin) {
2046 masterPtr->slaves[i]->before = None;
2046 masterPtr->slaves[i]->before = NULL;
20472047 }
20482048 if (masterPtr->slaves[i]->after == slavePtr->tkwin) {
2049 masterPtr->slaves[i]->after = None;
2049 masterPtr->slaves[i]->after = NULL;
20502050 }
20512051 }
20522052
394394 slavePtr = ckalloc(sizeof(Slave));
395395 memset(slavePtr, 0, sizeof(Slave));
396396 slavePtr->tkwin = tkwin;
397 slavePtr->inTkwin = None;
397 slavePtr->inTkwin = NULL;
398398 slavePtr->anchor = TK_ANCHOR_NW;
399399 slavePtr->borderMode = BM_INSIDE;
400400 slavePtr->optionTable = table;
615615 Tk_SavedOptions savedOptions;
616616 int mask;
617617 Slave *slavePtr;
618 Tk_Window masterWin = (Tk_Window) NULL;
618 Tk_Window masterWin = NULL;
619 TkWindow *master;
619620
620621 if (Tk_TopWinHierarchy(tkwin)) {
621622 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
693694 Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
694695 goto error;
695696 }
697
698 /*
699 * Check for management loops.
700 */
701
702 for (master = (TkWindow *)tkwin; master != NULL;
703 master = (TkWindow *)TkGetGeomMaster(master)) {
704 if (master == (TkWindow *)slavePtr->tkwin) {
705 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
706 "can't put %s inside %s, would cause management loop",
707 Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin)));
708 Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
709 goto error;
710 }
711 }
712 if (tkwin != Tk_Parent(slavePtr->tkwin)) {
713 ((TkWindow *)slavePtr->tkwin)->maintainerPtr = (TkWindow *)tkwin;
714 }
715
696716 if ((slavePtr->masterPtr != NULL)
697717 && (slavePtr->masterPtr->tkwin == tkwin)) {
698718 /*
11841204
11851205 if ((slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH))
11861206 && (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT))) {
1207 /*
1208 * Send a ConfigureNotify to indicate that the size change
1209 * request was rejected.
1210 */
1211
1212 TkDoConfigureNotify((TkWindow *)(slavePtr->tkwin));
11871213 return;
11881214 }
11891215 masterPtr = slavePtr->masterPtr;
2222 #define Cursor XCursor
2323 #endif
2424
25 /*
26 * Mask that selects any of the state bits corresponding to buttons, plus
27 * masks that select individual buttons' bits:
28 */
29
30 #define ALL_BUTTONS \
31 (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
32 static const unsigned int buttonMasks[] = {
33 Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
34 };
35 #define ButtonMask(b) (buttonMasks[(b)-Button1])
36
37 typedef struct ThreadSpecificData {
25 typedef struct {
3826 TkWindow *grabWinPtr; /* Window that defines the top of the grab
3927 * tree in a global grab. */
4028 int lastState; /* Last known state flags. */
266254 */
267255
268256 for (b = Button1; b <= Button5; b++) {
269 mask = ButtonMask(b);
257 mask = TkGetButtonMask(b);
270258 if (changes & mask) {
271259 if (state & mask) {
272260 type = ButtonPress;
514502 tsdPtr->restrictWinPtr = NULL;
515503 }
516504 if (!(tsdPtr->restrictWinPtr || tsdPtr->grabWinPtr)) {
517 TkpSetCapture(NULL);
505
506 /*
507 * Release mouse capture only if the dead window is the capturing
508 * window.
509 */
510
511 if (winPtr == (TkWindow *)TkpGetCapture()) {
512 TkpSetCapture(NULL);
513 }
518514 }
519515 }
520516
1111
1212 #include "tkInt.h"
1313 #include "tkCanvas.h"
14 #include "default.h"
1415
1516 /*
1617 * The structure below defines the record for each rectangle/oval item.
101102 "0,0", Tk_Offset(RectOvalItem, tsoffset),
102103 TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
103104 {TK_CONFIG_COLOR, "-outline", NULL, NULL,
104 "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL},
105 DEF_CANVITEM_OUTLINE, Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK, NULL},
105106 {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL,
106107 "0,0", Tk_Offset(RectOvalItem, outline.tsoffset),
107108 TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
257258 rectOvalPtr->fillStipple = None;
258259 rectOvalPtr->activeFillStipple = None;
259260 rectOvalPtr->disabledFillStipple = None;
260 rectOvalPtr->fillGC = None;
261 rectOvalPtr->fillGC = NULL;
261262
262263 /*
263264 * Process the arguments to fill in the item record.
465466 mask |= GCCapStyle;
466467 newGC = Tk_GetGC(tkwin, mask, &gcValues);
467468 } else {
468 newGC = None;
469 }
470 if (rectOvalPtr->outline.gc != None) {
469 newGC = NULL;
470 }
471 if (rectOvalPtr->outline.gc != NULL) {
471472 Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc);
472473 }
473474 rectOvalPtr->outline.gc = newGC;
499500 }
500501
501502 if (color == NULL) {
502 newGC = None;
503 newGC = NULL;
503504 } else {
504505 gcValues.foreground = color->pixel;
505506 if (stipple != None) {
514515 * Mac OS X CG drawing needs access to the outline linewidth even for
515516 * fills (as linewidth controls antialiasing).
516517 */
517
518 gcValues.line_width = rectOvalPtr->outline.gc != None ?
518 gcValues.line_width = rectOvalPtr->outline.gc != NULL ?
519519 rectOvalPtr->outline.gc->line_width : 0;
520520 mask |= GCLineWidth;
521521 #endif
522522 newGC = Tk_GetGC(tkwin, mask, &gcValues);
523523 }
524 if (rectOvalPtr->fillGC != None) {
524 if (rectOvalPtr->fillGC != NULL) {
525525 Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);
526526 }
527527 rectOvalPtr->fillGC = newGC;
594594 if (rectOvalPtr->disabledFillStipple != None) {
595595 Tk_FreeBitmap(display, rectOvalPtr->disabledFillStipple);
596596 }
597 if (rectOvalPtr->fillGC != None) {
597 if (rectOvalPtr->fillGC != NULL) {
598598 Tk_FreeGC(display, rectOvalPtr->fillGC);
599599 }
600600 }
663663 rectOvalPtr->bbox[0] = tmpX;
664664 }
665665
666 if (rectOvalPtr->outline.gc == None) {
666 if (rectOvalPtr->outline.gc == NULL) {
667667 /*
668668 * The Win32 switch was added for 8.3 to solve a problem with ovals
669669 * leaving traces on bottom and right of 1 pixel. This may not be the
877877 }
878878 }
879879
880 if (rectOvalPtr->fillGC != None) {
880 if (rectOvalPtr->fillGC != NULL) {
881881 if (fillStipple != None) {
882882 Tk_TSOffset *tsoffset;
883883 int w = 0, h = 0;
921921 }
922922 }
923923
924 if (rectOvalPtr->outline.gc != None) {
924 if (rectOvalPtr->outline.gc != NULL) {
925925 Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
926926 if (rectOvalPtr->header.typePtr == &tkRectangleType) {
927927 XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,
992992 y1 = rectPtr->bbox[1];
993993 x2 = rectPtr->bbox[2];
994994 y2 = rectPtr->bbox[3];
995 if (rectPtr->outline.gc != None) {
995 if (rectPtr->outline.gc != NULL) {
996996 inc = width/2.0;
997997 x1 -= inc;
998998 y1 -= inc;
10081008
10091009 if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
10101010 && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
1011 if ((rectPtr->fillGC != None) || (rectPtr->outline.gc == None)) {
1011 if ((rectPtr->fillGC != NULL) || (rectPtr->outline.gc == NULL)) {
10121012 return 0.0;
10131013 }
10141014 xDiff = pointPtr[0] - x1;
11041104 }
11051105
11061106
1107 filled = ovalPtr->fillGC != None;
1108 if (ovalPtr->outline.gc == None) {
1107 filled = ovalPtr->fillGC != NULL;
1108 if (ovalPtr->outline.gc == NULL) {
11091109 width = 0.0;
11101110 filled = 1;
11111111 }
11601160 }
11611161
11621162 halfWidth = width/2.0;
1163 if (rectPtr->outline.gc == None) {
1163 if (rectPtr->outline.gc == NULL) {
11641164 halfWidth = 0.0;
11651165 }
11661166
11701170 || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
11711171 return -1;
11721172 }
1173 if ((rectPtr->fillGC == None) && (rectPtr->outline.gc != None)
1173 if ((rectPtr->fillGC == NULL) && (rectPtr->outline.gc != NULL)
11741174 && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
11751175 && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
11761176 && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
12381238 */
12391239
12401240 halfWidth = width/2.0;
1241 if (ovalPtr->outline.gc == None) {
1241 if (ovalPtr->outline.gc == NULL) {
12421242 halfWidth = 0.0;
12431243 }
12441244 oval[0] = ovalPtr->bbox[0] - halfWidth;
12551255 * return "outside".
12561256 */
12571257
1258 if ((result == 0) && (ovalPtr->outline.gc != None)
1259 && (ovalPtr->fillGC == None)) {
1258 if ((result == 0) && (ovalPtr->outline.gc != NULL)
1259 && (ovalPtr->fillGC == NULL)) {
12601260 double centerX, centerY, height;
12611261 double xDelta1, yDelta1, xDelta2, yDelta2;
12621262
156156 * Forward declarations for procedures defined later in this file:
157157 */
158158
159 static void ComputeFormat(TkScale *scalePtr);
159 static void ComputeFormat(TkScale *scalePtr, int forTicks);
160160 static void ComputeScaleGeometry(TkScale *scalePtr);
161161 static int ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr,
162162 int objc, Tcl_Obj *const objv[]);
163163 static void DestroyScale(char *memPtr);
164 static double MaxTickRoundingError(TkScale *scalePtr,
165 double tickResolution);
164166 static void ScaleCmdDeletedProc(ClientData clientData);
165167 static void ScaleEventProc(ClientData clientData,
166168 XEvent *eventPtr);
181183 static const Tk_ClassProcs scaleClass = {
182184 sizeof(Tk_ClassProcs), /* size */
183185 ScaleWorldChanged, /* worldChangedProc */
184 NULL, /* createProc */
185 NULL /* modalProc */
186 NULL, /* createProc */
187 NULL /* modalProc */
186188 };
189
190 /*
191 *--------------------------------------------------------------
192 *
193 * ScaleDigit, ScaleMax, ScaleMin, ScaleRound --
194 *
195 * Simple math helper functions, designed to be automatically inlined by
196 * the compiler most of the time.
197 *
198 *--------------------------------------------------------------
199 */
200
201 static inline int
202 ScaleDigit(
203 double value)
204 {
205 return (int) floor(log10(fabs(value)));
206 }
207
208 static inline double
209 ScaleMax(
210 double a,
211 double b)
212 {
213 return (a > b) ? a : b;
214 }
215
216 static inline double
217 ScaleMin(
218 double a,
219 double b)
220 {
221 return (a < b) ? a : b;
222 }
223
224 static inline int
225 ScaleRound(
226 double value)
227 {
228 return (int) floor(value + 0.5);
229 }
187230
188231 /*
189232 *--------------------------------------------------------------
269312 scalePtr->activeBorder = NULL;
270313 scalePtr->sliderRelief = TK_RELIEF_RAISED;
271314 scalePtr->troughColorPtr = NULL;
272 scalePtr->troughGC = None;
273 scalePtr->copyGC = None;
315 scalePtr->troughGC = NULL;
316 scalePtr->copyGC = NULL;
274317 scalePtr->tkfont = NULL;
275318 scalePtr->textColorPtr = NULL;
276 scalePtr->textGC = None;
319 scalePtr->textGC = NULL;
277320 scalePtr->relief = TK_RELIEF_FLAT;
278321 scalePtr->highlightWidth = 0;
279322 scalePtr->highlightBorder = NULL;
290333 scalePtr->vertTroughX = 0;
291334 scalePtr->vertLabelX = 0;
292335 scalePtr->fontHeight = 0;
293 scalePtr->cursor = None;
336 scalePtr->cursor = NULL;
294337 scalePtr->takeFocusPtr = NULL;
295338 scalePtr->flags = NEVER_SET;
296339
429472 }
430473 value = TkScalePixelToValue(scalePtr, x, y);
431474 }
432 Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->format, value));
475 Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->valueFormat, value));
433476 break;
434477 }
435478 case COMMAND_IDENTIFY: {
517560 NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
518561 ScaleVarProc, scalePtr);
519562 }
520 if (scalePtr->troughGC != None) {
563 if (scalePtr->troughGC != NULL) {
521564 Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
522565 }
523 if (scalePtr->copyGC != None) {
566 if (scalePtr->copyGC != NULL) {
524567 Tk_FreeGC(scalePtr->display, scalePtr->copyGC);
525568 }
526 if (scalePtr->textGC != None) {
569 if (scalePtr->textGC != NULL) {
527570 Tk_FreeGC(scalePtr->display, scalePtr->textGC);
528571 }
529572 Tk_FreeConfigOptions((char *) scalePtr, scalePtr->optionTable,
610653 TCL_GLOBAL_ONLY);
611654 if ((valuePtr != NULL) &&
612655 (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
613 scalePtr->value = TkRoundToResolution(scalePtr, value);
656 scalePtr->value = TkRoundValueToResolution(scalePtr, value);
614657 }
615658 }
616659
619662 * orientation and creating GCs.
620663 */
621664
622 scalePtr->fromValue = TkRoundToResolution(scalePtr,
665 scalePtr->fromValue = TkRoundValueToResolution(scalePtr,
623666 scalePtr->fromValue);
624 scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
625 scalePtr->tickInterval = TkRoundToResolution(scalePtr,
667 scalePtr->toValue = TkRoundValueToResolution(scalePtr, scalePtr->toValue);
668 scalePtr->tickInterval = TkRoundIntervalToResolution(scalePtr,
626669 scalePtr->tickInterval);
627670
628671 /*
635678 scalePtr->tickInterval = -scalePtr->tickInterval;
636679 }
637680
638 ComputeFormat(scalePtr);
681 ComputeFormat(scalePtr, 0);
682 ComputeFormat(scalePtr, 1);
639683
640684 scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0;
641685
728772
729773 gcValues.foreground = scalePtr->troughColorPtr->pixel;
730774 gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues);
731 if (scalePtr->troughGC != None) {
775 if (scalePtr->troughGC != NULL) {
732776 Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
733777 }
734778 scalePtr->troughGC = gc;
736780 gcValues.font = Tk_FontId(scalePtr->tkfont);
737781 gcValues.foreground = scalePtr->textColorPtr->pixel;
738782 gc = Tk_GetGC(scalePtr->tkwin, GCForeground | GCFont, &gcValues);
739 if (scalePtr->textGC != None) {
783 if (scalePtr->textGC != NULL) {
740784 Tk_FreeGC(scalePtr->display, scalePtr->textGC);
741785 }
742786 scalePtr->textGC = gc;
743787
744 if (scalePtr->copyGC == None) {
788 if (scalePtr->copyGC == NULL) {
745789 gcValues.graphics_exposures = False;
746790 scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures,
747791 &gcValues);
758802 TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
759803 }
760804
805 /*
806 *----------------------------------------------------------------------
807 *
808 * MaxTickRoundingError --
809 *
810 * Given the separation between values that can be displayed on ticks,
811 * this calculates the maximum magnitude of error for the displayed
812 * value. Tries to be clever by working out the increment in error
813 * between ticks rather than testing all of them, so may overestimate
814 * error if it is greater than 0.25 x the value separation.
815 *
816 * Results:
817 * Maximum error magnitude of tick numbers.
818 *
819 * Side effects:
820 * None.
821 *
822 *----------------------------------------------------------------------
823 */
824
825 static double
826 MaxTickRoundingError(
827 TkScale *scalePtr, /* Information about scale widget. */
828 double tickResolution) /* Separation between displayable values. */
829 {
830 double tickPosn, firstTickError, lastTickError, intervalError;
831 int tickCount;
832
833 /*
834 * Compute the error for each tick-related measure.
835 */
836
837 tickPosn = scalePtr->fromValue / tickResolution;
838 firstTickError = tickPosn - ScaleRound(tickPosn);
839
840 tickPosn = scalePtr->tickInterval / tickResolution;
841 intervalError = tickPosn - ScaleRound(tickPosn);
842
843 tickCount = (int) ((scalePtr->toValue - scalePtr->fromValue) /
844 scalePtr->tickInterval); /* not including first */
845 lastTickError = ScaleMin(0.5,
846 fabs(firstTickError + tickCount * intervalError));
847
848 /*
849 * Compute the maximum cumulative rounding error.
850 */
851
852 return ScaleMax(fabs(firstTickError), lastTickError) * tickResolution;
853 }
854
761855 /*
762856 *----------------------------------------------------------------------
763857 *
764858 * ComputeFormat --
765859 *
766 * This procedure is invoked to recompute the "format" field of a scale's
767 * widget record, which determines how the value of the scale is
768 * converted to a string.
860 * This procedure is invoked to recompute the "valueFormat" or
861 * "tickFormat" field of a scale's widget record, which determines how
862 * the value of the scale or one of its ticks is converted to a string.
769863 *
770864 * Results:
771865 * None.
772866 *
773 * Side effects:
774 * The format field of scalePtr is modified.
867 * Side effects: The valueFormat or tickFormat field of scalePtr is modified.
775868 *
776869 *----------------------------------------------------------------------
777870 */
778871
779872 static void
780873 ComputeFormat(
781 TkScale *scalePtr) /* Information about scale widget. */
874 TkScale *scalePtr, /* Information about scale widget. */
875 int forTicks) /* Do for ticks rather than value */
782876 {
783877 double maxValue, x;
784878 int mostSigDigit, numDigits, leastSigDigit, afterDecimal;
797891 if (maxValue == 0) {
798892 maxValue = 1;
799893 }
800 mostSigDigit = (int) floor(log10(maxValue));
801
802 /*
803 * If the number of significant digits wasn't specified explicitly,
804 * compute it. It's the difference between the most significant digit
805 * needed to represent any number on the scale and the most significant
806 * digit of the smallest difference between numbers on the scale. In other
807 * words, display enough digits so that at least one digit will be
808 * different between any two adjacent positions of the scale.
809 */
810
811 numDigits = scalePtr->digits;
812 if (numDigits > TCL_MAX_PREC) {
813 numDigits = 0;
814 }
815 if (numDigits <= 0) {
816 if (scalePtr->resolution > 0) {
894 mostSigDigit = ScaleDigit(maxValue);
895
896 if (forTicks) {
897 /*
898 * Display only enough digits to ensure adjacent ticks have different
899 * values.
900 */
901
902 if (scalePtr->tickInterval != 0) {
903 leastSigDigit = ScaleDigit(scalePtr->tickInterval);
904
817905 /*
818 * A resolution was specified for the scale, so just use it.
906 * Now add more digits until max error is less than
907 * TICK_VALUES_DISPLAY_ACCURACY intervals
819908 */
820909
821 leastSigDigit = (int) floor(log10(scalePtr->resolution));
910 while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit))
911 > fabs(TICK_VALUES_DISPLAY_ACCURACY * scalePtr->tickInterval)) {
912 --leastSigDigit;
913 }
914 numDigits = 1 + mostSigDigit - leastSigDigit;
822915 } else {
823 /*
824 * No resolution was specified, so compute the difference in value
825 * between adjacent pixels and use it for the least significant
826 * digit.
827 */
828
829 x = fabs(scalePtr->fromValue - scalePtr->toValue);
830 if (scalePtr->length > 0) {
831 x /= scalePtr->length;
916 numDigits = 1;
917 }
918 } else {
919 /*
920 * If the number of significant digits wasn't specified explicitly,
921 * compute it. It's the difference between the most significant digit
922 * needed to represent any number on the scale and the most
923 * significant digit of the smallest difference between numbers on the
924 * scale. In other words, display enough digits so that at least one
925 * digit will be different between any two adjacent positions of the
926 * scale.
927 */
928
929 numDigits = scalePtr->digits;
930 if (numDigits > TCL_MAX_PREC) {
931 numDigits = 0;
932 }
933 if (numDigits <= 0) {
934 if (scalePtr->resolution > 0) {
935 /*
936 * A resolution was specified for the scale, so just use it.
937 */
938
939 leastSigDigit = ScaleDigit(scalePtr->resolution);
940 } else {
941 /*
942 * No resolution was specified, so compute the difference in
943 * value between adjacent pixels and use it for the least
944 * significant digit.
945 */
946
947 x = fabs(scalePtr->fromValue - scalePtr->toValue);
948 if (scalePtr->length > 0) {
949 x /= scalePtr->length;
950 }
951 if (x > 0) {
952 leastSigDigit = ScaleDigit(x);
953 } else {
954 leastSigDigit = 0;
955 }
832956 }
833 if (x > 0){
834 leastSigDigit = (int) floor(log10(x));
835 } else {
836 leastSigDigit = 0;
957 numDigits = mostSigDigit - leastSigDigit + 1;
958 if (numDigits < 1) {
959 numDigits = 1;
837960 }
838 }
839 numDigits = mostSigDigit - leastSigDigit + 1;
840 if (numDigits < 1) {
841 numDigits = 1;
842961 }
843962 }
844963
862981 if (mostSigDigit < 0) {
863982 fDigits++; /* Zero to left of decimal point. */
864983 }
865 if (fDigits <= eDigits) {
866 sprintf(scalePtr->format, "%%.%df", afterDecimal);
984
985 if (forTicks) {
986 if (fDigits <= eDigits) {
987 sprintf(scalePtr->tickFormat, "%%.%df", afterDecimal);
988 } else {
989 sprintf(scalePtr->tickFormat, "%%.%de", numDigits - 1);
990 }
867991 } else {
868 sprintf(scalePtr->format, "%%.%de", numDigits-1);
992 if (fDigits <= eDigits) {
993 sprintf(scalePtr->valueFormat, "%%.%df", afterDecimal);
994 } else {
995 sprintf(scalePtr->valueFormat, "%%.%de", numDigits - 1);
996 }
869997 }
870998 }
871999
8931021 register TkScale *scalePtr) /* Information about widget. */
8941022 {
8951023 char valueString[TCL_DOUBLE_SPACE];
896 int tmp, valuePixels, x, y, extraSpace;
1024 int tmp, valuePixels, tickPixels, x, y, extraSpace;
8971025 Tk_FontMetrics fm;
8981026
8991027 Tk_GetFontMetrics(scalePtr->tkfont, &fm);
9391067 * whichever length is longer.
9401068 */
9411069
942 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format,
1070 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
9431071 scalePtr->fromValue) < 0) {
9441072 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
9451073 }
9461074 valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
9471075
948 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format,
1076 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
9491077 scalePtr->toValue) < 0) {
9501078 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
9511079 }
9551083 }
9561084
9571085 /*
1086 * Now do the same thing for the tick values
1087 */
1088
1089 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,
1090 scalePtr->fromValue) < 0) {
1091 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
1092 }
1093 tickPixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
1094
1095 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,
1096 scalePtr->toValue) < 0) {
1097 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
1098 }
1099 tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1);
1100 if (tickPixels < tmp) {
1101 tickPixels = tmp;
1102 }
1103
1104 /*
9581105 * Assign x-locations to the elements of the scale, working from left to
9591106 * right.
9601107 */
9611108
9621109 x = scalePtr->inset;
9631110 if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) {
964 scalePtr->vertTickRightX = x + SPACING + valuePixels;
1111 scalePtr->vertTickRightX = x + SPACING + tickPixels;
9651112 scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels
9661113 + fm.ascent/2;
9671114 x = scalePtr->vertValueRightX + SPACING;
9681115 } else if (scalePtr->tickInterval != 0) {
969 scalePtr->vertTickRightX = x + SPACING + valuePixels;
1116 scalePtr->vertTickRightX = x + SPACING + tickPixels;
9701117 scalePtr->vertValueRightX = scalePtr->vertTickRightX;
9711118 x = scalePtr->vertTickRightX + SPACING;
9721119 } else if (scalePtr->showValue) {
11181265 /*
11191266 *--------------------------------------------------------------
11201267 *
1121 * TkRoundToResolution --
1268 * TkRoundValueToResolution, TkRoundIntervalToResolution --
11221269 *
11231270 * Round a given floating-point value to the nearest multiple of the
11241271 * scale's resolution.
1272 * TkRoundValueToResolution rounds an absolute value based on the from
1273 * value as a reference.
1274 * TkRoundIntervalToResolution rounds a relative value without
1275 * reference, i.e. it rounds an interval.
11251276 *
11261277 * Results:
11271278 * The return value is the rounded result.
11331284 */
11341285
11351286 double
1136 TkRoundToResolution(
1287 TkRoundValueToResolution(
1288 TkScale *scalePtr, /* Information about scale widget. */
1289 double value) /* Value to round. */
1290 {
1291 return TkRoundIntervalToResolution(scalePtr, value - scalePtr->fromValue)
1292 + scalePtr->fromValue;
1293 }
1294
1295 double
1296 TkRoundIntervalToResolution(
11371297 TkScale *scalePtr, /* Information about scale widget. */
11381298 double value) /* Value to round. */
11391299 {
11461306 rounded = scalePtr->resolution * tick;
11471307 rem = value - rounded;
11481308 if (rem < 0) {
1149 if (rem <= -scalePtr->resolution/2) {
1150 rounded = (tick - 1.0) * scalePtr->resolution;
1151 }
1309 if (rem <= -scalePtr->resolution/2) {
1310 rounded = (tick - 1.0) * scalePtr->resolution;
1311 }
11521312 } else {
1153 if (rem >= scalePtr->resolution/2) {
1154 rounded = (tick + 1.0) * scalePtr->resolution;
1155 }
1313 if (rem >= scalePtr->resolution/2) {
1314 rounded = (tick + 1.0) * scalePtr->resolution;
1315 }
11561316 }
11571317 return rounded;
11581318 }
11921352 int result;
11931353
11941354 /*
1195 * See ticket [5d991b82].
1196 */
1197
1198 if (scalePtr->varNamePtr == NULL) {
1199 if (!(flags & TCL_INTERP_DESTROYED)) {
1200 Tcl_UntraceVar2(interp, name1, name2,
1201 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1202 ScaleVarProc, clientData);
1203 }
1204 return NULL;
1205 }
1206
1207 /*
12081355 * If the variable is unset, then immediately recreate it unless the whole
12091356 * interpreter is going away.
12101357 */
12111358
12121359 if (flags & TCL_TRACE_UNSETS) {
1213 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
1360 if (!Tcl_InterpDeleted(interp) && scalePtr->varNamePtr) {
1361 ClientData probe = NULL;
1362
1363 do {
1364 probe = Tcl_VarTraceInfo(interp,
1365 Tcl_GetString(scalePtr->varNamePtr),
1366 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
1367 ScaleVarProc, probe);
1368 if (probe == (ClientData)scalePtr) {
1369 break;
1370 }
1371 } while (probe);
1372 if (probe) {
1373 /*
1374 * We were able to fetch the unset trace for our
1375 * varNamePtr, which means it is not unset and not
1376 * the cause of this unset trace. Instead some outdated
1377 * former variable must be, and we should ignore it.
1378 */
1379 return NULL;
1380 }
12141381 Tcl_TraceVar2(interp, Tcl_GetString(scalePtr->varNamePtr),
12151382 NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
12161383 ScaleVarProc, clientData);
12371404 resultStr = "can't assign non-numeric value to scale variable";
12381405 ScaleSetVariable(scalePtr);
12391406 } else {
1240 scalePtr->value = TkRoundToResolution(scalePtr, value);
1407 scalePtr->value = TkRoundValueToResolution(scalePtr, value);
12411408
12421409 /*
12431410 * This code is a bit tricky because it sets the scale's value before
12811448 int invokeCommand) /* Non-zero means invoked -command option to
12821449 * notify of new value, 0 means don't. */
12831450 {
1284 value = TkRoundToResolution(scalePtr, value);
1451 value = TkRoundValueToResolution(scalePtr, value);
12851452 if ((value < scalePtr->fromValue)
12861453 ^ (scalePtr->toValue < scalePtr->fromValue)) {
12871454 value = scalePtr->fromValue;
13361503 if (scalePtr->varNamePtr != NULL) {
13371504 char string[TCL_DOUBLE_SPACE];
13381505
1339 if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
1506 if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
13401507 scalePtr->value) < 0) {
13411508 string[TCL_DOUBLE_SPACE - 1] = '\0';
13421509 }
14011568 }
14021569 value = scalePtr->fromValue +
14031570 value * (scalePtr->toValue - scalePtr->fromValue);
1404 return TkRoundToResolution(scalePtr, value);
1571 return TkRoundValueToResolution(scalePtr, value);
14051572 }
14061573
14071574 /*
14381605 if (valueRange == 0) {
14391606 y = 0;
14401607 } else {
1441 y = (int) ((value - scalePtr->fromValue) * pixelRange
1442 / valueRange + 0.5);
1608 y = ScaleRound((value - scalePtr->fromValue) * pixelRange
1609 / valueRange);
14431610 if (y < 0) {
14441611 y = 0;
14451612 } else if (y > pixelRange) {
7272 * values. 0 means we get to choose the number
7373 * based on resolution and/or the range of the
7474 * scale. */
75 char format[16]; /* Sprintf conversion specifier computed from
75 char valueFormat[16]; /* Sprintf conversion specifier computed from
7676 * digits and other information. */
77 char tickFormat[16]; /* Sprintf conversion specifier computed from
78 * tick interval. */
7779 double bigIncrement; /* Amount to use for large increments to scale
7880 * value. (0 means we pick a value). */
7981 char *command; /* Command prefix to use when invoking Tcl
150152 */
151153
152154 int fontHeight; /* Height of scale font. */
153 Tk_Cursor cursor; /* Current cursor for window, or None. */
155 Tk_Cursor cursor; /* Current cursor for window, or NULL. */
154156 Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the
155157 * C code, but used by keyboard traversal
156158 * scripts. May be NULL. */
214216 #define SPACING 2
215217
216218 /*
219 * The tick values are all displayed with the same number of decimal places.
220 * This number of decimal places is such that the displayed values are all
221 * accurate to within the following proportion of a tick interval.
222 */
223
224 #define TICK_VALUES_DISPLAY_ACCURACY 0.2
225
226 /*
217227 * Declaration of procedures used in the implementation of the scale widget.
218228 */
219229
220230 MODULE_SCOPE void TkEventuallyRedrawScale(TkScale *scalePtr, int what);
221 MODULE_SCOPE double TkRoundToResolution(TkScale *scalePtr, double value);
231 MODULE_SCOPE double TkRoundValueToResolution(TkScale *scalePtr, double value);
232 MODULE_SCOPE double TkRoundIntervalToResolution(TkScale *scalePtr, double value);
222233 MODULE_SCOPE TkScale * TkpCreateScale(Tk_Window tkwin);
223234 MODULE_SCOPE void TkpDestroyScale(TkScale *scalePtr);
224235 MODULE_SCOPE void TkpDisplayScale(ClientData clientData);
184184 scrollPtr->lastUnit = 0;
185185 scrollPtr->firstFraction = 0.0;
186186 scrollPtr->lastFraction = 0.0;
187 scrollPtr->cursor = None;
187 scrollPtr->cursor = NULL;
188188 scrollPtr->takeFocus = NULL;
189189 scrollPtr->flags = 0;
190190
118118 * Miscellaneous information:
119119 */
120120
121 Tk_Cursor cursor; /* Current cursor for window, or None. */
121 Tk_Cursor cursor; /* Current cursor for window, or NULL. */
122122 char *takeFocus; /* Value of -takefocus option; not used in the
123123 * C code, but used by keyboard traversal
124124 * scripts. Malloc'ed, but may be NULL. */
2525 int charOffset; /* The offset of the next char to retrieve. */
2626 int byteOffset; /* The expected byte offset of the next
2727 * chunk. */
28 char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character
28 char buffer[4]; /* A buffer to hold part of a UTF character
2929 * that is split across chunks. */
3030 char command[1]; /* Command to invoke. Actual space is
3131 * allocated as large as necessary. This must
4747 * The structure below is used to keep each thread's pending list separate.
4848 */
4949
50 typedef struct ThreadSpecificData {
50 typedef struct {
5151 TkSelInProgress *pendingPtr;
5252 /* Topmost search in progress, or NULL if
5353 * none. */
168168 squarePtr->widgetCmd = Tcl_CreateObjCommand(interp,
169169 Tk_PathName(squarePtr->tkwin), SquareWidgetObjCmd, squarePtr,
170170 SquareDeletedProc);
171 squarePtr->gc = None;
171 squarePtr->gc = NULL;
172172 squarePtr->optionTable = optionTable;
173173
174174 if (Tk_InitOptions(interp, (char *) squarePtr, optionTable, tkwin)
334334 Tk_SetWindowBackground(squarePtr->tkwin,
335335 Tk_3DBorderColor(bgBorder)->pixel);
336336 Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
337 if ((squarePtr->gc == None) && (doubleBuffer)) {
337 if ((squarePtr->gc == NULL) && doubleBuffer) {
338338 XGCValues gcValues;
339339 gcValues.function = GXcopy;
340340 gcValues.graphics_exposures = False;
399399 if (squarePtr->tkwin != NULL) {
400400 Tk_FreeConfigOptions((char *) squarePtr, squarePtr->optionTable,
401401 squarePtr->tkwin);
402 if (squarePtr->gc != None) {
402 if (squarePtr->gc != NULL) {
403403 Tk_FreeGC(squarePtr->display, squarePtr->gc);
404404 }
405405 squarePtr->tkwin = NULL;
3737 */
3838
3939 #undef Tk_MainEx
40 #undef XVisualIDFromVisual
41 #undef XSynchronize
42 #undef XUngrabServer
43 #undef XNoOp
44 #undef XGrabServer
45 #undef XFree
46 #undef XFlush
4047
4148 #ifdef _WIN32
4249
108115 * the hex representation of a pointer. */
109116 Window window) /* Window to be printed into buffer. */
110117 {
111 sprintf(buf, "%#08lx", (unsigned long) (window));
118 sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)window);
112119 }
113120
114121 int
133140 return (TkRegion) XCreateRegion();
134141 }
135142
136 void TkDestroyRegion(TkRegion r)
137 {
138 XDestroyRegion((Region)r);
139 }
140
141 void TkSetRegion(Display *d, GC g, TkRegion r)
142 {
143 XSetRegion(d, g, (Region)r);
144 }
145
146 void TkUnionRectWithRegion(XRectangle *a, TkRegion b, TkRegion c)
147 {
148 XUnionRectWithRegion(a, (Region) b, (Region) c);
149 }
150
151 void TkClipBox(TkRegion a, XRectangle *b)
152 {
153 XClipBox((Region) a, b);
154 }
155
156 void TkIntersectRegion(TkRegion a, TkRegion b, TkRegion c)
157 {
158 XIntersectRegion((Region) a, (Region) b, (Region) c);
143 int TkDestroyRegion(TkRegion r)
144 {
145 return XDestroyRegion((Region)r);
146 }
147
148 int TkSetRegion(Display *d, GC g, TkRegion r)
149 {
150 return XSetRegion(d, g, (Region)r);
151 }
152
153 int TkUnionRectWithRegion(XRectangle *a, TkRegion b, TkRegion c)
154 {
155 return XUnionRectWithRegion(a, (Region) b, (Region) c);
156 }
157
158 int TkClipBox(TkRegion a, XRectangle *b)
159 {
160 return XClipBox((Region) a, b);
161 }
162
163 int TkIntersectRegion(TkRegion a, TkRegion b, TkRegion c)
164 {
165 return XIntersectRegion((Region) a, (Region) b, (Region) c);
159166 }
160167
161168 int TkRectInRegion (TkRegion r, int a, int b, unsigned int c, unsigned int d)
163170 return XRectInRegion((Region) r, a, b, c, d);
164171 }
165172
166 void TkSubtractRegion (TkRegion a, TkRegion b, TkRegion c)
167 {
168 XSubtractRegion((Region) a, (Region) b, (Region) c);
173 int TkSubtractRegion (TkRegion a, TkRegion b, TkRegion c)
174 {
175 return XSubtractRegion((Region) a, (Region) b, (Region) c);
169176 }
170177
171178 /* TODO: To be implemented for Cygwin */
177184 # define TkAlignImageData 0
178185 # define TkGenerateActivateEvents 0
179186 # define TkpGetMS 0
187 # define TkpGetCapture 0
180188 # define TkPointerDeadWindow 0
181189 # define TkpSetCapture 0
182190 # define TkpSetCursor 0
218226 # undef TkUnionRectWithRegion
219227 # undef TkSubtractRegion
220228
221 # define TkClipBox (void (*) (TkRegion, XRectangle *)) XClipBox
229 # define TkClipBox (int (*) (TkRegion, XRectangle *)) XClipBox
222230 # define TkCreateRegion (TkRegion (*) ()) XCreateRegion
223 # define TkDestroyRegion (void (*) (TkRegion)) XDestroyRegion
224 # define TkIntersectRegion (void (*) (TkRegion, TkRegion, TkRegion)) XIntersectRegion
231 # define TkDestroyRegion (int (*) (TkRegion)) XDestroyRegion
232 # define TkIntersectRegion (int (*) (TkRegion, TkRegion, TkRegion)) XIntersectRegion
225233 # define TkRectInRegion (int (*) (TkRegion, int, int, unsigned int, unsigned int)) XRectInRegion
226 # define TkSetRegion (void (*) (Display *, GC, TkRegion)) XSetRegion
227 # define TkUnionRectWithRegion (void (*) (XRectangle *, TkRegion, TkRegion)) XUnionRectWithRegion
228 # define TkSubtractRegion (void (*) (TkRegion, TkRegion, TkRegion)) XSubtractRegion
234 # define TkSetRegion (int (*) (Display *, GC, TkRegion)) XSetRegion
235 # define TkUnionRectWithRegion (int (*) (XRectangle *, TkRegion, TkRegion)) XUnionRectWithRegion
236 # define TkSubtractRegion (int (*) (TkRegion, TkRegion, TkRegion)) XSubtractRegion
229237 # endif
230238 #endif /* !_WIN32 */
231239
504512 TkWmCleanup, /* 43 */
505513 TkSendCleanup, /* 44 */
506514 TkpTestsendCmd, /* 45 */
515 0, /* 46 */
516 TkpGetCapture, /* 47 */
507517 #endif /* WIN */
508518 #ifdef MAC_OSX_TK /* AQUA */
509519 TkGenerateActivateEvents, /* 0 */
817827 XQueryColors, /* 89 */
818828 XQueryTree, /* 90 */
819829 XSync, /* 91 */
830 0, /* 92 */
831 0, /* 93 */
832 0, /* 94 */
833 0, /* 95 */
834 0, /* 96 */
835 0, /* 97 */
836 0, /* 98 */
837 0, /* 99 */
838 0, /* 100 */
839 0, /* 101 */
840 0, /* 102 */
841 0, /* 103 */
842 0, /* 104 */
843 0, /* 105 */
844 0, /* 106 */
845 XFlush, /* 107 */
846 XGrabServer, /* 108 */
847 XUngrabServer, /* 109 */
848 XFree, /* 110 */
849 XNoOp, /* 111 */
850 XSynchronize, /* 112 */
851 0, /* 113 */
852 XVisualIDFromVisual, /* 114 */
853 0, /* 115 */
854 0, /* 116 */
855 0, /* 117 */
856 0, /* 118 */
857 0, /* 119 */
858 0, /* 120 */
859 0, /* 121 */
860 0, /* 122 */
861 0, /* 123 */
862 0, /* 124 */
863 0, /* 125 */
864 0, /* 126 */
865 0, /* 127 */
866 0, /* 128 */
867 0, /* 129 */
868 0, /* 130 */
869 0, /* 131 */
870 0, /* 132 */
871 0, /* 133 */
872 0, /* 134 */
873 0, /* 135 */
874 0, /* 136 */
875 XPutImage, /* 137 */
820876 #endif /* AQUA */
821877 };
822878
9797 * Thread-local data.
9898 */
9999
100 typedef struct ThreadSpecificData {
100 typedef struct {
101101 int nbInit; /* Number of calls to the init proc. */
102102 Tcl_HashTable engineTable; /* Map a name to a style engine. Keys are
103103 * strings, values are Tk_StyleEngine
13591359 "style \"%s\" doesn't exist", name));
13601360 Tcl_SetErrorCode(interp, "TK", "LOOKUP", "STYLE", name, NULL);
13611361 }
1362 return (Tk_Style) NULL;
1362 return NULL;
13631363 }
13641364 stylePtr = Tcl_GetHashValue(entryPtr);
13651365
3030 #if defined(MAC_OSX_TK)
3131 #include "tkMacOSXInt.h"
3232 #include "tkScrollbar.h"
33 #define SIMULATE_DRAWING TkTestSimulateDrawing(true);
33 #define LOG_DISPLAY TkTestLogDisplay()
3434 #else
35 #define SIMULATE_DRAWING
35 #define LOG_DISPLAY 1
3636 #endif
3737
3838 #ifdef __UNIX__
211211 *
212212 * Tktest_Init --
213213 *
214 * This function performs intialization for the Tk test suite exensions.
214 * This function performs initialization for the Tk test suite extensions.
215215 *
216216 * Results:
217217 * Returns a standard Tcl completion code, and leaves an error message in
15551555 /*
15561556 * The purpose of the test image type is to track the calls to an image
15571557 * display proc and record the parameters passed in each call. On macOS
1558 * these tests will fail because of the asynchronous drawing. The low
1559 * level graphics calls below which are supposed to draw a rectangle will
1560 * not draw anything to the screen because the idle task will not be
1561 * processed inside of the drawRect method and hence will not be able to
1562 * obtain a valid graphics context. Instead, the window will be marked as
1563 * needing display, and will be redrawn during a future asynchronous call
1564 * to drawRect. This will generate an other call to this display proc,
1565 * and the recorded data will show extra calls, causing the test to fail.
1566 * To avoid this, we can set the [NSApp simulateDrawing] flag, which will
1567 * cause all low level drawing routines to return immediately and not
1568 * schedule the window for drawing later. This flag is cleared by the
1569 * next call to XSync, which is called by the update command.
1558 * a display proc must be run inside of the drawRect method of an NSView
1559 * in order for the graphics operations to have any effect. To deal with
1560 * this, whenever a display proc is called outside of any drawRect method
1561 * it schedules a redraw of the NSView by calling [view setNeedsDisplay:YES].
1562 * This will trigger a later call to the view's drawRect method which will
1563 * run the display proc a second time.
1564 *
1565 * This complicates testing, since it can result in more calls to the display
1566 * proc than are expected by the test. It can also result in an inconsistent
1567 * number of calls unless the test waits until the call to drawRect actually
1568 * occurs before validating its results.
1569 *
1570 * In an attempt to work around this, this display proc only logs those
1571 * calls which occur within a drawRect method. This means that tests must
1572 * be written so as to ensure that the drawRect method is run before
1573 * results are validated. In practice it usually suffices to run update
1574 * idletasks (to run the display proc the first time) followed by update
1575 * (to run the display proc in drawRect).
1576 *
1577 * This also has the consequence that the image changed command will log
1578 * different results on Aqua than on other systems, because when the image
1579 * is redisplayed in the drawRect method the entire image will be drawn,
1580 * not just the changed portion. Tests must account for this.
15701581 */
15711582
1572 sprintf(buffer, "%s display %d %d %d %d",
1573 instPtr->masterPtr->imageName, imageX, imageY, width, height);
1574 Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
1575 buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
1583 if (LOG_DISPLAY) {
1584 sprintf(buffer, "%s display %d %d %d %d",
1585 instPtr->masterPtr->imageName, imageX, imageY, width, height);
1586 Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName,
1587 NULL, buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
1588 }
15761589 if (width > (instPtr->masterPtr->width - imageX)) {
15771590 width = instPtr->masterPtr->width - imageX;
15781591 }
15801593 height = instPtr->masterPtr->height - imageY;
15811594 }
15821595
1583 SIMULATE_DRAWING
15841596 XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
15851597 (unsigned) (width-1), (unsigned) (height-1));
15861598 XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
405405 static void GenerateModifiedEvent(TkText *textPtr);
406406 static void GenerateUndoStackEvent(TkText *textPtr);
407407 static void UpdateDirtyFlag(TkSharedText *sharedPtr);
408 static void RunAfterSyncCmd(ClientData clientData);
409408 static void TextPushUndoAction(TkText *textPtr,
410409 Tcl_Obj *undoString, int insert,
411410 const TkTextIndex *index1Ptr,
586585
587586 textPtr->state = TK_TEXT_STATE_NORMAL;
588587 textPtr->relief = TK_RELIEF_FLAT;
589 textPtr->cursor = None;
588 textPtr->cursor = NULL;
590589 textPtr->charWidth = 1;
591590 textPtr->charHeight = 10;
592591 textPtr->wrapMode = TEXT_WRAPMODE_CHAR;
15461545 textPtr->afterSyncCmd = cmd;
15471546 } else {
15481547 textPtr->afterSyncCmd = cmd;
1549 Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr);
1548 Tcl_DoWhenIdle(TkTextRunAfterSyncCmd, (ClientData) textPtr);
15501549 }
15511550 break;
15521551 } else if (objc != 2) {
15581557 Tcl_DecrRefCount(textPtr->afterSyncCmd);
15591558 }
15601559 textPtr->afterSyncCmd = NULL;
1561 TkTextUpdateLineMetrics(textPtr, 1,
1560 TkTextUpdateLineMetrics(textPtr, 0,
15621561 TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1);
15631562 break;
15641563 }
22772276 textPtr->selTagPtr->affectsDisplay = 0;
22782277 textPtr->selTagPtr->affectsDisplayGeometry = 0;
22792278 if ((textPtr->selTagPtr->elideString != NULL)
2280 || (textPtr->selTagPtr->tkfont != None)
2279 || (textPtr->selTagPtr->tkfont != NULL)
22812280 || (textPtr->selTagPtr->justifyString != NULL)
22822281 || (textPtr->selTagPtr->lMargin1String != NULL)
22832282 || (textPtr->selTagPtr->lMargin2String != NULL)
49274926 TkTextEmbWindow *ewPtr = &segPtr->body.ew;
49284927 const char *pathname;
49294928
4930 if (ewPtr->tkwin == (Tk_Window) NULL) {
4929 if (ewPtr->tkwin == NULL) {
49314930 pathname = "";
49324931 } else {
49334932 pathname = Tk_PathName(ewPtr->tkwin);
55055504 /*
55065505 *----------------------------------------------------------------------
55075506 *
5508 * RunAfterSyncCmd --
5507 * TkTextRunAfterSyncCmd --
55095508 *
55105509 * This function is called by the event loop and executes the command
55115510 * scheduled by [.text sync -command $cmd].
55195518 *----------------------------------------------------------------------
55205519 */
55215520
5522 static void
5523 RunAfterSyncCmd(
5521 void
5522 TkTextRunAfterSyncCmd(
55245523 ClientData clientData) /* Information about text widget. */
55255524 {
55265525 register TkText *textPtr = (TkText *) clientData;
666666 /* Color for drawing traversal highlight area
667667 * when highlight is off. */
668668 XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
669 Tk_Cursor cursor; /* Current cursor for window, or None. */
669 Tk_Cursor cursor; /* Current cursor for window, or NULL. */
670670 XColor *fgColor; /* Default foreground color for text. */
671671 Tk_Font tkfont; /* Default font for displaying text. */
672672 int charWidth; /* Width of average character in default
10691069 MODULE_SCOPE int TkTextSharedGetObjIndex(Tcl_Interp *interp,
10701070 TkSharedText *sharedTextPtr, Tcl_Obj *idxPtr,
10711071 TkTextIndex *indexPtr);
1072 MODULE_SCOPE const TkTextIndex *TkTextGetIndexFromObj(Tcl_Interp *interp,
1072 MODULE_SCOPE const TkTextIndex *TkTextGetIndexFromObj(Tcl_Interp *interp,
10731073 TkText *textPtr, Tcl_Obj *objPtr);
10741074 MODULE_SCOPE TkTextTabArray *TkTextGetTabs(Tcl_Interp *interp,
10751075 TkText *textPtr, Tcl_Obj *stringPtr);
11581158 int objc, Tcl_Obj *const objv[]);
11591159 MODULE_SCOPE void TkTextWinFreeClient(Tcl_HashEntry *hPtr,
11601160 TkTextEmbWindowClient *client);
1161
1161 MODULE_SCOPE void TkTextRunAfterSyncCmd(ClientData clientData);
11621162 #endif /* _TKTEXT */
11631163
11641164 /*
218218 #define LOG(toVar,what) \
219219 if (OK_TO_LOG) \
220220 Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \
221 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT)
221 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT)
222222 #define CLEAR(var) \
223223 if (OK_TO_LOG) \
224224 Tcl_SetVar2(interp, var, NULL, "", TCL_GLOBAL_ONLY)
496496 * different character might be under the mouse
497497 * cursor now). Need to recompute the current
498498 * character before the next redisplay.
499 * OUT_OF_SYNC 1 means that the last <<WidgetViewSync>> event had
500 * value 0, indicating that the widget is out of sync.
499501 */
500502
501503 #define DINFO_OUT_OF_DATE 1
502504 #define REDRAW_PENDING 2
503505 #define REDRAW_BORDERS 4
504506 #define REPICK_NEEDED 8
505
507 #define OUT_OF_SYNC 16
506508 /*
507509 * Action values for FreeDLines:
508510 *
623625 static void GenerateWidgetViewSyncEvent(TkText *textPtr, Bool InSync);
624626 static void AsyncUpdateYScrollbar(ClientData clientData);
625627 static int IsStartOfNotMergedLine(TkText *textPtr,
626 CONST TkTextIndex *indexPtr);
628 const TkTextIndex *indexPtr);
627629
628630 /*
629631 * Result values returned by TextGetScrollInfoObj:
663665 dInfoPtr = ckalloc(sizeof(TextDInfo));
664666 Tcl_InitHashTable(&dInfoPtr->styleTable, sizeof(StyleValues)/sizeof(int));
665667 dInfoPtr->dLinePtr = NULL;
666 dInfoPtr->copyGC = None;
668 dInfoPtr->copyGC = NULL;
667669 gcValues.graphics_exposures = True;
668670 dInfoPtr->scrollGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures,
669671 &gcValues);
680682 dInfoPtr->scanTotalYScroll = 0;
681683 dInfoPtr->scanMarkY = 0;
682684 dInfoPtr->dLinesInvalidated = 0;
683 dInfoPtr->flags = DINFO_OUT_OF_DATE;
685 dInfoPtr->flags = 0;
684686 dInfoPtr->topPixelOffset = 0;
685687 dInfoPtr->newTopPixelOffset = 0;
686688 dInfoPtr->currentMetricUpdateLine = -1;
727729
728730 FreeDLines(textPtr, dInfoPtr->dLinePtr, NULL, DLINE_UNLINK);
729731 Tcl_DeleteHashTable(&dInfoPtr->styleTable);
730 if (dInfoPtr->copyGC != None) {
732 if (dInfoPtr->copyGC != NULL) {
731733 Tk_FreeGC(textPtr->display, dInfoPtr->copyGC);
732734 }
733735 Tk_FreeGC(textPtr->display, dInfoPtr->scrollGC);
859861 border = tagPtr->selBorder;
860862 }
861863
862 if ((tagPtr->selFgColor != None) && (isSelected)) {
864 if ((tagPtr->selFgColor != NULL) && isSelected) {
863865 fgColor = tagPtr->selFgColor;
864866 }
865867
886888 styleValues.bgStipple = tagPtr->bgStipple;
887889 bgStipplePrio = tagPtr->priority;
888890 }
889 if ((fgColor != None) && (tagPtr->priority > fgPrio)) {
891 if ((fgColor != NULL) && (tagPtr->priority > fgPrio)) {
890892 styleValues.fgColor = fgColor;
891893 fgPrio = tagPtr->priority;
892894 }
893 if ((tagPtr->tkfont != None) && (tagPtr->priority > fontPrio)) {
895 if ((tagPtr->tkfont != NULL) && (tagPtr->priority > fontPrio)) {
894896 styleValues.tkfont = tagPtr->tkfont;
895897 fontPrio = tagPtr->priority;
896898 }
928930 && (tagPtr->priority > overstrikePrio)) {
929931 styleValues.overstrike = tagPtr->overstrike;
930932 overstrikePrio = tagPtr->priority;
931 if (tagPtr->overstrikeColor != None) {
933 if (tagPtr->overstrikeColor != NULL) {
932934 styleValues.overstrikeColor = tagPtr->overstrikeColor;
933 } else if (fgColor != None) {
935 } else if (fgColor != NULL) {
934936 styleValues.overstrikeColor = fgColor;
935937 }
936938 }
973975 && (tagPtr->priority > underlinePrio)) {
974976 styleValues.underline = tagPtr->underline;
975977 underlinePrio = tagPtr->priority;
976 if (tagPtr->underlineColor != None) {
978 if (tagPtr->underlineColor != NULL) {
977979 styleValues.underlineColor = tagPtr->underlineColor;
978 } else if (fgColor != None) {
980 } else if (fgColor != NULL) {
979981 styleValues.underlineColor = fgColor;
980982 }
981983 }
10221024 }
10231025 stylePtr->bgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
10241026 } else {
1025 stylePtr->bgGC = None;
1027 stylePtr->bgGC = NULL;
10261028 }
10271029 mask = GCFont;
10281030 gcValues.font = Tk_FontId(styleValues.tkfont);
10731075 {
10741076 stylePtr->refCount--;
10751077 if (stylePtr->refCount == 0) {
1076 if (stylePtr->bgGC != None) {
1078 if (stylePtr->bgGC != NULL) {
10771079 Tk_FreeGC(textPtr->display, stylePtr->bgGC);
10781080 }
1079 if (stylePtr->fgGC != None) {
1081 if (stylePtr->fgGC != NULL) {
10801082 Tk_FreeGC(textPtr->display, stylePtr->fgGC);
10811083 }
1082 if (stylePtr->ulGC != None) {
1084 if (stylePtr->ulGC != NULL) {
10831085 Tk_FreeGC(textPtr->display, stylePtr->ulGC);
10841086 }
1085 if (stylePtr->ovGC != None) {
1087 if (stylePtr->ovGC != NULL) {
10861088 Tk_FreeGC(textPtr->display, stylePtr->ovGC);
10871089 }
10881090 Tcl_DeleteHashEntry(stylePtr->hPtr);
26872689 if ((chunkPtr->nextPtr == NULL) && (rightX < maxX)) {
26882690 rightX = maxX;
26892691 }
2690 if (chunkPtr->stylePtr->bgGC != None) {
2692 if (chunkPtr->stylePtr->bgGC != NULL) {
26912693 /*
26922694 * Not visible - bail out now.
26932695 */
30693071 * We have looped over all lines, so we're done. We must release our
30703072 * refCount on the widget (the timer token was already set to NULL
30713073 * above). If there is a registered aftersync command, run that first.
3074 * Cancel any pending idle task which would try to run the command
3075 * after the afterSyncCmd pointer had been set to NULL.
30723076 */
30733077
30743078 if (textPtr->afterSyncCmd) {
30753079 int code;
3080 Tcl_CancelIdleCall(TkTextRunAfterSyncCmd, textPtr);
30763081 Tcl_Preserve((ClientData) textPtr->interp);
30773082 code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd,
30783083 TCL_EVAL_GLOBAL);
30903095 * with its internal data (actually it will be after the next trip
30913096 * through the event loop, because the widget redraws at idle-time).
30923097 */
3093
30943098 GenerateWidgetViewSyncEvent(textPtr, 1);
30953099
30963100 if (textPtr->refCount-- <= 1) {
31143118 * GenerateWidgetViewSyncEvent --
31153119 *
31163120 * Send the <<WidgetViewSync>> event related to the text widget
3117 * line metrics asynchronous update.
3118 * This is equivalent to:
3121 * line metrics asynchronous update. These events should only
3122 * be sent when the sync status has changed. So this function
3123 * compares the requested state with the state saved in the
3124 * TkText structure, and only generates the event if they are
3125 * different. This means that it is safe to call this function
3126 * at any time when the state is known.
3127 *
3128 * If an event is sent, the effect is equivalent to:
31193129 * event generate $textWidget <<WidgetViewSync>> -data $s
31203130 * where $s is the sync status: true (when the widget view is in
31213131 * sync with its internal data) or false (when it is not).
31313141
31323142 static void
31333143 GenerateWidgetViewSyncEvent(
3134 TkText *textPtr, /* Information about text widget. */
3135 Bool InSync) /* true if in sync, false otherwise */
3144 TkText *textPtr, /* Information about text widget. */
3145 Bool InSync) /* true if becoming in sync, false otherwise */
31363146 {
3147 Bool NewSyncState = (InSync != 0); /* ensure 0 or 1 value */
3148 Bool OldSyncState = !(textPtr->dInfoPtr->flags & OUT_OF_SYNC);
3149
31373150 /*
31383151 * OSX 10.14 needs to be told to display the window when the Text Widget
31393152 * is in sync. (That is, to run DisplayText inside of the drawRect
31413154 * like a mouse click is received. But that extra drawing corrupts the
31423155 * data that the test suite is trying to collect.
31433156 */
3144
3157
31453158 if (!tkTextDebug) {
31463159 FORCE_DISPLAY(textPtr->tkwin);
31473160 }
3148
3149 TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync",
3150 Tcl_NewBooleanObj(InSync));
3161
3162 if (NewSyncState != OldSyncState) {
3163 if (NewSyncState) {
3164 textPtr->dInfoPtr->flags &= ~OUT_OF_SYNC;
3165 } else {
3166 textPtr->dInfoPtr->flags |= OUT_OF_SYNC;
3167 }
3168 TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync",
3169 Tcl_NewBooleanObj(NewSyncState));
3170 }
31513171 }
31523172
31533173 /*
31903210 TkTextLine *linePtr = NULL;
31913211 int count = 0;
31923212 int totalLines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr);
3213 int fullUpdateRequested = (lineNum == 0 &&
3214 endLine == totalLines &&
3215 doThisMuch == -1);
31933216
31943217 if (totalLines == 0) {
31953218 /*
32003223 }
32013224
32023225 while (1) {
3226
32033227 /*
32043228 * Get a suitable line.
32053229 */
32263250 */
32273251
32283252 if (textPtr->dInfoPtr->metricEpoch == -1 && lineNum == endLine) {
3253
32293254 /*
32303255 * We have looped over all lines, so we're done.
32313256 */
32493274
32503275 if (TkBTreeLinePixelEpoch(textPtr, linePtr)
32513276 == textPtr->dInfoPtr->lineMetricUpdateEpoch) {
3277
32523278 /*
32533279 * This line is already up to date. That means there's nothing
32543280 * to do here.
32553281 */
3282
32563283 } else if (doThisMuch == -1) {
32573284 count += 8 * TkTextUpdateOneLine(textPtr, linePtr, 0,NULL,0);
32583285 } else {
32743301 indexPtr = &textPtr->dInfoPtr->metricIndex;
32753302 pixelHeight = textPtr->dInfoPtr->metricPixelHeight;
32763303 } else {
3304
32773305 /*
32783306 * We must reset the partial line height calculation data
32793307 * here, so we don't use it when it is out of date.
32973325 pixelHeight, indexPtr, 1);
32983326
32993327 if (indexPtr->linePtr == linePtr) {
3328
33003329 /*
33013330 * We didn't complete the logical line, because it
33023331 * produced very many display lines, which must be because
33053334 */
33063335
33073336 if (pixelHeight == 0) {
3337
33083338 /*
33093339 * These have already been stored, unless we just
33103340 * started the new line.
33263356 textPtr->dInfoPtr->metricEpoch = -1;
33273357 }
33283358 } else {
3359
33293360 /*
33303361 * We must never recalculate the height of the last artificial
33313362 * line. It must stay at zero, and if we recalculate it, it will
33503381 }
33513382 }
33523383 if (doThisMuch == -1) {
3384
33533385 /*
3354 * If we were requested to provide a full update, then also update the
3355 * scrollbar.
3386 * If we were requested to update the entire range, then also update
3387 * the scrollbar.
33563388 */
33573389
33583390 GetYView(textPtr->interp, textPtr, 1);
3391 }
3392 if (fullUpdateRequested) {
3393 GenerateWidgetViewSyncEvent(textPtr, 1);
33593394 }
33603395 return lineNum;
33613396 }
35253560 textPtr->refCount++;
35263561 dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
35273562 AsyncUpdateLineMetrics, textPtr);
3528 GenerateWidgetViewSyncEvent(textPtr, 0);
3529 }
3563 }
3564
3565 /*
3566 * The widget is out of sync: send a <<WidgetViewSync>> event.
3567 */
3568 GenerateWidgetViewSyncEvent(textPtr, 0);
35303569 }
35313570
35323571 /*
45434582 dlPtr->spaceAbove,
45444583 dlPtr->height-dlPtr->spaceAbove-dlPtr->spaceBelow,
45454584 dlPtr->baseline - dlPtr->spaceAbove, NULL,
4546 (Drawable) None, dlPtr->y + dlPtr->spaceAbove);
4585 None, dlPtr->y + dlPtr->spaceAbove);
45474586 }
45484587 }
45494588 }
51795218
51805219 gcValues.graphics_exposures = False;
51815220 newGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures, &gcValues);
5182 if (dInfoPtr->copyGC != None) {
5221 if (dInfoPtr->copyGC != NULL) {
51835222 Tk_FreeGC(textPtr->display, dInfoPtr->copyGC);
51845223 }
51855224 dInfoPtr->copyGC = newGC;
52675306 AsyncUpdateLineMetrics, textPtr);
52685307 inSync = 0;
52695308 }
5270
5271 if (!inSync) {
5272 GenerateWidgetViewSyncEvent(textPtr, 0);
5273 }
5309
5310 GenerateWidgetViewSyncEvent(textPtr, inSync);
52745311 }
52755312 }
52765313
62956332 {
62966333 TextDInfo *dInfoPtr = textPtr->dInfoPtr;
62976334
6298 return (
6299 ((dInfoPtr->metricEpoch == -1) &&
6300 (dInfoPtr->lastMetricUpdateLine == dInfoPtr->currentMetricUpdateLine)) ?
6301 0 : 1);
6335 return ((dInfoPtr->flags & OUT_OF_SYNC) != 0);
63026336 }
63036337
63046338 /*
69536987 static int
69546988 IsStartOfNotMergedLine(
69556989 TkText *textPtr, /* Widget record for text widget. */
6956 CONST TkTextIndex *indexPtr) /* Index to check. */
6990 const TkTextIndex *indexPtr) /* Index to check. */
69576991 {
69586992 TkTextIndex indexPtr2;
69596993
79928026 */
79938027
79948028 if (!sValuePtr->elide && (numBytes > offsetBytes)
7995 && (stylePtr->fgGC != None)) {
8029 && (stylePtr->fgGC != NULL)) {
79968030 #if TK_DRAW_IN_CONTEXT
79978031 int start = ciPtr->baseOffset + offsetBytes;
79988032 int len = ciPtr->numBytes - offsetBytes;
3939 static int GetIndex(Tcl_Interp *interp, TkSharedText *sharedPtr,
4040 TkText *textPtr, const char *string,
4141 TkTextIndex *indexPtr, int *canCachePtr);
42 static int IndexCountBytesOrdered(CONST TkText *textPtr,
43 CONST TkTextIndex *indexPtr1,
44 CONST TkTextIndex *indexPtr2);
42 static int IndexCountBytesOrdered(const TkText *textPtr,
43 const TkTextIndex *indexPtr1,
44 const TkTextIndex *indexPtr2);
4545
4646 /*
4747 * The "textindex" Tcl_Obj definition:
12971297 if (forward) {
12981298 TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, &xOffset);
12991299 while (count-- > 0) {
1300
13001301 /*
13011302 * Go to the end of the line, then forward one char/byte
13021303 * to get to the beginning of the next line.
13091310 } else {
13101311 TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, &xOffset);
13111312 while (count-- > 0) {
1313 TkTextIndex indexPtr2;
1314
13121315 /*
13131316 * Go to the beginning of the line, then backward one
13141317 * char/byte to get to the end of the previous line.
13151318 */
13161319
13171320 TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
1318 TkTextIndexBackChars(textPtr, indexPtr, 1, indexPtr,
1321 TkTextIndexBackChars(textPtr, indexPtr, 1, &indexPtr2,
13191322 COUNT_DISPLAY_INDICES);
1323
1324 /*
1325 * If we couldn't go to the previous line, then we wanted
1326 to go before the start of the text: arrange for returning
1327 the first index of the first display line.
1328 */
1329
1330 if (!TkTextIndexCmp(indexPtr, &indexPtr2)) {
1331 xOffset = 0;
1332 break;
1333 }
1334 *indexPtr = indexPtr2;
13201335 }
1321 TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
1322 }
1336 }
1337 TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL);
13231338
13241339 /*
13251340 * This call assumes indexPtr is the beginning of a display line
16351650
16361651 int
16371652 TkTextIndexCountBytes(
1638 CONST TkText *textPtr,
1639 CONST TkTextIndex *indexPtr1, /* Index describing one location. */
1640 CONST TkTextIndex *indexPtr2) /* Index describing second location. */
1653 const TkText *textPtr,
1654 const TkTextIndex *indexPtr1, /* Index describing one location. */
1655 const TkTextIndex *indexPtr2) /* Index describing second location. */
16411656 {
16421657 int compare = TkTextIndexCmp(indexPtr1, indexPtr2);
16431658
16521667
16531668 static int
16541669 IndexCountBytesOrdered(
1655 CONST TkText *textPtr,
1656 CONST TkTextIndex *indexPtr1,
1670 const TkText *textPtr,
1671 const TkTextIndex *indexPtr1,
16571672 /* Index describing location of character from
16581673 * which to count. */
1659 CONST TkTextIndex *indexPtr2)
1674 const TkTextIndex *indexPtr2)
16601675 /* Index describing location of last character
16611676 * at which to stop the count. */
16621677 {
291291 if (mask == 0) {
292292 return TCL_ERROR;
293293 }
294 if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
294 if (mask & ~(unsigned long)(ButtonMotionMask|Button1MotionMask
295295 |Button2MotionMask|Button3MotionMask|Button4MotionMask
296296 |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
297297 |EnterWindowMask|LeaveWindowMask|KeyPressMask
515515 tagPtr->affectsDisplay = 0;
516516 tagPtr->affectsDisplayGeometry = 0;
517517 if ((tagPtr->elideString != NULL)
518 || (tagPtr->tkfont != None)
518 || (tagPtr->tkfont != NULL)
519519 || (tagPtr->justifyString != NULL)
520520 || (tagPtr->lMargin1String != NULL)
521521 || (tagPtr->lMargin2String != NULL)
14451445 TkText *textPtr = clientData;
14461446 int repick = 0;
14471447
1448 # define AnyButtonMask \
1449 (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
1450
14511448 textPtr->refCount++;
14521449
14531450 /*
14591456 if (eventPtr->type == ButtonPress) {
14601457 textPtr->flags |= BUTTON_DOWN;
14611458 } else if (eventPtr->type == ButtonRelease) {
1462 int mask;
1463
1464 switch (eventPtr->xbutton.button) {
1465 case Button1:
1466 mask = Button1Mask;
1467 break;
1468 case Button2:
1469 mask = Button2Mask;
1470 break;
1471 case Button3:
1472 mask = Button3Mask;
1473 break;
1474 case Button4:
1475 mask = Button4Mask;
1476 break;
1477 case Button5:
1478 mask = Button5Mask;
1479 break;
1480 default:
1481 mask = 0;
1482 break;
1483 }
1484 if ((eventPtr->xbutton.state & AnyButtonMask) == (unsigned) mask) {
1459 unsigned int mask;
1460
1461 mask = TkGetButtonMask(eventPtr->xbutton.button);
1462 if ((eventPtr->xbutton.state & ALL_BUTTONS) == mask) {
14851463 textPtr->flags &= ~BUTTON_DOWN;
14861464 repick = 1;
14871465 }
14881466 } else if ((eventPtr->type == EnterNotify)
14891467 || (eventPtr->type == LeaveNotify)) {
1490 if (eventPtr->xcrossing.state & AnyButtonMask) {
1468 if (eventPtr->xcrossing.state & ALL_BUTTONS) {
14911469 textPtr->flags |= BUTTON_DOWN;
14921470 } else {
14931471 textPtr->flags &= ~BUTTON_DOWN;
14951473 TkTextPickCurrent(textPtr, eventPtr);
14961474 goto done;
14971475 } else if (eventPtr->type == MotionNotify) {
1498 if (eventPtr->xmotion.state & AnyButtonMask) {
1476 if (eventPtr->xmotion.state & ALL_BUTTONS) {
14991477 textPtr->flags |= BUTTON_DOWN;
15001478 } else {
15011479 textPtr->flags &= ~BUTTON_DOWN;
15121490 unsigned int oldState;
15131491
15141492 oldState = eventPtr->xbutton.state;
1515 eventPtr->xbutton.state &= ~(Button1Mask|Button2Mask
1516 |Button3Mask|Button4Mask|Button5Mask);
1493 eventPtr->xbutton.state &= ~(unsigned long)ALL_BUTTONS;
15171494 if (!(textPtr->flags & DESTROYED)) {
15181495 TkTextPickCurrent(textPtr, eventPtr);
15191496 }
12431243 *
12441244 * TkUniCharToUtf --
12451245 *
1246 * Almost the same as Tcl_UniCharToUtf but producing surrogates if
1247 * TCL_UTF_MAX==3. So, up to 6 bytes might be produced.
1246 * Almost the same as Tcl_UniCharToUtf but producing 4-byte UTF-8
1247 * sequences even when TCL_UTF_MAX==3. So, up to 4 bytes might be produced.
12481248 *
12491249 * Results:
12501250 * *buf is filled with the UTF-8 string, and the return value is the
12611261 int size = Tcl_UniCharToUtf(ch, buf);
12621262 if ((((unsigned)(ch - 0x10000) <= 0xFFFFF)) && (size < 4)) {
12631263 /* Hey, this is wrong, we must be running TCL_UTF_MAX==3
1264 * The best thing we can do is spit out 2 surrogates */
1265 ch -= 0x10000;
1266 size = Tcl_UniCharToUtf(((ch >> 10) | 0xd800), buf);
1267 size += Tcl_UniCharToUtf(((ch & 0x3ff) | 0xdc00), buf+size);
1264 * The best thing we can do is spit out a 4-byte UTF-8 character */
1265 buf[3] = (char) ((ch | 0x80) & 0xBF);
1266 buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
1267 buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
1268 buf[0] = (char) ((ch >> 18) | 0xF0);
1269 size = 4;
12681270 }
12691271 return size;
12701272 }
2222 const char *name; /* Textual name of class. */
2323 int minLength; /* Minimum # characters that must be specified
2424 * for an unambiguous match. */
25 int class; /* X symbol for class. */
25 int c_class; /* X symbol for class. */
2626 } VisualDictionary;
2727 static const VisualDictionary visualNames[] = {
2828 {"best", 1, 0},
144144 return visual;
145145 }
146146 template.depth = Tk_Depth(tkwin2);
147 template.class = visual->class;
147 template.c_class = visual->c_class;
148148 template.red_mask = visual->red_mask;
149149 template.green_mask = visual->green_mask;
150150 template.blue_mask = visual->blue_mask;
191191 }
192192 }
193193 length = p - string;
194 template.class = -1;
194 template.c_class = -1;
195195 for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) {
196196 if ((dictPtr->name[0] == c) && (length >= dictPtr->minLength)
197197 && (strncmp(string, dictPtr->name,
198198 (size_t) length) == 0)) {
199 template.class = dictPtr->class;
199 template.c_class = dictPtr->c_class;
200200 break;
201201 }
202202 }
203 if (template.class == -1) {
203 if (template.c_class == -1) {
204204 Tcl_Obj *msgObj = Tcl_ObjPrintf(
205205 "unknown or ambiguous visual name \"%s\": class must be ",
206206 string);
261261 bestPrio = 0;
262262 bestPtr = NULL;
263263 for (i = 0; i < numVisuals; i++) {
264 switch (visInfoList[i].class) {
264 switch (visInfoList[i].c_class) {
265265 case DirectColor:
266266 prio = 5; break;
267267 case GrayScale:
3636 struct TkHalfdeadWindow *nextPtr;
3737 } TkHalfdeadWindow;
3838
39 typedef struct ThreadSpecificData {
39 typedef struct {
4040 int numMainWindows; /* Count of numver of main windows currently
4141 * open in this thread. */
4242 TkMainInfo *mainWindowList;
663663 winPtr->selHandlerList = NULL;
664664 winPtr->geomMgrPtr = NULL;
665665 winPtr->geomData = NULL;
666 winPtr->geomMgrName = NULL;
667 winPtr->maintainerPtr = NULL;
666668 winPtr->reqWidth = winPtr->reqHeight = 1;
667669 winPtr->internalBorderLeft = 0;
668670 winPtr->wmInfoPtr = NULL;
674676 winPtr->internalBorderBottom = 0;
675677 winPtr->minReqWidth = 0;
676678 winPtr->minReqHeight = 0;
677 winPtr->geometryMaster = NULL;
678679
679680 return winPtr;
680681 }
850851 * Create the basic TkWindow structure.
851852 */
852853
853 tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
854 tkwin = CreateTopLevelWindow(interp, NULL, baseName,
854855 screenName, /* flags */ 0);
855856 if (tkwin == NULL) {
856857 return NULL;
14591460 TkOptionDeadWindow(winPtr);
14601461 TkSelDeadWindow(winPtr);
14611462 TkGrabDeadWindow(winPtr);
1462 if (winPtr->geometryMaster != NULL) {
1463 ckfree(winPtr->geometryMaster);
1464 winPtr->geometryMaster = NULL;
1463 if (winPtr->geomMgrName != NULL) {
1464 ckfree(winPtr->geomMgrName);
1465 winPtr->geomMgrName = NULL;
14651466 }
14661467 if (winPtr->mainPtr != NULL) {
14671468 if (winPtr->pathName != NULL) {
20872088 Tk_UndefineCursor(
20882089 Tk_Window tkwin) /* Window to manipulate. */
20892090 {
2090 Tk_DefineCursor(tkwin, None);
2091 Tk_DefineCursor(tkwin, NULL);
20912092 }
20922093
20932094 void
28472848 * but before starting to execute commands. */
28482849 Tcl_Interp *interp)
28492850 {
2850 TCHAR name[MAX_PATH];
2851 WCHAR name[MAX_PATH];
28512852 int len;
28522853 void (*tkmainex)(int, char **, Tcl_AppInitProc *, Tcl_Interp *);
28532854
28542855 /* construct "<path>/libtk8.?.dll", from "<path>/tk8?.dll" */
28552856 len = GetModuleFileNameW(Tk_GetHINSTANCE(), name, MAX_PATH);
2856 name[len-2] = TEXT('.');
2857 name[len-2] = '.';
28572858 name[len-1] = name[len-5];
2858 _tcscpy(name+len, TEXT(".dll"));
2859 memcpy(name+len-8, TEXT("libtk8"), 6 * sizeof(TCHAR));
2860
2861 tkcygwindll = LoadLibrary(name);
2859 wcscpy(name+len, L".dll");
2860 memcpy(name+len-8, L"libtk8", 6 * sizeof(WCHAR));
2861
2862 tkcygwindll = LoadLibraryW(name);
28622863 if (!tkcygwindll) {
28632864 /* dll is not present */
28642865 return 0;
32593260 }
32603261 Tcl_ResetResult(interp);
32613262 if (sync) {
3262 XSynchronize(Tk_Display(Tk_MainWindow(interp)), True);
3263 (void)XSynchronize(Tk_Display(Tk_MainWindow(interp)), True);
32633264 }
32643265
32653266 /*
8080 * Compound base/image options
8181 */
8282 {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
83 "none", Tk_Offset(Base,base.compoundObj), -1,
84 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
83 NULL, Tk_Offset(Base,base.compoundObj), -1,
84 TK_OPTION_NULL_OK,(ClientData)ttkCompoundStrings,
85 GEOMETRY_CHANGED },
8586 {TK_OPTION_STRING, "-padding", "padding", "Pad",
8687 NULL, Tk_Offset(Base,base.paddingObj), -1,
8788 TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED},
44 *
55 */
66
7 #include <tk.h>
8 #include <X11/Xlib.h>
9 #include <X11/Xutil.h>
7 #include "tkInt.h"
108 #include "ttkTheme.h"
119
1210 #define DEFAULT_BORDERWIDTH "2"
33 * Tk alternate theme, intended to match the MSUE and Gtk's (old) default theme
44 */
55
6 #include <math.h>
7 #include <string.h>
8
9 #include <tkInt.h>
10 #include <X11/Xlib.h>
11 #include <X11/Xutil.h>
6 #include "tkInt.h"
127 #include "ttkTheme.h"
138
149 #if defined(_WIN32)
1510 static const int WIN32_XDRAWLINE_HACK = 1;
1611 #else
1712 static const int WIN32_XDRAWLINE_HACK = 0;
13 #endif
14
15 #if defined(MAC_OSX_TK)
16 #define IGNORES_VISUAL
1817 #endif
1918
2019 #define BORDERWIDTH 2
509508 XGCValues gcValues;
510509 GC copyGC;
511510 unsigned long imgColors[8];
512 XImage *img;
511 XImage *img = NULL;
513512
514513 Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
515514 b = Ttk_PadBox(b, padding);
549548 /*
550549 * Create a scratch buffer to store the image:
551550 */
552 img = XGetImage(display,d, 0, 0,
553 (unsigned int)spec->width, (unsigned int)spec->height,
554 AllPlanes, ZPixmap);
555 if (img == NULL)
551
552 #if defined(IGNORES_VISUAL)
553
554 /*
555 * Platforms which ignore the VisualInfo can use XCreateImage to get the
556 * scratch image. This is essential on macOS, where it is not safe to call
557 * XGetImage in a display procedure.
558 */
559
560 img = XCreateImage(display, NULL, 32, ZPixmap, 0, NULL,
561 (unsigned int)spec->width, (unsigned int)spec->height,
562 0, 0);
563 #else
564
565 /*
566 * This trick allows creating the scratch XImage without having to
567 * construct a VisualInfo.
568 */
569
570 img = XGetImage(display, d, 0, 0,
571 (unsigned int)spec->width, (unsigned int)spec->height,
572 AllPlanes, ZPixmap);
573 #endif
574
575 if (img == NULL) {
576 return;
577 }
578
579 #if defined(IGNORES_VISUAL)
580
581 img->data = ckalloc(img->bytes_per_line * img->height);
582 if (img->data == NULL) {
583 XDestroyImage(img);
556584 return;
585 }
586
587 #endif
557588
558589 /*
559 * Create the image, painting it into an XImage one pixel at a time.
590 * Create the image, painting it into the XImage one pixel at a time.
560591 */
592
561593 index = Ttk_StateTableLookup(spec->map, state);
562594 for (iy=0 ; iy<spec->height ; iy++) {
563595 for (ix=0 ; ix<spec->width ; ix++) {
567599 }
568600
569601 /*
570 * Copy onto our target drawable surface.
602 * Copy the image onto our target drawable surface.
571603 */
604
572605 memset(&gcValues, 0, sizeof(gcValues));
573606 copyGC = Tk_GetGC(tkwin, 0, &gcValues);
574
575607 TkPutImage(NULL, 0, display, d, copyGC, img, 0, 0, b.x, b.y,
576608 spec->width, spec->height);
577609
578610 /*
579611 * Tidy up.
580612 */
613
581614 Tk_FreeGC(display, copyGC);
615
616 /*
617 * Protect against the possibility that some future platform might
618 * not use the Tk memory manager in its implementation of XDestroyImage,
619 * even though that would be an extremely strange thing to do.
620 */
621
622 #if defined(IGNORES_VISUAL)
623 ckfree(img->data);
624 img->data = NULL;
625 #endif
626
582627 XDestroyImage(img);
583628 }
584629
77 * Copyright (c) 2004 Joe English
88 */
99
10 #include <string.h>
11 #include <stdio.h>
12 #include <tkInt.h>
13 #include <X11/Xatom.h>
14
10 #include "tkInt.h"
1511 #include "ttkTheme.h"
1612 #include "ttkWidget.h"
1713
332328 ClientData clientData, int offset, char *buffer, int maxBytes)
333329 {
334330 Entry *entryPtr = (Entry *) clientData;
335 size_t byteCount;
331 int byteCount;
336332 const char *string;
337333 const char *selStart, *selEnd;
338334
346342 selEnd = Tcl_UtfAtIndex(selStart,
347343 entryPtr->entry.selectLast - entryPtr->entry.selectFirst);
348344 byteCount = selEnd - selStart - offset;
349 if (byteCount > (size_t)maxBytes) {
345 if (byteCount > maxBytes) {
350346 /* @@@POSSIBLE BUG: Can transfer partial UTF-8 sequences. Is this OK? */
351347 byteCount = maxBytes;
352348 }
978974 Ttk_TraceHandle *vt = 0;
979975
980976 if (mask & TEXTVAR_CHANGED) {
981 if (textVarName && *Tcl_GetString(textVarName)) {
977 if (textVarName && *Tcl_GetString(textVarName) != '\0') {
982978 vt = Ttk_TraceVariable(interp,
983979 textVarName,EntryTextVariableTrace,entryPtr);
984980 if (!vt) return TCL_ERROR;
11541150 mask |= GCForeground;
11551151 }
11561152 gc = Tk_GetGC(entryPtr->core.tkwin, mask, &gcValues);
1157 if (clip != None) {
1153 if (clip != NULL) {
11581154 TkSetRegion(Tk_Display(entryPtr->core.tkwin), gc, clip);
11591155 }
11601156 return gc;
12641260 cursorX = field.x + field.width - cursorWidth;
12651261 }
12661262
1267 gc = EntryGetGC(entryPtr, es.insertColorObj, None);
1263 gc = EntryGetGC(entryPtr, es.insertColorObj, NULL);
12681264 XFillRectangle(Tk_Display(tkwin), d, gc,
12691265 cursorX, cursorY, cursorWidth, cursorHeight);
12701266 Tk_FreeGC(Tk_Display(tkwin), gc);
12961292 * it from the Xft guts (if they're being used).
12971293 */
12981294 #ifdef HAVE_XFT
1299 TkUnixSetXftClipRegion(None);
1295 TkUnixSetXftClipRegion(NULL);
13001296 #endif
13011297 TkDestroyRegion(clipRegion);
13021298 }
13651361 *indexPtr = Tk_PointToChar(entryPtr->entry.textLayout,
13661362 x - entryPtr->entry.layoutX, 0);
13671363
1364 TtkUpdateScrollInfo(entryPtr->entry.xscrollHandle);
13681365 if (*indexPtr < entryPtr->entry.xscroll.first) {
13691366 *indexPtr = entryPtr->entry.xscroll.first;
13701367 }
16591656 if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) {
16601657 return TCL_ERROR;
16611658 }
1662 TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst);
1659 TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst, 1);
16631660 return TCL_OK;
16641661 }
16651662 return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle);
17001697 TtkWidgetSize, /* sizeProc */
17011698 EntryDoLayout, /* layoutProc */
17021699 EntryDisplay /* displayProc */
1700 };
1701
1702 /*------------------------------------------------------------------------
1703 * Named indices for the combobox "current" command
1704 */
1705 static const char *const comboboxCurrentIndexNames[] = {
1706 "end", NULL
1707 };
1708 enum comboboxCurrentIndices {
1709 INDEX_END
17031710 };
17041711
17051712 /*------------------------------------------------------------------------
18031810 Tcl_SetObjResult(interp, Tcl_NewIntObj(currentIndex));
18041811 return TCL_OK;
18051812 } else if (objc == 3) {
1806 if (Tcl_GetIntFromObj(interp, objv[2], &currentIndex) != TCL_OK) {
1807 return TCL_ERROR;
1808 }
1809 if (currentIndex < 0 || currentIndex >= nValues) {
1810 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1811 "Index %s out of range", Tcl_GetString(objv[2])));
1812 Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL);
1813 return TCL_ERROR;
1814 }
1813 int result, index;
1814
1815 result = Tcl_GetIndexFromObj(NULL, objv[2], comboboxCurrentIndexNames,
1816 "", 0, &index);
1817 if (result == TCL_OK) {
1818
1819 /*
1820 * The index is one of the named indices.
1821 */
1822
1823 switch (index) {
1824 case INDEX_END:
1825 /* "end" index */
1826 currentIndex = nValues - 1;
1827 break;
1828 }
1829 } else {
1830
1831 /*
1832 * The index should be just an integer.
1833 */
1834
1835 if (Tcl_GetIntFromObj(NULL, objv[2], &currentIndex) != TCL_OK) {
1836 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1837 "Incorrect index %s", Tcl_GetString(objv[2])));
1838 Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_VALUE", NULL);
1839 return TCL_ERROR;
1840 }
1841
1842 if (currentIndex < 0 || currentIndex >= nValues) {
1843 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
1844 "Index %s out of range", Tcl_GetString(objv[2])));
1845 Tcl_SetErrorCode(interp, "TTK", "COMBOBOX", "IDX_RANGE", NULL);
1846 return TCL_ERROR;
1847 }
1848 }
18151849
18161850 cbPtr->combobox.currentIndex = currentIndex;
18171851
439439 */
440440 switch (LabelAnchorSide(style.labelAnchor)) {
441441 case TTK_SIDE_LEFT: borderParcel.x -= lw / 2;
442 /* FALLTHRU */
442443 case TTK_SIDE_RIGHT: borderParcel.width += lw/2; break;
443444 case TTK_SIDE_TOP: borderParcel.y -= lh / 2;
445 /* FALLTHRU */
444446 case TTK_SIDE_BOTTOM: borderParcel.height += lh / 2; break;
445447 }
446448 }
55 *
66 */
77
8 #include <tcl.h>
9 #include <tkInt.h>
8 #include "tkInt.h"
109 #include "ttkTheme.h"
1110
1211 /*----------------------------------------------------------------------
182181
183182 if (clipRegion != NULL) {
184183 #ifdef HAVE_XFT
185 TkUnixSetXftClipRegion(None);
184 TkUnixSetXftClipRegion(NULL);
186185 #endif
187186 XSetClipMask(Tk_Display(tkwin), gc1, None);
188187 XSetClipMask(Tk_Display(tkwin), gc2, None);
66 */
77
88 #include <string.h>
9 #include <tk.h>
9 #include "tkInt.h"
1010 #include "ttkThemeInt.h"
1111
1212 #define MAX(a,b) (a > b ? a : b)
6868 {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/,
6969 Tk_Offset(Tab,imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
7070 {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound",
71 "none", Tk_Offset(Tab,compoundObj), -1,
72 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
71 NULL, Tk_Offset(Tab,compoundObj), -1,
72 TK_OPTION_NULL_OK,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED },
7373 {TK_OPTION_INT, "-underline", "underline", "Underline", "-1",
7474 Tk_Offset(Tab,underlineObj), -1, 0,0,GEOMETRY_CHANGED },
7575 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 }
3333 * TtkScrollbarUpdateRequired, which will invoke step (5) (@@@ Fix this)
3434 */
3535
36 #include <tkInt.h>
36 #include "tkInt.h"
3737 #include "ttkTheme.h"
3838 #include "ttkWidget.h"
3939
180180 h->flags |= SCROLL_UPDATE_REQUIRED;
181181 }
182182
183 /* TtkUpdateScrollInfo --
184 * Call the layoutProc to update the scroll info first, last, and total.
185 * Do it only if needed, that is when a redisplay is pending (which
186 * indicates scroll info are possibly out of date).
187 */
188
189 void TtkUpdateScrollInfo(ScrollHandle h)
190 {
191 if (h->corePtr->flags & REDISPLAY_PENDING) {
192 h->corePtr->widgetSpec->layoutProc(h->corePtr);
193 }
194 }
195
183196 /* TtkScrollviewCommand --
184197 * Widget [xy]view command implementation.
185198 *
192205 Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle h)
193206 {
194207 Scrollable *s = h->scrollPtr;
195 int newFirst = s->first;
208 int newFirst;
209
210 TtkUpdateScrollInfo(h);
211 newFirst = s->first;
196212
197213 if (objc == 2) {
198214 Tcl_Obj *result[2];
225241 }
226242 }
227243
228 TtkScrollTo(h, newFirst);
244 TtkScrollTo(h, newFirst, 0);
229245
230246 return TCL_OK;
231247 }
232248
233 void TtkScrollTo(ScrollHandle h, int newFirst)
234 {
235 Scrollable *s = h->scrollPtr;
249 void TtkScrollTo(ScrollHandle h, int newFirst, int updateScrollInfo)
250 {
251 Scrollable *s = h->scrollPtr;
252
253 if (updateScrollInfo) {
254 TtkUpdateScrollInfo(h);
255 }
236256
237257 if (newFirst >= s->total)
238258 newFirst = s->total - 1;
130130 unsigned int mask = onbits | offbits;
131131 Tcl_DString result;
132132 int i;
133 size_t len;
133 int len;
134134
135135 Tcl_DStringInit(&result);
136136
146146 len = Tcl_DStringLength(&result);
147147 if (len) {
148148 /* 'len' includes extra trailing ' ' */
149 objPtr->bytes = Tcl_Alloc(len);
149 objPtr->bytes = ckalloc(len);
150150 objPtr->length = len-1;
151151 strncpy(objPtr->bytes, Tcl_DStringValue(&result), len-1);
152152 objPtr->bytes[len-1] = '\0';
153153 } else {
154154 /* empty string */
155155 objPtr->length = 0;
156 objPtr->bytes = Tcl_Alloc(1);
156 objPtr->bytes = ckalloc(1);
157157 *objPtr->bytes = '\0';
158158 }
159159
99 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
1010 */
1111
12 #include <stdlib.h>
13 #include <string.h>
14 #include <tk.h>
15 #include <tkInt.h>
12 #include "tkInt.h"
1613 #include "ttkThemeInt.h"
1714
1815 #define PKG_ASSOC_KEY "Ttk"
16
17 #ifdef MAC_OSX_TK
18 extern void TkMacOSXFlushWindows(void);
19 #define UPDATE_WINDOWS() TkMacOSXFlushWindows()
20 #else
21 #define UPDATE_WINDOWS()
22 #endif
1923
2024 /*------------------------------------------------------------------------
2125 * +++ Styles.
512516 Tcl_BackgroundException(pkgPtr->interp, code);
513517 }
514518 pkgPtr->themeChangePending = 0;
519 UPDATE_WINDOWS();
515520 }
516521
517522 /*
2828 * +++ Defaults for element option specifications.
2929 */
3030 #define DEFAULT_FONT "TkDefaultFont"
31 #ifdef MAC_OSX_TK
32 #define DEFAULT_BACKGROUND "systemTextBackgroundColor"
33 #define DEFAULT_FOREGROUND "systemTextColor"
34 #else
3135 #define DEFAULT_BACKGROUND "#d9d9d9"
3236 #define DEFAULT_FOREGROUND "black"
33
37 #endif
3438 /*------------------------------------------------------------------------
3539 * +++ Widget states.
3640 * Keep in sync with stateNames[] in tkstate.c.
2525 VarTraceProc(
2626 ClientData clientData, /* Widget record pointer */
2727 Tcl_Interp *interp, /* Interpreter containing variable. */
28 const char *name1, /* Name of variable. */
29 const char *name2, /* Second part of variable name. */
28 const char *name1, /* (unused) */
29 const char *name2, /* (unused) */
3030 int flags) /* Information about what happened. */
3131 {
3232 Ttk_TraceHandle *tracePtr = clientData;
3333 const char *name, *value;
3434 Tcl_Obj *valuePtr;
3535
36 if (flags & TCL_INTERP_DESTROYED) {
37 return NULL;
38 }
39
40 /*
41 * See ticket [5d991b82].
42 */
43
44 if (tracePtr->varnameObj == NULL) {
45 Tcl_UntraceVar2(interp, name1, name2,
46 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
47 VarTraceProc, clientData);
36 if (Tcl_InterpDeleted(interp)) {
4837 return NULL;
4938 }
5039
55
66 #include <string.h>
77 #include <stdio.h>
8 #include <tk.h>
8 #include "tkInt.h"
99 #include "ttkTheme.h"
1010 #include "ttkWidget.h"
1111
281281 0,0,0 },
282282 {TK_OPTION_BOOLEAN, "-stretch", "stretch", "Stretch",
283283 "1", -1, Tk_Offset(TreeColumn,stretch),
284 0,0,0 },
284 0,0,GEOMETRY_CHANGED },
285285 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
286286 "w", Tk_Offset(TreeColumn,anchorObj), -1, /* <<NOTE-ANCHOR>> */
287287 0,0,0 },
922922
923923 static TreeItem *IdentifyItem(Treeview *tv, int y); /*forward*/
924924
925 static const unsigned int TreeviewBindEventMask =
925 static const unsigned long TreeviewBindEventMask =
926926 KeyPressMask|KeyReleaseMask
927927 | ButtonPressMask|ButtonReleaseMask
928928 | PointerMotionMask|ButtonMotionMask
10651065 TreeviewFreeColumns(tv);
10661066
10671067 if (tv->tree.displayColumns)
1068 Tcl_Free((ClientData)tv->tree.displayColumns);
1068 ckfree((ClientData)tv->tree.displayColumns);
10691069
10701070 foreachHashEntry(&tv->tree.items, FreeItemCB);
10711071 Tcl_DeleteHashTable(&tv->tree.items);
12311231 if (mask & GEOMETRY_CHANGED) {
12321232 if (!Tk_IsMapped(tv->core.tkwin)) {
12331233 TtkResizeWidget(&tv->core);
1234 }
1235 RecomputeSlack(tv);
1234 } else {
1235 RecomputeSlack(tv);
1236 ResizeColumns(tv, TreeWidth(tv));
1237 }
12361238 }
12371239 TtkRedisplayWidget(&tv->core);
1238
1239 /* ASSERT: SLACKINVARIANT */
12401240
12411241 Tk_FreeSavedOptions(&savedOptions);
12421242 return TCL_OK;
16141614 Treeview *tv = clientData;
16151615 int visibleRows;
16161616
1617 /* ASSERT: SLACKINVARIANT */
1618
16191617 Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin));
16201618 tv->tree.treeArea = Ttk_ClientRegion(tv->core.layout, "treearea");
16211619
16221620 ResizeColumns(tv, tv->tree.treeArea.width);
1623 /* ASSERT: SLACKINVARIANT */
16241621
16251622 TtkScrolled(tv->tree.xscrollHandle,
16261623 tv->tree.xscroll.first,
22322229 Ttk_Element element;
22332230
22342231 BoundingBox(tv, item, NULL, &itemBox);
2235 PrepareItem(tv, item, &displayItem); /*@@@ FIX: -text, etc*/
2232 PrepareItem(tv, item, &displayItem);
2233 if (item->textObj) { displayItem.textObj = item->textObj; }
2234 if (item->imageObj) { displayItem.imageObj = item->imageObj; }
22362235 Ttk_RebindSublayout(layout, &displayItem);
22372236 Ttk_PlaceLayout(layout, ItemState(tv,item), itemBox);
22382237 element = Ttk_IdentifyElement(layout, x, y);
23442343 return TCL_OK;
23452344 }
23462345
2347 PrepareItem(tv, item, &displayItem); /*@@@ FIX: fill in -text,etc */
2346 PrepareItem(tv, item, &displayItem);
2347 if (item->textObj) { displayItem.textObj = item->textObj; }
2348 if (item->imageObj) { displayItem.imageObj = item->imageObj; }
23482349 Ttk_RebindSublayout(layout, &displayItem);
23492350 Ttk_PlaceLayout(layout, ItemState(tv,item), bbox);
23502351 element = Ttk_IdentifyElement(layout, x, y);
26792680 {
26802681 Treeview *tv = recordPtr;
26812682 TreeItem **items, *delq;
2682 int i;
2683 int i, selItemDeleted = 0;
26832684
26842685 if (objc != 3) {
26852686 Tcl_WrongNumArgs(interp, 2, objv, "items");
27062707 */
27072708 delq = 0;
27082709 for (i=0; items[i]; ++i) {
2710 if (items[i]->state & TTK_STATE_SELECTED) {
2711 selItemDeleted = 1;
2712 }
27092713 delq = DeleteItems(items[i], delq);
27102714 }
27112715
27222726 }
27232727
27242728 ckfree(items);
2729 if (selItemDeleted) {
2730 TtkSendVirtualEvent(tv->core.tkwin, "TreeviewSelect");
2731 }
27252732 TtkRedisplayWidget(&tv->core);
27262733 return TCL_OK;
27272734 }
28402847 */
28412848 rowNumber = RowNumber(tv, item);
28422849 if (rowNumber < tv->tree.yscroll.first) {
2843 TtkScrollTo(tv->tree.yscrollHandle, rowNumber);
2850 TtkScrollTo(tv->tree.yscrollHandle, rowNumber, 1);
28442851 } else if (rowNumber >= tv->tree.yscroll.last) {
28452852 TtkScrollTo(tv->tree.yscrollHandle,
2846 tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last));
2853 tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last), 1);
28472854 }
28482855
28492856 return TCL_OK;
28812888 int right = left + c->width;
28822889 if (c == column) {
28832890 DragColumn(tv, i, newx - right);
2884 /* ASSERT: SLACKINVARIANT */
28852891 TtkRedisplayWidget(&tv->core);
28862892 return TCL_OK;
28872893 }
28922898 "column %s is not displayed", Tcl_GetString(objv[2])));
28932899 Tcl_SetErrorCode(interp, "TTK", "TREE", "COLUMN_INVISIBLE", NULL);
28942900 return TCL_ERROR;
2901 }
2902
2903 static int TreeviewDropCommand(
2904 void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
2905 {
2906 Treeview *tv = recordPtr;
2907
2908 if (objc != 2) {
2909 Tcl_WrongNumArgs(interp, 1, objv, "drop");
2910 return TCL_ERROR;
2911 }
2912 ResizeColumns(tv, TreeWidth(tv));
2913 TtkRedisplayWidget(&tv->core);
2914 return TCL_OK;
28952915 }
28962916
28972917 /*------------------------------------------------------------------------
32433263 { "delete", TreeviewDeleteCommand,0 },
32443264 { "detach", TreeviewDetachCommand,0 },
32453265 { "drag", TreeviewDragCommand,0 },
3266 { "drop", TreeviewDropCommand,0 },
32463267 { "exists", TreeviewExistsCommand,0 },
32473268 { "focus", TreeviewFocusCommand,0 },
32483269 { "heading", TreeviewHeadingCommand,0 },
44 */
55
66 #include <string.h>
7 #include <tk.h>
7 #include "tkInt.h"
88 #include "ttkTheme.h"
99 #include "ttkWidget.h"
1010
194194 MODULE_SCOPE int TtkScrollviewCommand(
195195 Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle);
196196
197 MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst);
197 MODULE_SCOPE void TtkUpdateScrollInfo(ScrollHandle h);
198 MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst, int updateScrollInfo);
198199 MODULE_SCOPE void TtkScrolled(ScrollHandle, int first, int last, int total);
199200 MODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle);
200201
2020 if {[tk windowingsystem] eq "aqua"} {
2121 option add *ErrorDialog*background systemAlertBackgroundActive \
2222 widgetDefault
23 option add *ErrorDialog*info.text.background white widgetDefault
23 option add *ErrorDialog*info.text.background \
24 systemTextBackgroundColor widgetDefault
2425 option add *ErrorDialog*Button.highlightBackground \
2526 systemAlertBackgroundActive widgetDefault
2627 }
9697 # Arguments:
9798 # err - The error message.
9899 #
99 proc ::tk::dialog::error::bgerror err {
100 proc ::tk::dialog::error::bgerror {err {flag 1}} {
100101 global errorInfo
101102 variable button
102103
105106 set ret [catch {::tkerror $err} msg];
106107 if {$ret != 1} {return -code $ret $msg}
107108
108 # Ok the application's tkerror either failed or was not found
109 # we use the default dialog then :
109 # The application's tkerror either failed or was not found
110 # so we use the default dialog. But on Aqua we cannot display
111 # the dialog if the background error occurs in an idle task
112 # being processed inside of [NSView drawRect]. In that case
113 # we post the dialog as an after task instead.
110114 set windowingsystem [tk windowingsystem]
111115 if {$windowingsystem eq "aqua"} {
112 set ok [mc Ok]
113 } else {
114 set ok [mc OK]
115 }
116
116 if $flag {
117 set errorInfo $info
118 after 500 [list bgerror "$err" 0]
119 return
120 }
121 }
122
123 set ok [mc OK]
117124 # Truncate the message if it is too wide (>maxLine characters) or
118125 # too tall (>4 lines). Truncation occurs at the first point at
119126 # which one of those conditions is met.
747747 $w configure -state normal
748748 }
749749
750 # Restore the original button "selected" color; assume that the user
751 # wasn't monkeying around with things too much.
750 # Restore the original button "selected" color; but only if the user
751 # has not changed it in the meantime.
752752
753753 if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} {
754 $w configure -selectcolor $Priv($w,selectcolor)
754 if {[$w cget -selectcolor] eq $Priv($w,selectcolor)
755 || ([info exist Priv($w,aselectcolor)] &&
756 [$w cget -selectcolor] eq $Priv($w,aselectcolor))} {
757 $w configure -selectcolor $Priv($w,selectcolor)
758 }
755759 }
756760 unset -nocomplain Priv($w,selectcolor) Priv($w,aselectcolor)
757761
134134 set demo_arrowInfo(smallTips) {5 5 2}
135135 set demo_arrowInfo(count) 0
136136 if {[winfo depth $c] > 1} {
137 set demo_arrowInfo(bigLineStyle) "-fill SkyBlue1"
138 set demo_arrowInfo(boxStyle) "-fill {} -outline black -width 1"
139 set demo_arrowInfo(activeStyle) "-fill red -outline black -width 1"
137 if {[tk windowingsystem] eq "aqua"} {
138 set demo_arrowInfo(bigLineStyle) "-fill systemSelectedTextBackgroundColor"
139 } else {
140 set demo_arrowInfo(bigLineStyle) "-fill LightSeaGreen"
141 }
142 set demo_arrowInfo(boxStyle) "-fill {} -width 1"
143 set demo_arrowInfo(activeStyle) "-fill red -width 1"
140144 } else {
141145 # Main widget program sets variable tk_demoDirectory
142146 set demo_arrowInfo(bigLineStyle) "-fill black \
4646 set x [expr {-10 + 3*$i}]
4747 for {set j 0; set y -10} {$j < 10} {incr j; incr y 3} {
4848 $c create rect ${x}c ${y}c [expr {$x+2}]c [expr {$y+2}]c \
49 -outline black -fill $bg -tags rect
49 -fill $bg -tags rect
5050 $c create text [expr {$x+1}]c [expr {$y+1}]c -text "$i,$j" \
5151 -anchor center -tags text
5252 }
5959 bind $c <B2-Motion> "$c scan dragto %x %y"
6060 if {[tk windowingsystem] eq "aqua"} {
6161 bind $c <MouseWheel> {
62 %W yview scroll [expr {- (%D)}] units
62 %W yview scroll [expr {-(%D)}] units
6363 }
6464 bind $c <Option-MouseWheel> {
65 %W yview scroll [expr {-10 * (%D)}] units
65 %W yview scroll [expr {-10 * (%D)}] units
6666 }
6767 bind $c <Shift-MouseWheel> {
68 %W xview scroll [expr {- (%D)}] units
68 %W xview scroll [expr {-(%D)}] units
6969 }
7070 bind $c <Shift-Option-MouseWheel> {
71 %W xview scroll [expr {-10 * (%D)}] units
71 %W xview scroll [expr {-10 * (%D)}] units
72 }
73 } else {
74 bind $c <MouseWheel> {
75 %W yview scroll [expr {-(%D / 30)}] units
76 }
77 bind $c <Shift-MouseWheel> {
78 %W xview scroll [expr {-(%D / 30)}] units
7279 }
7380 }
81
82 if {[tk windowingsystem] eq "x11"} {
83 # Support for mousewheels on Linux/Unix commonly comes through mapping
84 # the wheel to the extended buttons. If you have a mousewheel, find
85 # Linux configuration info at:
86 # http://linuxreviews.org/howtos/xfree/mouse/
87 bind $c <4> {
88 if {!$tk_strictMotif} {
89 %W yview scroll -5 units
90 }
91 }
92 bind $c <Shift-4> {
93 if {!$tk_strictMotif} {
94 %W xview scroll -5 units
95 }
96 }
97 bind $c <5> {
98 if {!$tk_strictMotif} {
99 %W yview scroll 5 units
100 }
101 }
102 bind $c <Shift-5> {
103 if {!$tk_strictMotif} {
104 %W xview scroll 5 units
105 }
106 }
107 }
108
74109
75110 proc scrollEnter canvas {
76111 global oldFill
80115 }
81116 set oldFill [lindex [$canvas itemconfig $id -fill] 4]
82117 if {[winfo depth $canvas] > 1} {
83 $canvas itemconfigure $id -fill SeaGreen1
84 } else {
85 $canvas itemconfigure $id -fill black
86 $canvas itemconfigure [expr {$id+1}] -fill white
118 if {[tk windowingsystem] eq "aqua"} {
119 $canvas itemconfigure $id -fill systemSelectedTextBackgroundColor
120 } else {
121 $canvas itemconfigure $id -fill LightSeaGreen
122 }
87123 }
88124 }
89125
94130 set id [expr {$id-1}]
95131 }
96132 $canvas itemconfigure $id -fill $oldFill
97 $canvas itemconfigure [expr {$id+1}] -fill black
98133 }
99134
100135 proc scrollButton canvas {
101 global oldFill
102136 set id [$canvas find withtag current]
103137 if {[lsearch [$canvas gettags current] text] < 0} {
104138 set id [expr {$id+1}]
3939
4040 # First, create the text item and give it bindings so it can be edited.
4141
42 $c addtag text withtag [$c create text 250 200 -text "This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been been defined to support editing (see above)." -width 440 -anchor n -font $textFont -justify left]
42 $c addtag text withtag [$c create text 250 200 -text "This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been defined to support editing (see above)." -width 440 -anchor n -font $textFont -justify left]
4343 $c bind text <1> "textB1Press $c %x %y"
4444 $c bind text <B1-Motion> "textB1Move $c %x %y"
4545 $c bind text <Shift-1> "$c select adjust current @%x,%y"
11 #
22 # This demonstration script creates a dialog box with a local grab.
33
4 interp create slave
5 load {} Tk slave
6 slave eval {
7 wm title . slave
8 wm geometry . +700+30
9 pack [text .t -width 30 -height 10]
10 }
11
412 after idle {.dialog1.msg configure -wraplength 4i}
5 set i [tk_dialog .dialog1 "Dialog with local grab" {This is a modal dialog box. It uses Tk's "grab" command to create a "local grab" on the dialog box. The grab prevents any pointer-related events from getting to any other windows in the application until you have answered the dialog by invoking one of the buttons below. However, you can still interact with other applications.} \
13 set i [tk_dialog .dialog1 "Dialog with local grab" {This is a modal dialog box. It uses Tk's "grab" command to create a "local grab" on the dialog box. The grab prevents any mouse or keyboard events from getting to any other windows in the application until you have answered the dialog by invoking one of the buttons below. However, you can still interact with other applications. For example, you should be able to edit text in the window named "slave" which was created by a slave interpreter.} \
614 info 0 OK Cancel {Show Code}]
715
816 switch $i {
1018 1 {puts "You pressed Cancel"}
1119 2 {showCode .dialog1}
1220 }
21
22 if {[interp exists slave]} {
23 interp delete slave
24 }
77 after 100 {
88 grab -global .dialog2
99 }
10 set i [tk_dialog .dialog2 "Dialog with global grab" {This dialog box uses a global grab, so it prevents you from interacting with anything on your display until you invoke one of the buttons below. Global grabs are almost always a bad idea; don't use them unless you're truly desperate.} warning 0 OK Cancel {Show Code}]
10 set i [tk_dialog .dialog2 "Dialog with global grab" {This dialog box uses a global grab. If you are using an X11 window manager you will be prevented from interacting with anything on your display until you invoke one of the buttons below. This is almost always a bad idea; don't use global grabs with X11 unless you're truly desperate. On macOS systems you will not be able to interact with any window belonging to this process, but interaction with other macOS Applications will still be possible.}\
11 warning 0 OK Cancel {Show Code}]
1112
1213 switch $i {
1314 0 {puts "You pressed OK"}
9898 }
9999 set new [eval \
100100 "$w create polygon [$w coords $item] -fill $colors(active) \
101 -tags highlight"]
101 -outline {} -tags highlight"]
102102 $w raise $new marker
103103 }
104104
113113 # outline - Color to use for the floor's outline.
114114
115115 proc bg1 {w fill outline} {
116 $w create poly 347 80 349 82 351 84 353 85 363 92 375 99 386 104 \
116 $w create polygon 347 80 349 82 351 84 353 85 363 92 375 99 386 104 \
117117 386 129 398 129 398 162 484 162 484 129 559 129 559 133 725 \
118118 133 725 129 802 129 802 389 644 389 644 391 559 391 559 327 \
119119 508 327 508 311 484 311 484 278 395 278 395 288 400 288 404 \
126126 22 223 17 227 13 231 8 236 4 242 2 246 0 260 0 283 1 300 5 \
127127 321 14 335 22 348 25 365 29 363 39 358 48 352 56 337 70 \
128128 344 76 347 80 \
129 -tags {floor1 bg} -fill $fill
129 -tags {floor1 bg} -fill $fill -outline {}
130130 $w create line 386 129 398 129 -fill $outline -tags {floor1 bg}
131131 $w create line 258 355 258 387 -fill $outline -tags {floor1 bg}
132132 $w create line 60 387 60 391 -fill $outline -tags {floor1 bg}
238238 # outline - Color to use for the floor's outline.
239239
240240 proc bg2 {w fill outline} {
241 $w create poly 559 129 484 129 484 162 398 162 398 129 315 129 \
241 $w create polygon 559 129 484 129 484 162 398 162 398 129 315 129 \
242242 315 133 176 133 176 129 96 129 96 133 3 133 3 339 0 339 0 391 \
243243 60 391 60 387 258 387 258 329 350 329 350 311 395 311 395 280 \
244244 484 280 484 311 508 311 508 327 558 327 558 391 644 391 644 \
245245 367 802 367 802 129 725 129 725 133 559 133 559 129 \
246 -tags {floor2 bg} -fill $fill
246 -tags {floor2 bg} -fill $fill -outline {}
247247 $w create line 350 311 350 329 -fill $outline -tags {floor2 bg}
248248 $w create line 398 129 398 162 -fill $outline -tags {floor2 bg}
249249 $w create line 802 367 802 129 -fill $outline -tags {floor2 bg}
293293 # outline - Color to use for the floor's outline.
294294
295295 proc bg3 {w fill outline} {
296 $w create poly 159 300 107 300 107 248 159 248 159 129 96 129 96 \
296 $w create polygon 159 300 107 300 107 248 159 248 159 129 96 129 96 \
297297 133 21 133 21 331 0 331 0 391 60 391 60 370 159 370 159 300 \
298 -tags {floor3 bg} -fill $fill
299 $w create poly 258 370 258 329 350 329 350 311 399 311 399 129 \
298 -tags {floor3 bg} -fill $fill -outline {}
299 $w create polygon 258 370 258 329 350 329 350 311 399 311 399 129 \
300300 315 129 315 133 176 133 176 129 159 129 159 370 258 370 \
301 -tags {floor3 bg} -fill $fill
301 -tags {floor3 bg} -fill $fill -outline {}
302302 $w create line 96 133 96 129 -fill $outline -tags {floor3 bg}
303303 $w create line 176 129 96 129 -fill $outline -tags {floor3 bg}
304304 $w create line 176 129 176 133 -fill $outline -tags {floor3 bg}
332332
333333 proc fg1 {w color} {
334334 global floorLabels floorItems
335 set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -tags {floor1 room}]
335 set i [$w create polygon 375 246 375 172 341 172 341 246 -outline {} -tags {floor1 room}]
336336 set floorLabels($i) 101
337337 set {floorItems(101)} $i
338338 $w create text 358 209 -text 101 -fill $color -anchor c -tags {floor1 label}
339 set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -tags {floor1 room}]
339 set i [$w create polygon 307 240 339 240 339 206 307 206 -outline {} -tags {floor1 room}]
340340 set floorLabels($i) {Pub Lift1}
341341 set {floorItems(Pub Lift1)} $i
342342 $w create text 323 223 -text {Pub Lift1} -fill $color -anchor c -tags {floor1 label}
343 set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -tags {floor1 room}]
343 set i [$w create polygon 339 205 307 205 307 171 339 171 -outline {} -tags {floor1 room}]
344344 set floorLabels($i) {Priv Lift1}
345345 set {floorItems(Priv Lift1)} $i
346346 $w create text 323 188 -text {Priv Lift1} -fill $color -anchor c -tags {floor1 label}
347 set i [$w create polygon 42 389 42 337 1 337 1 389 -fill {} -tags {floor1 room}]
347 set i [$w create polygon 42 389 42 337 1 337 1 389 -outline {} -tags {floor1 room}]
348348 set floorLabels($i) 110
349349 set {floorItems(110)} $i
350350 $w create text 21.5 363 -text 110 -fill $color -anchor c -tags {floor1 label}
351 set i [$w create polygon 59 389 59 385 90 385 90 337 44 337 44 389 -fill {} -tags {floor1 room}]
351 set i [$w create polygon 59 389 59 385 90 385 90 337 44 337 44 389 -outline {} -tags {floor1 room}]
352352 set floorLabels($i) 109
353353 set {floorItems(109)} $i
354354 $w create text 67 363 -text 109 -fill $color -anchor c -tags {floor1 label}
355 set i [$w create polygon 51 300 51 253 6 253 6 300 -fill {} -tags {floor1 room}]
355 set i [$w create polygon 51 300 51 253 6 253 6 300 -outline {} -tags {floor1 room}]
356356 set floorLabels($i) 111
357357 set {floorItems(111)} $i
358358 $w create text 28.5 276.5 -text 111 -fill $color -anchor c -tags {floor1 label}
359 set i [$w create polygon 98 248 98 309 79 309 79 248 -fill {} -tags {floor1 room}]
359 set i [$w create polygon 98 248 98 309 79 309 79 248 -outline {} -tags {floor1 room}]
360360 set floorLabels($i) 117B
361361 set {floorItems(117B)} $i
362362 $w create text 88.5 278.5 -text 117B -fill $color -anchor c -tags {floor1 label}
363 set i [$w create polygon 51 251 51 204 6 204 6 251 -fill {} -tags {floor1 room}]
363 set i [$w create polygon 51 251 51 204 6 204 6 251 -outline {} -tags {floor1 room}]
364364 set floorLabels($i) 112
365365 set {floorItems(112)} $i
366366 $w create text 28.5 227.5 -text 112 -fill $color -anchor c -tags {floor1 label}
367 set i [$w create polygon 6 156 51 156 51 203 6 203 -fill {} -tags {floor1 room}]
367 set i [$w create polygon 6 156 51 156 51 203 6 203 -outline {} -tags {floor1 room}]
368368 set floorLabels($i) 113
369369 set {floorItems(113)} $i
370370 $w create text 28.5 179.5 -text 113 -fill $color -anchor c -tags {floor1 label}
371 set i [$w create polygon 85 169 79 169 79 192 85 192 -fill {} -tags {floor1 room}]
371 set i [$w create polygon 85 169 79 169 79 192 85 192 -outline {} -tags {floor1 room}]
372372 set floorLabels($i) 117A
373373 set {floorItems(117A)} $i
374374 $w create text 82 180.5 -text 117A -fill $color -anchor c -tags {floor1 label}
375 set i [$w create polygon 77 302 77 168 53 168 53 302 -fill {} -tags {floor1 room}]
375 set i [$w create polygon 77 302 77 168 53 168 53 302 -outline {} -tags {floor1 room}]
376376 set floorLabels($i) 117
377377 set {floorItems(117)} $i
378378 $w create text 65 235 -text 117 -fill $color -anchor c -tags {floor1 label}
379 set i [$w create polygon 51 155 51 115 6 115 6 155 -fill {} -tags {floor1 room}]
379 set i [$w create polygon 51 155 51 115 6 115 6 155 -outline {} -tags {floor1 room}]
380380 set floorLabels($i) 114
381381 set {floorItems(114)} $i
382382 $w create text 28.5 135 -text 114 -fill $color -anchor c -tags {floor1 label}
383 set i [$w create polygon 95 115 53 115 53 168 95 168 -fill {} -tags {floor1 room}]
383 set i [$w create polygon 95 115 53 115 53 168 95 168 -outline {} -tags {floor1 room}]
384384 set floorLabels($i) 115
385385 set {floorItems(115)} $i
386386 $w create text 74 141.5 -text 115 -fill $color -anchor c -tags {floor1 label}
387 set i [$w create polygon 87 113 87 27 10 27 10 113 -fill {} -tags {floor1 room}]
387 set i [$w create polygon 87 113 87 27 10 27 10 113 -outline {} -tags {floor1 room}]
388388 set floorLabels($i) 116
389389 set {floorItems(116)} $i
390390 $w create text 48.5 70 -text 116 -fill $color -anchor c -tags {floor1 label}
391 set i [$w create polygon 89 91 128 91 128 113 89 113 -fill {} -tags {floor1 room}]
391 set i [$w create polygon 89 91 128 91 128 113 89 113 -outline {} -tags {floor1 room}]
392392 set floorLabels($i) 118
393393 set {floorItems(118)} $i
394394 $w create text 108.5 102 -text 118 -fill $color -anchor c -tags {floor1 label}
395 set i [$w create polygon 178 128 178 132 216 132 216 91 163 91 163 112 149 112 149 128 -fill {} -tags {floor1 room}]
395 set i [$w create polygon 178 128 178 132 216 132 216 91 163 91 163 112 149 112 149 128 -outline {} -tags {floor1 room}]
396396 set floorLabels($i) 120
397397 set {floorItems(120)} $i
398398 $w create text 189.5 111.5 -text 120 -fill $color -anchor c -tags {floor1 label}
399 set i [$w create polygon 79 193 87 193 87 169 136 169 136 192 156 192 156 169 175 169 175 246 79 246 -fill {} -tags {floor1 room}]
399 set i [$w create polygon 79 193 87 193 87 169 136 169 136 192 156 192 156 169 175 169 175 246 79 246 -outline {} -tags {floor1 room}]
400400 set floorLabels($i) 122
401401 set {floorItems(122)} $i
402402 $w create text 131 207.5 -text 122 -fill $color -anchor c -tags {floor1 label}
403 set i [$w create polygon 138 169 154 169 154 191 138 191 -fill {} -tags {floor1 room}]
403 set i [$w create polygon 138 169 154 169 154 191 138 191 -outline {} -tags {floor1 room}]
404404 set floorLabels($i) 121
405405 set {floorItems(121)} $i
406406 $w create text 146 180 -text 121 -fill $color -anchor c -tags {floor1 label}
407 set i [$w create polygon 99 300 126 300 126 309 99 309 -fill {} -tags {floor1 room}]
407 set i [$w create polygon 99 300 126 300 126 309 99 309 -outline {} -tags {floor1 room}]
408408 set floorLabels($i) 106A
409409 set {floorItems(106A)} $i
410410 $w create text 112.5 304.5 -text 106A -fill $color -anchor c -tags {floor1 label}
411 set i [$w create polygon 128 299 128 309 150 309 150 248 99 248 99 299 -fill {} -tags {floor1 room}]
411 set i [$w create polygon 128 299 128 309 150 309 150 248 99 248 99 299 -outline {} -tags {floor1 room}]
412412 set floorLabels($i) 105
413413 set {floorItems(105)} $i
414414 $w create text 124.5 278.5 -text 105 -fill $color -anchor c -tags {floor1 label}
415 set i [$w create polygon 174 309 174 300 152 300 152 309 -fill {} -tags {floor1 room}]
415 set i [$w create polygon 174 309 174 300 152 300 152 309 -outline {} -tags {floor1 room}]
416416 set floorLabels($i) 106B
417417 set {floorItems(106B)} $i
418418 $w create text 163 304.5 -text 106B -fill $color -anchor c -tags {floor1 label}
419 set i [$w create polygon 176 299 176 309 216 309 216 248 152 248 152 299 -fill {} -tags {floor1 room}]
419 set i [$w create polygon 176 299 176 309 216 309 216 248 152 248 152 299 -outline {} -tags {floor1 room}]
420420 set floorLabels($i) 104
421421 set {floorItems(104)} $i
422422 $w create text 184 278.5 -text 104 -fill $color -anchor c -tags {floor1 label}
423 set i [$w create polygon 138 385 138 337 91 337 91 385 -fill {} -tags {floor1 room}]
423 set i [$w create polygon 138 385 138 337 91 337 91 385 -outline {} -tags {floor1 room}]
424424 set floorLabels($i) 108
425425 set {floorItems(108)} $i
426426 $w create text 114.5 361 -text 108 -fill $color -anchor c -tags {floor1 label}
427 set i [$w create polygon 256 337 140 337 140 385 256 385 -fill {} -tags {floor1 room}]
427 set i [$w create polygon 256 337 140 337 140 385 256 385 -outline {} -tags {floor1 room}]
428428 set floorLabels($i) 107
429429 set {floorItems(107)} $i
430430 $w create text 198 361 -text 107 -fill $color -anchor c -tags {floor1 label}
431 set i [$w create polygon 300 353 300 329 260 329 260 353 -fill {} -tags {floor1 room}]
431 set i [$w create polygon 300 353 300 329 260 329 260 353 -outline {} -tags {floor1 room}]
432432 set floorLabels($i) Smoking
433433 set {floorItems(Smoking)} $i
434434 $w create text 280 341 -text Smoking -fill $color -anchor c -tags {floor1 label}
435 set i [$w create polygon 314 135 314 170 306 170 306 246 177 246 177 135 -fill {} -tags {floor1 room}]
435 set i [$w create polygon 314 135 314 170 306 170 306 246 177 246 177 135 -outline {} -tags {floor1 room}]
436436 set floorLabels($i) 123
437437 set {floorItems(123)} $i
438438 $w create text 245.5 190.5 -text 123 -fill $color -anchor c -tags {floor1 label}
439 set i [$w create polygon 217 248 301 248 301 326 257 326 257 310 217 310 -fill {} -tags {floor1 room}]
439 set i [$w create polygon 217 248 301 248 301 326 257 326 257 310 217 310 -outline {} -tags {floor1 room}]
440440 set floorLabels($i) 103
441441 set {floorItems(103)} $i
442442 $w create text 259 287 -text 103 -fill $color -anchor c -tags {floor1 label}
443 set i [$w create polygon 396 188 377 188 377 169 316 169 316 131 396 131 -fill {} -tags {floor1 room}]
443 set i [$w create polygon 396 188 377 188 377 169 316 169 316 131 396 131 -outline {} -tags {floor1 room}]
444444 set floorLabels($i) 124
445445 set {floorItems(124)} $i
446446 $w create text 356 150 -text 124 -fill $color -anchor c -tags {floor1 label}
447 set i [$w create polygon 397 226 407 226 407 189 377 189 377 246 397 246 -fill {} -tags {floor1 room}]
447 set i [$w create polygon 397 226 407 226 407 189 377 189 377 246 397 246 -outline {} -tags {floor1 room}]
448448 set floorLabels($i) 125
449449 set {floorItems(125)} $i
450450 $w create text 392 217.5 -text 125 -fill $color -anchor c -tags {floor1 label}
451 set i [$w create polygon 399 187 409 187 409 207 474 207 474 164 399 164 -fill {} -tags {floor1 room}]
451 set i [$w create polygon 399 187 409 187 409 207 474 207 474 164 399 164 -outline {} -tags {floor1 room}]
452452 set floorLabels($i) 126
453453 set {floorItems(126)} $i
454454 $w create text 436.5 185.5 -text 126 -fill $color -anchor c -tags {floor1 label}
455 set i [$w create polygon 409 209 409 229 399 229 399 253 486 253 486 239 474 239 474 209 -fill {} -tags {floor1 room}]
455 set i [$w create polygon 409 209 409 229 399 229 399 253 486 253 486 239 474 239 474 209 -outline {} -tags {floor1 room}]
456456 set floorLabels($i) 127
457457 set {floorItems(127)} $i
458458 $w create text 436.5 231 -text 127 -fill $color -anchor c -tags {floor1 label}
459 set i [$w create polygon 501 164 501 174 495 174 495 188 490 188 490 204 476 204 476 164 -fill {} -tags {floor1 room}]
459 set i [$w create polygon 501 164 501 174 495 174 495 188 490 188 490 204 476 204 476 164 -outline {} -tags {floor1 room}]
460460 set floorLabels($i) MShower
461461 set {floorItems(MShower)} $i
462462 $w create text 488.5 184 -text MShower -fill $color -anchor c -tags {floor1 label}
463 set i [$w create polygon 497 176 513 176 513 204 492 204 492 190 497 190 -fill {} -tags {floor1 room}]
463 set i [$w create polygon 497 176 513 176 513 204 492 204 492 190 497 190 -outline {} -tags {floor1 room}]
464464 set floorLabels($i) Closet
465465 set {floorItems(Closet)} $i
466466 $w create text 502.5 190 -text Closet -fill $color -anchor c -tags {floor1 label}
467 set i [$w create polygon 476 237 476 206 513 206 513 254 488 254 488 237 -fill {} -tags {floor1 room}]
467 set i [$w create polygon 476 237 476 206 513 206 513 254 488 254 488 237 -outline {} -tags {floor1 room}]
468468 set floorLabels($i) WShower
469469 set {floorItems(WShower)} $i
470470 $w create text 494.5 230 -text WShower -fill $color -anchor c -tags {floor1 label}
471 set i [$w create polygon 486 131 558 131 558 135 724 135 724 166 697 166 697 275 553 275 531 254 515 254 515 174 503 174 503 161 486 161 -fill {} -tags {floor1 room}]
471 set i [$w create polygon 486 131 558 131 558 135 724 135 724 166 697 166 697 275 553 275 531 254 515 254 515 174 503 174 503 161 486 161 -outline {} -tags {floor1 room}]
472472 set floorLabels($i) 130
473473 set {floorItems(130)} $i
474474 $w create text 638.5 205 -text 130 -fill $color -anchor c -tags {floor1 label}
475 set i [$w create polygon 308 242 339 242 339 248 342 248 342 246 397 246 397 276 393 276 393 309 300 309 300 248 308 248 -fill {} -tags {floor1 room}]
475 set i [$w create polygon 308 242 339 242 339 248 342 248 342 246 397 246 397 276 393 276 393 309 300 309 300 248 308 248 -outline {} -tags {floor1 room}]
476476 set floorLabels($i) 102
477477 set {floorItems(102)} $i
478478 $w create text 367.5 278.5 -text 102 -fill $color -anchor c -tags {floor1 label}
479 set i [$w create polygon 397 255 486 255 486 276 397 276 -fill {} -tags {floor1 room}]
479 set i [$w create polygon 397 255 486 255 486 276 397 276 -outline {} -tags {floor1 room}]
480480 set floorLabels($i) 128
481481 set {floorItems(128)} $i
482482 $w create text 441.5 265.5 -text 128 -fill $color -anchor c -tags {floor1 label}
483 set i [$w create polygon 510 309 486 309 486 255 530 255 552 277 561 277 561 325 510 325 -fill {} -tags {floor1 room}]
483 set i [$w create polygon 510 309 486 309 486 255 530 255 552 277 561 277 561 325 510 325 -outline {} -tags {floor1 room}]
484484 set floorLabels($i) 129
485485 set {floorItems(129)} $i
486486 $w create text 535.5 293 -text 129 -fill $color -anchor c -tags {floor1 label}
487 set i [$w create polygon 696 281 740 281 740 387 642 387 642 389 561 389 561 277 696 277 -fill {} -tags {floor1 room}]
487 set i [$w create polygon 696 281 740 281 740 387 642 387 642 389 561 389 561 277 696 277 -outline {} -tags {floor1 room}]
488488 set floorLabels($i) 133
489489 set {floorItems(133)} $i
490490 $w create text 628.5 335 -text 133 -fill $color -anchor c -tags {floor1 label}
491 set i [$w create polygon 742 387 742 281 800 281 800 387 -fill {} -tags {floor1 room}]
491 set i [$w create polygon 742 387 742 281 800 281 800 387 -outline {} -tags {floor1 room}]
492492 set floorLabels($i) 132
493493 set {floorItems(132)} $i
494494 $w create text 771 334 -text 132 -fill $color -anchor c -tags {floor1 label}
495 set i [$w create polygon 800 168 800 280 699 280 699 168 -fill {} -tags {floor1 room}]
495 set i [$w create polygon 800 168 800 280 699 280 699 168 -outline {} -tags {floor1 room}]
496496 set floorLabels($i) 134
497497 set {floorItems(134)} $i
498498 $w create text 749.5 224 -text 134 -fill $color -anchor c -tags {floor1 label}
499 set i [$w create polygon 726 131 726 166 800 166 800 131 -fill {} -tags {floor1 room}]
499 set i [$w create polygon 726 131 726 166 800 166 800 131 -outline {} -tags {floor1 room}]
500500 set floorLabels($i) 135
501501 set {floorItems(135)} $i
502502 $w create text 763 148.5 -text 135 -fill $color -anchor c -tags {floor1 label}
503 set i [$w create polygon 340 360 335 363 331 365 326 366 304 366 304 312 396 312 396 288 400 288 404 288 409 290 413 292 418 297 421 302 422 309 421 318 417 325 411 330 405 332 397 333 344 333 340 334 336 336 335 338 332 342 331 347 332 351 334 354 336 357 341 359 -fill {} -tags {floor1 room}]
503 set i [$w create polygon 340 360 335 363 331 365 326 366 304 366 304 312 396 312 396 288 400 288 404 288 409 290 413 292 418 297 421 302 422 309 421 318 417 325 411 330 405 332 397 333 344 333 340 334 336 336 335 338 332 342 331 347 332 351 334 354 336 357 341 359 -outline {} -tags {floor1 room}]
504504 set floorLabels($i) {Ramona Stair}
505505 set {floorItems(Ramona Stair)} $i
506506 $w create text 368 323 -text {Ramona Stair} -fill $color -anchor c -tags {floor1 label}
507 set i [$w create polygon 30 23 30 5 93 5 98 5 104 7 110 10 116 16 119 20 122 28 123 32 123 68 220 68 220 87 90 87 90 23 -fill {} -tags {floor1 room}]
507 set i [$w create polygon 30 23 30 5 93 5 98 5 104 7 110 10 116 16 119 20 122 28 123 32 123 68 220 68 220 87 90 87 90 23 -outline {} -tags {floor1 room}]
508508 set floorLabels($i) {University Stair}
509509 set {floorItems(University Stair)} $i
510510 $w create text 155 77.5 -text {University Stair} -fill $color -anchor c -tags {floor1 label}
511 set i [$w create polygon 282 37 295 40 312 49 323 56 337 70 352 56 358 48 363 39 365 29 348 25 335 22 321 14 300 5 283 1 260 0 246 0 242 2 236 4 231 8 227 13 223 17 221 22 220 34 260 34 -fill {} -tags {floor1 room}]
511 set i [$w create polygon 282 37 295 40 312 49 323 56 337 70 352 56 358 48 363 39 365 29 348 25 335 22 321 14 300 5 283 1 260 0 246 0 242 2 236 4 231 8 227 13 223 17 221 22 220 34 260 34 -outline {} -tags {floor1 room}]
512512 set floorLabels($i) {Plaza Stair}
513513 set {floorItems(Plaza Stair)} $i
514514 $w create text 317.5 28.5 -text {Plaza Stair} -fill $color -anchor c -tags {floor1 label}
515 set i [$w create polygon 220 34 260 34 282 37 295 40 312 49 323 56 337 70 350 83 365 94 377 100 386 104 386 128 220 128 -fill {} -tags {floor1 room}]
515 set i [$w create polygon 220 34 260 34 282 37 295 40 312 49 323 56 337 70 350 83 365 94 377 100 386 104 386 128 220 128 -outline {} -tags {floor1 room}]
516516 set floorLabels($i) {Plaza Deck}
517517 set {floorItems(Plaza Deck)} $i
518518 $w create text 303 81 -text {Plaza Deck} -fill $color -anchor c -tags {floor1 label}
519 set i [$w create polygon 257 336 77 336 6 336 6 301 77 301 77 310 257 310 -fill {} -tags {floor1 room}]
519 set i [$w create polygon 257 336 77 336 6 336 6 301 77 301 77 310 257 310 -outline {} -tags {floor1 room}]
520520 set floorLabels($i) 106
521521 set {floorItems(106)} $i
522522 $w create text 131.5 318.5 -text 106 -fill $color -anchor c -tags {floor1 label}
523 set i [$w create polygon 146 110 162 110 162 91 130 91 130 115 95 115 95 128 114 128 114 151 157 151 157 153 112 153 112 130 97 130 97 168 175 168 175 131 146 131 -fill {} -tags {floor1 room}]
523 set i [$w create polygon 146 110 162 110 162 91 130 91 130 115 95 115 95 128 114 128 114 151 157 151 157 153 112 153 112 130 97 130 97 168 175 168 175 131 146 131 -outline {} -tags {floor1 room}]
524524 set floorLabels($i) 119
525525 set {floorItems(119)} $i
526526 $w create text 143.5 133 -text 119 -fill $color -anchor c -tags {floor1 label}
695695
696696 proc fg2 {w color} {
697697 global floorLabels floorItems
698 set i [$w create polygon 748 188 755 188 755 205 758 205 758 222 800 222 800 168 748 168 -fill {} -tags {floor2 room}]
698 set i [$w create polygon 748 188 755 188 755 205 758 205 758 222 800 222 800 168 748 168 -outline {} -tags {floor2 room}]
699699 set floorLabels($i) 238
700700 set {floorItems(238)} $i
701701 $w create text 774 195 -text 238 -fill $color -anchor c -tags {floor2 label}
702 set i [$w create polygon 726 188 746 188 746 166 800 166 800 131 726 131 -fill {} -tags {floor2 room}]
702 set i [$w create polygon 726 188 746 188 746 166 800 166 800 131 726 131 -outline {} -tags {floor2 room}]
703703 set floorLabels($i) 237
704704 set {floorItems(237)} $i
705705 $w create text 763 148.5 -text 237 -fill $color -anchor c -tags {floor2 label}
706 set i [$w create polygon 497 187 497 204 559 204 559 324 641 324 643 324 643 291 641 291 641 205 696 205 696 291 694 291 694 314 715 314 715 291 715 205 755 205 755 190 724 190 724 187 -fill {} -tags {floor2 room}]
706 set i [$w create polygon 497 187 497 204 559 204 559 324 641 324 643 324 643 291 641 291 641 205 696 205 696 291 694 291 694 314 715 314 715 291 715 205 755 205 755 190 724 190 724 187 -outline {} -tags {floor2 room}]
707707 set floorLabels($i) 246
708708 set {floorItems(246)} $i
709709 $w create text 600 264 -text 246 -fill $color -anchor c -tags {floor2 label}
710 set i [$w create polygon 694 279 643 279 643 314 694 314 -fill {} -tags {floor2 room}]
710 set i [$w create polygon 694 279 643 279 643 314 694 314 -outline {} -tags {floor2 room}]
711711 set floorLabels($i) 247
712712 set {floorItems(247)} $i
713713 $w create text 668.5 296.5 -text 247 -fill $color -anchor c -tags {floor2 label}
714 set i [$w create polygon 232 250 308 250 308 242 339 242 339 246 397 246 397 255 476 255 476 250 482 250 559 250 559 274 482 274 482 278 396 278 396 274 232 274 -fill {} -tags {floor2 room}]
714 set i [$w create polygon 232 250 308 250 308 242 339 242 339 246 397 246 397 255 476 255 476 250 482 250 559 250 559 274 482 274 482 278 396 278 396 274 232 274 -outline {} -tags {floor2 room}]
715715 set floorLabels($i) 202
716716 set {floorItems(202)} $i
717717 $w create text 285.5 260 -text 202 -fill $color -anchor c -tags {floor2 label}
718 set i [$w create polygon 53 228 53 338 176 338 233 338 233 196 306 196 306 180 175 180 175 169 156 169 156 196 176 196 176 228 -fill {} -tags {floor2 room}]
718 set i [$w create polygon 53 228 53 338 176 338 233 338 233 196 306 196 306 180 175 180 175 169 156 169 156 196 176 196 176 228 -outline {} -tags {floor2 room}]
719719 set floorLabels($i) 206
720720 set {floorItems(206)} $i
721721 $w create text 143 267 -text 206 -fill $color -anchor c -tags {floor2 label}
722 set i [$w create polygon 51 277 6 277 6 338 51 338 -fill {} -tags {floor2 room}]
722 set i [$w create polygon 51 277 6 277 6 338 51 338 -outline {} -tags {floor2 room}]
723723 set floorLabels($i) 212
724724 set {floorItems(212)} $i
725725 $w create text 28.5 307.5 -text 212 -fill $color -anchor c -tags {floor2 label}
726 set i [$w create polygon 557 276 486 276 486 309 510 309 510 325 557 325 -fill {} -tags {floor2 room}]
726 set i [$w create polygon 557 276 486 276 486 309 510 309 510 325 557 325 -outline {} -tags {floor2 room}]
727727 set floorLabels($i) 245
728728 set {floorItems(245)} $i
729729 $w create text 521.5 300.5 -text 245 -fill $color -anchor c -tags {floor2 label}
730 set i [$w create polygon 560 389 599 389 599 326 560 326 -fill {} -tags {floor2 room}]
730 set i [$w create polygon 560 389 599 389 599 326 560 326 -outline {} -tags {floor2 room}]
731731 set floorLabels($i) 244
732732 set {floorItems(244)} $i
733733 $w create text 579.5 357.5 -text 244 -fill $color -anchor c -tags {floor2 label}
734 set i [$w create polygon 601 389 601 326 643 326 643 389 -fill {} -tags {floor2 room}]
734 set i [$w create polygon 601 389 601 326 643 326 643 389 -outline {} -tags {floor2 room}]
735735 set floorLabels($i) 243
736736 set {floorItems(243)} $i
737737 $w create text 622 357.5 -text 243 -fill $color -anchor c -tags {floor2 label}
738 set i [$w create polygon 688 316 645 316 645 365 688 365 -fill {} -tags {floor2 room}]
738 set i [$w create polygon 688 316 645 316 645 365 688 365 -outline {} -tags {floor2 room}]
739739 set floorLabels($i) 242
740740 set {floorItems(242)} $i
741741 $w create text 666.5 340.5 -text 242 -fill $color -anchor c -tags {floor2 label}
742 set i [$w create polygon 802 367 759 367 759 226 802 226 -fill {} -tags {floor2 room}]
742 set i [$w create polygon 802 367 759 367 759 226 802 226 -outline {} -tags {floor2 room}]
743743 set floorLabels($i) {Barbecue Deck}
744744 set {floorItems(Barbecue Deck)} $i
745745 $w create text 780.5 296.5 -text {Barbecue Deck} -fill $color -anchor c -tags {floor2 label}
746 set i [$w create polygon 755 262 755 314 717 314 717 262 -fill {} -tags {floor2 room}]
746 set i [$w create polygon 755 262 755 314 717 314 717 262 -outline {} -tags {floor2 room}]
747747 set floorLabels($i) 240
748748 set {floorItems(240)} $i
749749 $w create text 736 288 -text 240 -fill $color -anchor c -tags {floor2 label}
750 set i [$w create polygon 755 316 689 316 689 365 755 365 -fill {} -tags {floor2 room}]
750 set i [$w create polygon 755 316 689 316 689 365 755 365 -outline {} -tags {floor2 room}]
751751 set floorLabels($i) 241
752752 set {floorItems(241)} $i
753753 $w create text 722 340.5 -text 241 -fill $color -anchor c -tags {floor2 label}
754 set i [$w create polygon 755 206 717 206 717 261 755 261 -fill {} -tags {floor2 room}]
754 set i [$w create polygon 755 206 717 206 717 261 755 261 -outline {} -tags {floor2 room}]
755755 set floorLabels($i) 239
756756 set {floorItems(239)} $i
757757 $w create text 736 233.5 -text 239 -fill $color -anchor c -tags {floor2 label}
758 set i [$w create polygon 695 277 643 277 643 206 695 206 -fill {} -tags {floor2 room}]
758 set i [$w create polygon 695 277 643 277 643 206 695 206 -outline {} -tags {floor2 room}]
759759 set floorLabels($i) 248
760760 set {floorItems(248)} $i
761761 $w create text 669 241.5 -text 248 -fill $color -anchor c -tags {floor2 label}
762 set i [$w create polygon 676 135 676 185 724 185 724 135 -fill {} -tags {floor2 room}]
762 set i [$w create polygon 676 135 676 185 724 185 724 135 -outline {} -tags {floor2 room}]
763763 set floorLabels($i) 236
764764 set {floorItems(236)} $i
765765 $w create text 700 160 -text 236 -fill $color -anchor c -tags {floor2 label}
766 set i [$w create polygon 675 135 635 135 635 145 628 145 628 185 675 185 -fill {} -tags {floor2 room}]
766 set i [$w create polygon 675 135 635 135 635 145 628 145 628 185 675 185 -outline {} -tags {floor2 room}]
767767 set floorLabels($i) 235
768768 set {floorItems(235)} $i
769769 $w create text 651.5 160 -text 235 -fill $color -anchor c -tags {floor2 label}
770 set i [$w create polygon 626 143 633 143 633 135 572 135 572 143 579 143 579 185 626 185 -fill {} -tags {floor2 room}]
770 set i [$w create polygon 626 143 633 143 633 135 572 135 572 143 579 143 579 185 626 185 -outline {} -tags {floor2 room}]
771771 set floorLabels($i) 234
772772 set {floorItems(234)} $i
773773 $w create text 606 160 -text 234 -fill $color -anchor c -tags {floor2 label}
774 set i [$w create polygon 557 135 571 135 571 145 578 145 578 185 527 185 527 131 557 131 -fill {} -tags {floor2 room}]
774 set i [$w create polygon 557 135 571 135 571 145 578 145 578 185 527 185 527 131 557 131 -outline {} -tags {floor2 room}]
775775 set floorLabels($i) 233
776776 set {floorItems(233)} $i
777777 $w create text 552.5 158 -text 233 -fill $color -anchor c -tags {floor2 label}
778 set i [$w create polygon 476 249 557 249 557 205 476 205 -fill {} -tags {floor2 room}]
778 set i [$w create polygon 476 249 557 249 557 205 476 205 -outline {} -tags {floor2 room}]
779779 set floorLabels($i) 230
780780 set {floorItems(230)} $i
781781 $w create text 516.5 227 -text 230 -fill $color -anchor c -tags {floor2 label}
782 set i [$w create polygon 476 164 486 164 486 131 525 131 525 185 476 185 -fill {} -tags {floor2 room}]
782 set i [$w create polygon 476 164 486 164 486 131 525 131 525 185 476 185 -outline {} -tags {floor2 room}]
783783 set floorLabels($i) 232
784784 set {floorItems(232)} $i
785785 $w create text 500.5 158 -text 232 -fill $color -anchor c -tags {floor2 label}
786 set i [$w create polygon 476 186 495 186 495 204 476 204 -fill {} -tags {floor2 room}]
786 set i [$w create polygon 476 186 495 186 495 204 476 204 -outline {} -tags {floor2 room}]
787787 set floorLabels($i) 229
788788 set {floorItems(229)} $i
789789 $w create text 485.5 195 -text 229 -fill $color -anchor c -tags {floor2 label}
790 set i [$w create polygon 474 207 409 207 409 187 399 187 399 164 474 164 -fill {} -tags {floor2 room}]
790 set i [$w create polygon 474 207 409 207 409 187 399 187 399 164 474 164 -outline {} -tags {floor2 room}]
791791 set floorLabels($i) 227
792792 set {floorItems(227)} $i
793793 $w create text 436.5 185.5 -text 227 -fill $color -anchor c -tags {floor2 label}
794 set i [$w create polygon 399 228 399 253 474 253 474 209 409 209 409 228 -fill {} -tags {floor2 room}]
794 set i [$w create polygon 399 228 399 253 474 253 474 209 409 209 409 228 -outline {} -tags {floor2 room}]
795795 set floorLabels($i) 228
796796 set {floorItems(228)} $i
797797 $w create text 436.5 231 -text 228 -fill $color -anchor c -tags {floor2 label}
798 set i [$w create polygon 397 246 397 226 407 226 407 189 377 189 377 246 -fill {} -tags {floor2 room}]
798 set i [$w create polygon 397 246 397 226 407 226 407 189 377 189 377 246 -outline {} -tags {floor2 room}]
799799 set floorLabels($i) 226
800800 set {floorItems(226)} $i
801801 $w create text 392 217.5 -text 226 -fill $color -anchor c -tags {floor2 label}
802 set i [$w create polygon 377 169 316 169 316 131 397 131 397 188 377 188 -fill {} -tags {floor2 room}]
802 set i [$w create polygon 377 169 316 169 316 131 397 131 397 188 377 188 -outline {} -tags {floor2 room}]
803803 set floorLabels($i) 225
804804 set {floorItems(225)} $i
805805 $w create text 356.5 150 -text 225 -fill $color -anchor c -tags {floor2 label}
806 set i [$w create polygon 234 198 306 198 306 249 234 249 -fill {} -tags {floor2 room}]
806 set i [$w create polygon 234 198 306 198 306 249 234 249 -outline {} -tags {floor2 room}]
807807 set floorLabels($i) 224
808808 set {floorItems(224)} $i
809809 $w create text 270 223.5 -text 224 -fill $color -anchor c -tags {floor2 label}
810 set i [$w create polygon 270 179 306 179 306 170 314 170 314 135 270 135 -fill {} -tags {floor2 room}]
810 set i [$w create polygon 270 179 306 179 306 170 314 170 314 135 270 135 -outline {} -tags {floor2 room}]
811811 set floorLabels($i) 223
812812 set {floorItems(223)} $i
813813 $w create text 292 157 -text 223 -fill $color -anchor c -tags {floor2 label}
814 set i [$w create polygon 268 179 221 179 221 135 268 135 -fill {} -tags {floor2 room}]
814 set i [$w create polygon 268 179 221 179 221 135 268 135 -outline {} -tags {floor2 room}]
815815 set floorLabels($i) 222
816816 set {floorItems(222)} $i
817817 $w create text 244.5 157 -text 222 -fill $color -anchor c -tags {floor2 label}
818 set i [$w create polygon 177 179 219 179 219 135 177 135 -fill {} -tags {floor2 room}]
818 set i [$w create polygon 177 179 219 179 219 135 177 135 -outline {} -tags {floor2 room}]
819819 set floorLabels($i) 221
820820 set {floorItems(221)} $i
821821 $w create text 198 157 -text 221 -fill $color -anchor c -tags {floor2 label}
822 set i [$w create polygon 299 327 349 327 349 284 341 284 341 276 299 276 -fill {} -tags {floor2 room}]
822 set i [$w create polygon 299 327 349 327 349 284 341 284 341 276 299 276 -outline {} -tags {floor2 room}]
823823 set floorLabels($i) 204
824824 set {floorItems(204)} $i
825825 $w create text 324 301.5 -text 204 -fill $color -anchor c -tags {floor2 label}
826 set i [$w create polygon 234 276 297 276 297 327 257 327 257 338 234 338 -fill {} -tags {floor2 room}]
826 set i [$w create polygon 234 276 297 276 297 327 257 327 257 338 234 338 -outline {} -tags {floor2 room}]
827827 set floorLabels($i) 205
828828 set {floorItems(205)} $i
829829 $w create text 265.5 307 -text 205 -fill $color -anchor c -tags {floor2 label}
830 set i [$w create polygon 256 385 256 340 212 340 212 385 -fill {} -tags {floor2 room}]
830 set i [$w create polygon 256 385 256 340 212 340 212 385 -outline {} -tags {floor2 room}]
831831 set floorLabels($i) 207
832832 set {floorItems(207)} $i
833833 $w create text 234 362.5 -text 207 -fill $color -anchor c -tags {floor2 label}
834 set i [$w create polygon 210 340 164 340 164 385 210 385 -fill {} -tags {floor2 room}]
834 set i [$w create polygon 210 340 164 340 164 385 210 385 -outline {} -tags {floor2 room}]
835835 set floorLabels($i) 208
836836 set {floorItems(208)} $i
837837 $w create text 187 362.5 -text 208 -fill $color -anchor c -tags {floor2 label}
838 set i [$w create polygon 115 340 162 340 162 385 115 385 -fill {} -tags {floor2 room}]
838 set i [$w create polygon 115 340 162 340 162 385 115 385 -outline {} -tags {floor2 room}]
839839 set floorLabels($i) 209
840840 set {floorItems(209)} $i
841841 $w create text 138.5 362.5 -text 209 -fill $color -anchor c -tags {floor2 label}
842 set i [$w create polygon 89 228 89 156 53 156 53 228 -fill {} -tags {floor2 room}]
842 set i [$w create polygon 89 228 89 156 53 156 53 228 -outline {} -tags {floor2 room}]
843843 set floorLabels($i) 217
844844 set {floorItems(217)} $i
845845 $w create text 71 192 -text 217 -fill $color -anchor c -tags {floor2 label}
846 set i [$w create polygon 89 169 97 169 97 190 89 190 -fill {} -tags {floor2 room}]
846 set i [$w create polygon 89 169 97 169 97 190 89 190 -outline {} -tags {floor2 room}]
847847 set floorLabels($i) 217A
848848 set {floorItems(217A)} $i
849849 $w create text 93 179.5 -text 217A -fill $color -anchor c -tags {floor2 label}
850 set i [$w create polygon 89 156 89 168 95 168 95 135 53 135 53 156 -fill {} -tags {floor2 room}]
850 set i [$w create polygon 89 156 89 168 95 168 95 135 53 135 53 156 -outline {} -tags {floor2 room}]
851851 set floorLabels($i) 216
852852 set {floorItems(216)} $i
853853 $w create text 71 145.5 -text 216 -fill $color -anchor c -tags {floor2 label}
854 set i [$w create polygon 51 179 51 135 6 135 6 179 -fill {} -tags {floor2 room}]
854 set i [$w create polygon 51 179 51 135 6 135 6 179 -outline {} -tags {floor2 room}]
855855 set floorLabels($i) 215
856856 set {floorItems(215)} $i
857857 $w create text 28.5 157 -text 215 -fill $color -anchor c -tags {floor2 label}
858 set i [$w create polygon 51 227 6 227 6 180 51 180 -fill {} -tags {floor2 room}]
858 set i [$w create polygon 51 227 6 227 6 180 51 180 -outline {} -tags {floor2 room}]
859859 set floorLabels($i) 214
860860 set {floorItems(214)} $i
861861 $w create text 28.5 203.5 -text 214 -fill $color -anchor c -tags {floor2 label}
862 set i [$w create polygon 51 275 6 275 6 229 51 229 -fill {} -tags {floor2 room}]
862 set i [$w create polygon 51 275 6 275 6 229 51 229 -outline {} -tags {floor2 room}]
863863 set floorLabels($i) 213
864864 set {floorItems(213)} $i
865865 $w create text 28.5 252 -text 213 -fill $color -anchor c -tags {floor2 label}
866 set i [$w create polygon 114 340 67 340 67 385 114 385 -fill {} -tags {floor2 room}]
866 set i [$w create polygon 114 340 67 340 67 385 114 385 -outline {} -tags {floor2 room}]
867867 set floorLabels($i) 210
868868 set {floorItems(210)} $i
869869 $w create text 90.5 362.5 -text 210 -fill $color -anchor c -tags {floor2 label}
870 set i [$w create polygon 59 389 59 385 65 385 65 340 1 340 1 389 -fill {} -tags {floor2 room}]
870 set i [$w create polygon 59 389 59 385 65 385 65 340 1 340 1 389 -outline {} -tags {floor2 room}]
871871 set floorLabels($i) 211
872872 set {floorItems(211)} $i
873873 $w create text 33 364.5 -text 211 -fill $color -anchor c -tags {floor2 label}
874 set i [$w create polygon 393 309 350 309 350 282 342 282 342 276 393 276 -fill {} -tags {floor2 room}]
874 set i [$w create polygon 393 309 350 309 350 282 342 282 342 276 393 276 -outline {} -tags {floor2 room}]
875875 set floorLabels($i) 203
876876 set {floorItems(203)} $i
877877 $w create text 367.5 292.5 -text 203 -fill $color -anchor c -tags {floor2 label}
878 set i [$w create polygon 99 191 91 191 91 226 174 226 174 198 154 198 154 192 109 192 109 169 99 169 -fill {} -tags {floor2 room}]
878 set i [$w create polygon 99 191 91 191 91 226 174 226 174 198 154 198 154 192 109 192 109 169 99 169 -outline {} -tags {floor2 room}]
879879 set floorLabels($i) 220
880880 set {floorItems(220)} $i
881881 $w create text 132.5 208.5 -text 220 -fill $color -anchor c -tags {floor2 label}
882 set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -tags {floor2 room}]
882 set i [$w create polygon 339 205 307 205 307 171 339 171 -outline {} -tags {floor2 room}]
883883 set floorLabels($i) {Priv Lift2}
884884 set {floorItems(Priv Lift2)} $i
885885 $w create text 323 188 -text {Priv Lift2} -fill $color -anchor c -tags {floor2 label}
886 set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -tags {floor2 room}]
886 set i [$w create polygon 307 240 339 240 339 206 307 206 -outline {} -tags {floor2 room}]
887887 set floorLabels($i) {Pub Lift 2}
888888 set {floorItems(Pub Lift 2)} $i
889889 $w create text 323 223 -text {Pub Lift 2} -fill $color -anchor c -tags {floor2 label}
890 set i [$w create polygon 175 168 97 168 97 131 175 131 -fill {} -tags {floor2 room}]
890 set i [$w create polygon 175 168 97 168 97 131 175 131 -outline {} -tags {floor2 room}]
891891 set floorLabels($i) 218
892892 set {floorItems(218)} $i
893893 $w create text 136 149.5 -text 218 -fill $color -anchor c -tags {floor2 label}
894 set i [$w create polygon 154 191 111 191 111 169 154 169 -fill {} -tags {floor2 room}]
894 set i [$w create polygon 154 191 111 191 111 169 154 169 -outline {} -tags {floor2 room}]
895895 set floorLabels($i) 219
896896 set {floorItems(219)} $i
897897 $w create text 132.5 180 -text 219 -fill $color -anchor c -tags {floor2 label}
898 set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -tags {floor2 room}]
898 set i [$w create polygon 375 246 375 172 341 172 341 246 -outline {} -tags {floor2 room}]
899899 set floorLabels($i) 201
900900 set {floorItems(201)} $i
901901 $w create text 358 209 -text 201 -fill $color -anchor c -tags {floor2 label}
10651065
10661066 proc fg3 {w color} {
10671067 global floorLabels floorItems
1068 set i [$w create polygon 89 228 89 180 70 180 70 228 -fill {} -tags {floor3 room}]
1068 set i [$w create polygon 89 228 89 180 70 180 70 228 -outline {} -tags {floor3 room}]
10691069 set floorLabels($i) 316
10701070 set {floorItems(316)} $i
10711071 $w create text 79.5 204 -text 316 -fill $color -anchor c -tags {floor3 label}
1072 set i [$w create polygon 115 368 162 368 162 323 115 323 -fill {} -tags {floor3 room}]
1072 set i [$w create polygon 115 368 162 368 162 323 115 323 -outline {} -tags {floor3 room}]
10731073 set floorLabels($i) 309
10741074 set {floorItems(309)} $i
10751075 $w create text 138.5 345.5 -text 309 -fill $color -anchor c -tags {floor3 label}
1076 set i [$w create polygon 164 323 164 368 211 368 211 323 -fill {} -tags {floor3 room}]
1076 set i [$w create polygon 164 323 164 368 211 368 211 323 -outline {} -tags {floor3 room}]
10771077 set floorLabels($i) 308
10781078 set {floorItems(308)} $i
10791079 $w create text 187.5 345.5 -text 308 -fill $color -anchor c -tags {floor3 label}
1080 set i [$w create polygon 256 368 212 368 212 323 256 323 -fill {} -tags {floor3 room}]
1080 set i [$w create polygon 256 368 212 368 212 323 256 323 -outline {} -tags {floor3 room}]
10811081 set floorLabels($i) 307
10821082 set {floorItems(307)} $i
10831083 $w create text 234 345.5 -text 307 -fill $color -anchor c -tags {floor3 label}
1084 set i [$w create polygon 244 276 297 276 297 327 260 327 260 321 244 321 -fill {} -tags {floor3 room}]
1084 set i [$w create polygon 244 276 297 276 297 327 260 327 260 321 244 321 -outline {} -tags {floor3 room}]
10851085 set floorLabels($i) 305
10861086 set {floorItems(305)} $i
10871087 $w create text 270.5 301.5 -text 305 -fill $color -anchor c -tags {floor3 label}
1088 set i [$w create polygon 251 219 251 203 244 203 244 219 -fill {} -tags {floor3 room}]
1088 set i [$w create polygon 251 219 251 203 244 203 244 219 -outline {} -tags {floor3 room}]
10891089 set floorLabels($i) 324B
10901090 set {floorItems(324B)} $i
10911091 $w create text 247.5 211 -text 324B -fill $color -anchor c -tags {floor3 label}
1092 set i [$w create polygon 251 249 244 249 244 232 251 232 -fill {} -tags {floor3 room}]
1092 set i [$w create polygon 251 249 244 249 244 232 251 232 -outline {} -tags {floor3 room}]
10931093 set floorLabels($i) 324A
10941094 set {floorItems(324A)} $i
10951095 $w create text 247.5 240.5 -text 324A -fill $color -anchor c -tags {floor3 label}
1096 set i [$w create polygon 223 135 223 179 177 179 177 135 -fill {} -tags {floor3 room}]
1096 set i [$w create polygon 223 135 223 179 177 179 177 135 -outline {} -tags {floor3 room}]
10971097 set floorLabels($i) 320
10981098 set {floorItems(320)} $i
10991099 $w create text 200 157 -text 320 -fill $color -anchor c -tags {floor3 label}
1100 set i [$w create polygon 114 368 114 323 67 323 67 368 -fill {} -tags {floor3 room}]
1100 set i [$w create polygon 114 368 114 323 67 323 67 368 -outline {} -tags {floor3 room}]
11011101 set floorLabels($i) 310
11021102 set {floorItems(310)} $i
11031103 $w create text 90.5 345.5 -text 310 -fill $color -anchor c -tags {floor3 label}
1104 set i [$w create polygon 23 277 23 321 68 321 68 277 -fill {} -tags {floor3 room}]
1104 set i [$w create polygon 23 277 23 321 68 321 68 277 -outline {} -tags {floor3 room}]
11051105 set floorLabels($i) 312
11061106 set {floorItems(312)} $i
11071107 $w create text 45.5 299 -text 312 -fill $color -anchor c -tags {floor3 label}
1108 set i [$w create polygon 23 229 68 229 68 275 23 275 -fill {} -tags {floor3 room}]
1108 set i [$w create polygon 23 229 68 229 68 275 23 275 -outline {} -tags {floor3 room}]
11091109 set floorLabels($i) 313
11101110 set {floorItems(313)} $i
11111111 $w create text 45.5 252 -text 313 -fill $color -anchor c -tags {floor3 label}
1112 set i [$w create polygon 68 227 23 227 23 180 68 180 -fill {} -tags {floor3 room}]
1112 set i [$w create polygon 68 227 23 227 23 180 68 180 -outline {} -tags {floor3 room}]
11131113 set floorLabels($i) 314
11141114 set {floorItems(314)} $i
11151115 $w create text 45.5 203.5 -text 314 -fill $color -anchor c -tags {floor3 label}
1116 set i [$w create polygon 95 179 95 135 23 135 23 179 -fill {} -tags {floor3 room}]
1116 set i [$w create polygon 95 179 95 135 23 135 23 179 -outline {} -tags {floor3 room}]
11171117 set floorLabels($i) 315
11181118 set {floorItems(315)} $i
11191119 $w create text 59 157 -text 315 -fill $color -anchor c -tags {floor3 label}
1120 set i [$w create polygon 99 226 99 204 91 204 91 226 -fill {} -tags {floor3 room}]
1120 set i [$w create polygon 99 226 99 204 91 204 91 226 -outline {} -tags {floor3 room}]
11211121 set floorLabels($i) 316B
11221122 set {floorItems(316B)} $i
11231123 $w create text 95 215 -text 316B -fill $color -anchor c -tags {floor3 label}
1124 set i [$w create polygon 91 202 99 202 99 180 91 180 -fill {} -tags {floor3 room}]
1124 set i [$w create polygon 91 202 99 202 99 180 91 180 -outline {} -tags {floor3 room}]
11251125 set floorLabels($i) 316A
11261126 set {floorItems(316A)} $i
11271127 $w create text 95 191 -text 316A -fill $color -anchor c -tags {floor3 label}
1128 set i [$w create polygon 97 169 109 169 109 192 154 192 154 198 174 198 174 226 101 226 101 179 97 179 -fill {} -tags {floor3 room}]
1128 set i [$w create polygon 97 169 109 169 109 192 154 192 154 198 174 198 174 226 101 226 101 179 97 179 -outline {} -tags {floor3 room}]
11291129 set floorLabels($i) 319
11301130 set {floorItems(319)} $i
11311131 $w create text 141.5 209 -text 319 -fill $color -anchor c -tags {floor3 label}
1132 set i [$w create polygon 65 368 58 368 58 389 1 389 1 333 23 333 23 323 65 323 -fill {} -tags {floor3 room}]
1132 set i [$w create polygon 65 368 58 368 58 389 1 389 1 333 23 333 23 323 65 323 -outline {} -tags {floor3 room}]
11331133 set floorLabels($i) 311
11341134 set {floorItems(311)} $i
11351135 $w create text 29.5 361 -text 311 -fill $color -anchor c -tags {floor3 label}
1136 set i [$w create polygon 154 191 111 191 111 169 154 169 -fill {} -tags {floor3 room}]
1136 set i [$w create polygon 154 191 111 191 111 169 154 169 -outline {} -tags {floor3 room}]
11371137 set floorLabels($i) 318
11381138 set {floorItems(318)} $i
11391139 $w create text 132.5 180 -text 318 -fill $color -anchor c -tags {floor3 label}
1140 set i [$w create polygon 175 168 97 168 97 131 175 131 -fill {} -tags {floor3 room}]
1140 set i [$w create polygon 175 168 97 168 97 131 175 131 -outline {} -tags {floor3 room}]
11411141 set floorLabels($i) 317
11421142 set {floorItems(317)} $i
11431143 $w create text 136 149.5 -text 317 -fill $color -anchor c -tags {floor3 label}
1144 set i [$w create polygon 274 194 274 221 306 221 306 194 -fill {} -tags {floor3 room}]
1144 set i [$w create polygon 274 194 274 221 306 221 306 194 -outline {} -tags {floor3 room}]
11451145 set floorLabels($i) 323
11461146 set {floorItems(323)} $i
11471147 $w create text 290 207.5 -text 323 -fill $color -anchor c -tags {floor3 label}
1148 set i [$w create polygon 306 222 274 222 274 249 306 249 -fill {} -tags {floor3 room}]
1148 set i [$w create polygon 306 222 274 222 274 249 306 249 -outline {} -tags {floor3 room}]
11491149 set floorLabels($i) 325
11501150 set {floorItems(325)} $i
11511151 $w create text 290 235.5 -text 325 -fill $color -anchor c -tags {floor3 label}
1152 set i [$w create polygon 263 179 224 179 224 135 263 135 -fill {} -tags {floor3 room}]
1152 set i [$w create polygon 263 179 224 179 224 135 263 135 -outline {} -tags {floor3 room}]
11531153 set floorLabels($i) 321
11541154 set {floorItems(321)} $i
11551155 $w create text 243.5 157 -text 321 -fill $color -anchor c -tags {floor3 label}
1156 set i [$w create polygon 314 169 306 169 306 192 273 192 264 181 264 135 314 135 -fill {} -tags {floor3 room}]
1156 set i [$w create polygon 314 169 306 169 306 192 273 192 264 181 264 135 314 135 -outline {} -tags {floor3 room}]
11571157 set floorLabels($i) 322
11581158 set {floorItems(322)} $i
11591159 $w create text 293.5 163.5 -text 322 -fill $color -anchor c -tags {floor3 label}
1160 set i [$w create polygon 307 240 339 240 339 206 307 206 -fill {} -tags {floor3 room}]
1160 set i [$w create polygon 307 240 339 240 339 206 307 206 -outline {} -tags {floor3 room}]
11611161 set floorLabels($i) {Pub Lift3}
11621162 set {floorItems(Pub Lift3)} $i
11631163 $w create text 323 223 -text {Pub Lift3} -fill $color -anchor c -tags {floor3 label}
1164 set i [$w create polygon 339 205 307 205 307 171 339 171 -fill {} -tags {floor3 room}]
1164 set i [$w create polygon 339 205 307 205 307 171 339 171 -outline {} -tags {floor3 room}]
11651165 set floorLabels($i) {Priv Lift3}
11661166 set {floorItems(Priv Lift3)} $i
11671167 $w create text 323 188 -text {Priv Lift3} -fill $color -anchor c -tags {floor3 label}
1168 set i [$w create polygon 350 284 376 284 376 276 397 276 397 309 350 309 -fill {} -tags {floor3 room}]
1168 set i [$w create polygon 350 284 376 284 376 276 397 276 397 309 350 309 -outline {} -tags {floor3 room}]
11691169 set floorLabels($i) 303
11701170 set {floorItems(303)} $i
11711171 $w create text 373.5 292.5 -text 303 -fill $color -anchor c -tags {floor3 label}
1172 set i [$w create polygon 272 203 272 249 252 249 252 230 244 230 244 221 252 221 252 203 -fill {} -tags {floor3 room}]
1172 set i [$w create polygon 272 203 272 249 252 249 252 230 244 230 244 221 252 221 252 203 -outline {} -tags {floor3 room}]
11731173 set floorLabels($i) 324
11741174 set {floorItems(324)} $i
11751175 $w create text 262 226 -text 324 -fill $color -anchor c -tags {floor3 label}
1176 set i [$w create polygon 299 276 299 327 349 327 349 284 341 284 341 276 -fill {} -tags {floor3 room}]
1176 set i [$w create polygon 299 276 299 327 349 327 349 284 341 284 341 276 -outline {} -tags {floor3 room}]
11771177 set floorLabels($i) 304
11781178 set {floorItems(304)} $i
11791179 $w create text 324 301.5 -text 304 -fill $color -anchor c -tags {floor3 label}
1180 set i [$w create polygon 375 246 375 172 341 172 341 246 -fill {} -tags {floor3 room}]
1180 set i [$w create polygon 375 246 375 172 341 172 341 246 -outline {} -tags {floor3 room}]
11811181 set floorLabels($i) 301
11821182 set {floorItems(301)} $i
11831183 $w create text 358 209 -text 301 -fill $color -anchor c -tags {floor3 label}
1184 set i [$w create polygon 397 246 377 246 377 185 397 185 -fill {} -tags {floor3 room}]
1184 set i [$w create polygon 397 246 377 246 377 185 397 185 -outline {} -tags {floor3 room}]
11851185 set floorLabels($i) 327
11861186 set {floorItems(327)} $i
11871187 $w create text 387 215.5 -text 327 -fill $color -anchor c -tags {floor3 label}
1188 set i [$w create polygon 316 131 316 169 377 169 377 185 397 185 397 131 -fill {} -tags {floor3 room}]
1188 set i [$w create polygon 316 131 316 169 377 169 377 185 397 185 397 131 -outline {} -tags {floor3 room}]
11891189 set floorLabels($i) 326
11901190 set {floorItems(326)} $i
11911191 $w create text 356.5 150 -text 326 -fill $color -anchor c -tags {floor3 label}
1192 set i [$w create polygon 308 251 242 251 242 274 342 274 342 282 375 282 375 274 397 274 397 248 339 248 339 242 308 242 -fill {} -tags {floor3 room}]
1192 set i [$w create polygon 308 251 242 251 242 274 342 274 342 282 375 282 375 274 397 274 397 248 339 248 339 242 308 242 -outline {} -tags {floor3 room}]
11931193 set floorLabels($i) 302
11941194 set {floorItems(302)} $i
11951195 $w create text 319.5 261 -text 302 -fill $color -anchor c -tags {floor3 label}
1196 set i [$w create polygon 70 321 242 321 242 200 259 200 259 203 272 203 272 193 263 180 242 180 175 180 175 169 156 169 156 196 177 196 177 228 107 228 70 228 70 275 107 275 107 248 160 248 160 301 107 301 107 275 70 275 -fill {} -tags {floor3 room}]
1196 set i [$w create polygon 70 321 242 321 242 200 259 200 259 203 272 203 272 193 263 180 242 180 175 180 175 169 156 169 156 196 177 196 177 228 107 228 70 228 70 275 107 275 107 248 160 248 160 301 107 301 107 275 70 275 -outline {} -tags {floor3 room}]
11971197 set floorLabels($i) 306
11981198 set {floorItems(306)} $i
11991199 $w create text 200.5 284.5 -text 306 -fill $color -anchor c -tags {floor3 label}
9494 $c create text 25c .2c -text Polygons -anchor n
9595 $c create polygon 21c 1.0c 22.5c 1.75c 24c 1.0c 23.25c 2.5c \
9696 24c 4.0c 22.5c 3.25c 21c 4.0c 21.75c 2.5c -fill $green \
97 -outline black -width 4 -tags item
97 -outline {} -width 4 -tags item
9898 $c create polygon 25c 4c 25c 4c 25c 1c 26c 1c 27c 4c 28c 1c \
99 29c 1c 29c 4c 29c 4c -fill $red -smooth on -tags item
99 29c 1c 29c 4c 29c 4c -fill $red -outline {} -smooth on -tags item
100100 $c create polygon 22c 4.5c 25c 4.5c 25c 6.75c 28c 6.75c \
101101 28c 5.25c 24c 5.25c 24c 6.0c 26c 6c 26c 7.5c 22c 7.5c \
102102 -stipple @[file join $tk_demoDirectory images gray25.xbm] \
103 -outline black -tags item
103 -fill $blue -outline {} -tags item
104104
105105 $c create text 5c 8.2c -text Rectangles -anchor n
106106 $c create rectangle 1c 9.5c 4c 12.5c -outline $red -width 3m -tags item
125125 -text "Several lines,\n each centered\nindividually,\nand all anchored\nat the left edge." \
126126 -justify center -tags item
127127 $c create rectangle 24.9c 13.9c 25.1c 14.1c
128 catch {
128129 $c create text 25c 14c -font $font2 -anchor c -fill $red -angle 15 \
129130 -text "Angled characters" -tags item
131 }
130132
131133 $c create text 5c 16.2c -text Arcs -anchor n
132134 $c create arc 0.5c 17c 7c 20c -fill $green -outline black \
139141 $c create arc 5.5c 20.5c 9.5c 23.5c -width 4m -style chord \
140142 -fill $blue -outline {} -start 45 -extent 270 -tags item
141143
144 $c create text 15c 16.2c -text "Bitmaps and Images" -anchor n
145 catch {
142146 image create photo items.ousterhout \
143147 -file [file join $tk_demoDirectory images ouster.png]
144148 image create photo items.ousterhout.active -format "png -alpha 0.5" \
145149 -file [file join $tk_demoDirectory images ouster.png]
146 $c create text 15c 16.2c -text "Bitmaps and Images" -anchor n
147150 $c create image 13c 20c -tags item -image items.ousterhout \
148151 -activeimage items.ousterhout.active
152 }
149153 $c create bitmap 17c 18.5c -tags item \
150154 -bitmap @[file join $tk_demoDirectory images noletter.xbm]
151155 $c create bitmap 17c 21.5c -tags item \
174174 wm withdraw $dlg
175175 set f [ttk::frame $dlg.f]
176176 set c [canvas $f.c -width 240 -height 240]
177 text $f.txt -width 10 -height 1 -background white \
177 text $f.txt -width 10 -height 1 \
178178 -yscrollcommand [list $f.vs set] -font {Arial 8}
179179 ttk::scrollbar $f.vs -command [list $f.txt yview]
180180
199199 set coords [list [expr {$col * 30 + 4}] [expr {$row * 30 + 4}] \
200200 [expr {$col * 30 + 30}] [expr {$row * 30 + 30}]]
201201 $c create rectangle $coords -fill $fill -disabledfill $dfill \
202 -width 2 -state disabled
202 -width 2 -state disabled -outline black
203203 }
204204 }
205205 if {[tk windowingsystem] ne "x11"} {
2525 panedwindow $w.pane
2626 pack $w.pane -side top -expand yes -fill both -pady 2 -padx 2m
2727
28 label $w.pane.left -text "This is the\nleft side" -bg yellow
29 label $w.pane.right -text "This is the\nright side" -bg cyan
28 label $w.pane.left -text "This is the\nleft side" -fg black -bg yellow
29 label $w.pane.right -text "This is the\nright side" -fg black -bg cyan
3030
3131 $w.pane add $w.pane.left $w.pane.right
125125 }
126126 bind $w.c <Configure> {
127127 %W coords plate 0 25 %w 25
128 set home [expr %w/2]
129 %W coords pivot [expr $home-5] 20 [expr $home+5] 30
128 set home [expr {%w/2}]
129 %W coords pivot [expr {$home-5}] 20 [expr {$home+5}] 30
130130 }
131131 bind $w.k <Configure> {
132 set psh [expr %h/2]
133 set psw [expr %w/2]
134 %W coords x_axis 2 $psh [expr %w-2] $psh
135 %W coords y_axis $psw [expr %h-2] $psw 2
136 %W coords label_dtheta [expr $psw-4] 6
137 %W coords label_theta [expr %w-6] [expr $psh+4]
132 set psh [expr {%h/2}]
133 set psw [expr {%w/2}]
134 %W coords x_axis 2 $psh [expr {%w-2}] $psh
135 %W coords y_axis $psw [expr {%h-2}] $psw 2
136 %W coords label_dtheta [expr {$psw-4}] 6
137 %W coords label_theta [expr {%w-6}] [expr {$psh+4}]
138138 }
139139
140140 # This procedure is the "business" part of the simulation that does
7272 set num [lindex $order $i]
7373 set xpos($num) [expr {($i%4)*.25}]
7474 set ypos($num) [expr {($i/4)*.25}]
75 button $w.frame.$num -relief raised -text $num -highlightthickness 0 \
75 button $w.frame.$num -relief raised -text $num -bd 0 -highlightthickness 0 \
7676 -command "puzzleSwitch $w $num"
7777 place $w.frame.$num -relx $xpos($num) -rely $ypos($num) \
7878 -relwidth .25 -relheight .25
1818
1919 proc rulerMkTab {c x y} {
2020 upvar #0 demo_rulerInfo v
21 $c create polygon $x $y [expr {$x+$v(size)}] [expr {$y+$v(size)}] \
22 [expr {$x-$v(size)}] [expr {$y+$v(size)}]
21 set newTab [$c create polygon $x $y \
22 [expr {$x+$v(size)}] [expr {$y+$v(size)}] \
23 [expr {$x-$v(size)}] [expr {$y+$v(size)}]]
24 set fill [$c itemcget $newTab -outline]
25 $c itemconfigure $newTab -fill $fill -outline {}
26 set v(normalStyle) "-fill $fill"
27 return $newTab
2328 }
2429
2530 set w .ruler
4651 set demo_rulerInfo(top) [winfo fpixels $c 1c]
4752 set demo_rulerInfo(bottom) [winfo fpixels $c 1.5c]
4853 set demo_rulerInfo(size) [winfo fpixels $c .2c]
49 set demo_rulerInfo(normalStyle) "-fill black"
5054 # Main widget program sets variable tk_demoDirectory
5155 if {[winfo depth $c] > 1} {
5256 set demo_rulerInfo(activeStyle) "-fill red -stipple {}"
6872 $c create text $x.15c .75c -text $i -anchor sw
6973 }
7074 $c addtag well withtag [$c create rect 13.2c 1c 13.8c 0.5c \
71 -outline black -fill [lindex [$c config -bg] 4]]
75 -fill [lindex [$c config -bg] 4]]
7276 $c addtag well withtag [rulerMkTab $c [winfo pixels $c 13.5c] \
7377 [winfo pixels $c .65c]]
7478
2626
2727 proc center {x y} {
2828 set a [.s size]
29 .s position [expr $x-($a/2)] [expr $y-($a/2)]
29 .s position [expr {$x-($a/2)}] [expr {$y-($a/2)}]
3030 }
3131
3232 # The procedures below provide a simple form of animation where
3030 ttk::frame $t.tearoff -cursor fleur
3131 ttk::separator $t.tearoff.to -orient vertical
3232 ttk::separator $t.tearoff.to2 -orient vertical
33 pack $t.tearoff.to -fill y -expand 1 -padx 2 -side left
33 pack $t.tearoff.to -fill y -expand 1 -padx 4 -side left
3434 pack $t.tearoff.to2 -fill y -expand 1 -side left
3535 ttk::frame $t.contents
3636 grid $t.tearoff $t.contents -sticky nsew
7878 interp alias {} doInsert {} $w.txt insert end ;# Make bindings easy to write
7979
8080 ## Arrange contents
81 grid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 2 -sticky ns
81 grid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 2 -pady 4 -sticky ns
8282 grid $t -sticky ew
8383 grid $w.sep -sticky ew
8484 grid $w.msg -sticky ew
7474 ttk::scrollbar $w.hsb -orient horizontal -command "$w.tree xview"
7575 $w.tree heading \#0 -text "Directory Structure"
7676 $w.tree heading size -text "File Size"
77 $w.tree column size -stretch 0 -width 70
77 $w.tree column size -width 70
7878 populateRoots $w.tree
7979 bind $w.tree <<TreeviewOpen>> {populateTree %W [%W focus]}
8080
2020 pack $w.msg -side top -fill x
2121
2222 ## See Code / Dismiss
23 pack [addSeeDismiss $w.seeDismiss $w {enabled cheese tomato basil oregano happyness}]\
23 pack [addSeeDismiss $w.seeDismiss $w {enabled cheese tomato basil oregano happiness}]\
2424 -side bottom -fill x
2525
2626 ## Add buttons for setting the theme
6868
6969 ## Set up the radiobutton group
7070 ttk::labelframe $w.radios -text "Radiobuttons"
71 ttk::radiobutton $w.radios.r1 -text "Great" -variable happyness -value great
72 ttk::radiobutton $w.radios.r2 -text "Good" -variable happyness -value good
73 ttk::radiobutton $w.radios.r3 -text "OK" -variable happyness -value ok
74 ttk::radiobutton $w.radios.r4 -text "Poor" -variable happyness -value poor
75 ttk::radiobutton $w.radios.r5 -text "Awful" -variable happyness -value awful
71 ttk::radiobutton $w.radios.r1 -text "Great" -variable happiness -value great
72 ttk::radiobutton $w.radios.r2 -text "Good" -variable happiness -value good
73 ttk::radiobutton $w.radios.r3 -text "OK" -variable happiness -value ok
74 ttk::radiobutton $w.radios.r4 -text "Poor" -variable happiness -value poor
75 ttk::radiobutton $w.radios.r5 -text "Awful" -variable happiness -value awful
7676 pack $w.radios.r1 $w.radios.r2 $w.radios.r3 $w.radios.r4 $w.radios.r5 \
7777 -fill x -padx 3 -pady 2
7878
103103 pack $w.outer -fill both -expand 1
104104 } else {
105105 text $w.txt -wrap word -yscroll "$w.sb set" -width 30 -borderwidth 0
106 scrollbar $w.sb -orient vertical -command "$w.txt yview"
106 ttk::scrollbar $w.sb -orient vertical -command "$w.txt yview"
107107 pack $w.sb -side right -fill y -in $w.outer.inRight.bot
108108 pack $w.txt -fill both -expand 1 -in $w.outer.inRight.bot
109109 pack $w.outer -fill both -expand 1 -padx 10 -pady {6 10}
77 }
88
99 package require Tk
10
11 # Make an Aqua button's fill color match its parent's background
12 proc blend {bt} {
13 if {[tk windowingsystem] eq "aqua"} {
14 $bt configure -highlightbackground [[winfo parent $bt] cget -background]
15 }
16 return $bt
17 }
1018
1119 set w .twind
1220 catch {destroy $w}
5260 $t insert end "and they can consist of arbitrary widgets. "
5361 $t insert end "For example, here are two embedded button "
5462 $t insert end "widgets. You can click on the first button to "
55 $t window create end -window $t.on
63 $t window create end -window [blend $t.on]
5664 $t insert end " horizontal scrolling, which also turns off "
5765 $t insert end "word wrapping. Or, you can click on the second "
5866 $t insert end "button to\n"
59 $t window create end -window $t.off
67 $t window create end -window [blend $t.off]
6068 $t insert end " horizontal scrolling and turn back on word wrapping.\n\n"
6169
6270 $t insert end "Or, here is another example. If you "
6371 $t window create end -create {
6472 button %W.click -text "Click Here" -command "textWindPlot %W" \
65 -cursor top_left_arrow}
73 -cursor top_left_arrow
74 blend %W.click
75 }
6676
6777 $t insert end " a canvas displaying an x-y plot will appear right here."
6878 $t mark set plot insert
7181 $t insert end "or you can click here to "
7282 $t window create end -create {
7383 button %W.delete -text "Delete" -command "textWindDel %W" \
74 -cursor top_left_arrow
84 -cursor top_left_arrow
85 blend %W.delete
7586 }
7687 $t insert end " the plot again.\n\n"
7788
7990 $t insert end "display the same underlying text. Click this button to "
8091 $t window create end \
8192 -create {button %W.peer -text "Make A Peer" -command "textMakePeer %W" \
82 -cursor top_left_arrow} -padx 3
93 -cursor top_left_arrow
94 blend %W.peer} -padx 3
8395 $t insert end " widget. Notice how peer widgets can have different "
8496 $t insert end "font settings, and by default contain all the images "
8597 $t insert end "of the 'parent', but that the embedded windows, "
91103 $t insert end "peers is for "
92104 $t window create end \
93105 -create {button %W.split -text "Split Windows" -command "textSplitWindow %W" \
94 -cursor top_left_arrow} -padx 3
106 -cursor top_left_arrow
107 blend %W.split} -padx 3
95108 $t insert end " \n\n"
96109
97110 $t insert end "Users of previous versions of Tk will also be interested "
127140 DarkSlateGray1 Aquamarine2 DarkSeaGreen2 SeaGreen1
128141 Yellow1 IndianRed1 IndianRed2 Tan1 Tan4} {
129142 button $t.color$i -text $color -cursor top_left_arrow -command \
130 "$t configure -bg $color"
131 $t window create end -window $t.color$i -padx 3 -pady 2
143 "changeBg $t $color"
144 $t window create end -window [blend $t.color$i] -padx 3 -pady 2
132145 incr i
133146 }
134 $t tag add buttons $t.default end
147 $t tag add buttons [blend $t.default] end
135148
136149 button $t.bigB -text "Big borders" -command "textWindBigB $t" \
137150 -cursor top_left_arrow
152165
153166 $t insert end "\nYou can also change the usual border width and "
154167 $t insert end "highlightthickness and padding.\n"
155 $t window create end -window $t.bigB
156 $t window create end -window $t.smallB
157 $t window create end -window $t.bigH
158 $t window create end -window $t.smallH
159 $t window create end -window $t.bigP
160 $t window create end -window $t.smallP
168 $t window create end -window [blend $t.bigB]
169 $t window create end -window [blend $t.smallB]
170 $t window create end -window [blend $t.bigH]
171 $t window create end -window [blend $t.smallH]
172 $t window create end -window [blend $t.bigP]
173 $t window create end -window [blend $t.smallP]
161174
162175 $t insert end "\n\nFinally, images fit comfortably in text widgets too:"
163176
187200 proc textWindSmallP w {
188201 $w configure -padx $::text_normal(pad) -pady $::text_normal(pad)
189202 }
190
191203
192204 proc textWindOn w {
193205 catch {destroy $w.scroll2}
289301 }
290302 }
291303
304 proc changeBg {t c} {
305 $t configure -background $c
306 if {[tk windowingsystem] eq "aqua"} {
307 foreach b [$t window names] {
308 if {[winfo class $b] eq "Button"} {
309 $b configure -highlightbackground $c
310 }
311 }
312 }
313 }
314
292315 proc embDefBg t {
293 $t configure -background [lindex [$t configure -background] 3]
316 set bg [lindex [$t configure -background] 3]
317 changeBg $t $bg
294318 }
295319
296320 proc textMakePeer {parent} {
130130 addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00"
131131 addSample $w Russian \
132132 "\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A"
133 if {[tk windowingsystem] ne "x11"} {
134 addSample $w Emoji \
135 "\uD83D\uDE00\uD83D\uDCA9\uD83D\uDC4D\uD83C\uDDF3\uD83C\uDDF1"
136 }
133137
134138 ## We're done processing, so change things back to normal running...
135139 destroy $w.wait
9191 }]
9292
9393 #----------------------------------------------------------------
94 # The code below create the main window, consisting of a menu bar and a text
94 # The code below creates the main window, consisting of a menu bar and a text
9595 # widget that explains how to use the program, plus lists all of the demos as
9696 # hypertext items.
9797 #----------------------------------------------------------------
9898
9999 menu .menuBar -tearoff 0
100100
101 # On Aqua, just use the default menu.
101102 if {[tk windowingsystem] ne "aqua"} {
102103 # This is a tk-internal procedure to make i18n easier
103104 ::tk::AmpMenuArgs .menuBar add cascade -label [mc "&File"] \
117118 -command {exit} -accelerator [mc "Meta-Q"]
118119 bind . <[mc "Meta-q"]> {exit}
119120 }
120 }
121
122 . configure -menu .menuBar
121 . configure -menu .menuBar
122 }
123123
124124 ttk::frame .statusBar
125125 ttk::label .statusBar.lab -text " " -anchor w
4343 }
4444
4545 set windowingsystem [tk windowingsystem]
46 if {$windowingsystem eq "aqua"} {
47 option add *Dialog*background systemDialogBackgroundActive widgetDefault
48 option add *Dialog*Button.highlightBackground \
49 systemDialogBackgroundActive widgetDefault
50 }
5146
5247 # 1. Create the top-level window and divide it into top
5348 # and bottom parts.
269269 if {!$tk_strictMotif} {
270270 %W delete [tk::EntryPreviousWord %W insert] insert
271271 }
272 }
273
274 # Bindings for IME text input and accents.
275
276 bind Entry <<TkStartIMEMarkedText>> {
277 dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
278 }
279 bind Entry <<TkEndIMEMarkedText>> {
280 if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } {
281 bell
282 } else {
283 %W selection range $mark insert
284 }
285 }
286 bind Entry <<TkClearIMEMarkedText>> {
287 %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert]
288 }
289 bind Entry <<TkAccentBackspace>> {
290 tk::EntryBackspace %W
272291 }
273292
274293 # A few additional bindings of my own.
651670 }
652671 return $entryString
653672 }
673
674
675
676
677
678
679
680
681
445445 bind $canvas <Control-B1-Motion> {;}
446446 bind $canvas <Shift-B1-Motion> [namespace code {my ShiftMotion1 %x %y}]
447447
448 if {[tk windowingsystem] eq "aqua"} {
449 bind $canvas <Shift-MouseWheel> [namespace code {my MouseWheel [expr {40 * (%D)}]}]
450 bind $canvas <Option-Shift-MouseWheel> [namespace code {my MouseWheel [expr {400 * (%D)}]}]
451 } else {
452 bind $canvas <Shift-MouseWheel> [namespace code {my MouseWheel %D}]
453 }
454 if {[tk windowingsystem] eq "x11"} {
455 bind $canvas <Shift-4> [namespace code {my MouseWheel 120}]
456 bind $canvas <Shift-5> [namespace code {my MouseWheel -120}]
457 }
458
448459 bind $canvas <<PrevLine>> [namespace code {my UpDown -1}]
449460 bind $canvas <<NextLine>> [namespace code {my UpDown 1}]
450461 bind $canvas <<PrevChar>> [namespace code {my LeftRight -1}]
491502 # ----------------------------------------------------------------------
492503
493504 # Event handlers
505 method MouseWheel {amount} {
506 if {$noScroll || $::tk_strictMotif} {
507 return
508 }
509 if {$amount > 0} {
510 $canvas xview scroll [expr {(-119-$amount) / 120}] units
511 } else {
512 $canvas xview scroll [expr {-($amount / 120)}] units
513 }
514 }
494515 method Btn1 {x y} {
495516 focus $canvas
496517 set i [$w index @$x,$y]
181181
182182 if {[tk windowingsystem] eq "aqua"} {
183183 bind Listbox <MouseWheel> {
184 %W yview scroll [expr {- (%D)}] units
184 %W yview scroll [expr {-(%D)}] units
185185 }
186186 bind Listbox <Option-MouseWheel> {
187187 %W yview scroll [expr {-10 * (%D)}] units
188188 }
189189 bind Listbox <Shift-MouseWheel> {
190 %W xview scroll [expr {- (%D)}] units
190 %W xview scroll [expr {-(%D)}] units
191191 }
192192 bind Listbox <Shift-Option-MouseWheel> {
193193 %W xview scroll [expr {-10 * (%D)}] units
194194 }
195195 } else {
196196 bind Listbox <MouseWheel> {
197 %W yview scroll [expr {- (%D / 120) * 4}] units
197 if {%D >= 0} {
198 %W yview scroll [expr {-%D/30}] units
199 } else {
200 %W yview scroll [expr {(29-%D)/30}] units
201 }
198202 }
199203 bind Listbox <Shift-MouseWheel> {
200 %W xview scroll [expr {- (%D / 120) * 4}] units
201 }
202 }
203
204 if {"x11" eq [tk windowingsystem]} {
204 if {%D >= 0} {
205 %W xview scroll [expr {-%D/30}] units
206 } else {
207 %W xview scroll [expr {(29-%D)/30}] units
208 }
209 }
210 }
211
212 if {[tk windowingsystem] eq "x11"} {
205213 # Support for mousewheels on Linux/Unix commonly comes through mapping
206214 # the wheel to the extended buttons. If you have a mousewheel, find
207215 # Linux configuration info at:
233233 }
234234 }
235235
236
236237 # ::tk::MbPost --
237238 # Given a menubutton, this procedure does all the work of posting
238239 # its associated menu and unposting any other menu that is currently
281282 set Priv(focus) [focus]
282283 $menu activate none
283284 GenerateMenuSelect $menu
284
285 # If this looks like an option menubutton then post the menu so
286 # that the current entry is on top of the mouse. Otherwise post
287 # the menu just below the menubutton, as for a pull-down.
288
289285 update idletasks
290 if {[catch {
291 switch [$w cget -direction] {
292 above {
293 set x [winfo rootx $w]
294 set y [expr {[winfo rooty $w] - [winfo reqheight $menu]}]
295 # if we go offscreen to the top, show as 'below'
296 if {$y < [winfo vrooty $w]} {
297 set y [expr {[winfo vrooty $w] + [winfo rooty $w] + [winfo reqheight $w]}]
298 }
299 PostOverPoint $menu $x $y
300 }
301 below {
302 set x [winfo rootx $w]
303 set y [expr {[winfo rooty $w] + [winfo height $w]}]
304 # if we go offscreen to the bottom, show as 'above'
305 set mh [winfo reqheight $menu]
306 if {($y + $mh) > ([winfo vrooty $w] + [winfo vrootheight $w])} {
307 set y [expr {[winfo vrooty $w] + [winfo vrootheight $w] + [winfo rooty $w] - $mh}]
308 }
309 PostOverPoint $menu $x $y
310 }
311 left {
312 set x [expr {[winfo rootx $w] - [winfo reqwidth $menu]}]
313 set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}]
314 set entry [MenuFindName $menu [$w cget -text]]
315 if {$entry eq ""} {
316 set entry 0
317 }
318 if {[$w cget -indicatoron]} {
319 if {$entry == [$menu index last]} {
320 incr y [expr {-([$menu yposition $entry] \
321 + [winfo reqheight $menu])/2}]
322 } else {
323 incr y [expr {-([$menu yposition $entry] \
324 + [$menu yposition [expr {$entry+1}]])/2}]
325 }
326 }
327 PostOverPoint $menu $x $y
328 if {$entry ne "" \
329 && [$menu entrycget $entry -state] ne "disabled"} {
330 $menu activate $entry
331 GenerateMenuSelect $menu
332 }
333 }
334 right {
335 set x [expr {[winfo rootx $w] + [winfo width $w]}]
336 set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}]
337 set entry [MenuFindName $menu [$w cget -text]]
338 if {$entry eq ""} {
339 set entry 0
340 }
341 if {[$w cget -indicatoron]} {
342 if {$entry == [$menu index last]} {
343 incr y [expr {-([$menu yposition $entry] \
344 + [winfo reqheight $menu])/2}]
345 } else {
346 incr y [expr {-([$menu yposition $entry] \
347 + [$menu yposition [expr {$entry+1}]])/2}]
348 }
349 }
350 PostOverPoint $menu $x $y
351 if {$entry ne "" \
352 && [$menu entrycget $entry -state] ne "disabled"} {
353 $menu activate $entry
354 GenerateMenuSelect $menu
355 }
356 }
357 default {
358 if {[$w cget -indicatoron]} {
359 if {$y eq ""} {
360 set x [expr {[winfo rootx $w] + [winfo width $w]/2}]
361 set y [expr {[winfo rooty $w] + [winfo height $w]/2}]
362 }
363 PostOverPoint $menu $x $y [MenuFindName $menu [$w cget -text]]
364 } else {
365 PostOverPoint $menu [winfo rootx $w] [expr {[winfo rooty $w]+[winfo height $w]}]
366 }
367 }
368 }
369 } msg opt]} {
286
287 if {[catch {PostMenubuttonMenu $w $menu} msg opt]} {
370288 # Error posting menu (e.g. bogus -postcommand). Unpost it and
371289 # reflect the error.
372
373290 MenuUnpost {}
374291 return -options $opt $msg
375292 }
376293
377294 set Priv(tearoff) $tearoff
378 if {$tearoff != 0} {
295 if {$tearoff != 0 && [tk windowingsystem] ne "aqua"} {
379296 focus $menu
380297 if {[winfo viewable $w]} {
381298 SaveGrabInfo $w
575492 if {[string is false $mode]} {
576493 set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}]
577494 if {[$menu type $index] eq "cascade"} {
495 # Catch these postcascade commands since the menu could be
496 # destroyed before they run.
578497 set Priv(menuActivatedTimer) \
579 [after $delay [list $menu postcascade active]]
498 [after $delay "catch {$menu postcascade active}"]
580499 } else {
581500 set Priv(menuDeactivatedTimer) \
582 [after $delay [list $menu postcascade none]]
501 [after $delay "catch {$menu postcascade none}"]
583502 }
584503 }
585504 }
12071126 return ""
12081127 }
12091128
1129 # ::tk::PostMenubuttonMenu --
1130 #
1131 # Given a menubutton and a menu, this procedure posts the menu at the
1132 # appropriate location. If the menubutton looks like an option
1133 # menubutton, meaning that the indicator is on and the direction is
1134 # neither above nor below, then the menu is posted so that the current
1135 # entry is vertically aligned with the menubutton. On the Mac this
1136 # will expose a small amount of the blue indicator on the right hand
1137 # side. On other platforms the entry is centered over the button.
1138
1139 if {[tk windowingsystem] eq "aqua"} {
1140 proc ::tk::PostMenubuttonMenu {button menu} {
1141 set entry ""
1142 if {[$button cget -indicatoron]} {
1143 set entry [MenuFindName $menu [$button cget -text]]
1144 if {$entry eq ""} {
1145 set entry 0
1146 }
1147 }
1148 set x [winfo rootx $button]
1149 set y [expr {2 + [winfo rooty $button]}]
1150 switch [$button cget -direction] {
1151 above {
1152 set entry ""
1153 incr y [expr {4 - [winfo reqheight $menu]}]
1154 }
1155 below {
1156 set entry ""
1157 incr y [expr {2 + [winfo height $button]}]
1158 }
1159 left {
1160 incr x [expr {-[winfo reqwidth $menu]}]
1161 }
1162 right {
1163 incr x [winfo width $button]
1164 }
1165 default {
1166 incr x [expr {[winfo width $button] - [winfo reqwidth $menu] - 5}]
1167 }
1168 }
1169 PostOverPoint $menu $x $y $entry
1170 }
1171 } else {
1172 proc ::tk::PostMenubuttonMenu {button menu} {
1173 set entry ""
1174 if {[$button cget -indicatoron]} {
1175 set entry [MenuFindName $menu [$button cget -text]]
1176 if {$entry eq ""} {
1177 set entry 0
1178 }
1179 }
1180 set x [winfo rootx $button]
1181 set y [winfo rooty $button]
1182 switch [$button cget -direction] {
1183 above {
1184 incr y [expr {-[winfo reqheight $menu]}]
1185 # if we go offscreen to the top, show as 'below'
1186 if {$y < [winfo vrooty $button]} {
1187 set y [expr {[winfo vrooty $button] + [winfo rooty $button]\
1188 + [winfo reqheight $button]}]
1189 }
1190 set entry {}
1191 }
1192 below {
1193 incr y [winfo height $button]
1194 # if we go offscreen to the bottom, show as 'above'
1195 set mh [winfo reqheight $menu]
1196 if {($y + $mh) > ([winfo vrooty $button] + [winfo vrootheight $button])} {
1197 set y [expr {[winfo vrooty $button] + [winfo vrootheight $button] \
1198 + [winfo rooty $button] - $mh}]
1199 }
1200 set entry {}
1201 }
1202 left {
1203 # It is not clear why this is needed.
1204 if {[tk windowingsystem] eq "win32"} {
1205 incr x [expr {-4 - [winfo reqwidth $button] / 2}]
1206 }
1207 incr x [expr {- [winfo reqwidth $menu]}]
1208 }
1209 right {
1210 incr x [expr {[winfo width $button]}]
1211 }
1212 default {
1213 if {[$button cget -indicatoron]} {
1214 incr x [expr {([winfo width $button] - \
1215 [winfo reqwidth $menu])/ 2}]
1216 } else {
1217 incr y [winfo height $button]
1218 }
1219 }
1220 }
1221 PostOverPoint $menu $x $y $entry
1222 }
1223 }
1224
12101225 # ::tk::PostOverPoint --
1211 # This procedure posts a given menu such that a given entry in the
1212 # menu is centered over a given point in the root window. It also
1213 # activates the given entry.
1226 #
1227 # This procedure posts a menu on the screen so that a given entry in
1228 # the menu is positioned with its upper left corner at a given point
1229 # in the root window. The procedure also activates that entry. If no
1230 # entry is specified the upper left corner of the entire menu is
1231 # placed at the point.
12141232 #
12151233 # Arguments:
12161234 # menu - Menu to post.
12191237 # If omitted or specified as {}, then the menu's
12201238 # upper-left corner goes at (x,y).
12211239
1222 proc ::tk::PostOverPoint {menu x y {entry {}}} {
1223 if {$entry ne ""} {
1224 if {$entry == [$menu index last]} {
1225 incr y [expr {-([$menu yposition $entry] \
1226 + [winfo reqheight $menu])/2}]
1240 if {[tk windowingsystem] ne "win32"} {
1241 proc ::tk::PostOverPoint {menu x y {entry {}}} {
1242 if {$entry ne ""} {
1243 $menu post $x $y $entry
1244 if {[$menu entrycget $entry -state] ne "disabled"} {
1245 $menu activate $entry
1246 GenerateMenuSelect $menu
1247 }
12271248 } else {
1228 incr y [expr {-([$menu yposition $entry] \
1229 + [$menu yposition [expr {$entry+1}]])/2}]
1230 }
1231 incr x [expr {-[winfo reqwidth $menu]/2}]
1232 }
1233
1234 if {[tk windowingsystem] eq "win32"} {
1249 $menu post $x $y
1250 }
1251 return
1252 }
1253 } else {
1254 proc ::tk::PostOverPoint {menu x y {entry {}}} {
1255 if {$entry ne ""} {
1256 incr y [expr {-[$menu yposition $entry]}]
1257 }
12351258 # osVersion is not available in safe interps
12361259 set ver 5
12371260 if {[info exists ::tcl_platform(osVersion)]} {
12471270 # manager provided with Vista and Windows 7.
12481271 if {$ver < 6} {
12491272 set yoffset [expr {[winfo screenheight $menu] \
1250 - $y - [winfo reqheight $menu] - 10}]
1273 - $y - [winfo reqheight $menu] - 10}]
12511274 if {$yoffset < [winfo vrooty $menu]} {
12521275 # The bottom of the menu is offscreen, so adjust upwards
12531276 incr y [expr {$yoffset - [winfo vrooty $menu]}]
12591282 set y [winfo vrooty $menu]
12601283 }
12611284 }
1262 }
1263 $menu post $x $y
1264 if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
1265 $menu activate $entry
1266 GenerateMenuSelect $menu
1285 $menu post $x $y
1286 if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
1287 $menu activate $entry
1288 GenerateMenuSelect $menu
1289 }
12671290 }
12681291 }
12691292
163163 "warning" {set data(-icon) "caution"}
164164 "info" {set data(-icon) "note"}
165165 }
166 option add *Dialog*background systemDialogBackgroundActive widgetDefault
167 option add *Dialog*Button.highlightBackground \
168 systemDialogBackgroundActive widgetDefault
169166 }
170167
171168 if {![winfo exists $data(-parent)]} {
127127 tk::ScrollToPos %W 1
128128 }
129129 }
130 switch [tk windowingsystem] {
131 "aqua" {
132 bind Scrollbar <MouseWheel> {
133 tk::ScrollByUnits %W v [expr {- (%D)}]
130
131 if {[tk windowingsystem] eq "aqua"} {
132 bind Scrollbar <MouseWheel> {
133 tk::ScrollByUnits %W v [expr {-(%D)}]
134 }
135 bind Scrollbar <Option-MouseWheel> {
136 tk::ScrollByUnits %W v [expr {-10 * (%D)}]
137 }
138 bind Scrollbar <Shift-MouseWheel> {
139 tk::ScrollByUnits %W h [expr {-(%D)}]
140 }
141 bind Scrollbar <Shift-Option-MouseWheel> {
142 tk::ScrollByUnits %W h [expr {-10 * (%D)}]
143 }
144 } else {
145 bind Scrollbar <MouseWheel> {
146 if {%D >= 0} {
147 tk::ScrollByUnits %W v [expr {-%D/30}]
148 } else {
149 tk::ScrollByUnits %W v [expr {(29-%D)/30}]
134150 }
135 bind Scrollbar <Option-MouseWheel> {
136 tk::ScrollByUnits %W v [expr {-10 * (%D)}]
151 }
152 bind Scrollbar <Shift-MouseWheel> {
153 if {%D >= 0} {
154 tk::ScrollByUnits %W h [expr {-%D/30}]
155 } else {
156 tk::ScrollByUnits %W h [expr {(29-%D)/30}]
137157 }
138 bind Scrollbar <Shift-MouseWheel> {
139 tk::ScrollByUnits %W h [expr {- (%D)}]
140 }
141 bind Scrollbar <Shift-Option-MouseWheel> {
142 tk::ScrollByUnits %W h [expr {-10 * (%D)}]
143 }
144 }
145 "win32" {
146 bind Scrollbar <MouseWheel> {
147 tk::ScrollByUnits %W v [expr {- (%D / 120) * 4}]
148 }
149 bind Scrollbar <Shift-MouseWheel> {
150 tk::ScrollByUnits %W h [expr {- (%D / 120) * 4}]
151 }
152 }
153 "x11" {
154 bind Scrollbar <MouseWheel> {
155 tk::ScrollByUnits %W v [expr {- (%D /120 ) * 4}]
156 }
157 bind Scrollbar <Shift-MouseWheel> {
158 tk::ScrollByUnits %W h [expr {- (%D /120 ) * 4}]
159 }
160 bind Scrollbar <4> {tk::ScrollByUnits %W v -5}
161 bind Scrollbar <5> {tk::ScrollByUnits %W v 5}
162 bind Scrollbar <Shift-4> {tk::ScrollByUnits %W h -5}
163 bind Scrollbar <Shift-5> {tk::ScrollByUnits %W h 5}
164 }
165 }
158 }
159 }
160
161 if {[tk windowingsystem] eq "x11"} {
162 bind Scrollbar <4> {tk::ScrollByUnits %W v -5}
163 bind Scrollbar <5> {tk::ScrollByUnits %W v 5}
164 bind Scrollbar <Shift-4> {tk::ScrollByUnits %W h -5}
165 bind Scrollbar <Shift-5> {tk::ScrollByUnits %W h 5}
166 }
167
166168 # tk::ScrollButtonDown --
167169 # This procedure is invoked when a button is pressed in a scrollbar.
168170 # It changes the way the scrollbar is displayed and takes actions
3737 # The code below creates the default class bindings for text widgets.
3838 #-------------------------------------------------------------------------
3939
40
41
4042 # Standard Motif bindings:
4143
4244 bind Text <1> {
8284 bind Text <ButtonRelease-1> {
8385 tk::CancelRepeat
8486 }
87
8588 bind Text <Control-1> {
8689 %W mark set insert @%x,%y
8790 # An operation that moves the insert mark without making it
385388 if {!$tk_strictMotif} {
386389 %W delete [tk::TextPrevPos %W insert tcl_startOfPreviousWord] insert
387390 }
391 }
392
393 # Bindings for IME text input.
394
395 bind Text <<TkStartIMEMarkedText>> {
396 dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
397 }
398 bind Text <<TkEndIMEMarkedText>> {
399 if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } {
400 bell
401 } else {
402 %W tag add IMEmarkedtext $mark insert
403 %W tag configure IMEmarkedtext -underline on
404 }
405 }
406 bind Text <<TkClearIMEMarkedText>> {
407 %W delete IMEmarkedtext.first IMEmarkedtext.last
408 }
409 bind Text <<TkAccentBackspace>> {
410 %W delete insert-1c
388411 }
389412
390413 # Macintosh only bindings:
458481 }
459482 }
460483
461 if {"x11" eq [tk windowingsystem]} {
484 if {[tk windowingsystem] eq "x11"} {
462485 # Support for mousewheels on Linux/Unix commonly comes through mapping
463486 # the wheel to the extended buttons. If you have a mousewheel, find
464487 # Linux configuration info at:
890913
891914 # ::tk::TextUpDownLine --
892915 # Returns the index of the character one display line above or below the
893 # insertion cursor. There are two tricky things here. First, we want to
894 # maintain the original x position across repeated operations, even though
895 # some lines that will get passed through don't have enough characters to
896 # cover the original column. Second, don't try to scroll past the
897 # beginning or end of the text.
916 # insertion cursor. There is a tricky thing here: we want to maintain the
917 # original x position across repeated operations, even though some lines
918 # that will get passed through don't have enough characters to cover the
919 # original column.
898920 #
899921 # Arguments:
900922 # w - The text window in which the cursor is to move.
911933 set lines [$w count -displaylines $Priv(textPosOrig) $i]
912934 set new [$w index \
913935 "$Priv(textPosOrig) + [expr {$lines + $n}] displaylines"]
914 if {[$w compare $new == end] \
915 || [$w compare $new == "insert display linestart"]} {
916 set new $i
917 }
918936 set Priv(prevPos) $new
937 if {[$w compare $new == "end display lineend"] \
938 || [$w compare $new == "insert display linestart"]} {
939 set Priv(textPosOrig) $new
940 }
919941 return $new
920942 }
921943
1010 # this file, and for a DISCLAIMER OF ALL WARRANTIES.
1111
1212 # Verify that we have Tk binary and script components from the same release
13 package require -exact Tk 8.6.9
13 package require -exact Tk 8.6.10
1414
1515 # Create a ::tk namespace
1616 namespace eval ::tk {
461461 # Official bindings
462462 # See http://support.apple.com/kb/HT1343
463463 event add <<SelectAll>> <Command-Key-a>
464 event add <<SelectNone>> <Option-Command-Key-a>
464 #Attach function keys not otherwise assigned to this event so they no-op - workaround for bug 0e6930dfe7
465 event add <<SelectNone>> <Option-Command-Key-a> <Key-F5> <Key-F1> <Key-F5> <Key-F6> <Key-F7> <Key-F8> <Key-F9> <Key-F10> <Key-F11> <Key-F12>
465466 event add <<Undo>> <Command-Key-z> <Command-Lock-Key-Z>
466467 event add <<Redo>> <Shift-Command-Key-z> <Shift-Command-Lock-Key-z>
467468 event add <<NextChar>> <Right> <Control-Key-f> <Control-Lock-Key-F>
675676 return $maxlen
676677 }
677678
678 # For now, turn off the custom mdef proc for the mac:
679 # For now, turn off the custom mdef proc for the Mac:
679680
680681 if {[tk windowingsystem] eq "aqua"} {
681682 namespace eval ::tk::mac {
682683 set useCustomMDEF 0
683684 }
684685 }
686
687
688 if {[tk windowingsystem] eq "aqua"} {
689 #stub procedures to respond to "do script" Apple Events
690 proc ::tk::mac::DoScriptFile {file} {
691 source $file
692 }
693 proc ::tk::mac::DoScriptText {script} {
694 eval $script
695 }
696 }
697
698 # Create a dictionary to store the starting index of the IME marked
699 # text in an Entry or Text widget.
700
701 set ::tk::Priv(IMETextMark) [dict create]
685702
686703 # Run the Ttk themed widget set initialization
687704 if {$::ttk::library ne ""} {
9595 ttk::style configure Treeview -background $colors(-window)
9696 ttk::style map Treeview \
9797 -background [list disabled $colors(-frame)\
98 {!disabled !selected} $colors(-window) \
9998 selected $colors(-selectbg)] \
10099 -foreground [list disabled $colors(-disabledfg) \
101 {!disabled !selected} black \
102100 selected $colors(-selectfg)]
103101
104102 ttk::style configure TScale \
66
77 ttk::style configure . \
88 -font TkDefaultFont \
9 -background systemWindowBody \
10 -foreground systemModelessDialogActiveText \
11 -selectbackground systemHighlight \
12 -selectforeground systemModelessDialogActiveText \
9 -background systemWindowBackgroundColor \
10 -foreground systemLabelColor \
11 -selectbackground systemSelectedTextBackgroundColor \
12 -selectforeground systemSelectedTextColor \
1313 -selectborderwidth 0 \
1414 -insertwidth 1
1515
1616 ttk::style map . \
17 -foreground {disabled systemModelessDialogInactiveText
18 background systemModelessDialogInactiveText} \
19 -selectbackground {background systemHighlightSecondary
20 !focus systemHighlightSecondary} \
21 -selectforeground {background systemModelessDialogInactiveText
22 !focus systemDialogActiveText}
17 -foreground {
18 disabled systemDisabledControlTextColor
19 background systemLabelColor} \
20 -selectbackground {
21 background systemSelectedTextBackgroundColor
22 !focus systemSelectedTextBackgroundColor} \
23 -selectforeground {
24 background systemSelectedTextColor
25 !focus systemSelectedTextColor}
26
27 # Button
28 ttk::style configure TButton -anchor center -width -6 \
29 -foreground systemControlTextColor
30 ttk::style map TButton \
31 -foreground {
32 pressed white
33 {alternate !pressed !background} white}
34 ttk::style configure TMenubutton -anchor center -padding {2 0 0 2}
35 ttk::style configure Toolbutton -anchor center
36
37 # Entry
38 ttk::style configure TEntry \
39 -foreground systemTextColor \
40 -background systemTextBackgroundColor
41 ttk::style map TEntry \
42 -foreground {
43 disabled systemDisabledControlTextColor
44 } \
45 -selectforeground {
46 background systemTextColor
47 } \
48 -selectbackground {
49 background systemTextBackgroundColor
50 }
51
2352
2453 # Workaround for #1100117:
2554 # Actually, on Aqua we probably shouldn't stipple images in
2655 # disabled buttons even if it did work...
2756 ttk::style configure . -stipple {}
2857
29 ttk::style configure TButton -anchor center -width -6
30 ttk::style configure Toolbutton -padding 4
31
58 # Notebook
3259 ttk::style configure TNotebook -tabmargins {10 0} -tabposition n
3360 ttk::style configure TNotebook -padding {18 8 18 17}
3461 ttk::style configure TNotebook.Tab -padding {12 3 12 2}
62 ttk::style configure TNotebook.Tab -foreground systemControlTextColor
63 ttk::style map TNotebook.Tab \
64 -foreground {
65 background systemControlTextColor
66 disabled systemDisabledControlTextColor
67 selected systemSelectedTabTextColor}
3568
3669 # Combobox:
37 ttk::style configure TCombobox -postoffset {5 -2 -10 0}
70 ttk::style configure TCombobox \
71 -foreground systemTextColor \
72 -background systemTransparent
73 ttk::style map TCombobox \
74 -foreground {
75 disabled systemDisabledControlTextColor
76 } \
77 -selectforeground {
78 background systemTextColor
79 } \
80 -selectbackground {
81 background systemTransparent
82 }
3883
84 # Spinbox
85 ttk::style configure TSpinbox \
86 -foreground systemTextColor \
87 -background systemTextBackgroundColor \
88 -selectforeground systemSelectedTextColor \
89 -selectbackground systemSelectedTextBackgroundColor
90 ttk::style map TSpinbox \
91 -foreground {
92 disabled systemDisabledControlTextColor
93 } \
94 -selectforeground {
95 !active systemTextColor
96 } \
97 -selectbackground {
98 !active systemTextBackgroundColor
99 !focus systemTextBackgroundColor
100 focus systemSelectedTextBackgroundColor
101 }
102
39103 # Treeview:
40 ttk::style configure Heading -font TkHeadingFont
41 ttk::style configure Treeview -rowheight 18 -background White
104 ttk::style configure Heading \
105 -font TkHeadingFont \
106 -foreground systemTextColor \
107 -background systemWindowBackgroundColor
108 ttk::style configure Treeview -rowheight 18 \
109 -background systemTextBackgroundColor \
110 -foreground systemTextColor \
111 -fieldbackground systemTextBackgroundColor
42112 ttk::style map Treeview \
43 -background [list disabled systemDialogBackgroundInactive \
44 {!disabled !selected} systemWindowBody \
45 {selected background} systemHighlightSecondary \
46 selected systemHighlight] \
47 -foreground [list disabled systemModelessDialogInactiveText \
48 {!disabled !selected} black \
49 selected systemModelessDialogActiveText]
113 -background {
114 selected systemSelectedTextBackgroundColor
115 }
50116
51117 # Enable animation for ttk::progressbar widget:
52118 ttk::style configure TProgressbar -period 100 -maxphase 255
131131 ttk::style configure Treeview -background $colors(-window)
132132 ttk::style map Treeview \
133133 -background [list disabled $colors(-frame)\
134 {!disabled !selected} $colors(-window) \
135134 selected $colors(-selectbg)] \
136135 -foreground [list disabled $colors(-disabledfg) \
137 {!disabled !selected} black \
138136 selected $colors(-selectfg)]
139137
140138 ttk::style configure TLabelframe \
9898 ttk::style configure Treeview -background $colors(-window)
9999 ttk::style map Treeview \
100100 -background [list disabled $colors(-frame)\
101 {!disabled !selected} $colors(-window) \
102101 selected $colors(-selectbg)] \
103102 -foreground [list disabled $colors(-disabledfg) \
104 {!disabled !selected} black \
105103 selected $colors(-selectfg)]
106104
107105 #
250250 ttk::releaseGrab $w
251251 }
252252
253 ###
254 #
255
256 namespace eval ::ttk::combobox {
257 # @@@ Until we have a proper native scrollbar on Aqua, use
258 # @@@ the regular Tk one. Use ttk::scrollbar on other platforms.
259 variable scrollbar ttk::scrollbar
260 if {[tk windowingsystem] eq "aqua"} {
261 set scrollbar ::scrollbar
262 }
263 }
264
265253 ## PopdownWindow --
266254 # Returns the popdown widget associated with a combobox,
267255 # creating it if necessary.
268256 #
269257 proc ttk::combobox::PopdownWindow {cb} {
270 variable scrollbar
271
272258 if {![winfo exists $cb.popdown]} {
273259 set poplevel [PopdownToplevel $cb.popdown]
274260 set popdown [ttk::frame $poplevel.f -style ComboboxPopdownFrame]
275261
276 $scrollbar $popdown.sb \
262 ttk::scrollbar $popdown.sb \
277263 -orient vertical -command [list $popdown.l yview]
278264 listbox $popdown.l \
279265 -listvariable ttk::combobox::Values($cb) \
110110 -foreground $colors(-text) ;
111111 ttk::style map Treeview \
112112 -background [list disabled $colors(-frame)\
113 {!disabled !selected} $colors(-window) \
114113 selected $colors(-selectbg)] \
115114 -foreground [list disabled $colors(-disabledfg) \
116 {!disabled !selected} black \
117115 selected $colors(-selectfg)]
118116
119117 # Combobox popdown frame
144144 bind TEntry <Control-Key-h> { ttk::entry::Backspace %W }
145145 bind TEntry <Control-Key-k> { %W delete insert end }
146146
147 # Bindings for IME text input.
148
149 bind TEntry <<TkStartIMEMarkedText>> {
150 dict set ::tk::Priv(IMETextMark) "%W" [%W index insert]
151 }
152 bind TEntry <<TkEndIMEMarkedText>> {
153 if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } {
154 bell
155 } else {
156 %W selection range $mark insert
157 }
158 }
159 bind TEntry <<TkClearIMEMarkedText>> {
160 %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert]
161 }
162 bind TEntry <<TkAccentBackspace>> {
163 ttk::entry::Backspace %W
164 }
165
147166 ### Clipboard procedures.
148167 #
149168
210229 ## See $index -- Make sure that the character at $index is visible.
211230 #
212231 proc ttk::entry::See {w {index insert}} {
213 update idletasks ;# ensure scroll data up-to-date
214232 set c [$w index $index]
215233 # @@@ OR: check [$w index left] / [$w index right]
216234 if {$c < [$w index @0] || $c >= [$w index @[winfo width $w]]} {
6060 }
6161
6262 # PostPosition --
63 # Returns the x and y coordinates where the menu
64 # should be posted, based on the menubutton and menu size
65 # and -direction option.
63 # Returns x and y coordinates and a menu item index.
64 # If the index is not an empty string the menu should
65 # be posted so that the upper left corner of the indexed
66 # menu item is located at the point (x, y). Otherwise
67 # the top left corner of the menu itself should be located
68 # at that point.
6669 #
6770 # TODO: adjust menu width to be at least as wide as the button
6871 # for -direction above, below.
6972 #
70 proc ttk::menubutton::PostPosition {mb menu} {
71 set x [winfo rootx $mb]
72 set y [winfo rooty $mb]
73 set dir [$mb cget -direction]
74
75 set bw [winfo width $mb]
76 set bh [winfo height $mb]
77 set mw [winfo reqwidth $menu]
78 set mh [winfo reqheight $menu]
79 set sw [expr {[winfo screenwidth $menu] - $bw - $mw}]
80 set sh [expr {[winfo screenheight $menu] - $bh - $mh}]
81
82 switch -- $dir {
83 above { if {$y >= $mh} { incr y -$mh } { incr y $bh } }
84 below { if {$y <= $sh} { incr y $bh } { incr y -$mh } }
85 left { if {$x >= $mw} { incr x -$mw } { incr x $bw } }
86 right { if {$x <= $sw} { incr x $bw } { incr x -$mw } }
87 flush {
88 # post menu atop menubutton.
89 # If there's a menu entry whose label matches the
90 # menubutton -text, assume this is an optionmenu
91 # and place that entry over the menubutton.
92 set index [FindMenuEntry $menu [$mb cget -text]]
93 if {$index ne ""} {
94 incr y -[$menu yposition $index]
95 }
96 }
97 }
98
99 return [list $x $y]
73
74 if {[tk windowingsystem] eq "aqua"} {
75 proc ::ttk::menubutton::PostPosition {mb menu} {
76 set menuPad 5
77 set buttonPad 1
78 set bevelPad 4
79 set mh [winfo reqheight $menu]
80 set bh [expr {[winfo height $mb]} + $buttonPad]
81 set bbh [expr {[winfo height $mb]} + $bevelPad]
82 set mw [winfo reqwidth $menu]
83 set bw [winfo width $mb]
84 set dF [expr {[winfo width $mb] - [winfo reqwidth $menu] - $menuPad}]
85 set entry ""
86 set entry [::tk::MenuFindName $menu [$mb cget -text]]
87 if {$entry eq ""} {
88 set entry 0
89 }
90 set x [winfo rootx $mb]
91 set y [winfo rooty $mb]
92 switch [$mb cget -direction] {
93 above {
94 set entry ""
95 incr y [expr {-$mh + 2 * $menuPad}]
96 }
97 below {
98 set entry ""
99 incr y $bh
100 }
101 left {
102 incr y $menuPad
103 incr x -$mw
104 }
105 right {
106 incr y $menuPad
107 incr x $bw
108 }
109 default {
110 incr y $bbh
111 }
112 }
113 return [list $x $y $entry]
114 }
115 } else {
116 proc ::ttk::menubutton::PostPosition {mb menu} {
117 set mh [expr {[winfo reqheight $menu]}]
118 set bh [expr {[winfo height $mb]}]
119 set mw [expr {[winfo reqwidth $menu]}]
120 set bw [expr {[winfo width $mb]}]
121 set dF [expr {[winfo width $mb] - [winfo reqwidth $menu]}]
122 if {[tk windowingsystem] eq "win32"} {
123 incr mh 6
124 incr mw 16
125 }
126 set entry {}
127 set entry [::tk::MenuFindName $menu [$mb cget -text]]
128 if {$entry eq {}} {
129 set entry 0
130 }
131 set x [winfo rootx $mb]
132 set y [winfo rooty $mb]
133 switch [$mb cget -direction] {
134 above {
135 set entry {}
136 incr y -$mh
137 # if we go offscreen to the top, show as 'below'
138 if {$y < [winfo vrooty $mb]} {
139 set y [expr {[winfo vrooty $mb] + [winfo rooty $mb]\
140 + [winfo reqheight $mb]}]
141 }
142 }
143 below {
144 set entry {}
145 incr y $bh
146 # if we go offscreen to the bottom, show as 'above'
147 if {($y + $mh) > ([winfo vrooty $mb] + [winfo vrootheight $mb])} {
148 set y [expr {[winfo vrooty $mb] + [winfo vrootheight $mb] \
149 + [winfo rooty $mb] - $mh}]
150 }
151 }
152 left {
153 incr x -$mw
154 }
155 right {
156 incr x $bw
157 }
158 default {
159 if {[$mb cget -style] eq ""} {
160 incr x [expr {([winfo width $mb] - \
161 [winfo reqwidth $menu])/ 2}]
162 } else {
163 incr y $bh
164 }
165 }
166 }
167 return [list $x $y $entry]
168 }
100169 }
101170
102171 # Popdown --
106175 if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} {
107176 return
108177 }
109 foreach {x y} [PostPosition $mb $menu] { break }
110 tk_popup $menu $x $y
178 foreach {x y entry} [PostPosition $mb $menu] { break }
179 tk_popup $menu $x $y $entry
111180 }
112181
113182 # Pulldown (X11 only) --
120189 if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} {
121190 return
122191 }
123 foreach {x y} [PostPosition $mb $menu] { break }
124192 set State(pulldown) 1
125193 set State(oldcursor) [$mb cget -cursor]
126194
127195 $mb state pressed
128196 $mb configure -cursor [$menu cget -cursor]
129 $menu post $x $y
197 foreach {x y entry} [PostPosition $mb $menu] { break }
198 if {$entry ne {}} {
199 $menu post $x $y $entry
200 } else {
201 $menu post $x $y
202 }
130203 tk_menuSetFocus $menu
131204 }
132205
142215 set State(pulldown) 0
143216
144217 set menu [$mb cget -menu]
218 foreach {x y entry} [PostPosition $mb $menu] { break }
145219 tk_popup $menu [winfo rootx $menu] [winfo rooty $menu]
146220 }
147221 }
00 #
11 # Bindings for TScrollbar widget
22 #
3
4 # Still don't have a working ttk::scrollbar under OSX -
5 # Swap in a [tk::scrollbar] on that platform,
6 # unless user specifies -class or -style.
7 #
8 if {[tk windowingsystem] eq "aqua"} {
9 rename ::ttk::scrollbar ::ttk::_scrollbar
10 proc ttk::scrollbar {w args} {
11 set constructor ::tk::scrollbar
12 foreach {option _} $args {
13 if {$option eq "-class" || $option eq "-style"} {
14 set constructor ::ttk::_scrollbar
15 break
16 }
17 }
18 return [$constructor $w {*}$args]
19 }
20 }
213
224 namespace eval ttk::scrollbar {
235 variable State
8080 # or <<Decrement> (+1, down) events.
8181 #
8282 proc ttk::spinbox::MouseWheel {w dir} {
83 if {[$w instate disabled]} { return }
8384 if {$dir < 0} {
8485 event generate $w <<Increment>>
8586 } else {
131132 # -from, -to, and -increment.
132133 #
133134 proc ttk::spinbox::Spin {w dir} {
135 if {[$w instate disabled]} { return }
134136 set nvalues [llength [set values [$w cget -values]]]
135137 set value [$w get]
136138 if {$nvalues} {
120120
121121 if {$w != $State(activeWidget) || $heading != $State(activeHeading)} {
122122 if {[winfo exists $State(activeWidget)] && $State(activeHeading) != {}} {
123 $State(activeWidget) heading $State(activeHeading) state !active
123 # It may happen that $State(activeHeading) no longer corresponds
124 # to an existing display column. This happens for instance when
125 # changing -displaycolumns in a bound script when this change
126 # triggers a <Leave> event. A proc checking if the display column
127 # $State(activeHeading) is really still present or not could be
128 # written but it would need to check several special cases:
129 # a. -displaycolumns "#all" or being an explicit columns list
130 # b. column #0 display is not governed by the -displaycolumn
131 # list but by the value of the -show option
132 # --> Let's rather catch the following line.
133 catch {$State(activeWidget) heading $State(activeHeading) state !active}
124134 }
125135 if {$heading != {}} {
126136 $w heading $heading state active
204214 }
205215
206216 proc ttk::treeview::resize.release {w x} {
207 # no-op
217 $w drop
208218 }
209219
210220 ### Heading activation.
335345 ## Toggle -- toggle opened/closed state of item
336346 #
337347 proc ttk::treeview::Toggle {w item} {
348 # don't allow toggling on indicators that
349 # are not present in front of leaf items
350 if {[$w children $item] == {}} {
351 return
352 }
353 # not a leaf, toggle!
338354 if {[$w item $item -open]} {
339355 CloseItem $w $item
340356 } else {
299299 #
300300
301301 proc ttk::bindMouseWheel {bindtag callback} {
302 switch -- [tk windowingsystem] {
303 x11 {
304 bind $bindtag <ButtonPress-4> "$callback -1"
305 bind $bindtag <ButtonPress-5> "$callback +1"
306 }
307 win32 {
308 bind $bindtag <MouseWheel> [append callback { [expr {-(%D/120)}]}]
309 }
310 aqua {
311 bind $bindtag <MouseWheel> [append callback { [expr {-(%D)}]} ]
312 }
302 if {[tk windowingsystem] eq "x11"} {
303 bind $bindtag <ButtonPress-4> "$callback -1"
304 bind $bindtag <ButtonPress-5> "$callback +1"
305 }
306 if {[tk windowingsystem] eq "aqua"} {
307 bind $bindtag <MouseWheel> [append callback { [expr {-(%D)}]} ]
308 bind $bindtag <Option-MouseWheel> [append callback { [expr {-10 *(%D)}]} ]
309 } else {
310 bind $bindtag <MouseWheel> [append callback { [expr {-(%D / 120)}]}]
313311 }
314312 }
315313
321319 # standard scrollbar protocol.
322320 #
323321
324 switch -- [tk windowingsystem] {
325 x11 {
326 bind TtkScrollable <ButtonPress-4> { %W yview scroll -5 units }
327 bind TtkScrollable <ButtonPress-5> { %W yview scroll 5 units }
328 bind TtkScrollable <Shift-ButtonPress-4> { %W xview scroll -5 units }
329 bind TtkScrollable <Shift-ButtonPress-5> { %W xview scroll 5 units }
330 }
331 win32 {
332 bind TtkScrollable <MouseWheel> \
333 { %W yview scroll [expr {-(%D/120)}] units }
334 bind TtkScrollable <Shift-MouseWheel> \
335 { %W xview scroll [expr {-(%D/120)}] units }
336 }
337 aqua {
338 bind TtkScrollable <MouseWheel> \
322 if {[tk windowingsystem] eq "x11"} {
323 bind TtkScrollable <ButtonPress-4> { %W yview scroll -5 units }
324 bind TtkScrollable <ButtonPress-5> { %W yview scroll 5 units }
325 bind TtkScrollable <Shift-ButtonPress-4> { %W xview scroll -5 units }
326 bind TtkScrollable <Shift-ButtonPress-5> { %W xview scroll 5 units }
327 }
328 if {[tk windowingsystem] eq "aqua"} {
329 bind TtkScrollable <MouseWheel> \
339330 { %W yview scroll [expr {-(%D)}] units }
340 bind TtkScrollable <Shift-MouseWheel> \
331 bind TtkScrollable <Shift-MouseWheel> \
341332 { %W xview scroll [expr {-(%D)}] units }
342 bind TtkScrollable <Option-MouseWheel> \
343 { %W yview scroll [expr {-10*(%D)}] units }
344 bind TtkScrollable <Shift-Option-MouseWheel> \
345 { %W xview scroll [expr {-10*(%D)}] units }
346 }
333 bind TtkScrollable <Option-MouseWheel> \
334 { %W yview scroll [expr {-10 * (%D)}] units }
335 bind TtkScrollable <Shift-Option-MouseWheel> \
336 { %W xview scroll [expr {-10 * (%D)}] units }
337 } else {
338 bind TtkScrollable <MouseWheel> \
339 { %W yview scroll [expr {-(%D / 120)}] units }
340 bind TtkScrollable <Shift-MouseWheel> \
341 { %W xview scroll [expr {-(%D / 120)}] units }
347342 }
348343
349344 #*EOF*
4747 ttk::style configure Treeview -background SystemWindow
4848 ttk::style map Treeview \
4949 -background [list disabled SystemButtonFace \
50 {!disabled !selected} SystemWindow \
5150 selected SystemHighlight] \
5251 -foreground [list disabled SystemGrayText \
53 {!disabled !selected} SystemWindowText \
5452 selected SystemHighlightText]
5553
5654 # Label and Toolbutton
7373 ttk::style configure Treeview -background SystemWindow
7474 ttk::style map Treeview \
7575 -background [list disabled SystemButtonFace \
76 {!disabled !selected} SystemWindow \
7776 selected SystemHighlight] \
7877 -foreground [list disabled SystemGrayText \
79 {!disabled !selected} SystemWindowText \
8078 selected SystemHighlightText]
8179
8280 ttk::style configure TProgressbar \
6666 ttk::style configure Treeview -background SystemWindow
6767 ttk::style map Treeview \
6868 -background [list disabled SystemButtonFace \
69 {!disabled !selected} SystemWindow \
7069 selected SystemHighlight] \
7170 -foreground [list disabled SystemGrayText \
72 {!disabled !selected} SystemWindowText \
7371 selected SystemHighlightText];
7472 }
7573 }
224224 @rm -f "${INSTALL_ROOT}${BINDIR}/${WISH}" && \
225225 rmdir -p "${INSTALL_ROOT}${BINDIR}" 2>&- || true
226226 else
227 # redo prebinding (when not building for Mac OS X 10.4 or later only)
228 @if [ "`echo "$${MACOSX_DEPLOYMENT_TARGET}" | \
229 awk -F '10\\.' '{print int($$2)}'`" -lt 4 -a "`echo "$${CFLAGS}" | \
230 awk -F '-mmacosx-version-min=10\\.' '{print int($$2)}'`" -lt 4 ]; \
231 then cd ${INSTALL_ROOT}/; \
232 if [ ! -d usr/lib ]; then mkdir -p usr && ln -fs /usr/lib usr/ && RM_USRLIB=1; fi; \
233 if [ -n "${TK_X11}" -a ! -d usr/X11R6 ]; then mkdir -p usr && ln -fs /usr/X11R6 usr/ && RM_USRX11=1; fi; \
234 if [ ! -d System ]; then ln -fs /System . && RM_SYSTEM=1; fi; \
235 if [ ! -d "./${LIBDIR}/Tcl.framework" ]; then ln -fs "${TCL_FRAMEWORK_DIR}/Tcl.framework" "./${LIBDIR}"; RM_TCL=1; fi; \
236 redo_prebinding -r . "./${TK_FMWK_DIR}/${PRODUCT_NAME}"; \
237 if [ -z "${TK_X11}" ]; then redo_prebinding -r . "./${TK_FMWK_DIR}/Resources/Wish.app/Contents/MacOS/Wish"; \
238 else redo_prebinding -r . "./${BINDIR}/${WISH}"; fi; \
239 if [ -n "$${RM_USRLIB:-}" ]; then rm -f usr/lib; rmdir -p usr 2>&-; fi; \
240 if [ -n "$${RM_USRX11:-}" ]; then rm -f usr/X11R6; rmdir -p usr 2>&-; fi; \
241 if [ -n "$${RM_SYSTEM:-}" ]; then rm -f System; fi; \
242 if [ -n "$${RM_TCL:-}" ]; then rm -f "./${LIBDIR}/Tcl.framework"; fi; fi
243227 # install wish symbolic link
244228 @ln -fs ${WISH} "${INSTALL_ROOT}${BINDIR}/${wish}"
245229 endif
1515 http://groups.google.com/group/comp.lang.tcl/
1616
1717 - The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on macOS, see
18 http://wiki.tcl.tk/_/ref?N=3753
19 http://wiki.tcl.tk/_/ref?N=8361
18 https://wiki.tcl-lang.org/page/MacOS
2019
2120 - Please report bugs with Tk on macOS to the tracker:
22 http://core.tcl.tk/tk/reportlist
21 https://core.tcl-lang.org/tk/reportlist
2322
2423 2. Using Tcl/Tk on macOS
2524 ---------------------------
2625
2726 - There are two versions of Tk available on macOS: TkAqua using the native
28 aqua widgets and look&feel, and TkX11 using the traditional unix X11 wigets.
29 TkX11 requires an X11 server to be installed, such as Apple's X11 (which is
30 available as an optional or default install on recent macOS).
27 aqua widgets and look&feel, and TkX11 using the traditional unix X11 widgets.
28 TkX11 requires an X11 server to be installed, such as XQuartz (available from www.xquartz.org).
3129 TkAqua and TkX11 can be distinguished at runtime via [tk windowingsystem].
3230
3331 - At a minimum, macOS 10.3 is required to run Tcl and TkX11.
5048 clicking Wish in the Finder (or using 'open Wish.app' from the Terminal).
5149
5250 - Tcl extensions can be installed in any of:
53 $HOME/Library/Tcl /Library/Tcl /System/Library/Tcl
54 $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
51 $HOME/Library/Tcl /Library/Tcl
52 $HOME/Library/Frameworks /Library/Frameworks
5553 (searched in that order).
5654 Given a potential package directory $pkg, Tcl on OSX checks for the file
5755 $pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
5856 This allows building extensions as frameworks with all script files contained in
5957 the Resources/Scripts directory of the framework.
6058
61 - [load]able binary extensions can linked as either ordinary shared libraries
62 (.dylib) or as MachO bundles (since 8.4.10/8.5a3); bundles have the advantage
63 that they are [load]ed more efficiently from a tcl VFS (no temporary copy to the
64 native filesystem required).
65
6659 - The 'deploy' target of macosx/GNUmakefile installs the html manpages into the
6760 standard documentation location in the Tcl/Tk frameworks:
6861 Tcl.framework/Resources/Documentation/Reference/Tcl
7164
7265 - The Tcl and Tk frameworks can be installed in any of the system's standard
7366 framework directories:
74 $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
67 $HOME/Library/Frameworks /Library/Frameworks
7568
7669 - ${prefix}/bin/wish8.x is a script that calls a copy of 'Wish' contained in
7770 Tk.framework/Resources
8578 particular PATH may not be what you expect. (Wish started by LaunchServices
8679 inherits loginwindow's environment variables, which are essentially those set in
8780 $HOME/.MacOSX/environment.plist, and are unrelated to those set in your shell).
88
89 - TkAqua drawing is antialiased by default, but (outline) linewidth can be used
90 to control whether a line/shape is drawn antialiased. The antialiasing threshold
91 is 0 by default (i.e. antialias everything), it can be changed by setting
92 set tk::mac::CGAntialiasLimit <limit>
93 in your script before drawing, in which case lines (or shapes with outlines)
94 thinner than <limit> pixels will not be antialiased.
95
96 - Text antialiasing by default uses the standard OS antialising settings.
97 Setting the global variable '::tk::mac::antialiasedtext' allows to control text
98 antialiasing from Tcl: a value of 1 enables AA, 0 disables AA and -1 restores
99 the default behaviour of respecting the OS settings.
100
101 - Scrollbars: There are two scrollbar variants in Aqua, normal & small. The
102 normal scrollbar has a small dimension of 15, the small variant 11.
103 Access to the small variant was added in Tk 8.4.2.
104
105 - The default metrics of native buttons, radiobuttons, checkboxes and
106 menubuttons in the Cocoa-based Tk 8.5.7 and later preserve compatibility with
107 the older Carbon-based implementation, you can turn off the compatibility
108 metrics to get more native-looking spacing by setting:
109 set tk::mac::useCompatibilityMetrics 0
11081
11182 - TkAqua provides access to native OS X images via the Tk native bitmap facility
11283 (including any image file readable by NSImage). A native bitmap name is
151122 This support was added with the Cocoa-based Tk 8.5.7.
152123
153124 - TkAqua has three special menu names that give access to the standard
154 Application, Window and Help menus, see menu.n for details.
155 By default, the platform-specific standard Help menu item "YourApp Help" peforms
156 the default Cocoa action of showing the Help Book configured in the
157 application's Info.plist (or displaying an alert if no Help Book is set). This
158 action can be customized by defining a procedure named [tk::mac::ShowHelp], if
159 present, this procedure is invoked instead by the standard Help menu item.
160 Support for the Window menu and [tk::mac::ShowHelp] was added with the
161 Cocoa-based Tk 8.5.7.
125 Application, Window and Help menus, see menu.n for details. By default, the
126 platform-specific standard Help menu item "YourApp Help" performs the default
127 Cocoa action of showing the Help Book configured in the application's
128 Info.plist (or displaying an alert if no Help Book is set). This action can be
129 customized by defining a procedure named [tk::mac::ShowHelp]. If present, this
130 procedure is invoked instead by the standard Help menu item. Support for the
131 Window menu and [tk::mac::ShowHelp] was added with the Cocoa-based Tk 8.5.7.
162132
163133 - The TkAqua-specific command [tk::unsupported::MacWindowStyle style] is used to
164134 get and set macOS-specific toplevel window class and attributes. Note that
179149 noActivates, hideOnSuspend, inWindowMenu, ignoreClicks, doesNotHide,
180150 canJoinAllSpaces, moveToActiveSpace, nonActivating
181151
182 Note that not all attributes are valid for all window classes.
183 Support for the 3 argument form was added with the Cocoa-based Tk 8.5.7, at the
184 same time support for some legacy Carbon-specific classes and attributes was
185 removed (they are still accepted by the command but no longer have any effect).
186
187 If you want to use Remote Debugging with Xcode, you need to set the
152 Note that not all attributes are valid for all window classes. Support for the
153 3 argument form was added with the Cocoa-based Tk 8.5.7, at the same time
154 support for some legacy Carbon-specific classes and attributes was removed
155 (they are still accepted by the command but no longer have any effect).
156
157 - Another command available in the tk::unsupported::MacWindowStyle namespace is:
158 tk::unsupported::MacWindowStyle tabbingid window ?newId?
159 which can be used to get or set the tabbingIdentifier for the NSWindow
160 associated with a Tk Window. See section 3 for details.
161
162 - The command:
163 tk::unsupported::MacWindowStyle appearance window ?newAppearance?
164 is available when Tk is built and run on macOS 10.14 (Mojave) or later. In
165 that case the Ttk widgets all support the "Dark Mode" appearance which was
166 introduced in 10.14. The command accepts the following values for the optional
167 newAppearance option: "aqua", "darkaqua", or "auto". If the appearance is set
168 to aqua or darkaqua then the window will be displayed with the corresponding
169 appearance independent of any preferences settings. If it is set to "auto"
170 the appearance will be determined by the preferences. This command can be
171 used to opt out of Dark Mode on a per-window basis. It may be best to run the "update" command before setting the appearance property, to allow the event loop to run.
172
173
174 - To determine the current appearance of a window in macOS 10.14 (Mojave) and
175 higher, one can use the command:
176 tk::unsupported::MacWindowStyle isdark window?
177 The boolean return value is true if the window is currently displayed with the
178 dark appearance.
179
180 - If you want to use Remote Debugging with Xcode, you need to set the
188181 environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
189182 cause us to force closing stdin & stdout. Otherwise, given how Xcode launches
190183 Wish remotely, they will be left open and then Wish & gdb will fight for stdin.
191184
192
193 3. Building Tcl/Tk on macOS
185 3. FullScreen, Split View and Tabbed Windows
186 --------------------------------------------
187
188 Since the release of OSX 10.6 (Snow Leopard) a steadily expanding sequence of
189 high level window operations have been added to Apple's window manager. These
190 operations are launched by user actions which are handled directly by the
191 window manager; they are not initiated by the application. In some, but not
192 all cases, the application is notified before and after the operations are
193 carried out.
194
195 In OSX releases up to and including 10.6 there were three buttons with
196 stoplight colors located on the left side of a window's title bar. The
197 function of the green button was to "zoom" or "maximize" the window, i.e. to
198 expand the window so that it fills the entire screen, while preserving the
199 appearance of the window including its title bar. The release of OSX 10.7
200 (Lion) introduced the "FullScreen" window which not only filled the screen but
201 also hid the window's title bar and the menu bar which normally appears at the
202 top of the screen. These hidden objects would only become visible when the
203 mouse hovered near the top of the screen. FullScreen mode was initiated by
204 pressing a button showing two outward pointing arrows located on the right side
205 of the title bar; it was terminated by pressing a similar button with inward
206 pointing arrows on the right hand side of the menu bar. In OSX 10.10
207 (Yosemite) the FullScreen button was removed. The green button was repurposed
208 to cause a window to become a FullScreen window. To zoom a window the user had
209 to hold down the option key while pressing the green button. The release of
210 OSX 10.11 added a third function to the green button: to create two half-screen
211 windows with hidden title bars and a hidden menu bar, called Split View
212 windows. If the green button is held down for one second its window expands to
213 fill half of the screen. It can be moved to one side or the other with the
214 mouse. The opposite side shows thumbnail images of other windows. Selecting
215 one of the thumbnails expands its window to fill that half of the screen. The
216 divider between the two windows can be moved to adjust the percentage of the
217 screen occupied by each of the two tiles. In OSX 10.12 (Sierra) Tabbed windows
218 were introduced. These allow an application with multiple windows to display
219 its windows as tabs within a single window frame. Clicking on a tab brings its
220 window into view. Tabs can be rearranged by dragging. Dragging a tab to the
221 desktop turns it into a separate window. Items in the Window menu can be used
222 to cycle through the tabs, move tabbed windows to separate windows, or merge a
223 set of separate windows as tabs in the same window frame.
224
225 Tk now fully supports all of these high level window operations on any system
226 where the operation exists. The FullScreen and Split View windows are handled
227 automatically with no action required on the part of the programmer. Tabbed
228 windows, on the other hand, require some attention from the programmer.
229 Because many of the operations with tabs are handled through the application's
230 Window menu, it is essential that an application provide a Windows menu to
231 avoid presenting a confusing interface to the user. This cannot be ignored, in
232 part because the systemwide Dock Preferences offers an option to always attempt
233 to open application windows as tabs. An application which does not provide a
234 Window menu will necessarily present a confusing interface to any user who has
235 selected this option.
236
237 A further complication is that it is not neccessarily appropriate for all of an
238 application's windows to be grouped together as tabs in the same frame. In
239 fact, the Apple guidelines insist that windows which are grouped together as
240 tabs should be similar to each other. The mechanism provided for arranging
241 this was to assign to each NSwindow a tabbingIdentifier, and to require that
242 all windows grouped together as tabs in the same window frame must have the
243 same tabbingIdentifier. A tabbingIdentifier is implemented as an arbitrary
244 string, and a system-generated default tabbingIdentifier is provided to all new
245 windows.
246
247 Tk provides a means for getting and setting the tabbingIdentifier of
248 the NSWindow underlying a Tk Window. This is handled by the command
249
250 tk::unsupported::MacWindowStyle tabbingid window ?newId?
251
252 (This command generates an error if used on OSX 10.11 or earlier, since the
253 tabbingIdentifier does not exist on those systems.) The command returns the
254 tabbingIdentifier which had been assigned to the window prior to execution of
255 the command. If the optional newId argument is omitted, the window's
256 tabbingIdentifier is not changed. Otherwise it is set to the string specified
257 by the argument.
258
259 Since NSWindows can only be grouped together as tabs if they all have the same
260 tabbingIdentifier, one can prevent a window from becoming a tab by giving it a
261 unique tabbingIdentifier. This is independent of any preferences setting. To
262 ensure that we maintain consistency, changing the tabbingIdentifier of a window
263 which is already displayed as a tab will also cause it to become a separate
264 window.
265
266 4. Ttk, Dark Mode and semantic colors
267 ---------------------------------------
268
269 With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua
270 appearance. Part of the implementation of the Dark Mode was to make
271 some of the named NSColors have dynamic values. Apple calls these
272 "semantic colors" because the name does not specify a specific color,
273 but rather refers to the context in which the color should be used.
274 Tk now provides the following semantic colors as system colors:
275 systemTextColor, systemTextBackgroundColor, systemSelectedTextColor,
276 systemSelectedTextBackgroundColor, systemControlTextColor,
277 systemDisabledControlTextColor, systemLabelColor, and
278 systemControlAccentColor. All of these except the last two were
279 present in OSX 10.0 (and those two are simulated in systems where they
280 do not exist). The change in 10.14 was that the RGB color value of
281 these colors became dynamic, meaning that the color value can change
282 when the application appearance changes. In particular, when a user
283 selects Dark Mode in the system preferences these colors change
284 appearance. For example systemTextColor is dark in Aqua and light in
285 DarkAqua. One additional color, systemSelectedTabTextColor, does not
286 exist in macOS but is used by Tk to match the different colors used
287 for Notebook tab text in different OS versions.
288
289 The default background and foreground colors of most of the Tk widgets
290 have been set to semantic colors, which means that the widgets will change
291 appearance, and remain usable, when Dark Mode is selected in the system
292 preferences. However, to get a close match to the native Dark Mode style it
293 is recommended to use Ttk widgets when possible.
294
295 Apple's tab view and GroupBox objects delimit their content by
296 displaying it within a rounded rectangle with a background color that
297 contrasts with the background of the containing object. This means
298 that the background color of a Ttk widget depends on how deeply it is
299 nested inside of other widgets that use contrasting backgrounds. To
300 support this, there are 8 contrasting system colors named
301 systemWindowBackgroundColor, and systemWindowBackgroundColor1 - 7.
302 The systemWindowBackgroundColor is the standard background for a
303 dialog window and the others match the contrasting background colors
304 used in ttk::notebooks and ttk::labelframes which are nested to the
305 corresponding depth.
306
307 5. Building Tcl/Tk on macOS
194308 ------------------------------
195309
196 - At least macOS 10.3 is required to build Tcl and TkX11, and macOS 10.6
197 is required to build TkAqua. The XCode application provides everything
198 needed to build Tk, but it is not necessary to install the full XCode.
310 - macOS 10.6 is required to build TkAqua and TkX11. The XCode application provides everything needed to build Tk, but it is not necessary to install the full XCode.
199311 It suffices to install the Command Line Tools package, which can be done
200312 by running the command:
201 xcode-selecct --install
313 xcode-select --install
202314
203315 - Tcl/Tk are most easily built as macOS frameworks via GNUmakefile in
204316 tcl/macosx and tk/macosx (see below for details), but can also be built with the
254366 ${USER}.pbxuser file (located inside the Tk.xcodeproj bundle directory) with a
255367 text editor.
256368
257 - To build universal binaries outside of the Xcode IDE, set CFLAGS as follows:
258 export CFLAGS="-arch i386 -arch x86_64 -arch ppc"
259 This requires macOS 10.4 and Xcode 2.4 (or Xcode 2.2 if -arch x86_64 is
260 omitted, but _not_ Xcode 2.1) and will work on any architecture (on PowerPC
261 Tiger you need to add "-isysroot /Developer/SDKs/MacOSX10.4u.sdk").
262 Note that configure requires CFLAGS to contain a least one architecture that can
263 be run on the build machine (i.e. ppc on G3/G4, ppc or ppc64 on G5, ppc or i386
264 on Core and ppc, i386 or x86_64 on Core2/Xeon).
265 Universal builds of Tcl TEA extensions are also possible with CFLAGS set as
266 above, they will be [load]able by universal as well as thin binaries of Tcl.
267
268369 - To enable weak-linking, set the MACOSX_DEPLOYMENT_TARGET environment variable
269370 to the minimal OS version the binaries should be able to run on, e.g:
270371 export MACOSX_DEPLOYMENT_TARGET=10.6
353454 TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
354455 The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.
355456
356 4. Details regarding the macOS port of Tk.
457 5. Details regarding the macOS port of Tk.
357458 -------------------------------------------
358459
359 4.1 About the event loop
460 5.1 About the event loop
360461 ~~~~~~~~~~~~~~~~~~~~~~~~
361462
362463 The main program in a typical OSX application looks like this (see
387488 all. Instead it uses the event loop built in to Tk. So the
388489 application must take care to replicate the important features of the
389490 method ourselves. The way that autorelease pools are handled is
390 discussed in 4.2 below. Here we discuss the event handling itself.
491 discussed in 5.2 below. Here we discuss the event handling itself.
391492
392493 The Tcl event loop simply consists of repeated calls to TclDoOneEvent.
393494 Each call to TclDoOneEvent begins by collecting all pending events from
415516 event to the Tcl queue.
416517
417518
418 4.2 Autorelease pools
519 5.2 Autorelease pools
419520 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
420521
421522 In order to carry out the job of managing autorelease pools, which
422523 would normally be handled by the [NSApp run] method, a private
423 NSAUtoreleasePool* property is added to the TkApplication subclass of
524 NSAutoreleasePool* property is added to the TkApplication subclass of
424525 NSApplication. The TkpInit function calls [NSApp _setup] which
425526 initializes this property by creating an NSAutoreleasePool prior to
426527 calling [NSApp finishLaunching]. This mimics the behavior of the
445546 One additional minor caveat for developers is that there are several
446547 steps of the Tk initialization which precede the call to TkpInit.
447548 Notably, the font package is initialized first. Since there is no
448 NSAUtoreleasePool in scope prior to calling TkpInit, the functions
549 NSAutoreleasePool in scope prior to calling TkpInit, the functions
449550 called in these preliminary stages need to create and drain their own
450551 NSAutoreleasePools whenever they call methods of Appkit objects
451552 (e.g. NSFont).
452553
453 4.3 Clipping regions and "ghost windows"
554 5.3 Clipping regions and "ghost windows"
454555 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
455556
456557 Another unusual aspect of the macOS port is its use of clipping
465566 rectangle, but drawing can be clipped to a smaller rectangle by
466567 calling TkpClipDrawableToRect.) The aboveVisRgn is the intersection of
467568 the window's bounding rectangle with the bounding rectangle of the
468 parent window. Much of the code in tkMacOSXSubindows.c is devoted to
569 parent window. Much of the code in tkMacOSXSubwindows.c is devoted to
469570 rebuilding these clipping regions whenever something changes in the
470571 layout of the windows. This turns out to be a tricky thing to do and
471572 it is extremely prone to errors which can be difficult to trace.
560661 windows are redrawn within the DisplayText function by some
561662 conditional code which is only used for macOS.
562663
563 5.0 Virtual events on 10.14
664 6.0 Virtual events on 10.14
564665 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
565666
566667 10.14 supports system appearance changes, and has added a "Dark Mode"
569670 your Tk app's appearance when the system appearance changes. Just bind
570671 your appearance-updating code to these virtual events and you will see
571672 it triggered when the system appearance toggles between dark and light.
673
674 7.0 Mac Services
675 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
676
677 With 8.6.10, Tk supports the Mac's NSServices API, documented at
678 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/introduction.html#//apple_ref/doc/uid/10000101-SW1
679 and in TIP 536 and Tk's man page. Tk presents a simple,
680 straightforward API to implement the Services functionality.
681
682 The Tk implementation of the NSServices API is intended for standalone
683 applications, such as one wrapped by the standalone version of Wish
684 and re-named into a different application. In particular such an
685 application would specify its own unique CFBundleIdentifier in its
686 Info.plist file. During development, however, if Wish itself is being
687 used as the receiver, it may be necessary to take some care to ensure
688 that the correct version of Wish.app is available as a receiver of
689 NSServices data.
690
691 When one macOS app uses NSServices to send data to another app that is
692 not running, LaunchServices will launch the receiver. LaunchServices
693 assumes that the CFBundleIdentifier uniquely identifies an app among
694 all of the apps installed on a system. But this may not be the case
695 for Wish.app if, for example, you have compiled Tk from source at some
696 time in the past. In that case the Tk build directory will contain
697 its own copy of Wish.app that will be visible to LaunchServices. It
698 may be necessary when testing your app to take some steps to ensure
699 that LaunchServices is launching the correct Wish.app. Instructions
700 for doing this are provided below.
701
702 The command line tool which manages the LaunchServices database has
703 an amazingly unwieldy path name. So, first, run this command:
704
705 alias lsregister='/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister'
706
707 Then you can reset the LaunchServices database like this:
708
709 $ lsregister -kill
710 $ lsregister -seed
711
712 To find out which versions of Wish.app have been located by
713 LaunchServices, run:
714
715 $ lsregister -dump | grep path | grep Wish
716
717 If more than one version of Wish is showing up in this list, eliminate
718 all of the unintended targets by running
719
720 lsregister -u /path/to/bad/Wish.app
721
722 Continue this until only the correct version of Wish shows up in the
723 list.
77 this file, and for a DISCLAIMER OF ALL WARRANTIES.
88 -->
99 <plist version="1.0">
10 <dict>
11 <key>CFBundleDevelopmentRegion</key>
12 <string>English</string>
13 <key>CFBundleDocumentTypes</key>
10 <dict>
11 <key>CFBundleDevelopmentRegion</key>
12 <string>English</string>
13 <key>CFBundleDocumentTypes</key>
14 <array>
15 <dict>
16 <key>CFBundleTypeExtensions</key>
1417 <array>
15 <dict>
16 <key>CFBundleTypeExtensions</key>
17 <array>
18 <string>tcl</string>
19 <string>TCL</string>
20 <string>*</string>
21 </array>
22 <key>CFBundleTypeMIMETypes</key>
23 <array>
24 <string>application/x-tcl</string>
25 <string>text/plain</string>
26 </array>
27 <key>CFBundleTypeName</key>
28 <string>NSStringPboardType</string>
29 <key>CFBundleTypeOSTypes</key>
30 <array>
31 <string>TEXT</string>
32 <string>****</string>
33 </array>
34 <key>CFBundleTypeRole</key>
35 <string>Viewer</string>
36 </dict>
18 <string>tcl</string>
19 <string>TCL</string>
20 <string>*</string>
3721 </array>
38 <key>CFBundleExecutable</key>
22 <key>CFBundleTypeMIMETypes</key>
23 <array>
24 <string>application/x-tcl</string>
25 <string>text/plain</string>
26 </array>
27 <key>CFBundleTypeName</key>
28 <string>NSStringPboardType</string>
29 <key>CFBundleTypeOSTypes</key>
30 <array>
31 <string>TEXT</string>
32 <string>****</string>
33 </array>
34 <key>CFBundleTypeRole</key>
35 <string>Viewer</string>
36 </dict>
37 </array>
38 <key>CFBundleURLTypes</key>
39 <array>
40 <dict>
41 <key>CFBundleTypeRole</key>
42 <string>Viewer</string>
43 <key>CFBundleURLSchemes</key>
44 <array>
45 <string>foo</string>
46 </array>
47 <key>CFBundleURLName</key>
48 <string>Get Foo</string>
49 </dict>
50 </array>
51 <key>CFBundleExecutable</key>
52 <string>Wish</string>
53 <key>CFBundleGetInfoString</key>
54 <string>Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@,
55 Copyright © 1989-@TK_YEAR@ Tcl Core Team,
56 Copyright © 1989-@TK_YEAR@ Contributors,
57 Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech Communications LLC,
58 Copyright © 2014-@TK_YEAR@ Marc Culler,
59 Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
60 Copyright © 2001-2009 Apple Inc.,
61 Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
62 <key>CFBundleIconFile</key>
63 <string>Wish.icns</string>
64 <key>CFBundleIdentifier</key>
65 <string>com.tcltk.wish</string>
66 <key>CFBundleInfoDictionaryVersion</key>
67 <string>6.0</string>
68 <key>CFBundleLocalizations</key>
69 <array>
70 @CFBUNDLELOCALIZATIONS@
71 </array>
72 <key>CFBundleName</key>
73 <string>Wish</string>
74 <key>CFBundlePackageType</key>
75 <string>APPL</string>
76 <key>CFBundleShortVersionString</key>
77 <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
78 <key>CFBundleSignature</key>
79 <string>WiSH</string>
80 <key>CFBundleVersion</key>
81 <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
82 <key>LSMinimumSystemVersion</key>
83 <string>10.6.0</string>
84 <key>LSRequiresCarbon</key>
85 <true/>
86 <key>NSAppleScriptEnabled</key>
87 <true/>
88 <key>OSAScriptingDefinition</key>
89 <string>Wish.sdef</string>
90 <key>NSHighResolutionCapable</key>
91 <string>True</string>
92 <key>NSServices</key>
93 <array>
94 <dict>
95 <key>NSMessage</key>
96 <string>provideService</string>
97 <key>NSPortName</key>
3998 <string>Wish</string>
40 <key>CFBundleGetInfoString</key>
41 <string>Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@,
42 Copyright © 1989-@TK_YEAR@ Tcl Core Team,
43 Copyright © 1989-@TK_YEAR@ Contributors,
44 Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech
45 Communications LLC,
46 Copyright © 2014-@TK_YEAR@ Marc Culler,
47 Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
48 Copyright © 2001-2009 Apple Inc.,
49 Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
50 <key>CFBundleIconFile</key>
51 <string>Wish.icns</string>
52 <key>CFBundleIdentifier</key>
53 <string>com.tcltk.wish</string>
54 <key>CFBundleInfoDictionaryVersion</key>
55 <string>6.0</string>
56 <key>CFBundleLocalizations</key>
99 <key>NSSendTypes</key>
57100 <array>
58 @CFBUNDLELOCALIZATIONS@
101 <string>NSStringPboardType</string>
102 <string>NSPasteboardTypeString</string>
59103 </array>
60 <key>CFBundleName</key>
61 <string>Wish</string>
62 <key>CFBundlePackageType</key>
63 <string>APPL</string>
64 <key>CFBundleShortVersionString</key>
65 <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
66 <key>CFBundleSignature</key>
67 <string>WiSH</string>
68 <key>CFBundleVersion</key>
69 <string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
70 <key>LSMinimumSystemVersion</key>
71 <string>10.6.0</string>
72 <key>LSRequiresCarbon</key>
73 <true/>
74 <key>NSAppleScriptEnabled</key>
75 <true/>
76 <key>OSAScriptingDefinition</key>
77 <string>Wish.sdef</string>
78 <key>NSHighResolutionCapable</key>
79 <string>True</string>
80 </dict>
104 </dict>
105 </array>
106 </dict>
81107 </plist>
3232 <type type="text"/>
3333 </result>
3434 </command>
35 <command name="open location" code="GURLGURL"
36 description="Open a URL.">
37 <direct-parameter description="URL" type="text">
38 <type type="text"/>
39 </direct-parameter>
40 <result description="Result">
41 <type type="text"/>
42 </result>
43 </command>
3544 </suite>
3645 </dictionary>
22862286 TK_VERSION=8.6
22872287 TK_MAJOR_VERSION=8
22882288 TK_MINOR_VERSION=6
2289 TK_PATCH_LEVEL=".9"
2289 TK_PATCH_LEVEL=".10"
22902290 VERSION=${TK_VERSION}
22912291 LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
22922292
23612361 for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
23622362 `ls -d /Library/Frameworks 2>/dev/null` \
23632363 `ls -d /Network/Library/Frameworks 2>/dev/null` \
2364 `ls -d /System/Library/Frameworks 2>/dev/null` \
23652364 ; do
23662365 if test -f "$i/Tcl.framework/tclConfig.sh" ; then
23672366 ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
23782377 `ls -d /usr/local/lib 2>/dev/null` \
23792378 `ls -d /usr/contrib/lib 2>/dev/null` \
23802379 `ls -d /usr/pkg/lib 2>/dev/null` \
2380 `ls -d /usr/lib/tcl8.6 2>/dev/null` \
23812381 `ls -d /usr/lib 2>/dev/null` \
23822382 `ls -d /usr/lib64 2>/dev/null` \
23832383 `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
45264526 if test "`uname -s`" = "AIX" ; then
45274527 tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
45284528 fi
4529 if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
4530 tcl_cv_sys_version=NetBSD-Debian
4531 fi
45294532 fi
45304533 fi
45314534
55955598 SHLIB_SUFFIX=".dylib"
55965599 DL_OBJS="tclLoadDyld.o"
55975600 DL_LIBS=""
5598 # Don't use -prebind when building for Mac OS X 10.4 or later only:
5599 if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \
5600 "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then :
5601
5602 LDFLAGS="$LDFLAGS -prebind"
5603 fi
56045601 LDFLAGS="$LDFLAGS -headerpad_max_install_names"
56055602 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5
56065603 $as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; }
81228119 XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
81238120 if test "$found_xft" = "no" ; then
81248121 found_xft=yes
8125 XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
8126 XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
8122 XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
8123 XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
81278124 fi
81288125 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_xft" >&5
81298126 $as_echo "$found_xft" >&6; }
86138610 TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
86148611 fi
86158612
8616 TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
8613 test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
86178614 PRIVATE_INCLUDE_DIR='$(includedir)'
86188615 HTML_DIR='$(DISTDIR)/html'
86198616 TK_PKG_DIR='tk$(VERSION)'
4848
4949 #define builtInIconSize 32
5050
51 #define OSTYPE_TO_UTI(x) (NSString *)UTTypeCreatePreferredIdentifierForTag( \
52 kUTTagClassOSType, UTCreateStringForOSType(x), nil)
53
5154 static Tcl_HashTable iconBitmapTable = {};
5255 typedef struct {
5356 int kind, width, height;
106109 }
107110 }
108111 }
109
110 /*
111 *----------------------------------------------------------------------
112 *
113 * GetBitmapForIcon --
114 *
115 * Results:
116 * Bitmap for the given IconRef.
112
113
114 /*
115 *----------------------------------------------------------------------
116 *
117 * PixmapFromImage --
118 *
119 * Results:
120 * Returns a Pixmap with an NSImage drawn into it.
117121 *
118122 * Side effects:
119123 * None.
122126 */
123127
124128 static Pixmap
125 GetBitmapForIcon(
129 PixmapFromImage(
126130 Display *display,
127 IconRef icon,
131 NSImage* image,
128132 CGSize size)
129133 {
130134 TkMacOSXDrawingContext dc;
133137 pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0);
134138 if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
135139 if (dc.context) {
136 const CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
137 .tx = 0, .ty = size.height };
138 const CGRect r = { .origin = { .x = 0, .y = 0 }, .size = size };
139
140 CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
141 .tx = 0, .ty = size.height};
140142 CGContextConcatCTM(dc.context, t);
141 PlotIconRefInContext(dc.context, &r, kAlignAbsoluteCenter,
142 kTransformNone, NULL, kPlotIconRefNormalFlags, icon);
143 [NSGraphicsContext saveGraphicsState];
144 [NSGraphicsContext setCurrentContext:[NSGraphicsContext
145 graphicsContextWithGraphicsPort:dc.context
146 flipped:NO]];
147 [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
148 operation:NSCompositeCopy fraction:1.0];
149 [NSGraphicsContext restoreGraphicsState];
143150 }
144151 TkMacOSXRestoreDrawingContext(&dc);
145152 }
146153 return pixmap;
147154 }
155
148156
149157 /*
150158 *----------------------------------------------------------------------
167175 Display *display,
168176 const void *source) /* Info about the icon to build. */
169177 {
170 Pixmap pixmap;
171 IconRef icon;
172 OSErr err;
173
174 err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
175 PTR2UINT(source), &icon);
176 if (err == noErr) {
177 pixmap = GetBitmapForIcon(display, icon, CGSizeMake(builtInIconSize,
178 builtInIconSize));
179 ReleaseIconRef(icon);
180 } else {
181 pixmap = Tk_GetPixmap(display, None, builtInIconSize,
182 builtInIconSize, 0);
183 }
178 NSString *iconUTI = OSTYPE_TO_UTI(PTR2UINT(source));
179 NSImage *iconImage = [[NSWorkspace sharedWorkspace]
180 iconForFileType: iconUTI];
181 CGSize size = CGSizeMake(builtInIconSize, builtInIconSize);
182 Pixmap pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
184183 return pixmap;
185184 }
185
186186
187187 /*
188188 *----------------------------------------------------------------------
209209 Tcl_UtfToExternalDString(encoding, s, -1, &ds);
210210 if (Tcl_DStringLength(&ds) <= 4) {
211211 char string[4] = {};
212 memcpy(string, Tcl_DStringValue(&ds), (size_t) Tcl_DStringLength(&ds));
212 memcpy(string, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
213213 *t = (OSType) string[0] << 24 | (OSType) string[1] << 16 |
214214 (OSType) string[2] << 8 | (OSType) string[3];
215215 result = TCL_OK;
218218 Tcl_FreeEncoding(encoding);
219219 return result;
220220 }
221
221222
222223 /*
223224 *----------------------------------------------------------------------
308309 }
309310 }
310311 if (image) {
311 TkMacOSXDrawingContext dc;
312 int depth = 0;
313
314 #ifdef MAC_OSX_TK_TODO
315 for (NSImageRep *r in [image representations]) {
316 NSInteger bitsPerSample = [r bitsPerSample];
317 if (bitsPerSample && bitsPerSample > depth) {
318 depth = bitsPerSample;
319 };
320 }
321 if (depth == 1) {
322 /* TODO: convert BW NSImage to CGImageMask */
323 }
324 #endif
325 pixmap = Tk_GetPixmap(display, None, size.width, size.height, depth);
326312 *width = size.width;
327313 *height = size.height;
328 if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
329 if (dc.context) {
330 CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
331 .tx = 0, .ty = size.height};
332
333 CGContextConcatCTM(dc.context, t);
334 [NSGraphicsContext saveGraphicsState];
335 [NSGraphicsContext setCurrentContext:[NSGraphicsContext
336 graphicsContextWithGraphicsPort:dc.context flipped:NO]];
337 [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
338 operation:NSCompositeCopy fraction:1.0];
339 [NSGraphicsContext restoreGraphicsState];
340 }
341 TkMacOSXRestoreDrawingContext(&dc);
342 }
314 pixmap = PixmapFromImage(display, image, NSSizeToCGSize(size));
343315 } else if (name) {
344316 OSType iconType;
345317 if (OSTypeFromString(name, &iconType) == TCL_OK) {
346 IconRef icon;
347 OSErr err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
348 iconType, &icon);
349 if (err == noErr) {
350 pixmap = GetBitmapForIcon(display, icon, NSSizeToCGSize(size));
351 *width = size.width;
352 *height = size.height;
353 ReleaseIconRef(icon);
354 }
318 NSString *iconUTI = OSTYPE_TO_UTI(iconType);
319 printf("Found image for UTI %s\n", iconUTI.UTF8String);
320 NSImage *iconImage = [[NSWorkspace sharedWorkspace]
321 iconForFileType: iconUTI];
322 pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
355323 }
356324 }
357325 return pixmap;
00 /*
11 * tkMacOSXButton.c --
22 *
3 * This file implements the Macintosh specific portion of the
4 * button widgets.
3 * This file implements the Macintosh specific portion of the button
4 * widgets.
55 *
66 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
77 * Copyright 2001, Apple Computer, Inc.
2828 * be allowed when drawing the HITheme button.
2929 */
3030
31 #define HI_PADX 2
31 #define HI_PADX 14
3232 #define HI_PADY 1
3333
3434 /*
35 * Some defines used to control what type of control is drawn.
36 */
37
38 #define DRAW_LABEL 0 /* Labels are treated genericly. */
39 #define DRAW_CONTROL 1 /* Draw using the Native control. */
40 #define DRAW_CUSTOM 2 /* Make our own button drawing. */
41 #define DRAW_BEVEL 3
42
43 /*
4435 * The delay in milliseconds between pulsing default button redraws.
4536 */
4637 #define PULSE_TIMER_MSECS 62 /* Largest value that didn't look stuttery */
5142
5243
5344 typedef struct {
54 int drawType;
5545 Tk_3DBorder border;
5646 int relief;
5747 int offset; /* 0 means this is a normal widget. 1 means
7969 * Forward declarations for procedures defined later in this file:
8070 */
8171
82
83 static void ButtonBackgroundDrawCB (const HIRect *btnbounds, MacButton *ptr,
84 SInt16 depth, Boolean isColorDev);
85 static void ButtonContentDrawCB (const HIRect *bounds, ThemeButtonKind kind,
86 const HIThemeButtonDrawInfo *info, MacButton *ptr, SInt16 depth,
87 Boolean isColorDev);
88 static void ButtonEventProc(ClientData clientData, XEvent *eventPtr);
89 static void TkMacOSXComputeButtonParams (TkButton * butPtr, ThemeButtonKind* btnkind,
90 HIThemeButtonDrawInfo* drawinfo);
91 static int TkMacOSXComputeButtonDrawParams (TkButton * butPtr, DrawParams * dpPtr);
92 static void TkMacOSXDrawButton (MacButton *butPtr, GC gc, Pixmap pixmap);
93 static void DrawButtonImageAndText(TkButton* butPtr);
94 static void PulseDefaultButtonProc(ClientData clientData);
95
72 static void ButtonBackgroundDrawCB(const HIRect *btnbounds,
73 MacButton *ptr, SInt16 depth, Boolean isColorDev);
74 static void ButtonContentDrawCB(const HIRect *bounds,
75 ThemeButtonKind kind,
76 const HIThemeButtonDrawInfo *info, MacButton *ptr,
77 SInt16 depth, Boolean isColorDev);
78 static void ButtonEventProc(ClientData clientData,
79 XEvent *eventPtr);
80 static void TkMacOSXComputeButtonParams(TkButton *butPtr,
81 ThemeButtonKind *btnkind,
82 HIThemeButtonDrawInfo *drawinfo);
83 static int TkMacOSXComputeButtonDrawParams(TkButton *butPtr,
84 DrawParams * dpPtr);
85 static void TkMacOSXDrawButton(MacButton *butPtr, GC gc,
86 Pixmap pixmap);
87 static void DrawButtonImageAndText(TkButton *butPtr);
88 static void PulseDefaultButtonProc(ClientData clientData);
9689
9790 /*
9891 * The class procedure table for the button widgets.
10497 };
10598
10699 static int bCount;
107
100
108101 /*
109102 *----------------------------------------------------------------------
110103 *
111104 * TkpButtonSetDefaults --
112105 *
113 * This procedure is invoked before option tables are created for
114 * buttons. It modifies some of the default values to match the current
115 * values defined for this platform.
106 * This procedure is invoked before option tables are created for buttons.
107 * It modifies some of the default values to match the current values
108 * defined for this platform.
116109 *
117110 * Results:
118111 * Some of the default values in *specPtr are modified.
126119 void
127120 TkpButtonSetDefaults()
128121 {
129 /*No-op.*/
130 }
131
122 /*No-op.*/
123 }
132124
133125 /*
134126 *----------------------------------------------------------------------
150142 TkpCreateButton(
151143 Tk_Window tkwin)
152144 {
153 MacButton *macButtonPtr = (MacButton *) ckalloc(sizeof(MacButton));
145 MacButton *macButtonPtr = ckalloc(sizeof(MacButton));
154146
155147 Tk_CreateEventHandler(tkwin, ActivateMask,
156 ButtonEventProc, (ClientData) macButtonPtr);
148 ButtonEventProc, macButtonPtr);
157149 macButtonPtr->id = bCount++;
158150 macButtonPtr->flags = FIRST_DRAW;
159151 macButtonPtr->btnkind = kThemePushButton;
161153 bzero(&macButtonPtr->drawinfo, sizeof(macButtonPtr->drawinfo));
162154 bzero(&macButtonPtr->lastdrawinfo, sizeof(macButtonPtr->lastdrawinfo));
163155
164 return (TkButton *)macButtonPtr;
156 return (TkButton *) macButtonPtr;
165157 }
166158
167159 /*
169161 *
170162 * TkpDisplayButton --
171163 *
172 * This procedure is invoked to display a button widget. It is
173 * normally invoked as an idle handler.
164 * This procedure is invoked to display a button widget. It is normally
165 * invoked as an idle handler.
174166 *
175167 * Results:
176168 * None.
177169 *
178170 * Side effects:
179 * Commands are output to X to display the button in its
180 * current mode. The REDRAW_PENDING flag is cleared.
171 * Commands are output to X to display the button in its current mode. The
172 * REDRAW_PENDING flag is cleared.
181173 *
182174 *----------------------------------------------------------------------
183175 */
186178 TkpDisplayButton(
187179 ClientData clientData) /* Information about widget. */
188180 {
189 MacButton *macButtonPtr = (MacButton *) clientData;
190 TkButton *butPtr = (TkButton *) clientData;
181 MacButton *macButtonPtr = clientData;
182 TkButton *butPtr = clientData;
191183 Tk_Window tkwin = butPtr->tkwin;
192184 Pixmap pixmap;
193185 DrawParams* dpPtr = &macButtonPtr->drawParams;
194186 int needhighlight = 0;
195187
188 if (butPtr->flags & BUTTON_DELETED) {
189 return;
190 }
196191 butPtr->flags &= ~REDRAW_PENDING;
197192 if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
198193 return;
199194 }
200195 pixmap = (Pixmap) Tk_WindowId(tkwin);
201 TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));
202
203 if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr) ) {
204 macButtonPtr->useTkText = 0;
205 } else {
206 macButtonPtr->useTkText = 1;
207 }
208
209196
210197 /*
211198 * Set up clipping region. Make sure the we are using the port
212199 * for this button, or we will set the wrong window's clip.
213200 */
214201
202 TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));
203
204 if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) {
205 macButtonPtr->useTkText = 0;
206 } else {
207 macButtonPtr->useTkText = 1;
208 }
215209 if (macButtonPtr->useTkText) {
216210 if (butPtr->type == TYPE_BUTTON) {
217211 Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0,
221215 Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
222216 }
223217
224 /* Display image or bitmap or text for labels or custom controls. */
218 /*
219 * Display image or bitmap or text for labels or custom controls.
220 */
221
225222 DrawButtonImageAndText(butPtr);
226 needhighlight = 1;
223 needhighlight = 1;
227224 } else {
228 /* Draw the native portion of the buttons. */
225 /*
226 * Draw the native portion of the buttons.
227 */
228
229229 TkMacOSXDrawButton(macButtonPtr, dpPtr->gc, pixmap);
230230
231 /* Draw highlight border, if needed. */
231 /*
232 * Ask for the highlight border, if needed.
233 */
234
232235 if (butPtr->highlightWidth < 3) {
233236 needhighlight = 1;
234237 }
235238 }
236239
237 /* Draw highlight border, if needed. */
240 /*
241 * Draw highlight border, if needed.
242 */
243
238244 if (needhighlight) {
239 if ((butPtr->flags & GOT_FOCUS)) {
240 Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,
241 Tk_Width(tkwin), Tk_Height(tkwin),
242 butPtr->highlightWidth, TK_RELIEF_SOLID);
243 }
245 GC gc = NULL;
246 if ((butPtr->flags & GOT_FOCUS) && butPtr->highlightColorPtr) {
247 gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
248 } else if (butPtr->type == TYPE_LABEL) {
249 gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), pixmap);
250 }
251 if (gc) {
252 TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth);
253 }
244254 }
245255 }
246256
249259 *
250260 * TkpComputeButtonGeometry --
251261 *
252 * After changes in a button's text or bitmap, this procedure
253 * recomputes the button's geometry and passes this information
254 * along to the geometry manager for the window.
262 * After changes in a button's text or bitmap, this procedure recomputes
263 * the button's geometry and passes this information along to the geometry
264 * manager for the window.
255265 *
256266 * Results:
257267 * None.
268278 {
269279 int width = 0, height = 0, charWidth = 1, haveImage = 0, haveText = 0;
270280 int txtWidth = 0, txtHeight = 0;
271 MacButton *mbPtr = (MacButton*)butPtr;
281 MacButton *mbPtr = (MacButton *) butPtr;
272282 Tk_FontMetrics fm;
273 DrawParams drawParams;
274
275 /*
276 * First figure out the size of the contents of the button.
277 */
283 char *text = Tcl_GetString(butPtr->textPtr);
278284
279285 TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
280286
282288 * If the indicator is on, get its size.
283289 */
284290
285 if ( butPtr->indicatorOn ) {
286 switch (butPtr->type) {
287 case TYPE_RADIO_BUTTON:
288 GetThemeMetric(kThemeMetricRadioButtonWidth, (SInt32 *)&butPtr->indicatorDiameter);
289 break;
290 case TYPE_CHECK_BUTTON:
291 GetThemeMetric(kThemeMetricCheckBoxWidth, (SInt32 *)&butPtr->indicatorDiameter);
292 break;
293 default:
294 break;
295 }
296 /* Allow 2px extra space next to the indicator. */
297 butPtr->indicatorSpace = butPtr->indicatorDiameter + 2;
291 if (butPtr->indicatorOn) {
292 switch (butPtr->type) {
293 case TYPE_RADIO_BUTTON:
294 GetThemeMetric(kThemeMetricRadioButtonWidth,
295 (SInt32 *) &butPtr->indicatorDiameter);
296 break;
297 case TYPE_CHECK_BUTTON:
298 GetThemeMetric(kThemeMetricCheckBoxWidth,
299 (SInt32 *) &butPtr->indicatorDiameter);
300 break;
301 default:
302 break;
303 }
304
305 /*
306 * Allow 2px extra space next to the indicator.
307 */
308
309 butPtr->indicatorSpace = butPtr->indicatorDiameter + 2;
298310 } else {
299 butPtr->indicatorSpace = 0;
300 butPtr->indicatorDiameter = 0;
311 butPtr->indicatorSpace = 0;
312 butPtr->indicatorDiameter = 0;
301313 }
302314
303315 if (butPtr->image != NULL) {
311323 if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {
312324 Tk_FreeTextLayout(butPtr->textLayout);
313325 butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
314 Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,
315 butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
316
317 txtWidth = butPtr->textWidth;
318 txtHeight = butPtr->textHeight;
319 charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
320 Tk_GetFontMetrics(butPtr->tkfont, &fm);
321 haveText = (txtWidth != 0 && txtHeight != 0);
326 text, -1, butPtr->wrapLength, butPtr->justify, 0,
327 &butPtr->textWidth, &butPtr->textHeight);
328
329 txtWidth = butPtr->textWidth + 2*butPtr->padX;
330 txtHeight = butPtr->textHeight + 2*butPtr->padY;
331 haveText = 1;
322332 }
323333
324334 if (haveImage && haveText) { /* Image and Text */
325335 switch ((enum compound) butPtr->compound) {
326 case COMPOUND_TOP:
327 case COMPOUND_BOTTOM:
328 /*
329 * Image is above or below text.
330 */
331
332 height += txtHeight + butPtr->padY;
333 width = (width > txtWidth ? width : txtWidth);
334 break;
335 case COMPOUND_LEFT:
336 case COMPOUND_RIGHT:
337 /*
338 * Image is left or right of text.
339 */
340
341 width += txtWidth + butPtr->padX;
342 height = (height > txtHeight ? height : txtHeight);
343 break;
344 case COMPOUND_CENTER:
345 /*
346 * Image and text are superimposed.
347 */
348
349 width = (width > txtWidth ? width : txtWidth);
350 height = (height > txtHeight ? height : txtHeight);
351 break;
352 default:
353 break;
336 case COMPOUND_TOP:
337 case COMPOUND_BOTTOM:
338 /*
339 * Image is above or below text.
340 */
341
342 height += txtHeight + butPtr->padY;
343 width = (width > txtWidth ? width : txtWidth);
344 break;
345 case COMPOUND_LEFT:
346 case COMPOUND_RIGHT:
347 /*
348 * Image is left or right of text.
349 */
350
351 width += txtWidth + 2*butPtr->padX;
352 height = (height > txtHeight ? height : txtHeight);
353 break;
354 case COMPOUND_CENTER:
355 /*
356 * Image and text are superimposed.
357 */
358
359 width = (width > txtWidth ? width : txtWidth);
360 height = (height > txtHeight ? height : txtHeight);
361 break;
362 default:
363 break;
354364 }
355365 width += butPtr->indicatorSpace;
356
357366 } else if (haveImage) { /* Image only */
358 width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace;
359 height = butPtr->height > 0 ? butPtr->height : height;
360
367 width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace;
368 height = butPtr->height > 0 ? butPtr->height : height;
369 if (butPtr->type == TYPE_BUTTON) {
370 /*
371 * Allow room to shift the image.
372 */
373 width += 2;
374 height += 2;
375 }
361376 } else { /* Text only */
362377 width = txtWidth + butPtr->indicatorSpace;
363378 height = txtHeight;
364379 if (butPtr->width > 0) {
365 width = butPtr->width * charWidth;
380 charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
381 width = butPtr->width * charWidth + 2*butPtr->padX;
366382 }
367383 if (butPtr->height > 0) {
368 height = butPtr->height * fm.linespace;
369 }
370 }
371
372 /* Add padding */
373 width += 2 * butPtr->padX;
374 height += 2 * butPtr->padY;
384 Tk_GetFontMetrics(butPtr->tkfont, &fm);
385 height = butPtr->height * fm.linespace + 2*butPtr->padY;
386 }
387 }
375388
376389 /*
377390 * Now figure out the size of the border decorations for the button.
381394 butPtr->highlightWidth = 0;
382395 }
383396
384 butPtr->inset = 0;
385 butPtr->inset += butPtr->highlightWidth;
386
387 if (TkMacOSXComputeButtonDrawParams(butPtr,&drawParams)) {
388 HIRect tmpRect;
389 HIRect contBounds;
390 int paddingx = 0;
391 int paddingy = 0;
392
393 tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY);
394
395 HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
396 /* If the content region has a minimum height, match it. */
397 if (height < contBounds.size.height) {
398 height = contBounds.size.height;
399 }
400
401 /* If the content region has a minimum width, match it. */
402 if (width < contBounds.size.width) {
403 width = contBounds.size.width;
404 }
405
406 /* Pad to fill difference between content bounds and button bounds. */
407 paddingx = contBounds.origin.x;
408 paddingy = contBounds.origin.y;
409
410 if (height < paddingx - 4) {
411 /* can't have buttons much shorter than button side diameter. */
412 height = paddingx - 4;
413 }
414
415 } else {
416 height += butPtr->borderWidth*2;
417 width += butPtr->borderWidth*2;
418 }
397 butPtr->inset = butPtr->borderWidth + butPtr->highlightWidth;
419398
420399 width += butPtr->inset*2;
421400 height += butPtr->inset*2;
422401 if ([NSApp macMinorVersion] == 6) {
423 width += 12;
424 }
425
402 width += 12;
403 }
404 if (mbPtr->btnkind == kThemePushButton) {
405 HIRect tmpRect;
406 HIRect contBounds;
407
408 /*
409 * A PushButton has a minimum size. We make sure that we are not
410 * underestimating the size by requesting the content size of a
411 * Pushbutton whose overall size is our content size expanded by the
412 * standard padding.
413 */
414
415 tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY);
416 HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
417 if (height < contBounds.size.height) {
418 height = contBounds.size.height;
419 }
420 if (width < contBounds.size.width) {
421 width = contBounds.size.width;
422 }
423 height += 2*HI_PADY;
424 width += 2*HI_PADX;
425 }
426426 Tk_GeometryRequest(butPtr->tkwin, width, height);
427427 Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
428428 }
429
429
430430 /*
431431 *----------------------------------------------------------------------
432432 *
433433 * DrawButtonImageAndText --
434434 *
435 * Draws the image and text associated with a button or label.
436 *
437 * Results:
438 * None.
439 *
440 * Side effects:
441 * The image and text are drawn.
435 * Draws the image and text associated with a button or label.
436 *
437 * Results:
438 * None.
439 *
440 * Side effects:
441 * The image and text are drawn.
442442 *
443443 *----------------------------------------------------------------------
444444 */
445445 static void
446446 DrawButtonImageAndText(
447 TkButton* butPtr)
448 {
449
450 MacButton *mbPtr = (MacButton*)butPtr;
451 Tk_Window tkwin = butPtr->tkwin;
452 Pixmap pixmap;
453 int haveImage = 0;
454 int haveText = 0;
455 int imageWidth = 0;
456 int imageHeight = 0;
457 int imageXOffset = 0;
458 int imageYOffset = 0;
459 int textXOffset = 0;
460 int textYOffset = 0;
461 int width = 0;
462 int height = 0;
463 int fullWidth = 0;
464 int fullHeight = 0;
465 int pressed = 0;
466
447 TkButton *butPtr)
448 {
449
450 MacButton *mbPtr = (MacButton *) butPtr;
451 Tk_Window tkwin = butPtr->tkwin;
452 Pixmap pixmap;
453 int haveImage = 0, haveText = 0, pressed = 0;
454 int imageWidth = 0, imageHeight = 0;
455 int imageXOffset = 0, imageYOffset = 0;
456 int textXOffset = 0, textYOffset = 0;
457 int width = 0, height = 0;
458 int fullWidth = 0, fullHeight = 0;
459 DrawParams *dpPtr = &mbPtr->drawParams;
467460
468461 if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
469462 return;
470463 }
471464
472 DrawParams* dpPtr = &mbPtr->drawParams;
473 pixmap = (Pixmap)Tk_WindowId(tkwin);
465 pixmap = (Pixmap) Tk_WindowId(tkwin);
474466
475467 if (butPtr->image != None) {
476468 Tk_SizeOfImage(butPtr->image, &width, &height);
480472 haveImage = 1;
481473 }
482474
483 imageWidth = width;
475 imageWidth = width;
484476 imageHeight = height;
485477
486478 if (mbPtr->drawinfo.state == kThemeStatePressed) {
487 /* Offset bitmaps by a bit when the button is pressed. */
488479 pressed = 1;
489480 }
490481
491482 haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
492483 if (haveImage && haveText) { /* Image and Text */
493 int x;
494 int y;
495 textXOffset = 0;
496 textYOffset = 0;
497 fullWidth = 0;
498 fullHeight = 0;
484 int x, y;
499485
500486 switch ((enum compound) butPtr->compound) {
501487 case COMPOUND_TOP:
502 case COMPOUND_BOTTOM: {
503 /* Image is above or below text */
504 if (butPtr->compound == COMPOUND_TOP) {
505 textYOffset = height + butPtr->padY;
506 } else {
507 imageYOffset = butPtr->textHeight + butPtr->padY;
508 }
509 fullHeight = height + butPtr->textHeight + butPtr->padY;
510 fullWidth = (width > butPtr->textWidth ? width :
511 butPtr->textWidth);
512 textXOffset = (fullWidth - butPtr->textWidth)/2;
513 imageXOffset = (fullWidth - width)/2;
514 break;
515 }
488 case COMPOUND_BOTTOM:
489 /* Image is above or below text */
490 if (butPtr->compound == COMPOUND_TOP) {
491 textYOffset = height + butPtr->padY;
492 } else {
493 imageYOffset = butPtr->textHeight + butPtr->padY;
494 }
495 fullHeight = height + butPtr->textHeight + butPtr->padY;
496 fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth);
497 textXOffset = (fullWidth - butPtr->textWidth)/2;
498 imageXOffset = (fullWidth - width)/2;
499 break;
516500 case COMPOUND_LEFT:
517 case COMPOUND_RIGHT: {
518 /*
519 * Image is left or right of text
520 */
521
522 if (butPtr->compound == COMPOUND_LEFT) {
523 textXOffset = width + butPtr->padX;
524 } else {
525 imageXOffset = butPtr->textWidth + butPtr->padX;
526 }
527 fullWidth = butPtr->textWidth + butPtr->padX + width;
528 fullHeight = (height > butPtr->textHeight ? height :
529 butPtr->textHeight);
530 textYOffset = (fullHeight - butPtr->textHeight)/2;
531 imageYOffset = (fullHeight - height)/2;
532 break;
533 }
534 case COMPOUND_CENTER: {
535 /*
536 * Image and text are superimposed
537 */
538
539 fullWidth = (width > butPtr->textWidth ? width :
540 butPtr->textWidth);
541 fullHeight = (height > butPtr->textHeight ? height :
542 butPtr->textHeight);
543 textXOffset = (fullWidth - butPtr->textWidth)/2;
544 imageXOffset = (fullWidth - width)/2;
545 textYOffset = (fullHeight - butPtr->textHeight)/2;
546 imageYOffset = (fullHeight - height)/2;
547 break;
548 }
501 case COMPOUND_RIGHT:
502 /*
503 * Image is left or right of text
504 */
505
506 if (butPtr->compound == COMPOUND_LEFT) {
507 textXOffset = width + butPtr->padX;
508 } else {
509 imageXOffset = butPtr->textWidth + butPtr->padX;
510 }
511 fullWidth = butPtr->textWidth + butPtr->padX + width;
512 fullHeight = (height > butPtr->textHeight ? height :
513 butPtr->textHeight);
514 textYOffset = (fullHeight - butPtr->textHeight)/2;
515 imageYOffset = (fullHeight - height)/2;
516 break;
517 case COMPOUND_CENTER:
518 /*
519 * Image and text are superimposed
520 */
521
522 fullWidth = (width > butPtr->textWidth ? width :
523 butPtr->textWidth);
524 fullHeight = (height > butPtr->textHeight ? height :
525 butPtr->textHeight);
526 textXOffset = (fullWidth - butPtr->textWidth)/2;
527 imageXOffset = (fullWidth - width)/2;
528 textYOffset = (fullHeight - butPtr->textHeight)/2;
529 imageYOffset = (fullHeight - height)/2;
530 break;
549531 default:
550 break;
532 break;
551533 }
552534
553535 TkComputeAnchor(butPtr->anchor, tkwin,
569551 }
570552 imageXOffset += x;
571553 imageYOffset += y;
572 textYOffset -= 1;
573554
574555 if (butPtr->image != NULL) {
575 if ((butPtr->selectImage != NULL) &&
576 (butPtr->flags & SELECTED)) {
577 Tk_RedrawImage(butPtr->selectImage, 0, 0,
578 width, height, pixmap, imageXOffset, imageYOffset);
579 } else if ((butPtr->tristateImage != NULL) &&
580 (butPtr->flags & TRISTATED)) {
581 Tk_RedrawImage(butPtr->tristateImage, 0, 0,
582 width, height, pixmap, imageXOffset, imageYOffset);
583 } else {
584 Tk_RedrawImage(butPtr->image, 0, 0, width,
585 height, pixmap, imageXOffset, imageYOffset);
586 }
556 if ((butPtr->selectImage != NULL) &&
557 (butPtr->flags & SELECTED)) {
558 Tk_RedrawImage(butPtr->selectImage, 0, 0,
559 width, height, pixmap, imageXOffset, imageYOffset);
560 } else if ((butPtr->tristateImage != NULL) &&
561 (butPtr->flags & TRISTATED)) {
562 Tk_RedrawImage(butPtr->tristateImage, 0, 0,
563 width, height, pixmap, imageXOffset, imageYOffset);
564 } else {
565 Tk_RedrawImage(butPtr->image, 0, 0, width,
566 height, pixmap, imageXOffset, imageYOffset);
567 }
587568 } else {
588 XSetClipOrigin(butPtr->display, dpPtr->gc,
589 imageXOffset, imageYOffset);
590 XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,
591 0, 0, (unsigned int) width, (unsigned int) height,
592 imageXOffset, imageYOffset, 1);
593 XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
594 }
595
596 Tk_DrawTextLayout(butPtr->display, pixmap,
597 dpPtr->gc, butPtr->textLayout,
598 x + textXOffset, y + textYOffset, 0, -1);
569 XSetClipOrigin(butPtr->display, dpPtr->gc,
570 imageXOffset, imageYOffset);
571 XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,
572 0, 0, (unsigned int) width, (unsigned int) height,
573 imageXOffset, imageYOffset, 1);
574 XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
575 }
576 y += 1; /* Tweak to match native buttons. */
577 Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout,
578 x + textXOffset, y + textYOffset, 0, -1);
599579 Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,
600580 butPtr->textLayout,
601581 x + textXOffset, y + textYOffset,
602582 butPtr->underline);
603583 } else if (haveImage) { /* Image only */
604 int x = 0;
605 int y;
584 int x = 0, y;
585
606586 TkComputeAnchor(butPtr->anchor, tkwin,
607 butPtr->padX + butPtr->borderWidth,
608 butPtr->padY + butPtr->borderWidth,
609 width + butPtr->indicatorSpace,
610 height, &x, &y);
587 butPtr->padX + butPtr->borderWidth,
588 butPtr->padY + butPtr->borderWidth,
589 width + butPtr->indicatorSpace, height, &x, &y);
611590 x += butPtr->indicatorSpace;
612591 if (pressed) {
613 x += dpPtr->offset;
614 y += dpPtr->offset;
592 x += dpPtr->offset;
593 y += dpPtr->offset;
615594 }
616595 imageXOffset += x;
617596 imageYOffset += y;
618597
619598 if (butPtr->image != NULL) {
620
621 if ((butPtr->selectImage != NULL) &&
622 (butPtr->flags & SELECTED)) {
623 Tk_RedrawImage(butPtr->selectImage, 0, 0, width,
624 height, pixmap, imageXOffset, imageYOffset);
625 } else if ((butPtr->tristateImage != NULL) &&
626 (butPtr->flags & TRISTATED)) {
627 Tk_RedrawImage(butPtr->tristateImage, 0, 0, width,
628 height, pixmap, imageXOffset, imageYOffset);
629 } else {
630 Tk_RedrawImage(butPtr->image, 0, 0, width, height,
631 pixmap, imageXOffset, imageYOffset);
632 }
599 if ((butPtr->selectImage != NULL) &&
600 (butPtr->flags & SELECTED)) {
601 Tk_RedrawImage(butPtr->selectImage, 0, 0, width,
602 height, pixmap, imageXOffset, imageYOffset);
603 } else if ((butPtr->tristateImage != NULL) &&
604 (butPtr->flags & TRISTATED)) {
605 Tk_RedrawImage(butPtr->tristateImage, 0, 0, width,
606 height, pixmap, imageXOffset, imageYOffset);
607 } else {
608 Tk_RedrawImage(butPtr->image, 0, 0, width, height,
609 pixmap, imageXOffset, imageYOffset);
610 }
633611 } else {
634 XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
635 XCopyPlane(butPtr->display, butPtr->bitmap,
636 pixmap, dpPtr->gc,
637 0, 0, (unsigned int) width,
638 (unsigned int) height,
639 imageXOffset, imageYOffset, 1);
640 XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
612 XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
613 XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc,
614 0, 0, (unsigned int) width, (unsigned int) height,
615 imageXOffset, imageYOffset, 1);
616 XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
641617 }
642618 } else { /* Text only */
643619 int x, y;
620
644621 TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
645 butPtr->textWidth + butPtr->indicatorSpace,
646 butPtr->textHeight, &x, &y);
622 butPtr->textWidth + butPtr->indicatorSpace,
623 butPtr->textHeight, &x, &y);
647624 x += butPtr->indicatorSpace;
625 y += 1; /* Tweak to match native buttons */
648626 Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout,
649627 x, y, 0, -1);
650628 }
651629
652630 /*
653631 * If the button is disabled with a stipple rather than a special
654 * foreground color, generate the stippled effect. If the widget
655 * is selected and we use a different background color when selected,
656 * must temporarily modify the GC so the stippling is the right color.
632 * foreground color, generate the stippled effect. If the widget is
633 * selected and we use a different background color when selected, must
634 * temporarily modify the GC so the stippling is the right color.
657635 */
658636
659637 if (mbPtr->useTkText) {
691669 */
692670
693671 if (dpPtr->relief != TK_RELIEF_FLAT) {
694 int inset = butPtr->highlightWidth;
695 Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset,
696 Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset,
697 butPtr->borderWidth, dpPtr->relief);
698 }
699 }
700
701 }
702
703
704
705
672 int inset = butPtr->highlightWidth;
673
674 Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset,
675 Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset,
676 butPtr->borderWidth, dpPtr->relief);
677 }
678 }
679 }
680
706681 /*
707682 *----------------------------------------------------------------------
708683 *
724699 TkButton *butPtr)
725700 {
726701 MacButton *mbPtr = (MacButton *) butPtr; /* Mac button. */
702
727703 if (mbPtr->defaultPulseHandler) {
728704 Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler);
729705 }
734710 *
735711 * TkMacOSXDrawButton --
736712 *
737 * This function draws the tk button using Mac controls
738 * In addition, this code may apply custom colors passed
739 * in the TkButton.
713 * This function draws the tk button using Mac controls. In addition,
714 * this code may apply custom colors passed in the TkButton.
740715 *
741716 * Results:
742717 * None.
755730 Pixmap pixmap) /* The pixmap we are drawing into - needed
756731 * for the bevel button */
757732 {
758 TkButton * butPtr = ( TkButton *)mbPtr;
759 TkWindow * winPtr;
760 HIRect cntrRect;
733 TkButton *butPtr = (TkButton *) mbPtr;
734 TkWindow *winPtr = (TkWindow *) butPtr->tkwin;
735 HIRect cntrRect;
761736 TkMacOSXDrawingContext dc;
762 DrawParams* dpPtr = &mbPtr->drawParams;
737 DrawParams *dpPtr = &mbPtr->drawParams;
763738 int useNewerHITools = 1;
764739
765 winPtr = (TkWindow *)butPtr->tkwin;
766
767740 TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
768741
769 cntrRect = CGRectMake(winPtr->privatePtr->xOff,
770 winPtr->privatePtr->yOff,
771 Tk_Width(butPtr->tkwin),
772 Tk_Height(butPtr->tkwin));
773
774 cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);
742 cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
743 Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));
744
745 cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);
775746
776747 if (useNewerHITools == 1) {
777748 HIRect contHIRec;
785756
786757 hiinfo.version = 0;
787758 hiinfo.state = mbPtr->drawinfo.state;
788 hiinfo.kind = mbPtr->btnkind;
759 hiinfo.kind = mbPtr->btnkind;
789760 hiinfo.value = mbPtr->drawinfo.value;
790761 hiinfo.adornment = mbPtr->drawinfo.adornment;
791762 hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
793764 hiinfo.animation.time.start = hiinfo.animation.time.current;
794765 }
795766
796 HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal,
797 &contHIRec);
767 /*
768 * To avoid buttons with white text on a white background, we set the
769 * state to inactive in Dark Mode unless the button is pressed or is a
770 * -default active button. This isn't perfect but it is mostly usable.
771 * Using a ttk::button would be a much better choice, however.
772 */
773
774 if (TkMacOSXInDarkMode(butPtr->tkwin) &&
775 mbPtr->drawinfo.state != kThemeStatePressed &&
776 !(mbPtr->drawinfo.adornment & kThemeAdornmentDefault)) {
777 hiinfo.state = kThemeStateInactive;
778 }
779 HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
780 kHIThemeOrientationNormal, &contHIRec);
798781
799782 TkMacOSXRestoreDrawingContext(&dc);
800783 ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo,
801 (MacButton *)mbPtr, 32, true);
802
784 (MacButton *) mbPtr, 32, true);
803785 } else {
804786 if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
805787 return;
815797 *
816798 * ButtonBackgroundDrawCB --
817799 *
818 * This function draws the background that
819 * lies under checkboxes and radiobuttons.
800 * This function draws the background that lies under checkboxes and
801 * radiobuttons.
820802 *
821803 * Results:
822804 * None.
826808 *
827809 *--------------------------------------------------------------
828810 */
811
829812 static void
830 ButtonBackgroundDrawCB (
831 const HIRect * btnbounds,
813 ButtonBackgroundDrawCB(
814 const HIRect *btnbounds,
832815 MacButton *ptr,
833816 SInt16 depth,
834817 Boolean isColorDev)
835818 {
836 MacButton* mbPtr = (MacButton*)ptr;
837 TkButton* butPtr = (TkButton*)mbPtr;
838 Tk_Window tkwin = butPtr->tkwin;
819 MacButton *mbPtr = (MacButton *) ptr;
820 TkButton *butPtr = (TkButton *) mbPtr;
821 Tk_Window tkwin = butPtr->tkwin;
839822 Pixmap pixmap;
840823 int usehlborder = 0;
841824
842825 if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
843826 return;
844827 }
845 pixmap = (Pixmap)Tk_WindowId(tkwin);
828 pixmap = (Pixmap) Tk_WindowId(tkwin);
846829
847830 if (butPtr->type != TYPE_LABEL) {
848831 switch (mbPtr->btnkind) {
849 case kThemeSmallBevelButton:
850 case kThemeBevelButton:
851 case kThemeRoundedBevelButton:
852 case kThemePushButton:
853 usehlborder = 1;
854 break;
832 case kThemeSmallBevelButton:
833 case kThemeBevelButton:
834 case kThemeRoundedBevelButton:
835 case kThemePushButton:
836 usehlborder = 1;
837 break;
855838 }
856839 }
857840 if (usehlborder) {
887870 SInt16 depth,
888871 Boolean isColorDev)
889872 {
890 TkButton *butPtr = (TkButton *)ptr;
891 Tk_Window tkwin = butPtr->tkwin;
873 TkButton *butPtr = (TkButton *) ptr;
874 Tk_Window tkwin = butPtr->tkwin;
892875
893876 if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
894877 return;
895878 }
896879
897880 /*
898 * Overlay Tk elements over button native region: drawing elements
899 * within button boundaries/native region causes unpredictable metrics.
881 * Overlay Tk elements over button native region: drawing elements within
882 * button boundaries/native region causes unpredictable metrics.
900883 */
884
901885 DrawButtonImageAndText( butPtr);
902886 }
903887
906890 *
907891 * ButtonEventProc --
908892 *
909 * This procedure is invoked by the Tk dispatcher for various
910 * events on buttons.
893 * This procedure is invoked by the Tk dispatcher for various events on
894 * buttons.
911895 *
912896 * Results:
913897 * None.
923907 ClientData clientData, /* Information about window. */
924908 XEvent *eventPtr) /* Information about event. */
925909 {
926 TkButton *buttonPtr = (TkButton *) clientData;
927 MacButton *mbPtr = (MacButton *) clientData;
910 TkButton *buttonPtr = clientData;
911 MacButton *mbPtr = clientData;
928912
929913 if (eventPtr->type == ActivateNotify
930914 || eventPtr->type == DeactivateNotify) {
937921 mbPtr->flags &= ~ACTIVE;
938922 }
939923 if ((buttonPtr->flags & REDRAW_PENDING) == 0) {
940 Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) buttonPtr);
924 Tcl_DoWhenIdle(TkpDisplayButton, buttonPtr);
941925 buttonPtr->flags |= REDRAW_PENDING;
942926 }
943927 }
948932 *
949933 * TkMacOSXComputeButtonParams --
950934 *
951 * This procedure computes the various parameters used
952 * when creating a Carbon Appearance control.
953 * These are determined by the various tk button parameters
935 * This procedure computes the various parameters used when creating a
936 * Carbon Appearance control. These are determined by the various tk
937 * button parameters
954938 *
955939 * Results:
956940 * None.
963947
964948 static void
965949 TkMacOSXComputeButtonParams(
966 TkButton * butPtr,
967 ThemeButtonKind* btnkind,
968 HIThemeButtonDrawInfo *drawinfo)
969 {
970 MacButton *mbPtr = (MacButton *)butPtr;
950 TkButton *butPtr,
951 ThemeButtonKind *btnkind,
952 HIThemeButtonDrawInfo *drawinfo)
953 {
954 MacButton *mbPtr = (MacButton *) butPtr;
971955
972956 if (butPtr->borderWidth <= 2) {
973957 *btnkind = kThemeSmallBevelButton;
981965
982966 if ((butPtr->image == None) && (butPtr->bitmap == None)) {
983967 switch (butPtr->type) {
984 case TYPE_BUTTON:
985 *btnkind = kThemePushButton;
986 break;
987 case TYPE_RADIO_BUTTON:
988 if (butPtr->borderWidth <= 1) {
989 *btnkind = kThemeSmallRadioButton;
990 } else {
991 *btnkind = kThemeRadioButton;
992 }
993 break;
994 case TYPE_CHECK_BUTTON:
995 if (butPtr->borderWidth <= 1) {
996 *btnkind = kThemeSmallCheckBox;
997 } else {
998 *btnkind = kThemeCheckBox;
999 }
1000 break;
968 case TYPE_BUTTON:
969 *btnkind = kThemePushButton;
970 break;
971 case TYPE_RADIO_BUTTON:
972 if (butPtr->borderWidth <= 1) {
973 *btnkind = kThemeSmallRadioButton;
974 } else {
975 *btnkind = kThemeRadioButton;
976 }
977 break;
978 case TYPE_CHECK_BUTTON:
979 if (butPtr->borderWidth <= 1) {
980 *btnkind = kThemeSmallCheckBox;
981 } else {
982 *btnkind = kThemeCheckBox;
983 }
984 break;
1001985 }
1002986 }
1003987
1004988 if (butPtr->indicatorOn) {
1005989 switch (butPtr->type) {
1006 case TYPE_RADIO_BUTTON:
1007 if (butPtr->borderWidth <= 1) {
1008 *btnkind = kThemeSmallRadioButton;
1009 } else {
1010 *btnkind = kThemeRadioButton;
1011 }
1012 break;
1013 case TYPE_CHECK_BUTTON:
1014 if (butPtr->borderWidth <= 1) {
1015 *btnkind = kThemeSmallCheckBox;
1016 } else {
1017 *btnkind = kThemeCheckBox;
1018 }
1019 break;
990 case TYPE_RADIO_BUTTON:
991 if (butPtr->borderWidth <= 1) {
992 *btnkind = kThemeSmallRadioButton;
993 } else {
994 *btnkind = kThemeRadioButton;
995 }
996 break;
997 case TYPE_CHECK_BUTTON:
998 if (butPtr->borderWidth <= 1) {
999 *btnkind = kThemeSmallCheckBox;
1000 } else {
1001 *btnkind = kThemeCheckBox;
1002 }
1003 break;
10201004 }
10211005 } else {
10221006 if (butPtr->type == TYPE_RADIO_BUTTON ||
1023 butPtr->type == TYPE_CHECK_BUTTON
1024 ) {
1007 butPtr->type == TYPE_CHECK_BUTTON) {
10251008 if (*btnkind == kThemePushButton) {
10261009 *btnkind = kThemeBevelButton;
10271010 }
10601043
10611044 drawinfo->adornment = kThemeAdornmentNone;
10621045 if (butPtr->defaultState == DEFAULT_ACTIVE) {
1063 drawinfo->adornment |= kThemeAdornmentDefault;
1046 if (drawinfo->state != kThemeStatePressed) {
1047 drawinfo->adornment |= kThemeAdornmentDefault;
1048 }
10641049 if (!mbPtr->defaultPulseHandler) {
10651050 mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
1066 PULSE_TIMER_MSECS, PulseDefaultButtonProc,
1067 (ClientData) butPtr);
1051 PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr);
10681052 }
10691053 } else if (mbPtr->defaultPulseHandler) {
10701054 Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler);
10811065 *
10821066 * TkMacOSXComputeButtonDrawParams --
10831067 *
1084 * This procedure computes the various parameters used
1085 * when drawing a button
1086 * These are determined by the various tk button parameters
1068 * This procedure computes the various parameters used when drawing a
1069 * button. These are determined by the various tk button parameters
10871070 *
10881071 * Results:
10891072 * 1 if control will be used, 0 otherwise.
10991082 TkButton *butPtr,
11001083 DrawParams *dpPtr)
11011084 {
1102 MacButton *mbPtr = (MacButton *)butPtr;
1085 MacButton *mbPtr = (MacButton *) butPtr;
11031086
11041087 dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)
11051088 || (butPtr->bitmap != None));
11081091 dpPtr->offset = 0;
11091092 if (dpPtr->hasImageOrBitmap) {
11101093 switch (mbPtr->btnkind) {
1111 case kThemeSmallBevelButton:
1112 case kThemeBevelButton:
1113 case kThemeRoundedBevelButton:
1114 case kThemePushButton:
1115 dpPtr->offset = 1;
1116 break;
1094 case kThemeSmallBevelButton:
1095 case kThemeBevelButton:
1096 case kThemeRoundedBevelButton:
1097 case kThemePushButton:
1098 dpPtr->offset = 1;
1099 break;
11171100 }
11181101 }
11191102 }
1120
11211103
11221104 dpPtr->border = butPtr->normalBorder;
11231105 if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
11251107 } else if (butPtr->type == TYPE_BUTTON && butPtr->state == STATE_ACTIVE) {
11261108 dpPtr->gc = butPtr->activeTextGC;
11271109 dpPtr->border = butPtr->activeBorder;
1110 } else if ((mbPtr->drawinfo.adornment & kThemeAdornmentDefault) &&
1111 mbPtr->drawinfo.state == kThemeStateActive) {
1112 /*
1113 * This is a "-default active" button in the front window.
1114 */
1115
1116 dpPtr->gc = butPtr->activeTextGC;
11281117 } else {
11291118 dpPtr->gc = butPtr->normalTextGC;
11301119 }
11351124 }
11361125
11371126 /*
1138 * Override the relief specified for the button if this is a
1139 * checkbutton or radiobutton and there's no indicator.
1127 * Override the relief specified for the button if this is a checkbutton or
1128 * radiobutton and there's no indicator.
11401129 */
11411130
11421131 dpPtr->relief = butPtr->relief;
11481137 }
11491138 }
11501139
1151 /*
1152 * Determine the draw type
1153 */
1154
1155 if (butPtr->type == TYPE_LABEL) {
1156 dpPtr->drawType = DRAW_LABEL;
1157 } else if (butPtr->type == TYPE_BUTTON) {
1158 if (!dpPtr->hasImageOrBitmap) {
1159 dpPtr->drawType = DRAW_CONTROL;
1160 } else {
1161 dpPtr->drawType = DRAW_BEVEL;
1162 }
1163 } else if (butPtr->indicatorOn) {
1164 dpPtr->drawType = DRAW_CONTROL;
1165 } else if (dpPtr->hasImageOrBitmap) {
1166 dpPtr->drawType = DRAW_BEVEL;
1167 } else {
1168 dpPtr->drawType = DRAW_CUSTOM;
1169 }
1170
1171 if ((dpPtr->drawType == DRAW_CONTROL) || (dpPtr->drawType == DRAW_BEVEL)) {
1140 if (butPtr->type != TYPE_LABEL && (butPtr->type == TYPE_BUTTON ||
1141 butPtr->indicatorOn || dpPtr->hasImageOrBitmap)) {
1142 /*
1143 * Draw this widget as a native control.
1144 */
1145
11721146 return 1;
11731147 } else {
1148 /*
1149 * Draw this widget from scratch.
1150 */
1151
11741152 return 0;
11751153 }
11761154 }
11911169 *
11921170 *--------------------------------------------------------------
11931171 */
1172
11941173 static void
11951174 PulseDefaultButtonProc(ClientData clientData)
11961175 {
1197 MacButton *mbPtr = (MacButton *)clientData;
1176 MacButton *mbPtr = clientData;
1177
11981178 TkpDisplayButton(clientData);
11991179 mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
12001180 PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData);
12011181 }
1202
1182
12031183 /*
12041184 * Local Variables:
12051185 * mode: objc
3434 targetPtr->type == dispPtr->utf8Atom) {
3535 for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr;
3636 cbPtr; cbPtr = cbPtr->nextPtr) {
37 NSString *s = [[NSString alloc] initWithBytesNoCopy:
38 cbPtr->buffer length:cbPtr->length
39 encoding:NSUTF8StringEncoding freeWhenDone:NO];
40
37 NSString *s = TclUniToNSString(cbPtr->buffer, cbPtr->length);
4138 [string appendString:s];
4239 [s release];
4340 }
122119 {
123120 int result = TCL_ERROR;
124121 TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
125
126 int haveExternalClip = ([[NSPasteboard generalPasteboard] changeCount] != changeCount);
122 int haveExternalClip =
123 ([[NSPasteboard generalPasteboard] changeCount] != changeCount);
124
127125 if (dispPtr && (haveExternalClip || dispPtr->clipboardActive)
128126 && selection == dispPtr->clipboardAtom
129127 && (target == XA_STRING || target == dispPtr->utf8Atom)) {
135133 if (type) {
136134 string = [pb stringForType:type];
137135 }
138 result = proc(clientData, interp, string ? [string UTF8String] : "");
136 if (string) {
137
138 /*
139 * Encode the string using the encoding which is used in Tcl
140 * when TCL_UTF_MAX = 3. This replaces each UTF-16 surrogate with
141 * a 3-byte sequence generated using the UTF-8 algorithm. (Even
142 * though UTF-8 does not allow encoding surrogates, the algorithm
143 * does produce a 3-byte sequence.)
144 */
145
146 char *bytes = NSStringToTclUni(string, NULL);
147 result = proc(clientData, interp, bytes);
148 if (bytes) {
149 ckfree(bytes);
150 }
151 }
139152 } else {
140153 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
141154 "%s selection doesn't exist or form \"%s\" not defined",
176189 clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL;
177190 if (!dispPtr->clipboardActive) {
178191 NSPasteboard *pb = [NSPasteboard generalPasteboard];
192
179193 changeCount = [pb declareTypes:[NSArray array] owner:NSApp];
180194 }
181195 }
187201 *
188202 * TkMacOSXSelDeadWindow --
189203 *
190 * This function is invoked just before a TkWindow is deleted. It
191 * performs selection-related cleanup.
204 * This function is invoked just before a TkWindow is deleted. It performs
205 * selection-related cleanup.
192206 *
193207 * Results:
194208 * None.
1616 #include "tkMacOSXPrivate.h"
1717 #include "tkColor.h"
1818
19 /*
20 * The colorType specifies how the color value should be interpreted. For the
21 * unique rgbColor entry, the RGB values are generated from the pixel value of
22 * an XColor. The ttkBackground and semantic types are dynamic, meaning
23 * that they change when dark mode is enabled on OSX 10.13 and later.
24 */
25
26 enum colorType {
27 clearColor, /* There should be only one of these. */
28 rgbColor, /* There should be only one of these. */
29 appearance, /* There should be only one of these. */
30 HIBrush, /* The value is a HITheme brush color table index. */
31 HIText, /* The value is a HITheme text color table index. */
32 HIBackground, /* The value is a HITheme background color table index. */
33 ttkBackground, /* The value can be used as a parameter.*/
34 semantic, /* The value can be used as a parameter.*/
35 };
36
37 /*
38
39 */
40
1941 struct SystemColorMapEntry {
2042 const char *name;
21 ThemeBrush brush;
22 ThemeTextColor textColor;
23 ThemeBackgroundKind background;
43 enum colorType type;
44 long value;
2445 }; /* unsigned char pixelCode; */
2546
2647 /*
3152
3253 #define MIN_PIXELCODE 30
3354 static const struct SystemColorMapEntry systemColorMap[] = {
34 { "Transparent", 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */
35 { "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */
36 { "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */
37 { "HighlightText", kThemeBrushBlack, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */
38 { "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */
39 { "ButtonText", 0, kThemeTextColorPushButtonActive, 0 }, /* 35: CONTROL_TEXT_PIXEL */
40 { "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 36 */
41 { "ButtonFace", kThemeBrushButtonFaceActive, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */
42 { "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 38 */
43 { "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */
44 { "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 40 */
45 { "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */
46 { "SheetBackground", kThemeBrushSheetBackground, 0, 0 }, /* 42 */
47 { "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */
48 { "Black", kThemeBrushBlack, 0, 0 }, /* 44 */
49 { "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */
50 { "White", kThemeBrushWhite, 0, 0 }, /* 46 */
51 { "Menu", kThemeBrushMenuBackground, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */
52 { "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0 }, /* 48 */
53 { "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 49: MENU_DISABLED_PIXEL */
54 { "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0 }, /* 50 */
55 { "MenuText", 0, kThemeTextColorMenuItemActive, 0 }, /* 51: MENU_TEXT_PIXEL */
56 { "AppearanceColor", 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */
57 { "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0 }, /* 53 */
58 { "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0 }, /* 54 */
59 { "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0 }, /* 55 */
60 { "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0 }, /* 56 */
61 { "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0 }, /* 57 */
62 { "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0 }, /* 58 */
63 { "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0 }, /* 59 */
64 { "ListViewBackground", kThemeBrushListViewBackground, 0, 0 }, /* 60 */
65 { "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0 }, /* 61 */
66 { "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0 }, /* 62 */
67 { "ChasingArrows", kThemeBrushChasingArrows, 0, 0 }, /* 63 */
68 { "DragHilite", kThemeBrushDragHilite, 0, 0 }, /* 64 */
69 { "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 65 */
70 { "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0 }, /* 66 */
71 { "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0 }, /* 67 */
72 { "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0 }, /* 68 */
73 { "FocusHighlight", kThemeBrushFocusHighlight, 0, 0 }, /* 69 */
74 { "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0 }, /* 70 */
75 { "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0 }, /* 71 */
76 { "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0 }, /* 72 */
77 { "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0 }, /* 73 */
78 { "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0 }, /* 74 */
79 { "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0 }, /* 75 */
80 { "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0 }, /* 76 */
81 { "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0 }, /* 77 */
82 { "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0 }, /* 78 */
83 { "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0 }, /* 79 */
84 { "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0 }, /* 80 */
85 { "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0 }, /* 81 */
86 { "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0 }, /* 82 */
87 { "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0 }, /* 83 */
88 { "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0 }, /* 84 */
89 { "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0 }, /* 85 */
90 { "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0 }, /* 86 */
91 { "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0 }, /* 87 */
92 { "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0 }, /* 88 */
93 { "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0 }, /* 89 */
94 { "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0 }, /* 90 */
95 { "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0 }, /* 91 */
96 { "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0 }, /* 92 */
97 { "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0 }, /* 93 */
98 { "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0 }, /* 94 */
99 { "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0 }, /* 95 */
100 { "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0 }, /* 96 */
101 { "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0 }, /* 97 */
102 { "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0 }, /* 98 */
103 { "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0 }, /* 99 */
104 { "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0 }, /* 100 */
105 { "DrawerBackground", kThemeBrushDrawerBackground, 0, 0 }, /* 101 */
106 { "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0 }, /* 102 */
107 { "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0 }, /* 103 */
108 { "MenuBackground", kThemeBrushMenuBackground, 0, 0 }, /* 104 */
109 { "Pixel", 0, 0, 0 }, /* 105: PIXEL_MAGIC */
110 { "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 106 */
111 { "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0 }, /* 107 */
112 { "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0 }, /* 108 */
113 { "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0 }, /* 109 */
114 { "BlackText", 0, kThemeTextColorBlack, 0 }, /* 110 */
115 { "DialogActiveText", 0, kThemeTextColorDialogActive, 0 }, /* 111 */
116 { "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0 }, /* 112 */
117 { "AlertActiveText", 0, kThemeTextColorAlertActive, 0 }, /* 113 */
118 { "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0 }, /* 114 */
119 { "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0 }, /* 115 */
120 { "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0 }, /* 116 */
121 { "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0 }, /* 117 */
122 { "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0 }, /* 118 */
123 { "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0 }, /* 119 */
124 { "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0 }, /* 120 */
125 { "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0 }, /* 121 */
126 { "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0 }, /* 122 */
127 { "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0 }, /* 123 */
128 { "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0 }, /* 124 */
129 { "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0 }, /* 125 */
130 { "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0 }, /* 126 */
131 { "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0 }, /* 127 */
132 { "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0 }, /* 128 */
133 { "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0 }, /* 129 */
134 { "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0 }, /* 130 */
135 { "IconLabelText", 0, kThemeTextColorIconLabel, 0 }, /* 131 */
136 { "ListViewText", 0, kThemeTextColorListView, 0 }, /* 132 */
137 { "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0 }, /* 133 */
138 { "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0 }, /* 134 */
139 { "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0 }, /* 135 */
140 { "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0 }, /* 136 */
141 { "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0 }, /* 137 */
142 { "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0 }, /* 138 */
143 { "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0 }, /* 139 */
144 { "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0 }, /* 140 */
145 { "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0 }, /* 141 */
146 { "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0 }, /* 142 */
147 { "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0 }, /* 143 */
148 { "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0 }, /* 144 */
149 { "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 145 */
150 { "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 146 */
151 { "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0 }, /* 147 */
152 { "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0 }, /* 148 */
153 { "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0 }, /* 149 */
154 { "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0 }, /* 150 */
155 { "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0 }, /* 151 */
156 { "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0 }, /* 152 */
157 { "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0 }, /* 153 */
158 { "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0 }, /* 154 */
159 { "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0 }, /* 155 */
160 { "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0 }, /* 156 */
161 { "NotificationText", 0, kThemeTextColorNotification, 0 }, /* 157 */
162 { "SystemDetailText", 0, kThemeTextColorSystemDetail, 0 }, /* 158 */
163 { "WhiteText", 0, kThemeTextColorWhite, 0 }, /* 159 */
164 { "TabPaneBackground", 0, 0, kThemeBackgroundTabPane }, /* 160 */
165 { "PlacardBackground", 0, 0, kThemeBackgroundPlacard }, /* 161 */
166 { "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader }, /* 162 */
167 { "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader }, /* 163 */
168 { "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox }, /* 164 */
169 { "MetalBackground", 0, 0, kThemeBackgroundMetal }, /* 165 */
170 { NULL, 0, 0, 0 }
55 { "Transparent", clearColor, 0 }, /* 30: TRANSPARENT_PIXEL */
56 { "Highlight", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 31 */
57 { "HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 32 */
58 { "HighlightText", HIBrush, kThemeBrushBlack }, /* 33 */
59 { "HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 34 */
60 { "ButtonText", HIText, kThemeTextColorPushButtonActive }, /* 35 */
61 { "PrimaryHighlightColor", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 36 */
62 { "ButtonFace", HIBrush, kThemeBrushButtonFaceActive }, /* 37 */
63 { "SecondaryHighlightColor", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 38 */
64 { "ButtonFrame", HIBrush, kThemeBrushButtonFrameActive }, /* 39 */
65 { "AlternatePrimaryHighlightColor", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 40 */
66 { "WindowBody", HIBrush, kThemeBrushDocumentWindowBackground }, /* 41 */
67 { "SheetBackground", HIBrush, kThemeBrushSheetBackground }, /* 42 */
68 { "MenuActive", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 43 */
69 { "Black", HIBrush, kThemeBrushBlack }, /* 44 */
70 { "MenuActiveText", HIText, kThemeTextColorMenuItemSelected }, /* 45 */
71 { "White", HIBrush, kThemeBrushWhite }, /* 46 */
72 { "Menu", HIBrush, kThemeBrushMenuBackground }, /* 47 */
73 { "DialogBackgroundActive", HIBrush, kThemeBrushDialogBackgroundActive }, /* 48 */
74 { "MenuDisabled", HIText, kThemeTextColorMenuItemDisabled }, /* 49 */
75 { "DialogBackgroundInactive", HIBrush, kThemeBrushDialogBackgroundInactive }, /* 50 */
76 { "MenuText", HIText, kThemeTextColorMenuItemActive }, /* 51 */
77 { "AppearanceColor", appearance, 0 }, /* 52: APPEARANCE_PIXEL */
78 { "AlertBackgroundActive", HIBrush, kThemeBrushAlertBackgroundActive }, /* 53 */
79 { "AlertBackgroundInactive", HIBrush, kThemeBrushAlertBackgroundInactive }, /* 54 */
80 { "ModelessDialogBackgroundActive", HIBrush, kThemeBrushModelessDialogBackgroundActive }, /* 55 */
81 { "ModelessDialogBackgroundInactive", HIBrush, kThemeBrushModelessDialogBackgroundInactive }, /* 56 */
82 { "UtilityWindowBackgroundActive", HIBrush, kThemeBrushUtilityWindowBackgroundActive }, /* 57 */
83 { "UtilityWindowBackgroundInactive", HIBrush, kThemeBrushUtilityWindowBackgroundInactive }, /* 58 */
84 { "ListViewSortColumnBackground", HIBrush, kThemeBrushListViewSortColumnBackground }, /* 59 */
85 { "ListViewBackground", HIBrush, kThemeBrushListViewBackground }, /* 60 */
86 { "IconLabelBackground", HIBrush, kThemeBrushIconLabelBackground }, /* 61 */
87 { "ListViewSeparator", HIBrush, kThemeBrushListViewSeparator }, /* 62 */
88 { "ChasingArrows", HIBrush, kThemeBrushChasingArrows }, /* 63 */
89 { "DragHilite", HIBrush, kThemeBrushDragHilite }, /* 64 */
90 { "DocumentWindowBackground", HIBrush, kThemeBrushDocumentWindowBackground }, /* 65 */
91 { "FinderWindowBackground", HIBrush, kThemeBrushFinderWindowBackground }, /* 66 */
92 { "ScrollBarDelimiterActive", HIBrush, kThemeBrushScrollBarDelimiterActive }, /* 67 */
93 { "ScrollBarDelimiterInactive", HIBrush, kThemeBrushScrollBarDelimiterInactive }, /* 68 */
94 { "FocusHighlight", HIBrush, kThemeBrushFocusHighlight }, /* 69 */
95 { "PopupArrowActive", HIBrush, kThemeBrushPopupArrowActive }, /* 70 */
96 { "PopupArrowPressed", HIBrush, kThemeBrushPopupArrowPressed }, /* 71 */
97 { "PopupArrowInactive", HIBrush, kThemeBrushPopupArrowInactive }, /* 72 */
98 { "AppleGuideCoachmark", HIBrush, kThemeBrushAppleGuideCoachmark }, /* 73 */
99 { "IconLabelBackgroundSelected", HIBrush, kThemeBrushIconLabelBackgroundSelected }, /* 74 */
100 { "StaticAreaFill", HIBrush, kThemeBrushStaticAreaFill }, /* 75 */
101 { "ActiveAreaFill", HIBrush, kThemeBrushActiveAreaFill }, /* 76 */
102 { "ButtonFrameActive", HIBrush, kThemeBrushButtonFrameActive }, /* 77 */
103 { "ButtonFrameInactive", HIBrush, kThemeBrushButtonFrameInactive }, /* 78 */
104 { "ButtonFaceActive", HIBrush, kThemeBrushButtonFaceActive }, /* 79 */
105 { "ButtonFaceInactive", HIBrush, kThemeBrushButtonFaceInactive }, /* 80 */
106 { "ButtonFacePressed", HIBrush, kThemeBrushButtonFacePressed }, /* 81 */
107 { "ButtonActiveDarkShadow", HIBrush, kThemeBrushButtonActiveDarkShadow }, /* 82 */
108 { "ButtonActiveDarkHighlight", HIBrush, kThemeBrushButtonActiveDarkHighlight }, /* 83 */
109 { "ButtonActiveLightShadow", HIBrush, kThemeBrushButtonActiveLightShadow }, /* 84 */
110 { "ButtonActiveLightHighlight", HIBrush, kThemeBrushButtonActiveLightHighlight }, /* 85 */
111 { "ButtonInactiveDarkShadow", HIBrush, kThemeBrushButtonInactiveDarkShadow }, /* 86 */
112 { "ButtonInactiveDarkHighlight", HIBrush, kThemeBrushButtonInactiveDarkHighlight }, /* 87 */
113 { "ButtonInactiveLightShadow", HIBrush, kThemeBrushButtonInactiveLightShadow }, /* 88 */
114 { "ButtonInactiveLightHighlight", HIBrush, kThemeBrushButtonInactiveLightHighlight }, /* 89 */
115 { "ButtonPressedDarkShadow", HIBrush, kThemeBrushButtonPressedDarkShadow }, /* 90 */
116 { "ButtonPressedDarkHighlight", HIBrush, kThemeBrushButtonPressedDarkHighlight }, /* 91 */
117 { "ButtonPressedLightShadow", HIBrush, kThemeBrushButtonPressedLightShadow }, /* 92 */
118 { "ButtonPressedLightHighlight", HIBrush, kThemeBrushButtonPressedLightHighlight }, /* 93 */
119 { "BevelActiveLight", HIBrush, kThemeBrushBevelActiveLight }, /* 94 */
120 { "BevelActiveDark", HIBrush, kThemeBrushBevelActiveDark }, /* 95 */
121 { "BevelInactiveLight", HIBrush, kThemeBrushBevelInactiveLight }, /* 96 */
122 { "BevelInactiveDark", HIBrush, kThemeBrushBevelInactiveDark }, /* 97 */
123 { "NotificationWindowBackground", HIBrush, kThemeBrushNotificationWindowBackground }, /* 98 */
124 { "MovableModalBackground", HIBrush, kThemeBrushMovableModalBackground }, /* 99 */
125 { "SheetBackgroundOpaque", HIBrush, kThemeBrushSheetBackgroundOpaque }, /* 100 */
126 { "DrawerBackground", HIBrush, kThemeBrushDrawerBackground }, /* 101 */
127 { "ToolbarBackground", HIBrush, kThemeBrushToolbarBackground }, /* 102 */
128 { "SheetBackgroundTransparent", HIBrush, kThemeBrushSheetBackgroundTransparent }, /* 103 */
129 { "MenuBackground", HIBrush, kThemeBrushMenuBackground }, /* 104 */
130 { "Pixel", rgbColor, 0 }, /* 105: PIXEL_MAGIC */
131 { "MenuBackgroundSelected", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 106 */
132 { "ListViewOddRowBackground", HIBrush, kThemeBrushListViewOddRowBackground }, /* 107 */
133 { "ListViewEvenRowBackground", HIBrush, kThemeBrushListViewEvenRowBackground }, /* 108 */
134 { "ListViewColumnDivider", HIBrush, kThemeBrushListViewColumnDivider }, /* 109 */
135 { "BlackText", HIText, kThemeTextColorBlack }, /* 110 */
136 { "DialogActiveText", HIText, kThemeTextColorDialogActive }, /* 111 */
137 { "DialogInactiveText", HIText, kThemeTextColorDialogInactive }, /* 112 */
138 { "AlertActiveText", HIText, kThemeTextColorAlertActive }, /* 113 */
139 { "AlertInactiveText", HIText, kThemeTextColorAlertInactive }, /* 114 */
140 { "ModelessDialogActiveText", HIText, kThemeTextColorModelessDialogActive }, /* 115 */
141 { "ModelessDialogInactiveText", HIText, kThemeTextColorModelessDialogInactive }, /* 116 */
142 { "WindowHeaderActiveText", HIText, kThemeTextColorWindowHeaderActive }, /* 117 */
143 { "WindowHeaderInactiveText", HIText, kThemeTextColorWindowHeaderInactive }, /* 118 */
144 { "PlacardActiveText", HIText, kThemeTextColorPlacardActive }, /* 119 */
145 { "PlacardInactiveText", HIText, kThemeTextColorPlacardInactive }, /* 120 */
146 { "PlacardPressedText", HIText, kThemeTextColorPlacardPressed }, /* 121 */
147 { "PushButtonActiveText", HIText, kThemeTextColorPushButtonActive }, /* 122 */
148 { "PushButtonInactiveText", HIText, kThemeTextColorPushButtonInactive }, /* 123 */
149 { "PushButtonPressedText", HIText, kThemeTextColorPushButtonPressed }, /* 124 */
150 { "BevelButtonActiveText", HIText, kThemeTextColorBevelButtonActive }, /* 125 */
151 { "BevelButtonInactiveText", HIText, kThemeTextColorBevelButtonInactive }, /* 126 */
152 { "BevelButtonPressedText", HIText, kThemeTextColorBevelButtonPressed }, /* 127 */
153 { "PopupButtonActiveText", HIText, kThemeTextColorPopupButtonActive }, /* 128 */
154 { "PopupButtonInactiveText", HIText, kThemeTextColorPopupButtonInactive }, /* 129 */
155 { "PopupButtonPressedText", HIText, kThemeTextColorPopupButtonPressed }, /* 130 */
156 { "IconLabelText", HIText, kThemeTextColorIconLabel }, /* 131 */
157 { "ListViewText", HIText, kThemeTextColorListView }, /* 132 */
158 { "DocumentWindowTitleActiveText", HIText, kThemeTextColorDocumentWindowTitleActive }, /* 133 */
159 { "DocumentWindowTitleInactiveText", HIText, kThemeTextColorDocumentWindowTitleInactive }, /* 134 */
160 { "MovableModalWindowTitleActiveText", HIText, kThemeTextColorMovableModalWindowTitleActive }, /* 135 */
161 { "MovableModalWindowTitleInactiveText",HIText, kThemeTextColorMovableModalWindowTitleInactive }, /* 136 */
162 { "UtilityWindowTitleActiveText", HIText, kThemeTextColorUtilityWindowTitleActive }, /* 137 */
163 { "UtilityWindowTitleInactiveText", HIText, kThemeTextColorUtilityWindowTitleInactive }, /* 138 */
164 { "PopupWindowTitleActiveText", HIText, kThemeTextColorPopupWindowTitleActive }, /* 139 */
165 { "PopupWindowTitleInactiveText", HIText, kThemeTextColorPopupWindowTitleInactive }, /* 140 */
166 { "RootMenuActiveText", HIText, kThemeTextColorRootMenuActive }, /* 141 */
167 { "RootMenuSelectedText", HIText, kThemeTextColorRootMenuSelected }, /* 142 */
168 { "RootMenuDisabledText", HIText, kThemeTextColorRootMenuDisabled }, /* 143 */
169 { "MenuItemActiveText", HIText, kThemeTextColorMenuItemActive }, /* 144 */
170 { "MenuItemSelectedText", HIText, kThemeTextColorMenuItemSelected }, /* 145 */
171 { "MenuItemDisabledText", HIText, kThemeTextColorMenuItemDisabled }, /* 146 */
172 { "PopupLabelActiveText", HIText, kThemeTextColorPopupLabelActive }, /* 147 */
173 { "PopupLabelInactiveText", HIText, kThemeTextColorPopupLabelInactive }, /* 148 */
174 { "TabFrontActiveText", HIText, kThemeTextColorTabFrontActive }, /* 149 */
175 { "TabNonFrontActiveText", HIText, kThemeTextColorTabNonFrontActive }, /* 150 */
176 { "TabNonFrontPressedText", HIText, kThemeTextColorTabNonFrontPressed }, /* 151 */
177 { "TabFrontInactiveText", HIText, kThemeTextColorTabFrontInactive }, /* 152 */
178 { "TabNonFrontInactiveText", HIText, kThemeTextColorTabNonFrontInactive }, /* 153 */
179 { "IconLabelSelectedText", HIText, kThemeTextColorIconLabelSelected }, /* 154 */
180 { "BevelButtonStickyActiveText", HIText, kThemeTextColorBevelButtonStickyActive }, /* 155 */
181 { "BevelButtonStickyInactiveText", HIText, kThemeTextColorBevelButtonStickyInactive }, /* 156 */
182 { "NotificationText", HIText, kThemeTextColorNotification }, /* 157 */
183 { "SystemDetailText", HIText, kThemeTextColorSystemDetail }, /* 158 */
184 { "WhiteText", HIText, kThemeTextColorWhite }, /* 159 */
185 { "TabPaneBackground", HIBackground, kThemeBackgroundTabPane }, /* 160 */
186 { "PlacardBackground", HIBackground, kThemeBackgroundPlacard }, /* 161 */
187 { "WindowHeaderBackground", HIBackground, kThemeBackgroundWindowHeader }, /* 162 */
188 { "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */
189 { "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */
190 { "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */
191
192 /*
193 * Colors based on "semantic" NSColors.
194 */
195
196 { "WindowBackgroundColor", ttkBackground, 0 }, /* 166 */
197 { "WindowBackgroundColor1", ttkBackground, 1 }, /* 167 */
198 { "WindowBackgroundColor2", ttkBackground, 2 }, /* 168 */
199 { "WindowBackgroundColor3", ttkBackground, 3 }, /* 169 */
200 { "WindowBackgroundColor4", ttkBackground, 4 }, /* 170 */
201 { "WindowBackgroundColor5", ttkBackground, 5 }, /* 171 */
202 { "WindowBackgroundColor6", ttkBackground, 6 }, /* 172 */
203 { "WindowBackgroundColor7", ttkBackground, 7 }, /* 173 */
204 { "TextColor", semantic, 0 }, /* 174 */
205 { "SelectedTextColor", semantic, 1 }, /* 175 */
206 { "LabelColor", semantic, 2 }, /* 176 */
207 { "ControlTextColor", semantic, 3 }, /* 177 */
208 { "DisabledControlTextColor", semantic, 4 }, /* 178 */
209 { "SelectedTabTextColor", semantic, 5 }, /* 179 */
210 { "TextBackgroundColor", semantic, 6 }, /* 180 */
211 { "SelectedTextBackgroundColor", semantic, 7 }, /* 181 */
212 { "ControlAccentColor", semantic, 8 }, /* 182 */
213 { NULL, 0, 0 }
171214 };
172 #define MAX_PIXELCODE 165
173
174 /*
175 *----------------------------------------------------------------------
176 *
177 * GetThemeFromPixelCode --
178 *
179 * When given a pixel code corresponding to a theme system color,
180 * set one of brush, textColor or background to the corresponding
181 * Appearance Mgr theme constant.
182 *
183 * Results:
184 * Returns false if not a real pixel, true otherwise.
215 #define FIRST_SEMANTIC_COLOR 166
216 #define MAX_PIXELCODE 182
217
218 /*
219 *----------------------------------------------------------------------
220 *
221 * GetEntryFromPixelCode --
222 *
223 * Extract a SystemColorMapEntry from the table.
224 *
225 * Results:
226 * Returns false if the code is out of bounds.
185227 *
186228 * Side effects:
187229 * None.
189231 *----------------------------------------------------------------------
190232 */
191233
192 static int
193 GetThemeFromPixelCode(
234 static bool
235 GetEntryFromPixelCode(
194236 unsigned char code,
195 ThemeBrush *brush,
196 ThemeTextColor *textColor,
197 ThemeBackgroundKind *background)
237 struct SystemColorMapEntry *entry)
198238 {
199239 if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) {
200 *brush = systemColorMap[code - MIN_PIXELCODE].brush;
201 *textColor = systemColorMap[code - MIN_PIXELCODE].textColor;
202 *background = systemColorMap[code - MIN_PIXELCODE].background;
240 *entry = systemColorMap[code - MIN_PIXELCODE];
241 return true;
203242 } else {
204 *brush = 0;
205 *textColor = 0;
206 *background = 0;
207 }
208 if (!*brush && !*textColor && !*background && code != PIXEL_MAGIC &&
209 code != TRANSPARENT_PIXEL) {
210243 return false;
211 } else {
212 return true;
213 }
214 }
215
216 /*
217 *----------------------------------------------------------------------
218 *
219 * GetThemeColor --
220 *
221 * Get RGB color for a given system color or pixel value.
244 }
245 }
246
247 /*
248 *----------------------------------------------------------------------
249 *
250 * SetCGColorComponents --
251 *
252 * Set the components of a CGColorRef from an XColor pixel value and a
253 * system color map entry. The pixel value is only used in the case where
254 * the color is of type rgbColor. In that case the normalized XColor RGB
255 * values are copied into the CGColorRef.
222256 *
223257 * Results:
224258 * OSStatus
229263 *----------------------------------------------------------------------
230264 */
231265
266 static NSColorSpace* deviceRGB = NULL;
267 static CGFloat blueAccentRGBA[4] = {0, 122.0 / 255, 1.0, 1.0};
268 static CGFloat windowBackground[4] =
269 {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
270
232271 static OSStatus
233 GetThemeColor(
272 SetCGColorComponents(
273 struct SystemColorMapEntry entry,
234274 unsigned long pixel,
235 ThemeBrush brush,
236 ThemeTextColor textColor,
237 ThemeBackgroundKind background,
238275 CGColorRef *c)
239276 {
240277 OSStatus err = noErr;
241
242 if (brush) {
243 err = ChkErr(HIThemeBrushCreateCGColor, brush, c);
244 /*} else if (textColor) {
245 err = ChkErr(GetThemeTextColor, textColor, 32, true, c);*/
246 } else {
247 CGFloat rgba[4] = {0, 0, 0, 1};
248
249 switch ((pixel >> 24) & 0xff) {
250 case PIXEL_MAGIC: {
251 unsigned short red, green, blue;
252 red = (pixel >> 16) & 0xff;
253 green = (pixel >> 8) & 0xff;
254 blue = (pixel ) & 0xff;
255 red |= red << 8;
256 green |= green << 8;
257 blue |= blue << 8;
258 rgba[0] = red / 65535.0;
259 rgba[1] = green / 65535.0;
260 rgba[2] = blue / 65535.0;
261 break;
262 }
263 case TRANSPARENT_PIXEL:
264 rgba[3] = 0.0;
265 break;
278 NSColor *bgColor, *color = nil;
279 CGFloat rgba[4] = {0, 0, 0, 1};
280 #if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
281 NSInteger colorVariant;
282 static CGFloat graphiteAccentRGBA[4] =
283 {152.0 / 255, 152.0 / 255, 152.0 / 255, 1.0};
284 #endif
285
286 if (!deviceRGB) {
287 deviceRGB = [NSColorSpace deviceRGBColorSpace];
288 }
289
290 /*
291 * This function is called before our autorelease pool is set up,
292 * so it needs its own pool.
293 */
294
295 NSAutoreleasePool *pool = [NSAutoreleasePool new];
296
297 switch (entry.type) {
298 case HIBrush:
299 err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c);
300 return err;
301 case rgbColor:
302 rgba[0] = ((pixel >> 16) & 0xff) / 255.0;
303 rgba[1] = ((pixel >> 8) & 0xff) / 255.0;
304 rgba[2] = ((pixel ) & 0xff) / 255.0;
305 break;
306 case ttkBackground:
307
308 /*
309 * Prior to OSX 10.14, getComponents returns black when applied to
310 * windowBackGroundColor.
311 */
312
313 if ([NSApp macMinorVersion] < 14) {
314 for (int i=0; i<3; i++) {
315 rgba[i] = windowBackground[i];
316 }
317 } else {
318 bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace:
319 deviceRGB];
320 [bgColor getComponents: rgba];
266321 }
267
268 static CGColorSpaceRef deviceRGBSpace = NULL;
269 if (!deviceRGBSpace) {
270 deviceRGBSpace = CGColorSpaceCreateDeviceRGB();
322 if (rgba[0] + rgba[1] + rgba[2] < 1.5) {
323 for (int i=0; i<3; i++) {
324 rgba[i] += entry.value*8.0 / 255.0;
325 }
326 } else {
327 for (int i=0; i<3; i++) {
328 rgba[i] -= entry.value*8.0 / 255.0;
329 }
271330 }
272 *c = CGColorCreate(deviceRGBSpace, rgba );
273 }
331 break;
332 case semantic:
333 switch (entry.value) {
334 case 0:
335 color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
336 break;
337 case 1:
338 color = [[NSColor selectedTextColor] colorUsingColorSpace: deviceRGB];
339 break;
340 case 2:
341 if ([NSApp macMinorVersion] > 9) {
342 #if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
343 color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB];
344 #endif
345 } else {
346 color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
347 }
348 break;
349 case 3:
350 color = [[NSColor controlTextColor] colorUsingColorSpace:
351 deviceRGB];
352 break;
353 case 4:
354 color = [[NSColor disabledControlTextColor] colorUsingColorSpace:
355 deviceRGB];
356 break;
357 case 5:
358 if ([NSApp macMinorVersion] > 6) {
359 color = [[NSColor whiteColor] colorUsingColorSpace:
360 deviceRGB];
361 } else {
362 color = [[NSColor blackColor] colorUsingColorSpace:
363 deviceRGB];
364 }
365 break;
366 case 6:
367 color = [[NSColor textBackgroundColor] colorUsingColorSpace:
368 deviceRGB];
369 break;
370 case 7:
371 color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace:
372 deviceRGB];
373 break;
374 case 8:
375 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
376 if (@available(macOS 10.14, *)) {
377 color = [[NSColor controlAccentColor] colorUsingColorSpace:
378 deviceRGB];
379 } else {
380 color = [NSColor colorWithColorSpace: deviceRGB
381 components: blueAccentRGBA
382 count: 4];
383 }
384 #else
385 colorVariant = [[NSUserDefaults standardUserDefaults]
386 integerForKey:@"AppleAquaColorVariant"];
387 if (colorVariant == 6) {
388 color = [NSColor colorWithColorSpace: deviceRGB
389 components: graphiteAccentRGBA
390 count: 4];
391 } else {
392 color = [NSColor colorWithColorSpace: deviceRGB
393 components: blueAccentRGBA
394 count: 4];
395 }
396 #endif
397 break;
398 default:
399 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
400 if ([NSApp macMinorVersion] >= 10) {
401 color = [[NSColor labelColor] colorUsingColorSpace:
402 deviceRGB];
403 break;
404 }
405 #endif
406 color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
407 break;
408 }
409 [color getComponents: rgba];
410 break;
411 case clearColor:
412 rgba[3] = 0.0;
413 break;
414
415 /*
416 * There are no HITheme functions which convert Text or background colors
417 * to CGColors. (GetThemeTextColor has been removed, and it was never
418 * possible with backgrounds.) If we get one of these we return black.
419 */
420
421 case HIText:
422 case HIBackground:
423 default:
424 break;
425 }
426 *c = CGColorCreate(deviceRGB.CGColorSpace, rgba);
427 [pool drain];
274428 return err;
275429 }
276430
277431 /*
278432 *----------------------------------------------------------------------
279433 *
434 * TkMacOSXInDarkMode --
435 *
436 * Tests whether the given window's NSView has a DarkAqua Appearance.
437 *
438 * Results:
439 * Returns true if the NSView is in DarkMode, false if not.
440 *
441 * Side effects:
442 * None.
443 *
444 *----------------------------------------------------------------------
445 */
446
447 MODULE_SCOPE Bool
448 TkMacOSXInDarkMode(Tk_Window tkwin)
449 {
450 int result = false;
451
452 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
453 if ([NSApp macMinorVersion] >= 14) {
454 static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua";
455 TkWindow *winPtr = (TkWindow*) tkwin;
456 NSView *view = TkMacOSXDrawableView(winPtr->privatePtr);
457 result = (view &&
458 [view.effectiveAppearance.name isEqualToString:darkAqua]);
459 }
460 #endif
461 return result;
462 }
463
464 /*
465 *----------------------------------------------------------------------
466 *
280467 * TkSetMacColor --
281468 *
282 * Creates a CGColorRef from a X style pixel value.
283 *
284 * Results:
285 * Returns false if not a real pixel, true otherwise.
469 * Sets the components of a CGColorRef from an XColor pixel value.
470 * The high order byte of the pixel value is used as an index into
471 * the system color table, and then SetCGColorComponents is called
472 * with the table entry and the pixel value.
473 *
474 * Results:
475 * Returns false if the high order byte is not a valid index, true
476 * otherwise.
286477 *
287478 * Side effects:
288479 * The variable macColor is set to a new CGColorRef, the caller is
298489 {
299490 CGColorRef *color = (CGColorRef*)macColor;
300491 OSStatus err = -1;
301 ThemeBrush brush;
302 ThemeTextColor textColor;
303 ThemeBackgroundKind background;
304
305 if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor,
306 &background)) {
307 err = ChkErr(GetThemeColor, pixel, brush, textColor, background,
308 color);
492 struct SystemColorMapEntry entry;
493
494 if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) {
495 err = ChkErr(SetCGColorComponents, entry, pixel, color);
309496 }
310497 return (err == noErr);
311498 }
320507 * Results:
321508 * None resp. retained CGColorRef for CopyCachedColor()
322509 *
323 * Side effects:
510 * Side effects:M
324511 * None.
325512 *
326513 *----------------------------------------------------------------------
449636 if (cgColor) {
450637 NSColorSpace *colorSpace = [[NSColorSpace alloc]
451638 initWithCGColorSpace:CGColorGetColorSpace(cgColor)];
639
452640 nsColor = [NSColor colorWithColorSpace:colorSpace
453641 components:CGColorGetComponents(cgColor)
454642 count:CGColorGetNumberOfComponents(cgColor)];
483671 unsigned long pixel,
484672 CGContextRef context)
485673 {
486 OSStatus err = -1;
487 CGColorRef cgColor = CopyCachedColor(gc, pixel);
488 ThemeBrush brush;
489 ThemeTextColor textColor;
490 ThemeBackgroundKind background;
491
492 if (!cgColor && GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush,
493 &textColor, &background)) {
494 if (brush) {
495 err = ChkErr(HIThemeSetFill, brush, NULL, context,
674 OSStatus err = noErr;
675 CGColorRef cgColor = nil;
676 struct SystemColorMapEntry entry;
677 CGRect rect;
678 int code = (pixel >> 24) & 0xff;
679 HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};;
680 static CGColorSpaceRef deviceRGBSpace = NULL;
681
682 if (!deviceRGBSpace) {
683 deviceRGBSpace = CGColorSpaceCreateDeviceRGB();
684 }
685 if (code < FIRST_SEMANTIC_COLOR) {
686 cgColor = CopyCachedColor(gc, pixel);
687 }
688 if (!cgColor && GetEntryFromPixelCode(code, &entry)) {
689 switch (entry.type) {
690 case HIBrush:
691 err = ChkErr(HIThemeSetFill, entry.value, NULL, context,
496692 kHIThemeOrientationNormal);
497693 if (err == noErr) {
498 err = ChkErr(HIThemeSetStroke, brush, NULL, context,
694 err = ChkErr(HIThemeSetStroke, entry.value, NULL, context,
499695 kHIThemeOrientationNormal);
500696 }
501 } else if (textColor) {
502 err = ChkErr(HIThemeSetTextFill, textColor, NULL, context,
697 break;
698 case HIText:
699 err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context,
503700 kHIThemeOrientationNormal);
504 } else if (background) {
505 CGRect rect = CGContextGetClipBoundingBox(context);
506 HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive,
507 background };
508
701 break;
702 case HIBackground:
703 info.kind = entry.value;
704 rect = CGContextGetClipBoundingBox(context);
509705 err = ChkErr(HIThemeApplyBackground, &rect, &info,
510706 context, kHIThemeOrientationNormal);
707 break;
708 default:
709 err = ChkErr(SetCGColorComponents, entry, pixel, &cgColor);
710 if (err == noErr) {
711 SetCachedColor(gc, pixel, cgColor);
712 }
713 break;
511714 }
512 if (err == noErr) {
513 return;
514 }
515 err = ChkErr(GetThemeColor, pixel, brush, textColor, background,
516 &cgColor);
517 if (err == noErr) {
518 SetCachedColor(gc, pixel, cgColor);
519 }
520 } else if (!cgColor) {
521 TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel);
522715 }
523716 if (cgColor) {
524717 CGContextSetFillColorWithColor(context, cgColor);
525718 CGContextSetStrokeColorWithColor(context, cgColor);
526719 CGColorRelease(cgColor);
527720 }
721 if (err != noErr) {
722 TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel);
723 }
528724 }
529725
530726 /*
548744 TkColor *
549745 TkpGetColor(
550746 Tk_Window tkwin, /* Window in which color will be used. */
551 Tk_Uid name) /* Name of color to allocated (in form
747 Tk_Uid name) /* Name of color to be allocated (in form
552748 * suitable for passing to XParseColor). */
553749 {
554750 Display *display = tkwin != None ? Tk_Display(tkwin) : NULL;
560756 * Check to see if this is a system color. Otherwise, XParseColor
561757 * will do all the work.
562758 */
759
563760 if (strncasecmp(name, "system", 6) == 0) {
564761 Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1);
565762 int idx, result;
566763
567764 result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap,
568 sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx);
765 sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx);
569766 Tcl_DecrRefCount(strPtr);
570767 if (result == TCL_OK) {
571768 OSStatus err;
572769 CGColorRef c;
573770 unsigned char pixelCode = idx + MIN_PIXELCODE;
574 ThemeBrush brush = systemColorMap[idx].brush;
575 ThemeTextColor textColor = systemColorMap[idx].textColor;
576 ThemeBackgroundKind background = systemColorMap[idx].background;
577
578 err = ChkErr(GetThemeColor, 0, brush, textColor, background, &c);
771 struct SystemColorMapEntry entry = systemColorMap[idx];
772
773 err = ChkErr(SetCGColorComponents, entry, 0, &c);
579774 if (err == noErr) {
580775 const size_t n = CGColorGetNumberOfComponents(c);
581776 const CGFloat *rgba = CGColorGetComponents(c);
590785 color.red = color.green = color.blue = rgba[0] * 65535.0;
591786 break;
592787 default:
593 Tcl_Panic("CGColor with %d components", (int) n);
788 Tcl_Panic("CGColor with %d components", (int) n);
594789 }
595790 color.pixel = ((((((pixelCode << 8)
596 | ((color.red >> 8) & 0xff)) << 8)
597 | ((color.green >> 8) & 0xff)) << 8)
598 | ((color.blue >> 8) & 0xff));
791 | ((color.red >> 8) & 0xff)) << 8)
792 | ((color.green >> 8) & 0xff)) << 8)
793 | ((color.blue >> 8) & 0xff));
599794 CGColorRelease(c);
600795 goto validXColor;
601796 }
7878 #define NSInformationalAlertStyle NSAlertStyleInformational
7979 #define NSCriticalAlertStyle NSAlertStyleCritical
8080 #define NSCenterTextAlignment NSTextAlignmentCenter
81 #define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
82 #define NSCommandKeyMask NSEventModifierFlagCommand
83 #define NSShiftKeyMask NSEventModifierFlagShift
84 #define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
85 #define NSAlternateKeyMask NSEventModifierFlagOption
86 #define NSControlKeyMask NSEventModifierFlagControl
87 #define NSNumericPadKeyMask NSEventModifierFlagNumericPad
88 #define NSFunctionKeyMask NSEventModifierFlagFunction
89 #define NSKeyUp NSEventTypeKeyUp
90 #define NSKeyDown NSEventTypeKeyDown
91 #define NSFlagsChanged NSEventTypeFlagsChanged
92 #define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
93 #define NSShiftKeyMask NSEventModifierFlagShift
9481 #define NSAnyEventMask NSEventMaskAny
9582 #define NSApplicationDefinedMask NSEventMaskApplicationDefined
96 #define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
9783 #define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow
9884 #define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel
9985 #define NSDocModalWindowMask NSWindowStyleMaskDocModalWindow
184184 * Declarations of static variables used in this file.
185185 */
186186
187 static TkMacOSXCursor * gCurrentCursor = NULL;
187 static TkMacOSXCursor *gCurrentCursor = NULL;
188188 /* A pointer to the current cursor. */
189189 static int gResizeOverride = false;
190190 /* A boolean indicating whether we should use
193193 * cursor. If not (for instance, in the case
194194 * where a Tk window is embedded in another
195195 * app's window, and the cursor is out of the
196 * tk window, we will not attempt to adjust
196 * Tk window, we will not attempt to adjust
197197 * the cursor. */
198198
199199 /*
277277 kCGColorSpaceGenericGray);
278278 CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
279279 bitmap, pix*pix/8, NULL);
280
280281 if (provider) {
281282 img = CGImageCreate(pix, pix, 1, 1, pix/8, colorspace,
282283 kCGBitmapByteOrderDefault, provider, decodeWB, 0,
298299 initWithCGImage:maskedImg];
299300 CFRelease(maskedImg);
300301 }
301 if (mask) { CFRelease(mask); }
302 if (img) { CFRelease(img); }
303 if (colorspace) { CFRelease(colorspace); }
302 if (mask) {
303 CFRelease(mask);
304 }
305 if (img) {
306 CFRelease(img);
307 }
308 if (colorspace) {
309 CFRelease(colorspace);
310 }
304311 if (bitmapImageRep) {
305312 image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)];
306313 [image addRepresentation:bitmapImageRep];
307314 [bitmapImageRep release];
308315 }
316
309317 uint16_t *hotSpotData = (uint16_t*)(bitmap + 2*pix*pix/8);
310318 hotSpot.y = CFSwapInt16BigToHost(*hotSpotData++);
311319 hotSpot.x = CFSwapInt16BigToHost(*hotSpotData);
2222 /*
2323 * The definitions below provide symbolic names for the default colors.
2424 * NORMAL_BG - Normal background color.
25 * NORMAL_FG - Normal foreground color.
2526 * ACTIVE_BG - Background color when widget is active.
27 * ACTIVE_FG - Foreground color when widget is active.
2628 * SELECT_BG - Background color for selected text.
2729 * SELECT_FG - Foreground color for selected text.
2830 * TROUGH - Background color for troughs in scales and scrollbars.
3234
3335 #define BLACK "Black"
3436 #define WHITE "White"
35 #define NORMAL_BG "systemWindowBody"
36 #define ACTIVE_BG "systemButtonFacePressed"
37 #define ACTIVE_FG "systemPushButtonPressedText"
38 #define SELECT_BG "systemHighlight"
39 #define SELECT_FG None
40 #define INACTIVE_SELECT_BG "systemHighlightSecondary"
37 #define NORMAL_BG "systemWindowBackgroundColor"
38 #define TEXT_BG "systemTextBackgroundColor"
39 #define NORMAL_FG "systemTextColor"
40 #define ACTIVE_BG "systemWindowBackgroundColor"
41 #define ACTIVE_FG "systemTextColor"
42 #define SELECT_BG "systemSelectedTextBackgroundColor"
43 #define SELECT_FG "systemSelectedTextColor"
44 #define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor"
4145 #define TROUGH "#c3c3c3"
4246 #define INDICATOR "#b03060"
4347 #define DISABLED "#a3a3a3"
4953 #define DEF_BUTTON_ANCHOR "center"
5054 #define DEF_BUTTON_ACTIVE_BG_COLOR ACTIVE_BG
5155 #define DEF_BUTTON_ACTIVE_BG_MONO BLACK
52 #define DEF_BUTTON_ACTIVE_FG_COLOR ACTIVE_FG
53 #define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR
56 #define DEF_BUTTON_ACTIVE_FG_COLOR WHITE
57 #define DEF_CHKRAD_ACTIVE_FG_COLOR ACTIVE_FG
5458 #define DEF_BUTTON_ACTIVE_FG_MONO WHITE
55 /* #define DEF_BUTTON_BG_COLOR "systemButtonFace"*/
56 #define DEF_BUTTON_BG_COLOR WHITE
59 #define DEF_BUTTON_BG_COLOR NORMAL_BG
5760 #define DEF_BUTTON_BG_MONO WHITE
5861 #define DEF_BUTTON_BITMAP ""
5962 #define DEF_BUTTON_BORDER_WIDTH "2"
6366 #define DEF_BUTTON_DEFAULT "disabled"
6467 #define DEF_BUTTON_DISABLED_FG_COLOR DISABLED
6568 #define DEF_BUTTON_DISABLED_FG_MONO ""
66 #define DEF_BUTTON_FG "systemButtonText"
69 #define DEF_BUTTON_FG NORMAL_FG
6770 #define DEF_CHKRAD_FG DEF_BUTTON_FG
6871 #define DEF_BUTTON_FONT "TkDefaultFont"
6972 #define DEF_BUTTON_HEIGHT "0"
7780 //#else
7881 #define DEF_BUTTON_HIGHLIGHT_WIDTH "1"
7982 //#endif
80 #define DEF_BUTTON_IMAGE ((char *) NULL)
83 #define DEF_BUTTON_IMAGE NULL
8184 #define DEF_BUTTON_INDICATOR "1"
8285 #define DEF_BUTTON_JUSTIFY "center"
8386 #define DEF_BUTTON_OFF_VALUE "0"
104107 #define DEF_BUTTON_REPEAT_INTERVAL "0"
105108 #define DEF_BUTTON_SELECT_COLOR INDICATOR
106109 #define DEF_BUTTON_SELECT_MONO BLACK
107 #define DEF_BUTTON_SELECT_IMAGE ((char *) NULL)
110 #define DEF_BUTTON_SELECT_IMAGE NULL
108111 #define DEF_BUTTON_STATE "normal"
109112 #define DEF_LABEL_TAKE_FOCUS "0"
110 #define DEF_BUTTON_TAKE_FOCUS ((char *) NULL)
113 #define DEF_BUTTON_TAKE_FOCUS NULL
111114 #define DEF_BUTTON_TEXT ""
112115 #define DEF_BUTTON_TEXT_VARIABLE ""
113116 #define DEF_BUTTON_UNDERLINE "-1"
145148 #define DEF_CANVAS_SELECT_BD_MONO "0"
146149 #define DEF_CANVAS_SELECT_FG_COLOR SELECT_FG
147150 #define DEF_CANVAS_SELECT_FG_MONO WHITE
148 #define DEF_CANVAS_TAKE_FOCUS ((char *) NULL)
151 #define DEF_CANVAS_TAKE_FOCUS NULL
149152 #define DEF_CANVAS_WIDTH "10c"
150153 #define DEF_CANVAS_X_SCROLL_CMD ""
151154 #define DEF_CANVAS_X_SCROLL_INCREMENT "0"
168171 #define MAC_OSX_ENTRY_RELIEF TK_RELIEF_SUNKEN
169172 #define MAC_OSX_ENTRY_SELECT_RELIEF TK_RELIEF_FLAT
170173
171 #define DEF_ENTRY_BG_COLOR NORMAL_BG
174 #define DEF_ENTRY_BG_COLOR TEXT_BG
172175 #define DEF_ENTRY_BG_MONO WHITE
173176 #define DEF_ENTRY_BORDER_WIDTH "2"
174177 #define DEF_ENTRY_CURSOR "xterm"
177180 #define DEF_ENTRY_DISABLED_FG DISABLED
178181 #define DEF_ENTRY_EXPORT_SELECTION "1"
179182 #define DEF_ENTRY_FONT "TkTextFont"
180 #define DEF_ENTRY_FG BLACK
183 #define DEF_ENTRY_FG NORMAL_FG
181184 #define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG
182185 #define DEF_ENTRY_HIGHLIGHT BLACK
183 /* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */
184186 #define DEF_ENTRY_HIGHLIGHT_WIDTH "3"
185 #define DEF_ENTRY_INSERT_BG BLACK
187 #define DEF_ENTRY_INSERT_BG NORMAL_FG
186188 #define DEF_ENTRY_INSERT_BD_COLOR "0"
187189 #define DEF_ENTRY_INSERT_BD_MONO "0"
188190 #define DEF_ENTRY_INSERT_OFF_TIME "300"
189191 #define DEF_ENTRY_INSERT_ON_TIME "600"
190 /* #define DEF_ENTRY_INSERT_WIDTH "2" */
191192 #define DEF_ENTRY_INSERT_WIDTH "1"
192193 #define DEF_ENTRY_JUSTIFY "left"
193194 #define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG
194195 #define DEF_ENTRY_READONLY_BG_MONO WHITE
195196 #define DEF_ENTRY_RELIEF "sunken"
196 /* #define DEF_ENTRY_RELIEF "solid" */
197197 #define DEF_ENTRY_SCROLL_COMMAND ""
198198 #define DEF_ENTRY_SELECT_COLOR SELECT_BG
199199 #define DEF_ENTRY_SELECT_MONO BLACK
201201 #define DEF_ENTRY_SELECT_BD_MONO "0"
202202 #define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG
203203 #define DEF_ENTRY_SELECT_FG_MONO WHITE
204 #define DEF_ENTRY_SHOW ((char *) NULL)
204 #define DEF_ENTRY_SHOW NULL
205205 #define DEF_ENTRY_STATE "normal"
206 #define DEF_ENTRY_TAKE_FOCUS ((char *) NULL)
206 #define DEF_ENTRY_TAKE_FOCUS NULL
207207 #define DEF_ENTRY_TEXT_VARIABLE ""
208208 #define DEF_ENTRY_WIDTH "20"
209209
236236 #define DEF_LABELFRAME_BORDER_WIDTH "2"
237237 #define DEF_LABELFRAME_CLASS "Labelframe"
238238 #define DEF_LABELFRAME_RELIEF "groove"
239 #define DEF_LABELFRAME_FG "systemButtonText"
239 #define DEF_LABELFRAME_FG NORMAL_FG
240240 #define DEF_LABELFRAME_FONT "TkDefaultFont"
241241 #define DEF_LABELFRAME_TEXT ""
242242 #define DEF_LABELFRAME_LABELANCHOR "nw"
246246 */
247247
248248 #define DEF_LISTBOX_ACTIVE_STYLE "dotbox"
249 #define DEF_LISTBOX_BG_COLOR WHITE
249 #define DEF_LISTBOX_BG_COLOR TEXT_BG
250250 #define DEF_LISTBOX_BG_MONO WHITE
251251 #define DEF_LISTBOX_BORDER_WIDTH "1"
252252 #define DEF_LISTBOX_CURSOR ""
253253 #define DEF_LISTBOX_DISABLED_FG DISABLED
254254 #define DEF_LISTBOX_EXPORT_SELECTION "1"
255255 #define DEF_LISTBOX_FONT "TkTextFont"
256 #define DEF_LISTBOX_FG BLACK
256 #define DEF_LISTBOX_FG NORMAL_FG
257257 #define DEF_LISTBOX_HEIGHT "10"
258258 #define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG
259259 #define DEF_LISTBOX_HIGHLIGHT BLACK
270270 #define DEF_LISTBOX_SELECT_MODE "browse"
271271 #define DEF_LISTBOX_SET_GRID "0"
272272 #define DEF_LISTBOX_STATE "normal"
273 #define DEF_LISTBOX_TAKE_FOCUS ((char *) NULL)
273 #define DEF_LISTBOX_TAKE_FOCUS NULL
274274 #define DEF_LISTBOX_WIDTH "20"
275275
276276 /*
277277 * Defaults for individual entries of menus:
278278 */
279279
280 #define DEF_MENU_ENTRY_ACTIVE_BG ((char *) NULL)
281 #define DEF_MENU_ENTRY_ACTIVE_FG ((char *) NULL)
282 #define DEF_MENU_ENTRY_ACCELERATOR ((char *) NULL)
283 #define DEF_MENU_ENTRY_BG ((char *) NULL)
284 #define DEF_MENU_ENTRY_BITMAP None
280 #define DEF_MENU_ENTRY_ACTIVE_BG NULL
281 #define DEF_MENU_ENTRY_ACTIVE_FG NULL
282 #define DEF_MENU_ENTRY_ACCELERATOR NULL
283 #define DEF_MENU_ENTRY_BG NULL
284 #define DEF_MENU_ENTRY_BITMAP NULL
285285 #define DEF_MENU_ENTRY_COLUMN_BREAK "0"
286 #define DEF_MENU_ENTRY_COMMAND ((char *) NULL)
286 #define DEF_MENU_ENTRY_COMMAND NULL
287287 #define DEF_MENU_ENTRY_COMPOUND "none"
288 #define DEF_MENU_ENTRY_FG ((char *) NULL)
289 #define DEF_MENU_ENTRY_FONT ((char *) NULL)
288 #define DEF_MENU_ENTRY_FG NULL
289 #define DEF_MENU_ENTRY_FONT NULL
290290 #define DEF_MENU_ENTRY_HIDE_MARGIN "0"
291 #define DEF_MENU_ENTRY_IMAGE ((char *) NULL)
291 #define DEF_MENU_ENTRY_IMAGE NULL
292292 #define DEF_MENU_ENTRY_INDICATOR "1"
293 #define DEF_MENU_ENTRY_LABEL ((char *) NULL)
294 #define DEF_MENU_ENTRY_MENU ((char *) NULL)
293 #define DEF_MENU_ENTRY_LABEL NULL
294 #define DEF_MENU_ENTRY_MENU NULL
295295 #define DEF_MENU_ENTRY_OFF_VALUE "0"
296296 #define DEF_MENU_ENTRY_ON_VALUE "1"
297 #define DEF_MENU_ENTRY_SELECT_IMAGE ((char *) NULL)
297 #define DEF_MENU_ENTRY_SELECT_IMAGE NULL
298298 #define DEF_MENU_ENTRY_STATE "normal"
299 #define DEF_MENU_ENTRY_VALUE ((char *) NULL)
300 #define DEF_MENU_ENTRY_CHECK_VARIABLE ((char *) NULL)
299 #define DEF_MENU_ENTRY_VALUE NULL
300 #define DEF_MENU_ENTRY_CHECK_VARIABLE NULL
301301 #define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton"
302 #define DEF_MENU_ENTRY_SELECT ((char *) NULL)
302 #define DEF_MENU_ENTRY_SELECT NULL
303303 #define DEF_MENU_ENTRY_UNDERLINE "-1"
304304
305305 /*
325325 #define DEF_MENU_SELECT_MONO BLACK
326326 #define DEF_MENU_TAKE_FOCUS "0"
327327 #define DEF_MENU_TEAROFF "0"
328 #define DEF_MENU_TEAROFF_CMD ((char *) NULL)
328 #define DEF_MENU_TEAROFF_CMD NULL
329329 #define DEF_MENU_TITLE ""
330330 #define DEF_MENU_TYPE "normal"
331331
333333 * Defaults for menubuttons:
334334 */
335335
336 #define DEF_MENUBUTTON_ANCHOR "center"
336 #define DEF_MENUBUTTON_ANCHOR "w"
337337 #define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG
338 #define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK
338 #define DEF_MENUBUTTON_ACTIVE_BG_MONO WHITE
339339 #define DEF_MENUBUTTON_ACTIVE_FG_COLOR ACTIVE_FG
340 #define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE
340 #define DEF_MENUBUTTON_ACTIVE_FG_MONO BLACK
341341 #define DEF_MENUBUTTON_BG_COLOR NORMAL_BG
342342 #define DEF_MENUBUTTON_BG_MONO WHITE
343343 #define DEF_MENUBUTTON_BITMAP ""
344 #define DEF_MENUBUTTON_BORDER_WIDTH "2"
344 #define DEF_MENUBUTTON_BORDER_WIDTH "0"
345345 #define DEF_MENUBUTTON_CURSOR ""
346346 #define DEF_MENUBUTTON_DIRECTION "below"
347347 #define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED
348348 #define DEF_MENUBUTTON_DISABLED_FG_MONO ""
349349 #define DEF_MENUBUTTON_FONT "TkDefaultFont"
350 #define DEF_MENUBUTTON_FG BLACK
350 #define DEF_MENUBUTTON_FG NORMAL_FG
351351 #define DEF_MENUBUTTON_HEIGHT "0"
352352 #define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR
353353 #define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO
354354 #define DEF_MENUBUTTON_HIGHLIGHT BLACK
355355 #define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0"
356 #define DEF_MENUBUTTON_IMAGE ((char *) NULL)
356 #define DEF_MENUBUTTON_IMAGE NULL
357357 #define DEF_MENUBUTTON_INDICATOR "1"
358358 #define DEF_MENUBUTTON_JUSTIFY "left"
359359 #define DEF_MENUBUTTON_MENU ""
360 #define DEF_MENUBUTTON_PADX "4"
361 #define DEF_MENUBUTTON_PADY "3"
360 #define DEF_MENUBUTTON_PADX "0"
361 #define DEF_MENUBUTTON_PADY "0"
362362 #define DEF_MENUBUTTON_RELIEF "flat"
363363 #define DEF_MENUBUTTON_STATE "normal"
364364 #define DEF_MENUBUTTON_TAKE_FOCUS "0"
378378 #define DEF_MESSAGE_BG_MONO WHITE
379379 #define DEF_MESSAGE_BORDER_WIDTH "1"
380380 #define DEF_MESSAGE_CURSOR ""
381 #define DEF_MESSAGE_FG BLACK
381 #define DEF_MESSAGE_FG NORMAL_FG
382382 #define DEF_MESSAGE_FONT "TkDefaultFont"
383383 #define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG
384384 #define DEF_MESSAGE_HIGHLIGHT BLACK
442442 #define DEF_SCALE_CURSOR ""
443443 #define DEF_SCALE_DIGITS "0"
444444 #define DEF_SCALE_FONT "TkDefaultFont"
445 #define DEF_SCALE_FG_COLOR BLACK
445 #define DEF_SCALE_FG_COLOR NORMAL_FG
446446 #define DEF_SCALE_FG_MONO BLACK
447447 #define DEF_SCALE_FROM "0"
448448 #define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR
462462 #define DEF_SCALE_SLIDER_LENGTH "30"
463463 #define DEF_SCALE_SLIDER_RELIEF "raised"
464464 #define DEF_SCALE_STATE "normal"
465 #define DEF_SCALE_TAKE_FOCUS ((char *) NULL)
465 #define DEF_SCALE_TAKE_FOCUS NULL
466466 #define DEF_SCALE_TICK_INTERVAL "0"
467467 #define DEF_SCALE_TO "100"
468468 #define DEF_SCALE_VARIABLE ""
489489 #define DEF_SCROLLBAR_RELIEF "flat"
490490 #define DEF_SCROLLBAR_REPEAT_DELAY "300"
491491 #define DEF_SCROLLBAR_REPEAT_INTERVAL "100"
492 #define DEF_SCROLLBAR_TAKE_FOCUS ((char *) NULL)
492 #define DEF_SCROLLBAR_TAKE_FOCUS NULL
493493 #define DEF_SCROLLBAR_TROUGH_COLOR TROUGH
494494 #define DEF_SCROLLBAR_TROUGH_MONO WHITE
495495 #define DEF_SCROLLBAR_WIDTH "15"
499499 */
500500
501501 #define DEF_TEXT_AUTO_SEPARATORS "1"
502 #define DEF_TEXT_BG_COLOR NORMAL_BG
502 #define DEF_TEXT_BG_COLOR TEXT_BG
503503 #define DEF_TEXT_BG_MONO WHITE
504504 #define DEF_TEXT_BLOCK_CURSOR "0"
505505 #define DEF_TEXT_BORDER_WIDTH "0"
506506 #define DEF_TEXT_CURSOR "xterm"
507 #define DEF_TEXT_FG BLACK
507 #define DEF_TEXT_FG NORMAL_FG
508508 #define DEF_TEXT_EXPORT_SELECTION "1"
509509 #define DEF_TEXT_FONT "TkFixedFont"
510510 #define DEF_TEXT_HEIGHT "24"
511511 #define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG
512512 #define DEF_TEXT_HIGHLIGHT BLACK
513513 #define DEF_TEXT_HIGHLIGHT_WIDTH "3"
514 #define DEF_TEXT_INSERT_BG BLACK
514 #define DEF_TEXT_INSERT_BG NORMAL_FG
515515 #define DEF_TEXT_INSERT_BD_COLOR "0"
516516 #define DEF_TEXT_INSERT_BD_MONO "0"
517517 #define DEF_TEXT_INSERT_OFF_TIME "300"
537537 #define DEF_TEXT_STATE "normal"
538538 #define DEF_TEXT_TABS ""
539539 #define DEF_TEXT_TABSTYLE "tabular"
540 #define DEF_TEXT_TAKE_FOCUS ((char *) NULL)
540 #define DEF_TEXT_TAKE_FOCUS NULL
541541 #define DEF_TEXT_UNDO "0"
542542 #define DEF_TEXT_WIDTH "80"
543543 #define DEF_TEXT_WRAP "char"
551551 #define DEF_CANVTEXT_FONT "TkDefaultFont"
552552
553553 /*
554 * Defaults for canvas items
555 * (arcs, bitmaps, lines, polygons, rectangles, and ovals):
556 */
557
558 #define DEF_CANVBMAP_FG NORMAL_FG
559 #define DEF_CANVITEM_OUTLINE NORMAL_FG
560
561 /*
554562 * Defaults for toplevels (most of the defaults for frames also apply
555563 * to toplevels):
556564 */
2121 #else
2222 #define modalOK NSModalResponseOK
2323 #define modalCancel NSModalResponseCancel
24 #endif
24 #endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090
2525 #define modalOther -1
2626 #define modalError -2
2727
28 /*Vars for filtering in "open file" and "save file" dialogs.*/
28 /*
29 * Vars for filtering in "open file" and "save file" dialogs.
30 */
31
2932 typedef struct {
30 bool doFileTypes; // show the accessory view which displays the filter menu
31 bool preselectFilter; // a filter was selected by the typevariable
32 bool userHasSelectedFilter; // The user has changed the filter in the accessory view
33
34 NSMutableArray *fileTypeNames; // array of names, e.g. "Text document"
35 NSMutableArray *fileTypeExtensions; // array of allowed extensions per name, e.g. "txt", "doc"
36 NSMutableArray *fileTypeLabels; // displayed string, e.g. "Text document (.txt, .doc)"
37 NSMutableArray *fileTypeAllowsAll; // boolean if the all pattern (*.*) is included
38
39 NSMutableArray *allowedExtensions; // set of all allowed extensions
40 bool allowedExtensionsAllowAll; // set of all allowed extensions includes *.*
41
42 NSUInteger fileTypeIndex; // index of currently selected filter
33 bool doFileTypes; /* Show the accessory view which
34 * displays the filter menu */
35 bool preselectFilter; /* A filter was selected by the
36 * typevariable. */
37 bool userHasSelectedFilter; /* The user has changed the filter in
38 * the accessory view. */
39 NSMutableArray *fileTypeNames; /* Array of names, e.g. "Text
40 * document". */
41 NSMutableArray *fileTypeExtensions; /* Array of allowed extensions per
42 * name, e.g. "txt", "doc". */
43 NSMutableArray *fileTypeLabels; /* Displayed string, e.g. "Text
44 * document (.txt, .doc)". */
45 NSMutableArray *fileTypeAllowsAll; /* Boolean if the all pattern (*.*) is
46 * included. */
47 NSMutableArray *allowedExtensions; /* Set of all allowed extensions. */
48 bool allowedExtensionsAllowAll; /* Set of all allowed extensions
49 * includes *.* */
50 NSUInteger fileTypeIndex; /* Index of currently selected
51 * filter. */
4352 } filepanelFilterInfo;
4453
45 filepanelFilterInfo filterInfo;
46
47 NSOpenPanel *openpanel;
48 NSSavePanel *savepanel;
54 static filepanelFilterInfo filterInfo;
55 static NSOpenPanel *openpanel;
56 static NSSavePanel *savepanel;
4957
5058 static const char *const colorOptionStrings[] = {
5159 "-initialcolor", "-parent", "-title", NULL
165173 };
166174
167175 /*
168 * Construct a file URL from directory and filename. Either may
169 * be nil. If both are nil, returns nil.
170 */
171 static NSURL *getFileURL(NSString *directory, NSString *filename) {
176 * Construct a file URL from directory and filename. Either may be nil. If both
177 * are nil, returns nil.
178 */
179
180 static NSURL *
181 getFileURL(
182 NSString *directory,
183 NSString *filename)
184 {
172185 NSURL *url = nil;
173186 if (directory) {
174187 url = [NSURL fileURLWithPath:directory isDirectory:YES];
181194
182195 #pragma mark TKApplication(TKDialog)
183196
184 @interface NSColorPanel(TKDialog)
185 - (void) _setUseModalAppearance: (BOOL) flag;
186 @end
187
188197 @implementation TKApplication(TKDialog)
198
199 - (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {
200 return YES;
201 }
202
203 - (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url {
204 }
205
206 - (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError {
207 *outError = nil;
208 return YES;
209 }
189210
190211 - (void) tkFilePanelDidEnd: (NSSavePanel *) panel
191212 returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
232253 }
233254 }
234255
235
236256 - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode
237257 contextInfo: (void *) contextInfo
238258 {
275295
276296 if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) {
277297 [openpanel setAllowsOtherFileTypes:YES];
278 /* setAllowsOtherFileTypes might have no effect; it's inherited from the
279 * NSSavePanel, where it has the effect that it does not append an extension
280 * Setting the allowed file types to nil allows selecting any file */
298
299 /*
300 * setAllowsOtherFileTypes might have no effect; it's inherited from
301 * the NSSavePanel, where it has the effect that it does not append an
302 * extension. Setting the allowed file types to nil allows selecting
303 * any file.
304 */
305
281306 [openpanel setAllowedFileTypes:nil];
282307 } else {
283 NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
308 NSMutableArray *allowedtypes =
309 [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
284310 [openpanel setAllowedFileTypes:allowedtypes];
285311 [openpanel setAllowsOtherFileTypes:NO];
286312 }
296322 [savepanel setAllowsOtherFileTypes:YES];
297323 [savepanel setAllowedFileTypes:nil];
298324 } else {
299 NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
325 NSMutableArray *allowedtypes =
326 [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
300327 [savepanel setAllowedFileTypes:allowedtypes];
301328 [savepanel setAllowsOtherFileTypes:NO];
302329 }
307334 @end
308335
309336 #pragma mark -
337
338 static NSInteger showOpenSavePanel(
339 NSSavePanel *panel,
340 NSWindow *parent,
341 FilePanelCallbackInfo *callbackInfo)
342 {
343 NSInteger modalReturnCode;
344
345 if (parent && ![parent attachedSheet] && [NSApp macMinorVersion] < 15) {
346 [panel beginSheetModalForWindow:parent
347 completionHandler:^(NSInteger returnCode) {
348 [NSApp tkFilePanelDidEnd:panel
349 returnCode:returnCode
350 contextInfo:callbackInfo ];
351 }];
352 modalReturnCode = callbackInfo->cmdObj ? modalOther :
353 [NSApp runModalForWindow:panel];
354 } else {
355 modalReturnCode = [panel runModal];
356 [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
357 contextInfo:callbackInfo];
358 }
359 return modalReturnCode;
360 }
310361
311362 /*
312363 *----------------------------------------------------------------------
387438 [colorPanel _setUseModalAppearance:YES];
388439 if (title) {
389440 NSString *s = [[NSString alloc] initWithUTF8String:title];
441
390442 [colorPanel setTitle:s];
391443 [s release];
392444 }
418470 return result;
419471 }
420472
421 /* dissect the -filetype nested lists and store the information
422 * in the filterInfo structure */
423 int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVariablePtr) {
473 /*
474 * Dissect the -filetype nested lists and store the information in the
475 * filterInfo structure.
476 */
477
478 static int
479 parseFileFilters(
480 Tcl_Interp *interp,
481 Tcl_Obj *fileTypesPtr,
482 Tcl_Obj *typeVariablePtr)
483 {
424484
425485 if (!fileTypesPtr) {
426486 filterInfo.doFileTypes = false;
428488 }
429489
430490 FileFilterList fl;
491
431492 TkInitFileFilters(&fl);
432493 if (TkGetFileFilters(interp, &fl, fileTypesPtr, 0) != TCL_OK) {
433494 TkFreeFileFilters(&fl);
448509 if (filterInfo.doFileTypes) {
449510 for (FileFilter *filterPtr = fl.filters; filterPtr;
450511 filterPtr = filterPtr->next) {
451 NSString * name = [[NSString alloc] initWithUTF8String: filterPtr -> name];
512 NSString *name = [[NSString alloc] initWithUTF8String: filterPtr->name];
513
452514 [filterInfo.fileTypeNames addObject:name];
453515 [name release];
454 NSMutableArray * clauseextensions = [NSMutableArray array];
455 NSMutableArray * displayextensions = [NSMutableArray array];
516 NSMutableArray *clauseextensions = [NSMutableArray array];
517 NSMutableArray *displayextensions = [NSMutableArray array];
456518 bool allowsAll = NO;
457519
458520 for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr;
463525 const char *str = globPtr->pattern;
464526 while (*str && (*str == '*' || *str == '.')) {
465527 str++;
466 }
528 }
467529 if (*str) {
468530 NSString *extension = [[NSString alloc] initWithUTF8String:str];
469531 if (![filterInfo.allowedExtensions containsObject:extension]) {
475537
476538 [extension release];
477539 } else {
478 // it is the all pattern (*, .* or *.*)
540 /*
541 * It is the all pattern (*, .* or *.*)
542 */
543
479544 allowsAll = YES;
480545 filterInfo.allowedExtensionsAllowAll = YES;
481546 [displayextensions addObject:@"*"];
485550 [filterInfo.fileTypeExtensions addObject:clauseextensions];
486551 [filterInfo.fileTypeAllowsAll addObject:[NSNumber numberWithBool:allowsAll]];
487552
488 NSMutableString * label = [[NSMutableString alloc] initWithString:name];
553 NSMutableString *label = [[NSMutableString alloc] initWithString:name];
489554 [label appendString:@" ("];
490555 [label appendString:[displayextensions componentsJoinedByString:@", "]];
491556 [label appendString:@")"];
492557 [filterInfo.fileTypeLabels addObject:label];
493558 [label release];
494
495 }
496
497 /* Check if the typevariable exists and matches one of the names */
559 }
560
561 /*
562 * Check if the typevariable exists and matches one of the names.
563 */
564
498565 filterInfo.preselectFilter = false;
499566 filterInfo.userHasSelectedFilter = false;
500567 if (typeVariablePtr) {
501 /* extract the variable content as a NSString */
502 Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, typeVariablePtr, NULL, TCL_GLOBAL_ONLY);
503
504 /* check that the typevariable exists */
568 /*
569 * Extract the variable content as a NSString.
570 */
571
572 Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp,
573 typeVariablePtr, NULL, TCL_GLOBAL_ONLY);
574
575 /*
576 * Check that the typevariable exists.
577 */
578
505579 if (selectedFileTypeObj != NULL) {
506 const char *selectedFileType = Tcl_GetString(selectedFileTypeObj);
507 NSString *selectedFileTypeStr = [[NSString alloc] initWithUTF8String:selectedFileType];
508 NSUInteger index = [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr];
580 const char *selectedFileType =
581 Tcl_GetString(selectedFileTypeObj);
582 NSString *selectedFileTypeStr =
583 [[NSString alloc] initWithUTF8String:selectedFileType];
584 NSUInteger index =
585 [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr];
509586
510587 if (index != NSNotFound) {
511588 filterInfo.fileTypeIndex = index;
520597 return TCL_OK;
521598 }
522599
523 bool filterCompatible(NSString *extension, int filterIndex) {
524 NSMutableArray *allowedExtensions = [filterInfo.fileTypeExtensions objectAtIndex: filterIndex];
525
526 /* If this contains the all pattern, accept any extension */
600 static bool
601 filterCompatible(
602 NSString *extension,
603 int filterIndex)
604 {
605 NSMutableArray *allowedExtensions =
606 [filterInfo.fileTypeExtensions objectAtIndex: filterIndex];
607
608 /*
609 * If this contains the all pattern, accept any extension.
610 */
611
527612 if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterIndex] boolValue]) {
528613 return true;
529614 }
530615
531616 return [allowedExtensions containsObject: extension];
532617 }
533
534618
535619 /*
536620 *----------------------------------------------------------------------
569653 NSInteger modalReturnCode = modalError;
570654 BOOL parentIsKey = NO;
571655
656 [openpanel setDelegate:NSApp];
657
572658 for (i = 1; i < objc; i += 2) {
573659 if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,
574660 sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
630716 break;
631717 }
632718 }
633
634719 if (title) {
635720 [openpanel setTitle:title];
636721
637 /* From OSX 10.11, the title string is silently ignored in the open panel.
638 * Prepend the title to the message in this case
639 * NOTE should be conditional on OSX version, but
640 * -mmacosx-version-min does not revert this behaviour*/
641
642 if (message) {
643 NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message];
644 [message release];
645 [title release];
646 message = fullmessage;
647 } else {
648 message = title;
722 /*
723 * From OSX 10.11, the title string is silently ignored in the open
724 * panel. Prepend the title to the message in this case.
725 */
726
727 if ([NSApp macMinorVersion] > 10) {
728 if (message) {
729 NSString *fullmessage =
730 [[NSString alloc] initWithFormat:@"%@\n%@", title, message];
731 [message release];
732 [title release];
733 message = fullmessage;
734 } else {
735 message = title;
736 }
649737 }
650738 }
651739
661749 }
662750
663751 if (filterInfo.doFileTypes) {
664 NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
665 NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)];
752 NSTextField *label = [[NSTextField alloc]
753 initWithFrame:NSMakeRect(0, 0, 60, 22)];
754 NSPopUpButton *popupButton = [[NSPopUpButton alloc]
755 initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO];
756 NSView *accessoryView = [[NSView alloc]
757 initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
758
666759 [label setEditable:NO];
667760 [label setStringValue:@"Filter:"];
668761 [label setBordered:NO];
669762 [label setBezeled:NO];
670763 [label setDrawsBackground:NO];
671
672 NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO];
673764 [popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
674765 [popupButton setAction:@selector(selectFormat:)];
675
676766 [accessoryView addSubview:label];
677767 [accessoryView addSubview:popupButton];
678
679768 if (filterInfo.preselectFilter) {
680 /* A specific filter was selected from the typevariable. Select it and
681 * open the accessory view */
769
770 /*
771 * A specific filter was selected from the typevariable. Select it
772 * and open the accessory view.
773 */
774
682775 [popupButton selectItemAtIndex:filterInfo.fileTypeIndex];
683 /* on OSX > 10.11, the optons are not visible by default. Ergo allow all file types
776
777 /*
778 * On OSX > 10.11, the options are not visible by default. Ergo
779 * allow all file types
684780 [openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]];
685781 */
782
686783 [openpanel setAllowedFileTypes:filterInfo.allowedExtensions];
687784 } else {
688785 [openpanel setAllowedFileTypes:filterInfo.allowedExtensions];
689786 }
690
691787 if (filterInfo.allowedExtensionsAllowAll) {
692788 [openpanel setAllowsOtherFileTypes:YES];
693789 } else {
694790 [openpanel setAllowsOtherFileTypes:NO];
695791 }
696
697792 [openpanel setAccessoryView:accessoryView];
698793 } else {
699 /* No filters are given. Allow picking all files */
794 /*
795 * No filters are given. Allow picking all files.
796 */
797
700798 [openpanel setAllowsOtherFileTypes:YES];
701799 }
702
703800 if (cmdObj) {
704 callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
705801 if (Tcl_IsShared(cmdObj)) {
706802 cmdObj = Tcl_DuplicateObj(cmdObj);
707803 }
708804 Tcl_IncrRefCount(cmdObj);
709805 }
710
806 callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
711807 callbackInfo->cmdObj = cmdObj;
712808 callbackInfo->interp = interp;
713809 callbackInfo->multiple = multiple;
714 parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
715 if (haveParentOption && parent && ![parent attachedSheet]) {
716 parentIsKey = [parent isKeyWindow];
717 if (directory || filename ) {
718 NSURL * fileURL = getFileURL(directory, filename);
719 [openpanel setDirectoryURL:fileURL];
720 }
721
722 [openpanel beginSheetModalForWindow:parent
723 completionHandler:^(NSInteger returnCode)
724 { [NSApp tkFilePanelDidEnd:openpanel
725 returnCode:returnCode
726 contextInfo:callbackInfo ]; } ];
727 modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:openpanel];
810 if (directory || filename) {
811 NSURL *fileURL = getFileURL(directory, filename);
812
813 [openpanel setDirectoryURL:fileURL];
814 }
815 if (haveParentOption) {
816 parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
817 parentIsKey = parent && [parent isKeyWindow];
728818 } else {
729 if (directory || filename ) {
730 NSURL * fileURL = getFileURL(directory, filename);
731 [openpanel setDirectoryURL:fileURL];
732 }
733
734 modalReturnCode = [openpanel runModal];
735 [NSApp tkFilePanelDidEnd:openpanel returnCode:modalReturnCode
736 contextInfo:callbackInfo];
737 }
819 parent = nil;
820 parentIsKey = False;
821 }
822 modalReturnCode = showOpenSavePanel(openpanel, parent, callbackInfo);
738823 result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
739824 if (parentIsKey) {
740825 [parent makeKeyWindow];
741826 }
742
743 if ((typeVariablePtr && (modalReturnCode == NSOKButton)) &&
744 filterInfo.doFileTypes) {
827 if ((typeVariablePtr && (modalReturnCode == NSOKButton))
828 && filterInfo.doFileTypes) {
745829 /*
746 * The -typevariable must be set to the selected file type, if the dialog was not cancelled
830 * The -typevariable must be set to the selected file type, if the
831 * dialog was not cancelled.
747832 */
833
748834 NSUInteger selectedFilterIndex = filterInfo.fileTypeIndex;
749835 NSString *selectedFilter = NULL;
836
750837 if (filterInfo.userHasSelectedFilter) {
751838 selectedFilterIndex = filterInfo.fileTypeIndex;
752839 selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
753840 } else {
754 /* Difficult case: the user has not touched the filter settings, but we must
755 * return something in the typevariable. First check if the preselected type is compatible
756 * with the selected file, otherwise choose the first compatible type from the list,
757 * finally fall back to the empty string */
841 /*
842 * Difficult case: the user has not touched the filter settings,
843 * but we must return something in the typevariable. First check if
844 * the preselected type is compatible with the selected file,
845 * otherwise choose the first compatible type from the list,
846 * finally fall back to the empty string.
847 */
848
758849 NSURL *selectedFile;
850 NSString *extension;
759851 if (multiple) {
760 // Use the first file in the case of multiple selection
761 // Anyway it is not overly useful here
852 /*
853 * Use the first file in the case of multiple selection.
854 * Anyway it is not overly useful here.
855 */
762856 selectedFile = [[openpanel URLs] objectAtIndex:0];
763857 } else {
764858 selectedFile = [openpanel URL];
765859 }
766860
767 NSString *extension = [selectedFile pathExtension];
861 extension = [selectedFile pathExtension];
862
768863 if (filterInfo.preselectFilter &&
769 filterCompatible(extension, filterInfo.fileTypeIndex)) {
864 filterCompatible(extension, filterInfo.fileTypeIndex)) {
770865 selectedFilterIndex = filterInfo.fileTypeIndex; // The preselection from the typevariable
771866 selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
772867 } else {
773 // scan the list
774868 NSUInteger i;
869
775870 for (i = 0; i < [filterInfo.fileTypeNames count]; i++) {
776871 if (filterCompatible(extension, i)) {
777872 selectedFilterIndex = i;
783878 } else {
784879 selectedFilter = @"";
785880 }
786
787 }
788 }
789
881 }
882 }
790883 Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
791 Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
792 }
793
794
795 end:
884 Tcl_NewStringObj([selectedFilter UTF8String], -1),
885 TCL_GLOBAL_ONLY);
886 }
887 end:
796888 return result;
797889 }
798
799890
800891 /*
801892 *----------------------------------------------------------------------
810901 *
811902 * Side effects:
812903 * See user documentation.
904 *
813905 *----------------------------------------------------------------------
814906 */
815907
831923 NSString *directory = nil, *filename = nil, *defaultType = nil;
832924 NSString *message = nil, *title = nil;
833925 NSWindow *parent;
834 savepanel = [NSSavePanel savePanel];
926 savepanel = [NSSavePanel savePanel];
835927 NSInteger modalReturnCode = modalError;
836928 BOOL parentIsKey = NO;
929
930 [savepanel setDelegate:NSApp];
837931
838932 for (i = 1; i < objc; i += 2) {
839933 if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,
9091003 if (title) {
9101004 [savepanel setTitle:title];
9111005
912 /* From OSX 10.11, the title string is silently ignored, if the save panel is a sheet.
913 * Prepend the title to the message in this case
914 * NOTE should be conditional on OSX version, but
915 * -mmacosx-version-min does not revert this behaviour*/
1006 /*
1007 * From OSX 10.11, the title string is silently ignored, if the save
1008 * panel is a sheet. Prepend the title to the message in this case.
1009 * NOTE: should be conditional on OSX version, but -mmacosx-version-min
1010 * does not revert this behaviour.
1011 */
1012
9161013 if (haveParentOption) {
9171014 if (message) {
918 NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message];
1015 NSString *fullmessage =
1016 [[NSString alloc] initWithFormat:@"%@\n%@",title,message];
9191017 [message release];
9201018 [title release];
9211019 message = fullmessage;
9351033 }
9361034
9371035 if (filterInfo.doFileTypes) {
938 NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
939 NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)];
1036 NSView *accessoryView = [[NSView alloc]
1037 initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
1038 NSTextField *label = [[NSTextField alloc]
1039 initWithFrame:NSMakeRect(0, 0, 60, 22)];
1040
9401041 [label setEditable:NO];
9411042 [label setStringValue:NSLocalizedString(@"Format:", nil)];
9421043 [label setBordered:NO];
9431044 [label setBezeled:NO];
9441045 [label setDrawsBackground:NO];
9451046
946 NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO];
1047 NSPopUpButton *popupButton = [[NSPopUpButton alloc]
1048 initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO];
1049
9471050 [popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
9481051 [popupButton selectItemAtIndex:filterInfo.fileTypeIndex];
9491052 [popupButton setAction:@selector(saveFormat:)];
9561059 [savepanel setAllowedFileTypes:[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]];
9571060 [savepanel setAllowsOtherFileTypes:filterInfo.allowedExtensionsAllowAll];
9581061 } else if (defaultType) {
959 /* If no filetypes are given, defaultextension is an alternative way
960 * to specify the attached extension. Just propose this extension,
961 * but don't display an accessory view */
1062 /*
1063 * If no filetypes are given, defaultextension is an alternative way to
1064 * specify the attached extension. Just propose this extension, but
1065 * don't display an accessory view.
1066 */
1067
9621068 NSMutableArray *AllowedFileTypes = [NSMutableArray array];
1069
9631070 [AllowedFileTypes addObject:defaultType];
9641071 [savepanel setAllowedFileTypes:AllowedFileTypes];
9651072 [savepanel setAllowsOtherFileTypes:YES];
9691076 [savepanel setExtensionHidden:NO];
9701077
9711078 if (cmdObj) {
972 callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
9731079 if (Tcl_IsShared(cmdObj)) {
9741080 cmdObj = Tcl_DuplicateObj(cmdObj);
9751081 }
9761082 Tcl_IncrRefCount(cmdObj);
9771083 }
1084 callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
9781085 callbackInfo->cmdObj = cmdObj;
9791086 callbackInfo->interp = interp;
9801087 callbackInfo->multiple = 0;
9811088
982 parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
983 if (haveParentOption && parent && ![parent attachedSheet]) {
984 parentIsKey = [parent isKeyWindow];
985 if (directory) {
986 [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
987 }
988 /*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/
989 if (filename) {
990 [savepanel setNameFieldStringValue:filename];
991 } else {
992 [savepanel setNameFieldStringValue:@""];
993 }
994 [savepanel beginSheetModalForWindow:parent
995 completionHandler:^(NSInteger returnCode)
996 { [NSApp tkFilePanelDidEnd:savepanel
997 returnCode:returnCode
998 contextInfo:callbackInfo ]; } ];
999 modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:savepanel];
1089 if (directory) {
1090 [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
1091 }
1092
1093 /*
1094 * Check for file name and set to the empty string if nil. This prevents a crash
1095 * with an uncaught exception.
1096 */
1097
1098 if (filename) {
1099 [savepanel setNameFieldStringValue:filename];
10001100 } else {
1001 if (directory) {
1002 [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
1003 }
1004 /*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/
1005 if (filename) {
1006 [savepanel setNameFieldStringValue:filename];
1007 } else {
1008 [savepanel setNameFieldStringValue:@""];
1009 }
1010 modalReturnCode = [savepanel runModal];
1011 [NSApp tkFilePanelDidEnd:savepanel returnCode:modalReturnCode
1012 contextInfo:callbackInfo];
1013 }
1101 [savepanel setNameFieldStringValue:@""];
1102 }
1103 if (haveParentOption) {
1104 parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
1105 parentIsKey = parent && [parent isKeyWindow];
1106 } else {
1107 parent = nil;
1108 parentIsKey = False;
1109 }
1110 modalReturnCode = showOpenSavePanel(savepanel, parent, callbackInfo);
10141111 result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
10151112 if (parentIsKey) {
10161113 [parent makeKeyWindow];
10171114 }
10181115
1019 if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) {
1116 if (typeVariablePtr && (modalReturnCode == NSOKButton)
1117 && filterInfo.doFileTypes) {
10201118 /*
1021 * The -typevariable must be set to the selected file type, if the dialog was not cancelled
1119 * The -typevariable must be set to the selected file type, if the
1120 * dialog was not cancelled.
10221121 */
1023 NSString * selectedFilter = [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex];
1122
1123 NSString *selectedFilter =
1124 [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex];
10241125 Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
1025 Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
1026 }
1027
1126 Tcl_NewStringObj([selectedFilter UTF8String], -1),
1127 TCL_GLOBAL_ONLY);
1128 }
10281129
10291130 end:
10301131 return result;
10691170 NSInteger modalReturnCode = modalError;
10701171 BOOL parentIsKey = NO;
10711172
1173 [panel setDelegate:NSApp];
1174
10721175 for (i = 1; i < objc; i += 2) {
10731176 if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,
10741177 sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
11241227 [panel setCanChooseDirectories:YES];
11251228 [panel setCanCreateDirectories:!mustexist];
11261229 if (cmdObj) {
1127 callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
11281230 if (Tcl_IsShared(cmdObj)) {
11291231 cmdObj = Tcl_DuplicateObj(cmdObj);
11301232 }
11311233 Tcl_IncrRefCount(cmdObj);
11321234 }
1235 callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
11331236 callbackInfo->cmdObj = cmdObj;
11341237 callbackInfo->interp = interp;
11351238 callbackInfo->multiple = 0;
1136 /*check for directory value, set to root if not specified; otherwise crashes with exception because of nil string parameter*/
1239
1240 /*
1241 * Check for directory value, set to root if not specified; otherwise
1242 * crashes with exception because of nil string parameter.
1243 */
1244
11371245 if (!directory) {
11381246 directory = @"/";
11391247 }
11401248 parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
1141 if (haveParentOption && parent && ![parent attachedSheet]) {
1142 parentIsKey = [parent isKeyWindow];
1143 [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
1144 [panel beginSheetModalForWindow:parent
1145 completionHandler:^(NSInteger returnCode)
1146 { [NSApp tkFilePanelDidEnd:panel
1147 returnCode:returnCode
1148 contextInfo:callbackInfo ]; } ];
1149 modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
1249 [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
1250 if (haveParentOption) {
1251 parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
1252 parentIsKey = parent && [parent isKeyWindow];
11501253 } else {
1151 [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
1152 modalReturnCode = [panel runModal];
1153 [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
1154 contextInfo:callbackInfo];
1155 }
1254 parent = nil;
1255 parentIsKey = False;
1256 }
1257 modalReturnCode = showOpenSavePanel(panel, parent, callbackInfo);
11561258 result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
11571259 if (parentIsKey) {
11581260 [parent makeKeyWindow];
11971299 NSString *year = [dateFormatter stringFromDate:[NSDate date]];
11981300
11991301 [dateFormatter release];
1200
1302
12011303 /*
12021304 * This replaces the old about dialog with a standard alert that displays
12031305 * correctly on 10.14.
12041306 */
1205
1307
12061308 NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL;
1207 NSString *url = @"www.tcl-lang.org";
1309 NSString *url = @"www.tcl-lang.org";
12081310 NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)];
12091311 NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
12101312 NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font
12111313 forKey:NSFontAttributeName];
1314
12121315 [credits insertText: [[NSAttributedString alloc]
12131316 initWithString:[NSString stringWithFormat: @"\n"
12141317 "Tcl and Tk are distributed under a modified BSD license: "
12221325 "%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n"
12231326 "%1$C 1998-2000 Scriptics Inc.\n\n"
12241327 "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year]
1225 attributes:textAttributes]
1226 replacementRange:NSMakeRange(0,0)];
1328 attributes:textAttributes]
1329 replacementRange:NSMakeRange(0,0)];
12271330 [credits setDrawsBackground:NO];
12281331 [credits setEditable:NO];
1229 NSAlert *about = [[NSAlert alloc] init];
1332
1333 NSAlert *about = [[NSAlert alloc] init];
1334
12301335 [[about window] setTitle:@"About Tcl & Tk"];
12311336 [about setMessageText: version];
12321337 [about setInformativeText:url];
13811486 */
13821487
13831488 if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1],
1384 alertButtonStrings, sizeof(char *), "-default value", TCL_EXACT, &index) != TCL_OK) {
1489 alertButtonStrings, sizeof(char *), "-default value",
1490 TCL_EXACT, &index) != TCL_OK) {
13851491 goto end;
13861492 }
13871493
14021508 [alert setAlertStyle:alertStyles[iconIndex]];
14031509 i = 0;
14041510 while (i < 3 && alertButtonNames[typeIndex][i]) {
1405 [alert addButtonWithTitle:(NSString*)alertButtonNames[typeIndex][i++]];
1511 [alert addButtonWithTitle:(NSString*) alertButtonNames[typeIndex][i++]];
14061512 }
14071513 buttons = [alert buttons];
14081514 for (NSButton *b in buttons) {
14171523 [[buttons objectAtIndex: defaultNativeButtonIndex-1]
14181524 setKeyEquivalent: @"\r"];
14191525 if (cmdObj) {
1420 callbackInfo = ckalloc(sizeof(AlertCallbackInfo));
14211526 if (Tcl_IsShared(cmdObj)) {
14221527 cmdObj = Tcl_DuplicateObj(cmdObj);
14231528 }
14241529 Tcl_IncrRefCount(cmdObj);
14251530 }
1531 callbackInfo = ckalloc(sizeof(AlertCallbackInfo));
14261532 callbackInfo->cmdObj = cmdObj;
14271533 callbackInfo->interp = interp;
14281534 callbackInfo->typeIndex = typeIndex;
14291535 parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
14301536 if (haveParentOption && parent && ![parent attachedSheet]) {
14311537 parentIsKey = [parent isKeyWindow];
1432 #if MAC_OS_X_VERSION_MIN_REQUIRED > 1090
1538 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
14331539 [alert beginSheetModalForWindow:parent
1434 completionHandler:^(NSModalResponse returnCode)
1435 { [NSApp tkAlertDidEnd:alert
1436 returnCode:returnCode
1437 contextInfo:callbackInfo ]; } ];
1540 completionHandler:^(NSModalResponse returnCode) {
1541 [NSApp tkAlertDidEnd:alert
1542 returnCode:returnCode
1543 contextInfo:callbackInfo];
1544 }];
14381545 #else
14391546 [alert beginSheetModalForWindow:parent
14401547 modalDelegate:NSApp
14421549 contextInfo:callbackInfo];
14431550 #endif
14441551 modalReturnCode = cmdObj ? 0 :
1445 [NSApp runModalForWindow:[alert window]];
1552 [alert runModal];
14461553 } else {
14471554 modalReturnCode = [alert runModal];
14481555 [NSApp tkAlertDidEnd:alert returnCode:modalReturnCode
14741581 Tk_Window parent;
14751582 } FontchooserData;
14761583
1477 enum FontchooserEvent { FontchooserClosed, FontchooserSelection };
1584 enum FontchooserEvent {
1585 FontchooserClosed,
1586 FontchooserSelection
1587 };
14781588
14791589 static void FontchooserEvent(int kind);
14801590 static Tcl_Obj * FontchooserCget(FontchooserData *fcdPtr,
15661676 *
15671677 * FontchooserEvent --
15681678 *
1569 * This processes events generated by user interaction with the
1570 * font panel.
1679 * This processes events generated by user interaction with the font
1680 * panel.
15711681 *
15721682 * Results:
15731683 * None.
16261736 *
16271737 * FontchooserCget --
16281738 *
1629 * Helper for the FontchooserConfigure command to return the
1630 * current value of any of the options (which may be NULL in
1631 * the structure)
1739 * Helper for the FontchooserConfigure command to return the current value
1740 * of any of the options (which may be NULL in the structure).
16321741 *
16331742 * Results:
16341743 * Tcl object of option value.
16911800 *
16921801 * FontchooserConfigureCmd --
16931802 *
1694 * Implementation of the 'tk fontchooser configure' ensemble command.
1695 * See the user documentation for what it does.
1803 * Implementation of the 'tk fontchooser configure' ensemble command. See
1804 * the user documentation for what it does.
16961805 *
16971806 * Results:
16981807 * See the user documentation.
18251934 [fm setSelectedAttributes:fontPanelFontAttributes
18261935 isMultiple:NO];
18271936 if ([fp isVisible]) {
1828 TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
1937 TkSendVirtualEvent(fcdPtr->parent,
1938 "TkFontchooserFontChanged", NULL);
18291939 }
18301940 break;
18311941 case FontchooserCmd:
18531963 *
18541964 * FontchooserShowCmd --
18551965 *
1856 * Implements the 'tk fontchooser show' ensemble command. The
1857 * per-interp configuration data for the dialog is held in an interp
1858 * associated structure.
1966 * Implements the 'tk fontchooser show' ensemble command. The per-interp
1967 * configuration data for the dialog is held in an interp associated
1968 * structure.
18591969 *
18601970 * Results:
18611971 * See the user documentation.
18811991 Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,
18821992 FontchooserParentEventHandler, fcdPtr);
18831993 }
1994
18841995 NSFontManager *fm = [NSFontManager sharedFontManager];
18851996 NSFontPanel *fp = [fm fontPanel:YES];
1997
18861998 if ([fp delegate] != NSApp) {
18871999 [fp setDelegate:NSApp];
18882000 }
19002012 *
19012013 * FontchooserHideCmd --
19022014 *
1903 * Implementation of the 'tk fontchooser hide' ensemble. See the
1904 * user documentation for details.
2015 * Implementation of the 'tk fontchooser hide' ensemble. See the user
2016 * documentation for details.
19052017 *
19062018 * Results:
19072019 * See the user documentation.
19202032 Tcl_Obj *const objv[])
19212033 {
19222034 NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO];
2035
19232036 if ([fp isVisible]) {
19242037 [fp orderOut:NSApp];
19252038 }
19532066 if (eventPtr->type == DestroyNotify) {
19542067 Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask,
19552068 FontchooserParentEventHandler, fcdPtr);
1956 fcdPtr->parent = None;
2069 fcdPtr->parent = NULL;
19572070 FontchooserHideCmd(NULL, NULL, 0, NULL);
19582071 }
19592072 }
20002113 *
20012114 * TkInitFontchooser --
20022115 *
2003 * Associate the font chooser configuration data with the Tcl
2004 * interpreter. There is one font chooser per interp.
2116 * Associate the font chooser configuration data with the Tcl interpreter.
2117 * There is one font chooser per interp.
20052118 *
20062119 * Results:
20072120 * None.
00 /*
11 * tkMacOSXDraw.c --
22 *
3 * This file contains functions that perform drawing to
4 * Xlib windows. Most of the functions simple emulate
5 * Xlib functions.
3 * This file contains functions that perform drawing to Xlib windows. Most
4 * of the functions simply emulate Xlib functions.
65 *
76 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
87 * Copyright 2001-2009, Apple Inc.
3029 #endif
3130 */
3231
33 #define radians(d) ((d) * (M_PI/180.0))
32 #define radians(d) ((d) * (M_PI/180.0))
3433
3534 /*
3635 * Non-antialiased CG drawing looks better and more like X11 drawing when using
3938 #define NON_AA_CG_OFFSET .999
4039
4140 static int cgAntiAliasLimit = 0;
42 #define notAA(w) ((w) < cgAntiAliasLimit)
41 #define notAA(w) ((w) < cgAntiAliasLimit)
4342
4443 static int useThemedToplevel = 0;
4544 static int useThemedFrame = 0;
118117 * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that
119118 * is what is being used here. However, that method only works when the
120119 * view has a valid CGContext, and a view is only guaranteed to have a
121 * valid context during a call to [NSView drawRect]. To further
122 * complicate matters, cacheDisplayInRect calls [NSView drawRect].
123 * Essentially it is asking the view to draw a subrectangle of itself into
124 * a special graphics context which is linked to the BitmapImageRep. But
125 * our implementation of [NSView drawRect] does not allow recursive calls.
126 * If called recursively it returns immediately without doing any drawing.
120 * valid context during a call to [NSView drawRect]. To further complicate
121 * matters, cacheDisplayInRect calls [NSView drawRect]. Essentially it is
122 * asking the view to draw a subrectangle of itself into a special
123 * graphics context which is linked to the BitmapImageRep. But our
124 * implementation of [NSView drawRect] does not allow recursive calls. If
125 * called recursively it returns immediately without doing any drawing.
127126 * So the bottom line is that this function either returns a NULL pointer
128 * or a black image. To make it useful would require a significant amount
129 * of rewriting of the drawRect method. Perhaps the next release of OSX
127 * or a black image. To make it useful would require a significant amount
128 * of rewriting of the drawRect method. Perhaps the next release of OSX
130129 * will include some more helpful ways of doing this.
131130 *
132131 * Results:
133 * Returns an NSBitmapRep representing the image of the given
134 * rectangle of the given drawable. This object is retained.
135 * The caller is responsible for releasing it.
136 *
137 * NOTE: The x,y coordinates should be relative to a coordinate system with
138 * origin at the top left, as used by XImage and CGImage, not bottom
132 * Returns an NSBitmapRep representing the image of the given rectangle of
133 * the given drawable. This object is retained. The caller is responsible
134 * for releasing it.
135 *
136 * NOTE: The x,y coordinates should be relative to a coordinate system
137 * with origin at the top left, as used by XImage and CGImage, not bottom
139138 * left as used by NSView.
140139 *
141140 * Side effects:
143142 *
144143 *----------------------------------------------------------------------
145144 */
146 NSBitmapImageRep*
145
146 NSBitmapImageRep *
147147 TkMacOSXBitmapRepFromDrawableRect(
148 Drawable drawable,
149 int x,
150 int y,
151 unsigned int width,
152 unsigned int height)
148 Drawable drawable,
149 int x,
150 int y,
151 unsigned int width,
152 unsigned int height)
153153 {
154154 MacDrawable *mac_drawable = (MacDrawable *) drawable;
155155 CGContextRef cg_context = NULL;
156 CGImageRef cg_image=NULL, sub_cg_image = NULL;
156 CGImageRef cg_image = NULL, sub_cg_image = NULL;
157157 NSBitmapImageRep *bitmap_rep = NULL;
158 NSView *view=NULL;
159 if ( mac_drawable->flags & TK_IS_PIXMAP ) {
160
158 NSView *view = NULL;
159 if (mac_drawable->flags & TK_IS_PIXMAP) {
161160 /*
162161 * This MacDrawable is a bitmap, so its view is NULL.
163162 */
164163
164 CGRect image_rect = CGRectMake(x, y, width, height);
165
165166 cg_context = TkMacOSXGetCGContextForDrawable(drawable);
166 CGRect image_rect = CGRectMake(x, y, width, height);
167 cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context);
167 cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context);
168168 sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
169 if ( sub_cg_image ) {
169 if (sub_cg_image) {
170170 bitmap_rep = [NSBitmapImageRep alloc];
171171 [bitmap_rep initWithCGImage:sub_cg_image];
172172 }
173 if ( cg_image ) {
173 if (cg_image) {
174174 CGImageRelease(cg_image);
175175 }
176 } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) {
177
176 } else if ((view = TkMacOSXDrawableView(mac_drawable)) != NULL) {
178177 /*
179178 * Convert Tk top-left to NSView bottom-left coordinates.
180179 */
181180
182181 int view_height = [view bounds].size.height;
183182 NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
184 view_height - height - y - mac_drawable->yOff,
185 width, height);
183 view_height - height - y - mac_drawable->yOff,
184 width, height);
186185
187186 /*
188187 * Attempt to copy from the view to a bitmapImageRep. If the view does
217216 * None.
218217 *
219218 * Side effects:
220 * Data is moved from a window or bitmap to a second window or
221 * bitmap.
222 *
223 *----------------------------------------------------------------------
224 */
225
226 void
219 * Data is moved from a window or bitmap to a second window or bitmap.
220 *
221 *----------------------------------------------------------------------
222 */
223
224 int
227225 XCopyArea(
228226 Display *display, /* Display. */
229227 Drawable src, /* Source drawable. */
230228 Drawable dst, /* Destination drawable. */
231 GC gc, /* GC to use. */
229 GC gc, /* GC to use. */
232230 int src_x, /* X & Y, width & height */
233231 int src_y, /* define the source rectangle */
234 unsigned int width, /* that will be copied. */
232 unsigned int width, /* that will be copied. */
235233 unsigned int height,
236234 int dest_x, /* Dest X & Y on dest rect. */
237235 int dest_y)
244242
245243 display->request++;
246244 if (!width || !height) {
247 return;
245 return BadDrawable;
248246 }
249247
250248 if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
251 return;
252249 TkMacOSXDbgMsg("Failed to setup drawing context.");
253 }
254
255 if ( dc.context ) {
256 if (srcDraw->flags & TK_IS_PIXMAP) {
257 img = TkMacOSXCreateCGImageWithDrawable(src);
258 }else if (TkMacOSXDrawableWindow(src)) {
259 bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src,
260 src_x, src_y, width, height);
261 if ( bitmap_rep ) {
262 img = [bitmap_rep CGImage];
263 }
264 } else {
265 TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
266 }
267
268 if (img) {
269 bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
270 srcRect = CGRectMake(src_x, src_y, width, height);
271 dstRect = CGRectMake(dest_x, dest_y, width, height);
272 TkMacOSXDrawCGImage(dst, gc, dc.context, img,
273 gc->foreground, gc->background, bounds, srcRect, dstRect);
274 CFRelease(img);
275 } else {
276 TkMacOSXDbgMsg("Failed to construct CGImage.");
277 }
278
250 return BadDrawable;
251 }
252
253 if (!dc.context) {
254 TkMacOSXDbgMsg("Invalid destination drawable - no context.");
255 return BadDrawable;
256 }
257
258 if (srcDraw->flags & TK_IS_PIXMAP) {
259 img = TkMacOSXCreateCGImageWithDrawable(src);
260 } else if (TkMacOSXDrawableWindow(src)) {
261 bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src,
262 src_x, src_y, width, height);
263 if (bitmap_rep) {
264 img = [bitmap_rep CGImage];
265 }
279266 } else {
280 TkMacOSXDbgMsg("Invalid destination drawable - no context.");
281 return;
267 TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
268 }
269
270 if (img) {
271 bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
272 srcRect = CGRectMake(src_x, src_y, width, height);
273 dstRect = CGRectMake(dest_x, dest_y, width, height);
274 TkMacOSXDrawCGImage(dst, gc, dc.context, img,
275 gc->foreground, gc->background, bounds, srcRect, dstRect);
276 CFRelease(img);
277 } else {
278 TkMacOSXDbgMsg("Failed to construct CGImage.");
282279 }
283280
284281 TkMacOSXRestoreDrawingContext(&dc);
282 return Success;
285283 }
286284
287285 /*
289287 *
290288 * XCopyPlane --
291289 *
292 * Copies a bitmap from a source drawable to a destination
293 * drawable. The plane argument specifies which bit plane of
294 * the source contains the bitmap. Note that this implementation
295 * ignores the gc->function.
290 * Copies a bitmap from a source drawable to a destination drawable. The
291 * plane argument specifies which bit plane of the source contains the
292 * bitmap. Note that this implementation ignores the gc->function.
296293 *
297294 * Results:
298295 * None.
303300 *----------------------------------------------------------------------
304301 */
305302
306 void
303 int
307304 XCopyPlane(
308305 Display *display, /* Display. */
309306 Drawable src, /* Source drawable. */
324321 display->request++;
325322 if (!width || !height) {
326323 /* TkMacOSXDbgMsg("Drawing of empty area requested"); */
327 return;
324 return BadDrawable;
328325 }
329326 if (plane != 1) {
330327 Tcl_Panic("Unexpected plane specified for XCopyPlane");
331328 }
332329 if (srcDraw->flags & TK_IS_PIXMAP) {
333330 if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
334 return;
335 }
331 return BadDrawable;
332 }
333
336334 CGContextRef context = dc.context;
335
337336 if (context) {
338337 CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
338
339339 if (img) {
340340 TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
341341 unsigned long imageBackground = gc->background;
342 if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){
342
343 if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) {
343344 srcRect = CGRectMake(src_x, src_y, width, height);
344 CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap);
345 CGImageRef submask = CGImageCreateWithImageInRect(img, srcRect);
345 CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(
346 clipPtr->value.pixmap);
347 CGImageRef submask = CGImageCreateWithImageInRect(
348 img, srcRect);
346349 CGRect rect = CGRectMake(dest_x, dest_y, width, height);
350
347351 rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
348352 CGContextSaveGState(context);
349 /* Move the origin of the destination to top left. */
350 CGContextTranslateCTM(context, 0, rect.origin.y + CGRectGetMaxY(rect));
353
354 /*
355 * Move the origin of the destination to top left.
356 */
357
358 CGContextTranslateCTM(context,
359 0, rect.origin.y + CGRectGetMaxY(rect));
351360 CGContextScaleCTM(context, 1, -1);
352 /* Fill with the background color, clipping to the mask. */
361
362 /*
363 * Fill with the background color, clipping to the mask.
364 */
365
353366 CGContextClipToMask(context, rect, submask);
354367 TkMacOSXSetColorInContext(gc, gc->background, dc.context);
355368 CGContextFillRect(context, rect);
356 /* Fill with the foreground color, clipping to the
357 intersection of img and mask. */
358 CGImageRef subimage = CGImageCreateWithImageInRect(img, srcRect);
369
370 /*
371 * Fill with the foreground color, clipping to the
372 * intersection of img and mask.
373 */
374
375 CGImageRef subimage = CGImageCreateWithImageInRect(
376 img, srcRect);
359377 CGContextClipToMask(context, rect, subimage);
360378 TkMacOSXSetColorInContext(gc, gc->foreground, context);
361379 CGContextFillRect(context, rect);
365383 CGImageRelease(submask);
366384 CGImageRelease(subimage);
367385 } else {
368 bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
386 bounds = CGRectMake(0, 0,
387 srcDraw->size.width, srcDraw->size.height);
369388 srcRect = CGRectMake(src_x, src_y, width, height);
370389 dstRect = CGRectMake(dest_x, dest_y, width, height);
371 TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground,
372 imageBackground, bounds, srcRect, dstRect);
390 TkMacOSXDrawCGImage(dst, gc, dc.context, img,
391 gc->foreground, imageBackground, bounds,
392 srcRect, dstRect);
373393 CGImageRelease(img);
374394 }
375 } else { /* no image */
395 } else {
396 /* no image */
376397 TkMacOSXDbgMsg("Invalid source drawable");
377398 }
378399 } else {
379 TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context.");
400 TkMacOSXDbgMsg("Invalid destination drawable - "
401 "could not get a bitmap context.");
380402 }
381403 TkMacOSXRestoreDrawingContext(&dc);
382 } else { /* source drawable is a window, not a Pixmap */
383 XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x, dest_y);
404 return Success;
405 } else {
406 /*
407 * Source drawable is a Window, not a Pixmap.
408 */
409
410 return XCopyArea(display, src, dst, gc, src_x, src_y, width, height,
411 dest_x, dest_y);
384412 }
385413 }
386414
429457 *----------------------------------------------------------------------
430458 */
431459
432 static NSImage*
460 static NSImage *
433461 CreateNSImageWithPixmap(
434462 Pixmap pixmap,
435463 int width,
465493 *----------------------------------------------------------------------
466494 */
467495
468 NSImage*
496 NSImage *
469497 TkMacOSXGetNSImageWithTkImage(
470498 Display *display,
471499 Tk_Image image,
472500 int width,
473501 int height)
474502 {
475 Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
503 Pixmap pixmap;
476504 NSImage *nsImage;
477
505 if (width == 0 || height == 0) {
506 return nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0,0)];
507 }
508 pixmap = Tk_GetPixmap(display, None, width, height, 0);
478509 Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
479510 nsImage = CreateNSImageWithPixmap(pixmap, width, height);
480511 Tk_FreePixmap(display, pixmap);
498529 *----------------------------------------------------------------------
499530 */
500531
501 NSImage*
532 NSImage *
502533 TkMacOSXGetNSImageWithBitmap(
503534 Display *display,
504535 Pixmap bitmap,
549580 CGColorSpaceRef colorspace = NULL;
550581 CGBitmapInfo bitmapInfo =
551582 #ifdef __LITTLE_ENDIAN__
552 kCGBitmapByteOrder32Host;
583 kCGBitmapByteOrder32Host;
553584 #else
554 kCGBitmapByteOrderDefault;
585 kCGBitmapByteOrderDefault;
555586 #endif
556587 char *data;
557 CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height);
588 CGRect bounds = CGRectMake(0, 0,
589 macDraw->size.width, macDraw->size.height);
558590
559591 if (macDraw->flags & TK_IS_BW_PIXMAP) {
560592 bitsPerPixel = 8;
561 bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;
593 bitmapInfo = (CGBitmapInfo) kCGImageAlphaOnly;
562594 } else {
563595 colorspace = CGColorSpaceCreateDeviceRGB();
564596 bitsPerPixel = 32;
565597 bitmapInfo |= kCGImageAlphaPremultipliedFirst;
566598 }
567 bytesPerRow = ((size_t) macDraw->size.width * bitsPerPixel + 127) >> 3
568 & ~15;
599 bytesPerRow = ((size_t)
600 macDraw->size.width * bitsPerPixel + 127) >> 3 & ~15;
569601 len = macDraw->size.height * bytesPerRow;
570602 data = ckalloc(len);
571603 bzero(data, len);
629661 dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);
630662 if (CGImageIsMask(image)) {
631663 if (macDraw->flags & TK_IS_BW_PIXMAP) {
632
633 /* Set fill color to black; background comes from the context,
664 /*
665 * Set fill color to black; background comes from the context,
634666 * or is transparent.
635667 */
636668
654686 CGContextSetRGBFillColor(context, 0, 1, 0, 0.1);
655687 CGContextFillRect(context, dstBounds);
656688 CGContextStrokeRect(context, dstBounds);
689
657690 CGPoint p[4] = {dstBounds.origin,
658691 CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMaxY(dstBounds)),
659692 CGPointMake(CGRectGetMinX(dstBounds), CGRectGetMaxY(dstBounds)),
660693 CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMinY(dstBounds))
661694 };
695
662696 CGContextStrokeLineSegments(context, p, 4);
663697 CGContextRestoreGState(context);
664698 TkMacOSXDbgMsg("Drawing CGImage at (x=%f, y=%f), (w=%f, h=%f)",
735769 CGContextAddLineToPoint(dc.context, prevx, prevy);
736770 }
737771 }
772
738773 /*
739 * In the case of closed polylines, the first and last points
740 * are the same. We want miter or bevel join be rendered also
741 * at this point, this needs telling CoreGraphics that the
742 * path is closed.
774 * In the case of closed polylines, the first and last points are the
775 * same. We want miter or bevel join be rendered also at this point,
776 * this needs telling CoreGraphics that the path is closed.
743777 */
778
744779 if ((points[0].x == points[npoints-1].x) &&
745780 (points[0].y == points[npoints-1].y)) {
746781 CGContextClosePath(dc.context);
817852 *----------------------------------------------------------------------
818853 */
819854
820 void
855 int
821856 XFillPolygon(
822 Display* display, /* Display. */
857 Display *display, /* Display. */
823858 Drawable d, /* Draw on this. */
824859 GC gc, /* Use this GC. */
825 XPoint* points, /* Array of points. */
860 XPoint *points, /* Array of points. */
826861 int npoints, /* Number of points. */
827862 int shape, /* Shape to draw. */
828863 int mode) /* Drawing mode. */
833868
834869 display->request++;
835870 if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
836 return;
871 return BadDrawable;
837872 }
838873 if (dc.context) {
839874 double prevx, prevy;
857892 CGContextEOFillPath(dc.context);
858893 }
859894 TkMacOSXRestoreDrawingContext(&dc);
895 return Success;
860896 }
861897
862898 /*
875911 *----------------------------------------------------------------------
876912 */
877913
878 void
914 int
879915 XDrawRectangle(
880916 Display *display, /* Display. */
881917 Drawable d, /* Draw on this. */
889925 int lw = gc->line_width;
890926
891927 if (width == 0 || height == 0) {
892 return;
928 return BadDrawable;
893929 }
894930
895931 display->request++;
896932 if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
897 return;
933 return BadDrawable;
898934 }
899935 if (dc.context) {
900936 CGRect rect;
901937 double o = (lw % 2) ? .5 : 0;
902938
903939 rect = CGRectMake(
904 macWin->xOff + x + o,
905 macWin->yOff + y + o,
940 macWin->xOff + x + o, macWin->yOff + y + o,
906941 width, height);
907942 CGContextStrokeRect(dc.context, rect);
908943 }
909944 TkMacOSXRestoreDrawingContext(&dc);
945 return Success;
910946 }
911947
912948 #ifdef TK_MACOSXDRAW_UNUSED
915951 *
916952 * XDrawRectangles --
917953 *
918 * Draws the outlines of the specified rectangles as if a
919 * five-point PolyLine protocol request were specified for each
920 * rectangle:
954 * Draws the outlines of the specified rectangles as if a five-point
955 * PolyLine protocol request were specified for each rectangle:
921956 *
922957 * [x,y] [x+width,y] [x+width,y+height] [x,y+height] [x,y]
923958 *
924 * For the specified rectangles, these functions do not draw a
925 * pixel more than once. XDrawRectangles draws the rectangles in
926 * the order listed in the array. If rectangles intersect, the
927 * intersecting pixels are drawn multiple times. Draws a
928 * rectangle.
959 * For the specified rectangles, these functions do not draw a pixel more
960 * than once. XDrawRectangles draws the rectangles in the order listed in
961 * the array. If rectangles intersect, the intersecting pixels are drawn
962 * multiple times. Draws a rectangle.
929963 *
930964 * Results:
931965 * None.
9901024
9911025 int
9921026 XFillRectangles(
993 Display* display, /* Display. */
1027 Display *display, /* Display. */
9941028 Drawable d, /* Draw on this. */
9951029 GC gc, /* Use this GC. */
9961030 XRectangle *rectangles, /* Rectangle array. */
10261060 /*
10271061 *----------------------------------------------------------------------
10281062 *
1063 * TkMacOSXDrawSolidBorder --
1064 *
1065 * Draws a border rectangle of specified thickness inside the bounding
1066 * rectangle of a Tk Window. The border rectangle can be inset within the
1067 * bounding rectangle. For a highlight border the inset should be 0, but
1068 * for a solid border around the actual window the inset should equal the
1069 * thickness of the highlight border. The color of the border rectangle
1070 * is the foreground color of the graphics context passed to the function.
1071 *
1072 * Results:
1073 * None.
1074 *
1075 * Side effects:
1076 * Draws a rectangular border inside the bounding rectangle of a window.
1077 *
1078 *----------------------------------------------------------------------
1079 */
1080
1081 MODULE_SCOPE void
1082 TkMacOSXDrawSolidBorder(
1083 Tk_Window tkwin,
1084 GC gc,
1085 int inset,
1086 int thickness)
1087 {
1088 Drawable d = Tk_WindowId(tkwin);
1089 TkMacOSXDrawingContext dc;
1090 CGRect outerRect, innerRect;
1091
1092 if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
1093 return;
1094 }
1095 if (dc.context) {
1096 outerRect = CGRectMake(Tk_X(tkwin), Tk_Y(tkwin),
1097 Tk_Width(tkwin), Tk_Height(tkwin));
1098 outerRect = CGRectInset(outerRect, inset, inset);
1099 innerRect = CGRectInset(outerRect, thickness, thickness);
1100 CGContextBeginPath(dc.context);
1101 CGContextAddRect(dc.context, outerRect);
1102 CGContextAddRect(dc.context, innerRect);
1103 CGContextEOFillPath(dc.context);
1104 }
1105 TkMacOSXRestoreDrawingContext(&dc);
1106 }
1107
1108 /*
1109 *----------------------------------------------------------------------
1110 *
10291111 * XDrawArc --
10301112 *
10311113 * Draw an arc.
10391121 *----------------------------------------------------------------------
10401122 */
10411123
1042 void
1124 int
10431125 XDrawArc(
1044 Display* display, /* Display. */
1126 Display *display, /* Display. */
10451127 Drawable d, /* Draw on this. */
10461128 GC gc, /* Use this GC. */
10471129 int x, int y, /* Upper left of bounding rect. */
10551137 int lw = gc->line_width;
10561138
10571139 if (width == 0 || height == 0 || angle2 == 0) {
1058 return;
1140 return BadDrawable;
10591141 }
10601142
10611143 display->request++;
10621144 if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
1063 return;
1145 return BadDrawable;
10641146 }
10651147 if (dc.context) {
10661148 CGRect rect;
10901172 }
10911173 }
10921174 TkMacOSXRestoreDrawingContext(&dc);
1175 return Success;
10931176 }
10941177
10951178 #ifdef TK_MACOSXDRAW_UNUSED
10981181 *
10991182 * XDrawArcs --
11001183 *
1101 * Draws multiple circular or elliptical arcs. Each arc is
1102 * specified by a rectangle and two angles. The center of the
1103 * circle or ellipse is the center of the rect- angle, and the
1104 * major and minor axes are specified by the width and height.
1105 * Positive angles indicate counterclock- wise motion, and
1106 * negative angles indicate clockwise motion. If the magnitude
1107 * of angle2 is greater than 360 degrees, XDrawArcs truncates it
1108 * to 360 degrees.
1184 * Draws multiple circular or elliptical arcs. Each arc is specified by a
1185 * rectangle and two angles. The center of the circle or ellipse is the
1186 * center of the rect- angle, and the major and minor axes are specified
1187 * by the width and height. Positive angles indicate counterclock- wise
1188 * motion, and negative angles indicate clockwise motion. If the magnitude
1189 * of angle2 is greater than 360 degrees, XDrawArcs truncates it to 360
1190 * degrees.
11091191 *
11101192 * Results:
11111193 * None.
11161198 *----------------------------------------------------------------------
11171199 */
11181200
1119 void
1201 int
11201202 XDrawArcs(
11211203 Display *display,
11221204 Drawable d,
11241206 XArc *arcArr,
11251207 int nArcs)
11261208 {
1127
11281209 MacDrawable *macWin = (MacDrawable *) d;
11291210 TkMacOSXDrawingContext dc;
11301211 XArc *arcPtr;
11321213
11331214 display->request++;
11341215 if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
1135 return;
1216 return BadDrawable;
11361217 }
11371218 if (dc.context) {
11381219 CGRect rect;
11731254 }
11741255 }
11751256 TkMacOSXRestoreDrawingContext(&dc);
1257 return Success;
11761258 }
11771259 #endif
11781260
11921274 *----------------------------------------------------------------------
11931275 */
11941276
1195 void
1277 int
11961278 XFillArc(
1197 Display* display, /* Display. */
1279 Display *display, /* Display. */
11981280 Drawable d, /* Draw on this. */
11991281 GC gc, /* Use this GC. */
12001282 int x, int y, /* Upper left of bounding rect. */
12081290 int lw = gc->line_width;
12091291
12101292 if (width == 0 || height == 0 || angle2 == 0) {
1211 return;
1293 return BadDrawable;
12121294 }
12131295
12141296 display->request++;
12151297 if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
1216 return;
1298 return BadDrawable;
12171299 }
12181300 if (dc.context) {
12191301 CGRect rect;
12521334 }
12531335 }
12541336 TkMacOSXRestoreDrawingContext(&dc);
1337 return Success;
12551338 }
12561339
12571340 #ifdef TK_MACOSXDRAW_UNUSED
13591442 *
13601443 * TkScrollWindow --
13611444 *
1362 * Scroll a rectangle of the specified window and accumulate
1363 * a damage region.
1364 *
1365 * Results:
1366 * Returns 0 if the scroll generated no additional damage.
1367 * Otherwise, sets the region that needs to be repainted after
1368 * scrolling and returns 1.
1445 * Scroll a rectangle of the specified window and accumulate a damage
1446 * region.
1447 *
1448 * Results:
1449 * Returns 0 if the scroll generated no additional damage. Otherwise, sets
1450 * the region that needs to be repainted after scrolling and returns 1.
13691451 *
13701452 * Side effects:
13711453 * Scrolls the bits in the window.
13841466 {
13851467 Drawable drawable = Tk_WindowId(tkwin);
13861468 MacDrawable *macDraw = (MacDrawable *) drawable;
1387 TKContentView *view = (TKContentView *)TkMacOSXDrawableView(macDraw);
1469 TKContentView *view = (TKContentView *) TkMacOSXDrawableView(macDraw);
13881470 CGRect srcRect, dstRect;
13891471 HIShapeRef dmgRgn = NULL, extraRgn = NULL;
13901472 NSRect bounds, visRect, scrollSrc, scrollDst;
13911473 int result = 0;
13921474
1393 if ( view ) {
1394 /* Get the scroll area in NSView coordinates (origin at bottom left). */
1475 if (view) {
1476 /*
1477 * Get the scroll area in NSView coordinates (origin at bottom left).
1478 */
1479
13951480 bounds = [view bounds];
13961481 scrollSrc = NSMakeRect(macDraw->xOff + x,
1397 bounds.size.height - height - (macDraw->yOff + y),
1398 width, height);
1482 bounds.size.height - height - (macDraw->yOff + y),
1483 width, height);
13991484 scrollDst = NSOffsetRect(scrollSrc, dx, -dy);
14001485
1401 /* Limit scrolling to the window content area. */
1486 /*
1487 * Limit scrolling to the window content area.
1488 */
1489
14021490 visRect = [view visibleRect];
14031491 scrollSrc = NSIntersectionRect(scrollSrc, visRect);
14041492 scrollDst = NSIntersectionRect(scrollDst, visRect);
1405 if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) {
1493 if (!NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst)) {
14061494 /*
14071495 * Mark the difference between source and destination as damaged.
1408 * This region is described in NSView coordinates (y=0 at the bottom)
1409 * and converted to Tk coordinates later.
1496 * This region is described in NSView coordinates (y=0 at the
1497 * bottom) and converted to Tk coordinates later.
14101498 */
14111499
14121500 srcRect = CGRectMake(x, y, width, height);
14131501 dstRect = CGRectOffset(srcRect, dx, dy);
14141502
1415 /* Compute the damage. */
1503 /*
1504 * Compute the damage.
1505 */
1506
14161507 dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
14171508 extraRgn = HIShapeCreateWithRect(&dstRect);
1418 ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn);
1509 ChkErr(HIShapeDifference, dmgRgn, extraRgn,
1510 (HIMutableShapeRef) dmgRgn);
14191511 result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
14201512
1421 /* Convert to Tk coordinates, offset by the window origin. */
1513 /*
1514 * Convert to Tk coordinates, offset by the window origin.
1515 */
1516
14221517 TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
14231518 if (extraRgn) {
14241519 CFRelease(extraRgn);
14251520 }
14261521
1427 /* Scroll the rectangle. */
1522 /*
1523 * Scroll the rectangle.
1524 */
1525
14281526 [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];
14291527 }
14301528 } else {
14711569 * Set up a drawing context for the given drawable and GC.
14721570 *
14731571 * Results:
1474 * Boolean indicating whether it is ok to draw; if false, drawing
1475 * context was not setup, so do not attempt to draw and do not call
1572 * Boolean indicating whether it is ok to draw; if false, drawing context
1573 * was not setup, so do not attempt to draw and do not call
14761574 * TkMacOSXRestoreDrawingContext().
14771575 *
14781576 * Side effects:
14851583 TkMacOSXSetupDrawingContext(
14861584 Drawable d,
14871585 GC gc,
1488 int useCG, /* advisory only ! */
1586 int useCG, /* advisory only ! */
14891587 TkMacOSXDrawingContext *dcPtr)
14901588 {
1491 MacDrawable *macDraw = ((MacDrawable*)d);
1589 MacDrawable *macDraw = (MacDrawable *) d;
14921590 Bool canDraw = true;
14931591 NSWindow *win = NULL;
14941592 TkMacOSXDrawingContext dc = {};
14951593 CGRect clipBounds;
14961594
14971595 /*
1498 * If we are simulating drawing for tests, just return false.
1499 */
1500
1501 if ([NSApp simulateDrawing]) {
1502 return false;
1503 }
1504
1505 /*
1506 * If the drawable is not a pixmap and it has an associated
1507 * NSWindow then we know we are drawing to a window.
1596 * If the drawable is not a pixmap and it has an associated NSWindow then
1597 * we know we are drawing to a window.
15081598 */
15091599
15101600 if (!(macDraw->flags & TK_IS_PIXMAP)) {
15231613 }
15241614
15251615 /*
1526 * If we already have a CGContext, use it. Otherwise, if we
1527 * are drawing to a window then we can get one from the
1528 * window.
1616 * If we already have a CGContext, use it. Otherwise, if we are drawing to
1617 * a window then we can get one from the window.
15291618 */
15301619
15311620 dc.context = TkMacOSXGetCGContextForDrawable(d);
15331622 dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
15341623 } else if (win) {
15351624 NSView *view = TkMacOSXDrawableView(macDraw);
1536 if (view) {
1537
1538 /*
1539 * We can only draw into the view when the current CGContext is
1540 * valid and belongs to the view. Validity can only be guaranteed
1541 * inside of a view's drawRect or setFrame methods. The isDrawing
1542 * attribute tells us whether we are being called from one of those
1543 * methods.
1544 *
1545 * If the CGContext is not valid, or belongs to a different View,
1546 * then we mark our view as needing display and return failure.
1547 * It should get drawn in a later call to drawRect.
1548 */
1549
1550 if (view != [NSView focusView]) {
1551 [view setNeedsDisplay:YES];
1552 canDraw = false;
1553 goto end;
1554 }
1555 dc.view = view;
1556 dc.context = GET_CGCONTEXT;
1557 dc.portBounds = NSRectToCGRect([view bounds]);
1558 if (dc.clipRgn) {
1559 clipBounds = CGContextGetClipBoundingBox(dc.context);
1560 }
1561 } else {
1625
1626 if (!view) {
15621627 Tcl_Panic("TkMacOSXSetupDrawingContext(): "
15631628 "no NSView to draw into !");
1629 }
1630
1631 /*
1632 * We can only draw into the view when the current CGContext is valid
1633 * and belongs to the view. Validity can only be guaranteed inside of
1634 * a view's drawRect or setFrame methods. The isDrawing attribute
1635 * tells us whether we are being called from one of those methods.
1636 *
1637 * If the CGContext is not valid then we mark our view as needing
1638 * display in the bounding rectangle of the clipping region and
1639 * return failure. That rectangle should get drawn in a later call
1640 * to drawRect.
1641 *
1642 * As an exception to the above, if mouse buttons are pressed at the
1643 * moment when we fail to obtain a valid context we schedule the entire
1644 * view for a redraw rather than just the clipping region. The purpose
1645 * of this is to make sure that scrollbars get updated correctly.
1646 */
1647
1648 if (![NSApp isDrawing] || view != [NSView focusView]) {
1649 NSRect bounds = [view bounds];
1650 NSRect dirtyNS = bounds;
1651 if ([NSEvent pressedMouseButtons]) {
1652 [view setNeedsDisplay:YES];
1653 } else {
1654 CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
1655 .ty = dirtyNS.size.height};
1656 if (dc.clipRgn) {
1657 CGRect dirtyCG = NSRectToCGRect(dirtyNS);
1658 HIShapeGetBounds(dc.clipRgn, &dirtyCG);
1659 dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
1660 }
1661 [view setNeedsDisplayInRect:dirtyNS];
1662 }
1663 canDraw = false;
1664 goto end;
1665 }
1666
1667 dc.view = view;
1668 dc.context = GET_CGCONTEXT;
1669 dc.portBounds = NSRectToCGRect([view bounds]);
1670 if (dc.clipRgn) {
1671 clipBounds = CGContextGetClipBoundingBox(dc.context);
15641672 }
15651673 } else {
15661674 Tcl_Panic("TkMacOSXSetupDrawingContext(): "
15721680 */
15731681
15741682 if (dc.context) {
1575 CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
1576 .ty = dc.portBounds.size.height};
1683 CGAffineTransform t = {
1684 .a = 1, .b = 0,
1685 .c = 0, .d = -1,
1686 .tx = 0,
1687 .ty = dc.portBounds.size.height
1688 };
1689
15771690 dc.portBounds.origin.x += macDraw->xOff;
15781691 dc.portBounds.origin.y += macDraw->yOff;
15791692 CGContextSaveGState(dc.context);
15881701 CGContextRestoreGState(dc.context);
15891702 #endif /* TK_MAC_DEBUG_DRAWING */
15901703 CGRect r;
1704
15911705 if (!HIShapeIsRectangular(dc.clipRgn) || !CGRectContainsRect(
15921706 *HIShapeGetBounds(dc.clipRgn, &r),
15931707 CGRectApplyAffineTransform(clipBounds, t))) {
16151729 CGContextSetPatternPhase(dc.context, CGSizeMake(
16161730 dc.portBounds.size.width, dc.portBounds.size.height));
16171731 }
1618 if(gc->function != GXcopy) {
1732 if (gc->function != GXcopy) {
16191733 TkMacOSXDbgMsg("Logical functions other than GXcopy are "
16201734 "not supported for CG drawing!");
16211735 }
1622 /* When should we antialias? */
1736
1737 /*
1738 * When should we antialias?
1739 */
1740
16231741 shouldAntialias = !notAA(gc->line_width);
16241742 if (!shouldAntialias) {
1625 /* Make non-antialiased CG drawing look more like X11 */
1743 /*
1744 * Make non-antialiased CG drawing look more like X11.
1745 */
1746
16261747 w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);
16271748 }
16281749 CGContextSetShouldAntialias(dc.context, shouldAntialias);
16291750 CGContextSetLineWidth(dc.context, w);
16301751 if (gc->line_style != LineSolid) {
16311752 int num = 0;
1632 char *p = &(gc->dashes);
1753 char *p = &gc->dashes;
16331754 CGFloat dashOffset = gc->dash_offset;
16341755 CGFloat lengths[10];
16351756
16391760 }
16401761 CGContextSetLineDash(dc.context, dashOffset, lengths, num);
16411762 }
1642 if ((unsigned)gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
1763 if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
16431764 CGContextSetLineCap(dc.context,
1644 cgCap[(unsigned)gc->cap_style]);
1765 cgCap[(unsigned) gc->cap_style]);
16451766 }
16461767 if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {
16471768 CGContextSetLineJoin(dc.context,
1648 cgJoin[(unsigned)gc->join_style]);
1769 cgJoin[(unsigned) gc->join_style]);
16491770 }
16501771 }
16511772 }
16541775 #ifdef TK_MAC_DEBUG_DRAWING
16551776 if (!canDraw && win != NULL) {
16561777 TkWindow *winPtr = TkMacOSXGetTkWindow(win);
1657 if (winPtr) fprintf(stderr, "Cannot draw in %s - postponing.\n",
1658 Tk_PathName(winPtr));
1778
1779 if (winPtr) {
1780 fprintf(stderr, "Cannot draw in %s - postponing.\n",
1781 Tk_PathName(winPtr));
1782 }
16591783 }
16601784 #endif
16611785 if (!canDraw && dc.clipRgn) {
17261850 TkMacOSXUpdateClipRgn(macDraw->winPtr);
17271851 #ifdef TK_MAC_DEBUG_DRAWING
17281852 TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName);
1853
17291854 NSView *view = TkMacOSXDrawableView(macDraw);
1855
17301856 CGContextSaveGState(context);
17311857 CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,
17321858 -1.0, 0.0, [view bounds].size.height));
17501876 *
17511877 * TkMacOSXSetUpClippingRgn --
17521878 *
1753 * Set up the clipping region so that drawing only occurs on the
1754 * specified X subwindow.
1879 * Set up the clipping region so that drawing only occurs on the specified
1880 * X subwindow.
17551881 *
17561882 * Results:
17571883 * None.
17731899 *
17741900 * TkpClipDrawableToRect --
17751901 *
1776 * Clip all drawing into the drawable d to the given rectangle.
1777 * If width or height are negative, reset to no clipping.
1902 * Clip all drawing into the drawable d to the given rectangle. If width
1903 * or height are negative, reset to no clipping.
17781904 *
17791905 * Results:
17801906 * None.
18391965 HIShapeRef *clipRgnPtr) /* must point to initialized variable */
18401966 {
18411967 if (gc && gc->clip_mask &&
1842 ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) {
1843 TkRegion gcClip = ((TkpClipMask*)gc->clip_mask)->value.region;
1968 ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {
1969 TkRegion gcClip = ((TkpClipMask *) gc->clip_mask)->value.region;
18441970 int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin;
18451971 int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin;
18461972 HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn;
18631989 *
18641990 * TkMacOSXMakeStippleMap --
18651991 *
1866 * Given a drawable and a stipple pattern this function draws the
1867 * pattern repeatedly over the drawable. The drawable can then
1868 * be used as a mask for bit-bliting a stipple pattern over an
1869 * object.
1992 * Given a drawable and a stipple pattern this function draws the pattern
1993 * repeatedly over the drawable. The drawable can then be used as a mask
1994 * for bit-bliting a stipple pattern over an object.
18701995 *
18711996 * Results:
18721997 * A BitMap data structure.
18902015 *
18912016 * TkpDrawHighlightBorder --
18922017 *
1893 * This procedure draws a rectangular ring around the outside of
1894 * a widget to indicate that it has received the input focus.
1895 *
1896 * On the Macintosh, this puts a 1 pixel border in the bgGC color
1897 * between the widget and the focus ring, except in the case where
1898 * highlightWidth is 1, in which case the border is left out.
2018 * This procedure draws a rectangular ring around the outside of a widget
2019 * to indicate that it has received the input focus.
2020 *
2021 * On the Macintosh, this puts a 1 pixel border in the bgGC color between
2022 * the widget and the focus ring, except in the case where highlightWidth
2023 * is 1, in which case the border is left out.
18992024 *
19002025 * For proper Mac L&F, use highlightWidth of 3.
19012026 *
19032028 * None.
19042029 *
19052030 * Side effects:
1906 * A rectangle "width" pixels wide is drawn in "drawable",
1907 * corresponding to the outer area of "tkwin".
2031 * A rectangle "width" pixels wide is drawn in "drawable", corresponding
2032 * to the outer area of "tkwin".
19082033 *
19092034 *----------------------------------------------------------------------
19102035 */
19332058 *
19342059 * TkpDrawFrame --
19352060 *
1936 * This procedure draws the rectangular frame area. If the user
1937 * has requested themeing, it draws with the background theme.
2061 * This procedure draws the rectangular frame area. If the user has
2062 * requested themeing, it draws with the background theme.
19382063 *
19392064 * Results:
19402065 * None.
271271 }
272272
273273 usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent);
274 if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) {
274 if (usePtr == NULL) {
275 if (interp != NULL) {
276 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
277 "couldn't create child of window \"%s\"", string));
278 Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL);
279 }
280 return TCL_ERROR;
281 } else if (!(usePtr->flags & TK_CONTAINER)) {
275282 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
276283 "window \"%s\" doesn't have -container option set",
277284 usePtr->pathName));
280287 }
281288
282289 /*
283 * The code below can probably be simplified given we have already
284 * discovered 'usePtr' above.
285 */
286
287 /*
288 * Save information about the container and the embedded window in a
289 * Container structure. Currently, there must already be an existing
290 * Container structure, since we only allow the case where both container
291 * and embedded app. are in the same process.
290 * Since we do not allow embedding into windows belonging to a different
291 * process, we know that a container will exist showing the parent window
292 * as the parent. This loop finds that container.
292293 */
293294
294295 for (containerPtr = firstContainerPtr; containerPtr != NULL;
311312 }
312313
313314 macWin->winPtr = winPtr;
314 winPtr->privatePtr = macWin;
315
316 /*
317 * The grafPtr will be NULL for a Tk in Tk embedded window. It is none of
318 * our business what it is for a Tk not in Tk embedded window, but we will
319 * initialize it to NULL, and let the registerWinProc set it. In any case,
320 * you must always use TkMacOSXGetDrawablePort to get the portPtr. It will
321 * correctly find the container's port.
322 */
323
324315 macWin->view = nil;
325316 macWin->context = NULL;
326317 macWin->size = CGSizeZero;
332323 macWin->toplevel = macWin;
333324 macWin->toplevel->referenceCount++;
334325
326 winPtr->privatePtr = macWin;
335327 winPtr->flags |= TK_EMBEDDED;
336328
337329 /*
340332 */
341333
342334 macWin->flags |= TK_EMBEDDED;
343
344 /*
345 * Now check whether it is embedded in another Tk widget. If not (the
346 * first case below) we see if there is an in-process embedding handler
347 * registered, and if so, let that fill in the rest of the macWin.
348 */
349
350 if (containerPtr == NULL) {
351 /*
352 * If someone has registered an in-process embedding handler, then
353 * see if it can handle this window...
354 */
355
356 if (tkMacOSXEmbedHandler == NULL ||
357 tkMacOSXEmbedHandler->registerWinProc((long) parent,
358 (Tk_Window) winPtr) != TCL_OK) {
359 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
360 "The window ID %s does not correspond to a valid Tk Window",
361 string));
362 Tcl_SetErrorCode(interp, "TK", "EMBED", "HANDLE", NULL);
363 return TCL_ERROR;
364 }
365
366 containerPtr = ckalloc(sizeof(Container));
367
368 containerPtr->parentPtr = NULL;
369 containerPtr->embedded = (Window) macWin;
370 containerPtr->embeddedPtr = macWin->winPtr;
371 containerPtr->nextPtr = firstContainerPtr;
372 firstContainerPtr = containerPtr;
373 } else {
374 /*
375 * The window is embedded in another Tk window.
376 */
377
378 macWin->xOff = parent->winPtr->privatePtr->xOff +
379 parent->winPtr->changes.border_width +
380 winPtr->changes.x;
381 macWin->yOff = parent->winPtr->privatePtr->yOff +
382 parent->winPtr->changes.border_width +
383 winPtr->changes.y;
384
385 /*
386 * Finish filling up the container structure with the embedded
387 * window's information.
388 */
389
390 containerPtr->embedded = (Window) macWin;
391 containerPtr->embeddedPtr = macWin->winPtr;
392
393 /*
394 * Create an event handler to clean up the Container structure when
395 * tkwin is eventually deleted.
396 */
397
398 Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
399 winPtr);
400 }
335 macWin->xOff = parent->winPtr->privatePtr->xOff +
336 parent->winPtr->changes.border_width +
337 winPtr->changes.x;
338 macWin->yOff = parent->winPtr->privatePtr->yOff +
339 parent->winPtr->changes.border_width +
340 winPtr->changes.y;
341
342 /*
343 * Finish filling up the container structure with the embedded window's
344 * information.
345 */
346
347 containerPtr->embedded = (Window) macWin;
348 containerPtr->embeddedPtr = macWin->winPtr;
349
350 /*
351 * Create an event handler to clean up the Container structure when
352 * tkwin is eventually deleted.
353 */
354
355 Tk_CreateEventHandler(tkwin, StructureNotifyMask,
356 EmbeddedEventProc, winPtr);
401357
402358 return TCL_OK;
403359 }
493449 }
494450 }
495451 Tcl_Panic("TkMacOSXContainerId couldn't find window");
496 return None;
452 return NULL;
497453 }
498454
499455 /*
529485 * TODO: Here we should handle out of process embedding.
530486 */
531487
532 if (contWinPtr == NULL) {
533 return None;
488 if (!contWinPtr) {
489 return NULL;
534490 }
535491 return TkMacOSXGetHostToplevel(contWinPtr);
536492 }
541497 * TkpClaimFocus --
542498 *
543499 * This procedure is invoked when someone asks for the input focus to be
544 * put on a window in an embedded application, but the application
545 * doesn't currently have the focus. It requests the input focus from the
546 * container application.
500 * put on a window in an embedded application.
547501 *
548502 * Results:
549503 * None.
582536 event.xfocus.window = containerPtr->parent;
583537 event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
584538 event.xfocus.detail = force;
585 Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL);
539 Tk_HandleEvent(&event);
586540 }
587541
588542 /*
613567 Container *containerPtr;
614568 Tcl_DString dString;
615569 char buffer[50];
570 Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
616571
617572 if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
618573 all = 1;
622577 Tcl_DStringInit(&dString);
623578 for (containerPtr = firstContainerPtr; containerPtr != NULL;
624579 containerPtr = containerPtr->nextPtr) {
580 if (containerPtr->embeddedPtr != NULL) {
581 embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;
582 }
583 if (containerPtr->parentPtr != NULL) {
584 parentInterp = containerPtr->parentPtr->mainPtr->interp;
585 }
586 if (embeddedInterp != interp && parentInterp != interp) {
587 continue;
588 }
625589 Tcl_DStringStartSublist(&dString);
590
591 /*
592 * Parent id
593 */
594
626595 if (containerPtr->parent == None) {
627596 Tcl_DStringAppendElement(&dString, "");
628597 } else if (all) {
629 sprintf(buffer, "0x%x", (int) containerPtr->parent);
598 sprintf(buffer, "0x%lx", containerPtr->parent);
630599 Tcl_DStringAppendElement(&dString, buffer);
631600 } else {
632601 Tcl_DStringAppendElement(&dString, "XXX");
633602 }
634 if (containerPtr->parentPtr == NULL) {
603
604 /*
605 * Parent pathName
606 */
607
608 if (containerPtr->parentPtr == NULL ||
609 parentInterp != interp) {
635610 Tcl_DStringAppendElement(&dString, "");
636611 } else {
637612 Tcl_DStringAppendElement(&dString,
638613 containerPtr->parentPtr->pathName);
639614 }
640 if (containerPtr->embedded == None) {
641 Tcl_DStringAppendElement(&dString, "");
642 } else if (all) {
643 sprintf(buffer, "0x%x", (int) containerPtr->embedded);
644 Tcl_DStringAppendElement(&dString, buffer);
645 } else {
646 Tcl_DStringAppendElement(&dString, "XXX");
647 }
648 if (containerPtr->embeddedPtr == NULL) {
615
616 /*
617 * On X11 embedded is a wrapper, which does not exist on macOS.
618 */
619
620 Tcl_DStringAppendElement(&dString, "");
621
622 /*
623 * Embedded window pathName
624 */
625
626 if (containerPtr->embeddedPtr == NULL ||
627 embeddedInterp != interp) {
649628 Tcl_DStringAppendElement(&dString, "");
650629 } else {
651630 Tcl_DStringAppendElement(&dString,
802781 /*
803782 * When the interpreter is being dismantled this can be nil.
804783 */
784
805785 return;
806786 }
807787
867847 eventPtr->xmaprequest.window);
868848 } else if (eventPtr->type == DestroyNotify) {
869849 /*
870 * The embedded application is gone. Destroy the container window.
850 * It is not clear whether the container should be destroyed
851 * when an embedded window is destroyed. See ticket [67384bce7d].
852 * Here we are following unix, by destroying the container.
871853 */
872854
873855 Tk_DestroyWindow((Tk_Window) winPtr);
903885 Tk_ErrorHandler errHandler;
904886
905887 if (eventPtr->type == ConfigureNotify) {
888
889 /*
890 * Send a ConfigureNotify to the embedded application.
891 */
892
893 if (containerPtr->embeddedPtr != None) {
894 TkDoConfigureNotify(containerPtr->embeddedPtr);
895 }
906896 if (containerPtr->embedded != None) {
907897 /*
908898 * Ignore errors, since the embedded application could have
10511041 /*
10521042 * Forward the requested size into our geometry management hierarchy via
10531043 * the container window. We need to send a Configure event back to the
1054 * embedded application if we decide not to honor its request; to make
1055 * this happen, process all idle event handlers synchronously here (so
1056 * that the geometry managers have had a chance to do whatever they want
1057 * to do), and if the window's size didn't change then generate a
1058 * configure event.
1044 * embedded application if we decide not to honor its request; to make this
1045 * happen, process all idle event handlers synchronously here (so that the
1046 * geometry managers have had a chance to do whatever they want to do), and
1047 * if the window's size didn't change then generate a configure event.
10591048 */
10601049
10611050 Tk_GeometryRequest((Tk_Window) winPtr, width, height);
10771066 * application of its current size and location. This procedure is called
10781067 * when the embedded application made a geometry request that we did not
10791068 * grant, so that the embedded application knows that its geometry didn't
1080 * change after all. It is a response to ConfigureRequest events, which
1081 * we do not currently synthesize on the Mac
1069 * change after all. It is a response to ConfigureRequest events, which we
1070 * do not currently synthesize on the Mac
10821071 *
10831072 * Results:
10841073 * None.
11381127 containerPtr->parentPtr->flags & TK_BOTH_HALVES) {
11391128 XEvent event;
11401129
1141 event.xany.serial =
1142 LastKnownRequestProcessed(Tk_Display(containerPtr->parentPtr));
1130 event.xany.serial = LastKnownRequestProcessed(
1131 Tk_Display(containerPtr->parentPtr));
11431132 event.xany.send_event = False;
11441133 event.xany.display = Tk_Display(containerPtr->parentPtr);
11451134
122122 if (isSpinbox) {
123123 int incDecWidth;
124124
125 /*
126 * If native spinbox buttons are going to be drawn, then temporarily
127 * change the width of the widget so that the same code can be used
128 * for drawing the Entry portion of the Spinbox as is used to draw
129 * an ordinary Entry. The width must be restored before returning.
130 */
131
125132 oldWidth = Tk_Width(tkwin);
126
127 ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH,
128 &incDecWidth);
129 Tk_Width(tkwin) -= incDecWidth + 1;
133 if (ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH,
134 &incDecWidth) != 0) {
135 Tk_Width(tkwin) -= incDecWidth + 1;
136 }
130137 }
131138
132139 /*
148155 bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
149156 bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
150157 if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
158
159 /*
160 * No graphics context is available. If the widget is a Spinbox, we
161 * must restore its width before returning 0. (Ticket [273b6a4996].)
162 */
163
164 if (isSpinbox) {
165 Tk_Width(tkwin) = oldWidth;
166 }
151167 return 0;
152168 }
153169 ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);
170186 * have to implement it.
171187 *
172188 * Results:
173 * 1 if it has drawn the border, 0 if not.
189 * 1 if it has drawn the buttons, 0 if not.
174190 *
175191 * Side effects:
176 * May draw the entry border into pixmap.
192 * May draw the buttons into pixmap.
177193 *
178194 *--------------------------------------------------------------
179195 */
242258 */
243259
244260 bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d);
245 rects[0].x = bounds.origin.x;
261 rects[0].x = Tk_Width(tkwin) - incDecWidth - 1;
246262 rects[0].y = 0;
247 rects[0].width = Tk_Width(tkwin);
263 rects[0].width = incDecWidth + 1;
248264 rects[0].height = Tk_Height(tkwin);
249265 XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1);
250266
113113 *
114114 * This routine is a stub called by XSync, which is called during the Tk
115115 * update command. The language specification does not require that the
116 * update command be synchronous but many of the tests assume that is the
117 * case. It is not naturally the case on macOS since many idle tasks are
118 * run inside of the drawRect method of a window's contentView, and that
119 * method will not be called until after this function returns. To make
120 * the tests work, we attempt to force this to be synchronous by waiting
121 * until drawRect has been called for each window. The mechanism we use
122 * for this is to have drawRect post an ApplicationDefined NSEvent on the
123 * AppKit event queue when it finishes drawing, and wait for it here.
116 * update command be synchronous but many of the tests implicitly assume
117 * that it is. It is definitely asynchronous on macOS since many idle
118 * tasks are run inside of the drawRect method of a window's contentView,
119 * which will not be called until after this function returns.
124120 *
125121 * Results:
126122 * None.
127123 *
128 * Side effects:
129 * Calls the drawRect method of the contentView of each visible
130 * window.
124 * Side effects: Processes all pending idle events then calls the display
125 * method of each visible window.
131126 *
132127 *----------------------------------------------------------------------
133128 */
135130 MODULE_SCOPE void
136131 TkMacOSXFlushWindows(void)
137132 {
138 NSArray *macWindows = [NSApp orderedWindows];
139 if ([NSApp simulateDrawing]) {
140 [NSApp setSimulateDrawing:NO];
133 if (Tk_GetNumMainWindows() == 0) {
141134 return;
142135 }
143 for (NSWindow *w in macWindows) {
144 if (TkMacOSXGetXWindow(w)) {
145 [w displayIfNeeded];
146 }
136 while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
137 for (NSWindow *w in [NSApp orderedWindows]) {
138 [w display];
147139 }
148140 }
149141
00 /*
11 * tkMacOSXFont.c --
22 *
3 * Contains the Macintosh implementation of the platform-independant
4 * font package interface.
3 * Contains the Macintosh implementation of the platform-independent font
4 * package interface.
55 *
66 * Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de
77 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
3131 */
3232
3333 typedef struct {
34 TkFont font; /* Stuff used by generic font package. Must
35 * be first in structure. */
36
34 TkFont font; /* Stuff used by generic font package. Must be
35 * first in structure. */
3736 NSFont *nsFont;
3837 NSDictionary *nsAttributes;
3938 } MacFont;
8281 static NSCharacterSet *whitespaceCharacterSet = nil;
8382 static NSCharacterSet *lineendingCharacterSet = nil;
8483
85 static void GetTkFontAttributesForNSFont(NSFont *nsFont,
86 TkFontAttributes *faPtr);
87 static NSFont *FindNSFont(const char *familyName, NSFontTraitMask traits,
88 NSInteger weight, CGFloat size, int fallbackToDefault);
89 static void InitFont(NSFont *nsFont, const TkFontAttributes *reqFaPtr,
90 MacFont * fontPtr);
91 static int CreateNamedSystemFont(Tcl_Interp *interp, Tk_Window tkwin,
92 const char* name, TkFontAttributes *faPtr);
93 static void DrawCharsInContext(Display *display, Drawable drawable, GC gc,
94 Tk_Font tkfont, const char *source, int numBytes, int rangeStart,
95 int rangeLength, int x, int y, double angle);
96
97 @interface NSFont(TKFont)
98 - (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters
99 length: (NSUInteger) length attributes: (NSDictionary *) attributes
100 actualCoveredLength: (NSUInteger *) coveredLength;
101 @end
84 static void GetTkFontAttributesForNSFont(NSFont *nsFont,
85 TkFontAttributes *faPtr);
86 static NSFont * FindNSFont(const char *familyName,
87 NSFontTraitMask traits, NSInteger weight,
88 CGFloat size, int fallbackToDefault);
89 static void InitFont(NSFont *nsFont,
90 const TkFontAttributes *reqFaPtr,
91 MacFont *fontPtr);
92 static int CreateNamedSystemFont(Tcl_Interp *interp,
93 Tk_Window tkwin, const char *name,
94 TkFontAttributes *faPtr);
95 static void DrawCharsInContext(Display *display, Drawable drawable,
96 GC gc, Tk_Font tkfont, const char *source,
97 int numBytes, int rangeStart, int rangeLength,
98 int x, int y, double angle);
10299
103100 #pragma mark -
104101 #pragma mark Font Helpers:
105102
103 /*
104 *---------------------------------------------------------------------------
105 *
106 * TclUniToNSString --
107 *
108 * When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot
109 * deal directly with UTF-8 encoded non-BMP characters, since their UTF-8
110 * encoding requires 4 bytes.
111 *
112 * As a workaround, these versions of Tcl encode non-BMP characters as a string
113 * of length 6 in which the high and low UTF-16 surrogates have been encoded
114 * using the UTF-8 algorithm. The UTF-8 encoding does not allow encoding
115 * surrogates, so these 6-byte strings are not valid UTF-8, and hence Apple's
116 * NString class will refuse to instantiate an NSString from the 6-byte
117 * encoding. This function allows creating an NSString from a C-string which
118 * has been encoded using this scheme.
119 *
120 * Results:
121 * An NSString, which may be nil.
122 *
123 * Side effects:
124 * None.
125 *---------------------------------------------------------------------------
126 */
127
128 MODULE_SCOPE NSString*
129 TclUniToNSString(
130 const char *source,
131 int numBytes)
132 {
133 NSString *string = [[NSString alloc] initWithBytesNoCopy:(void *)source
134 length:numBytes
135 encoding:NSUTF8StringEncoding
136 freeWhenDone:NO];
137 if (!string) {
138 const unichar *characters = ckalloc(numBytes*sizeof(unichar));
139 const char *in = source;
140 unichar *out = (unichar *) characters;
141 while (in < source + numBytes) {
142 in += Tcl_UtfToUniChar(in, out++);
143 }
144 string = [[NSString alloc] initWithCharacters:characters
145 length:(out - characters)];
146 ckfree(characters);
147 }
148 return string;
149 }
150
151 /*
152 *---------------------------------------------------------------------------
153 *
154 * TclUniAtIndex --
155 *
156 * Write a sequence of bytes up to length 6 which is an encoding of a UTF-16
157 * character in an NSString. Also record the unicode code point of the character.
158 * this may be a non-BMP character constructed by reading two surrogates from
159 * the NSString.
160 *
161 * Results:
162 * Returns the number of bytes written.
163 *
164 * Side effects:
165 * Bytes are written to the char array referenced by the pointer uni and
166 * the unicode code point is written to the integer referenced by the
167 * pointer code.
168 *
169 */
170
171 MODULE_SCOPE int
172 TclUniAtIndex(
173 NSString *string,
174 int index,
175 char *uni,
176 unsigned int *code)
177 {
178 char *ptr = uni;
179 UniChar uniChar = [string characterAtIndex: index];
180 if (CFStringIsSurrogateHighCharacter(uniChar)) {
181 UniChar lowChar = [string characterAtIndex: ++index];
182 *code = CFStringGetLongCharacterForSurrogatePair(
183 uniChar, lowChar);
184 ptr += Tcl_UniCharToUtf(uniChar, ptr);
185 ptr += Tcl_UniCharToUtf(lowChar, ptr);
186 return ptr - uni;
187 } else {
188 *code = (int) uniChar;
189 [[string substringWithRange: NSMakeRange(index, 1)]
190 getCString: uni
191 maxLength: XMaxTransChars
192 encoding: NSUTF8StringEncoding];
193 return strlen(uni);
194 }
195 }
196
197 /*
198 *---------------------------------------------------------------------------
199 *
200 * NSStringToTclUni --
201 *
202 * Encodes the unicode string represented by an NSString object with the
203 * internal encoding that Tcl uses when TCL_UTF_MAX = 3. This encoding
204 * is similar to UTF-8 except that non-BMP characters are encoded as two
205 * successive 3-byte sequences which are constructed from UTF-16 surrogates
206 * by applying the UTF-8 algorithm. Even though the UTF-8 encoding does not
207 * allow encoding surrogates, the algorithm does produce a well-defined
208 * 3-byte sequence.
209 *
210 * Results:
211 * Returns a pointer to a null-terminated byte array which encodes the
212 * NSString.
213 *
214 * Side effects:
215 * Memory is allocated to hold the byte array, which must be freed with
216 * ckalloc. If the pointer numBytes is not NULL the number of non-null
217 * bytes written to the array is stored in the integer it references.
218 */
219
220 MODULE_SCOPE char*
221 NSStringToTclUni(
222 NSString *string,
223 int *numBytes)
224 {
225 unsigned int code;
226 int i;
227 char *ptr, *bytes = ckalloc(6*[string length] + 1);
228
229 ptr = bytes;
230 if (ptr) {
231 for (i = 0; i < [string length]; i++) {
232 ptr += TclUniAtIndex(string, i, ptr, &code);
233 if (code > 0xffff){
234 i++;
235 }
236 }
237 *ptr = '\0';
238 }
239 if (numBytes) {
240 *numBytes = ptr - bytes;
241 }
242 return bytes;
243 }
244
106245 #define GetNSFontTraitsFromTkFontAttributes(faPtr) \
107246 ((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \
108247 ((faPtr)->slant == TK_FS_ITALIC ? NSItalicFontMask : NSUnitalicFontMask)
130269 {
131270 NSFontTraitMask traits = [[NSFontManager sharedFontManager]
132271 traitsOfFont:nsFont];
133
134272 faPtr->family = Tk_GetUid([[nsFont familyName] UTF8String]);
135273 faPtr->size = [nsFont pointSize];
136274 faPtr->weight = (traits & NSBoldFontMask ? TK_FW_BOLD : TK_FW_NORMAL);
137275 faPtr->slant = (traits & NSItalicFontMask ? TK_FS_ITALIC : TK_FS_ROMAN);
276
138277 }
139278
140279 /*
178317 size = [defaultFont pointSize];
179318 }
180319 nsFont = [fm fontWithFamily:family traits:traits weight:weight size:size];
320
321 /*
322 * A second bug in NSFontManager that Apple created for the Catalina OS
323 * causes requests as above to sometimes return fonts with additional
324 * traits that were not requested, even though fonts without those unwanted
325 * traits exist on the system. See bug [90d555e088]. As a workaround
326 * we ask the font manager to remove any unrequested traits.
327 */
328
329 if (nsFont) {
330 nsFont = [fm convertFont:nsFont toNotHaveTrait:~traits];
331 }
181332 if (!nsFont) {
182333 NSArray *availableFamilies = [fm availableFontFamilies];
183334 NSString *caseFamily = nil;
237388 int ascent, descent/*, dontAA*/;
238389 static const UniChar ch[] = {'.', 'W', ' ', 0xc4, 0xc1, 0xc2, 0xc3, 0xc7};
239390 /* ., W, Space, Auml, Aacute, Acirc, Atilde, Ccedilla */
240 #define nCh (sizeof(ch) / sizeof(UniChar))
391 #define nCh (sizeof(ch) / sizeof(UniChar))
241392 CGGlyph glyphs[nCh];
242393 CGRect boundingRects[nCh];
243394
249400 TkInitFontAttributes(faPtr);
250401 }
251402 fontPtr->nsFont = nsFont;
252 // some don't like antialiasing on fixed-width even if bigger than limit
403
404 /*
405 * Some don't like antialiasing on fixed-width even if bigger than limit
406 */
407
253408 // dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10;
254409 if (antialiasedTextEnabled >= 0/* || dontAA*/) {
255410 renderingMode = (antialiasedTextEnabled == 0/* || dontAA*/) ?
299454 NSLigatureAttributeName,
300455 [NSNumber numberWithDouble:kern], NSKernAttributeName, nil];
301456 fontPtr->nsAttributes = [nsAttributes retain];
302 #undef nCh
457 #undef nCh
303458 }
304459
305460 /*
341496 *
342497 * This procedure is called when an application is created. It
343498 * initializes all the structures that are used by the
344 * platform-dependant code on a per application basis.
499 * platform-dependent code on a per application basis.
345500 * Note that this is called before TkpInit() !
346501 *
347502 * Results:
363518 NSFont *nsFont;
364519 TkFontAttributes fa;
365520 NSMutableCharacterSet *cs;
366 /* Since we called before TkpInit, we need our own autorelease pool. */
521 /*
522 * Since we called before TkpInit, we need our own autorelease pool.
523 */
367524 NSAutoreleasePool *pool = [NSAutoreleasePool new];
368525
369 /* force this for now */
526 /*
527 * Force this for now.
528 */
370529 if (!mainPtr->winPtr->mainPtr) {
371530 mainPtr->winPtr->mainPtr = mainPtr;
372531 }
388547 systemFont++;
389548 }
390549 TkInitFontAttributes(&fa);
550 #if 0
551
552 /*
553 * In macOS 10.15.1 Apple introduced a bug in NSFontManager which caused
554 * it to not recognize the familyName ".SF NSMono" which is the familyName
555 * of the default fixed pitch system fault on that system. See bug [855049e799].
556 * As a workaround we call [NSFont userFixedPitchFontOfSize:11] instead.
557 * This returns a user font in the "Menlo" family.
558 */
559
391560 nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);
561 #else
562 nsFont = [NSFont userFixedPitchFontOfSize:11];
563 #endif
392564 if (nsFont) {
393565 GetTkFontAttributesForNSFont(nsFont, &fa);
566 #if 0
394567 CFRelease(nsFont);
568 #endif
395569 } else {
396570 fa.family = Tk_GetUid("Monaco");
397571 fa.size = 11;
418592 * Map a platform-specific native font name to a TkFont.
419593 *
420594 * Results:
421 * The return value is a pointer to a TkFont that represents the
422 * native font. If a native font by the given name could not be
423 * found, the return value is NULL.
424 *
425 * Every call to this procedure returns a new TkFont structure, even
426 * if the name has already been seen before. The caller should call
595 * The return value is a pointer to a TkFont that represents the native
596 * font. If a native font by the given name could not be found, the return
597 * value is NULL.
598 *
599 * Every call to this procedure returns a new TkFont structure, even if
600 * the name has already been seen before. The caller should call
427601 * TkpDeleteFont() when the font is no longer needed.
428602 *
429 * The caller is responsible for initializing the memory associated
430 * with the generic TkFont when this function returns and releasing
431 * the contents of the generics TkFont before calling TkpDeleteFont().
603 * The caller is responsible for initializing the memory associated with
604 * the generic TkFont when this function returns and releasing the
605 * contents of the generics TkFont before calling TkpDeleteFont().
432606 *
433607 * Side effects:
434608 * None.
454628 } else {
455629 return NULL;
456630 }
457 ctFont = CTFontCreateUIFontForLanguage(HIThemeGetUIFontType(
458 themeFontId), 0, NULL);
631 ctFont = CTFontCreateUIFontForLanguage(
632 HIThemeGetUIFontType(themeFontId), 0, NULL);
459633 if (ctFont) {
460634 fontPtr = ckalloc(sizeof(MacFont));
461635 InitFont((NSFont*) ctFont, NULL, fontPtr);
473647 * closest matching attributes.
474648 *
475649 * Results:
476 * The return value is a pointer to a TkFont that represents the font
477 * with the desired attributes. If a font with the desired attributes
478 * could not be constructed, some other font will be substituted
479 * automatically.
480 *
481 * Every call to this procedure returns a new TkFont structure, even
482 * if the specified attributes have already been seen before. The
483 * caller should call TkpDeleteFont() to free the platform- specific
484 * data when the font is no longer needed.
485 *
486 * The caller is responsible for initializing the memory associated
487 * with the generic TkFont when this function returns and releasing
488 * the contents of the generic TkFont before calling TkpDeleteFont().
650 * The return value is a pointer to a TkFont that represents the font with
651 * the desired attributes. If a font with the desired attributes could not
652 * be constructed, some other font will be substituted automatically.
653 *
654 * Every call to this procedure returns a new TkFont structure, even if
655 * the specified attributes have already been seen before. The caller
656 * should call TkpDeleteFont() to free the platform- specific data when
657 * the font is no longer needed.
658 *
659 * The caller is responsible for initializing the memory associated with
660 * the generic TkFont when this function returns and releasing the
661 * contents of the generic TkFont before calling TkpDeleteFont().
489662 *
490663 * Side effects:
491664 * None.
497670 TkpGetFontFromAttributes(
498671 TkFont *tkFontPtr, /* If non-NULL, store the information in this
499672 * existing TkFont structure, rather than
500 * allocating a new structure to hold the
501 * font; the existing contents of the font
502 * will be released. If NULL, a new TkFont
503 * structure is allocated. */
673 * allocating a new structure to hold the font;
674 * the existing contents of the font will be
675 * released. If NULL, a new TkFont structure is
676 * allocated. */
504677 Tk_Window tkwin, /* For display where font will be used. */
505678 const TkFontAttributes *faPtr)
506679 /* Set of attributes to match. */
507680 {
508681 MacFont *fontPtr;
509 int points = (int)(TkFontGetPoints(tkwin, faPtr->size) + 0.5);
682 int points = (int) (TkFontGetPoints(tkwin, faPtr->size) + 0.5);
510683 NSFontTraitMask traits = GetNSFontTraitsFromTkFontAttributes(faPtr);
511684 NSInteger weight = (faPtr->weight == TK_FW_BOLD ? 9 : 5);
512685 NSFont *nsFont;
543716 * TkpDeleteFont --
544717 *
545718 * Called to release a font allocated by TkpGetNativeFont() or
546 * TkpGetFontFromAttributes(). The caller should have already
547 * released the fields of the TkFont that are used exclusively by the
548 * generic TkFont code.
719 * TkpGetFontFromAttributes(). The caller should have already released the
720 * fields of the TkFont that are used exclusively by the generic TkFont
721 * code.
549722 *
550723 * Results:
551724 * TkFont is deallocated.
572745 *
573746 * TkpGetFontFamilies --
574747 *
575 * Return information about the font families that are available on
576 * the display of the given window.
748 * Return information about the font families that are available on the
749 * display of the given window.
577750 *
578751 * Results:
579752 * Modifies interp's result object to hold a list of all the available
605778 *
606779 * TkpGetSubFonts --
607780 *
608 * A function used by the testing package for querying the actual
609 * screen fonts that make up a font object.
610 *
611 * Results:
612 * Modifies interp's result object to hold a list containing the names
613 * of the screen fonts that make up the given font object.
781 * A function used by the testing package for querying the actual screen
782 * fonts that make up a font object.
783 *
784 * Results:
785 * Modifies interp's result object to hold a list containing the names of
786 * the screen fonts that make up the given font object.
614787 *
615788 * Side effects:
616789 * None.
647820 *
648821 * TkpGetFontAttrsForChar --
649822 *
650 * Retrieve the font attributes of the actual font used to render a
651 * given character.
823 * Retrieve the font attributes of the actual font used to render a given
824 * character.
652825 *
653826 * Results:
654827 * None.
750923 * all the characters on the line for context.
751924 *
752925 * Results:
753 * The return value is the number of bytes from source that
754 * fit into the span that extends from 0 to maxLength. *lengthPtr is
755 * filled with the x-coordinate of the right edge of the last
756 * character that did fit.
926 * The return value is the number of bytes from source that fit into the
927 * span that extends from 0 to maxLength. *lengthPtr is filled with the
928 * x-coordinate of the right edge of the last character that did fit.
757929 *
758930 * Side effects:
759931 * None.
779951 * TK_PARTIAL_OK means include the last char
780952 * which only partially fits on this line.
781953 * TK_WHOLE_WORDS means stop on a word
782 * boundary, if possible. TK_AT_LEAST_ONE
783 * means return at least one character even
784 * if no characters fit. If TK_WHOLE_WORDS
785 * and TK_AT_LEAST_ONE are set and the first
786 * word doesn't fit, we return at least one
954 * boundary, if possible. TK_AT_LEAST_ONE means
955 * return at least one character even if no
956 * characters fit. If TK_WHOLE_WORDS and
957 * TK_AT_LEAST_ONE are set and the first word
958 * doesn't fit, we return at least one
787959 * character or whatever characters fit into
788960 * maxLength. TK_ISOLATE_END means that the
789961 * last character should not be considered in
813985 if (maxLength > 32767) {
814986 maxLength = 32767;
815987 }
816 string = [[NSString alloc] initWithBytesNoCopy:(void*)source
817 length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO];
988 string = TclUniToNSString((const char *)source, numBytes);
818989 if (!string) {
819990 length = 0;
820991 fit = rangeLength;
8691040 }
8701041
8711042 /*
872 * If there is no line breakpoint in the source string between
873 * its start and the index position that fits in maxWidth, then
1043 * If there is no line breakpoint in the source string between its
1044 * start and the index position that fits in maxWidth, then
8741045 * CTTypesetterSuggestLineBreak() returns that very last index.
875 * However if the TK_WHOLE_WORDS flag is set, we want to break
876 * at a word boundary. In this situation, unless TK_AT_LEAST_ONE
877 * is set, we must report that zero chars actually fit (in other
878 * words the smallest word of the source string is still larger
879 * than maxWidth).
1046 * However if the TK_WHOLE_WORDS flag is set, we want to break at a
1047 * word boundary. In this situation, unless TK_AT_LEAST_ONE is set, we
1048 * must report that zero chars actually fit (in other words the
1049 * smallest word of the source string is still larger than maxWidth).
8801050 */
8811051
8821052 if ((index >= start) && (index < len) &&
9081078 CFRelease(line);
9091079 }
9101080
911 /* The call to CTTypesetterSuggestClusterBreak above will always
912 return at least one character regardless of whether it exceeded
913 it or not. Clean that up now. */
1081 /*
1082 * The call to CTTypesetterSuggestClusterBreak above will always return
1083 * at least one character regardless of whether it exceeded it or not.
1084 * Clean that up now.
1085 */
1086
9141087 while (width > maxWidth && !(flags & TK_PARTIAL_OK)
9151088 && index > start+(flags & TK_AT_LEAST_ONE)) {
9161089 range.length = --index;
9511124 * actual implementation in TkpDrawCharsInContext().
9521125 *
9531126 * Results:
954 * None.
1127 * None.
9551128 *
9561129 * Side effects:
9571130 * Information gets drawn on the screen.
9691142 const char *source, /* UTF-8 string to be displayed. Need not be
9701143 * '\0' terminated. All Tk meta-characters
9711144 * (tabs, control characters, and newlines)
972 * should be stripped out of the string that
973 * is passed to this function. If they are not
1145 * should be stripped out of the string that is
1146 * passed to this function. If they are not
9741147 * stripped out, they will be displayed as
9751148 * regular printing characters. */
9761149 int numBytes, /* Number of bytes in string. */
9911164 const char *source, /* UTF-8 string to be displayed. Need not be
9921165 * '\0' terminated. All Tk meta-characters
9931166 * (tabs, control characters, and newlines)
994 * should be stripped out of the string that
995 * is passed to this function. If they are not
1167 * should be stripped out of the string that is
1168 * passed to this function. If they are not
9961169 * stripped out, they will be displayed as
9971170 * regular printing characters. */
9981171 int numBytes, /* Number of bytes in string. */
10341207 const char * source, /* UTF-8 string to be displayed. Need not be
10351208 * '\0' terminated. All Tk meta-characters
10361209 * (tabs, control characters, and newlines)
1037 * should be stripped out of the string that
1038 * is passed to this function. If they are not
1210 * should be stripped out of the string that is
1211 * passed to this function. If they are not
10391212 * stripped out, they will be displayed as
10401213 * regular printing characters. */
10411214 int numBytes, /* Number of bytes in string. */
10591232 const char * source, /* UTF-8 string to be displayed. Need not be
10601233 * '\0' terminated. All Tk meta-characters
10611234 * (tabs, control characters, and newlines)
1062 * should be stripped out of the string that
1063 * is passed to this function. If they are not
1235 * should be stripped out of the string that is
1236 * passed to this function. If they are not
10641237 * stripped out, they will be displayed as
10651238 * regular printing characters. */
10661239 int numBytes, /* Number of bytes in string. */
10911264 !TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) {
10921265 return;
10931266 }
1094 string = [[NSString alloc] initWithBytesNoCopy:(void*)source
1095 length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO];
1267 string = TclUniToNSString((const char *)source, numBytes);
10961268 if (!string) {
10971269 return;
10981270 }
11241296 len = Tcl_NumUtfChars(source, rangeStart + rangeLength);
11251297 if (start > 0) {
11261298 CGRect clipRect = CGRectInfinite, startBounds;
1299
11271300 line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start));
11281301 startBounds = CTLineGetImageBounds(line, context);
11291302 CFRelease(line);
12461419 NSUnderlineStyleAttributeName];
12471420 id strikethrough = [nsAttributes objectForKey:
12481421 NSStrikethroughStyleAttributeName];
1422
12491423 objv[i++] = Tcl_NewStringObj(familyName, -1);
12501424 objv[i++] = Tcl_NewIntObj([nsFont pointSize]);
1251 #define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1))
1425 #define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1))
12521426 objv[i++] = (traits & NSBoldFontMask) ? S(bold) : S(normal);
12531427 objv[i++] = (traits & NSItalicFontMask) ? S(italic) : S(roman);
12541428 if ([underline respondsToSelector:@selector(intValue)] &&
12721446 * TkMacOSXUseAntialiasedText --
12731447 *
12741448 * Enables or disables application-wide use of antialiased text (where
1275 * available). Sets up a linked Tcl global variable to allow
1276 * disabling of antialiased text from tcl.
1449 * available). Sets up a linked Tcl global variable to allow disabling of
1450 * antialiased text from Tcl.
1451 *
12771452 * The possible values for this variable are:
12781453 *
12791454 * -1 - Use system default as configurable in "System Prefs" -> "General".
00 /*
11 * tkMacOSXFont.h --
22 *
3 * Contains the Macintosh implementation of the platform-independant
3 * Contains the Macintosh implementation of the platform-independent
44 * font package interface.
55 *
66 * Copyright (c) 1990-1994 The Regents of the University of California.
00 /*
11 * tkMacOSXHLEvents.c --
22 *
3 * Implements high level event support for the Macintosh. Currently, the
4 * only event that really does anything is the Quit event.
3 * Implements high level event support for the Macintosh.
54 *
65 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
7 * Copyright 2001-2009, Apple Inc.
6 * Copyright (c) 2001-2009, Apple Inc.
87 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
9 * Copyright (c) 2015 Marc Culler
8 * Copyright (c) 2015-2019 Marc Culler
9 * Copyright (c) 2019 Kevin Walzer/WordTech Communications LLC.
1010 *
1111 * See the file "license.terms" for information on usage and redistribution
1212 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
2929 } KillEvent;
3030
3131 /*
32 * When processing an AppleEvent as an idle task, a pointer to one
33 * of these structs is passed as the clientData.
34 */
35
36 typedef struct AppleEventInfo {
37 Tcl_Interp *interp;
38 const char *procedure;
39 Tcl_DString command;
40 NSAppleEventDescriptor *replyEvent; /* Only used for DoScriptText. */
41 } AppleEventInfo;
42
43 /*
3244 * Static functions used only in this file.
3345 */
3446
35 static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event,
36 NSAppleEventDescriptor* replyEvent,
37 Tcl_Interp *interp,
38 const char* procedure);
3947 static int MissedAnyParameters(const AppleEvent *theEvent);
4048 static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
49 static void ProcessAppleEvent(ClientData clientData);
50
51 /*
52 * Names of the procedures which can be used to process AppleEvents.
53 */
54
55 static const char *openDocumentProc = "::tk::mac::OpenDocument";
56 static const char *launchURLProc = "::tk::mac::LaunchURL";
57 static const char *printDocProc = "::tk::mac::PrintDocument";
58 static const char *scriptFileProc = "::tk::mac::DoScriptFile";
59 static const char *scriptTextProc = "::tk::mac::DoScriptText";
4160
4261 #pragma mark TKApplication(TKHLEvents)
4362
7796 - (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
7897 withReplyEvent: (NSAppleEventDescriptor *)replyEvent
7998 {
80 Tcl_Interp *interp = _eventInterp;
81
82 if (interp &&
99 if (_eventInterp &&
83100 Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){
84101 int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication",
85102 -1, TCL_EVAL_GLOBAL);
92109 - (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
93110 withReplyEvent: (NSAppleEventDescriptor *)replyEvent
94111 {
95 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
96 ProcessSerialNumber thePSN = {0, kCurrentProcess};
97 SetFrontProcess(&thePSN);
98 #else
99 [[NSApplication sharedApplication] activateIgnoringOtherApps: YES];
100 #endif
112 [NSApp activateIgnoringOtherApps: YES];
101113 if (_eventInterp && Tcl_FindCommand(_eventInterp,
102114 "::tk::mac::ReopenApplication", NULL, 0)) {
103115 int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication",
123135
124136 - (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
125137 withReplyEvent: (NSAppleEventDescriptor *)replyEvent
126 {
127 tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::OpenDocument");
128 }
129
130 - (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
131 withReplyEvent: (NSAppleEventDescriptor *)replyEvent
132 {
133 tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::PrintDocument");
134 }
135
136 - (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
137 withReplyEvent: (NSAppleEventDescriptor *)replyEvent
138 {
139 OSStatus err;
140 const AEDesc *theDesc = nil;
141 DescType type = 0, initialType = 0;
142 Size actual;
143 int tclErr = -1;
144 char URLBuffer[1 + URL_MAX_LENGTH];
145 char errString[128];
146 char typeString[5];
147
148 /*
149 * The DoScript event receives one parameter that should be text data or a
150 * fileURL.
151 */
152
153 theDesc = [event aeDesc];
154 if (theDesc == nil) {
155 return;
156 }
157
158 err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,
159 NULL, 0, NULL);
160 if (err != noErr) {
161 sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err);
162 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
163 errString, strlen(errString));
164 return;
165 }
166
167 if (MissedAnyParameters((AppleEvent*)theDesc)) {
168 sprintf(errString, "AEDoScriptHandler: extra parameters");
169 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
170 errString, strlen(errString));
171 return;
172 }
173
174 if (initialType == typeFileURL || initialType == typeAlias) {
175 /*
176 * The descriptor can be coerced to a file url. Source the file, or
177 * pass the path as a string argument to ::tk::mac::DoScriptFile if
178 * that procedure exists.
179 */
180 err = AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
181 (Ptr) URLBuffer, URL_MAX_LENGTH, &actual);
182 if (err == noErr && actual > 0){
183 URLBuffer[actual] = '\0';
184 NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
185 NSURL *fileURL = [NSURL URLWithString:urlString];
186 Tcl_DString command;
187 Tcl_DStringInit(&command);
188 if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)){
189 Tcl_DStringAppend(&command, "::tk::mac::DoScriptFile", -1);
190 } else {
191 Tcl_DStringAppend(&command, "source", -1);
192 }
193 Tcl_DStringAppendElement(&command, [[fileURL path] UTF8String]);
194 tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
195 Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
196 }
197 } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
198 NULL, 0, &actual)) {
199 if (actual > 0) {
200 /*
201 * The descriptor can be coerced to UTF8 text. Evaluate as Tcl, or
202 * or pass the text as a string argument to ::tk::mac::DoScriptText
203 * if that procedure exists.
204 */
205 char *data = ckalloc(actual + 1);
206 if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
207 data, actual, NULL)) {
208 if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", NULL, 0)){
209 Tcl_DString command;
210 Tcl_DStringInit(&command);
211 Tcl_DStringAppend(&command, "::tk::mac::DoScriptText", -1);
212 Tcl_DStringAppendElement(&command, data);
213 tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
214 Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
215 } else {
216 tclErr = Tcl_EvalEx(_eventInterp, data, actual, TCL_EVAL_GLOBAL);
217 }
218 }
219 ckfree(data);
220 }
221 } else {
222 /*
223 * The descriptor can not be coerced to a fileURL or UTF8 text.
224 */
225 for (int i = 0; i < 4; i++) {
226 typeString[i] = ((char*)&initialType)[3-i];
227 }
228 typeString[4] = '\0';
229 sprintf(errString, "AEDoScriptHandler: invalid script type '%s', "
230 "must be coercable to 'furl' or 'utf8'", typeString);
231 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, errString,
232 strlen(errString));
233 }
234 /*
235 * If we ran some Tcl code, put the result in the reply.
236 */
237 if (tclErr >= 0) {
238 int reslen;
239 const char *result =
240 Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen);
241 if (tclErr == TCL_OK) {
242 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyDirectObject, typeChar,
243 result, reslen);
244 } else {
245 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
246 result, reslen);
247 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorNumber, typeSInt32,
248 (Ptr) &tclErr,sizeof(int));
249 }
250 }
251 return;
252 }
253 @end
254
255 #pragma mark -
256
257 /*
258 *----------------------------------------------------------------------
259 *
260 * TkMacOSXProcessFiles --
261 *
262 * Extract a list of fileURLs from an AppleEvent and call the specified
263 * procedure with the file paths as arguments.
264 *
265 * Results:
266 * None.
267 *
268 * Side effects:
269 * The event is handled by running the procedure.
270 *
271 *----------------------------------------------------------------------
272 */
273
274 static void
275 tkMacOSXProcessFiles(
276 NSAppleEventDescriptor* event,
277 NSAppleEventDescriptor* replyEvent,
278 Tcl_Interp *interp,
279 const char* procedure)
280138 {
281139 Tcl_Encoding utf8;
282140 const AEDesc *fileSpecDesc = nil;
287145 Size actual;
288146 long count, index;
289147 AEKeyword keyword;
290 Tcl_DString command, pathName;
291 int code;
148 Tcl_DString pathName;
292149
293150 /*
294 * Do nothing if we don't have an interpreter or the procedure doesn't exist.
151 * Do nothing if we don't have an interpreter.
295152 */
296153
297 if (!interp || !Tcl_FindCommand(interp, procedure, NULL, 0)) {
154 if (!_eventInterp) {
298155 return;
299156 }
300157
324181 }
325182
326183 /*
327 * Construct a Tcl command which calls the procedure, passing the
328 * paths contained in the AppleEvent as arguments.
184 * Construct a Tcl expression which calls the ::tk::mac::OpenDocument
185 * procedure, passing the paths contained in the AppleEvent as arguments.
329186 */
330187
331 Tcl_DStringInit(&command);
332 Tcl_DStringAppend(&command, procedure, -1);
188 AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
189 Tcl_DString *openCommand = &AEInfo->command;
190 Tcl_DStringInit(openCommand);
191 Tcl_DStringAppend(openCommand, openDocumentProc, -1);
333192 utf8 = Tcl_GetEncoding(NULL, "utf-8");
334193
335194 for (index = 1; index <= count; index++) {
346205 continue;
347206 }
348207 Tcl_ExternalToUtfDString(utf8, [[fileURL path] UTF8String], -1, &pathName);
349 Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
208 Tcl_DStringAppendElement(openCommand, Tcl_DStringValue(&pathName));
350209 Tcl_DStringFree(&pathName);
351210 }
352211
353212 Tcl_FreeEncoding(utf8);
354213 AEDisposeDesc(&contents);
214 AEInfo->interp = _eventInterp;
215 AEInfo->procedure = openDocumentProc;
216 AEInfo->replyEvent = nil;
217 Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
218 }
219
220 - (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
221 withReplyEvent: (NSAppleEventDescriptor *)replyEvent
222 {
223 NSString* file = [[event paramDescriptorForKeyword:keyDirectObject]
224 stringValue];
225 const char *printFile = [file UTF8String];
226 AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
227 Tcl_DString *printCommand = &AEInfo->command;
228 Tcl_DStringInit(printCommand);
229 Tcl_DStringAppend(printCommand, printDocProc, -1);
230 Tcl_DStringAppendElement(printCommand, printFile);
231 AEInfo->interp = _eventInterp;
232 AEInfo->procedure = printDocProc;
233 AEInfo->replyEvent = nil;
234 Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
235 }
236
237 - (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
238 withReplyEvent: (NSAppleEventDescriptor *)replyEvent
239 {
240 OSStatus err;
241 const AEDesc *theDesc = nil;
242 DescType type = 0, initialType = 0;
243 Size actual;
244 char URLBuffer[1 + URL_MAX_LENGTH];
245 char errString[128];
355246
356247 /*
357 * Handle the event by evaluating the Tcl expression we constructed.
248 * The DoScript event receives one parameter that should be text data or a
249 * fileURL.
358250 */
359251
360 code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
361 Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
252 theDesc = [event aeDesc];
253 if (theDesc == nil) {
254 return;
255 }
256
257 err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,
258 NULL, 0, NULL);
259 if (err != noErr) {
260 sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err);
261 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString,
262 typeChar, errString, strlen(errString));
263 return;
264 }
265
266 if (MissedAnyParameters((AppleEvent*)theDesc)) {
267 sprintf(errString, "AEDoScriptHandler: extra parameters");
268 AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString,
269 typeChar,errString, strlen(errString));
270 return;
271 }
272
273 if (initialType == typeFileURL || initialType == typeAlias) {
274
275 /*
276 * This descriptor can be coerced to a file url. Construct a Tcl
277 * expression which passes the file path as a string argument to
278 * ::tk::mac::DoScriptFile.
279 */
280
281 if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
282 (Ptr) URLBuffer, URL_MAX_LENGTH, &actual)) {
283 if (actual > 0) {
284 URLBuffer[actual] = '\0';
285 NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
286 NSURL *fileURL = [NSURL URLWithString:urlString];
287 AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
288 Tcl_DString *scriptFileCommand = &AEInfo->command;
289 Tcl_DStringInit(scriptFileCommand);
290 Tcl_DStringAppend(scriptFileCommand, scriptFileProc, -1);
291 Tcl_DStringAppendElement(scriptFileCommand, [[fileURL path] UTF8String]);
292 AEInfo->interp = _eventInterp;
293 AEInfo->procedure = scriptFileProc;
294 AEInfo->replyEvent = nil;
295 Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
296 }
297 }
298 } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
299 NULL, 0, &actual)) {
300 /*
301 * The descriptor cannot be coerced to a file URL but can be coerced to
302 * text. Construct a Tcl expression which passes the text as a string
303 * argument to ::tk::mac::DoScriptText.
304 */
305
306 if (actual > 0) {
307 char *data = ckalloc(actual + 1);
308 if (noErr == AEGetParamPtr(theDesc, keyDirectObject,
309 typeUTF8Text, &type,
310 data, actual, NULL)) {
311 AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
312 Tcl_DString *scriptTextCommand = &AEInfo->command;
313 Tcl_DStringInit(scriptTextCommand);
314 Tcl_DStringAppend(scriptTextCommand, scriptTextProc, -1);
315 Tcl_DStringAppendElement(scriptTextCommand, data);
316 AEInfo->interp = _eventInterp;
317 AEInfo->procedure = scriptTextProc;
318 if (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
319 AEInfo->replyEvent = replyEvent;
320 ProcessAppleEvent((ClientData)AEInfo);
321 } else {
322 AEInfo->replyEvent = nil;
323 Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
324 }
325 }
326 }
327 }
328 }
329
330 - (void)handleURLEvent:(NSAppleEventDescriptor*)event
331 withReplyEvent:(NSAppleEventDescriptor*)replyEvent
332 {
333 NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
334 stringValue];
335 const char *cURL=[url UTF8String];
336 AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
337 Tcl_DString *launchCommand = &AEInfo->command;
338 Tcl_DStringInit(launchCommand);
339 Tcl_DStringAppend(launchCommand, launchURLProc, -1);
340 Tcl_DStringAppendElement(launchCommand, cURL);
341 AEInfo->interp = _eventInterp;
342 AEInfo->procedure = launchURLProc;
343 AEInfo->replyEvent = nil;
344 Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
345 }
346
347 @end
348
349 #pragma mark -
350
351 /*
352 *----------------------------------------------------------------------
353 *
354 * ProcessAppleEvent --
355 *
356 * Usually used as an idle task which evaluates a Tcl expression generated
357 * from an AppleEvent. If the AppleEventInfo passed as the client data
358 * has a non-null replyEvent, the result of evaluating the expression will
359 * be added to the reply. This must not be done when this function is
360 * called as an idle task, but is done when handling DoScriptText events
361 * when this function is called directly.
362 *
363 * Results:
364 * None.
365 *
366 * Side effects:
367 * The expression will be evaluated and the clientData will be freed.
368 * The replyEvent may be modified to contain the result of evaluating
369 * a Tcl expression.
370 *
371 *----------------------------------------------------------------------
372 */
373
374 static void ProcessAppleEvent(
375 ClientData clientData)
376 {
377 int code;
378 AppleEventInfo *AEInfo = (AppleEventInfo*) clientData;
379 if (!AEInfo->interp ||
380 !Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
381 return;
382 }
383 code = Tcl_EvalEx(AEInfo->interp, Tcl_DStringValue(&AEInfo->command),
384 Tcl_DStringLength(&AEInfo->command), TCL_EVAL_GLOBAL);
362385 if (code != TCL_OK) {
363 Tcl_BackgroundException(interp, code);
364 }
365 Tcl_DStringFree(&command);
386 Tcl_BackgroundException(AEInfo->interp, code);
387 }
388
389 if (AEInfo->replyEvent && code >= 0) {
390 int reslen;
391 const char *result = Tcl_GetStringFromObj(Tcl_GetObjResult(AEInfo->interp),
392 &reslen);
393 if (code == TCL_OK) {
394 AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
395 keyDirectObject, typeChar, result, reslen);
396 } else {
397 AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
398 keyErrorString, typeChar, result, reslen);
399 AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
400 keyErrorNumber, typeSInt32, (Ptr) &code, sizeof(int));
401 }
402 }
403 Tcl_DStringFree(&AEInfo->command);
404 ckfree(clientData);
366405 }
367406
368407 /*
413452 forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
414453
415454 [aeManager setEventHandler:NSApp
416 andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)
455 andSelector:@selector(handlePrintDocumentsEvent:withReplyEvent:)
417456 forEventClass:kCoreEventClass andEventID:kAEPrintDocuments];
418457
419458 [aeManager setEventHandler:NSApp
420459 andSelector:@selector(handleDoScriptEvent:withReplyEvent:)
421460 forEventClass:kAEMiscStandards andEventID:kAEDoScript];
461
462 [aeManager setEventHandler:NSApp
463 andSelector:@selector(handleURLEvent:withReplyEvent:)
464 forEventClass:kInternetEventClass andEventID:kAEGetURL];
465
422466 }
423467 }
424468
2222 {
2323 return 0;
2424 }
25
25
2626 /*
2727 *----------------------------------------------------------------------
2828 *
8080 data = memcpy(ckalloc(len), image->data + image->xoffset, len);
8181 }
8282 if (data) {
83 provider = CGDataProviderCreateWithData(data, data, len, releaseData);
83 provider = CGDataProviderCreateWithData(data, data, len,
84 releaseData);
8485 }
8586 if (provider) {
86 img = CGImageMaskCreate(image->width, image->height, bitsPerComponent,
87 bitsPerPixel, image->bytes_per_line, provider, decode, 0);
88 }
89 } else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
90
87 img = CGImageMaskCreate(image->width, image->height,
88 bitsPerComponent, bitsPerPixel, image->bytes_per_line,
89 provider, decode, 0);
90 }
91 } else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) {
9192 /*
9293 * Color image
9394 */
9495
9596 CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
97
98 if (image->width == 0 && image->height == 0) {
99 /*
100 * CGCreateImage complains on early macOS releases.
101 */
102
103 return NULL;
104 }
96105 bitsPerComponent = 8;
97106 bitsPerPixel = 32;
98107 bitmapInfo = (image->byte_order == MSBFirst ?
99 kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
108 kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
100109 bitmapInfo |= kCGImageAlphaLast;
101110 data = memcpy(ckalloc(len), image->data + image->xoffset, len);
102111 if (data) {
103 provider = CGDataProviderCreateWithData(data, data, len, releaseData);
112 provider = CGDataProviderCreateWithData(data, data, len,
113 releaseData);
104114 }
105115 if (provider) {
106116 img = CGImageCreate(image->width, image->height, bitsPerComponent,
117127 return img;
118128 }
119129
120
121130 /*
122131 *----------------------------------------------------------------------
123132 *
169178
170179 if (win && has_retina == unknown) {
171180 #ifdef __clang__
172 has_retina = [win respondsToSelector:@selector(backingScaleFactor)]?
173 yes : no;
181 has_retina = [win respondsToSelector:@selector(backingScaleFactor)] ?
182 yes : no;
174183 #else
175184 has_retina = no;
176185 #endif
177186 }
178187
179188 if (has_retina == yes) {
180
181189 /*
182190 * We only allow scale factors 1 or 2, as Apple currently does.
183191 */
195203 }
196204
197205 bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable,
198 x, y, width, height);
206 x, y, width, height);
199207 if (!bitmap_rep) {
200208 TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
201209 return NULL;
204212 size = [bitmap_rep bytesPerPlane];
205213 bytes_per_row = [bitmap_rep bytesPerRow];
206214 bitmap = ckalloc(size);
207 if (!bitmap ||
208 (bitmap_fmt != 0 && bitmap_fmt != 1) ||
209 [bitmap_rep samplesPerPixel] != 4 ||
210 [bitmap_rep isPlanar] != 0 ||
211 bytes_per_row < 4 * scaled_width ||
212 size != bytes_per_row*scaled_height ) {
215 if (!bitmap
216 || (bitmap_fmt != 0 && bitmap_fmt != 1)
217 || [bitmap_rep samplesPerPixel] != 4
218 || [bitmap_rep isPlanar] != 0
219 || bytes_per_row < 4 * scaled_width
220 || size != bytes_per_row * scaled_height) {
213221 TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
214222 CFRelease(bitmap_rep);
215223 return NULL;
218226 CFRelease(bitmap_rep);
219227
220228 /*
221 * When Apple extracts a bitmap from an NSView, it may be in
222 * either BGRA or ABGR format. For an XImage we need RGBA.
229 * When Apple extracts a bitmap from an NSView, it may be in either
230 * BGRA or ABGR format. For an XImage we need RGBA.
223231 */
224232
225233 struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr;
238246 }
239247 }
240248 imagePtr = XCreateImage(display, NULL, depth, format, offset,
241 (char*)bitmap, scaled_width, scaled_height,
242 bitmap_pad, bytes_per_row);
249 (char*) bitmap, scaled_width, scaled_height,
250 bitmap_pad, bytes_per_row);
243251 if (scalefactor == 2) {
244252 imagePtr->pixelpower = 1;
245253 }
246254 } else {
247255 /*
248 * There are some calls to XGetImage in the generic Tk
249 * code which pass an XYPixmap rather than a ZPixmap.
250 * XYPixmaps should be handled here.
256 * There are some calls to XGetImage in the generic Tk code which pass
257 * an XYPixmap rather than a ZPixmap. XYPixmaps should be handled
258 * here.
251259 */
252260 TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment.");
253261 }
313321 + (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
314322
315323 switch (image->bits_per_pixel) {
316 case 32: {
317 r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
318 g = (*((unsigned int*) srcPtr) >> 8) & 0xff;
319 b = (*((unsigned int*) srcPtr) ) & 0xff;
320 /*if (image->byte_order == LSBFirst) {
321 r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
322 } else {
323 r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
324 }*/
325 break;
326 }
327 case 16:
328 r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
329 g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
330 b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
331 break;
332 case 8:
333 r = (*srcPtr << 2) & 0xc0;
334 g = (*srcPtr << 4) & 0xc0;
335 b = (*srcPtr << 6) & 0xc0;
336 r |= r >> 2 | r >> 4 | r >> 6;
337 g |= g >> 2 | g >> 4 | g >> 6;
338 b |= b >> 2 | b >> 4 | b >> 6;
339 break;
340 case 4: {
341 unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
342 r = (c & 0x04) ? 0xff : 0;
343 g = (c & 0x02) ? 0xff : 0;
344 b = (c & 0x01) ? 0xff : 0;
345 break;
346 }
347 case 1:
348 r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
349 break;
324 case 32:
325 r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
326 g = (*((unsigned int*) srcPtr) >> 8) & 0xff;
327 b = (*((unsigned int*) srcPtr) ) & 0xff;
328 /*if (image->byte_order == LSBFirst) {
329 r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
330 } else {
331 r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
332 }*/
333 break;
334 case 16:
335 r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
336 g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
337 b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
338 break;
339 case 8:
340 r = (*srcPtr << 2) & 0xc0;
341 g = (*srcPtr << 4) & 0xc0;
342 b = (*srcPtr << 6) & 0xc0;
343 r |= r >> 2 | r >> 4 | r >> 6;
344 g |= g >> 2 | g >> 4 | g >> 6;
345 b |= b >> 2 | b >> 4 | b >> 6;
346 break;
347 case 4: {
348 unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
349
350 r = (c & 0x04) ? 0xff : 0;
351 g = (c & 0x02) ? 0xff : 0;
352 b = (c & 0x01) ? 0xff : 0;
353 break;
354 }
355 case 1:
356 r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
357 break;
350358 }
351359 }
352360 return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;
379387 unsigned char *dstPtr = ((unsigned char*) image->data)
380388 + (y * image->bytes_per_line)
381389 + (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
390
382391 if (image->bits_per_pixel == 32) {
383392 *((unsigned int*) dstPtr) = pixel;
384393 } else {
410419 }
411420 return 0;
412421 }
413
422
414423 /*
415424 *----------------------------------------------------------------------
416425 *
441450 int bytes_per_line)
442451 {
443452 XImage *ximage;
453
444454 display->request++;
445455 ximage = ckalloc(sizeof(XImage));
446456
451461 ximage->format = format;
452462 ximage->data = data;
453463 ximage->obdata = NULL;
454 /* The default pixelpower is 0. This must be explicitly set to 1 in the
464
465 /*
466 * The default pixelpower is 0. This must be explicitly set to 1 in the
455467 * case of an XImage extracted from a Retina display.
456468 */
469
457470 ximage->pixelpower = 0;
458471
459472 if (format == ZPixmap) {
466479 if (bitmap_pad) {
467480 ximage->bitmap_pad = bitmap_pad;
468481 } else {
469 /* Use 16 byte alignment for best Quartz perfomance */
482 /*
483 * Use 16 byte alignment for best Quartz perfomance.
484 */
485
470486 ximage->bitmap_pad = 128;
471487 }
472488 if (bytes_per_line) {
499515 /*
500516 *----------------------------------------------------------------------
501517 *
502 * TkPutImage --
503 *
504 * Copies a rectangular subimage of an XImage into a drawable.
505 * Currently this is only called by TkImgPhotoDisplay, using
506 * a Window as the drawable.
518 * TkPutImage, XPutImage --
519 *
520 * Copies a rectangular subimage of an XImage into a drawable. Currently
521 * this is only called by TkImgPhotoDisplay, using a Window as the
522 * drawable.
507523 *
508524 * Results:
509525 * None.
515531 */
516532
517533 int
518 TkPutImage(
519 unsigned long *colors, /* Unused on Macintosh. */
520 int ncolors, /* Unused on Macintosh. */
534 XPutImage(
521535 Display* display, /* Display. */
522536 Drawable drawable, /* Drawable to place image on. */
523537 GC gc, /* GC to use. */
549563 }
550564 if (img) {
551565
552 /* If the XImage has big pixels, the source is rescaled to reflect
566 /*
567 * If the XImage has big pixels, the source is rescaled to reflect
553568 * the actual pixel dimensions. This is not currently used, but
554569 * could arise if the image were copied from a retina monitor and
555570 * redrawn on an ordinary monitor.
556571 */
557572
558573 int pp = image->pixelpower;
574
559575 bounds = CGRectMake(0, 0, image->width, image->height);
560576 srcRect = CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp);
561577 dstRect = CGRectMake(dest_x, dest_y, width, height);
572588 TkMacOSXRestoreDrawingContext(&dc);
573589 return Success;
574590 }
591
592 int
593 TkPutImage(
594 unsigned long *colors, /* Array of pixel values used by this image.
595 * May be NULL. */
596 int ncolors, /* Number of colors used, or 0. */
597 Display *display,
598 Drawable d, /* Destination drawable. */
599 GC gc,
600 XImage *image, /* Source image. */
601 int src_x, int src_y, /* Offset of subimage. */
602 int dest_x, int dest_y, /* Position of subimage origin in drawable. */
603 unsigned int width, unsigned int height)
604 /* Dimensions of subimage. */
605 {
606 return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
607 }
575608
576609 /*
577610 * Local Variables:
2929
3030 #pragma mark TKApplication(TKInit)
3131
32 @interface TKApplication(TKKeyboard)
33 - (void) keyboardChanged: (NSNotification *) notification;
34 @end
35
36 #define TKApplication_NSApplicationDelegate <NSApplicationDelegate>
37 @interface TKApplication(TKWindowEvent) TKApplication_NSApplicationDelegate
38 - (void) _setupWindowNotifications;
39 @end
40
41 @interface TKApplication(TKMenus)
42 - (void) _setupMenus;
43 @end
44
4532 @implementation TKApplication
4633 @synthesize poolLock = _poolLock;
4734 @synthesize macMinorVersion = _macMinorVersion;
4835 @synthesize isDrawing = _isDrawing;
49 @synthesize simulateDrawing = _simulateDrawing;
5036 @end
5137
5238 /*
5844 @implementation TKApplication(TKInit)
5945 - (void) _resetAutoreleasePool
6046 {
61 if([self poolLock] == 0) {
47 if ([self poolLock] == 0) {
6248 [_mainPool drain];
6349 _mainPool = [NSAutoreleasePool new];
6450 } else {
115101 _defaultMainMenu = nil;
116102 [self _setupMenus];
117103
118
119104 /*
120105 * Initialize event processing.
121106 */
131116 -(void)applicationDidFinishLaunching:(NSNotification *)notification
132117 {
133118 /*
134 * It is not safe to force activation of the NSApp until this
135 * method is called. Activating too early can cause the menu
136 * bar to be unresponsive.
137 */
119 * It is not safe to force activation of the NSApp until this method is
120 * called. Activating too early can cause the menu bar to be unresponsive.
121 * The call to activateIgnoringOtherApps was moved here to avoid this.
122 * However, with the release of macOS 10.15 (Catalina) this was no longer
123 * sufficient. (See ticket bf93d098d7.) Apparently apps were being
124 * activated automatically, and this was sometimes being done too early.
125 * As a workaround we deactivate and then reactivate the app, even though
126 * Apple says that "Normally, you shouldn’t invoke this method".
127 */
128
129 [NSApp deactivate];
138130 [NSApp activateIgnoringOtherApps: YES];
131
132 /*
133 * Process events to ensure that the root window is fully initialized. See
134 * ticket 56a1823c73.
135 */
136
137 [NSApp _lockAutoreleasePool];
138 while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
139 [NSApp _unlockAutoreleasePool];
139140 }
140141
141142 - (void) _setup: (Tcl_Interp *) interp
155156 * Record the OS version we are running on.
156157 */
157158 int minorVersion;
158 #if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
159 #if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
159160 Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
160161 #else
161162 NSOperatingSystemVersion systemVersion;
165166 [NSApp setMacMinorVersion: minorVersion];
166167
167168 /*
168 * We are not drawing yet.
169 * We are not drawing right now.
169170 */
170171
171172 [NSApp setIsDrawing:NO];
172 [NSApp setSimulateDrawing:NO];
173173
174174 /*
175175 * Be our own delegate.
176176 */
177
177178 [self setDelegate:self];
178179
179180 /*
186187 * If no icon has been set from an Info.plist file, use the Wish icon from
187188 * the Tk framework.
188189 */
190
189191 NSString *iconFile = [[NSBundle mainBundle] objectForInfoDictionaryKey:
190192 @"CFBundleIconFile"];
191193 if (!iconFile) {
314316 }
315317
316318 /*
317 * Instantiate our NSApplication object. This needs to be
318 * done before we check whether to open a console window.
319 * Instantiate our NSApplication object. This needs to be done before
320 * we check whether to open a console window.
319321 */
320322
321323 NSAutoreleasePool *pool = [NSAutoreleasePool new];
329331 [TKApplication sharedApplication];
330332 [pool drain];
331333 [NSApp _setup:interp];
334
335 /*
336 * WARNING: The finishLaunching method runs asynchronously, apparently
337 * in a separate thread. This creates a race between the
338 * initialization of the NSApplication and the initialization of Tk.
339 * If Tk wins the race bad things happen with the root window (see
340 * below). If the NSApplication wins then an AppleEvent created during
341 * launch, e.g. by dropping a file icon on the application icon, will
342 * be delivered before the procedure meant to to handle the AppleEvent
343 * has been defined. This is now handled by processing the AppleEvent
344 * as an idle task. See tkMacOSXHLEvents.c.
345 */
346
332347 [NSApp finishLaunching];
348
349 /*
350 * Create a Tk event source based on the Appkit event queue.
351 */
352
353 Tk_MacOSXSetupTkNotifier();
354
355 /*
356 * If Tk initialization wins the race, the root window is mapped before
357 * the NSApplication is initialized. This can cause bad things to
358 * happen. The root window can open off screen with no way to make it
359 * appear on screen until the app icon is clicked. This will happen if
360 * a Tk application opens a modal window in its startup script (see
361 * ticket 56a1823c73). In other cases, an empty root window can open
362 * on screen and remain visible for a noticeable amount of time while
363 * the Tk initialization finishes (see ticket d1989fb7cf). The call
364 * below forces Tk to block until the Appkit event queue has been
365 * created. This seems to be sufficient to ensure that the
366 * NSApplication initialization wins the race, avoiding these bad
367 * window behaviors.
368 */
369
370 Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT);
333371
334372 /*
335373 * If we don't have a TTY and stdin is a special character file of
346384 Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));
347385
348386 /*
349 * Only show the console if we don't have a startup script
350 * and tcl_interactive hasn't been set already.
387 * Only show the console if we don't have a startup script and
388 * tcl_interactive hasn't been set already.
351389 */
352390
353391 if (Tcl_GetStartupScript(NULL) == NULL) {
364402 }
365403 }
366404
367 }
368
369 Tk_MacOSXSetupTkNotifier();
405 /*
406 * Initialize the NSServices object here. Apple's docs say to do this
407 * in applicationDidFinishLaunching, but the Tcl interpreter is not
408 * initialized until this function call.
409 */
410
411 TkMacOSXServices_Init(interp);
412 }
370413
371414 if (tkLibPath[0] != '\0') {
372415 Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY);
381424 TkMacOSXStandardAboutPanelObjCmd, NULL, NULL);
382425 Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap",
383426 TkMacOSXIconBitmapObjCmd, NULL, NULL);
384
427 Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", TkMacOSXGetAppPath, NULL, NULL);
385428 return TCL_OK;
386429 }
387430
421464 }
422465 Tcl_DStringAppend(namePtr, name, -1);
423466 }
424
467
468 /*
469 *----------------------------------------------------------------------
470 *
471 * TkMacOSXGetAppPath --
472 *
473 * Returns the path of the Wish application bundle.
474 *
475 * Results:
476 * Returns the application path.
477 *
478 * Side effects:
479 * None.
480 *
481 *----------------------------------------------------------------------
482 */
483 int TkMacOSXGetAppPath(
484 ClientData cd,
485 Tcl_Interp *ip,
486 int objc,
487 Tcl_Obj *const objv[])
488 {
489
490 CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
491
492
493 /*
494 * Convert the URL reference into a string reference.
495 */
496
497 CFStringRef appPath = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
498
499 /*
500 * Get the system encoding method.
501 */
502
503 CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
504
505 /*
506 * Convert the string reference into a C string.
507 */
508
509 char *path = (char *) CFStringGetCStringPtr(appPath, encodingMethod);
510
511 Tcl_SetResult(ip, path, NULL);
512
513 CFRelease(mainBundleURL);
514 CFRelease(appPath);
515 return TCL_OK;
516
517 }
518
425519 /*
426520 *----------------------------------------------------------------------
427521 *
7070 * gone. */
7171 struct TkWindowPrivate *toplevel;
7272 /* Pointer to the toplevel datastruct. */
73 CGFloat fillRGBA[4]; /* Background used by the ttk FillElement */
7374 int flags; /* Various state see defines below. */
7475 };
7576 typedef struct TkWindowPrivate MacDrawable;
8586 #define TK_IS_PIXMAP 0x10
8687 #define TK_IS_BW_PIXMAP 0x20
8788 #define TK_DO_NOT_DRAW 0x40
89 #define TTK_HAS_CONTRASTING_BG 0x80
8890
8991 /*
9092 * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags
199201 MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
200202 MODULE_SCOPE Bool TkpAppIsDrawing(void);
201203 MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
202 MODULE_SCOPE void TkTestSimulateDrawing(Bool);
204 MODULE_SCOPE Bool TkTestLogDisplay(void);
205 MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin);
203206
204207 /*
205208 * Include the stubbed internal platform-specific API.
208211 #include "tkIntPlatDecls.h"
209212
210213 #endif /* _TKMACINT */
214
215 /*
216 * Local Variables:
217 * mode: objc
218 * c-basic-offset: 4
219 * fill-column: 79
220 * coding: utf-8
221 * End:
222 */
66 * Copyright 2001-2009, Apple Inc.
77 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
88 * Copyright (c) 2012 Adrian Robert.
9 * Copyright 2015 Marc Culler.
9 * Copyright 2015-2019 Marc Culler.
1010 *
1111 * See the file "license.terms" for information on usage and redistribution of
1212 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
1313 */
1414
1515 #include "tkMacOSXPrivate.h"
16 #include "tkMacOSXEvent.h"
16 #include "tkMacOSXInt.h"
1717 #include "tkMacOSXConstants.h"
1818
1919 /*
2323 */
2424 #define NS_KEYLOG 0
2525
26
27 static Tk_Window grabWinPtr = NULL;
28 /* Current grab window, NULL if no grab. */
2926 static Tk_Window keyboardGrabWinPtr = NULL;
3027 /* Current keyboard grab window. */
3128 static NSWindow *keyboardGrabNSWindow = nil;
32 /* NSWindow for the current keyboard grab window. */
29 /* NSWindow for the current keyboard grab
30 * window. */
3331 static NSModalSession modalSession = nil;
34
3532 static BOOL processingCompose = NO;
36 static BOOL finishedCompose = NO;
37
33 static Tk_Window composeWin = NULL;
3834 static int caret_x = 0, caret_y = 0, caret_height = 0;
35 static unsigned short releaseCode;
3936
4037 static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state);
41 static unsigned isFunctionKey(unsigned int code);
42
43 unsigned short releaseCode;
38 static unsigned isFunctionKey(unsigned int code);
4439
4540
4641 #pragma mark TKApplication(TKKeyEvent)
5247 #ifdef TK_MAC_DEBUG_EVENTS
5348 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
5449 #endif
55 NSWindow* w;
56 NSEventType type = [theEvent type];
57 NSUInteger modifiers, len = 0;
58 BOOL repeat = NO;
59 unsigned short keyCode;
60 NSString *characters = nil, *charactersIgnoringModifiers = nil;
50 NSWindow *w;
51 NSEventType type = [theEvent type];
52 NSUInteger modifiers = ([theEvent modifierFlags] &
53 NSDeviceIndependentModifierFlagsMask);
54 NSUInteger len = 0;
55 BOOL repeat = NO;
56 unsigned short keyCode = [theEvent keyCode];
57 NSString *characters = nil, *charactersIgnoringModifiers = nil;
6158 static NSUInteger savedModifiers = 0;
6259 static NSMutableArray *nsEvArray;
6360
64 if (nsEvArray == nil)
65 {
61 if (nsEvArray == nil) {
6662 nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
6763 processingCompose = NO;
68 }
64 }
6965
7066 w = [theEvent window];
7167 TkWindow *winPtr = TkMacOSXGetTkWindow(w);
7369 XEvent xEvent;
7470
7571 if (!winPtr) {
72 return theEvent;
73 }
74
75 /*
76 * Control-Tab and Control-Shift-Tab are used to switch tabs in a tabbed
77 * window. We do not want to generate an Xevent for these since that might
78 * cause the deselected tab to be reactivated.
79 */
80
81 if (keyCode == 48 && (modifiers & NSControlKeyMask) == NSControlKeyMask) {
7682 return theEvent;
7783 }
7884
8995 charactersIgnoringModifiers = [theEvent charactersIgnoringModifiers];
9096 len = [charactersIgnoringModifiers length];
9197 case NSFlagsChanged:
92 modifiers = [theEvent modifierFlags];
93 keyCode = [theEvent keyCode];
9498
9599 #if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1
96100 TKLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type);
101105 return theEvent; /* Unrecognized key event. */
102106 }
103107
104 /* Create an Xevent to add to the Tk queue. */
108 /*
109 * Create an Xevent to add to the Tk queue.
110 */
111
105112 if (!processingCompose) {
106113 unsigned int state = 0;
107114
108115 if (modifiers & NSAlphaShiftKeyMask) {
109 state |= LockMask;
116 state |= LockMask;
110117 }
111118 if (modifiers & NSShiftKeyMask) {
112 state |= ShiftMask;
119 state |= ShiftMask;
113120 }
114121 if (modifiers & NSControlKeyMask) {
115 state |= ControlMask;
122 state |= ControlMask;
116123 }
117124 if (modifiers & NSCommandKeyMask) {
118 state |= Mod1Mask; /* command key */
125 state |= Mod1Mask; /* command key */
119126 }
120127 if (modifiers & NSAlternateKeyMask) {
121 state |= Mod2Mask; /* option key */
128 state |= Mod2Mask; /* option key */
122129 }
123130 if (modifiers & NSNumericPadKeyMask) {
124 state |= Mod3Mask;
131 state |= Mod3Mask;
125132 }
126133 if (modifiers & NSFunctionKeyMask) {
127 state |= Mod4Mask;
134 state |= Mod4Mask;
128135 }
129136
130137 /*
131 * The focus must be in the FrontWindow on the Macintosh. We then query Tk
132 * to determine the exact Tk window that owns the focus.
138 * Key events are only received for the front Window on the Macintosh. So
139 * to build an XEvent we look up the Tk window associated to the Front
140 * window.
133141 */
134142
135143 TkWindow *winPtr = TkMacOSXGetTkWindow(w);
136144 Tk_Window tkwin = (Tk_Window) winPtr;
137145
146 if (tkwin) {
147 TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
148
149 /*
150 * If a local grab is in effect, key events for windows in the
151 * grabber's application are redirected to the grabber. Key events
152 * for other applications are delivered normally. If a global
153 * grab is in effect all key events are redirected to the grabber.
154 */
155
156 if (grabWinPtr) {
157 if (winPtr->dispPtr->grabFlags || /* global grab */
158 grabWinPtr->mainPtr == winPtr->mainPtr){ /* same appl. */
159 tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
160 }
161 }
162 } else {
163 tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
164 }
138165 if (!tkwin) {
139 TkMacOSXDbgMsg("tkwin == NULL");
140 return theEvent;
166 TkMacOSXDbgMsg("tkwin == NULL");
167 return theEvent; /* Give up. No window for this event. */
141168 }
142 tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
143 if (!tkwin) {
144 TkMacOSXDbgMsg("tkwin == NULL");
145 return theEvent; /* Give up. No window for this event. */
146 }
147169
148170 /*
149 * If it's a function key, or we have modifiers other than Shift or Alt,
150 * pass it straight to Tk. Otherwise we'll send for input processing.
171 * If it's a function key, or we have modifiers other than Shift or
172 * Alt, pass it straight to Tk. Otherwise we'll send for input
173 * processing.
151174 */
152 int code = (len == 0) ?
153 0 : [charactersIgnoringModifiers characterAtIndex: 0];
175
176 int code = (len == 0) ? 0 :
177 [charactersIgnoringModifiers characterAtIndex: 0];
154178 if (type != NSKeyDown || isFunctionKey(code)
155 || (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) {
156
179 || (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) {
157180 XEvent xEvent;
181
158182 setupXEvent(&xEvent, w, state);
159
160183 if (type == NSFlagsChanged) {
161 if (savedModifiers > modifiers) {
162 xEvent.xany.type = KeyRelease;
163 } else {
164 xEvent.xany.type = KeyPress;
165 }
166
167 /*
168 * Use special '-1' to signify a special keycode to our platform
169 * specific code in tkMacOSXKeyboard.c. This is rather like what
170 * happens on Windows.
171 */
172
173 xEvent.xany.send_event = -1;
174
175 /*
176 * Set keycode (which was zero) to the changed modifier
177 */
178
179 xEvent.xkey.keycode = (modifiers ^ savedModifiers);
184 if (savedModifiers > modifiers) {
185 xEvent.xany.type = KeyRelease;
186 } else {
187 xEvent.xany.type = KeyPress;
188 }
189
190 /*
191 * Use special '-1' to signify a special keycode to our
192 * platform specific code in tkMacOSXKeyboard.c. This is rather
193 * like what happens on Windows.
194 */
195
196 xEvent.xany.send_event = -1;
197
198 /*
199 * Set keycode (which was zero) to the changed modifier
200 */
201
202 xEvent.xkey.keycode = (modifiers ^ savedModifiers);
180203 } else {
181 if (type == NSKeyUp || repeat) {
182 xEvent.xany.type = KeyRelease;
183 } else {
184 xEvent.xany.type = KeyPress;
185 }
186
187 /* For command key, take input manager's word so things
188 like dvorak / qwerty layout work. */
189 if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask
190 && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask
191 && len > 0 && !isFunctionKey(code)) {
192 // head off keycode-based translation in tkMacOSXKeyboard.c
193 xEvent.xkey.nbytes = [characters length]; //len
194 }
195
196 if ([characters length] > 0) {
197 xEvent.xkey.keycode =
198 (keyCode << 16) | (UInt16) [characters characterAtIndex:0];
199 if (![characters getCString:xEvent.xkey.trans_chars
200 maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) {
201 /* prevent SF bug 2907388 (crash on some composite chars) */
202 //PENDING: we might not need this anymore
203 TkMacOSXDbgMsg("characters too long");
204 return theEvent;
205 }
206 }
207
208 if (repeat) {
209 Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
210 xEvent.xany.type = KeyPress;
211 xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
212 }
204 if (type == NSKeyUp || repeat) {
205 xEvent.xany.type = KeyRelease;
206 } else {
207 xEvent.xany.type = KeyPress;
208 }
209
210 if ([characters length] > 0) {
211 xEvent.xkey.keycode = (keyCode << 16) |
212 (UInt16) [characters characterAtIndex:0];
213 if (![characters getCString:xEvent.xkey.trans_chars
214 maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) {
215 /* prevent SF bug 2907388 (crash on some composite chars) */
216 //PENDING: we might not need this anymore
217 TkMacOSXDbgMsg("characters too long");
218 return theEvent;
219 }
220 }
221
222 if (repeat) {
223 Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
224 xEvent.xany.type = KeyPress;
225 xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
226 }
213227 }
214228 Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
215229 savedModifiers = modifiers;
216230 return theEvent;
217 } /* if send straight to TK */
218
219 } /* if not processing compose */
231 } /* if this is a function key or has modifiers */
232 } /* if not processing compose */
220233
221234 if (type == NSKeyDown) {
222 if (NS_KEYLOG)
223 fprintf (stderr, "keyDown: %s compose sequence.\n",
224 processingCompose == YES ? "Continue" : "Begin");
225 processingCompose = YES;
226 [nsEvArray addObject: theEvent];
227 [[w contentView] interpretKeyEvents: nsEvArray];
228 [nsEvArray removeObject: theEvent];
229 }
230
235 if (NS_KEYLOG) {
236 TKLog(@"keyDown: %s compose sequence.\n",
237 processingCompose == YES ? "Continue" : "Begin");
238 }
239
240 /*
241 * Call the interpretKeyEvents method to interpret composition key
242 * strokes. When it detects a complete composition sequence it will
243 * call our implementation of insertText: replacementRange, which
244 * generates a key down XEvent with the appropriate character. In IME
245 * when multiple characters have the same composition sequence and the
246 * chosen character is not the default it may be necessary to hit the
247 * enter key multiple times before the character is accepted and
248 * rendered. We send enter key events until inputText has cleared
249 * the processingCompose flag.
250 */
251
252 processingCompose = YES;
253 while(processingCompose) {
254 [nsEvArray addObject: theEvent];
255 [[w contentView] interpretKeyEvents: nsEvArray];
256 [nsEvArray removeObject: theEvent];
257 if ([theEvent keyCode] != 36) {
258 break;
259 }
260 }
261 }
231262 savedModifiers = modifiers;
232
233263 return theEvent;
234264 }
235 @end
236
237
238
239 @implementation TKContentView
240 /* <NSTextInput> implementation (called through interpretKeyEvents:]). */
241
242 /* <NSTextInput>: called when done composing;
243 NOTE: also called when we delete over working text, followed immed.
244 by doCommandBySelector: deleteBackward: */
245 - (void)insertText: (id)aString
246 {
247 int i, len = [(NSString *)aString length];
248 XEvent xEvent;
249
250 if (NS_KEYLOG)
251 TKLog (@"insertText '%@'\tlen = %d", aString, len);
252 processingCompose = NO;
253 finishedCompose = YES;
254
255 /* first, clear any working text */
256 if (privateWorkingText != nil)
257 [self deleteWorkingText];
258
259 /* now insert the string as keystrokes */
260 setupXEvent(&xEvent, [self window], 0);
261 xEvent.xany.type = KeyPress;
262
263 for (i =0; i<len; i++)
264 {
265 xEvent.xkey.keycode = (UInt16) [aString characterAtIndex: i];
266 [[aString substringWithRange: NSMakeRange(i,1)]
267 getCString: xEvent.xkey.trans_chars
268 maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
269 xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
270 xEvent.xany.type = KeyPress;
271 releaseCode = (UInt16) [aString characterAtIndex: 0];
272 Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
273 }
274 releaseCode = (UInt16) [aString characterAtIndex: 0];
275 }
276
277
278 /* <NSTextInput>: inserts display of composing characters */
279 - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
280 {
281 NSString *str = [aString respondsToSelector: @selector (string)] ?
282 [aString string] : aString;
283 if (NS_KEYLOG)
284 TKLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str,
285 (unsigned long) [str length], (unsigned long) selRange.length,
286 (unsigned long) selRange.location);
287
288 if (privateWorkingText != nil)
289 [self deleteWorkingText];
290 if ([str length] == 0)
291 return;
292
293 processingCompose = YES;
294 privateWorkingText = [str copy];
295
296 //PENDING: insert workingText underlined
297 }
298
299
300 - (BOOL)hasMarkedText
301 {
302 return privateWorkingText != nil;
303 }
304
305
306 - (NSRange)markedRange
307 {
308 NSRange rng = privateWorkingText != nil
309 ? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0);
310 if (NS_KEYLOG)
311 TKLog (@"markedRange request");
312 return rng;
313 }
314
315
316 - (void)unmarkText
317 {
318 if (NS_KEYLOG)
319 TKLog (@"unmark (accept) text");
320 [self deleteWorkingText];
321 processingCompose = NO;
322 }
323
324
325 /* used to position char selection windows, etc. */
326 - (NSRect)firstRectForCharacterRange: (NSRange)theRange
327 {
328 NSRect rect;
329 NSPoint pt;
330
331 pt.x = caret_x;
332 pt.y = caret_y;
333
334 pt = [self convertPoint: pt toView: nil];
335 pt = [[self window] tkConvertPointToScreen: pt];
336 pt.y -= caret_height;
337
338 rect.origin = pt;
339 rect.size.width = caret_height;
340 rect.size.height = caret_height;
341 return rect;
342 }
343
344
345 - (NSInteger)conversationIdentifier
346 {
347 return (NSInteger)self;
348 }
349
350
351 - (void)doCommandBySelector: (SEL)aSelector
352 {
353 if (NS_KEYLOG)
354 TKLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
355 processingCompose = NO;
356 if (aSelector == @selector (deleteBackward:))
357 {
358 /* happens when user backspaces over an ongoing composition:
359 throw a 'delete' into the event queue */
360 XEvent xEvent;
361 setupXEvent(&xEvent, [self window], 0);
362 xEvent.xany.type = KeyPress;
363 xEvent.xkey.nbytes = 1;
364 xEvent.xkey.keycode = (0x33 << 16) | 0x7F;
365 xEvent.xkey.trans_chars[0] = 0x7F;
366 xEvent.xkey.trans_chars[1] = 0x0;
367 Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
368 }
369 }
370
371
372 - (NSArray *)validAttributesForMarkedText
373 {
374 static NSArray *arr = nil;
375 if (arr == nil) arr = [NSArray new];
376 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
377 return arr;
378 }
379
380
381 - (NSRange)selectedRange
382 {
383 if (NS_KEYLOG)
384 TKLog (@"selectedRange request");
385 return NSMakeRange (NSNotFound, 0);
386 }
387
388
389 - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
390 {
391 if (NS_KEYLOG)
392 TKLog (@"characterIndexForPoint request");
393 return 0;
394 }
395
396
397 - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
398 {
399 static NSAttributedString *str = nil;
400 if (str == nil) str = [NSAttributedString new];
401 if (NS_KEYLOG)
402 TKLog (@"attributedSubstringFromRange request");
403 return str;
404 }
405 /* End <NSTextInput> impl. */
406265 @end
407266
408267
268 @implementation TKContentView
269
270 -(id)init {
271 self = [super init];
272 if (self) {
273 _needsRedisplay = NO;
274 }
275 return self;
276 }
277
278 /*
279 * Implementation of the NSTextInputClient protocol.
280 */
281
282 /* [NSTextInputClient inputText: replacementRange:] is called by
283 * interpretKeyEvents when a composition sequence is complete. It is also
284 * called when we delete over working text. In that case the call is followed
285 * immediately by doCommandBySelector: deleteBackward:
286 */
287 - (void)insertText: (id)aString
288 replacementRange: (NSRange)repRange
289 {
290 int i, len;
291 XEvent xEvent;
292 NSString *str;
293
294 str = ([aString isKindOfClass: [NSAttributedString class]]) ?
295 [aString string] : aString;
296 len = [str length];
297
298 if (NS_KEYLOG) {
299 TKLog(@"insertText '%@'\tlen = %d", aString, len);
300 }
301
302 processingCompose = NO;
303
304 /*
305 * Clear any working text.
306 */
307
308 if (privateWorkingText != nil) {
309 [self deleteWorkingText];
310 }
311
312 /*
313 * Insert the string as a sequence of keystrokes.
314 */
315
316 setupXEvent(&xEvent, [self window], 0);
317 xEvent.xany.type = KeyPress;
318
319 /*
320 * Apple evidently sets location to 0 to signal that an accented letter has
321 * been selected from the accent menu. An unaccented letter has already
322 * been displayed and we need to erase it before displaying the accented
323 * letter.
324 */
325
326 if (repRange.location == 0) {
327 TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
328 Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
329 TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
330 }
331
332 /*
333 * Next we generate an XEvent for each unicode character in our string.
334 *
335 * NSString uses UTF-16 internally, which means that a non-BMP character is
336 * represented by a sequence of two 16-bit "surrogates". In principle we
337 * could record this in the XEvent by setting the keycode to the 32-bit
338 * unicode code point and setting the trans_chars string to the 4-byte
339 * UTF-8 string for the non-BMP character. However, that will not work
340 * when TCL_UTF_MAX is set to 3, as is the case for Tcl 8.6. A workaround
341 * used internally by Tcl 8.6 is to encode each surrogate as a 3-byte
342 * sequence using the UTF-8 algorithm (ignoring the fact that the UTF-8
343 * encoding specification does not allow encoding UTF-16 surrogates).
344 * This gives a 6-byte encoding of the non-BMP character which we write into
345 * the trans_chars field of the XEvent.
346 */
347
348 for (i = 0; i < len; i++) {
349 xEvent.xkey.nbytes = TclUniAtIndex(str, i, xEvent.xkey.trans_chars,
350 &xEvent.xkey.keycode);
351 if (xEvent.xkey.keycode > 0xffff){
352 i++;
353 }
354 xEvent.xany.type = KeyPress;
355 Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
356 }
357 releaseCode = (UInt16) [str characterAtIndex: 0];
358 }
359
360 /*
361 * This required method is allowed to return nil.
362 */
363
364 - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange
365 actualRange:(NSRangePointer)thePointer
366 {
367 return nil;
368 }
369
370 /*
371 * This method is supposed to insert (or replace selected text with) the string
372 * argument. If the argument is an NSString, it should be displayed with a
373 * distinguishing appearance, e.g underlined.
374 */
375
376 - (void)setMarkedText: (id)aString
377 selectedRange: (NSRange)selRange
378 replacementRange: (NSRange)repRange
379 {
380 TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
381 Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
382 NSString *temp;
383 NSString *str;
384
385 str = ([aString isKindOfClass: [NSAttributedString class]]) ?
386 [aString string] : aString;
387
388 if (focusWin) {
389
390 /*
391 * Remember the widget where the composition is happening, in case it
392 * gets defocussed during the composition.
393 */
394
395 composeWin = focusWin;
396 } else {
397 return;
398 }
399 if (NS_KEYLOG) {
400 TKLog(@"setMarkedText '%@' len =%lu range %lu from %lu", str,
401 (unsigned long) [str length], (unsigned long) selRange.length,
402 (unsigned long) selRange.location);
403 }
404
405 if (privateWorkingText != nil) {
406 [self deleteWorkingText];
407 }
408
409 if ([str length] == 0) {
410 return;
411 }
412
413 /*
414 * Use our insertText method to display the marked text.
415 */
416
417 TkSendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
418 temp = [str copy];
419 [self insertText: temp replacementRange:repRange];
420 privateWorkingText = temp;
421 processingCompose = YES;
422 TkSendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
423 }
424
425 - (BOOL)hasMarkedText
426 {
427 return privateWorkingText != nil;
428 }
429
430
431 - (NSRange)markedRange
432 {
433 NSRange rng = privateWorkingText != nil
434 ? NSMakeRange(0, [privateWorkingText length])
435 : NSMakeRange(NSNotFound, 0);
436
437 if (NS_KEYLOG) {
438 TKLog(@"markedRange request");
439 }
440 return rng;
441 }
442
443 - (void)cancelComposingText
444 {
445 if (NS_KEYLOG) {
446 TKLog(@"cancelComposingText");
447 }
448 [self deleteWorkingText];
449 processingCompose = NO;
450 }
451
452 - (void)unmarkText
453 {
454 if (NS_KEYLOG) {
455 TKLog(@"unmarkText");
456 }
457 [self deleteWorkingText];
458 processingCompose = NO;
459 }
460
461
462 /*
463 * Called by the system to get a position for popup character selection windows
464 * such as a Character Palette, or a selection menu for IME.
465 */
466
467 - (NSRect)firstRectForCharacterRange: (NSRange)theRange
468 actualRange: (NSRangePointer)thePointer
469 {
470 NSRect rect;
471 NSPoint pt;
472 pt.x = caret_x;
473 pt.y = caret_y;
474
475 pt = [self convertPoint: pt toView: nil];
476 pt = [[self window] tkConvertPointToScreen: pt];
477 pt.y -= caret_height;
478
479 rect.origin = pt;
480 rect.size.width = 0;
481 rect.size.height = caret_height;
482 return rect;
483 }
484
485 - (NSInteger)conversationIdentifier
486 {
487 return (NSInteger) self;
488 }
489
490 - (void)doCommandBySelector: (SEL)aSelector
491 {
492 if (NS_KEYLOG) {
493 TKLog(@"doCommandBySelector: %@", NSStringFromSelector(aSelector));
494 }
495 processingCompose = NO;
496 if (aSelector == @selector (deleteBackward:)) {
497 TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
498 Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
499 TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
500 }
501 }
502
503 - (NSArray *)validAttributesForMarkedText
504 {
505 static NSArray *arr = nil;
506 if (arr == nil) {
507 arr = [[NSArray alloc] initWithObjects:
508 NSUnderlineStyleAttributeName,
509 NSUnderlineColorAttributeName,
510 nil];
511 [arr retain];
512 }
513 return arr;
514 }
515
516 - (NSRange)selectedRange
517 {
518 if (NS_KEYLOG) {
519 TKLog(@"selectedRange request");
520 }
521 return NSMakeRange(0, 0);
522 }
523
524 - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
525 {
526 if (NS_KEYLOG) {
527 TKLog(@"characterIndexForPoint request");
528 }
529 return NSNotFound;
530 }
531
532 - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
533 {
534 static NSAttributedString *str = nil;
535 if (str == nil) {
536 str = [NSAttributedString new];
537 }
538 if (NS_KEYLOG) {
539 TKLog(@"attributedSubstringFromRange request");
540 }
541 return str;
542 }
543 /* End of NSTextInputClient implementation. */
544
545 @synthesize needsRedisplay = _needsRedisplay;
546 @end
547
548
409549 @implementation TKContentView(TKKeyEvent)
410 /* delete display of composing characters [not in <NSTextInput>] */
550
551 /*
552 * Tell the widget to erase the displayed composing characters. This
553 * is not part of the NSTextInputClient protocol.
554 */
555
411556 - (void)deleteWorkingText
412557 {
413 if (privateWorkingText == nil)
414 return;
415 if (NS_KEYLOG)
416 TKLog(@"deleteWorkingText len = %lu\n",
417 (unsigned long)[privateWorkingText length]);
418 [privateWorkingText release];
419 privateWorkingText = nil;
420 processingCompose = NO;
421
422 //PENDING: delete working text
558 if (privateWorkingText == nil) {
559 return;
560 } else {
561
562 if (NS_KEYLOG) {
563 TKLog(@"deleteWorkingText len = %lu\n",
564 (unsigned long)[privateWorkingText length]);
565 }
566
567 [privateWorkingText release];
568 privateWorkingText = nil;
569 processingCompose = NO;
570 if (composeWin) {
571 TkSendVirtualEvent(composeWin, "TkClearIMEMarkedText", NULL);
572 }
573 }
423574 }
424575 @end
425576
426
427
428 /*
429 * Set up basic fields in xevent for keyboard input.
430 */
577 /*
578 * Set up basic fields in xevent for keyboard input.
579 */
580
431581 static void
432582 setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
433583 {
434584 TkWindow *winPtr = TkMacOSXGetTkWindow(w);
435585 Tk_Window tkwin = (Tk_Window) winPtr;
586
436587 if (!winPtr) {
437588 return;
438589 }
439590
440591 memset(xEvent, 0, sizeof(XEvent));
441592 xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
442 xEvent->xany.send_event = false;
443593 xEvent->xany.display = Tk_Display(tkwin);
444594 xEvent->xany.window = Tk_WindowId(tkwin);
445595
446596 xEvent->xkey.root = XRootWindow(Tk_Display(tkwin), 0);
447 xEvent->xkey.subwindow = None;
448597 xEvent->xkey.time = TkpGetMS();
449598 xEvent->xkey.state = state;
450599 xEvent->xkey.same_screen = true;
451 xEvent->xkey.trans_chars[0] = 0;
452 xEvent->xkey.nbytes = 0;
600 /* No need to initialize other fields implicitly here,
601 * because of the memset() above. */
453602 }
454603
455604 #pragma mark -
480629 Time time)
481630 {
482631 keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);
483 if (keyboardGrabWinPtr && grabWinPtr) {
632 TkWindow *captureWinPtr = (TkWindow *) TkpGetCapture();
633
634 if (keyboardGrabWinPtr && captureWinPtr) {
484635 NSWindow *w = TkMacOSXDrawableWindow(grab_window);
485636 MacDrawable *macWin = (MacDrawable *) grab_window;
486637
487 if (w && macWin->toplevel->winPtr == (TkWindow*) grabWinPtr) {
638 if (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) {
488639 if (modalSession) {
489640 Tcl_Panic("XGrabKeyboard: already grabbed");
490641 }
512663 *----------------------------------------------------------------------
513664 */
514665
515 void
666 int
516667 XUngrabKeyboard(
517668 Display* display,
518669 Time time)
526677 keyboardGrabNSWindow = nil;
527678 }
528679 keyboardGrabWinPtr = NULL;
680 return Success;
529681 }
530682
531683 /*
532684 *----------------------------------------------------------------------
533685 *
534 * TkMacOSXGetCapture --
686 * TkMacOSXGetModalSession --
535687 *
536688 * Results:
537 * Returns the current grab window
689 * Returns the current modal session
538690 *
539691 * Side effects:
540692 * None.
542694 *----------------------------------------------------------------------
543695 */
544696
545 Tk_Window
546 TkMacOSXGetCapture(void)
547 {
548 return grabWinPtr;
549 }
550
551 /*
552 *----------------------------------------------------------------------
553 *
554 * TkMacOSXGetModalSession --
555 *
556 * Results:
557 * Returns the current modal session
558 *
559 * Side effects:
560 * None.
561 *
562 *----------------------------------------------------------------------
563 */
564
565697 MODULE_SCOPE NSModalSession
566698 TkMacOSXGetModalSession(void)
567699 {
568700 return modalSession;
569 }
570
571 /*
572 *----------------------------------------------------------------------
573 *
574 * TkpSetCapture --
575 *
576 * This function captures the mouse so that all future events will be
577 * reported to this window, even if the mouse is outside the window. If
578 * the specified window is NULL, then the mouse is released.
579 *
580 * Results:
581 * None.
582 *
583 * Side effects:
584 * Sets the capture flag and captures the mouse.
585 *
586 *----------------------------------------------------------------------
587 */
588
589 void
590 TkpSetCapture(
591 TkWindow *winPtr) /* Capture window, or NULL. */
592 {
593 while (winPtr && !Tk_IsTopLevel(winPtr)) {
594 winPtr = winPtr->parentPtr;
595 }
596 grabWinPtr = (Tk_Window) winPtr;
597701 }
598702
599703 /*
651755 }
652756 }
653757
654 /* But adjust for fact that NS uses flipped view. */
758 /*
759 * But adjust for fact that NS uses flipped view.
760 */
761
655762 y = Tk_Height(tkwin) - y;
656763
657764 caret_x = x;
662769
663770 static unsigned convert_ns_to_X_keysym[] =
664771 {
665 NSHomeFunctionKey, 0x50,
666 NSLeftArrowFunctionKey, 0x51,
667 NSUpArrowFunctionKey, 0x52,
668 NSRightArrowFunctionKey, 0x53,
669 NSDownArrowFunctionKey, 0x54,
670 NSPageUpFunctionKey, 0x55,
671 NSPageDownFunctionKey, 0x56,
672 NSEndFunctionKey, 0x57,
673 NSBeginFunctionKey, 0x58,
674 NSSelectFunctionKey, 0x60,
675 NSPrintFunctionKey, 0x61,
676 NSExecuteFunctionKey, 0x62,
677 NSInsertFunctionKey, 0x63,
678 NSUndoFunctionKey, 0x65,
679 NSRedoFunctionKey, 0x66,
680 NSMenuFunctionKey, 0x67,
681 NSFindFunctionKey, 0x68,
682 NSHelpFunctionKey, 0x6A,
683 NSBreakFunctionKey, 0x6B,
684
685 NSF1FunctionKey, 0xBE,
686 NSF2FunctionKey, 0xBF,
687 NSF3FunctionKey, 0xC0,
688 NSF4FunctionKey, 0xC1,
689 NSF5FunctionKey, 0xC2,
690 NSF6FunctionKey, 0xC3,
691 NSF7FunctionKey, 0xC4,
692 NSF8FunctionKey, 0xC5,
693 NSF9FunctionKey, 0xC6,
694 NSF10FunctionKey, 0xC7,
695 NSF11FunctionKey, 0xC8,
696 NSF12FunctionKey, 0xC9,
697 NSF13FunctionKey, 0xCA,
698 NSF14FunctionKey, 0xCB,
699 NSF15FunctionKey, 0xCC,
700 NSF16FunctionKey, 0xCD,
701 NSF17FunctionKey, 0xCE,
702 NSF18FunctionKey, 0xCF,
703 NSF19FunctionKey, 0xD0,
704 NSF20FunctionKey, 0xD1,
705 NSF21FunctionKey, 0xD2,
706 NSF22FunctionKey, 0xD3,
707 NSF23FunctionKey, 0xD4,
708 NSF24FunctionKey, 0xD5,
709
710 NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
711 NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
712 NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
713
714 NSTabCharacter, 0x09,
715 0x19, 0x09, /* left tab->regular since pass shift */
716 NSCarriageReturnCharacter, 0x0D,
717 NSNewlineCharacter, 0x0D,
718 NSEnterCharacter, 0x8D,
719
720 0x1B, 0x1B /* escape */
772 NSHomeFunctionKey, 0x50,
773 NSLeftArrowFunctionKey, 0x51,
774 NSUpArrowFunctionKey, 0x52,
775 NSRightArrowFunctionKey, 0x53,
776 NSDownArrowFunctionKey, 0x54,
777 NSPageUpFunctionKey, 0x55,
778 NSPageDownFunctionKey, 0x56,
779 NSEndFunctionKey, 0x57,
780 NSBeginFunctionKey, 0x58,
781 NSSelectFunctionKey, 0x60,
782 NSPrintFunctionKey, 0x61,
783 NSExecuteFunctionKey, 0x62,
784 NSInsertFunctionKey, 0x63,
785 NSUndoFunctionKey, 0x65,
786 NSRedoFunctionKey, 0x66,
787 NSMenuFunctionKey, 0x67,
788 NSFindFunctionKey, 0x68,
789 NSHelpFunctionKey, 0x6A,
790 NSBreakFunctionKey, 0x6B,
791
792 NSF1FunctionKey, 0xBE,
793 NSF2FunctionKey, 0xBF,
794 NSF3FunctionKey, 0xC0,
795 NSF4FunctionKey, 0xC1,
796 NSF5FunctionKey, 0xC2,
797 NSF6FunctionKey, 0xC3,
798 NSF7FunctionKey, 0xC4,
799 NSF8FunctionKey, 0xC5,
800 NSF9FunctionKey, 0xC6,
801 NSF10FunctionKey, 0xC7,
802 NSF11FunctionKey, 0xC8,
803 NSF12FunctionKey, 0xC9,
804 NSF13FunctionKey, 0xCA,
805 NSF14FunctionKey, 0xCB,
806 NSF15FunctionKey, 0xCC,
807 NSF16FunctionKey, 0xCD,
808 NSF17FunctionKey, 0xCE,
809 NSF18FunctionKey, 0xCF,
810 NSF19FunctionKey, 0xD0,
811 NSF20FunctionKey, 0xD1,
812 NSF21FunctionKey, 0xD2,
813 NSF22FunctionKey, 0xD3,
814 NSF23FunctionKey, 0xD4,
815 NSF24FunctionKey, 0xD5,
816
817 NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
818 NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
819 NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
820
821 NSTabCharacter, 0x09,
822 0x19, 0x09, /* left tab->regular since pass shift */
823 NSCarriageReturnCharacter, 0x0D,
824 NSNewlineCharacter, 0x0D,
825 NSEnterCharacter, 0x8D,
826
827 0x1B, 0x1B /* escape */
721828 };
722829
723830
724 static unsigned isFunctionKey(unsigned code)
725 {
726 const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym)
727 / sizeof (convert_ns_to_X_keysym[0]));
728 unsigned keysym;
729 for (keysym = 0; keysym < last_keysym; keysym += 2)
730 if (code == convert_ns_to_X_keysym[keysym])
731 return 0xFF00 | convert_ns_to_X_keysym[keysym+1];
732 return 0;
733 }
831 static unsigned
832 isFunctionKey(
833 unsigned code)
834 {
835 const unsigned last_keysym = (sizeof(convert_ns_to_X_keysym)
836 / sizeof(convert_ns_to_X_keysym[0]));
837 unsigned keysym;
838
839 for (keysym = 0; keysym < last_keysym; keysym += 2) {
840 if (code == convert_ns_to_X_keysym[keysym]) {
841 return 0xFF00 | convert_ns_to_X_keysym[keysym + 1];
842 }
843 }
844 return 0;
845 }
734846
735847 /*
736848 * Local Variables:
179179 for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
180180 hPtr = Tcl_CreateHashEntry(&keycodeTable, INT2PTR(kPtr->keycode),
181181 &dummy);
182 Tcl_SetHashValue(hPtr, kPtr->keysym);
182 Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));
183183 }
184184 Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
185185 for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
186186 hPtr = Tcl_CreateHashEntry(&vkeyTable, INT2PTR(kPtr->keycode),
187187 &dummy);
188 Tcl_SetHashValue(hPtr, kPtr->keysym);
188 Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));
189189 }
190190 initialized = 1;
191191 }
442442 * result. */
443443 {
444444 (void) winPtr; /*unused*/
445 int ch;
446
445447 Tcl_DStringInit(dsPtr);
446 return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
448 return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars,
449 TkUtfToUniChar(eventPtr->xkey.trans_chars, &ch));
447450 }
448451
449452 /*
716719 }
717720
718721 if (keysym <= LATIN1_MAX) {
719 int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars);
722 int done = TkUniCharToUtf(keysym, eventPtr->xkey.trans_chars);
720723
721724 eventPtr->xkey.trans_chars[done] = 0;
722725 } else {
802805 /* If nbytes has been set, it's not a function key, but a regular key that
803806 has been translated in tkMacOSXKeyEvent.c; just use that. */
804807 if (eventPtr->xkey.nbytes) {
805 return eventPtr->xkey.keycode & 0xFFFF;
808 return eventPtr->xkey.keycode;
806809 }
807810
808811 /*
109109
110110 #pragma mark TKMenu
111111
112 /*
113 * This interface is not declared in tkMacOSXPrivate.h because it requires
114 * tkMenu.h.
115 */
116
112117 @interface TKMenu(TKMenuPrivate)
113118 - (id) initWithTkMenu: (TkMenu *) tkMenu;
114119 - (TkMenu *) tkMenu;
115120 - (int) tkIndexOfItem: (NSMenuItem *) menuItem;
116121 - (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index;
117 @end
118
119 #define TKMenu_NSMenuDelegate <NSMenuDelegate>
120 @interface TKMenu(TKMenuDelegate) TKMenu_NSMenuDelegate
121122 @end
122123
123124 @implementation TKMenu
191192 - (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index
192193 {
193194 if (_tkMenu && index >= 0) {
194 if ((NSUInteger)index <= _tkOffset) {
195 if ((NSUInteger) index <= _tkOffset) {
195196 _tkOffset++;
196197 } else {
197 NSAssert((NSUInteger)index >= _tkItemCount + _tkOffset,
198 NSAssert((NSUInteger) index >= _tkItemCount + _tkOffset,
198199 @"Cannot insert in the middle of Tk menu");
199200 }
200201 }
204205 - (void) removeItemAtIndex: (NSInteger) index
205206 {
206207 if (_tkMenu && index >= 0) {
207 if ((NSUInteger)index < _tkOffset) {
208 if ((NSUInteger) index < _tkOffset) {
208209 _tkOffset--;
209 } else if ((NSUInteger)index < _tkItemCount + _tkOffset) {
210 } else if ((NSUInteger) index < _tkItemCount + _tkOffset) {
210211 _tkItemCount--;
211212 }
212213 }
219220 action:@selector(tkMenuItemInvoke:) keyEquivalent:@""];
220221
221222 [menuItem setTarget:self];
222 [menuItem setTag:(NSInteger)mePtr];
223 [menuItem setTag:(NSInteger) mePtr];
223224 return menuItem;
224225 }
225226 @end
226227
227228 @implementation TKMenu(TKMenuActions)
228 // target methods
229229
230230 - (BOOL) validateMenuItem: (NSMenuItem *) menuItem
231231 {
232232 return [menuItem isEnabled];
233233 }
234234
235 // Workaround for bug 3572016; leaves menu items enabled during modal dialog.
235 /*
236 * Workaround for bug 3572016; leave menu items enabled during modal dialog.
237 */
238
236239 - (BOOL)worksWhenModal
237240 {
238241 return YES;
242245 {
243246 /*
244247 * With the delegate matching key equivalents, when a menu action is sent
245 * in response to a key equivalent, sender is the whole menu and not the
246 * the specific menu item, use this to ignore key equivalents for our
248 * in response to a key equivalent, the sender is the whole menu and not the
249 * specific menu item. We use this to ignore key equivalents for Tk
247250 * menus (as Tk handles them directly via bindings).
248251 */
249252
250253 if ([sender isKindOfClass:[NSMenuItem class]]) {
251 NSMenuItem *menuItem = (NSMenuItem *)sender;
252 TkMenu *menuPtr = (TkMenu *)_tkMenu;
253 TkMenuEntry *mePtr = (TkMenuEntry *)[menuItem tag];
254 NSMenuItem *menuItem = (NSMenuItem *) sender;
255 TkMenu *menuPtr = (TkMenu *) _tkMenu;
256 TkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag];
254257
255258 if (menuPtr && mePtr) {
256259 Tcl_Interp *interp = menuPtr->interp;
257 /*Add time for errors to fire if necessary. This is sub-optimal
258 *but avoids issues with Tcl/Cocoa event loop integration.
260
261 /*
262 * Add time for errors to fire if necessary. This is sub-optimal
263 * but avoids issues with Tcl/Cocoa event loop integration.
259264 */
260 Tcl_Sleep(100);
265
266 //Tcl_Sleep(100);
261267 Tcl_Preserve(interp);
262268 Tcl_Preserve(menuPtr);
263269
276282 @end
277283
278284 @implementation TKMenu(TKMenuDelegate)
279 #define keyEquivModifiersMatch(km, m) (( \
280 ((km) & NSCommandKeyMask) != ((m) & NSCommandKeyMask) || \
281 ((km) & NSAlternateKeyMask) != ((m) & NSAlternateKeyMask) || \
282 ((km) & NSControlKeyMask) != ((m) & NSControlKeyMask) || \
283 (((km) & NSShiftKeyMask) != ((m) & NSShiftKeyMask) && \
284 ((m) & NSFunctionKeyMask))) ? NO : YES)
285285
286286 - (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event
287287 target: (id *) target action: (SEL *) action
288288 {
289 /*Use lowercaseString to keep "shift" from firing twice if bound to different procedure.*/
289 /*
290 * Use lowercaseString when comparing keyEquivalents since the notion of
291 * a shifted upper case letter does not make much sense.
292 */
293
290294 NSString *key = [[event charactersIgnoringModifiers] lowercaseString];
291295 NSUInteger modifiers = [event modifierFlags] &
292296 NSDeviceIndependentModifierFlagsMask;
293297
294298 if (modifiers == (NSCommandKeyMask | NSShiftKeyMask) &&
295299 [key compare:@"?"] == NSOrderedSame) {
300 /*
301 * Command-Shift-? has not been allowed as a keyboard equivalent since
302 * the first aqua port, for some mysterious reason.
303 */
304
296305 return NO;
297 }
298
299 // For command key, take input manager's word so things
300 // like dvorak / qwerty layout work.
301 if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
302 key = [event characters];
306 } else if (modifiers == (NSControlKeyMask | NSShiftKeyMask) &&
307 [event keyCode] == 48) {
308 /*
309 * Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used
310 * to select window tabs. But for some even more mysterious reason the
311 * Control-Shift-Tab event has character 0x19 = NSBackTabCharacter
312 * rather than 0x09 = NSTabCharacter. At the same time, the
313 * keyEquivalent must be \0x09 in order for it to be displayed
314 * correctly in the menu. This makes it impossible for the standard
315 * "Select Previous Tab" to work correctly, unless we intervene.
316 */
317
318 key = @"\t";
319 } else if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
320 /*
321 * If the command modifier is set, use the full character string so
322 * things like the dvorak / qwerty layout will work.
323 */
324
325 key = [event characters];
303326 }
304327
305328 NSArray *itemArray = [self itemArray];
306
307329 for (NSMenuItem *item in itemArray) {
308 if ([item isEnabled] && [[item keyEquivalent] compare:key] ==
309 NSOrderedSame) {
330 if ([item isEnabled] &&
331 [[item keyEquivalent] compare:key] == NSOrderedSame) {
310332 NSUInteger keyEquivModifiers = [item keyEquivalentModifierMask];
311
312 if (keyEquivModifiersMatch(keyEquivModifiers, modifiers)) {
333 if (keyEquivModifiers == modifiers) {
313334 *target = [item target];
314335 *action = [item action];
315336 return YES;
365386 @end
366387
367388 #pragma mark TKApplication(TKMenu)
368
369 @interface NSApplication(TKMenu)
370 - (void) setAppleMenu: (NSMenu *) menu;
371 @end
372389
373390 @implementation TKApplication(TKMenu)
374391
610627 &imageHeight);
611628 image = TkMacOSXGetNSImageWithBitmap(mePtr->menuPtr->display, bitmap,
612629 gc, imageWidth, imageHeight);
630 if (gc->foreground == defaultFg) {
631 // Use a semantic foreground color by default
632 [image setTemplate:YES];
633 }
613634 }
614635 [menuItem setImage:image];
615636 if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr &&
632653 gc->foreground!=defaultFg? gc->foreground:gc->background);
633654
634655 attributes = [[attributes mutableCopy] autorelease];
635 [(NSMutableDictionary *)attributes setObject:color
656 [(NSMutableDictionary *) attributes setObject:color
636657 forKey:NSForegroundColorAttributeName];
637658 }
638659 if (attributes) {
672693 [submenu setTitle:title];
673694
674695 if ([menuItem isEnabled]) {
675 /* This menuItem might have been previously disabled (XXX:
676 track this), which would have disabled entries; we must
677 re-enable the entries here. */
678 int i = 0;
679 NSArray *itemArray = [submenu itemArray];
680 for (NSMenuItem *item in itemArray) {
681 TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
682 /* Work around an apparent bug where itemArray can have
683 more items than the menu's entries[] array. */
684 if (i >= menuRefPtr->menuPtr->numEntries) break;
685 [item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
686 i++;
687 }
696
697 /*
698 * This menuItem might have been previously disabled (XXX:
699 * track this), which would have disabled entries; we must
700 * re-enable the entries here.
701 */
702
703 int i = 0;
704 NSArray *itemArray = [submenu itemArray];
705
706 for (NSMenuItem *item in itemArray) {
707 TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
708
709 /*
710 * Work around an apparent bug where itemArray can have
711 * more items than the menu's entries[] array.
712 */
713
714 if (i >= (int) menuRefPtr->menuPtr->numEntries) {
715 break;
716 }
717 [item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
718 i++;
719 }
688720 }
689
690721 }
691722 }
692723 }
737768 *
738769 * TkpPostMenu --
739770 *
740 * Posts a menu on the screen
741 *
742 * Results:
743 * None.
771 * Posts a menu on the screen. If entry is < 0 then the menu is drawn so
772 * its top left corner is located at the point with screen coordinates
773 * (x,y). Otherwise the top left corner of the specified entry is located
774 * at that point.
775 *
776 * Results:
777 * Returns a standard Tcl result.
744778 *
745779 * Side effects:
746780 * The menu is posted and handled.
752786 TkpPostMenu(
753787 Tcl_Interp *interp, /* The interpreter this menu lives in */
754788 TkMenu *menuPtr, /* The menu we are posting */
755 int x, /* The global x-coordinate of the top, left-
756 * hand corner of where the menu is supposed
757 * to be posted. */
758 int y) /* The global y-coordinate */
759 {
760
761
762 /* Get the object that holds this Tk Window.*/
763 Tk_Window root;
764 root = Tk_MainWindow(interp);
765 if (root == NULL) {
766 return TCL_ERROR;
767 }
768
769 Drawable d = Tk_WindowId(root);
770 NSView *rootview = TkMacOSXGetRootControl(d);
771 NSWindow *win = [rootview window];
789 int x, int y, /* The screen coordinates where the top left
790 * corner of the menu, or of the specified
791 * entry, will be located. */
792 int index)
793 {
772794 int result;
795 Tk_Window realWin = menuPtr->tkwin;
796 TkWindow *realWinPtr;
797 NSView *realWinView;
798
799 while (1) {
800 if (realWin == NULL) {
801 return TCL_ERROR;
802 }
803 /*
804 * Fix for bug 07cfc9f03e: use the view for the parent real (non-menu)
805 * toplevel window, rather than always using the root window.
806 * This allows menus to appear on a separate monitor than the root
807 * window, and to use the appearance of their parent real window
808 * rather than the appearance of the root window.
809 */
810 realWinPtr = (TkWindow*) realWin;
811 realWinView = TkMacOSXDrawableView(realWinPtr->privatePtr);
812 if (realWinView != nil) {
813 break;
814 }
815 realWin = Tk_Parent(realWin);
816 }
817 NSWindow *win = [realWinView window];
818 NSView *view = [win contentView];
819 NSMenu *menu = (NSMenu *) menuPtr->platformData;
820 NSInteger itemIndex = index;
821 NSInteger numItems = [menu numberOfItems];
822 NSMenuItem *item = nil;
823 NSPoint location = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
773824
774825 inPostMenu = 1;
775
776826 result = TkPreprocessMenu(menuPtr);
777827 if (result != TCL_OK) {
778828 inPostMenu = 0;
779829 return result;
780830 }
781
782 int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
783 NSView *view = [win contentView];
784 NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
785
786 frame.origin = [view convertPoint:
787 [win tkConvertPointFromScreen:frame.origin] fromView:nil];
788
789 NSMenu *menu = (NSMenu *) menuPtr->platformData;
790 NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
791 initTextCell:@"" pullsDown:NO];
792
793 [popUpButtonCell setAltersStateOfSelectedItem:NO];
794 [popUpButtonCell setMenu:menu];
795 [popUpButtonCell selectItem:nil];
796 [popUpButtonCell performClickWithFrame:frame inView:view];
797 [popUpButtonCell release];
798 Tcl_SetServiceMode(oldMode);
831 if (itemIndex >= numItems) {
832 itemIndex = numItems - 1;
833 }
834 if (itemIndex >= 0) {
835 item = [menu itemAtIndex:itemIndex];
836 }
837
838 /*
839 * The post commands could have deleted the menu, which means we are dead
840 * and should go away.
841 */
842
843 if (menuPtr->tkwin == NULL) {
844 return TCL_OK;
845 }
846
847 [menu popUpMenuPositioningItem:item
848 atLocation:[win tkConvertPointFromScreen:location]
849 inView:view];
799850 inPostMenu = 0;
851 return TCL_OK;
852 }
853
854 /*
855 *----------------------------------------------------------------------
856 *
857 * TkpPostTearoffMenu --
858 *
859 * Tearoff menus are not supported on the Mac. This placeholder function,
860 * which is simply a copy of the unix function, posts a completely useless
861 * window with a black background on the screen. If entry is < 0 then the
862 * window is positioned so that its top left corner is located at the
863 * point with screen coordinates (x, y). Otherwise the window position is
864 * offset so that top left corner of the specified entry would be located
865 * at that point, if there actually were a menu.
866 *
867 * Mac menus steal all mouse or keyboard input from the application until
868 * the menu is dismissed, with or without a selection, by a mouse or key
869 * event. Posting a Mac menu in a regression test will cause the test to
870 * halt waiting for user input. This is why the TkpPostMenu function is
871 * not being used as the placeholder.
872 *
873 * Results:
874 * None.
875 *
876 * Side effects:
877 * A useless window is posted.
878 *
879 *----------------------------------------------------------------------
880 */
881
882 int
883 TkpPostTearoffMenu(
884 Tcl_Interp *interp, /* The interpreter this menu lives in */
885 TkMenu *menuPtr, /* The menu we are posting */
886 int x, int y, int index) /* The screen coordinates where the top left
887 * corner of the menu, or of the specified
888 * entry, will be located. */
889 {
890 int vRootX, vRootY, vRootWidth, vRootHeight;
891 int result;
892
893 if (index >= (int) menuPtr->numEntries) {
894 index = menuPtr->numEntries - 1;
895 }
896 if (index >= 0) {
897 y -= menuPtr->entries[index]->y;
898 }
899
900 TkActivateMenuEntry(menuPtr, -1);
901 TkRecomputeMenu(menuPtr);
902 result = TkPostCommand(menuPtr);
903 if (result != TCL_OK) {
904 return result;
905 }
906
907 /*
908 * The post commands could have deleted the menu, which means we are dead
909 * and should go away.
910 */
911
912 if (menuPtr->tkwin == NULL) {
913 return TCL_OK;
914 }
915
916 /*
917 * Adjust the position of the menu if necessary to keep it visible on the
918 * screen. There are two special tricks to make this work right:
919 *
920 * 1. If a virtual root window manager is being used then the coordinates
921 * are in the virtual root window of menuPtr's parent; since the menu
922 * uses override-redirect mode it will be in the *real* root window for
923 * the screen, so we have to map the coordinates from the virtual root
924 * (if any) to the real root. Can't get the virtual root from the menu
925 * itself (it will never be seen by the wm) so use its parent instead
926 * (it would be better to have an an option that names a window to use
927 * for this...).
928 * 2. The menu may not have been mapped yet, so its current size might be
929 * the default 1x1. To compute how much space it needs, use its
930 * requested size, not its actual size.
931 */
932
933 Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
934 &vRootWidth, &vRootHeight);
935 vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
936 if (x > vRootX + vRootWidth) {
937 x = vRootX + vRootWidth;
938 }
939 if (x < vRootX) {
940 x = vRootX;
941 }
942 vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
943 if (y > vRootY + vRootHeight) {
944 y = vRootY + vRootHeight;
945 }
946 if (y < vRootY) {
947 y = vRootY;
948 }
949 Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
950 if (!Tk_IsMapped(menuPtr->tkwin)) {
951 Tk_MapWindow(menuPtr->tkwin);
952 }
953 TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
800954 return TCL_OK;
801955 }
802956
834988 *
835989 * TkpSetMainMenubar --
836990 *
837 * Puts the menu associated with a window into the menubar. Should only
838 * be called when the window is in front.
991 * Puts the menu associated with a window into the menubar. Should only be
992 * called when the window is in front.
839993 *
840994 * This is a no-op on all other platforms. On OS X it is a no-op when
841 * passed a NULL menuName or a nonexistent menuName, with an exception
842 * for the first call in a new interpreter. In that special case, passing a
995 * passed a NULL menuName or a nonexistent menuName, with an exception for
996 * the first call in a new interpreter. In that special case, passing a
843997 * NULL menuName installs the default menu.
844998 *
845999 * Results:
8591013 {
8601014 static Tcl_Interp *currentInterp = NULL;
8611015 TKMenu *menu = nil;
1016 TkWindow *winPtr = (TkWindow *) tkwin;
1017
1018 /*
1019 * We will be called when an embedded window receives an ActivationNotify
1020 * event, but we should not change the menubar in that case.
1021 */
1022
1023 if (Tk_IsEmbedded(winPtr)) {
1024 return;
1025 }
8621026
8631027 if (menuName) {
864 TkWindow *winPtr = (TkWindow *) tkwin;
865
866 if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr &&
867 winPtr->wmInfoPtr->menuPtr->masterMenuPtr &&
868 winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin &&
869 !strcmp(menuName, Tk_PathName(
870 winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin))) {
1028 Tk_Window menubar = NULL;
1029
1030 if (winPtr->wmInfoPtr &&
1031 winPtr->wmInfoPtr->menuPtr &&
1032 winPtr->wmInfoPtr->menuPtr->masterMenuPtr) {
1033 menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin;
1034 }
1035
1036 /*
1037 * Attempt to find the NSMenu directly. If that fails, ask Tk to find
1038 * it.
1039 */
1040
1041 if (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) {
8711042 menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;
8721043 } else {
8731044 TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp,
8791050 }
8801051 }
8811052 }
1053
1054 /*
1055 * If we couldn't find a menu, do nothing unless the window belongs to a
1056 * different application. In that case, install the default menubar.
1057 */
1058
8821059 if (menu || interp != currentInterp) {
8831060 [NSApp tkSetMainMenu:menu];
8841061 }
8911068 * CheckForSpecialMenu --
8921069 *
8931070 * Given a menu, check to see whether or not it is a cascade in a menubar
894 * with one of the special names .apple, .help or .window If it is, the
895 * entry that points to this menu will be marked.
1071 * with one of the special names ".apple", ".help" or ".window". If it is,
1072 * the entry that points to this menu will be marked.
8961073 *
8971074 * Results:
8981075 * None.
10691246 TkpComputeStandardMenuGeometry(
10701247 TkMenu *menuPtr) /* Structure describing menu. */
10711248 {
1249 NSSize menuSize;
10721250 Tk_Font tkfont, menuFont;
10731251 Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
10741252 int modifierCharWidth, menuModifierCharWidth;
10751253 int x, y, modifierWidth, labelWidth, indicatorSpace;
10761254 int windowWidth, windowHeight, accelWidth;
1077 int i, j, lastColumnBreak, maxWidth;
1255 int i, maxWidth;
10781256 int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
1079 TkMenuEntry *mePtr, *columnEntryPtr;
1257 TkMenuEntry *mePtr;
10801258 int haveAccel = 0;
10811259
1082 if (menuPtr->tkwin == NULL) {
1260 /*
1261 * Do nothing if this menu is a clone.
1262 */
1263
1264 if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) {
10831265 return;
10841266 }
10851267
1268 menuSize = [(NSMenu *) menuPtr->platformData size];
10861269 Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
10871270 &borderWidth);
10881271 Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
10891272 &activeBorderWidth);
10901273 x = y = borderWidth;
1091 windowHeight = maxWidth = lastColumnBreak = 0;
1274 windowHeight = maxWidth = 0;
10921275 maxIndicatorSpace = 0;
10931276
10941277 /*
10961279 * want to do it intelligently. We are going to precalculate them and pass
10971280 * them down to all of the measuring and drawing routines. We will measure
10981281 * the font metrics of the menu once. If an entry does not have its own
1099 * font set, then we give the geometry/drawing routines the menu's font
1100 * and metrics. If an entry has its own font, we will measure that font
1101 * and give all of the geometry/drawing the entry's font and metrics.
1282 * font set, then we give the geometry/drawing routines the menu's font and
1283 * metrics. If an entry has its own font, we will measure that font and
1284 * give all of the geometry/drawing the entry's font and metrics.
11021285 */
11031286
11041287 menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
11051288 Tk_GetFontMetrics(menuFont, &menuMetrics);
11061289 menuModifierCharWidth = ModifierCharWidth(menuFont);
11071290
1108 for (i = 0; i < menuPtr->numEntries; i++) {
1291 for (i = 0; i < (int) menuPtr->numEntries; i++) {
11091292 mePtr = menuPtr->entries[i];
11101293 if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) {
11111294 haveAccel = 1;
11131296 }
11141297 }
11151298
1116 for (i = 0; i < menuPtr->numEntries; i++) {
1299 for (i = 0; i < (int) menuPtr->numEntries; i++) {
11171300 mePtr = menuPtr->entries[i];
1301 if (mePtr->type == TEAROFF_ENTRY) {
1302 continue;
1303 }
11181304 if (mePtr->fontPtr == NULL) {
11191305 tkfont = menuFont;
11201306 fmPtr = &menuMetrics;
11251311 fmPtr = &entryMetrics;
11261312 modifierCharWidth = ModifierCharWidth(tkfont);
11271313 }
1128
1129 if ((i > 0) && mePtr->columnBreak) {
1130 if (maxIndicatorSpace != 0) {
1131 maxIndicatorSpace += 2;
1132 }
1133 for (j = lastColumnBreak; j < i; j++) {
1134 columnEntryPtr = menuPtr->entries[j];
1135 columnEntryPtr->indicatorSpace = maxIndicatorSpace;
1136 columnEntryPtr->width = maxIndicatorSpace + maxWidth
1137 + 2 * activeBorderWidth;
1138 columnEntryPtr->x = x;
1139 columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
1140 }
1141 x += maxIndicatorSpace + maxWidth + 2 * activeBorderWidth;
1142 maxWidth = maxIndicatorSpace = 0;
1143 lastColumnBreak = i;
1144 y = borderWidth;
1145 }
11461314 accelWidth = modifierWidth = indicatorSpace = 0;
1147 if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {
1315 if (mePtr->type == SEPARATOR_ENTRY) {
11481316 mePtr->height = menuSeparatorHeight;
11491317 } else {
11501318 /*
11621330 if (mePtr->image) {
11631331 Tk_SizeOfImage(mePtr->image, &width, &height);
11641332 haveImage = 1;
1333 height += 2; /* tweak */
11651334 } else if (mePtr->bitmapPtr) {
11661335 Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,
11671336 mePtr->bitmapPtr);
11681337
11691338 Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
11701339 haveImage = 1;
1340 height += 2; /* tweak */
11711341 }
11721342 if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
11731343 NSAttributedString *attrTitle = [menuItem attributedTitle];
11791349 size = [[menuItem title] sizeWithAttributes:
11801350 TkMacOSXNSFontAttributesForFont(tkfont)];
11811351 }
1182 size.width += menuTextLeadingEdgeMargin +
1183 menuTextTrailingEdgeMargin;
1184 if (size.height < fmPtr->linespace) {
1185 size.height = fmPtr->linespace;
1186 }
1352 size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
1353 size.height -= 1; /* tweak */
11871354 if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
11881355 int margin = width + menuIconTrailingEdgeMargin;
11891356
11991366 height = size.height;
12001367 }
12011368 }
1369 else {
1370 /* image only. */
1371 }
12021372 labelWidth = width + menuItemExtraWidth;
12031373 mePtr->height = height + menuItemExtraHeight;
1204
12051374 if (mePtr->type == CASCADE_ENTRY) {
12061375 modifierWidth = modifierCharWidth;
12071376 } else if (mePtr->accelLength == 0) {
12321401 if (entryWidth > maxWidth) {
12331402 maxWidth = entryWidth;
12341403 }
1404 menuPtr->entries[i]->width = entryWidth;
12351405 mePtr->height += 2 * activeBorderWidth;
12361406 }
1407 mePtr->x = x;
12371408 mePtr->y = y;
12381409 y += menuPtr->entries[i]->height + borderWidth;
1239 if (y > windowHeight) {
1240 windowHeight = y;
1241 }
1242 }
1243
1244 for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
1245 columnEntryPtr = menuPtr->entries[j];
1246 columnEntryPtr->indicatorSpace = maxIndicatorSpace;
1247 columnEntryPtr->width = maxIndicatorSpace + maxWidth
1248 + 2 * activeBorderWidth;
1249 columnEntryPtr->x = x;
1250 columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
1251 }
1252 windowWidth = x + maxIndicatorSpace + maxWidth
1253 + 2 * activeBorderWidth + borderWidth;
1254 windowHeight += borderWidth;
1255
1410 }
1411 windowWidth = menuSize.width;
12561412 if (windowWidth <= 0) {
12571413 windowWidth = 1;
12581414 }
1415 windowHeight = menuSize.height;
12591416 if (windowHeight <= 0) {
12601417 windowHeight = 1;
12611418 }
12891446 if (menuPtr) {
12901447 int index = [menu tkIndexOfItem:menuItem];
12911448
1292 if (index < 0 || index >= menuPtr->numEntries ||
1449 if (index < 0 || index >= (int) menuPtr->numEntries ||
12931450 (menuPtr->entries[index])->state == ENTRY_DISABLED) {
12941451 TkActivateMenuEntry(menuPtr, -1);
12951452 } else {
13681525 int i;
13691526
13701527 TkActivateMenuEntry(menuPtr, -1);
1371 for (i = 0; i < menuPtr->numEntries; i++) {
1528 for (i = 0; i < (int) menuPtr->numEntries; i++) {
13721529 TkMenuEntry *mePtr = menuPtr->entries[i];
13731530
13741531 if (mePtr->type == CASCADE_ENTRY
14031560 if (mainMenu && [mainMenu isKindOfClass:[TKMenu class]]) {
14041561 TkMenu *menuPtr = [(TKMenu *) mainMenu tkMenu];
14051562
1406 if (menuPtr && menuPtr->numEntries && menuPtr->entries) {
1563 if (menuPtr &&
1564 !(menuPtr->menuFlags & MENU_DELETION_PENDING) &&
1565 menuPtr->numEntries > 0 &&
1566 menuPtr->entries != NULL) {
14071567 RecursivelyClearActiveMenu(menuPtr);
14081568 }
14091569 }
14631623 #undef observe
14641624
14651625 [NSMenuItem setUsesUserKeyEquivalents:NO];
1466 tkColPtr = TkpGetColor(None, DEF_MENU_BG_COLOR);
1626 tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
14671627 defaultBg = tkColPtr->color.pixel;
14681628 ckfree(tkColPtr);
1469 tkColPtr = TkpGetColor(None, DEF_MENU_FG);
1629 tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
14701630 defaultFg = tkColPtr->color.pixel;
14711631 ckfree(tkColPtr);
14721632
16571817 * TkMacOSXUseID --
16581818 *
16591819 * Take the ID out of the available list for new menus. Used by the
1660 * default menu bar's menus so that they do not get created at the tk
1820 * default menu bar's menus so that they do not get created at the Tk
16611821 * level. See TkMacOSXGetNewMenuID for more information.
16621822 *
16631823 * Results:
16821842 *
16831843 * TkMacOSXDispatchMenuEvent --
16841844 *
1685 * Given a menu id and an item, dispatches the command associated with
1686 * it.
1845 * Given a menu id and an item, dispatches the command associated with it.
16871846 *
16881847 * Results:
16891848 * None.
17331892 *
17341893 * TkMacOSXSetHelpMenuItemCount --
17351894 *
1736 * Has to be called after the first call to InsertMenu. Sets up the
1737 * global variable for the number of items in the unmodified help menu.
1738 * NB. Nobody uses this any more, since you can get the number of system
1895 * Has to be called after the first call to InsertMenu. Sets up the global
1896 * variable for the number of items in the unmodified help menu.
1897 *
1898 * NB: Nobody uses this any more, since you can get the number of system
17391899 * help items from HMGetHelpMenu trivially. But it is in the stubs
17401900 * table...
17411901 *
00 /*
11 * tkMacOSXMenubutton.c --
22 *
3 * This file implements the Macintosh specific portion of the
4 * menubutton widget.
3 * This file implements the Macintosh specific portion of the menubutton
4 * widget.
55 *
66 * Copyright (c) 1996 by Sun Microsystems, Inc.
77 * Copyright 2001, Apple Computer, Inc.
3030 GC gc;
3131 int hasImageOrBitmap;
3232 } DrawParams;
33
3433
3534 /*
3635 * Declaration of Mac specific button structure.
4645 } MacMenuButton;
4746
4847 /*
49 * Forward declarations for procedures defined later in this file:
50 */
51
52 static void MenuButtonEventProc(ClientData clientData, XEvent *eventPtr);
53 static void MenuButtonBackgroundDrawCB ( MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
54 static void MenuButtonContentDrawCB ( ThemeButtonKind kind, const HIThemeButtonDrawInfo * info, MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
55 static void MenuButtonEventProc ( ClientData clientData, XEvent *eventPtr);
56 static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo* drawinfo);
57 static int TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr, DrawParams * dpPtr);
58 static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr,
59 GC gc, Pixmap pixmap);
60 static void DrawMenuButtonImageAndText(TkMenuButton* butPtr);
48 * Forward declarations for static functions defined later in this file:
49 */
50
51 static void MenuButtonEventProc(ClientData clientData,
52 XEvent *eventPtr);
53 static void MenuButtonBackgroundDrawCB(MacMenuButton *ptr,
54 SInt16 depth, Boolean isColorDev);
55 static void MenuButtonContentDrawCB(ThemeButtonKind kind,
56 const HIThemeButtonDrawInfo *info,
57 MacMenuButton *ptr, SInt16 depth,
58 Boolean isColorDev);
59 static void MenuButtonEventProc(ClientData clientData,
60 XEvent *eventPtr);
61 static void TkMacOSXComputeMenuButtonParams(TkMenuButton *butPtr,
62 ThemeButtonKind *btnkind,
63 HIThemeButtonDrawInfo *drawinfo);
64 static void TkMacOSXComputeMenuButtonDrawParams(
65 TkMenuButton *butPtr, DrawParams *dpPtr);
66 static void TkMacOSXDrawMenuButton(MacMenuButton *butPtr, GC gc,
67 Pixmap pixmap);
68 static void DrawMenuButtonImageAndText(TkMenuButton *butPtr);
6169
6270 /*
6371 * The structure below defines menubutton class behavior by means of
6977 TkMenuButtonWorldChanged, /* worldChangedProc */
7078 };
7179
72
73 /*
74 *----------------------------------------------------------------------
75 *
76 * TkpCreateMenuButton --
80 /*
81 * We use Apple's Pop-Up Button widget to represent the Tk Menubutton.
82 * However, we do not use the NSPopUpButton class for this control. Instead we
83 * render the Pop-Up Button using the HITheme library. This imposes some
84 * constraints on what can be done. The HITheme renderer allows only specific
85 * dimensions for the button.
86 *
87 * The HITheme library allows drawing a Pop-Up Button with an arbitrary bounds
88 * rectangle. However the button is always drawn as a rounded box which is 22
89 * pixels high. If the bounds rectangle is less than 22 pixels high, the
90 * button is drawn at the top of the rectangle and the bottom of the button is
91 * clipped away. So we set a minimum height of 22 pixels for a Menubutton. If
92 * the bounds rectangle is more than 22 pixels high, then the button is drawn
93 * centered vertically in the bounds rectangle.
94 *
95 * The content rectangle of the button is inset by 14 pixels on the left and 28
96 * pixels on the right. The rightmost part of the button contains the blue
97 * double-arrow symbol which is 28 pixels wide.
98 *
99 * To maintain compatibility with code that runs on multiple operating systems,
100 * the width and height of the content rectangle includes the borderWidth, the
101 * highlightWidth and the padX and padY dimensions of the Menubutton. However,
102 * to be consistent with the standard Apple appearance, the content is always
103 * be drawn at the left side of the content rectangle. All of the excess space
104 * appears on the right side of the content, and the anchor property is
105 * ignored. The easiest way to comply with Apple's Human Interface Guidelines
106 * would be to set bd = highlightthickness = padx = 0 and to specify an
107 * explicit width for the button. Apple also recommends using the same width
108 * for all Pop-Up Buttons in a given window.
109 */
110
111 #define LEFT_INSET 8
112 #define RIGHT_INSET 28
113 #define MIN_HEIGHT 22
114
115 /*
116 *----------------------------------------------------------------------
117 *
118 * TkpCreateMenuButton --
77119 *
78120 * Allocate a new TkMenuButton structure.
79121 *
92134 {
93135 MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));
94136
95 Tk_CreateEventHandler(tkwin, ActivateMask,
96 MenuButtonEventProc, (ClientData) mbPtr);
137 Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr);
97138 mbPtr->flags = FIRST_DRAW;
98139 mbPtr->btnkind = kThemePopupButton;
99140 bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo));
100141 bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo));
101
102142 return (TkMenuButton *) mbPtr;
103143 }
104144
113153 * None.
114154 *
115155 * Side effects:
116 * Commands are output to X to display the menubutton in its
117 * current mode.
156 * Commands are output to X to display the menubutton in its current mode.
118157 *
119158 *----------------------------------------------------------------------
120159 */
123162 TkpDisplayMenuButton(
124163 ClientData clientData) /* Information about widget. */
125164 {
126 MacMenuButton *mbPtr = (MacMenuButton *)clientData;
127 TkMenuButton *butPtr = (TkMenuButton *) clientData;
128 Tk_Window tkwin = butPtr->tkwin;
165 MacMenuButton *mbPtr = clientData;
166 TkMenuButton *butPtr = clientData;
167 Tk_Window tkwin = butPtr->tkwin;
129168 Pixmap pixmap;
130 DrawParams* dpPtr = &mbPtr->drawParams;
169 DrawParams *dpPtr = &mbPtr->drawParams;
131170
132171 butPtr->flags &= ~REDRAW_PENDING;
133172 if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
139178 TkMacOSXComputeMenuButtonDrawParams(butPtr, dpPtr);
140179
141180 /*
142 * set up clipping region. Make sure the we are using the port
143 * for this button, or we will set the wrong window's clip.
181 * Set up clipping region. Make sure the we are using the port for this
182 * button, or we will set the wrong window's clip.
144183 */
145184
146185 TkMacOSXSetUpClippingRgn(pixmap);
147186
148 /* Draw the native portion of the buttons. */
187 /*
188 * Draw the native portion of the buttons.
189 */
190
149191 TkMacOSXDrawMenuButton(mbPtr, dpPtr->gc, pixmap);
150192
151 /* Draw highlight border, if needed. */
193 /*
194 * Draw highlight border, if needed.
195 */
196
152197 if (butPtr->highlightWidth < 3) {
153 if ((butPtr->flags & GOT_FOCUS)) {
154 Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,
155 Tk_Width(tkwin), Tk_Height(tkwin),
156 butPtr->highlightWidth, TK_RELIEF_SOLID);
157 }
198 if (butPtr->flags & GOT_FOCUS) {
199 GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
200 TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth);
201 }
158202 }
159203 }
160204
163207 *
164208 * TkpDestroyMenuButton --
165209 *
166 * Free data structures associated with the menubutton control.
210 * Free data structures associated with the menubutton control. This is a
211 * no-op on the Mac.
167212 *
168213 * Results:
169214 * None.
170215 *
171216 * Side effects:
172 * Restores the default control state.
217 * None.
173218 *
174219 *----------------------------------------------------------------------
175220 */
203248 register TkMenuButton *butPtr; /* Widget record for menu button. */
204249 {
205250 int width, height, avgWidth, haveImage = 0, haveText = 0;
206 MacMenuButton *mbPtr = (MacMenuButton*)butPtr;
207251 int txtWidth, txtHeight;
208252 Tk_FontMetrics fm;
209 DrawParams drawParams;
210 int paddingx = 0;
211 int paddingy = 0;
253 int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0;
212254
213255 /*
214 * First figure out the size of the contents of the button.
256 * First compute the size of the contents of the button.
215257 */
216258
217259 width = 0;
219261 txtWidth = 0;
220262 txtHeight = 0;
221263 avgWidth = 0;
222
223 TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
224264
225265 if (butPtr->image != NULL) {
226266 Tk_SizeOfImage(butPtr->image, &width, &height);
230270 haveImage = 1;
231271 }
232272
233 if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {
273 if (butPtr->text && strlen(butPtr->text) > 0) {
274 haveText = 1;
234275 Tk_FreeTextLayout(butPtr->textLayout);
235276 butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
236277 butPtr->text, -1, butPtr->wrapLength,
237278 butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
238
239279 txtWidth = butPtr->textWidth;
240280 txtHeight = butPtr->textHeight;
241281 avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
242282 Tk_GetFontMetrics(butPtr->tkfont, &fm);
243 haveText = (txtWidth != 0 && txtHeight != 0);
244283 }
245284
246285 /*
247 * If the button is compound (ie, it shows both an image and text),
248 * the new geometry is a combination of the image and text geometry.
249 * We only honor the compound bit if the button has both text and an
250 * image, because otherwise it is not really a compound button.
286 * If the button is compound (ie, it shows both an image and text), the new
287 * geometry is a combination of the image and text geometry. We only honor
288 * the compound bit if the button has both text and an image, because
289 * otherwise it is not really a compound button.
251290 */
252291
253 if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
292 if (haveImage && haveText) {
254293 switch ((enum compound) butPtr->compound) {
255 case COMPOUND_TOP:
256 case COMPOUND_BOTTOM: {
257 /*
258 * Image is above or below text
259 */
260
261 height += txtHeight + butPtr->padY;
262 width = (width > txtWidth ? width : txtWidth);
263 break;
264 }
265 case COMPOUND_LEFT:
266 case COMPOUND_RIGHT: {
267 /*
268 * Image is left or right of text
269 */
270
271 width += txtWidth + butPtr->padX;
272 height = (height > txtHeight ? height : txtHeight);
273 break;
274 }
275 case COMPOUND_CENTER: {
276 /*
277 * Image and text are superimposed
278 */
279
280 width = (width > txtWidth ? width : txtWidth);
281 height = (height > txtHeight ? height : txtHeight);
282 break;
283 }
284 case COMPOUND_NONE: {break;}
294 case COMPOUND_TOP:
295 case COMPOUND_BOTTOM:
296 /*
297 * Image is above or below text
298 */
299
300 height += txtHeight + butPtr->padY;
301 width = (width > txtWidth ? width : txtWidth);
302 break;
303 case COMPOUND_LEFT:
304 case COMPOUND_RIGHT:
305 /*
306 * Image is left or right of text
307 */
308
309 width += txtWidth + butPtr->padX;
310 height = (height > txtHeight ? height : txtHeight);
311 break;
312 case COMPOUND_CENTER:
313 /*
314 * Image and text are superimposed
315 */
316
317 width = (width > txtWidth ? width : txtWidth);
318 height = (height > txtHeight ? height : txtHeight);
319 break;
320 case COMPOUND_NONE:
321 break;
285322 }
286323
287324 if (butPtr->width > 0) {
292329 }
293330
294331 } else {
295 if (haveImage) {
332 if (haveImage) { /* Image only */
296333 if (butPtr->width > 0) {
297334 width = butPtr->width;
298335 }
299336 if (butPtr->height > 0) {
300337 height = butPtr->height;
301338 }
302 } else {
339 } else { /* Text only */
303340 width = txtWidth;
304341 height = txtHeight;
305342 if (butPtr->width > 0) {
306 width = butPtr->width * avgWidth;
343 width = butPtr->width * avgWidth + 2*butPtr->padX;
307344 }
308345 if (butPtr->height > 0) {
309 height = butPtr->height * fm.linespace;
346 height = butPtr->height * fm.linespace + 2*butPtr->padY;
310347 }
311348 }
312349 }
313 width += 2 * butPtr->padX - 2;
314 height += 2 * butPtr->padY - 2;
315
316 /*Add padding for button arrows.*/
317 width += 22;
318
319 /*
320 * Now figure out the size of the border decorations for the button.
321 */
322
323 if (butPtr->highlightWidth < 0) {
324 butPtr->highlightWidth = 0;
325 }
326 butPtr->inset = 0;
327 butPtr->inset += butPtr->highlightWidth;
328
329 TkMacOSXComputeMenuButtonDrawParams(butPtr,&drawParams);
330
331 HIRect tmpRect;
332 HIRect contBounds;
333
334 tmpRect = CGRectMake(0, 0, width, height);
335
336 HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
337
338
339
340 /* If the content region has a minimum height, match it. */
341 if (height < contBounds.size.height) {
342 height = contBounds.size.height;
343 }
344
345 /* If the content region has a minimum width, match it. */
346 if (width < contBounds.size.width) {
347 width = contBounds.size.width;
348 }
349
350 /* Pad to fill difference between content bounds and button bounds. */
351 paddingx = tmpRect.origin.x - contBounds.origin.x;
352 paddingy = tmpRect.origin.y - contBounds.origin.y;
353
354 if (paddingx > 0) {
355 width += paddingx;
356 }
357 if (paddingy > 0) {
358 height += paddingy;
359 }
360
361 width += butPtr->inset*2;
362 height += butPtr->inset*2;
363
364
350
351 butPtr->inset = highlightWidth + butPtr->borderWidth;
352 width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset;
353 height += 2*butPtr->inset;
354 height = height < MIN_HEIGHT ? MIN_HEIGHT : height;
365355 Tk_GeometryRequest(butPtr->tkwin, width, height);
366356 Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
367357 }
383373 */
384374 void
385375 DrawMenuButtonImageAndText(
386 TkMenuButton* butPtr)
387 {
388 MacMenuButton *mbPtr = (MacMenuButton*)butPtr;
389 Tk_Window tkwin = butPtr->tkwin;
390 Pixmap pixmap;
391 int haveImage = 0;
392 int haveText = 0;
393 int imageWidth = 0;
394 int imageHeight = 0;
395 int imageXOffset = 0;
396 int imageYOffset = 0;
397 int textXOffset = 0;
398 int textYOffset = 0;
399 int width = 0;
400 int height = 0;
401 int fullWidth = 0;
402 int fullHeight = 0;
403 int pressed;
376 TkMenuButton *butPtr)
377 {
378 MacMenuButton *mbPtr = (MacMenuButton *) butPtr;
379 Tk_Window tkwin = butPtr->tkwin;
380 Pixmap pixmap;
381 int haveImage = 0, haveText = 0;
382 int imageWidth = 0, imageHeight = 0;
383 int imageXOffset = 0, imageYOffset = 0;
384 int textXOffset = 0, textYOffset = 0;
385 int width = 0, height = 0;
386 int fullWidth = 0, fullHeight = 0;
404387
405388 if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
406389 return;
407390 }
408391
409 DrawParams* dpPtr = &mbPtr->drawParams;
410 pixmap = (Pixmap)Tk_WindowId(tkwin);
411
392 DrawParams *dpPtr = &mbPtr->drawParams;
393 pixmap = (Pixmap) Tk_WindowId(tkwin);
412394
413395 if (butPtr->image != None) {
414396 Tk_SizeOfImage(butPtr->image, &width, &height);
418400 haveImage = 1;
419401 }
420402
421 imageWidth = width;
403 imageWidth = width;
422404 imageHeight = height;
423405
424 if (mbPtr->drawinfo.state == kThemeStatePressed) {
425 /* Offset bitmaps by a bit when the button is pressed. */
426 pressed = 1;
427 }
428
429 haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
430 if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
431 int x = 0;
432 int y = 0;
406 haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
407 if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
408 int x = 0, y = 0;
409
433410 textXOffset = 0;
434411 textYOffset = 0;
435412 fullWidth = 0;
436413 fullHeight = 0;
437414
438415 switch ((enum compound) butPtr->compound) {
439 case COMPOUND_TOP:
440 case COMPOUND_BOTTOM: {
441 /* Image is above or below text */
442 if (butPtr->compound == COMPOUND_TOP) {
443 textYOffset = height + butPtr->padY;
444 } else {
445 imageYOffset = butPtr->textHeight + butPtr->padY;
446 }
447 fullHeight = height + butPtr->textHeight + butPtr->padY;
448 fullWidth = (width > butPtr->textWidth ? width :
449 butPtr->textWidth);
450 textXOffset = (fullWidth - butPtr->textWidth)/2;
451 imageXOffset = (fullWidth - width)/2;
452 break;
453 }
454 case COMPOUND_LEFT:
455 case COMPOUND_RIGHT: {
456 /*
457 * Image is left or right of text
458 */
459
460 if (butPtr->compound == COMPOUND_LEFT) {
461 textXOffset = width + butPtr->padX - 2;
462 } else {
463 imageXOffset = butPtr->textWidth + butPtr->padX;
464 }
465 fullWidth = butPtr->textWidth + butPtr->padX + width;
466 fullHeight = (height > butPtr->textHeight ? height :
467 butPtr->textHeight);
468 textYOffset = (fullHeight - butPtr->textHeight)/2;
469 imageYOffset = (fullHeight - height)/2;
470 break;
471 }
472 case COMPOUND_CENTER: {
473 /*
474 * Image and text are superimposed
475 */
476
477 fullWidth = (width > butPtr->textWidth ? width :
478 butPtr->textWidth);
479 fullHeight = (height > butPtr->textHeight ? height :
480 butPtr->textHeight);
481 textXOffset = (fullWidth - butPtr->textWidth)/2;
482 imageXOffset = (fullWidth - width)/2;
483 textYOffset = (fullHeight - butPtr->textHeight)/2;
484 imageYOffset = (fullHeight - height)/2;
485 break;
486 }
487 case COMPOUND_NONE: {break;}
416 case COMPOUND_TOP:
417 case COMPOUND_BOTTOM:
418 /*
419 * Image is above or below text.
420 */
421
422 if (butPtr->compound == COMPOUND_TOP) {
423 textYOffset = height + butPtr->padY;
424 } else {
425 imageYOffset = butPtr->textHeight + butPtr->padY;
426 }
427 fullHeight = height + butPtr->textHeight + butPtr->padY;
428 fullWidth = (width > butPtr->textWidth ?
429 width : butPtr->textWidth);
430 textXOffset = (fullWidth - butPtr->textWidth)/2;
431 imageXOffset = (fullWidth - width)/2;
432 break;
433 case COMPOUND_LEFT:
434 case COMPOUND_RIGHT:
435 /*
436 * Image is left or right of text
437 */
438
439 if (butPtr->compound == COMPOUND_LEFT) {
440 textXOffset = width + butPtr->padX - 2;
441 } else {
442 imageXOffset = butPtr->textWidth + butPtr->padX;
443 }
444 fullWidth = butPtr->textWidth + butPtr->padX + width;
445 fullHeight = (height > butPtr->textHeight ? height :
446 butPtr->textHeight);
447 textYOffset = (fullHeight - butPtr->textHeight)/2;
448 imageYOffset = (fullHeight - height)/2;
449 break;
450 case COMPOUND_CENTER:
451 /*
452 * Image and text are superimposed
453 */
454
455 fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth);
456 fullHeight = (height > butPtr->textHeight ? height :
457 butPtr->textHeight);
458 textXOffset = (fullWidth - butPtr->textWidth) / 2;
459 imageXOffset = (fullWidth - width) / 2;
460 textYOffset = (fullHeight - butPtr->textHeight) / 2;
461 imageYOffset = (fullHeight - height) / 2;
462 break;
463 case COMPOUND_NONE:
464 break;
488465 }
489466
490467 TkComputeAnchor(butPtr->anchor, tkwin,
491 butPtr->padX + butPtr->borderWidth,
492 butPtr->padY + butPtr->borderWidth,
468 butPtr->padX + butPtr->inset, butPtr->padY + butPtr->inset,
493469 fullWidth, fullHeight, &x, &y);
494 imageXOffset += x;
470 imageXOffset = LEFT_INSET;
495471 imageYOffset += y;
496472 textYOffset -= 1;
497473
498474 if (butPtr->image != NULL) {
499 Tk_RedrawImage(butPtr->image, 0, 0, width,
500 height, pixmap, imageXOffset, imageYOffset);
475 Tk_RedrawImage(butPtr->image, 0, 0, width,
476 height, pixmap, imageXOffset, imageYOffset);
501477 } else {
502478 XSetClipOrigin(butPtr->display, dpPtr->gc,
503479 imageXOffset, imageYOffset);
511487 dpPtr->gc, butPtr->textLayout,
512488 x + textXOffset, y + textYOffset, 0, -1);
513489 Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,
514 butPtr->textLayout,
515 x + textXOffset, y + textYOffset,
490 butPtr->textLayout, x + textXOffset, y + textYOffset,
516491 butPtr->underline);
517492 } else {
493 int x, y;
494
518495 if (haveImage) {
519 int x = 0;
520 int y;
521496 TkComputeAnchor(butPtr->anchor, tkwin,
522497 butPtr->padX + butPtr->borderWidth,
523498 butPtr->padY + butPtr->borderWidth,
524499 width, height, &x, &y);
525 imageXOffset += x;
526 imageYOffset += y;
527
528 if (butPtr->image != NULL) {
529 Tk_RedrawImage(butPtr->image, 0, 0, width, height,
530 pixmap, imageXOffset, imageYOffset);
500 imageXOffset = LEFT_INSET;
501 imageYOffset += y;
502 if (butPtr->image != NULL) {
503 Tk_RedrawImage(butPtr->image, 0, 0, width, height,
504 pixmap, imageXOffset, imageYOffset);
531505 } else {
532506 XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
533507 XCopyPlane(butPtr->display, butPtr->bitmap,
534 pixmap, dpPtr->gc,
535 0, 0, (unsigned int) width,
536 (unsigned int) height,
537 imageXOffset, imageYOffset, 1);
508 pixmap, dpPtr->gc,
509 0, 0, (unsigned int) width,
510 (unsigned int) height,
511 imageXOffset, imageYOffset, 1);
538512 XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
539513 }
540514 } else {
541 /*Move x back by eight pixels to give the menubutton arrows room.*/
542 int x = 0;
543 int y;
544 textXOffset = 8;
515 textXOffset = LEFT_INSET;
545516 TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
546 butPtr->textWidth, butPtr->textHeight, &x, &y);
517 butPtr->textWidth, butPtr->textHeight, &x, &y);
547518 Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc,
548 butPtr->textLayout, x - textXOffset, y, 0, -1);
519 butPtr->textLayout, textXOffset, y, 0, -1);
549520 y += butPtr->textHeight/2;
550 }
521 }
551522 }
552523 }
553
554
555
524
556525 /*
557526 *--------------------------------------------------------------
558527 *
559528 * TkMacOSXDrawMenuButton --
560529 *
561 * This function draws the tk menubutton using Mac controls
562 * In addition, this code may apply custom colors passed
563 * in the TkMenubutton.
530 * This function draws the tk menubutton using Mac controls. In
531 * addition, this code may apply custom colors passed in the
532 * TkMenubutton.
564533 *
565534 * Results:
566535 * None.
570539 *
571540 *--------------------------------------------------------------
572541 */
542
573543 static void
574544 TkMacOSXDrawMenuButton(
575545 MacMenuButton *mbPtr, /* Mac menubutton. */
576 GC gc, /* The GC we are drawing into - needed for
577 * the bevel button */
578 Pixmap pixmap) /* The pixmap we are drawing into - needed
579 * for the bevel button */
580
581 {
582 TkMenuButton * butPtr = ( TkMenuButton *)mbPtr;
583 TkWindow * winPtr;
584 HIRect cntrRect;
546 GC gc, /* The GC we are drawing into - needed for the bevel
547 * button */
548 Pixmap pixmap) /* The pixmap we are drawing into - needed for the
549 * bevel button */
550 {
551 TkMenuButton *butPtr = (TkMenuButton *) mbPtr;
552 TkWindow *winPtr = (TkWindow *) butPtr->tkwin;
553 HIRect cntrRect;
585554 TkMacOSXDrawingContext dc;
586 DrawParams* dpPtr = &mbPtr->drawParams;
555 DrawParams *dpPtr = &mbPtr->drawParams;
587556 int useNewerHITools = 1;
588557
589 winPtr = (TkWindow *)butPtr->tkwin;
590
591558 TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
592559
593 cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, Tk_Width(butPtr->tkwin),Tk_Height(butPtr->tkwin));
594
595 cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);
596
560 cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
561 Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));
597562
598563 if (useNewerHITools == 1) {
599564 HIRect contHIRec;
600565 static HIThemeButtonDrawInfo hiinfo;
601566
602 MenuButtonBackgroundDrawCB((MacMenuButton*) mbPtr, 32, true);
603
567 MenuButtonBackgroundDrawCB(mbPtr, 32, true);
604568 if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
605569 return;
606570 }
607571
608
609572 hiinfo.version = 0;
610573 hiinfo.state = mbPtr->drawinfo.state;
611 hiinfo.kind = mbPtr->btnkind;
574 hiinfo.kind = mbPtr->btnkind;
612575 hiinfo.value = mbPtr->drawinfo.value;
613576 hiinfo.adornment = mbPtr->drawinfo.adornment;
614577 hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
616579 hiinfo.animation.time.start = hiinfo.animation.time.current;
617580 }
618581
619 HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec);
620
582 /*
583 * To avoid menubuttons with white text on a white background, we
584 * always set the state to inactive in Dark Mode. It isn't perfect but
585 * it is usable. Using a ttk::menubutton would be a better choice,
586 * however.
587 */
588
589 if (TkMacOSXInDarkMode(butPtr->tkwin)) {
590 hiinfo.state = kThemeStateInactive;
591 }
592
593 HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
594 kHIThemeOrientationNormal, &contHIRec);
621595 TkMacOSXRestoreDrawingContext(&dc);
622
623 MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo, (MacMenuButton *)mbPtr, 32, true);
596 MenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo,
597 mbPtr, 32, true);
624598 } else {
625599 if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
626600 return;
627601 }
628
629
630602 TkMacOSXRestoreDrawingContext(&dc);
631603 }
632604 mbPtr->lastdrawinfo = mbPtr->drawinfo;
637609 *
638610 * MenuButtonBackgroundDrawCB --
639611 *
640 * This function draws the background that
641 * lies under checkboxes and radiobuttons.
642 *
643 * Results:
644 * None.
645 *
646 * Side effects:
647 * The background gets updated to the current color.
612 * This function draws the background that lies under checkboxes and
613 * radiobuttons.
614 *
615 * Results:
616 * None.
617 *
618 * Side effects:
619 * The background gets updated to the current color.
648620 *
649621 *--------------------------------------------------------------
650622 */
623
651624 static void
652625 MenuButtonBackgroundDrawCB (
653626 MacMenuButton *ptr,
654627 SInt16 depth,
655628 Boolean isColorDev)
656629 {
657 TkMenuButton* butPtr = (TkMenuButton*)ptr;
658 Tk_Window tkwin = butPtr->tkwin;
630 TkMenuButton* butPtr = (TkMenuButton *) ptr;
631 Tk_Window tkwin = butPtr->tkwin;
659632 Pixmap pixmap;
633
660634 if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
661635 return;
662636 }
663 pixmap = (Pixmap)Tk_WindowId(tkwin);
664
637 pixmap = (Pixmap) Tk_WindowId(tkwin);
665638 Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,
666 Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
639 Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
667640 }
668641
669642 /*
671644 *
672645 * MenuButtonContentDrawCB --
673646 *
674 * This function draws the label and image for the button.
675 *
676 * Results:
677 * None.
678 *
679 * Side effects:
680 * The content of the button gets updated.
647 * This function draws the label and image for the button.
648 *
649 * Results:
650 * None.
651 *
652 * Side effects:
653 * The content of the button gets updated.
681654 *
682655 *--------------------------------------------------------------
683656 */
657
684658 static void
685659 MenuButtonContentDrawCB (
686660 ThemeButtonKind kind,
689663 SInt16 depth,
690664 Boolean isColorDev)
691665 {
692 TkMenuButton *butPtr = (TkMenuButton *)ptr;
693 Tk_Window tkwin = butPtr->tkwin;
666 TkMenuButton *butPtr = (TkMenuButton *) ptr;
667 Tk_Window tkwin = butPtr->tkwin;
694668
695669 if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
696670 return;
697671 }
698
699 DrawMenuButtonImageAndText( butPtr);
672 DrawMenuButtonImageAndText(butPtr);
700673 }
701674
702675 /*
704677 *
705678 * MenuButtonEventProc --
706679 *
707 * This procedure is invoked by the Tk dispatcher for various
708 * events on buttons.
680 * This procedure is invoked by the Tk dispatcher for various events on
681 * buttons.
709682 *
710683 * Results:
711684 * None.
721694 ClientData clientData, /* Information about window. */
722695 XEvent *eventPtr) /* Information about event. */
723696 {
724 TkMenuButton *buttonPtr = (TkMenuButton *) clientData;
725 MacMenuButton *mbPtr = (MacMenuButton *) clientData;
697 TkMenuButton *buttonPtr = clientData;
698 MacMenuButton *mbPtr = clientData;
726699
727700 if (eventPtr->type == ActivateNotify
728701 || eventPtr->type == DeactivateNotify) {
746719 *
747720 * TkMacOSXComputeMenuButtonParams --
748721 *
749 * This procedure computes the various parameters used
750 * when creating a Carbon Appearance control.
751 * These are determined by the various tk button parameters
722 * This procedure computes the various parameters used when creating a
723 * Carbon Appearance control. These are determined by the various Tk
724 * button parameters
752725 *
753726 * Results:
754727 * None.
760733 */
761734
762735 static void
763 TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo *drawinfo)
764 {
765 MacMenuButton *mbPtr = (MacMenuButton *)butPtr;
766
767 if (butPtr->image || butPtr->bitmap) {
736 TkMacOSXComputeMenuButtonParams(
737 TkMenuButton *butPtr,
738 ThemeButtonKind *btnkind,
739 HIThemeButtonDrawInfo *drawinfo)
740 {
741 MacMenuButton *mbPtr = (MacMenuButton *) butPtr;
742
743 if (butPtr->image || butPtr->bitmap || butPtr->text) {
768744 /* TODO: allow for Small and Mini menubuttons. */
769745 *btnkind = kThemePopupButton;
770 } else {
771 if (!butPtr->text || !*butPtr->text) {
772 *btnkind = kThemeArrowButton;
773 } else {
774 *btnkind = kThemePopupButton;
775 }
746 } else { /* This should never happen. */
747 *btnkind = kThemeArrowButton;
776748 }
777749
778750 drawinfo->value = kThemeButtonOff;
811783 *
812784 * TkMacOSXComputeMenuButtonDrawParams --
813785 *
814 * This procedure computes the various parameters used
815 * when drawing a button
816 * These are determined by the various tk button parameters
817 *
818 * Results:
819 * 1 if control will be used, 0 otherwise.
820 *
821 * Side effects:
822 * Sets the button draw parameters
823 *
824 *----------------------------------------------------------------------
825 */
826
827 static int
828 TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
829 {
830 dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)
831 || (butPtr->bitmap != None));
786 * This procedure selects an appropriate drawing context for drawing a
787 * menubutton.
788 *
789 * Results:
790 * None.
791 *
792 * Side effects:
793 * Sets the button draw parameters.
794 *
795 *----------------------------------------------------------------------
796 */
797
798 static void
799 TkMacOSXComputeMenuButtonDrawParams(
800 TkMenuButton *butPtr,
801 DrawParams *dpPtr)
802 {
803 dpPtr->hasImageOrBitmap =
804 ((butPtr->image != NULL) || (butPtr->bitmap != None));
832805 dpPtr->border = butPtr->normalBorder;
833806 if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
834807 dpPtr->gc = butPtr->disabledGC;
838811 } else {
839812 dpPtr->gc = butPtr->normalTextGC;
840813 }
841
842 return 1;
843 }
844
814 }
815
845816 /*
846817 * Local Variables:
847818 * mode: objc
1616
1717 static void GenerateEditEvent(const char *name);
1818 static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
19
1920
2021 #pragma mark TKApplication(TKMenus)
2122
6869 [NSMenuItem itemWithTitle:
6970 [NSString stringWithFormat:@"About %@", aboutName]
7071 action:@selector(orderFrontStandardAboutPanel:)] atIndex:0];
71
72 TKMenu *fileMenu = [TKMenu menuWithTitle:@"File" menuItems:
73 [NSArray arrayWithObjects:
72 _defaultFileMenuItems =
73 [[NSArray arrayWithObjects:
7474 [NSMenuItem itemWithTitle:
7575 [NSString stringWithFormat:@"Source%C", 0x2026]
7676 action:@selector(tkSource:)],
7878 action:@selector(tkDemo:)],
7979 [NSMenuItem itemWithTitle:@"Close" action:@selector(performClose:)
8080 target:nil keyEquivalent:@"w"],
81 nil]];
81 nil] retain];
82 _demoMenuItem = [_defaultFileMenuItems objectAtIndex:1];
83 TKMenu *fileMenu = [TKMenu menuWithTitle:@"File"
84 menuItems: _defaultFileMenuItems];
8285 TKMenu *editMenu = [TKMenu menuWithTitle:@"Edit" menuItems:
8386 [NSArray arrayWithObjects:
8487 [NSMenuItem itemWithTitle:@"Undo" action:@selector(undo:)
9699 target:nil],
97100 nil]];
98101
99 _defaultWindowsMenuItems = [[NSArray arrayWithObjects:
100 [NSMenuItem itemWithTitle:@"Minimize"
101 action:@selector(performMiniaturize:) target:nil
102 keyEquivalent:@"m"],
103 [NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:)
104 target:nil],
105 [NSMenuItem separatorItem],
102 _defaultWindowsMenuItems = [NSArray arrayWithObjects:
103 [NSMenuItem itemWithTitle:@"Minimize"
104 action:@selector(performMiniaturize:) target:nil
105 keyEquivalent:@"m"],
106 [NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:)
107 target:nil],
108 nil];
109
110 /*
111 * On OS X 10.12 we get duplicate tab control items if we create them here.
112 */
113
114 if ([NSApp macMinorVersion] > 12) {
115 _defaultWindowsMenuItems = [_defaultWindowsMenuItems
116 arrayByAddingObjectsFromArray:
117 [NSArray arrayWithObjects:
118 [NSMenuItem separatorItem],
119 [NSMenuItem itemWithTitle:@"Show Previous Tab"
120 action:@selector(selectPreviousTab:)
121 target:nil
122 keyEquivalent:@"\t"
123 keyEquivalentModifierMask:
124 NSControlKeyMask|NSShiftKeyMask],
125 [NSMenuItem itemWithTitle:@"Show Next Tab"
126 action:@selector(selectNextTab:)
127 target:nil
128 keyEquivalent:@"\t"
129 keyEquivalentModifierMask:NSControlKeyMask],
130 [NSMenuItem itemWithTitle:@"Move Tab To New Window"
131 action:@selector(moveTabToNewWindow:)
132 target:nil],
133 [NSMenuItem itemWithTitle:@"Merge All Windows"
134 action:@selector(mergeAllWindows:)
135 target:nil],
136 [NSMenuItem separatorItem],
137 nil]];
138 }
139 _defaultWindowsMenuItems = [_defaultWindowsMenuItems arrayByAddingObject:
106140 [NSMenuItem itemWithTitle:@"Bring All to Front"
107 action:@selector(arrangeInFront:)],
108 nil] retain];
109
141 action:@selector(arrangeInFront:)]];
142 [_defaultWindowsMenuItems retain];
110143 TKMenu *windowsMenu = [TKMenu menuWithTitle:@"Window" menuItems:
111 _defaultWindowsMenuItems];
112
144 _defaultWindowsMenuItems];
113145 _defaultHelpMenuItems = [[NSArray arrayWithObjects:
114146 [NSMenuItem itemWithTitle:
115147 [NSString stringWithFormat:@"%@ Help", applicationName]
116148 action:@selector(showHelp:) keyEquivalent:@"?"],
117149 nil] retain];
118
119150 TKMenu *helpMenu = [TKMenu menuWithTitle:@"Help" menuItems:
120151 _defaultHelpMenuItems];
121
122152 [self setServicesMenu:_servicesMenu];
123153 [self setWindowsMenu:windowsMenu];
124154 _defaultMainMenu = [[TKMenu menuWithTitle:@"" submenus:[NSArray
137167 [_defaultHelpMenuItems release];
138168 [_defaultWindowsMenuItems release];
139169 [_defaultApplicationMenuItems release];
170 [_defaultFileMenuItems release];
140171 [super dealloc];
141172 }
142173
145176 SEL action = [anItem action];
146177
147178 if (sel_isEqual(action, @selector(preferences:))) {
148
149179 return (_eventInterp && Tcl_FindCommand(_eventInterp,
150180 "::tk::mac::ShowPreferences", NULL, 0));
151181 } else if (sel_isEqual(action, @selector(tkDemo:))) {
231261 if (path) {
232262 Tcl_IncrRefCount(path);
233263
264 [_demoMenuItem setHidden:YES];
234265 int code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);
235266
236267 if (code != TCL_OK) {
2323 Point global;
2424 Point local;
2525 } MouseEventData;
26 static Tk_Window captureWinPtr = NULL; /* Current capture window; may be
27 * NULL. */
2628
2729 static int GenerateButtonEvent(MouseEventData *medPtr);
2830 static unsigned int ButtonModifiers2State(UInt32 buttonState,
29 UInt32 keyModifiers);
31 UInt32 keyModifiers);
3032
3133 #pragma mark TKApplication(TKMouseEvent)
3234
3335 enum {
3436 NSWindowWillMoveEventType = 20
3537 };
38
3639 /*
3740 * In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil
3841 * window attribute pointing to the active window. As of 10.8 this behavior
4649 @implementation TKApplication(TKMouseEvent)
4750 - (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent
4851 {
52 NSWindow *eventWindow = [theEvent window];
53 NSEventType eventType = [theEvent type];
54 TkWindow *winPtr = NULL, *grabWinPtr;
55 Tk_Window tkwin;
56 NSPoint local, global;
57 #if 0
58 NSTrackingArea *trackingArea = nil;
59 NSInteger eventNumber, clickCount, buttonNumber;
60 #endif
61 [NSEvent stopPeriodicEvents];
62
4963 #ifdef TK_MAC_DEBUG_EVENTS
5064 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
51 #endif
52 NSWindow* eventWindow = [theEvent window];
53 NSEventType eventType = [theEvent type];
54 #if 0
55 NSTrackingArea *trackingArea = nil;
56 NSInteger eventNumber, clickCount, buttonNumber;
5765 #endif
5866 switch (eventType) {
5967 case NSMouseEntered:
7280 case NSTabletPoint:
7381 case NSTabletProximity:
7482 case NSScrollWheel:
75 break;
83 break;
7684 default: /* Unrecognized mouse event. */
7785 return theEvent;
7886 }
7987
80 /* Remember the window in case we need it next time. */
81 if (eventWindow && eventWindow != _windowWithMouse) {
82 if (_windowWithMouse) {
83 [_windowWithMouse release];
84 }
85 _windowWithMouse = eventWindow;
86 [_windowWithMouse retain];
87 }
88
89 /* Create an Xevent to add to the Tk queue. */
90 NSPoint global, local = [theEvent locationInWindow];
91 if (eventWindow) { /* local will be in window coordinates. */
88 /*
89 * Compute the mouse position in Tk screen coordinates (global) and in the
90 * Tk coordinates of its containing Tk Window (local). If a grab is in effect,
91 * the local coordinates should be relative to the grab window.
92 */
93
94 if (eventWindow) {
95 local = [theEvent locationInWindow];
9296 global = [eventWindow tkConvertPointToScreen: local];
97 tkwin = TkMacOSXGetCapture();
98 if (tkwin) {
99 winPtr = (TkWindow *) tkwin;
100 eventWindow = TkMacOSXDrawableWindow(winPtr->window);
101 if (eventWindow) {
102 local = [eventWindow tkConvertPointFromScreen: global];
103 } else {
104 return theEvent;
105 }
106 }
93107 local.y = [eventWindow frame].size.height - local.y;
94 global.y = tkMacOSXZeroScreenHeight - global.y;
95 } else { /* local will be in screen coordinates. */
96 if (_windowWithMouse ) {
97 eventWindow = _windowWithMouse;
98 global = local;
99 local = [eventWindow tkConvertPointFromScreen: local];
100 local.y = [eventWindow frame].size.height - local.y;
101 global.y = tkMacOSXZeroScreenHeight - global.y;
102 } else { /* We have no window. Use the screen???*/
103 local.y = tkMacOSXZeroScreenHeight - local.y;
104 global = local;
105 }
106 }
107
108 Window window = TkMacOSXGetXWindow(eventWindow);
109 Tk_Window tkwin = window ? Tk_IdToWindow(TkGetDisplayList()->display,
110 window) : NULL;
108 global.y = TkMacOSXZeroScreenHeight() - global.y;
109 } else {
110
111 /*
112 * If the event has no NSWindow, the location is in screen coordinates.
113 */
114
115 global = [theEvent locationInWindow];
116 tkwin = TkMacOSXGetCapture();
117 if (tkwin) {
118 winPtr = (TkWindow *) tkwin;
119 eventWindow = TkMacOSXDrawableWindow(winPtr->window);
120 } else {
121 eventWindow = [NSApp mainWindow];
122 }
123 if (!eventWindow) {
124 return theEvent;
125 }
126 local = [eventWindow tkConvertPointFromScreen: global];
127 local.y = [eventWindow frame].size.height - local.y;
128 global.y = TkMacOSXZeroScreenHeight() - global.y;
129 }
130
131 /*
132 * If we still don't have a window, try using the toplevel that
133 * manages the NSWindow.
134 */
135
111136 if (!tkwin) {
112 tkwin = TkMacOSXGetCapture();
137 winPtr = TkMacOSXGetTkWindow(eventWindow);
138 tkwin = (Tk_Window) winPtr;
113139 }
114140 if (!tkwin) {
115 return theEvent; /* Give up. No window for this event. */
116 }
117
118 TkWindow *winPtr = (TkWindow *) tkwin;
119 local.x -= winPtr->wmInfoPtr->xInParent;
120 local.y -= winPtr->wmInfoPtr->yInParent;
141
142 /*
143 * We can't find a window for this event. We have to ignore it.
144 */
145
146 #ifdef TK_MAC_DEBUG_EVENTS
147 TkMacOSXDbgMsg("tkwin == NULL");
148 #endif
149 return theEvent;
150 }
151
152 /*
153 * Ignore the event if a local grab is in effect and the Tk event window is
154 * not in the grabber's subtree.
155 */
156
157 grabWinPtr = winPtr->dispPtr->grabWinPtr;
158 if (grabWinPtr && /* There is a grab in effect ... */
159 !winPtr->dispPtr->grabFlags && /* and it is a local grab ... */
160 grabWinPtr->mainPtr == winPtr->mainPtr){ /* in the same application. */
161 Tk_Window tkwin2, tkEventWindow = Tk_CoordsToWindow(global.x, global.y, tkwin);
162 if (!tkEventWindow) {
163 return theEvent;
164 }
165 for (tkwin2 = tkEventWindow;
166 !Tk_IsTopLevel(tkwin2);
167 tkwin2 = Tk_Parent(tkwin2)) {
168 if (tkwin2 == (Tk_Window) grabWinPtr) {
169 break;
170 }
171 }
172 if (tkwin2 != (Tk_Window) grabWinPtr) {
173 return theEvent;
174 }
175 }
176
177 /*
178 * Convert local from NSWindow flipped coordinates to the toplevel's
179 * coordinates.
180 */
181
182 if (Tk_IsEmbedded(winPtr)) {
183 TkWindow *contPtr = TkpGetOtherWindow(winPtr);
184 if (Tk_IsTopLevel(contPtr)) {
185 local.x -= contPtr->wmInfoPtr->xInParent;
186 local.y -= contPtr->wmInfoPtr->yInParent;
187 } else {
188 TkWindow *topPtr = TkMacOSXGetHostToplevel(winPtr)->winPtr;
189 local.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);
190 local.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);
191 }
192 } else {
193 local.x -= winPtr->wmInfoPtr->xInParent;
194 local.y -= winPtr->wmInfoPtr->yInParent;
195 }
196
197 /*
198 * Use the toplevel coordinates to find the containing Tk window. Then
199 * convert local into the coordinates of that window. (The converted
200 * local coordinates are only needed for scrollwheel events.)
201 */
121202
122203 int win_x, win_y;
123 tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y,
124 &win_x, &win_y);
204 tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
205 local.x = win_x;
206 local.y = win_y;
207
208 /*
209 * Generate an XEvent for this mouse event.
210 */
125211
126212 unsigned int state = 0;
127 NSInteger button = [theEvent buttonNumber];
213 int button = [theEvent buttonNumber] + Button1;
128214 EventRef eventRef = (EventRef)[theEvent eventRef];
129215 UInt32 buttons;
130216 OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord,
131 typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
217 typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
132218
133219 if (err == noErr) {
134 state |= (buttons & ((1<<5) - 1)) << 8;
135 } else if (button < 5) {
220 state |= (buttons & 0x1F) * Button1Mask;
221 } else if (button <= Button5) {
136222 switch (eventType) {
137223 case NSLeftMouseDown:
138224 case NSRightMouseDown:
139225 case NSLeftMouseDragged:
140226 case NSRightMouseDragged:
141227 case NSOtherMouseDown:
142 state |= 1 << (button + 8);
228 state |= TkGetButtonMask(button);
143229 break;
144230 default:
145231 break;
171257 }
172258
173259 if (eventType != NSScrollWheel) {
260
261 /*
262 * For normal mouse events, Tk_UpdatePointer will send the XEvent.
263 */
264
174265 #ifdef TK_MAC_DEBUG_EVENTS
175 TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state);
266 TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d",
267 tkwin, global.x, global.y, state);
176268 #endif
177269 Tk_UpdatePointer(tkwin, global.x, global.y, state);
178 } else { /* handle scroll wheel event */
270 } else {
271
272 /*
273 * For scroll wheel events we need to send the XEvent here.
274 */
275
179276 CGFloat delta;
180277 int coarseDelta;
181278 XEvent xEvent;
192289 delta = [theEvent deltaY];
193290 if (delta != 0.0) {
194291 coarseDelta = (delta > -1.0 && delta < 1.0) ?
195 (signbit(delta) ? -1 : 1) : lround(delta);
292 (signbit(delta) ? -1 : 1) : lround(delta);
196293 xEvent.xbutton.state = state;
197294 xEvent.xkey.keycode = coarseDelta;
198295 xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
201298 delta = [theEvent deltaX];
202299 if (delta != 0.0) {
203300 coarseDelta = (delta > -1.0 && delta < 1.0) ?
204 (signbit(delta) ? -1 : 1) : lround(delta);
301 (signbit(delta) ? -1 : 1) : lround(delta);
205302 xEvent.xbutton.state = state | ShiftMask;
206303 xEvent.xkey.keycode = coarseDelta;
207304 xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
298395 unsigned int state;
299396
300397 /*
301 * Tk supports at most 5 buttons.
302 */
303
304 state = (buttonState & ((1<<5) - 1)) << 8;
398 * Tk on OSX supports at most 5 buttons.
399 */
400
401 state = (buttonState & 0x1F) * Button1Mask;
305402
306403 if (keyModifiers & alphaLock) {
307404 state |= LockMask;
384481 }
385482 if (getGlobal) {
386483 *root_x_return = global.x;
387 *root_y_return = tkMacOSXZeroScreenHeight - global.y;
484 *root_y_return = TkMacOSXZeroScreenHeight() - global.y;
388485 }
389486 }
390487 if (mask_return) {
436533 * TkGenerateButtonEvent --
437534 *
438535 * Given a global x & y position and the button key status this procedure
439 * generates the appropiate X button event. It also handles the state
536 * generates the appropriate X button event. It also handles the state
440537 * changes needed to implement implicit grabs.
441538 *
442539 * Results:
468565 med.local = med.global;
469566
470567 if (win) {
471 NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
568 NSPoint local = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
472569
473570 local = [win tkConvertPointFromScreen:local];
474571 local.y = [win frame].size.height - local.y;
477574 local.y -= macWin->winPtr->wmInfoPtr->yInParent;
478575 }
479576 med.local.h = local.x;
480 med.local.v = tkMacOSXZeroScreenHeight - local.y;
577 med.local.v = TkMacOSXZeroScreenHeight() - local.y;
481578 }
482579
483580 return GenerateButtonEvent(&med);
510607 TkDisplay *dispPtr;
511608
512609 #if UNUSED
610
513611 /*
514612 * ButtonDown events will always occur in the front window. ButtonUp
515613 * events, however, may occur anywhere on the screen. ButtonUp events
542640 TkDisplay *dispPtr)
543641 {
544642 CGPoint pt;
545 UInt32 buttonState;
643 NSPoint loc;
644 int wNum;
546645
547646 if (dispPtr->warpWindow) {
548647 int x, y;
549
648 TkWindow *winPtr = (TkWindow *) dispPtr->warpWindow;
649 TkWindow *topPtr = winPtr->privatePtr->toplevel->winPtr;
650 NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
651 wNum = [w windowNumber];
550652 Tk_GetRootCoords(dispPtr->warpWindow, &x, &y);
551653 pt.x = x + dispPtr->warpX;
552654 pt.y = y + dispPtr->warpY;
655 loc.x = dispPtr->warpX;
656 loc.y = Tk_Height(topPtr) - dispPtr->warpY;
553657 } else {
554 pt.x = dispPtr->warpX;
658 wNum = 0;
659 pt.x = loc.x = dispPtr->warpX;
555660 pt.y = dispPtr->warpY;
556 }
557
558 /*
559 * Tell the OSX core to generate the events to make it happen.
560 */
561
562 buttonState = [NSEvent pressedMouseButtons];
563 CGEventType type = kCGEventMouseMoved;
564 CGEventRef theEvent = CGEventCreateMouseEvent(NULL,
565 type,
566 pt,
567 buttonState);
661 loc.y = TkMacOSXZeroScreenHeight() - pt.y;
662 }
663
664 /*
665 * Generate an NSEvent of type NSMouseMoved.
666 *
667 * It is not clear why this is necessary. For example, calling
668 * event generate $w <Motion> -warp 1 -x $X -y $Y
669 * will cause two <Motion> events to be added to the Tcl queue.
670 */
671
568672 CGWarpMouseCursorPosition(pt);
569 CGEventPost(kCGHIDEventTap, theEvent);
570 CFRelease(theEvent);
673 NSEvent *warpEvent = [NSEvent mouseEventWithType:NSMouseMoved
674 location:loc
675 modifierFlags:0
676 timestamp:GetCurrentEventTime()
677 windowNumber:wNum
678 context:nil
679 eventNumber:0
680 clickCount:1
681 pressure:0.0];
682 [NSApp postEvent:warpEvent atStart:NO];
683 }
684
685 /*
686 *----------------------------------------------------------------------
687 *
688 * TkpSetCapture --
689 *
690 * This function captures the mouse so that all future events will be
691 * reported to this window, even if the mouse is outside the window. If
692 * the specified window is NULL, then the mouse is released.
693 *
694 * Results:
695 * None.
696 *
697 * Side effects:
698 * Sets the capture flag and captures the mouse.
699 *
700 *----------------------------------------------------------------------
701 */
702
703 void
704 TkpSetCapture(
705 TkWindow *winPtr) /* Capture window, or NULL. */
706 {
707 while (winPtr && !Tk_IsTopLevel(winPtr)) {
708 winPtr = winPtr->parentPtr;
709 }
710 [NSEvent stopPeriodicEvents];
711 captureWinPtr = (Tk_Window) winPtr;
712 }
713
714 /*
715 *----------------------------------------------------------------------
716 *
717 * TkMacOSXGetCapture --
718 *
719 * Results:
720 * Returns the current grab window
721 *
722 * Side effects:
723 * None.
724 *
725 *----------------------------------------------------------------------
726 */
727
728 Tk_Window
729 TkMacOSXGetCapture(void)
730 {
731 return captureWinPtr;
571732 }
572733
573734 /*
3232 static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
3333
3434 #ifdef TK_MAC_DEBUG_EVENTS
35 static char* Tk_EventName[39] = {
35 static const char *Tk_EventName[39] = {
3636 "",
3737 "",
3838 "KeyPress", /*2*/
8383 const char *name;
8484 long serial = ve->serial;
8585 long time = eventPtr->xkey.time;
86
86
8787 if (eventPtr->type == VirtualEvent) {
8888 name = ve->name;
8989 } else {
111111 # endif
112112
113113 #pragma mark TKApplication(TKNotify)
114
115 @interface NSApplication(TKNotify)
116 /* We need to declare this hidden method. */
117 - (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
118 @end
119114
120115 @implementation TKApplication(TKNotify)
121116 /*
139134 */
140135
141136 /*
142 * Call super then check the pasteboard.
137 * Since the contentView is the first responder for a Tk Window, it is
138 * responsible for sending events up the responder chain. We also check the
139 * pasteboard here.
143140 */
144141 - (void) sendEvent: (NSEvent *) theEvent
145142 {
146143 [super sendEvent:theEvent];
147144 [NSApp tkCheckPasteboard];
148145 #ifdef TK_MAC_DEBUG_EVENTS
149 fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
146 fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
150147 DebugPrintQueue();
151148 #endif
152149 }
192189 *
193190 * Tk_MacOSXSetupTkNotifier --
194191 *
195 * This procedure is called during Tk initialization to create
196 * the event source for TkAqua events.
192 * This procedure is called during Tk initialization to create the event
193 * source for TkAqua events.
197194 *
198195 * Results:
199196 * None.
226223 "first [load] of TkAqua has to occur in the main thread!");
227224 }
228225 Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
229 TkMacOSXEventsCheckProc,
230 NULL);
226 TkMacOSXEventsCheckProc, NULL);
231227 TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
232228 Tcl_SetServiceMode(TCL_SERVICE_ALL);
233229 TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
260256 TSD_INIT();
261257
262258 Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
263 TkMacOSXEventsCheckProc,
264 NULL);
259 TkMacOSXEventsCheckProc, NULL);
265260 tsdPtr->initialized = 0;
266261 }
267262
270265 *
271266 * TkMacOSXEventsSetupProc --
272267 *
273 * This procedure implements the setup part of the MacOSX event
274 * source. It is invoked by Tcl_DoOneEvent before calling
275 * TkMacOSXEventsProc to process all queued NSEvents. In our
276 * case, all we need to do is to set the Tcl MaxBlockTime to
277 * 0 before starting the loop to process all queued NSEvents.
268 * This procedure implements the setup part of the MacOSX event source. It
269 * is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsProc to
270 * process all queued NSEvents. In our case, all we need to do is to set
271 * the Tcl MaxBlockTime to 0 before starting the loop to process all
272 * queued NSEvents.
278273 *
279274 * Results:
280275 * None.
281276 *
282277 * Side effects:
283278 *
284 * If NSEvents are queued, then the maximum block time will be set
285 * to 0 to ensure that control returns immediately to Tcl.
279 * If NSEvents are queued, then the maximum block time will be set to 0 to
280 * ensure that control returns immediately to Tcl.
286281 *
287282 *----------------------------------------------------------------------
288283 */
292287 ClientData clientData,
293288 int flags)
294289 {
290 static Bool havePeriodicEvents = NO;
295291 NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
296 /* runloopMode will be nil if we are in a Tcl event loop. */
292
293 /*
294 * runloopMode will be nil if we are in a Tcl event loop.
295 */
296
297297 if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
298298 static const Tcl_Time zeroBlockTime = { 0, 0 };
299299 [NSApp _resetAutoreleasePool];
300 /* Call this with dequeue=NO -- just checking if the queue is empty. */
301 NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
302 untilDate:[NSDate distantPast]
303 inMode:GetRunLoopMode(TkMacOSXGetModalSession())
304 dequeue:NO];
300
301 /*
302 * Call this with dequeue=NO -- just checking if the queue is empty.
303 */
304
305 NSEvent *currentEvent =
306 [NSApp nextEventMatchingMask:NSAnyEventMask
307 untilDate:[NSDate distantPast]
308 inMode:GetRunLoopMode(TkMacOSXGetModalSession())
309 dequeue:NO];
305310 if (currentEvent) {
306311 if (currentEvent.type > 0) {
307312 Tcl_SetMaxBlockTime(&zeroBlockTime);
313 [NSEvent stopPeriodicEvents];
314 havePeriodicEvents = NO;
308315 }
316 } else if (!havePeriodicEvents){
317
318 /*
319 * When the user is not generating events we schedule a "hearbeat"
320 * event to fire every 0.1 seconds. This helps to make the vwait
321 * command more responsive when there is no user input, e.g. when
322 * running the test suite.
323 */
324
325 havePeriodicEvents = YES;
326 [NSEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.1];
309327 }
310328 }
311329 }
315333 *
316334 * TkMacOSXEventsCheckProc --
317335 *
318 * This procedure loops through all NSEvents waiting in the
319 * TKApplication event queue, generating X events from them.
336 * This procedure loops through all NSEvents waiting in the TKApplication
337 * event queue, generating X events from them.
320338 *
321339 * Results:
322340 * None.
323341 *
324342 * Side effects:
325 * NSevents are used to generate X events, which are added to the
326 * Tcl event queue.
343 * NSevents are used to generate X events, which are added to the Tcl
344 * event queue.
327345 *
328346 *----------------------------------------------------------------------
329347 */
333351 int flags)
334352 {
335353 NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
336 /* runloopMode will be nil if we are in a Tcl event loop. */
354
355 /*
356 * runloopMode will be nil if we are in a Tcl event loop.
357 */
358
337359 if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
338360 NSEvent *currentEvent = nil;
339361 NSEvent *testEvent = nil;
340362 NSModalSession modalSession;
341 /* It is possible for the SetupProc to be called before this function
363
364 /*
365 * It is possible for the SetupProc to be called before this function
342366 * returns. This happens, for example, when we process an event which
343367 * opens a modal window. To prevent premature release of our
344368 * application-wide autorelease pool by a nested call to the SetupProc,
345369 * we must lock it here.
346370 */
371
347372 [NSApp _lockAutoreleasePool];
348373 do {
349374 modalSession = TkMacOSXGetModalSession();
350 testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
351 untilDate:[NSDate distantPast]
352 inMode:GetRunLoopMode(modalSession)
353 dequeue:NO];
354 /* We must not steal any events during LiveResize. */
375 testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
376 untilDate:[NSDate distantPast]
377 inMode:GetRunLoopMode(modalSession)
378 dequeue:NO];
379
380 /*
381 * We must not steal any events during LiveResize.
382 */
383
355384 if (testEvent && [[testEvent window] inLiveResize]) {
356385 break;
357386 }
358387 currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
359 untilDate:[NSDate distantPast]
360 inMode:GetRunLoopMode(modalSession)
361 dequeue:YES];
388 untilDate:[NSDate distantPast]
389 inMode:GetRunLoopMode(modalSession)
390 dequeue:YES];
362391 if (currentEvent) {
363 /* Generate Xevents. */
392 /*
393 * Generate Xevents.
394 */
395
364396 int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
365397 NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
366398 Tcl_SetServiceMode(oldServiceMode);
367 if (processedEvent) { /* Should always be non-NULL. */
399 if (processedEvent) {
368400 #ifdef TK_MAC_DEBUG_EVENTS
369401 TKLog(@" event: %@", currentEvent);
370402 #endif
378410 break;
379411 }
380412 } while (1);
381 /* Now we can unlock the pool. */
413
414 /*
415 * Now we can unlock the pool.
416 */
417
382418 [NSApp _unlockAutoreleasePool];
383419 }
384420 }
385
386421
387422 /*
388423 * Local Variables:
2222 #include <math.h>
2323 #include <pwd.h>
2424 #include <stdlib.h>
25 #include <assert.h>
2526 #include <string.h>
2627 #include <sys/types.h>
2728 #include <sys/file.h>
109110 * no-op functions on the Macintosh.
110111 */
111112
112 #define XFlush(display)
113 #define XFree(data) {if ((data) != NULL) ckfree(data);}
114 #define XGrabServer(display)
115 #define XNoOp(display) {display->request++;}
116 #define XUngrabServer(display)
117 #define XSynchronize(display, bool) {display->request++;}
113 #undef XFlush
114 #define XFlush(display) (0)
115 #undef XFree
116 #define XFree(data) (((data) != NULL) ? (ckfree(data),0) : 0)
117 #undef XGrabServer
118 #define XGrabServer(display) (0)
119 #undef XNoOp
120 #define XNoOp(display) (display->request++,0)
121 #undef XUngrabServer
122 #define XUngrabServer(display) (0)
123 #undef XSynchronize
124 #define XSynchronize(display, onoff) (display->request++,NULL)
125 #undef XVisualIDFromVisual
118126 #define XVisualIDFromVisual(visual) (visual->visualid)
119127
120128 /*
127135 #define TkpSync(display)
128136
129137 /*
130 * The following macro returns the pixel value that corresponds to the
131 * RGB values in the given XColor structure.
138 * TkMacOSXGetCapture is a legacy function used on the Mac. When fixing
139 * [943d5ebe51], TkpGetCapture was added to the Windows port. Both
140 * are actually the same feature and should bear the same name. However,
141 * in order to avoid potential backwards incompatibilities, renaming
142 * TkMacOSXGetCapture into TkpGetCapture in *PlatDecls.h shall not be
143 * done in a patch release, therefore use a define here.
132144 */
133145
134 #define PIXEL_MAGIC ((unsigned char) 0x69)
135 #define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
136 | (((p)->red >> 8) & 0xff)) << 8) \
137 | (((p)->green >> 8) & 0xff)) << 8) \
138 | (((p)->blue >> 8) & 0xff))
146 #define TkpGetCapture TkMacOSXGetCapture
139147
140148 /*
141149 * This macro stores a representation of the window handle in a string.
158166 */
159167
160168 #define TRANSPARENT_PIXEL 30
161 #define HIGHLIGHT_PIXEL 31
162 #define HIGHLIGHT_SECONDARY_PIXEL 32
163 #define HIGHLIGHT_TEXT_PIXEL 33
164 #define HIGHLIGHT_ALTERNATE_PIXEL 34
165 #define CONTROL_TEXT_PIXEL 35
166 #define CONTROL_BODY_PIXEL 37
167 #define CONTROL_FRAME_PIXEL 39
168 #define WINDOW_BODY_PIXEL 41
169 #define MENU_ACTIVE_PIXEL 43
170 #define MENU_ACTIVE_TEXT_PIXEL 45
171 #define MENU_BACKGROUND_PIXEL 47
172 #define MENU_DISABLED_PIXEL 49
173 #define MENU_TEXT_PIXEL 51
174169 #define APPEARANCE_PIXEL 52
170 #define PIXEL_MAGIC ((unsigned char) 0x69)
171
172 /*
173 * The following macro returns the pixel value that corresponds to the
174 * 16-bit RGB values in the given XColor structure.
175 * The format is: (PIXEL_MAGIC <<< 24) | (R << 16) | (G << 8) | B
176 * where each of R, G and B is the high order byte of a 16-bit component.
177 */
178
179 #define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
180 | (((p)->red >> 8) & 0xff)) << 8) \
181 | (((p)->green >> 8) & 0xff)) << 8) \
182 | (((p)->blue >> 8) & 0xff))
183
175184
176185 #endif /* _TKMACPORT */
136136 * Variables internal to TkAqua.
137137 */
138138
139 MODULE_SCOPE CGFloat tkMacOSXZeroScreenHeight;
140 MODULE_SCOPE CGFloat tkMacOSXZeroScreenTop;
141139 MODULE_SCOPE long tkMacOSXMacOSXVersion;
142140
143141 /*
176174 MODULE_SCOPE void * TkMacOSXGetNamedSymbol(const char *module,
177175 const char *symbol);
178176 MODULE_SCOPE void TkMacOSXDisplayChanged(Display *display);
177 MODULE_SCOPE CGFloat TkMacOSXZeroScreenHeight();
178 MODULE_SCOPE CGFloat TkMacOSXZeroScreenTop();
179179 MODULE_SCOPE int TkMacOSXUseAntialiasedText(Tcl_Interp *interp,
180180 int enable);
181181 MODULE_SCOPE int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable,
232232 MODULE_SCOPE int TkMacOSXIconBitmapObjCmd(ClientData clientData,
233233 Tcl_Interp *interp, int objc,
234234 Tcl_Obj *const objv[]);
235 MODULE_SCOPE void TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc,
236 int inset, int thickness);
237 MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp);
238 MODULE_SCOPE int TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData,
239 Tcl_Interp *interp, int objc,
240 Tcl_Obj *const objv[]);
241 MODULE_SCOPE NSString* TclUniToNSString(const char *source, int numBytes);
242 MODULE_SCOPE int TclUniAtIndex(NSString *string, int index, char *uni,
243 unsigned int *code);
244 MODULE_SCOPE char* NSStringToTclUni(NSString *string, int *numBytes);
235245
236246 #pragma mark Private Objective-C Classes
237247
249259 - (BOOL)isSpecial:(NSUInteger)special;
250260 @end
251261
262 @interface TKMenu(TKMenuDelegate) <NSMenuDelegate>
263 @end
264
252265 VISIBILITY_HIDDEN
253266 @interface TKApplication : NSApplication {
254267 @private
255268 Tcl_Interp *_eventInterp;
256269 NSMenu *_servicesMenu;
257270 TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
271 NSMenuItem *_demoMenuItem;
258272 NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
259 NSArray *_defaultHelpMenuItems;
260 NSWindow *_windowWithMouse;
273 NSArray *_defaultHelpMenuItems, *_defaultFileMenuItems;
261274 NSAutoreleasePool *_mainPool;
262275 #ifdef __i386__
263276 /* The Objective C runtime used on i386 requires this. */
264277 int _poolLock;
265278 int _macMinorVersion;
266279 Bool _isDrawing;
267 Bool _simulateDrawing;
268280 #endif
269281 }
270282 @property int poolLock;
271283 @property int macMinorVersion;
272284 @property Bool isDrawing;
273 @property Bool simulateDrawing;
274285
275286 @end
276287 @interface TKApplication(TKInit)
279290 - (void)_lockAutoreleasePool;
280291 - (void)_unlockAutoreleasePool;
281292 @end
293 @interface TKApplication(TKKeyboard)
294 - (void) keyboardChanged: (NSNotification *) notification;
295 @end
296 @interface TKApplication(TKWindowEvent) <NSApplicationDelegate>
297 - (void) _setupWindowNotifications;
298 @end
299 @interface TKApplication(TKDialog) <NSOpenSavePanelDelegate>
300 @end
301 @interface TKApplication(TKMenu)
302 - (void)tkSetMainMenu:(TKMenu *)menu;
303 @end
304 @interface TKApplication(TKMenus)
305 - (void) _setupMenus;
306 @end
307 @interface NSApplication(TKNotify)
308 /* We need to declare this hidden method. */
309 - (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
310 @end
282311 @interface TKApplication(TKEvent)
283312 - (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
284313 @end
287316 @end
288317 @interface TKApplication(TKKeyEvent)
289318 - (NSEvent *)tkProcessKeyEvent:(NSEvent *)theEvent;
290 @end
291 @interface TKApplication(TKMenu)
292 - (void)tkSetMainMenu:(TKMenu *)menu;
293319 @end
294320 @interface TKApplication(TKClipboard)
295321 - (void)tkProvidePasteboard:(TkDisplay *)dispPtr;
312338 withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
313339 - (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
314340 withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
341 - (void)handleURLEvent: (NSAppleEventDescriptor*)event
342 withReplyEvent: (NSAppleEventDescriptor*)replyEvent;
315343 @end
316344
317345 VISIBILITY_HIDDEN
318 @interface TKContentView : NSView <NSTextInput> {
346 /*
347 * Subclass TKContentView from NSTextInputClient to enable composition and
348 * input from the Character Palette.
349 */
350
351 @interface TKContentView : NSView <NSTextInputClient>
352 {
319353 @private
320 /*Remove private API calls.*/
321 #if 0
322 id _savedSubviews;
323 BOOL _subviewsSetAside;
324 #endif
325354 NSString *privateWorkingText;
355 Bool _needsRedisplay;
326356 }
357 @property Bool needsRedisplay;
327358 @end
328359
329360 @interface TKContentView(TKKeyEvent)
331362 @end
332363
333364 @interface TKContentView(TKWindowEvent)
334 - (void) drawRect: (NSRect) rect;
335 - (void) generateExposeEvents: (HIShapeRef) shape;
365 - (void) generateExposeEvents: (HIShapeRef) shape;
336366 - (void) tkToolbarButton: (id) sender;
337 - (BOOL) isOpaque;
338 - (BOOL) wantsDefaultClipping;
339 - (BOOL) acceptsFirstResponder;
340 - (void) keyDown: (NSEvent *) theEvent;
341 @end
342
343 VISIBILITY_HIDDEN
344 @interface TKWindow : NSWindow
345367 @end
346368
347369 @interface NSWindow(TKWm)
348370 - (NSPoint) tkConvertPointToScreen:(NSPoint)point;
349371 - (NSPoint) tkConvertPointFromScreen:(NSPoint)point;
372 @end
373
374 VISIBILITY_HIDDEN
375 @interface TKWindow : NSWindow
376 @end
377
378 @interface TKWindow(TKWm)
379 - (void) tkLayoutChanged;
380 @end
381
382 @interface NSDrawerWindow : NSWindow
383 {
384 id _i1, _i2;
385 }
350386 @end
351387
352388 #pragma mark NSMenu & NSMenuItem Utilities
377413 keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;
378414 @end
379415
416 @interface NSColorPanel(TKDialog)
417 - (void) _setUseModalAppearance: (BOOL) flag;
418 @end
419
420 @interface NSFont(TKFont)
421 - (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters
422 length: (NSUInteger) length attributes: (NSDictionary *) attributes
423 actualCoveredLength: (NSUInteger *) coveredLength;
424 @end
425
426 /*
427 * This method of NSApplication is not declared in NSApplication.h so we
428 * declare it here to be a method of the TKMenu category.
429 */
430
431 @interface NSApplication(TKMenu)
432 - (void) setAppleMenu: (NSMenu *) menu;
433 @end
434
380435 #endif /* _TKMACPRIV */
436
437 int TkMacOSXGetAppPath(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]);
438
439 /*
440 * Local Variables:
441 * mode: objc
442 * c-basic-offset: 4
443 * fill-column: 79
444 * coding: utf-8
445 * End:
446 */
5353 *----------------------------------------------------------------------
5454 */
5555
56 void
56 int
5757 TkDestroyRegion(
5858 TkRegion r)
5959 {
6060 if (r) {
6161 CFRelease(r);
6262 }
63 return Success;
6364 }
6465
6566 /*
7980 *----------------------------------------------------------------------
8081 */
8182
82 void
83 int
8384 TkIntersectRegion(
8485 TkRegion sra,
8586 TkRegion srb,
8788 {
8889 ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb,
8990 (HIMutableShapeRef) dr_return);
91 return Success;
9092 }
9193
9294 /*
106108 *----------------------------------------------------------------------
107109 */
108110
109 void
111 int
110112 TkSubtractRegion(
111113 TkRegion sra,
112114 TkRegion srb,
114116 {
115117 ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb,
116118 (HIMutableShapeRef) dr_return);
119 return Success;
117120 }
118121
119122 /*
133136 *----------------------------------------------------------------------
134137 */
135138
136 void
139 int
137140 TkUnionRectWithRegion(
138141 XRectangle* rectangle,
139142 TkRegion src_region,
152155 (HIMutableShapeRef) dest_region_return);
153156 CFRelease(rectRgn);
154157 }
158 return Success;
155159 }
156160
157161 /*
186190 * Xwindow documentation for more details.
187191 *
188192 * Results:
189 * Returns RectanglePart or RectangleOut. Note that this is not a
190 * complete implementation since it doesn't test for RectangleIn.
193 * Returns RectanglePart or RectangleOut. Note that this is not a complete
194 * implementation since it doesn't test for RectangleIn.
191195 *
192196 * Side effects:
193197 * None.
203207 unsigned int width,
204208 unsigned int height)
205209 {
206 if ( TkMacOSXIsEmptyRegion(region) ) {
207 return RectangleOut;
208 }
209 else {
210 if (TkMacOSXIsEmptyRegion(region)) {
211 return RectangleOut;
212 } else {
210213 const CGRect r = CGRectMake(x, y, width, height);
214
211215 return HIShapeIntersectsRect((HIShapeRef) region, &r) ?
212 RectanglePart : RectangleOut;
216 RectanglePart : RectangleOut;
213217 }
214218 }
215219
230234 *----------------------------------------------------------------------
231235 */
232236
233 void
237 int
234238 TkClipBox(
235239 TkRegion r,
236 XRectangle* rect_return)
240 XRectangle *rect_return)
237241 {
238242 CGRect rect;
239243
242246 rect_return->y = rect.origin.y;
243247 rect_return->width = rect.size.width;
244248 rect_return->height = rect.size.height;
249 return Success;
245250 }
246251
247252 /*
5050 * Forward declarations for procedures defined later in this file:
5151 */
5252
53 static void MacScaleEventProc(ClientData clientData, XEvent *eventPtr);
54 static pascal void ScaleActionProc(ControlRef theControl,
55 ControlPartCode partCode);
56
53 static void MacScaleEventProc(ClientData clientData,
54 XEvent *eventPtr);
55 static pascal void ScaleActionProc(ControlRef theControl,
56 ControlPartCode partCode);
5757
5858 /*
5959 *----------------------------------------------------------------------
8383 }
8484
8585 Tk_CreateEventHandler(tkwin, ButtonPressMask,
86 MacScaleEventProc, (ClientData) macScalePtr);
86 MacScaleEventProc, macScalePtr);
8787
8888 return (TkScale *) macScalePtr;
8989 }
124124 *
125125 * TkpDisplayScale --
126126 *
127 * This procedure is invoked as an idle handler to redisplay
128 * the contents of a scale widget.
127 * This procedure is invoked as an idle handler to redisplay the contents
128 * of a scale widget.
129129 *
130130 * Results:
131131 * None.
140140 TkpDisplayScale(
141141 ClientData clientData) /* Widget record for scale. */
142142 {
143 TkScale *scalePtr = (TkScale *) clientData;
143 TkScale *scalePtr = clientData;
144144 Tk_Window tkwin = scalePtr->tkwin;
145145 Tcl_Interp *interp = scalePtr->interp;
146146 int result;
147147 char string[TCL_DOUBLE_SPACE];
148 MacScale *macScalePtr = (MacScale *) clientData;
148 MacScale *macScalePtr = clientData;
149149 Rect r;
150150 WindowRef windowRef;
151151 CGrafPtr destPort, savePort;
167167 * Invoke the scale's command if needed.
168168 */
169169
170 Tcl_Preserve((ClientData) scalePtr);
170 Tcl_Preserve(scalePtr);
171171 if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
172 Tcl_Preserve((ClientData) interp);
172 Tcl_Preserve(interp);
173173 if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
174174 scalePtr->value) < 0) {
175175 string[TCL_DOUBLE_SPACE - 1] = '\0';
184184 Tcl_AddErrorInfo(interp, "\n (command executed by scale)");
185185 Tcl_BackgroundException(interp, result);
186186 }
187 Tcl_Release((ClientData) interp);
187 Tcl_Release(interp);
188188 }
189189 scalePtr->flags &= ~INVOKE_COMMAND;
190190 if (scalePtr->flags & SCALE_DELETED) {
191 Tcl_Release((ClientData) scalePtr);
191 Tcl_Release(scalePtr);
192192 return;
193193 }
194 Tcl_Release((ClientData) scalePtr);
195
196 /*
197 * Now handle the part of redisplay that is the same for
198 * horizontal and vertical scales: border and traversal
199 * highlight.
194 Tcl_Release(scalePtr);
195
196 /*
197 * Now handle the part of redisplay that is the same for horizontal and
198 * vertical scales: border and traversal highlight.
200199 */
201200
202201 if (scalePtr->highlightWidth != 0) {
228227 #define MAC_OSX_SCROLL_WIDTH 10
229228
230229 if (scalePtr->orient == ORIENT_HORIZONTAL) {
231 int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH)/2;
230 int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
232231
233232 if (offset < 0) {
234233 offset = 0;
239238 r.right = macDraw->xOff+Tk_Width(tkwin) - scalePtr->inset;
240239 r.bottom = macDraw->yOff + offset + MAC_OSX_SCROLL_WIDTH/2;
241240 } else {
242 int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH)/2;
241 int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
243242
244243 if (offset < 0) {
245244 offset = 0;
248247 r.left = macDraw->xOff + offset;
249248 r.top = macDraw->yOff + scalePtr->inset;
250249 r.right = macDraw->xOff + offset + MAC_OSX_SCROLL_WIDTH/2;
251 r.bottom = macDraw->yOff+Tk_Height(tkwin) - scalePtr->inset;
250 r.bottom = macDraw->yOff + Tk_Height(tkwin) - scalePtr->inset;
252251 }
253252
254253 if (macScalePtr->scaleHandle == NULL) {
272271
273272 CreateSliderControl(windowRef, &r, initialValue, minValue, maxValue,
274273 kControlSliderPointsDownOrRight, numTicks, 1, scaleActionProc,
275 &(macScalePtr->scaleHandle));
274 &macScalePtr->scaleHandle);
276275 SetControlReference(macScalePtr->scaleHandle, (UInt32) scalePtr);
277276
278277 if (IsWindowActive(windowRef)) {
289288 * Finally draw the control.
290289 */
291290
292 SetControlVisibility(macScalePtr->scaleHandle,true,true);
293 HiliteControl(macScalePtr->scaleHandle,0);
291 SetControlVisibility(macScalePtr->scaleHandle, true, true);
292 HiliteControl(macScalePtr->scaleHandle, 0);
294293 Draw1Control(macScalePtr->scaleHandle);
295294
296295 if (portChanged) {
305304 *
306305 * TkpScaleElement --
307306 *
308 * Determine which part of a scale widget lies under a given
309 * point.
307 * Determine which part of a scale widget lies under a given point.
310308 *
311309 * Results:
312 * The return value is either TROUGH1, SLIDER, TROUGH2, or
313 * OTHER, depending on which of the scale's active elements
314 * (if any) is under the point at (x,y).
310 * The return value is either TROUGH1, SLIDER, TROUGH2, or OTHER,
311 * depending on which of the scale's active elements (if any) is under the
312 * point at (x,y).
315313 *
316314 * Side effects:
317315 * None.
356354 #endif
357355
358356 switch (part) {
359 case inSlider:
360 return SLIDER;
361 case inInc:
362 if (scalePtr->orient == ORIENT_VERTICAL) {
363 return TROUGH1;
364 } else {
365 return TROUGH2;
366 }
367 case inDecr:
368 if (scalePtr->orient == ORIENT_VERTICAL) {
369 return TROUGH2;
370 } else {
371 return TROUGH1;
372 }
373 default:
374 return OTHER;
357 case inSlider:
358 return SLIDER;
359 case inInc:
360 if (scalePtr->orient == ORIENT_VERTICAL) {
361 return TROUGH1;
362 } else {
363 return TROUGH2;
364 }
365 case inDecr:
366 if (scalePtr->orient == ORIENT_VERTICAL) {
367 return TROUGH2;
368 } else {
369 return TROUGH1;
370 }
371 default:
372 return OTHER;
375373 }
376374 }
377375
380378 *
381379 * MacScaleEventProc --
382380 *
383 * This procedure is invoked by the Tk dispatcher for
384 * ButtonPress events on scales.
381 * This procedure is invoked by the Tk dispatcher for ButtonPress events
382 * on scales.
385383 *
386384 * Results:
387385 * None.
388386 *
389387 * Side effects:
390 * When the window gets deleted, internal structures get
391 * cleaned up. When it gets exposed, it is redisplayed.
388 * When the window gets deleted, internal structures get cleaned up. When
389 * it gets exposed, it is redisplayed.
392390 *
393391 *--------------------------------------------------------------
394392 */
410408 #endif
411409
412410 /*
413 * To call Macintosh control routines we must have the port
414 * set to the window containing the control. We will then test
415 * which part of the control was hit and act accordingly.
411 * To call Macintosh control routines we must have the port set to the
412 * window containing the control. We will then test which part of the
413 * control was hit and act accordingly.
416414 */
417415
418416 destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin));
460458 * ScaleActionProc --
461459 *
462460 * Callback procedure used by the Macintosh toolbox call
463 * HandleControlClick. This call will update the display
464 * while the scrollbar is being manipulated by the user.
461 * HandleControlClick. This call will update the display while the
462 * scrollbar is being manipulated by the user.
465463 *
466464 * Results:
467465 * None.
485483 #endif
486484 value = GetControlValue(theControl);
487485 TkScaleSetValue(scalePtr, value, 1, 1);
488 Tcl_Preserve((ClientData) scalePtr);
486 Tcl_Preserve(scalePtr);
489487 TkMacOSXRunTclEventLoop();
490 Tcl_Release((ClientData) scalePtr);
488 Tcl_Release(scalePtr);
491489 }
492490 #endif
493491
77 * Copyright 2001-2009, Apple Inc.
88 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
99 * Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC.
10 * Copyright (c) 2018 Marc Culler
10 * Copyright (c) 2018-2019 Marc Culler
11 *
1112 * See the file "license.terms" for information on usage and redistribution
1213 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
1314 */
1617 #include "tkScrollbar.h"
1718 #include "tkMacOSXPrivate.h"
1819
19
20 #define MIN_SCROLLBAR_VALUE 0
21
2220 /*
2321 * Minimum slider length, in pixels (designed to make sure that the slider is
2422 * always easy to grab with the mouse).
2523 */
2624
27 #define MIN_SLIDER_LENGTH 5
28
29 /*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.*/
25 #define MIN_SLIDER_LENGTH 18
26 #define MIN_GAP 4
27
28 /*
29 * Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.
30 */
31
3032 #ifdef __LP64__
31 #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
33 #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
3234 #else
33 #define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
35 #define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
3436 #endif /* __LP64__ */
3537
3638 /*
3739 * Apple reversed the scroll direction with the release of OSX 10.7 Lion.
3840 */
3941
40 #define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138)
42 #define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138)
4143
4244 /*
4345 * Declaration of an extended scrollbar structure with Mac specific additions.
4749 TkScrollbar information; /* Generic scrollbar info. */
4850 GC troughGC; /* For drawing trough. */
4951 GC copyGC; /* Used for copying from pixmap onto screen. */
50 Bool buttonDown; /* Is the mouse button down? */
52 Bool buttonDown; /* Is the mouse button down? */
5153 Bool mouseOver; /* Is the pointer over the scrollbar. */
52 HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */
54 HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */
5355 } MacScrollbar;
5456
5557 /* Used to initialize a MacScrollbar's info field. */
6870
6971 const Tk_ClassProcs tkpScrollbarProcs = {
7072 sizeof(Tk_ClassProcs), /* size */
71 NULL, /* worldChangedProc */
72 NULL, /* createProc */
73 NULL /* modalProc */
73 NULL, /* worldChangedProc */
74 NULL, /* createProc */
75 NULL /* modalProc */
7476 };
7577
76
77 /* Information on scrollbar layout, metrics, and draw info.*/
78 /*
79 * Information on scrollbar layout, metrics, and draw info.
80 */
81
7882 typedef struct ScrollbarMetrics {
7983 SInt32 width, minThumbHeight;
8084 int minHeight, topArrowHeight, bottomArrowHeight;
8185 NSControlSize controlSize;
8286 } ScrollbarMetrics;
8387
84
8588 static ScrollbarMetrics metrics = {
86 15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */
89 /* kThemeScrollBarMedium */
90 15, MIN_SLIDER_LENGTH, 26, 14, 14, kControlSizeNormal
8791 };
8892
89
9093 /*
9194 * Declarations of static functions defined later in this file:
9295 */
9396
94 static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr);
95 static int ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr);
96 static void UpdateControlValues(TkScrollbar *scrollPtr);
97
97 static void ScrollbarEventProc(ClientData clientData,
98 XEvent *eventPtr);
99 static int ScrollbarEvent(TkScrollbar *scrollPtr,
100 XEvent *eventPtr);
101 static void UpdateControlValues(TkScrollbar *scrollPtr);
102
98103 /*
99104 *----------------------------------------------------------------------
100105 *
113118
114119 TkScrollbar *
115120 TkpCreateScrollbar(
116 Tk_Window tkwin)
117 {
118
119 MacScrollbar *scrollPtr = (MacScrollbar *)ckalloc(sizeof(MacScrollbar));
120
121 scrollPtr->troughGC = None;
122 scrollPtr->copyGC = None;
121 Tk_Window tkwin)
122 {
123 MacScrollbar *scrollPtr = ckalloc(sizeof(MacScrollbar));
124
125 scrollPtr->troughGC = NULL;
126 scrollPtr->copyGC = NULL;
123127 scrollPtr->info = defaultInfo;
124128 scrollPtr->buttonDown = false;
125
129
126130 Tk_CreateEventHandler(tkwin,
127 ExposureMask |
128 StructureNotifyMask |
129 FocusChangeMask |
130 ButtonPressMask |
131 ButtonReleaseMask |
132 EnterWindowMask |
133 LeaveWindowMask |
134 VisibilityChangeMask,
135 ScrollbarEventProc, scrollPtr);
131 ExposureMask |
132 StructureNotifyMask |
133 FocusChangeMask |
134 ButtonPressMask |
135 ButtonReleaseMask |
136 EnterWindowMask |
137 LeaveWindowMask |
138 VisibilityChangeMask,
139 ScrollbarEventProc, scrollPtr);
136140
137141 return (TkScrollbar *) scrollPtr;
138142 }
143147 * TkpDisplayScrollbar --
144148 *
145149 * This procedure redraws the contents of a scrollbar window. It is
146 * invoked as a do-when-idle handler, so it only runs when there's
147 * nothing else for the application to do.
150 * invoked as a do-when-idle handler, so it only runs when there's nothing
151 * else for the application to do.
148152 *
149153 * Results:
150154 * None.
155159 *--------------------------------------------------------------
156160 */
157161
162 #if MAC_OS_X_VERSION_MAX_ALLOWED > 1080
163
164 /*
165 * This stand-alone drawing function is used on macOS 10.9 and newer because
166 * the HIToolbox does not draw the scrollbar thumb at the expected size on
167 * those systems. The thumb is drawn too large, causing a mouse click on the
168 * thumb to be interpreted as a mouse click in the trough.
169 */
170
171 static void drawMacScrollbar(
172 TkScrollbar *scrollPtr,
173 MacScrollbar *msPtr,
174 CGContextRef context)
175 {
176 MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
177 NSView *view = TkMacOSXDrawableView(macWin);
178 CGPathRef path;
179 CGPoint inner[2], outer[2], thumbOrigin;
180 CGSize thumbSize;
181 CGRect troughBounds = msPtr->info.bounds;
182 troughBounds.origin.y = [view bounds].size.height -
183 (troughBounds.origin.y + troughBounds.size.height);
184 if (scrollPtr->vertical) {
185 thumbOrigin.x = troughBounds.origin.x + MIN_GAP;
186 thumbOrigin.y = troughBounds.origin.y + scrollPtr->sliderFirst;
187 thumbSize.width = troughBounds.size.width - 2*MIN_GAP + 1;
188 thumbSize.height = scrollPtr->sliderLast - scrollPtr->sliderFirst;
189 inner[0] = troughBounds.origin;
190 inner[1] = CGPointMake(inner[0].x,
191 inner[0].y + troughBounds.size.height);
192 outer[0] = CGPointMake(inner[0].x + troughBounds.size.width - 1,
193 inner[0].y);
194 outer[1] = CGPointMake(outer[0].x, inner[1].y);
195 } else {
196 thumbOrigin.x = troughBounds.origin.x + scrollPtr->sliderFirst;
197 thumbOrigin.y = troughBounds.origin.y + MIN_GAP;
198 thumbSize.width = scrollPtr->sliderLast - scrollPtr->sliderFirst;
199 thumbSize.height = troughBounds.size.height - 2*MIN_GAP + 1;
200 inner[0] = troughBounds.origin;
201 inner[1] = CGPointMake(inner[0].x + troughBounds.size.width,
202 inner[0].y + 1);
203 outer[0] = CGPointMake(inner[0].x,
204 inner[0].y + troughBounds.size.height);
205 outer[1] = CGPointMake(inner[1].x, outer[0].y);
206 }
207 CGContextSetShouldAntialias(context, false);
208 CGContextSetGrayFillColor(context, 250.0 / 255, 1.0);
209 CGContextFillRect(context, troughBounds);
210 CGContextSetGrayStrokeColor(context, 232.0 / 255, 1.0);
211 CGContextStrokeLineSegments(context, inner, 2);
212 CGContextSetGrayStrokeColor(context, 238.0 / 255, 1.0);
213 CGContextStrokeLineSegments(context, outer, 2);
214
215 /*
216 * Do not display the thumb unless scrolling is possible, in accordance
217 * with macOS behavior.
218 *
219 * Native scrollbars and Ttk scrollbars are always 15 pixels wide, but we
220 * allow Tk scrollbars to have any width, even if it looks bad. To prevent
221 * sporadic assertion errors when drawing skinny thumbs we must make sure
222 * the radius is at most half the width.
223 */
224
225 if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) {
226 CGRect thumbBounds = {thumbOrigin, thumbSize};
227 int width = scrollPtr->vertical ? thumbSize.width : thumbSize.height;
228 int radius = width >= 8 ? 4 : width >> 1;
229 path = CGPathCreateWithRoundedRect(thumbBounds, radius, radius, NULL);
230 CGContextBeginPath(context);
231 CGContextAddPath(context, path);
232 if (msPtr->info.trackInfo.scrollbar.pressState != 0) {
233 CGContextSetGrayFillColor(context, 133.0 / 255, 1.0);
234 } else {
235 CGContextSetGrayFillColor(context, 200.0 / 255, 1.0);
236 }
237 CGContextSetShouldAntialias(context, true);
238 CGContextFillPath(context);
239 CFRelease(path);
240 }
241 }
242 #endif
243
158244 void
159245 TkpDisplayScrollbar(
160 ClientData clientData) /* Information about window. */
161 {
162 register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
246 ClientData clientData) /* Information about window. */
247 {
248 register TkScrollbar *scrollPtr = clientData;
163249 MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
164250 register Tk_Window tkwin = scrollPtr->tkwin;
165251 TkWindow *winPtr = (TkWindow *) tkwin;
168254 scrollPtr->flags &= ~REDRAW_PENDING;
169255
170256 if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
171 return;
172 }
173
174 MacDrawable *macWin = (MacDrawable *) winPtr->window;
257 return;
258 }
259
260 MacDrawable *macWin = (MacDrawable *) winPtr->window;
175261 NSView *view = TkMacOSXDrawableView(macWin);
176 if (!view ||
177 macWin->flags & TK_DO_NOT_DRAW ||
178 !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
179 return;
180 }
262
263 if ((view == NULL)
264 || (macWin->flags & TK_DO_NOT_DRAW)
265 || !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
266 return;
267 }
268
269 /*
270 * Transform NSView coordinates to CoreGraphics coordinates.
271 */
181272
182273 CGFloat viewHeight = [view bounds].size.height;
183 CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
184 .ty = viewHeight};
274 CGAffineTransform t = {
275 .a = 1, .b = 0,
276 .c = 0, .d = -1,
277 .tx = 0, .ty = viewHeight
278 };
279
185280 CGContextConcatCTM(dc.context, t);
186281
187 /*Draw a 3D rectangle to provide a base for the native scrollbar.*/
282 /*
283 * Draw a 3D rectangle to provide a base for the native scrollbar.
284 */
285
188286 if (scrollPtr->highlightWidth != 0) {
189287 GC fgGC, bgGC;
190288
195293 fgGC = bgGC;
196294 }
197295 TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth,
198 (Pixmap) macWin);
296 (Pixmap) macWin);
199297 }
200298
201299 Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
202 scrollPtr->highlightWidth, scrollPtr->highlightWidth,
203 Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
204 Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
205 scrollPtr->borderWidth, scrollPtr->relief);
300 scrollPtr->highlightWidth, scrollPtr->highlightWidth,
301 Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
302 Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
303 scrollPtr->borderWidth, scrollPtr->relief);
206304 Tk_Fill3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
207 scrollPtr->inset, scrollPtr->inset,
208 Tk_Width(tkwin) - 2*scrollPtr->inset,
209 Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
210
211 /* Update values and then draw the native scrollbar over the rectangle.*/
305 scrollPtr->inset, scrollPtr->inset,
306 Tk_Width(tkwin) - 2*scrollPtr->inset,
307 Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
308
309 /*
310 * Update values and then draw the native scrollbar over the rectangle.
311 */
312
212313 UpdateControlValues(scrollPtr);
213314
214315 if (SNOW_LEOPARD_STYLE) {
215 HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationInverted);
316 HIThemeDrawTrack(&msPtr->info, 0, dc.context,
317 kHIThemeOrientationInverted);
318 } else if ([NSApp macMinorVersion] <= 8) {
319 HIThemeDrawTrack(&msPtr->info, 0, dc.context,
320 kHIThemeOrientationNormal);
216321 } else {
217 HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationNormal);
322 #if MAC_OS_X_VERSION_MAX_ALLOWED > 1080
323
324 /*
325 * Switch back to NSView coordinates and draw a modern scrollbar.
326 */
327
328 CGContextConcatCTM(dc.context, t);
329 drawMacScrollbar(scrollPtr, msPtr, dc.context);
330 #endif
218331 }
219332 TkMacOSXRestoreDrawingContext(&dc);
220
221333 scrollPtr->flags &= ~REDRAW_PENDING;
222334 }
223
335
224336 /*
225337 *----------------------------------------------------------------------
226338 *
239351 *----------------------------------------------------------------------
240352 */
241353
242
243
244354 extern void
245355 TkpComputeScrollbarGeometry(
246356 register TkScrollbar *scrollPtr)
247 /* Scrollbar whose geometry may have
248 * changed. */
249 {
250
251 /*
252 * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to
253 * account for some differences between macOS and X11. The Unix scrollbar
254 * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the
255 * scrollbars by default have both arrow buttons at the bottom or right.
256 * (There is a preferences setting to use the Unix layout, but we are not
257 * supporting that!) On more recent versions of macOS there are no arrow
258 * buttons at all. The case of no arrow buttons can be handled as a special
259 * case of having both buttons at the end, but where scrollPtr->arrowLength
260 * happens to be zero. To adjust for having both arrows at the same end we
261 * shift the scrollbar up by the arrowLength.
262 */
357 /* Scrollbar whose geometry may have
358 * changed. */
359 {
360 /*
361 * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to
362 * account for some differences between macOS and X11. The Unix scrollbar
363 * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the
364 * scrollbars by default have both arrow buttons at the bottom or right.
365 * (There is a preferences setting to use the Unix layout, but we are not
366 * supporting that!) On more recent versions of macOS there are no arrow
367 * buttons at all. The case of no arrow buttons can be handled as a special
368 * case of having both buttons at the end, but where scrollPtr->arrowLength
369 * happens to be zero. To adjust for having both arrows at the same end we
370 * shift the scrollbar up by the arrowLength.
371 */
263372
264373 int fieldLength;
265374
266375 if (scrollPtr->highlightWidth < 0) {
267 scrollPtr->highlightWidth = 0;
376 scrollPtr->highlightWidth = 0;
268377 }
269378 scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
270379 if ([NSApp macMinorVersion] == 6) {
271 scrollPtr->arrowLength = scrollPtr->width;
380 scrollPtr->arrowLength = scrollPtr->width;
272381 } else {
273 scrollPtr->arrowLength = 0;
382 scrollPtr->arrowLength = 0;
274383 }
275384 fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
276 : Tk_Width(scrollPtr->tkwin))
277 - 2*(scrollPtr->arrowLength + scrollPtr->inset);
385 : Tk_Width(scrollPtr->tkwin))
386 - 2*(scrollPtr->arrowLength + scrollPtr->inset);
278387 if (fieldLength < 0) {
279 fieldLength = 0;
388 fieldLength = 0;
280389 }
281390 scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;
282391 scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;
283392
284393 /*
285 * Adjust the slider so that some piece of it is always displayed in the
286 * scrollbar and so that it has at least a minimal width (so it can be
287 * grabbed with the mouse).
288 */
289
394 * Adjust the slider so that it has at least a minimal size and so there
395 * is a small gap on either end which can be used to scroll by one page.
396 */
397
398 if (scrollPtr->sliderFirst < MIN_GAP) {
399 scrollPtr->sliderFirst = MIN_GAP;
400 scrollPtr->sliderLast += MIN_GAP;
401 }
402 if (scrollPtr->sliderLast > fieldLength - MIN_GAP) {
403 scrollPtr->sliderLast = fieldLength - MIN_GAP;
404 scrollPtr->sliderFirst -= MIN_GAP;
405 }
290406 if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) {
291 scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;
292 }
293 if (scrollPtr->sliderFirst < 0) {
294 scrollPtr->sliderFirst = 0;
407 scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;
295408 }
296409 if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) {
297 scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
298 }
299 if (scrollPtr->sliderLast > fieldLength) {
300 scrollPtr->sliderLast = fieldLength;
410 scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
301411 }
302412 scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset;
303413 scrollPtr->sliderLast += scrollPtr->inset;
309419 * be redisplayed.
310420 */
311421
312 if (scrollPtr->vertical) {
313 Tk_GeometryRequest(scrollPtr->tkwin,
314 scrollPtr->width + 2*scrollPtr->inset,
315 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
316 + scrollPtr->inset) + metrics.minThumbHeight);
422 if (scrollPtr->vertical) {
423 Tk_GeometryRequest(scrollPtr->tkwin,
424 scrollPtr->width + 2*scrollPtr->inset,
425 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
426 + scrollPtr->inset) + metrics.minThumbHeight);
317427 } else {
318 Tk_GeometryRequest(scrollPtr->tkwin,
319 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
320 + scrollPtr->inset) + metrics.minThumbHeight,
321 scrollPtr->width + 2*scrollPtr->inset);
428 Tk_GeometryRequest(scrollPtr->tkwin,
429 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
430 + scrollPtr->inset) + metrics.minThumbHeight,
431 scrollPtr->width + 2*scrollPtr->inset);
322432 }
323433 Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
324434 }
325
435
326436 /*
327437 *----------------------------------------------------------------------
328438 *
341451
342452 void
343453 TkpDestroyScrollbar(
344 TkScrollbar *scrollPtr)
345 {
346 MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr;
454 TkScrollbar *scrollPtr)
455 {
456 MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
347457
348458 if (macScrollPtr->troughGC != None) {
349459 Tk_FreeGC(scrollPtr->display, macScrollPtr->troughGC);
352462 Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC);
353463 }
354464 }
355
465
356466 /*
357467 *----------------------------------------------------------------------
358468 *
359469 * TkpConfigureScrollbar --
360470 *
361 * This procedure is called after the generic code has finished
362 * processing configuration options, in order to configure platform
363 * specific options. There are no such option on the Mac, however.
471 * This procedure is called after the generic code has finished processing
472 * configuration options, in order to configure platform specific options.
473 * There are no such option on the Mac, however.
364474 *
365475 * Results:
366476 * None.
373483
374484 void
375485 TkpConfigureScrollbar(
376 register TkScrollbar *scrollPtr)
377 {
378
379 }
380
486 register TkScrollbar *scrollPtr)
487 {
488 /* empty */
489 }
490
381491 /*
382492 *--------------------------------------------------------------
383493 *
402512 /* Scrollbar widget record. */
403513 int x, int y) /* Coordinates within scrollPtr's window. */
404514 {
405
406 /*
407 * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment
408 * since it does not involve the arrow buttons.
409 */
515 /*
516 * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment
517 * since it does not involve the arrow buttons.
518 */
410519
411520 int length, width, tmp;
412521 register const int inset = scrollPtr->inset;
413522
414523 if (scrollPtr->vertical) {
415 length = Tk_Height(scrollPtr->tkwin);
416 width = Tk_Width(scrollPtr->tkwin);
524 length = Tk_Height(scrollPtr->tkwin);
525 width = Tk_Width(scrollPtr->tkwin);
417526 } else {
418 tmp = x;
419 x = y;
420 y = tmp;
421 length = Tk_Width(scrollPtr->tkwin);
422 width = Tk_Height(scrollPtr->tkwin);
527 tmp = x;
528 x = y;
529 y = tmp;
530 length = Tk_Width(scrollPtr->tkwin);
531 width = Tk_Height(scrollPtr->tkwin);
423532 }
424533
425534 if (x < inset || x >= width - inset ||
426 y < inset || y >= length - inset) {
427 return OUTSIDE;
535 y < inset || y >= length - inset) {
536 return OUTSIDE;
428537 }
429538
430539 /*
435544 */
436545
437546 if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) {
438 return TOP_GAP;
439 }
440 if (y < scrollPtr->sliderLast) {
441 return SLIDER;
442 }
443 if (y < length - (2*scrollPtr->arrowLength + inset)) {
444 return BOTTOM_GAP;
445 }
446 /* On systems newer than 10.6 we have already returned. */
447 if (y < length - (scrollPtr->arrowLength + inset)) {
448 return TOP_ARROW;
449 }
450 return BOTTOM_ARROW;
451 }
452
547 return TOP_GAP;
548 }
549 if (y < scrollPtr->sliderLast) {
550 return SLIDER;
551 }
552 if (y < length - (2*scrollPtr->arrowLength + inset)) {
553 return BOTTOM_GAP;
554 }
555
556 /*
557 * On systems newer than 10.6 we have already returned.
558 */
559
560 if (y < length - (scrollPtr->arrowLength + inset)) {
561 return TOP_ARROW;
562 }
563 return BOTTOM_ARROW;
564 }
565
453566 /*
454567 *--------------------------------------------------------------
455568 *
456569 * UpdateControlValues --
457570 *
458 * This procedure updates the Macintosh scrollbar control to
459 * display the values defined by the Tk scrollbar. This is the
460 * key interface to the Mac-native scrollbar; the Unix bindings
461 * drive scrolling in the Tk window and all the Mac scrollbar has
462 * to do is redraw itself.
571 * This procedure updates the Macintosh scrollbar control to display the
572 * values defined by the Tk scrollbar. This is the key interface to the
573 * Mac-native scrollbar; the Unix bindings drive scrolling in the Tk
574 * window and all the Mac scrollbar has to do is redraw itself.
463575 *
464576 * Results:
465577 * None.
472584
473585 static void
474586 UpdateControlValues(
475 TkScrollbar *scrollPtr) /* Scrollbar data struct. */
476 {
477 MacScrollbar *msPtr = (MacScrollbar *)scrollPtr;
587 TkScrollbar *scrollPtr) /* Scrollbar data struct. */
588 {
589 MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
478590 Tk_Window tkwin = scrollPtr->tkwin;
479591 MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
480592 double dViewSize;
481 HIRect contrlRect;
593 HIRect contrlRect;
482594 short width, height;
483595
484596 NSView *view = TkMacOSXDrawableView(macWin);
485597 CGFloat viewHeight = [view bounds].size.height;
486598 NSRect frame;
599
487600 frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
488 Tk_Height(tkwin));
601 Tk_Height(tkwin));
489602 frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);
490603 frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
491604
493606 msPtr->info.bounds = contrlRect;
494607
495608 width = contrlRect.size.width;
496 height = contrlRect.size.height;
609 height = contrlRect.size.height - scrollPtr->arrowLength;
497610
498611 /*
499612 * Ensure we set scrollbar control bounds only once all size adjustments
502615
503616 msPtr->info.bounds = contrlRect;
504617 if (scrollPtr->vertical) {
505 msPtr->info.attributes &= ~kThemeTrackHorizontal;
618 msPtr->info.attributes &= ~kThemeTrackHorizontal;
506619 } else {
507 msPtr->info.attributes |= kThemeTrackHorizontal;
620 msPtr->info.attributes |= kThemeTrackHorizontal;
508621 }
509622
510623 /*
517630 * the view area.
518631 */
519632
520 double maximum = 100, factor;
521 factor = RangeToFactor(maximum);
522 dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction)
523 * factor;
524 msPtr->info.max = MIN_SCROLLBAR_VALUE +
525 factor - dViewSize;
633 double factor = RangeToFactor(100.0);
634 dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor;
635 msPtr->info.max = factor - dViewSize;
526636 msPtr->info.trackInfo.scrollbar.viewsize = dViewSize;
527637 if (scrollPtr->vertical) {
528 if (SNOW_LEOPARD_STYLE) {
638 if (SNOW_LEOPARD_STYLE) {
639 msPtr->info.value = factor * scrollPtr->firstFraction;
640 } else {
641 msPtr->info.value = msPtr->info.max -
642 factor * scrollPtr->firstFraction;
643 }
644 } else {
529645 msPtr->info.value = factor * scrollPtr->firstFraction;
530 } else {
531 msPtr->info.value = msPtr->info.max - factor * scrollPtr->firstFraction;
532 }
533 } else {
534 msPtr->info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction;
535 }
536
537 if((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)
538 || height <= metrics.minHeight) {
646 }
647
648 if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)
649 || height <= metrics.minHeight) {
539650 msPtr->info.enableState = kThemeTrackHideTrack;
540651 } else {
541652 msPtr->info.enableState = kThemeTrackActive;
542 msPtr->info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
543 }
544
545 }
546
653 msPtr->info.attributes =
654 kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
655 }
656 }
657
547658 /*
548659 *--------------------------------------------------------------
549660 *
550661 * ScrollbarEvent --
551662 *
552 * This procedure is invoked in response to <ButtonPress>, <ButtonRelease>,
553 * <EnterNotify>, and <LeaveNotify> events. The Scrollbar appearance is
554 * modified for each event.
663 * This procedure is invoked in response to <ButtonPress>,
664 * <ButtonRelease>, <EnterNotify>, and <LeaveNotify> events. The
665 * Scrollbar appearance is modified for each event.
555666 *
556667 *--------------------------------------------------------------
557668 */
558669
559670 static int
560 ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr)
561 {
562 MacScrollbar *msPtr = (MacScrollbar *)scrollPtr;
563
564 /* The pressState does not indicate whether the moused button was
565 * pressed at some location in the Scrollbar. Rather, it indicates
566 * that the scrollbar should appear as if it were pressed in that
567 * location. The standard Mac behavior is that once the button is
568 * pressed inside the Scrollbar the appearance should not change until
569 * the button is released, even if the mouse moves outside of the
570 * scrollbar. However, if the mouse lies over the scrollbar but the
571 * button is not pressed then the appearance should be the same as if
572 * the button had been pressed on the slider, i.e. kThemeThumbPressed.
573 * See the file Appearance.r, or HIToolbox.bridgesupport on 10.14.
671 ScrollbarEvent(
672 TkScrollbar *scrollPtr,
673 XEvent *eventPtr)
674 {
675 MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
676
677 /*
678 * The pressState does not indicate whether the moused button was pressed
679 * at some location in the Scrollbar. Rather, it indicates that the
680 * scrollbar should appear as if it were pressed in that location. The
681 * standard Mac behavior is that once the button is pressed inside the
682 * Scrollbar the appearance should not change until the button is released,
683 * even if the mouse moves outside of the scrollbar. However, if the mouse
684 * lies over the scrollbar but the button is not pressed then the
685 * appearance should be the same as if the button had been pressed on the
686 * slider, i.e. kThemeThumbPressed. See the file Appearance.r, or
687 * HIToolbox.bridgesupport on 10.14.
574688 */
575689
576690 if (eventPtr->type == ButtonPress) {
577691 msPtr->buttonDown = true;
578692 UpdateControlValues(scrollPtr);
693
579694 int where = TkpScrollbarPosition(scrollPtr,
580 eventPtr->xbutton.x,
581 eventPtr->xbutton.y);
582 switch(where) {
695 eventPtr->xbutton.x, eventPtr->xbutton.y);
696
697 switch (where) {
583698 case OUTSIDE:
584699 msPtr->info.trackInfo.scrollbar.pressState = 0;
585700 break;
590705 msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
591706 break;
592707 case BOTTOM_GAP:
593 msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomTrackPressed;
708 msPtr->info.trackInfo.scrollbar.pressState =
709 kThemeBottomTrackPressed;
594710 break;
595711 case TOP_ARROW:
596 /* This looks wrong and the docs say it is wrong but it works. */
597 msPtr->info.trackInfo.scrollbar.pressState = kThemeTopInsideArrowPressed;
712
713 /*
714 * This looks wrong and the docs say it is wrong but it works.
715 */
716
717 msPtr->info.trackInfo.scrollbar.pressState =
718 kThemeTopInsideArrowPressed;
598719 break;
599720 case BOTTOM_ARROW:
600 msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomOutsideArrowPressed;
721 msPtr->info.trackInfo.scrollbar.pressState =
722 kThemeBottomOutsideArrowPressed;
601723 break;
602724 }
603725 }
619741 msPtr->info.trackInfo.scrollbar.pressState = 0;
620742 }
621743 }
744 TkScrollbarEventuallyRedraw(scrollPtr);
622745 return TCL_OK;
623746 }
624
625
626
747
627748 /*
628749 *--------------------------------------------------------------
629750 *
644765
645766 static void
646767 ScrollbarEventProc(
647 ClientData clientData, /* Information about window. */
648 XEvent *eventPtr) /* Information about event. */
768 ClientData clientData, /* Information about window. */
769 XEvent *eventPtr) /* Information about event. */
649770 {
650771 TkScrollbar *scrollPtr = clientData;
651772
667788 TkScrollbarEventProc(clientData, eventPtr);
668789 }
669790 }
670
791
671792 /*
672793 * Local Variables:
673794 * mode: objc
5050 * A registry of all interpreters for a display is kept in a property
5151 * "InterpRegistry" on the root window of the display. It is organized as a
5252 * series of zero or more concatenated strings (in no particular order), each
53 * of the form
53 * of the form:
5454 * window space name '\0'
5555 * where "window" is the hex id of the comm. window to use to talk to an
5656 * interpreter named "name".
7777 * XFree; zero means use ckfree. */
7878 } NameRegistry;
7979
80 static int initialized = 0; /* A flag to denote if we have initialized
80 static int initialized = 0; /* A flag to denote if we have initialized
8181 * yet. */
8282
8383 static RegisteredInterp *interpListPtr = NULL;
324324 int objc, /* Number of arguments */
325325 Tcl_Obj *const objv[]) /* The arguments */
326326 {
327 const char *const sendOptions[] = {"-async", "-displayof", "-", NULL};
327 const char *const sendOptions[] = {"-async", "-displayof", "--", NULL};
328328 char *stringRep, *destName;
329329 /*int async = 0;*/
330330 int i, index, firstArg;
0 /*
1 * tkMacOSXServices.c --
2 *\
3 * This file allows the integration of Tk and the Cocoa NSServices API.
4 *
5 * Copyright (c) 2010-2019 Kevin Walzer/WordTech Communications LLC.
6 * Copyright (c) 2019 Marc Culler.
7 * Copyright (c) 2010 Adrian Robert.
8 *
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 */
12
13 #include <tkInt.h>
14 #include <tkMacOSXInt.h>
15
16 /*
17 * Event proc which calls the PerformService procedure.
18 */
19
20 static int
21 ServicesEventProc(
22 Tcl_Event *event,
23 int flags)
24 {
25 TkMainInfo *info = TkGetMainInfoList();
26 Tcl_GlobalEval(info->interp, "::tk::mac::PerformService");
27 return 1;
28 }
29
30 /*
31 * The Wish application can send the current selection in the Tk clipboard
32 * to other applications which accept messages of type NSString. The TkService
33 * object provides this service via its provideService method. (The method
34 * must be specified in the application's Info.plist file for this to work.)
35 */
36
37 @interface TkService : NSObject {
38
39 }
40
41 + (void) initialize;
42 - (void) provideService:(NSPasteboard *)pboard
43 userData:(NSString *)data
44 error:(NSString **)error;
45 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
46 types:(NSArray *)types;
47
48 @end
49
50 /*
51 * Class methods.
52 */
53
54 @implementation TkService
55
56 + (void) initialize {
57 NSArray *sendTypes = [NSArray arrayWithObjects:@"NSStringPboardType",
58 @"NSPasteboardTypeString", nil];
59 [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:sendTypes];
60 return;
61 }
62
63 /*
64 * Get the current Tk selection and copy it to the system pasteboard.
65 */
66
67 - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
68 types:(NSArray *)types
69 {
70 NSArray *typesDeclared = nil;
71 NSString *pboardType = nil;
72 TkMainInfo *info = TkGetMainInfoList();
73
74 for (NSString *typeString in types) {
75 if ([typeString isEqualToString:@"NSStringPboardType"] ||
76 [typeString isEqualToString:@"NSPasteboardTypeString"]) {
77 typesDeclared = [NSArray arrayWithObject:typeString];
78 pboardType = typeString;
79 break;
80 }
81 }
82 if (!typesDeclared) {
83 return NO;
84 }
85 Tcl_Eval(info->interp, "selection get");
86
87 char *copystring = Tcl_GetString(Tcl_GetObjResult(info->interp));
88 NSString *writestring = [NSString stringWithUTF8String:copystring];
89
90 [pboard declareTypes:typesDeclared owner:nil];
91 return [pboard setString:writestring forType:pboardType];
92 }
93
94 /*
95 * This is the method that actually calls the Tk service; it must be specified
96 * in Info.plist.
97 */
98
99 - (void)provideService:(NSPasteboard *)pboard
100 userData:(NSString *)data
101 error:(NSString **)error
102 {
103 NSString *pboardString = nil, *pboardType = nil;
104 NSArray *types = [pboard types];
105 Tcl_Event *event;
106
107 /*
108 * Get a string from the private pasteboard and copy it to the general
109 * pasteboard to make it available to other applications.
110 */
111
112 for (NSString *typeString in types) {
113 if ([typeString isEqualToString:@"NSStringPboardType"] ||
114 [typeString isEqualToString:@"NSPasteboardTypeString"]) {
115 pboardString = [pboard stringForType:typeString];
116 pboardType = typeString;
117 break;
118 }
119 }
120 if (pboardString) {
121 NSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard];
122 [generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil]
123 owner:nil];
124 [generalpasteboard setString:pboardString forType:pboardType];
125 event = ckalloc(sizeof(Tcl_Event));
126 event->proc = ServicesEventProc;
127 Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);
128 }
129 }
130 @end
131
132 /*
133 * Instantiate a TkService object and register it with the NSApplication.
134 * This is called exactly one time from TkpInit.
135 */
136
137 int
138 TkMacOSXServices_Init(
139 Tcl_Interp *interp)
140 {
141 /*
142 * Initialize an instance of TkService and register it with the NSApp.
143 */
144
145 TkService *service = [[TkService alloc] init];
146 [NSApp setServicesProvider:service];
147 return TCL_OK;
148 }
149
150 /*
151 * Local Variables:
152 * mode: objc
153 * c-basic-offset: 4
154 * fill-column: 79
155 * coding: utf-8
156 * End:
157 */
4848 *----------------------------------------------------------------------
4949 */
5050
51 void
51 int
5252 XDestroyWindow(
5353 Display *display, /* Display. */
5454 Window window) /* Window. */
6464 TkMacOSXSelDeadWindow(macWin->winPtr);
6565 macWin->toplevel->referenceCount--;
6666
67 if (!Tk_IsTopLevel(macWin->winPtr) ) {
67 if (!Tk_IsTopLevel(macWin->winPtr)) {
6868 TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
6969 if (macWin->winPtr->parentPtr != NULL) {
7070 TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
7171 }
7272 if (macWin->visRgn) {
7373 CFRelease(macWin->visRgn);
74 macWin->visRgn = NULL;
7475 }
7576 if (macWin->aboveVisRgn) {
7677 CFRelease(macWin->aboveVisRgn);
78 macWin->aboveVisRgn = NULL;
7779 }
7880 if (macWin->drawRgn) {
7981 CFRelease(macWin->drawRgn);
82 macWin->drawRgn = NULL;
8083 }
8184
8285 if (macWin->toplevel->referenceCount == 0) {
8386 ckfree(macWin->toplevel);
8487 }
8588 ckfree(macWin);
86 return;
89 return Success;
8790 }
8891 if (macWin->visRgn) {
8992 CFRelease(macWin->visRgn);
93 macWin->visRgn = NULL;
9094 }
9195 if (macWin->aboveVisRgn) {
9296 CFRelease(macWin->aboveVisRgn);
97 macWin->aboveVisRgn = NULL;
9398 }
9499 if (macWin->drawRgn) {
95100 CFRelease(macWin->drawRgn);
101 macWin->drawRgn = NULL;
96102 }
97103 macWin->view = nil;
98104
104110 if (macWin->toplevel->referenceCount == 0) {
105111 ckfree(macWin->toplevel);
106112 }
113 return Success;
107114 }
108115
109116 /*
123130 *----------------------------------------------------------------------
124131 */
125132
126 void
133 int
127134 XMapWindow(
128135 Display *display, /* Display. */
129136 Window window) /* Window. */
130137 {
131138 MacDrawable *macWin = (MacDrawable *) window;
139 TkWindow *winPtr = macWin->winPtr;
140 NSWindow *win = TkMacOSXDrawableWindow(window);
132141 XEvent event;
133142
134143 /*
144153 }
145154
146155 display->request++;
147 macWin->winPtr->flags |= TK_MAPPED;
148 if (Tk_IsTopLevel(macWin->winPtr)) {
149 if (!Tk_IsEmbedded(macWin->winPtr)) {
150 NSWindow *win = TkMacOSXDrawableWindow(window);
156 winPtr->flags |= TK_MAPPED;
157 if (Tk_IsTopLevel(winPtr)) {
158 if (!Tk_IsEmbedded(winPtr)) {
159
151160 /*
152 * We want to activate Tk when a toplevel is mapped
153 * but we must not supply YES here. This is because
154 * during Tk initialization the root window is mapped
155 * before applicationDidFinishLaunching returns. Forcing
156 * the app to activate too early can make the menu bar
157 * unresponsive.
161 * We want to activate Tk when a toplevel is mapped but we must not
162 * supply YES here. This is because during Tk initialization the
163 * root window is mapped before applicationDidFinishLaunching
164 * returns. Forcing the app to activate too early can make the menu
165 * bar unresponsive.
158166 */
167
168 TkMacOSXApplyWindowAttributes(winPtr, win);
169 [win setExcludedFromWindowsMenu:NO];
159170 [NSApp activateIgnoringOtherApps:NO];
160 if ( [win canBecomeKeyWindow] ) {
171 [[win contentView] setNeedsDisplay:YES];
172 if ([win canBecomeKeyWindow]) {
161173 [win makeKeyAndOrderFront:NSApp];
174 } else {
175 [win orderFrontRegardless];
162176 }
163 TkMacOSXApplyWindowAttributes(macWin->winPtr, win);
164177 } else {
178 TkWindow *contWinPtr = TkpGetOtherWindow(winPtr);
179
165180 /*
166181 * Rebuild the container's clipping region and display
167182 * the window.
168183 */
169 TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr);
170 TkMacOSXInvalClipRgns((Tk_Window)contWinPtr);
184
185 TkMacOSXInvalClipRgns((Tk_Window) contWinPtr);
171186 TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
172187 }
173 TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr);
188
189 TkMacOSXInvalClipRgns((Tk_Window) winPtr);
174190
175191 /*
176192 * We only need to send the MapNotify event for toplevel windows.
183199 event.xmap.window = window;
184200 event.xmap.type = MapNotify;
185201 event.xmap.event = window;
186 event.xmap.override_redirect = macWin->winPtr->atts.override_redirect;
202 event.xmap.override_redirect = winPtr->atts.override_redirect;
187203 Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
188204 } else {
205
189206 /*
190 * Rebuild the parent's clipping region and display the window.
191 *
207 * For non-toplevel windows, rebuild the parent's clipping region
208 * and redisplay the window.
192209 */
193210
194 TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
195 TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
211 TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
212 }
213
214 if ([NSApp isDrawing]) {
215 [[win contentView] setNeedsRedisplay:YES];
216 } else {
217 [[win contentView] setNeedsDisplay:YES];
196218 }
197219
198220 /*
203225 event.xany.display = display;
204226 event.xvisibility.type = VisibilityNotify;
205227 event.xvisibility.state = VisibilityUnobscured;
206 NotifyVisibility(macWin->winPtr, &event);
207
208 /*
209 * Make sure that subwindows get displayed.
210 */
211
212 GenerateConfigureNotify(macWin->winPtr, 1);
213
228 NotifyVisibility(winPtr, &event);
229 return Success;
214230 }
215231
216232 /*
264280 *----------------------------------------------------------------------
265281 */
266282
267 void
283 int
268284 XUnmapWindow(
269285 Display *display, /* Display. */
270286 Window window) /* Window. */
272288 MacDrawable *macWin = (MacDrawable *) window;
273289 TkWindow *winPtr = macWin->winPtr;
274290 TkWindow *parentPtr = winPtr->parentPtr;
291 NSWindow *win = TkMacOSXDrawableWindow(window);
275292 XEvent event;
276293
277294 display->request++;
278295 if (Tk_IsTopLevel(winPtr)) {
279296 if (!Tk_IsEmbedded(winPtr) &&
280297 winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
281 NSWindow *win = TkMacOSXDrawableWindow(window);
282
283 if ([win isVisible]) {
284 [[win parentWindow] removeChildWindow:win];
285 [win orderOut:NSApp];
286 }
298 [win orderOut:nil];
287299 }
288300 TkMacOSXInvalClipRgns((Tk_Window) winPtr);
289301
301313 event.xunmap.from_configure = false;
302314 Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
303315 } else {
304
305316 /*
306317 * Rebuild the visRgn clip region for the parent so it will be allowed
307 * to draw in the space from which this subwindow was removed.
318 * to draw in the space from which this subwindow was removed and then
319 * redraw the window.
308320 */
309321
310322 if (parentPtr && parentPtr->privatePtr->visRgn) {
311 TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(parentPtr->privatePtr),
312 parentPtr->privatePtr->visRgn);
323 TkMacOSXInvalidateViewRegion(
324 TkMacOSXDrawableView(parentPtr->privatePtr),
325 parentPtr->privatePtr->visRgn);
313326 }
314327 TkMacOSXInvalClipRgns((Tk_Window) parentPtr);
315328 TkMacOSXUpdateClipRgn(parentPtr);
316329 }
317330 winPtr->flags &= ~TK_MAPPED;
331 if ([NSApp isDrawing]) {
332 [[win contentView] setNeedsRedisplay:YES];
333 } else {
334 [[win contentView] setNeedsDisplay:YES];
335 }
336 return Success;
318337 }
319338
320339 /*
334353 *----------------------------------------------------------------------
335354 */
336355
337 void
356 int
338357 XResizeWindow(
339358 Display *display, /* Display. */
340359 Window window, /* Window. */
342361 unsigned int height)
343362 {
344363 MacDrawable *macWin = (MacDrawable *) window;
364
345365 display->request++;
346366 if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
347367 NSWindow *w = macWin->winPtr->wmInfoPtr->window;
368
348369 if (w) {
349370 NSRect r = [w contentRectForFrameRect:[w frame]];
371
350372 r.origin.y += r.size.height - height;
351373 r.size.width = width;
352374 r.size.height = height;
355377 } else {
356378 MoveResizeWindow(macWin);
357379 }
380 return Success;
358381 }
359382
360383 /*
362385 *
363386 * XMoveResizeWindow --
364387 *
365 * Move or resize a given X window. See X windows documentation
366 * for further details.
367 *
368 * Results:
369 * None.
370 *
371 * Side effects:
372 * None.
373 *
374 *----------------------------------------------------------------------
375 */
376
377 void
388 * Move or resize a given X window. See X windows documentation for
389 * further details.
390 *
391 * Results:
392 * None.
393 *
394 * Side effects:
395 * None.
396 *
397 *----------------------------------------------------------------------
398 */
399
400 int
378401 XMoveResizeWindow(
379402 Display *display, /* Display. */
380403 Window window, /* Window. */
387410 display->request++;
388411 if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
389412 NSWindow *w = macWin->winPtr->wmInfoPtr->window;
413
390414 if (w) {
391
392 /* We explicitly convert everything to doubles so we don't get
415 /*
416 * We explicitly convert everything to doubles so we don't get
393417 * surprised (again) by what happens when you do arithmetic with
394418 * unsigned ints.
395419 */
396420
397 CGFloat X = (CGFloat)x;
398 CGFloat Y = (CGFloat)y;
399 CGFloat Width = (CGFloat)width;
400 CGFloat Height = (CGFloat)height;
401 CGFloat XOff = (CGFloat)macWin->winPtr->wmInfoPtr->xInParent;
402 CGFloat YOff = (CGFloat)macWin->winPtr->wmInfoPtr->yInParent;
403 NSRect r = NSMakeRect(X + XOff,
404 tkMacOSXZeroScreenHeight - Y - YOff - Height,
405 Width, Height);
421 CGFloat X = (CGFloat) x;
422 CGFloat Y = (CGFloat) y;
423 CGFloat Width = (CGFloat) width;
424 CGFloat Height = (CGFloat) height;
425 CGFloat XOff = (CGFloat) macWin->winPtr->wmInfoPtr->xInParent;
426 CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent;
427 NSRect r = NSMakeRect(
428 X + XOff, TkMacOSXZeroScreenHeight() - Y - YOff - Height,
429 Width, Height);
430
406431 [w setFrame:[w frameRectForContentRect:r] display:YES];
407432 }
408433 } else {
409434 MoveResizeWindow(macWin);
410435 }
436 return Success;
411437 }
412438
413439 /*
415441 *
416442 * XMoveWindow --
417443 *
418 * Move a given X window. See X windows documentation for further
419 * details.
420 *
421 * Results:
422 * None.
423 *
424 * Side effects:
425 * None.
426 *
427 *----------------------------------------------------------------------
428 */
429
430 void
444 * Move a given X window. See X windows documentation for further details.
445 *
446 * Results:
447 * None.
448 *
449 * Side effects:
450 * None.
451 *
452 *----------------------------------------------------------------------
453 */
454
455 int
431456 XMoveWindow(
432457 Display *display, /* Display. */
433458 Window window, /* Window. */
438463 display->request++;
439464 if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
440465 NSWindow *w = macWin->winPtr->wmInfoPtr->window;
466
441467 if (w) {
442 [w setFrameTopLeftPoint:NSMakePoint(x, tkMacOSXZeroScreenHeight - y)];
468 [w setFrameTopLeftPoint: NSMakePoint(
469 x, TkMacOSXZeroScreenHeight() - y)];
443470 }
444471 } else {
445472 MoveResizeWindow(macWin);
446473 }
474 return Success;
447475 }
448476
449477 /*
480508 if (contWinPtr) {
481509 macParent = contWinPtr->privatePtr;
482510 } else {
483
484511 /*
485512 * Here we should handle out of process embedding. At this point,
486513 * we are assuming that the changes.x,y is not maintained, if you
489516 */
490517 }
491518 } else {
492
493519 /*
494520 * TODO: update all xOff & yOffs
495521 */
570596 *----------------------------------------------------------------------
571597 */
572598
573 void
599 int
574600 XRaiseWindow(
575601 Display *display, /* Display. */
576602 Window window) /* Window. */
581607 if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
582608 TkWmRestackToplevel(macWin->winPtr, Above, NULL);
583609 } else {
584
585610 /*
586611 * TODO: this should generate damage
587612 */
588613 }
614 return Success;
589615 }
590616
591617 #if 0
616642 if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
617643 TkWmRestackToplevel(macWin->winPtr, Below, NULL);
618644 } else {
619
620645 /*
621646 * TODO: this should generate damage
622647 */
642667 *----------------------------------------------------------------------
643668 */
644669
645 void
670 int
646671 XConfigureWindow(
647672 Display *display, /* Display. */
648673 Window w, /* Window. */
679704 TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
680705 TkMacOSXWinBounds(winPtr, &bounds);
681706 r = NSMakeRect(bounds.left,
682 [view bounds].size.height - bounds.bottom,
683 bounds.right - bounds.left, bounds.bottom - bounds.top);
707 [view bounds].size.height - bounds.bottom,
708 bounds.right - bounds.left, bounds.bottom - bounds.top);
684709 [view setNeedsDisplayInRect:r];
685710 }
686711 }
687712
688 /* TkGenWMMoveRequestEvent(macWin->winPtr,
689 macWin->winPtr->changes.x, macWin->winPtr->changes.y); */
713 #if 0
714 TkGenWMMoveRequestEvent(macWin->winPtr,
715 macWin->winPtr->changes.x, macWin->winPtr->changes.y);
716 #endif
717 return Success;
690718 }
691719
692720 /*
708736
709737 void
710738 TkMacOSXSetDrawingEnabled(
711 TkWindow *winPtr,
712 int flag)
739 TkWindow *winPtr,
740 int flag)
713741 {
714742 TkWindow *childPtr;
715743 MacDrawable *macWin = winPtr->privatePtr;
716744
717745 if (macWin) {
718 if (flag ) {
746 if (flag) {
719747 macWin->flags &= ~TK_DO_NOT_DRAW;
720748 } else {
721749 macWin->flags |= TK_DO_NOT_DRAW;
723751 }
724752
725753 /*
726 * Set the flag for all children & their descendants, excluding
727 * Toplevels. (??? Do we need to exclude Toplevels?)
754 * Set the flag for all children & their descendants, excluding Toplevels.
755 * (??? Do we need to exclude Toplevels?)
728756 */
729757
730758 childPtr = winPtr->childList;
888916 }
889917 CFRelease(rgn);
890918 } else {
891
892919 /*
893920 * An unmapped window has empty clip regions to prevent any
894921 * (erroneous) drawing into it or its children from becoming
918945 * TkMacOSXVisableClipRgn --
919946 *
920947 * This function returns the Macintosh clipping region for the given
921 * window. The caller is responsible for disposing of the returned
922 * region via TkDestroyRegion().
948 * window. The caller is responsible for disposing of the returned region
949 * via TkDestroyRegion().
923950 *
924951 * Results:
925952 * The region.
937964 if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
938965 TkMacOSXUpdateClipRgn(winPtr);
939966 }
940 return (TkRegion)HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);
967 return (TkRegion) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);
941968 }
942969
943970 /*
957984 */
958985
959986 static OSStatus
960 InvalViewRect(int msg, HIShapeRef rgn, const CGRect *rect, void *ref) {
987 InvalViewRect(
988 int msg,
989 HIShapeRef rgn,
990 const CGRect *rect,
991 void *ref)
992 {
961993 static CGAffineTransform t;
962994 NSView *view = ref;
963995
10371069 *----------------------------------------------------------------------
10381070 */
10391071
1040 NSWindow*
1072 NSWindow *
10411073 TkMacOSXDrawableWindow(
10421074 Drawable drawable)
10431075 {
10551087 result = macWin->winPtr->wmInfoPtr->window;
10561088 } else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) {
10571089 TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
1090
10581091 if (contWinPtr) {
10591092 result = TkMacOSXDrawableWindow((Drawable) contWinPtr->privatePtr);
10601093 }
11081141 *----------------------------------------------------------------------
11091142 */
11101143
1111 NSView*
1144 NSView *
11121145 TkMacOSXDrawableView(
11131146 MacDrawable *macWin)
11141147 {
11221155 result = macWin->toplevel->view;
11231156 } else {
11241157 TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
1158
11251159 if (contWinPtr) {
11261160 result = TkMacOSXDrawableView(contWinPtr->privatePtr);
11271161 }
11491183 TkMacOSXGetRootControl(
11501184 Drawable drawable)
11511185 {
1152
11531186 /*
11541187 * will probably need to fix this up for embedding
11551188 */
12661299 TkWindow *winPtr,
12671300 void *bounds)
12681301 {
1269 Rect *b = (Rect *)bounds;
1302 Rect *b = (Rect *) bounds;
1303
12701304 b->left = winPtr->privatePtr->xOff;
12711305 b->top = winPtr->privatePtr->yOff;
12721306 b->right = b->left + winPtr->changes.width;
13091343 * UpdateOffsets --
13101344 *
13111345 * Updates the X & Y offsets of the given TkWindow from the TopLevel it is
1312 * a decendant of.
1346 * a descendant of.
13131347 *
13141348 * Results:
13151349 * None.
13301364 TkWindow *childPtr;
13311365
13321366 if (winPtr->privatePtr == NULL) {
1333
13341367 /*
13351368 * We haven't called Tk_MakeWindowExist for this window yet. The offset
13361369 * information will be postponed and calulated at that time. (This will
1212 */
1313
1414 #include "tkMacOSXPrivate.h"
15 #include "tkMacOSXConstants.h"
1516
1617 /*
1718 * Forward declarations of procedures defined later in this file:
1819 */
1920
21 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
2022 static int DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp,
21 int objc, Tcl_Obj *const objv[]);
23 int objc, Tcl_Obj *const objv[]);
24 #endif
25 static int PressButtonObjCmd (ClientData dummy, Tcl_Interp *interp,
26 int objc, Tcl_Obj *const objv[]);
27
2228
2329 /*
2430 *----------------------------------------------------------------------
4551 * Add commands for platform specific tests on MacOS here.
4652 */
4753
48 Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd,
49 (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
54 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
55 Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, NULL, NULL);
56 #endif
57 Tcl_CreateObjCommand(interp, "pressbutton", PressButtonObjCmd, NULL, NULL);
5058
5159 return TCL_OK;
5260 }
5664 *
5765 * DebuggerObjCmd --
5866 *
59 * This procedure simply calls the low level debugger.
67 * This procedure simply calls the low level debugger, which was
68 * deprecated in OSX 10.8.
6069 *
6170 * Results:
6271 * A standard Tcl result.
6776 *----------------------------------------------------------------------
6877 */
6978
79 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
7080 static int
7181 DebuggerObjCmd(
7282 ClientData clientData, /* Not used. */
7787 Debugger();
7888 return TCL_OK;
7989 }
80
81 /*
82 *----------------------------------------------------------------------
83 *
84 * TkTestSimulateDrawing --
85 *
86 * A test widget display procedure which records calls can use this to
87 * avoid duplicate calls which would occur due to fact that no valid
88 * graphics context is available to the idle task which is running the
89 * display proc. Note that no actual drawing to the screen will take
90 * place when this flag is set. This is just a wrapper for the NSApp
91 * property.
92 *
93 *
94 * Results:
95 * Calls to low level drawing routines will return without actually
96 * drawing anything to the screen.
90 #endif
91
92 /*
93 *----------------------------------------------------------------------
94 *
95 * TkTestLogDisplay --
96 *
97 * The test image display procedure calls this to determine whether it
98 * should write a log message recording that it has being run. On OSX
99 * 10.14 and later, only calls to the display procedure which occur inside
100 * of the drawRect method should be logged, since those are the only ones
101 * which actually draw anything. On earlier systems the opposite is true.
102 * The calls from within the drawRect method are redundant, since the
103 * first time the display procedure is run it will do the drawing and that
104 * first call will usually not occur inside of drawRect.
105 *
106 * Results:
107 * On OSX 10.14 and later, returns true if and only if called from
108 * within [NSView drawRect]. On earlier systems returns false if
109 * and only if called from with [NSView drawRect].
97110 *
98111 * Side effects:
99112 * None
100113 *
101114 *----------------------------------------------------------------------
102115 */
103 MODULE_SCOPE void
104 TkTestSimulateDrawing(Bool yesno) {
105 [NSApp setSimulateDrawing:yesno];
106 }
107
116 MODULE_SCOPE Bool
117 TkTestLogDisplay(void) {
118 if ([NSApp macMinorVersion] >= 14) {
119 return [NSApp isDrawing];
120 } else {
121 return ![NSApp isDrawing];
122 }
123 }
124
125 /*
126 *----------------------------------------------------------------------
127 *
128 * PressButtonObjCmd --
129 *
130 * This Tcl command simulates a button press at a specific screen
131 * location. It injects NSEvents into the NSApplication event queue,
132 * as opposed to adding events to the Tcl queue as event generate
133 * would do. One application is for testing the grab command.
134 *
135 * Results:
136 * A standard Tcl result.
137 *
138 * Side effects:
139 * None.
140 *
141 *----------------------------------------------------------------------
142 */
143
144 /* ARGSUSED */
145 static int
146 PressButtonObjCmd(
147 ClientData clientData,
148 Tcl_Interp *interp,
149 int objc,
150 Tcl_Obj *const objv[])
151 {
152 int x, y, i, value, wNum;
153 CGPoint pt;
154 NSPoint loc;
155 NSEvent *motion, *press, *release;
156 NSArray *screens = [NSScreen screens];
157 CGFloat ScreenHeight = 0;
158 enum {X=1, Y};
159
160 if (screens && [screens count]) {
161 ScreenHeight = [[screens objectAtIndex:0] frame].size.height;
162 }
163
164 if (objc != 3) {
165 Tcl_WrongNumArgs(interp, 1, objv, "x y");
166 return TCL_ERROR;
167 }
168 for (i = 1; i < objc; i++) {
169 if (Tcl_GetIntFromObj(interp,objv[i],&value) != TCL_OK) {
170 return TCL_ERROR;
171 }
172 switch (i) {
173 case X:
174 x = value;
175 break;
176 case Y:
177 y = value;
178 break;
179 default:
180 break;
181 }
182 }
183 pt.x = loc.x = x;
184 pt.y = y;
185 loc.y = ScreenHeight - y;
186 wNum = 0;
187 CGWarpMouseCursorPosition(pt);
188 motion = [NSEvent mouseEventWithType:NSMouseMoved
189 location:loc
190 modifierFlags:0
191 timestamp:GetCurrentEventTime()
192 windowNumber:wNum
193 context:nil
194 eventNumber:0
195 clickCount:1
196 pressure:0.0];
197 [NSApp postEvent:motion atStart:NO];
198 press = [NSEvent mouseEventWithType:NSLeftMouseDown
199 location:loc
200 modifierFlags:0
201 timestamp:GetCurrentEventTime()
202 windowNumber:wNum
203 context:nil
204 eventNumber:1
205 clickCount:1
206 pressure:0.0];
207 [NSApp postEvent:press atStart:NO];
208 release = [NSEvent mouseEventWithType:NSLeftMouseUp
209 location:loc
210 modifierFlags:0
211 timestamp:GetCurrentEventTime()
212 windowNumber:wNum
213 context:nil
214 eventNumber:2
215 clickCount:1
216 pressure:0.0];
217 [NSApp postEvent:release atStart:NO];
218 return TCL_OK;
219 }
108220
109221
110222 /*
3030 */
3131
3232 static int GenerateUpdates(HIShapeRef updateRgn,
33 CGRect *updateBounds, TkWindow *winPtr);
33 CGRect *updateBounds, TkWindow *winPtr);
3434 static int GenerateActivateEvents(TkWindow *winPtr,
3535 int activeFlag);
3636 static void DoWindowActivate(ClientData clientData);
6767 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
6868 #endif
6969 BOOL movedOnly = [[notification name]
70 isEqualToString:NSWindowDidMoveNotification];
71
70 isEqualToString:NSWindowDidMoveNotification];
7271 NSWindow *w = [notification object];
7372 TkWindow *winPtr = TkMacOSXGetTkWindow(w);
7473
7877 int x, y, width = -1, height = -1, flags = 0;
7978
8079 x = bounds.origin.x;
81 y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height);
82 if (winPtr->changes.x != x || winPtr->changes.y != y){
80 y = TkMacOSXZeroScreenHeight() - (bounds.origin.y + bounds.size.height);
81 if (winPtr->changes.x != x || winPtr->changes.y != y) {
8382 flags |= TK_LOCATION_CHANGED;
8483 } else {
8584 x = y = -1;
9190 flags |= TK_SIZE_CHANGED;
9291 }
9392 if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
94
9593 /*
9694 * Propagate geometry changes immediately.
9795 */
9896
9997 flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
10098 }
99
101100 TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
102101 }
102
103103 }
104104
105105 - (void) windowExpanded: (NSNotification *) notification
135135 }
136136 }
137137
138 - (NSRect)windowWillUseStandardFrame:(NSWindow *)window
139 defaultFrame:(NSRect)newFrame
140 {
141 /*
142 * This method needs to be implemented in order for [NSWindow isZoomed] to
143 * give the correct answer. But it suffices to always validate every
144 * request.
145 */
146
147 return newFrame;
148 }
149
150 - (NSSize)window:(NSWindow *)window
151 willUseFullScreenContentSize:(NSSize)proposedSize
152 {
153 /*
154 * We don't need to change the proposed size, but we do need to implement
155 * this method. Otherwise the full screen window will be sized to the
156 * screen's visibleFrame, leaving black bands at the top and bottom.
157 */
158
159 return proposedSize;
160 }
161
162 - (void) windowEnteredFullScreen: (NSNotification *) notification
163 {
164 #ifdef TK_MAC_DEBUG_NOTIFICATIONS
165 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
166 #endif
167 [(TKWindow *)[notification object] tkLayoutChanged];
168 }
169
170 - (void) windowExitedFullScreen: (NSNotification *) notification
171 {
172 #ifdef TK_MAC_DEBUG_NOTIFICATIONS
173 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
174 #endif
175 [(TKWindow *)[notification object] tkLayoutChanged];
176 }
177
138178 - (void) windowCollapsed: (NSNotification *) notification
139179 {
140180 #ifdef TK_MAC_DEBUG_NOTIFICATIONS
157197
158198 if (winPtr) {
159199 TkGenWMDestroyEvent((Tk_Window) winPtr);
160 if (_windowWithMouse == w) {
161 _windowWithMouse = nil;
162 [w release];
163 }
164 }
165
166 /*
167 * If necessary, TkGenWMDestroyEvent() handles [close]ing the window,
168 * so can always return NO from -windowShouldClose: for a Tk window.
200 }
201
202 /*
203 * If necessary, TkGenWMDestroyEvent() handles [close]ing the window, so
204 * can always return NO from -windowShouldClose: for a Tk window.
169205 */
170206
171207 return (winPtr ? NO : YES);
172208 }
173
174209
175210 #ifdef TK_MAC_DEBUG_NOTIFICATIONS
176211
212247 }
213248 }
214249
215
216250 #endif /* TK_MAC_DEBUG_NOTIFICATIONS */
217251
218252 - (void) _setupWindowNotifications
221255
222256 #define observe(n, s) \
223257 [nc addObserver:self selector:@selector(s) name:(n) object:nil]
258
224259 observe(NSWindowDidBecomeKeyNotification, windowActivation:);
225260 observe(NSWindowDidResignKeyNotification, windowActivation:);
226261 observe(NSWindowDidMoveNotification, windowBoundsChanged:);
227262 observe(NSWindowDidResizeNotification, windowBoundsChanged:);
228263 observe(NSWindowDidDeminiaturizeNotification, windowExpanded:);
229264 observe(NSWindowDidMiniaturizeNotification, windowCollapsed:);
265
266 #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
267 observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:);
268 observe(NSWindowDidExitFullScreenNotification, windowExitedFullScreen:);
269 #endif
270
230271 #ifdef TK_MAC_DEBUG_NOTIFICATIONS
231272 observe(NSWindowWillMoveNotification, windowDragStart:);
232273 observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);
250291 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
251292 #endif
252293 [NSApp tkCheckPasteboard];
294
295 /*
296 * When the application is activated with Command-Tab it will create a
297 * zombie window for every Tk window which has been withdrawn. So iterate
298 * through the list of windows and order out any withdrawn window.
299 */
300
301 for (NSWindow *win in [NSApp windows]) {
302 TkWindow *winPtr = TkMacOSXGetTkWindow(win);
303 if (!winPtr || !winPtr->wmInfoPtr) {
304 continue;
305 }
306 if (winPtr->wmInfoPtr->hints.initial_state == WithdrawnState) {
307 [win orderOut:nil];
308 }
309 }
253310 }
254311
255312 - (void) applicationDeactivate: (NSNotification *) notification
258315 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
259316 #endif
260317 }
318
319 - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
320 hasVisibleWindows:(BOOL)flag
321 {
322 /*
323 * Allowing the default response means that withdrawn windows will get
324 * displayed on the screen with unresponsive title buttons. We don't
325 * really want that. Besides, we can write our own code to handle this
326 * with ::tk::mac::ReopenApplication. So we just say NO.
327 */
328
329 return NO;
330 }
331
261332
262333 - (void) applicationShowHide: (NSNotification *) notification
263334 {
298369 *
299370 * TkpAppIsDrawing --
300371 *
301 * A widget display procedure can call this to determine whether it
302 * is being run inside of the drawRect method. This is needed for
303 * some tests, especially of the Text widget, which record data in
304 * a global Tcl variable and assume that display procedures will be
305 * run in a predictable sequence as Tcl idle tasks.
372 * A widget display procedure can call this to determine whether it is
373 * being run inside of the drawRect method. This is needed for some tests,
374 * especially of the Text widget, which record data in a global Tcl
375 * variable and assume that display procedures will be run in a
376 * predictable sequence as Tcl idle tasks.
306377 *
307378 * Results:
308379 * True only while running the drawRect method of a TKContentView;
312383 *
313384 *----------------------------------------------------------------------
314385 */
386
315387 MODULE_SCOPE Bool
316388 TkpAppIsDrawing(void) {
317389 return [NSApp isDrawing];
318390 }
319
320391
321392 /*
322393 *----------------------------------------------------------------------
442513 int activeFlag)
443514 {
444515 TkGenerateActivateEvents(winPtr, activeFlag);
445 TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
516 if (activeFlag || ![NSApp isActive]) {
517 TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
518 }
446519 return true;
447520 }
448521
599672 if (flags & TK_LOCATION_CHANGED) {
600673 wmPtr->x = x;
601674 wmPtr->y = y;
602 wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
603675 }
604676 if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&
605677 ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {
606678 if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) {
607
608679 /*
609680 * Don't set external width, since the user didn't change it
610681 * from what the widgets asked for.
611682 */
612
613683 } else if (wmPtr->gridWin != NULL) {
614684 wmPtr->width = wmPtr->reqGridWidth
615685 + (width - winPtr->reqWidth)/wmPtr->widthInc;
621691 }
622692
623693 if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) {
624
625694 /*
626695 * Don't set external height, since the user didn't change it
627696 * from what the widgets asked for.
628697 */
629
630698 } else if (wmPtr->gridWin != NULL) {
631699 wmPtr->height = wmPtr->reqGridHeight
632700 + (height - winPtr->reqHeight)/wmPtr->heightInc;
799867 *
800868 */
801869
802 /*Restrict event processing to Expose events.*/
870 /*
871 * Restrict event processing to Expose events.
872 */
873
803874 static Tk_RestrictAction
804875 ExposeRestrictProc(
805876 ClientData arg,
809880 ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
810881 }
811882
812 /*Restrict event processing to ConfigureNotify events.*/
883 /*
884 * Restrict event processing to ConfigureNotify events.
885 */
886
813887 static Tk_RestrictAction
814888 ConfigureRestrictProc(
815889 ClientData arg,
818892 return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
819893 }
820894
895 /*
896 * If a window gets mapped inside the drawRect method, this will be run as an
897 * idle task, after drawRect returns, to clean up the mess.
898 */
899
900 static void
901 RedisplayView(
902 ClientData clientdata)
903 {
904 NSView *view = (NSView *) clientdata;
905
906 /*
907 * Make sure that we are not trying to displaying a view that no longer
908 * exists.
909 */
910
911 for (NSWindow *w in [NSApp orderedWindows]) {
912 if ([w contentView] == view) {
913 [view setNeedsDisplay:YES];
914 break;
915 }
916 }
917 }
918
821919 @implementation TKContentView(TKWindowEvent)
822920
823921 - (void) drawRect: (NSRect) rect
831929 Tk_PathName(winPtr));
832930 #endif
833931
834 if ([NSApp simulateDrawing]) {
835 return;
836 }
837
838 /*
839 * We do not allow recursive calls to drawRect, but we only log
840 * them on OSX > 10.13, where they should never happen.
841 */
842
843 if ([NSApp isDrawing] && [NSApp macMinorVersion] > 13) {
844 TKLog(@"WARNING: a recursive call to drawRect was aborted.");
932 /*
933 * We do not allow recursive calls to drawRect, but we only log them on OSX
934 * > 10.13, where they should never happen.
935 */
936
937 if ([NSApp isDrawing]) {
938 if ([NSApp macMinorVersion] > 13) {
939 TKLog(@"WARNING: a recursive call to drawRect was aborted.");
940 }
845941 return;
846942 }
847943
865961 [self generateExposeEvents:(HIShapeRef)drawShape];
866962 CFRelease(drawShape);
867963 [NSApp setIsDrawing: NO];
964
965 if ([self needsRedisplay]) {
966 [self setNeedsRedisplay:NO];
967 Tcl_DoWhenIdle(RedisplayView, self);
968 }
868969
869970 #ifdef TK_MAC_DEBUG_DRAWING
870971 fprintf(stderr, "drawRect: done.\n");
877978 NSWindow *w = [self window];
878979 TkWindow *winPtr = TkMacOSXGetTkWindow(w);
879980 Tk_Window tkwin = (Tk_Window) winPtr;
981
982 if (![self inLiveResize] &&
983 [w respondsToSelector: @selector (tkLayoutChanged)]) {
984 [(TKWindow *)w tkLayoutChanged];
985 }
986
880987 if (winPtr) {
881 /* On OSX versions below 10.14 setFrame calls drawRect.
882 * On 10.14 it does its own drawing.
883 */
884 if ([NSApp macMinorVersion] > 13) {
885 [NSApp setIsDrawing:YES];
886 }
887988 unsigned int width = (unsigned int)newsize.width;
888989 unsigned int height=(unsigned int)newsize.height;
889990 ClientData oldArg;
890991 Tk_RestrictProc *oldProc;
891992
892993 /*
893 * This can be called from outside the Tk event loop.
894 * Since it calls Tcl_DoOneEvent, we need to make sure we
895 * don't clobber the AutoreleasePool set up by the caller.
994 * This can be called from outside the Tk event loop. Since it calls
995 * Tcl_DoOneEvent, we need to make sure we don't clobber the
996 * AutoreleasePool set up by the caller.
896997 */
897998
898999 [NSApp _lockAutoreleasePool];
9081009 */
9091010
9101011 TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
911 TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
1012 TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
9121013 oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
9131014 Tk_RestrictEvents(oldProc, oldArg, &oldArg);
9141015
9321033 /*
9331034 * Finally, unlock the main autoreleasePool.
9341035 */
935
1036
9361037 [NSApp _unlockAutoreleasePool];
9371038 }
9381039 }
9961097 }
9971098
9981099 /*
999 * This method is called when a user changes between light and dark mode.
1000 * The implementation here generates a Tk virtual event which can be bound
1001 * to a function that redraws the window in an appropriate style.
1100 * This method is called when a user changes between light and dark mode. The
1101 * implementation here generates a Tk virtual event which can be bound to a
1102 * function that redraws the window in an appropriate style.
10021103 */
10031104
10041105 - (void) viewDidChangeEffectiveAppearance
10051106 {
10061107 XVirtualEvent event;
10071108 int x, y;
1008 NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
10091109 NSWindow *w = [self window];
10101110 TkWindow *winPtr = TkMacOSXGetTkWindow(w);
10111111 Tk_Window tkwin = (Tk_Window) winPtr;
10261126 &event.x_root, &event.y_root, &x, &y, &event.state);
10271127 Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
10281128 event.same_screen = true;
1029 if (osxMode == nil) {
1030 event.name = Tk_GetUid("LightAqua");
1031 Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
1032 return;
1033 }
1034 if ([osxMode isEqual:@"Dark"]) {
1129 if (TkMacOSXInDarkMode(tkwin)) {
10351130 event.name = Tk_GetUid("DarkAqua");
1036 Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
1037 return;
1038 }
1039 }
1040
1041 /*
1042 * This is no-op on 10.7 and up because Apple has removed this widget,
1043 * but we are leaving it here for backwards compatibility.
1131 } else {
1132 event.name = Tk_GetUid("LightAqua");
1133 }
1134 Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
1135 }
1136
1137 /*
1138 * This is no-op on 10.7 and up because Apple has removed this widget, but we
1139 * are leaving it here for backwards compatibility.
10441140 */
10451141
10461142 - (void) tkToolbarButton: (id) sender
10891185 return YES;
10901186 }
10911187
1188 /*
1189 * This keyDown method does nothing, which is a huge improvement over the
1190 * default keyDown method which beeps every time a key is pressed.
1191 */
1192
10921193 - (void) keyDown: (NSEvent *) theEvent
10931194 {
10941195 #ifdef TK_MAC_DEBUG_EVENTS
10951196 TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
10961197 #endif
1198 }
1199
1200 /*
1201 * When the services menu is opened this is called for each Responder in
1202 * the Responder chain until a service provider is found. The TkContentView
1203 * should be the first (and generally only) Responder in the chain. We
1204 * return the TkServices object that was created in TkpInit.
1205 */
1206
1207 - (id)validRequestorForSendType:(NSString *)sendType
1208 returnType:(NSString *)returnType
1209 {
1210 if ([sendType isEqualToString:@"NSStringPboardType"] ||
1211 [sendType isEqualToString:@"NSPasteboardTypeString"]) {
1212 return [NSApp servicesProvider];
1213 }
1214 return [super validRequestorForSendType:sendType returnType:returnType];
10971215 }
10981216
10991217 @end
22 *
33 * This module takes care of the interactions between a Tk-based
44 * application and the window manager. Among other things, it implements
5 * the "wm" command and passes geometry information to the window
6 * manager.
5 * the "wm" command and passes geometry information to the window manager.
76 *
87 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
98 * Copyright 2001-2009, Apple Inc.
109 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
1110 * Copyright (c) 2010 Kevin Walzer/WordTech Communications LLC.
12 * Copyright (c) 2017 Marc Culler.
11 * Copyright (c) 2017-2019 Marc Culler.
1312 *
1413 * See the file "license.terms" for information on usage and redistribution
1514 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
5352 | kWindowDoesNotCycleAttribute | tkWindowDoesNotHideAttribute \
5453 | tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute \
5554 | tkNonactivatingPanelAttribute | tkHUDWindowAttribute)
56
5755
5856 static const struct {
5957 const UInt64 validAttrs, defaultAttrs, forceOnAttrs, forceOffAttrs;
151149 typedef enum {
152150 WMATT_ALPHA, WMATT_FULLSCREEN, WMATT_MODIFIED, WMATT_NOTIFY,
153151 WMATT_TITLEPATH, WMATT_TOPMOST, WMATT_TRANSPARENT,
154 _WMATT_LAST_ATTRIBUTE
152 WMATT_TYPE, _WMATT_LAST_ATTRIBUTE
155153 } WmAttribute;
156154
157155 static const char *const WmAttributeNames[] = {
158156 "-alpha", "-fullscreen", "-modified", "-notify",
159157 "-titlepath", "-topmost", "-transparent",
160 NULL
158 "-type", NULL
161159 };
162160
163161 /*
193191
194192 static Tcl_HashTable windowTable;
195193 static int windowHashInit = false;
196
197
198 #pragma mark NSWindow(TKWm)
199
200 /*
201 * Conversion of coordinates between window and screen.
202 */
203
204 @implementation NSWindow(TKWm)
205 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
206 - (NSPoint) tkConvertPointToScreen: (NSPoint) point
207 {
208 return [self convertBaseToScreen:point];
209 }
210 - (NSPoint) tkConvertPointFromScreen: (NSPoint)point
211 {
212 return [self convertScreenToBase:point];
213 }
214 #else
215 - (NSPoint) tkConvertPointToScreen: (NSPoint) point
216 {
217 NSRect pointrect;
218 pointrect.origin = point;
219 pointrect.size.width = 0;
220 pointrect.size.height = 0;
221 return [self convertRectToScreen:pointrect].origin;
222 }
223 - (NSPoint) tkConvertPointFromScreen: (NSPoint)point
224 {
225 NSRect pointrect;
226 pointrect.origin = point;
227 pointrect.size.width = 0;
228 pointrect.size.height = 0;
229 return [self convertRectFromScreen:pointrect].origin;
230 }
231 #endif
232
233 - (NSSize)windowWillResize:(NSWindow *)sender
234 toSize:(NSSize)frameSize
235 {
236 NSRect currentFrame = [sender frame];
237 TkWindow *winPtr = TkMacOSXGetTkWindow(sender);
238 if (winPtr) {
239 if (winPtr->wmInfoPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
240 frameSize.width = currentFrame.size.width;
241 }
242 if (winPtr->wmInfoPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
243 frameSize.height = currentFrame.size.height;
244 }
245 }
246 return frameSize;
247 }
248 @end
249
250 #pragma mark -
251
252194
253195 /*
254196 * Forward declarations for procedures defined in this file:
364306 static void WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);
365307 static int WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr,
366308 int objc, Tcl_Obj *const objv[]);
309 static int WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr,
310 int objc, Tcl_Obj *const objv[]);
311 static int WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr,
312 int objc, Tcl_Obj *const objv[]);
367313 static void ApplyWindowAttributeFlagChanges(TkWindow *winPtr,
368314 NSWindow *macWindow, UInt64 oldAttributes,
369315 int oldFlags, int create, int initial);
375321 int *maxHeightPtr);
376322 static void RemapWindows(TkWindow *winPtr,
377323 MacDrawable *parentWin);
324 static void RemoveTransient(TkWindow *winPtr);
325
326 #pragma mark NSWindow(TKWm)
327
328 @implementation NSWindow(TKWm)
329
330 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
331 - (NSPoint) tkConvertPointToScreen: (NSPoint) point
332 {
333 return [self convertBaseToScreen:point];
334 }
335 - (NSPoint) tkConvertPointFromScreen: (NSPoint)point
336 {
337 return [self convertScreenToBase:point];
338 }
339 #else
340 - (NSPoint) tkConvertPointToScreen: (NSPoint) point
341 {
342 NSRect pointrect = {point, {0,0}};
343 return [self convertRectToScreen:pointrect].origin;
344 }
345 - (NSPoint) tkConvertPointFromScreen: (NSPoint)point
346 {
347 NSRect pointrect = {point, {0,0}};
348 return [self convertRectFromScreen:pointrect].origin;
349 }
350 #endif
351
352 @end
353
354 #pragma mark -
378355
379356 #pragma mark TKWindow(TKWm)
380357
381 @interface NSDrawerWindow : NSWindow
382 {
383 id _i1, _i2;
384 }
358 @implementation TKWindow: NSWindow
359
385360 @end
386361
387
388 @implementation TKWindow: NSWindow
389
390 /* Custom fullscreen implementation on 10.13 and above. On older versions of
391 * macOS dating back to 10.7, the NSWindow fullscreen API was opt-in, requiring
392 * explicit calls to toggleFullScreen. On 10.13, the API became implicit,
393 * applying to all NSWindows unless they were marked non-resizable; this caused
394 * issues with Tk, which was not aware of changes in screen geometry. Here we
395 * override the toggleFullScreen call to hook directly into Tk's own fullscreen
396 * API, allowing Tk to function smoothly with the Mac's fullscreen button.
397 */
398
399 NSStatusItem *exitFullScreen;
400
401
402 - (void)toggleFullScreen:(id)sender
403 {
404 TkWindow *winPtr = TkMacOSXGetTkWindow(self);
405 if (!winPtr) {
406 return;
407 }
408 Tcl_Interp *interp = Tk_Interp((Tk_Window)winPtr);
409 if ([NSApp macMinorVersion] > 12) {
410 if (([self styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask) {
411 TkMacOSXMakeFullscreen(winPtr, self, 0, interp);
412 } else {
413 TkMacOSXMakeFullscreen(winPtr, self, 1, interp);
414 }
415 } else {
416 TKLog (@"toggleFullScreen is ignored by Tk on OSX versions < 10.13");
417 }
418 }
419
420 -(void)restoreOldScreen:(id)sender
362 @implementation TKWindow(TKWm)
363
364 /*
365 * This method synchronizes Tk's understanding of the bounds of a contentView
366 * with the window's. It is needed because there are situations when the
367 * window manager can change the layout of an NSWindow without having been
368 * requested to do so by Tk. Examples are when a window goes FullScreen or
369 * shows a tab bar. NSWindow methods which involve such layout changes should
370 * be overridden or protected by methods which call this.
371 */
372
373 - (void) tkLayoutChanged
374 {
375 TkWindow *winPtr = TkMacOSXGetTkWindow(self);
376
377 if (winPtr) {
378 NSRect frameRect;
379
380 /*
381 * This avoids including the title bar for full screen windows
382 * but does include it for normal windows.
383 */
384
385 if ([self styleMask] & NSFullScreenWindowMask) {
386 frameRect = [NSWindow frameRectForContentRect:NSZeroRect
387 styleMask:[self styleMask]];
388 } else {
389 frameRect = [self frameRectForContentRect:NSZeroRect];
390 }
391
392 WmInfo *wmPtr = winPtr->wmInfoPtr;
393
394 wmPtr->xInParent = -frameRect.origin.x;
395 wmPtr->yInParent = frameRect.origin.y + frameRect.size.height;
396 wmPtr->parentWidth = winPtr->changes.width + frameRect.size.width;
397 wmPtr->parentHeight = winPtr->changes.height + frameRect.size.height;
398 }
399 }
400
401 #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101200)
402 - (void)toggleTabBar:(id)sender
421403 {
422404 TkWindow *winPtr = TkMacOSXGetTkWindow(self);
423405 if (!winPtr) {
424406 return;
425407 }
426 Tcl_Interp *interp = Tk_Interp((Tk_Window)winPtr);
427 TkMacOSXMakeFullscreen(winPtr, self, 0, interp);
428 [[NSStatusBar systemStatusBar] removeStatusItem: exitFullScreen];
429 }
430
431 @end
432
433 @implementation TKWindow(TKWm)
408 [super toggleTabBar:sender];
409 [self tkLayoutChanged];
410 }
411 #endif
412
413 - (NSSize)windowWillResize:(NSWindow *)sender
414 toSize:(NSSize)frameSize
415 {
416 NSRect currentFrame = [sender frame];
417 TkWindow *winPtr = TkMacOSXGetTkWindow(sender);
418 if (winPtr) {
419 if (winPtr->wmInfoPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
420 frameSize.width = currentFrame.size.width;
421 }
422 if (winPtr->wmInfoPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
423 frameSize.height = currentFrame.size.height;
424 }
425 }
426 return frameSize;
427 }
434428
435429 - (BOOL) canBecomeKeyWindow
436430 {
452446 if (title == nil) {
453447 title = "unnamed window";
454448 }
455 if (DEBUG_ZOMBIES > 1){
449 if (DEBUG_ZOMBIES > 1) {
456450 fprintf(stderr, "Retained <%s>. Count is: %lu\n",
457451 title, [self retainCount]);
458452 }
466460 if (title == nil) {
467461 title = "unnamed window";
468462 }
469 if (DEBUG_ZOMBIES > 1){
463 if (DEBUG_ZOMBIES > 1) {
470464 fprintf(stderr, "Autoreleased <%s>. Count is %lu\n",
471465 title, [self retainCount]);
472466 }
478472 if (title == nil) {
479473 title = "unnamed window";
480474 }
481 if (DEBUG_ZOMBIES > 1){
475 if (DEBUG_ZOMBIES > 1) {
482476 fprintf(stderr, "Releasing <%s>. Count is %lu\n",
483477 title, [self retainCount]);
484478 }
490484 if (title == nil) {
491485 title = "unnamed window";
492486 }
493 if (DEBUG_ZOMBIES > 0){
487 if (DEBUG_ZOMBIES > 0) {
494488 fprintf(stderr, ">>>> Freeing <%s>. Count is %lu\n",
495489 title, [self retainCount]);
496490 }
497491 [super dealloc];
498492 }
499
500493
501494 #endif
502495 @end
596589 *
597590 * FrontWindowAtPoint --
598591 *
599 * Find frontmost toplevel window at a given screen location.
592 * Find frontmost toplevel window at a given screen location which has the
593 * specified mainPtr. If the location is in the title bar, return NULL.
600594 *
601595 * Results:
602596 * TkWindow*.
609603
610604 static TkWindow*
611605 FrontWindowAtPoint(
612 int x, int y)
613 {
614 NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
606 int x,
607 int y)
608 {
609 NSPoint p = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
615610 NSArray *windows = [NSApp orderedWindows];
616611 TkWindow *winPtr = NULL;
617612
618613 for (NSWindow *w in windows) {
619614 winPtr = TkMacOSXGetTkWindow(w);
620 if (winPtr && NSMouseInRect(p, [w frame], NO)) {
621 break;
622 }
623 }
624 return winPtr;
615 if (winPtr) {
616 WmInfo *wmPtr = winPtr->wmInfoPtr;
617 NSRect windowFrame = [w frame];
618 NSRect contentFrame = [w frame];
619
620 contentFrame.size.height = [[w contentView] frame].size.height;
621 /*
622 * For consistency with other platforms, points in the
623 * title bar are not considered to be contained in the
624 * window.
625 */
626
627 if ((wmPtr->hints.initial_state == NormalState ||
628 wmPtr->hints.initial_state == ZoomState)) {
629 if (NSMouseInRect(p, contentFrame, NO)) {
630 return winPtr;
631 } else if (NSMouseInRect(p, windowFrame, NO)) {
632 return NULL;
633 }
634 }
635 }
636 }
637 return NULL;
625638 }
626639
627640 /*
651664 wmPtr->reparent = None;
652665 wmPtr->titleUid = NULL;
653666 wmPtr->iconName = NULL;
654 wmPtr->master = None;
667 wmPtr->master = NULL;
655668 wmPtr->hints.flags = InputHint | StateHint;
656669 wmPtr->hints.input = True;
657670 wmPtr->hints.initial_state = NormalState;
661674 wmPtr->hints.icon_mask = None;
662675 wmPtr->hints.window_group = None;
663676 wmPtr->leaderName = NULL;
664 wmPtr->masterWindowName = NULL;
665677 wmPtr->icon = NULL;
666678 wmPtr->iconFor = NULL;
679 wmPtr->transientPtr = NULL;
667680 wmPtr->sizeHintsFlags = 0;
668681 wmPtr->minWidth = wmPtr->minHeight = 1;
669682 wmPtr->maxWidth = 0;
816829 */
817830
818831 XMapWindow(winPtr->display, winPtr->window);
819
820 /*Add window to Window menu.*/
821 NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
822 [win setExcludedFromWindowsMenu:NO];
823832 }
824833
825834 /*
873882 if (wmPtr == NULL) {
874883 return;
875884 }
885
886 /*
887 *If the dead window is a transient, remove it from the master's list.
888 */
889
890 RemoveTransient(winPtr);
876891 Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
877892 Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
878893 TopLevelEventProc, winPtr);
888903 if (wmPtr->leaderName != NULL) {
889904 ckfree(wmPtr->leaderName);
890905 }
891 if (wmPtr->masterWindowName != NULL) {
892 ckfree(wmPtr->masterWindowName);
893 }
894906 if (wmPtr->icon != NULL) {
895907 wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
896908 wmPtr2->iconFor = NULL;
902914 }
903915 while (wmPtr->protPtr != NULL) {
904916 ProtocolHandler *protPtr = wmPtr->protPtr;
905
906917 wmPtr->protPtr = protPtr->nextPtr;
907918 Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
908919 }
914925 }
915926 if (wmPtr->flags & WM_UPDATE_PENDING) {
916927 Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
928 }
929
930 /*
931 * If the dead window has a transient, remove references to it from
932 * the transient.
933 */
934
935 for (Transient *transientPtr = wmPtr->transientPtr;
936 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
937 TkWindow *winPtr2 = transientPtr->winPtr;
938 TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
939
940 if (masterPtr == winPtr) {
941 wmPtr2 = winPtr2->wmInfoPtr;
942 wmPtr2->master = NULL;
943 }
944 }
945
946 while (wmPtr->transientPtr != NULL) {
947 Transient *transientPtr = wmPtr->transientPtr;
948
949 wmPtr->transientPtr = transientPtr->nextPtr;
950 ckfree(transientPtr);
917951 }
918952
919953 /*
925959
926960 NSWindow *window = wmPtr->window;
927961
928 if (window && !Tk_IsEmbedded(winPtr) ) {
962 if (window && !Tk_IsEmbedded(winPtr)) {
929963 NSWindow *parent = [window parentWindow];
964
930965 if (parent) {
931966 [parent removeChildWindow:window];
932967 }
936971 if (title == nil) {
937972 title = "unnamed window";
938973 }
939 printf(">>>> Closing <%s>. Count is: %lu\n", title, [window retainCount]);
974 fprintf(stderr, ">>>> Closing <%s>. Count is: %lu\n", title,
975 [window retainCount]);
940976 }
941977 #endif
942978 [window close];
951987 NSArray *windows = [NSApp orderedWindows];
952988 for (id nswindow in windows) {
953989 TkWindow *winPtr2 = TkMacOSXGetTkWindow(nswindow);
990
954991 if (winPtr2 && nswindow != window) {
955992 WmInfo *wmPtr = winPtr2->wmInfoPtr;
956 BOOL minimized = (wmPtr->hints.initial_state == IconicState ||
957 wmPtr->hints.initial_state == WithdrawnState);
993 BOOL minimized = (wmPtr->hints.initial_state == IconicState
994 || wmPtr->hints.initial_state == WithdrawnState);
995
958996 /*
959 * If no windows are left on the screen and the next
960 * window is iconified or withdrawn, we don't want to
961 * make it be the KeyWindow because that would cause
962 * it to be displayed on the screen.
997 * If no windows are left on the screen and the next window is
998 * iconified or withdrawn, we don't want to make it be the
999 * KeyWindow because that would cause it to be displayed on the
1000 * screen.
9631001 */
1002
9641003 if ([nswindow canBecomeKeyWindow] && !minimized) {
9651004 [nswindow makeKeyAndOrderFront:NSApp];
9661005 break;
9671006 }
9681007 }
9691008 }
1009
9701010 /*
9711011 * Process all window events immediately to force the closed window to
9721012 * be deallocated. But don't do this for the root window as that is
9731013 * unnecessary and can lead to segfaults.
9741014 */
1015
9751016 if (winPtr->parentPtr) {
976 while (Tk_DoOneEvent(TK_WINDOW_EVENTS|TK_DONT_WAIT)) {}
1017 while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
9771018 }
9781019 [NSApp _resetAutoreleasePool];
979
9801020 #if DEBUG_ZOMBIES > 0
9811021 fprintf(stderr, "================= Pool dump ===================\n");
9821022 [NSAutoreleasePool showPools];
12991339 return TCL_ERROR;
13001340 }
13011341 if (boolean != ((wmPtr->flags & WM_FULLSCREEN) != 0)) {
1302 if (TkMacOSXMakeFullscreen(winPtr, macWindow, boolean, interp)
1303 != TCL_OK) {
1304 return TCL_ERROR;
1305 }
1342 #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
1343 [macWindow toggleFullScreen:macWindow];
1344 #else
1345 TKLog(@"The fullscreen attribute is ignored on this system.");
1346 #endif
13061347 }
13071348 break;
13081349 case WMATT_MODIFIED:
13781419 TkMacOSXInvalidateWindow((MacDrawable *) winPtr->window,
13791420 TK_PARENT_WINDOW);
13801421 }
1422 break;
1423 case WMATT_TYPE:
1424 TKLog(@"The type attribute is ignored on macOS.");
13811425 break;
13821426 case _WMATT_LAST_ATTRIBUTE:
13831427 default:
14291473 case WMATT_TRANSPARENT:
14301474 result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT);
14311475 break;
1476 case WMATT_TYPE:
1477 result = Tcl_NewStringObj("unsupported", -1);
1478 break;
14321479 case _WMATT_LAST_ATTRIBUTE:
14331480 default:
14341481 break;
14821529 WmGetAttribute(winPtr, macWindow, attribute));
14831530 }
14841531 Tcl_SetObjResult(interp, result);
1485 } else if (objc == 4) { /* wm attributes $win -attribute */
1532 } else if (objc == 4) { /* wm attributes $win -attribute */
14861533 if (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames,
14871534 sizeof(char *), "attribute", 0, &attribute) != TCL_OK) {
14881535 return TCL_ERROR;
16911738 }
16921739 return TCL_OK;
16931740 }
1694 if (Tcl_GetString(objv[3])[0] == 0) {
1741 if (*Tcl_GetString(objv[3]) == '\0') {
16951742 if (wmPtr->commandObj != NULL) {
16961743 Tcl_DecrRefCount(wmPtr->commandObj);
16971744 wmPtr->commandObj = NULL;
17361783 Tcl_Obj *const objv[]) /* Argument objects. */
17371784 {
17381785 register WmInfo *wmPtr = winPtr->wmInfoPtr;
1786 NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
17391787
17401788 if (objc != 3) {
17411789 Tcl_WrongNumArgs(interp, 2, objv, "window");
17581806
17591807 TkpWmSetState(winPtr, TkMacOSXIsWindowZoomed(winPtr) ?
17601808 ZoomState : NormalState);
1809 [win setExcludedFromWindowsMenu:NO];
1810 TkMacOSXApplyWindowAttributes(winPtr, win);
1811 [win orderFront:nil];
1812 if (wmPtr->icon) {
1813 Tk_UnmapWindow((Tk_Window)wmPtr->icon);
1814 }
1815
1816 /*
1817 * If this window has a transient, the transient must also be deiconified if
1818 * it was withdrawn by the master.
1819 */
1820
1821 for (Transient *transientPtr = wmPtr->transientPtr;
1822 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
1823 TkWindow *winPtr2 = transientPtr->winPtr;
1824 WmInfo *wmPtr2 = winPtr2->wmInfoPtr;
1825 TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
1826
1827 if (masterPtr == winPtr) {
1828 if ((wmPtr2->hints.initial_state == WithdrawnState) &&
1829 ((transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) {
1830 TkpWmSetState(winPtr2, NormalState);
1831 transientPtr->flags &= ~WITHDRAWN_BY_MASTER;
1832 }
1833 }
1834 }
1835
17611836 return TCL_OK;
17621837 }
17631838
19081983 {
19091984 register WmInfo *wmPtr = winPtr->wmInfoPtr;
19101985 Window window;
1986 char buf[TCL_INTEGER_SPACE];
19111987
19121988 if (objc != 3) {
19131989 Tcl_WrongNumArgs(interp, 2, objv, "window");
19171993 if (window == None) {
19181994 window = Tk_WindowId((Tk_Window) winPtr);
19191995 }
1920 Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", (unsigned) window));
1996 sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)window);
1997 Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
19211998 return TCL_OK;
19221999 }
19232000
19472024 Tcl_Obj *const objv[]) /* Argument objects. */
19482025 {
19492026 register WmInfo *wmPtr = winPtr->wmInfoPtr;
1950 char xSign, ySign;
1951 int width, height;
2027 NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
2028 char xSign = '+', ySign = '+';
2029 int width, height, x = wmPtr->x, y= wmPtr->y;
19522030 char *argv3;
19532031
19542032 if ((objc != 3) && (objc != 4)) {
19562034 return TCL_ERROR;
19572035 }
19582036 if (objc == 3) {
1959 xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
1960 ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
19612037 if (wmPtr->gridWin != NULL) {
19622038 width = wmPtr->reqGridWidth + (winPtr->changes.width
19632039 - winPtr->reqWidth)/wmPtr->widthInc;
19672043 width = winPtr->changes.width;
19682044 height = winPtr->changes.height;
19692045 }
2046 if (win) {
2047 if (wmPtr->flags & WM_NEGATIVE_X) {
2048 xSign = '-';
2049 x = wmPtr->vRootWidth - wmPtr->x
2050 - (width + (wmPtr->parentWidth - winPtr->changes.width));
2051 }
2052 if (wmPtr->flags & WM_NEGATIVE_Y) {
2053 ySign = '-';
2054 y = wmPtr->vRootHeight - wmPtr->y
2055 - (height + (wmPtr->parentHeight - winPtr->changes.height));
2056 }
2057 }
19702058 Tcl_SetObjResult(interp, Tcl_ObjPrintf("%dx%d%c%d%c%d",
1971 width, height, xSign, wmPtr->x, ySign, wmPtr->y));
2059 width, height, xSign, x, ySign, y));
19722060 return TCL_OK;
19732061 }
19742062 argv3 = Tcl_GetString(objv[3]);
22462334 Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
22472335 NULL);
22482336 return TCL_ERROR;
2249 } else if (wmPtr->master != None) {
2337 } else if (wmPtr->master != NULL) {
22502338 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
22512339 "can't iconify \"%s\": it is a transient", winPtr->pathName));
22522340 Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
22662354 }
22672355
22682356 TkpWmSetState(winPtr, IconicState);
2357 if (wmPtr->icon) {
2358 Tk_MapWindow((Tk_Window)wmPtr->icon);
2359 }
2360
2361 /*
2362 * If this window has a transient the transient must be withdrawn when
2363 * the master is iconified.
2364 */
2365
2366 for (Transient *transientPtr = wmPtr->transientPtr;
2367 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
2368 TkWindow *winPtr2 = transientPtr->winPtr;
2369 TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
2370 if (masterPtr == winPtr &&
2371 winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
2372 TkpWmSetState(winPtr2, WithdrawnState);
2373 transientPtr->flags |= WITHDRAWN_BY_MASTER;
2374 }
2375 }
2376
22692377 return TCL_OK;
22702378 }
22712379
24092517 {
24102518 Tk_Image tk_icon;
24112519 int width, height, isDefault = 0;
2520 NSImage *newIcon = NULL;
24122521
24132522 if (objc < 4) {
24142523 Tcl_WrongNumArgs(interp, 2, objv,
24162525 return TCL_ERROR;
24172526 }
24182527
2419 /*Parse args.*/
2528 /*
2529 * Parse args.
2530 */
2531
24202532 if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
24212533 isDefault = 1;
24222534 if (objc == 4) {
24262538 }
24272539 }
24282540
2429 /*Get icon name. We only use the first icon name because macOS does not
2430 support multiple images in Tk photos.*/
2541 /*
2542 * Get icon name. We only use the first icon name because macOS does not
2543 * support multiple images in Tk photos.
2544 */
2545
24312546 char *icon;
24322547 if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) {
24332548 icon = Tcl_GetString(objv[4]);
2434 } else {
2549 } else {
24352550 icon = Tcl_GetString(objv[3]);
24362551 }
24372552
2438 /*Get image and convert to NSImage that can be displayed as icon.*/
2553 /*
2554 * Get image and convert to NSImage that can be displayed as icon.
2555 */
2556
24392557 tk_icon = Tk_GetImage(interp, tkwin, icon, NULL, NULL);
24402558 if (tk_icon == NULL) {
24412559 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
24452563 return TCL_ERROR;
24462564 }
24472565
2448 NSImage *newIcon;
24492566 Tk_SizeOfImage(tk_icon, &width, &height);
2450 newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, width, height);
2567 if (width != 0 && height != 0) {
2568 newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
2569 width, height);
2570 }
24512571 Tk_FreeImage(tk_icon);
24522572 if (newIcon == NULL) {
2573 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
2574 "failed to create an iconphoto with image \"%s\"", icon));
2575 Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
24532576 return TCL_ERROR;
24542577 }
24552578 [NSApp setApplicationIconImage: newIcon];
25042627 wmPtr->hints.flags &= ~IconPositionHint;
25052628 } else {
25062629 if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
2507 || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){
2630 || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) {
25082631 return TCL_ERROR;
25092632 }
25102633 wmPtr->hints.icon_x = x;
25842707 return TCL_ERROR;
25852708 }
25862709 if (wmPtr->icon != NULL) {
2587 WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
2588
2710 TkWindow *oldIcon = (TkWindow *)wmPtr->icon;
2711 WmInfo *wmPtr3 = oldIcon->wmInfoPtr;
2712 NSWindow *win = TkMacOSXDrawableWindow(oldIcon->window);
2713
2714 /*
2715 * The old icon should be withdrawn.
2716 */
2717
2718 TkpWmSetState(oldIcon, WithdrawnState);
2719 [win orderOut:nil];
2720 [win setExcludedFromWindowsMenu:YES];
25892721 wmPtr3->iconFor = NULL;
25902722 }
25912723 Tk_MakeWindowExist(tkwin2);
25952727 wmPtr2->iconFor = (Tk_Window) winPtr;
25962728 if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
25972729 /*
2598 * Don't have iconwindows on the Mac. We just withdraw.
2730 * If the window is in normal or zoomed state, the icon should be
2731 * unmapped.
25992732 */
26002733
2601 Tk_UnmapWindow(tkwin2);
2734 if (wmPtr->hints.initial_state == NormalState ||
2735 wmPtr->hints.initial_state == ZoomState) {
2736 Tk_UnmapWindow(tkwin2);
2737 }
26022738 }
26032739 }
26042740 return TCL_OK;
26512787 Tk_MakeWindowExist((Tk_Window) winPtr);
26522788 macWin = (MacDrawable *) winPtr->window;
26532789 }
2654 TkWmMapWindow(winPtr);
2655 Tk_UnmapWindow(frameWin);
26562790 }
26572791 wmPtr = winPtr->wmInfoPtr;
26582792 winPtr->flags &= ~TK_MAPPED;
26632797 winPtr->flags |=
26642798 (TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED);
26652799 TkMapTopFrame(frameWin);
2800 TkWmMapWindow(winPtr);
26662801 } else if (Tk_IsTopLevel(frameWin)) {
26672802 /* Already managed by wm - ignore it */
26682803 }
28022937 int objc, /* Number of arguments. */
28032938 Tcl_Obj *const objv[]) /* Argument objects. */
28042939 {
2805 int boolean;
2940 int flag;
28062941 XSetWindowAttributes atts;
2942 TKWindow *win = (TKWindow *)TkMacOSXDrawableWindow(winPtr->window);
28072943
28082944 if ((objc != 3) && (objc != 4)) {
28092945 Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
28162952 return TCL_OK;
28172953 }
28182954
2819 if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) {
2955 if (Tcl_GetBooleanFromObj(interp, objv[3], &flag) != TCL_OK) {
28202956 return TCL_ERROR;
28212957 }
2822 atts.override_redirect = (boolean) ? True : False;
2958 atts.override_redirect = flag ? True : False;
28232959 Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
2824 ApplyMasterOverrideChanges(winPtr, NULL);
2960 ApplyMasterOverrideChanges(winPtr, win);
28252961 return TCL_OK;
28262962 }
28272963
29663102 */
29673103
29683104 for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;
2969 prevPtr = protPtr, protPtr = protPtr->nextPtr) {
3105 prevPtr = protPtr, protPtr = protPtr->nextPtr) {
29703106 if (protPtr->protocol == protocol) {
29713107 if (prevPtr == NULL) {
29723108 wmPtr->protPtr = protPtr->nextPtr;
31773313
31783314 if (objc == 3) {
31793315 windows = TkWmStackorderToplevel(winPtr);
3180 if (windows == NULL) {
3181 Tcl_Panic("TkWmStackorderToplevel failed");
3182 }
3183
3184 resultObj = Tcl_NewObj();
3185 for (windowPtr = windows; *windowPtr ; windowPtr++) {
3186 Tcl_ListObjAppendElement(NULL, resultObj,
3316 if (windows != NULL) {
3317 resultObj = Tcl_NewObj();
3318 for (windowPtr = windows; *windowPtr ; windowPtr++) {
3319 Tcl_ListObjAppendElement(NULL, resultObj,
31873320 TkNewWindowObj((Tk_Window) *windowPtr));
3188 }
3189 Tcl_SetObjResult(interp, resultObj);
3190 ckfree(windows);
3191 return TCL_OK;
3321 }
3322 Tcl_SetObjResult(interp, resultObj);
3323 ckfree(windows);
3324 return TCL_OK;
3325 } else {
3326 return TCL_ERROR;
3327 }
31923328 } else {
31933329 TkWindow *winPtr2;
31943330 int index1 = -1, index2 = -1, result;
33193455 return TCL_ERROR;
33203456 }
33213457
3322 if (index == OPT_NORMAL) {
3458 switch (index) {
3459 case OPT_NORMAL:
33233460 TkpWmSetState(winPtr, NormalState);
33243461
33253462 /*
33263463 * This varies from 'wm deiconify' because it does not force the
33273464 * window to be raised and receive focus
33283465 */
3329 } else if (index == OPT_ICONIC) {
3466
3467 break;
3468 case OPT_ICONIC:
33303469 if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
33313470 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
33323471 "can't iconify \"%s\": override-redirect flag is set",
33353474 "OVERRIDE_REDIRECT", NULL);
33363475 return TCL_ERROR;
33373476 }
3338 if (wmPtr->master != None) {
3477 if (wmPtr->master != NULL) {
33393478 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
33403479 "can't iconify \"%s\": it is a transient",
33413480 winPtr->pathName));
33443483 return TCL_ERROR;
33453484 }
33463485 TkpWmSetState(winPtr, IconicState);
3347 } else if (index == OPT_WITHDRAWN) {
3486 break;
3487 case OPT_WITHDRAWN:
33483488 TkpWmSetState(winPtr, WithdrawnState);
3349 } else { /* OPT_ZOOMED */
3489 break;
3490 default: /* OPT_ZOOMED */
33503491 TkpWmSetState(winPtr, ZoomState);
3492 break;
33513493 }
33523494 } else if (wmPtr->iconFor != NULL) {
33533495 Tcl_SetObjResult(interp, Tcl_NewStringObj("icon", -1));
34503592 {
34513593 register WmInfo *wmPtr = winPtr->wmInfoPtr;
34523594 Tk_Window master;
3595 TkWindow *masterPtr, *w;
34533596 WmInfo *wmPtr2;
3454 char *masterWindowName;
3455 int length;
3597 Transient *transient;
34563598
34573599 if ((objc != 3) && (objc != 4)) {
34583600 Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
34593601 return TCL_ERROR;
34603602 }
34613603 if (objc == 3) {
3462 if (wmPtr->master != None) {
3604 if (wmPtr->master != NULL) {
34633605 Tcl_SetObjResult(interp,
3464 Tcl_NewStringObj(wmPtr->masterWindowName, -1));
3606 Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1));
34653607 }
34663608 return TCL_OK;
34673609 }
3468 if (Tcl_GetString(objv[3])[0] == '\0') {
3469 wmPtr->master = None;
3470 if (wmPtr->masterWindowName != NULL) {
3471 ckfree(wmPtr->masterWindowName);
3472 }
3473 wmPtr->masterWindowName = NULL;
3610 if (*Tcl_GetString(objv[3]) == '\0') {
3611 RemoveTransient(winPtr);
34743612 } else {
34753613 if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
34763614 return TCL_ERROR;
34773615 }
3478 TkWindow* masterPtr = (TkWindow*) master;
3616 masterPtr = (TkWindow*) master;
34793617 while (!Tk_TopWinHierarchy(masterPtr)) {
34803618 /*
34813619 * Ensure that the master window is actually a Tk toplevel.
34943632 }
34953633
34963634 wmPtr2 = masterPtr->wmInfoPtr;
3497 /* Under some circumstances, wmPtr2 is NULL here */
3635
3636 /*
3637 * Under some circumstances, wmPtr2 is NULL here.
3638 */
3639
34983640 if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) {
34993641 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
35003642 "can't make \"%s\" a master: it is an icon for %s",
35033645 return TCL_ERROR;
35043646 }
35053647
3506 if (masterPtr == winPtr) {
3507 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3508 "can't make \"%s\" its own master", Tk_PathName(winPtr)));
3509 Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
3510 return TCL_ERROR;
3511 }
3512
3513 wmPtr->master = Tk_WindowId(masterPtr);
3514 masterWindowName = masterPtr->pathName;
3515 length = strlen(masterWindowName);
3516 if (wmPtr->masterWindowName != NULL) {
3517 ckfree(wmPtr->masterWindowName);
3518 }
3519 wmPtr->masterWindowName = ckalloc(length+1);
3520 strcpy(wmPtr->masterWindowName, masterWindowName);
3648 for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
3649 w = (TkWindow *)w->wmInfoPtr->master) {
3650 if (w == winPtr) {
3651 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3652 "setting \"%s\" as master creates a transient/master cycle",
3653 Tk_PathName(masterPtr)));
3654 Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
3655 return TCL_ERROR;
3656 }
3657 }
3658
3659 /*
3660 * Add the transient to the master's list, if it not already there.
3661 */
3662
3663 for (transient = wmPtr2->transientPtr;
3664 transient != NULL && transient->winPtr != winPtr;
3665 transient = transient->nextPtr) {}
3666 if (transient == NULL) {
3667 transient = ckalloc(sizeof(Transient));
3668 transient->winPtr = winPtr;
3669 transient->flags = 0;
3670 transient->nextPtr = wmPtr2->transientPtr;
3671 wmPtr2->transientPtr = transient;
3672 }
3673
3674 /*
3675 * If the master is withdrawn or iconic then withdraw the transient.
3676 */
3677
3678 if ((wmPtr2->hints.initial_state == WithdrawnState ||
3679 wmPtr2->hints.initial_state == IconicState) &&
3680 wmPtr->hints.initial_state != WithdrawnState) {
3681 TkpWmSetState(winPtr, WithdrawnState);
3682 transient->flags |= WITHDRAWN_BY_MASTER;
3683 }
3684
3685 wmPtr->master = (Tk_Window) masterPtr;
35213686 }
35223687 ApplyMasterOverrideChanges(winPtr, NULL);
35233688 return TCL_OK;
3689 }
3690
3691 /*
3692 *----------------------------------------------------------------------
3693 *
3694 * RemoveTransient --
3695 *
3696 * Clears the transient's master record and removes the transient from the
3697 * master's list.
3698 *
3699 * Results:
3700 * None
3701 *
3702 * Side effects:
3703 * References to a master are removed from the transient's wmInfo
3704 * structure and references to the transient are removed from its master's
3705 * wmInfo.
3706 *
3707 *----------------------------------------------------------------------
3708 */
3709
3710 static void
3711 RemoveTransient(
3712 TkWindow *winPtr)
3713 {
3714 WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
3715 TkWindow *masterPtr;
3716 Transient *transPtr, *temp;
3717
3718 if (wmPtr == NULL || wmPtr->master == NULL) {
3719 return;
3720 }
3721 masterPtr = (TkWindow*)wmPtr->master;
3722 wmPtr2 = masterPtr->wmInfoPtr;
3723 if (wmPtr2 == NULL) {
3724 return;
3725 }
3726 wmPtr->master = NULL;
3727 transPtr = wmPtr2->transientPtr;
3728 while (transPtr != NULL) {
3729 if (transPtr->winPtr != winPtr) {
3730 break;
3731 }
3732 temp = transPtr->nextPtr;
3733 ckfree(transPtr);
3734 transPtr = temp;
3735 }
3736 wmPtr2->transientPtr = transPtr;
3737 while (transPtr != NULL) {
3738 if (transPtr->nextPtr && transPtr->nextPtr->winPtr == winPtr) {
3739 temp = transPtr->nextPtr;
3740 transPtr->nextPtr = temp->nextPtr;
3741 ckfree(temp);
3742 } else {
3743 transPtr = transPtr->nextPtr;
3744 }
3745 }
35243746 }
35253747
35263748 /*
35623784 Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL);
35633785 return TCL_ERROR;
35643786 }
3787
35653788 TkpWmSetState(winPtr, WithdrawnState);
3566 /*Remove window from Window menu.*/
3789
35673790 NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
3791 [win orderOut:nil];
35683792 [win setExcludedFromWindowsMenu:YES];
35693793
3794 /*
3795 * If this window has a transient, the transient must also be withdrawn.
3796 */
3797
3798 for (Transient *transientPtr = wmPtr->transientPtr;
3799 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
3800 TkWindow *winPtr2 = transientPtr->winPtr;
3801 TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
3802
3803 if (masterPtr == winPtr &&
3804 winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
3805 TkpWmSetState(winPtr2, WithdrawnState);
3806 transientPtr->flags |= WITHDRAWN_BY_MASTER;
3807 }
3808 }
3809
35703810 return TCL_OK;
35713811 }
3572
3573 /*
3574 * Invoked by those wm subcommands that affect geometry.
3575 * Schedules a geometry update.
3812
3813 /*
3814 * Invoked by those wm subcommands that affect geometry. Schedules a geometry
3815 * update.
35763816 */
35773817
35783818 static void
36593899
36603900 /*
36613901 * If gridding was previously off, then forget about any window size
3662 * requests made by the user or via "wm geometry": these are in pixel
3663 * units and there's no easy way to translate them to grid units since the
3664 * new requested size of the top-level window in pixels may not yet have
3665 * been registered yet (it may filter up the hierarchy in DoWhenIdle
3666 * handlers). However, if the window has never been mapped yet then just
3667 * leave the window size alone: assume that it is intended to be in grid
3668 * units but just happened to have been specified before this procedure
3669 * was called.
3902 * requests made by the user or via "wm geometry": these are in pixel units
3903 * and there's no easy way to translate them to grid units since the new
3904 * requested size of the top-level window in pixels may not yet have been
3905 * registered yet (it may filter up the hierarchy in DoWhenIdle handlers).
3906 * However, if the window has never been mapped yet then just leave the
3907 * window size alone: assume that it is intended to be in grid units but
3908 * just happened to have been specified before this procedure was called.
36703909 */
36713910
36723911 if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {
39474186 } else if ((max > 0) && (height > max)) {
39484187 height = max;
39494188 }
3950
3951 /*
3952 * Compute the new position for the upper-left pixel of the window's
3953 * decorative frame. This is tricky, because we need to include the border
3954 * widths supplied by a reparented parent in this calculation, but can't
3955 * use the parent's current overall size since that may change as a result
3956 * of this code.
3957 */
3958
3959 if (wmPtr->flags & WM_NEGATIVE_X) {
3960 x = wmPtr->vRootWidth - wmPtr->x
3961 - (width + (wmPtr->parentWidth - winPtr->changes.width));
3962 } else {
3963 x = wmPtr->x;
3964 }
3965 if (wmPtr->flags & WM_NEGATIVE_Y) {
3966 y = wmPtr->vRootHeight - wmPtr->y
3967 - (height + (wmPtr->parentHeight - winPtr->changes.height));
3968 } else {
3969 y = wmPtr->y;
3970 }
4189 x = wmPtr->x;
4190 y = wmPtr->y;
39714191
39724192 /*
39734193 * If the window's size is going to change and the window is supposed to
41284348
41294349 width = wmPtr->width;
41304350 height = wmPtr->height;
4131 x = wmPtr->x;
4132 y = wmPtr->y;
4351 x = -1;
4352 y = -1;
41334353 flags = wmPtr->flags;
41344354 if (isdigit(UCHAR(*p))) {
41354355 width = strtoul(p, &end, 10);
41934413 * Everything was parsed OK. Update the fields of *wmPtr and arrange for
41944414 * the appropriate information to be percolated out to the window manager
41954415 * at the next idle moment.
4416 *
4417 * Computing the new position for the upper-left pixel of the window's
4418 * decorative frame is tricky because we need to include the border
4419 * widths supplied by a reparented parent in the calculation, but we can't
4420 * use the parent's current overall size since that may change as a result
4421 * of this code.
41964422 */
41974423
41984424 wmPtr->width = width;
41994425 wmPtr->height = height;
4200 if ((x != wmPtr->x) || (y != wmPtr->y)
4201 || ((flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y))
4202 != (wmPtr->flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y)))) {
4203 if (wmPtr->flags & WM_FULLSCREEN) {
4204 wmPtr->configX = x;
4205 wmPtr->configY = y;
4206 } else {
4207 wmPtr->x = x;
4208 wmPtr->y = y;
4209 }
4210 flags |= WM_MOVE_PENDING;
4211 }
4426 if (flags & WM_NEGATIVE_X) {
4427 int borderwidth = wmPtr->parentWidth - winPtr->changes.width;
4428 int newWidth = width == -1 ? winPtr->changes.width : width;
4429
4430 x = (x == -1) ?
4431 wmPtr->x + winPtr->changes.width - newWidth :
4432 wmPtr->vRootWidth - x - newWidth - borderwidth;
4433 }
4434 if (x == -1) {
4435 x = wmPtr->x;
4436 }
4437 if (flags & WM_NEGATIVE_Y) {
4438 int borderheight = wmPtr->parentHeight - winPtr->changes.height;
4439 int newHeight = height == -1 ? winPtr->changes.height : height;
4440
4441 y = (y == -1) ?
4442 wmPtr->y + winPtr->changes.height - newHeight :
4443 wmPtr->vRootHeight - y - newHeight - borderheight;
4444 }
4445 if (y == -1) {
4446 y = wmPtr->y;
4447 }
4448 if (wmPtr->flags & WM_FULLSCREEN) {
4449 wmPtr->configX = x;
4450 wmPtr->configY = y;
4451 } else {
4452 wmPtr->x = x;
4453 wmPtr->y = y;
4454 }
4455 flags |= WM_MOVE_PENDING;
42124456 wmPtr->flags = flags;
4213
42144457 if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
42154458 Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
42164459 wmPtr->flags |= WM_UPDATE_PENDING;
43244567 *
43254568 * Results:
43264569 * The return result is either a token for the window corresponding to
4327 * rootX and rootY, or else NULL to indicate that there is no such
4328 * window.
4570 * rootX and rootY, or else NULL to indicate that there is no such window.
43294571 *
43304572 * Side effects:
43314573 * None.
44174659 }
44184660 winPtr = nextPtr;
44194661 }
4662 if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
4663 return NULL;
4664 }
44204665 return (Tk_Window) winPtr;
44214666 }
44224667
46714916 wmPtr->x = x;
46724917 wmPtr->y = y;
46734918 wmPtr->flags |= WM_MOVE_PENDING;
4674 wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
46754919 if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {
46764920 wmPtr->sizeHintsFlags |= USPosition;
46774921 wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
47274971 /*
47284972 * If the Tk windows has no drawable, or is withdrawn do nothing.
47294973 */
4974
47304975 if (winPtr->window == None ||
4731 wmPtr == NULL ||
4732 wmPtr->hints.initial_state == WithdrawnState) {
4976 wmPtr == NULL ||
4977 wmPtr->hints.initial_state == WithdrawnState) {
47334978 return;
47344979 }
47354980 macWindow = TkMacOSXDrawableWindow(winPtr->window);
47384983 }
47394984 if (otherPtr) {
47404985 /*
4741 * When otherPtr is non-NULL, if the other window has no
4742 * drawable or is withdrawn, do nothing.
4986 * When otherPtr is non-NULL, if the other window has no drawable or is
4987 * withdrawn, do nothing.
47434988 */
4989
47444990 WmInfo *otherWmPtr = otherPtr->wmInfoPtr;
47454991 if (winPtr->window == None ||
4746 otherWmPtr == NULL ||
4747 otherWmPtr->hints.initial_state == WithdrawnState) {
4748 return;
4992 otherWmPtr == NULL ||
4993 otherWmPtr->hints.initial_state == WithdrawnState) {
4994 return;
47494995 }
47504996 otherMacWindow = TkMacOSXDrawableWindow(otherPtr->window);
47514997 if (otherMacWindow == nil) {
47524998 return;
4753 } else {
4754 /*
4755 * If the other window is OK, get its number.
4756 */
4757 otherNumber = [otherMacWindow windowNumber];
4758 }
4999 }
5000
5001 /*
5002 * If the other window is OK, get its number.
5003 */
5004
5005 otherNumber = [otherMacWindow windowNumber];
47595006 }
47605007
47615008 /*
4762 * Just let the Mac window manager deal with all the subtleties
4763 * of keeping track of off-screen windows, etc.
5009 * Just let the Mac window manager deal with all the subtleties of keeping
5010 * track of off-screen windows, etc.
47645011 */
5012
47655013 [macWindow orderWindow:macAboveBelow relativeTo:otherNumber];
47665014 }
47675015
49605208 *
49615209 * This function calculates the initial bounds for a new Mac toplevel
49625210 * window. Unless the geometry is specified by the user this code will
4963 * auto place the windows in a cascade diagonially across the main
4964 * monitor of the Mac.
5211 * auto place the windows in a cascade diagonially across the main monitor
5212 * of the Mac.
49655213 *
49665214 * Results:
49675215 * Window bounds.
49865234 cascadePoint = [macWindow cascadeTopLeftFromPoint:cascadePoint];
49875235 frame = [macWindow frame];
49885236 wmPtr->x = frame.origin.x;
4989 wmPtr->y = tkMacOSXZeroScreenHeight - (frame.origin.y +
5237 wmPtr->y = TkMacOSXZeroScreenHeight() - (frame.origin.y +
49905238 frame.size.height);
49915239 }
49925240 return NSMakeRect(wmPtr->x, wmPtr->y, winPtr->changes.width,
51085356 *----------------------------------------------------------------------
51095357 */
51105358
5111 Window
5359 Tk_Window
51125360 TkGetTransientMaster(
51135361 TkWindow *winPtr)
51145362 {
51155363 if (winPtr->wmInfoPtr != NULL) {
5116 return winPtr->wmInfoPtr->master;
5117 }
5118 return None;
5364 return (Tk_Window)winPtr->wmInfoPtr->master;
5365 }
5366 return NULL;
51195367 }
51205368
51215369 /*
51995447 TkMacOSXIsWindowZoomed(
52005448 TkWindow *winPtr)
52015449 {
5202 return [TkMacOSXDrawableWindow(winPtr->window) isZoomed];
5203 }
5204
5450 NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
5451 return [macWindow isZoomed];
5452 }
52055453
52065454 /*
52075455 *----------------------------------------------------------------------
52445492 * Do nothing if already in desired zoom state.
52455493 */
52465494
5247 if ((![window isZoomed] == (zoomPart == inZoomIn))) {
5495 if (([window isZoomed] == (zoomPart == inZoomOut))) {
52485496 return false;
52495497 }
5250 [window zoom:NSApp];
5251
5252 wmPtr->hints.initial_state =
5253 (zoomPart == inZoomIn ? NormalState : ZoomState);
5498 [window zoom:NSApp];
5499
5500 wmPtr->hints.initial_state =
5501 (zoomPart == inZoomIn ? NormalState : ZoomState);
52545502 return true;
52555503 }
52565504
52575505 /*
52585506 *----------------------------------------------------------------------
52595507 *
5260 * TkUnsupported1Cmd --
5508 * TkUnsupported1ObjCmd --
52615509 *
52625510 * This procedure is invoked to process the
52635511 * "::tk::unsupported::MacWindowStyle" Tcl command. This command allows
52815529 Tcl_Obj *const objv[]) /* Argument objects. */
52825530 {
52835531 static const char *const subcmds[] = {
5284 "style", NULL
5532 "style", "tabbingid", "appearance", "isdark", NULL
52855533 };
52865534 enum SubCmds {
5287 TKMWS_STYLE
5535 TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE, TKMWS_ISDARK
52885536 };
52895537 Tk_Window tkwin = clientData;
52905538 TkWindow *winPtr;
52945542 Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
52955543 return TCL_ERROR;
52965544 }
5297
52985545
52995546 winPtr = (TkWindow *)
53005547 Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
53125559 sizeof(char *), "option", 0, &index) != TCL_OK) {
53135560 return TCL_ERROR;
53145561 }
5315 if (((enum SubCmds) index) == TKMWS_STYLE) {
5562 switch((enum SubCmds) index) {
5563 case TKMWS_STYLE:
53165564 if ((objc < 3) || (objc > 5)) {
53175565 Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?");
53185566 return TCL_ERROR;
53195567 }
53205568 return WmWinStyle(interp, winPtr, objc, objv);
5321 }
5322 /* won't be reached */
5323 return TCL_ERROR;
5569 case TKMWS_TABID:
5570 if ([NSApp macMinorVersion] < 12) {
5571 Tcl_SetObjResult(interp, Tcl_NewStringObj(
5572 "Tabbing identifiers did not exist until OSX 10.12.", -1));
5573 Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TABBINGID", NULL);
5574 return TCL_ERROR;
5575 }
5576 if ((objc < 3) || (objc > 4)) {
5577 Tcl_WrongNumArgs(interp, 2, objv, "window ?newid?");
5578 return TCL_ERROR;
5579 }
5580 return WmWinTabbingId(interp, winPtr, objc, objv);
5581 case TKMWS_APPEARANCE:
5582 if ([NSApp macMinorVersion] < 9) {
5583 Tcl_SetObjResult(interp, Tcl_NewStringObj(
5584 "Window appearances did not exist until OSX 10.9.", -1));
5585 Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL);
5586 return TCL_ERROR;
5587 }
5588 if ((objc < 3) || (objc > 4)) {
5589 Tcl_WrongNumArgs(interp, 2, objv, "window ?appearancename?");
5590 return TCL_ERROR;
5591 }
5592 if (objc == 4 && [NSApp macMinorVersion] < 14) {
5593 Tcl_SetObjResult(interp, Tcl_NewStringObj(
5594 "Window appearances cannot be changed before OSX 10.14.",
5595 -1));
5596 Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL);
5597 return TCL_ERROR;
5598 }
5599 return WmWinAppearance(interp, winPtr, objc, objv);
5600 case TKMWS_ISDARK:
5601 if ((objc != 3)) {
5602 Tcl_WrongNumArgs(interp, 2, objv, "window");
5603 return TCL_ERROR;
5604 }
5605 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
5606 TkMacOSXInDarkMode((Tk_Window) winPtr)));
5607 return TCL_OK;
5608 default:
5609 return TCL_ERROR;
5610 }
53245611 }
53255612
53265613 /*
54135700 { "moveToActiveSpace", tkMoveToActiveSpaceAttribute },
54145701 { "nonActivating", tkNonactivatingPanelAttribute },
54155702 { "hud", tkHUDWindowAttribute },
5416 { "black", 0 },
5417 { "dark", 0 },
5418 { "light", 0 },
5419 { "gray", 0 },
5420 { "red", 0 },
5421 { "green", 0 },
5422 { "blue", 0 },
5423 { "cyan", 0 },
5424 { "yellow", 0 },
5425 { "magenta", 0 },
5426 { "orange", 0 },
5427 { "purple", 0 },
5428 { "brown", 0 },
5429 { "clear", 0 },
5430 { "opacity", 0 },
54315703 { NULL }
54325704 };
54335705
55095781 macClassAttrs[macClass].validAttrs);
55105782 wmPtr->flags |= macClassAttrs[macClass].flags;
55115783 wmPtr->macClass = macClass;
5512
55135784 ApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags,
55145785 0, 1);
5515
55165786 return TCL_OK;
55175787
55185788 badClassAttrs:
55215791 }
55225792
55235793 return TCL_OK;
5794 }
5795
5796 /*
5797 *----------------------------------------------------------------------
5798 *
5799 * WmWinTabbingId --
5800 *
5801 * This procedure is invoked to process the
5802 * "::tk::unsupported::MacWindowStyle tabbingid" subcommand. The command
5803 * allows you to get or set the tabbingIdentifier for the NSWindow
5804 * associated with a Tk Window. The syntax is:
5805 *
5806 * tk::unsupported::MacWindowStyle tabbingid window ?newId?
5807 *
5808 * Results:
5809 * Returns the tabbingIdentifier of the window prior to calling this
5810 * function. If the optional newId argument is omitted, the window's
5811 * tabbingIdentifier is not changed.
5812 *
5813 * Side effects:
5814 * Windows may only be grouped together as tabs if they all have the same
5815 * tabbingIdentifier. In particular, by giving a window a unique
5816 * tabbingIdentifier one can prevent it from becoming a tab in any other
5817 * window. Changing the tabbingIdentifier of a window which is already
5818 * a tab causes it to become a separate window.
5819 *
5820 *----------------------------------------------------------------------
5821 */
5822
5823 static int
5824 WmWinTabbingId(
5825 Tcl_Interp *interp, /* Current interpreter. */
5826 TkWindow *winPtr, /* Window to be manipulated. */
5827 int objc, /* Number of arguments. */
5828 Tcl_Obj * const objv[]) /* Argument objects. */
5829 {
5830 #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101200)
5831 Tcl_Obj *result = NULL;
5832 NSString *idString;
5833 NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
5834 if (win) {
5835 idString = win.tabbingIdentifier;
5836 result = Tcl_NewStringObj(idString.UTF8String, [idString length]);
5837 }
5838 if (result == NULL) {
5839 NSLog(@"Failed to read tabbing identifier; try calling update idletasks before getting/setting the tabbing identifier of the window.");
5840 return TCL_OK;
5841 }
5842 Tcl_SetObjResult(interp, result);
5843 if (objc == 3) {
5844 return TCL_OK;
5845 } else if (objc == 4) {
5846 int len;
5847 char *newId = Tcl_GetStringFromObj(objv[3], &len);
5848 NSString *newIdString = [NSString stringWithUTF8String:newId];
5849 [win setTabbingIdentifier: newIdString];
5850
5851 /*
5852 * If the tabbingIdentifier of a tab is changed we also turn it into a
5853 * separate window so we don't violate the rule that all tabs in the
5854 * same frame must have the same tabbingIdentifier.
5855 */
5856
5857 if ([idString compare:newIdString] != NSOrderedSame
5858 #if MAC_OS_X_VERSION_MIN_REQUIRED > 101200
5859 && [win tab]
5860 #endif
5861 ) {
5862 [win moveTabToNewWindow:nil];
5863 }
5864 return TCL_OK;
5865 }
5866 #endif
5867 return TCL_ERROR;
5868 }
5869
5870 /*
5871 *----------------------------------------------------------------------
5872 *
5873 * WmWinAppearance --
5874 *
5875 * This procedure is invoked to process the
5876 * "::tk::unsupported::MacWindowStyle appearance" subcommand. The command
5877 * allows you to get or set the appearance for the NSWindow associated
5878 * with a Tk Window. The syntax is:
5879 *
5880 * tk::unsupported::MacWindowStyle tabbingid window ?newAppearance?
5881 *
5882 * Allowed appearance names are "aqua", "darkaqua", and "auto".
5883 *
5884 * Results:
5885 * Returns the appearance setting of the window prior to calling this
5886 * function.
5887 *
5888 * Side effects:
5889 * The underlying NSWindow's appearance property is set to the specified
5890 * value if the optional newAppearance argument is supplied. Otherwise the
5891 * window's appearance property is not changed. If the appearance is set
5892 * to aqua or darkaqua then the window will use the associated
5893 * NSAppearance even if the user has selected a different appearance with
5894 * the system preferences. If it is set to auto then the appearance
5895 * property is set to nil, meaning that the preferences will determine the
5896 * appearance.
5897 *
5898 *----------------------------------------------------------------------
5899 */
5900
5901 static int
5902 WmWinAppearance(
5903 Tcl_Interp *interp, /* Current interpreter. */
5904 TkWindow *winPtr, /* Window to be manipulated. */
5905 int objc, /* Number of arguments. */
5906 Tcl_Obj * const objv[]) /* Argument objects. */
5907 {
5908 #if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
5909 static const char *const appearanceStrings[] = {
5910 "aqua", "darkaqua", "auto", NULL
5911 };
5912 enum appearances {
5913 APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO
5914 };
5915 Tcl_Obj *result = NULL;
5916 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
5917 NSAppearanceName appearance;
5918 #else
5919 NSString *appearance;
5920 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
5921
5922 const char *resultString = "unrecognized";
5923 NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
5924 if (win) {
5925 appearance = win.appearance.name;
5926 if (appearance == nil) {
5927 resultString = appearanceStrings[APPEARANCE_AUTO];
5928 } else if (appearance == NSAppearanceNameAqua) {
5929 resultString = appearanceStrings[APPEARANCE_AQUA];
5930 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
5931 } else if (@available(macOS 10.14, *)) {
5932 if (appearance == NSAppearanceNameDarkAqua) {
5933 resultString = appearanceStrings[APPEARANCE_DARKAQUA];
5934 }
5935 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
5936 }
5937 result = Tcl_NewStringObj(resultString, strlen(resultString));
5938 }
5939 if (result == NULL) {
5940 NSLog(@"Failed to read appearance name; try calling update idletasks before getting/setting the appearance of the window.");
5941 return TCL_OK;
5942 }
5943 if (objc == 4) {
5944 int index;
5945 if (Tcl_GetIndexFromObjStruct(interp, objv[3], appearanceStrings,
5946 sizeof(char *), "appearancename", 0, &index) != TCL_OK) {
5947 return TCL_ERROR;
5948 }
5949 switch ((enum appearances) index) {
5950 case APPEARANCE_AQUA:
5951 win.appearance = [NSAppearance appearanceNamed:
5952 NSAppearanceNameAqua];
5953 break;
5954 case APPEARANCE_DARKAQUA:
5955 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
5956 if (@available(macOS 10.14, *)) {
5957 win.appearance = [NSAppearance appearanceNamed:
5958 NSAppearanceNameDarkAqua];
5959 }
5960 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
5961 break;
5962 default:
5963 win.appearance = nil;
5964 }
5965 }
5966 Tcl_SetObjResult(interp, result);
5967 return TCL_OK;
5968 #else // MAC_OS_X_VERSION_MAX_ALLOWED > 1090
5969 return TCL_ERROR;
5970 #endif
55245971 }
55255972
55265973 /*
55846031 {
55856032 WmInfo *wmPtr = winPtr->wmInfoPtr;
55866033 MacDrawable *macWin;
6034 WindowClass macClass;
6035 Bool overrideRedirect = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
55876036
55886037 if (TkMacOSXHostToplevelExists(winPtr)) {
55896038 return;
55926041 macWin = (MacDrawable *) winPtr->window;
55936042
55946043 /*
5595 * If this is embedded, make sure its container's toplevel exists,
5596 * then return...
6044 * If this is embedded, make sure its container's toplevel exists, then
6045 * return...
55976046 */
55986047
55996048 if (Tk_IsEmbedded(winPtr)) {
56206069 * TODO: Here we should handle out of process embedding.
56216070 */
56226071 }
5623 WindowClass macClass = wmPtr->macClass;
6072
6073 /*
6074 * If this is an override-redirect window, the NSWindow is created first as
6075 * a document window then converted to a simple window.
6076 */
6077
6078 if (overrideRedirect) {
6079 wmPtr->macClass = kDocumentWindowClass;
6080 }
6081 macClass = wmPtr->macClass;
56246082 wmPtr->attributes &= (tkAlwaysValidAttributes |
56256083 macClassAttrs[macClass].validAttrs);
56266084 wmPtr->flags |= macClassAttrs[macClass].flags |
56486106 NSRect structureRect = [winClass frameRectForContentRect:NSZeroRect
56496107 styleMask:styleMask];
56506108 NSRect contentRect = NSMakeRect(5 - structureRect.origin.x,
5651 tkMacOSXZeroScreenHeight - (tkMacOSXZeroScreenTop + 5 +
6109 TkMacOSXZeroScreenHeight() - (TkMacOSXZeroScreenTop() + 5 +
56526110 structureRect.origin.y + structureRect.size.height + 200), 200, 200);
56536111 NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
56546112 styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
56686126 if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) &&
56696127 !(styleMask & NSDocModalWindowMask)) {
56706128 /*
5671 * Workaround for [Bug 2824538]: Textured windows are draggable
5672 * from opaque content.
6129 * Workaround for [Bug 2824538]: Textured windows are draggable from
6130 * opaque content.
56736131 */
56746132 [window setMovableByWindowBackground:NO];
56756133 }
5676
56776134 [window setDocumentEdited:NO];
56786135 wmPtr->window = window;
56796136 macWin->view = window.contentView;
56806137 TkMacOSXApplyWindowAttributes(winPtr, window);
5681
56826138 NSRect geometry = InitialWindowBounds(winPtr, window);
5683 geometry.size.width += structureRect.size.width;
6139 geometry.size.width += structureRect.size.width;
56846140 geometry.size.height += structureRect.size.height;
5685 geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y +
6141 geometry.origin.y = TkMacOSXZeroScreenHeight() - (geometry.origin.y +
56866142 geometry.size.height);
56876143 [window setFrame:geometry display:YES];
56886144 TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
6145
56896146 macWin->flags |= TK_HOST_EXISTS;
6147 if (overrideRedirect) {
6148 XSetWindowAttributes atts;
6149
6150 atts.override_redirect = True;
6151 Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
6152 ApplyMasterOverrideChanges(winPtr, NULL);
6153 }
56906154 }
56916155
56926156 /*
56946158 *
56956159 * TkpDisplayWindow --
56966160 *
5697 * Mark the contentView of this window as needing display so the
5698 * window will be drawn by the window manager. If this is called
5699 * within the drawRect method, do nothing.
6161 * Mark the contentView of this window as needing display so the window
6162 * will be drawn by the window manager. If this is called within the
6163 * drawRect method, do nothing.
57006164 *
57016165 * Results:
57026166 * None.
57106174 MODULE_SCOPE void
57116175 TkpDisplayWindow(Tk_Window tkwin) {
57126176 if (![NSApp isDrawing]) {
5713 TkWindow *winPtr = (TkWindow*)tkwin;
6177 TkWindow *winPtr = (TkWindow *) tkwin;
57146178 NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
6179
57156180 [[w contentView] setNeedsDisplay: YES];
57166181 }
57176182 }
57216186 *
57226187 * TkMacOSXRegisterOffScreenWindow --
57236188 *
5724 * This function adds the passed in Off Screen Port to the hash table
5725 * that maps Mac windows to root X windows.
6189 * This function adds the passed in Off Screen Port to the hash table that
6190 * maps Mac windows to root X windows.
57266191 *
57276192 * Results:
57286193 * None.
60616526 *----------------------------------------------------------------------
60626527 */
60636528
6064 void
6529 int
60656530 XSetInputFocus(
60666531 Display* display,
60676532 Window focus,
60716536 /*
60726537 * Don't need to do a thing. Tk manages the focus for us.
60736538 */
6539 return Success;
60746540 }
60756541
60766542 /*
60786544 *
60796545 * TkpChangeFocus --
60806546 *
6081 * This procedure is a stub on the Mac because we always own the focus if
6082 * we are a front most application.
6547 * This function is called when Tk moves focus from one window to another.
6548 * It should be passed a non-embedded TopLevel. That toplevel gets raised
6549 * to the top of the Tk stacking order and the associated NSWindow is
6550 * ordered Front.
60836551 *
60846552 * Results:
60856553 * The return value is the serial number of the command that changed the
61046572 return 0;
61056573 }
61066574
6107 if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) ){
6575 if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) {
61086576 NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
6577
61096578 TkWmRestackToplevel(winPtr, Above, NULL);
6110 if (force ) {
6579 if (force) {
61116580 [NSApp activateIgnoringOtherApps:YES];
61126581 }
6113 if ( win && [win canBecomeKeyWindow] ) {
6582 if (win && [win canBecomeKeyWindow]) {
61146583 [win makeKeyAndOrderFront:NSApp];
61156584 }
61166585 }
61566625 Tcl_HashEntry *hPtr;
61576626 int newEntry;
61586627
6159 if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr)
6628 if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)
61606629 && (winPtr->display == display)) {
61616630 hPtr = Tcl_CreateHashEntry(table,
61626631 (char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry);
61776646 * This procedure returns the stack order of toplevel windows.
61786647 *
61796648 * Results:
6180 * An array of pointers to tk window objects in stacking order or else
6181 * NULL if there was an error.
6649 * A NULL terminated array of pointers to tk window objects in stacking
6650 * order or else NULL if there was an error.
61826651 *
61836652 * Side effects:
61846653 * None.
61936662 TkWindow *childWinPtr, **windows, **windowPtr;
61946663 Tcl_HashTable table;
61956664 Tcl_HashEntry *hPtr;
6196 Tcl_HashSearch search;
6197
6198 /*
6199 * Map mac windows to a TkWindow of the wrapped toplevel.
6200 */
6201
6202 Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
6203 WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
6204
6205 windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
6206
6207 /*
6208 * Special cases: If zero or one toplevels were mapped there is no need to
6209 * enumerate Windows.
6210 */
6211
6212 switch (table.numEntries) {
6213 case 0:
6214 windows[0] = NULL;
6215 goto done;
6216 case 1:
6217 hPtr = Tcl_FirstHashEntry(&table, &search);
6218 windows[0] = Tcl_GetHashValue(hPtr);
6219 windows[1] = NULL;
6220 goto done;
6221 }
6222
62236665 NSArray *macWindows = [NSApp orderedWindows];
6666 NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects];
62246667 NSInteger windowCount = [macWindows count];
62256668
6226 if (!windowCount) {
6227 ckfree(windows);
6228 windows = NULL;
6229 } else {
6230 windowPtr = windows + table.numEntries;
6231 *windowPtr-- = NULL;
6232 for (NSWindow *w in macWindows) {
6669 windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *));
6670 if (windows != NULL) {
6671 Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
6672 WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
6673 for (NSWindow *w in backToFront) {
62336674 hPtr = Tcl_FindHashEntry(&table, (char*) w);
62346675 if (hPtr != NULL) {
62356676 childWinPtr = Tcl_GetHashValue(hPtr);
6236 *windowPtr-- = childWinPtr;
6677 *windowPtr++ = childWinPtr;
62376678 }
62386679 }
6239 if (windowPtr != windows-1) {
6240 Tcl_Panic("num matched toplevel windows does not equal num "
6241 "children");
6242 }
6243 }
6244
6245 done:
6246 Tcl_DeleteHashTable(&table);
6680 *windowPtr = NULL;
6681 Tcl_DeleteHashTable(&table);
6682 }
62476683 return windows;
62486684 }
62496685
62696705 NSWindow *macWindow)
62706706 {
62716707 WmInfo *wmPtr = winPtr->wmInfoPtr;
6708
62726709 ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1);
6273 if (wmPtr->master != None || winPtr->atts.override_redirect) {
6710 if (wmPtr->master != NULL || winPtr->atts.override_redirect) {
62746711 ApplyMasterOverrideChanges(winPtr, macWindow);
62756712 }
62766713 }
63086745 if (changedAttributes || wmPtr->flags != oldFlags || initial) {
63096746 if (!macWindow) {
63106747 if (winPtr->window == None) {
6311 if (create) {
6312 Tk_MakeWindowExist((Tk_Window) winPtr);
6313 } else {
6748 if (!create) {
63146749 return;
63156750 }
6751 Tk_MakeWindowExist((Tk_Window) winPtr);
63166752 }
63176753 if (!TkMacOSXHostToplevelExists(winPtr)) {
6318 if (create) {
6319 TkMacOSXMakeRealWindowExist(winPtr);
6320 } else {
6754 if (!create) {
63216755 return;
63226756 }
6757 TkMacOSXMakeRealWindowExist(winPtr);
63236758 }
63246759 macWindow = TkMacOSXDrawableWindow(winPtr->window);
63256760 }
63566791 if ((newAttributes & kWindowToolbarButtonAttribute) &&
63576792 ![macWindow toolbar]) {
63586793 NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""];
6794
63596795 [toolbar setVisible:NO];
63606796 [macWindow setToolbar:toolbar];
63616797 [toolbar release];
63896825 tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute)) ||
63906826 initial) {
63916827 NSWindowCollectionBehavior b = NSWindowCollectionBehaviorDefault;
6828
6829 /*
6830 * This behavior, which makes the green button expand a window to
6831 * full screen, was included in the default as of OSX 10.13. For
6832 * uniformity we use the new default in all versions of the OS
6833 * after 10.10.
6834 */
6835
6836 #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101000)
6837 if (!(macWindow.styleMask & NSUtilityWindowMask)) {
6838 /*
6839 * Exclude overrideredirect, transient, and "help"-styled
6840 * windows from moving into their own fullscreen space.
6841 */
6842
6843 if ((winPtr->atts.override_redirect) ||
6844 (wmPtr->master != NULL) ||
6845 (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {
6846 b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |
6847 NSWindowCollectionBehaviorFullScreenAuxiliary);
6848 } else {
6849 NSSize screenSize = [[macWindow screen] frame].size;
6850 b |= NSWindowCollectionBehaviorFullScreenPrimary;
6851
6852 /*
6853 * The default max size has height less than the screen
6854 * height. This causes the window manager to refuse to
6855 * allow the window to be resized when it is a split
6856 * window. To work around this we make the max size equal
6857 * to the screen size. (For 10.11 and up, only)
6858 */
6859 if ([NSApp macMinorVersion] > 10) {
6860 [macWindow setMaxFullScreenContentSize:screenSize];
6861 }
6862 }
6863 }
6864 #endif
6865
63926866 if (newAttributes & tkCanJoinAllSpacesAttribute) {
63936867 b |= NSWindowCollectionBehaviorCanJoinAllSpaces;
63946868 } else if (newAttributes & tkMoveToActiveSpaceAttribute) {
64106884
64116885 /*
64126886 * The change of window class/attributes might have changed the window
6413 * structure widths:
6887 * frame geometry:
64146888 */
64156889
64166890 NSRect structureRect = [macWindow frameRectForContentRect:NSZeroRect];
6891
64176892 wmPtr->xInParent = -structureRect.origin.x;
64186893 wmPtr->yInParent = structureRect.origin.y + structureRect.size.height;
64196894 wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;
64456920 WmInfo *wmPtr = winPtr->wmInfoPtr;
64466921 UInt64 oldAttributes = wmPtr->attributes;
64476922 int oldFlags = wmPtr->flags;
6923 unsigned long styleMask;
6924 NSRect structureRect;
6925 NSWindow *parentWindow;
6926
6927 if (!macWindow && winPtr->window != None &&
6928 TkMacOSXHostToplevelExists(winPtr)) {
6929 macWindow = TkMacOSXDrawableWindow(winPtr->window);
6930 }
6931 styleMask = [macWindow styleMask];
64486932
64496933 /*
64506934 * FIX: We need an UpdateWrapper equivalent to make this 100% correct
64566940 wmPtr->attributes = macClassAttrs[kSimpleWindowClass].defaultAttrs;
64576941 }
64586942 wmPtr->attributes |= kWindowNoActivatesAttribute;
6943 if ([NSApp macMinorVersion] == 6) {
6944 styleMask = 0;
6945 } else {
6946 styleMask &= ~NSTitledWindowMask;
6947 }
64596948 } else {
64606949 if (wmPtr->macClass == kSimpleWindowClass &&
64616950 oldAttributes == kWindowNoActivatesAttribute) {
64646953 macClassAttrs[kDocumentWindowClass].defaultAttrs;
64656954 }
64666955 wmPtr->attributes &= ~kWindowNoActivatesAttribute;
6467 }
6468 if (!macWindow && winPtr->window != None &&
6469 TkMacOSXHostToplevelExists(winPtr)) {
6470 macWindow = TkMacOSXDrawableWindow(winPtr->window);
6956 if ([NSApp macMinorVersion] == 6) {
6957 styleMask = NSTitledWindowMask |
6958 NSClosableWindowMask |
6959 NSMiniaturizableWindowMask |
6960 NSResizableWindowMask;
6961 } else {
6962 styleMask |= NSTitledWindowMask;
6963 }
64716964 }
64726965 if (macWindow) {
6473 if (winPtr->atts.override_redirect && wmPtr->master != None) {
6474 wmPtr->flags |= WM_TOPMOST;
6966 structureRect = [NSWindow frameRectForContentRect:NSZeroRect
6967 styleMask:styleMask];
6968
6969 /*
6970 * Synchronize the wmInfoPtr to match the new window configuration
6971 * so windowBoundsChanged won't corrupt the window manager info.
6972 */
6973
6974 wmPtr->xInParent = -structureRect.origin.x;
6975 wmPtr->yInParent = structureRect.origin.y + structureRect.size.height;
6976 wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;
6977 wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;
6978 if (winPtr->atts.override_redirect) {
6979 [macWindow setExcludedFromWindowsMenu:YES];
6980 [macWindow setStyleMask:styleMask];
6981 if (wmPtr->hints.initial_state == NormalState) {
6982 [macWindow orderFront:nil];
6983 }
6984 if (wmPtr->master != NULL) {
6985 wmPtr->flags |= WM_TOPMOST;
6986 } else {
6987 wmPtr->flags &= ~WM_TOPMOST;
6988 }
64756989 } else {
6990 const char *title = winPtr->wmInfoPtr->titleUid;
6991
6992 if (!title) {
6993 title = winPtr->nameUid;
6994 }
6995 [macWindow setStyleMask:styleMask];
6996 [macWindow setTitle:[NSString stringWithUTF8String:title]];
6997 [macWindow setExcludedFromWindowsMenu:NO];
64766998 wmPtr->flags &= ~WM_TOPMOST;
64776999 }
6478 NSWindow *parentWindow = [macWindow parentWindow];
64797000 if (wmPtr->master != None) {
6480 TkDisplay *dispPtr = TkGetDisplayList();
6481 TkWindow *masterWinPtr = (TkWindow *)
6482 Tk_IdToWindow(dispPtr->display, wmPtr->master);
6483
6484 if (masterWinPtr && masterWinPtr->window != None &&
6485 TkMacOSXHostToplevelExists(masterWinPtr)) {
6486 NSWindow *masterMacWin =
6487 TkMacOSXDrawableWindow(masterWinPtr->window);
6488
6489 if (masterMacWin && masterMacWin != parentWindow &&
6490 (winPtr->flags & TK_MAPPED)) {
6491 if (parentWindow) {
7001 TkWindow *masterWinPtr = (TkWindow *) wmPtr->master;
7002
7003 if (masterWinPtr && (masterWinPtr->window != None)
7004 && TkMacOSXHostToplevelExists(masterWinPtr)) {
7005 NSWindow *masterMacWin = TkMacOSXDrawableWindow(
7006 masterWinPtr->window);
7007
7008 /*
7009 * Try to add the transient window as a child window of the
7010 * master. A child NSWindow retains its relative position with
7011 * respect to the parent when the parent is moved. This is
7012 * pointless if the parent is offscreen, and adding a child to
7013 * an offscreen window causes the parent to be displayed as a
7014 * zombie. So we only do this if the parent is visible.
7015 */
7016
7017 if (masterMacWin && [masterMacWin isVisible]
7018 && (winPtr->flags & TK_MAPPED)) {
7019 /*
7020 * If the transient is already a child of some other window,
7021 * remove it.
7022 */
7023
7024 parentWindow = [macWindow parentWindow];
7025 if (parentWindow && parentWindow != masterMacWin) {
64927026 [parentWindow removeChildWindow:macWindow];
64937027 }
7028
64947029 [masterMacWin addChildWindow:macWindow
6495 ordered:NSWindowAbove];
6496 if (wmPtr->flags & WM_TOPMOST) {
6497 [macWindow setLevel:kCGUtilityWindowLevel];
6498 }
7030 ordered:NSWindowAbove];
64997031 }
65007032 }
6501 } else if (parentWindow) {
6502 [parentWindow removeChildWindow:macWindow];
7033 } else {
7034 parentWindow = [macWindow parentWindow];
7035 if (parentWindow) {
7036 [parentWindow removeChildWindow:macWindow];
7037 }
7038 }
7039 if (wmPtr->flags & WM_TOPMOST) {
7040 [macWindow setLevel:kCGUtilityWindowLevel];
65037041 }
65047042 ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,
65057043 oldFlags, 0, 0);
65067044 }
6507 }
6508
6509 /*
6510 *----------------------------------------------------------------------
6511 *
6512 * TkMacOSXMakeFullscreen --
6513 *
6514 * This procedure sets a fullscreen window to the size of the screen.
6515 *
6516 * Results:
6517 * A standard Tcl result.
6518 *
6519 * Side effects:
6520 * None.
6521 *
6522 *----------------------------------------------------------------------
6523 */
6524
6525 int
6526 TkMacOSXMakeFullscreen(
6527 TkWindow *winPtr,
6528 NSWindow *window,
6529 int fullscreen,
6530 Tcl_Interp *interp)
6531 {
6532 WmInfo *wmPtr = winPtr->wmInfoPtr;
6533 int screenWidth = WidthOfScreen(Tk_Screen(winPtr));
6534 int screenHeight = HeightOfScreen(Tk_Screen(winPtr));
6535
6536 if (fullscreen) {
6537
6538 /*
6539 * Check max width and height if set by the user.
6540 */
6541
6542 if ((wmPtr->maxWidth > 0 && wmPtr->maxWidth < screenWidth)
6543 || (wmPtr->maxHeight > 0 && wmPtr->maxHeight < screenHeight)) {
6544 if (interp) {
6545 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
6546 "can't set fullscreen attribute for \"%s\": max"
6547 " width/height is too small", winPtr->pathName));
6548 Tcl_SetErrorCode(interp, "TK", "FULLSCREEN",
6549 "CONSTRAINT_FAILURE", NULL);
6550 }
6551 wmPtr->flags &= ~WM_FULLSCREEN;
6552 return TCL_ERROR;
6553 }
6554
6555 /*
6556 * Save the current window state.
6557 */
6558
6559 wmPtr->cachedBounds = [window frame];
6560 wmPtr->cachedStyle = [window styleMask];
6561 wmPtr->cachedPresentation = [NSApp presentationOptions];
6562
6563 /*
6564 * Adjust the window style so it looks like a Fullscreen window.
6565 */
6566
6567 [window setStyleMask: NSFullScreenWindowMask];
6568 [NSApp setPresentationOptions: (NSApplicationPresentationAutoHideDock |
6569 NSApplicationPresentationAutoHideMenuBar)];
6570
6571 /*For 10.13 and later add a button for exiting Fullscreen.*/
6572 if ([NSApp macMinorVersion] > 12) {
6573 #if MAC_OS_X_VERSION_MAX_ALLOWED > 101200
6574 exitFullScreen = [[[NSStatusBar systemStatusBar]
6575 statusItemWithLength:NSVariableStatusItemLength] retain];
6576 NSImage *exitIcon = [NSImage imageNamed:@"NSExitFullScreenTemplate"];
6577 exitFullScreen.button.image = exitIcon;
6578 exitFullScreen.button.cell.highlighted = NO;
6579 exitFullScreen.button.toolTip = @"Exit Full Screen";
6580 exitFullScreen.button.target = window;
6581 exitFullScreen.button.action = @selector(restoreOldScreen:);
6582 #endif
6583 }
6584
6585 /*
6586 * Resize the window to fill the screen. (After setting the style!)
6587 */
6588
6589 wmPtr->flags |= WM_SYNC_PENDING;
6590 NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight);
6591 [window setFrame:screenBounds display:YES];
6592 wmPtr->flags &= ~WM_SYNC_PENDING;
6593 wmPtr->flags |= WM_FULLSCREEN;
6594 } else {
6595
6596 /*
6597 * Restore the previous styles and attributes.
6598 */
6599
6600 [NSApp setPresentationOptions: wmPtr->cachedPresentation];
6601 [window setStyleMask: wmPtr->cachedStyle];
6602 UInt64 oldAttributes = wmPtr->attributes;
6603 wmPtr->flags &= ~WM_FULLSCREEN;
6604 wmPtr->attributes |= wmPtr->configAttributes &
6605 kWindowResizableAttribute;
6606 ApplyWindowAttributeFlagChanges(winPtr, window, oldAttributes,
6607 wmPtr->flags, 1, 0);
6608
6609 /*
6610 * Resize the window to its previous size.
6611 */
6612
6613 wmPtr->flags |= WM_SYNC_PENDING;
6614 [window setFrame:wmPtr->cachedBounds display:YES];
6615 wmPtr->flags &= ~WM_SYNC_PENDING;
6616 }
6617 return TCL_OK;
66187045 }
66197046
66207047 /*
67927219 MacDrawable *parentWin)
67937220 {
67947221 TkWindow *childPtr;
7222
67957223 /*
67967224 * Remove the OS specific window. It will get rebuilt when the window gets
67977225 * Mapped.
68097237 #endif
68107238 }
68117239
6812 /* Repeat for all the children */
7240 /*
7241 * Repeat for all the children.
7242 */
7243
68137244 for (childPtr = winPtr->childList; childPtr != NULL;
68147245 childPtr = childPtr->nextPtr) {
68157246 RemapWindows(childPtr, (MacDrawable *) winPtr->window);
3535 * THE LAST FIELD OF THE STRUCTURE. */
3636 } ProtocolHandler;
3737
38 /* The following data structure is used in the TkWmInfo to maintain a list of all of the
39 * transient windows belonging to a given master.
40 */
41
42 typedef struct Transient {
43 TkWindow *winPtr;
44 int flags;
45 struct Transient *nextPtr;
46 } Transient;
47
48 #define WITHDRAWN_BY_MASTER 0x1
3849
3950 /*
4051 * A data structure of the following type holds window-manager-related
5364 Tk_Uid titleUid; /* Title to display in window caption. If NULL,
5465 * use name of widget. */
5566 char *iconName; /* Name to display in icon. */
56 Window master; /* Master window for TRANSIENT_FOR property, or
67 Tk_Window master; /* Master window for TRANSIENT_FOR property, or
5768 * None. */
5869 XWMHints hints; /* Various pieces of information for window
5970 * manager. */
6172 * (corresponds to hints.window_group).
6273 * Malloc-ed. Note: this field doesn't get
6374 * updated if leader is destroyed. */
64 char *masterWindowName; /* Path name of window specified as master in
65 * "wm transient" command, or NULL. Malloc-ed.
66 * Note: this field doesn't get updated if
67 * masterWindowName is destroyed. */
6875 Tk_Window icon; /* Window to use as icon for this window, or
6976 * NULL. */
7077 Tk_Window iconFor; /* Window for which this window is icon, or
7178 * NULL if this isn't an icon for anyone. */
79 Transient *transientPtr; /* First item in a list of all transient windows
80 * belonging to this window, or NULL if there
81 * are no transients. */
7282
7383 /*
7484 * Information used to construct an XSizeHints structure for the window
3131 #endif
3232
3333 #define ROOT_ID 10
34
35 CGFloat tkMacOSXZeroScreenHeight = 0;
36 CGFloat tkMacOSXZeroScreenTop = 0;
3734
3835 /*
3936 * Declarations of static variables used in this file.
8986 nsScreens = [NSScreen screens];
9087 if (nsScreens && [nsScreens count]) {
9188 NSScreen *s = [nsScreens objectAtIndex:0];
92 NSRect bounds = [s frame], visible = [s visibleFrame];
89 NSRect bounds = [s frame];
9390 NSRect maxBounds = NSZeroRect;
94
95 tkMacOSXZeroScreenHeight = bounds.size.height;
96 tkMacOSXZeroScreenTop = tkMacOSXZeroScreenHeight -
97 (visible.origin.y + visible.size.height);
9891
9992 screen->root_depth = NSBitsPerPixelFromDepth([s depth]);
10093 screen->width = bounds.size.width;
107100 }
108101 *((NSRect *)screen->ext_data) = maxBounds;
109102 }
103 }
104
105 /*
106 *----------------------------------------------------------------------
107 *
108 * TkMacOSXZeroScreenHeight --
109 *
110 * Replacement for the tkMacOSXZeroScreenHeight variable to avoid
111 * caching values from NSScreen (fixes bug aea00be199).
112 *
113 * Results:
114 * Returns the height of screen 0 (the screen assigned the menu bar
115 * in System Preferences), or 0.0 if getting [NSScreen screens] fails.
116 *
117 * Side effects:
118 * None.
119 *
120 *----------------------------------------------------------------------
121 */
122
123 CGFloat
124 TkMacOSXZeroScreenHeight()
125 {
126 NSArray *nsScreens = [NSScreen screens];
127 if (nsScreens && [nsScreens count]) {
128 NSScreen *s = [nsScreens objectAtIndex:0];
129 NSRect bounds = [s frame];
130 return bounds.size.height;
131 }
132 return 0.0;
133 }
134
135 /*
136 *----------------------------------------------------------------------
137 *
138 * TkMacOSXZeroScreenTop --
139 *
140 * Replacement for the tkMacOSXZeroScreenTop variable to avoid
141 * caching values from visibleFrame.
142 *
143 * Results:
144 * Returns how far below the top of screen 0 to draw
145 * (i.e. the height of the menu bar if it is always shown),
146 * or 0.0 if getting [NSScreen screens] fails.
147 *
148 * Side effects:
149 * None.
150 *
151 *----------------------------------------------------------------------
152 */
153
154 CGFloat
155 TkMacOSXZeroScreenTop()
156 {
157 NSArray *nsScreens = [NSScreen screens];
158 if (nsScreens && [nsScreens count]) {
159 NSScreen *s = [nsScreens objectAtIndex:0];
160 NSRect bounds = [s frame], visible = [s visibleFrame];
161 return bounds.size.height - (visible.origin.y + visible.size.height);
162 }
163 return 0.0;
110164 }
111165
112166 /*
177231 {
178232 int major, minor, patch;
179233
180 #if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
234 #if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
181235 Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
182236 Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
183237 Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
201255
202256 screen->root_visual = ckalloc(sizeof(Visual));
203257 screen->root_visual->visualid = 0;
204 screen->root_visual->class = TrueColor;
258 screen->root_visual->c_class = TrueColor;
205259 screen->root_visual->red_mask = 0x00FF0000;
206260 screen->root_visual->green_mask = 0x0000FF00;
207261 screen->root_visual->blue_mask = 0x000000FF;
224278 bzero(gMacDisplay, sizeof(TkDisplay));
225279 gMacDisplay->display = display;
226280 [pool drain];
281
282 /*
283 * Key map info must be available immediately, because of "send event".
284 */
285 TkpInitKeymapInfo(gMacDisplay);
286
227287 return gMacDisplay;
228288 }
229289
428488 return 1;
429489 }
430490
431 void
491 int
432492 XChangeProperty(
433493 Display* display,
434494 Window w,
440500 int nelements)
441501 {
442502 Debugger();
443 }
444
445 void
503 return Success;
504 }
505
506 int
446507 XSelectInput(
447508 Display* display,
448509 Window w,
449510 long event_mask)
450511 {
451512 Debugger();
513 return Success;
452514 }
453515
454516 int
507569 return 0;
508570 }
509571
510 void
572 int
511573 XClearWindow(
512574 Display* display,
513575 Window w)
514576 {
577 return Success;
515578 }
516579
517580 /*
523586 int x,
524587 int y)
525588 {
589 return Success;
526590 }
527591
528592 int
534598 int npoints,
535599 int mode)
536600 {
601 return Success;
537602 }
538603 */
539604
552617 return Success;
553618 }
554619
555 void
620 int
556621 XQueryColor(
557622 Display* display,
558623 Colormap colormap,
571636 d->blue = (b << 8) | b;
572637 d->flags = DoRed|DoGreen|DoBlue;
573638 d->pad = 0;
574 }
575
576 void
639 return Success;
640 }
641
642 int
577643 XQueryColors(
578644 Display* display,
579645 Colormap colormap,
596662 d->flags = DoRed|DoGreen|DoBlue;
597663 d->pad = 0;
598664 }
665 return Success;
599666 }
600667
601668 int
634701 return 0;
635702 }
636703
637 void
704 int
638705 XRefreshKeyboardMapping(
639706 XMappingEvent *x)
640707 {
641708 /* used by tkXEvent.c */
642709 Debugger();
643 }
644
645 void
710 return Success;
711 }
712
713 int
646714 XSetIconName(
647715 Display* display,
648716 Window w,
652720 * This is a no-op, no icon name for Macs.
653721 */
654722 display->request++;
655 }
656
657 void
723 return Success;
724 }
725
726 int
658727 XForceScreenSaver(
659728 Display* display,
660729 int mode)
666735 */
667736
668737 display->request++;
738 return Success;
669739 }
670740
671741 void
679749 int
680750 XSync(
681751 Display *display,
682 Bool flag)
752 Bool discard)
683753 {
684754 TkMacOSXFlushWindows();
685755 display->request++;
769839 *----------------------------------------------------------------------
770840 */
771841
772 void
842 int
773843 XChangeWindowAttributes(
774844 Display *display,
775845 Window w,
776846 unsigned long value_mask,
777847 XSetWindowAttributes *attributes)
778848 {
779 }
780
781 void
849 return Success;
850 }
851
852 int
782853 XSetWindowBackground(
783854 Display *display,
784855 Window window,
785856 unsigned long value)
786857 {
787 }
788
789 void
858 return Success;
859 }
860
861 int
790862 XSetWindowBackgroundPixmap(
791863 Display *display,
792864 Window w,
793865 Pixmap background_pixmap)
794866 {
795 }
796
797 void
867 return Success;
868 }
869
870 int
798871 XSetWindowBorder(
799872 Display *display,
800873 Window w,
801874 unsigned long border_pixel)
802875 {
803 }
804
805 void
876 return Success;
877 }
878
879 int
806880 XSetWindowBorderPixmap(
807881 Display *display,
808882 Window w,
809883 Pixmap border_pixmap)
810884 {
811 }
812
813 void
885 return Success;
886 }
887
888 int
814889 XSetWindowBorderWidth(
815890 Display *display,
816891 Window w,
817892 unsigned int width)
818893 {
819 }
820
821 void
894 return Success;
895 }
896
897 int
822898 XSetWindowColormap(
823899 Display *display,
824900 Window w,
825901 Colormap colormap)
826902 {
827903 Debugger();
904 return Success;
828905 }
829906
830907 Status
847924 }
848925
849926 XIC
850 XCreateIC(void)
927 XCreateIC(XIM xim, ...)
851928 {
852929 Debugger();
853930 return (XIC) 0;
854931 }
855932
933 #undef XVisualIDFromVisual
934 VisualID
935 XVisualIDFromVisual(
936 Visual *visual)
937 {
938 return visual->visualid;
939 }
940
941 #undef XSynchronize
942 XAfterFunction
943 XSynchronize(
944 Display *display,
945 Bool onoff)
946 {
947 display->request++;
948 return NULL;
949 }
950
951 #undef XUngrabServer
952 int
953 XUngrabServer(
954 Display *display)
955 {
956 return 0;
957 }
958
959 #undef XNoOp
960 int
961 XNoOp(
962 Display *display)
963 {
964 display->request++;
965 return 0;
966 }
967
968 #undef XGrabServer
969 int
970 XGrabServer(
971 Display *display)
972 {
973 return 0;
974 }
975
976 #undef XFree
977 int
978 XFree(
979 void *data)
980 {
981 if ((data) != NULL) {
982 ckfree(data);
983 }
984 return 0;
985 }
986 #undef XFlush
987 int
988 XFlush(
989 Display *display)
990 {
991 return 0;
992 }
993
856994 /*
857995 *----------------------------------------------------------------------
858996 *
00 /*
11 * ttkMacOSXTheme.c --
22 *
3 * Tk theme engine for Mac OSX, using the Appearance Manager API.
3 * Tk theme engine for Mac OSX, using the Appearance Manager API.
44 *
55 * Copyright (c) 2004 Joe English
66 * Copyright (c) 2005 Neil Madden
77 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
88 * Copyright 2008-2009, Apple Inc.
99 * Copyright 2009 Kevin Walzer/WordTech Communications LLC.
10 * Copyright 2019 Marc Culler
1011 *
1112 * See the file "license.terms" for information on usage and redistribution
1213 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
1415 * See also:
1516 *
1617 * <URL: http://developer.apple.com/documentation/Carbon/Reference/
17 * Appearance_Manager/appearance_manager/APIIndex.html >
18 * Appearance_Manager/appearance_manager/APIIndex.html >
1819 *
1920 * Notes:
20 * "Active" means different things in Mac and Tk terminology --
21 * On Aqua, widgets are "Active" if they belong to the foreground window,
22 * "Inactive" if they are in a background window.
23 * Tk uses the term "active" to mean that the mouse cursor
24 * is over a widget; aka "hover", "prelight", or "hot-tracked".
25 * Aqua doesn't use this kind of feedback.
26 *
27 * The QuickDraw/Carbon coordinate system is relative to the
28 * top-level window, not to the Tk_Window. BoxToRect()
29 * accounts for this.
21 * "Active" means different things in Mac and Tk terminology --
22 * On Aqua, widgets are "Active" if they belong to the foreground window,
23 * "Inactive" if they are in a background window. Tk uses the term
24 * "active" to mean that the mouse cursor is over a widget; aka "hover",
25 * "prelight", or "hot-tracked". Aqua doesn't use this kind of feedback.
26 *
27 * The QuickDraw/Carbon coordinate system is relative to the top-level
28 * window, not to the Tk_Window. BoxToRect() accounts for this.
3029 */
3130
3231 #include "tkMacOSXPrivate.h"
3332 #include "ttk/ttkTheme.h"
33 #include <math.h>
3434
3535 /*
36 * Use this version in the core:
37 */
38 #define BEGIN_DRAWING(d) { \
36 * Macros for handling drawing contexts.
37 */
38
39 #define BEGIN_DRAWING(d) { \
3940 TkMacOSXDrawingContext dc; \
4041 if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;}
4142 #define END_DRAWING \
42 TkMacOSXRestoreDrawingContext(&dc); }
43 TkMacOSXRestoreDrawingContext(&dc);}
4344
4445 #define HIOrientation kHIThemeOrientationNormal
46 #define NoThemeMetric 0xFFFFFFFF
4547
4648 #ifdef __LP64__
4749 #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
4951 #define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
5052 #endif /* __LP64__ */
5153
54 #define TTK_STATE_FIRST_TAB TTK_STATE_USER1
55 #define TTK_STATE_LAST_TAB TTK_STATE_USER2
56 #define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1
57
58 /*
59 * Colors and gradients used in Dark Mode.
60 */
61
62 static CGFloat darkButtonFace[4] = {
63 112.0 / 255, 113.0 / 255, 115.0 / 255, 1.0
64 };
65 static CGFloat darkPressedBevelFace[4] = {
66 135.0 / 255, 136.0 / 255, 138.0 / 255, 1.0
67 };
68 static CGFloat darkSelectedBevelFace[4] = {
69 162.0 / 255, 163.0 / 255, 165.0 / 255, 1.0
70 };
71 static CGFloat darkDisabledButtonFace[4] = {
72 86.0 / 255, 87.0 / 255, 89.0 / 255, 1.0
73 };
74 static CGFloat darkInactiveSelectedTab[4] = {
75 159.0 / 255, 160.0 / 255, 161.0 / 255, 1.0
76 };
77 static CGFloat darkFocusRing[4] = {
78 38.0 / 255, 113.0 / 255, 159.0 / 255, 1.0
79 };
80 static CGFloat darkFocusRingTop[4] = {
81 50.0 / 255, 124.0 / 255, 171.0 / 255, 1.0
82 };
83 static CGFloat darkFocusRingBottom[4] = {
84 57.0 / 255, 130.0 / 255, 176.0 / 255, 1.0
85 };
86 static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25};
87 static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25};
88 static CGFloat darkFrameTop[4] = {1.0, 1.0, 1.0, 0.0625};
89 static CGFloat darkFrameBottom[4] = {1.0, 1.0, 1.0, 0.125};
90 static CGFloat darkFrameAccent[4] = {0.0, 0.0, 0.0, 0.0625};
91 static CGFloat darkTopGradient[8] = {
92 1.0, 1.0, 1.0, 0.3,
93 1.0, 1.0, 1.0, 0.0
94 };
95 static CGFloat darkBackgroundGradient[8] = {
96 0.0, 0.0, 0.0, 0.1,
97 0.0, 0.0, 0.0, 0.25
98 };
99 static CGFloat darkInactiveGradient[8] = {
100 89.0 / 255, 90.0 / 255, 93.0 / 255, 1.0,
101 119.0 / 255, 120.0 / 255, 122.0 / 255, 1.0
102 };
103 static CGFloat darkSelectedGradient[8] = {
104 23.0 / 255, 111.0 / 255, 232.0 / 255, 1.0,
105 20.0 / 255, 94.0 / 255, 206.0 / 255, 1.0
106 };
107 static CGFloat pressedPushButtonGradient[8] = {
108 35.0 / 255, 123.0 / 255, 244.0 / 255, 1.0,
109 30.0 / 255, 114.0 / 255, 235.0 / 255, 1.0
110 };
111
112 /*
113 * When building on systems earlier than 10.8 there is no reasonable way to
114 * convert an NSColor to a CGColor. We do run-time checking of the OS version,
115 * and never need the CGColor property on older systems, so we can use this
116 * CGCOLOR macro, which evaluates to NULL without raising compiler warnings.
117 * Similarly, we never draw rounded rectangles on older systems which did not
118 * have CGPathCreateWithRoundedRect, so we just redefine it to return NULL.
119 */
120
121 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
122 #define CGCOLOR(nscolor) nscolor.CGColor
123 #else
124 #define CGCOLOR(nscolor) (0 ? (CGColorRef) nscolor : NULL)
125 #define CGPathCreateWithRoundedRect(w, x, y, z) NULL
126 #endif
127
128 /*
129 * If we try to draw a rounded rectangle with too large of a radius
130 * CoreGraphics will raise a fatal exception. This macro returns if
131 * the width or height is less than twice the radius. Presumably this
132 * only happens when a widget has not yet been configured and has size
133 * 1x1.
134 */
135
136 #define CHECK_RADIUS(radius, bounds) \
137 if (radius > bounds.size.width / 2 || radius > bounds.size.height / 2) { \
138 return; \
139 }
140
52141 /*----------------------------------------------------------------------
53142 * +++ Utilities.
54143 */
55144
56145 /*
57146 * BoxToRect --
58 * Convert a Ttk_Box in Tk coordinates relative to the given Drawable
59 * to a native Rect relative to the containing port.
60 */
61 static inline CGRect BoxToRect(Drawable d, Ttk_Box b)
62 {
63 MacDrawable *md = (MacDrawable*)d;
147 * Convert a Ttk_Box in Tk coordinates relative to the given Drawable
148 * to a native Rect relative to the containing port.
149 */
150
151 static inline CGRect BoxToRect(
152 Drawable d,
153 Ttk_Box b)
154 {
155 MacDrawable *md = (MacDrawable *) d;
64156 CGRect rect;
65157
66 rect.origin.y = b.y + md->yOff;
67 rect.origin.x = b.x + md->xOff;
68 rect.size.height = b.height;
69 rect.size.width = b.width;
158 rect.origin.y = b.y + md->yOff;
159 rect.origin.x = b.x + md->xOff;
160 rect.size.height = b.height;
161 rect.size.width = b.width;
70162
71163 return rect;
72164 }
76168 */
77169
78170 static Ttk_StateTable ThemeStateTable[] = {
171 {kThemeStateActive, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND},
79172 {kThemeStateUnavailable, TTK_STATE_DISABLED, 0},
80173 {kThemeStatePressed, TTK_STATE_PRESSED, 0},
81174 {kThemeStateInactive, TTK_STATE_BACKGROUND, 0},
82175 {kThemeStateActive, 0, 0}
83 /* Others: Not sure what these are supposed to mean.
84 Up/Down have something to do with "little arrow" increment controls...
85 Dunno what a "Rollover" is.
86 NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by the
87 looks of things
88 {kThemeStateRollover, 0, 0},
89 {kThemeStateUnavailableInactive, 0, 0}
90 {kThemeStatePressedUp, 0, 0},
91 {kThemeStatePressedDown, 0, 0}
92 */
93 };
176
177 /* Others: Not sure what these are supposed to mean. Up/Down have
178 * something to do with "little arrow" increment controls... Dunno what
179 * a "Rollover" is.
180 * NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by
181 * the looks of things
182 *
183 * {kThemeStateRollover, 0, 0},
184 * {kThemeStateUnavailableInactive, 0, 0}
185 * {kThemeStatePressedUp, 0, 0},
186 * {kThemeStatePressedDown, 0, 0}
187 */
188 };
189
190 /*----------------------------------------------------------------------
191 * NormalizeButtonBounds --
192 *
193 * Apple's Human Interface Guidelines only allow three specific heights
194 * for most buttons: Regular, small and mini. We always use the regular
195 * size. However, Ttk may provide an arbitrary bounding rectangle. We
196 * always draw the button centered vertically on the rectangle, and
197 * having the same width as the rectangle. This function returns the
198 * actual bounding rectangle that will be used in drawing the button.
199 *
200 * The BevelButton is allowed to have arbitrary size, and also has
201 * external padding. This is handled separately here.
202 */
203
204 static CGRect NormalizeButtonBounds(
205 SInt32 heightMetric,
206 CGRect bounds)
207 {
208 SInt32 height;
209
210 if (heightMetric != (SInt32) NoThemeMetric) {
211 ChkErr(GetThemeMetric, heightMetric, &height);
212 bounds.origin.y += (bounds.size.height - height) / 2;
213 bounds.size.height = height;
214 }
215 return bounds;
216 }
217
218 /*----------------------------------------------------------------------
219 * +++ Backgrounds
220 *
221 * Support for contrasting background colors when GroupBoxes or Tabbed
222 * panes are nested inside each other. Early versions of macOS used ridged
223 * borders, so do not need contrasting backgrounds.
224 */
225
226 /*
227 * For systems older than 10.14, [NSColor windowBackGroundColor] generates
228 * garbage when called from this function. In 10.14 it works correctly, and
229 * must be used in order to have a background color which responds to Dark
230 * Mode. So we use this hard-wired RGBA color on the older systems which don't
231 * support Dark Mode anyway.
232 */
233
234 static CGFloat windowBackground[4] = {
235 235.0 / 255, 235.0 / 255, 235.0 / 255, 1.0
236 };
237 static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0};
238 static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0};
239
240 /*----------------------------------------------------------------------
241 * GetBackgroundColor --
242 *
243 * Fills the array rgba with the color coordinates for a background color.
244 * Start with the background color of a window's geometry master, or the
245 * standard ttk window background if there is no master. If the contrast
246 * parameter is nonzero, modify this color to be darker, for the aqua
247 * appearance, or lighter for the DarkAqua appearance. This is primarily
248 * used by the Fill and Background elements.
249 */
250
251 static void GetBackgroundColor(
252 CGContextRef context,
253 Tk_Window tkwin,
254 int contrast,
255 CGFloat *rgba)
256 {
257 TkWindow *winPtr = (TkWindow *) tkwin;
258 TkWindow *masterPtr = (TkWindow *) TkGetGeomMaster(tkwin);
259
260 while (masterPtr && masterPtr->privatePtr) {
261 if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) {
262 break;
263 }
264 masterPtr = (TkWindow *) TkGetGeomMaster(masterPtr);
265 }
266 if (masterPtr && masterPtr->privatePtr) {
267 for (int i = 0; i < 4; i++) {
268 rgba[i] = masterPtr->privatePtr->fillRGBA[i];
269 }
270 } else {
271 if ([NSApp macMinorVersion] > 13) {
272 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
273 NSColor *windowColor = [[NSColor windowBackgroundColor]
274 colorUsingColorSpace: deviceRGB];
275 [windowColor getComponents: rgba];
276 } else {
277 for (int i = 0; i < 4; i++) {
278 rgba[i] = windowBackground[i];
279 }
280 }
281 }
282 if (contrast) {
283 int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5);
284
285 if (isDark) {
286 for (int i = 0; i < 3; i++) {
287 rgba[i] += 8.0 / 255.0;
288 }
289 } else {
290 for (int i = 0; i < 3; i++) {
291 rgba[i] -= 8.0 / 255.0;
292 }
293 }
294 if (winPtr->privatePtr) {
295 winPtr->privatePtr->flags |= TTK_HAS_CONTRASTING_BG;
296 for (int i = 0; i < 4; i++) {
297 winPtr->privatePtr->fillRGBA[i] = rgba[i];
298 }
299 }
300 }
301 }
302
303
304 /*----------------------------------------------------------------------
305 * +++ Single Arrow Buttons --
306 *
307 * Used in ListHeaders and Comboboxes.
308 */
309
310 static void DrawDownArrow(
311 CGContextRef context,
312 CGRect bounds,
313 CGFloat inset,
314 CGFloat size,
315 CGFloat *rgba)
316 {
317 CGFloat x, y;
318
319 CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
320 CGContextSetLineWidth(context, 1.5);
321 x = bounds.origin.x + inset;
322 y = bounds.origin.y + trunc(bounds.size.height / 2);
323 CGContextBeginPath(context);
324 CGPoint arrow[3] = {
325 {x, y - size / 4}, {x + size / 2, y + size / 4},
326 {x + size, y - size / 4}
327 };
328 CGContextAddLines(context, arrow, 3);
329 CGContextStrokePath(context);
330 }
331
332 static void DrawUpArrow(
333 CGContextRef context,
334 CGRect bounds,
335 CGFloat inset,
336 CGFloat size,
337 CGFloat *rgba)
338 {
339 CGFloat x, y;
340
341 CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
342 CGContextSetLineWidth(context, 1.5);
343 x = bounds.origin.x + inset;
344 y = bounds.origin.y + trunc(bounds.size.height / 2);
345 CGContextBeginPath(context);
346 CGPoint arrow[3] = {
347 {x, y + size / 4}, {x + size / 2, y - size / 4},
348 {x + size, y + size / 4}
349 };
350 CGContextAddLines(context, arrow, 3);
351 CGContextStrokePath(context);
352 }
353
354 /*----------------------------------------------------------------------
355 * +++ Double Arrow Buttons --
356 *
357 * Used in MenuButtons and SpinButtons.
358 */
359
360 static void DrawUpDownArrows(
361 CGContextRef context,
362 CGRect bounds,
363 CGFloat inset,
364 CGFloat size,
365 CGFloat *rgba)
366 {
367 CGFloat x, y;
368
369 CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
370 CGContextSetLineWidth(context, 1.5);
371 x = bounds.origin.x + inset;
372 y = bounds.origin.y + trunc(bounds.size.height / 2);
373 CGContextBeginPath(context);
374 CGPoint bottomArrow[3] =
375 {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}};
376 CGContextAddLines(context, bottomArrow, 3);
377 CGPoint topArrow[3] =
378 {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}};
379 CGContextAddLines(context, topArrow, 3);
380 CGContextStrokePath(context);
381 }
382
383
384 /*----------------------------------------------------------------------
385 * +++ FillButtonBackground --
386 *
387 * Fills a rounded rectangle with a transparent black gradient.
388 * This is a no-op if building on 10.8 or older.
389 */
390
391 static void FillButtonBackground(
392 CGContextRef context,
393 CGRect bounds,
394 CGFloat radius)
395 {
396 CHECK_RADIUS(radius, bounds)
397
398 CGPathRef path;
399 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
400 CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents(
401 deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2);
402 CGPoint backgroundEnd = {
403 bounds.origin.x,
404 bounds.origin.y + bounds.size.height
405 };
406 CGContextBeginPath(context);
407 path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
408 CGContextAddPath(context, path);
409 CGContextClip(context);
410 CGContextDrawLinearGradient(context, backgroundGradient,
411 bounds.origin, backgroundEnd, 0);
412 CFRelease(path);
413 CFRelease(backgroundGradient);
414 }
415
416 /*----------------------------------------------------------------------
417 * +++ HighlightButtonBorder --
418 *
419 * Accent the top border of a rounded rectangle with a transparent
420 * white gradient.
421 */
422
423 static void HighlightButtonBorder(
424 CGContextRef context,
425 CGRect bounds)
426 {
427 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
428 CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3};
429 CGGradientRef topGradient = CGGradientCreateWithColorComponents(
430 deviceRGB.CGColorSpace, darkTopGradient, NULL, 2);
431
432 CGContextSaveGState(context);
433 CGContextBeginPath(context);
434 CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4,
435 4, PI, 3 * PI / 2, 0);
436 CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4,
437 bounds.origin.y + 4, 4, 3 * PI / 2, 0, 0);
438 CGContextReplacePathWithStrokedPath(context);
439 CGContextClip(context);
440 CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd,
441 0.0);
442 CGContextRestoreGState(context);
443 CFRelease(topGradient);
444 }
445
446 /*----------------------------------------------------------------------
447 * DrawGroupBox --
448 *
449 * This is a standalone drawing procedure which draws the contrasting
450 * rounded rectangular box for LabelFrames and Notebook panes used in
451 * more recent versions of macOS.
452 */
453
454 static void DrawGroupBox(
455 CGRect bounds,
456 CGContextRef context,
457 Tk_Window tkwin)
458 {
459 CHECK_RADIUS(4, bounds)
460
461 CGPathRef path;
462 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
463 NSColor *borderColor, *bgColor;
464 static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25};
465 CGFloat fill[4];
466
467 GetBackgroundColor(context, tkwin, 1, fill);
468 bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill
469 count: 4];
470 CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace);
471 CGContextSetFillColorWithColor(context, CGCOLOR(bgColor));
472 path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL);
473 CGContextClipToRect(context, bounds);
474 CGContextBeginPath(context);
475 CGContextAddPath(context, path);
476 CGContextFillPath(context);
477 borderColor = [NSColor colorWithColorSpace: deviceRGB components: border
478 count: 4];
479 CGContextSetFillColorWithColor(context, CGCOLOR(borderColor));
480 [borderColor getComponents: fill];
481 CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]);
482
483 CGContextBeginPath(context);
484 CGContextAddPath(context, path);
485 CGContextReplacePathWithStrokedPath(context);
486 CGContextFillPath(context);
487 CFRelease(path);
488 }
489
490 /*----------------------------------------------------------------------
491 * SolidFillRoundedRectangle --
492 *
493 * Fill a rounded rectangle with a specified solid color.
494 */
495
496 static void SolidFillRoundedRectangle(
497 CGContextRef context,
498 CGRect bounds,
499 CGFloat radius,
500 NSColor *color)
501 {
502 CGPathRef path;
503 CHECK_RADIUS(radius, bounds)
504
505 CGContextSetFillColorWithColor(context, CGCOLOR(color));
506 path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
507 CGContextBeginPath(context);
508 CGContextAddPath(context, path);
509 CGContextFillPath(context);
510 CFRelease(path);
511 }
512
513 /*----------------------------------------------------------------------
514 * +++ DrawListHeader --
515 *
516 * This is a standalone drawing procedure which draws column headers for
517 * a Treeview in the Aqua appearance. The HITheme headers have not
518 * matched the native ones since OSX 10.8. Note that the header image is
519 * ignored, but we draw arrows according to the state.
520 */
521
522 static void DrawListHeader(
523 CGRect bounds,
524 CGContextRef context,
525 Tk_Window tkwin,
526 int state)
527 {
528 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
529 NSColor *strokeColor, *bgColor;
530 static CGFloat borderRGBA[4] = {
531 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0
532 };
533 static CGFloat separatorRGBA[4] = {
534 220.0 / 255, 220.0 / 255, 220.0 / 255, 1.0
535 };
536 static CGFloat activeBgRGBA[4] = {
537 238.0 / 255, 238.0 / 255, 238.0 / 255, 1.0
538 };
539 static CGFloat inactiveBgRGBA[4] = {
540 246.0 / 255, 246.0 / 255, 246.0 / 255, 1.0
541 };
542
543 /*
544 * Apple changes the background of a list header when the window is not
545 * active. But Ttk does not indicate that in the state of a TreeHeader.
546 * So we have to query the Apple window manager.
547 */
548
549 NSWindow *win = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
550 CGFloat *bgRGBA = [win isKeyWindow] ? activeBgRGBA : inactiveBgRGBA;
551 CGFloat x = bounds.origin.x, y = bounds.origin.y;
552 CGFloat w = bounds.size.width, h = bounds.size.height;
553 CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}};
554 CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
555 CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}};
556
557 bgColor = [NSColor colorWithColorSpace: deviceRGB
558 components: bgRGBA
559 count: 4];
560 CGContextSaveGState(context);
561 CGContextSetShouldAntialias(context, false);
562 CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace);
563 CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
564 CGContextBeginPath(context);
565 CGContextSetFillColorWithColor(context, CGCOLOR(bgColor));
566 CGContextAddRect(context, bounds);
567 CGContextFillPath(context);
568 strokeColor = [NSColor colorWithColorSpace: deviceRGB
569 components: separatorRGBA
570 count: 4];
571 CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
572 CGContextAddLines(context, separator, 2);
573 CGContextStrokePath(context);
574 strokeColor = [NSColor colorWithColorSpace: deviceRGB
575 components: borderRGBA
576 count: 4];
577 CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
578 CGContextAddLines(context, top, 2);
579 CGContextStrokePath(context);
580 CGContextAddLines(context, bottom, 2);
581 CGContextStrokePath(context);
582 CGContextRestoreGState(context);
583
584 if (state & TTK_TREEVIEW_STATE_SORTARROW) {
585 CGRect arrowBounds = bounds;
586 arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
587 arrowBounds.size.width = 16;
588 if (state & TTK_STATE_ALTERNATE) {
589 DrawUpArrow(context, arrowBounds, 3, 8, blackRGBA);
590 } else if (state & TTK_STATE_SELECTED) {
591 DrawDownArrow(context, arrowBounds, 3, 8, blackRGBA);
592 }
593 }
594 }
595
596 /*----------------------------------------------------------------------
597 * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up).
598 *
599 * The HIToolbox does not support Dark Mode, and apparently never will,
600 * so to make widgets look "native" we have to provide analogues of the
601 * HITheme drawing functions to be used in DarkAqua. We continue to use
602 * HITheme in Aqua, since it understands earlier versions of the OS.
603 *
604 * Drawing the dark widgets requires NSColors that were introduced in OSX
605 * 10.14, so we make some of these functions be no-ops when building on
606 * systems older than 10.14.
607 */
608
609 /*----------------------------------------------------------------------
610 * GradientFillRoundedRectangle --
611 *
612 * Fill a rounded rectangle with a specified gradient.
613 */
614
615 static void GradientFillRoundedRectangle(
616 CGContextRef context,
617 CGRect bounds,
618 CGFloat radius,
619 CGFloat *colors,
620 int numColors)
621 {
622 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
623 CGPathRef path;
624 CHECK_RADIUS(radius, bounds)
625
626 CGPoint end = {
627 bounds.origin.x,
628 bounds.origin.y + bounds.size.height
629 };
630 CGGradientRef gradient = CGGradientCreateWithColorComponents(
631 deviceRGB.CGColorSpace, colors, NULL, numColors);
632
633 path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
634 CGContextBeginPath(context);
635 CGContextAddPath(context, path);
636 CGContextClip(context);
637 CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0);
638 CFRelease(path);
639 CFRelease(gradient);
640 }
641
642 /*----------------------------------------------------------------------
643 * +++ DrawDarkButton --
644 *
645 * This is a standalone drawing procedure which draws PushButtons and
646 * PopupButtons in the Dark Mode style.
647 */
648
649 static void DrawDarkButton(
650 CGRect bounds,
651 ThemeButtonKind kind,
652 Ttk_State state,
653 CGContextRef context)
654 {
655 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
656 NSColor *faceColor;
657
658 /*
659 * To match the appearance of Apple's buttons we need to increase the
660 * height by 1 pixel.
661 */
662
663 bounds.size.height += 1;
664
665 CGContextClipToRect(context, bounds);
666 FillButtonBackground(context, bounds, 5);
667
668 /*
669 * Fill the button face with the appropriate color.
670 */
671
672 bounds = CGRectInset(bounds, 1, 1);
673 if (kind == kThemePushButton && (state & TTK_STATE_PRESSED)) {
674 GradientFillRoundedRectangle(context, bounds, 4,
675 pressedPushButtonGradient, 2);
676 } else if (kind == kThemePushButton &&
677 (state & TTK_STATE_ALTERNATE) &&
678 !(state & TTK_STATE_BACKGROUND)) {
679 GradientFillRoundedRectangle(context, bounds, 4,
680 darkSelectedGradient, 2);
681 } else {
682 if (state & TTK_STATE_DISABLED) {
683 faceColor = [NSColor colorWithColorSpace: deviceRGB
684 components: darkDisabledButtonFace
685 count: 4];
686 } else {
687 faceColor = [NSColor colorWithColorSpace: deviceRGB
688 components: darkButtonFace
689 count: 4];
690 }
691 SolidFillRoundedRectangle(context, bounds, 4, faceColor);
692 }
693
694 /*
695 * If this is a popup, draw the arrow button.
696 */
697
698 if ((kind == kThemePopupButton) | (kind == kThemeComboBox)) {
699 CGRect arrowBounds = bounds;
700 arrowBounds.size.width = 16;
701 arrowBounds.origin.x += bounds.size.width - 16;
702
703 /*
704 * If the toplevel is front, paint the button blue.
705 */
706
707 if (!(state & TTK_STATE_BACKGROUND) &&
708 !(state & TTK_STATE_DISABLED)) {
709 GradientFillRoundedRectangle(context, arrowBounds, 4,
710 darkSelectedGradient, 2);
711 }
712 if (kind == kThemePopupButton) {
713 DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA);
714 } else {
715 DrawDownArrow(context, arrowBounds, 4, 8, whiteRGBA);
716 }
717 }
718
719 HighlightButtonBorder(context, bounds);
720 }
721
722 /*----------------------------------------------------------------------
723 * +++ DrawDarkIncDecButton --
724 *
725 * This is a standalone drawing procedure which draws an IncDecButton
726 * (as used in a Spinbox) in the Dark Mode style.
727 */
728
729 static void DrawDarkIncDecButton(
730 CGRect bounds,
731 ThemeDrawState drawState,
732 Ttk_State state,
733 CGContextRef context)
734 {
735 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
736 NSColor *faceColor;
737
738 bounds = CGRectInset(bounds, 0, -1);
739 CGContextClipToRect(context, bounds);
740 FillButtonBackground(context, bounds, 6);
741
742 /*
743 * Fill the button face with the appropriate color.
744 */
745
746 bounds = CGRectInset(bounds, 1, 1);
747 if (state & TTK_STATE_DISABLED) {
748 faceColor = [NSColor colorWithColorSpace: deviceRGB
749 components: darkDisabledButtonFace
750 count: 4];
751 } else {
752 faceColor = [NSColor colorWithColorSpace: deviceRGB
753 components: darkButtonFace
754 count: 4];
755 }
756 SolidFillRoundedRectangle(context, bounds, 4, faceColor);
757
758 /*
759 * If pressed, paint the appropriate half blue.
760 */
761
762 if (state & TTK_STATE_PRESSED) {
763 CGRect clip = bounds;
764 clip.size.height /= 2;
765 CGContextSaveGState(context);
766 if (drawState == kThemeStatePressedDown) {
767 clip.origin.y += clip.size.height;
768 }
769 CGContextClipToRect(context, clip);
770 GradientFillRoundedRectangle(context, bounds, 5,
771 darkSelectedGradient, 2);
772 CGContextRestoreGState(context);
773 }
774 DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA);
775 HighlightButtonBorder(context, bounds);
776 }
777
778 /*----------------------------------------------------------------------
779 * +++ DrawDarkBevelButton --
780 *
781 * This is a standalone drawing procedure which draws RoundedBevelButtons
782 * in the Dark Mode style.
783 */
784
785 static void DrawDarkBevelButton(
786 CGRect bounds,
787 Ttk_State state,
788 CGContextRef context)
789 {
790 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
791 NSColor *faceColor;
792
793 CGContextClipToRect(context, bounds);
794 FillButtonBackground(context, bounds, 5);
795
796 /*
797 * Fill the button face with the appropriate color.
798 */
799
800 bounds = CGRectInset(bounds, 1, 1);
801 if (state & TTK_STATE_PRESSED) {
802 faceColor = [NSColor colorWithColorSpace: deviceRGB
803 components: darkPressedBevelFace
804 count: 4];
805 } else if ((state & TTK_STATE_DISABLED) ||
806 (state & TTK_STATE_ALTERNATE)) {
807 faceColor = [NSColor colorWithColorSpace: deviceRGB
808 components: darkDisabledButtonFace
809 count: 4];
810 } else if (state & TTK_STATE_SELECTED) {
811 faceColor = [NSColor colorWithColorSpace: deviceRGB
812 components: darkSelectedBevelFace
813 count: 4];
814 } else {
815 faceColor = [NSColor colorWithColorSpace: deviceRGB
816 components: darkButtonFace
817 count: 4];
818 }
819 SolidFillRoundedRectangle(context, bounds, 4, faceColor);
820 HighlightButtonBorder(context, bounds);
821 }
822
823 /*----------------------------------------------------------------------
824 * +++ DrawDarkCheckBox --
825 *
826 * This is a standalone drawing procedure which draws Checkboxes in the
827 * Dark Mode style.
828 */
829
830 static void DrawDarkCheckBox(
831 CGRect bounds,
832 Ttk_State state,
833 CGContextRef context)
834 {
835 CGRect checkbounds = {{0, bounds.size.height / 2 - 8}, {16, 16}};
836 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
837 NSColor *stroke;
838 CGFloat x, y;
839
840 bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y);
841 x = bounds.origin.x;
842 y = bounds.origin.y;
843
844 CGContextClipToRect(context, bounds);
845 FillButtonBackground(context, bounds, 4);
846 bounds = CGRectInset(bounds, 1, 1);
847 if (!(state & TTK_STATE_BACKGROUND) &&
848 !(state & TTK_STATE_DISABLED) &&
849 ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) {
850 GradientFillRoundedRectangle(context, bounds, 3,
851 darkSelectedGradient, 2);
852 } else {
853 GradientFillRoundedRectangle(context, bounds, 3,
854 darkInactiveGradient, 2);
855 }
856 HighlightButtonBorder(context, bounds);
857 if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) {
858 CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
859 if (state & TTK_STATE_DISABLED) {
860 stroke = [NSColor disabledControlTextColor];
861 } else {
862 stroke = [NSColor controlTextColor];
863 }
864 CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
865 }
866 if (state & TTK_STATE_SELECTED) {
867 CGContextSetLineWidth(context, 1.5);
868 CGContextBeginPath(context);
869 CGPoint check[3] = {{x + 4, y + 8}, {x + 7, y + 11}, {x + 11, y + 4}};
870 CGContextAddLines(context, check, 3);
871 CGContextStrokePath(context);
872 } else if (state & TTK_STATE_ALTERNATE) {
873 CGContextSetLineWidth(context, 2.0);
874 CGContextBeginPath(context);
875 CGPoint bar[2] = {{x + 4, y + 8}, {x + 12, y + 8}};
876 CGContextAddLines(context, bar, 2);
877 CGContextStrokePath(context);
878 }
879 }
880
881 /*----------------------------------------------------------------------
882 * +++ DrawDarkRadioButton --
883 *
884 * This is a standalone drawing procedure which draws RadioButtons
885 * in the Dark Mode style.
886 */
887
888 static void DrawDarkRadioButton(
889 CGRect bounds,
890 Ttk_State state,
891 CGContextRef context)
892 {
893 CGRect checkbounds = {{0, bounds.size.height / 2 - 9}, {18, 18}};
894 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
895 NSColor *fill;
896 CGFloat x, y;
897
898 bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y);
899 x = bounds.origin.x;
900 y = bounds.origin.y;
901
902 CGContextClipToRect(context, bounds);
903 FillButtonBackground(context, bounds, 9);
904 bounds = CGRectInset(bounds, 1, 1);
905 if (!(state & TTK_STATE_BACKGROUND) &&
906 !(state & TTK_STATE_DISABLED) &&
907 ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) {
908 GradientFillRoundedRectangle(context, bounds, 8,
909 darkSelectedGradient, 2);
910 } else {
911 GradientFillRoundedRectangle(context, bounds, 8,
912 darkInactiveGradient, 2);
913 }
914 HighlightButtonBorder(context, bounds);
915 if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) {
916 CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
917 if (state & TTK_STATE_DISABLED) {
918 fill = [NSColor disabledControlTextColor];
919 } else {
920 fill = [NSColor controlTextColor];
921 }
922 CGContextSetFillColorWithColor(context, CGCOLOR(fill));
923 }
924 if (state & TTK_STATE_SELECTED) {
925 CGContextBeginPath(context);
926 CGRect dot = {{x + 6, y + 6}, {6, 6}};
927 CGContextAddEllipseInRect(context, dot);
928 CGContextFillPath(context);
929 } else if (state & TTK_STATE_ALTERNATE) {
930 CGRect bar = {{x + 5, y + 8}, {8, 2}};
931 CGContextFillRect(context, bar);
932 }
933 }
934
935 /*----------------------------------------------------------------------
936 * +++ DrawDarkTab --
937 *
938 * This is a standalone drawing procedure which draws Tabbed Pane
939 * Tabs in the Dark Mode style.
940 */
941
942 static void DrawDarkTab(
943 CGRect bounds,
944 Ttk_State state,
945 CGContextRef context)
946 {
947 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
948 NSColor *faceColor, *stroke;
949 CGRect originalBounds = bounds;
950
951 CGContextSetLineWidth(context, 1.0);
952 CGContextClipToRect(context, bounds);
953
954 /*
955 * Extend the bounds to one or both sides so the rounded part will be
956 * clipped off.
957 */
958
959 if (!(state & TTK_STATE_FIRST_TAB)) {
960 bounds.origin.x -= 10;
961 bounds.size.width += 10;
962 }
963
964 if (!(state & TTK_STATE_LAST_TAB)) {
965 bounds.size.width += 10;
966 }
967
968 /*
969 * Fill the tab face with the appropriate color or gradient. Use a solid
970 * color if the tab is not selected, otherwise use a blue or gray
971 * gradient.
972 */
973
974 bounds = CGRectInset(bounds, 1, 1);
975 if (!(state & TTK_STATE_SELECTED)) {
976 if (state & TTK_STATE_DISABLED) {
977 faceColor = [NSColor colorWithColorSpace: deviceRGB
978 components: darkDisabledButtonFace
979 count: 4];
980 } else {
981 faceColor = [NSColor colorWithColorSpace: deviceRGB
982 components: darkButtonFace
983 count: 4];
984 }
985 SolidFillRoundedRectangle(context, bounds, 4, faceColor);
986
987 /*
988 * Draw a separator line on the left side of the tab if it
989 * not first.
990 */
991
992 if (!(state & TTK_STATE_FIRST_TAB)) {
993 CGContextSaveGState(context);
994 CGContextSetShouldAntialias(context, false);
995 stroke = [NSColor colorWithColorSpace: deviceRGB
996 components: darkTabSeparator
997 count: 4];
998 CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
999 CGContextBeginPath(context);
1000 CGContextMoveToPoint(context, originalBounds.origin.x,
1001 originalBounds.origin.y + 1);
1002 CGContextAddLineToPoint(context, originalBounds.origin.x,
1003 originalBounds.origin.y + originalBounds.size.height - 1);
1004 CGContextStrokePath(context);
1005 CGContextRestoreGState(context);
1006 }
1007 } else {
1008
1009 /*
1010 * This is the selected tab; paint it blue. If it is first, cover up
1011 * the separator line drawn by the second one. (The selected tab is
1012 * always drawn last.)
1013 */
1014
1015 if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) {
1016 bounds.size.width += 1;
1017 }
1018 if (!(state & TTK_STATE_BACKGROUND)) {
1019 GradientFillRoundedRectangle(context, bounds, 4,
1020 darkSelectedGradient, 2);
1021 } else {
1022 faceColor = [NSColor colorWithColorSpace: deviceRGB
1023 components: darkInactiveSelectedTab
1024 count: 4];
1025 SolidFillRoundedRectangle(context, bounds, 4, faceColor);
1026 }
1027 HighlightButtonBorder(context, bounds);
1028 }
1029 }
1030
1031 /*----------------------------------------------------------------------
1032 * +++ DrawDarkSeparator --
1033 *
1034 * This is a standalone drawing procedure which draws a separator widget
1035 * in Dark Mode.
1036 */
1037
1038 static void DrawDarkSeparator(
1039 CGRect bounds,
1040 CGContextRef context,
1041 Tk_Window tkwin)
1042 {
1043 static CGFloat fill[4] = {1.0, 1.0, 1.0, 0.3};
1044 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
1045 NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB
1046 components: fill
1047 count:4];
1048
1049 CGContextSetFillColorWithColor(context, CGCOLOR(fillColor));
1050 CGContextFillRect(context, bounds);
1051 }
1052
1053 /*----------------------------------------------------------------------
1054 * +++ DrawDarkFocusRing --
1055 *
1056 * This is a standalone drawing procedure which draws a focus ring around
1057 * an Entry widget in Dark Mode.
1058 */
1059
1060 static void DrawDarkFocusRing(
1061 CGRect bounds,
1062 CGContextRef context)
1063 {
1064 CGRect insetBounds = CGRectInset(bounds, -3, -3);
1065 CHECK_RADIUS(4, insetBounds)
1066
1067 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
1068 NSColor *strokeColor;
1069 NSColor *fillColor = [NSColor colorWithColorSpace:deviceRGB
1070 components:darkFocusRing
1071 count:4];
1072 CGFloat x = bounds.origin.x, y = bounds.origin.y;
1073 CGFloat w = bounds.size.width, h = bounds.size.height;
1074 CGPoint topPart[4] = {
1075 {x, y + h}, {x, y + 1}, {x + w - 1, y + 1}, {x + w - 1, y + h}
1076 };
1077 CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
1078
1079 CGContextSaveGState(context);
1080 CGContextSetShouldAntialias(context, false);
1081 CGContextBeginPath(context);
1082 strokeColor = [NSColor colorWithColorSpace: deviceRGB
1083 components: darkFocusRingTop
1084 count: 4];
1085 CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
1086 CGContextAddLines(context, topPart, 4);
1087 CGContextStrokePath(context);
1088 strokeColor = [NSColor colorWithColorSpace: deviceRGB
1089 components: darkFocusRingBottom
1090 count: 4];
1091 CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor));
1092 CGContextAddLines(context, bottom, 2);
1093 CGContextStrokePath(context);
1094 CGContextSetShouldAntialias(context, true);
1095 CGContextSetFillColorWithColor(context, CGCOLOR(fillColor));
1096 CGPathRef path = CGPathCreateWithRoundedRect(insetBounds, 4, 4, NULL);
1097 CGContextBeginPath(context);
1098 CGContextAddPath(context, path);
1099 CGContextAddRect(context, bounds);
1100 CGContextEOFillPath(context);
1101 CGContextRestoreGState(context);
1102 }
1103 /*----------------------------------------------------------------------
1104 * +++ DrawDarkFrame --
1105 *
1106 * This is a standalone drawing procedure which draws various
1107 * types of borders in Dark Mode.
1108 */
1109
1110 static void DrawDarkFrame(
1111 CGRect bounds,
1112 CGContextRef context,
1113 HIThemeFrameKind kind)
1114 {
1115 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
1116 NSColor *stroke;
1117
1118 CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
1119 CGFloat x = bounds.origin.x, y = bounds.origin.y;
1120 CGFloat w = bounds.size.width, h = bounds.size.height;
1121 CGPoint topPart[4] = {
1122 {x, y + h - 1}, {x, y + 1}, {x + w, y + 1}, {x + w, y + h - 1}
1123 };
1124 CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
1125 CGPoint accent[2] = {{x, y + 1}, {x + w, y + 1}};
1126
1127 switch (kind) {
1128 case kHIThemeFrameTextFieldSquare:
1129 CGContextSaveGState(context);
1130 CGContextSetShouldAntialias(context, false);
1131 CGContextBeginPath(context);
1132 stroke = [NSColor colorWithColorSpace: deviceRGB
1133 components: darkFrameTop
1134 count: 4];
1135 CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
1136 CGContextAddLines(context, topPart, 4);
1137 CGContextStrokePath(context);
1138 stroke = [NSColor colorWithColorSpace: deviceRGB
1139 components: darkFrameBottom
1140 count: 4];
1141 CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
1142 CGContextAddLines(context, bottom, 2);
1143 CGContextStrokePath(context);
1144 stroke = [NSColor colorWithColorSpace: deviceRGB
1145 components: darkFrameAccent
1146 count: 4];
1147 CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
1148 CGContextAddLines(context, accent, 2);
1149 CGContextStrokePath(context);
1150 CGContextRestoreGState(context);
1151 break;
1152 default:
1153 break;
1154 }
1155 }
1156
1157 /*----------------------------------------------------------------------
1158 * +++ DrawListHeader --
1159 *
1160 * This is a standalone drawing procedure which draws column
1161 * headers for a Treeview in the Dark Mode.
1162 */
1163
1164 static void DrawDarkListHeader(
1165 CGRect bounds,
1166 CGContextRef context,
1167 Tk_Window tkwin,
1168 int state)
1169 {
1170 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
1171 NSColor *stroke;
1172
1173 CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
1174 CGFloat x = bounds.origin.x, y = bounds.origin.y;
1175 CGFloat w = bounds.size.width, h = bounds.size.height;
1176 CGPoint top[2] = {{x, y}, {x + w, y}};
1177 CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
1178 CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}};
1179
1180 CGContextSaveGState(context);
1181 CGContextSetShouldAntialias(context, false);
1182 stroke = [NSColor colorWithColorSpace: deviceRGB
1183 components: darkFrameBottom
1184 count: 4];
1185 CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke));
1186 CGContextBeginPath(context);
1187 CGContextAddLines(context, top, 2);
1188 CGContextStrokePath(context);
1189 CGContextAddLines(context, bottom, 2);
1190 CGContextStrokePath(context);
1191 CGContextAddLines(context, separator, 2);
1192 CGContextStrokePath(context);
1193 CGContextRestoreGState(context);
1194
1195 if (state & TTK_TREEVIEW_STATE_SORTARROW) {
1196 CGRect arrowBounds = bounds;
1197
1198 arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
1199 arrowBounds.size.width = 16;
1200 if (state & TTK_STATE_ALTERNATE) {
1201 DrawUpArrow(context, arrowBounds, 3, 8, whiteRGBA);
1202 } else if (state & TTK_STATE_SELECTED) {
1203 DrawDownArrow(context, arrowBounds, 3, 8, whiteRGBA);
1204 }
1205 }
1206 }
941207
951208 /*----------------------------------------------------------------------
961209 * +++ Button element: Used for elements drawn with DrawThemeButton.
971210 */
981211
991212 /*
100 * Extra margins to account for drop shadow.
101 */
102 static Ttk_Padding ButtonMargins = {2,2,2,2};
103
104 #define NoThemeMetric 0xFFFFFFFF
1213 * When Ttk draws the various types of buttons, a pointer to one of these
1214 * is passed as the clientData.
1215 */
1051216
1061217 typedef struct {
1071218 ThemeButtonKind kind;
1081219 ThemeMetric heightMetric;
1091220 } ThemeButtonParams;
110
1111221 static ThemeButtonParams
112 PushButtonParams = { kThemePushButton, kThemeMetricPushButtonHeight },
113 CheckBoxParams = { kThemeCheckBox, kThemeMetricCheckBoxHeight },
114 RadioButtonParams = { kThemeRadioButton, kThemeMetricRadioButtonHeight },
115 BevelButtonParams = { kThemeBevelButton, NoThemeMetric },
116 PopupButtonParams = { kThemePopupButton, kThemeMetricPopupButtonHeight },
117 DisclosureParams = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight },
118 ListHeaderParams = { kThemeListHeaderButton, kThemeMetricListHeaderHeight };
119
1222 PushButtonParams = {kThemePushButton, kThemeMetricPushButtonHeight},
1223 CheckBoxParams = {kThemeCheckBox, kThemeMetricCheckBoxHeight},
1224 RadioButtonParams = {kThemeRadioButton, kThemeMetricRadioButtonHeight},
1225 BevelButtonParams = {kThemeRoundedBevelButton, NoThemeMetric},
1226 PopupButtonParams = {kThemePopupButton, kThemeMetricPopupButtonHeight},
1227 DisclosureParams = {
1228 kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight
1229 },
1230 ListHeaderParams =
1231 {kThemeListHeaderButton, kThemeMetricListHeaderHeight};
1201232 static Ttk_StateTable ButtonValueTable[] = {
121 { kThemeButtonMixed, TTK_STATE_ALTERNATE, 0 },
122 { kThemeButtonOn, TTK_STATE_SELECTED, 0 },
123 { kThemeButtonOff, 0, 0 }
124 /* Others: kThemeDisclosureRight, kThemeDisclosureDown, kThemeDisclosureLeft */
125 };
126
1233 {kThemeButtonOff, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND},
1234 {kThemeButtonMixed, TTK_STATE_ALTERNATE, 0},
1235 {kThemeButtonOn, TTK_STATE_SELECTED, 0},
1236 {kThemeButtonOff, 0, 0}
1237
1238 /*
1239 * Others: kThemeDisclosureRight, kThemeDisclosureDown,
1240 * kThemeDisclosureLeft
1241 */
1242
1243 };
1271244 static Ttk_StateTable ButtonAdornmentTable[] = {
128 { kThemeAdornmentDefault| kThemeAdornmentFocus,
129 TTK_STATE_ALTERNATE| TTK_STATE_FOCUS, 0 },
130 { kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0 },
131 { kThemeAdornmentFocus, TTK_STATE_FOCUS, 0 },
132 { kThemeAdornmentNone, 0, 0 }
133 };
134
135 /*
136 * computeButtonDrawInfo --
137 * Fill in an appearance manager HIThemeButtonDrawInfo record.
138 */
1245 {kThemeAdornmentNone, TTK_STATE_ALTERNATE | TTK_STATE_BACKGROUND, 0},
1246 {kThemeAdornmentDefault | kThemeAdornmentFocus,
1247 TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0},
1248 {kThemeAdornmentFocus, TTK_STATE_FOCUS, 0},
1249 {kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0},
1250 {kThemeAdornmentNone, 0, 0}
1251 };
1252
1253 /*----------------------------------------------------------------------
1254 * +++ computeButtonDrawInfo --
1255 *
1256 * Fill in an appearance manager HIThemeButtonDrawInfo record.
1257 */
1258
1391259 static inline HIThemeButtonDrawInfo computeButtonDrawInfo(
140 ThemeButtonParams *params, Ttk_State state)
141 {
1260 ThemeButtonParams *params,
1261 Ttk_State state,
1262 Tk_Window tkwin)
1263 {
1264
1265 /*
1266 * See ButtonElementDraw for the explanation of why we always draw
1267 * PushButtons in the active state.
1268 */
1269
1270 SInt32 HIThemeState;
1271
1272 HIThemeState = Ttk_StateTableLookup(ThemeStateTable, state);
1273 switch (params->kind) {
1274 case kThemePushButton:
1275 HIThemeState &= ~kThemeStateInactive;
1276 HIThemeState |= kThemeStateActive;
1277 break;
1278 default:
1279 break;
1280 }
1281
1421282 const HIThemeButtonDrawInfo info = {
1431283 .version = 0,
144 .state = Ttk_StateTableLookup(ThemeStateTable, state),
1284 .state = HIThemeState,
1451285 .kind = params ? params->kind : 0,
1461286 .value = Ttk_StateTableLookup(ButtonValueTable, state),
1471287 .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state),
1491289 return info;
1501290 }
1511291
152 static void ButtonElementSizeNoPadding(
153 void *clientData, void *elementRecord, Tk_Window tkwin,
154 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1292 /*----------------------------------------------------------------------
1293 * +++ Button elements.
1294 */
1295
1296 static void ButtonElementMinSize(
1297 void *clientData,
1298 void *elementRecord,
1299 Tk_Window tkwin,
1300 int *minWidth,
1301 int *minHeight,
1302 Ttk_Padding *paddingPtr)
1551303 {
1561304 ThemeButtonParams *params = clientData;
1571305
1581306 if (params->heightMetric != NoThemeMetric) {
159 SInt32 height;
160
161 ChkErr(GetThemeMetric, params->heightMetric, &height);
162 *heightPtr = height;
1307 ChkErr(GetThemeMetric, params->heightMetric, minHeight);
1308
1309 /*
1310 * The theme height does not include the 1-pixel border around
1311 * the button, although it does include the 1-pixel shadow at
1312 * the bottom.
1313 */
1314
1315 *minHeight += 2;
1316
1317 /*
1318 * The minwidth must be 0 to force the generic ttk code to compute the
1319 * correct text layout. For example, a non-zero value will cause the
1320 * text to be left justified, no matter what -anchor setting is used in
1321 * the style.
1322 */
1323
1324 *minWidth = 0;
1631325 }
1641326 }
1651327
1661328 static void ButtonElementSize(
167 void *clientData, void *elementRecord, Tk_Window tkwin,
168 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1329 void *clientData,
1330 void *elementRecord,
1331 Tk_Window tkwin,
1332 int *minWidth,
1333 int *minHeight,
1334 Ttk_Padding *paddingPtr)
1691335 {
1701336 ThemeButtonParams *params = clientData;
171 const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0);
1337 const HIThemeButtonDrawInfo info =
1338 computeButtonDrawInfo(params, 0, tkwin);
1721339 static const CGRect scratchBounds = {{0, 0}, {100, 100}};
173 CGRect contentBounds;
174
175 ButtonElementSizeNoPadding(
176 clientData, elementRecord, tkwin,
177 widthPtr, heightPtr, paddingPtr);
1340 CGRect contentBounds, backgroundBounds;
1341 int verticalPad;
1342
1343 ButtonElementMinSize(clientData, elementRecord, tkwin,
1344 minWidth, minHeight, paddingPtr);
1781345
1791346 /*
180 * To compute internal padding, query the appearance manager
181 * for the content bounds of a dummy rectangle, then use
182 * the difference as the padding.
1347 * Given a hypothetical bounding rectangle for a button, HIToolbox will
1348 * compute a bounding rectangle for the button contents and a bounding
1349 * rectangle for the button background. The background bounds are large
1350 * enough to contain the image of the button in any state, which might
1351 * include highlight borders, shadows, etc. The content rectangle is not
1352 * centered vertically within the background rectangle, presumably because
1353 * shadows only appear on the bottom. Nonetheless, when HITools is asked
1354 * to draw a button with a certain bounding rectangle it draws the button
1355 * centered within the rectangle.
1356 *
1357 * To compute the effective padding around a button we request the
1358 * content and bounding rectangles for a 100x100 button and use the
1359 * padding between those. However, we symmetrize the padding on the
1360 * top and bottom, because that is how the button will be drawn.
1831361 */
1362
1841363 ChkErr(HIThemeGetButtonContentBounds,
1851364 &scratchBounds, &info, &contentBounds);
186
187 paddingPtr->left = CGRectGetMinX(contentBounds);
188 paddingPtr->top = CGRectGetMinY(contentBounds);
189 paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds) + 1;
190 paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds);
191
192 /*
193 * Now add a little extra padding to account for drop shadows.
194 * @@@ SHOULD: call GetThemeButtonBackgroundBounds() instead.
195 */
196
197 *paddingPtr = Ttk_AddPadding(*paddingPtr, ButtonMargins);
198 *widthPtr += Ttk_PaddingWidth(ButtonMargins);
199 *heightPtr += Ttk_PaddingHeight(ButtonMargins);
1365 ChkErr(HIThemeGetButtonBackgroundBounds,
1366 &scratchBounds, &info, &backgroundBounds);
1367 paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x;
1368 paddingPtr->right =
1369 CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds);
1370 verticalPad = backgroundBounds.size.height - contentBounds.size.height;
1371 paddingPtr->top = paddingPtr->bottom = verticalPad / 2;
2001372 }
2011373
2021374 static void ButtonElementDraw(
203 void *clientData, void *elementRecord, Tk_Window tkwin,
204 Drawable d, Ttk_Box b, Ttk_State state)
1375 void *clientData,
1376 void *elementRecord,
1377 Tk_Window tkwin,
1378 Drawable d,
1379 Ttk_Box b,
1380 Ttk_State state)
2051381 {
2061382 ThemeButtonParams *params = clientData;
207 CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ButtonMargins));
208 const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state);
1383 CGRect bounds = BoxToRect(d, b);
1384 HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin);
1385
1386 bounds = NormalizeButtonBounds(params->heightMetric, bounds);
2091387
2101388 BEGIN_DRAWING(d)
211 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
1389 if (TkMacOSXInDarkMode(tkwin)) {
1390 switch (info.kind) {
1391 case kThemePushButton:
1392 case kThemePopupButton:
1393 DrawDarkButton(bounds, info.kind, state, dc.context);
1394 break;
1395 case kThemeCheckBox:
1396 DrawDarkCheckBox(bounds, state, dc.context);
1397 break;
1398 case kThemeRadioButton:
1399 DrawDarkRadioButton(bounds, state, dc.context);
1400 break;
1401 case kThemeRoundedBevelButton:
1402 DrawDarkBevelButton(bounds, state, dc.context);
1403 break;
1404 default:
1405 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context,
1406 HIOrientation, NULL);
1407 }
1408 } else if (info.kind == kThemePushButton &&
1409 (state & TTK_STATE_PRESSED)) {
1410 bounds.size.height += 2;
1411 if ([NSApp macMinorVersion] > 8) {
1412 GradientFillRoundedRectangle(dc.context, bounds, 4,
1413 pressedPushButtonGradient, 2);
1414 }
1415 } else {
1416
1417 /*
1418 * Apple's PushButton and PopupButton do not change their fill color
1419 * when the window is inactive. However, except in 10.7 (Lion), the
1420 * color of the arrow button on a PopupButton does change. For some
1421 * reason HITheme fills inactive buttons with a transparent color that
1422 * allows the window background to show through, leading to
1423 * inconsistent behavior. We work around this by filling behind an
1424 * inactive PopupButton with a text background color before asking
1425 * HIToolbox to draw it. For PushButtons, we simply draw them in the
1426 * active state.
1427 */
1428
1429 if (info.kind == kThemePopupButton &&
1430 (state & TTK_STATE_BACKGROUND)) {
1431 CGRect innerBounds = CGRectInset(bounds, 1, 1);
1432 NSColor *whiteRGBA = [NSColor whiteColor];
1433 SolidFillRoundedRectangle(dc.context, innerBounds, 4, whiteRGBA);
1434 }
1435
1436 /*
1437 * A BevelButton with mixed value is drawn borderless, which does make
1438 * much sense for us.
1439 */
1440
1441 if (info.kind == kThemeRoundedBevelButton &&
1442 info.value == kThemeButtonMixed) {
1443 info.value = kThemeButtonOff;
1444 info.state = kThemeStateInactive;
1445 }
1446 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
1447 NULL);
1448 }
2121449 END_DRAWING
2131450 }
2141451
2241461 * +++ Notebook elements.
2251462 */
2261463
227
2281464 /* Tab position logic, c.f. ttkNotebook.c TabState() */
229
230 #define TTK_STATE_NOTEBOOK_FIRST TTK_STATE_USER1
231 #define TTK_STATE_NOTEBOOK_LAST TTK_STATE_USER2
2321465 static Ttk_StateTable TabStyleTable[] = {
233 { kThemeTabFrontInactive, TTK_STATE_SELECTED|TTK_STATE_BACKGROUND},
234 { kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND},
235 { kThemeTabFrontUnavailable, TTK_STATE_DISABLED|TTK_STATE_SELECTED},
236 { kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED},
237 { kThemeTabFront, TTK_STATE_SELECTED},
238 { kThemeTabNonFrontPressed, TTK_STATE_PRESSED},
239 { kThemeTabNonFront, 0}
240 };
241
1466 {kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND},
1467 {kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND},
1468 {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED},
1469 {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED},
1470 {kThemeTabFront, TTK_STATE_SELECTED},
1471 {kThemeTabNonFrontPressed, TTK_STATE_PRESSED},
1472 {kThemeTabNonFront, 0}
1473 };
2421474 static Ttk_StateTable TabAdornmentTable[] = {
243 { kHIThemeTabAdornmentNone,
244 TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST},
245 {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_NOTEBOOK_FIRST},
246 {kHIThemeTabAdornmentNone, TTK_STATE_NOTEBOOK_LAST},
247 {kHIThemeTabAdornmentTrailingSeparator, 0 },
248 };
249
1475 {kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB},
1476 {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB},
1477 {kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB},
1478 {kHIThemeTabAdornmentTrailingSeparator, 0},
1479 };
2501480 static Ttk_StateTable TabPositionTable[] = {
251 { kHIThemeTabPositionOnly,
252 TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST},
253 { kHIThemeTabPositionFirst, TTK_STATE_NOTEBOOK_FIRST},
254 { kHIThemeTabPositionLast, TTK_STATE_NOTEBOOK_LAST},
255 { kHIThemeTabPositionMiddle, 0 },
1481 {kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB},
1482 {kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB},
1483 {kHIThemeTabPositionLast, TTK_STATE_LAST_TAB},
1484 {kHIThemeTabPositionMiddle, 0},
2561485 };
2571486
2581487 /*
2701499 * should be placed so that there are equal margins of space before and after
2711500 * it. The guidelines below provide the specifications you should use for tab
2721501 * labels:
273 * - Regular size: System font. Center in tab, leaving 12 pixels on each side.
1502 * - Regular size: System font. Center in tab, leaving 12 pixels on each
1503 *side.
2741504 * - Small: Small system font. Center in tab, leaving 10 pixels on each side.
2751505 * - Mini: Mini system font. Center in tab, leaving 8 pixels on each side.
2761506 *
2841514 * the tab view, leave enough space below the tab view so the controls are 20
2851515 * pixels above the bottom edge of the window and 12 pixels between the tab
2861516 * view and the controls.
1517 *
2871518 * If you choose to extend the tab view sides and bottom so that they meet the
2881519 * window sides and bottom, you should leave a margin of at least 20 pixels
2891520 * between the content in the tab view and the tab-view edges.
2941525 */
2951526
2961527 static void TabElementSize(
297 void *clientData, void *elementRecord, Tk_Window tkwin,
298 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
299 {
300 GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *)heightPtr);
1528 void *clientData,
1529 void *elementRecord,
1530 Tk_Window tkwin,
1531 int *minWidth,
1532 int *minHeight,
1533 Ttk_Padding *paddingPtr)
1534 {
1535 GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *) minHeight);
3011536 *paddingPtr = Ttk_MakePadding(0, 0, 0, 2);
3021537
3031538 }
3041539
3051540 static void TabElementDraw(
306 void *clientData, void *elementRecord, Tk_Window tkwin,
307 Drawable d, Ttk_Box b, Ttk_State state)
1541 void *clientData,
1542 void *elementRecord,
1543 Tk_Window tkwin,
1544 Drawable d,
1545 Ttk_Box b,
1546 Ttk_State state)
3081547 {
3091548 CGRect bounds = BoxToRect(d, b);
3101549 HIThemeTabDrawInfo info = {
3181557 };
3191558
3201559 BEGIN_DRAWING(d)
321 ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL);
1560 if (TkMacOSXInDarkMode(tkwin)) {
1561 DrawDarkTab(bounds, state, dc.context);
1562 } else {
1563 ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation,
1564 NULL);
1565 }
3221566 END_DRAWING
3231567 }
3241568
3331577 /*
3341578 * Notebook panes:
3351579 */
1580
3361581 static void PaneElementSize(
337 void *clientData, void *elementRecord, Tk_Window tkwin,
338 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1582 void *clientData,
1583 void *elementRecord,
1584 Tk_Window tkwin,
1585 int *minWidth,
1586 int *minHeight,
1587 Ttk_Padding *paddingPtr)
3391588 {
3401589 *paddingPtr = Ttk_MakePadding(9, 5, 9, 9);
3411590 }
3421591
3431592 static void PaneElementDraw(
344 void *clientData, void *elementRecord, Tk_Window tkwin,
345 Drawable d, Ttk_Box b, Ttk_State state)
1593 void *clientData,
1594 void *elementRecord,
1595 Tk_Window tkwin,
1596 Drawable d,
1597 Ttk_Box b,
1598 Ttk_State state)
3461599 {
3471600 CGRect bounds = BoxToRect(d, b);
348 HIThemeTabPaneDrawInfo info = {
349 .version = 1,
350 .state = Ttk_StateTableLookup(ThemeStateTable, state),
351 .direction = kThemeTabNorth,
352 .size = kHIThemeTabSizeNormal,
353 .kind = kHIThemeTabKindNormal,
354 .adornment = kHIThemeTabPaneAdornmentNormal,
355 };
3561601
3571602 bounds.origin.y -= kThemeMetricTabFrameOverlap;
3581603 bounds.size.height += kThemeMetricTabFrameOverlap;
3591604 BEGIN_DRAWING(d)
360 ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation);
1605 if ([NSApp macMinorVersion] > 8) {
1606 DrawGroupBox(bounds, dc.context, tkwin);
1607 } else {
1608 HIThemeTabPaneDrawInfo info = {
1609 .version = 1,
1610 .state = Ttk_StateTableLookup(ThemeStateTable, state),
1611 .direction = kThemeTabNorth,
1612 .size = kHIThemeTabSizeNormal,
1613 .kind = kHIThemeTabKindNormal,
1614 .adornment = kHIThemeTabPaneAdornmentNormal,
1615 };
1616 bounds.origin.y -= kThemeMetricTabFrameOverlap;
1617 bounds.size.height += kThemeMetricTabFrameOverlap;
1618 ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation);
1619 }
3611620 END_DRAWING
3621621 }
3631622
3691628 PaneElementDraw
3701629 };
3711630
372 /*
373 * Labelframe borders:
374 * Use "primary group box ..."
375 * Quoth DrawThemePrimaryGroup reference:
376 * "The primary group box frame is drawn inside the specified
377 * rectangle and is a maximum of 2 pixels thick."
378 *
379 * "Maximum of 2 pixels thick" is apparently a lie;
380 * looks more like 4 to me with shading.
381 */
1631 /*----------------------------------------------------------------------
1632 * +++ Labelframe elements --
1633 *
1634 * Labelframe borders: Use "primary group box ..." Quoth
1635 * DrawThemePrimaryGroup reference: "The primary group box frame is drawn
1636 * inside the specified rectangle and is a maximum of 2 pixels thick."
1637 *
1638 * "Maximum of 2 pixels thick" is apparently a lie; looks more like 4 to me
1639 * with shading.
1640 */
1641
3821642 static void GroupElementSize(
383 void *clientData, void *elementRecord, Tk_Window tkwin,
384 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1643 void *clientData,
1644 void *elementRecord,
1645 Tk_Window tkwin,
1646 int *minWidth,
1647 int *minHeight,
1648 Ttk_Padding *paddingPtr)
3851649 {
3861650 *paddingPtr = Ttk_UniformPadding(4);
3871651 }
3881652
3891653 static void GroupElementDraw(
390 void *clientData, void *elementRecord, Tk_Window tkwin,
391 Drawable d, Ttk_Box b, Ttk_State state)
1654 void *clientData,
1655 void *elementRecord,
1656 Tk_Window tkwin,
1657 Drawable d,
1658 Ttk_Box b,
1659 Ttk_State state)
3921660 {
3931661 CGRect bounds = BoxToRect(d, b);
394 const HIThemeGroupBoxDrawInfo info = {
395 .version = 0,
396 .state = Ttk_StateTableLookup(ThemeStateTable, state),
397 .kind = kHIThemeGroupBoxKindPrimaryOpaque,
398 };
3991662
4001663 BEGIN_DRAWING(d)
401 ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation);
1664 if ([NSApp macMinorVersion] > 8) {
1665 DrawGroupBox(bounds, dc.context, tkwin);
1666 } else {
1667 const HIThemeGroupBoxDrawInfo info = {
1668 .version = 0,
1669 .state = Ttk_StateTableLookup(ThemeStateTable, state),
1670 .kind = kHIThemeGroupBoxKindPrimaryOpaque,
1671 };
1672 ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation);
1673 }
4021674 END_DRAWING
4031675 }
4041676
4111683 };
4121684
4131685 /*----------------------------------------------------------------------
414 * +++ Entry element --
415 * 3 pixels padding for focus rectangle
416 * 2 pixels padding for EditTextFrame
1686 * +++ Entry elements --
1687 *
1688 * 3 pixels padding for focus rectangle
1689 * 2 pixels padding for EditTextFrame
4171690 */
4181691
4191692 typedef struct {
420 Tcl_Obj *backgroundObj;
1693 Tcl_Obj *backgroundObj;
1694 Tcl_Obj *fieldbackgroundObj;
4211695 } EntryElement;
4221696
1697 #define ENTRY_DEFAULT_BACKGROUND "systemTextBackgroundColor"
1698
4231699 static Ttk_ElementOptionSpec EntryElementOptions[] = {
424 { "-background", TK_OPTION_BORDER,
425 Tk_Offset(EntryElement,backgroundObj), "white" },
1700 {"-background", TK_OPTION_BORDER,
1701 Tk_Offset(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND},
1702 {"-fieldbackground", TK_OPTION_BORDER,
1703 Tk_Offset(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND},
4261704 {0}
4271705 };
4281706
4291707 static void EntryElementSize(
430 void *clientData, void *elementRecord, Tk_Window tkwin,
431 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
432 {
433 *paddingPtr = Ttk_UniformPadding(5);
1708 void *clientData,
1709 void *elementRecord,
1710 Tk_Window tkwin,
1711 int *minWidth,
1712 int *minHeight,
1713 Ttk_Padding *paddingPtr)
1714 {
1715 *paddingPtr = Ttk_MakePadding(7, 5, 7, 6);
4341716 }
4351717
4361718 static void EntryElementDraw(
437 void *clientData, void *elementRecord, Tk_Window tkwin,
438 Drawable d, Ttk_Box b, Ttk_State state)
1719 void *clientData,
1720 void *elementRecord,
1721 Tk_Window tkwin,
1722 Drawable d,
1723 Ttk_Box b,
1724 Ttk_State state)
4391725 {
4401726 EntryElement *e = elementRecord;
441 Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj);
4421727 Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3));
4431728 CGRect bounds = BoxToRect(d, inner);
444 const HIThemeFrameDrawInfo info = {
445 .version = 0,
446 .kind = kHIThemeFrameTextFieldSquare,
447 .state = Ttk_StateTableLookup(ThemeStateTable, state),
448 .isFocused = state & TTK_STATE_FOCUS,
449 };
450
451 /*
452 * Erase w/background color:
453 */
454 XFillRectangle(Tk_Display(tkwin), d,
455 Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
456 inner.x,inner.y, inner.width, inner.height);
457
458 BEGIN_DRAWING(d)
459 ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);
460 /*if (state & TTK_STATE_FOCUS) {
461 ChkErr(DrawThemeFocusRect, &bounds, 1);
462 }*/
463 END_DRAWING
1729 NSColor *background;
1730 Tk_3DBorder backgroundPtr = NULL;
1731 static const char *defaultBG = ENTRY_DEFAULT_BACKGROUND;
1732
1733 if (TkMacOSXInDarkMode(tkwin)) {
1734 BEGIN_DRAWING(d)
1735 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
1736 CGFloat fill[4];
1737 GetBackgroundColor(dc.context, tkwin, 1, fill);
1738
1739 /*
1740 * Lighten the background to provide contrast.
1741 */
1742
1743 for (int i = 0; i < 3; i++) {
1744 fill[i] += 9.0 / 255.0;
1745 }
1746 background = [NSColor colorWithColorSpace: deviceRGB
1747 components: fill
1748 count: 4];
1749 CGContextSetFillColorWithColor(dc.context, CGCOLOR(background));
1750 CGContextFillRect(dc.context, bounds);
1751 if (state & TTK_STATE_FOCUS) {
1752 DrawDarkFocusRing(bounds, dc.context);
1753 } else {
1754 DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare);
1755 }
1756 END_DRAWING
1757 } else {
1758 const HIThemeFrameDrawInfo info = {
1759 .version = 0,
1760 .kind = kHIThemeFrameTextFieldSquare,
1761 .state = Ttk_StateTableLookup(ThemeStateTable, state),
1762 .isFocused = state & TTK_STATE_FOCUS,
1763 };
1764
1765 /*
1766 * Earlier versions of the Aqua theme ignored the -fieldbackground
1767 * option and used the -background as if it were -fieldbackground.
1768 * Here we are enabling -fieldbackground. For backwards
1769 * compatibility, if -fieldbackground is set to the default color and
1770 * -background is set to a different color then we use -background as
1771 * -fieldbackground.
1772 */
1773
1774 if (0 != strcmp(Tcl_GetString(e->fieldbackgroundObj), defaultBG)) {
1775 backgroundPtr =
1776 Tk_Get3DBorderFromObj(tkwin, e->fieldbackgroundObj);
1777 } else if (0 != strcmp(Tcl_GetString(e->backgroundObj), defaultBG)) {
1778 backgroundPtr = Tk_Get3DBorderFromObj(tkwin, e->backgroundObj);
1779 }
1780 if (backgroundPtr != NULL) {
1781 XFillRectangle(Tk_Display(tkwin), d,
1782 Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
1783 inner.x, inner.y, inner.width, inner.height);
1784 }
1785 BEGIN_DRAWING(d)
1786 if (backgroundPtr == NULL) {
1787 if ([NSApp macMinorVersion] > 8) {
1788 background = [NSColor textBackgroundColor];
1789 CGContextSetFillColorWithColor(dc.context, CGCOLOR(background));
1790 } else {
1791 CGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0);
1792 }
1793 CGContextFillRect(dc.context, bounds);
1794 }
1795 ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);
1796 END_DRAWING
1797 }
4641798 }
4651799
4661800 static Ttk_ElementSpec EntryElementSpec = {
4721806 };
4731807
4741808 /*----------------------------------------------------------------------
475 * +++ Combobox:
1809 * +++ Combobox elements --
4761810 *
4771811 * NOTES:
478 * kThemeMetricComboBoxLargeDisclosureWidth -> 17
479 * Padding and margins guesstimated by trial-and-error.
480 */
481
482 static Ttk_Padding ComboboxPadding = { 2, 3, 17, 1 };
483 static Ttk_Padding ComboboxMargins = { 3, 3, 4, 4 };
1812 * The HIToolbox has incomplete and inconsistent support for ComboBoxes.
1813 * There is no constant available to get the height of a ComboBox with
1814 * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as
1815 * PopupButtons and PushButtons, but they have no shadow at the bottom.
1816 * As a result, they are drawn 1 pixel above the center of the bounds
1817 * rectangle rather than being centered like the other buttons. One can
1818 * request background bounds for a ComboBox, and it is reported with
1819 * height 23, while the actual button face, including its 1-pixel border
1820 * has height 21. Attempting to request the content bounds returns a 0x0
1821 * rectangle. Measurement indicates that the arrow button has width 18.
1822 *
1823 * With no help available from HIToolbox, we have to use hard-wired
1824 * constants for the padding. We shift the bounding rectangle downward by
1825 * 1 pixel to account for the fact that the button is not centered.
1826 */
1827
1828 static Ttk_Padding ComboboxPadding = {4, 2, 20, 2};
4841829
4851830 static void ComboboxElementSize(
486 void *clientData, void *elementRecord, Tk_Window tkwin,
487 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
488 {
489 *widthPtr = 0;
490 *heightPtr = 0;
491 *paddingPtr = Ttk_AddPadding(ComboboxMargins, ComboboxPadding);
1831 void *clientData,
1832 void *elementRecord,
1833 Tk_Window tkwin,
1834 int *minWidth,
1835 int *minHeight,
1836 Ttk_Padding *paddingPtr)
1837 {
1838 *minWidth = 24;
1839 *minHeight = 23;
1840 *paddingPtr = ComboboxPadding;
4921841 }
4931842
4941843 static void ComboboxElementDraw(
495 void *clientData, void *elementRecord, Tk_Window tkwin,
496 Drawable d, Ttk_Box b, Ttk_State state)
497 {
498 CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ComboboxMargins));
1844 void *clientData,
1845 void *elementRecord,
1846 Tk_Window tkwin,
1847 Drawable d,
1848 Ttk_Box b,
1849 Ttk_State state)
1850 {
1851 CGRect bounds = BoxToRect(d, b);
4991852 const HIThemeButtonDrawInfo info = {
5001853 .version = 0,
5011854 .state = Ttk_StateTableLookup(ThemeStateTable, state),
5051858 };
5061859
5071860 BEGIN_DRAWING(d)
1861 bounds.origin.y += 1;
1862 if (TkMacOSXInDarkMode(tkwin)) {
1863 bounds.size.height += 1;
1864 DrawDarkButton(bounds, info.kind, state, dc.context);
1865 } else if ([NSApp macMinorVersion] > 8) {
1866 if ((state & TTK_STATE_BACKGROUND) &&
1867 !(state & TTK_STATE_DISABLED)) {
1868 NSColor *background = [NSColor textBackgroundColor];
1869 CGRect innerBounds = CGRectInset(bounds, 1, 2);
1870 SolidFillRoundedRectangle(dc.context, innerBounds, 4, background);
1871 }
1872 }
5081873 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
5091874 END_DRAWING
5101875 }
5171882 ComboboxElementDraw
5181883 };
5191884
520
521
522
523
524 /*----------------------------------------------------------------------
525 * +++ Spinbuttons.
526 *
527 * From Apple HIG, part III, section "Controls", "The Stepper Control":
528 * there should be 2 pixels of space between the stepper control
529 * (AKA IncDecButton, AKA "little arrows") and the text field it modifies.
530 */
531
532 static Ttk_Padding SpinbuttonMargins = {2,0,2,0};
533 static void SpinButtonElementSize(
534 void *clientData, void *elementRecord, Tk_Window tkwin,
535 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
1885 /*----------------------------------------------------------------------
1886 * +++ Spinbutton elements --
1887 *
1888 * From Apple HIG, part III, section "Controls", "The Stepper Control":
1889 * there should be 2 pixels of space between the stepper control (AKA
1890 * IncDecButton, AKA "little arrows") and the text field it modifies.
1891 *
1892 * Ttk expects the up and down arrows to be distinct elements but
1893 * HIToolbox draws them as one widget with two different pressed states.
1894 * We work around this by defining them as separate elements in the
1895 * layout, but making each one have a drawing method which also draws the
1896 * other one. The down button does no drawing when not pressed, and when
1897 * pressed draws the entire IncDecButton in its "pressed down" state.
1898 * The up button draws the entire IncDecButton when not pressed and when
1899 * pressed draws the IncDecButton in its "pressed up" state. NOTE: This
1900 * means that when the down button is pressed the IncDecButton will be
1901 * drawn twice, first in unpressed state by the up arrow and then in
1902 * "pressed down" state by the down button. The drawing must be done in
1903 * that order. So the up button must be listed first in the layout.
1904 */
1905
1906 static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0};
1907
1908 static void SpinButtonUpElementSize(
1909 void *clientData,
1910 void *elementRecord,
1911 Tk_Window tkwin,
1912 int *minWidth,
1913 int *minHeight,
1914 Ttk_Padding *paddingPtr)
5361915 {
5371916 SInt32 s;
5381917
5391918 ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s);
540 *widthPtr = s + Ttk_PaddingWidth(SpinbuttonMargins);
1919 *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins);
5411920 ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s);
542 *heightPtr = s + Ttk_PaddingHeight(SpinbuttonMargins);
543 }
544
545 static void SpinButtonElementDraw(
546 void *clientData, void *elementRecord, Tk_Window tkwin,
547 Drawable d, Ttk_Box b, Ttk_State state)
1921 *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2;
1922 }
1923
1924 static void SpinButtonUpElementDraw(
1925 void *clientData,
1926 void *elementRecord,
1927 Tk_Window tkwin,
1928 Drawable d,
1929 Ttk_Box b,
1930 Ttk_State state)
5481931 {
5491932 CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));
550 /* @@@ can't currently distinguish PressedUp (== Pressed) from PressedDown;
551 * ignore this bit for now [see #2219588]
552 */
1933 int infoState;
1934
1935 bounds.size.height *= 2;
1936 if (state & TTK_STATE_PRESSED) {
1937 infoState = kThemeStatePressedUp;
1938 } else {
1939 infoState = Ttk_StateTableLookup(ThemeStateTable, state);
1940 }
5531941 const HIThemeButtonDrawInfo info = {
5541942 .version = 0,
555 .state = Ttk_StateTableLookup(ThemeStateTable, state & ~TTK_STATE_PRESSED),
1943 .state = infoState,
5561944 .kind = kThemeIncDecButton,
5571945 .value = Ttk_StateTableLookup(ButtonValueTable, state),
5581946 .adornment = kThemeAdornmentNone,
5591947 };
560
5611948 BEGIN_DRAWING(d)
562 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
1949 if (TkMacOSXInDarkMode(tkwin)) {
1950 DrawDarkIncDecButton(bounds, infoState, state, dc.context);
1951 } else {
1952 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
1953 NULL);
1954 }
5631955 END_DRAWING
5641956 }
5651957
566 static Ttk_ElementSpec SpinButtonElementSpec = {
1958 static Ttk_ElementSpec SpinButtonUpElementSpec = {
5671959 TK_STYLE_VERSION_2,
5681960 sizeof(NullElement),
5691961 TtkNullElementOptions,
570 SpinButtonElementSize,
571 SpinButtonElementDraw
572 };
573
1962 SpinButtonUpElementSize,
1963 SpinButtonUpElementDraw
1964 };
1965 static void SpinButtonDownElementSize(
1966 void *clientData,
1967 void *elementRecord,
1968 Tk_Window tkwin,
1969 int *minWidth,
1970 int *minHeight,
1971 Ttk_Padding *paddingPtr)
1972 {
1973 SInt32 s;
1974
1975 ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s);
1976 *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins);
1977 ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s);
1978 *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2;
1979 }
1980
1981 static void SpinButtonDownElementDraw(
1982 void *clientData,
1983 void *elementRecord,
1984 Tk_Window tkwin,
1985 Drawable d,
1986 Ttk_Box b,
1987 Ttk_State state)
1988 {
1989 CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins));
1990 int infoState = 0;
1991
1992 bounds.origin.y -= bounds.size.height;
1993 bounds.size.height *= 2;
1994 if (state & TTK_STATE_PRESSED) {
1995 infoState = kThemeStatePressedDown;
1996 } else {
1997 return;
1998 }
1999 const HIThemeButtonDrawInfo info = {
2000 .version = 0,
2001 .state = infoState,
2002 .kind = kThemeIncDecButton,
2003 .value = Ttk_StateTableLookup(ButtonValueTable, state),
2004 .adornment = kThemeAdornmentNone,
2005 };
2006
2007 BEGIN_DRAWING(d)
2008 if (TkMacOSXInDarkMode(tkwin)) {
2009 DrawDarkIncDecButton(bounds, infoState, state, dc.context);
2010 } else {
2011 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
2012 NULL);
2013 }
2014 END_DRAWING
2015 }
2016
2017 static Ttk_ElementSpec SpinButtonDownElementSpec = {
2018 TK_STYLE_VERSION_2,
2019 sizeof(NullElement),
2020 TtkNullElementOptions,
2021 SpinButtonDownElementSize,
2022 SpinButtonDownElementDraw
2023 };
5742024
5752025 /*----------------------------------------------------------------------
5762026 * +++ DrawThemeTrack-based elements --
577 * Progress bars and scales. (See also: <<NOTE-TRACKS>>)
2027 *
2028 * Progress bars and scales. (See also: <<NOTE-TRACKS>>)
2029 */
2030
2031 /*
2032 * Apple does not change the appearance of a slider when the window becomes
2033 * inactive. So we shouldn't either.
5782034 */
5792035
5802036 static Ttk_StateTable ThemeTrackEnableTable[] = {
581 { kThemeTrackDisabled, TTK_STATE_DISABLED, 0 },
582 { kThemeTrackInactive, TTK_STATE_BACKGROUND, 0 },
583 { kThemeTrackActive, 0, 0 }
2037 {kThemeTrackDisabled, TTK_STATE_DISABLED, 0},
2038 {kThemeTrackActive, TTK_STATE_BACKGROUND, 0},
2039 {kThemeTrackActive, 0, 0}
5842040 /* { kThemeTrackNothingToScroll, ?, ? }, */
5852041 };
5862042
587 typedef struct { /* TrackElement client data */
588 ThemeTrackKind kind;
589 SInt32 thicknessMetric;
2043 typedef struct { /* TrackElement client data */
2044 ThemeTrackKind kind;
2045 SInt32 thicknessMetric;
5902046 } TrackElementData;
5912047
5922048 static TrackElementData ScaleData = {
5932049 kThemeSlider, kThemeMetricHSliderHeight
5942050 };
5952051
596
5972052 typedef struct {
598 Tcl_Obj *fromObj; /* minimum value */
599 Tcl_Obj *toObj; /* maximum value */
600 Tcl_Obj *valueObj; /* current value */
601 Tcl_Obj *orientObj; /* horizontal / vertical */
2053 Tcl_Obj *fromObj; /* minimum value */
2054 Tcl_Obj *toObj; /* maximum value */
2055 Tcl_Obj *valueObj; /* current value */
2056 Tcl_Obj *orientObj; /* horizontal / vertical */
6022057 } TrackElement;
6032058
6042059 static Ttk_ElementOptionSpec TrackElementOptions[] = {
605 { "-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,fromObj) },
606 { "-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,toObj) },
607 { "-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,valueObj) },
608 { "-orient", TK_OPTION_STRING, Tk_Offset(TrackElement,orientObj) },
609 {0,0,0}
610 };
611
2060 {"-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, fromObj)},
2061 {"-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, toObj)},
2062 {"-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, valueObj)},
2063 {"-orient", TK_OPTION_STRING, Tk_Offset(TrackElement, orientObj)},
2064 {0, 0, 0}
2065 };
6122066 static void TrackElementSize(
613 void *clientData, void *elementRecord, Tk_Window tkwin,
614 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
2067 void *clientData,
2068 void *elementRecord,
2069 Tk_Window tkwin,
2070 int *minWidth,
2071 int *minHeight,
2072 Ttk_Padding *paddingPtr)
6152073 {
6162074 TrackElementData *data = clientData;
617 SInt32 size = 24; /* reasonable default ... */
2075 SInt32 size = 24; /* reasonable default ... */
6182076
6192077 ChkErr(GetThemeMetric, data->thicknessMetric, &size);
620 *widthPtr = *heightPtr = size;
2078 *minWidth = *minHeight = size;
6212079 }
6222080
6232081 static void TrackElementDraw(
624 void *clientData, void *elementRecord, Tk_Window tkwin,
625 Drawable d, Ttk_Box b, Ttk_State state)
2082 void *clientData,
2083 void *elementRecord,
2084 Tk_Window tkwin,
2085 Drawable d,
2086 Ttk_Box b,
2087 Ttk_State state)
6262088 {
6272089 TrackElementData *data = clientData;
6282090 TrackElement *elem = elementRecord;
6332095 Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from);
6342096 Tcl_GetDoubleFromObj(NULL, elem->toObj, &to);
6352097 Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value);
636 factor = RangeToFactor(to - from);
2098 factor = RangeToFactor(to);
6372099
6382100 HIThemeTrackDrawInfo info = {
6392101 .version = 0,
6432105 .max = to * factor,
6442106 .value = value * factor,
6452107 .attributes = kThemeTrackShowThumb |
646 (orientation == TTK_ORIENT_HORIZONTAL ?
647 kThemeTrackHorizontal : 0),
2108 (orientation == TTK_ORIENT_HORIZONTAL ?
2109 kThemeTrackHorizontal : 0),
6482110 .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),
6492111 .trackInfo.progress.phase = 0,
6502112 };
6512113
6522114 if (info.kind == kThemeSlider) {
6532115 info.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ?
654 kThemeThumbPressed : 0;
655 info.trackInfo.slider.thumbDir = kThemeThumbPlain;
656 }
657
658
2116 kThemeThumbPressed : 0;
2117 if (state & TTK_STATE_ALTERNATE) {
2118 info.trackInfo.slider.thumbDir = kThemeThumbDownward;
2119 } else {
2120 info.trackInfo.slider.thumbDir = kThemeThumbPlain;
2121 }
2122 }
6592123 BEGIN_DRAWING(d)
2124 if (TkMacOSXInDarkMode(tkwin)) {
2125 CGRect bounds = BoxToRect(d, b);
2126 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
2127 NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
2128 components: darkTrack
2129 count: 4];
2130 if (orientation == TTK_ORIENT_HORIZONTAL) {
2131 bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 2);
2132 } else {
2133 bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 2);
2134 }
2135 SolidFillRoundedRectangle(dc.context, bounds, 2, trackColor);
2136 }
6602137 ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation);
6612138 END_DRAWING
6622139 }
6692146 TrackElementDraw
6702147 };
6712148
672 /*
673 * Slider element -- <<NOTE-TRACKS>>
2149 /*----------------------------------------------------------------------
2150 * Slider elements -- <<NOTE-TRACKS>>
2151 *
6742152 * Has geometry only. The Scale widget adjusts the position of this element,
6752153 * and uses it for hit detection. In the Aqua theme, the slider is actually
6762154 * drawn as part of the trough element.
6772155 *
678 * Also buggy: The geometry here is a Wild-Assed-Guess; I can't
679 * figure out how to get the Appearance Manager to tell me the
680 * slider size.
681 */
2156 */
2157
6822158 static void SliderElementSize(
683 void *clientData, void *elementRecord, Tk_Window tkwin,
684 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
685 {
686 *widthPtr = *heightPtr = 24;
2159 void *clientData,
2160 void *elementRecord,
2161 Tk_Window tkwin,
2162 int *minWidth,
2163 int *minHeight,
2164 Ttk_Padding *paddingPtr)
2165 {
2166 *minWidth = *minHeight = 24;
6872167 }
6882168
6892169 static Ttk_ElementSpec SliderElementSpec = {
6952175 };
6962176
6972177 /*----------------------------------------------------------------------
698 * +++ Progress bar element (new):
2178 * +++ Progress bar elements --
6992179 *
7002180 * @@@ NOTE: According to an older revision of the Aqua reference docs,
7012181 * @@@ the 'phase' field is between 0 and 4. Newer revisions say
7032183 */
7042184
7052185 typedef struct {
706 Tcl_Obj *orientObj; /* horizontal / vertical */
707 Tcl_Obj *valueObj; /* current value */
708 Tcl_Obj *maximumObj; /* maximum value */
709 Tcl_Obj *phaseObj; /* animation phase */
710 Tcl_Obj *modeObj; /* progress bar mode */
2186 Tcl_Obj *orientObj; /* horizontal / vertical */
2187 Tcl_Obj *valueObj; /* current value */
2188 Tcl_Obj *maximumObj; /* maximum value */
2189 Tcl_Obj *phaseObj; /* animation phase */
2190 Tcl_Obj *modeObj; /* progress bar mode */
7112191 } PbarElement;
7122192
7132193 static Ttk_ElementOptionSpec PbarElementOptions[] = {
714 { "-orient", TK_OPTION_STRING,
715 Tk_Offset(PbarElement,orientObj), "horizontal" },
716 { "-value", TK_OPTION_DOUBLE,
717 Tk_Offset(PbarElement,valueObj), "0" },
718 { "-maximum", TK_OPTION_DOUBLE,
719 Tk_Offset(PbarElement,maximumObj), "100" },
720 { "-phase", TK_OPTION_INT,
721 Tk_Offset(PbarElement,phaseObj), "0" },
722 { "-mode", TK_OPTION_STRING,
723 Tk_Offset(PbarElement,modeObj), "determinate" },
724 {0,0,0,0}
725 };
726
2194 {"-orient", TK_OPTION_STRING,
2195 Tk_Offset(PbarElement, orientObj), "horizontal"},
2196 {"-value", TK_OPTION_DOUBLE,
2197 Tk_Offset(PbarElement, valueObj), "0"},
2198 {"-maximum", TK_OPTION_DOUBLE,
2199 Tk_Offset(PbarElement, maximumObj), "100"},
2200 {"-phase", TK_OPTION_INT,
2201 Tk_Offset(PbarElement, phaseObj), "0"},
2202 {"-mode", TK_OPTION_STRING,
2203 Tk_Offset(PbarElement, modeObj), "determinate"},
2204 {0, 0, 0, 0}
2205 };
7272206 static void PbarElementSize(
728 void *clientData, void *elementRecord, Tk_Window tkwin,
729 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
730 {
731 SInt32 size = 24; /* @@@ Check HIG for correct default */
2207 void *clientData,
2208 void *elementRecord,
2209 Tk_Window tkwin,
2210 int *minWidth,
2211 int *minHeight,
2212 Ttk_Padding *paddingPtr)
2213 {
2214 SInt32 size = 24; /* @@@ Check HIG for correct default */
7322215
7332216 ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size);
734 *widthPtr = *heightPtr = size;
2217 *minWidth = *minHeight = size;
7352218 }
7362219
7372220 static void PbarElementDraw(
738 void *clientData, void *elementRecord, Tk_Window tkwin,
739 Drawable d, Ttk_Box b, Ttk_State state)
2221 void *clientData,
2222 void *elementRecord,
2223 Tk_Window tkwin,
2224 Drawable d,
2225 Ttk_Box b,
2226 Ttk_State state)
7402227 {
7412228 PbarElement *pbar = elementRecord;
7422229 int orientation = TTK_ORIENT_HORIZONTAL, phase = 0;
7502237
7512238 HIThemeTrackDrawInfo info = {
7522239 .version = 0,
753 .kind = (!strcmp("indeterminate", Tcl_GetString(pbar->modeObj)) && value) ?
754 kThemeIndeterminateBar : kThemeProgressBar,
2240 .kind =
2241 (!strcmp("indeterminate",
2242 Tcl_GetString(pbar->modeObj)) && value) ?
2243 kThemeIndeterminateBar : kThemeProgressBar,
7552244 .bounds = BoxToRect(d, b),
7562245 .min = 0,
7572246 .max = maximum * factor,
7582247 .value = value * factor,
7592248 .attributes = kThemeTrackShowThumb |
760 (orientation == TTK_ORIENT_HORIZONTAL ?
761 kThemeTrackHorizontal : 0),
2249 (orientation == TTK_ORIENT_HORIZONTAL ?
2250 kThemeTrackHorizontal : 0),
7622251 .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state),
7632252 .trackInfo.progress.phase = phase,
7642253 };
7652254
7662255 BEGIN_DRAWING(d)
2256 if (TkMacOSXInDarkMode(tkwin)) {
2257 CGRect bounds = BoxToRect(d, b);
2258 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
2259 NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
2260 components: darkTrack
2261 count: 4];
2262 if (orientation == TTK_ORIENT_HORIZONTAL) {
2263 bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 3);
2264 } else {
2265 bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 1);
2266 }
2267 SolidFillRoundedRectangle(dc.context, bounds, 3, trackColor);
2268 }
7672269 ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation);
7682270 END_DRAWING
7692271 }
7772279 };
7782280
7792281 /*----------------------------------------------------------------------
2282 * +++ Scrollbar elements
2283 */
2284
2285 typedef struct
2286 {
2287 Tcl_Obj *orientObj;
2288 } ScrollbarElement;
2289
2290 static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
2291 {"-orient", TK_OPTION_STRING,
2292 Tk_Offset(ScrollbarElement, orientObj), "horizontal"},
2293 {0, 0, 0, 0}
2294 };
2295 static void TroughElementSize(
2296 void *clientData,
2297 void *elementRecord,
2298 Tk_Window tkwin,
2299 int *minWidth,
2300 int *minHeight,
2301 Ttk_Padding *paddingPtr)
2302 {
2303 ScrollbarElement *scrollbar = elementRecord;
2304 int orientation = TTK_ORIENT_HORIZONTAL;
2305 SInt32 thickness = 15;
2306
2307 Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
2308 ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness);
2309 if (orientation == TTK_ORIENT_HORIZONTAL) {
2310 *minHeight = thickness;
2311 if ([NSApp macMinorVersion] > 7) {
2312 *paddingPtr = Ttk_MakePadding(4, 4, 4, 3);
2313 }
2314 } else {
2315 *minWidth = thickness;
2316 if ([NSApp macMinorVersion] > 7) {
2317 *paddingPtr = Ttk_MakePadding(4, 4, 3, 4);
2318 }
2319 }
2320 }
2321
2322 static CGFloat lightTrough[4] = {250.0 / 255, 250.0 / 255, 250.0 / 255, 1.0};
2323 static CGFloat darkTrough[4] = {45.0 / 255, 46.0 / 255, 49.0 / 255, 1.0};
2324 static CGFloat lightInactiveThumb[4] = {
2325 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0
2326 };
2327 static CGFloat lightActiveThumb[4] = {
2328 133.0 / 255, 133.0 / 255, 133.0 / 255, 1.0
2329 };
2330 static CGFloat darkInactiveThumb[4] = {
2331 116.0 / 255, 117.0 / 255, 118.0 / 255, 1.0
2332 };
2333 static CGFloat darkActiveThumb[4] = {
2334 158.0 / 255, 158.0 / 255, 159.0 / 255, 1.0
2335 };
2336 static void TroughElementDraw(
2337 void *clientData,
2338 void *elementRecord,
2339 Tk_Window tkwin,
2340 Drawable d,
2341 Ttk_Box b,
2342 Ttk_State state)
2343 {
2344 ScrollbarElement *scrollbar = elementRecord;
2345 int orientation = TTK_ORIENT_HORIZONTAL;
2346 CGRect bounds = BoxToRect(d, b);
2347 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
2348 NSColor *troughColor;
2349 CGFloat *rgba = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough;
2350
2351 Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
2352 if (orientation == TTK_ORIENT_HORIZONTAL) {
2353 bounds = CGRectInset(bounds, 0, 1);
2354 } else {
2355 bounds = CGRectInset(bounds, 1, 0);
2356 }
2357 troughColor = [NSColor colorWithColorSpace: deviceRGB
2358 components: rgba
2359 count: 4];
2360 BEGIN_DRAWING(d)
2361 if ([NSApp macMinorVersion] > 8) {
2362 CGContextSetFillColorWithColor(dc.context, CGCOLOR(troughColor));
2363 } else {
2364 ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL,
2365 dc.context, HIOrientation);
2366 }
2367 CGContextFillRect(dc.context, bounds);
2368 END_DRAWING
2369 }
2370
2371 static Ttk_ElementSpec TroughElementSpec = {
2372 TK_STYLE_VERSION_2,
2373 sizeof(ScrollbarElement),
2374 ScrollbarElementOptions,
2375 TroughElementSize,
2376 TroughElementDraw
2377 };
2378 static void ThumbElementSize(
2379 void *clientData,
2380 void *elementRecord,
2381 Tk_Window tkwin,
2382 int *minWidth,
2383 int *minHeight,
2384 Ttk_Padding *paddingPtr)
2385 {
2386 ScrollbarElement *scrollbar = elementRecord;
2387 int orientation = TTK_ORIENT_HORIZONTAL;
2388
2389 Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
2390 if (orientation == TTK_ORIENT_VERTICAL) {
2391 *minHeight = 18;
2392 *minWidth = 8;
2393 } else {
2394 *minHeight = 8;
2395 *minWidth = 18;
2396 }
2397 }
2398
2399 static void ThumbElementDraw(
2400 void *clientData,
2401 void *elementRecord,
2402 Tk_Window tkwin,
2403 Drawable d,
2404 Ttk_Box b,
2405 Ttk_State state)
2406 {
2407 ScrollbarElement *scrollbar = elementRecord;
2408 int orientation = TTK_ORIENT_HORIZONTAL;
2409
2410 Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);
2411
2412 /*
2413 * In order to make ttk scrollbars work correctly it is necessary to be
2414 * able to display the thumb element at the size and location which the ttk
2415 * scrollbar widget requests. The algorithm that HIToolbox uses to
2416 * determine the thumb geometry from the input values of min, max, value
2417 * and viewSize is undocumented. A seemingly natural algorithm is
2418 * implemented below. This code uses that algorithm for older OS versions,
2419 * because using HITools also handles drawing the buttons and 3D thumb used
2420 * on those systems. For newer systems the cleanest approach is to just
2421 * draw the thumb directly.
2422 */
2423
2424 if ([NSApp macMinorVersion] > 8) {
2425 CGRect thumbBounds = BoxToRect(d, b);
2426 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
2427 NSColor *thumbColor;
2428 CGFloat *rgba;
2429 if ((orientation == TTK_ORIENT_HORIZONTAL &&
2430 thumbBounds.size.width >= Tk_Width(tkwin) - 8) ||
2431 (orientation == TTK_ORIENT_VERTICAL &&
2432 thumbBounds.size.height >= Tk_Height(tkwin) - 8)) {
2433 return;
2434 }
2435 int isDark = TkMacOSXInDarkMode(tkwin);
2436 if ((state & TTK_STATE_PRESSED) ||
2437 (state & TTK_STATE_HOVER)) {
2438 rgba = isDark ? darkActiveThumb : lightActiveThumb;
2439 } else {
2440 rgba = isDark ? darkInactiveThumb : lightInactiveThumb;
2441 }
2442 thumbColor = [NSColor colorWithColorSpace: deviceRGB
2443 components: rgba
2444 count: 4];
2445 BEGIN_DRAWING(d)
2446 SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor);
2447 END_DRAWING
2448 } else {
2449 double thumbSize, trackSize, visibleSize, factor, fraction;
2450 MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin);
2451 CGRect troughBounds = {{macWin->xOff, macWin->yOff},
2452 {Tk_Width(tkwin), Tk_Height(tkwin)}};
2453
2454 /*
2455 * The info struct has integer fields, which will be converted to
2456 * floats in the drawing routine. All of values provided in the info
2457 * struct, namely min, max, value, and viewSize are only defined up to
2458 * an arbitrary scale factor. To avoid roundoff error we scale so
2459 * that the viewSize is a large float which is smaller than the
2460 * largest int.
2461 */
2462
2463 HIThemeTrackDrawInfo info = {
2464 .version = 0,
2465 .bounds = troughBounds,
2466 .min = 0,
2467 .attributes = kThemeTrackShowThumb |
2468 kThemeTrackThumbRgnIsNotGhost,
2469 .enableState = kThemeTrackActive
2470 };
2471 factor = RangeToFactor(100.0);
2472 if (orientation == TTK_ORIENT_HORIZONTAL) {
2473 trackSize = troughBounds.size.width;
2474 thumbSize = b.width;
2475 fraction = b.x / trackSize;
2476 } else {
2477 trackSize = troughBounds.size.height;
2478 thumbSize = b.height;
2479 fraction = b.y / trackSize;
2480 }
2481 visibleSize = (thumbSize / trackSize) * factor;
2482 info.max = factor - visibleSize;
2483 info.trackInfo.scrollbar.viewsize = visibleSize;
2484 if ([NSApp macMinorVersion] < 8 ||
2485 orientation == TTK_ORIENT_HORIZONTAL) {
2486 info.value = factor * fraction;
2487 } else {
2488 info.value = info.max - factor * fraction;
2489 }
2490 if ((state & TTK_STATE_PRESSED) ||
2491 (state & TTK_STATE_HOVER)) {
2492 info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
2493 } else {
2494 info.trackInfo.scrollbar.pressState = 0;
2495 }
2496 if (orientation == TTK_ORIENT_HORIZONTAL) {
2497 info.attributes |= kThemeTrackHorizontal;
2498 } else {
2499 info.attributes &= ~kThemeTrackHorizontal;
2500 }
2501 BEGIN_DRAWING(d)
2502 HIThemeDrawTrack(&info, 0, dc.context, kHIThemeOrientationNormal);
2503 END_DRAWING
2504 }
2505 }
2506
2507 static Ttk_ElementSpec ThumbElementSpec = {
2508 TK_STYLE_VERSION_2,
2509 sizeof(ScrollbarElement),
2510 ScrollbarElementOptions,
2511 ThumbElementSize,
2512 ThumbElementDraw
2513 };
2514 static void ArrowElementSize(
2515 void *clientData,
2516 void *elementRecord,
2517 Tk_Window tkwin,
2518 int *minWidth,
2519 int *minHeight,
2520 Ttk_Padding *paddingPtr)
2521 {
2522 if ([NSApp macMinorVersion] < 8) {
2523 *minHeight = *minWidth = 14;
2524 } else {
2525 *minHeight = *minWidth = -1;
2526 }
2527 }
2528
2529 static Ttk_ElementSpec ArrowElementSpec = {
2530 TK_STYLE_VERSION_2,
2531 sizeof(ScrollbarElement),
2532 ScrollbarElementOptions,
2533 ArrowElementSize,
2534 TtkNullElementDraw
2535 };
2536
2537 /*----------------------------------------------------------------------
7802538 * +++ Separator element.
7812539 *
782 * DrawThemeSeparator() guesses the orientation of the line from
783 * the width and height of the rectangle, so the same element can
784 * can be used for horizontal, vertical, and general separators.
2540 * DrawThemeSeparator() guesses the orientation of the line from the width
2541 * and height of the rectangle, so the same element can can be used for
2542 * horizontal, vertical, and general separators.
7852543 */
7862544
7872545 static void SeparatorElementSize(
788 void *clientData, void *elementRecord, Tk_Window tkwin,
789 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
790 {
791 *widthPtr = *heightPtr = 1;
2546 void *clientData,
2547 void *elementRecord,
2548 Tk_Window tkwin,
2549 int *minWidth,
2550 int *minHeight,
2551 Ttk_Padding *paddingPtr)
2552 {
2553 *minWidth = *minHeight = 1;
7922554 }
7932555
7942556 static void SeparatorElementDraw(
795 void *clientData, void *elementRecord, Tk_Window tkwin,
796 Drawable d, Ttk_Box b, unsigned int state)
2557 void *clientData,
2558 void *elementRecord,
2559 Tk_Window tkwin,
2560 Drawable d,
2561 Ttk_Box b,
2562 unsigned int state)
7972563 {
7982564 CGRect bounds = BoxToRect(d, b);
7992565 const HIThemeSeparatorDrawInfo info = {
8002566 .version = 0,
801 /* Separator only supports kThemeStateActive, kThemeStateInactive */
802 .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND),
2567 /* Separator only supports kThemeStateActive, kThemeStateInactive */
2568 .state = Ttk_StateTableLookup(ThemeStateTable,
2569 state & TTK_STATE_BACKGROUND),
8032570 };
8042571
8052572 BEGIN_DRAWING(d)
806 ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation);
2573 if (TkMacOSXInDarkMode(tkwin)) {
2574 DrawDarkSeparator(bounds, dc.context, tkwin);
2575 } else {
2576 ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context,
2577 HIOrientation);
2578 }
8072579 END_DRAWING
8082580 }
8092581
8162588 };
8172589
8182590 /*----------------------------------------------------------------------
819 * +++ Size grip element.
820 */
2591 * +++ Size grip elements -- (obsolete)
2592 */
2593
8212594 static const ThemeGrowDirection sizegripGrowDirection
822 = kThemeGrowRight|kThemeGrowDown;
2595 = kThemeGrowRight | kThemeGrowDown;
8232596
8242597 static void SizegripElementSize(
825 void *clientData, void *elementRecord, Tk_Window tkwin,
826 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
2598 void *clientData,
2599 void *elementRecord,
2600 Tk_Window tkwin,
2601 int *minWidth,
2602 int *minHeight,
2603 Ttk_Padding *paddingPtr)
8272604 {
8282605 HIThemeGrowBoxDrawInfo info = {
8292606 .version = 0,
8352612 CGRect bounds = CGRectZero;
8362613
8372614 ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds);
838 *widthPtr = bounds.size.width;
839 *heightPtr = bounds.size.height;
2615 *minWidth = bounds.size.width;
2616 *minHeight = bounds.size.height;
8402617 }
8412618
8422619 static void SizegripElementDraw(
843 void *clientData, void *elementRecord, Tk_Window tkwin,
844 Drawable d, Ttk_Box b, unsigned int state)
2620 void *clientData,
2621 void *elementRecord,
2622 Tk_Window tkwin,
2623 Drawable d,
2624 Ttk_Box b,
2625 unsigned int state)
8452626 {
8462627 CGRect bounds = BoxToRect(d, b);
8472628 HIThemeGrowBoxDrawInfo info = {
8482629 .version = 0,
849 /* Grow box only supports kThemeStateActive, kThemeStateInactive */
850 .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND),
2630 /* Grow box only supports kThemeStateActive, kThemeStateInactive */
2631 .state = Ttk_StateTableLookup(ThemeStateTable,
2632 state & TTK_STATE_BACKGROUND),
8512633 .kind = kHIThemeGrowBoxKindNormal,
8522634 .direction = sizegripGrowDirection,
8532635 .size = kHIThemeGrowBoxSizeNormal,
8542636 };
8552637
8562638 BEGIN_DRAWING(d)
857 ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, HIOrientation);
2639 ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context,
2640 HIOrientation);
8582641 END_DRAWING
8592642 }
8602643
8672650 };
8682651
8692652 /*----------------------------------------------------------------------
870 * +++ Background and fill elements.
871 *
872 * This isn't quite right: In Aqua, the correct background for
873 * a control depends on what kind of container it belongs to,
874 * and the type of the top-level window.
875 *
876 * Also: patterned backgrounds should be aligned with the coordinate
877 * system of the top-level window. If we're drawing into an
878 * off-screen graphics port this leads to alignment glitches.
2653 * +++ Background and fill elements --
2654 *
2655 * Before drawing any ttk widget, its bounding rectangle is filled with a
2656 * background color. This color must match the background color of the
2657 * containing widget to avoid looking ugly. The need for care when doing
2658 * this is exacerbated by the fact that ttk enforces its "native look" by
2659 * not allowing user control of the background or highlight colors of ttk
2660 * widgets.
2661 *
2662 * This job is made more complicated in recent versions of macOS by the
2663 * fact that the Appkit GroupBox (used for ttk LabelFrames) and
2664 * TabbedPane (used for the Notebook widget) both place their content
2665 * inside a rectangle with rounded corners that has a color which
2666 * contrasts with the dialog background color. Moreover, although the
2667 * Apple human interface guidelines recommend against doing so, there are
2668 * times when one wants to nest these widgets, for example placing a
2669 * GroupBox inside of a TabbedPane. To have the right contrast, each
2670 * level of nesting requires a different color.
2671 *
2672 * Previous Tk releases used the HIThemeDrawGroupBox routine to draw
2673 * GroupBoxes and TabbedPanes. This meant that the best that could be
2674 * done was to set the GroupBox to be of kind
2675 * kHIThemeGroupBoxKindPrimaryOpaque, and set its fill color to be the
2676 * system background color. If widgets inside the box were drawn with
2677 * the system background color the backgrounds would match. But this
2678 * produces a GroupBox with no contrast, the only visual clue being a
2679 * faint highlighting around the top of the GroupBox. Moreover, the
2680 * TabbedPane does not have an Opaque version, so while it is drawn
2681 * inside a contrasting rounded rectangle, the widgets inside the pane
2682 * needed to be enclosed in a frame with the system background
2683 * color. This added a visual artifact since the frame's background color
2684 * does not match the Pane's background color. That code has now been
2685 * replaced with the standalone drawing procedure macOSXDrawGroupBox,
2686 * which draws a rounded rectangle with an appropriate contrasting
2687 * background color.
2688 *
2689 * Patterned backgrounds, which are now obsolete, should be aligned with
2690 * the coordinate system of the top-level window. Apparently failing to
2691 * do this used to cause graphics anomalies when drawing into an
2692 * off-screen graphics port. The code for handling this is currently
2693 * commented out.
8792694 */
8802695
8812696 static void FillElementDraw(
882 void *clientData, void *elementRecord, Tk_Window tkwin,
883 Drawable d, Ttk_Box b, Ttk_State state)
2697 void *clientData,
2698 void *elementRecord,
2699 Tk_Window tkwin,
2700 Drawable d,
2701 Ttk_Box b,
2702 Ttk_State state)
8842703 {
8852704 CGRect bounds = BoxToRect(d, b);
886 ThemeBrush brush = (state & TTK_STATE_BACKGROUND)
2705
2706 if ([NSApp macMinorVersion] > 8) {
2707 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
2708 NSColor *bgColor;
2709 CGFloat fill[4];
2710 BEGIN_DRAWING(d)
2711 GetBackgroundColor(dc.context, tkwin, 0, fill);
2712 bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill
2713 count: 4];
2714 CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace);
2715 CGContextSetFillColorWithColor(dc.context, CGCOLOR(bgColor));
2716 CGContextFillRect(dc.context, bounds);
2717 END_DRAWING
2718 } else {
2719 ThemeBrush brush = (state & TTK_STATE_BACKGROUND)
8872720 ? kThemeBrushModelessDialogBackgroundInactive
8882721 : kThemeBrushModelessDialogBackgroundActive;
889
890 BEGIN_DRAWING(d)
891 ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation);
892 //QDSetPatternOrigin(PatternOrigin(tkwin, d));
893 CGContextFillRect(dc.context, bounds);
894 END_DRAWING
2722 BEGIN_DRAWING(d)
2723 ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation);
2724 //QDSetPatternOrigin(PatternOrigin(tkwin, d));
2725 CGContextFillRect(dc.context, bounds);
2726 END_DRAWING
2727 }
8952728 }
8962729
8972730 static void BackgroundElementDraw(
898 void *clientData, void *elementRecord, Tk_Window tkwin,
899 Drawable d, Ttk_Box b, unsigned int state)
900 {
901 FillElementDraw(
902 clientData, elementRecord, tkwin,
903 d, Ttk_WinBox(tkwin), state);
2731 void *clientData,
2732 void *elementRecord,
2733 Tk_Window tkwin,
2734 Drawable d,
2735 Ttk_Box b,
2736 unsigned int state)
2737 {
2738 FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin),
2739 state);
9042740 }
9052741
9062742 static Ttk_ElementSpec FillElementSpec = {
9102746 TtkNullElementSize,
9112747 FillElementDraw
9122748 };
913
9142749 static Ttk_ElementSpec BackgroundElementSpec = {
9152750 TK_STYLE_VERSION_2,
9162751 sizeof(NullElement),
9222757 /*----------------------------------------------------------------------
9232758 * +++ ToolbarBackground element -- toolbar style for frames.
9242759 *
925 * This is very similar to the normal background element, but uses a
926 * different ThemeBrush in order to get the lighter pinstripe effect
927 * used in toolbars. We use SetThemeBackground() rather than
928 * ApplyThemeBackground() in order to get the right style.
929 *
930 * <URL: http://developer.apple.com/documentation/Carbon/Reference/
931 * Appearance_Manager/appearance_manager/constant_7.html#/
932 * /apple_ref/doc/uid/TP30000243/C005321>
933 *
934 */
2760 * This is very similar to the normal background element, but uses a
2761 * different ThemeBrush in order to get the lighter pinstripe effect
2762 * used in toolbars. We use SetThemeBackground() rather than
2763 * ApplyThemeBackground() in order to get the right style.
2764 *
2765 * <URL: http://developer.apple.com/documentation/Carbon/Reference/
2766 * Appearance_Manager/appearance_manager/constant_7.html#/
2767 * /apple_ref/doc/uid/TP30000243/C005321>
2768 *
2769 */
2770
9352771 static void ToolbarBackgroundElementDraw(
936 void *clientData, void *elementRecord, Tk_Window tkwin,
937 Drawable d, Ttk_Box b, Ttk_State state)
2772 void *clientData,
2773 void *elementRecord,
2774 Tk_Window tkwin,
2775 Drawable d,
2776 Ttk_Box b,
2777 Ttk_State state)
9382778 {
9392779 ThemeBrush brush = kThemeBrushToolbarBackground;
9402780 CGRect bounds = BoxToRect(d, Ttk_WinBox(tkwin));
9552795 };
9562796
9572797 /*----------------------------------------------------------------------
958 * +++ Treeview header
959 * Redefine the header to use a kThemeListHeaderButton.
960 */
961
962 #define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1
2798 * +++ Field elements --
2799 *
2800 * Used for the Treeview widget. This is like the BackgroundElement
2801 * except that the fieldbackground color is configureable.
2802 */
2803
2804 typedef struct {
2805 Tcl_Obj *backgroundObj;
2806 } FieldElement;
2807
2808 static Ttk_ElementOptionSpec FieldElementOptions[] = {
2809 {"-fieldbackground", TK_OPTION_BORDER,
2810 Tk_Offset(FieldElement, backgroundObj), "white"},
2811 {NULL, 0, 0, NULL}
2812 };
2813
2814 static void FieldElementDraw(
2815 void *clientData,
2816 void *elementRecord,
2817 Tk_Window tkwin,
2818 Drawable d,
2819 Ttk_Box b,
2820 Ttk_State state)
2821 {
2822 FieldElement *e = elementRecord;
2823 Tk_3DBorder backgroundPtr =
2824 Tk_Get3DBorderFromObj(tkwin, e->backgroundObj);
2825
2826 XFillRectangle(Tk_Display(tkwin), d,
2827 Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC),
2828 b.x, b.y, b.width, b.height);
2829 }
2830
2831 static Ttk_ElementSpec FieldElementSpec = {
2832 TK_STYLE_VERSION_2,
2833 sizeof(FieldElement),
2834 FieldElementOptions,
2835 TtkNullElementSize,
2836 FieldElementDraw
2837 };
2838
2839 /*----------------------------------------------------------------------
2840 * +++ Treeview headers --
2841 *
2842 * On systems older than 10.9 The header is a kThemeListHeaderButton drawn
2843 * by HIToolbox. On newer systems those buttons do not match the Apple
2844 * buttons, so we draw them from scratch.
2845 */
2846
9632847 static Ttk_StateTable TreeHeaderValueTable[] = {
964 { kThemeButtonOn, TTK_STATE_ALTERNATE},
965 { kThemeButtonOn, TTK_STATE_SELECTED},
966 { kThemeButtonOff, 0}
967 };
2848 {kThemeButtonOn, TTK_STATE_ALTERNATE},
2849 {kThemeButtonOn, TTK_STATE_SELECTED},
2850 {kThemeButtonOff, 0}
2851 };
2852
9682853 static Ttk_StateTable TreeHeaderAdornmentTable[] = {
969 { kThemeAdornmentHeaderButtonSortUp,
970 TTK_STATE_ALTERNATE|TTK_TREEVIEW_STATE_SORTARROW},
971 { kThemeAdornmentDefault,
972 TTK_STATE_SELECTED|TTK_TREEVIEW_STATE_SORTARROW},
973 { kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE},
974 { kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED},
975 { kThemeAdornmentFocus, TTK_STATE_FOCUS},
976 { kThemeAdornmentNone, 0}
977 };
2854 {kThemeAdornmentHeaderButtonSortUp,
2855 TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW},
2856 {kThemeAdornmentDefault,
2857 TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW},
2858 {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE},
2859 {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED},
2860 {kThemeAdornmentFocus, TTK_STATE_FOCUS},
2861 {kThemeAdornmentNone, 0}
2862 };
2863
2864 static void TreeAreaElementSize (
2865 void *clientData,
2866 void *elementRecord,
2867 Tk_Window tkwin,
2868 int *minWidth,
2869 int *minHeight,
2870 Ttk_Padding *paddingPtr)
2871 {
2872
2873 /*
2874 * Padding is needed to get the heading text to align correctly, since the
2875 * widget expects the heading to be the same height as a row.
2876 */
2877
2878 if ([NSApp macMinorVersion] > 8) {
2879 paddingPtr->top = 4;
2880 }
2881 }
2882
2883 static Ttk_ElementSpec TreeAreaElementSpec = {
2884 TK_STYLE_VERSION_2,
2885 sizeof(NullElement),
2886 TtkNullElementOptions,
2887 TreeAreaElementSize,
2888 TtkNullElementDraw
2889 };
2890 static void TreeHeaderElementSize(
2891 void *clientData,
2892 void *elementRecord,
2893 Tk_Window tkwin,
2894 int *minWidth,
2895 int *minHeight,
2896 Ttk_Padding *paddingPtr)
2897 {
2898 if ([NSApp macMinorVersion] > 8) {
2899 *minHeight = 24;
2900 } else {
2901 ButtonElementSize(clientData, elementRecord, tkwin, minWidth,
2902 minHeight, paddingPtr);
2903 }
2904 }
9782905
9792906 static void TreeHeaderElementDraw(
980 void *clientData, void *elementRecord, Tk_Window tkwin,
981 Drawable d, Ttk_Box b, Ttk_State state)
2907 void *clientData,
2908 void *elementRecord,
2909 Tk_Window tkwin,
2910 Drawable d,
2911 Ttk_Box b,
2912 Ttk_State state)
9822913 {
9832914 ThemeButtonParams *params = clientData;
9842915 CGRect bounds = BoxToRect(d, b);
9912922 };
9922923
9932924 BEGIN_DRAWING(d)
994 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
2925 if ([NSApp macMinorVersion] > 8) {
2926
2927 /*
2928 * Compensate for the padding added in TreeHeaderElementSize, so
2929 * the larger heading will be drawn at the top of the widget.
2930 */
2931
2932 bounds.origin.y -= 4;
2933 if (TkMacOSXInDarkMode(tkwin)) {
2934 DrawDarkListHeader(bounds, dc.context, tkwin, state);
2935 } else {
2936 DrawListHeader(bounds, dc.context, tkwin, state);
2937 }
2938 } else {
2939 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
2940 NULL);
2941 }
9952942 END_DRAWING
9962943 }
9972944
9992946 TK_STYLE_VERSION_2,
10002947 sizeof(NullElement),
10012948 TtkNullElementOptions,
1002 ButtonElementSizeNoPadding,
2949 TreeHeaderElementSize,
10032950 TreeHeaderElementDraw
10042951 };
10052952
1006 /*
1007 * Disclosure triangle:
1008 */
1009 #define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1
1010 #define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2
2953 /*----------------------------------------------------------------------
2954 * +++ Disclosure triangles --
2955 */
2956
2957 #define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1
2958 #define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2
10112959 static Ttk_StateTable DisclosureValueTable[] = {
1012 { kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0 },
1013 { kThemeDisclosureRight, 0, 0 },
1014 };
1015
2960 {kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0},
2961 {kThemeDisclosureRight, 0, 0},
2962 };
10162963 static void DisclosureElementSize(
1017 void *clientData, void *elementRecord, Tk_Window tkwin,
1018 int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
2964 void *clientData,
2965 void *elementRecord,
2966 Tk_Window tkwin,
2967 int *minWidth,
2968 int *minHeight,
2969 Ttk_Padding *paddingPtr)
10192970 {
10202971 SInt32 s;
10212972
10222973 ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s);
1023 *widthPtr = s;
2974 *minWidth = s;
10242975 ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s);
1025 *heightPtr = s;
2976 *minHeight = s;
10262977 }
10272978
10282979 static void DisclosureElementDraw(
1029 void *clientData, void *elementRecord, Tk_Window tkwin,
1030 Drawable d, Ttk_Box b, Ttk_State state)
2980 void *clientData,
2981 void *elementRecord,
2982 Tk_Window tkwin,
2983 Drawable d,
2984 Ttk_Box b,
2985 Ttk_State state)
10312986 {
10322987 if (!(state & TTK_TREEVIEW_STATE_LEAF)) {
2988 int triangleState = TkMacOSXInDarkMode(tkwin) ?
2989 kThemeStateInactive : kThemeStateActive;
10332990 CGRect bounds = BoxToRect(d, b);
10342991 const HIThemeButtonDrawInfo info = {
10352992 .version = 0,
1036 .state = Ttk_StateTableLookup(ThemeStateTable, state),
2993 .state = triangleState,
10372994 .kind = kThemeDisclosureTriangle,
10382995 .value = Ttk_StateTableLookup(DisclosureValueTable, state),
10392996 .adornment = kThemeAdornmentDrawIndicatorOnly,
10402997 };
10412998
10422999 BEGIN_DRAWING(d)
1043 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
3000 ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
3001 NULL);
10443002 END_DRAWING
10453003 }
10463004 }
10543012 };
10553013
10563014 /*----------------------------------------------------------------------
1057 * +++ Widget layouts.
3015 * +++ Widget layouts --
10583016 */
10593017
10603018 TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
10643022
10653023 TTK_LAYOUT("TButton",
10663024 TTK_GROUP("Button.button", TTK_FILL_BOTH,
1067 TTK_GROUP("Button.padding", TTK_FILL_BOTH,
1068 TTK_NODE("Button.label", TTK_FILL_BOTH))))
3025 TTK_GROUP("Button.padding", TTK_FILL_BOTH,
3026 TTK_NODE("Button.label", TTK_FILL_BOTH))))
10693027
10703028 TTK_LAYOUT("TRadiobutton",
10713029 TTK_GROUP("Radiobutton.button", TTK_FILL_BOTH,
1072 TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH,
1073 TTK_NODE("Radiobutton.label", TTK_PACK_LEFT))))
3030 TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH,
3031 TTK_NODE("Radiobutton.label", TTK_PACK_LEFT))))
10743032
10753033 TTK_LAYOUT("TCheckbutton",
10763034 TTK_GROUP("Checkbutton.button", TTK_FILL_BOTH,
1077 TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH,
1078 TTK_NODE("Checkbutton.label", TTK_PACK_LEFT))))
3035 TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH,
3036 TTK_NODE("Checkbutton.label", TTK_PACK_LEFT))))
10793037
10803038 TTK_LAYOUT("TMenubutton",
10813039 TTK_GROUP("Menubutton.button", TTK_FILL_BOTH,
1082 TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH,
1083 TTK_NODE("Menubutton.label", TTK_PACK_LEFT))))
3040 TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH,
3041 TTK_NODE("Menubutton.label", TTK_PACK_LEFT))))
10843042
10853043 TTK_LAYOUT("TCombobox",
1086 TTK_GROUP("Combobox.button", TTK_PACK_TOP|TTK_FILL_X,
1087 TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
1088 TTK_NODE("Combobox.textarea", TTK_FILL_X))))
3044 TTK_GROUP("Combobox.button", TTK_FILL_BOTH,
3045 TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
3046 TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))
10893047
10903048 /* Notebook tabs -- no focus ring */
10913049 TTK_LAYOUT("Tab",
10923050 TTK_GROUP("Notebook.tab", TTK_FILL_BOTH,
1093 TTK_GROUP("Notebook.padding", TTK_EXPAND|TTK_FILL_BOTH,
1094 TTK_NODE("Notebook.label", TTK_EXPAND|TTK_FILL_BOTH))))
3051 TTK_GROUP("Notebook.padding", TTK_EXPAND | TTK_FILL_BOTH,
3052 TTK_NODE("Notebook.label", TTK_EXPAND | TTK_FILL_BOTH))))
3053
3054 /* Spinbox -- buttons 2px to the right of the field. */
3055 TTK_LAYOUT("TSpinbox",
3056 TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT,
3057 TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP | TTK_STICK_E)
3058 TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM | TTK_STICK_E))
3059 TTK_GROUP("Spinbox.field", TTK_EXPAND | TTK_FILL_X,
3060 TTK_NODE("Spinbox.textarea", TTK_EXPAND | TTK_FILL_X)))
10953061
10963062 /* Progress bars -- track only */
1097 TTK_LAYOUT("TSpinbox",
1098 TTK_NODE("Spinbox.spinbutton", TTK_PACK_RIGHT|TTK_STICK_E)
1099 TTK_GROUP("Spinbox.field", TTK_EXPAND|TTK_FILL_X,
1100 TTK_NODE("Spinbox.textarea", TTK_EXPAND|TTK_FILL_X)))
1101
11023063 TTK_LAYOUT("TProgressbar",
1103 TTK_NODE("Progressbar.track", TTK_EXPAND|TTK_FILL_BOTH))
3064 TTK_NODE("Progressbar.track", TTK_EXPAND | TTK_FILL_BOTH))
3065
3066 /* Treeview -- no border. */
3067 TTK_LAYOUT("Treeview",
3068 TTK_GROUP("Treeview.field", TTK_FILL_BOTH,
3069 TTK_GROUP("Treeview.padding", TTK_FILL_BOTH,
3070 TTK_NODE("Treeview.treearea", TTK_FILL_BOTH))))
11043071
11053072 /* Tree heading -- no border, fixed height */
11063073 TTK_LAYOUT("Heading",
1107 TTK_NODE("Treeheading.cell", TTK_FILL_X)
3074 TTK_NODE("Treeheading.cell", TTK_FILL_BOTH)
11083075 TTK_NODE("Treeheading.image", TTK_PACK_RIGHT)
1109 TTK_NODE("Treeheading.text", 0))
3076 TTK_NODE("Treeheading.text", TTK_PACK_TOP))
11103077
11113078 /* Tree items -- omit focus ring */
11123079 TTK_LAYOUT("Item",
11133080 TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH,
1114 TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT)
1115 TTK_NODE("Treeitem.image", TTK_PACK_LEFT)
1116 TTK_NODE("Treeitem.text", TTK_PACK_LEFT)))
3081 TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT)
3082 TTK_NODE("Treeitem.image", TTK_PACK_LEFT)
3083 TTK_NODE("Treeitem.text", TTK_PACK_LEFT)))
3084
3085 /* Scrollbar Layout -- Buttons at the bottom (Snow Leopard and Lion only) */
3086
3087 TTK_LAYOUT("Vertical.TScrollbar",
3088 TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y,
3089 TTK_NODE("Vertical.Scrollbar.thumb",
3090 TTK_PACK_TOP | TTK_EXPAND | TTK_FILL_BOTH)
3091 TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM)
3092 TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM)))
3093
3094 TTK_LAYOUT("Horizontal.TScrollbar",
3095 TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X,
3096 TTK_NODE("Horizontal.Scrollbar.thumb",
3097 TTK_PACK_LEFT | TTK_EXPAND | TTK_FILL_BOTH)
3098 TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT)
3099 TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT)))
11173100
11183101 TTK_END_LAYOUT_TABLE
11193102
11203103 /*----------------------------------------------------------------------
1121 * +++ Initialization.
1122 */
1123
1124 static int AquaTheme_Init(Tcl_Interp *interp)
3104 * +++ Initialization --
3105 */
3106
3107 static int AquaTheme_Init(
3108 Tcl_Interp *interp)
11253109 {
11263110 Ttk_Theme themePtr = Ttk_CreateTheme(interp, "aqua", NULL);
11273111
11323116 /*
11333117 * Elements:
11343118 */
1135 Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, 0);
3119
3120 Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec,
3121 0);
11363122 Ttk_RegisterElementSpec(themePtr, "fill", &FillElementSpec, 0);
3123 Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, 0);
11373124 Ttk_RegisterElementSpec(themePtr, "Toolbar.background",
11383125 &ToolbarBackgroundElementSpec, 0);
11393126
11473134 &ButtonElementSpec, &BevelButtonParams);
11483135 Ttk_RegisterElementSpec(themePtr, "Menubutton.button",
11493136 &ButtonElementSpec, &PopupButtonParams);
1150 Ttk_RegisterElementSpec(themePtr, "Spinbox.spinbutton",
1151 &SpinButtonElementSpec, 0);
3137 Ttk_RegisterElementSpec(themePtr, "Spinbox.uparrow",
3138 &SpinButtonUpElementSpec, 0);
3139 Ttk_RegisterElementSpec(themePtr, "Spinbox.downarrow",
3140 &SpinButtonDownElementSpec, 0);
11523141 Ttk_RegisterElementSpec(themePtr, "Combobox.button",
11533142 &ComboboxElementSpec, 0);
11543143 Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator",
11563145 Ttk_RegisterElementSpec(themePtr, "Treeheading.cell",
11573146 &TreeHeaderElementSpec, &ListHeaderParams);
11583147
3148 Ttk_RegisterElementSpec(themePtr, "Treeview.treearea",
3149 &TreeAreaElementSpec, 0);
11593150 Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0);
11603151 Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0);
11613152
1162 Ttk_RegisterElementSpec(themePtr, "Labelframe.border",&GroupElementSpec,0);
1163 Ttk_RegisterElementSpec(themePtr, "Entry.field",&EntryElementSpec,0);
1164 Ttk_RegisterElementSpec(themePtr, "Spinbox.field",&EntryElementSpec,0);
1165
1166 Ttk_RegisterElementSpec(themePtr, "separator",&SeparatorElementSpec,0);
1167 Ttk_RegisterElementSpec(themePtr, "hseparator",&SeparatorElementSpec,0);
1168 Ttk_RegisterElementSpec(themePtr, "vseparator",&SeparatorElementSpec,0);
1169
1170 Ttk_RegisterElementSpec(themePtr, "sizegrip",&SizegripElementSpec,0);
3153 Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec,
3154 0);
3155 Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec, 0);
3156 Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec, 0);
3157
3158 Ttk_RegisterElementSpec(themePtr, "separator", &SeparatorElementSpec, 0);
3159 Ttk_RegisterElementSpec(themePtr, "hseparator", &SeparatorElementSpec, 0);
3160 Ttk_RegisterElementSpec(themePtr, "vseparator", &SeparatorElementSpec, 0);
3161
3162 Ttk_RegisterElementSpec(themePtr, "sizegrip", &SizegripElementSpec, 0);
11713163
11723164 /*
11733165 * <<NOTE-TRACKS>>
1174 * The Progressbar widget adjusts the size of the pbar element.
1175 * In the Aqua theme, the appearance manager computes the bar geometry;
1176 * we do all the drawing in the ".track" element and leave the .pbar out.
3166 * In some themes the Layouts for a progress bar has a trough element and a
3167 * pbar element. But in our case the appearance manager draws both parts
3168 * of the progress bar, so we just have a single element called ".track".
11773169 */
1178 Ttk_RegisterElementSpec(themePtr,"Scale.trough",
1179 &TrackElementSpec, &ScaleData);
1180 Ttk_RegisterElementSpec(themePtr,"Scale.slider",&SliderElementSpec,0);
1181 Ttk_RegisterElementSpec(themePtr,"Progressbar.track", &PbarElementSpec, 0);
3170
3171 Ttk_RegisterElementSpec(themePtr, "Progressbar.track", &PbarElementSpec,
3172 0);
3173
3174 Ttk_RegisterElementSpec(themePtr, "Scale.trough", &TrackElementSpec,
3175 &ScaleData);
3176 Ttk_RegisterElementSpec(themePtr, "Scale.slider", &SliderElementSpec, 0);
3177
3178 Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.trough",
3179 &TroughElementSpec, 0);
3180 Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.thumb",
3181 &ThumbElementSpec, 0);
3182 Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.trough",
3183 &TroughElementSpec, 0);
3184 Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.thumb",
3185 &ThumbElementSpec, 0);
3186
3187 /*
3188 * If we are not in Snow Leopard or Lion the arrows won't actually be
3189 * displayed.
3190 */
3191
3192 Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.uparrow",
3193 &ArrowElementSpec, 0);
3194 Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.downarrow",
3195 &ArrowElementSpec, 0);
3196 Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.leftarrow",
3197 &ArrowElementSpec, 0);
3198 Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.rightarrow",
3199 &ArrowElementSpec, 0);
11823200
11833201 /*
11843202 * Layouts:
11853203 */
3204
11863205 Ttk_RegisterLayouts(themePtr, LayoutTable);
11873206
11883207 Tcl_PkgProvide(interp, "ttk::theme::aqua", TTK_VERSION);
11903209 }
11913210
11923211 MODULE_SCOPE
1193 int Ttk_MacOSXPlatformInit(Tcl_Interp *interp)
3212 int Ttk_MacOSXPlatformInit(
3213 Tcl_Interp *interp)
11943214 {
11953215 return AquaTheme_Init(interp);
11963216 }
1197
3217
11983218 /*
11993219 * Local Variables:
12003220 * mode: objc
12033223 * coding: utf-8
12043224 * End:
12053225 */
1206
9898 }
9999
100100 bind .t.c <Shift-B1-Motion> {
101 .t.c move circle [expr %x-$curx] [expr %y-$cury]
101 .t.c move circle [expr {%x-$curx}] [expr {%y-$cury}]
102102 set curx %x
103103 set cury %y
104104 }
126126 }
127127 incr i $delta
128128 c -start $i
129 c -extent [expr 360-2*$i]
129 c -extent [expr {360-2*$i}]
130130 after 20
131131 update
132132 }
2121 bind Test $event {}
2222 }
2323 foreach event [bind all] {
24 bind all $event {}
24 bind all $event {}
2525 }
2626
2727 proc unsetBindings {} {
3131 bind xyz <Enter> {}
3232 bind {a b} <Enter> {}
3333 bind .t <Enter> {}
34 }
35
36 # This function fills the pattern matcher's ring buffer with events of
37 # the specified type. This can be used when testing with generated
38 # events to make sure that there are no stray events in the ring
39 # buffer which might cause the pattern matcher to find unintended
40 # matches. The size of the ring buffer is EVENT_BUFFER_SIZE, which is
41 # currently set to 30 (or 45 on macOS). If this changes, the code
42 # below will need to change.
43 proc clearRingBuffer {{event}} {
44 for {set i 0} {$i < 45} {incr i} {
45 event generate . $event
46 }
4734 }
4835
4936 # move the mouse pointer away of the testing area
8976 } -result {test script
9077 more text}
9178 test bind-1.8 {bind command} -body {
92 bind .t <gorp-> {test script}
79 bind .t <gorp-> {test script}
9380 } -returnCodes error -result {bad event type or keysym "gorp"}
9481 test bind-1.9 {bind command} -body {
95 catch {bind .t <gorp-> {test script}}
82 catch {bind .t <gorp-> {test script}}
9683 bind .t
9784 } -result {}
9885 test bind-1.10 {bind command} -body {
153140 test bind-2.9 {bindtags command} -body {
154141 frame .t.f
155142 bindtags .t.f {a b c}
156 bindtags .t.f "\{"
157 } -cleanup {
158 destroy .t.f
159 } -returnCodes error -result {unmatched open brace in list}
143 bindtags .t.f "\{"
144 } -cleanup {
145 destroy .t.f
146 } -returnCodes error -result {unmatched open brace in list}
160147 test bind-2.10 {bindtags command} -body {
161148 frame .t.f
162149 bindtags .t.f {a b c}
168155 test bind-2.11 {bindtags command} -body {
169156 frame .t.f
170157 bindtags .t.f {a b c}
171 bindtags .t.f "a .gorp b"
172 } -cleanup {
173 destroy .t.f
174 } -returnCodes ok
158 bindtags .t.f "a .gorp b"
159 } -cleanup {
160 destroy .t.f
161 } -returnCodes ok
175162 test bind-2.12 {bindtags command} -body {
176163 frame .t.f
177164 bindtags .t.f {a b c}
211198 bind {a b} <Enter> {lappend x "%W enter {a b}"}
212199 bind .t <Enter> {lappend x "%W enter .t"}
213200 bind .t.f <Enter> {lappend x "%W enter .t.f"}
214
201
215202 event generate .t.f <Enter>
216203 return $x
217204 } -cleanup {
231218 bind {a b} <Enter> {lappend x "%W enter {a b}"}
232219 bind .t <Enter> {lappend x "%W enter .t"}
233220 bind .t.f <Enter> {lappend x "%W enter .t.f"}
234
221
235222 bindtags .t.f {.t.f {a b} xyz}
236 event generate .t.f <Enter>
223 event generate .t.f <Enter>
237224 return $x
238225 } -cleanup {
239226 destroy .t.f
247234 bind xyz <Enter> {lappend x "%W enter xyz"}
248235 bind {a b} <Enter> {lappend x "%W enter {a b}"}
249236 bind .t <Enter> {lappend x "%W enter .t"}
250
237
251238 event generate .t <Enter>
252239 return $x
253240 } -cleanup {
267254 bind xyz <Enter> {lappend x "%W enter xyz"}
268255 bind {a b} <Enter> {lappend x "%W enter {a b}"}
269256 bind .t <Enter> {lappend x "%W enter .t"}
270
257
271258 bindtags .t.f {.t.f .t.f2 .t.f3}
272259 bind .t.f <Enter> {lappend x "%W enter .t.f"}
273260 bind .t.f3 <Enter> {lappend x "%W enter .t.f3"}
291278 bind {a b} <Enter> {lappend x "%W enter {a b}"}
292279 bind .t <Enter> {lappend x "%W enter .t"}
293280 bindtags .t.f {a b c d e f g h i j k l m n o p q r s t u v w x y z}
294
281
295282 event generate .t.f <Enter>
296283 } -cleanup {
297284 destroy .t.f
354341 } -body {
355342 frame .t.f -class Test -width 150 -height 100
356343 foreach i {a b c d} {
357 bind .t.f $i "binding for $i"
344 bind .t.f $i "binding for $i"
358345 }
359346 foreach i {b d a c} {
360 bind .t.f $i {}
361 lappend result [lsort [bind .t.f]]
347 bind .t.f $i {}
348 lappend result [lsort [bind .t.f]]
362349 }
363350 return $result
364351 } -cleanup {
369356 } -body {
370357 frame .t.f -class Test -width 150 -height 100
371358 foreach i {<1> <Meta-1> <Control-1> <Double-Alt-1>} {
372 bind .t.f $i "binding for $i"
359 bind .t.f $i "binding for $i"
373360 }
374361 foreach i {<Control-1> <Double-Alt-1> <1> <Meta-1>} {
375 bind .t.f $i {}
376 lappend result [lsort [bind .t.f]]
362 bind .t.f $i {}
363 lappend result [lsort [bind .t.f]]
377364 }
378365 return $result
379366 } -cleanup {
395382 } -result {Test}
396383
397384 test bind-11.1 {Tk_GetAllBindings procedure} -body {
398 frame .t.f
385 frame .t.f
399386 foreach i "! a \\\{ ~ <Delete> <space> <<Paste>> <Tab> <Linefeed> <less> <Meta-a> <Acircumflex>" {
400 bind .t.f $i Test
387 bind .t.f $i Test
401388 }
402389 lsort [bind .t.f]
403390 } -cleanup {
404391 destroy .t.f
405392 } -result {! <<Paste>> <Key-Acircumflex> <Key-Delete> <Key-Linefeed> <Key-Tab> <Key-less> <Key-space> <Meta-Key-a> a \{ ~}
406393 test bind-11.2 {Tk_GetAllBindings procedure} -body {
407 frame .t.f
394 frame .t.f
408395 foreach i "<Double-1> <Triple-1> <Meta-Control-a> <Double-Alt-Enter> <1>" {
409 bind .t.f $i Test
396 bind .t.f $i Test
410397 }
411398 lsort [bind .t.f]
412399 } -cleanup {
413400 destroy .t.f
414401 } -result {<Button-1> <Control-Meta-Key-a> <Double-Alt-Enter> <Double-Button-1> <Triple-Button-1>}
415402 test bind-11.3 {Tk_GetAllBindings procedure} -body {
416 frame .t.f
403 frame .t.f
417404 foreach i "<Double-Triple-1> abcd a<Leave>b" {
418 bind .t.f $i Test
405 bind .t.f $i Test
419406 }
420407 lsort [bind .t.f]
421408 } -cleanup {
430417 test bind-12.2 {Tk_DeleteAllBindings procedure} -body {
431418 frame .t.f -class Test -width 150 -height 100
432419 foreach i "a b c <Meta-1> <Alt-a> <Control-a>" {
433 bind .t.f $i x
420 bind .t.f $i x
434421 }
435422 destroy .t.f
436423 } -result {}
447434 bind Test : {lappend x "%W %K Test :"}
448435 bind all _ {lappend x "%W %K all _"}
449436 bind .t.f : {lappend x "%W %K .t.f :"}
450
437
451438 event generate .t.f <Key-colon>
452439 event generate .t.f <Key-plus>
453440 event generate .t.f <Key-underscore>
470457 bind Test <KeyPress> {lappend x "%W %K Test press any"; break}
471458 bind all <KeyPress> {continue; lappend x "%W %K all press any"}
472459 bind .t.f : {lappend x "%W %K .t.f pressed colon"}
473
460
474461 event generate .t.f <Key-colon>
475462 return $x
476463 } -cleanup {
526513 frame .t.g -gorp foo
527514 } -cleanup {
528515 bind all <Destroy> {}
529 } -returnCodes error -result {unknown option "-gorp"}
516 } -returnCodes error -result {unknown option "-gorp"}
530517 test bind-13.6 {Tk_BindEvent procedure} -body {
531518 bind all <Destroy> {lappend x "%W destroyed"}
532519 set x {}
533 catch {frame .t.g -gorp foo}
520 catch {frame .t.g -gorp foo}
534521 return $x
535522 } -cleanup {
536523 bind all <Destroy> {}
611598 set x {}
612599 } -body {
613600 bind .t.f <Motion> "lappend x Motion%#(%x,%y)"
614 event generate .t.f <Motion> -serial 100 -x 100 -y 200 -when tail
601 event generate .t.f <Motion> -serial 100 -x 100 -y 200 -when tail
615602 update
616603 event generate .t.f <Motion> -serial 101 -x 200 -y 300 -when tail
617 event generate .t.f <Motion> -serial 102 -x 300 -y 400 -when tail
604 event generate .t.f <Motion> -serial 102 -x 300 -y 400 -when tail
618605 update
619606 return $x
620607 } -cleanup {
628615 } -body {
629616 bind .t.f <Key> "lappend x %K%#"
630617 bind .t.f <KeyRelease> "lappend x %K%#"
631 event generate .t.f <Key-Shift_L> -serial 100 -when tail
632 event generate .t.f <KeyRelease-Shift_L> -serial 101 -when tail
633 event generate .t.f <Key-Shift_L> -serial 102 -when tail
634 event generate .t.f <KeyRelease-Shift_L> -serial 103 -when tail
618 event generate .t.f <Key-Shift_L> -serial 100 -when tail
619 event generate .t.f <KeyRelease-Shift_L> -serial 101 -when tail
620 event generate .t.f <Key-Shift_L> -serial 102 -when tail
621 event generate .t.f <KeyRelease-Shift_L> -serial 103 -when tail
635622 update
636623 } -cleanup {
637624 destroy .t.f
867854 set x {}
868855 } -body {
869856 bind .t.f <Button-2> {set x Button-2}
870 event generate .t.f <Button-2>
857 event generate .t.f <Button-2>
871858 return $x
872859 } -cleanup {
873860 destroy .t.f
947934 set x {}
948935 } -body {
949936 bindtags .t.f {a b c d e f g h i j k l m n o p}
950 foreach p [bindtags .t.f] {
937 foreach p [bindtags .t.f] {
951938 bind $p <1> "lappend x $p"
952939 }
953940 event generate .t.f <1>
10311018 } -result {b1}
10321019 test bind-13.45 {Tk_BindEvent procedure: error in script} -setup {
10331020 proc bgerror msg {
1034 global x
1021 global x
10351022 lappend x $msg
10361023 }
10371024 frame .t.f -class Test -width 150 -height 100
12201207 } -cleanup {
12211208 destroy .t.f
12221209 } -result {0}
1223 test bind-15.12 {MatchPatterns procedure, ignore modifier presses and releases} -constraints {
1210 test bind-15.12 {MatchPatterns procedure, ignore modifier presses and releases} -constraints {
12241211 nonPortable
12251212 } -setup {
12261213 frame .t.f -class Test -width 150 -height 100
12611248 } -body {
12621249 bind .t.f <Double-1> {set x 1}
12631250 set x 0
1264 event generate .t.f <Button-2>
1251 event generate .t.f <Button-2>
12651252 event generate .t.f <ButtonRelease-2>
12661253 event generate .t.f <Button-1> -x 30 -y 40
12671254 event generate .t.f <Button-1> -x 31 -y 39
12781265 } -body {
12791266 bind .t.f <Double-1> {set x 1}
12801267 set x 0
1281 event generate .t.f <Button-2>
1268 event generate .t.f <Button-2>
12821269 event generate .t.f <ButtonRelease-2>
12831270 event generate .t.f <Button-1> -x 30 -y 40
12841271 event generate .t.f <Button-1> -x 29 -y 41
12951282 } -body {
12961283 bind .t.f <Double-1> {set x 1}
12971284 set x 0
1298 event generate .t.f <Button-2>
1285 event generate .t.f <Button-2>
12991286 event generate .t.f <ButtonRelease-2>
13001287 event generate .t.f <Button-1> -x 30 -y 40
13011288 event generate .t.f <Button-1> -x 40 -y 40
13121299 } -body {
13131300 bind .t.f <Double-1> {set x 1}
13141301 set x 0
1315 event generate .t.f <Button-2>
1302 event generate .t.f <Button-2>
13161303 event generate .t.f <ButtonRelease-2>
13171304 event generate .t.f <Button-1> -x 30 -y 40
13181305 event generate .t.f <Button-1> -x 20 -y 40
13291316 } -body {
13301317 bind .t.f <Double-1> {set x 1}
13311318 set x 0
1332 event generate .t.f <Button-2>
1319 event generate .t.f <Button-2>
13331320 event generate .t.f <ButtonRelease-2>
13341321 event generate .t.f <Button-1> -x 30 -y 40
13351322 event generate .t.f <Button-1> -x 30 -y 30
13461333 } -body {
13471334 bind .t.f <Double-1> {set x 1}
13481335 set x 0
1349 event generate .t.f <Button-2>
1336 event generate .t.f <Button-2>
13501337 event generate .t.f <ButtonRelease-2>
13511338 event generate .t.f <Button-1> -x 30 -y 40
13521339 event generate .t.f <Button-1> -x 30 -y 50
13631350 } -body {
13641351 bind .t.f <Double-1> {set x 1}
13651352 set x 0
1366 event generate .t.f <Button-2>
1353 event generate .t.f <Button-2>
13671354 event generate .t.f <ButtonRelease-2>
13681355 event generate .t.f <Button-1> -time 300
13691356 event generate .t.f <Button-1> -time 700
13801367 } -body {
13811368 bind .t.f <Double-1> {set x 1}
13821369 set x 0
1383 event generate .t.f <Button-2>
1370 event generate .t.f <Button-2>
13841371 event generate .t.f <ButtonRelease-2>
13851372 event generate .t.f <Button-1> -time 300
13861373 event generate .t.f <Button-1> -time 900
13941381 pack .t.f
13951382 focus -force .t.f
13961383 update
1397 clearRingBuffer <Key>
13981384 } -body {
13991385 bind .t.f <Double-1> {set x 1}
14001386 set x 0
14101396 pack .t.f
14111397 focus -force .t.f
14121398 update
1413 clearRingBuffer <Key>
14141399 } -body {
14151400 bind .t.f <Double-1> {set x 1}
14161401 set x 0
14271412 focus -force .t.f
14281413 update
14291414 set x {}
1430 clearRingBuffer <Key>
14311415 } -body {
14321416 event add <<Paste>> <Button-1>
14331417 bind .t.f <<Paste>> {lappend x paste}
14441428 focus -force .t.f
14451429 update
14461430 set x {}
1447 clearRingBuffer <Key>
14481431 } -body {
14491432 event add <<Paste>> <Shift-Button-1>
14501433 bind .t.f <<Paste>> {lappend x paste}
14611444 focus -force .t.f
14621445 update
14631446 set x {}
1464 clearRingBuffer <Key>
14651447 } -body {
14661448 event add <<V1>> <Button>
14671449 event add <<V2>> <Button-1>
14881470 pack .t.f
14891471 focus -force .t.f
14901472 update
1491 clearRingBuffer <Button>
14921473 } -body {
14931474 bind .t.f <KeyPress> {set x 0}
14941475 bind .t.f 1 {set x 1}
15031484 pack .t.f
15041485 focus -force .t.f
15051486 update
1506 clearRingBuffer <Button>
15071487 } -body {
15081488 bind .t.f <KeyPress> {set x 0}
15091489 bind .t.f 1 {set x 1}
15181498 pack .t.f
15191499 focus -force .t.f
15201500 update
1521 clearRingBuffer <Button>
15221501 } -body {
15231502 bind .t.f <KeyPress> {lappend x 0}
15241503 bind .t.f 1 {lappend x 1}
15361515 pack .t.f
15371516 focus -force .t.f
15381517 update
1539 clearRingBuffer <Key>
15401518 } -body {
15411519 bind .t.f <ButtonPress> {set x 0}
15421520 bind .t.f <1> {set x 1}
15531531 focus -force .t.f
15541532 update
15551533 set x {}
1556 clearRingBuffer <Button>
15571534 } -body {
15581535 bind .t.f <M1-Key> {set x 0}
15591536 bind .t.f <M2-Key> {set x 1}
15671544 pack .t.f
15681545 focus -force .t.f
15691546 update
1570 clearRingBuffer <Button>
15711547 } -body {
15721548 bind .t.f <M2-Key> {set x 0}
15731549 bind .t.f <M1-Key> {set x 1}
15831559 focus -force .t.f
15841560 update
15851561 set x {}
1586 clearRingBuffer <Key>
15871562 } -body {
15881563 bind .t.f <1> {lappend x single}
15891564 bind Test <1> {lappend x single(Test)}
20482023 destroy .t.f
20492024 } -result {781 632}
20502025 test bind-16.35 {ExpandPercents procedure} -constraints {
2051 nonPortable
2026 nonPortable
20522027 } -setup {
20532028 frame .t.f -class Test -width 150 -height 100
20542029 pack .t.f
22312206 focus -force .t.e
22322207 foreach p [event info] {event delete $p}
22332208 update
2234 clearRingBuffer <Button>
22352209 } -body {
22362210 bind all <Key> {set z "%M"}
22372211 bind Entry <Key> {set y "%M"}
22742248 event add <<Paste>> <Control-v> <Button-2> abc <xyz> <1>
22752249 } -cleanup {
22762250 event delete <<Paste>>
2277 } -returnCodes error -result {bad event type or keysym "xyz"}
2251 } -returnCodes error -result {bad event type or keysym "xyz"}
22782252 test bind-17.7 {event command: add with error} -body {
22792253 event delete <<Paste>>
22802254 catch {event add <<Paste>> <Control-v> <Button-2> abc <xyz> <1>}
22922266 event delete <<Paste>> <1> <2>
22932267 lsort [event info <<Paste>>]
22942268 } -cleanup {
2269 event delete <<Paste>>
22952270 event delete <<Paste>> <3> t
22962271 } -result {<Button-3> t}
22972272 test bind-17.10 {event command: delete all} -body {
23672342 test bind-18.2 {CreateVirtualEvent procedure: FindSequence} -body {
23682343 event add <<asd>> <Ctrl-v>
23692344 } -returnCodes error -result {bad event type or keysym "Ctrl"}
2370 test bind-18.3 {CreateVirtualEvent procedure: new physical} -body {
2345 test bind-18.3 {CreateVirtualEvent procedure: new physical} -body {
23712346 event delete <<xyz>>
23722347 event add <<xyz>> <Control-v>
23732348 event info <<xyz>>
23762351 } -result {<Control-Key-v>}
23772352 test bind-18.4 {CreateVirtualEvent procedure: duplicate physical} -body {
23782353 event delete <<xyz>>
2379 event add <<xyz>> <Control-v>
2354 event add <<xyz>> <Control-v>
23802355 event add <<xyz>> <Control-v>
23812356 event info <<xyz>>
23822357 } -cleanup {
24472422 foreach p [event info] {event delete $p}
24482423 event add <<xyz>> <Control-v>
24492424 event delete <<xyz>>
2450 event info
2425 event info
24512426 } -result {}
24522427 test bind-19.8 {DeleteVirtualEvent procedure: owns 1, delete 1} -body {
24532428 foreach p [event info] {event delete $p}
24542429 event add <<xyz>> <Control-v>
24552430 event delete <<xyz>> <Control-v>
2456 event info
2431 event info
24572432 } -result {}
24582433 test bind-19.9 {DeleteVirtualEvent procedure: owns many, delete all} -body {
24592434 foreach p [event info] {event delete $p}
25052480 event generate .t.f <ButtonRelease-2>
25062481 event generate .t.f <Control-Button-2>
25072482 event generate .t.f <Control-ButtonRelease-2>
2508 event delete <<xyz>>
2483 event delete <<xyz>>
25092484 event generate .t.f <Button-2>
25102485 event generate .t.f <ButtonRelease-2>
25112486 event generate .t.f <Control-Button-2>
25722547 event generate .t.f <Control-ButtonRelease-2>
25732548 event generate .t.f <Shift-Button-2>
25742549 event generate .t.f <Shift-ButtonRelease-2>
2575 event delete <<xyz>>
2550 event delete <<xyz>>
25762551 event generate .t.f <Button-2>
25772552 event generate .t.f <ButtonRelease-2>
25782553 event generate .t.f <Control-Button-2>
25892564 pack [frame .t.f -class Test -width 150 -height 100]
25902565 pack [frame .t.g -class Test -width 150 -height 100]
25912566 pack [frame .t.h -class Test -width 150 -height 100]
2567 after 250 ;# we need a bit time to ensure that .t.h is mapped (<TODO>: fix this race condition)
25922568 focus -force .t.f
25932569 update
25942570 set x {}
26082584 event generate .t.g <ButtonRelease-2>
26092585 event generate .t.h <Button-2>
26102586 event generate .t.h <ButtonRelease-2>
2611 event delete <<xyz>>
2587 event delete <<xyz>>
26122588 event generate .t.f <Button-2>
26132589 event generate .t.f <ButtonRelease-2>
26142590 event generate .t.g <Button-2>
26252601 pack [frame .t.f -class Test -width 150 -height 100]
26262602 pack [frame .t.g -class Test -width 150 -height 100]
26272603 pack [frame .t.h -class Test -width 150 -height 100]
2604 after 250 ;# we need a bit time to ensure that .t.h is mapped (<TODO>: fix this race condition)
26282605 focus -force .t.f
26292606 update
26302607 set x {}
26612638 pack [frame .t.f -class Test -width 150 -height 100]
26622639 pack [frame .t.g -class Test -width 150 -height 100]
26632640 pack [frame .t.h -class Test -width 150 -height 100]
2641 after 250 ;# we need a bit time to ensure that .t.h is mapped (<TODO>: fix this race condition)
26642642 focus -force .t.f
26652643 update
26662644 set x {}
26802658 event generate .t.g <ButtonRelease-2>
26812659 event generate .t.h <Button-2>
26822660 event generate .t.h <ButtonRelease-2>
2683 event delete <<def>>
2661 event delete <<def>>
26842662 event generate .t.f <Button-2>
26852663 event generate .t.f <ButtonRelease-2>
26862664 event generate .t.g <Button-2>
27732751 } -returnCodes error -result {bad event type or keysym "xyz"}
27742752 test bind-22.6 {HandleEventGenerate} -body {
27752753 event generate . <Double-Button-1>
2776 } -returnCodes error -result {Double or Triple modifier not allowed}
2754 } -returnCodes error -result {Double, Triple, or Quadruple modifier not allowed}
27772755 test bind-22.7 {HandleEventGenerate} -body {
27782756 event generate . xyz
27792757 } -returnCodes error -result {only one event specification allowed}
34173395 set x {}
34183396 } -body {
34193397 bind .t.f <Map> "lappend x %o"
3420 event generate .t.f <Map> -override xyz
3398 event generate .t.f <Map> -override xyz
34213399 } -cleanup {
34223400 destroy .t.f
34233401 } -returnCodes error -result {expected boolean value but got "xyz"}
34303408 set x {}
34313409 } -body {
34323410 bind .t.f <Map> "lappend x %o"
3433 event generate .t.f <Map> -override 1
3411 event generate .t.f <Map> -override 1
34343412 return $x
34353413 } -cleanup {
34363414 destroy .t.f
34443422 set x {}
34453423 } -body {
34463424 bind .t.f <Reparent> "lappend x %o"
3447 event generate .t.f <Reparent> -override 1
3425 event generate .t.f <Reparent> -override 1
34483426 return $x
34493427 } -cleanup {
34503428 destroy .t.f
34583436 set x {}
34593437 } -body {
34603438 bind .t.f <Configure> "lappend x %o"
3461 event generate .t.f <Configure> -override 1
3439 event generate .t.f <Configure> -override 1
34623440 return $x
34633441 } -cleanup {
34643442 destroy .t.f
34723450 set x {}
34733451 } -body {
34743452 bind .t.f <Key> "lappend x %k"
3475 event generate .t.f <Key> -override 1
3453 event generate .t.f <Key> -override 1
34763454 } -cleanup {
34773455 destroy .t.f
34783456 } -returnCodes error -result {<Key> event doesn't accept "-override" option}
34853463 set x {}
34863464 } -body {
34873465 bind .t.f <Circulate> "lappend x %p"
3488 event generate .t.f <Circulate> -place xyz
3466 event generate .t.f <Circulate> -place xyz
34893467 } -cleanup {
34903468 destroy .t.f
34913469 } -returnCodes error -result {bad -place value "xyz": must be PlaceOnTop, or PlaceOnBottom}
34983476 set x {}
34993477 } -body {
35003478 bind .t.f <Circulate> "lappend x %p"
3501 event generate .t.f <Circulate> -place PlaceOnTop
3479 event generate .t.f <Circulate> -place PlaceOnTop
35023480 return $x
35033481 } -cleanup {
35043482 destroy .t.f
35123490 set x {}
35133491 } -body {
35143492 bind .t.f <Key> "lappend x %k"
3515 event generate .t.f <Key> -place PlaceOnTop
3493 event generate .t.f <Key> -place PlaceOnTop
35163494 } -cleanup {
35173495 destroy .t.f
35183496 } -returnCodes error -result {<Key> event doesn't accept "-place" option}
35253503 set x {}
35263504 } -body {
35273505 bind .t.f <Key> "lappend x %R"
3528 event generate .t.f <Key> -root .xyz
3506 event generate .t.f <Key> -root .xyz
35293507 } -cleanup {
35303508 destroy .t.f
35313509 } -returnCodes error -result {bad window path name ".xyz"}
35383516 set x {}
35393517 } -body {
35403518 bind .t.f <Key> "lappend x %R"
3541 event generate .t.f <Key> -root .t
3519 event generate .t.f <Key> -root .t
35423520 expr {[winfo id .t] eq $x}
35433521 } -cleanup {
35443522 destroy .t.f
35523530 set x {}
35533531 } -body {
35543532 bind .t.f <Key> "lappend x %R"
3555 event generate .t.f <Key> -root xyz
3533 event generate .t.f <Key> -root xyz
35563534 } -cleanup {
35573535 destroy .t.f
35583536 } -returnCodes error -result {bad window name/identifier "xyz"}
35653543 set x {}
35663544 } -body {
35673545 bind .t.f <Key> "lappend x %R"
3568 event generate .t.f <Key> -root [winfo id .t]
3546 event generate .t.f <Key> -root [winfo id .t]
35693547 expr {[winfo id .t] eq $x}
35703548 } -cleanup {
35713549 destroy .t.f
35793557 set x {}
35803558 } -body {
35813559 bind .t.f <Button> "lappend x %R"
3582 event generate .t.f <Button> -root .t
3560 event generate .t.f <Button> -root .t
35833561 expr {[winfo id .t] eq $x}
35843562 } -cleanup {
35853563 destroy .t.f
35933571 set x {}
35943572 } -body {
35953573 bind .t.f <ButtonRelease> "lappend x %R"
3596 event generate .t.f <ButtonRelease> -root .t
3574 event generate .t.f <ButtonRelease> -root .t
35973575 expr {[winfo id .t] eq $x}
35983576 } -cleanup {
35993577 destroy .t.f
36073585 set x {}
36083586 } -body {
36093587 bind .t.f <Motion> "lappend x %R"
3610 event generate .t.f <Motion> -root .t
3588 event generate .t.f <Motion> -root .t
36113589 expr {[winfo id .t] eq $x}
36123590 } -cleanup {
36133591 destroy .t.f
36213599 set x {}
36223600 } -body {
36233601 bind .t.f <<Paste>> "lappend x %R"
3624 event generate .t.f <<Paste>> -root .t
3602 event generate .t.f <<Paste>> -root .t
36253603 expr {[winfo id .t] eq $x}
36263604 } -cleanup {
36273605 destroy .t.f
36353613 set x {}
36363614 } -body {
36373615 bind .t.f <Enter> "lappend x %R"
3638 event generate .t.f <Enter> -root .t
3616 event generate .t.f <Enter> -root .t
36393617 expr {[winfo id .t] eq $x}
36403618 } -cleanup {
36413619 destroy .t.f
36493627 set x {}
36503628 } -body {
36513629 bind .t.f <Configure> "lappend x %R"
3652 event generate .t.f <Configure> -root .t
3630 event generate .t.f <Configure> -root .t
36533631 } -cleanup {
36543632 destroy .t.f
36553633 } -returnCodes error -result {<Configure> event doesn't accept "-root" option}
36623640 set x {}
36633641 } -body {
36643642 bind .t.f <Key> "lappend x %X"
3665 event generate .t.f <Key> -rootx xyz
3643 event generate .t.f <Key> -rootx xyz
36663644 } -cleanup {
36673645 destroy .t.f
36683646 } -returnCodes error -result {bad screen distance "xyz"}
36753653 set x {}
36763654 } -body {
36773655 bind .t.f <Key> "lappend x %X"
3678 event generate .t.f <Key> -rootx 2i
3656 event generate .t.f <Key> -rootx 2i
36793657 expr {[winfo pixels .t.f 2i] eq $x}
36803658 } -cleanup {
36813659 destroy .t.f
36893667 set x {}
36903668 } -body {
36913669 bind .t.f <Button> "lappend x %X"
3692 event generate .t.f <Button> -rootx 2i
3670 event generate .t.f <Button> -rootx 2i
36933671 expr {[winfo pixels .t.f 2i] eq $x}
36943672 } -cleanup {
36953673 destroy .t.f
37033681 set x {}
37043682 } -body {
37053683 bind .t.f <ButtonRelease> "lappend x %X"
3706 event generate .t.f <ButtonRelease> -rootx 2i
3684 event generate .t.f <ButtonRelease> -rootx 2i
37073685 expr {[winfo pixels .t.f 2i] eq $x}
37083686 } -cleanup {
37093687 destroy .t.f
37173695 set x {}
37183696 } -body {
37193697 bind .t.f <Motion> "lappend x %X"
3720 event generate .t.f <Motion> -rootx 2i
3698 event generate .t.f <Motion> -rootx 2i
37213699 expr {[winfo pixels .t.f 2i] eq $x}
37223700 } -cleanup {
37233701 destroy .t.f
37313709 set x {}
37323710 } -body {
37333711 bind .t.f <<Paste>> "lappend x %X"
3734 event generate .t.f <<Paste>> -rootx 2i
3712 event generate .t.f <<Paste>> -rootx 2i
37353713 expr {[winfo pixels .t.f 2i] eq $x}
37363714 } -cleanup {
37373715 destroy .t.f
37453723 set x {}
37463724 } -body {
37473725 bind .t.f <Enter> "lappend x %X"
3748 event generate .t.f <Enter> -rootx 2i
3726 event generate .t.f <Enter> -rootx 2i
37493727 expr {[winfo pixels .t.f 2i] eq $x}
37503728 } -cleanup {
37513729 destroy .t.f
37593737 set x {}
37603738 } -body {
37613739 bind .t.f <Configure> "lappend x %X"
3762 event generate .t.f <Configure> -rootx 2i
3740 event generate .t.f <Configure> -rootx 2i
37633741 } -cleanup {
37643742 destroy .t.f
37653743 } -returnCodes error -result {<Configure> event doesn't accept "-rootx" option}
37723750 set x {}
37733751 } -body {
37743752 bind .t.f <Key> "lappend x %Y"
3775 event generate .t.f <Key> -rooty xyz
3753 event generate .t.f <Key> -rooty xyz
37763754 } -cleanup {
37773755 destroy .t.f
37783756 } -returnCodes error -result {bad screen distance "xyz"}
37853763 set x {}
37863764 } -body {
37873765 bind .t.f <Key> "lappend x %Y"
3788 event generate .t.f <Key> -rooty 2i
3766 event generate .t.f <Key> -rooty 2i
37893767 expr {[winfo pixels .t.f 2i] eq $x}
37903768 } -cleanup {
37913769 destroy .t.f
37993777 set x {}
38003778 } -body {
38013779 bind .t.f <Button> "lappend x %Y"
3802 event generate .t.f <Button> -rooty 2i
3780 event generate .t.f <Button> -rooty 2i
38033781 expr {[winfo pixels .t.f 2i] eq $x}
38043782 } -cleanup {
38053783 destroy .t.f
38133791 set x {}
38143792 } -body {
38153793 bind .t.f <ButtonRelease> "lappend x %Y"
3816 event generate .t.f <ButtonRelease> -rooty 2i
3794 event generate .t.f <ButtonRelease> -rooty 2i
38173795 expr {[winfo pixels .t.f 2i] eq $x}
38183796 } -cleanup {
38193797 destroy .t.f
38273805 set x {}
38283806 } -body {
38293807 bind .t.f <Motion> "lappend x %Y"
3830 event generate .t.f <Motion> -rooty 2i
3808 event generate .t.f <Motion> -rooty 2i
38313809 expr {[winfo pixels .t.f 2i] eq $x}
38323810 } -cleanup {
38333811 destroy .t.f
38413819 set x {}
38423820 } -body {
38433821 bind .t.f <<Paste>> "lappend x %Y"
3844 event generate .t.f <<Paste>> -rooty 2i
3822 event generate .t.f <<Paste>> -rooty 2i
38453823 expr {[winfo pixels .t.f 2i] eq $x}
38463824 } -cleanup {
38473825 destroy .t.f
38553833 set x {}
38563834 } -body {
38573835 bind .t.f <Enter> "lappend x %Y"
3858 event generate .t.f <Enter> -rooty 2i
3836 event generate .t.f <Enter> -rooty 2i
38593837 expr {[winfo pixels .t.f 2i] eq $x}
38603838 } -cleanup {
38613839 destroy .t.f
38693847 set x {}
38703848 } -body {
38713849 bind .t.f <Configure> "lappend x %Y"
3872 event generate .t.f <Configure> -rooty 2i
3850 event generate .t.f <Configure> -rooty 2i
38733851 } -cleanup {
38743852 destroy .t.f
38753853 } -returnCodes error -result {<Configure> event doesn't accept "-rooty" option}
38823860 set x {}
38833861 } -body {
38843862 bind .t.f <Key> "lappend x %E"
3885 event generate .t.f <Key> -sendevent xyz
3863 event generate .t.f <Key> -sendevent xyz
38863864 } -cleanup {
38873865 destroy .t.f
38883866 } -returnCodes error -result {expected boolean value but got "xyz"}
38953873 set x {}
38963874 } -body {
38973875 bind .t.f <Key> "lappend x %E"
3898 event generate .t.f <Key> -sendevent 1
3876 event generate .t.f <Key> -sendevent 1
38993877 return $x
39003878 } -cleanup {
39013879 destroy .t.f
39093887 set x {}
39103888 } -body {
39113889 bind .t.f <Key> "lappend x %E"
3912 event generate .t.f <Key> -sendevent yes
3890 event generate .t.f <Key> -sendevent yes
39133891 return $x
39143892 } -cleanup {
39153893 destroy .t.f
39233901 set x {}
39243902 } -body {
39253903 bind .t.f <Key> "lappend x %E"
3926 event generate .t.f <Key> -sendevent 43
3927 return $x
3928 } -cleanup {
3929 destroy .t.f
3930 } -result {43}
3904 event generate .t.f <Key> -sendevent 43
3905 return $x
3906 } -cleanup {
3907 destroy .t.f
3908 } -result {1}
39313909
39323910 test bind-22.93 {HandleEventGenerate: options <Key> -serial xyz} -setup {
39333911 frame .t.f -class Test -width 150 -height 100
39373915 set x {}
39383916 } -body {
39393917 bind .t.f <Key> "lappend x %#"
3940 event generate .t.f <Key> -serial xyz
3918 event generate .t.f <Key> -serial xyz
39413919 } -cleanup {
39423920 destroy .t.f
39433921 } -returnCodes error -result {expected integer but got "xyz"}
39503928 set x {}
39513929 } -body {
39523930 bind .t.f <Key> "lappend x %#"
3953 event generate .t.f <Key> -serial 100
3931 event generate .t.f <Key> -serial 100
39543932 return $x
39553933 } -cleanup {
39563934 destroy .t.f
39643942 set x {}
39653943 } -body {
39663944 bind .t.f <Key> "lappend x %s"
3967 event generate .t.f <Key> -state xyz
3945 event generate .t.f <Key> -state xyz
39683946 } -cleanup {
39693947 destroy .t.f
39703948 } -returnCodes error -result {expected integer but got "xyz"}
39773955 set x {}
39783956 } -body {
39793957 bind .t.f <Key> "lappend x %s"
3980 event generate .t.f <Key> -state 1
3958 event generate .t.f <Key> -state 1
39813959 return $x
39823960 } -cleanup {
39833961 destroy .t.f
39913969 set x {}
39923970 } -body {
39933971 bind .t.f <Button> "lappend x %s"
3994 event generate .t.f <Button> -state 1025
3972 event generate .t.f <Button> -state 1025
39953973 return $x
39963974 } -cleanup {
39973975 destroy .t.f
40053983 set x {}
40063984 } -body {
40073985 bind .t.f <ButtonRelease> "lappend x %s"
4008 event generate .t.f <ButtonRelease> -state 1025
3986 event generate .t.f <ButtonRelease> -state 1025
40093987 return $x
40103988 } -cleanup {
40113989 destroy .t.f
40193997 set x {}
40203998 } -body {
40213999 bind .t.f <Motion> "lappend x %s"
4022 event generate .t.f <Motion> -state 1
4000 event generate .t.f <Motion> -state 1
40234001 return $x
40244002 } -cleanup {
40254003 destroy .t.f
40334011 set x {}
40344012 } -body {
40354013 bind .t.f <<Paste>> "lappend x %s"
4036 event generate .t.f <<Paste>> -state 1
4014 event generate .t.f <<Paste>> -state 1
40374015 return $x
40384016 } -cleanup {
40394017 destroy .t.f
40474025 set x {}
40484026 } -body {
40494027 bind .t.f <Enter> "lappend x %s"
4050 event generate .t.f <Enter> -state 1
4028 event generate .t.f <Enter> -state 1
40514029 return $x
40524030 } -cleanup {
40534031 destroy .t.f
40614039 set x {}
40624040 } -body {
40634041 bind .t.f <Visibility> "lappend x %s"
4064 event generate .t.f <Visibility> -state xyz
4042 event generate .t.f <Visibility> -state xyz
40654043 } -cleanup {
40664044 destroy .t.f
40674045 } -returnCodes error -result {bad -state value "xyz": must be VisibilityUnobscured, VisibilityPartiallyObscured, or VisibilityFullyObscured}
40744052 set x {}
40754053 } -body {
40764054 bind .t.f <Visibility> "lappend x %s"
4077 event generate .t.f <Visibility> -state VisibilityUnobscured
4055 event generate .t.f <Visibility> -state VisibilityUnobscured
40784056 return $x
40794057 } -cleanup {
40804058 destroy .t.f
40884066 set x {}
40894067 } -body {
40904068 bind .t.f <Configure> "lappend x %s"
4091 event generate .t.f <Configure> -state xyz
4069 event generate .t.f <Configure> -state xyz
40924070 } -cleanup {
40934071 destroy .t.f
40944072 } -returnCodes error -result {<Configure> event doesn't accept "-state" option}
41014079 set x {}
41024080 } -body {
41034081 bind .t.f <Key> "lappend x %S"
4104 event generate .t.f <Key> -subwindow .xyz
4082 event generate .t.f <Key> -subwindow .xyz
41054083 } -cleanup {
41064084 destroy .t.f
41074085 } -returnCodes error -result {bad window path name ".xyz"}
41144092 set x {}
41154093 } -body {
41164094 bind .t.f <Key> "lappend x %S"
4117 event generate .t.f <Key> -subwindow .t
4095 event generate .t.f <Key> -subwindow .t
41184096 expr {[winfo id .t] eq $x}
41194097 } -cleanup {
41204098 destroy .t.f
41284106 set x {}
41294107 } -body {
41304108 bind .t.f <Key> "lappend x %S"
4131 event generate .t.f <Key> -subwindow xyz
4109 event generate .t.f <Key> -subwindow xyz
41324110 } -cleanup {
41334111 destroy .t.f
41344112 } -returnCodes error -result {bad window name/identifier "xyz"}
41414119 set x {}
41424120 } -body {
41434121 bind .t.f <Key> "lappend x %S"
4144 event generate .t.f <Key> -subwindow [winfo id .t]
4122 event generate .t.f <Key> -subwindow [winfo id .t]
41454123 expr {[winfo id .t] eq $x}
41464124 } -cleanup {
41474125 destroy .t.f
41554133 set x {}
41564134 } -body {
41574135 bind .t.f <Button> "lappend x %S"
4158 event generate .t.f <Button> -subwindow .t
4136 event generate .t.f <Button> -subwindow .t
41594137 expr {[winfo id .t] eq $x}
41604138 } -cleanup {
41614139 destroy .t.f
41694147 set x {}
41704148 } -body {
41714149 bind .t.f <ButtonRelease> "lappend x %S"
4172 event generate .t.f <ButtonRelease> -subwindow .t
4150 event generate .t.f <ButtonRelease> -subwindow .t
41734151 expr {[winfo id .t] eq $x}
41744152 } -cleanup {
41754153 destroy .t.f
41834161 set x {}
41844162 } -body {
41854163 bind .t.f <Motion> "lappend x %S"
4186 event generate .t.f <Motion> -subwindow .t
4164 event generate .t.f <Motion> -subwindow .t
41874165 expr {[winfo id .t] eq $x}
41884166 } -cleanup {
41894167 destroy .t.f
41974175 set x {}
41984176 } -body {
41994177 bind .t.f <<Paste>> "lappend x %S"
4200 event generate .t.f <<Paste>> -subwindow .t
4178 event generate .t.f <<Paste>> -subwindow .t
42014179 expr {[winfo id .t] eq $x}
42024180 } -cleanup {
42034181 destroy .t.f
42114189 set x {}
42124190 } -body {
42134191 bind .t.f <Enter> "lappend x %S"
4214 event generate .t.f <Enter> -subwindow .t
4192 event generate .t.f <Enter> -subwindow .t
42154193 expr {[winfo id .t] eq $x}
42164194 } -cleanup {
42174195 destroy .t.f
42254203 set x {}
42264204 } -body {
42274205 bind .t.f <Configure> "lappend x %S"
4228 event generate .t.f <Configure> -subwindow .t
4206 event generate .t.f <Configure> -subwindow .t
42294207 } -cleanup {
42304208 destroy .t.f
42314209 } -returnCodes error -result {<Configure> event doesn't accept "-subwindow" option}
42384216 set x {}
42394217 } -body {
42404218 bind .t.f <Key> "lappend x %t"
4241 event generate .t.f <Key> -time xyz
4219 event generate .t.f <Key> -time xyz
42424220 } -cleanup {
42434221 destroy .t.f
42444222 } -returnCodes error -result {expected integer but got "xyz"}
42514229 set x {}
42524230 } -body {
42534231 bind .t.f <Key> "lappend x %t"
4254 event generate .t.f <Key> -time 100
4232 event generate .t.f <Key> -time 100
42554233 return $x
42564234 } -cleanup {
42574235 destroy .t.f
42654243 set x {}
42664244 } -body {
42674245 bind .t.f <Button> "lappend x %t"
4268 event generate .t.f <Button> -time 100
4246 event generate .t.f <Button> -time 100
42694247 return $x
42704248 } -cleanup {
42714249 destroy .t.f
42794257 set x {}
42804258 } -body {
42814259 bind .t.f <ButtonRelease> "lappend x %t"
4282 event generate .t.f <ButtonRelease> -time 100
4260 event generate .t.f <ButtonRelease> -time 100
42834261 return $x
42844262 } -cleanup {
42854263 destroy .t.f
42934271 set x {}
42944272 } -body {
42954273 bind .t.f <Motion> "lappend x %t"
4296 event generate .t.f <Motion> -time 100
4274 event generate .t.f <Motion> -time 100
42974275 return $x
42984276 } -cleanup {
42994277 destroy .t.f
43074285 set x {}
43084286 } -body {
43094287 bind .t.f <<Paste>> "lappend x %t"
4310 event generate .t.f <<Paste>> -time 100
4288 event generate .t.f <<Paste>> -time 100
43114289 return $x
43124290 } -cleanup {
43134291 destroy .t.f
43214299 set x {}
43224300 } -body {
43234301 bind .t.f <Enter> "lappend x %t"
4324 event generate .t.f <Enter> -time 100
4302 event generate .t.f <Enter> -time 100
43254303 return $x
43264304 } -cleanup {
43274305 destroy .t.f
43354313 set x {}
43364314 } -body {
43374315 bind .t.f <Property> "lappend x %t"
4338 event generate .t.f <Property> -time 100
4316 event generate .t.f <Property> -time 100
43394317 return $x
43404318 } -cleanup {
43414319 destroy .t.f
43494327 set x {}
43504328 } -body {
43514329 bind .t.f <Configure> "lappend x %t"
4352 event generate .t.f <Configure> -time 100
4330 event generate .t.f <Configure> -time 100
43534331 } -cleanup {
43544332 destroy .t.f
43554333 } -returnCodes error -result {<Configure> event doesn't accept "-time" option}
43624340 set x {}
43634341 } -body {
43644342 bind .t.f <Expose> "lappend x %w"
4365 event generate .t.f <Expose> -width xyz
4343 event generate .t.f <Expose> -width xyz
43664344 } -cleanup {
43674345 destroy .t.f
43684346 } -returnCodes error -result {bad screen distance "xyz"}
43754353 set x {}
43764354 } -body {
43774355 bind .t.f <Expose> "lappend x %w"
4378 event generate .t.f <Expose> -width 2i
4356 event generate .t.f <Expose> -width 2i
43794357 expr {[winfo pixels .t.f 2i] eq $x}
43804358 } -cleanup {
43814359 destroy .t.f
43894367 set x {}
43904368 } -body {
43914369 bind .t.f <Configure> "lappend x %w"
4392 event generate .t.f <Configure> -width 2i
4370 event generate .t.f <Configure> -width 2i
43934371 expr {[winfo pixels .t.f 2i] eq $x}
43944372 } -cleanup {
43954373 destroy .t.f
44034381 set x {}
44044382 } -body {
44054383 bind .t.f <Key> "lappend x %k"
4406 event generate .t.f <Key> -width 2i
4384 event generate .t.f <Key> -width 2i
44074385 } -cleanup {
44084386 destroy .t.f
44094387 } -returnCodes error -result {<Key> event doesn't accept "-width" option}
44164394 set x {}
44174395 } -body {
44184396 bind .t.f <Unmap> "lappend x %W"
4419 event generate .t.f <Unmap> -window .xyz
4397 event generate .t.f <Unmap> -window .xyz
44204398 } -cleanup {
44214399 destroy .t.f
44224400 } -returnCodes error -result {bad window path name ".xyz"}
44294407 set x {}
44304408 } -body {
44314409 bind .t.f <Unmap> "lappend x %W"
4432 event generate .t.f <Unmap> -window .t.f
4410 event generate .t.f <Unmap> -window .t.f
44334411 return $x
44344412 } -cleanup {
44354413 destroy .t.f
44434421 set x {}
44444422 } -body {
44454423 bind .t.f <Unmap> "lappend x %W"
4446 event generate .t.f <Unmap> -window xyz
4424 event generate .t.f <Unmap> -window xyz
44474425 } -cleanup {
44484426 destroy .t.f
44494427 } -returnCodes error -result {bad window name/identifier "xyz"}
44564434 set x {}
44574435 } -body {
44584436 bind .t.f <Unmap> "lappend x %W"
4459 event generate .t.f <Unmap> -window [winfo id .t.f]
4437 event generate .t.f <Unmap> -window [winfo id .t.f]
44604438 return $x
44614439 } -cleanup {
44624440 destroy .t.f
44704448 set x {}
44714449 } -body {
44724450 bind .t.f <Unmap> "lappend x %W"
4473 event generate .t.f <Unmap> -window .t.f
4451 event generate .t.f <Unmap> -window .t.f
44744452 return $x
44754453 } -cleanup {
44764454 destroy .t.f
44844462 set x {}
44854463 } -body {
44864464 bind .t.f <Map> "lappend x %W"
4487 event generate .t.f <Map> -window .t.f
4465 event generate .t.f <Map> -window .t.f
44884466 return $x
44894467 } -cleanup {
44904468 destroy .t.f
44984476 set x {}
44994477 } -body {
45004478 bind .t.f <Reparent> "lappend x %W"
4501 event generate .t.f <Reparent> -window .t.f
4479 event generate .t.f <Reparent> -window .t.f
45024480 return $x
45034481 } -cleanup {
45044482 destroy .t.f
45124490 set x {}
45134491 } -body {
45144492 bind .t.f <Configure> "lappend x %W"
4515 event generate .t.f <Configure> -window .t.f
4493 event generate .t.f <Configure> -window .t.f
45164494 return $x
45174495 } -cleanup {
45184496 destroy .t.f
45264504 set x {}
45274505 } -body {
45284506 bind .t.f <Gravity> "lappend x %W"
4529 event generate .t.f <Gravity> -window .t.f
4507 event generate .t.f <Gravity> -window .t.f
45304508 return $x
45314509 } -cleanup {
45324510 destroy .t.f
45404518 set x {}
45414519 } -body {
45424520 bind .t.f <Circulate> "lappend x %W"
4543 event generate .t.f <Circulate> -window .t.f
4521 event generate .t.f <Circulate> -window .t.f
45444522 return $x
45454523 } -cleanup {
45464524 destroy .t.f
45544532 set x {}
45554533 } -body {
45564534 bind .t.f <Key> "lappend x %W"
4557 event generate .t.f <Key> -window .t.f
4535 event generate .t.f <Key> -window .t.f
45584536 } -cleanup {
45594537 destroy .t.f
45604538 } -returnCodes error -result {<Key> event doesn't accept "-window" option}
45674545 set x {}
45684546 } -body {
45694547 bind .t.f <Key> "lappend x %x"
4570 event generate .t.f <Key> -x xyz
4548 event generate .t.f <Key> -x xyz
45714549 } -cleanup {
45724550 destroy .t.f
45734551 } -returnCodes error -result {bad screen distance "xyz"}
45804558 set x {}
45814559 } -body {
45824560 bind .t.f <Key> "lappend x %x"
4583 event generate .t.f <Key> -x 2i
4561 event generate .t.f <Key> -x 2i
45844562 expr {[winfo pixels .t.f 2i] eq $x}
45854563 } -cleanup {
45864564 destroy .t.f
45944572 set x {}
45954573 } -body {
45964574 bind .t.f <Button> "lappend x %x"
4597 event generate .t.f <Button> -x 2i
4575 event generate .t.f <Button> -x 2i
45984576 expr {[winfo pixels .t.f 2i] eq $x}
45994577 } -cleanup {
46004578 destroy .t.f
46084586 set x {}
46094587 } -body {
46104588 bind .t.f <ButtonRelease> "lappend x %x"
4611 event generate .t.f <ButtonRelease> -x 2i
4589 event generate .t.f <ButtonRelease> -x 2i
46124590 expr {[winfo pixels .t.f 2i] eq $x}
46134591 } -cleanup {
46144592 destroy .t.f
46224600 set x {}
46234601 } -body {
46244602 bind .t.f <Motion> "lappend x %x"
4625 event generate .t.f <Motion> -x 2i
4603 event generate .t.f <Motion> -x 2i
46264604 expr {[winfo pixels .t.f 2i] eq $x}
46274605 } -cleanup {
46284606 destroy .t.f
46364614 set x {}
46374615 } -body {
46384616 bind .t.f <<Paste>> "lappend x %x"
4639 event generate .t.f <<Paste>> -x 2i
4617 event generate .t.f <<Paste>> -x 2i
46404618 expr {[winfo pixels .t.f 2i] eq $x}
46414619 } -cleanup {
46424620 destroy .t.f
46504628 set x {}
46514629 } -body {
46524630 bind .t.f <Enter> "lappend x %x"
4653 event generate .t.f <Enter> -x 2i
4631 event generate .t.f <Enter> -x 2i
46544632 expr {[winfo pixels .t.f 2i] eq $x}
46554633 } -cleanup {
46564634 destroy .t.f
46644642 set x {}
46654643 } -body {
46664644 bind .t.f <Expose> "lappend x %x"
4667 event generate .t.f <Expose> -x 2i
4645 event generate .t.f <Expose> -x 2i
46684646 expr {[winfo pixels .t.f 2i] eq $x}
46694647 } -cleanup {
46704648 destroy .t.f
46784656 set x {}
46794657 } -body {
46804658 bind .t.f <Configure> "lappend x %x"
4681 event generate .t.f <Configure> -x 2i
4659 event generate .t.f <Configure> -x 2i
46824660 expr {[winfo pixels .t.f 2i] eq $x}
46834661 } -cleanup {
46844662 destroy .t.f
46924670 set x {}
46934671 } -body {
46944672 bind .t.f <Gravity> "lappend x %x"
4695 event generate .t.f <Gravity> -x 2i
4673 event generate .t.f <Gravity> -x 2i
46964674 expr {[winfo pixels .t.f 2i] eq $x}
46974675 } -cleanup {
46984676 destroy .t.f
47064684 set x {}
47074685 } -body {
47084686 bind .t.f <Reparent> "lappend x %x"
4709 event generate .t.f <Reparent> -x 2i
4687 event generate .t.f <Reparent> -x 2i
47104688 expr {[winfo pixels .t.f 2i] eq $x}
47114689 } -cleanup {
47124690 destroy .t.f
47204698 set x {}
47214699 } -body {
47224700 bind .t.f <Map> "lappend x %x"
4723 event generate .t.f <Map> -x 2i
4701 event generate .t.f <Map> -x 2i
47244702 } -cleanup {
47254703 destroy .t.f
47264704 } -returnCodes error -result {<Map> event doesn't accept "-x" option}
47334711 set x {}
47344712 } -body {
47354713 bind .t.f <Key> "lappend x %y"
4736 event generate .t.f <Key> -y xyz
4714 event generate .t.f <Key> -y xyz
47374715 } -cleanup {
47384716 destroy .t.f
47394717 } -returnCodes error -result {bad screen distance "xyz"}
47464724 set x {}
47474725 } -body {
47484726 bind .t.f <Key> "lappend x %y"
4749 event generate .t.f <Key> -y 2i
4727 event generate .t.f <Key> -y 2i
47504728 expr {[winfo pixels .t.f 2i] eq $x}
47514729 } -cleanup {
47524730 destroy .t.f
47604738 set x {}
47614739 } -body {
47624740 bind .t.f <Button> "lappend x %y"
4763 event generate .t.f <Button> -y 2i
4741 event generate .t.f <Button> -y 2i
47644742 expr {[winfo pixels .t.f 2i] eq $x}
47654743 } -cleanup {
47664744 destroy .t.f
47744752 set x {}
47754753 } -body {
47764754 bind .t.f <ButtonRelease> "lappend x %y"
4777 event generate .t.f <ButtonRelease> -y 2i
4755 event generate .t.f <ButtonRelease> -y 2i
47784756 expr {[winfo pixels .t.f 2i] eq $x}
47794757 } -cleanup {
47804758 destroy .t.f
47884766 set x {}
47894767 } -body {
47904768 bind .t.f <Motion> "lappend x %y"
4791 event generate .t.f <Motion> -y 2i
4769 event generate .t.f <Motion> -y 2i
47924770 expr {[winfo pixels .t.f 2i] eq $x}
47934771 } -cleanup {
47944772 destroy .t.f
48024780 set x {}
48034781 } -body {
48044782 bind .t.f <<Paste>> "lappend x %y"
4805 event generate .t.f <<Paste>> -y 2i
4783 event generate .t.f <<Paste>> -y 2i
48064784 expr {[winfo pixels .t.f 2i] eq $x}
48074785 } -cleanup {
48084786 destroy .t.f
48164794 set x {}
48174795 } -body {
48184796 bind .t.f <Enter> "lappend x %y"
4819 event generate .t.f <Enter> -y 2i
4797 event generate .t.f <Enter> -y 2i
48204798 expr {[winfo pixels .t.f 2i] eq $x}
48214799 } -cleanup {
48224800 destroy .t.f
48304808 set x {}
48314809 } -body {
48324810 bind .t.f <Expose> "lappend x %y"
4833 event generate .t.f <Expose> -y 2i
4811 event generate .t.f <Expose> -y 2i
48344812 expr {[winfo pixels .t.f 2i] eq $x}
48354813 } -cleanup {
48364814 destroy .t.f
48444822 set x {}
48454823 } -body {
48464824 bind .t.f <Configure> "lappend x %y"
4847 event generate .t.f <Configure> -y 2i
4825 event generate .t.f <Configure> -y 2i
48484826 expr {[winfo pixels .t.f 2i] eq $x}
48494827 } -cleanup {
48504828 destroy .t.f
48584836 set x {}
48594837 } -body {
48604838 bind .t.f <Gravity> "lappend x %y"
4861 event generate .t.f <Gravity> -y 2i
4839 event generate .t.f <Gravity> -y 2i
48624840 expr {[winfo pixels .t.f 2i] eq $x}
48634841 } -cleanup {
48644842 destroy .t.f
48724850 set x {}
48734851 } -body {
48744852 bind .t.f <Reparent> "lappend x %y"
4875 event generate .t.f <Reparent> -y 2i
4853 event generate .t.f <Reparent> -y 2i
48764854 expr {[winfo pixels .t.f 2i] eq $x}
48774855 } -cleanup {
48784856 destroy .t.f
48864864 set x {}
48874865 } -body {
48884866 bind .t.f <Map> "lappend x %y"
4889 event generate .t.f <Map> -y 2i
4867 event generate .t.f <Map> -y 2i
48904868 } -cleanup {
48914869 destroy .t.f
48924870 } -returnCodes error -result {<Map> event doesn't accept "-y" option}
48994877 set x {}
49004878 } -body {
49014879 bind .t.f <Key> "lappend x %k"
4902 event generate .t.f <Key> -xyz 1
4880 event generate .t.f <Key> -xyz 1
49034881 } -cleanup {
49044882 destroy .t.f
49054883 } -returnCodes error -result {bad option "-xyz": must be -when, -above, -borderwidth, -button, -count, -data, -delta, -detail, -focus, -height, -keycode, -keysym, -mode, -override, -place, -root, -rootx, -rooty, -sendevent, -serial, -state, -subwindow, -time, -warp, -width, -window, -x, or -y}
49414919 destroy .t.f
49424920 } -result {}
49434921 test bind-24.4 {FindSequence procedure: virtual not allowed} -body {
4944 event add <<Paste>> <<Alive>>
4922 event add <<Paste>> <<Alive>>
49454923 } -returnCodes error -result {virtual event not allowed in definition of another virtual event}
49464924 test bind-24.5 {FindSequence procedure, multiple bindings} -setup {
49474925 frame .t.f -class Test -width 150 -height 100
51205098 } -cleanup {
51215099 destroy .t.f
51225100 } -result a
5123 test bind-25.4 {ParseEventDescription} -body {
5124 bind .t <<Shift-Paste>> {puts hi}
5125 bind .t
5101 test bind-25.4 {ParseEventDescription} -setup {
5102 frame .t.f -class Test -width 150 -height 100
5103 } -body {
5104 bind .t.f <<Shift-Paste>> {puts hi}
5105 bind .t.f
5106 } -cleanup {
5107 destroy .t.f
51265108 } -result {<<Shift-Paste>>}
51275109
51285110 # Assorted error cases in event sequence parsing
51695151 # Modifier canonicalization tests
51705152
51715153 test bind-25.18 {modifier names} -setup {
5172 frame .t.f -class Test -width 150 -height 100
5154 frame .t.f -class Test -width 150 -height 100
51735155 } -body {
51745156 bind .t.f {<Control- a>} foo
5175 bind .t.f
5176 } -cleanup {
5177 destroy .t.f
5157 bind .t.f
5158 } -cleanup {
5159 destroy .t.f
51785160 } -result <Control-Key-a>
51795161
51805162 test bind-25.19 {modifier names} -setup {
5181 frame .t.f -class Test -width 150 -height 100
5182 } -body {
5183 bind .t.f <Shift-a> foo
5184 bind .t.f
5185 } -cleanup {
5186 destroy .t.f
5163 frame .t.f -class Test -width 150 -height 100
5164 } -body {
5165 bind .t.f <Shift-a> foo
5166 bind .t.f
5167 } -cleanup {
5168 destroy .t.f
51875169 } -result <Shift-Key-a>
51885170
51895171 test bind-25.20 {modifier names} -setup {
5190 frame .t.f -class Test -width 150 -height 100
5191 } -body {
5192 bind .t.f <Lock-a> foo
5193 bind .t.f
5194 } -cleanup {
5195 destroy .t.f
5172 frame .t.f -class Test -width 150 -height 100
5173 } -body {
5174 bind .t.f <Lock-a> foo
5175 bind .t.f
5176 } -cleanup {
5177 destroy .t.f
51965178 } -result <Lock-Key-a>
51975179
51985180 test bind-25.21 {modifier names} -setup {
5199 frame .t.f -class Test -width 150 -height 100
5200 } -body {
5201 bind .t.f <Meta---a> foo
5202 bind .t.f
5203 } -cleanup {
5204 destroy .t.f
5181 frame .t.f -class Test -width 150 -height 100
5182 } -body {
5183 bind .t.f <Meta---a> foo
5184 bind .t.f
5185 } -cleanup {
5186 destroy .t.f
52055187 } -result <Meta-Key-a>
52065188
52075189 test bind-25.22 {modifier names} -setup {
5208 frame .t.f -class Test -width 150 -height 100
5209 } -body {
5210 bind .t.f <M-a> foo
5211 bind .t.f
5212 } -cleanup {
5213 destroy .t.f
5190 frame .t.f -class Test -width 150 -height 100
5191 } -body {
5192 bind .t.f <M-a> foo
5193 bind .t.f
5194 } -cleanup {
5195 destroy .t.f
52145196 } -result <Meta-Key-a>
52155197
52165198 test bind-25.23 {modifier names} -setup {
5217 frame .t.f -class Test -width 150 -height 100
5218 } -body {
5219 bind .t.f <Alt-a> foo
5220 bind .t.f
5221 } -cleanup {
5222 destroy .t.f
5199 frame .t.f -class Test -width 150 -height 100
5200 } -body {
5201 bind .t.f <Alt-a> foo
5202 bind .t.f
5203 } -cleanup {
5204 destroy .t.f
52235205 } -result <Alt-Key-a>
52245206
52255207 test bind-25.24 {modifier names} -setup {
5226 frame .t.f -class Test -width 150 -height 100
5227 } -body {
5228 bind .t.f <B1-a> foo
5229 bind .t.f
5230 } -cleanup {
5231 destroy .t.f
5208 frame .t.f -class Test -width 150 -height 100
5209 } -body {
5210 bind .t.f <B1-a> foo
5211 bind .t.f
5212 } -cleanup {
5213 destroy .t.f
52325214 } -result <B1-Key-a>
52335215
52345216 test bind-25.25 {modifier names} -setup {
5235 frame .t.f -class Test -width 150 -height 100
5236 } -body {
5237 bind .t.f <B2-a> foo
5238 bind .t.f
5239 } -cleanup {
5240 destroy .t.f
5217 frame .t.f -class Test -width 150 -height 100
5218 } -body {
5219 bind .t.f <B2-a> foo
5220 bind .t.f
5221 } -cleanup {
5222 destroy .t.f
52415223 } -result <B2-Key-a>
52425224
52435225 test bind-25.26 {modifier names} -setup {
5244 frame .t.f -class Test -width 150 -height 100
5245 } -body {
5246 bind .t.f <B3-a> foo
5247 bind .t.f
5248 } -cleanup {
5249 destroy .t.f
5226 frame .t.f -class Test -width 150 -height 100
5227 } -body {
5228 bind .t.f <B3-a> foo
5229 bind .t.f
5230 } -cleanup {
5231 destroy .t.f
52505232 } -result <B3-Key-a>
52515233
52525234 test bind-25.27 {modifier names} -setup {
5253 frame .t.f -class Test -width 150 -height 100
5254 } -body {
5255 bind .t.f <B4-a> foo
5256 bind .t.f
5257 } -cleanup {
5258 destroy .t.f
5235 frame .t.f -class Test -width 150 -height 100
5236 } -body {
5237 bind .t.f <B4-a> foo
5238 bind .t.f
5239 } -cleanup {
5240 destroy .t.f
52595241 } -result <B4-Key-a>
52605242
52615243 test bind-25.28 {modifier names} -setup {
5262 frame .t.f -class Test -width 150 -height 100
5263 } -body {
5264 bind .t.f <B5-a> foo
5265 bind .t.f
5266 } -cleanup {
5267 destroy .t.f
5244 frame .t.f -class Test -width 150 -height 100
5245 } -body {
5246 bind .t.f <B5-a> foo
5247 bind .t.f
5248 } -cleanup {
5249 destroy .t.f
52685250 } -result <B5-Key-a>
52695251
52705252 test bind-25.29 {modifier names} -setup {
5271 frame .t.f -class Test -width 150 -height 100
5272 } -body {
5273 bind .t.f <Button1-a> foo
5274 bind .t.f
5275 } -cleanup {
5276 destroy .t.f
5253 frame .t.f -class Test -width 150 -height 100
5254 } -body {
5255 bind .t.f <Button1-a> foo
5256 bind .t.f
5257 } -cleanup {
5258 destroy .t.f
52775259 } -result <B1-Key-a>
52785260
52795261 test bind-25.30 {modifier names} -setup {
5280 frame .t.f -class Test -width 150 -height 100
5281 } -body {
5282 bind .t.f <Button2-a> foo
5283 bind .t.f
5284 } -cleanup {
5285 destroy .t.f
5262 frame .t.f -class Test -width 150 -height 100
5263 } -body {
5264 bind .t.f <Button2-a> foo
5265 bind .t.f
5266 } -cleanup {
5267 destroy .t.f
52865268 } -result <B2-Key-a>
52875269
52885270 test bind-25.31 {modifier names} -setup {
5289 frame .t.f -class Test -width 150 -height 100
5290 } -body {
5291 bind .t.f <Button3-a> foo
5292 bind .t.f
5293 } -cleanup {
5294 destroy .t.f
5271 frame .t.f -class Test -width 150 -height 100
5272 } -body {
5273 bind .t.f <Button3-a> foo
5274 bind .t.f
5275 } -cleanup {
5276 destroy .t.f
52955277 } -result <B3-Key-a>
52965278
52975279 test bind-25.32 {modifier names} -setup {
5298 frame .t.f -class Test -width 150 -height 100
5299 } -body {
5300 bind .t.f <Button4-a> foo
5301 bind .t.f
5302 } -cleanup {
5303 destroy .t.f
5280 frame .t.f -class Test -width 150 -height 100
5281 } -body {
5282 bind .t.f <Button4-a> foo
5283 bind .t.f
5284 } -cleanup {
5285 destroy .t.f
53045286 } -result <B4-Key-a>
53055287
53065288 test bind-25.33 {modifier names} -setup {
5307 frame .t.f -class Test -width 150 -height 100
5308 } -body {
5309 bind .t.f <Button5-a> foo
5310 bind .t.f
5311 } -cleanup {
5312 destroy .t.f
5289 frame .t.f -class Test -width 150 -height 100
5290 } -body {
5291 bind .t.f <Button5-a> foo
5292 bind .t.f
5293 } -cleanup {
5294 destroy .t.f
53135295 } -result <B5-Key-a>
53145296
53155297 test bind-25.34 {modifier names} -setup {
5316 frame .t.f -class Test -width 150 -height 100
5317 } -body {
5318 bind .t.f <M1-a> foo
5319 bind .t.f
5320 } -cleanup {
5321 destroy .t.f
5298 frame .t.f -class Test -width 150 -height 100
5299 } -body {
5300 bind .t.f <M1-a> foo
5301 bind .t.f
5302 } -cleanup {
5303 destroy .t.f
53225304 } -result <Mod1-Key-a>
53235305
53245306 test bind-25.35 {modifier names} -setup {
5325 frame .t.f -class Test -width 150 -height 100
5326 } -body {
5327 bind .t.f <M2-a> foo
5328 bind .t.f
5329 } -cleanup {
5330 destroy .t.f
5307 frame .t.f -class Test -width 150 -height 100
5308 } -body {
5309 bind .t.f <M2-a> foo
5310 bind .t.f
5311 } -cleanup {
5312 destroy .t.f
53315313 } -result <Mod2-Key-a>
53325314
53335315 test bind-25.36 {modifier names} -setup {
5334 frame .t.f -class Test -width 150 -height 100
5335 } -body {
5336 bind .t.f <M3-a> foo
5337 bind .t.f
5338 } -cleanup {
5339 destroy .t.f
5316 frame .t.f -class Test -width 150 -height 100
5317 } -body {
5318 bind .t.f <M3-a> foo
5319 bind .t.f
5320 } -cleanup {
5321 destroy .t.f
53405322 } -result <Mod3-Key-a>
53415323
53425324 test bind-25.37 {modifier names} -setup {
5343 frame .t.f -class Test -width 150 -height 100
5344 } -body {
5345 bind .t.f <M4-a> foo
5346 bind .t.f
5347 } -cleanup {
5348 destroy .t.f
5325 frame .t.f -class Test -width 150 -height 100
5326 } -body {
5327 bind .t.f <M4-a> foo
5328 bind .t.f
5329 } -cleanup {
5330 destroy .t.f
53495331 } -result <Mod4-Key-a>
53505332
53515333 test bind-25.38 {modifier names} -setup {
5352 frame .t.f -class Test -width 150 -height 100
5353 } -body {
5354 bind .t.f <M5-a> foo
5355 bind .t.f
5356 } -cleanup {
5357 destroy .t.f
5334 frame .t.f -class Test -width 150 -height 100
5335 } -body {
5336 bind .t.f <M5-a> foo
5337 bind .t.f
5338 } -cleanup {
5339 destroy .t.f
53585340 } -result <Mod5-Key-a>
53595341
53605342 test bind-25.39 {modifier names} -setup {
5361 frame .t.f -class Test -width 150 -height 100
5362 } -body {
5363 bind .t.f <Mod1-a> foo
5364 bind .t.f
5365 } -cleanup {
5366 destroy .t.f
5343 frame .t.f -class Test -width 150 -height 100
5344 } -body {
5345 bind .t.f <Mod1-a> foo
5346 bind .t.f
5347 } -cleanup {
5348 destroy .t.f
53675349 } -result <Mod1-Key-a>
53685350
53695351 test bind-25.40 {modifier names} -setup {
5370 frame .t.f -class Test -width 150 -height 100
5371 } -body {
5372 bind .t.f <Mod2-a> foo
5373 bind .t.f
5374 } -cleanup {
5375 destroy .t.f
5352 frame .t.f -class Test -width 150 -height 100
5353 } -body {
5354 bind .t.f <Mod2-a> foo
5355 bind .t.f
5356 } -cleanup {
5357 destroy .t.f
53765358 } -result <Mod2-Key-a>
53775359
53785360 test bind-25.41 {modifier names} -setup {
5379 frame .t.f -class Test -width 150 -height 100
5380 } -body {
5381 bind .t.f <Mod3-a> foo
5382 bind .t.f
5383 } -cleanup {
5384 destroy .t.f
5361 frame .t.f -class Test -width 150 -height 100
5362 } -body {
5363 bind .t.f <Mod3-a> foo
5364 bind .t.f
5365 } -cleanup {
5366 destroy .t.f
53855367 } -result <Mod3-Key-a>
53865368
53875369 test bind-25.42 {modifier names} -setup {
5388 frame .t.f -class Test -width 150 -height 100
5389 } -body {
5390 bind .t.f <Mod4-a> foo
5391 bind .t.f
5392 } -cleanup {
5393 destroy .t.f
5370 frame .t.f -class Test -width 150 -height 100
5371 } -body {
5372 bind .t.f <Mod4-a> foo
5373 bind .t.f
5374 } -cleanup {
5375 destroy .t.f
53945376 } -result <Mod4-Key-a>
53955377
53965378 test bind-25.43 {modifier names} -setup {
5397 frame .t.f -class Test -width 150 -height 100
5398 } -body {
5399 bind .t.f <Mod5-a> foo
5400 bind .t.f
5401 } -cleanup {
5402 destroy .t.f
5379 frame .t.f -class Test -width 150 -height 100
5380 } -body {
5381 bind .t.f <Mod5-a> foo
5382 bind .t.f
5383 } -cleanup {
5384 destroy .t.f
54035385 } -result <Mod5-Key-a>
54045386
54055387 test bind-25.44 {modifier names} -setup {
5406 frame .t.f -class Test -width 150 -height 100
5407 } -body {
5408 bind .t.f <Double-a> foo
5409 bind .t.f
5410 } -cleanup {
5411 destroy .t.f
5388 frame .t.f -class Test -width 150 -height 100
5389 } -body {
5390 bind .t.f <Double-a> foo
5391 bind .t.f
5392 } -cleanup {
5393 destroy .t.f
54125394 } -result <Double-Key-a>
54135395
54145396 test bind-25.45 {modifier names} -setup {
5415 frame .t.f -class Test -width 150 -height 100
5416 } -body {
5417 bind .t.f <Triple-a> foo
5418 bind .t.f
5419 } -cleanup {
5420 destroy .t.f
5397 frame .t.f -class Test -width 150 -height 100
5398 } -body {
5399 bind .t.f <Triple-a> foo
5400 bind .t.f
5401 } -cleanup {
5402 destroy .t.f
54215403 } -result <Triple-Key-a>
54225404
54235405 test bind-25.46 {modifier names} -setup {
5424 frame .t.f -class Test -width 150 -height 100
5425 } -body {
5426 bind .t.f {<Double 1>} foo
5427 bind .t.f
5428 } -cleanup {
5429 destroy .t.f
5406 frame .t.f -class Test -width 150 -height 100
5407 } -body {
5408 bind .t.f {<Double 1>} foo
5409 bind .t.f
5410 } -cleanup {
5411 destroy .t.f
54305412 } -result <Double-Button-1>
54315413
54325414 test bind-25.47 {modifier names} -setup {
5433 frame .t.f -class Test -width 150 -height 100
5434 } -body {
5435 bind .t.f <Triple-1> foo
5436 bind .t.f
5437 } -cleanup {
5438 destroy .t.f
5415 frame .t.f -class Test -width 150 -height 100
5416 } -body {
5417 bind .t.f <Triple-1> foo
5418 bind .t.f
5419 } -cleanup {
5420 destroy .t.f
54395421 } -result <Triple-Button-1>
54405422
54415423 test bind-25.48 {modifier names} -setup {
5442 frame .t.f -class Test -width 150 -height 100
5443 } -body {
5444 bind .t.f {<M1-M2 M3-M4 B1-Control-a>} foo
5445 bind .t.f
5446 } -cleanup {
5447 destroy .t.f
5424 frame .t.f -class Test -width 150 -height 100
5425 } -body {
5426 bind .t.f {<M1-M2 M3-M4 B1-Control-a>} foo
5427 bind .t.f
5428 } -cleanup {
5429 destroy .t.f
54485430 } -result <Control-B1-Mod1-Mod2-Mod3-Mod4-Key-a>
54495431
54505432 test bind-25.49 {modifier names} -setup {
5451 frame .t.f -class Test -width 150 -height 100
5452 } -body {
5453 bind .t.f <Extended-Return> foo
5454 bind .t.f
5455 } -cleanup {
5456 destroy .t.f
5433 frame .t.f -class Test -width 150 -height 100
5434 } -body {
5435 bind .t.f <Extended-Return> foo
5436 bind .t.f
5437 } -cleanup {
5438 destroy .t.f
54575439 } -result <Extended-Key-Return>
54585440
54595441
54605442
54615443 test bind-26.1 {event names} -setup {
5462 frame .t.f -class Test -width 150 -height 100
5444 frame .t.f -class Test -width 150 -height 100
54635445 } -body {
54645446 bind .t.f <FocusIn> {nothing}
54655447 bind .t.f
54665448 } -cleanup {
5467 destroy .t.f
5449 destroy .t.f
54685450 } -result <FocusIn>
54695451 test bind-26.2 {event names} -setup {
5470 frame .t.f -class Test -width 150 -height 100
5452 frame .t.f -class Test -width 150 -height 100
54715453 } -body {
54725454 bind .t.f <FocusOut> {nothing}
54735455 bind .t.f
54745456 } -cleanup {
5475 destroy .t.f
5457 destroy .t.f
54765458 } -result <FocusOut>
54775459 test bind-26.3 {event names} -setup {
54785460 frame .t.f -class Test -width 150 -height 100
54945476 focus -force .t.f
54955477 update
54965478 } -body {
5497 bind .t.f <Motion> "set x {event Motion}"
5498 set x xyzzy
5499 event generate .t.f <Motion>
5500 list $x [bind .t.f]
5501 } -cleanup {
5502 destroy .t.f
5479 bind .t.f <Motion> "set x {event Motion}"
5480 set x xyzzy
5481 event generate .t.f <Motion>
5482 list $x [bind .t.f]
5483 } -cleanup {
5484 destroy .t.f
55035485 } -result {{event Motion} <Motion>}
55045486
55055487 test bind-26.5 {event names: Button} -setup {
55085490 focus -force .t.f
55095491 update
55105492 } -body {
5511 bind .t.f <Button> "set x {event Button}"
5512 set x xyzzy
5513 event generate .t.f <Button>
5514 list $x [bind .t.f]
5515 } -cleanup {
5516 destroy .t.f
5493 bind .t.f <Button> "set x {event Button}"
5494 set x xyzzy
5495 event generate .t.f <Button>
5496 list $x [bind .t.f]
5497 } -cleanup {
5498 destroy .t.f
55175499 } -result {{event Button} <Button>}
55185500
55195501 test bind-26.6 {event names: ButtonPress} -setup {
55225504 focus -force .t.f
55235505 update
55245506 } -body {
5525 bind .t.f <ButtonPress> "set x {event ButtonPress}"
5526 set x xyzzy
5527 event generate .t.f <ButtonPress>
5528 list $x [bind .t.f]
5529 } -cleanup {
5530 destroy .t.f
5507 bind .t.f <ButtonPress> "set x {event ButtonPress}"
5508 set x xyzzy
5509 event generate .t.f <ButtonPress>
5510 list $x [bind .t.f]
5511 } -cleanup {
5512 destroy .t.f
55315513 } -result {{event ButtonPress} <Button>}
55325514
55335515 test bind-26.7 {event names: ButtonRelease} -setup {
55365518 focus -force .t.f
55375519 update
55385520 } -body {
5539 bind .t.f <ButtonRelease> "set x {event ButtonRelease}"
5540 set x xyzzy
5541 event generate .t.f <ButtonRelease>
5542 list $x [bind .t.f]
5543 } -cleanup {
5544 destroy .t.f
5521 bind .t.f <ButtonRelease> "set x {event ButtonRelease}"
5522 set x xyzzy
5523 event generate .t.f <ButtonRelease>
5524 list $x [bind .t.f]
5525 } -cleanup {
5526 destroy .t.f
55455527 } -result {{event ButtonRelease} <ButtonRelease>}
55465528
55475529 test bind-26.8 {event names: Colormap} -setup {
55505532 focus -force .t.f
55515533 update
55525534 } -body {
5553 bind .t.f <Colormap> "set x {event Colormap}"
5554 set x xyzzy
5555 event generate .t.f <Colormap>
5556 list $x [bind .t.f]
5557 } -cleanup {
5558 destroy .t.f
5535 bind .t.f <Colormap> "set x {event Colormap}"
5536 set x xyzzy
5537 event generate .t.f <Colormap>
5538 list $x [bind .t.f]
5539 } -cleanup {
5540 destroy .t.f
55595541 } -result {{event Colormap} <Colormap>}
55605542
55615543 test bind-26.9 {event names: Enter} -setup {
55645546 focus -force .t.f
55655547 update
55665548 } -body {
5567 bind .t.f <Enter> "set x {event Enter}"
5568 set x xyzzy
5569 event generate .t.f <Enter>
5570 list $x [bind .t.f]
5571 } -cleanup {
5572 destroy .t.f
5549 bind .t.f <Enter> "set x {event Enter}"
5550 set x xyzzy
5551 event generate .t.f <Enter>
5552 list $x [bind .t.f]
5553 } -cleanup {
5554 destroy .t.f
55735555 } -result {{event Enter} <Enter>}
55745556
55755557 test bind-26.10 {event names: Leave} -setup {
55785560 focus -force .t.f
55795561 update
55805562 } -body {
5581 bind .t.f <Leave> "set x {event Leave}"
5582 set x xyzzy
5583 event generate .t.f <Leave>
5584 list $x [bind .t.f]
5585 } -cleanup {
5586 destroy .t.f
5563 bind .t.f <Leave> "set x {event Leave}"
5564 set x xyzzy
5565 event generate .t.f <Leave>
5566 list $x [bind .t.f]
5567 } -cleanup {
5568 destroy .t.f
55875569 } -result {{event Leave} <Leave>}
55885570
55895571 test bind-26.11 {event names: Expose} -setup {
55925574 focus -force .t.f
55935575 update
55945576 } -body {
5595 bind .t.f <Expose> "set x {event Expose}"
5596 set x xyzzy
5597 event generate .t.f <Expose>
5598 list $x [bind .t.f]
5599 } -cleanup {
5600 destroy .t.f
5577 bind .t.f <Expose> "set x {event Expose}"
5578 set x xyzzy
5579 event generate .t.f <Expose>
5580 list $x [bind .t.f]
5581 } -cleanup {
5582 destroy .t.f
56015583 } -result {{event Expose} <Expose>}
56025584
56035585 test bind-26.12 {event names: Key} -setup {
56065588 focus -force .t.f
56075589 update
56085590 } -body {
5609 bind .t.f <Key> "set x {event Key}"
5610 set x xyzzy
5611 event generate .t.f <Key>
5612 list $x [bind .t.f]
5613 } -cleanup {
5614 destroy .t.f
5591 bind .t.f <Key> "set x {event Key}"
5592 set x xyzzy
5593 event generate .t.f <Key>
5594 list $x [bind .t.f]
5595 } -cleanup {
5596 destroy .t.f
56155597 } -result {{event Key} <Key>}
56165598
56175599 test bind-26.13 {event names: KeyPress} -setup {
56205602 focus -force .t.f
56215603 update
56225604 } -body {
5623 bind .t.f <KeyPress> "set x {event KeyPress}"
5624 set x xyzzy
5625 event generate .t.f <KeyPress>
5626 list $x [bind .t.f]
5627 } -cleanup {
5628 destroy .t.f
5605 bind .t.f <KeyPress> "set x {event KeyPress}"
5606 set x xyzzy
5607 event generate .t.f <KeyPress>
5608 list $x [bind .t.f]
5609 } -cleanup {
5610 destroy .t.f
56295611 } -result {{event KeyPress} <Key>}
56305612
56315613 test bind-26.14 {event names: KeyRelease} -setup {
56345616 focus -force .t.f
56355617 update
56365618 } -body {
5637 bind .t.f <KeyRelease> "set x {event KeyRelease}"
5638 set x xyzzy
5639 event generate .t.f <KeyRelease>
5640 list $x [bind .t.f]
5641 } -cleanup {
5642 destroy .t.f
5619 bind .t.f <KeyRelease> "set x {event KeyRelease}"
5620 set x xyzzy
5621 event generate .t.f <KeyRelease>
5622 list $x [bind .t.f]
5623 } -cleanup {
5624 destroy .t.f
56435625 } -result {{event KeyRelease} <KeyRelease>}
56445626
56455627 test bind-26.15 {event names: Property} -setup {
56485630 focus -force .t.f
56495631 update
56505632 } -body {
5651 bind .t.f <Property> "set x {event Property}"
5652 set x xyzzy
5653 event generate .t.f <Property>
5654 list $x [bind .t.f]
5655 } -cleanup {
5656 destroy .t.f
5633 bind .t.f <Property> "set x {event Property}"
5634 set x xyzzy
5635 event generate .t.f <Property>
5636 list $x [bind .t.f]
5637 } -cleanup {
5638 destroy .t.f
56575639 } -result {{event Property} <Property>}
56585640
56595641 test bind-26.16 {event names: Visibility} -setup {
56625644 focus -force .t.f
56635645 update
56645646 } -body {
5665 bind .t.f <Visibility> "set x {event Visibility}"
5666 set x xyzzy
5667 event generate .t.f <Visibility>
5668 list $x [bind .t.f]
5669 } -cleanup {
5670 destroy .t.f
5647 bind .t.f <Visibility> "set x {event Visibility}"
5648 set x xyzzy
5649 event generate .t.f <Visibility>
5650 list $x [bind .t.f]
5651 } -cleanup {
5652 destroy .t.f
56715653 } -result {{event Visibility} <Visibility>}
56725654
56735655 test bind-26.17 {event names: Activate} -setup {
56765658 focus -force .t.f
56775659 update
56785660 } -body {
5679 bind .t.f <Activate> "set x {event Activate}"
5680 set x xyzzy
5681 event generate .t.f <Activate>
5682 list $x [bind .t.f]
5683 } -cleanup {
5684 destroy .t.f
5661 bind .t.f <Activate> "set x {event Activate}"
5662 set x xyzzy
5663 event generate .t.f <Activate>
5664 list $x [bind .t.f]
5665 } -cleanup {
5666 destroy .t.f
56855667 } -result {{event Activate} <Activate>}
56865668
56875669 test bind-26.18 {event names: Deactivate} -setup {
56905672 focus -force .t.f
56915673 update
56925674 } -body {
5693 bind .t.f <Deactivate> "set x {event Deactivate}"
5694 set x xyzzy
5695 event generate .t.f <Deactivate>
5696 list $x [bind .t.f]
5697 } -cleanup {
5698 destroy .t.f
5675 bind .t.f <Deactivate> "set x {event Deactivate}"
5676 set x xyzzy
5677 event generate .t.f <Deactivate>
5678 list $x [bind .t.f]
5679 } -cleanup {
5680 destroy .t.f
56995681 } -result {{event Deactivate} <Deactivate>}
57005682
57015683
57065688 focus -force .t.f
57075689 update
57085690 } -body {
5709 bind .t.f <Circulate> "set x {event Circulate}"
5710 set x xyzzy
5711 event generate .t.f <Circulate>
5712 list $x [bind .t.f]
5713 } -cleanup {
5714 destroy .t.f
5691 bind .t.f <Circulate> "set x {event Circulate}"
5692 set x xyzzy
5693 event generate .t.f <Circulate>
5694 list $x [bind .t.f]
5695 } -cleanup {
5696 destroy .t.f
57155697 } -result {{event Circulate} <Circulate>}
57165698
57175699 test bind-26.20 {event names: Configure} -setup {
57205702 focus -force .t.f
57215703 update
57225704 } -body {
5723 bind .t.f <Configure> "set x {event Configure}"
5724 set x xyzzy
5725 event generate .t.f <Configure>
5726 list $x [bind .t.f]
5727 } -cleanup {
5728 destroy .t.f
5705 bind .t.f <Configure> "set x {event Configure}"
5706 set x xyzzy
5707 event generate .t.f <Configure>
5708 list $x [bind .t.f]
5709 } -cleanup {
5710 destroy .t.f
57295711 } -result {{event Configure} <Configure>}
57305712
57315713 test bind-26.21 {event names: Gravity} -setup {
57345716 focus -force .t.f
57355717 update
57365718 } -body {
5737 bind .t.f <Gravity> "set x {event Gravity}"
5738 set x xyzzy
5739 event generate .t.f <Gravity>
5740 list $x [bind .t.f]
5741 } -cleanup {
5742 destroy .t.f
5719 bind .t.f <Gravity> "set x {event Gravity}"
5720 set x xyzzy
5721 event generate .t.f <Gravity>
5722 list $x [bind .t.f]
5723 } -cleanup {
5724 destroy .t.f
57435725 } -result {{event Gravity} <Gravity>}
57445726
57455727 test bind-26.22 {event names: Map} -setup {
57485730 focus -force .t.f
57495731 update
57505732 } -body {
5751 bind .t.f <Map> "set x {event Map}"
5752 set x xyzzy
5753 event generate .t.f <Map>
5754 list $x [bind .t.f]
5755 } -cleanup {
5756 destroy .t.f
5733 bind .t.f <Map> "set x {event Map}"
5734 set x xyzzy
5735 event generate .t.f <Map>
5736 list $x [bind .t.f]
5737 } -cleanup {
5738 destroy .t.f
57575739 } -result {{event Map} <Map>}
57585740
57595741 test bind-26.23 {event names: Reparent} -setup {
57625744 focus -force .t.f
57635745 update
57645746 } -body {
5765 bind .t.f <Reparent> "set x {event Reparent}"
5766 set x xyzzy
5767 event generate .t.f <Reparent>
5768 list $x [bind .t.f]
5769 } -cleanup {
5770 destroy .t.f
5747 bind .t.f <Reparent> "set x {event Reparent}"
5748 set x xyzzy
5749 event generate .t.f <Reparent>
5750 list $x [bind .t.f]
5751 } -cleanup {
5752 destroy .t.f
57715753 } -result {{event Reparent} <Reparent>}
57725754
57735755 test bind-26.24 {event names: Unmap} -setup {
57765758 focus -force .t.f
57775759 update
57785760 } -body {
5779 bind .t.f <Unmap> "set x {event Unmap}"
5780 set x xyzzy
5781 event generate .t.f <Unmap>
5782 list $x [bind .t.f]
5783 } -cleanup {
5784 destroy .t.f
5761 bind .t.f <Unmap> "set x {event Unmap}"
5762 set x xyzzy
5763 event generate .t.f <Unmap>
5764 list $x [bind .t.f]
5765 } -cleanup {
5766 destroy .t.f
57855767 } -result {{event Unmap} <Unmap>}
57865768
57875769
57905772 } -returnCodes error -result {specified button "1" for non-button event}
57915773 test bind-27.2 {button names} -body {
57925774 bind .t <Button-6> foo
5793 } -returnCodes error -result {specified keysym "6" for non-key event}
5775 } -returnCodes error -result {bad button number "6"}
57945776 test bind-27.3 {button names} -setup {
57955777 frame .t.f -class Test -width 150 -height 100
57965778 pack .t.f
59355917 } -cleanup {
59365918 destroy .t.f
59375919 } -result {X x {keysym X}}
5938
5939
5940 test bind-29.1 {Tk_BackgroundError procedure} -setup {
5920 test bind-28.9 {keysym names, Eth -> ETH} -body {
5921 frame .t.f -class Test -width 150 -height 100
5922 bind .t.f <Eth> foo
5923 bind .t.f
5924 } -cleanup {
5925 destroy .t.f
5926 } -result {<Key-ETH>}
5927 test bind-28.10 {keysym names, Ooblique -> Oslash} -body {
5928 frame .t.f -class Test -width 150 -height 100
5929 bind .t.f <Ooblique> foo
5930 bind .t.f
5931 } -cleanup {
5932 destroy .t.f
5933 } -result {<Key-Oslash>}
5934 test bind-28.11 {keysym names, gcedilla} -body {
5935 frame .t.f -class Test -width 150 -height 100
5936 bind .t.f <gcedilla> foo
5937 bind .t.f
5938 } -cleanup {
5939 destroy .t.f
5940 } -result {<Key-gcedilla>}
5941 test bind-28.12 {keysym names, Greek_IOTAdiaeresis -> Greek_IOTAdieresis} -body {
5942 frame .t.f -class Test -width 150 -height 100
5943 bind .t.f <Greek_IOTAdiaeresis> foo
5944 bind .t.f
5945 } -cleanup {
5946 destroy .t.f
5947 } -result {<Key-Greek_IOTAdieresis>}
5948
5949
5950 test bind-29.1 {Tcl_BackgroundError procedure} -setup {
59415951 proc bgerror msg {
59425952 global x errorInfo
59435953 set x [list $msg $errorInfo]
59605970 while executing
59615971 "error "This is a test""
59625972 (command bound to event)}}
5963
5964 test bind-29.2 {Tk_BackgroundError procedure} -setup {
5973
5974 test bind-29.2 {Tcl_BackgroundError procedure} -setup {
59655975 proc do {} {
59665976 event generate .t.f <Button>
59675977 event generate .t.f <ButtonRelease>
61256135 destroy .t.f
61266136 } -result {{} {} {TestUserData >b<}}
61276137
6128 test bind-32 {-warp, window was destroyed before the idle callback DoWarp} -setup {
6138 test bind-32.1 {-warp, window was destroyed before the idle callback DoWarp} -setup {
61296139 frame .t.f
61306140 pack .t.f
61316141 focus -force .t.f
61376147 update ; # shall simply not crash
61386148 } -cleanup {
61396149 } -result {}
6140
6150 test bind-32.2 {detection of double click should not fail} -setup {
6151 pack [frame .t.f]
6152 focus -force .t.f
6153 bind .t.f <Double-Button-1> { set x "Double" }
6154 update
6155 set x {}
6156 } -body {
6157 event generate .t.f <ButtonPress-1>
6158 event generate .t.f <ButtonRelease-1>
6159 # Simulate a lot of intervening exposure events. The old implementation
6160 # that used an event ring overflowed, and the double click was not detected.
6161 # But new implementation should work properly.
6162 for {set i 0} {$i < 1000} {incr i} {
6163 event generate .t.f <Expose>
6164 }
6165 event generate .t.f <ButtonPress-1>
6166 event generate .t.f <ButtonRelease-1>
6167 set x
6168 } -cleanup {
6169 destroy .t.f
6170 } -result {Double}
6171 test bind-32.3 {should trigger best match of modifier states} -setup {
6172 pack [frame .t.f]
6173 focus -force .t.f
6174 update
6175 set x {}
6176 } -body {
6177 bind .t.f <Alt-Control-Key-A> { lappend x "Alt-Control" }
6178 bind .t.f <Shift-Control-Key-A> { lappend x "Shift-Control" }
6179 bind .t.f <Shift-Key-A> { lappend x "Shift" }
6180 event generate .t.f <Alt-Control-Key-A>
6181 set x
6182 } -cleanup {
6183 destroy .t.f
6184 } -result {Shift-Control}
6185 test bind-32.4 {should not trigger Double-1} -setup {
6186 pack [frame .t.f]
6187 focus -force .t.f
6188 update
6189 set x {}
6190 } -body {
6191 bind .t.f <Double-1> { set x "Double" }
6192 event generate .t.f <1> -time current
6193 after 1000
6194 event generate .t.f <1> -time current
6195 set x
6196 } -cleanup {
6197 destroy .t.f
6198 } -result {}
6199 test bind-32.5 {should trigger Quadruple-1} -setup {
6200 pack [frame .t.f]
6201 focus -force .t.f
6202 update
6203 set x {}
6204 } -body {
6205 bind .t.f <Quadruple-1> { set x "Quadruple" }
6206 bind .t.f <Triple-1> { set x "Triple" }
6207 bind .t.f <Double-1> { set x "Double" }
6208 bind .t.f <1> { set x "Single" }
6209 # Old implementation triggered "Double", but new implementation
6210 # triggers "Quadruple", the latter behavior conforms to other toolkits.
6211 event generate .t.f <Button-1> -time 0
6212 event generate .t.f <Button-1> -time 400
6213 event generate .t.f <Button-1> -time 800
6214 event generate .t.f <Button-1> -time 1200
6215 set x
6216 } -cleanup {
6217 destroy .t.f
6218 } -result {Quadruple}
6219 test bind-32.6 {problem with sendevent} -setup {
6220 pack [frame .t.f]
6221 focus -force .t.f
6222 update
6223 set x {}
6224 } -body {
6225 # Old implementation was losing sendevent value
6226 bind .t.f <FocusIn> { set x "sendevent=%E" }
6227 event generate .t.f <FocusIn> -sendevent 1
6228 set x
6229 } -cleanup {
6230 destroy .t.f
6231 } -result {sendevent=1}
6232 test bind-32.7 {test sequences} -setup {
6233 pack [frame .t.f]
6234 focus -force .t.f
6235 update
6236 set x {}
6237 } -body {
6238 bind .t.f <Double-1> { lappend x "Double" }
6239 bind .t.f <1><1><a> { lappend x "11" }
6240 event generate .t.f <1>
6241 event generate .t.f <1>
6242 event generate .t.f <a>
6243 set x
6244 } -cleanup {
6245 destroy .t.f
6246 } -result {Double 11}
6247 test bind-32.8 {test sequences} -setup {
6248 pack [frame .t.f]
6249 focus -force .t.f
6250 update
6251 set x {}
6252 } -body {
6253 bind .t.f <a><1><Double-1><1><a> { lappend x "Double" }
6254 event generate .t.f <a>
6255 event generate .t.f <1>
6256 event generate .t.f <1>
6257 event generate .t.f <1>
6258 event generate .t.f <1>
6259 event generate .t.f <a>
6260 set x
6261 } -cleanup {
6262 destroy .t.f
6263 } -result {Double}
6264 test bind-32.9 {trigger events for modifier keys} -setup {
6265 pack [frame .t.f]
6266 focus -force .t.f
6267 update
6268 set x {}
6269 } -body {
6270 bind .t.f <Any-Key> { set x "Key" }
6271 event generate .t.f <KeyPress> -keysym Caps_Lock
6272 set x
6273 } -cleanup {
6274 destroy .t.f
6275 } -result {Key}
6276 test bind-32.10 {reset key state when destroying window} -setup {
6277 set x {}
6278 } -body {
6279 pack [frame .t.f]; update; focus -force .t.f
6280 bind .t.f <Key-A> { set x "A" }
6281 event generate .t.f <KeyPress-A>
6282 event generate .t.f <KeyPress-A>
6283 destroy .t.f; update
6284 pack [frame .t.f]; update; focus -force .t.f
6285 bind .t.f <Key-A> { set x "A" }
6286 bind .t.f <Double-Key-A> { set x "AA" }
6287 event generate .t.f <KeyPress-A>
6288 destroy .t.f
6289 set x
6290 } -result {A}
6291 test bind-32.11 {match detailed virtual} -setup {
6292 pack [frame .t.f -class Test]
6293 focus -force .t.f
6294 update
6295 set x {}
6296 } -body {
6297 event add <<TestControlButton1>> <Control-Button-1>
6298 bind Test <<TestControlButton1>> { set x "Control-Button-1" }
6299 bind Test <Button-1> { set x "Button-1" }
6300 bind .t.f <Button-1> { set x "Button-1" }
6301 event generate .t.f <Control-ButtonPress-1>
6302 set x
6303 } -cleanup {
6304 destroy .t.f
6305 event delete <<TestControlButton1>>
6306 bind Test <Button-1> {#}
6307 } -result {Control-Button-1}
6308 test bind-32.12 {don't detect repetition when window has changed} -setup {
6309 pack [frame .t.f]
6310 pack [frame .t.g]
6311 focus -force .t.f
6312 update
6313 set x {}
6314 } -body {
6315 bind .t.f <Button-1> { set x "1" }
6316 bind .t.f <Double-Button-1> { set x "11" }
6317 event generate .t.f <ButtonPress-1>
6318 event generate .t.g <ButtonPress-1>
6319 event generate .t.f <ButtonPress-1>
6320 set x
6321 } -cleanup {
6322 destroy .t.f
6323 destroy .t.g
6324 } -result {1}
6325 test bind-32.13 {don't detect repetition when window has changed} -setup {
6326 pack [frame .t.f]
6327 pack [frame .t.g]
6328 update
6329 set x {}
6330 } -body {
6331 bind .t.f <Key-A> { set x "A" }
6332 bind .t.f <Double-Key-A> { set x "AA" }
6333 focus -force .t.f; event generate .t.f <KeyPress-A>
6334 focus -force .t.g; event generate .t.g <KeyPress-A>
6335 focus -force .t.f; event generate .t.f <KeyPress-A>
6336 set x
6337 } -cleanup {
6338 destroy .t.f
6339 destroy .t.g
6340 } -result {A}
6341 test bind-32.14 {don't detect repetition when window has changed} -setup {
6342 pack [frame .t.f]
6343 pack [frame .t.g]
6344 update
6345 set x {}
6346 } -body {
6347 bind .t.f <ButtonPress-1> { set x "1" }
6348 bind .t.f <Double-ButtonPress-1> { set x "11" }
6349 focus -force .t.f; event generate .t.f <ButtonPress-1>
6350 focus -force .t.g; event generate .t.g <ButtonPress-1>
6351 focus -force .t.f; event generate .t.f <ButtonPress-1>
6352 set x
6353 } -cleanup {
6354 destroy .t.f
6355 destroy .t.g
6356 } -result {1}
6357 test bind-32.15 {reset button state when destroying window} -setup {
6358 set x {}
6359 } -body {
6360 pack [frame .t.f]; update; focus -force .t.f
6361 bind .t.f <ButtonPress-1> { set x "1" }
6362 event generate .t.f <ButtonPress-1>
6363 event generate .t.f <ButtonPress-1>
6364 destroy .t.f; update
6365 pack [frame .t.f]; update; focus -force .t.f
6366 bind .t.f <ButtonPress-1> { set x "1" }
6367 bind .t.f <Double-ButtonPress-1> { set x "11" }
6368 event generate .t.f <ButtonPress-1>
6369 destroy .t.f
6370 set x
6371 } -result {1}
6372
6373 test bind-33.1 {prefer longest match} -setup {
6374 pack [frame .t.f]
6375 focus -force .t.f
6376 update
6377 set x {}
6378 } -body {
6379 bind .t.f <a><1><1> { lappend x "a11" }
6380 bind .t.f <Double-1> { lappend x "Double" }
6381 event generate .t.f <a>
6382 event generate .t.f <1>
6383 event generate .t.f <1>
6384 set x
6385 } -cleanup {
6386 destroy .t.f
6387 } -result {a11}
6388 test bind-33.2 {should prefer most specific event} -setup {
6389 pack [frame .t.f]
6390 focus -force .t.f
6391 update
6392 set x {}
6393 } -body {
6394 bind .t.f <Double-1> { lappend x "Double" }
6395 bind .t.f <1><1> { lappend x "11" }
6396 event generate .t.f <1>
6397 event generate .t.f <1>
6398 set x
6399 } -cleanup {
6400 destroy .t.f
6401 # This test case shows that old implementation has an issue, because
6402 # it is expected that <Double-1> is matching, this binding
6403 # is more specific. But new implementation will be conform to old,
6404 # and so "11" is the expected result.
6405 } -result {11}
6406 test bind-33.3 {should prefer most specific event} -setup {
6407 pack [frame .t.f]
6408 focus -force .t.f
6409 update
6410 set x {}
6411 } -body {
6412 bind .t.f <a><Double-1><a> { lappend x "Double" }
6413 bind .t.f <a><1><1><a> { lappend x "11" }
6414 event generate .t.f <a>
6415 event generate .t.f <1>
6416 event generate .t.f <1>
6417 event generate .t.f <a>
6418 set x
6419 } -cleanup {
6420 destroy .t.f
6421 # Also this test case shows that old implementation has an issue, it is
6422 # expected that <a><Double-1><a> is matching, because <Double-1> is more
6423 # specific than <1><1>. But new implementation will be conform to old,
6424 # and so "11" is the expected result.
6425 } -result {11}
6426 test bind-33.4 {prefer most specific event} -setup {
6427 pack [frame .t.f]
6428 focus -force .t.f
6429 update
6430 set x {}
6431 } -body {
6432 bind .t.f <1><1> { lappend x "11" }
6433 bind .t.f <Double-1> { lappend x "Double" }
6434 event generate .t.f <1> -time 0
6435 event generate .t.f <1> -time 1000
6436 set x
6437 } -cleanup {
6438 destroy .t.f
6439 } -result {11}
6440 test bind-33.5 {prefer most specific event} -setup {
6441 pack [frame .t.f]
6442 focus -force .t.f
6443 update
6444 set x {}
6445 } -body {
6446 bind .t.f <1><1> { lappend x "11" }
6447 bind .t.f <Double-ButtonPress> { lappend x "Double" }
6448 event generate .t.f <1>
6449 event generate .t.f <1>
6450 set x
6451 } -cleanup {
6452 destroy .t.f
6453 } -result {11}
6454 test bind-33.6 {prefer most specific event} -setup {
6455 pack [frame .t.f]
6456 focus -force .t.f
6457 update
6458 set x {}
6459 } -body {
6460 bind .t.f <a><1><1><1><1><a> { lappend x "1111" }
6461 bind .t.f <a><ButtonPress><Double-ButtonPress><ButtonPress><a> { lappend x "Any-Double-Any" }
6462 event generate .t.f <a>
6463 event generate .t.f <1>
6464 event generate .t.f <1>
6465 event generate .t.f <1>
6466 event generate .t.f <1>
6467 event generate .t.f <a>
6468 set x
6469 } -cleanup {
6470 destroy .t.f
6471 } -result {1111}
6472 test bind-33.7 {prefer most specific event} -setup {
6473 pack [frame .t.f]
6474 focus -force .t.f
6475 update
6476 set x {}
6477 } -body {
6478 bind .t.f <ButtonPress-1><a> { lappend x "1" }
6479 bind .t.f <ButtonPress><a> { lappend x "Any" }
6480 event generate .t.f <1>
6481 event generate .t.f <a>
6482 set x
6483 } -cleanup {
6484 destroy .t.f
6485 } -result {1}
6486 test bind-33.8 {prefer most specific event} -setup {
6487 pack [frame .t.f]
6488 focus -force .t.f
6489 update
6490 set x {}
6491 } -body {
6492 bind .t.f <Double-ButtonPress-1><a> { lappend x "1" }
6493 bind .t.f <ButtonPress><ButtonPress><a> { lappend x "Any" }
6494 event generate .t.f <1>
6495 event generate .t.f <1>
6496 event generate .t.f <a>
6497 set x
6498 } -cleanup {
6499 destroy .t.f
6500 } -result {1}
6501 test bind-33.9 {prefer last in case of homogeneous equal patterns} -setup {
6502 pack [frame .t.f]
6503 focus -force .t.f
6504 update
6505 set x {}
6506 } -body {
6507 bind .t.f <1><2><2><Double-1> { lappend x "first" }
6508 bind .t.f <1><Double-2><1><1> { lappend x "last" }
6509 event generate .t.f <1>
6510 event generate .t.f <2>
6511 event generate .t.f <2>
6512 event generate .t.f <1>
6513 event generate .t.f <1>
6514 set x
6515 } -cleanup {
6516 destroy .t.f
6517 } -result {last}
6518 test bind-33.10 {prefer last in case of homogeneous equal patterns} -setup {
6519 pack [frame .t.f]
6520 focus -force .t.f
6521 update
6522 set x {}
6523 } -body {
6524 bind .t.f <1><Double-2><1><1> { lappend x "first" }
6525 bind .t.f <1><2><2><Double-1> { lappend x "last" }
6526 event generate .t.f <1>
6527 event generate .t.f <2>
6528 event generate .t.f <2>
6529 event generate .t.f <1>
6530 event generate .t.f <1>
6531 set x
6532 } -cleanup {
6533 destroy .t.f
6534 } -result {last}
6535 test bind-33.11 {should prefer most specific} -setup {
6536 pack [frame .t.f]
6537 focus -force .t.f
6538 update
6539 set x {}
6540 } -body {
6541 bind .t.f <2><Double-1><Double-2><Double-1><2><2> { lappend x "first" }
6542 bind .t.f <2><1><1><2><2><Double-1><Double-2> { lappend x "last" }
6543 event generate .t.f <2>
6544 event generate .t.f <1>
6545 event generate .t.f <1>
6546 event generate .t.f <2>
6547 event generate .t.f <2>
6548 event generate .t.f <1>
6549 event generate .t.f <1>
6550 event generate .t.f <2>
6551 event generate .t.f <2>
6552 set x
6553 } -cleanup {
6554 destroy .t.f
6555 # This test case shows that old implementation has an issue, because
6556 # it is expected that first one is matching, this binding
6557 # is more specific. But new implementation will be conform to old,
6558 # and so "last" is the expected result.
6559 } -result {last}
6560 test bind-33.12 {prefer last in case of homogeneous equal patterns} -setup {
6561 pack [frame .t.f]
6562 focus -force .t.f
6563 update
6564 set x {}
6565 } -body {
6566 bind .t.f <Control-1><1> { lappend x "first" }
6567 bind .t.f <1><Control-1> { lappend x "last" }
6568 event generate .t.f <Control-1>
6569 event generate .t.f <Control-1>
6570 set x
6571 } -cleanup {
6572 destroy .t.f
6573 } -result {last}
6574 test bind-33.13 {prefer last in case of homogeneous equal patterns} -setup {
6575 pack [frame .t.f]
6576 focus -force .t.f
6577 update
6578 set x {}
6579 } -body {
6580 bind .t.f <1><Control-1> { lappend x "first" }
6581 bind .t.f <Control-1><1> { lappend x "last" }
6582 event generate .t.f <Control-1>
6583 event generate .t.f <Control-1>
6584 set x
6585 } -cleanup {
6586 destroy .t.f
6587 # Old implementation failed, and returned "first", but this was wrong,
6588 # because both bindings are homogeneous equal, so the most recently defined
6589 # must be preferred.
6590 } -result {last}
6591 test bind-33.14 {prefer last in case of homogeneous equal patterns} -setup {
6592 pack [frame .t.f]
6593 focus -force .t.f
6594 update
6595 set x {}
6596 } -body {
6597 bind .t.f <1><ButtonPress><1><ButtonPress> { lappend x "first" }
6598 bind .t.f <ButtonPress><1><ButtonPress><1> { lappend x "last" }
6599 event generate .t.f <1>
6600 event generate .t.f <1>
6601 event generate .t.f <1>
6602 event generate .t.f <1>
6603 set x
6604 } -cleanup {
6605 destroy .t.f
6606 } -result {last}
6607 test bind-33.15 {prefer last in case of homogeneous equal patterns} -setup {
6608 pack [frame .t.f]
6609 focus -force .t.f
6610 update
6611 set x {}
6612 } -body {
6613 bind .t.f <ButtonPress><1><ButtonPress><1> { lappend x "first" }
6614 bind .t.f <1><ButtonPress><1><ButtonPress> { lappend x "last" }
6615 event generate .t.f <1>
6616 event generate .t.f <1>
6617 event generate .t.f <1>
6618 event generate .t.f <1>
6619 set x
6620 } -cleanup {
6621 destroy .t.f
6622 # Old implementation failed, and returned "first", but this was wrong,
6623 # because both bindings are homogeneous equal, so the most recently defined
6624 # must be preferred.
6625 } -result {last}
6626
6627 test bind-34.1 {-warp works relatively to a window} -setup {
6628 toplevel .top
6629 } -body {
6630 # In order to avoid platform-dependent coordinate results due to
6631 # decorations and borders, this test warps the pointer twice
6632 # relatively to a window that moved in the meantime, and checks
6633 # how much the pointer moved
6634 wm geometry .top +200+200
6635 update
6636 event generate .top <Motion> -x 20 -y 20 -warp 1
6637 update idletasks ; # DoWarp is an idle callback
6638 after 50 ; # Win specific - wait for SendInput to be executed
6639 set pointerPos1 [winfo pointerxy .t]
6640 wm geometry .top +600+600
6641 update
6642 event generate .top <Motion> -x 20 -y 20 -warp 1
6643 update idletasks ; # DoWarp is an idle callback
6644 after 50 ; # Win specific - wait for SendInput to be executed
6645 set pointerPos2 [winfo pointerxy .t]
6646 # from the first warped position to the second one, the mouse
6647 # pointer should have moved the same amount as the window moved
6648 set res 1
6649 foreach pos1 $pointerPos1 pos2 $pointerPos2 {
6650 if {$pos1 != [expr {$pos2 - 400}]} {
6651 set res [list $pointerPos1 $pointerPos2]
6652 }
6653 }
6654 set res
6655 } -cleanup {
6656 destroy .top
6657 } -result {1}
6658 test bind-34.2 {-warp works relatively to the screen} -setup {
6659 } -body {
6660 # Contrary to bind-34.1, we're directly checking screen coordinates
6661 event generate {} <Motion> -x 20 -y 20 -warp 1
6662 update idletasks ; # DoWarp is an idle callback
6663 after 50 ; # Win specific - wait for SendInput to be executed
6664 set res [winfo pointerxy .]
6665 event generate {} <Motion> -x 200 -y 200 -warp 1
6666 update idletasks ; # DoWarp is an idle callback
6667 after 50 ; # Win specific - wait for SendInput to be executed
6668 lappend res {*}[winfo pointerxy .]
6669 } -cleanup {
6670 } -result {20 20 200 200}
6671 test bind-34.3 {-warp works with null or negative coordinates} -setup {
6672 } -body {
6673 event generate {} <Motion> -x 0 -y 0 -warp 1
6674 update idletasks ; # DoWarp is an idle callback
6675 after 50 ; # Win specific - wait for SendInput to be executed
6676 set res [winfo pointerxy .]
6677 event generate {} <Motion> -x -1 -y -1 -warp 1
6678 update idletasks ; # DoWarp is an idle callback
6679 after 50 ; # Win specific - wait for SendInput to be executed
6680 foreach dim [winfo pointerxy .] {
6681 if {$dim <= 0} {
6682 lappend res ok
6683 } else {
6684 lappend res $dim
6685 }
6686 }
6687 set res
6688 } -cleanup {
6689 } -result {0 0 ok ok}
61416690
61426691 # cleanup
61436692 cleanupTests
61446693 return
61456694
6695 # vi:set ts=4 sw=4 et:
61466696 # Local Variables:
61476697 # mode: tcl
61486698 # End:
+0
-41
tests/bugs.tcl less more
0 # This file is a Tcl script to test out various known bugs that will
1 # cause Tk to crash. This file ends with .tcl instead of .test to make
2 # sure it isn't run when you type "source all". We currently are not
3 # shipping this file with the rest of the source release.
4 #
5 # Copyright (c) 1996 Sun Microsystems, Inc.
6 #
7 # See the file "license.terms" for information on usage and redistribution
8 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9
10 if {[info procs test] != "test"} {
11 source defs
12 }
13
14 test crash-1.0 {imgPhoto} {
15 image create photo p1
16 image create photo p2
17 catch {image create photo p2 -file bogus}
18 p1 copy p2
19 label .l -image p1
20 destroy .l
21 set foo ""
22 } {}
23
24 test crash-1.1 {color} {
25 . configure -bg rgb:345
26 set foo ""
27 } {}
28
29
30
31
32
33
34
35
36
37
38
39
40
34433443 set expectedwidth [expr {$textwidth + 2*[.b cget -borderwidth] \
34443444 + 2*[.b cget -highlightthickness] + 2*[.b cget -padx]}]
34453445 incr expectedwidth 2 ; # added (hardcoded) in tkUnixButton.c
3446 set result [expr $expectedwidth == [winfo reqwidth .b]]
3446 set result [expr {$expectedwidth == [winfo reqwidth .b]}]
34473447 set linespace [lindex [font metrics [.b cget -font] -displayof .b] 5]
34483448 set expectedheight [expr {$linespace + 2*[.b cget -borderwidth] \
34493449 + 2*[.b cget -highlightthickness] + 2*[.b cget -pady]}]
34503450 incr expectedheight 2 ; # added (hardcoded) in tkUnixButton.c
3451 lappend result [expr $expectedheight == [winfo reqheight .b]]
3451 lappend result [expr {$expectedheight == [winfo reqheight .b]}]
34523452 # 2. button with a bitmap image
34533453 # there is no access to characteristics the predefined bitmaps,
34543454 # so define one as an image (copied from questhead.xbm)
34673467 set expectedwidth [expr {[image width $myquesthead] + 2*[.b cget -borderwidth] \
34683468 + 2*[.b cget -highlightthickness]}]
34693469 incr expectedwidth 2 ; # added (hardcoded) in tkUnixButton.c
3470 lappend result [expr $expectedwidth == [winfo reqwidth .b]]
3470 lappend result [expr {$expectedwidth == [winfo reqwidth .b]}]
34713471 set expectedheight [expr {[image height $myquesthead] + 2*[.b cget -borderwidth] \
34723472 + 2*[.b cget -highlightthickness]}]
34733473 incr expectedheight 2 ; # added (hardcoded) in tkUnixButton.c
3474 lappend result [expr $expectedheight == [winfo reqheight .b]]
3474 lappend result [expr {$expectedheight == [winfo reqheight .b]}]
34753475 } -cleanup {
34763476 destroy .b
34773477 } -result {1 1 1 1}
39573957 destroy .top.b .top
39583958 } -result {}
39593959
3960 test button-15.1 {Bug [5d991b822e]} {
3961 # Want this not to segfault
3962 set var INIT
3963 button .b -textvariable var
3964 trace add variable var unset {apply {args {
3965 .b configure -textvariable {}
3966 }}}
3967 pack .b
3968 bind .b <Configure> {unset var}
3969 update
3970 destroy .b
3971 } {}
3972 test button-15.2 {Bug [5d991b822e]} {
3973 # Want this not to leak traces
3974 set var INIT
3975 button .b -textvariable var
3976 trace add variable var unset {apply {args {
3977 .b configure -textvariable new
3978 }}}
3979 pack .b
3980 bind .b <Configure> {unset -nocomplain var}
3981 update
3982 destroy .b
3983 unset new
3984 } {}
3985 test button-15.3 {Bug [5d991b822e]} {
3986 # Want this not to leak traces
3987 set var INIT
3988 checkbutton .b -variable var
3989 trace add variable var unset {apply {args {
3990 .b configure -variable {}
3991 }}}
3992 pack .b
3993 bind .b <Configure> {unset var}
3994 update
3995 destroy .b
3996 } {}
3997
3998
39603999 imageFinish
39614000 cleanupTests
39624001 return
155155 .c delete all
156156 image delete foo
157157 } -result {{{foo free}} {}}
158 test canvImg-4.2 {ConfiugreImage procedure} -constraints testImageType -setup {
159 .c delete all
160 } -body {
161 image create test foo -variable x
158 test canvImg-4.2 {ConfigureImage procedure} -constraints testImageType -setup {
159 .c delete all
160 } -body {
161 image create test foo -variable x
162162 image create test foo2 -variable y
163163 foo2 changed 0 0 0 0 80 60
164164 .c create image 50 100 -image foo -tags i1 -anchor nw
165165 update
166166 set x {}
167167 set y {}
168 set timer [after 300 {lappend y "timed out"}]
168169 .c itemconfigure i1 -image foo2
169 update
170 update idletasks
171 update
172 # On MacOS we need to wait for the test image display procedure to run.
173 while {"timed out" ni $y && [lindex $y end 1] ne "display"} {
174 vwait y
175 }
176 after cancel timer
170177 list $x $y [.c bbox i1]
171178 } -cleanup {
172 .c delete all
173 image delete foo
174 image delete foo2
179 .c delete all
180 image delete foo
181 image delete foo2
175182 } -result {{{foo free}} {{foo2 get} {foo2 display 0 0 80 60}} {50 100 130 160}}
176183 test canvImg-4.3 {ConfiugreImage procedure} -constraints testImageType -setup {
177184 .c delete all
719726 image delete foo
720727 } -result {75 150 105 165}
721728
729 if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
730 # Aqua >= 10.14 will redraw the entire image.
731 set result_10_1 {{foo display 0 0 30 15}}
732 } else {
733 set result_10_1 {{foo display 2 4 6 8}}
734 }
722735 test canvImg-10.1 {TranslateImage procedure} -constraints testImageType -setup {
723736 .c delete all
724 } -body {
725 image create test foo -variable x
737 update
738 } -body {
739 image create test foo -variable x
726740 .c create image 50 100 -image foo -tags image -anchor nw
727741 update
728742 set x {}
743 set timer [after 500 {lappend x "timed out"}]
729744 foo changed 2 4 6 8 30 15
745 vwait x
746 after cancel $timer
730747 update
731748 return $x
732749 } -cleanup {
733 .c delete all
734 image delete foo
735 } -result {{foo display 2 4 6 8}}
750 .c delete all
751 image delete foo
752 } -result $result_10_1
736753
737754 test canvImg-11.1 {TranslateImage procedure} -constraints testImageType -setup {
738755 .c delete all
739 } -body {
740 image create test foo -variable x
756 update
757 } -body {
758 image create test foo -variable x
741759 .c create image 50 100 -image foo -tags image -anchor nw
742760 update
743761 set x {}
762 set timer [after 500 {lappend x "timed out"}]
744763 foo changed 2 4 6 8 40 50
764 vwait x
765 after cancel $timer
745766 update
746767 return $x
747768 } -cleanup {
748 .c delete all
749 image delete foo
769 .c delete all
770 image delete foo
750771 } -result {{foo display 0 0 40 50}}
751772 test canvImg-11.2 {ImageChangedProc procedure} -constraints {
752773 testImageType
763784 .c delete all
764785 image delete foo
765786 } -result {30 75 70 125}
787 if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
788 # Aqua >= 10.14 will redraw the entire image.
789 set result_11_3 {{foo2 display 0 0 80 60}}
790 } else {
791 set result_11_3 {{foo2 display 0 0 20 40}}
792 }
766793 test canvImg-11.3 {ImageChangedProc procedure} -constraints {
767794 testImageType
768795 } -setup {
769796 .c delete all
797 update
770798 } -body {
771799 image create test foo -variable x
772 image create test foo2 -variable y
800 image create test foo2 -variable z
773801 foo changed 0 0 0 0 40 50
774802 foo2 changed 0 0 0 0 80 60
775
776803 .c create image 50 100 -image foo -tags image -anchor nw
777804 .c create image 70 110 -image foo2 -anchor nw
778805 update
779 set y {}
806 set z {}
807 set timer [after 500 {lappend z "timed out"}]
780808 image create test foo -variable x
781 update
782 return $y
783 } -cleanup {
784 .c delete all
785 image delete foo foo2
786 } -result {{foo2 display 0 0 20 40}}
809 vwait x
810 after cancel $timer
811 return $z
812 } -cleanup {
813 .c delete all
814 image delete foo foo2
815 } -result $result_11_3
787816
788817 # cleanup
789818 imageFinish
268268 .c create text 0 0 -tag test
269269 .c itemconfig test -font $font -text 0
270270 expr {[.c itemconfig test -anchor n; .c bbox test] \
271 eq "[expr -$ax/2-1] 0 [expr $ax/2+1] $ay"}
271 eq "[expr {-$ax/2-1}] 0 [expr {$ax/2+1}] $ay"}
272272 } -cleanup {
273273 .c delete test
274274 } -result 1
281281 .c create text 0 0 -tag test
282282 .c itemconfig test -font $font -text 0
283283 expr {[.c itemconfig test -anchor nw; .c bbox test] \
284 eq "-1 0 [expr $ax+1] $ay"}
284 eq "-1 0 [expr {$ax+1}] $ay"}
285285 } -cleanup {
286286 .c delete test
287287 } -result 1
353353 for {set i 0} {$i < $size} {incr i} {
354354 set x [expr {-10 + 3*$i}]
355355 for {set j 0; set y -10} {$j < 10} {incr j; incr y 3} {
356 .c create rect ${x}c ${y}c [expr $x+2]c [expr $y+2]c \
356 .c create rect ${x}c ${y}c [expr {$x+2}]c [expr {$y+2}]c \
357357 -outline black -fill blue -tags rect
358 .c create text [expr $x+1]c [expr $y+1]c -text "$i,$j" \
358 .c create text [expr {$x+1}]c [expr {$y+1}]c -text "$i,$j" \
359359 -anchor center -tags text
360360 }
361361 }
99 # Note: Multiple display clipboard handling will only be tested if the
1010 # environment variable TK_ALT_DISPLAY is set to an alternate display.
1111 #
12
13 #################################################################
14 # Note that some of these tests may fail if another application #
15 # is grabbing the clipboard (e.g. an X server, or a VNC viewer) #
16 #################################################################
1217
1318 package require tcltest 2.2
1419 namespace import ::tcltest::*
7777 # tests 3.1 and 3.2 fail when individually run
7878 # if there is no catch {tk_chooseColor -foo 1} msg
7979 # before settin isNative
80 catch {tk_chooseColor -foo 1} msg
80 catch {tk_chooseColor -foo 1} msg
8181 set isNative [expr {[info commands tk::dialog::color::] eq ""}]
8282
8383 proc ToPressButton {parent btn} {
1818 for {set x 0} {$x < 8} {incr x} {
1919 frame $w.f$x,$y -width 40 -height 40 -bd 2 -relief raised \
2020 -bg [format #%02x%02x%02x $red $green $blue]
21 place $w.f$x,$y -x [expr 40*$x] -y [expr 40*$y]
21 place $w.f$x,$y -x [expr {40*$x}] -y [expr {40*$y}]
2222 incr red $redInc
2323 incr green $greenInc
2424 incr blue $blueInc
167167 if {$rgb != [lrange $line 0 2] } {
168168 append result $line\n
169169 }
170
170
171171 }
172172 return $result
173173 } {}
189189 [testConstraint userInteraction] ||
190190 ([testConstraint unix] && [testConstraint notAqua])
191191 }]
192 testConstraint haveDISPLAY [info exists env(DISPLAY)]
192 testConstraint haveDISPLAY [expr {[info exists env(DISPLAY)] && [testConstraint x11]}]
193193 testConstraint altDisplay [info exists env(TK_ALT_DISPLAY)]
194194 testConstraint noExceed [expr {
195195 ![testConstraint unix] || [catch {font actual "\{xyz"}]
16701670 } -body {
16711671 .e configure -font {Courier -12} -width 4 -xscrollcommand scroll
16721672 .e insert end "01234567890"
1673 update
1673 set timeout [after 500 {set $scrollInfo "timeout"}]
1674 vwait scrollInfo
16741675 .e configure -width 5
16751676 format {%.6f %.6f} {*}$scrollInfo
16761677 } -cleanup {
16771678 destroy .e
1679 after cancel $timeout
16781680 } -result {0.000000 0.363636}
16791681
16801682
19151917 .e configure -textvariable contents -xscrollcommand scroll
19161918 .e insert 0 abcde
19171919 .e insert 2 XXX
1918 update
1920 set timeout [after 500 {set $scrollInfo "timeout"}]
1921 vwait scrollInfo
19191922 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
19201923 } -cleanup {
19211924 destroy .e
1925 after cancel $timeout
19221926 } -result {abXXXcde abXXXcde {0.000000 1.000000}}
19231927
19241928 test entry-7.2 {InsertChars procedure} -setup {
19301934 .e configure -textvariable contents -xscrollcommand scroll
19311935 .e insert 0 abcde
19321936 .e insert 500 XXX
1933 update
1937 set timeout [after 500 {set $scrollInfo "timeout"}]
1938 vwait scrollInfo
19341939 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
19351940 } -cleanup {
19361941 destroy .e
1942 after cancel $timeout
19371943 } -result {abcdeXXX abcdeXXX {0.000000 1.000000}}
19381944 test entry-7.3 {InsertChars procedure} -setup {
19391945 entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
20622068 .e configure -textvariable contents -xscrollcommand scroll
20632069 .e insert 0 abcde
20642070 .e delete 2 4
2065 update
2071 set timeout [after 500 {set $scrollInfo "timeout"}]
2072 vwait scrollInfo
20662073 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
20672074 } -cleanup {
20682075 destroy .e
2076 after cancel $timeout
20692077 } -result {abe abe {0.000000 1.000000}}
20702078 test entry-8.2 {DeleteChars procedure} -setup {
20712079 unset -nocomplain contents
20762084 .e configure -textvariable contents -xscrollcommand scroll
20772085 .e insert 0 abcde
20782086 .e delete -2 2
2079 update
2087 set timeout [after 500 {set $scrollInfo "timeout"}]
2088 vwait scrollInfo
20802089 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
20812090 } -cleanup {
20822091 destroy .e
2092 after cancel $timeout
20832093 } -result {cde cde {0.000000 1.000000}}
20842094 test entry-8.3 {DeleteChars procedure} -setup {
20852095 unset -nocomplain contents
20902100 .e configure -textvariable contents -xscrollcommand scroll
20912101 .e insert 0 abcde
20922102 .e delete 3 1000
2093 update
2103 set timeout [after 500 {set $scrollInfo "timeout"}]
2104 vwait scrollInfo
20942105 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
20952106 } -cleanup {
20962107 destroy .e
2108 after cancel $timeout
20972109 } -result {abc abc {0.000000 1.000000}}
20982110 test entry-8.4 {DeleteChars procedure} -setup {
20992111 entry .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
29262938 pack .e
29272939 .e delete 0 end
29282940 .e insert 0 123
2929 update
2941 set timeout [after 500 {set $scrollInfo "timeout"}]
2942 vwait scrollInfo
29302943 format {%.6f %.6f} {*}$scrollInfo
29312944 } -cleanup {
29322945 destroy .e
2946 after cancel $timeout
29332947 } -result {0.000000 1.000000}
29342948 test entry-17.2 {EntryUpdateScrollbar procedure} -body {
29352949 entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
29362950 pack .e
29372951 .e insert 0 0123456789abcdef
29382952 .e xview 3
2939 update
2953 set timeout [after 500 {set $scrollInfo "timeout"}]
2954 vwait scrollInfo
29402955 format {%.6f %.6f} {*}$scrollInfo
29412956 } -cleanup {
29422957 destroy .e
2958 after cancel $timeout
29432959 } -result {0.187500 0.812500}
29442960 test entry-17.3 {EntryUpdateScrollbar procedure} -body {
29452961 entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
29462962 pack .e
29472963 .e insert 0 abcdefghijklmnopqrs
29482964 .e xview 6
2949 update
2965 set timeout [after 500 {set $scrollInfo "timeout"}]
2966 vwait scrollInfo
29502967 format {%.6f %.6f} {*}$scrollInfo
29512968 } -cleanup {
29522969 destroy .e
2970 after cancel $timeout
29532971 } -result {0.315789 0.842105}
29542972 test entry-17.4 {EntryUpdateScrollbar procedure} -setup {
29552973 proc bgerror msg {
29592977 } -body {
29602978 entry .e -width 5 -xscrollcommand thisisnotacommand
29612979 pack .e
2962 update
2980 vwait x
29632981 list $x $errorInfo
29642982 } -cleanup {
29652983 destroy .e
35013519 destroy .e
35023520 } -result {can't trace "thisnsdoesntexist::myvar": parent namespace doesn't exist}
35033521
3522 test entry-25.1 {Bug [5d991b822e]} {
3523 # Want this not to segfault, or write to variable with empty name
3524 set var INIT
3525 entry .b -textvariable var
3526 trace add variable var unset {apply {args {
3527 .b configure -textvariable {}
3528 }}}
3529 pack .b
3530 bind .b <Configure> {unset var}
3531 update
3532 destroy .b
3533 info exists {}
3534 } 0
3535 test entry-25.2 {Bug [5d991b822e]} {
3536 # Want this not to leak traces
3537 set var INIT
3538 entry .b -textvariable var
3539 trace add variable var unset {apply {args {
3540 .b configure -textvariable new
3541 }}}
3542 pack .b
3543 bind .b <Configure> {unset -nocomplain var}
3544 update
3545 destroy .b
3546 unset new
3547 } {}
3548
3549
35043550 # Gathered comments about lacks
35053551 # XXX Still need to write tests for EntryBlinkProc, EntryFocusProc,
35063552 # and EntryTextVarProc.
244244 set e [entry $t.e]
245245 pack $e
246246 tkwait visibility $e
247 # Avoid a hang when macOS puts the mouse pointer on the green button
248 wm geometry .t +200+100
247249 _keypress_string $e MELLO
248250 _keypress $e BackSpace
249251 _keypress $e BackSpace
108108 font actual xyz -displayof
109109 } -returnCodes error -result {value for "-displayof" missing}
110110 test font-4.2 {font command: actual: arguments} -body {
111 # (objc < 3)
111 # (objc < 3)
112112 font actual
113113 } -returnCodes error -result {wrong # args: should be "font actual font ?-displayof window? ?option? ?--? ?char?"}
114114 test font-4.3 {font command: actual: arguments} -body {
159159
160160
161161 test font-5.1 {font command: configure} -body {
162 # (objc < 3)
162 # (objc < 3)
163163 font configure
164164 } -returnCodes error -result {wrong # args: should be "font configure fontname ?-option value ...?"}
165165 test font-5.2 {font command: configure: non-existent font} -body {
172172 pack [label .t.f]
173173 update
174174 } -body {
175 # (nfPtr->deletePending != 0)
175 # (nfPtr->deletePending != 0)
176176 font create xyz
177177 .t.f configure -font xyz
178178 font delete xyz
262262 test font-6.5 {font command: create: bad option creating new font} -setup {
263263 catch {font delete xyz}
264264 } -body {
265 # name was specified so skip = 3
265 # name was specified so skip = 3
266266 font create xyz -xyz times
267267 } -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
268268 test font-6.6 {font command: create: bad option creating new font} -setup {
269269 clearnondefaultfonts
270270 } -body {
271 # name was not specified so skip = 2
271 # name was not specified so skip = 2
272272 font create -xyz times
273273 } -returnCodes error -result {bad option "-xyz": must be -family, -size, -weight, -slant, -underline, or -overstrike}
274274 test font-6.7 {font command: create: already exists} -setup {
282282 } -returnCodes error -result {named font "xyz" already exists}
283283
284284 test font-7.1 {font command: delete: arguments} -body {
285 # (objc < 3)
285 # (objc < 3)
286286 font delete
287287 } -returnCodes error -result {wrong # args: should be "font delete fontname ?fontname ...?"}
288288 test font-7.2 {font command: delete: loop test} -setup {
289289 clearnondefaultfonts
290290 set x {}
291291 } -body {
292 # for (i = 2; i < objc; i++)
292 # for (i = 2; i < objc; i++)
293293 font create a -underline 1
294294 font create b -underline 1
295295 font create c -underline 1
320320 test font-7.4 {font command: delete: non-existent} -setup {
321321 catch {font delete xyz}
322322 } -body {
323 # (namedHashPtr == NULL)
323 # (namedHashPtr == NULL)
324324 font delete xyz
325325 } -returnCodes error -result {named font "xyz" doesn't exist}
326326 test font-7.5 {font command: delete: mark for later deletion} -setup {
387387 expr {[font measure xyz -displayof] > 0}
388388 } -returnCodes ok -result 1
389389 test font-9.2 {font command: measure: arguments} -body {
390 # (objc - skip != 4)
390 # (objc - skip != 4)
391391 font measure
392392 } -returnCodes error -result {wrong # args: should be "font measure font ?-displayof window? text"}
393393 test font-9.3 {font command: measure: arguments} -body {
394 # (objc - skip != 4)
394 # (objc - skip != 4)
395395 font measure xyz abc def
396396 } -returnCodes error -result {wrong # args: should be "font measure font ?-displayof window? text"}
397397 test font-9.4 {font command: measure: arguments} -constraints noExceed -body {
421421 font metrics xyz -displayof
422422 } -returnCodes error -result {value for "-displayof" missing}
423423 test font-10.3 {font command: metrics: arguments} -body {
424 # (objc < 3)
424 # (objc < 3)
425425 font metrics
426426 } -returnCodes error -result {wrong # args: should be "font metrics font ?-displayof window? ?option?"}
427427 test font-10.4 {font command: metrics: arguments} -body {
584584
585585
586586 test font-15.1 {Tk_AllocFontFromObj - converting internal reps} -constraints {
587 testfont
587 testfont
588588 } -setup {
589589 destroy .b1 .b2
590590 } -body {
597597 destroy .b1 .b2
598598 } -result {{1 0}}
599599 test font-15.2 {Tk_AllocFontFromObj - discard stale font} -constraints {
600 testfont
600 testfont
601601 } -setup {
602602 destroy .b1 .b2
603603 set result {}
612612 destroy .b2
613613 } -result {{} {{1 1}}}
614614 test font-15.3 {Tk_AllocFontFromObj - reuse existing font} -constraints {
615 testfont
615 testfont
616616 } -setup {
617617 destroy .b1 .b2
618618 set result {}
643643 pack [label .t.f]
644644 update
645645 } -body {
646 # (namedHashPtr != NULL)
647 font create xyz
648 .t.f config -font xyz
646 # (namedHashPtr != NULL)
647 font create xyz
648 .t.f config -font xyz
649649 } -cleanup {
650650 destroy .t.f
651651 font delete xyz
661661 destroy .t.f
662662 } -result {-family} -result {}
663663 test font-15.7 {Tk_AllocFontFromObj procedure: get native font} -constraints {
664 unix
664 unix
665665 } -setup {
666666 destroy .t.f
667667 pack [label .t.f]
668668 update
669669 } -body {
670 # not (fontPtr == NULL)
670 # not (fontPtr == NULL)
671671 .t.f config -font fixed
672672 } -result {}
673673 test font-15.8 {Tk_AllocFontFromObj procedure: get native font} -constraints {
674 win
674 win
675675 } -setup {
676676 destroy .t.f
677677 clearnondefaultfonts
678678 pack [label .t.f]
679679 update
680680 } -body {
681 # not (fontPtr == NULL)
681 # not (fontPtr == NULL)
682682 .t.f config -font oemfixed
683683 } -cleanup {
684684 destroy .t.f
688688 pack [label .t.f]
689689 update
690690 } -body {
691 # (fontPtr == NULL)
691 # (fontPtr == NULL)
692692 .t.f config -font {xxx yyy zzz}
693693 } -cleanup {
694694 destroy .t.f
723723 update
724724 } -cleanup {
725725 destroy .t.f
726 } -result {}
726 } -result {}
727727
728728
729729 test font-16.1 {Tk_NameOfFont procedure} -setup {
739739
740740
741741 test font-17.1 {Tk_FreeFontFromObj - reference counts} -constraints {
742 testfont
742 testfont
743743 } -setup {
744744 destroy .b1 .b2 .b3
745745 set result {}
784784 pack [label .t.f]
785785 update
786786 } -body {
787 # (fontPtr->namedHashPtr != NULL)
787 # (fontPtr->namedHashPtr != NULL)
788788 font create xyz
789789 .t.f config -font xyz
790790 destroy .t.f
796796 pack [label .t.f]
797797 update
798798 } -body {
799 # not (fontPtr->refCount == 0)
799 # not (fontPtr->refCount == 0)
800800 font create xyz -underline 1
801801 .t.f config -font xyz
802802 font delete xyz
810810 pack [label .t.f]
811811 update
812812 } -body {
813 font create xyz
813 font create xyz
814814 .t.f config -font xyz
815815 button .t.b -font xyz
816816 font delete xyz
869869 # Procedure used in 21.* tests
870870 proc psfontname {name} {
871871 destroy .t.c
872 canvas .t.c -closeenough 0
872 canvas .t.c -closeenough 0
873873 .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
874874 pack .t.c
875875 update
895895 }
896896 } -result {AvantGarde-Book}
897897 test font-21.2 {Tk_PostscriptFontName procedure: native} -constraints {
898 win
898 win
899899 } -body {
900900 psfontname "arial 10"
901901 } -result {Helvetica}
902902 test font-21.3 {Tk_PostscriptFontName procedure: native} -constraints {
903 win
903 win
904904 } -body {
905905 psfontname "{times new roman} 10"
906906 } -result {Times-Roman}
907907 test font-21.4 {Tk_PostscriptFontName procedure: native} -constraints {
908 win
908 win
909909 } -body {
910910 psfontname "{courier new} 10"
911911 } -result {Courier}
912912 test font-21.5 {Tk_PostscriptFontName procedure: spaces} -constraints {
913 unix
913 unix
914914 } -body {
915915 set x [font actual {{lucida bright} 10} -family]
916916 if {[string match lucida*bright $x]} {
920920 }
921921 } -result {LucidaBright}
922922 test font-21.6 {Tk_PostscriptFontName procedure: spaces} -constraints {
923 x11
923 x11
924924 } -body {
925925 psfontname "{new century schoolbook} 10"
926926 } -result {NewCenturySchlbk-Roman}
927927
928928 test font-21.7 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
929 unix
929 unix
930930 } -body {
931931 set name {avantgarde 12 roman normal}
932932 if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
936936 }
937937 } -result {AvantGarde-Book}
938938 test font-21.8 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
939 unix
939 unix
940940 } -body {
941941 set name {avantgarde 12 roman bold}
942942 if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
946946 }
947947 } -result {AvantGarde-Demi}
948948 test font-21.9 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
949 unix
949 unix
950950 } -body {
951951 set name {avantgarde 12 italic normal}
952952 if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
956956 }
957957 } -result {AvantGarde-BookOblique}
958958 test font-21.10 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
959 unix
959 unix
960960 } -body {
961961 set name {avantgarde 12 italic bold}
962962 if {[font actual {avantgarde 12 roman normal} -family] == "avantgarde"} {
967967 } -result {AvantGarde-DemiOblique}
968968
969969 test font-21.11 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
970 unix
970 unix
971971 } -body {
972972 set name {bookman 12 roman normal}
973973 if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
977977 }
978978 } -result {Bookman-Light}
979979 test font-21.12 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
980 unix
980 unix
981981 } -body {
982982 set name {bookman 12 roman bold}
983983 if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
987987 }
988988 } -result {Bookman-Demi}
989989 test font-21.13 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
990 unix
990 unix
991991 } -body {
992992 set name {bookman 12 italic normal}
993993 if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
997997 }
998998 } -result {Bookman-LightItalic}
999999 test font-21.14 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1000 unix
1000 unix
10011001 } -body {
10021002 set name {bookman 12 italic bold}
10031003 if {[font actual {avantgarde 12 roman normal} -family] == "bookman"} {
10081008 } -result {Bookman-DemiItalic}
10091009
10101010 test font-21.15 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1011 unix
1011 unix
10121012 } -body {
10131013 set name {courier 12 roman normal}
10141014 if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
10181018 }
10191019 } -result {Courier}
10201020 test font-21.16 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1021 unix
1021 unix
10221022 } -body {
10231023 set name {courier 12 roman bold}
10241024 if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
10281028 }
10291029 } -result {Courier-Bold}
10301030 test font-21.17 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1031 unix
1031 unix
10321032 } -body {
10331033 set name {courier 12 italic normal}
10341034 if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
10381038 }
10391039 } -result {Courier-Oblique}
10401040 test font-21.18 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1041 unix
1041 unix
10421042 } -body {
10431043 set name {courier 12 italic bold}
10441044 if {[font actual {avantgarde 12 roman normal} -family] == "courier"} {
10491049 } -result {Courier-BoldOblique}
10501050
10511051 test font-21.19 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1052 unix
1052 unix
10531053 } -body {
10541054 set name {helvetica 12 roman normal}
10551055 if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
10591059 }
10601060 } -result {Helvetica}
10611061 test font-21.20 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1062 unix
1062 unix
10631063 } -body {
10641064 set name {helvetica 12 roman bold}
10651065 if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
10691069 }
10701070 } -result {Helvetica-Bold}
10711071 test font-21.21 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1072 unix
1072 unix
10731073 } -body {
10741074 set name {helvetica 12 italic normal}
10751075 if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
10791079 }
10801080 } -result {Helvetica-Oblique}
10811081 test font-21.22 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1082 unix
1082 unix
10831083 } -body {
10841084 set name {helvetica 12 italic bold}
10851085 if {[font actual {avantgarde 12 roman normal} -family] == "helvetica"} {
10901090 } -result {Helvetica-BoldOblique}
10911091
10921092 test font-21.23 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1093 unix
1093 unix
10941094 } -body {
10951095 set name {{new century schoolbook} 12 roman normal}
10961096 if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
11001100 }
11011101 } -result {NewCenturySchlbk-Roman}
11021102 test font-21.24 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1103 unix
1103 unix
11041104 } -body {
11051105 set name {{new century schoolbook} 12 roman bold}
11061106 if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
11101110 }
11111111 } -result {NewCenturySchlbk-Bold}
11121112 test font-21.25 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1113 unix
1113 unix
11141114 } -body {
11151115 set name {{new century schoolbook} 12 italic normal}
11161116 if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
11201120 }
11211121 } -result {NewCenturySchlbk-Italic}
11221122 test font-21.26 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1123 unix
1123 unix
11241124 } -body {
11251125 set name {{new century schoolbook} 12 italic bold}
11261126 if {[font actual {avantgarde 12 roman normal} -family] == "new century schoolbook"} {
11311131 } -result {NewCenturySchlbk-BoldItalic}
11321132
11331133 test font-21.27 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1134 unix
1134 unix
11351135 } -body {
11361136 set name {palatino 12 roman normal}
11371137 if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
11411141 }
11421142 } -result {Palatino-Roman}
11431143 test font-21.28 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1144 unix
1144 unix
11451145 } -body {
11461146 set name {palatino 12 roman bold}
11471147 if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
11511151 }
11521152 } -result {Palatino-Bold}
11531153 test font-21.29 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1154 unix
1154 unix
11551155 } -body {
11561156 set name {palatino 12 italic normal}
11571157 if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
11611161 }
11621162 } -result {Palatino-Italic}
11631163 test font-21.30 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1164 unix
1164 unix
11651165 } -body {
11661166 set name {palatino 12 italic bold}
11671167 if {[font actual {avantgarde 12 roman normal} -family] == "palatino"} {
11721172 } -result {Palatino-BoldItalic}
11731173
11741174 test font-21.31 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1175 unix
1175 unix
11761176 } -body {
11771177 set name {symbol 12 roman normal}
11781178 if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
11821182 }
11831183 } -result {Symbol}
11841184 test font-21.32 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1185 unix
1185 unix
11861186 } -body {
11871187 set name {symbol 12 roman bold}
11881188 if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
11921192 }
11931193 } -result {Symbol}
11941194 test font-21.33 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1195 unix
1195 unix
11961196 } -body {
11971197 set name {symbol 12 italic normal}
11981198 if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
12021202 }
12031203 } -result {Symbol}
12041204 test font-21.34 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1205 unix
1205 unix
12061206 } -body {
12071207 set name {symbol 12 italic bold}
12081208 if {[font actual {avantgarde 12 roman normal} -family] == "symbol"} {
12131213 } -result {Symbol}
12141214
12151215 test font-21.35 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1216 unix
1216 unix
12171217 } -body {
12181218 set name {times 12 roman normal}
12191219 if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
12231223 }
12241224 } -result {Times-Roman}
12251225 test font-21.36 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1226 unix
1226 unix
12271227 } -body {
12281228 set name {times 12 roman bold}
12291229 if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
12331233 }
12341234 } -result {Times-Bold}
12351235 test font-21.37 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1236 unix
1236 unix
12371237 } -body {
12381238 set name {times 12 italic normal}
12391239 if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
12431243 }
12441244 } -result {Times-Italic}
12451245 test font-21.38 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1246 unix
1246 unix
12471247 } -body {
12481248 set name {times 12 italic bold}
12491249 if {[font actual {avantgarde 12 roman normal} -family] == "times"} {
12541254 } -result {Times-BoldItalic}
12551255
12561256 test font-21.39 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1257 unix
1257 unix
12581258 } -body {
12591259 set name {zapfchancery 12 roman normal}
12601260 if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
12641264 }
12651265 } -result {ZapfChancery-MediumItalic}
12661266 test font-21.40 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1267 unix
1267 unix
12681268 } -body {
12691269 set name {zapfchancery 12 roman bold}
12701270 if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
12741274 }
12751275 } -result {ZapfChancery-MediumItalic}
12761276 test font-21.41 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1277 unix
1277 unix
12781278 } -body {
12791279 set name {zapfchancery 12 italic normal}
12801280 if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
12841284 }
12851285 } -result {ZapfChancery-MediumItalic}
12861286 test font-21.42 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1287 unix
1287 unix
12881288 } -body {
12891289 set name {zapfchancery 12 italic bold}
12901290 if {[font actual {avantgarde 12 roman normal} -family] == "zapfchancery"} {
12951295 } -result {ZapfChancery-MediumItalic}
12961296
12971297 test font-21.43 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1298 unix
1298 unix
12991299 } -body {
13001300 set name {zapfdingbats 12 roman normal}
13011301 if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
13051305 }
13061306 } -result {ZapfDingbats}
13071307 test font-21.44 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1308 unix
1308 unix
13091309 } -body {
13101310 set name {zapfdingbats 12 roman bold}
13111311 if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
13151315 }
13161316 } -result {ZapfDingbats}
13171317 test font-21.45 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1318 unix
1318 unix
13191319 } -body {
13201320 set name {zapfdingbats 12 italic normal}
13211321 if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
13251325 }
13261326 } -result {ZapfDingbats}
13271327 test font-21.46 {Tk_PostscriptFontName procedure: exhaustive} -constraints {
1328 unix
1328 unix
13291329 } -body {
13301330 set name {zapfdingbats 12 italic bold}
13311331 if {[font actual {avantgarde 12 roman normal} -family] == "zapfdingbats"} {
14421442
14431443
14441444 test font-22.1 {Tk_TextWidth procedure} -setup {
1445 destroy .t.l
1445 destroy .t.l
14461446 } -body {
14471447 label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
14481448 -text "0" -font "Courier -12"
14681468
14691469
14701470 # Data used in 24.* tests
1471 destroy .t.l
1471 destroy .t.l
14721472 label .t.l -padx 0 -pady 0 -bd 0 -highlightthickness 0 -justify left \
14731473 -text "0" -font "Courier -12"
14741474 pack .t.l
15931593 lappend x [expr {[winfo reqheight .t.l] eq [expr {$ay * 2}]}]
15941594 return $x
15951595 } -result {1 1 1 1}
1596 destroy .t.l
1596 destroy .t.l
15971597
15981598 test font-24.15 {Tk_ComputeTextLayout: justification} -setup {
15991599 set x {}
16001600 destroy .t.c
1601 canvas .t.c -closeenough 0
1601 canvas .t.c -closeenough 0
16021602 .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
16031603 pack .t.c
16041604 update
16271627 } -cleanup {
16281628 destroy .t.f
16291629 } -result {}
1630
1630
16311631
16321632 # Canvas created for tests: 26.*
16331633 destroy .t.c
1634 canvas .t.c -closeenough 0
1634 canvas .t.c -closeenough 0
16351635 .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
16361636 pack .t.c
16371637 update
16891689
16901690 # Canvas created for tests: 28.*
16911691 destroy .t.c
1692 canvas .t.c -closeenough 0
1692 canvas .t.c -closeenough 0
16931693 .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
16941694 pack .t.c
16951695 update
17811781
17821782 # Canvas created for tests: 30.*
17831783 destroy .t.c
1784 canvas .t.c -closeenough 0
1784 canvas .t.c -closeenough 0
17851785 .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
17861786 pack .t.c
17871787 update
19241924
19251925 # Canvas created for tests 31.*
19261926 destroy .t.c
1927 canvas .t.c -closeenough 0
1927 canvas .t.c -closeenough 0
19281928 .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
19291929 pack .t.c
19301930 update
19701970
19711971 test font-32.1 {Tk_TextLayoutToPostscript: ensure buffer doesn't overflow} -setup {
19721972 destroy .t.c
1973 canvas .t.c -closeenough 0
1973 canvas .t.c -closeenough 0
19741974 .t.c create text 0 0 -tags text -anchor nw -just left -font "Courier -12"
19751975 pack .t.c
19761976 update
19831983 .t.c insert text end "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
19841984 .t.c insert text end "end"
19851985 set x [.t.c postscript]
1986 set i [string first "(qwerty" $x]
1986 set i [string first "(qwerty" $x]
19871987 string range $x $i [expr {$i + 278}]
19881988 } -cleanup {
19891989 destroy .t.c
21992199 set x {}
22002200 } -body {
22012201 font create xyz -underline yes
2202 font config xyz -underline
2202 font config xyz -underline
22032203 } -cleanup {
22042204 font delete xyz
22052205 } -result {1}
22082208 set x {}
22092209 } -body {
22102210 font create xyz -overstrike no
2211 font config xyz -overstrike
2211 font config xyz -overstrike
22122212 } -cleanup {
22132213 font delete xyz
22142214 } -result {0}
5959 .f configure -class
6060 } -cleanup {
6161 deleteWindows
62 } -result {-class class Class Frame NewFrame}
62 } -result {-class class Class Frame NewFrame}
6363 test frame-1.2 {frame configuration options} -setup {
6464 deleteWindows
6565 } -body {
622622 deleteWindows
623623 option clear
624624 } -result {#123456}
625 test frame-3.6 {TkCreateFrame procedure} -setup {
626 deleteWindows
627 } -body {
628 option add *NewFrame.background #123456
629 frame .f -class NewFrame
630 lindex [.f configure -background] 4
631 } -cleanup {
632 deleteWindows
633 option clear
634 } -result {#123456}
635625 test frame-3.7 {TkCreateFrame procedure} -setup {
636626 deleteWindows
637627 } -body {
667657 [expr {[winfo rooty .x] - [winfo rooty .t]}] \
668658 [winfo width .t] [winfo height .t]
669659 } -cleanup {
660 # This call to update idletasks was added to prevent a crash that was
661 # observed on OSX 10.12 (Sierra) only. Any change, such as using the
662 # Development version to make debugging symbols available, adding a print
663 # statement, or calling update idletasks here, would make the test pass
664 # with no segfault.
665 update idletasks
670666 deleteWindows
671667 } -result {0 0 140 300}
672668 test frame-3.10 {TkCreateFrame procedure, -use option} -constraints {
677673 toplevel .t -container 1 -width 300 -height 120
678674 wm geometry .t +0+0
679675 option add *x.use [winfo id .t]
676 update
680677 toplevel .x -width 140 -height 300 -bg green
681678 tkwait visibility .x
679 update
682680 list [expr {[winfo rootx .x] - [winfo rootx .t]}] \
683681 [expr {[winfo rooty .x] - [winfo rooty .t]}] \
684682 [winfo width .t] [winfo height .t]
791789 } -setup {
792790 deleteWindows
793791 } -body {
794 toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
792 toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
795793 wm geometry .t +0+0
796794 update
797795 colorsFree .t 131 131 131
835833 deleteWindows
836834 } -body {
837835 set x ok
838 toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
836 toplevel .t -visual {grayscale 8} -width 300 -height 200 -bg #434343
839837 wm geometry .t +0+0
840838 update
841839 colorsFree .t 131 131 131
11311129 place .f -x 0 -y 0 -width 100 -height 100
11321130 pack [frame .f.f] -fill both -expand 1
11331131
1134 set result {}
1132 set result {}
11351133 foreach lp {nw n ne en e es se s sw ws w wn} {
11361134 .f configure -labelanchor $lp
11371135 update
1111 tcltest::loadTestedCommands
1212 namespace import -force tcltest::test
1313
14 # There's currently no way to test the actual grab effect, per se,
15 # in an automated test. Therefore, this test suite only covers the
16 # interface to the grab command (ie, error messages, etc.)
17
14 # The macOS test module includes the pressbutton command to simulate a
15 # mouse button press event by injecting events into the NSApplication
16 # event queue. On other platforms there is currently no way to test
17 # the actual grab effect, per se, in an automated test. Therefore,
18 # this test suite only covers the interface to the grab command (ie,
19 # error messages, etc.) on platforms other than macOS.
20
21 testConstraint pressbutton [llength [info commands pressbutton]]
1822
1923 test grab-1.1 {Tk_GrabObjCmd} -body {
2024 grab
181185 grab release .
182186 } -result {. global}
183187
188 test grab-6.1 {local grab on child window} -constraints {
189 pressbutton
190 } -body {
191 wm geometry . 100x200+200+100
192 set result {}
193 frame .f -background red -padx 10 -pady 10 -height 100 -width 80
194 bind . <Button-1> {lappend result "outside"}
195 bind .f <Button-1> {lappend result "inside"}
196 pack .f
197 update idletasks
198 pressbutton 250 150
199 update
200 lappend result ":"
201 pressbutton 250 250
202 update
203 lappend result ":"
204 grab set .f
205 pressbutton 250 150
206 update
207 lappend result ":"
208 pressbutton 250 250
209 update
210 return $result
211 } -cleanup {
212 grab release .f
213 } -result {inside outside : outside : inside outside :}
184214
185215 cleanupTests
186216 return
7878 } -cleanup {
7979 grid_reset 1.9
8080 } -returnCodes ok -result {}
81
8182
8283 test grid-2.1 {bbox} -body {
8384 grid bbox .
191192 } -cleanup {
192193 grid_reset 3.9
193194 } -returnCodes error -result {invalid window shortcut, "y" should be '-', 'x', or '^'}
195 test grid-3.10 {ConfigureSlave procedure, bad -in option} -body {
196 frame .f
197 grid .f -in .f
198 } -cleanup {
199 grid_reset 3.10
200 } -returnCodes error -result {window can't be managed in itself}
201 test grid-3.11 {prevent management loops} -body {
202 frame .f1
203 frame .f2
204 grid .f1 -in .f2
205 grid .f2 -in .f1
206 } -cleanup {
207 grid_reset 3.11
208 } -returnCodes error -result {can't put .f2 inside .f1, would cause management loop}
209 test grid-3.12 {prevent management loops} -body {
210 frame .f1
211 frame .f2
212 frame .f3
213 grid .f1 -in .f2
214 grid .f2 -in .f3
215 grid .f3 -in .f1
216 } -cleanup {
217 grid_reset 3.12
218 } -returnCodes error -result {can't put .f3 inside .f1, would cause management loop}
194219
195220 test grid-4.1 {forget: basic argument checking} -body {
196221 grid forget foo
3232 image c bad_type
3333 } -returnCodes error -result {image type "bad_type" doesn't exist}
3434 test image-1.5 {Tk_ImageCmd procedure, "create" option} -constraints {
35 testImageType
35 testImageType
3636 } -body {
3737 list [image create test myimage] [imageNames]
3838 } -cleanup {
3939 imageCleanup
4040 } -result {myimage myimage}
4141 test image-1.6 {Tk_ImageCmd procedure, "create" option} -constraints {
42 testImageType
42 testImageType
4343 } -setup {
4444 imageCleanup
4545 } -body {
4646 scan [image create test] image%d first
4747 image create test myimage
4848 scan [image create test -variable x] image%d second
49 expr $second-$first
49 expr {$second-$first}
5050 } -cleanup {
5151 imageCleanup
5252 } -result {1}
5353
5454 test image-1.7 {Tk_ImageCmd procedure, "create" option} -constraints {
55 testImageType
55 testImageType
5656 } -setup {
5757 imageCleanup
5858 } -body {
6161 .c create image 100 150 -image myimage
6262 update
6363 set x {}
64 set timer [after 500 {lappend x "timed out"}]
6465 image create test myimage -variable x
65 update
66 update idletasks
67 update
68 # On MacOS we need to wait for the test image display procedure to run.
69 while {"timed out" ni $x && [lindex $x end 1] ne "display"} {
70 vwait x
71 }
72 after cancel timer
73 if {[lindex $x end] eq "timed out"} {
74 return [lreplace $x end end]
75 }
6676 return $x
6777 } -cleanup {
6878 imageCleanup
6979 } -result {{myimage free} {myimage free} {myimage delete} {myimage get} {myimage get} {myimage display 0 0 30 15} {myimage display 0 0 30 15}}
7080 test image-1.8 {Tk_ImageCmd procedure, "create" option} -constraints {
71 testImageType
81 testImageType
7282 } -setup {
7383 .c delete all
7484 imageCleanup
7989 image delete myimage
8090 update
8191 set x {}
92 set timer [after 500 {lappend x "timed out"}]
8293 image create test myimage -variable x
83 update
94 vwait x
95 after cancel $timer
8496 return $x
8597 } -cleanup {
8698 .c delete all
8799 imageCleanup
88100 } -result {{myimage get} {myimage get} {myimage display 0 0 30 15} {myimage display 0 0 30 15}}
89101 test image-1.9 {Tk_ImageCmd procedure, "create" option} -constraints {
90 testImageType
102 testImageType
91103 } -body {
92104 image create test -badName foo
93105 } -returnCodes error -result {bad option name "-badName"}
94106 test image-1.10 {Tk_ImageCmd procedure, "create" option} -constraints {
95 testImageType
107 testImageType
96108 } -body {
97109 catch {image create test -badName foo}
98110 imageNames
141153 image delete
142154 } -result {}
143155 test image-2.2 {Tk_ImageCmd procedure, "delete" option} -constraints {
144 testImageType
156 testImageType
145157 } -setup {
146158 imageCleanup
147159 set result {}
155167 imageCleanup
156168 } -result {{img2 myimage} {}}
157169 test image-2.3 {Tk_ImageCmd procedure, "delete" option} -constraints {
158 testImageType
170 testImageType
159171 } -setup {
160172 imageCleanup
161173 } -body {
166178 imageCleanup
167179 } -returnCodes error -result {image "gorp" doesn't exist}
168180 test image-2.4 {Tk_ImageCmd procedure, "delete" option} -constraints {
169 testImageType
181 testImageType
170182 } -setup {
171183 imageCleanup
172184 } -body {
189201 image height foo
190202 } -returnCodes error -result {image "foo" doesn't exist}
191203 test image-3.4 {Tk_ImageCmd procedure, "height" option} -constraints {
192 testImageType
204 testImageType
193205 } -setup {
194206 imageCleanup
195207 } -body {
206218 image names x
207219 } -returnCodes error -result {wrong # args: should be "image names"}
208220 test image-4.2 {Tk_ImageCmd procedure, "names" option} -constraints {
209 testImageType
221 testImageType
210222 } -setup {
211223 catch {interp delete testinterp}
212224 } -body {
248260 } -returnCodes error -result {image "foo" doesn't exist}
249261
250262 test image-5.4 {Tk_ImageCmd procedure, "type" option} -constraints {
251 testImageType
263 testImageType
252264 } -setup {
253265 imageCleanup
254266 } -body {
258270 imageCleanup
259271 } -result {test}
260272 test image-5.5 {Tk_ImageCmd procedure, "type" option} -constraints {
261 testImageType
273 testImageType
262274 } -setup {
263275 imageCleanup
264276 } -body {
270282 imageCleanup
271283 } -returnCodes error -result {image "myimage" doesn't exist}
272284 test image-5.6 {Tk_ImageCmd procedure, "type" option} -constraints {
273 testOldImageType
285 testOldImageType
274286 } -setup {
275287 imageCleanup
276288 } -body {
280292 imageCleanup
281293 } -result {oldtest}
282294 test image-5.7 {Tk_ImageCmd procedure, "type" option} -constraints {
283 testOldImageType
295 testOldImageType
284296 } -setup {
285297 .c delete all
286298 imageCleanup
299311 image types x
300312 } -returnCodes error -result {wrong # args: should be "image types"}
301313 test image-6.2 {Tk_ImageCmd procedure, "types" option} -constraints {
302 testImageType
314 testImageType
303315 } -body {
304316 lsort [image types]
305317 } -result {bitmap oldtest photo test}
315327 image width foo
316328 } -returnCodes error -result {image "foo" doesn't exist}
317329 test image-7.4 {Tk_ImageCmd procedure, "width" option} -constraints {
318 testImageType
330 testImageType
319331 } -setup {
320332 imageCleanup
321333 } -body {
329341
330342
331343 test image-8.1 {Tk_ImageCmd procedure, "inuse" option} -constraints {
332 testImageType
344 testImageType
333345 } -setup {
334346 imageCleanup
335347 set res {}
343355 imageCleanup
344356 catch {destroy .b}
345357 } -result [list 0 1]
346
347
358
359 if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
360 # Aqua >= 10.14 will redraw the entire image in drawRect.
361 set result_9_1 {{foo display 0 0 30 15}}
362 } else {
363 set result_9_1 {{foo display 5 6 7 8}}
364 }
348365 test image-9.1 {Tk_ImageChanged procedure} -constraints testImageType -setup {
349366 .c delete all
350367 imageCleanup
368 update
351369 } -body {
352370 image create test foo -variable x
353371 .c create image 50 50 -image foo
354372 update
355373 set x {}
374 set timer [after 500 {lappend x "timed out"}]
356375 foo changed 5 6 7 8 30 15
357 update
358 return $x
359 } -cleanup {
360 .c delete all
361 imageCleanup
362 } -result {{foo display 5 6 7 8}}
376 update idletasks
377 update
378 # On MacOS we need to wait for the test image display procedure to run.
379 while {"timed out" ni $x && [lindex $x end 1] ne "display"} {
380 vwait x
381 }
382 after cancel $timer
383 return $x
384 } -cleanup {
385 .c delete all
386 imageCleanup
387 } -result $result_9_1
388 if {[tk windowingsystem] == "aqua" && $tcl_platform(osVersion) > 18} {
389 # Aqua >= 10.14 will redraw the entire image.
390 set result_9_2 {{foo display 0 0 30 15} {foo display 0 0 30 15}}
391 } else {
392 set result_9_2 {{foo display 5 6 25 9} {foo display 0 0 12 14}}
393 }
363394 test image-9.2 {Tk_ImageChanged procedure} -constraints testImageType -setup {
364395 .c delete all
365396 imageCleanup
397 update
366398 } -body {
367399 image create test foo -variable x
368400 .c create image 50 50 -image foo
370402 update
371403 set x {}
372404 foo changed 5 6 7 8 30 15
373 update
374 return $x
375 } -cleanup {
376 .c delete all
377 imageCleanup
378 } -result {{foo display 5 6 25 9} {foo display 0 0 12 14}}
379
405 set timer [after 500 {lappend x "timed out"}]
406 image create test myimage -variable x
407 vwait x
408 after cancel $timer
409 return $x
410 } -cleanup {
411 .c delete all
412 imageCleanup
413 } -result $result_9_2
380414
381415 test image-10.1 {Tk_GetImage procedure} -setup {
382416 imageCleanup
410444 update
411445 set x {}
412446 .c delete i1
447 set timer [after 500 {lappend x "timed out"}]
413448 pack .c
414 update
449 vwait x
450 after cancel $timer
415451 list [imageNames] $x
416452 } -cleanup {
417453 .c delete all
612648 .c delete all
613649 imageCleanup
614650 } -result {10 10 20 20 foo {} {10 10 30 30} foo}
615
651
616652 destroy .c
617653 imageFinish
618654
12111211 image create photo -file $fileName -format "gif -index 2"
12121212 } -returnCodes error -result {no image data for this index}
12131213
1214 test imgPhoto-14.6 {Access Subimage after Subimage with buffer overflow. Ticket 4da2191b} -setup {
1215 set data {
1216 R0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM
1217 hASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1218 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1219 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1220 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1221 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1222 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1223 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1224 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1225 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1226 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1227 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1228 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1229 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1230 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1231 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
1232 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/
1233 AP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD
1234 hxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN
1235 mzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC
1236 BUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J
1237 qlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn
1238 uqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0
1239 hciva9/Ovbv37+BzBgE7ACH5BAFkAAMALAAAAAAEAAQAAAMEKLrckgA7
1240 }
1241 } -body {
1242 image create photo photo1 -data $data -format "GIF -index 1"
1243 } -cleanup {
1244 catch {image delete photo1}
1245 } -result photo1
1246
12141247 test imgPhoto-15.1 {photo images can fail to allocate memory gracefully} -constraints {
12151248 nonPortable
12161249 } -body {
14031403 } -body {
14041404 set x [list a b c d]
14051405 set y [list 1 2 3 4]
1406 listbox .l2
1406 listbox .l2
14071407 .l2 configure -listvar x
14081408 .l2 configure -listvar y
14091409 .l2 insert end 5 6 7 8
15511551 } -cleanup {
15521552 destroy .l
15531553 } -result {}
1554
1554
15551555
15561556 # Listbox used in 6.*, 7.* tests
15571557 destroy .l
19121912 deleteWindows
19131913 } -result {{} {}}
19141914 test listbox-9.2 {ListboxCmdDeletedProc procedure, disabling -setgrid} -constraints {
1915 fonts
1915 fonts
19161916 } -setup {
19171917 destroy .top
19181918 } -body {
22082208 } -body {
22092209 listbox .l -height 5 -yscrollcommand "record y"
22102210 pack .l
2211 update
22112212 .l insert 0 a b c d e f g h i j
22122213 .l yview 3
22132214 update
26612662 destroy .l
26622663 } -body {
26632664 catch {unset x}
2665 listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
26642666 set log {}
2665 listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
26662667 pack .l
2667 update
2668 set timeout [after 500 {set log timeout}]
2669 vwait log
26682670 lappend x "0000000000"
26692671 update
26702672 lappend x "00000000000000000000"
26722674 set log
26732675 } -cleanup {
26742676 destroy .l
2677 after cancel $timeout
26752678 } -result [list {x 0 1} {x 0 1} {x 0 0.5}]
26762679 test listbox-21.10 {ListboxListVarProc, test hscrollbar after listvar mod} -setup {
26772680 destroy .l
26782681 } -body {
26792682 catch {unset x}
2683 listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
26802684 set log {}
2681 listbox .l -font $fixed -width 10 -xscrollcommand "record x" -listvar x
26822685 pack .l
2683 update
2686 set timeout [after 500 {set log timeout}]
2687 vwait log
26842688 lappend x "0000000000"
26852689 update
26862690 lappend x "00000000000000000000"
26902694 set log
26912695 } -cleanup {
26922696 destroy .l
2697 after cancel timeout
26932698 } -result [list {x 0 1} {x 0 1} {x 0 0.5} {x 0 1}]
26942699 test listbox-21.11 {ListboxListVarProc, bad list} -setup {
26952700 destroy .l
27542759 destroy .l
27552760 } -body {
27562761 catch {unset x}
2762 listbox .l -font $fixed -height 3 -yscrollcommand "record y" -listvar x
2763 update
27572764 set log {}
2758 listbox .l -listvar x -yscrollcommand "record y" -font fixed -height 3
27592765 pack .l
2766 set timeout [after 500 {set log timeout}]
2767 vwait log
27602768 update
27612769 lappend x a b c d e f
2762 update
2770 vwait log
27632771 set log
27642772 } -cleanup {
27652773 destroy .l
2774 after cancel $timeout
27662775 } -result [list {y 0 1} {y 0 0.5}]
27672776 test listbox-21.16 {ListboxListVarProc, update vertical scrollbar} -setup {
27682777 destroy .l
27702779 catch {unset x}
27712780 listbox .l -listvar x -height 3
27722781 pack .l
2773 update
27742782 set x [list 0 1 2 3 4 5]
27752783 .l yview scroll 3 units
27762784 update
27912799 test listbox-22.1 {UpdateHScrollbar} -setup {
27922800 destroy .l
27932801 } -body {
2802 listbox .l -font $fixed -width 10 -xscrollcommand "record x"
27942803 set log {}
2795 listbox .l -font $fixed -width 10 -xscrollcommand "record x"
27962804 pack .l
2797 update
2805 set timeout [after 500 {set log timeout}]
2806 vwait log
27982807 .l insert end "0000000000"
27992808 update
28002809 .l insert end "00000000000000000000"
2801 update
2810 vwait log
28022811 set log
28032812 } -cleanup {
28042813 destroy .l
2814 after cancel $timeout
28052815 } -result [list {x 0 1} {x 0 1} {x 0 0.5}]
28062816
28072817
29933003 } -cleanup {
29943004 destroy .l
29953005 } -result {{} red}
2996
3006
29973007
29983008 # state issues
29993009 test listbox-26.1 {listbox disabled state disallows inserts} -setup {
31763186 destroy .l
31773187 } -result {{.l 0} {{} {}}}
31783188
3189 test listbox-32.1 {Bug [5d991b822e]} {
3190 # Want this not to segfault, or write to variable with empty name
3191 set var INIT
3192 listbox .b -listvariable var
3193 trace add variable var unset {apply {args {
3194 .b configure -listvariable {}
3195 }}}
3196 pack .b
3197 bind .b <Configure> {unset var}
3198 update
3199 destroy .b
3200 info exists {}
3201 } 0
3202 test listbox-32.2 {Bug [5d991b822e]} {
3203 # Want this not to leak traces
3204 set var INIT
3205 listbox .b -listvariable var
3206 trace add variable var unset {apply {args {
3207 .b configure -listvariable new
3208 }}}
3209 pack .b
3210 bind .b <Configure> {unset -nocomplain var}
3211 update
3212 destroy .b
3213 unset new
3214 } {}
3215
31793216 resetGridInfo
31803217 deleteWindows
31813218 option clear
16051605 .m1 post
16061606 } -cleanup {
16071607 destroy .m1
1608 } -returnCodes error -result {wrong # args: should be ".m1 post x y"}
1608 } -returnCodes error -result {wrong # args: should be ".m1 post x y ?index?"}
16091609 test menu-3.48 {MenuWidgetCmd procedure, "post" option} -setup {
16101610 destroy .m1
16111611 } -body {
31613161 } -cleanup {
31623162 deleteWindows
31633163 } -result {{} goodbye {}}
3164 test menu-17.6 {MenuVarProc [5d991b822e]} -setup {
3165 deleteWindows
3166 } -body {
3167 # Want this not to crash
3168 menu .b
3169 set var INIT
3170 .b add checkbutton -variable var
3171 trace add variable var unset {apply {args {
3172 .b entryconfigure 1 -variable {}
3173 }}}
3174 unset var
3175 } -cleanup {
3176 deleteWindows
3177 } -result {}
3178 test menu-17.7 {MenuVarProc [5d991b822e]} -setup {
3179 deleteWindows
3180 } -body {
3181 # Want this not to duplicate traces
3182 menu .b
3183 set var INIT
3184 .b add checkbutton -variable var
3185 trace add variable var unset {apply {args {
3186 .b entryconfigure 1 -variable new
3187 }}}
3188 unset var
3189 } -cleanup {
3190 deleteWindows
3191 } -result {}
31643192
31653193
31663194 test menu-18.1 {TkActivateMenuEntry} -setup {
1919 } -result {.m1}
2020
2121
22 test menuDraw-2.1 {TkIntializeMenuEntryDrawingFields} -setup {
22 test menuDraw-2.1 {TkInitializeMenuEntryDrawingFields} -setup {
2323 deleteWindows
2424 } -body {
2525 menu .m1
541541 deleteWindows
542542 } -result {{} {}}
543543
544
544 if {[tk windowingsystem] == "aqua"} {
545 set extraWidth 36
546 } else {
547 set extraWidth 0
548 }
545549 test menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {
546550 testImageType
547551 } -setup {
554558 } -cleanup {
555559 deleteWindows
556560 imageCleanup
557 } -result {38 23}
561 } -result [list [expr {38 + $extraWidth}] 23]
558562 test menubutton-7.2 {ComputeMenuButtonGeometry procedure} -constraints {
559563 testImageType
560564 } -setup {
561565 deleteWindows
562566 image create test image1
563567 } -body {
564 menubutton .mb -image image1 -bd 1 -highlightthickness 2
565 pack .mb
566 list [winfo reqwidth .mb] [winfo reqheight .mb]
567 } -cleanup {
568 deleteWindows
569 imageCleanup
570 } -result {36 21}
568 menubutton .mb -image image1 -bd 3 -highlightthickness 1
569 pack .mb
570 list [winfo reqwidth .mb] [winfo reqheight .mb]
571 } -cleanup {
572 deleteWindows
573 imageCleanup
574 } -result [list [expr {38 + $extraWidth}] 23]
571575 test menubutton-7.3 {ComputeMenuButtonGeometry procedure} -constraints {
572576 testImageType
573577 } -setup {
574578 deleteWindows
575579 image create test image1
576580 } -body {
577 menubutton .mb -image image1 -bd 0 -highlightthickness 2 -padx 5 -pady 5
578 pack .mb
579 list [winfo reqwidth .mb] [winfo reqheight .mb]
580 } -cleanup {
581 deleteWindows
582 imageCleanup
583 } -result {34 19}
581 menubutton .mb -image image1 -bd 1 -highlightthickness 3 -padx 5 -pady 5
582 pack .mb
583 list [winfo reqwidth .mb] [winfo reqheight .mb]
584 } -cleanup {
585 deleteWindows
586 imageCleanup
587 } -result [list [expr {38 + $extraWidth}] 23]
584588 test menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {
585589 testImageType
586590 } -setup {
594598 } -cleanup {
595599 deleteWindows
596600 imageCleanup
597 } -result {48 23}
601 } -result [list [expr {48 + $extraWidth}] 23]
598602 test menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {
599603 testImageType
600604 } -setup {
608612 } -cleanup {
609613 deleteWindows
610614 imageCleanup
611 } -result {38 38}
615 } -result [list [expr {38 + $extraWidth}] 38]
612616 test menubutton-7.6 {ComputeMenuButtonGeometry procedure} -setup {
613617 deleteWindows
614618 } -body {
618622 list [winfo reqwidth .mb] [winfo reqheight .mb]
619623 } -cleanup {
620624 deleteWindows
621 } -result {25 35}
625 } -result [list [expr {25 + $extraWidth}] 35]
622626 test menubutton-7.7 {ComputeMenuButtonGeometry procedure} -setup {
623627 deleteWindows
624628 } -body {
628632 list [winfo reqwidth .mb] [winfo reqheight .mb]
629633 } -cleanup {
630634 deleteWindows
631 } -result {46 33}
635 } -result [list [expr {46 + $extraWidth}] 33]
632636 test menubutton-7.8 {ComputeMenuButtonGeometry procedure} -setup {
633637 deleteWindows
634638 } -body {
638642 list [winfo reqwidth .mb] [winfo reqheight .mb]
639643 } -cleanup {
640644 deleteWindows
641 } -result {23 56}
645 } -result [list [expr {23 + $extraWidth}] 56]
642646 test menubutton-7.9 {ComputeMenuButtonGeometry procedure} -constraints {
643647 fonts
644648 } -setup {
746750 expr {$res1 eq $res2}
747751 } -result 1
748752
753 test menubutton-9.1 {Bug [5d991b822e]} {
754 # Want this not to segfault, or write to variable with empty name
755 unset -nocomplain {}
756 set var INIT
757 menubutton .b -textvariable var
758 trace add variable var unset {apply {args {
759 .b configure -textvariable {}
760 }}}
761 pack .b
762 bind .b <Configure> {unset var}
763 update
764 destroy .b
765 info exists {}
766 } 0
767 test menubutton-9.2 {Bug [5d991b822e]} {
768 # Want this not to leak traces
769 set var INIT
770 menubutton .b -textvariable var
771 trace add variable var unset {apply {args {
772 .b configure -textvariable new
773 }}}
774 pack .b
775 bind .b <Configure> {unset -nocomplain var}
776 update
777 destroy .b
778 unset new
779 } {}
780
781
749782
750783
751784 deleteWindows
469469 destroy .m
470470 } -result {4}
471471
472 test message-4.1 {Bug [5d991b822e]} {
473 # Want this not to segfault, or write to variable with empty name
474 unset -nocomplain {}
475 set var INIT
476 message .b -textvariable var
477 trace add variable var unset {apply {args {
478 .b configure -textvariable {}
479 }}}
480 pack .b
481 bind .b <Configure> {unset var}
482 update
483 destroy .b
484 info exists {}
485 } 0
486 test message-4.2 {Bug [5d991b822e]} {
487 # Want this not to leak traces
488 set var INIT
489 message .b -textvariable var
490 trace add variable var unset {apply {args {
491 .b configure -textvariable new
492 }}}
493 pack .b
494 bind .b <Configure> {unset -nocomplain var}
495 update
496 destroy .b
497 unset new
498 } {}
499
472500 cleanupTests
473501 return
975975 winfo manager .pack.a
976976 pack .pack.a -in .pack.a
977977 } -returnCodes error -result {can't pack .pack.a inside itself}
978 test pack-10.5 {prevent management loops} -body {
979 frame .f1
980 frame .f2
981 pack .f1 -in .f2
982 pack .f2 -in .f1
983 } -cleanup {
984 destroy .f1
985 destroy .f2
986 } -returnCodes error -result {can't put .f2 inside .f1, would cause management loop}
987 test pack-10.6 {prevent management loops} -body {
988 frame .f1
989 frame .f2
990 frame .f3
991 pack .f1 -in .f2
992 pack .f2 -in .f3
993 pack .f3 -in .f1
994 } -cleanup {
995 destroy .f1
996 destroy .f2
997 destroy .f3
998 } -returnCodes error -result {can't put .f3 inside .f1, would cause management loop}
978999
9791000
9801001 test pack-11.1 {info option} -setup {
15401561
15411562 wm geometry .pack +100+100
15421563
1543 # On the PC, when the width/height is configured while the window is
1564 # On the PC, when the width/height is configured while the window is
15441565 # unmapped, the changes don't take effect until the window is remapped.
15451566 # Who knows why?
15461567
117117 } -body {
118118 place .t.f2 -in .
119119 } -returnCodes error -result {can't place .t.f2 relative to .}
120
120 test place-4.5 {ConfigureSlave procedure, bad -in option} -setup {
121 } -body {
122 frame .t.f1
123 place .t.f1 -in .t.f1
124 } -returnCodes error -result {can't place .t.f1 relative to itself}
125 test place-4.6 {prevent management loops} -setup {
126 place forget .t.f1
127 } -body {
128 place .t.f1 -in .t.f2
129 place .t.f2 -in .t.f1
130 } -returnCodes error -result {can't put .t.f2 inside .t.f1, would cause management loop}
131 test place-4.7 {prevent management loops} -setup {
132 place forget .t.f1
133 place forget .t.f2
134 } -body {
135 frame .t.f3
136 place .t.f1 -in .t.f2
137 place .t.f2 -in .t.f3
138 place .t.f3 -in .t.f1
139 } -returnCodes error -result {can't put .t.f3 inside .t.f1, would cause management loop}
121140
122141 test place-5.1 {ConfigureSlave procedure, -relwidth option} -body {
123142 place .t.f2 -relwidth abcd
130130 raise_getOrder
131131 } -result {a d d a c e e e}
132132 test raise-3.2 {raise internal windows after creation} -constraints {
133 testmakeexist
133 testmakeexist
134134 } -body {
135135 raise_setup
136136 testmakeexist .raise.a .raise.b
139139 raise_getOrder
140140 } -result {d d d a c e e e}
141141 test raise-3.3 {raise internal windows after creation} -constraints {
142 testmakeexist
142 testmakeexist
143143 } -body {
144144 raise_setup
145145 testmakeexist .raise.a .raise.d
148148 raise_getOrder
149149 } -result {d d d a c e e e}
150150 test raise-3.4 {raise internal windows after creation} -constraints {
151 testmakeexist
151 testmakeexist
152152 } -body {
153153 raise_setup
154154 testmakeexist .raise.a .raise.c .raise.d
11031103 destroy .s
11041104 pack [scale .s]
11051105 update
1106 test scale-14.1 {RoundToResolution procedure} -body {
1106 test scale-14.1 {RoundValueToResolution procedure} -body {
11071107 .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2 \
11081108 -orient horizontal -resolution 4.0
11091109 update
11101110 .s get 84 152
11111111 } -result 72
1112 test scale-14.2 {RoundToResolution procedure} -body {
1112 test scale-14.2 {RoundValueToResolution procedure} -body {
11131113 .s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2 \
11141114 -orient horizontal -resolution 4.0
11151115 update
11161116 .s get 86 152
11171117 } -result 76
11181118
1119 test scale-14.3 {RoundToResolution procedure} -body {
1119 test scale-14.3 {RoundValueToResolution procedure} -body {
11201120 .s configure -from 100 -to 0 -sliderlength 10 -length 114 -bd 2 \
11211121 -orient horizontal -resolution 4.0
11221122 update
11231123 .s get 84 152
11241124 } -result 28
1125 test scale-14.4 {RoundToResolution procedure} -body {
1125 test scale-14.4 {RoundValueToResolution procedure} -body {
11261126 .s configure -from 100 -to 0 -sliderlength 10 -length 114 -bd 2 \
11271127 -orient horizontal -resolution 4.0
11281128 update
11291129 .s get 86 152
11301130 } -result 24
11311131
1132 test scale-14.5 {RoundToResolution procedure} -body {
1132 test scale-14.5 {RoundValueToResolution procedure} -body {
11331133 .s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \
11341134 -orient horizontal -resolution 4.0
11351135 update
11361136 .s get 84 152
11371137 } -result {-28}
1138 test scale-14.6 {RoundToResolution procedure} -body {
1138 test scale-14.6 {RoundValueToResolution procedure} -body {
11391139 .s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \
11401140 -orient horizontal -resolution 4.0
11411141 update
11421142 .s get 86 152
11431143 } -result {-24}
11441144
1145 test scale-14.7 {RoundToResolution procedure} -body {
1145 test scale-14.7 {RoundValueToResolution procedure} -body {
11461146 .s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \
11471147 -orient horizontal -resolution 4.0
11481148 update
11491149 .s get 84 152
11501150 } -result {-72}
1151 test scale-14.8 {RoundToResolution procedure} -body {
1151 test scale-14.8 {RoundValueToResolution procedure} -body {
11521152 .s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \
11531153 -orient horizontal -resolution 4.0
11541154 update
11551155 .s get 86 152
11561156 } -result {-76}
11571157
1158 test scale-14.9 {RoundToResolution procedure} -body {
1158 test scale-14.9 {RoundValueToResolution procedure} -body {
11591159 .s configure -from 0 -to 2.25 -sliderlength 10 -length 114 -bd 2 \
11601160 -orient horizontal -resolution 0
11611161 update
11621162 .s get 84 152
11631163 } -result {1.64}
1164 test scale-14.10 {RoundToResolution procedure} -body {
1164 test scale-14.10 {RoundValueToResolution procedure} -body {
11651165 .s configure -from 0 -to 2.25 -sliderlength 10 -length 114 -bd 2 \
11661166 -orient horizontal -resolution 0
11671167 update
11681168 .s get 86 152
11691169 } -result {1.69}
11701170
1171 test scale-14.11 {RoundToResolution procedure} -body {
1171 test scale-14.11 {RoundValueToResolution procedure} -body {
11721172 .s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \
11731173 -orient horizontal -resolution 0 -digits 5
11741174 update
11751175 .s get 84 152
11761176 } -result {164.25}
1177 test scale-14.12 {RoundToResolution procedure} -body {
1177 test scale-14.12 {RoundValueToResolution procedure} -body {
11781178 .s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \
11791179 -orient horizontal -resolution 0 -digits 5
11801180 update
11811181 .s get 86 152
11821182 } -result {168.75}
11831183 destroy .s
1184
1185 test scale-14.13 {RoundValueToResolution procedure, round-off errors} -setup {
1186 # see [220665ffff], and duplicates [220265ffff] and [779559ffff]
1187 set x NotSet
1188 pack [scale .s -orient horizontal -resolution .1 -from -180 -to 180 -command "set x"]
1189 update
1190 } -body {
1191 .s configure -background red
1192 update
1193 set x
1194 } -cleanup {
1195 destroy .s
1196 } -result {NotSet}
1197
1198 test scale-14a.1 {RoundValueToResolution, RoundIntervalToResolution procedures} -setup {
1199 pack [scale .s -orient horizontal]
1200 update
1201 } -body {
1202 .s configure -length 400 -bd 0 -from 1 -to 9 -resolution 2 -tickinterval 1
1203 update
1204 .s get 200 0
1205 } -cleanup {
1206 destroy .s
1207 } -result {5}
1208 test scale-14a.2 {RoundValueToResolution, RoundIntervalToResolution procedures} -setup {
1209 pack [scale .s -orient horizontal]
1210 update
1211 } -body {
1212 .s configure -length 400 -bd 0 -from -1.5 -to 1.5 -resolution 1 \
1213 -tickinterval 1 -digits 2
1214 update
1215 .s get 250 0
1216 } -cleanup {
1217 destroy .s
1218 } -result {0.5}
11841219
11851220
11861221 test scale-15.1 {ScaleVarProc procedure} -setup {
14421477 scale .s -from 1 -to 50 -command {set commandedVar}
14431478 .s set 10
14441479 pack .s
1445 update ; # -command callback shall fire
1480 set timeout [after 500 {set $commandedVar "timeout"}]
1481 vwait commandedVar ; # -command callback shall fire
14461482 set res [list [.s get] $commandedVar]
14471483 } -cleanup {
14481484 destroy .s
1485 after cancel $timeout
14491486 } -result {10 10}
14501487 test scale-20.5 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 5} -setup {
14511488 catch {destroy .s}
14701507 pack .s
14711508 .s configure -command {set commandedVar}
14721509 .s set 10
1473 update ; # -command callback shall fire
1510 set timeout [after 500 {set $commandedVar "timeout"}]
1511 vwait commandedVar ; # -command callback shall fire
14741512 set res [list [.s get] $commandedVar]
14751513 } -cleanup {
14761514 destroy .s
1515 after cancel $timeout
14771516 } -result {10 10}
14781517 test scale-20.7 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 7} -setup {
14791518 catch {destroy .s}
14831522 scale .s -from 1 -to 50 -command {set commandedVar}
14841523 pack .s
14851524 .s set 10
1486 update ; # -command callback shall fire
1525 set timeout [after 500 {set $commandedVar "timeout"}]
1526 vwait commandedVar ; # -command callback shall fire
14871527 set res [list [.s get] $commandedVar]
14881528 } -cleanup {
14891529 destroy .s
1530 after cancel $timeout
14901531 } -result {10 10}
14911532 test scale-20.8 {Bug [2262543fff] - Scale widget unexpectedly fires command callback, case 8} -setup {
14921533 catch {destroy .s}
14971538 scale .s -from 1 -to 50 -variable scaleVar -command {set commandedVar}
14981539 pack .s
14991540 .s set 10
1500 update ; # -command callback shall fire
1541 set timeout [after 500 {set $commandedVar "timeout"}]
1542 vwait commandedVar ; # -command callback shall fire
15011543 set res [list [.s get] $commandedVar]
15021544 } -cleanup {
15031545 destroy .s
1546 after cancel $timeout
15041547 } -result {10 10}
15051548
15061549 test scale-21.1 {Bug [55b95f578a] - Associating variable with bignum value with scale crashes it} -setup {
15231566 destroy .s
15241567 } -result {}
15251568
1569 test scale-22.1 {Bug [5d991b822e]} {
1570 # Want this not to crash
1571 set var INIT
1572 scale .b -variable var
1573 trace add variable var unset {apply {args {
1574 .b configure -variable {}
1575 }}}
1576 pack .b
1577 bind .b <Configure> {unset var}
1578 update
1579 destroy .b
1580 } {}
1581 test scale-22.2 {Bug [5d991b822e]} {
1582 # Want this not to leak traces
1583 set var INIT
1584 scale .b -variable var
1585 trace add variable var unset {apply {args {
1586 .b configure -variable new
1587 }}}
1588 pack .b
1589 bind .b <Configure> {unset -nocomplain var}
1590 update
1591 destroy .b
1592 unset new
1593 } {}
1594
15261595 option clear
15271596
15281597 # cleanup
1919 if {[testConstraint testmetrics]} {
2020 # Only Windows has [testmetrics]
2121 if [string match v* [$w cget -orient]] {
22 return [expr [winfo height $w] - 2*[testmetrics cyvscroll $w]]
22 return [expr {[winfo height $w] - 2*[testmetrics cyvscroll $w]}]
2323 } else {
24 return [expr [winfo width $w] - 2*[testmetrics cxhscroll $w]]
24 return [expr {[winfo width $w] - 2*[testmetrics cxhscroll $w]}]
2525 }
2626 } else {
2727 if {[tk windowingsystem] eq "x11"} {
2828 # Calculations here assume that the arrow area is a square.
2929 if [string match v* [$w cget -orient]] {
30 return [expr [winfo height $w] \
30 return [expr {[winfo height $w] \
3131 - ([winfo width $w] \
3232 - [$w cget -highlightthickness] \
33 - [$w cget -bd] + 1)*2]
33 - [$w cget -bd] + 1)*2}]
3434 } else {
35 return [expr [winfo width $w] \
35 return [expr {[winfo width $w] \
3636 - ([winfo height $w] \
3737 - [$w cget -highlightthickness] \
38 - [$w cget -bd] + 1)*2]
38 - [$w cget -bd] + 1)*2}]
3939 }
4040 } else {
4141 # macOS aqua
4242 if [string match v* [$w cget -orient]] {
43 return [expr [winfo height $w] \
43 return [expr {[winfo height $w] \
4444 - ([$w cget -highlightthickness] \
45 +[$w cget -bd])*2]
45 +[$w cget -bd])*2}]
4646 } else {
47 return [expr [winfo width $w] \
47 return [expr {[winfo width $w] \
4848 - ([$w cget -highlightthickness] \
49 +[$w cget -bd])*2]
49 +[$w cget -bd])*2}]
5050 }
5151 }
5252 }
5757 # as you fix bugs and add features.
5858
5959 foreach {width height} [wm minsize .] {
60 set height [expr ($height < 200) ? 200 : $height]
61 set width [expr ($width < 1) ? 1 : $width]
60 set height [expr {($height < 200) ? 200 : $height}]
61 set width [expr {($width < 1) ? 1 : $width}]
6262 }
6363
6464 frame .f -height $height -width $width
232232 } {0}
233233 test scrollbar-3.26 {ScrollbarWidgetCmd procedure, "delta" option} {
234234 format {%.6g} [.s delta 0 20]
235 } [format %.6g [expr 20.0/([getTroughSize .s]-1)]]
235 } [format %.6g [expr {20.0/([getTroughSize .s]-1)}]]
236236 test scrollbar-3.27 {ScrollbarWidgetCmd procedure, "delta" option} {
237237 format {%.6g} [.s delta 0 -20]
238 } [format %.6g [expr -20.0/([getTroughSize .s]-1)]]
238 } [format %.6g [expr {-20.0/([getTroughSize .s]-1)}]]
239239 test scrollbar-3.28 {ScrollbarWidgetCmd procedure, "delta" option} {
240240 toplevel .t -width 250 -height 100
241241 wm geom .t +0+0
243243 place .t.s -width 201
244244 update
245245 set result [list [format {%.6g} [.t.s delta 0 20]] \
246 [format {%.6g} [.t.s delta [expr [getTroughSize .t.s] - 1] 0]]]
246 [format {%.6g} [.t.s delta [expr {[getTroughSize .t.s] - 1}] 0]]]
247247 destroy .t
248248 set result
249249 } {0 1}
267267 } {1}
268268 test scrollbar-3.35 {ScrollbarWidgetCmd procedure, "fraction" option} {
269269 format {%.6g} [.s fraction 4 21]
270 } [format %.6g [expr (21.0 - ([winfo height .s] - [getTroughSize .s])/2.0) \
271 /([getTroughSize .s] - 1)]]
270 } [format %.6g [expr {(21.0 - ([winfo height .s] - [getTroughSize .s])/2.0) \
271 /([getTroughSize .s] - 1)}]]
272272 test scrollbar-3.36 {ScrollbarWidgetCmd procedure, "fraction" option} x11 {
273273 format {%.6g} [.s fraction 4 179]
274274 } {1}
275275 test scrollbar-3.37 {ScrollbarWidgetCmd procedure, "fraction" option} {testmetrics} {
276 format {%.6g} [.s fraction 4 [expr 200 - [testmetrics cyvscroll .s]]]
276 format {%.6g} [.s fraction 4 [expr {200 - [testmetrics cyvscroll .s]}]]
277277 } {1}
278278 test scrollbar-3.38 {ScrollbarWidgetCmd procedure, "fraction" option} x11 {
279279 format {%.6g} [.s fraction 4 178]
280280 } {0.993711}
281281 test scrollbar-3.39 {ScrollbarWidgetCmd procedure, "fraction" option} {testmetrics win} {
282 expr \
283 [format {%.6g} [.s fraction 4 [expr 200 - [testmetrics cyvscroll .s] - 2]]] \
284 == [format %g [expr (200.0 - [testmetrics cyvscroll .s]*2 - 2) \
285 / ($height - 1 - [testmetrics cyvscroll .s]*2)]]
282 expr {
283 [format {%.6g} [.s fraction 4 [expr {200 - [testmetrics cyvscroll .s] - 2}]]]
284 == [format %g [expr {(200.0 - [testmetrics cyvscroll .s]*2 - 2)
285 / ($height - 1 - [testmetrics cyvscroll .s]*2)}]]}
286286 } 1
287287
288288 toplevel .t -width 250 -height 100
296296 } {0.5}
297297 if {[testConstraint testmetrics]} {
298298 # Only Windows has [testmetrics]
299 place configure .t.s -width [expr 2*[testmetrics cxhscroll .t.s]+1]
299 place configure .t.s -width [expr {2*[testmetrics cxhscroll .t.s]+1}]
300300 } else {
301301 if {[tk windowingsystem] eq "x11"} {
302 place configure .t.s -width [expr [winfo height .t.s] - 2*([.t.s cget -highlightthickness] + [.t.s cget -bd] + 1)]
302 place configure .t.s -width [expr {[winfo height .t.s] - 2*([.t.s cget -highlightthickness] + [.t.s cget -bd] + 1)}]
303303 } else {
304304 # macOS aqua
305 place configure .t.s -width [expr 2*([.t.s cget -highlightthickness] + [.t.s cget -bd])]
305 place configure .t.s -width [expr {2*([.t.s cget -highlightthickness] + [.t.s cget -bd])}]
306306 }
307307 }
308308 update
472472 .s identify 19 100
473473 } {}
474474 test scrollbar-6.7 {ScrollbarPosition procedure} {
475 .s identify [expr [winfo width .s] / 2] -1
475 .s identify [expr {[winfo width .s] / 2}] -1
476476 } {}
477477 test scrollbar-6.8 {ScrollbarPosition procedure} {
478 .s identify [expr [winfo width .s] / 2] [expr [winfo height .s]]
478 .s identify [expr {[winfo width .s] / 2}] [winfo height .s]
479479 } {}
480480 test scrollbar-6.9 {ScrollbarPosition procedure} {
481 .s identify -1 [expr [winfo height .s] / 2]
481 .s identify -1 [expr {[winfo height .s] / 2}]
482482 } {}
483483 test scrollbar-6.10 {ScrollbarPosition procedure} {
484 .s identify [winfo width .s] [expr [winfo height .s] / 2]
484 .s identify [winfo width .s] [expr {[winfo height .s] / 2}]
485485 } {}
486486 test scrollbar-6.11.1 {ScrollbarPosition procedure} x11 {
487487 .s identify 8 4
498498 .s identify 8 19
499499 } {trough1}
500500 test scrollbar-6.14 {ScrollbarPosition procedure} win {
501 .s identify [expr [winfo width .s] / 2] 0
501 .s identify [expr {[winfo width .s] / 2}] 0
502502 } {arrow1}
503503 test scrollbar-6.15 {ScrollbarPosition procedure} {testmetrics win} {
504 .s identify [expr [winfo width .s] / 2] [expr [testmetrics cyvscroll .s] - 1]
504 .s identify [expr {[winfo width .s] / 2}] [expr {[testmetrics cyvscroll .s] - 1}]
505505 } {arrow1}
506506 test scrollbar-6.16 {ScrollbarPosition procedure} unix {
507507 .s identify 8 20
512512 .s identify 8 51
513513 } {trough1}
514514 test scrollbar-6.18 {ScrollbarPosition procedure} {testmetrics win} {
515 .s identify [expr [winfo width .s] / 2] [testmetrics cyvscroll .s]
515 .s identify [expr {[winfo width .s] / 2}] [testmetrics cyvscroll .s]
516516 } {trough1}
517517 test scrollbar-6.19 {ScrollbarPosition procedure} {testmetrics win} {
518 .s identify [expr [winfo width .s] / 2] [expr int(.2 / [.s delta 0 1]) \
519 + [testmetrics cyvscroll .s] - 1]
518 .s identify [expr {[winfo width .s] / 2}] [expr {int(.2 / [.s delta 0 1])
519 + [testmetrics cyvscroll .s] - 1}]
520520 } {trough1}
521521 test scrollbar-6.20 {ScrollbarPosition procedure} unix {
522522 .s identify 8 52
527527 .s identify 8 83
528528 } {slider}
529529 test scrollbar-6.22 {ScrollbarPosition procedure} {testmetrics win} {
530 .s identify [expr [winfo width .s] / 2] \
531 [expr int(.2 / [.s delta 0 1] + 0.5) + [testmetrics cyvscroll .s]]
530 .s identify [expr {[winfo width .s] / 2}] \
531 [expr {int(.2 / [.s delta 0 1] + 0.5) + [testmetrics cyvscroll .s]}]
532532 } {slider}
533533 test scrollbar-6.23 {ScrollbarPosition procedure} {testmetrics win} {
534 .s identify [expr [winfo width .s] / 2] [expr int(.4 / [.s delta 0 1]) \
535 + [testmetrics cyvscroll .s] - 1]
534 .s identify [expr {[winfo width .s] / 2}] [expr {int(.4 / [.s delta 0 1])
535 + [testmetrics cyvscroll .s] - 1}]
536536 } {slider}
537537 test scrollbar-6.24 {ScrollbarPosition procedure} unix {
538538 .s identify 8 84
541541 .s identify 8 179
542542 } {trough2}
543543 test scrollbar-6.27 {ScrollbarPosition procedure} {testmetrics win} {
544 .s identify [expr [winfo width .s] / 2] [expr int(.4 / [.s delta 0 1]) \
545 + [testmetrics cyvscroll .s]]
544 .s identify [expr {[winfo width .s] / 2}] [expr {int(.4 / [.s delta 0 1])
545 + [testmetrics cyvscroll .s]}]
546546 } {trough2}
547547 test scrollbar-6.28 {ScrollbarPosition procedure} {testmetrics win} {
548 .s identify [expr [winfo width .s] / 2] [expr [winfo height .s] \
549 - [testmetrics cyvscroll .s] - 1]
548 .s identify [expr {[winfo width .s] / 2}] [expr {[winfo height .s]
549 - [testmetrics cyvscroll .s] - 1}]
550550 } {trough2}
551551 test scrollbar-6.29.1 {ScrollbarPosition procedure} x11 {
552552 .s identify 8 180
563563 .s identify 8 195
564564 } {trough2}
565565 test scrollbar-6.32 {ScrollbarPosition procedure} {testmetrics win} {
566 .s identify [expr [winfo width .s] / 2] [expr [winfo height .s] \
567 - [testmetrics cyvscroll .s]]
566 .s identify [expr {[winfo width .s] / 2}] [expr {[winfo height .s]
567 - [testmetrics cyvscroll .s]}]
568568 } {arrow2}
569569 test scrollbar-6.33 {ScrollbarPosition procedure} win {
570 .s identify [expr [winfo width .s] / 2] [expr [winfo height .s] - 1]
570 .s identify [expr {[winfo width .s] / 2}] [expr {[winfo height .s] - 1}]
571571 } {arrow2}
572572 test scrollbar-6.34 {ScrollbarPosition procedure} unix {
573573 .s identify 4 100
579579 .s identify 0 100
580580 } {trough2}
581581 test scrollbar-6.38 {ScrollbarPosition procedure} win {
582 .s identify [expr [winfo width .s] - 1] 100
582 .s identify [expr {[winfo width .s] - 1}] 100
583583 } {trough2}
584584
585585 catch {destroy .t}
598598 .t.s identify 4 8
599599 } {trough1}
600600 test scrollbar-6.40 {ScrollbarPosition procedure} win {
601 .t.s identify 0 [expr [winfo height .t.s] / 2]
601 .t.s identify 0 [expr {[winfo height .t.s] / 2}]
602602 } {arrow1}
603603 test scrollbar-6.41.1 {ScrollbarPosition procedure} x11 {
604604 .t.s identify 82 8
608608 .t.s identify 82 8
609609 } {trough2}
610610 test scrollbar-6.43 {ScrollbarPosition procedure} {testmetrics win} {
611 .t.s identify [expr int(.4 / [.t.s delta 1 0]) + [testmetrics cxhscroll .t.s] \
612 - 1] [expr [winfo height .t.s] / 2]
611 .t.s identify [expr {int(.4 / [.t.s delta 1 0]) + [testmetrics cxhscroll .t.s]
612 - 1}] [expr {[winfo height .t.s] / 2}]
613613 } {slider}
614614 test scrollbar-6.44 {ScrollbarPosition procedure} unix {
615615 .t.s identify 100 18
616616 } {trough2}
617617 test scrollbar-6.46 {ScrollbarPosition procedure} win {
618 .t.s identify 100 [expr [winfo height .t.s] - 1]
618 .t.s identify 100 [expr {[winfo height .t.s] - 1}]
619619 } {trough2}
620620
621621 test scrollbar-7.1 {EventuallyRedraw} {
644644 .t.f.s set 0 .5
645645 update
646646 set result [winfo exists .t.f.s]
647 event generate .t.f.s <ButtonPress> -button 1 -x [expr [winfo width .t.f.s] / 2] -y 5
647 event generate .t.f.s <ButtonPress> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5
648648 event generate .t <ButtonRelease> -button 1
649649 update
650650 lappend result [winfo exists .t.f.s] [winfo exists .t.f]
665665 .t.f.s set 0 .5
666666 update
667667 set result [winfo exists .t.f.s]
668 event generate .t.f.s <ButtonPress> -button 1 -x [expr [winfo width .t.f.s] / 2] -y 5
668 event generate .t.f.s <ButtonPress> -button 1 -x [expr {[winfo width .t.f.s] / 2}] -y 5
669669 event generate .t.f <ButtonRelease> -button 1
670670 update
671671 lappend result [winfo exists .t.f.s] [winfo exists .t.f]
3535 if {$numBytes <= 0} {
3636 return ""
3737 }
38 string range $selValue $offset [expr $numBytes+$offset]
38 string range $selValue $offset [expr {$numBytes+$offset}]
3939 }
4040
4141 proc errIncrHandler {type offset count} {
5454 if {$numBytes <= 0} {
5555 return ""
5656 }
57 string range $selValue $offset [expr $numBytes+$offset]
57 string range $selValue $offset [expr {$numBytes+$offset}]
5858 }
5959
6060 proc errHandler args {
6969 if {$numBytes <= 0} {
7070 return ""
7171 }
72 string range $selValue $offset [expr $numBytes+$offset]
72 string range $selValue $offset [expr {$numBytes+$offset}]
7373 }
7474 proc reallyBadHandler {path type offset count} {
7575 global selValue selInfo pass
8585 if {$numBytes <= 0} {
8686 return ""
8787 }
88 string range $selValue $offset [expr $numBytes+$offset]
88 string range $selValue $offset [expr {$numBytes+$offset}]
8989 }
9090
9191 # Eliminate any existing selection on the screen. This is needed in case
11461146 if {$numBytes <= 0} {
11471147 return ""
11481148 }
1149 string range $selValue $offset [expr $numBytes+$offset]
1149 string range $selValue $offset [expr {$numBytes+$offset}]
11501150 }
11511151 set selValue $longValue
11521152 set selInfo ""
196196 list [tk appname foo] [testsend prop root InterpRegistry]
197197 } "{foo #4} {$commId foo #4\n$id foo\n$id foo #2\n$id foo #3\n}"
198198
199 test send-8.1 {Tk_SendCmd procedure, options} {secureserver} {
199 #macOS does not send to other processes
200 test send-8.1 {Tk_SendCmd procedure, options} {secureserver notAqua} {
200201 setupbg
201202 set app [dobg {tk appname}]
202203 set a 66
221222 cleanupbg
222223 set result
223224 } {altDisplay homeDisplay}
224 test send-8.3 {Tk_SendCmd procedure, options} {secureserver} {
225 # Since macOS has no registry of interpreters, 8.3, 8.4 and 8.10 will fail.
226 test send-8.3 {Tk_SendCmd procedure, options} {secureserver notAqua} {
225227 list [catch {send -- -async foo bar baz} msg] $msg
226228 } {1 {no application named "-async"}}
227 test send-8.4 {Tk_SendCmd procedure, options} {secureserver} {
229 test send-8.4 {Tk_SendCmd procedure, options} {secureserver notAqua} {
228230 list [catch {send -gorp foo bar baz} msg] $msg
229231 } {1 {no application named "-gorp"}}
230232 test send-8.5 {Tk_SendCmd procedure, options} {secureserver} {
252254 "open bad_file"
253255 invoked from within
254256 "send [tk appname] open bad_file"} {posix enoent {no such file or directory}}}
255 test send-8.10 {Tk_SendCmd procedure, no such interpreter} {secureserver} {
257 test send-8.10 {Tk_SendCmd procedure, no such interpreter} {secureserver notAqua} {
256258 list [catch {send bogus_name bogus_command} msg] $msg
257259 } {1 {no application named "bogus_name"}}
258260
541543
542544 catch {testsend prop root InterpRegistry ""}
543545
544 test send-12.2 {TimeoutProc procedure} {secureserver} {
546 #macOS does not send to other processes
547 test send-12.2 {TimeoutProc procedure} {secureserver notAqua} {
545548 winfo interps
546549 tk appname tktest
547550 update
556559 set result
557560 } {1 {target application died}}
558561
562 #macOS does not send to other processes
559563 winfo interps
560564 tk appname tktest
561 test send-13.1 {DeleteProc procedure} {secureserver} {
565 test send-13.1 {DeleteProc procedure} {secureserver notAqua} {
562566 setupbg
563567 set app [dobg {rename send {}; tk appname}]
564568 set result [list [catch {send $app foo} msg] $msg [winfo interps]]
565569 cleanupbg
566570 set result
567571 } {1 {no application named "tktest #2"} tktest}
568 test send-13.2 {DeleteProc procedure} {secureserver} {
572 test send-13.2 {DeleteProc procedure} {secureserver notAqua} {
569573 winfo interps
570574 tk appname tktest
571575 rename send {}
20122012 } -body {
20132013 .e configure -font {Courier -12} -width 4 -xscrollcommand scroll
20142014 .e insert end "01234567890"
2015 update
2015 set timeout [after 500 {set $scrollInfo "timeout"}]
2016 vwait scrollInfo
20162017 .e configure -width 5
20172018 format {%.6f %.6f} {*}$scrollInfo
20182019 } -cleanup {
20192020 destroy .e
2021 after cancel $timeout
20202022 } -result {0.000000 0.363636}
20212023
20222024 test spinbox-5.8 {ConfigureSpinbox procedure} -constraints {
22022204 .e configure -textvariable contents -xscrollcommand scroll
22032205 .e insert 0 abcde
22042206 .e insert 2 XXX
2205 update
2207 set timeout [after 500 {set $scrollInfo "timeout"}]
2208 vwait scrollInfo
22062209 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
22072210 } -cleanup {
22082211 destroy .e
2212 after cancel $timeout
22092213 } -result {abXXXcde abXXXcde {0.000000 1.000000}}
22102214
22112215 test spinbox-7.2 {InsertChars procedure} -setup {
22172221 .e configure -textvariable contents -xscrollcommand scroll
22182222 .e insert 0 abcde
22192223 .e insert 500 XXX
2220 update
2224 set timeout [after 500 {set $scrollInfo "timeout"}]
2225 vwait scrollInfo
22212226 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
22222227 } -cleanup {
22232228 destroy .e
2229 after cancel $timeout
22242230 } -result {abcdeXXX abcdeXXX {0.000000 1.000000}}
22252231 test spinbox-7.3 {InsertChars procedure} -setup {
22262232 spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
23492355 .e configure -textvariable contents -xscrollcommand scroll
23502356 .e insert 0 abcde
23512357 .e delete 2 4
2352 update
2358 set timeout [after 500 {set $scrollInfo "timeout"}]
2359 vwait scrollInfo
23532360 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
23542361 } -cleanup {
23552362 destroy .e
2363 after cancel $timeout
23562364 } -result {abe abe {0.000000 1.000000}}
23572365 test spinbox-8.2 {DeleteChars procedure} -setup {
23582366 unset -nocomplain contents
23632371 .e configure -textvariable contents -xscrollcommand scroll
23642372 .e insert 0 abcde
23652373 .e delete -2 2
2366 update
2374 set timeout [after 500 {set $scrollInfo "timeout"}]
2375 vwait scrollInfo
23672376 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
23682377 } -cleanup {
23692378 destroy .e
2379 after cancel $timeout
23702380 } -result {cde cde {0.000000 1.000000}}
23712381 test spinbox-8.3 {DeleteChars procedure} -setup {
23722382 unset -nocomplain contents
23772387 .e configure -textvariable contents -xscrollcommand scroll
23782388 .e insert 0 abcde
23792389 .e delete 3 1000
2380 update
2390 set timeout [after 500 {set $scrollInfo "timeout"}]
2391 vwait scrollInfo
23812392 list [.e get] $contents [format {%.6f %.6f} {*}$scrollInfo]
23822393 } -cleanup {
23832394 destroy .e
2395 after cancel $timeout
23842396 } -result {abc abc {0.000000 1.000000}}
23852397 test spinbox-8.4 {DeleteChars procedure} -setup {
23862398 spinbox .e -width 10 -font {Courier -12} -highlightthickness 2 -bd 2
31623174 pack .e
31633175 .e delete 0 end
31643176 .e insert 0 123
3165 update
3177 set timeout [after 500 {set $scrollInfo "timeout"}]
3178 vwait scrollInfo
31663179 format {%.6f %.6f} {*}$scrollInfo
31673180 } -cleanup {
31683181 destroy .e
3182 after cancel $timeout
31693183 } -result {0.000000 1.000000}
31703184 test spinbox-17.2 {SpinboxUpdateScrollbar procedure} -body {
31713185 spinbox .e -width 10 -xscrollcommand scroll -font {Courier -12}
31723186 pack .e
31733187 .e insert 0 0123456789abcdef
31743188 .e xview 3
3175 update
3189 set timeout [after 500 {set $scrollInfo "timeout"}]
3190 vwait scrollInfo
31763191 format {%.6f %.6f} {*}$scrollInfo
31773192 } -cleanup {
31783193 destroy .e
3194 after cancel $timeout
31793195 } -result {0.187500 0.812500}
31803196 test spinbox-17.3 {SpinboxUpdateScrollbar procedure} -body {
31813197 spinbox .e -width 10 -xscrollcommand scroll -font {Courier -12}
31823198 pack .e
31833199 .e insert 0 abcdefghijklmnopqrs
31843200 .e xview 6
3185 update
3201 set timeout [after 500 {set $scrollInfo "timeout"}]
3202 vwait scrollInfo
31863203 format {%.6f %.6f} {*}$scrollInfo
31873204 } -cleanup {
31883205 destroy .e
3206 after cancel $timeout
31893207 } -result {0.315789 0.842105}
31903208 test spinbox-17.4 {SpinboxUpdateScrollbar procedure} -setup {
31913209 proc bgerror msg {
31953213 } -body {
31963214 spinbox .e -width 5 -xscrollcommand thisisnotacommand
31973215 pack .e
3198 update
3216 vwait x
31993217 list $x $errorInfo
32003218 } -cleanup {
32013219 destroy .e
26852685 set res {}
26862686 } -body {
26872687 for {set i 1} {$i < 5} {incr i} {
2688 .t insert end "Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr 64+$i]]\n"
2688 .t insert end "Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr {64+$i}]]\n"
26892689 }
26902690 .t tag configure hidden -elide true
26912691 .t tag add hidden 2.15 3.10
27072707 for {set i 1} {$i < 5} {incr i} {
27082708 # 0 1 2 3 4
27092709 # 012345 678901234 567890123 456789012 34567890123456789
2710 .mytop.t insert end "Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr 64+$i]]\n"
2710 .mytop.t insert end "Line $i+++Line $i---Line $i///Line $i - This is Line [format %c [expr {64+$i}]]\n"
27112711 }
27122712 .mytop.t tag configure hidden -elide true
27132713 .mytop.t tag add hidden 2.30 3.10
29352935 } -cleanup {
29362936 destroy .yt
29372937 } -result {1 {wrong # args: should be ".yt pendingsync"}}
2938
29382939 test text-11a.2 {TextWidgetCmd procedure, "pendingsync" option} -setup {
29392940 destroy .top.yt .top
29402941 } -body {
29412942 toplevel .top
29422943 pack [text .top.yt]
2944 update
29432945 set content {}
29442946 for {set i 1} {$i < 300} {incr i} {
29452947 append content [string repeat "$i " 15] \n
29772979 } -body {
29782980 toplevel .top
29792981 pack [text .top.yt]
2982 update
29802983 set content {}
2984 # Use long lines so the line metrics will need updating.
29812985 for {set i 1} {$i < 30} {incr i} {
2982 append content [string repeat "$i " 15] \n
2986 append content [string repeat "$i " 200] \n
29832987 }
29842988 .top.yt insert 1.0 $content
29852989 # wait for end of line metrics calculation to get correct $fraction1
30203024 set ::x 0
30213025 toplevel .top
30223026 pack [text .top.yt]
3027 update
30233028 set content {}
30243029 for {set i 1} {$i < 30} {incr i} {
30253030 append content [string repeat "$i " 15] \n
30263031 }
30273032 .top.yt insert 1.0 $content
30283033 # first case: line metrics calculation still running when launching 'sync -command'
3029 lappend res [.top.yt pendingsync]
3034 lappend res [.top.yt pendingsync] ; # {1}
30303035 .top.yt sync -command [list set ::x 1]
3031 lappend res $::x
3036 lappend res $::x ; # {1 0}
30323037 # now finish line metrics calculations
30333038 while {[.top.yt pendingsync]} {update}
3034 lappend res [.top.yt pendingsync] $::x
3039 lappend res [.top.yt pendingsync] $::x ; # {1 0 0 1}
30353040 # second case: line metrics calculation completed when launching 'sync -command'
30363041 .top.yt sync -command [list set ::x 2]
3037 lappend res $::x
3042 lappend res $::x ; # {1 0 0 1 1}
30383043 vwait ::x
3039 lappend res $::x
3044 lappend res $::x ; # {1 0 0 1 1 2}
30403045 } -cleanup {
30413046 destroy .top.yt .top
30423047 } -result {1 0 0 1 1 2}
30463051 } -body {
30473052 toplevel .top
30483053 pack [text .top.yt]
3054 update
30493055 set content {}
30503056 for {set i 1} {$i < 300} {incr i} {
30513057 append content [string repeat "$i " 15] \n
30523058 }
3059 # Sync the widget and process <<WidgetViewSync>> events before binding.
3060 .top.yt sync
3061 update
3062 bind .top.yt <<WidgetViewSync>> { if {%d} {set yud(%W) 1} }
30533063 .top.yt insert 1.0 $content
3054 update
3055 bind .top.yt <<WidgetViewSync>> { if {%d} {set yud(%W) 1} }
3056 # wait for end of line metrics calculation to get correct $fraction1
3057 # as a reference
3058 if {[.top.yt pendingsync]} {vwait yud(.top.yt)}
30593064 .top.yt yview moveto 1
30603065 set fraction1 [lindex [.top.yt yview] 0]
30613066 set res [expr {$fraction1 > 0}]
30623067 .top.yt delete 1.0 end
30633068 .top.yt insert 1.0 $content
30643069 # synchronously wait for completion of line metrics calculation
3065 # and ensure the test is relevant
3070 # and verify that the fractions agree.
30663071 set waited 0
30673072 if {[.top.yt pendingsync]} {set waited 1 ; vwait yud(.top.yt)}
30683073 lappend res $waited
30763081 test text-11a.41 {"sync" "pendingsync" and <<WidgetViewSync>>} -setup {
30773082 destroy .top.yt .top
30783083 } -body {
3079 set res {}
30803084 toplevel .top
30813085 pack [text .top.yt]
3086 update
30823087 set content {}
30833088 for {set i 1} {$i < 300} {incr i} {
30843089 append content [string repeat "$i " 50] \n
30853090 }
3091 # Sync the widget and process all <<WidgetViewSync>> events before binding.
3092 .top.yt sync
3093 update
30863094 bind .top.yt <<WidgetViewSync>> {lappend res Sync:%d}
3095 set res {}
3096 # The next line triggers <<WidgetViewSync>> with %d==0 i.e. out of sync.
30873097 .top.yt insert 1.0 $content
3088 vwait res ; # event dealt with by the event loop, with %d==0 i.e. we're out of sync
3089 # ensure the test is relevant
3098 vwait res
3099 # Verify that the line metrics are not up-to-date (pendingsync is 1).
30903100 lappend res "Pending:[.top.yt pendingsync]"
3091 # - <<WidgetViewSync>> fires when sync returns if there was pending syncs
3092 # - there is no more any pending sync after running 'sync'
3101 # Update all line metrics by calling the sync command.
30933102 .top.yt sync
3094 vwait res ; # event dealt with by the event loop, with %d==1 i.e. we're in sync again
3103 # <<WidgetViewSync>> should fire with %d==1 i.e. back in sync.
3104 vwait res
3105 # At this time the line metrics should be up-to-date (pendingsync is 0).
30953106 lappend res "Pending:[.top.yt pendingsync]"
30963107 set res
30973108 } -cleanup {
31063117 set res {}
31073118 toplevel .top
31083119 pack [text .top.t]
3120 update
31093121 for {set i 1} {$i < 10000} {incr i} {
31103122 .top.t insert end "Hello world!\n"
31113123 }
34613473 # minimum size and it was interfering with the size requested by the -setgrid.
34623474 # The "overrideredirect" gets rid of the titlebar so the toplevel can shrink
34633475 # to the appropriate size.
3476 # On macOS, however, there is no way to make the window overlap the menubar.
3477 if {[tk windowingsystem] == "aqua"} {
3478 set minY 23
3479 } else {
3480 set minY 0
3481 }
34643482 test text-14.19 {ConfigureText procedure} -setup {
34653483 toplevel .top
34663484 text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
34683486 .top.t configure -width 20 -height 10 -setgrid 1
34693487 wm overrideredirect .top 1
34703488 pack .top.t
3471 wm geometry .top +0+0
3489 wm geometry .top +0+$minY
34723490 update
34733491 wm geometry .top
34743492 } -cleanup {
34753493 destroy .top
3476 } -result {20x10+0+0}
3494 } -result "20x10+0+$minY"
34773495 # This test was failing on Windows because the title bar on .t was a certain
34783496 # minimum size and it was interfering with the size requested by the -setgrid.
34793497 # The "overrideredirect" gets rid of the titlebar so the toplevel can shrink
34803498 # to the appropriate size.
3499 # On macOS we again use minY as a workaround.
34813500 test text-14.20 {ConfigureText procedure} -setup {
34823501 toplevel .top
34833502 text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
34853504 .top.t configure -width 20 -height 10 -setgrid 1
34863505 wm overrideredirect .top 1
34873506 pack .top.t
3488 wm geometry .top +0+0
3507 wm geometry .top +0+$minY
34893508 update
34903509 set result [wm geometry .top]
34913510 wm geometry .top 15x8
34963515 lappend result [wm geometry .top]
34973516 } -cleanup {
34983517 destroy .top
3499 } -result {20x10+0+0 15x8+0+0 15x8+0+0}
3518 } -result "20x10+0+$minY 15x8+0+$minY 15x8+0+$minY"
35003519
35013520
35023521 test text-15.1 {TextWorldChanged procedure, spacing options} -constraints {
61136132 .t insert end "1\t2\t3\t4\t55.5"
61146133 .t configure -tabs {100 right 200 left 300 center 400 numeric}
61156134 update idletasks
6116 list [expr [lindex [.t bbox 1.2] 0] + [lindex [.t bbox 1.2] 2]] \
6135 list [expr {[lindex [.t bbox 1.2] 0] + [lindex [.t bbox 1.2] 2]}] \
61176136 [lindex [.t bbox 1.4] 0] \
6118 [expr [lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]/2] \
6137 [expr {[lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]/2}] \
61196138 [lindex [.t bbox 1.10] 0]
61206139 } -cleanup {
61216140 destroy .t
61276146 .t insert end "1\t2\t3\t4\t55.5"
61286147 .t configure -tabs {105 r 205 l 305 c 405 n}
61296148 update idletasks
6130 list [expr [lindex [.t bbox 1.2] 0] + [lindex [.t bbox 1.2] 2]] \
6149 list [expr {[lindex [.t bbox 1.2] 0] + [lindex [.t bbox 1.2] 2]}] \
61316150 [lindex [.t bbox 1.4] 0] \
6132 [expr [lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]/2] \
6151 [expr {[lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]/2}] \
61336152 [lindex [.t bbox 1.10] 0]
61346153 } -cleanup {
61356154 destroy .t
65416560 test text-27.11 {TextEditCmd procedure, set modified flag repeat} -setup {
65426561 text .t
65436562 pack .t
6563 # Make sure the Text is mapped before we start
6564 update
65446565 set ::retval {}
65456566 } -body {
65466567 bind .t <<Modified>> "lappend ::retval modified"
73507371 destroy .t
73517372 } -result {1}
73527373
7353
7354 test text-33.1 {TextWidgetCmd procedure, "peer" option} -setup {
7355 text .t
7356 } -body {
7357 .t peer foo 1
7358 } -cleanup {
7359 destroy .t
7360 } -returnCodes {error} -result {bad peer option "foo": must be create or names}
7361 test text-33.2 {TextWidgetCmd procedure, "peer" option} -setup {
7362 text .t
7363 } -body {
7364 .t peer names foo
7365 } -cleanup {
7366 destroy .t
7367 } -returnCodes {error} -result {wrong # args: should be ".t peer names"}
7368 test text-33.3 {TextWidgetCmd procedure, "peer" option} -setup {
7369 text .t
7370 } -body {
7371 .t pee names
7372 } -cleanup {
7373 destroy .t
7374 } -returnCodes {ok} -result {}
7375 test text-33.4 {TextWidgetCmd procedure, "peer" option} -setup {
7376 text .t
7377 } -body {
7378 .t peer names
7379 } -cleanup {
7380 destroy .t
7381 } -result {}
7382 test text-33.5 {TextWidgetCmd procedure, "peer" option} -setup {
7383 text .t
7384 } -body {
7385 .t peer create foo
7386 } -cleanup {
7387 destroy .t
7388 } -returnCodes {error} -result {bad window path name "foo"}
7389 test text-33.6 {TextWidgetCmd procedure, "peer" option} -setup {
7390 text .t
7391 set res {}
7392 } -body {
7393 .t peer create .t2
7394 lappend res [.t peer names]
7395 lappend res [.t2 peer names]
7396 destroy .t2
7397 lappend res [.t peer names]
7398 } -cleanup {
7399 destroy .t
7400 } -result {.t2 .t {}}
7401 test text-33.7 {peer widget -start, -end} -body {
7402 text .t
7403 set res [.t configure -start 10 -end 5]
7404 return $res
7405 } -cleanup {
7406 destroy .t
7407 } -returnCodes {2} -result {}
7408 test text-33.8 {peer widget -start, -end} -body {
7409 text .t
7410 for {set i 1} {$i < 100} {incr i} {
7411 .t insert end "Line $i\n"
7412 }
7413 .t configure -start 10 -end 5
7414 } -cleanup {
7415 destroy .t
7416 } -returnCodes {error} -result {-startline must be less than or equal to -endline}
7417 test text-33.9 {peer widget -start, -end} -body {
7418 text .t
7419 for {set i 1} {$i < 100} {incr i} {
7420 .t insert end "Line $i\n"
7421 }
7422 .t configure -start 5 -end 10
7423 } -cleanup {
7424 destroy .t
7425 } -returnCodes {ok} -result {}
7426 test text-33.10 {peer widget -start, -end} -body {
7427 text .t
7428 for {set i 1} {$i < 100} {incr i} {
7429 .t insert end "Line $i\n"
7430 }
7431 set res [.t index end]
7432 lappend res [catch {.t configure -start 5 -end 10 -tab foo}]
7433 lappend res [.t index end]
7434 lappend res [catch {.t configure -tab foo -start 15 -end 20}]
7435 lappend res [.t index end]
7436 .t configure -start {} -end {}
7437 lappend res [.t index end]
7438 return $res
7439 } -cleanup {
7440 destroy .t
7441 } -result {101.0 1 101.0 1 101.0 101.0}
7442 test text-33.11 {peer widget -start, -end} -body {
7443 text .t
7444 for {set i 1} {$i < 100} {incr i} {
7445 .t insert end "Line $i\n"
7446 }
7447 set res [.t index end]
7448 lappend res [catch {.t configure -start 5 -end 15}]
7449 lappend res [.t index end]
7450 lappend res [catch {.t configure -start 10 -end 40}]
7451 lappend res [.t index end]
7452 .t configure -start {} -end {}
7453 lappend res [.t index end]
7454 return $res
7455 } -cleanup {
7456 destroy .t
7457 } -result {101.0 0 11.0 0 31.0 101.0}
7458
7459 test text-34.1 {peer widget -start, -end and selection} -setup {
7460 text .t
7461 set res {}
7462 } -body {
7463 for {set i 1} {$i < 100} {incr i} {
7464 .t insert end "Line $i\n"
7465 }
7466 .t tag add sel 10.0 20.0
7467 lappend res [.t tag ranges sel]
7468 .t configure -start 5 -end 30
7469 lappend res [.t tag ranges sel]
7470 .t configure -start 5 -end 15
7471 lappend res [.t tag ranges sel]
7472 .t configure -start 15 -end 30
7473 lappend res [.t tag ranges sel]
7474 .t configure -start 15 -end 16
7475 lappend res [.t tag ranges sel]
7476 .t configure -start 25 -end 30
7477 lappend res [.t tag ranges sel]
7478 .t configure -start {} -end {}
7479 lappend res [.t tag ranges sel]
7480 return $res
7481 } -cleanup {
7482 destroy .t
7483 } -result {{10.0 20.0} {6.0 16.0} {6.0 11.0} {1.0 6.0} {1.0 2.0} {} {10.0 20.0}}
7484
74857374 test text-32.2 {peer widget -start, -end and deletion (bug 1630262)} -setup {
74867375 destroy .t .pt
74877376 set res {}
75767465 destroy .pt .t
75777466 } -result {5 11 8 10 5 8 6 8 22 27 38 44 55 60 57 57}
75787467
7468
7469 test text-33.1 {TextWidgetCmd procedure, "peer" option} -setup {
7470 text .t
7471 } -body {
7472 .t peer foo 1
7473 } -cleanup {
7474 destroy .t
7475 } -returnCodes {error} -result {bad peer option "foo": must be create or names}
7476 test text-33.2 {TextWidgetCmd procedure, "peer" option} -setup {
7477 text .t
7478 } -body {
7479 .t peer names foo
7480 } -cleanup {
7481 destroy .t
7482 } -returnCodes {error} -result {wrong # args: should be ".t peer names"}
7483 test text-33.3 {TextWidgetCmd procedure, "peer" option} -setup {
7484 text .t
7485 } -body {
7486 .t pee names
7487 } -cleanup {
7488 destroy .t
7489 } -returnCodes {ok} -result {}
7490 test text-33.4 {TextWidgetCmd procedure, "peer" option} -setup {
7491 text .t
7492 } -body {
7493 .t peer names
7494 } -cleanup {
7495 destroy .t
7496 } -result {}
7497 test text-33.5 {TextWidgetCmd procedure, "peer" option} -setup {
7498 text .t
7499 } -body {
7500 .t peer create foo
7501 } -cleanup {
7502 destroy .t
7503 } -returnCodes {error} -result {bad window path name "foo"}
7504 test text-33.6 {TextWidgetCmd procedure, "peer" option} -setup {
7505 text .t
7506 set res {}
7507 } -body {
7508 .t peer create .t2
7509 lappend res [.t peer names]
7510 lappend res [.t2 peer names]
7511 destroy .t2
7512 lappend res [.t peer names]
7513 } -cleanup {
7514 destroy .t
7515 } -result {.t2 .t {}}
7516 test text-33.7 {peer widget -start, -end} -body {
7517 text .t
7518 set res [.t configure -start 10 -end 5]
7519 return $res
7520 } -cleanup {
7521 destroy .t
7522 } -returnCodes {2} -result {}
7523 test text-33.8 {peer widget -start, -end} -body {
7524 text .t
7525 for {set i 1} {$i < 100} {incr i} {
7526 .t insert end "Line $i\n"
7527 }
7528 .t configure -start 10 -end 5
7529 } -cleanup {
7530 destroy .t
7531 } -returnCodes {error} -result {-startline must be less than or equal to -endline}
7532 test text-33.9 {peer widget -start, -end} -body {
7533 text .t
7534 for {set i 1} {$i < 100} {incr i} {
7535 .t insert end "Line $i\n"
7536 }
7537 .t configure -start 5 -end 10
7538 } -cleanup {
7539 destroy .t
7540 } -returnCodes {ok} -result {}
7541 test text-33.10 {peer widget -start, -end} -body {
7542 text .t
7543 for {set i 1} {$i < 100} {incr i} {
7544 .t insert end "Line $i\n"
7545 }
7546 set res [.t index end]
7547 lappend res [catch {.t configure -start 5 -end 10 -tab foo}]
7548 lappend res [.t index end]
7549 lappend res [catch {.t configure -tab foo -start 15 -end 20}]
7550 lappend res [.t index end]
7551 .t configure -start {} -end {}
7552 lappend res [.t index end]
7553 return $res
7554 } -cleanup {
7555 destroy .t
7556 } -result {101.0 1 101.0 1 101.0 101.0}
7557 test text-33.11 {peer widget -start, -end} -body {
7558 text .t
7559 for {set i 1} {$i < 100} {incr i} {
7560 .t insert end "Line $i\n"
7561 }
7562 set res [.t index end]
7563 lappend res [catch {.t configure -start 5 -end 15}]
7564 lappend res [.t index end]
7565 lappend res [catch {.t configure -start 10 -end 40}]
7566 lappend res [.t index end]
7567 .t configure -start {} -end {}
7568 lappend res [.t index end]
7569 return $res
7570 } -cleanup {
7571 destroy .t
7572 } -result {101.0 0 11.0 0 31.0 101.0}
7573
7574 test text-34.1 {peer widget -start, -end and selection} -setup {
7575 text .t
7576 set res {}
7577 } -body {
7578 for {set i 1} {$i < 100} {incr i} {
7579 .t insert end "Line $i\n"
7580 }
7581 .t tag add sel 10.0 20.0
7582 lappend res [.t tag ranges sel]
7583 .t configure -start 5 -end 30
7584 lappend res [.t tag ranges sel]
7585 .t configure -start 5 -end 15
7586 lappend res [.t tag ranges sel]
7587 .t configure -start 15 -end 30
7588 lappend res [.t tag ranges sel]
7589 .t configure -start 15 -end 16
7590 lappend res [.t tag ranges sel]
7591 .t configure -start 25 -end 30
7592 lappend res [.t tag ranges sel]
7593 .t configure -start {} -end {}
7594 lappend res [.t tag ranges sel]
7595 return $res
7596 } -cleanup {
7597 destroy .t
7598 } -result {{10.0 20.0} {6.0 16.0} {6.0 11.0} {1.0 6.0} {1.0 2.0} {} {10.0 20.0}}
7599
75797600 test text-35.1 {widget dump -command alters tags} -setup {
75807601 proc Dumpy {key value index} {
75817602 #puts "KK: $key, $value"
421421 setup
422422 .t insert 1.1 $bigText2
423423 for {set i 0} {$i < 100} {incr i} {
424 set j [expr $i+2]
425 set k [expr 1+2*$i]
424 set j [expr {$i+2}]
425 set k [expr {1+2*$i}]
426426 .t tag add x $j.1 $j.3
427427 .t tag add y $k.1 $k.6
428428 }
438438 setup
439439 .t insert 1.1 $bigText2
440440 for {set i 0} {$i < 100} {incr i} {
441 set j [expr $i+2]
442 set k [expr 1+2*$i]
441 set j [expr {$i+2}]
442 set k [expr {1+2*$i}]
443443 .t tag add x $j.1 $j.3
444444 .t tag add y $k.1 $k.6
445445 }
446446 for {set i 199} {$i >= 2} {incr i -1} {
447 .t delete $i.0 [expr $i+1].0
447 .t delete $i.0 [expr {$i+1}].0
448448 }
449449 list [.t tag ranges x] [.t tag ranges y]
450450 } -result {{3.0 3.1 3.4 3.12 4.2 4.6} {1.1 1.6 3.4 3.5}}
99 eval tcltest::configure $argv
1010 tcltest::loadTestedCommands
1111 namespace import -force tcltest::test
12
13 # Platform specific procedure for updating the text widget.
14
15 if {[tk windowingsystem] == "aqua"} {
16 proc updateText {} {
17 update idletasks
18 }
19 } else {
20 proc updateText {} {
21 update
22 }
23 }
1224
1325 # The procedure below is used as the scrolling command for the text;
1426 # it just saves the scrolling information in a variable "scrollInfo".
7688 wm minsize . 1 1
7789 wm positionfrom . user
7890 wm deiconify .
79 update
91 updateText
8092
8193 # Some window managers (like olwm under SunOS 4.1.3) misbehave in a way
8294 # that tends to march windows off the top and left of the screen. If
157169 .txt tag configure SYSTEM -elide 0
158170 .txt tag configure TRAFFIC -elide 1
159171 .txt insert end "\n" {TRAFFIC SYSTEM}
160 update
172 updateText
161173 destroy .txt
162174 } {}
163175
170182 .txt tag configure TRAFFIC -elide 1
171183 .txt insert end "\n" {SYSTEM TRAFFIC}
172184 # Crash was here.
173 update
185 updateText
174186 destroy .txt
175187 } {}
176188
184196 .txt insert end "\n" {SYSTEM TRAFFIC}
185197 .txt insert end "\n" WELCOME
186198 # Crash was here.
187 update
199 updateText
188200 destroy .txt
189201 } {}
190202
215227 .t tag configure x -wrap word
216228 .t tag configure y -wrap none
217229 .t tag raise y
218 update
230 updateText
219231 set result [list [.t bbox 2.20]]
220232 .t tag add x 2.0 2.1
221233 lappend result [.t bbox 2.20]
229241 .t delete 1.0 end
230242 .t insert 1.0 "This is some sample text for testing."
231243 list [.t bbox 1.19] [.t bbox 1.20]
232 } [list [list [expr 5 + $fixedWidth * 19] 5 $fixedWidth $fixedHeight] [list 5 [expr 5 + $fixedHeight] $fixedWidth $fixedHeight]]
244 } [list [list [expr {5 + $fixedWidth * 19}] 5 $fixedWidth $fixedHeight] [list 5 [expr {5 + $fixedHeight}] $fixedWidth $fixedHeight]]
233245 test textDisp-2.2 {LayoutDLine, basics} {textfonts} {
234246 .t configure -wrap char
235247 .t delete 1.0 end
273285 }
274286 scan [wm geom .] %dx%d width height
275287 test textDisp-2.8 {LayoutDLine, extra chunk at end of dline} {textfonts} {
276 wm geom . [expr $width+1]x$height
277 update
288 wm geom . [expr {$width+1}]x$height
289 updateText
278290 .t configure -wrap char
279291 .t delete 1.0 end
280292 .t insert 1.0 "This isxx some sample text for testing."
282294 list [.t bbox 1.19] [.t bbox 1.20]
283295 } [list [list 138 5 8 $fixedHeight] [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight]]
284296 wm geom . {}
285 update
297 updateText
286298 test textDisp-2.9 {LayoutDLine, marks and tags} {textfonts} {
287299 .t configure -wrap word
288300 .t delete 1.0 end
413425 .t insert end "to wrap around a couple of times"
414426 .t insert end "\nLine 3\nLine 4"
415427 set i [.t dlineinfo 1.0]
416 set b1 [expr [lindex $i 1] + [lindex $i 4]]
428 set b1 [expr {[lindex $i 1] + [lindex $i 4]}]
417429 set i [.t dlineinfo 2.0]
418 set b2 [expr [lindex $i 1] + [lindex $i 4]]
430 set b2 [expr {[lindex $i 1] + [lindex $i 4]}]
419431 set i [.t dlineinfo 2.end]
420 set b3 [expr [lindex $i 1] + [lindex $i 4]]
432 set b3 [expr {[lindex $i 1] + [lindex $i 4]}]
421433 set i [.t dlineinfo 3.0]
422 set b4 [expr [lindex $i 1] + [lindex $i 4]]
434 set b4 [expr {[lindex $i 1] + [lindex $i 4]}]
423435 .t configure -spacing1 2 -spacing2 1 -spacing3 3
424436 set i [.t dlineinfo 1.0]
425 set b1 [expr [lindex $i 1] + [lindex $i 4] - $b1]
437 set b1 [expr {[lindex $i 1] + [lindex $i 4] - $b1}]
426438 set i [.t dlineinfo 2.0]
427 set b2 [expr [lindex $i 1] + [lindex $i 4] - $b2]
439 set b2 [expr {[lindex $i 1] + [lindex $i 4] - $b2}]
428440 set i [.t dlineinfo 2.end]
429 set b3 [expr [lindex $i 1] + [lindex $i 4] - $b3]
441 set b3 [expr {[lindex $i 1] + [lindex $i 4] - $b3}]
430442 set i [.t dlineinfo 3.0]
431 set b4 [expr [lindex $i 1] + [lindex $i 4] - $b4]
443 set b4 [expr {[lindex $i 1] + [lindex $i 4] - $b4}]
432444 list $b1 $b2 $b3 $b4
433445 } [list 2 7 10 15]
434446 .t configure -spacing1 0 -spacing2 0 -spacing3 0
440452 .t insert end "to wrap around a couple of times"
441453 .t insert end "\nLine 3\nLine 4"
442454 set i [.t dlineinfo 1.0]
443 set b1 [expr [lindex $i 1] + [lindex $i 4]]
455 set b1 [expr {[lindex $i 1] + [lindex $i 4]}]
444456 set i [.t dlineinfo 2.0]
445 set b2 [expr [lindex $i 1] + [lindex $i 4]]
457 set b2 [expr {[lindex $i 1] + [lindex $i 4]}]
446458 set i [.t dlineinfo 2.end]
447 set b3 [expr [lindex $i 1] + [lindex $i 4]]
459 set b3 [expr {[lindex $i 1] + [lindex $i 4]}]
448460 set i [.t dlineinfo 3.0]
449 set b4 [expr [lindex $i 1] + [lindex $i 4]]
461 set b4 [expr {[lindex $i 1] + [lindex $i 4]}]
450462 .t configure -spacing1 4 -spacing2 4 -spacing3 4
451463 .t tag configure x -spacing1 1 -spacing2 2 -spacing3 3
452464 .t tag add x 1.0 end
454466 .t tag add y 2.19 end
455467 .t tag raise y
456468 set i [.t dlineinfo 1.0]
457 set b1 [expr [lindex $i 1] + [lindex $i 4] - $b1]
469 set b1 [expr {[lindex $i 1] + [lindex $i 4] - $b1}]
458470 set i [.t dlineinfo 2.0]
459 set b2 [expr [lindex $i 1] + [lindex $i 4] - $b2]
471 set b2 [expr {[lindex $i 1] + [lindex $i 4] - $b2}]
460472 set i [.t dlineinfo 2.end]
461 set b3 [expr [lindex $i 1] + [lindex $i 4] - $b3]
473 set b3 [expr {[lindex $i 1] + [lindex $i 4] - $b3}]
462474 set i [.t dlineinfo 3.0]
463 set b4 [expr [lindex $i 1] + [lindex $i 4] - $b4]
475 set b4 [expr {[lindex $i 1] + [lindex $i 4] - $b4}]
464476 list $b1 $b2 $b3 $b4
465477 } [list 1 5 13 16]
466478 .t configure -spacing1 0 -spacing2 0 -spacing3 0
534546 test textDisp-4.1 {UpdateDisplayInfo, basic} {textfonts} {
535547 .t delete 1.0 end
536548 .t insert end "Line 1\nLine 2\nLine 3\n"
537 update
549 updateText
538550 .t delete 2.0 2.end
539 update
551 updateText
540552 set res $tk_textRelayout
541553 .t insert 2.0 "New Line 2"
542 update
554 updateText
543555 lappend res [.t bbox 1.0] [.t bbox 2.0] [.t bbox 3.0] $tk_textRelayout
544556 } [list 2.0 [list 5 5 7 $fixedHeight] [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 5 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] 2.0]
545557 test textDisp-4.2 {UpdateDisplayInfo, re-use tail of text line} {textfonts} {
546558 .t delete 1.0 end
547559 .t insert end "Line 1\nLine 2 is so long that it wraps around\nLine 3"
548 update
560 updateText
549561 .t mark set x 2.21
550562 .t delete 2.2
551 update
563 updateText
552564 set res $tk_textRelayout
553565 .t insert 2.0 X
554 update
566 updateText
555567 lappend res [.t bbox 2.0] [.t bbox x] [.t bbox 3.0] $tk_textRelayout
556568 } [list 2.0 2.20 [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 12 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] [list 5 [expr {3*$fixedDiff + 44}] 7 $fixedHeight] {2.0 2.20}]
557569 test textDisp-4.3 {UpdateDisplayInfo, tail of text line shifts} {textfonts} {
558570 .t delete 1.0 end
559571 .t insert end "Line 1\nLine 2 is so long that it wraps around\nLine 3"
560 update
572 updateText
561573 .t mark set x 2.21
562574 .t delete 2.2
563 update
575 updateText
564576 list [.t bbox 2.0] [.t bbox x] [.t bbox 3.0] $tk_textRelayout
565577 } [list [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 5 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] [list 5 [expr {3*$fixedDiff + 44}] 7 $fixedHeight] {2.0 2.20}]
566578 .t mark unset x
568580 .t configure -wrap none
569581 .t delete 1.0 end
570582 .t insert end "Line 1\nLine 2 is so long that it wraps around\nLine 3"
571 update
583 updateText
572584 list [.t bbox 2.0] [.t bbox 2.25] [.t bbox 3.0] $tk_textRelayout
573585 } [list [list 5 [expr {$fixedDiff + 18}] 7 $fixedHeight] {} [list 5 [expr {2*$fixedDiff + 31}] 7 $fixedHeight] {1.0 2.0 3.0}]
574586 test textDisp-4.5 {UpdateDisplayInfo, tiny window} {textfonts} {
576588 wm overrideredirect . 1
577589 }
578590 wm geom . 103x$height
579 update
591 updateText
580592 .t configure -wrap none
581593 .t delete 1.0 end
582594 .t insert end "Line 1\nLine 2 is so long that it wraps around\nLine 3"
583 update
595 updateText
584596 list [.t bbox 2.0] [.t bbox 2.1] [.t bbox 3.0] $tk_textRelayout
585597 } [list [list 5 [expr {$fixedDiff + 18}] 1 $fixedHeight] {} [list 5 [expr {2*$fixedDiff + 31}] 1 $fixedHeight] {1.0 2.0 3.0}]
586598 if {$tcl_platform(platform) == "windows"} {
600612 frame .f2 -width 20 -height 100
601613 pack .f2 -before .f
602614 wm geom . 103x103
603 update
615 updateText
604616 .t configure -wrap none -borderwidth 2
605617 .t delete 1.0 end
606618 .t insert end "Line 1\nLine 2 is so long that it wraps around\nLine 3"
607 update
619 updateText
608620 set x [list [.t bbox 1.0] [.t bbox 2.0] $tk_textRelayout]
609621 wm overrideredirect . 0
610 update
622 updateText
611623 set x
612624 } [list [list 5 5 1 1] {} 1.0]
613625 catch {destroy .f2}
614626 .t configure -borderwidth 0 -wrap char
615627 wm geom . {}
616 update
628 updateText
617629 set bw [.t cget -borderwidth]
618630 set px [.t cget -padx]
619631 set py [.t cget -pady]
632644 .t delete 1.0 end
633645 .t insert end "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
634646 .t yview 1.0
635 update
647 updateText
636648 .t yview 16.0
637 update
649 updateText
638650 set x [list [.t index @0,0] $tk_textRelayout $tk_textRedraw]
639651 wm overrideredirect . 0
640 update
652 updateText
641653 set x
642654 } {8.0 {16.0 17.0 15.0 14.0 13.0 12.0 11.0 10.0 9.0 8.0} {8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0}}
643655 test textDisp-4.8 {UpdateDisplayInfo, filling in extra vertical space} {
644656 .t delete 1.0 end
645657 .t insert end "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
646658 .t yview 16.0
647 update
659 updateText
648660 .t delete 5.0 14.0
649 update
661 updateText
650662 set x [list [.t index @0,0] $tk_textRelayout $tk_textRedraw]
651663 } {1.0 {5.0 4.0 3.0 2.0 1.0} {1.0 2.0 3.0 4.0 5.0 eof}}
652664 test textDisp-4.9 {UpdateDisplayInfo, filling in extra vertical space} {textfonts} {
653665 .t delete 1.0 end
654666 .t insert end "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
655667 .t yview 16.0
656 update
668 updateText
657669 .t delete 15.0 end
658670 list [.t bbox 7.0] [.t bbox 12.0]
659671 } [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]]
661673 .t delete 1.0 end
662674 .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"
663675 .t yview end
664 update
676 updateText
665677 .t delete 13.0 end
666 update
678 updateText
667679 list [.t index @0,0] $tk_textRelayout $tk_textRedraw
668680 } {5.0 {12.0 7.0 6.40 6.20 6.0 5.0} {5.0 6.0 6.20 6.40 7.0 12.0}}
669681 test textDisp-4.11 {UpdateDisplayInfo, filling in extra vertical space} {
670682 .t delete 1.0 end
671683 .t insert end "1\n2\n3\n4\n5\nLine 6 is such a long line that it wraps around, not once but really quite a few times.\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17"
672684 .t yview end
673 update
685 updateText
674686 .t delete 14.0 end
675 update
687 updateText
676688 list [.t index @0,0] $tk_textRelayout $tk_textRedraw
677689 } {6.40 {13.0 7.0 6.80 6.60 6.40} {6.40 6.60 6.80 7.0 13.0}}
678690 test textDisp-4.12 {UpdateDisplayInfo, filling in extra vertical space} {
681693 button .b -text "Test" -bd 2 -highlightthickness 2
682694 .t window create 3.end -window .b
683695 .t yview moveto 1
684 update
696 updateText
685697 .t yview moveto 0
686 update
698 updateText
687699 .t yview moveto 1
688 update
700 updateText
689701 winfo ismapped .b
690702 } {0}
691703 .t configure -wrap word
698710 test textDisp-4.13 {UpdateDisplayInfo, special handling for top/bottom lines} {
699711 .t tag add x 1.0 end
700712 .t yview 1.0
701 update
713 updateText
702714 .t yview scroll 3 units
703 update
715 updateText
704716 list $tk_textRelayout $tk_textRedraw
705717 } {{11.0 12.0 13.0} {4.0 10.0 11.0 12.0 13.0}}
706718 test textDisp-4.14 {UpdateDisplayInfo, special handling for top/bottom lines} {
707719 .t tag remove x 1.0 end
708720 .t yview 1.0
709 update
721 updateText
710722 .t yview scroll 3 units
711 update
723 updateText
712724 list $tk_textRelayout $tk_textRedraw
713725 } {{11.0 12.0 13.0} {11.0 12.0 13.0}}
714726 test textDisp-4.15 {UpdateDisplayInfo, special handling for top/bottom lines} {
715727 .t tag add x 1.0 end
716728 .t yview 4.0
717 update
729 updateText
718730 .t yview scroll -2 units
719 update
731 updateText
720732 list $tk_textRelayout $tk_textRedraw
721733 } {{2.0 3.0} {2.0 3.0 4.0 11.0}}
722734 test textDisp-4.16 {UpdateDisplayInfo, special handling for top/bottom lines} {
723735 .t tag remove x 1.0 end
724736 .t yview 4.0
725 update
737 updateText
726738 .t yview scroll -2 units
727 update
739 updateText
728740 list $tk_textRelayout $tk_textRedraw
729741 } {{2.0 3.0} {2.0 3.0}}
730742 test textDisp-4.17 {UpdateDisplayInfo, horizontal scrolling} {textfonts} {
732744 .t delete 1.0 end
733745 .t insert end "Short line 1\nLine 2 is long enough to scroll horizontally"
734746 .t insert end "\nLine 3\nLine 4"
735 update
747 updateText
736748 .t xview scroll 3 units
737 update
749 updateText
738750 list $tk_textRelayout $tk_textRedraw [.t bbox 2.0] [.t bbox 2.5] \
739751 [.t bbox 2.23]
740752 } [list {} {1.0 2.0 3.0 4.0} {} [list 17 [expr {$fixedDiff + 16}] 7 $fixedHeight] {}]
743755 .t delete 1.0 end
744756 .t insert end "Short line 1\nLine 2 is long enough to scroll horizontally"
745757 .t insert end "\nLine 3\nLine 4"
746 update
758 updateText
747759 .t xview scroll 100 units
748 update
760 updateText
749761 list $tk_textRelayout $tk_textRedraw [.t bbox 2.25]
750762 } [list {} {1.0 2.0 3.0 4.0} [list 10 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
751763 test textDisp-4.19 {UpdateDisplayInfo, horizontal scrolling} {textfonts} {
753765 .t delete 1.0 end
754766 .t insert end "Short line 1\nLine 2 is long enough to scroll horizontally"
755767 .t insert end "\nLine 3\nLine 4"
756 update
768 updateText
757769 .t xview moveto 0
758770 .t xview scroll -10 units
759 update
771 updateText
760772 list $tk_textRelayout $tk_textRedraw [.t bbox 2.5]
761773 } [list {} {1.0 2.0 3.0 4.0} [list 38 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
762774 test textDisp-4.20 {UpdateDisplayInfo, horizontal scrolling} {textfonts} {
766778 .t insert end "\nLine 3\nLine 4"
767779 .t xview moveto 0.0
768780 .t xview scroll 100 units
769 update
781 updateText
770782 .t delete 2.30 2.44
771 update
783 updateText
772784 list $tk_textRelayout $tk_textRedraw [.t bbox 2.25]
773785 } [list 2.0 {1.0 2.0 3.0 4.0} [list 108 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
774786 test textDisp-4.21 {UpdateDisplayInfo, horizontal scrolling} {textfonts} {
777789 .t insert end "Short line 1\nLine 2 is long enough to scroll horizontally"
778790 .t insert end "\nLine 3\nLine 4"
779791 .t xview moveto .9
780 update
792 updateText
781793 .t xview moveto .6
782 update
794 updateText
783795 list $tk_textRelayout $tk_textRedraw
784796 } {{} {}}
785797 test textDisp-4.22 {UpdateDisplayInfo, no horizontal scrolling except for -wrap none} {textfonts} {
788800 .t insert end "Short line 1\nLine 2 is long enough to scroll horizontally"
789801 .t insert end "\nLine 3\nLine 4"
790802 .t xview scroll 25 units
791 update
803 updateText
792804 .t configure -wrap word
793805 list [.t bbox 2.0] [.t bbox 2.16]
794806 } [list [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight] [list 10 [expr {2*$fixedDiff + 29}] 7 $fixedHeight]]
798810 .t insert end "Short line 1\nLine 2 is long enough to scroll horizontally"
799811 .t insert end "\nLine 3\nLine 4"
800812 .t xview scroll 25 units
801 update
813 updateText
802814 .t configure -wrap char
803815 list [.t bbox 2.0] [.t bbox 2.16]
804816 } [list [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight] [list 115 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
816828 .t window create 1.7 -window .t.f2 -align center
817829 .t window create 2.1 -window .t.f3 -align bottom
818830 .t window create 2.10 -window .t.f4 -align baseline
819 update
831 updateText
820832 list [winfo geometry .t.f1] [winfo geometry .t.f2] \
821833 [winfo geometry .t.f3] [winfo geometry .t.f4]
822834 } [list 10x4+24+11 10x4+55+[expr {$fixedDiff/2 + 15}] 10x4+10+[expr {2*$fixedDiff + 43}] 10x4+76+[expr {2*$fixedDiff + 40}]]
831843 frame .t.f -width 20 -height 20 -bd 2 -relief raised
832844 bind .t.f <Configure> {.t.f configure -width 30 -height 30}
833845 .t window create insert -window .t.f
834 update
846 updateText
835847 list [winfo width .t.f] [winfo height .t.f]
836848 } [list 30 30]
837849
842854 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
843855 .t insert end "\nLine $i"
844856 }
845 update
857 updateText
846858 .t delete 2.0 3.0
847 update
859 updateText
848860 list $tk_textRelayout $tk_textRedraw
849861 } {{2.0 10.0} {2.0 10.0}}
850862 test textDisp-6.2 {scrolling in DisplayText, scroll down} {
853865 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
854866 .t insert end "\nLine $i"
855867 }
856 update
868 updateText
857869 .t insert 2.0 "New Line 2\n"
858 update
870 updateText
859871 list $tk_textRelayout $tk_textRedraw
860872 } {{2.0 3.0} {2.0 3.0}}
861873 test textDisp-6.3 {scrolling in DisplayText, multiple scrolls} {
865877 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
866878 .t insert end "\nLine $i"
867879 }
868 update
880 updateText
869881 .t insert 2.end "is so long that it wraps"
870882 .t insert 4.end "is so long that it wraps"
871 update
883 updateText
872884 list $tk_textRelayout $tk_textRedraw
873885 } {{2.0 2.20 4.0 4.20} {2.0 2.20 4.0 4.20}}
874886 test textDisp-6.4 {scrolling in DisplayText, scrolls interfere} {
878890 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
879891 .t insert end "\nLine $i"
880892 }
881 update
893 updateText
882894 .t insert 2.end "is so long that it wraps around, not once but three times"
883895 .t insert 4.end "is so long that it wraps"
884 update
896 updateText
885897 list $tk_textRelayout $tk_textRedraw
886898 } {{2.0 2.20 2.40 2.60 4.0 4.20} {2.0 2.20 2.40 2.60 4.0 4.20 6.0}}
887899 test textDisp-6.5 {scrolling in DisplayText, scroll source obscured} {nonPortable} {
893905 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
894906 .t insert end "\nLine $i"
895907 }
896 update
908 updateText
897909 .t delete 1.6 1.end
898 update
910 updateText
899911 destroy .f2
900912 list $tk_textRelayout $tk_textRedraw
901913 } {{1.0 9.0 10.0} {1.0 4.0 5.0 9.0 10.0}}
910922 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
911923 .t insert end "\nLine $i"
912924 }
913 update
925 updateText
914926 .t delete 1.6 1.end
915927 destroy .f2
916 update
928 updateText
917929 list $tk_textRelayout $tk_textRedraw
918930 } {{1.0 9.0 10.0} {borders 1.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0}}
919931 .t configure -bd 0
920932 test textDisp-6.7 {DisplayText, vertical scrollbar updates} {
921933 .t configure -wrap char
922934 .t delete 1.0 end
923 update ; .t count -update -ypixels 1.0 end ; update
935 updateText
936 .t count -update -ypixels 1.0 end
937 updateText
924938 set scrollInfo
925939 } {0.0 1.0}
926940 test textDisp-6.8 {DisplayText, vertical scrollbar updates} {
927941 .t configure -wrap char
928942 .t delete 1.0 end
929943 .t insert 1.0 "Line 1"
930 update
944 updateText
931945 set scrollInfo "unchanged"
932946 foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {
933947 .t insert end "\nLine $i"
934948 }
935 update ; .t count -update -ypixels 1.0 end ; update
949 updateText
950 .t count -update -ypixels 1.0 end ; update
936951 set scrollInfo
937952 } [list 0.0 [expr {10.0/13}]]
938953 .t configure -yscrollcommand {} -xscrollcommand scroll
939954 test textDisp-6.9 {DisplayText, horizontal scrollbar updates} {
940955 .t configure -wrap none
941956 .t delete 1.0 end
942 update
957 updateText
943958 set scrollInfo unchanged
944959 .t insert end xxxxxxxxx\n
945960 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
946961 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx
947 update
962 updateText
948963 set scrollInfo
949964 } [list 0.0 [expr {4.0/11}]]
950965 test textDisp-6.10 {DisplayText, redisplay embedded windows after scroll.} {aqua} {
963978 .t insert end "\nLine 8\n"
964979 .t window create end -create {
965980 button %W.button_three -text "Button 3"}
966 update
981 updateText
967982 .t delete 2.0 3.0
968 update
983 updateText
969984 list $tk_textEmbWinDisplay
970985 } {{4.0 6.0}}
971986
983998 test textDisp-7.1 {TkTextRedrawRegion} {nonPortable} {
984999 frame .f2 -bg #ff0000
9851000 place .f2 -in .t -relx 0.2 -relwidth 0.6 -rely 0.22 -relheight 0.55
986 update
1001 updateText
9871002 destroy .f2
988 update
1003 updateText
9891004 list $tk_textRelayout $tk_textRedraw
9901005 } {{} {1.40 2.0 3.0 4.0 5.0 6.0}}
9911006 test textDisp-7.2 {TkTextRedrawRegion} {nonPortable} {
9921007 frame .f2 -bg #ff0000
9931008 place .f2 -in .t -relx 0 -relwidth 0.5 -rely 0 -relheight 0.5
994 update
1009 updateText
9951010 destroy .f2
996 update
1011 updateText
9971012 list $tk_textRelayout $tk_textRedraw
9981013 } {{} {borders 1.0 1.20 1.40 2.0 3.0}}
9991014 test textDisp-7.3 {TkTextRedrawRegion} {nonPortable} {
10001015 frame .f2 -bg #ff0000
10011016 place .f2 -in .t -relx 0.5 -relwidth 0.5 -rely 0.5 -relheight 0.5
1002 update
1017 updateText
10031018 destroy .f2
1004 update
1019 updateText
10051020 list $tk_textRelayout $tk_textRedraw
10061021 } {{} {borders 4.0 5.0 6.0 7.0 8.0}}
10071022 test textDisp-7.4 {TkTextRedrawRegion} {nonPortable} {
10081023 frame .f2 -bg #ff0000
10091024 place .f2 -in .t -relx 0.4 -relwidth 0.2 -rely 0 -relheight 0.2 \
10101025 -bordermode ignore
1011 update
1026 updateText
10121027 destroy .f2
1013 update
1028 updateText
10141029 list $tk_textRelayout $tk_textRedraw
10151030 } {{} {borders 1.0 1.20}}
10161031 test textDisp-7.5 {TkTextRedrawRegion} {nonPortable} {
10171032 frame .f2 -bg #ff0000
10181033 place .f2 -in .t -relx 0.4 -relwidth 0.2 -rely 1.0 -relheight 0.2 \
10191034 -anchor s -bordermode ignore
1020 update
1035 updateText
10211036 destroy .f2
1022 update
1037 updateText
10231038 list $tk_textRelayout $tk_textRedraw
10241039 } {{} {borders 7.0 8.0}}
10251040 test textDisp-7.6 {TkTextRedrawRegion} {nonPortable} {
10261041 frame .f2 -bg #ff0000
10271042 place .f2 -in .t -relx 0 -relwidth 0.2 -rely 0.55 -relheight 0.2 \
10281043 -anchor w -bordermode ignore
1029 update
1044 updateText
10301045 destroy .f2
1031 update
1046 updateText
10321047 list $tk_textRelayout $tk_textRedraw
10331048 } {{} {borders 3.0 4.0 5.0}}
10341049 test textDisp-7.7 {TkTextRedrawRegion} {nonPortable} {
10351050 frame .f2 -bg #ff0000
10361051 place .f2 -in .t -relx 1.0 -relwidth 0.2 -rely 0.55 -relheight 0.2 \
10371052 -anchor e -bordermode ignore
1038 update
1053 updateText
10391054 destroy .f2
1040 update
1055 updateText
10411056 list $tk_textRelayout $tk_textRedraw
10421057 } {{} {borders 3.0 4.0 5.0}}
10431058 test textDisp-7.8 {TkTextRedrawRegion} {nonPortable} {
10461061 frame .f2 -bg #ff0000
10471062 place .f2 -in .t -relx 0.0 -relwidth 0.4 -rely 0.35 -relheight 0.4 \
10481063 -anchor nw -bordermode ignore
1049 update
1064 updateText
10501065 destroy .f2
1051 update
1066 updateText
10521067 list $tk_textRelayout $tk_textRedraw
10531068 } {{} {borders 4.0 5.0 6.0 7.0 eof}}
10541069 .t configure -bd 0
10601075 foreach i {3 4 5 6 7 8 9 10 11 12 13 14 15} {
10611076 .t insert end "\nLine $i"
10621077 }
1063 update
1078 updateText
10641079 .t delete 2.36 2.38
1065 update
1080 updateText
10661081 list $tk_textRelayout $tk_textRedraw [.t bbox 2.32]
10671082 } [list {2.0 2.18 2.38} {2.0 2.18 2.38} [list 101 [expr {2*$fixedDiff + 29}] 7 $fixedHeight]]
10681083 .t configure -wrap char
10721087 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
10731088 .t insert end "\nLine $i"
10741089 }
1075 update
1090 updateText
10761091 .t insert 1.2 xx
1077 update
1092 updateText
10781093 list $tk_textRelayout $tk_textRedraw
10791094 } {{1.0 1.20 1.40} {1.0 1.20 1.40}}
10801095 test textDisp-8.3 {TkTextChanged} {
10831098 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
10841099 .t insert end "\nLine $i"
10851100 }
1086 update
1101 updateText
10871102 .t insert 2.0 xx
1088 update
1103 updateText
10891104 list $tk_textRelayout $tk_textRedraw
10901105 } {2.0 2.0}
10911106 test textDisp-8.4 {TkTextChanged} {
10941109 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
10951110 .t insert end "\nLine $i"
10961111 }
1097 update
1112 updateText
10981113 .t delete 1.5
1099 update
1114 updateText
11001115 list $tk_textRelayout $tk_textRedraw
11011116 } {{1.0 1.20 1.40} {1.0 1.20 1.40}}
11021117 test textDisp-8.5 {TkTextChanged} {
11051120 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
11061121 .t insert end "\nLine $i"
11071122 }
1108 update
1123 updateText
11091124 .t delete 1.40 1.44
1110 update
1125 updateText
11111126 list $tk_textRelayout $tk_textRedraw
11121127 } {{1.0 1.20 1.40} {1.0 1.20 1.40}}
11131128 test textDisp-8.6 {TkTextChanged} {
11161131 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
11171132 .t insert end "\nLine $i"
11181133 }
1119 update
1134 updateText
11201135 .t delete 1.41 1.44
1121 update
1136 updateText
11221137 list $tk_textRelayout $tk_textRedraw
11231138 } {{1.0 1.20 1.40} {1.0 1.20 1.40}}
11241139 test textDisp-8.7 {TkTextChanged} {
11271142 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
11281143 .t insert end "\nLine $i"
11291144 }
1130 update
1145 updateText
11311146 .t delete 1.2 1.end
1132 update
1147 updateText
11331148 list $tk_textRelayout $tk_textRedraw
11341149 } {{1.0 9.0 10.0} {1.0 9.0 10.0}}
11351150 test textDisp-8.8 {TkTextChanged} {
11381153 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
11391154 .t insert end "\nLine $i"
11401155 }
1141 update
1156 updateText
11421157 .t delete 2.2
1143 update
1158 updateText
11441159 list $tk_textRelayout $tk_textRedraw
11451160 } {2.0 2.0}
11461161 test textDisp-8.9 {TkTextChanged} {
11491164 foreach i {2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
11501165 .t insert end "\nLine $i"
11511166 }
1152 update
1167 updateText
11531168 .t delete 2.0 3.0
1154 update
1169 updateText
11551170 list $tk_textRelayout $tk_textRedraw
11561171 } {{2.0 8.0} {2.0 8.0}}
11571172 test textDisp-8.10 {TkTextChanged} {
11591174 .t delete 1.0 end
11601175 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
11611176 .t tag add big 2.19
1162 update
1177 updateText
11631178 .t delete 2.19
1164 update
1179 updateText
11651180 set tk_textRedraw
11661181 } {2.0 2.20 eof}
11671182 test textDisp-8.11 {TkTextChanged, scrollbar notification when changes are off-screen} {
11681183 .t delete 1.0 end
11691184 .t insert end "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n"
11701185 .t configure -yscrollcommand scroll
1171 update
1186 updateText
11721187 set scrollInfo ""
11731188 .t insert end "a\nb\nc\n"
11741189 # We need to wait for our asychronous callbacks to update the
11751190 # scrollbar
1176 update ; .t count -update -ypixels 1.0 end ; update
1191 updateText
1192 .t count -update -ypixels 1.0 end
1193 updateText
11771194 .t configure -yscrollcommand ""
11781195 set scrollInfo
11791196 } {0.0 0.625}
11861203 .t tag add hidden 5.0 8.0
11871204 .t tag configure hidden -elide true
11881205 .t mark set insert 9.0
1189 update
1206 updateText
11901207 .t mark set insert 8.0 ; # up one line
1191 update
1208 updateText
11921209 set res [list $tk_textRedraw]
11931210 .t mark set insert 12.2 ; # in the visible text
1194 update
1211 updateText
11951212 lappend res $tk_textRedraw
11961213 .t mark set insert 6.5 ; # in the hidden text
1197 update
1214 updateText
11981215 lappend res $tk_textRedraw
11991216 .t mark set insert 3.5 ; # in the visible text again
1200 update
1217 updateText
12011218 lappend res $tk_textRedraw
12021219 .t mark set insert 3.8 ; # within the same line
1203 update
1220 updateText
12041221 lappend res $tk_textRedraw
12051222 } {{8.0 9.0} {8.0 12.0} {8.0 12.0} {3.0 8.0} {3.0 4.0}}
12061223 test textDisp-8.13 {TkTextChanged, used to crash, see [06c1433906]} {
12071224 .t delete 1.0 end
12081225 .t insert 1.0 \nLine2\nLine3\n
1209 update
1226 updateText
12101227 .t insert 3.0 ""
12111228 .t delete 1.0 2.0
12121229 update idletasks
12161233 .t configure -wrap char
12171234 .t delete 1.0 end
12181235 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
1219 update
1236 updateText
12201237 .t tag add big 2.2 2.4
1221 update
1238 updateText
12221239 list $tk_textRelayout $tk_textRedraw
12231240 } {{2.0 2.18} {2.0 2.18}}
12241241 test textDisp-9.2 {TkTextRedrawTag} {textfonts} {
12251242 .t configure -wrap char
12261243 .t delete 1.0 end
12271244 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
1228 update
1245 updateText
12291246 .t tag add big 1.2 2.4
1230 update
1247 updateText
12311248 list $tk_textRelayout $tk_textRedraw
12321249 } {{1.0 2.0 2.17} {1.0 2.0 2.17}}
12331250 test textDisp-9.3 {TkTextRedrawTag} {
12341251 .t configure -wrap char
12351252 .t delete 1.0 end
12361253 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
1237 update
1254 updateText
12381255 .t tag add big 2.2 2.4
1239 update
1256 updateText
12401257 .t tag remove big 1.0 end
1241 update
1258 updateText
12421259 list $tk_textRelayout $tk_textRedraw
12431260 } {{2.0 2.20} {2.0 2.20 eof}}
12441261 test textDisp-9.4 {TkTextRedrawTag} {
12451262 .t configure -wrap char
12461263 .t delete 1.0 end
12471264 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
1248 update
1265 updateText
12491266 .t tag add big 2.2 2.20
1250 update
1267 updateText
12511268 .t tag remove big 1.0 end
1252 update
1269 updateText
12531270 list $tk_textRelayout $tk_textRedraw
12541271 } {{2.0 2.20} {2.0 2.20 eof}}
12551272 test textDisp-9.5 {TkTextRedrawTag} {
12561273 .t configure -wrap char
12571274 .t delete 1.0 end
12581275 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap around\nLine 3\nLine 4"
1259 update
1276 updateText
12601277 .t tag add big 2.2 2.end
1261 update
1278 updateText
12621279 .t tag remove big 1.0 end
1263 update
1280 updateText
12641281 list $tk_textRelayout $tk_textRedraw
12651282 } {{2.0 2.20} {2.0 2.20 eof}}
12661283 test textDisp-9.6 {TkTextRedrawTag} {
12671284 .t configure -wrap char
12681285 .t delete 1.0 end
12691286 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap"
1270 update
1287 updateText
12711288 .t tag add big 2.2 3.5
1272 update
1289 updateText
12731290 .t tag remove big 1.0 end
1274 update
1291 updateText
12751292 list $tk_textRelayout $tk_textRedraw
12761293 } {{2.0 2.20 3.0 3.20} {2.0 2.20 3.0 3.20 eof}}
12771294 test textDisp-9.7 {TkTextRedrawTag} {
12791296 .t delete 1.0 end
12801297 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
12811298 .t tag add big 2.19
1282 update
1299 updateText
12831300 .t tag remove big 2.19
1284 update
1301 updateText
12851302 set tk_textRedraw
12861303 } {2.0 2.20 eof}
12871304 test textDisp-9.8 {TkTextRedrawTag} {textfonts} {
12891306 .t delete 1.0 end
12901307 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
12911308 .t tag add big 1.0 2.0
1292 update
1309 updateText
12931310 .t tag add big 2.0 2.5
1294 update
1311 updateText
12951312 set tk_textRedraw
12961313 } {2.0 2.17}
12971314 test textDisp-9.9 {TkTextRedrawTag} {textfonts} {
12991316 .t delete 1.0 end
13001317 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
13011318 .t tag add big 1.0 2.0
1302 update
1319 updateText
13031320 .t tag add big 1.5 2.5
1304 update
1321 updateText
13051322 set tk_textRedraw
13061323 } {2.0 2.17}
13071324 test textDisp-9.10 {TkTextRedrawTag} {
13091326 .t delete 1.0 end
13101327 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
13111328 .t tag add big 1.0 2.0
1312 update
1329 updateText
13131330 set tk_textRedraw {none}
13141331 .t tag add big 1.3 1.5
1315 update
1332 updateText
13161333 set tk_textRedraw
13171334 } {none}
13181335 test textDisp-9.11 {TkTextRedrawTag} {
13201337 .t delete 1.0 end
13211338 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
13221339 .t tag add big 1.0 2.0
1323 update
1340 updateText
13241341 .t tag add big 1.0 2.0
1325 update
1342 updateText
13261343 set tk_textRedraw
13271344 } {}
13281345 test textDisp-9.12 {TkTextRedrawTag} {
13331350 }
13341351 .t tag configure hidden -elide true
13351352 .t tag add hidden 2.6 3.6
1336 update
1353 updateText
13371354 .t tag add hidden 3.11 4.6
1338 update
1355 updateText
13391356 list $tk_textRelayout $tk_textRedraw
13401357 } {2.0 {2.0 eof}}
13411358 test textDisp-9.13 {TkTextRedrawTag} {
13421359 .t configure -wrap none
13431360 .t delete 1.0 end
13441361 for {set i 1} {$i < 10} {incr i} {
1345 .t insert end "Line $i - This is Line [format %c [expr 64+$i]]\n"
1362 .t insert end "Line $i - This is Line [format %c [expr {64+$i}]]\n"
13461363 }
13471364 .t tag add hidden 2.8 2.17
13481365 .t tag add hidden 6.8 7.17
13491366 .t tag configure hidden -background red
13501367 .t tag configure hidden -elide true
1351 update
1368 updateText
13521369 .t tag configure hidden -elide false
1353 update
1370 updateText
13541371 list $tk_textRelayout $tk_textRedraw
13551372 } {{2.0 6.0 7.0} {2.0 6.0 7.0}}
13561373 test textDisp-9.14 {TkTextRedrawTag} {
13601377 }
13611378 .tnocrash tag configure mytag1 -relief raised
13621379 .tnocrash tag configure mytag2 -relief solid
1363 update
1380 updateText
13641381 proc doit {} {
13651382 .tnocrash tag add mytag1 4.0 5.0
13661383 .tnocrash tag add mytag2 4.0 5.0
13821399 .t configure -wrap char
13831400 .t delete 1.0 end
13841401 .t insert 1.0 "Line 1\nLine 2 is long enough to wrap\nLine 3 is also long enough to wrap\nLine 4"
1385 update
1402 updateText
13861403 .t configure -bg black
1387 update
1404 updateText
13881405 list $tk_textRelayout $tk_textRedraw
13891406 } {{1.0 2.0 2.20 3.0 3.20 4.0} {borders 1.0 2.0 2.20 3.0 3.20 4.0 eof}}
13901407 .t configure -bg [lindex [.t configure -bg] 3]
13981415 .top.t see insert
13991416 tkwait visibility .top.t
14001417 place .top.t -width 150 -height 100
1401 update
1418 updateText
14021419 .top.t index @0,0
14031420 } {1.0}
14041421 catch {destroy .top}
14081425 for {set i 2} {$i <= 200} {incr i} {
14091426 .t insert end "\nLine $i"
14101427 }
1411 update
1428 updateText
14121429 test textDisp-11.1 {TkTextSetYView} {
14131430 .t yview 30.0
1414 update
1431 updateText
14151432 .t index @0,0
14161433 } {30.0}
14171434 test textDisp-11.2 {TkTextSetYView} {
14181435 .t yview 30.0
1419 update
1436 updateText
14201437 .t yview 32.0
1421 update
1438 updateText
14221439 list [.t index @0,0] $tk_textRedraw
14231440 } {32.0 {40.0 41.0}}
14241441 test textDisp-11.3 {TkTextSetYView} {
14251442 .t yview 30.0
1426 update
1443 updateText
14271444 .t yview 28.0
1428 update
1445 updateText
14291446 list [.t index @0,0] $tk_textRedraw
14301447 } {28.0 {28.0 29.0}}
14311448 test textDisp-11.4 {TkTextSetYView} {
14321449 .t yview 30.0
1433 update
1450 updateText
14341451 .t yview 31.4
1435 update
1452 updateText
14361453 list [.t index @0,0] $tk_textRedraw
14371454 } {31.0 40.0}
14381455 test textDisp-11.5 {TkTextSetYView} {
14391456 .t yview 30.0
1440 update
1457 updateText
14411458 set tk_textRedraw {}
14421459 .t yview -pickplace 31.0
1443 update
1460 updateText
14441461 list [.t index @0,0] $tk_textRedraw
14451462 } {30.0 {}}
14461463 test textDisp-11.6 {TkTextSetYView} {
14471464 .t yview 30.0
1448 update
1465 updateText
14491466 set tk_textRedraw {}
14501467 .t yview -pickplace 28.0
1451 update
1468 updateText
14521469 list [.t index @0,0] $tk_textRedraw
14531470 } {28.0 {28.0 29.0}}
14541471 test textDisp-11.7 {TkTextSetYView} {
14551472 .t yview 30.0
1456 update ; update
1473 updateText
14571474 set tk_textRedraw {}
14581475 .t yview -pickplace 26.0
1459 update
1476 updateText
14601477 list [.t index @0,0] $tk_textRedraw
14611478 } {21.0 {21.0 22.0 23.0 24.0 25.0 26.0 27.0 28.0 29.0}}
14621479 test textDisp-11.8 {TkTextSetYView} {
14631480 .t yview 30.0
1464 update
1481 updateText
14651482 set tk_textRedraw {}
14661483 .t yview -pickplace 41.0
1467 update
1484 updateText
14681485 list [.t index @0,0] $tk_textRedraw
14691486 } {32.0 {40.0 41.0}}
14701487 test textDisp-11.9 {TkTextSetYView} {
14711488 .t yview 30.0
1472 update
1489 updateText
14731490 set tk_textRedraw {}
14741491 .t yview -pickplace 43.0
1475 update
1492 updateText
14761493 list [.t index @0,0] $tk_textRedraw
14771494 } {38.0 {40.0 41.0 42.0 43.0 44.0 45.0 46.0 47.0 48.0}}
14781495 test textDisp-11.10 {TkTextSetYView} {
14791496 .t yview 30.0
1480 update
1497 updateText
14811498 set tk_textRedraw {}
14821499 .t yview 10000.0
1483 update
1500 updateText
14841501 list [.t index @0,0] $tk_textRedraw
14851502 } {191.0 {191.0 192.0 193.0 194.0 195.0 196.0 197.0 198.0 199.0 200.0}}
14861503 test textDisp-11.11 {TkTextSetYView} {
14871504 .t yview 195.0
1488 update
1505 updateText
14891506 set tk_textRedraw {}
14901507 .t yview 197.0
1491 update
1508 updateText
14921509 list [.t index @0,0] $tk_textRedraw
14931510 } {191.0 {191.0 192.0 193.0 194.0 195.0 196.0}}
14941511 test textDisp-11.12 {TkTextSetYView, wrapped line is off-screen} {
14951512 .t insert 10.0 "Long line with enough text to wrap\n"
14961513 .t yview 1.0
1497 update
1514 updateText
14981515 set tk_textRedraw {}
14991516 .t see 10.30
1500 update
1517 updateText
15011518 list [.t index @0,0] $tk_textRedraw
15021519 } {2.0 10.20}
15031520 .t delete 10.0 11.0
15111528 for {set i 2} {$i <= 100} {incr i} {
15121529 .top.t insert end "\nLine $i"
15131530 }
1514 update
1531 updateText
15151532 scan [wm geometry .top] "%dx%d" w2 h2
1516 wm geometry .top ${w2}x[expr $h2-2]
1517 update
1533 wm geometry .top ${w2}x[expr {$h2-2}]
1534 updateText
15181535 .top.t yview 1.0
1519 update
1536 updateText
15201537 set tk_textRedraw {}
15211538 .top.t see 5.0
1522 update
1539 updateText
15231540 # Note, with smooth scrolling, the results of this test
15241541 # have changed, and the old '2.0 {5.0 6.0}' is quite wrong.
15251542 list [.top.t index @0,0] $tk_textRedraw
15331550 for {set i 2} {$i <= 20} {incr i} {
15341551 .top.t insert end "\nLine $i"
15351552 }
1536 update
1553 updateText
15371554 test textDisp-11.14 {TkTextSetYView, only a few lines visible} {
15381555 .top.t yview 5.0
1539 update
1556 updateText
15401557 .top.t see 10.0
15411558 .top.t index @0,0
15421559 } {8.0}
15431560 test textDisp-11.15 {TkTextSetYView, only a few lines visible} {
15441561 .top.t yview 5.0
1545 update
1562 updateText
15461563 .top.t see 11.0
15471564 .top.t index @0,0
15481565 # The index 9.0 should be just visible by a couple of pixels
15491566 } {9.0}
15501567 test textDisp-11.16 {TkTextSetYView, only a few lines visible} {
15511568 .top.t yview 8.0
1552 update
1569 updateText
15531570 .top.t see 5.0
15541571 .top.t index @0,0
15551572 } {5.0}
15561573 test textDisp-11.17 {TkTextSetYView, only a few lines visible} {
15571574 .top.t yview 8.0
1558 update
1575 updateText
15591576 .top.t see 4.0
15601577 .top.t index @0,0
15611578 # The index 2.0 should be just visible by a couple of pixels
15701587 .top.t tag add hidden 4.10 "4.10 lineend"
15711588 .top.t tag add hidden 5.15 10.3
15721589 .top.t tag configure hidden -elide true
1573 update
1590 updateText
15741591 .top.t see "8.0 lineend"
15751592 # The index "8.0 lineend" is on screen despite elided -> no scroll
15761593 .top.t index @0,0
15901607 # Indices 21.0, 17.0 and 15.0 are all on the same display line
15911608 # therefore index @0,0 shall be the same for all of them
15921609 .top.t see end
1593 update
1610 updateText
15941611 .top.t see 21.0
1595 update
1612 updateText
15961613 set ind1 [.top.t index @0,0]
15971614 .top.t see end
1598 update
1615 updateText
15991616 .top.t see 17.0
1600 update
1617 updateText
16011618 set ind2 [.top.t index @0,0]
16021619 .top.t see end
1603 update
1620 updateText
16041621 .top.t see 15.0
1605 update
1622 updateText
16061623 set ind3 [.top.t index @0,0]
16071624 list [expr {$ind1 == $ind2}] [expr {$ind1 == $ind3}]
16081625 } {1 1}
16251642 }
16261643 set lineheight [font metrics [.top.t cget -font] -linespace]
16271644 wm geometry .top 200x[expr {$lineheight / 2}]
1628 update
1645 updateText
16291646 .top.t see 1.0
16301647 .top.t index @0,[expr {$lineheight - 2}]
16311648 } {1.0}
16351652 .t insert 50.0 "This is a long line, one that will wrap around twice.\n"
16361653 test textDisp-12.1 {MeasureUp} {
16371654 .t yview 100.0
1638 update
1655 updateText
16391656 .t yview -pickplace 52.0
1640 update
1657 updateText
16411658 .t index @0,0
16421659 } {49.0}
16431660 test textDisp-12.2 {MeasureUp} {
16441661 .t yview 100.0
1645 update
1662 updateText
16461663 .t yview -pickplace 53.0
1647 update
1664 updateText
16481665 .t index @0,0
16491666 } {50.0}
16501667 test textDisp-12.3 {MeasureUp} {
16511668 .t yview 100.0
1652 update
1669 updateText
16531670 .t yview -pickplace 50.10
1654 update
1671 updateText
16551672 .t index @0,0
16561673 } {45.0}
16571674 .t configure -wrap none
16581675 test textDisp-12.4 {MeasureUp} {
16591676 .t yview 100.0
1660 update
1677 updateText
16611678 .t yview -pickplace 53.0
1662 update
1679 updateText
16631680 .t index @0,0
16641681 } {48.0}
16651682 test textDisp-12.5 {MeasureUp} {
16661683 .t yview 100.0
1667 update
1684 updateText
16681685 .t yview -pickplace 50.10
1669 update
1686 updateText
16701687 .t index @0,0
16711688 } {45.0}
16721689
16891706 test textDisp-13.4 {TkTextSeeCmd procedure} {
16901707 .t xview moveto 0
16911708 .t yview moveto 0
1692 update
1709 updateText
16931710 .t see 4.2
16941711 .t index @0,0
16951712 } {1.0}
16971714 .t configure -wrap char
16981715 .t xview moveto 0
16991716 .t yview moveto 0
1700 update
1717 updateText
17011718 .t see 12.1
17021719 .t index @0,0
17031720 } {3.0}
17051722 .t configure -wrap char
17061723 .t xview moveto 0
17071724 .t yview moveto 0
1708 update
1725 updateText
17091726 .t see 30.50
17101727 set x [.t index @0,0]
17111728 .t configure -wrap none
17161733 .t yview moveto 0
17171734 .t tag add sel 30.20
17181735 .t tag add sel 30.40
1719 update
1736 updateText
17201737 .t see 30.50
17211738 .t yview 25.0
17221739 .t see 30.50
17331750 .t yview moveto 0
17341751 .t tag add sel 30.20
17351752 .t tag add sel 30.50
1736 update
1753 updateText
17371754 .t see 30.50
17381755 set x [list [.t bbox 30.50]]
17391756 .t see 30.60
17441761 lappend x [.t bbox 30.90]
17451762 } [list [list 73 [expr {9*$fixedDiff/2 + 64}] 7 $fixedHeight] [list 136 [expr {9*$fixedDiff/2 + 64}] 7 $fixedHeight] [list 136 [expr {9*$fixedDiff/2 + 64}] 7 $fixedHeight] [list 73 [expr {9*$fixedDiff/2 + 64}] 7 $fixedHeight]]
17461763 test textDisp-13.9 {TkTextSeeCmd procedure} {textfonts} {
1747 wm geom . [expr $width-2]x$height
1764 wm geom . [expr {$width-2}]x$height
17481765 .t xview moveto 0
17491766 .t yview moveto 0
17501767 .t tag add sel 30.20
17511768 .t tag add sel 30.50
1752 update
1769 updateText
17531770 .t see 30.50
17541771 set x [list [.t bbox 30.50]]
17551772 .t see 30.60
17811798
17821799 }
17831800 wm geometry .top2 300x200+0+0
1784 update
1801 updateText
17851802 .top2.t2 see "1.0 lineend"
1786 update
1803 updateText
17871804 set ref [.top2.t2 index @0,0]
17881805 .top2.t2 insert "1.0 lineend" ç
17891806 .top2.t2 see "1.0 lineend"
1790 update
1807 updateText
17911808 set new [.top2.t2 index @0,0]
17921809 set res [.top2.t2 compare $ref == $new]
17931810 destroy .top2
17981815 .t configure -wrap none
17991816 test textDisp-14.1 {TkTextXviewCmd procedure} {
18001817 .t delete 1.0 end
1801 update
1818 updateText
18021819 .t insert end xxxxxxxxx\n
18031820 .t insert end "xxxxx xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxx\n"
18041821 .t insert end "xxxx xxxxxxxxx xxxxxxxxxxxxx"
18081825 .t configure -wrap char
18091826 test textDisp-14.2 {TkTextXviewCmd procedure} {
18101827 .t delete 1.0 end
1811 update
1828 updateText
18121829 .t insert end xxxxxxxxx\n
18131830 .t insert end "xxxxx\n"
18141831 .t insert end "xxxx"
18171834 .t configure -wrap none
18181835 test textDisp-14.3 {TkTextXviewCmd procedure} {
18191836 .t delete 1.0 end
1820 update
1837 updateText
18211838 .t insert end xxxxxxxxx\n
18221839 .t insert end "xxxxx\n"
18231840 .t insert end "xxxx"
19101927 .t insert 50.0 "This is a long line, one that will wrap around twice.\n"
19111928 test textDisp-15.1 {ScrollByLines procedure, scrolling backwards} {
19121929 .t yview 45.0
1913 update
1930 updateText
19141931 .t yview scroll -3 units
19151932 .t index @0,0
19161933 } {42.0}
19171934 test textDisp-15.2 {ScrollByLines procedure, scrolling backwards} {
19181935 .t yview 51.0
1919 update
1936 updateText
19201937 .t yview scroll -2 units
19211938 .t index @0,0
19221939 } {50.20}
19231940 test textDisp-15.3 {ScrollByLines procedure, scrolling backwards} {
19241941 .t yview 51.0
1925 update
1942 updateText
19261943 .t yview scroll -4 units
19271944 .t index @0,0
19281945 } {49.0}
19291946 test textDisp-15.4 {ScrollByLines procedure, scrolling backwards} {
19301947 .t yview 50.20
1931 update
1948 updateText
19321949 .t yview scroll -2 units
19331950 .t index @0,0
19341951 } {49.0}
19351952 test textDisp-15.5 {ScrollByLines procedure, scrolling backwards} {
19361953 .t yview 50.40
1937 update
1954 updateText
19381955 .t yview scroll -2 units
19391956 .t index @0,0
19401957 } {50.0}
19411958 test textDisp-15.6 {ScrollByLines procedure, scrolling backwards} {
19421959 .t yview 3.2
1943 update
1960 updateText
19441961 .t yview scroll -5 units
19451962 .t index @0,0
19461963 } {1.0}
19471964 test textDisp-15.7 {ScrollByLines procedure, scrolling forwards} {
19481965 .t yview 48.0
1949 update
1966 updateText
19501967 .t yview scroll 4 units
19511968 .t index @0,0
19521969 } {50.40}
19721989 for {set i 1} {$i < $textheight} {incr i} {
19731990 .tf.f.t insert end "\nLine $i"
19741991 }
1975 update ; after 1000 ; update
1992 updateText
19761993 set refind [.tf.f.t index @0,[winfo height .tf.f.t]]
19771994 # Should scroll and should not crash!
19781995 .tf.f.t yview scroll 1 unit
19922009 .t tag add big 100.0 105.0
19932010 .t insert 151.end { has a lot of extra text, so that it wraps around on the screen several times over.}
19942011 .t insert 153.end { also has enoug extra text to wrap.}
1995 update ; .t count -update -ypixels 1.0 end
2012 updateText
2013 .t count -update -ypixels 1.0 end
19962014 test textDisp-16.1 {TkTextYviewCmd procedure} {
19972015 .t yview 21.0
19982016 set x [.t yview]
20132031 } {1 {bad option "-bogus": must be moveto or scroll}}
20142032 test textDisp-16.6 {TkTextYviewCmd procedure, integer position} {
20152033 .t yview 100.0
2016 update
2034 updateText
20172035 .t yview 98
20182036 .t index @0,0
20192037 } {99.0}
20682086 text .top1.t -height 3 -width 4 -wrap none -setgrid 1 -padx 6 \
20692087 -spacing3 6
20702088 pack .top1.t
2071 update
2089 updateText
20722090 .top1.t insert end "1\n2\n3\n4\n5\n6"
20732091 .top1.t yview moveto 0.3333
20742092 set result [.top1.t yview]
20892107 } {1 {expected integer but got "badInt"}}
20902108 test textDisp-16.22 {TkTextYviewCmd procedure, "scroll" option, back pages} {
20912109 .t yview 50.0
2092 update
2110 updateText
20932111 .t yview scroll -1 pages
20942112 .t index @0,0
20952113 } {42.0}
20982116 } {1 {ambiguous argument "p": must be units, pages, or pixels}}
20992117 test textDisp-16.23 {TkTextYviewCmd procedure, "scroll" option, back pages} {
21002118 .t yview 50.0
2101 update
2119 updateText
21022120 .t yview scroll -3 pa
21032121 .t index @0,0
21042122 } {26.0}
21052123 test textDisp-16.24 {TkTextYviewCmd procedure, "scroll" option, back pages} {
21062124 .t yview 5.0
2107 update
2125 updateText
21082126 .t yview scroll -3 pa
21092127 .t index @0,0
21102128 } {1.0}
21112129 test textDisp-16.25 {TkTextYviewCmd procedure, "scroll" option, back pages} {
21122130 .t configure -height 1
2113 update
2131 updateText
21142132 .t yview 50.0
2115 update
2133 updateText
21162134 .t yview scroll -1 pages
21172135 set x [.t index @0,0]
21182136 .t configure -height 10
2119 update
2137 updateText
21202138 set x
21212139 } {49.0}
21222140 test textDisp-16.26 {TkTextYviewCmd procedure, "scroll" option, forward pages} {
21232141 .t yview 50.0
2124 update
2142 updateText
21252143 .t yview scroll 1 pages
21262144 .t index @0,0
21272145 } {58.0}
21282146 test textDisp-16.27 {TkTextYviewCmd procedure, "scroll" option, forward pages} {
21292147 .t yview 50.0
2130 update
2148 updateText
21312149 .t yview scroll 2 pages
21322150 .t index @0,0
21332151 } {66.0}
21342152 test textDisp-16.28 {TkTextYviewCmd procedure, "scroll" option, forward pages} {textfonts} {
21352153 .t yview 98.0
2136 update
2154 updateText
21372155 .t yview scroll 1 page
2138 set res [expr int([.t index @0,0])]
2156 set res [expr {int([.t index @0,0])}]
21392157 if {$fixedDiff > 1} {
21402158 incr res -1
21412159 }
21432161 } {102}
21442162 test textDisp-16.29 {TkTextYviewCmd procedure, "scroll" option, forward pages} {
21452163 .t configure -height 1
2146 update
2164 updateText
21472165 .t yview 50.0
2148 update
2166 updateText
21492167 .t yview scroll 1 pages
21502168 set x [.t index @0,0]
21512169 .t configure -height 10
2152 update
2170 updateText
21532171 set x
21542172 } {51.0}
21552173 test textDisp-16.30 {TkTextYviewCmd procedure, "scroll units" option} {
21562174 .t yview 45.0
2157 update
2175 updateText
21582176 .t yview scroll -3 units
21592177 .t index @0,0
21602178 } {42.0}
21612179 test textDisp-16.31 {TkTextYviewCmd procedure, "scroll units" option} {
21622180 .t yview 149.0
2163 update
2181 updateText
21642182 .t yview scroll 4 units
21652183 .t index @0,0
21662184 } {151.40}
22652283 .t tag configure hidden -elide true
22662284 .t yview 35.0
22672285 .t yview scroll [expr {- 15 * $fixedHeight}] pixels
2268 update
2286 updateText
22692287 .t index @0,0
22702288 } {5.0}
22712289 test textDisp-16.43 {TkTextYviewCmd procedure with indices in elided lines} {
22792297 .t tag configure hidden -elide true
22802298 .t yview 35.0
22812299 .t yview scroll -15 units
2282 update
2300 updateText
22832301 .t index @0,0
22842302 } {5.0}
22852303 test textDisp-16.44 {TkTextYviewCmd procedure, scroll down, with elided lines} {
22902308 .t insert end "$x 1111\n$x 2222\n$x 3333\n$x 4444\n$x 5555\n$x 6666" hidden
22912309 }
22922310 .t tag configure hidden -elide true ; # 5 hidden lines
2293 update
2294 .t see [expr {5 + [winfo height .t] / $fixedHeight} + 1].0
2295 update
2311 updateText
2312 .t see [expr {5 + [winfo height .t] / $fixedHeight + 1}].0
2313 updateText
22962314 .t index @0,0
22972315 } {2.0}
22982316
23682386 .t insert end xxxxxxxxx\n
23692387 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
23702388 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx
2371 update
2389 updateText
23722390 set scrollInfo
23732391 } [list 0.0 [expr {4.0/11}]]
23742392 test textDisp-18.2 {GetXView procedure} {
23772395 .t insert end xxxxxxxxx\n
23782396 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
23792397 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx
2380 update
2398 updateText
23812399 set scrollInfo
23822400 } {0.0 1.0}
23832401 test textDisp-18.3 {GetXView procedure} {
23842402 .t configure -wrap none
23852403 .t delete 1.0 end
2386 update
2404 updateText
23872405 set scrollInfo
23882406 } {0.0 1.0}
23892407 test textDisp-18.4 {GetXView procedure} {
23922410 .t insert end xxxxxxxxx\n
23932411 .t insert end xxxxxx\n
23942412 .t insert end xxxxxxxxxxxxxxxxx
2395 update
2413 updateText
23962414 set scrollInfo
23972415 } {0.0 1.0}
23982416 test textDisp-18.5 {GetXView procedure} {
24022420 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
24032421 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxx
24042422 .t xview scroll 31 units
2405 update
2423 updateText
24062424 set scrollInfo
24072425 } [list [expr {31.0/55}] [expr {51.0/55}]]
24082426 test textDisp-18.6 {GetXView procedure} {
24132431 .t insert end "xxxx xxxxxxxxx xxxxxxxxxxxxx"
24142432 .t xview moveto 0
24152433 .t xview scroll 31 units
2416 update
2434 updateText
24172435 set x {}
24182436 lappend x $scrollInfo
24192437 .t configure -wrap char
2420 update
2438 updateText
24212439 lappend x $scrollInfo
24222440 .t configure -wrap word
2423 update
2441 updateText
24242442 lappend x $scrollInfo
24252443 .t configure -wrap none
2426 update
2444 updateText
24272445 lappend x $scrollInfo
24282446 } [list [list [expr {31.0/56}] [expr {51.0/56}]] {0.0 1.0} {0.0 1.0} [list 0.0 [expr {5.0/14}]]]
24292447 test textDisp-18.7 {GetXView procedure} {
24302448 .t configure -wrap none
24312449 .t delete 1.0 end
2432 update
2450 updateText
24332451 set scrollInfo unchanged
24342452 .t insert end xxxxxx\n
24352453 .t insert end xxx
2436 update
2454 updateText
24372455 set scrollInfo
24382456 } {unchanged}
24392457 test textDisp-18.8 {GetXView procedure} {
24472465 .t configure -wrap none
24482466 .t delete 1.0 end
24492467 .t insert end xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n
2450 update
2468 updateText
24512469 .t delete 1.0 end
24522470 .t configure -xscrollcommand scrollError
2453 update
2471 updateText
24542472 set x
24552473 } {{scrolling error} {scrolling error
24562474 while executing
24672485 test textDisp-19.1 {GetYView procedure} {
24682486 .t configure -wrap char
24692487 .t delete 1.0 end
2470 update
2488 updateText
24712489 set scrollInfo
24722490 } {0.0 1.0}
24732491 test textDisp-19.2 {GetYView procedure} {
24742492 .t configure -wrap char
24752493 .t delete 1.0 end
2476 update
2494 updateText
24772495 set scrollInfo "unchanged"
24782496 .t insert 1.0 "Line1\nLine2"
2479 update
2497 updateText
24802498 set scrollInfo
24812499 } {unchanged}
24822500 test textDisp-19.3 {GetYView procedure} {
24832501 .t configure -wrap char
24842502 .t delete 1.0 end
2485 update; after 10 ; update
2503 updateText
24862504 set scrollInfo "unchanged"
24872505 .t insert 1.0 "Line 1\nLine 2 is so long that it wraps around\nLine 3"
2488 update
2506 updateText
24892507 set scrollInfo
24902508 } {unchanged}
24912509 test textDisp-19.4 {GetYView procedure} {
24922510 .t configure -wrap char
24932511 .t delete 1.0 end
24942512 .t insert 1.0 "Line 1"
2495 update
2513 updateText
24962514 set scrollInfo "unchanged"
24972515 foreach i {2 3 4 5 6 7 8 9 10 11 12 13} {
24982516 .t insert end "\nLine $i"
24992517 }
2500 update
2518 updateText
25012519 set scrollInfo
25022520 } [list 0.0 [expr {70.0/91}]]
25032521 test textDisp-19.5 {GetYView procedure} {
25082526 .t insert end "\nLine $i"
25092527 }
25102528 .t insert 2.end " is really quite long; in fact it's so long that it wraps three times"
2511 update ; after 100
2529 updateText
25122530 set x $scrollInfo
25132531 } {0.0 0.625}
25142532 test textDisp-19.6 {GetYView procedure} {
25202538 }
25212539 .t insert 2.end " is really quite long; in fact it's so long that it wraps three times"
25222540 .t yview 4.0
2523 update
2541 updateText
25242542 set x $scrollInfo
25252543 } {0.375 1.0}
25262544 test textDisp-19.7 {GetYView procedure} {
25322550 }
25332551 .t insert 2.end " is really quite long; in fact it's so long that it wraps three times"
25342552 .t yview 2.26
2535 update; after 1; update
2553 updateText
25362554 set x $scrollInfo
25372555 } {0.125 0.75}
25382556 test textDisp-19.8 {GetYView procedure} {
25442562 }
25452563 .t insert 10.end " is really quite long; in fact it's so long that it wraps three times"
25462564 .t yview 2.0
2547 update
2565 updateText
25482566 .t count -update -ypixels 1.0 end
25492567 set x $scrollInfo
25502568 } {0.0625 0.6875}
25562574 .t insert end "\nLine $i"
25572575 }
25582576 .t yview 3.0
2559 update
2577 updateText
25602578 set scrollInfo
25612579 } [list [expr {4.0/30}] 0.8]
25622580 test textDisp-19.10 {GetYView procedure} {
25672585 .t insert end "\nLine $i"
25682586 }
25692587 .t yview 11.0
2570 update
2588 updateText
25712589 set scrollInfo
25722590 } [list [expr {1.0/3}] 1.0]
25732591 test textDisp-19.10.1 {Widget manipulation causes height miscount} {
25782596 .t insert end "\nLine $i"
25792597 }
25802598 .t yview 11.0
2581 update
2599 updateText
25822600 .t configure -wrap word
25832601 .t delete 1.0 end
25842602 .t insert 1.0 "Line 1"
25882606 .t insert end "\nThis last line wraps around four "
25892607 .t insert end "times with a little bit left on the last line."
25902608 .t yview insert
2591 update
2609 updateText
25922610 .t count -update -ypixels 1.0 end
25932611 set scrollInfo
25942612 } {0.5 1.0}
26022620 .t insert end "\nThis last line wraps around four "
26032621 .t insert end "times with a little bit left on the last line."
26042622 .t yview insert
2605 update
2623 updateText
26062624 .t count -update -ypixels 1.0 end
26072625 set scrollInfo
26082626 } {0.5 1.0}
27402758 pack .top.t -expand yes -fill both
27412759 .top.t insert end "Line 1\nLine 2\nLine 3\nLine 4\nLine 5"
27422760 # Need to wait for asychronous calculations to complete.
2743 update ; after 10
2761 updateText
27442762 scan [wm geom .top] %dx%d twidth theight
2745 wm geom .top ${twidth}x[expr $theight - 3]
2746 update
2763 wm geom .top ${twidth}x[expr {$theight - 3}]
2764 updateText
27472765 .top.t yview
27482766 } [list 0.0 [expr {(5.0 * $fixedHeight - 3.0)/ (5.0 * $fixedHeight)}]]
27492767 test textDisp-19.13 {GetYView procedure, partially visible last line} {textfonts} {
27542772 pack .top.t -expand yes -fill both
27552773 .top.t insert end "Line 1\nLine 2\nLine 3\nLine 4 has enough text to wrap around at least once"
27562774 # Need to wait for asychronous calculations to complete.
2757 update ; after 10
2775 updateText
27582776 scan [wm geom .top] %dx%d twidth theight
2759 wm geom .top ${twidth}x[expr $theight - 3]
2760 update
2777 wm geom .top ${twidth}x[expr {$theight - 3}]
2778 updateText
27612779 .top.t yview
27622780 } [list 0.0 [expr {(5.0 * $fixedHeight - 3.0)/ (5.0 * $fixedHeight)}]]
27632781 catch {destroy .top}
27712789 .t insert end "\nThis last line wraps around four "
27722790 .t insert end "times with a little bit left on the last line."
27732791 # Need to update so everything is calculated.
2774 update ; .t count -update -ypixels 1.0 end
2775 update ; after 10 ; update
2792 updateText
2793 .t count -update -ypixels 1.0 end
2794 updateText
27762795 set scrollInfo "unchanged"
27772796 .t mark set insert 3.0
27782797 .t tag configure x -background red
27792798 .t tag add x 1.0 5.0
2780 update
2799 updateText
27812800 .t tag delete x
27822801 set scrollInfo
27832802 } {unchanged}
27902809 }
27912810 .t insert end "\nThis last line wraps around four "
27922811 .t insert end "times with a bit little left on the last line."
2793 update
2812 updateText
27942813 .t configure -yscrollcommand scrollError
27952814 proc bgerror args {
27962815 global x errorInfo errorCode
27972816 set x [list $args $errorInfo $errorCode]
27982817 }
27992818 .t delete 1.0 end
2800 update
2819 updateText
28012820 rename bgerror {}
28022821 .t configure -yscrollcommand scroll
28032822 set x
28192838 .t insert end "\nThis last line wraps around four "
28202839 .t insert end "times with a little bit left on the last line."
28212840 # Need to update so everything is calculated.
2822 update ; .t count -update -ypixels 1.0 end ; update
2841 updateText
2842 .t count -update -ypixels 1.0 end
2843 updateText
28232844 set res {}
28242845 lappend res \
28252846 [.t count -ypixels 1.0 end] \
28702891 update
28712892 lappend res [.t count -ypixels 5.0 25.0]
28722893 .t yview scroll [expr {- 15 * $fixedHeight}] pixels
2873 update
2894 updateText
28742895 lappend res [.t count -ypixels 5.0 25.0]
28752896 } [list [expr {5 * $fixedHeight}] [expr {5 * $fixedHeight}]]
28762897 test textDisp-19.19 {count -ypixels with indices in elided lines} {
28832904 .t tag add hidden 5.27 11.0
28842905 .t tag configure hidden -elide true
28852906 .t yview 5.0
2886 update
2907 updateText
28872908 set res [list [.t count -ypixels 5.0 11.0] [.t count -ypixels 5.0 11.20]]
28882909 } [list [expr {1 * $fixedHeight}] [expr {2 * $fixedHeight}]]
28892910 .t delete 1.0 end
29752996 .t configure -wrap word
29762997 .t delete 50.0 51.0
29772998 .t insert 50.0 "This is a long line, one that will wrap around twice.\n"
2978 update
2999 updateText
29793000 .t tag add x 50.1
29803001 test textDisp-22.1 {TkTextCharBbox} {textfonts} {
29813002 .t config -wrap word
29913012 test textDisp-22.3 {TkTextCharBbox, cut-off lines} {textfonts} {
29923013 .t config -wrap char
29933014 .t yview 10.0
2994 wm geom . ${width}x[expr $height-1]
2995 update
3015 wm geom . ${width}x[expr {$height-1}]
3016 updateText
29963017 list [.t bbox 19.1] [.t bbox 20.1]
29973018 } [list [list 10 [expr {3+9*$fixedHeight}] 7 $fixedHeight] [list 10 [expr {3+10*$fixedHeight}] 7 3]]
29983019 test textDisp-22.4 {TkTextCharBbox, cut-off lines} {textfonts} {
29993020 .t config -wrap char
30003021 .t yview 10.0
3001 wm geom . ${width}x[expr $height+1]
3002 update
3022 wm geom . ${width}x[expr {$height+1}]
3023 updateText
30033024 list [.t bbox 19.1] [.t bbox 20.1]
30043025 } [list [list 10 [expr {3+9*$fixedHeight}] 7 $fixedHeight] [list 10 [expr {3+10*$fixedHeight}] 7 5]]
30053026 test textDisp-22.5 {TkTextCharBbox, cut-off char} {textfonts} {
30063027 .t config -wrap none
30073028 .t yview 10.0
3008 wm geom . [expr $width-95]x$height
3009 update
3029 wm geom . [expr {$width-95}]x$height
3030 updateText
30103031 .t bbox 15.6
30113032 } [list 45 [expr {3+5*$fixedHeight}] 7 $fixedHeight]
30123033 test textDisp-22.6 {TkTextCharBbox, line visible but not char} {textfonts} {
30133034 .t config -wrap char
30143035 .t yview 10.0
30153036 .t tag add big 20.2 20.5
3016 wm geom . ${width}x[expr $height+3]
3017 update
3037 wm geom . ${width}x[expr {$height+3}]
3038 updateText
30183039 list [.t bbox 19.1] [.t bbox 20.1] [.t bbox 20.2]
30193040 } [list [list 10 [expr {3+9*$fixedHeight}] 7 $fixedHeight] {} [list 17 [expr {3+10*$fixedHeight}] 14 7]]
30203041 wm geom . {}
3021 update
3042 updateText
30223043 test textDisp-22.7 {TkTextCharBbox, different character sizes} {textfonts} {
30233044 .t config -wrap char
30243045 .t yview 10.0
30253046 .t tag add big 12.2 12.5
3026 update
3047 updateText
30273048 list [.t bbox 12.1] [.t bbox 12.2]
30283049 } [list [list 10 [expr {3 + 2*$fixedHeight + $ascentDiff}] 7 $fixedHeight] [list 17 [expr {3+ 2*$fixedHeight}] 14 27]]
30293050 .t tag remove big 1.0 end
30503071 .t window create 1.7 -window .t.f2 -align center
30513072 .t window create 2.1 -window .t.f3 -align bottom
30523073 .t window create 2.10 -window .t.f4 -align baseline
3053 update
3074 updateText
30543075 list [.t bbox .t.f1] [.t bbox .t.f2] [.t bbox .t.f3] [.t bbox .t.f4] \
30553076 [.t bbox 1.1] [.t bbox 2.9]
30563077 } [list [list 24 11 10 4] [list 55 [expr {$fixedDiff/2 + 15}] 10 4] [list 10 [expr {2*$fixedDiff + 43}] 10 4] [list 76 [expr {2*$fixedDiff + 40}] 10 4] [list 10 11 7 $fixedHeight] [list 69 [expr {$fixedDiff + 34}] 7 $fixedHeight]]
30593080 .t configure -wrap char
30603081 .t delete 1.0 end
30613082 for {set i 1} {$i < 10} {incr i} {
3062 .t insert end "Line $i - Line [format %c [expr 64+$i]]\n"
3083 .t insert end "Line $i - Line [format %c [expr {64+$i}]]\n"
30633084 }
30643085 .t tag add hidden 2.8 2.13
30653086 .t tag add hidden 6.8 7.13
30663087 .t tag configure hidden -elide true
3067 update
3088 updateText
30683089 list \
30693090 [expr {[lindex [.t bbox 2.9] 0] - [lindex [.t bbox 2.8] 0]}] \
30703091 [expr {[lindex [.t bbox 2.10] 0] - [lindex [.t bbox 2.8] 0]}] \
30823103 .t configure -wrap char
30833104 .t delete 1.0 end
30843105 for {set i 1} {$i < 10} {incr i} {
3085 .t insert end "Line $i - Line _$i - Lines .$i - Line [format %c [expr 64+$i]]\n"
3106 .t insert end "Line $i - Line _$i - Lines .$i - Line [format %c [expr {64+$i}]]\n"
30863107 }
30873108 .t tag add hidden 1.30 2.5
30883109 .t tag configure hidden -elide true
3089 update
3110 updateText
30903111 list \
30913112 [expr {[lindex [.t bbox 1.30] 0] - [lindex [.t bbox 2.4] 0]}] \
30923113 [expr {[lindex [.t bbox 1.30] 0] - [lindex [.t bbox 2.5] 0]}]
31003121 .t configure -wrap word
31013122 .t delete 50.0 51.0
31023123 .t insert 50.0 "This is a long line, one that will wrap around twice.\n"
3103 update
3124 updateText
31043125 test textDisp-23.1 {TkTextDLineInfo} {textfonts} {
31053126 .t config -wrap word
31063127 .t yview 48.0
31093130 } [list {} [list 3 3 49 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {4*$fixedDiff + 55}] 91 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] {}]
31103131 test textDisp-23.2 {TkTextDLineInfo} {textfonts} {
31113132 .t config -bd 4 -wrap word
3112 update
3133 updateText
31133134 .t yview 48.0
31143135 .t dlineinfo 50.40
31153136 } [list 7 [expr {4*$fixedDiff + 59}] 91 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]]
31163137 .t config -bd 0
31173138 test textDisp-23.3 {TkTextDLineInfo} {textfonts} {
31183139 .t config -wrap none
3119 update
3140 updateText
31203141 .t yview 48.0
31213142 list [.t dlineinfo 50.40] [.t dlineinfo 57.3]
31223143 } [list [list 3 [expr {2*$fixedDiff + 29}] 371 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {9*$fixedDiff + 120}] 49 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]]]
31233144 test textDisp-23.4 {TkTextDLineInfo, cut-off lines} {textfonts} {
31243145 .t config -wrap char
31253146 .t yview 10.0
3126 wm geom . ${width}x[expr $height-1]
3127 update
3147 wm geom . ${width}x[expr {$height-1}]
3148 updateText
31283149 list [.t dlineinfo 19.0] [.t dlineinfo 20.0]
31293150 } [list [list 3 [expr {9*$fixedDiff + 120}] 49 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {10*$fixedDiff + 133}] 49 3 [expr {$fixedDiff + 10}]]]
31303151 test textDisp-23.5 {TkTextDLineInfo, cut-off lines} {textfonts} {
31313152 .t config -wrap char
31323153 .t yview 10.0
3133 wm geom . ${width}x[expr $height+1]
3134 update
3154 wm geom . ${width}x[expr {$height+1}]
3155 updateText
31353156 list [.t dlineinfo 19.0] [.t dlineinfo 20.0]
31363157 } [list [list 3 [expr {9*$fixedDiff + 120}] 49 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 3 [expr {10*$fixedDiff + 133}] 49 5 [expr {$fixedDiff + 10}]]]
31373158 wm geom . {}
3138 update
3159 updateText
31393160 test textDisp-23.6 {TkTextDLineInfo, horizontal scrolling} {textfonts} {
31403161 .t config -wrap none
31413162 .t delete 1.0 end
31433164 .t insert end "Second line is a very long one that doesn't all fit.\n"
31443165 .t insert end "Third"
31453166 .t xview scroll 6 units
3146 update
3167 updateText
31473168 list [.t dlineinfo 1.0] [.t dlineinfo 2.0] [.t dlineinfo 3.0]
31483169 } [list [list -39 3 70 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list -39 [expr {$fixedDiff + 16}] 364 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list -39 [expr {2*$fixedDiff + 29}] 35 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]]]
31493170 .t xview moveto 0
31713192 .t configure -wrap char
31723193 .t delete 1.0 end
31733194 .t insert 1.0 "abcdefghijklmnopqrstuvwxyz"
3174 wm geom . [expr $width+1]x$height
3175 update
3195 wm geom . [expr {$width+1}]x$height
3196 updateText
31763197 list [.t bbox 1.19] [.t bbox 1.20]
31773198 } [list [list 136 3 12 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
31783199 test textDisp-24.3 {TkTextCharLayoutProc} {textfonts} {
31793200 .t configure -wrap char
31803201 .t delete 1.0 end
31813202 .t insert 1.0 "abcdefghijklmnopqrstuvwxyz"
3182 wm geom . [expr $width-1]x$height
3183 update
3203 wm geom . [expr {$width-1}]x$height
3204 updateText
31843205 list [.t bbox 1.19] [.t bbox 1.20]
31853206 } [list [list 136 3 10 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
31863207 test textDisp-24.4 {TkTextCharLayoutProc, newline not visible} {textfonts} {
31883209 .t delete 1.0 end
31893210 .t insert 1.0 01234567890123456789\n012345678901234567890
31903211 wm geom . {}
3191 update
3212 updateText
31923213 list [.t bbox 1.19] [.t bbox 1.20] [.t bbox 2.20]
31933214 } [list [list 136 3 7 $fixedHeight] [list 143 3 0 $fixedHeight] [list 3 [expr {2*$fixedDiff + 29}] 7 $fixedHeight]]
31943215 test textDisp-24.5 {TkTextCharLayoutProc, char doesn't fit, newline not visible} {unix textfonts} {
31963217 .t delete 1.0 end
31973218 .t insert 1.0 0\n1\n
31983219 wm geom . 110x$height
3199 update
3220 updateText
32003221 list [.t bbox 1.0] [.t bbox 1.1] [.t bbox 2.0]
32013222 } [list [list 3 3 4 $fixedHeight] [list 7 3 0 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 4 $fixedHeight]]
32023223 test textDisp-24.6 {TkTextCharLayoutProc, line ends with space} {textfonts} {
32043225 .t delete 1.0 end
32053226 .t insert 1.0 "a b c d e f g h i j k l m n o p"
32063227 wm geom . {}
3207 update
3228 updateText
32083229 list [.t bbox 1.19] [.t bbox 1.20]
32093230 } [list [list 136 3 7 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
32103231 test textDisp-24.7 {TkTextCharLayoutProc, line ends with space} {textfonts} {
32113232 .t configure -wrap char
32123233 .t delete 1.0 end
32133234 .t insert 1.0 "a b c d e f g h i j k l m n o p"
3214 wm geom . [expr $width+1]x$height
3215 update
3235 wm geom . [expr {$width+1}]x$height
3236 updateText
32163237 list [.t bbox 1.19] [.t bbox 1.20]
32173238 } [list [list 136 3 12 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
32183239 test textDisp-24.8 {TkTextCharLayoutProc, line ends with space} {textfonts} {
32193240 .t configure -wrap char
32203241 .t delete 1.0 end
32213242 .t insert 1.0 "a b c d e f g h i j k l m n o p"
3222 wm geom . [expr $width-1]x$height
3223 update
3243 wm geom . [expr {$width-1}]x$height
3244 updateText
32243245 list [.t bbox 1.19] [.t bbox 1.20]
32253246 } [list [list 136 3 10 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
32263247 test textDisp-24.9 {TkTextCharLayoutProc, line ends with space} {textfonts} {
32273248 .t configure -wrap char
32283249 .t delete 1.0 end
32293250 .t insert 1.0 "a b c d e f g h i j k l m n o p"
3230 wm geom . [expr $width-6]x$height
3231 update
3251 wm geom . [expr {$width-6}]x$height
3252 updateText
32323253 list [.t bbox 1.19] [.t bbox 1.20]
32333254 } [list [list 136 3 5 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
32343255 test textDisp-24.10 {TkTextCharLayoutProc, line ends with space} {textfonts} {
32353256 .t configure -wrap char
32363257 .t delete 1.0 end
32373258 .t insert 1.0 "a b c d e f g h i j k l m n o p"
3238 wm geom . [expr $width-7]x$height
3239 update
3259 wm geom . [expr {$width-7}]x$height
3260 updateText
32403261 list [.t bbox 1.19] [.t bbox 1.20]
32413262 } [list [list 136 3 4 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
32423263 test textDisp-24.11 {TkTextCharLayoutProc, line ends with space that doesn't quite fit} {textfonts} {
32433264 .t configure -wrap char
32443265 .t delete 1.0 end
32453266 .t insert 1.0 "01234567890123456789 \nabcdefg"
3246 wm geom . [expr $width-2]x$height
3247 update
3267 wm geom . [expr {$width-2}]x$height
3268 updateText
32483269 set result {}
32493270 lappend result [.t bbox 1.21] [.t bbox 2.0]
32503271 .t mark set insert 1.21
32633284 .t delete 1.0 end
32643285 .t insert 1.0 "abcdefghijklmnopqrstuvwxyz"
32653286 wm geom . {}
3266 update
3287 updateText
32673288 list [.t bbox 1.19] [.t bbox 1.20]
32683289 } [list [list 136 3 7 $fixedHeight] {}]
32693290 test textDisp-24.14 {TkTextCharLayoutProc, -wrap none} {textfonts} {
32703291 .t configure -wrap none
32713292 .t delete 1.0 end
32723293 .t insert 1.0 "abcdefghijklmnopqrstuvwxyz"
3273 wm geom . [expr $width+1]x$height
3274 update
3294 wm geom . [expr {$width+1}]x$height
3295 updateText
32753296 list [.t bbox 1.19] [.t bbox 1.20]
32763297 } [list [list 136 3 7 $fixedHeight] [list 143 3 5 $fixedHeight]]
32773298 test textDisp-24.15 {TkTextCharLayoutProc, -wrap none} {textfonts} {
32783299 .t configure -wrap none
32793300 .t delete 1.0 end
32803301 .t insert 1.0 "abcdefghijklmnopqrstuvwxyz"
3281 wm geom . [expr $width-1]x$height
3282 update
3302 wm geom . [expr {$width-1}]x$height
3303 updateText
32833304 list [.t bbox 1.19] [.t bbox 1.20]
32843305 } [list [list 136 3 7 $fixedHeight] [list 143 3 3 $fixedHeight]]
32853306 test textDisp-24.16 {TkTextCharLayoutProc, no chars fit} {textfonts} {
32903311 .t delete 1.0 end
32913312 .t insert 1.0 "abcdefghijklmnopqrstuvwxyz"
32923313 wm geom . 103x$height
3293 update
3314 updateText
32943315 list [.t bbox 1.0] [.t bbox 1.1] [.t bbox 1.2]
32953316 } [list [list 3 3 1 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 1 $fixedHeight] [list 3 [expr {2*$fixedDiff + 29}] 1 $fixedHeight]]
32963317 if {$tcl_platform(platform) == "windows"} {
33013322 .t delete 1.0 end
33023323 .t insert 1.0 "This is a line that wraps around"
33033324 wm geom . {}
3304 update
3325 updateText
33053326 list [.t bbox 1.19] [.t bbox 1.20]
33063327 } [list [list 136 3 7 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
33073328 test textDisp-24.18 {TkTextCharLayoutProc, -wrap word} {textfonts} {
33093330 .t delete 1.0 end
33103331 .t insert 1.0 "xxThis is a line that wraps around"
33113332 wm geom . {}
3312 update
3333 updateText
33133334 list [.t bbox 1.15] [.t bbox 1.16] [.t bbox 1.17]
33143335 } [list [list 108 3 7 $fixedHeight] [list 115 3 28 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 7 $fixedHeight]]
33153336 test textDisp-24.19 {TkTextCharLayoutProc, -wrap word} {textfonts} {
33173338 .t delete 1.0 end
33183339 .t insert 1.0 "xxThis is a line that wraps around"
33193340 wm geom . {}
3320 update
3341 updateText
33213342 list [.t bbox 1.14] [.t bbox 1.15] [.t bbox 1.16]
33223343 } [list [list 101 3 7 $fixedHeight] [list 108 3 7 $fixedHeight] [list 115 3 28 $fixedHeight]]
33233344 test textDisp-24.20 {TkTextCharLayoutProc, vertical offset} {textfonts} {
33353356 set result
33363357 } [list [list 10 [expr {$fixedDiff + 16}] 7 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 42 [expr {$fixedDiff + 13}] [expr {$fixedDiff + 10}]] [list 10 [expr {$fixedDiff + 16}] 7 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 42 [expr {$fixedDiff + 19}] [expr {$fixedDiff + 16}]] [list 10 [expr {$fixedDiff + 18}] 7 $fixedHeight] [list 3 [expr {$fixedDiff + 16}] 42 [expr {$fixedDiff + 15}] [expr {$fixedDiff + 10}]]]
33373358 .t configure -width 30
3338 update
3359 updateText
33393360 test textDisp-24.21 {TkTextCharLayoutProc, word breaks} {textfonts} {
33403361 .t configure -wrap word
33413362 .t delete 1.0 end
33653386 } [list 3 [expr {2*$fixedDiff + 29}] 30 20]
33663387 catch {destroy .t.f}
33673388 .t configure -width 20
3368 update
3389 updateText
33693390 test textDisp-24.24 {TkTextCharLayoutProc, justification and tabs} {textfonts} {
33703391 .t delete 1.0 end
33713392 .t tag configure x -justify center
33783399 pack .tt
33793400 } -body {
33803401 .tt insert end \t9\n\t99\n\t999
3381 update
3402 updateText
33823403 list [.tt bbox 1.1] [.tt bbox 2.2] [.tt bbox 3.3]
33833404 } -cleanup {
33843405 destroy .tt
33863407
33873408 .t configure -width 40 -bd 0 -relief flat -highlightthickness 0 -padx 0 \
33883409 -tabs 100
3389 update
3410 updateText
33903411 test textDisp-25.1 {CharBboxProc procedure, check tab width} {textfonts} {
33913412 .t delete 1.0 end
33923413 .t insert 1.0 abc\td\tfgh
33953416
33963417 .t configure -width 40 -bd 0 -relief flat -highlightthickness 0 -padx 0 \
33973418 -tabs {}
3398 update
3419 updateText
33993420 test textDisp-26.1 {AdjustForTab procedure, no tabs} {textfonts} {
34003421 .t delete 1.0 end
34013422 .t insert 1.0 a\tbcdefghij\tc\td
34273448 .t tag configure x -tabs {40 70 right}
34283449 .t tag add x 1.0 end
34293450 list [lindex [.t bbox 1.2] 0] \
3430 [expr [lindex [.t bbox 1.4] 0] + [lindex [.t bbox 1.4] 2]] \
3431 [expr [lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]] \
3432 [expr [lindex [.t bbox 1.8] 0] + [lindex [.t bbox 1.8] 2]]
3451 [expr {[lindex [.t bbox 1.4] 0] + [lindex [.t bbox 1.4] 2]}] \
3452 [expr {[lindex [.t bbox 1.6] 0] + [lindex [.t bbox 1.6] 2]}] \
3453 [expr {[lindex [.t bbox 1.8] 0] + [lindex [.t bbox 1.8] 2]}]
34333454 } [list 40 70 100 130]
34343455 test textDisp-26.4 {AdjustForTab procedure, different alignments} {
34353456 .t delete 1.0 end
35183539 .t tag add y 1.9
35193540 button .b -text "="
35203541 .t window create 1.3 -window .b
3521 update
3542 updateText
35223543 lindex [.t bbox 1.5] 0
35233544 } {120}
35243545 test textDisp-26.13 {AdjustForTab procedure, not enough space} {textfonts} {
35653586
35663587 .t configure -width 20 -bd 2 -highlightthickness 2 -relief sunken -tabs {} \
35673588 -wrap char
3568 update
3589 updateText
35693590 test textDisp-27.1 {SizeOfTab procedure, old-style tabs} {textfonts} {
35703591 .t delete 1.0 end
35713592 .t insert 1.0 a\tbcdefghij\tc\td
36343655 # Tk_GetPixelsFromObj uses the standard 'int(0.5 + float)' rounding,
36353656 # so must we.
36363657 set tab [expr {4 + int(0.5 + $tab + $cm)}]
3637 update
3658 updateText
36383659 set res [.t bbox 2.23]
36393660 lset res 0 [expr {[lindex $res 0] - $tab}]
36403661 set res
36553676 # Tk_GetPixelsFromObj uses the standard 'int(0.5 + float)' rounding,
36563677 # so must we.
36573678 set tab [expr {4 + int(0.5 + $tab + $cm)}]
3658 update
3679 updateText
36593680 set res [.t bbox 2.23]
36603681 .t configure -tabstyle tabular
36613682 lset res 0 [expr {[lindex $res 0] - $tab}]
36703691 }
36713692 .t configure -tabs $interpolatetab -wrap none -width 150
36723693 .t insert 1.0 [string repeat "a\t" 20]
3673 update
3694 updateText
36743695 set res [.t bbox 1.20]
36753696 # Now, Tk's interpolated tabs should be the same as
36763697 # non-interpolated.
36773698 .t configure -tabs $precisetab
3678 update
3699 updateText
36793700 expr {[lindex $res 0] - [lindex [.t bbox 1.20] 0]}
36803701 } {0}
36813702
36823703 .t configure -wrap char -tabs {} -width 20
3683 update
3704 updateText
36843705 test textDisp-27.8 {SizeOfTab procedure, right alignment} {textfonts} {
36853706 .t delete 1.0 end
36863707 .t insert 1.0 a\t\txyzzyabc
37243745 .t2.t insert end "1\n2\n3\n4\n5\n6\n7\n8\n"
37253746 pack .t2.t
37263747 wm geometry .t2 +0+0
3727 update
3748 updateText
37283749 .t2.t configure -yscrollcommand bizarre_scroll
37293750 .t2.t yview 100.0
37303751 set result [.t2.t index @0,0]
3731 update
3752 updateText
37323753 lappend result [.t2.t index @0,0]
37333754 } {6.0 1.0}
37343755
37443765 .t2.t insert end 123
37453766 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
37463767 .t2.t window create 1.1 -window .t2.t.f
3747 update
3768 updateText
37483769 list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
37493770 } [list [list 0.0 [expr {20.0*$fixedWidth/300}]] 300x50+[expr {$twbw + $twht + 1}]+[expr {$twbw + $twht + $fixedHeight + 1}] [list [expr {$twbw + $twht + $fixedWidth + 1}] [expr {$twbw + $twht + $fixedHeight + 50 + 1}] $fixedWidth $fixedHeight]]
37503771 test textDisp-29.2 {miscellaneous: lines wrap but are still too long} {textfonts} {
37593780 .t2.t insert end 123
37603781 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
37613782 .t2.t window create 1.1 -window .t2.t.f
3762 update
3783 updateText
37633784 .t2.t xview scroll 1 unit
3764 update
3785 updateText
37653786 list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
37663787 } [list [list [expr {1.0*$fixedWidth/300}] [expr {21.0*$fixedWidth/300}]] 300x50+[expr {$twbw + $twht + 1 - $fixedWidth}]+[expr {$twbw + $twht + $fixedHeight + 1}] [list [expr {$twbw + $twht + $fixedWidth + 1 - $fixedWidth}] [expr {$twbw + $twht + $fixedHeight + 50 + 1}] $fixedWidth $fixedHeight]]
37673788 test textDisp-29.2.1 {miscellaneous: lines wrap but are still too long} {textfonts} {
37753796 pack .t2.s -side bottom -fill x
37763797 .t2.t insert end 1\n
37773798 .t2.t insert end [string repeat "abc" 30]
3778 update
3799 updateText
37793800 .t2.t xview scroll 5 unit
3780 update
3801 updateText
37813802 .t2.t xview
37823803 } [list [expr {5.0/90}] [expr {25.0/90}]]
37833804 test textDisp-29.2.2 {miscellaneous: lines wrap but are still too long} {textfonts} {
37923813 .t2.t insert end 123
37933814 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
37943815 .t2.t window create 1.1 -window .t2.t.f
3795 update
3816 updateText
37963817 .t2.t xview scroll 2 unit
3797 update
3818 updateText
37983819 list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
37993820 } [list [list [expr {2.0*$fixedWidth/300}] [expr {22.0*$fixedWidth/300}]] 300x50+[expr {$twbw + $twht + 1 - 2*$fixedWidth}]+[expr {$twbw + $twht + $fixedHeight + 1}] {}]
38003821 test textDisp-29.2.3 {miscellaneous: lines wrap but are still too long} {textfonts} {
38093830 .t2.t insert end 123
38103831 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
38113832 .t2.t window create 1.1 -window .t2.t.f
3812 update
3833 updateText
38133834 .t2.t xview scroll 7 pixels
3814 update
3835 updateText
38153836 list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
38163837 } [list [list [expr {7.0/300}] [expr {(20.0*$fixedWidth + 7)/300}]] 300x50+[expr {$twbw + $twht + 1 - 7}]+[expr {$twbw + $twht + $fixedHeight + 1}] [list [expr {$twbw + $twht + $fixedWidth + 1 - 7}] [expr {$twbw + $twht + $fixedHeight + 50 + 1}] $fixedWidth $fixedHeight]]
38173838 test textDisp-29.2.4 {miscellaneous: lines wrap but are still too long} {textfonts} {
38263847 .t2.t insert end 123
38273848 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
38283849 .t2.t window create 1.1 -window .t2.t.f
3829 update
3850 updateText
38303851 .t2.t xview scroll 17 pixels
3831 update
3852 updateText
38323853 list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
38333854 } [list [list [expr {17.0/300}] [expr {(20.0*$fixedWidth + 17)/300}]] 300x50+[expr {$twbw + $twht + 1 - 17}]+[expr {$twbw + $twht + $fixedHeight + 1}] {}]
38343855 test textDisp-29.2.5 {miscellaneous: can show last character} {
38453866 grid columnconfigure .t2 0 -weight 1
38463867 grid rowconfigure .t2 0 -weight 1
38473868 grid rowconfigure .t2 1 -weight 0
3848 update ; update
3869 updateText
38493870 set xv [.t2.t xview]
38503871 set xd [expr {[lindex $xv 1] - [lindex $xv 0]}]
38513872 .t2.t xview moveto [expr {1.0-$xd}]
38713892 .t2.t insert end 123
38723893 frame .t2.t.f -width 300 -height 50 -bd 2 -relief raised
38733894 .t2.t window create 1.1 -window .t2.t.f
3874 update
3895 updateText
38753896 .t2.t xview scroll 200 units
3876 update
3897 updateText
38773898 list [.t2.t xview] [winfo geom .t2.t.f] [.t2.t bbox 1.3]
38783899 } [list [list [expr {16.0/30}] 1.0] 300x50+-155+[expr {$fixedDiff + 18}] {}]
38793900 test textDisp-30.1 {elidden text joining multiple logical lines} {
38933914 catch {destroy .t2}
38943915
38953916 .t configure -height 1
3896 update
3917 updateText
38973918
38983919 test textDisp-31.1 {line embedded window height update} {
38993920 set res {}
39113932 test textDisp-31.2 {line update index shifting} {
39123933 set res {}
39133934 .t.f configure -height 100
3914 update
3935 updateText
39153936 lappend res [.t count -update -ypixels 1.0 end]
39163937 .t.f configure -height 10
39173938 .t insert 1.0 "abc\n"
39333954 # have been performed.
39343955 set res {}
39353956 .t.f configure -height 100
3936 update
3957 updateText
39373958 lappend res [.t count -update -ypixels 1.0 end]
39383959 .t.f configure -height 10
39393960 .t insert 1.0 "abc\n"
39543975 image create photo textest -height 100 -width 10
39553976 .t delete 3.0
39563977 .t image create 3.0 -image textest
3957 update
3978 updateText
39583979 lappend res [.t count -update -ypixels 1.0 end]
39593980 textest configure -height 10
39603981 lappend res [.t count -ypixels 1.0 end]
39653986 test textDisp-31.5 {line update index shifting} {
39663987 set res {}
39673988 textest configure -height 100
3968 update ; after 1000 ; update
3989 updateText
39693990 lappend res [.t count -update -ypixels 1.0 end]
39703991 textest configure -height 10
39713992 .t insert 1.0 "abc\n"
39874008 # have been performed.
39884009 set res {}
39894010 textest configure -height 100
3990 update ; after 1000 ; update
39914011 lappend res [.t count -update -ypixels 1.0 end]
39924012 textest configure -height 10
39934013 .t insert 1.0 "abc\n"
40304050 .tt insert 0.0 HELLO
40314051 .tt tag configure HIDE -elide 1
40324052 .tt tag add HIDE 0.0 end
4033 update ; update ; update ; update
4053 updateText
40344054 destroy .tt
40354055 } {}
40364056 test textDisp-32.1 {everything elided} {
40374057 # Must not crash
40384058 pack [text .tt]
4039 update
4059 updateText
40404060 .tt insert 0.0 HELLO
4041 update
4061 updateText
40424062 .tt tag configure HIDE -elide 1
4043 update
4063 updateText
40444064 .tt tag add HIDE 0.0 end
4045 update ; update ; update ; update
4065 updateText
40464066 destroy .tt
40474067 } {}
40484068 test textDisp-32.2 {elide and tags} {
40534073 {testtag1 testtag3} \
40544074 {[this bit here uses tags 2 and 3]} \
40554075 {testtag2 testtag3}
4056 update
4076 updateText
40574077 # indent left margin of tag 1 by 20 pixels
40584078 # text should be indented
4059 .tt tag configure testtag1 -lmargin1 20 ; update
4079 .tt tag configure testtag1 -lmargin1 20
4080 updateText
40604081 #1
40614082 set res {}
40624083 lappend res [list [.tt index "1.0 + 0 displaychars"] \
40644085 [lindex [.tt bbox "1.0 + 0 displaychars"] 0]]
40654086 # hide tag 1, remaining text should not be indented, since
40664087 # the indented tag and character is hidden.
4067 .tt tag configure testtag1 -elide 1 ; update
4088 .tt tag configure testtag1 -elide 1
4089 updateText
40684090 #2
40694091 lappend res [list [.tt index "1.0 + 0 displaychars"] \
40704092 [lindex [.tt bbox 1.0] 0] \
40744096 .tt tag configure testtag1 -elide 0
40754097 # indent left margin of tag 2 by 20 pixels
40764098 # text should not be indented, since tag1 has lmargin1 of 0.
4077 .tt tag configure testtag2 -lmargin1 20 ; update
4099 .tt tag configure testtag2 -lmargin1 20
4100 updateText
40784101 #3
40794102 lappend res [list [.tt index "1.0 + 0 displaychars"] \
40804103 [lindex [.tt bbox 1.0] 0] \
40824105 # hide tag 1, remaining text should now be indented, but
40834106 # the bbox of 1.0 should have zero width and zero indent,
40844107 # since it is elided at that position.
4085 .tt tag configure testtag1 -elide 1 ; update
4108 .tt tag configure testtag1 -elide 1
4109 updateText
40864110 #4
40874111 lappend res [list [.tt index "1.0 + 0 displaychars"] \
40884112 [lindex [.tt bbox 1.0] 0] \
40944118 # text should be indented, since this tag takes
40954119 # precedence over testtag1, and is applied to the
40964120 # start of the text.
4097 .tt tag configure testtag3 -lmargin1 20 ; update
4121 .tt tag configure testtag3 -lmargin1 20
4122 updateText
40984123 #5
40994124 lappend res [list [.tt index "1.0 + 0 displaychars"] \
41004125 [lindex [.tt bbox 1.0] 0] \
41024127 # hide tag 1, remaining text should still be indented,
41034128 # since it still has testtag3 on it. Again the
41044129 # bbox of 1.0 should have 0.
4105 .tt tag configure testtag1 -elide 1 ; update
4130 .tt tag configure testtag1 -elide 1
4131 updateText
41064132 #6
41074133 lappend res [list [.tt index "1.0 + 0 displaychars"] \
41084134 [lindex [.tt bbox 1.0] 0] \
41404166 .tt insert end ":)" emoticon
41414167 .tt image create end -image $img
41424168 pack .tt
4143 update; update; update
4169 updateText
41444170 } -cleanup {
41454171 image delete $img
41464172 destroy .tt
41494175 test textDisp-33.0 {one line longer than fits in the widget} {
41504176 pack [text .tt -wrap char]
41514177 .tt insert 1.0 [string repeat "more wrap + " 300]
4152 update ; update ; update
4178 updateText
41534179 .tt see 1.0
41544180 lindex [.tt yview] 0
41554181 } {0.0}
41574183 destroy .tt
41584184 pack [text .tt -wrap char]
41594185 .tt insert 1.0 [string repeat "more wrap + " 300]
4160 update ; update ; update
4186 updateText
41614187 .tt yview "1.0 +1 displaylines"
41624188 if {[lindex [.tt yview] 0] > 0.1} {
41634189 set result "window should be scrolled to the top"
41814207 .tt debug 1
41824208 set tk_textHeightCalc ""
41834209 .tt insert 1.0 [string repeat "more wrap + " 300]
4184 update ; .tt count -update -ypixels 1.0 end ; update
4210 updateText
4211 .tt count -update -ypixels 1.0 end
4212 updateText
41854213 # Each line should have been recalculated just once
41864214 .tt debug 0
41874215 expr {[llength $tk_textHeightCalc] == [.tt count -displaylines 1.0 end]}
41924220 .tt debug 1
41934221 set tk_textHeightCalc ""
41944222 .tt insert 1.0 [string repeat "more wrap + " 300]
4195 update ; update ; update
4223 updateText
41964224 set idx [.tt index "1.0 + 1 displaylines"]
41974225 .tt yview $idx
41984226 if {[lindex [.tt yview] 0] > 0.1} {
42144242 .tt tag configure bi -font bi
42154243 .tt tag configure no -font no
42164244 .tt insert end abcd no efgh bi ijkl\n no
4217 update
4245 updateText
42184246 set bb {}
42194247 for {set i 0} {$i < 12} {incr i 4} {
42204248 lappend bb [lindex [.tt bbox 1.$i] 0]
42414269 .t1 debug 1
42424270 set ge [winfo geometry .]
42434271 scan $ge "%dx%d+%d+%d" width height left top
4244 update
4272 updateText
42454273 .t1 sync
42464274 set negative 0
42474275 bind .t1 <<WidgetViewSync>> { if {%d < 0} {set negative 1} }
42514279 # Thus we use this way to check for regression regarding bug 2677890,
42524280 # i.e. to check that the fix for this bug really is still in.
42534281 wm geometry . "[expr {$width * 2}]x$height+$left+$top"
4254 update
4282 updateText
42554283 .t1 sync
42564284 set negative
42574285 } -cleanup {
802802 .t index "2.40 -1displaylines"
803803 } {2.20}
804804
805 test textIndex-19.12.1 {Display lines} {
806 .t index "2.50 - 100 displaylines"
807 } {1.0}
808
809 test textIndex-19.12.2 {Display lines} {
810 .t compare [.t index "2.50 + 100 displaylines"] == "end - 1 c"
811 } {1}
812
805813 test textIndex-19.13 {Display lines} {
806814 destroy {*}[pack slaves .]
807815 text .txt -height 1 -wrap word -yscroll ".sbar set" -width 400
14761476
14771477
14781478 set c [.t bbox 2.1]
1479 set x1 [expr [lindex $c 0] + [lindex $c 2]/2]
1480 set y1 [expr [lindex $c 1] + [lindex $c 3]/2]
1479 set x1 [expr {[lindex $c 0] + [lindex $c 2]/2}]
1480 set y1 [expr {[lindex $c 1] + [lindex $c 3]/2}]
14811481 set c [.t bbox 3.2]
1482 set x2 [expr [lindex $c 0] + [lindex $c 2]/2]
1483 set y2 [expr [lindex $c 1] + [lindex $c 3]/2]
1482 set x2 [expr {[lindex $c 0] + [lindex $c 2]/2}]
1483 set y2 [expr {[lindex $c 1] + [lindex $c 3]/2}]
14841484 set c [.t bbox 4.3]
1485 set x3 [expr [lindex $c 0] + [lindex $c 2]/2]
1486 set y3 [expr [lindex $c 1] + [lindex $c 3]/2]
1485 set x3 [expr {[lindex $c 0] + [lindex $c 2]/2}]
1486 set y3 [expr {[lindex $c 1] + [lindex $c 3]/2}]
14871487
14881488 test textTag-15.1 {TkTextBindProc} -constraints haveCourier12 -setup {
14891489 .t tag delete x y
3737 wm minsize . 1 1
3838 wm positionfrom . user
3939 wm deiconify .
40
41 # This update is needed on MacOS to make sure that the window is mapped
42 # when the tests begin.
43
44 update
4045
4146 set bw [.t cget -borderwidth]
4247 set px [.t cget -padx]
946951 destroy .f
947952 place forget .t
948953 pack .t
954 # Make sure the Text is mapped before we start
955 update
949956 } -body {
950957 .t insert 1.0 "Some sample text"
951958 pack forget .t
952959 place .t -x 30 -y 50
953960 frame .f -width 30 -height 20 -bg $color
954961 .t window create 1.12 -window .f
955 update
962 update ; after 100 ; update
956963 winfo geom .f
957964 } -cleanup {
958965 destroy .f
964971 destroy .t.f
965972 place forget .t
966973 pack .t
974 # Make sure the Text is mapped before we start
975 update
967976 } -body {
968977 .t insert 1.0 "Some sample text"
969978 pack forget .t
970979 place .t -x 30 -y 50
971980 frame .t.f -width 30 -height 20 -bg $color
972981 .t window create 1.12 -window .t.f
973 update
982 update ; after 100 ; update
974983 winfo geom .t.f
975984 } -cleanup {
976985 destroy .t.f
983992 destroy .f
984993 place forget .t
985994 pack .t
995 # Make sure the Text is mapped before we start
996 update
986997 } -body {
987998 .t insert 1.0 "Some sample text"
988999 frame .f -width 30 -height 20 -bg $color
4242 .cb current
4343 } -result -1
4444
45 test combobox-2.5 "current -- set to end index" -body {
46 .cb configure -values [list a b c d e thelastone]
47 .cb current end
48 .cb get
49 } -result thelastone
50
51 test combobox-2.6 "current -- set to unknown index" -body {
52 .cb configure -values [list a b c d e]
53 .cb current notanindex
54 } -returnCodes error -result {Incorrect index notanindex}
55
4556 test combobox-2.end "Cleanup" -body { destroy .cb }
4657
4758 test combobox-3 "Read postoffset value dynamically from current style" -body {
7676 test entry-2.2 "Initial scroll position" -body {
7777 ttk::entry .e -font fixed -width 5 -xscrollcommand scroll
7878 .e insert end "0123456789"
79 pack .e; update
79 pack .e;
80 set timeout [after 500 {set $scrollInfo "timeout"}]
81 vwait scrollInfo
8082 set scrollInfo
81 } -result {0.0 0.5} -cleanup { destroy .e }
83 } -cleanup {
84 destroy .e
85 after cancel $timeout
86 } -result {0.0 0.5}
8287 # NOTE: result can vary depending on font.
8388
8489 # Bounding box / scrolling tests.
102107 test entry-3.2 "xview" -body {
103108 .e delete 0 end;
104109 .e insert end [string repeat "0" 40]
105 update idletasks
106110 set result [.e xview]
107111 } -result {0.0 0.5}
112
113 test entry-3.3 "xview" -body {
114 .e delete 0 end;
115 .e insert end abcdefghijklmnopqrstuvwxyz
116 .e xview end
117 set result [.e index @0]
118 } -result {7}
119
120 test entry-3.4 "xview" -body {
121 .e delete 0 end;
122 .e insert end abcdefghijklmnopqrstuvwxyz
123 .e xview moveto 1.0
124 set result [.e index @0]
125 } -result {7}
126
127 test entry-3.5 "xview" -body {
128 .e delete 0 end;
129 .e insert end abcdefghijklmnopqrstuvwxyz
130 .e xview scroll 5 units
131 set result [.e index @0]
132 } -result {5}
133
134 test entry-3.6 "xview" -body {
135 .e delete 0 end;
136 .e insert end [string repeat abcdefghijklmnopqrstuvwxyz 5]
137 .e xview scroll 2 pages
138 set result [.e index @0]
139 } -result {40}
108140
109141 test entry-3.last "Series 3 cleanup" -body {
110142 destroy .e
6868 .nb tab .nb.foo
6969 } -result [list \
7070 -padding 0 -sticky nsew \
71 -state normal -text "Changed Foo" -image "" -compound none -underline -1]
71 -state normal -text "Changed Foo" -image "" -compound {} -underline -1]
7272
7373 test notebook-4.1 "Test .nb index end" -body {
7474 .nb index end
33
44 testConstraint coreScrollbar [expr {[tk windowingsystem] eq "aqua"}]
55
6 test scrollbar-swapout-1 "Use core scrollbars on OSX..." -constraints {
7 coreScrollbar
6 # Before 2019 the code in library/ttk/scrollbar.tcl would replace the
7 # constructor of ttk::scrollbar with the constructor of tk::scrollbar
8 # unless the -class or -style options were specified..
9 # Now there is an implementation of ttk::scrollbar for macOS. The
10 # tests are left in place, though, except that scrollbar-swapout-1
11 # test was changed to expect the class to be TScrollbar instead of
12 # Scrollbar.
13
14 test scrollbar-swapout-1 "Don't use core scrollbars on OSX..." \
15 -constraints {
16 coreScrollbar
817 } -body {
918 ttk::scrollbar .sb -command "yadda"
1019 list [winfo class .sb] [.sb cget -command]
11 } -result [list Scrollbar yadda] -cleanup {
20 } -result [list TScrollbar yadda] -cleanup {
1221 destroy .sb
1322 }
1423
15 test scrollbar-swapout-2 "... unless -style is specified ..." -constraints {
24 test scrollbar-swapout-2 "... regardless of whether -style ..." \
25 -constraints {
1626 coreScrollbar
1727 } -body {
1828 ttk::style layout Vertical.Custom.TScrollbar \
2333 destroy .sb
2434 }
2535
26 test scrollbar-swapout-3 "... or -class." -constraints {
36 test scrollbar-swapout-3 "... or -class is specified." -constraints {
2737 coreScrollbar
2838 } -body {
2939 ttk::scrollbar .sb -command "yadda" -class Custom.TScrollbar
4353
4454 test scrollbar-1.2 "Set orientation" -body {
4555 .tsb configure -orient vertical
46 set w [winfo reqwidth .tsb] ; set h [winfo reqheight .tsb]
56 pack .tsb -side right -anchor e -expand 1 -fill y
57 wm geometry . 200x200
58 update
59 set w [winfo width .tsb] ; set h [winfo height .tsb]
4760 expr {$h > $w}
4861 } -result 1
4962
5063 test scrollbar-1.3 "Change orientation" -body {
5164 .tsb configure -orient horizontal
52 set w [winfo reqwidth .tsb] ; set h [winfo reqheight .tsb]
65 pack .tsb -side bottom -anchor s -expand 1 -fill x
66 wm geometry . 200x200
67 update
68 set w [winfo width .tsb] ; set h [winfo height .tsb]
5369 expr {$h < $w}
5470 } -result 1
5571
458458 .tv selection badop foo
459459 } -returnCodes 1 -match glob -result {bad selection operation "badop": must be *}
460460
461 test treeview-8.6 "Selection - <<TreeviewSelect>> on selection add" -body {
462 .tv selection set {}
463 bind .tv <<TreeviewSelect>> {set res 1}
464 set res 0
465 .tv selection add newnode.n1
466 update
467 set res
468 } -result {1}
469
470 test treeview-8.7 "<<TreeviewSelect>> on selected item deletion" -body {
471 .tv selection set {}
472 .tv insert "" end -id selectedDoomed -text DeadItem
473 .tv insert "" end -id doomed -text AlsoDead
474 .tv selection add selectedDoomed
475 update
476 bind .tv <<TreeviewSelect>> {lappend res 1}
477 set res 0
478 .tv delete doomed
479 update
480 set res [expr {$res == 0}]
481 .tv delete selectedDoomed
482 update
483 set res
484 } -result {1 1}
485
461486 ### NEED: more tests for see/yview/scrolling
462487
463488 proc scrollcallback {args} {
469494 update
470495 set ::scrolldata
471496 } -result [list 0.0 1.0]
497
498 test treeview-9.1 "scrolling" -setup {
499 pack [ttk::treeview .tree -show tree] -fill y
500 for {set i 1} {$i < 100} {incr i} {
501 .tree insert {} end -text $i
502 }
503 } -body {
504 .tree yview scroll 5 units
505 .tree identify item 2 2
506 } -cleanup {
507 destroy .tree
508 } -result {I006}
472509
473510 ### identify tests:
474511 #
635672 destroy .tv
636673 } -result [list]
637674
675 test treeview-368fa4561e "indicators cannot be clicked on leafs" -setup {
676 pack [ttk::treeview .tv]
677 .tv insert {} end -id foo -text "<-- (1) Click the blank space to my left"
678 update
679 } -body {
680 foreach {x y w h} [.tv bbox foo #0] {}
681 set res [.tv item foo -open]
682 # using $h even for x computation is intentional here in order to simulate
683 # a mouse click on the (invisible since we're on a leaf) indicator
684 event generate .tv <ButtonPress-1> \
685 -x [expr {$x + $h / 2}] \
686 -y [expr {$y + $h / 2}]
687 lappend res [.tv item foo -open]
688 .tv insert foo end -text "sub"
689 lappend res [.tv item foo -open]
690 } -cleanup {
691 destroy .tv
692 } -result {0 0 0}
693
694 test treeview-ce470f20fd-1 "dragging further than the right edge of the treeview is allowed" -setup {
695 pack [ttk::treeview .tv]
696 .tv heading #0 -text "Drag my right edge -->"
697 update
698 } -body {
699 set res [.tv column #0 -width]
700 .tv drag #0 400
701 lappend res [expr {[.tv column #0 -width] > $res}]
702 } -cleanup {
703 destroy .tv
704 } -result {200 1}
705
706 proc nostretch {tv} {
707 foreach col [$tv cget -columns] {
708 $tv column $col -stretch 0
709 }
710 $tv column #0 -stretch 0
711 update idletasks ; # redisplay $tv
712 }
713
714 test treeview-ce470f20fd-2 "changing -stretch resizes columns" -setup {
715 pack [ttk::treeview .tv -columns {bar colA colB colC foo}]
716 foreach col [.tv cget -columns] {
717 .tv heading $col -text $col
718 }
719 nostretch .tv
720 .tv column colA -width 50 ; .tv column colB -width 50 ; # slack created
721 update idletasks ; # redisplay treeview
722 } -body {
723 # when no column is stretchable and one of them becomes stretchable
724 # the stretchable column takes the slack and the widget is redisplayed
725 # automatically at idle time
726 set res [.tv column colA -width]
727 .tv column colA -stretch 1
728 update idletasks ; # no slack anymore, widget redisplayed
729 lappend res [expr {[.tv column colA -width] > $res}]
730 } -cleanup {
731 destroy .tv
732 } -result {50 1}
733
734 test treeview-ce470f20fd-3 "changing -stretch resizes columns" -setup {
735 pack [ttk::treeview .tv -columns {bar colA colB colC foo}]
736 foreach col [.tv cget -columns] {
737 .tv heading $col -text $col
738 }
739 .tv configure -displaycolumns {colB colA colC}
740 nostretch .tv
741 .tv column colA -width 50 ; .tv column colB -width 50 ; # slack created
742 update idletasks ; # redisplay treeview
743 } -body {
744 # only some columns are displayed (and in a different order than declared
745 # in -columns), a displayed column becomes stretchable --> the stretchable
746 # column expands
747 set res [.tv column colA -width]
748 .tv column colA -stretch 1
749 update idletasks ; # no slack anymore, widget redisplayed
750 lappend res [expr {[.tv column colA -width] > $res}]
751 } -cleanup {
752 destroy .tv
753 } -result {50 1}
754
755 test treeview-ce470f20fd-4 "changing -stretch resizes columns" -setup {
756 pack [ttk::treeview .tv -columns {bar colA colB colC foo}]
757 foreach col [.tv cget -columns] {
758 .tv heading $col -text $col
759 }
760 .tv configure -displaycolumns {colB colA colC}
761 nostretch .tv
762 .tv column colA -width 50 ; .tv column bar -width 60 ; # slack created
763 update idletasks ; # redisplay treeview
764 } -body {
765 # only some columns are displayed (and in a different order than declared
766 # in -columns), a non-displayed column becomes stretchable --> nothing
767 # happens
768 set origTreeWidth [winfo width .tv]
769 set res [list [.tv column bar -width] [.tv column colA -width]]
770 .tv column bar -stretch 1
771 update idletasks ; # no change, widget redisplayed
772 lappend res [.tv column bar -width] [.tv column colA -width]
773 # this column becomes visible --> widget resizes
774 .tv configure -displaycolumns {bar colC colA colB}
775 update idletasks ; # no slack anymore because the widget resizes (shrinks)
776 lappend res [.tv column bar -width] [.tv column colA -width] \
777 [expr {[winfo width .tv] < $origTreeWidth}]
778 } -cleanup {
779 destroy .tv
780 } -result {60 50 60 50 60 50 1}
781
638782 tcltest::cleanupTests
205205 destroy .b
206206 set ttk28 {}
207207 pack [ttk::button .b -command {set ::ttk28 failed}]
208 update
208209 } -body {
209210 bind .b <ButtonPress-1> {after 0 {.b configure -state disabled}}
210211 after 1 {event generate .b <ButtonPress-1>}
268269 test ttk-4.0 "Setup" -body {
269270 catch { destroy .t }
270271 pack [ttk::label .t -text "Button 1"]
271 testConstraint fontOption [expr ![catch { set prevFont [.t cget -font] }]]
272 testConstraint fontOption [expr {![catch { set prevFont [.t cget -font] }]}]
272273 ok
273274 }
274275
3434 error "trace aborted"
3535 }
3636
37
37 if {[tk windowingsystem] eq "aqua"} {
38 set smallIndicator 20
39 set bigIndicator 20
40 set defaultBorder 10
41 } else {
42 set smallIndicator 27
43 set bigIndicator 40
44 set defaultBorder 20
45 }
3846 test unixbutton-1.1 {TkpComputeButtonGeometry procedure} -constraints {
3947 unix testImageType
4048 } -setup {
5664 } -cleanup {
5765 deleteWindows
5866 image delete image1
59 } -result {68 48 74 54 112 52 112 52}
67 } -result [list 68 48 \
68 74 54 \
69 [expr {72 + $bigIndicator}] 52 \
70 [expr {72 + $bigIndicator}] 52]
6071 test unixbutton-1.2 {TkpComputeButtonGeometry procedure} -constraints {
6172 unix
6273 } -setup {
7485 [winfo reqwidth .b4] [winfo reqheight .b4]
7586 } -cleanup {
7687 deleteWindows
77 } -result {23 33 29 39 54 37 54 37}
88 } -result [list 23 33 \
89 29 39 \
90 [expr {27 + $smallIndicator}] 37 \
91 [expr {27 + $smallIndicator}] 37]
7892 test unixbutton-1.3 {TkpComputeButtonGeometry procedure} -constraints {
7993 unix
8094 } -setup {
185199 list [winfo reqwidth .b2] [winfo reqheight .b2]
186200 } -cleanup {
187201 deleteWindows
188 } -result {37 47}
202 } -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]
189203 test unixbutton-1.10 {TkpComputeButtonGeometry procedure} -constraints {
190204 unix
191205 } -setup {
195209 list [winfo reqwidth .b2] [winfo reqheight .b2]
196210 } -cleanup {
197211 deleteWindows
198 } -result {37 47}
212 } -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]
199213 test unixbutton-1.11 {TkpComputeButtonGeometry procedure} -constraints {
200214 unix
201215 } -setup {
0 # This file is a Tcl script to test out the procedures in the file
0 # This file is a Tcl script to test out the procedures in the file
11 # tkUnixEmbed.c. It is organized in the standard fashion for Tcl
22 # tests.
33 #
99 eval tcltest::configure $argv
1010 tcltest::loadTestedCommands
1111 namespace import -force tcltest::test
12
13 namespace eval ::_test_tmp {}
14
15 # ------------------------------------------------------------------------------
16 # Proc ::_test_tmp::testInterp
17 # ------------------------------------------------------------------------------
18 # Command that creates an unsafe child interpreter and tries to load Tk.
19 # This code is borrowed from safePrimarySelection.test
20 # This is necessary for loading Tktest if the tests are done in the build
21 # directory without installing Tk. In that case the usual auto_path loading
22 # mechanism cannot work because the tk binary is not where pkgIndex.tcl says
23 # it is.
24 # ------------------------------------------------------------------------------
25
26 namespace eval ::_test_tmp {
27 variable TkLoadCmd
28 }
29
30 foreach pkg [info loaded] {
31 if {[lindex $pkg 1] eq "Tk"} {
32 set ::_test_tmp::TkLoadCmd [list load {*}$pkg]
33 break
34 }
35 }
36
37 proc ::_test_tmp::testInterp {name} {
38 variable TkLoadCmd
39 interp create $name
40 $name eval [list set argv [list -name $name]]
41 catch {{*}$TkLoadCmd $name}
42 }
1243
1344 setupbg
1445 dobg {wm withdraw .}
5384 && ([lindex $vals 2]/256 == $blue)
5485 }
5586
87 testConstraint pressbutton [llength [info commands pressbutton]]
88
5689 test unixEmbed-1.1 {TkpUseWindow procedure, bad window identifier} -constraints {
57 unix
90 unix
5891 } -setup {
5992 deleteWindows
6093 } -body {
6194 toplevel .t -use xyz
6295 } -returnCodes error -result {expected integer but got "xyz"}
6396 test unixEmbed-1.2 {TkpUseWindow procedure, bad window identifier} -constraints {
64 unix
97 unix
6598 } -setup {
6699 deleteWindows
67100 } -body {
96129 } -result {1}
97130
98131 test unixEmbed-1.5 {TkpUseWindow procedure, creating Container records} -constraints {
99 unix testembed
132 unix testembed notAqua
100133 } -setup {
101134 deleteWindows
102135 } -body {
112145 } -cleanup {
113146 deleteWindows
114147 } -result {{{XXX {} {} .t}} 0}
115 test unixEmbed-1.6 {TkpUseWindow procedure, creating Container records} -constraints {
116 unix testembed
117 } -setup {
118 deleteWindows
148 test unixEmbed-1.5a {TkpUseWindow procedure, creating Container records} -constraints {
149 unix testembed
150 } -setup {
151 deleteWindows
152 catch {interp delete slave}
153 ::_test_tmp::testInterp slave
154 load {} Tktest slave
119155 } -body {
120156 frame .f1 -container 1 -width 200 -height 50
121157 frame .f2 -container 1 -width 200 -height 50
122158 pack .f1 .f2
159 slave alias w winfo id .f1
160 slave eval {
161 destroy [winfo child .]
162 toplevel .t -use [w]
163 list [testembed] [expr {[lindex [lindex [testembed all] 0] 0] - [w]}]
164 }
165 } -cleanup {
166 interp delete slave
167 deleteWindows
168 } -result {{{XXX {} {} .t}} 0}
169 test unixEmbed-1.6 {TkpUseWindow procedure, creating Container records} -constraints {
170 unix testembed notAqua
171 } -setup {
172 deleteWindows
173 } -body {
174 frame .f1 -container 1 -width 200 -height 50
175 frame .f2 -container 1 -width 200 -height 50
176 pack .f1 .f2
123177 dobg "set w1 [winfo id .f1]"
124178 dobg "set w2 [winfo id .f2]"
125179 dobg {
130184 }
131185 } -cleanup {
132186 deleteWindows
187 } -result {{XXX {} {} .t2} {XXX {} {} .t1}}
188 test unixEmbed-1.6a {TkpUseWindow procedure, creating Container records} -constraints {
189 unix testembed
190 } -setup {
191 deleteWindows
192 catch {interp delete slave}
193 ::_test_tmp::testInterp slave
194 load {} Tktest slave
195 } -body {
196 frame .f1 -container 1 -width 200 -height 50
197 frame .f2 -container 1 -width 200 -height 50
198 pack .f1 .f2
199 slave alias w1 winfo id .f1
200 slave alias w2 winfo id .f2
201 slave eval {
202 destroy [winfo child .]
203 toplevel .t1 -use [w1]
204 toplevel .t2 -use [w2]
205 testembed
206 }
207 } -cleanup {
208 interp delete slave
209 deleteWindows
133210 } -result {{XXX {} {} .t2} {XXX {} {} .t1}}
134211 test unixEmbed-1.7 {TkpUseWindow procedure, container and embedded in same app} -constraints {
135212 unix testembed
151228
152229
153230 test unixEmbed-2.1 {EmbeddedEventProc procedure} -constraints {
154 unix testembed
231 unix testembed notAqua
155232 } -setup {
156233 deleteWindows
157234 } -body {
170247 }
171248 } -cleanup {
172249 deleteWindows
250 } -result {}
251 test unixEmbed-2.1a {EmbeddedEventProc procedure} -constraints {
252 unix testembed
253 } -setup {
254 deleteWindows
255 catch {interp delete slave}
256 ::_test_tmp::testInterp slave
257 load {} Tktest slave
258 } -body {
259 frame .f1 -container 1 -width 200 -height 50
260 pack .f1
261 slave alias w1 winfo id .f1
262 slave eval {
263 destroy [winfo child .]
264 toplevel .t1 -use [w1]
265 testembed
266 }
267 destroy .f1
268 update
269 slave eval {
270 testembed
271 }
272 } -cleanup {
273 deleteWindows
173274 } -result {}
174275 test unixEmbed-2.2 {EmbeddedEventProc procedure} -constraints {
175 unix testembed
276 unix testembed notAqua
176277 } -setup {
177278 deleteWindows
178279 } -body {
189290 } -cleanup {
190291 deleteWindows
191292 } -result {}
293 test unixEmbed-2.2a {EmbeddedEventProc procedure} -constraints {
294 unix testembed
295 } -setup {
296 deleteWindows
297 catch {interp delete slave}
298 ::_test_tmp::testInterp slave
299 load {} Tktest slave
300 } -body {
301 frame .f1 -container 1 -width 200 -height 50
302 pack .f1
303 slave alias w1 winfo id .f1
304 slave eval {
305 destroy [winfo child .]
306 toplevel .t1 -use [w1]
307 testembed
308 destroy .t1
309 testembed
310 }
311 } -cleanup {
312 interp delete slave
313 deleteWindows
314 } -result {}
192315 test unixEmbed-2.3 {EmbeddedEventProc procedure} -constraints {
193 unix testembed
316 unix testembed notAqua
194317 } -setup {
195318 deleteWindows
196319 } -body {
206329 } -setup {
207330 deleteWindows
208331 } -body {
209 frame .f1 -container 1 -width 200 -height 50
210 pack .f1
332 pack [frame .f1 -container 1 -width 200 -height 50]
211333 toplevel .t1 -use [winfo id .f1]
334 set x [testembed]
212335 update
213336 destroy .t1
214 set x [testembed]
215 update
216 list $x [testembed]
217 } -cleanup {
218 deleteWindows
219 } -result {{{XXX .f1 {} {}}} {}}
337 update
338 list $x [winfo exists .t1] [winfo exists .f1] [testembed]
339 } -cleanup {
340 deleteWindows
341 } -result "{{XXX .f1 {} .t1}} 0 0 {}"
220342
221343
222344 test unixEmbed-3.1 {ContainerEventProc procedure, detect creation} -constraints {
235357 } -cleanup {
236358 deleteWindows
237359 } -result {{{XXX .f1 {} {}}} {{XXX .f1 XXX {}}}}
360 test unixEmbed-3.1a {ContainerEventProc procedure, detect creation} -constraints {
361 unix testembed
362 } -setup {
363 catch {interp delete slave}
364 ::_test_tmp::testInterp slave
365 load {} Tktest slave
366 } -body {
367 frame .f1 -container 1 -width 200 -height 50
368 pack .f1
369 slave alias w1 winfo id .f1
370 set x [testembed]
371 slave eval {
372 destroy [winfo child .]
373 toplevel .t1 -use [w1]
374 wm withdraw .t1
375 }
376 list $x [testembed]
377 } -cleanup {
378 interp delete slave
379 deleteWindows
380 } -result {{{XXX .f1 {} {}}} {{XXX .f1 {} {}}}}
238381 test unixEmbed-3.2 {ContainerEventProc procedure, set size on creation} -constraints {
239 unix
240 } -setup {
241 deleteWindows
382 unix
383 } -setup {
384 deleteWindows
385 update
242386 } -body {
243387 toplevel .t1 -container 1
244388 wm geometry .t1 +0+0
249393 deleteWindows
250394 } -result {200x200+0+0}
251395 test unixEmbed-3.3 {ContainerEventProc procedure, disallow position changes} -constraints {
252 unix
396 unix notAqua
253397 } -setup {
254398 deleteWindows
255399 } -body {
269413 } -cleanup {
270414 deleteWindows
271415 } -result {200x200+0+0}
416 test unixEmbed-3.3a {ContainerEventProc procedure, disallow position changes} -constraints {
417 unix
418 } -setup {
419 deleteWindows
420 catch {interp delete slave}
421 ::_test_tmp::testInterp slave
422 load {} Tktest slave
423 } -body {
424 frame .f1 -container 1 -width 200 -height 50
425 pack .f1
426 slave alias w1 winfo id .f1
427 slave eval {
428 destroy [winfo child .]
429 toplevel .t1 -use [w1] -bd 2 -relief raised
430 update
431 wm geometry .t1 +30+40
432 update
433 wm geometry .t1
434 }
435 } -cleanup {
436 interp delete slave
437 deleteWindows
438 } -result {200x200+0+0}
272439 test unixEmbed-3.4 {ContainerEventProc procedure, disallow position changes} -constraints {
273 unix
440 unix notAqua
274441 } -setup {
275442 deleteWindows
276443 } -body {
290457 } -cleanup {
291458 deleteWindows
292459 } -result {300x100+0+0}
460 test unixEmbed-3.4a {ContainerEventProc procedure, disallow position changes} -constraints {
461 unix
462 } -setup {
463 deleteWindows
464 catch {interp delete slave}
465 ::_test_tmp::testInterp slave
466 load {} Tktest slave
467 } -body {
468 frame .f1 -container 1 -width 200 -height 50
469 pack .f1
470 slave alias w1 winfo id .f1
471 slave eval {
472 destroy [winfo child .]
473 toplevel .t1 -use [w1]
474 update
475 wm geometry .t1 300x100+30+40
476 update
477 wm geometry .t1
478 }
479 } -cleanup {
480 interp delete slave
481 deleteWindows
482 } -result {300x100+0+0}
293483 test unixEmbed-3.5 {ContainerEventProc procedure, geometry requests} -constraints {
294 unix
484 unix notAqua
295485 } -setup {
296486 deleteWindows
297487 } -body {
310500 list [winfo width .f1] [winfo height .f1] [dobg {wm geometry .t1}]
311501 } -cleanup {
312502 deleteWindows
503 } -result {300 80 300x80+0+0}
504 test unixEmbed-3.5a {ContainerEventProc procedure, geometry requests} -constraints {
505 unix
506 } -setup {
507 deleteWindows
508 catch {interp delete slave}
509 ::_test_tmp::testInterp slave
510 load {} Tktest slave
511 } -body {
512 frame .f1 -container 1 -width 200 -height 50
513 pack .f1
514 slave alias w1 winfo id .f1
515 slave eval {
516 destroy [winfo child .]
517 toplevel .t1 -use [w1]
518 .t1 configure -width 300 -height 80
519 update
520 }
521 list [winfo width .f1] [winfo height .f1] [slave eval {wm geometry .t1}]
522 } -cleanup {
523 interp delete slave
524 deleteWindows
313525 } -result {300 80 300x80+0+0}
314526 test unixEmbed-3.6 {ContainerEventProc procedure, map requests} -constraints {
315 unix
527 unix notAqua
316528 } -setup {
317529 deleteWindows
318530 } -body {
334546 } -cleanup {
335547 deleteWindows
336548 } -result {mapped}
549 test unixEmbed-3.6a {ContainerEventProc procedure, map requests} -constraints {
550 unix
551 } -setup {
552 deleteWindows
553 catch {interp delete slave}
554 ::_test_tmp::testInterp slave
555 load {} Tktest slave
556 } -body {
557 frame .f1 -container 1 -width 200 -height 50
558 pack .f1
559 slave alias w1 winfo id .f1
560 slave eval {
561 destroy [winfo child .]
562 toplevel .t1 -use [w1]
563 set x unmapped
564 bind .t1 <Map> {set x mapped}
565 update
566 after 100
567 update
568 set x
569 }
570 } -cleanup {
571 interp delete slave
572 deleteWindows
573 } -result {mapped}
337574 test unixEmbed-3.7 {ContainerEventProc procedure, destroy events} -constraints {
338 unix
575 unix notAqua
339576 } -setup {
340577 deleteWindows
341578 } -body {
357594 } -cleanup {
358595 deleteWindows
359596 } -result {dead 0}
360
597 test unixEmbed-3.7a {ContainerEventProc procedure, destroy events} -constraints {
598 unix
599 } -setup {
600 deleteWindows
601 catch {interp delete slave}
602 ::_test_tmp::testInterp slave
603 load {} Tktest slave
604 } -body {
605 frame .f1 -container 1 -width 200 -height 50
606 pack .f1
607 slave alias w1 winfo id .f1
608 bind .f1 <Destroy> {set x dead}
609 set x alive
610 slave eval {
611 destroy [winfo child .]
612 toplevel .t1 -use [w1]
613 update
614 destroy .t1
615 }
616 update
617 list $x [winfo exists .f1]
618 } -cleanup {
619 interp delete slave
620 deleteWindows
621 } -result {dead 0}
361622
362623 test unixEmbed-4.1 {EmbedStructureProc procedure, configure events} -constraints {
363 unix
624 unix notAqua
364625 } -setup {
365626 deleteWindows
366627 } -body {
381642 }
382643 } -cleanup {
383644 deleteWindows
645 } -result {180x100+0+0}
646 test unixEmbed-4.1a {EmbedStructureProc procedure, configure events} -constraints {
647 unix
648 } -setup {
649 deleteWindows
650 catch {interp delete slave}
651 ::_test_tmp::testInterp slave
652 load {} Tktest slave
653 } -body {
654 frame .f1 -container 1 -width 200 -height 50
655 pack .f1
656 slave alias w1 winfo id .f1
657 slave eval {
658 destroy [winfo child .]
659 toplevel .t1 -use [w1]
660 update
661 .t1 configure -width 180 -height 100
662 update
663 winfo geometry .t1
664 }
665 } -cleanup {
666 interp delete slave
667 deleteWindows
384668 } -result {180x100+0+0}
385669 test unixEmbed-4.2 {EmbedStructureProc procedure, destroy events} -constraints {
386 unix testembed
387 } -setup {
388 deleteWindows
389 } -body {
390 frame .f1 -container 1 -width 200 -height 50
391 pack .f1
392 dobg "set w1 [winfo id .f1]"
393 dobg {
394 eval destroy [winfo child .]
395 toplevel .t1 -use $w1
396 }
397 update
670 unix testembed notAqua
671 } -setup {
672 deleteWindows
673 } -body {
674 frame .f1 -container 1 -width 200 -height 50
675 pack .f1
676 dobg "set w1 [winfo id .f1]"
677 dobg {
678 eval destroy [winfo child .]
679 toplevel .t1 -use $w1
680 }
681 update
682 set x [testembed]
683 destroy .f1
684 update
685 list $x [testembed]
686 } -cleanup {
687 deleteWindows
688 } -result {{{XXX .f1 XXX {}}} {}}
689 test unixEmbed-4.2a {EmbedStructureProc procedure, destroy events} -constraints {
690 unix testembed
691 } -setup {
692 deleteWindows
693 catch {interp delete slave}
694 ::_test_tmp::testInterp slave
695 load {} Tktest slave
696 } -body {
697 frame .f1 -container 1 -width 200 -height 50
698 pack .f1
699 update
700 slave alias w1 winfo id .f1
701 slave eval {
702 destroy [winfo child .]
703 toplevel .t1 -use [w1]
704 }
398705 set x [testembed]
399706 destroy .f1
400707 list $x [testembed]
401708 } -cleanup {
402 deleteWindows
403 } -result {{{XXX .f1 XXX {}}} {}}
709 interp delete slave
710 deleteWindows
711 } -result "{{XXX .f1 {} {}}} {}"
404712
405713
406714 test unixEmbed-5.1 {EmbedFocusProc procedure, FocusIn events} -constraints {
407 unix
715 unix notAqua
408716 } -setup {
409717 deleteWindows
410718 } -body {
424732 } -cleanup {
425733 deleteWindows
426734 } -result {{focus in .t1}}
735 test unixEmbed-5.1a {EmbedFocusProc procedure, FocusIn events} -constraints {
736 unix
737 } -setup {
738 deleteWindows
739 catch {interp delete slave}
740 ::_test_tmp::testInterp slave
741 load {} Tktest slave
742 } -body {
743 frame .f1 -container 1 -width 200 -height 50
744 pack .f1
745 slave alias w1 winfo id .f1
746 slave eval {
747 destroy [winfo child .]
748 toplevel .t1 -use [w1]
749 bind .t1 <FocusIn> {lappend x "focus in %W"}
750 bind .t1 <FocusOut> {lappend x "focus out %W"}
751 update
752 set x {}
753 }
754 focus -force .f1
755 update
756 slave eval {set x}
757 } -cleanup {
758 interp delete slave
759 deleteWindows
760 } -result {{focus in .t1}}
427761 test unixEmbed-5.2 {EmbedFocusProc procedure, focusing on dead window} -constraints {
428 unix
762 unix notAqua
429763 } -setup {
430764 deleteWindows
431765 } -body {
446780 } -cleanup {
447781 deleteWindows
448782 } -result {}
783 test unixEmbed-5.2a {EmbedFocusProc procedure, focusing on dead window} -constraints {
784 unix
785 } -setup {
786 deleteWindows
787 catch {interp delete slave}
788 ::_test_tmp::testInterp slave
789 load {} Tktest slave
790 } -body {
791 frame .f1 -container 1 -width 200 -height 50
792 pack .f1
793 slave alias w1 winfo id .f1
794 slave eval {
795 destroy [winfo child .]
796 toplevel .t1 -use [w1]
797 update
798 after 200 {destroy .t1}
799 }
800 after 400
801 focus -force .f1
802 update
803 } -cleanup {
804 interp delete slave
805 deleteWindows
806 } -result {}
449807 test unixEmbed-5.3 {EmbedFocusProc procedure, FocusOut events} -constraints {
450 unix
808 unix notAqua
451809 } -setup {
452810 deleteWindows
453811 } -body {
470828 } -cleanup {
471829 deleteWindows
472830 } -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}
831 test unixEmbed-5.3a {EmbedFocusProc procedure, FocusOut events} -constraints {
832 unix
833 } -setup {
834 deleteWindows
835 catch {interp delete slave}
836 ::_test_tmp::testInterp slave
837 load {} Tktest slave
838 } -body {
839 frame .f1 -container 1 -width 200 -height 50
840 pack .f1
841 slave alias w1 winfo id .f1
842 slave eval {
843 destroy [winfo child .]
844 toplevel .t1 -use [w1]
845 set x {}
846 bind .t1 <FocusIn> {lappend x "focus in %W"}
847 bind .t1 <FocusOut> {lappend x "focus out %W"}
848 update
849 }
850 focus -force .f1
851 update
852 set x [slave eval {update; set x }]
853 focus .
854 update
855 list $x [slave eval {update; set x}]
856 } -cleanup {
857 interp delete slave
858 deleteWindows
859 } -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}
473860
474861
475862 test unixEmbed-6.1 {EmbedGeometryRequest procedure, window changes size} -constraints {
476 unix
477 } -setup {
478 deleteWindows
479 } -body {
480 frame .f1 -container 1 -width 200 -height 50
481 pack .f1
482 dobg "set w1 [winfo id .f1]"
483 dobg {
484 eval destroy [winfo child .]
485 toplevel .t1 -use $w1
486 }
487 update
488 dobg {
863 unix notAqua
864 } -setup {
865 deleteWindows
866 } -body {
867 frame .f1 -container 1 -width 200 -height 50
868 pack .f1
869 dobg "set w1 [winfo id .f1]"
870 dobg {
871 eval destroy [winfo child .]
872 toplevel .t1 -use $w1
873 update
489874 bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
490875 set x {}
491876 .t1 configure -width 300 -height 120
495880 } -cleanup {
496881 deleteWindows
497882 } -result {{{configure .t1 300 120}} 300x120+0+0}
883 test unixEmbed-6.1a {EmbedGeometryRequest procedure, window changes size} -constraints {
884 unix
885 } -setup {
886 deleteWindows
887 catch {interp delete slave}
888 ::_test_tmp::testInterp slave
889 load {} Tktest slave
890 } -body {
891 frame .f1 -container 1 -width 200 -height 50
892 pack .f1
893 slave alias w1 winfo id .f1
894 slave eval {
895 destroy [winfo child .]
896 toplevel .t1 -use [w1]
897 update
898 bind .t1 <Configure> {set x {configure .t1 %w %h}}
899 set x {}
900 .t1 configure -width 300 -height 120
901 update
902 list $x [winfo geom .t1]
903 }
904 } -cleanup {
905 interp delete slave
906 deleteWindows
907 } -result {{configure .t1 300 120} 300x120+0+0}
498908 test unixEmbed-6.2 {EmbedGeometryRequest procedure, window changes size} -constraints {
499 unix
909 unix notAqua
500910 } -setup {
501911 deleteWindows
502912 } -body {
506916 dobg {
507917 eval destroy [winfo child .]
508918 toplevel .t1 -use $w1
509 }
510 after 300 {set x done}
511 vwait x
512 dobg {
919 update
513920 bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
514921 set x {}
515922 .t1 configure -width 300 -height 120
516 update
923 update
517924 list $x [winfo geom .t1]
518925 }
519926 } -cleanup {
520927 deleteWindows
521928 } -result {{{configure .t1 200 200}} 200x200+0+0}
929 test unixEmbed-6.2a {EmbedGeometryRequest procedure, window changes size} -constraints {
930 unix
931 } -setup {
932 deleteWindows
933 catch {interp delete slave}
934 ::_test_tmp::testInterp slave
935 load {} Tktest slave
936 } -body {
937 frame .f1 -container 1 -width 200 -height 50
938 place .f1 -width 200 -height 200
939 update
940 slave alias w1 winfo id .f1
941 slave eval {
942 destroy [winfo child .]
943 toplevel .t1 -use [w1]
944 update
945 bind .t1 <Configure> {set x {configure .t1 %w %h}}
946 set x {}
947 .t1 configure -width 300 -height 120
948 update
949 list $x [winfo geom .t1]
950 }
951 } -cleanup {
952 interp delete slave
953 deleteWindows
954 } -result {{configure .t1 200 200} 200x200+0+0}
522955
523956 # Can't think up any tests for TkpGetOtherWindow procedure.
524957
525
526958 test unixEmbed-7.1 {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {
527 unix
959 unix notAqua
528960 } -setup {
529961 deleteWindows
530962 } -body {
552984 deleteWindows
553985 bind . <KeyPress> {}
554986 } -result {{{key a 1}} {}}
987 # TkpRedirectKeyEvent is not implemented in win or aqua. If someone
988 # implements it they should change the constraints for this test.
989 test unixEmbed-7.1a {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {
990 unix notAqua
991 } -setup {
992 deleteWindows
993 catch {interp delete slave}
994 ::_test_tmp::testInterp slave
995 load {} Tktest slave
996 } -body {
997 deleteWindows
998 frame .f1 -container 1 -width 200 -height 50
999 pack .f1
1000 slave alias w1 winfo id .f1
1001 slave eval {
1002 destroy [winfo child .]
1003 toplevel .t1 -use [w1]
1004 }
1005 focus -force .
1006 bind . <KeyPress> {lappend x {key %A %E}}
1007 set x {}
1008 set y [slave eval {
1009 update
1010 bind .t1 <KeyPress> {lappend y {key %A}}
1011 set y {}
1012 event generate .t1 <KeyPress> -keysym a
1013 set y
1014 }]
1015 update
1016 list $x $y
1017 } -cleanup {
1018 interp delete slave
1019 deleteWindows
1020 bind . <KeyPress> {}
1021 } -result {{{key a 1}} {}}
5551022 test unixEmbed-7.2 {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {
556 unix
1023 unix notAqua
5571024 } -setup {
5581025 deleteWindows
5591026 } -body {
5821049 deleteWindows
5831050 bind . <KeyPress> {}
5841051 } -result {{} {{key b}}}
585
586
587 test unixEmbed-8.1 {TkpClaimFocus procedure} -constraints unix -setup {
1052 test unixEmbed-7.2a {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {
1053 unix
1054 } -setup {
1055 deleteWindows
1056 catch {interp delete slave}
1057 ::_test_tmp::testInterp slave
1058 load {} Tktest slave
1059 } -body {
1060 frame .f1 -container 1 -width 200 -height 50
1061 pack .f1
1062 slave alias w1 winfo id .f1
1063 slave eval {
1064 destroy [winfo child .]
1065 toplevel .t1 -use [w1]
1066 }
1067 update
1068 focus -force .f1
1069 update
1070 bind . <KeyPress> {lappend x {key %A}}
1071 set x {}
1072 set y [slave eval {
1073 update
1074 bind .t1 <KeyPress> {lappend y {key %A}}
1075 set y {}
1076 event generate .t1 <KeyPress> -keysym b
1077 set y
1078 }]
1079 update
1080 list $x $y
1081 } -cleanup {
1082 interp delete slave
1083 deleteWindows
1084 bind . <KeyPress> {}
1085 } -result {{} {{key b}}}
1086
1087 test unixEmbed-8.1 {TkpClaimFocus procedure} -constraints {
1088 unix notAqua
1089 } -setup {
5881090 deleteWindows
5891091 } -body {
5901092 frame .f1 -container 1 -width 200 -height 50
6081110 } -cleanup {
6091111 deleteWindows
6101112 } -result {{{} .t1} .f1}
611 test unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {
612 deleteWindows
613 catch {interp delete child}
614 deleteWindows
1113 test unixEmbed-8.1a {TkpClaimFocus procedure} -constraints unix -setup {
1114 deleteWindows
1115 catch {interp delete slave}
1116 ::_test_tmp::testInterp slave
1117 load {} Tktest slave
6151118 } -body {
6161119 frame .f1 -container 1 -width 200 -height 50
6171120 frame .f2 -width 200 -height 50
6181121 pack .f1 .f2
1122 update
1123 slave alias w1 winfo id .f1
1124 slave eval {
1125 destroy [winfo child .]
1126 toplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken
1127 }
1128 # This should clear focus from the application embedded in .f1
1129 focus -force .f2
1130 update
1131 list [slave eval {
1132 set x [list [focus]]
1133 focus .t1
1134 update
1135 lappend x [focus]
1136 }] [focus]
1137 } -cleanup {
1138 interp delete slave
1139 deleteWindows
1140 } -result {{{} .t1} .f1}
1141 test unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {
1142 deleteWindows
1143 catch {interp delete child}
6191144 interp create child
1145 } -body {
1146 frame .f1 -container 1 -width 200 -height 50
1147 frame .f2 -width 200 -height 50
1148 pack .f1 .f2
1149 update
1150 set w1 [winfo id .f1]
6201151 child eval "set argv {-use [winfo id .f1]}"
6211152 load {} Tk child
6221153 child eval {
6341165 deleteWindows
6351166 } -result {{{} .} .f1}
6361167 catch {interp delete child}
637
6381168
6391169 test unixEmbed-9.1 {EmbedWindowDeleted procedure, check parentPtr} -constraints {
6401170 unix testembed
6571187 deleteWindows
6581188 } -result {{{XXX .f4 {} {}} {XXX .f3 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f4 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}}} {}}
6591189 test unixEmbed-9.2 {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {
660 unix testembed
661 } -setup {
662 deleteWindows
663 } -body {
664 frame .f1 -container 1 -width 200 -height 50
665 pack .f1
1190 unix testembed notAqua
1191 } -setup {
1192 deleteWindows
1193 } -body {
1194 frame .f1 -container 1 -width 200 -height 50
1195 pack .f1
1196 update
6661197 dobg "set w1 [winfo id .f1]"
6671198 dobg {
6681199 eval destroy [winfo child .]
6751206 } -cleanup {
6761207 deleteWindows
6771208 } -result {{{XXX {} {} .t1}} {}}
1209 test unixEmbed-9.2a {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {
1210 unix testembed
1211 } -setup {
1212 deleteWindows
1213 catch {interp delete slave}
1214 ::_test_tmp::testInterp slave
1215 load {} Tktest slave
1216 } -body {
1217 frame .f1 -container 1 -width 200 -height 50
1218 pack .f1
1219 slave alias w1 winfo id .f1
1220 slave eval {
1221 destroy [winfo child .]
1222 toplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken
1223 set x {}
1224 lappend x [testembed]
1225 destroy .t1
1226 lappend x [testembed]
1227 }
1228 } -cleanup {
1229 interp delete slave
1230 deleteWindows
1231 } -result {{{XXX {} {} .t1}} {}}
6781232
6791233
6801234 test unixEmbed-10.1 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {
681 unix
682 } -setup {
683 deleteWindows
684 } -body {
685 frame .f1 -container 1 -width 200 -height 50
686 pack .f1
1235 unix
1236 } -setup {
1237 deleteWindows
1238 } -body {
1239 frame .f1 -container 1 -width 200 -height 50
1240 update
1241 pack .f1
1242 update
6871243 toplevel .t1 -use [winfo id .f1] -width 150 -height 80
6881244 update
6891245 wm geometry .t1 +40+50
6931249 deleteWindows
6941250 } -result {150x80+0+0}
6951251 test unixEmbed-10.2 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {
696 unix
1252 unix
6971253 } -setup {
6981254 deleteWindows
6991255 } -body {
7071263 } -cleanup {
7081264 deleteWindows
7091265 } -result {70x300+0+0}
1266
1267 test unixEmbed-11.1 {focus -force works for embedded toplevels} -constraints {
1268 unix
1269 } -setup {
1270 deleteWindows
1271 } -body {
1272 toplevel .t
1273 pack [frame .t.f -container 1 -width 200 -height 200] -fill both
1274 update idletasks
1275 toplevel .embed -use [winfo id .t.f] -bg green
1276 update idletasks
1277 focus -force .t
1278 focus -force .embed
1279 focus
1280 } -cleanup {
1281 deleteWindows
1282 } -result .embed
1283 test unixEmbed-11.2 {mouse coordinates in embedded toplevels} -constraints {
1284 unix pressbutton
1285 } -setup {
1286 deleteWindows
1287 } -body {
1288 toplevel .main
1289 set result {}
1290 pack [button .main.b -text "Main Button" \
1291 -command {lappend result ".main.b"}] -padx 30 -pady 30
1292 pack [frame .main.f -container 1 -width 200 -height 200] -fill both
1293 update idletasks
1294 toplevel .embed -use [winfo id .main.f] -bg green
1295 pack [button .embed.b -text "Emb Button" \
1296 -command {lappend result ".embed.b"}] -padx 30 -pady 30
1297 wm geometry .main 200x400+100+100
1298 update idletasks
1299 focus -force .main
1300 set x [expr {[winfo x .main ] + [winfo x .main.b] + 40}]
1301 set y [expr {[winfo y .main ] + [winfo y .main.b] + 38}]
1302 lappend result [winfo containing $x $y]
1303 after 200
1304 pressbutton $x $y
1305 update
1306 set y [expr {$y + 80}]
1307 lappend result [winfo containing $x $y]
1308 after 200
1309 pressbutton $x $y
1310 update
1311 set result
1312 } -cleanup {
1313 deleteWindows
1314 } -result {.main.b .main.b .embed.b .embed.b}
1315
7101316
7111317 # cleanup
7121318 deleteWindows
7131319 cleanupbg
7141320 cleanupTests
7151321 return
716
0 # This file is a Tcl script to test out the procedures in tkUnixFont.c.
0 # This file is a Tcl script to test out the procedures in tkUnixFont.c.
11 # It is organized in the standard fashion for Tcl tests.
22 #
33 # Many of these tests are visually oriented and cannot be checked
55 # underlined?"); these tests attempt to exercise the code in question,
66 # but there are no results that can be checked. Some tests depend on the
77 # fonts having or not having certain properties, which may not be valid
8 # at all sites.
8 # at all sites.
99 #
1010 # Copyright (c) 1996 Sun Microsystems, Inc.
1111 # Copyright (c) 1998-1999 by Scriptics Corporation.
123123
124124 font actual {-size 14}
125125 set x {}
126 } {}
126 } {}
127127
128128 test unixfont-3.1 {TkpDeleteFont procedure} x11 {
129129 font actual {-family xyz}
1818 vwait x
1919 }
2020
21 # The macOS window manager shows an animation when a window is deiconified.
22 # Tests which check the geometry of a window after deiconifying it should
23 # wait for the animation to finish.
24
25 proc animationDelay {} {
26 if {[tk windowingsystem] == "aqua"} {
27 sleep 250
28 }
29 }
30
2131 # Procedure to set up a collection of top-level windows
2232
2333 proc makeToplevels {} {
2939 }
3040 }
3141
42 # On macOS windows are not allowed to overlap the menubar at the top
43 # of the screen. So tests which move a window and then check whether
44 # it got moved to the requested location should use a y coordinate
45 # larger than the height of the menubar (normally 23 pixels).
46
47 if {[tk windowingsystem] eq "aqua"} {
48 set Y0 23
49 set Y2 25
50 set Y5 28
51 } else {
52 set Y0 0
53 set Y2 2
54 set Y5 5
55 }
56
3257 set i 1
33 foreach geom {+20+80 +80+20 +0+0} {
58 foreach geom "+23+80 +80+23 +0+$Y0" {
3459 destroy .t
3560 test unixWm-1.$i {initial window position} unix {
3661 toplevel .t -width 200 -height 150
5681 scan [wm geom .t] %dx%d+%d+%d width height x y
5782 set xerr [expr 150-$x]
5883 set yerr [expr 150-$y]
59 foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
84 foreach geom "+20+80 +80+23 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
6085 test unixWm-2.$i {moving window while mapped} unix {
6186 wm geom .t $geom
6287 update
6893 }
6994
7095 set i 1
71 foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
96 foreach geom "+20+80 +80+23 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
7297 test unixWm-3.$i {moving window while iconified} unix {
7398 wm iconify .t
7499 sleep 200
75100 wm geom .t $geom
76101 update
77102 wm deiconify .t
103 animationDelay
78104 scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
79105 format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
80106 [eval expr $y$ysign$yerr]
83109 }
84110
85111 set i 1
86 foreach geom {+20+80 +100+40 +0+0} {
112 foreach geom "+20+80 +100+40 +0+$Y0" {
87113 test unixWm-4.$i {moving window while withdrawn} unix {
88114 wm withdraw .t
89115 sleep 200
90116 wm geom .t $geom
91117 update
92118 wm deiconify .t
119 animationDelay
93120 wm geom .t
94121 } 100x150$geom
95122 incr i
166193
167194 destroy .t
168195 toplevel .t -width 200 -height 100
169 wm geom .t +10+10
196 wm geom .t +10+23
170197 wm minsize .t 1 1
171198 update
172199 test unixWm-6.1 {size changes} unix {
173200 .t config -width 180 -height 150
174201 update
175202 wm geom .t
176 } 180x150+10+10
203 } 180x150+10+23
177204 test unixWm-6.2 {size changes} unix {
178205 wm geom .t 250x60
179206 .t config -width 170 -height 140
180207 update
181208 wm geom .t
182 } 250x60+10+10
209 } 250x60+10+23
183210 test unixWm-6.3 {size changes} unix {
184211 wm geom .t 250x60
185212 .t config -width 170 -height 140
186213 wm geom .t {}
187214 update
188215 wm geom .t
189 } 170x140+10+10
216 } 170x140+10+23
190217 test unixWm-6.4 {size changes} {unix nonPortable userInteraction} {
191218 wm minsize .t 1 1
192219 update
399426 destroy .t
400427 sleep 500
401428 toplevel .t -width 100 -height 50 -bg blue
429 tkwait visibility .t
402430 wm iconwindow . .t
403431 update
404432 set result [winfo ismapped .t]
629657 list [catch {wm focusmodel .t bogus} msg] $msg
630658 } {1 {bad argument "bogus": must be active or passive}}
631659 test unixWm-17.3 {Tk_WmCmd procedure, "focusmodel" option} unix {
632 set result {}
660 set result {}
633661 lappend result [wm focusmodel .t]
634662 wm focusmodel .t active
635663 lappend result [wm focusmodel .t]
794822 WM_HINTS] 0]]]
795823 lappend result [wm iconbitmap .t] $bit
796824 } {{} questhead 0x4 {} 0x0}
797 test unixWm-22.3 {Tk_WmCmd procedure, "iconbitmap" option} unix {
825 if {[tk windowingsystem] == "aqua"} {
826 set result_22_3 {0 {}}
827 } else {
828 set result_22_3 {1 {bitmap "bad-bitmap" not defined}}
829 }
830 test unixWm-22.3 {Tk_WmCmd procedure, "iconbitmap" option for unix only} \
831 unix {
798832 list [catch {wm iconbitmap .t bad-bitmap} msg] $msg
799 } {1 {bitmap "bad-bitmap" not defined}}
833 } $result_22_3
800834
801835 test unixWm-23.1 {Tk_WmCmd procedure, "iconify" option} unix {
802836 list [catch {wm iconify .t 12} msg] $msg
11991233 test unixWm-34.3 {Tk_WmCmd procedure, "sizefrom" option} unix {
12001234 list [catch {wm sizefrom .t none} msg] $msg
12011235 } {1 {bad argument "none": must be program or user}}
1202
1203 test unixWm-35.1 {Tk_WmCmd procedure, "state" option} unix {
1236 if {[tk windowingsystem] == "aqua"} {
1237 set result_35_1 {1 {bad argument "1": must be normal, iconic, withdrawn, or zoomed}}
1238 } else {
1239 set result_35_1 {1 {bad argument "1": must be normal, iconic, or withdrawn}}
1240 }
1241 test unixWm-35.1 {Tk_WmCmd procedure, "state" option} {unix notAqua} {
12041242 list [catch {wm state .t 1} msg] $msg
1205 } {1 {bad argument "1": must be normal, iconic, or withdrawn}}
1243 } $result_35_1
12061244 test unixWm-35.2 {Tk_WmCmd procedure, "state" option} unix {
12071245 list [catch {wm state .t iconic 1} msg] $msg
12081246 } {1 {wrong # args: should be "wm state window ?state?"}}
13251363 destroy .t
13261364 toplevel .t
13271365 wm geometry .t 30x10+0+0
1328 listbox .t.l -height 20 -width 20 -setgrid 1
1366 listbox .t.l -height 20 -width 20 -setgrid 1
13291367 pack .t.l -fill both -expand 1
13301368 update
13311369 wm geometry .t
13331371 test unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix {
13341372 destroy .t
13351373 toplevel .t
1336 wm geometry .t 200x100+0+0
1337 listbox .t.l -height 20 -width 20
1374 wm geometry .t 200x100+0+$Y0
1375 listbox .t.l -height 20 -width 20
13381376 pack .t.l -fill both -expand 1
13391377 update
13401378 .t.l configure -setgrid 1
13411379 update
13421380 wm geometry .t
1343 } {20x20+0+0}
1381 } "20x20+0+$Y0"
13441382
13451383 test unixWm-41.1 {ConfigureEvent procedure, internally generated size changes} unix {
13461384 destroy .t
14141452 bind .t <Unmap> {set x "unmapped"}
14151453 set x {no event}
14161454 wm iconify .t
1455 animationDelay
14171456 lappend result $x [winfo ismapped .t]
14181457 set x {no event}
14191458 wm deiconify .t
1459 animationDelay
14201460 lappend result $x [winfo ismapped .t]
14211461 } {unmapped 0 mapped 1}
14221462
15061546 update
15071547 list [winfo width .t] [winfo height .t]
15081548 } {1 72}
1549 destroy .t
1550 toplevel .t -width 80 -height 60
15091551 test unixWm-44.6 {UpdateGeometryInfo procedure, negative height} unix {
1510 destroy .t
1511 toplevel .t -width 80 -height 60
15121552 wm grid .t 18 7 10 12
15131553 wm geometry .t +30+40
15141554 wm overrideredirect .t 1
15171557 update
15181558 list [winfo width .t] [winfo height .t]
15191559 } {100 1}
1520
15211560 destroy .t
15221561 toplevel .t -width 80 -height 60
15231562 test unixWm-44.7 {UpdateGeometryInfo procedure, computing position} unix {
1563 tkwait visibility .t
1564 wm overrideredirect .t 1
1565 update
15241566 wm geometry .t +5-10
1525 wm overrideredirect .t 1
1526 tkwait visibility .t
1567 update
15271568 list [winfo x .t] [winfo y .t]
15281569 } [list 5 [expr [winfo screenheight .t] - 70]]
1529
15301570 destroy .t
15311571 toplevel .t -width 80 -height 60
15321572 test unixWm-44.8 {UpdateGeometryInfo procedure, computing position} unix {
1533 wm geometry .t -30+2
1573 tkwait visibility .t
15341574 wm overrideredirect .t 1
1535 tkwait visibility .t
1575 update
1576 wm geometry .t -30+$Y2
1577 update
15361578 list [winfo x .t] [winfo y .t]
1537 } [list [expr [winfo screenwidth .t] - 110] 2]
1579 } [list [expr [winfo screenwidth .t] - 110] $Y2]
15381580 destroy .t
15391581
15401582 test unixWm-44.9 {UpdateGeometryInfo procedure, updating fixed dimensions} {unix testwrapper} {
17471789 testmenubar window .t .t.m
17481790 update
17491791 list [expr [winfo rootx .t.m.f] - $x] [expr [winfo rooty .t.m.f] - $y] \
1750 [expr [winfo rootx .t.f] - $x] [expr [winfo rooty .t.f] - $y]
1792 [expr [winfo rootx .t.f] - $x] [expr [winfo rooty .t.f] - $y]
17511793 } {52 7 12 62}
17521794
17531795 deleteWindows
1754 wm iconify .
1755 test unixWm-50.1 {Tk_CoordsToWindow procedure, finding a toplevel, x-coords} unix {
1756 deleteWindows
1796 wm withdraw .
1797 if {[tk windowingsystem] == "aqua"} {
1798 # Modern mac windows have no border.
1799 set result_50_1 {{} {} .t .t .t2 {} .t2 .t .t}
1800 } else {
1801 # Windows are assumed to have a border (invisible in Gnome 3).
1802 set result_50_1 {{} {} .t {} .t2 {} .t2 {} .t}
1803 }
1804 test unixWm-50.1 {Tk_CoordsToWindow procedure, finding a toplevel, x-coords, title bar} unix {
1805 update
17571806 toplevel .t -width 300 -height 400 -bg green
1758 wm geom .t +40+0
1759 tkwait visibility .t
1760 toplevel .t2 -width 100 -height 80 -bg red
1761 wm geom .t2 +140+200
1807 wm geom .t +100+100
1808 tkwait visibility .t
1809 toplevel .t2 -width 100 -height 200 -bg red
1810 wm geom .t2 +200+200
17621811 tkwait visibility .t2
17631812 raise .t2
1813 update
17641814 set x [winfo rootx .t]
17651815 set y [winfo rooty .t]
1766 list [winfo containing [expr $x - 30] [expr $y + 250]] \
1767 [winfo containing [expr $x - 1] [expr $y + 250]] \
1768 [winfo containing $x [expr $y + 250]] \
1769 [winfo containing [expr $x + 99] [expr $y + 250]] \
1770 [winfo containing [expr $x + 100] [expr $y + 250]] \
1771 [winfo containing [expr $x + 199] [expr $y + 250]] \
1772 [winfo containing [expr $x + 200] [expr $y + 250]] \
1773 [winfo containing [expr $x + 220] [expr $y + 250]]
1774 } {{} {} .t {} .t2 .t2 {} .t}
1816 list [winfo containing [expr $x - 30] [expr $y + 250]] \
1817 [winfo containing [expr $x - 1] [expr $y + 250]] \
1818 [winfo containing $x [expr $y + 250]] \
1819 [winfo containing [expr $x + 99] [expr $y + 250]] \
1820 [winfo containing [expr $x + 100] [expr $y + 250]] \
1821 [winfo containing [expr $x + 150] [expr $y + 90]] \
1822 [winfo containing [expr $x + 199] [expr $y + 250]] \
1823 [winfo containing [expr $x + 200] [expr $y + 250]] \
1824 [winfo containing [expr $x + 220] [expr $y + 250]] \
1825 } $result_50_1
17751826 test unixWm-50.2 {Tk_CoordsToWindow procedure, finding a toplevel, y-coords and overrideredirect} unix {
17761827 deleteWindows
1777 toplevel .t -width 300 -height 400 -bg yellow
1778 wm geom .t +0+50
1779 tkwait visibility .t
1780 toplevel .t2 -width 100 -height 80 -bg blue
1828 toplevel .t -width 400 -height 300 -bg yellow
1829 wm geom .t +100+100
1830 tkwait visibility .t
1831 toplevel .t2 -width 200 -height 100 -bg blue
17811832 wm overrideredirect .t2 1
1782 wm geom .t2 +100+200
1833 wm geom .t2 +200+200
17831834 tkwait visibility .t2
17841835 raise .t2
17851836 set x [winfo rootx .t]
17861837 set y [winfo rooty .t]
17871838 set y2 [winfo rooty .t2]
1788 list [winfo containing [expr $x +150] 10] \
1789 [winfo containing [expr $x +150] [expr $y - 1]] \
1790 [winfo containing [expr $x +150] $y] \
1791 [winfo containing [expr $x +150] [expr $y2 - 1]] \
1792 [winfo containing [expr $x +150] $y2] \
1793 [winfo containing [expr $x +150] [expr $y2 + 79]] \
1794 [winfo containing [expr $x +150] [expr $y2 + 80]] \
1795 [winfo containing [expr $x +150] [expr $y + 450]]
1839 list [winfo containing [expr $x +200] [expr $y - 30]] \
1840 [winfo containing [expr $x +200] [expr $y - 1]] \
1841 [winfo containing [expr $x +200] $y] \
1842 [winfo containing [expr $x +200] [expr $y2 - 1]] \
1843 [winfo containing [expr $x +200] $y2] \
1844 [winfo containing [expr $x +200] [expr $y2 + 99]] \
1845 [winfo containing [expr $x +200] [expr $y2 + 100]] \
1846 [winfo containing [expr $x +200] [expr $y + 450]]
17961847 } {{} {} .t .t .t2 .t2 .t {}}
17971848 test unixWm-50.3 {
17981849 Tk_CoordsToWindow procedure, finding a toplevel with embedding
1799 } -constraints tempNotWin -setup {
1850 } tempNotWin {
18001851 deleteWindows
1852 catch {interp delete slave}
1853
18011854 toplevel .t -width 300 -height 400 -bg blue
1802 wm geom .t +0+50
1803 frame .t.f -container 1
1855 wm geom .t +100+100
1856 frame .t.f -container 1 -bg red
18041857 place .t.f -x 150 -y 50
18051858 tkwait visibility .t.f
1806 setupbg
1807 } -body {
1808 dobg "
1859 update
1860 interp create slave
1861 load {} Tk slave
1862 slave alias frameid winfo id .t.f
1863 slave eval {
18091864 wm withdraw .
1810 toplevel .x -width 100 -height 80 -use [winfo id .t.f] -bg yellow
1811 tkwait visibility .x"
1812 set result [dobg {
1813 set x [winfo rootx .x]
1814 set y [winfo rooty .x]
1815 list [winfo containing [expr $x - 1] [expr $y + 50]] \
1816 [winfo containing $x [expr $y +50]]
1817 }]
1865 toplevel .x -width 100 -height 80 -use [frameid] -bg yellow
1866 tkwait visibility .x
1867 update
1868 set x [winfo rootx .x]
1869 set y [winfo rooty .x]
1870 }
1871 set result [list [slave eval {winfo containing [expr $x - 1] [expr $y + 50]}] \
1872 [slave eval {winfo containing $x [expr $y + 50]}]]
1873 interp delete slave
18181874 set x [winfo rootx .t]
18191875 set y [winfo rooty .t]
18201876 lappend result [winfo containing [expr $x + 200] [expr $y + 49]] \
1821 [winfo containing [expr $x + 200] [expr $y +50]]
1822 } -cleanup {
1823 cleanupbg
1824 } -result {{} .x .t .t.f}
1877 [winfo containing [expr $x + 200] [expr $y +50]]
1878 set result
1879 } {{} .x .t .t.f}
18251880 test unixWm-50.4 {Tk_CoordsToWindow procedure, window in other application} unix {
18261881 destroy .t
1882
18271883 catch {interp delete slave}
18281884 toplevel .t -width 200 -height 200 -bg green
1829 wm geometry .t +0+0
1830 tkwait visibility .t
1885 wm geometry .t +100+100
1886 tkwait visibility .t
1887 update
18311888 interp create slave
18321889 load {} Tk slave
1833 slave eval {wm geometry . 200x200+0+0; tkwait visibility .}
1834 set result [list [winfo containing 100 100] \
1835 [slave eval {winfo containing 100 100}]]
1890 slave eval {wm geometry . 200x200+100+100; tkwait visibility . ; update}
1891 set result [list [winfo containing 200 200] \
1892 [slave eval {winfo containing 200 200}]]
18361893 interp delete slave
18371894 set result
18381895 } {{} .}
18501907 update
18511908 set x [winfo rootx .t]
18521909 set y [winfo rooty .t]
1853 list [winfo containing $x [expr $y - 31]] \
1854 [winfo containing $x [expr $y - 30]] \
1855 [winfo containing [expr $x + 50] [expr $y - 19]] \
1856 [winfo containing [expr $x + 50] [expr $y - 18]] \
1857 [winfo containing [expr $x + 50] $y] \
1858 [winfo containing [expr $x + 11] [expr $y + 152]] \
1859 [winfo containing [expr $x + 12] [expr $y + 152]]
1910 list [winfo containing $x [expr $y - 31]] \
1911 [winfo containing $x [expr $y - 30]] \
1912 [winfo containing [expr $x + 50] [expr $y - 19]] \
1913 [winfo containing [expr $x + 50] [expr $y - 18]] \
1914 [winfo containing [expr $x + 50] $y] \
1915 [winfo containing [expr $x + 11] [expr $y + 152]] \
1916 [winfo containing [expr $x + 12] [expr $y + 152]]
18601917 } {{} .t.menu .t.menu .t.menu.f .t .t .t.f}
18611918 test unixWm-50.6 {Tk_CoordsToWindow procedure, embedding within one app.} unix {
18621919 deleteWindows
19211978 tkwait visibility .t2
19221979 set result [list [winfo containing 100 100]]
19231980 wm iconify .t2
1981 animationDelay
19241982 lappend result [winfo containing 100 100]
19251983 } {.t2 .t}
19261984 test unixWm-50.10 {Tk_CoordsToWindow procedure, unmapped windows} unix {
20062064 test unixWm-51.7 {TkWmRestackToplevel procedure, other window isn't mapped} unix {
20072065 foreach w {.t .t2 .t3} {
20082066 destroy $w
2067 update
20092068 toplevel $w -width 200 -height 200 -bg green
20102069 wm geometry $w +0+0
20112070 }
20422101 raise .t2
20432102 lappend result [winfo containing $x $y]
20442103 } {.t2 .t .t2}
2104 # The mac won't put an overrideredirect window above the root,
2105 if {[tk windowingsystem] == "aqua"} {
2106 wm withdraw .
2107 }
20452108 test unixWm-51.9 {TkWmRestackToplevel procedure, other window overrideredirect} unix {
20462109 foreach w {.t .t2 .t3} {
20472110 destroy $w
2111 update
20482112 toplevel $w -width 200 -height 200 -bg green
20492113 wm overrideredirect $w 1
20502114 wm geometry $w +0+0
20512115 tkwait visibility $w
2116 update
20522117 }
20532118 lower .t3 .t2
20542119 update
20642129 lower .t2
20652130 lappend result [winfo containing $x $y]
20662131 } {.t2 .t3}
2132 if {[tk windowingsystem] == "aqua"} {
2133 wm deiconify .
2134 }
20672135 test unixWm-51.10 {TkWmRestackToplevel procedure, don't move window that's already in the right place} unix {
20682136 makeToplevels
20692137 raise .raise1
24392507 # NOTE: since [wm attributes] is not guaranteed to have any effect,
24402508 # the only thing we can really test here is the syntax.
24412509 #
2510 if {[tk windowingsystem] == "aqua"} {
2511 set result_60_1 {-alpha 1.0 -fullscreen 0 -modified 0 -notify 0\
2512 -titlepath {} -topmost 0 -transparent 0\
2513 -type unsupported}
2514 } else {
2515 set result_60_1 {-alpha 1.0 -topmost 0 -zoomed 0 -fullscreen 0 -type {}}
2516 }
24422517 test unixWm-60.1 {wm attributes - test} -constraints unix -body {
24432518 destroy .t
24442519 toplevel .t
24452520 wm attributes .t
2446 } -result [list -alpha 1.0 -topmost 0 -zoomed 0 -fullscreen 0 -type {}]
2521 } -result $result_60_1
24472522
24482523 test unixWm-60.2 {wm attributes - test} -constraints unix -body {
24492524 destroy .t
2828 pack $w.c
2929 for {set y 0} {$y < 8} {incr y} {
3030 for {set x 0} {$x < 40} {incr x} {
31 set color [format #%02x%02x%02x [expr $x*6] [expr $y*30] 0]
32 $w.c create rectangle [expr 10*$x] [expr 20*$y] \
33 [expr 10*$x + 10] [expr 20*$y + 20] -outline {} \
31 set color [format #%02x%02x%02x [expr {$x*6}] [expr {$y*30}] 0]
32 $w.c create rectangle [expr {10*$x}] [expr {20*$y}] \
33 [expr {10*$x + 10}] [expr {20*$y + 20}] -outline {} \
3434 -fill $color
3535 }
3636 }
4949
5050 proc colorsFree {w {red 31} {green 245} {blue 192}} {
5151 set vals [winfo rgb $w [format #%02x%02x%02x $red $green $blue]]
52 expr ([lindex $vals 0]/256 == $red) && ([lindex $vals 1]/256 == $green) \
53 && ([lindex $vals 2]/256 == $blue)
52 expr {([lindex $vals 0]/256 == $red) && ([lindex $vals 1]/256 == $green)
53 && ([lindex $vals 2]/256 == $blue)}
5454 }
5555
5656 # If more than one visual type is available for the screen, pick one
1414 tcltest::loadTestedCommands
1515 namespace import -force tcltest::test
1616
17 # Note that these tests may fail if another application is grabbing the
18 # clipboard (e.g. an X server)
17 #################################################################
18 # Note that some of these tests may fail if another application #
19 # is grabbing the clipboard (e.g. an X server, or a VNC viewer) #
20 #################################################################
1921
2022 test winClipboard-1.1 {TkSelGetSelection} -constraints win -setup {
2123 clipboard clear
255255 Click cancel
256256 }]
257257 # Note this also tests fix for
258 # http://core.tcl.tk/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6
258 # https://core.tcl-lang.org/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6
259259 # $x is expected to be empty
260260 append x $y
261261 } -result {0}
375375 test winDialog-5.7.6 {GetFileName: All/extension } -constraints {
376376 nt testwinevent
377377 } -body {
378 # In 8.6.4 this combination resulted in bar.ext.ext which is bad
379 start {set x [tk_getSaveFile -filetypes {{All *}} -defaultextension {ext} -title Save]}
378 # In 8.6.4 this combination resulted in bar.aaa.aaa which is bad
379 start {set x [tk_getSaveFile -filetypes {{All *}} -defaultextension {aaa} -title Save]}
380380 set msg {}
381381 then {
382382 if {[catch {SetText [vista? 0x47C 0x3e9] bar} msg]} {
388388 set x "[file tail $x]$msg"
389389 } -cleanup {
390390 unset msg
391 } -result bar.ext
391 } -result bar.aaa
392392
393393 test winDialog-5.7.7 {tk_getOpenFile: -defaultextension} -constraints {
394394 nt testwinevent
395395 } -body {
396396 unset -nocomplain x
397 tcltest::makeFile "" "5 7 7.ext" [initialdir]
397 tcltest::makeFile "" "5 7 7.aaa" [initialdir]
398398 start {set x [tk_getOpenFile \
399 -defaultextension ext \
399 -defaultextension aaa \
400400 -initialdir [file nativename [initialdir]] \
401401 -initialfile "5 7 7" -title Foo]}
402402 then {
403403 Click ok
404404 }
405405 return $x
406 } -result [file join [initialdir] "5 7 7.ext"]
406 } -result [file join [initialdir] "5 7 7.aaa"]
407407
408408 test winDialog-5.7.8 {tk_getOpenFile: -defaultextension} -constraints {
409409 nt testwinevent
410410 } -body {
411411 unset -nocomplain x
412 tcltest::makeFile "" "5 7 8.ext" [initialdir]
412 tcltest::makeFile "" "5 7 8.aaa" [initialdir]
413413 start {set x [tk_getOpenFile \
414 -defaultextension ext \
414 -defaultextension aaa \
415415 -initialdir [file nativename [initialdir]] \
416 -initialfile "5 7 8.ext" -title Foo]}
417 then {
418 Click ok
419 }
420 return $x
421 } -result [file join [initialdir] "5 7 8.ext"]
416 -initialfile "5 7 8.aaa" -title Foo]}
417 then {
418 Click ok
419 }
420 return $x
421 } -result [file join [initialdir] "5 7 8.aaa"]
422422
423423 test winDialog-5.8 {GetFileName: extension doesn't begin with .} -constraints {
424424 nt testwinevent
179179 set ax [winfo reqwidth .t.l]
180180 set ay [winfo reqheight .t.l]
181181
182 .t.l config -wrap [expr $ax*10] -text "00000000"
182 .t.l config -wrap [expr {$ax*10}] -text "00000000"
183183 list [expr {[winfo reqwidth .t.l] eq 8*$ax}] \
184184 [expr {[winfo reqheight .t.l] eq $ay}]
185185 } -cleanup {
198198 set ax [winfo reqwidth .t.l]
199199 set ay [winfo reqheight .t.l]
200200
201 .t.l config -wrap [expr $ax*6] -text "00000000"
201 .t.l config -wrap [expr {$ax*6}] -text "00000000"
202202 list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \
203203 [expr {[winfo reqheight .t.l] eq 2*$ay}]
204204 } -cleanup {
217217
218218 .t.c dchars $t 0 end
219219 .t.c insert $t 0 "0000"
220 .t.c index $t @[expr int($cx*2.5)],1
220 .t.c index $t @[expr {int($cx*2.5)}],1
221221 } -cleanup {
222222 destroy .t.c
223223 } -result {2}
253253 set ax [winfo reqwidth .t.l]
254254 set ay [winfo reqheight .t.l]
255255
256 .t.l config -wrap [expr $ax*8] -text "000000 0000"
256 .t.l config -wrap [expr {$ax*8}] -text "000000 0000"
257257 list [expr {[winfo reqwidth .t.l] eq 6*$ax}] \
258258 [expr {[winfo reqheight .t.l] eq 2*$ay}]
259259 } -cleanup {
272272 set ax [winfo reqwidth .t.l]
273273 set ay [winfo reqheight .t.l]
274274
275 .t.l config -wrap [expr $ax*12] -text "000000 0000000"
275 .t.l config -wrap [expr {$ax*12}] -text "000000 0000000"
276276 list [expr {[winfo reqwidth .t.l] eq 7*$ax}] \
277277 [expr {[winfo reqheight .t.l] eq 2*$ay}]
278278 } -cleanup {
291291 set ax [winfo reqwidth .t.l]
292292 set ay [winfo reqheight .t.l]
293293
294 .t.l config -wrap [expr $ax*12] -text "000 00 00000"
294 .t.l config -wrap [expr {$ax*12}] -text "000 00 00000"
295295 list [expr {[winfo reqwidth .t.l] eq 7*$ax}] \
296296 [expr {[winfo reqheight .t.l] eq 2*$ay}]
297297 } -cleanup {
310310 set ax [winfo reqwidth .t.l]
311311 set ay [winfo reqheight .t.l]
312312
313 .t.l config -wrap [expr $ax*12] -text "0000000000000000"
313 .t.l config -wrap [expr {$ax*12}] -text "0000000000000000"
314314 list [expr {[winfo reqwidth .t.l] eq 12*$ax}] \
315315 [expr {[winfo reqheight .t.l] eq 2*$ay}]
316316 } -cleanup {
333333 .t.l config -text "XaYoYaKaWx"
334334 set x [lindex [getsize] 0]
335335 .t.l config -font $font
336 expr $x < ($width*10)
336 expr {$x < ($width*10)}
337337 } -cleanup {
338338 destroy .t.l
339339 } -result {1}
117117 } {0 b {}}
118118 test winSend-2.4 {Tk_SendObjCmd - sending to ourselves in a different interp with errors} winSend {
119119 newApp testApp
120 list [catch {send testApp {expr 2 / 0}} msg] $msg $errorCode $errorInfo [interp delete testApp]
121 } "1 {divide by zero} {ARITH DIVZERO {divide by zero}} {divide by zero\n while executing\n\"expr 2 / 0\"\n invoked from within\n\"send testApp {expr 2 / 0}\"} {}"
120 list [catch {send testApp {expr {2 / 0}}} msg] $msg $errorCode $errorInfo [interp delete testApp]
121 } "1 {divide by zero} {ARITH DIVZERO {divide by zero}} {divide by zero\n while executing\n\"expr {2 / 0}\"\n invoked from within\n\"send testApp {expr {2 / 0}}\"} {}"
122122 test winSend-2.5 {Tk_SendObjCmd - sending to another app async} winSend {
123123 set newInterps [winfo interps]
124124 foreach interp $newInterps {
144144 break
145145 }
146146 }
147 list [catch {send $interp {expr 2 / 0}} msg] $msg $errorCode $errorInfo
148 } "1 {divide by zero} {ARITH DIVZERO {divide by zero}} {divide by zero\n while executing\n\"expr 2 / 0\"\n invoked from within\n\"send \$interp {expr 2 / 0}\"}"
147 list [catch {send $interp {expr {2 / 0}}} msg] $msg $errorCode $errorInfo
148 } "1 {divide by zero} {ARITH DIVZERO {divide by zero}} {divide by zero\n while executing\n\"expr {2 / 0}\"\n invoked from within\n\"send \$interp {expr {2 / 0}}\"}"
149149
150150 test winSend-3.1 {TkGetInterpNames} winSend {
151151 set origLength [llength $currentInterps]
169169 break
170170 }
171171 }
172 list [send $interp {send [tk appname] {expr 2 / 1}}]
172 list [send $interp {send [tk appname] {expr {2 / 1}}}]
173173 } {2}
174174 test winSend-5.2 {ExecuteRemoteObject - error} winSend {
175175 set newInterps [winfo interps]
178178 break
179179 }
180180 }
181 list [catch {send $interp {send [tk appname] {expr 2 / 0}}} msg] $msg
181 list [catch {send $interp {send [tk appname] {expr {2 / 0}}}} msg] $msg
182182 } {1 {divide by zero}}
183183
184184 test winSend-6.1 {SendDDEServer - XTYP_CONNECT} winSend {
245245 break
246246 }
247247 }
248 set command "send [tk appname] {expr $foo + 1}"
248 set command "send [tk appname] {expr {$foo + 1}}"
249249 list [catch "send \{$interp\} \{$command\}" msg] $msg
250250 } {0 4}
251251 test winSend-6.7 {SendDDEServer - XTYP_EXECUTE} winSend {
255255 break
256256 }
257257 }
258 set command "send [tk appname] {expr 4 / 2}"
258 set command "send [tk appname] {expr {4 / 2}}"
259259 list [catch "send \{$interp\} \{$command\}" msg] $msg
260260 } {0 2}
261261 test winSend-6.8 {SendDDEServer - XTYP_WILDCONNECT} winSend {
385385 } {0 winSend-10.17}
386386 test winSend-10.18 {Tk_DDEObjCmd - services} winSend {
387387 set currentService [list Tk [tk appname]]
388 list [catch {dde services Tk {}} msg] [expr [lsearch $msg $currentService] >= 0]
388 list [catch {dde services Tk {}} msg] [expr {[lsearch $msg $currentService] >= 0}]
389389 } {0 1}
390390
391391 # Get rid of the other app and all of its interps
2626 pack $w.c
2727 for {set y 0} {$y < 8} {incr y} {
2828 for {set x 0} {$x < 40} {incr x} {
29 set color [format #%02x%02x%02x [expr $x*6] [expr $y*30] 0]
30 $w.c create rectangle [expr 10*$x] [expr 20*$y] \
31 [expr 10*$x + 10] [expr 20*$y + 20] -outline {} \
29 set color [format #%02x%02x%02x [expr {$x*6}] [expr {$y*30}] 0]
30 $w.c create rectangle [expr {10*$x}] [expr {20*$y}] \
31 [expr {10*$x + 10}] [expr {20*$y + 20}] -outline {} \
3232 -fill $color
3333 }
3434 }
155155 wm geom .t +0+0
156156 update
157157
158 winfo containing [expr [winfo rootx .t.f]-1] [expr [winfo rooty .t.f]-1]
158 winfo containing [expr {[winfo rootx .t.f]-1}] [expr {[winfo rooty .t.f]-1}]
159159 } -cleanup {
160160 destroy .t
161161 } -result .t
168168 wm geom .t +0+0
169169 update
170170
171 set x [winfo containing -display .t.f [expr [winfo rootx .t]+600] \
172 [expr [winfo rooty .t.f]+450]]
171 set x [winfo containing -display .t.f [expr {[winfo rootx .t]+600}] \
172 [expr {[winfo rooty .t.f]+450}]]
173173 expr {($x == ".") || ($x == "")}
174174 } -cleanup {
175175 destroy .t
363363 } -result {3}
364364 test winfo-11.6 {"winfo visualid" command} -body {
365365 set x [lindex [lindex [winfo visualsa . includeids] 0] 2]
366 expr $x + 2 - $x
366 expr {$x + 2 - $x}
367367 } -result {2}
368368
369369
393393 deleteWindows
394394 } -result {rootx 1 rooty 1}
395395
396 # Windows does not destroy the container when an embedded window is
397 # destroyed. Unix and macOS do destroy it. See ticket [67384bce7d].
398 if {[tk windowingsystem] == "win32"} {
399 set result_13_2 {embedded 0 container 1}
400 } else {
401 set result_13_2 {embedded 0 container 0}
402 }
396403 test winfo-13.2 {destroying embedded toplevel} -setup {
397404 deleteWindows
398405 } -body {
408415 list embedded [winfo exists .emb.b] container [winfo exists .con]
409416 } -cleanup {
410417 deleteWindows
411 } -result {embedded 0 container 1}
418 } -result $result_13_2
412419
413420 test winfo-13.3 {destroying container window} -setup {
414421 deleteWindows
139139 } -result {bad attribute "_": must be -alpha, -topmost, -zoomed, -fullscreen, or -type}
140140 test wm-attributes-1.2.5 {usage} -constraints aqua -returnCodes error -body {
141141 wm attributes . _
142 } -result {bad attribute "_": must be -alpha, -fullscreen, -modified, -notify, -titlepath, -topmost, or -transparent}
142 } -result {bad attribute "_": must be -alpha, -fullscreen, -modified, -notify, -titlepath, -topmost, -transparent, or -type}
143143
144144
145145 ### wm client ###
872872 # we currently have no return info
873873 wm iconphoto . -default
874874 } -result {wrong # args: should be "wm iconphoto window ?-default? image1 ?image2 ...?"}
875 test wm-iconphoto-1.5.1 {usage} -constraints aquaOrWin32 -returnCodes error -body {
876 wm iconphoto . -default [image create photo -file {}]
877 } -match {glob} -result {failed to create an iconphoto with image *}
878 test wm-iconphoto-1.5.2 {usage} -constraints x11 -body {
879 wm iconphoto . -default [image create photo -file {}]
880 } -result {}
875881
876882 # All other iconphoto tests are platform specific
877883
15151521 } -cleanup {
15161522 destroy .t
15171523 } -result {.t .}
1518 test wm-stackorder-5.2 {A normal toplevel can't be\
1519 raised above an overrideredirect toplevel} -body {
1520 toplevel .t
1524 test wm-stackorder-5.2 {A normal toplevel can't be raised above an \
1525 overrideredirect toplevel on unix} -constraints x11 -body {
1526 toplevel .t
1527 tkwait visibility .t
15211528 wm overrideredirect .t 1
15221529 raise .
15231530 update
15261533 } -cleanup {
15271534 destroy .t
15281535 } -result 0
1536 test wm-stackorder-5.2.1 {A normal toplevel can be raised above an \
1537 overrideredirect toplevel on macOS or win} -constraints aquaOrWin32 -body {
1538 toplevel .t
1539 tkwait visibility .t
1540 wm overrideredirect .t 1
1541 raise .
1542 update
1543 raiseDelay
1544 wm stackorder . isabove .t
1545 } -cleanup {
1546 destroy .t
1547 } -result 1
15291548 test wm-stackorder-5.3 {An overrideredirect window\
15301549 can be explicitly lowered} -body {
15311550 toplevel .t
1551 tkwait visibility .t
15321552 wm overrideredirect .t 1
15331553 lower .t
15341554 update
15381558 destroy .t
15391559 } -result 1
15401560
1541 test wm-stackorder-6.1 {An embedded toplevel does not\
1542 appear in the stacking order} -body {
1561 test wm-stackorder-6.1 {An embedded toplevel does not appear in the \
1562 stacking order} -body {
15431563 toplevel .real -container 1
15441564 toplevel .embd -bg blue -use [winfo id .real]
15451565 update
15471567 } -cleanup {
15481568 deleteWindows
15491569 } -result {. .real}
1550
15511570
15521571 stdWindow
15531572
16161635 wm transient .master .master
16171636 } -cleanup {
16181637 deleteWindows
1619 } -result {can't make ".master" its own master}
1638 } -result {setting ".master" as master creates a transient/master cycle}
16201639 test wm-transient-1.8 {usage} -returnCodes error -body {
1640 toplevel .t1
1641 toplevel .t2
1642 toplevel .t3
1643 wm transient .t2 .t1
1644 wm transient .t3 .t2
1645 wm transient .t1 .t3
1646 } -cleanup {
1647 deleteWindows
1648 } -result {setting ".t3" as master creates a transient/master cycle}
1649 test wm-transient-1.9 {usage} -returnCodes error -body {
16211650 toplevel .master
16221651 frame .master.f
16231652 wm transient .master .master.f
16241653 } -cleanup {
16251654 deleteWindows
1626 } -result {can't make ".master" its own master}
1655 } -result {setting ".master" as master creates a transient/master cycle}
16271656
16281657 test wm-transient-2.1 {basic get/set of master} -setup {
16291658 set results [list]
3434 libdir = @libdir@
3535 includedir = @includedir@
3636 datarootdir = @datarootdir@
37 runstatedir = @runstatedir@
3738 mandir = @mandir@
3839
3940 # The following definition can be set to non-null for special systems
394395 tkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \
395396 tkMacOSXDialog.o tkMacOSXDraw.o tkMacOSXEmbed.o tkMacOSXEntry.o \
396397 tkMacOSXEvent.o tkMacOSXFont.o tkMacOSXHLEvents.o tkMacOSXImage.o \
397 tkMacOSXInit.o tkMacOSXKeyboard.o tkMacOSXKeyEvent.o tkMacOSXMenu.o \
398 tkMacOSXInit.o tkMacOSXKeyboard.o tkMacOSXKeyEvent.o \
399 tkMacOSXMenu.o \
398400 tkMacOSXMenubutton.o tkMacOSXMenus.o tkMacOSXMouseEvent.o \
399401 tkMacOSXNotify.o tkMacOSXRegion.o tkMacOSXScrlbr.o tkMacOSXSend.o \
400 tkMacOSXSubwindows.o tkMacOSXWindowEvent.o \
402 tkMacOSXServices.o tkMacOSXSubwindows.o tkMacOSXWindowEvent.o \
401403 tkMacOSXWm.o tkMacOSXXStubs.o \
402404 tkFileFilter.o tkMacWinMenu.o tkPointer.o tkUnix3d.o tkUnixScale.o \
403405 xcolors.o xdraw.o xgc.o ximage.o xutil.o \
520522 $(MAC_OSX_DIR)/tkMacOSXFont.c $(MAC_OSX_DIR)/tkMacOSXHLEvents.c \
521523 $(MAC_OSX_DIR)/tkMacOSXImage.c \
522524 $(MAC_OSX_DIR)/tkMacOSXInit.c $(MAC_OSX_DIR)/tkMacOSXKeyboard.c \
523 $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c $(MAC_OSX_DIR)/tkMacOSXMenu.c \
525 $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c \
526 $(MAC_OSX_DIR)/tkMacOSXMenu.c \
524527 $(MAC_OSX_DIR)/tkMacOSXMenubutton.c $(MAC_OSX_DIR)/tkMacOSXMenus.c \
525528 $(MAC_OSX_DIR)/tkMacOSXMouseEvent.c $(MAC_OSX_DIR)/tkMacOSXNotify.c \
526529 $(MAC_OSX_DIR)/tkMacOSXRegion.c $(MAC_OSX_DIR)/tkMacOSXScrlbr.c \
530 $(MAC_OSX_DIR)/tkMacOSXServices.c \
527531 $(MAC_OSX_DIR)/tkMacOSXSend.c $(MAC_OSX_DIR)/tkMacOSXSubwindows.c \
528532 $(MAC_OSX_DIR)/tkMacOSXTest.c $(MAC_OSX_DIR)/tkMacOSXWindowEvent.c \
529533 $(MAC_OSX_DIR)/tkMacOSXWm.c $(MAC_OSX_DIR)/tkMacOSXXStubs.c \
13121316 tkMacOSXSend.o: $(MAC_OSX_DIR)/tkMacOSXSend.c
13131317 $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSend.c
13141318
1319 tkMacOSXServices.o: $(MAC_OSX_DIR)/tkMacOSXServices.c
1320 $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXServices.c
1321
13151322 tkMacOSXSubwindows.o: $(MAC_OSX_DIR)/tkMacOSXSubwindows.c
13161323 $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXSubwindows.c
13171324
15631570 cp -p $(GENERIC_DIR)/*.decls $(DISTDIR)/generic
15641571 cp -p $(GENERIC_DIR)/README $(DISTDIR)/generic
15651572 cp -p $(TOP_DIR)/changes $(TOP_DIR)/ChangeLog \
1566 $(TOP_DIR)/ChangeLog.2??? $(TOP_DIR)/README \
1573 $(TOP_DIR)/ChangeLog.2??? $(TOP_DIR)/README.md \
15671574 $(TOP_DIR)/license.terms $(DISTDIR)
15681575 rm -f $(DISTDIR)/generic/blt*.[ch]
15691576 mkdir $(DISTDIR)/generic/ttk
55 specific to UNIX.
66
77 The information in this file is maintained at:
8 http://www.tcl.tk/doc/howto/compile.html
8 https://www.tcl-lang.org//doc/howto/compile.html
99
1010 For information on platforms where Tcl/Tk is known to compile, along with any
1111 porting notes for getting it to work on those platforms, see:
12 http://www.tcl.tk/software/tcltk/platforms.html
12 https://www.tcl-lang.org//software/tcltk/platforms.html
1313
1414 The rest of this file contains instructions on how to do this. The release
1515 should compile and run either "out of the box" or with trivial changes on any
13371337 TK_VERSION=8.6
13381338 TK_MAJOR_VERSION=8
13391339 TK_MINOR_VERSION=6
1340 TK_PATCH_LEVEL=".9"
1340 TK_PATCH_LEVEL=".10"
13411341 VERSION=${TK_VERSION}
13421342 LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
13431343
14141414 for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
14151415 `ls -d /Library/Frameworks 2>/dev/null` \
14161416 `ls -d /Network/Library/Frameworks 2>/dev/null` \
1417 `ls -d /System/Library/Frameworks 2>/dev/null` \
14181417 ; do
14191418 if test -f "$i/Tcl.framework/tclConfig.sh" ; then
14201419 ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
14311430 `ls -d /usr/local/lib 2>/dev/null` \
14321431 `ls -d /usr/contrib/lib 2>/dev/null` \
14331432 `ls -d /usr/pkg/lib 2>/dev/null` \
1433 `ls -d /usr/lib/tcl8.6 2>/dev/null` \
14341434 `ls -d /usr/lib 2>/dev/null` \
14351435 `ls -d /usr/lib64 2>/dev/null` \
14361436 `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
42924292 fi
42934293 if test "`uname -s`" = "AIX" ; then
42944294 tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
4295 fi
4296 if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
4297 tcl_cv_sys_version=NetBSD-Debian
42954298 fi
42964299 fi
42974300 fi
56815684 SHLIB_SUFFIX=".dylib"
56825685 DL_OBJS="tclLoadDyld.o"
56835686 DL_LIBS=""
5684 # Don't use -prebind when building for Mac OS X 10.4 or later only:
5685 if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \
5686 "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then
5687
5688 LDFLAGS="$LDFLAGS -prebind"
5689 fi
5690
56915687 LDFLAGS="$LDFLAGS -headerpad_max_install_names"
56925688 echo "$as_me:$LINENO: checking if ld accepts -search_paths_first flag" >&5
56935689 echo $ECHO_N "checking if ld accepts -search_paths_first flag... $ECHO_C" >&6
94609456 /usr/openwin/share/include'
94619457
94629458 if test "$ac_x_includes" = no; then
9463 # Guess where to find include files, by looking for Intrinsic.h.
9459 # Guess where to find include files, by looking for Xlib.h.
94649460 # First, try using that file with no special directory specified.
94659461 cat >conftest.$ac_ext <<_ACEOF
94669462 /* confdefs.h. */
94689464 cat confdefs.h >>conftest.$ac_ext
94699465 cat >>conftest.$ac_ext <<_ACEOF
94709466 /* end confdefs.h. */
9471 #include <X11/Intrinsic.h>
9467 #include <X11/Xlib.h>
94729468 _ACEOF
94739469 if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
94749470 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
94959491 sed 's/^/| /' conftest.$ac_ext >&5
94969492
94979493 for ac_dir in $ac_x_header_dirs; do
9498 if test -r "$ac_dir/X11/Intrinsic.h"; then
9494 if test -r "$ac_dir/X11/Xlib.h"; then
94999495 ac_x_includes=$ac_dir
95009496 break
95019497 fi
95099505 # See if we find them without any special options.
95109506 # Don't add to $LIBS permanently.
95119507 ac_save_LIBS=$LIBS
9512 LIBS="-lXt $LIBS"
9508 LIBS="-lX11 $LIBS"
95139509 cat >conftest.$ac_ext <<_ACEOF
95149510 /* confdefs.h. */
95159511 _ACEOF
95169512 cat confdefs.h >>conftest.$ac_ext
95179513 cat >>conftest.$ac_ext <<_ACEOF
95189514 /* end confdefs.h. */
9519 #include <X11/Intrinsic.h>
9515 #include <X11/Xlib.h>
95209516 int
95219517 main ()
95229518 {
9523 XtMalloc (0)
9519 XrmInitialize ()
95249520 ;
95259521 return 0;
95269522 }
1001210008 XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
1001310009 if test "$found_xft" = "no" ; then
1001410010 found_xft=yes
10015 XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
10016 XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
10011 XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
10012 XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
1001710013 fi
1001810014 echo "$as_me:$LINENO: result: $found_xft" >&5
1001910015 echo "${ECHO_T}$found_xft" >&6
1093710933 TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
1093810934 fi
1093910935
10940 TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
10936 test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
1094110937 PRIVATE_INCLUDE_DIR='$(includedir)'
1094210938 HTML_DIR='$(DISTDIR)/html'
1094310939 TK_PKG_DIR='tk$(VERSION)'
2424 TK_VERSION=8.6
2525 TK_MAJOR_VERSION=8
2626 TK_MINOR_VERSION=6
27 TK_PATCH_LEVEL=".9"
27 TK_PATCH_LEVEL=".10"
2828 VERSION=${TK_VERSION}
2929 LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
3030
469469 XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
470470 if test "$found_xft" = "no" ; then
471471 found_xft=yes
472 XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
473 XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
472 XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
473 XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
474474 fi
475475 AC_MSG_RESULT([$found_xft])
476476 dnl make sure that compiling against Xft header file doesn't bomb
662662 TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
663663 fi
664664
665 TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
665 test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
666666 PRIVATE_INCLUDE_DIR='$(includedir)'
667667 HTML_DIR='$(DISTDIR)/html'
668668 TK_PKG_DIR='tk$(VERSION)'
9191 exit 2 ;;
9292 esac
9393
94 Name=`basename $ManPage .$Section`
9495 SrcDir=`dirname $ManPage`
9596
9697 ########################################################################
9798 ### Process Page to Create Target Pages
9899 ###
100
101 Specials="FindPhoto FontId MeasureChar"
102 for n in $Specials; do
103 if [ "$Name" = "$n" ] ; then
104 Names="$n $Names"
105 fi
106 done
99107
100108 First=""
101109 for Target in $Names; do
105113 First=$Target
106114 sed -e "/man\.macros/r $SrcDir/man.macros" -e "/man\.macros/d" \
107115 $ManPage > $Dir/$First
108 chmod 444 $Dir/$First
116 chmod 644 $Dir/$First
109117 $Gzip $Dir/$First
110118 else
111119 ln $SymOrLoc$First$Gz $Dir/$Target$Gz
7676 for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
7777 `ls -d /Library/Frameworks 2>/dev/null` \
7878 `ls -d /Network/Library/Frameworks 2>/dev/null` \
79 `ls -d /System/Library/Frameworks 2>/dev/null` \
8079 ; do
8180 if test -f "$i/Tcl.framework/tclConfig.sh" ; then
8281 ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
9392 `ls -d /usr/local/lib 2>/dev/null` \
9493 `ls -d /usr/contrib/lib 2>/dev/null` \
9594 `ls -d /usr/pkg/lib 2>/dev/null` \
95 `ls -d /usr/lib/tcl8.6 2>/dev/null` \
9696 `ls -d /usr/lib 2>/dev/null` \
9797 `ls -d /usr/lib64 2>/dev/null` \
9898 `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
209209 for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
210210 `ls -d /Library/Frameworks 2>/dev/null` \
211211 `ls -d /Network/Library/Frameworks 2>/dev/null` \
212 `ls -d /System/Library/Frameworks 2>/dev/null` \
213212 ; do
214213 if test -f "$i/Tk.framework/tkConfig.sh" ; then
215214 ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
226225 `ls -d /usr/local/lib 2>/dev/null` \
227226 `ls -d /usr/contrib/lib 2>/dev/null` \
228227 `ls -d /usr/pkg/lib 2>/dev/null` \
228 `ls -d /usr/lib/tk8.6 2>/dev/null` \
229229 `ls -d /usr/lib 2>/dev/null` \
230230 `ls -d /usr/lib64 2>/dev/null` \
231231 `ls -d /usr/local/lib/tk8.6 2>/dev/null` \
926926 fi
927927 if test "`uname -s`" = "AIX" ; then
928928 tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
929 fi
930 if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
931 tcl_cv_sys_version=NetBSD-Debian
929932 fi
930933 fi
931934 fi
16011604 SHLIB_SUFFIX=".dylib"
16021605 DL_OBJS="tclLoadDyld.o"
16031606 DL_LIBS=""
1604 # Don't use -prebind when building for Mac OS X 10.4 or later only:
1605 AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
1606 "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
1607 LDFLAGS="$LDFLAGS -prebind"])
16081607 LDFLAGS="$LDFLAGS -headerpad_max_install_names"
16091608 AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
16101609 tcl_cv_ld_search_paths_first, [
26822681 #
26832682 #--------------------------------------------------------------------
26842683
2685 AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [AC_CHECK_FUNC(gethostbyaddr_r, [
2684 AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [
2685 # Avoids picking hidden internal symbol from libc
2686 SC_TCL_GETHOSTBYADDR_R_DECL
2687
2688 if test "$tcl_cv_api_gethostbyaddr_r" = yes; then
2689 SC_TCL_GETHOSTBYADDR_R_TYPE
2690 fi
2691 ])
2692
2693 AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_DECL], [AC_CHECK_DECLS(gethostbyaddr_r, [
2694 tcl_cv_api_gethostbyaddr_r=yes],[tcl_cv_api_gethostbyaddr_r=no],[#include <netdb.h>])
2695 ])
2696
2697 AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_TYPE], [AC_CHECK_FUNC(gethostbyaddr_r, [
26862698 AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [
26872699 AC_TRY_COMPILE([
26882700 #include <netdb.h>
27432755 # Results:
27442756 #
27452757 # Might define the following vars:
2746 # HAVE_GETHOSTBYADDR_R
2747 # HAVE_GETHOSTBYADDR_R_3
2748 # HAVE_GETHOSTBYADDR_R_5
2749 # HAVE_GETHOSTBYADDR_R_6
2750 #
2751 #--------------------------------------------------------------------
2752
2753 AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [AC_CHECK_FUNC(gethostbyname_r, [
2758 # HAVE_GETHOSTBYNAME_R
2759 # HAVE_GETHOSTBYNAME_R_3
2760 # HAVE_GETHOSTBYNAME_R_5
2761 # HAVE_GETHOSTBYNAME_R_6
2762 #
2763 #--------------------------------------------------------------------
2764
2765 AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [
2766 # Avoids picking hidden internal symbol from libc
2767 SC_TCL_GETHOSTBYNAME_R_DECL
2768
2769 if test "$tcl_cv_api_gethostbyname_r" = yes; then
2770 SC_TCL_GETHOSTBYNAME_R_TYPE
2771 fi
2772 ])
2773
2774 AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_DECL], [AC_CHECK_DECLS(gethostbyname_r, [
2775 tcl_cv_api_gethostbyname_r=yes],[tcl_cv_api_gethostbyname_r=no],[#include <netdb.h>])
2776 ])
2777
2778 AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_TYPE], [AC_CHECK_FUNC(gethostbyname_r, [
27542779 AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [
27552780 AC_TRY_COMPILE([
27562781 #include <netdb.h>
66
77 Name: The Tk Toolkit
88 Description: Tk is a cross-platform graphical user interface toolkit, the standard GUI not only for Tcl, but for many other dynamic languages as well.
9 URL: http://www.tcl.tk/
9 URL: https://www.tcl-lang.org/
1010 Version: @TK_VERSION@@TK_PATCH_LEVEL@
1111 Requires: tcl >= 8.6
1212 Libs: -L${libdir} @TK_LIB_FLAG@ @TK_STUB_LIB_FLAG@
33
44 Name: tk
55 Summary: Tk graphical toolkit for the Tcl scripting language.
6 Version: 8.6.9
6 Version: 8.6.10
77 Release: 2
88 License: BSD
99 Group: Development/Languages
1010 Source: http://prdownloads.sourceforge.net/tcl/tk%{version}-src.tar.gz
11 URL: http://www.tcl.tk/
11 URL: https://www.tcl-lang.org/
1212 Buildroot: /var/tmp/%{name}%{version}
1313 Buildrequires: XFree86-devel tcl >= %version
1414 Requires: tcl >= %version
4747 {
4848 UnixBorder *borderPtr = ckalloc(sizeof(UnixBorder));
4949
50 borderPtr->solidGC = None;
50 borderPtr->solidGC = NULL;
5151 return (TkBorder *) borderPtr;
5252 }
5353
7575 UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;
7676 Display *display = DisplayOfScreen(borderPtr->screen);
7777
78 if (unixBorderPtr->solidGC != None) {
78 if (unixBorderPtr->solidGC != NULL) {
7979 Tk_FreeGC(display, unixBorderPtr->solidGC);
8080 }
8181 }
123123 GC left, right;
124124 Display *display = Tk_Display(tkwin);
125125
126 if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT)) {
126 if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT)) {
127127 TkpGetShadows(borderPtr, tkwin);
128128 }
129129
158158 (unsigned) width, (unsigned) height);
159159 } else if (relief == TK_RELIEF_SOLID) {
160160 UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;
161 if (unixBorderPtr->solidGC == None) {
161 if (unixBorderPtr->solidGC == NULL) {
162162 XGCValues gcValues;
163163
164164 gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);
215215 Display *display = Tk_Display(tkwin);
216216 int bottom, halfway, x1, x2, x1Delta, x2Delta;
217217 UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;
218 GC topGC = None, bottomGC = None;
218 GC topGC = NULL, bottomGC = NULL;
219219 /* Initializations needed only to prevent
220220 * compiler warnings. */
221221
222 if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT) &&
222 if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT) &&
223223 (relief != TK_RELIEF_SOLID)) {
224224 TkpGetShadows(borderPtr, tkwin);
225225 }
245245 bottomGC = borderPtr->darkGC;
246246 break;
247247 case TK_RELIEF_SOLID:
248 if (unixBorderPtr->solidGC == None) {
248 if (unixBorderPtr->solidGC == NULL) {
249249 XGCValues gcValues;
250250
251251 gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);
343343 int r, g, b;
344344 XGCValues gcValues;
345345
346 if (borderPtr->lightGC != None) {
346 if (borderPtr->lightGC != NULL) {
347347 return;
348348 }
349349 stressed = TkpCmapStressed(tkwin, borderPtr->colormap);
442442 }
443443
444444 if (borderPtr->shadow == None) {
445 borderPtr->shadow = Tk_GetBitmap((Tcl_Interp *) NULL, tkwin,
445 borderPtr->shadow = Tk_GetBitmap(NULL, tkwin,
446446 Tk_GetUid("gray50"));
447447 if (borderPtr->shadow == None) {
448448 Tcl_Panic("TkpGetShadows couldn't allocate bitmap for border");
8484 */
8585
8686 visual = tkColPtr->visual;
87 if ((visual->class != StaticGray) && (visual->class != StaticColor)
87 if ((visual->c_class != StaticGray) && (visual->c_class != StaticColor)
8888 && (tkColPtr->color.pixel != BlackPixelOfScreen(screen))
8989 && (tkColPtr->color.pixel != WhitePixelOfScreen(screen))) {
9090 Tk_ErrorHandler handler;
156156 }
157157 if (strlen(name) > 99) {
158158 /* Don't bother to parse this. [Bug 2809525]*/
159 return (TkColor *) NULL;
159 return NULL;
160160 } else if (XAllocNamedColor(display, colormap, name, &screen, &color) != 0) {
161161 DeleteStressedCmap(display, colormap);
162162 } else {
3030 #define ACTIVE_BG "#ececec"
3131 #define SELECT_BG "#c3c3c3"
3232 #define TROUGH "#b3b3b3"
33 #define CHECK_INDICATOR WHITE
34 #define MENU_INDICATOR BLACK
33 #define INDICATOR WHITE
3534 #define DISABLED "#a3a3a3"
3635
3736 /*
7877 #define DEF_LABCHKRAD_RELIEF "flat"
7978 #define DEF_BUTTON_REPEAT_DELAY "0"
8079 #define DEF_BUTTON_REPEAT_INTERVAL "0"
81 #define DEF_BUTTON_SELECT_COLOR CHECK_INDICATOR
80 #define DEF_BUTTON_SELECT_COLOR INDICATOR
8281 #define DEF_BUTTON_SELECT_MONO BLACK
8382 #define DEF_BUTTON_SELECT_IMAGE ((char *) NULL)
8483 #define DEF_BUTTON_STATE "normal"
243242 #define DEF_MENU_ENTRY_ACTIVE_FG ((char *) NULL)
244243 #define DEF_MENU_ENTRY_ACCELERATOR ((char *) NULL)
245244 #define DEF_MENU_ENTRY_BG ((char *) NULL)
246 #define DEF_MENU_ENTRY_BITMAP None
245 #define DEF_MENU_ENTRY_BITMAP NULL
247246 #define DEF_MENU_ENTRY_COLUMN_BREAK "0"
248247 #define DEF_MENU_ENTRY_COMMAND ((char *) NULL)
249248 #define DEF_MENU_ENTRY_COMPOUND "none"
283282 #define DEF_MENU_FG BLACK
284283 #define DEF_MENU_POST_COMMAND ""
285284 #define DEF_MENU_RELIEF "raised"
286 #define DEF_MENU_SELECT_COLOR MENU_INDICATOR
285 #define DEF_MENU_SELECT_COLOR BLACK
287286 #define DEF_MENU_SELECT_MONO BLACK
288287 #define DEF_MENU_TAKE_FOCUS "0"
289288 #define DEF_MENU_TEAROFF "1"
514513 #define DEF_CANVTEXT_FONT "TkDefaultFont"
515514
516515 /*
516 * Defaults for canvas items
517 * (arcs, bitmaps, lines, polygons, rectangles, and ovals):
518 */
519
520 #define DEF_CANVBMAP_FG BLACK
521 #define DEF_CANVITEM_OUTLINE BLACK
522
523 /*
517524 * Defaults for toplevels (most of the defaults for frames also apply
518525 * to toplevels):
519526 */
4141 * process. */
4242 } Container;
4343
44 typedef struct ThreadSpecificData {
44 typedef struct {
4545 Container *firstContainerPtr;
4646 /* First in list of all containers managed by
4747 * this process. */
502502 Tk_ErrorHandler errHandler;
503503
504504 if (eventPtr->type == ConfigureNotify) {
505 /*
506 * Send a ConfigureNotify to the embedded application.
507 */
508
509 if (containerPtr->embeddedPtr != None) {
510 TkDoConfigureNotify(containerPtr->embeddedPtr);
511 }
505512 if (containerPtr->wrapper != None) {
513
506514 /*
507515 * Ignore errors, since the embedded application could have
508516 * deleted its window.
872880 Container *containerPtr;
873881 Tcl_DString dString;
874882 char buffer[50];
883 Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
875884 ThreadSpecificData *tsdPtr =
876885 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
877886
883892 Tcl_DStringInit(&dString);
884893 for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;
885894 containerPtr = containerPtr->nextPtr) {
895 if (containerPtr->embeddedPtr != NULL) {
896 embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;
897 }
898 if (containerPtr->parentPtr != NULL) {
899 parentInterp = containerPtr->parentPtr->mainPtr->interp;
900 }
901 if (embeddedInterp != interp && parentInterp != interp) {
902 continue;
903 }
886904 Tcl_DStringStartSublist(&dString);
905 /* Parent id */
887906 if (containerPtr->parent == None) {
888907 Tcl_DStringAppendElement(&dString, "");
889908 } else if (all) {
890 sprintf(buffer, "0x%x", (int) containerPtr->parent);
909 sprintf(buffer, "0x%lx", containerPtr->parent);
891910 Tcl_DStringAppendElement(&dString, buffer);
892911 } else {
893912 Tcl_DStringAppendElement(&dString, "XXX");
894913 }
895 if (containerPtr->parentPtr == NULL) {
914 /* Parent pathName */
915 if (containerPtr->parentPtr == NULL ||
916 parentInterp != interp) {
896917 Tcl_DStringAppendElement(&dString, "");
897918 } else {
898919 Tcl_DStringAppendElement(&dString,
899920 containerPtr->parentPtr->pathName);
900921 }
922 /* Wrapper */
901923 if (containerPtr->wrapper == None) {
902924 Tcl_DStringAppendElement(&dString, "");
903925 } else if (all) {
904 sprintf(buffer, "0x%x", (int) containerPtr->wrapper);
926 sprintf(buffer, "0x%lx", containerPtr->wrapper);
905927 Tcl_DStringAppendElement(&dString, buffer);
906928 } else {
907929 Tcl_DStringAppendElement(&dString, "XXX");
908930 }
909 if (containerPtr->embeddedPtr == NULL) {
931 /* Embedded window pathName */
932 if (containerPtr->embeddedPtr == NULL ||
933 embeddedInterp != interp) {
910934 Tcl_DStringAppendElement(&dString, "");
911935 } else {
912936 Tcl_DStringAppendElement(&dString,
2222 * the current thread.
2323 */
2424
25 typedef struct ThreadSpecificData {
25 typedef struct {
2626 int initialized;
2727 } ThreadSpecificData;
2828 static Tcl_ThreadDataKey dataKey;
165165 if (display == NULL) {
166166 /*fprintf(stderr,"event=%d error=%d major=%d minor=%d reason=%d\nDisabling xkb\n",
167167 event, error, major, minor, reason);*/
168 display = XOpenDisplay(displayNameStr);
168 display = XOpenDisplay(displayNameStr);
169169 } else {
170170 use_xkb = TK_DISPLAY_USE_XKB;
171171 /*fprintf(stderr, "Using xkb %d.%d\n", major, minor);*/
185185 #endif
186186 Tcl_CreateFileHandler(ConnectionNumber(display), TCL_READABLE,
187187 DisplayFileProc, dispPtr);
188
189 /*
190 * Observed weird WidthMMOfScreen() in X on Wayland on a
191 * Fedora 30/i386 running in a VM. Fallback to 75 dpi,
192 * otherwise many other strange things may happen later.
193 * See: [https://core.tcl-lang.org/tk/tktview?name=a01b6f7227]
194 */
195 if (WidthMMOfScreen(DefaultScreenOfDisplay(display)) <= 0) {
196 int mm;
197
198 mm = WidthOfScreen(DefaultScreenOfDisplay(display)) * (25.4 / 75.0);
199 WidthMMOfScreen(DefaultScreenOfDisplay(display)) = mm;
200 }
201 if (HeightMMOfScreen(DefaultScreenOfDisplay(display)) <= 0) {
202 int mm;
203
204 mm = HeightOfScreen(DefaultScreenOfDisplay(display)) * (25.4 / 75.0);
205 HeightMMOfScreen(DefaultScreenOfDisplay(display)) = mm;
206 }
207
208 /*
209 * Key map info must be available immediately, because of "send event".
210 */
211 TkpInitKeymapInfo(dispPtr);
212
188213 return dispPtr;
189214 }
190215
3636
3737 #define FONTMAP_SHIFT 10
3838
39 #define FONTMAP_PAGES (1 << (sizeof(Tcl_UniChar)*8 - FONTMAP_SHIFT))
4039 #define FONTMAP_BITSPERPAGE (1 << FONTMAP_SHIFT)
40 #define FONTMAP_PAGES (0x30000 / FONTMAP_BITSPERPAGE)
4141
4242 typedef struct FontFamily {
4343 struct FontFamily *nextPtr; /* Next in list of all known font families. */
152152 TkXLFDAttributes xa;
153153 } FontAttributes;
154154
155 typedef struct ThreadSpecificData {
155 typedef struct {
156156 FontFamily *fontFamilyList; /* The list of font families that are
157157 * currently loaded. As screen fonts are
158158 * loaded, this list grows to hold information
170170 * encodings into the names expected by the Tcl encoding package.
171171 */
172172
173 static EncodingAlias encodingAliases[] = {
173 static const EncodingAlias encodingAliases[] = {
174174 {"gb2312-raw", "gb2312*"},
175175 {"big5", "big5*"},
176176 {"cns11643-1", "cns11643*-1"},
185185 {"tis620", "tis620*"},
186186 {"ksc5601", "ksc5601*"},
187187 {"dingbats", "*dingbats"},
188 #ifdef WORDS_BIGENDIAN
189 {"unicode", "iso10646-1"},
190 #else
191 /*
192 * ucs-2be is needed if native order isn't BE.
193 */
194188 {"ucs-2be", "iso10646-1"},
195 #endif
196189 {NULL, NULL}
197190 };
198191
245238 static void ReleaseFont(UnixFont *fontPtr);
246239 static void ReleaseSubFont(Display *display, SubFont *subFontPtr);
247240 static int SeenName(const char *name, Tcl_DString *dsPtr);
248 #ifndef WORDS_BIGENDIAN
249241 static int Ucs2beToUtfProc(ClientData clientData, const char*src,
250242 int srcLen, int flags, Tcl_EncodingState*statePtr,
251243 char *dst, int dstLen, int *srcReadPtr,
254246 int srcLen, int flags, Tcl_EncodingState*statePtr,
255247 char *dst, int dstLen, int *srcReadPtr,
256248 int *dstWrotePtr, int *dstCharsPtr);
257 #endif
258249
259250 /*
260251 *-------------------------------------------------------------------------
319310 {
320311 ThreadSpecificData *tsdPtr =
321312 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
322 Tcl_EncodingType type;
323313 SubFont dummy;
324314 int i;
315 Tcl_Encoding ucs2;
325316
326317 if (tsdPtr->controlFamily.encoding == NULL) {
327 type.encodingName = "X11ControlChars";
328 type.toUtfProc = ControlUtfProc;
329 type.fromUtfProc = ControlUtfProc;
330 type.freeProc = NULL;
331 type.clientData = NULL;
332 type.nullSize = 0;
333
318
319 Tcl_EncodingType type = {"X11ControlChars", ControlUtfProc, ControlUtfProc, NULL, NULL, 0};
334320 tsdPtr->controlFamily.refCount = 2;
335321 tsdPtr->controlFamily.encoding = Tcl_CreateEncoding(&type);
336322 tsdPtr->controlFamily.isTwoByteFont = 0;
342328 FontMapInsert(&dummy, i + 0x80);
343329 }
344330
345 #ifndef WORDS_BIGENDIAN
346331 /*
347332 * UCS-2BE is unicode (UCS-2) in big-endian format. Define this if
348 * native order isn't BE. It is used in iso10646 fonts.
333 * if it doesn't exist yet. It is used in iso10646 fonts.
349334 */
350335
351 type.encodingName = "ucs-2be";
352 type.toUtfProc = Ucs2beToUtfProc;
353 type.fromUtfProc = UtfToUcs2beProc;
354 type.freeProc = NULL;
355 type.clientData = NULL;
356 type.nullSize = 2;
357 Tcl_CreateEncoding(&type);
358 #endif
336 ucs2 = Tcl_GetEncoding(NULL, "ucs-2be");
337 if (ucs2 == NULL) {
338 Tcl_EncodingType ucs2type = {"ucs-2be", Ucs2beToUtfProc, UtfToUcs2beProc, NULL, NULL, 2};
339 Tcl_CreateEncoding(&ucs2type);
340 } else {
341 Tcl_FreeEncoding(ucs2);
342 }
359343 Tcl_CreateThreadExitHandler(FontPkgCleanup, NULL);
360344 }
361345 }
427411 }
428412 src += TkUtfToUniChar(src, &ch);
429413 dst[0] = '\\';
430 if (((size_t) ch < sizeof(mapChars)) && (mapChars[ch] != 0)) {
414 if (((size_t)ch < sizeof(mapChars)) && (mapChars[ch] != 0)) {
431415 dst[1] = mapChars[ch];
432416 dst += 2;
433 } else if (ch < 256) {
417 } else if ((size_t)ch < 256) {
434418 dst[1] = 'x';
435419 dst[2] = hexChars[(ch >> 4) & 0xf];
436420 dst[3] = hexChars[ch & 0xf];
437421 dst += 4;
438 } else if (ch < 0x10000) {
422 } else if ((size_t)ch < 0x10000) {
439423 dst[1] = 'u';
440424 dst[2] = hexChars[(ch >> 12) & 0xf];
441425 dst[3] = hexChars[(ch >> 8) & 0xf];
458442 return result;
459443 }
460444
461 #ifndef WORDS_BIGENDIAN
462445 /*
463446 *-------------------------------------------------------------------------
464447 *
465448 * Ucs2beToUtfProc --
466449 *
467450 * Convert from UCS-2BE (big-endian 16-bit Unicode) to UTF-8.
468 * This is only defined on LE machines.
469451 *
470452 * Results:
471453 * Returns TCL_OK if conversion was successful.
514496 result = TCL_CONVERT_MULTIBYTE;
515497 srcLen--;
516498 }
499 /* If last code point is a high surrogate, we cannot handle that yet */
500 if ((srcLen >= 2) && ((src[srcLen - 2] & 0xFC) == 0xD8)) {
501 result = TCL_CONVERT_MULTIBYTE;
502 srcLen -= 2;
503 }
517504
518505 srcStart = src;
519506 srcEnd = src + srcLen;
532519 * UCS-2BE. We know this is an LE->BE swap.
533520 */
534521
535 dst += Tcl_UniCharToUtf(htons(*((short *)src)), dst);
522 dst += TkUniCharToUtf(htons(*((short *)src)), dst);
536523 src += 2 /* sizeof(UCS-2) */;
537524 }
538525
588575 {
589576 const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
590577 int result, numChars;
591 Tcl_UniChar ch;
578 Tcl_UniChar *chPtr = (Tcl_UniChar *)statePtr;
579
580 if (flags & TCL_ENCODING_START) {
581 *statePtr = 0;
582 }
592583
593584 srcStart = src;
594585 srcEnd = src + srcLen;
607598 * If there is more string to follow, this will ensure that the
608599 * last UTF-8 character in the source buffer hasn't been cut off.
609600 */
610
611601 result = TCL_CONVERT_MULTIBYTE;
612602 break;
613603 }
614604 if (dst > dstEnd) {
615605 result = TCL_CONVERT_NOSPACE;
616606 break;
617 }
618 src += Tcl_UtfToUniChar(src, &ch);
607 }
608 src += Tcl_UtfToUniChar(src, chPtr);
619609
620610 /*
621611 * Ensure big-endianness (store big bits first).
623613 * sure to work in char* for Tcl_UtfToUniChar alignment. [Bug 1122671]
624614 */
625615
626 *dst++ = (ch >> 8);
627 *dst++ = (ch & 0xFF);
616
617 *dst++ = (char)(*chPtr >> 8);
618 *dst++ = (char)*chPtr;
628619 }
629620 *srcReadPtr = src - srcStart;
630621 *dstWrotePtr = dst - dstStart;
631622 *dstCharsPtr = numChars;
632623 return result;
633624 }
634 #endif /* WORDS_BIGENDIAN */
635625
636626 /*
637627 *---------------------------------------------------------------------------
19851975 SubFont *subFontPtr;
19861976 Tcl_DString ds;
19871977
1988 if (FontMapLookup(&fontPtr->subFontArray[0], ch)) {
1989 return &fontPtr->subFontArray[0];
1990 }
1991
1992 for (i = 1; i < fontPtr->numSubFonts; i++) {
1978 if (ch < 0 || ch > 0x30000) {
1979 ch = 0xfffd;
1980 }
1981
1982 for (i = 0; i < fontPtr->numSubFonts; i++) {
19931983 if (FontMapLookup(&fontPtr->subFontArray[i], ch)) {
19941984 return &fontPtr->subFontArray[i];
19951985 }
21392129 {
21402130 int row, bitOffset;
21412131
2132 if (ch < 0 || ch >= 0x30000) {
2133 return 0;
2134 }
21422135 row = ch >> FONTMAP_SHIFT;
21432136 if (subFontPtr->fontMap[row] == NULL) {
21442137 FontMapLoadPage(subFontPtr, row);
21792172 {
21802173 int row, bitOffset;
21812174
2182 row = ch >> FONTMAP_SHIFT;
2183 if (subFontPtr->fontMap[row] == NULL) {
2184 FontMapLoadPage(subFontPtr, row);
2185 }
2186 bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
2187 subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
2175 if (ch >= 0 && ch < 0x30000) {
2176 row = ch >> FONTMAP_SHIFT;
2177 if (subFontPtr->fontMap[row] == NULL) {
2178 FontMapLoadPage(subFontPtr, row);
2179 }
2180 bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
2181 subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
2182 }
21882183 }
21892184
21902185 /*
30143009 GetEncodingAlias(
30153010 const char *name) /* The name to look up. */
30163011 {
3017 EncodingAlias *aliasPtr;
3012 const EncodingAlias *aliasPtr;
30183013
30193014 for (aliasPtr = encodingAliases; aliasPtr->aliasPattern != NULL; ) {
3020 if (Tcl_StringMatch(name, aliasPtr->aliasPattern)) {
3015 if (Tcl_StringCaseMatch(name, aliasPtr->aliasPattern, 0)) {
30213016 return aliasPtr->realName;
30223017 }
30233018 aliasPtr++;
207207 Tcl_DStringValue(&buf)[len] = '\0';
208208
209209 if (len == 1) {
210 len = Tcl_UniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0],
210 len = TkUniCharToUtf((unsigned char) Tcl_DStringValue(&buf)[0],
211211 Tcl_DStringValue(dsPtr));
212212 Tcl_DStringSetLength(dsPtr, len);
213213 } else {
856856 if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
857857 int len;
858858
859 /*
860 * Do the unicode call just to prevent overruns.
861 */
862
863 Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len);
859 len = Tcl_GetCharLength(mePtr->labelPtr);
864860 if (mePtr->underline < len) {
865861 int activeBorderWidth, leftEdge;
866862 const char *label, *start, *end;
888884 *
889885 * TkpPostMenu --
890886 *
891 * Posts a menu on the screen
887 * Posts a menu on the screen so that the top left corner of the
888 * specified entry is located at the point (x, y) in screen coordinates.
889 * If the entry parameter is negative, the upper left corner of the
890 * menu itself is placed at the point.
892891 *
893892 * Results:
894893 * None.
903902 TkpPostMenu(
904903 Tcl_Interp *interp,
905904 TkMenu *menuPtr,
906 int x, int y)
907 {
908 return TkPostTearoffMenu(interp, menuPtr, x, y);
905 int x, int y, int index)
906 {
907 return TkpPostTearoffMenu(interp, menuPtr, x, y, index);
908 }
909
910 /*
911 *----------------------------------------------------------------------
912 *
913 * TkpPostTearoffMenu --
914 *
915 * Posts a tearoff menu on the screen so that the top left corner of the
916 * specified entry is located at the point (x, y) in screen coordinates.
917 * If the index parameter is negative, the upper left corner of the menu
918 * itself is placed at the point. On unix this is called when posting
919 * any menu. Adjusts the menu's position so that it fits on the screen,
920 * and maps and raises the menu.
921 *
922 * Results:
923 * Returns a standard Tcl Error.
924 *
925 * Side effects:
926 * The menu is posted.
927 *
928 *----------------------------------------------------------------------
929 */
930
931 int
932 TkpPostTearoffMenu(
933 Tcl_Interp *interp, /* The interpreter of the menu */
934 TkMenu *menuPtr, /* The menu we are posting */
935 int x, int y, int index) /* The root X,Y coordinates where the
936 * specified entry will be posted */
937 {
938 int vRootX, vRootY, vRootWidth, vRootHeight;
939 int result;
940
941 if (index >= menuPtr->numEntries) {
942 index = menuPtr->numEntries - 1;
943 }
944 if (index >= 0) {
945 y -= menuPtr->entries[index]->y;
946 }
947
948 TkActivateMenuEntry(menuPtr, -1);
949 TkRecomputeMenu(menuPtr);
950 result = TkPostCommand(menuPtr);
951 if (result != TCL_OK) {
952 return result;
953 }
954
955 /*
956 * The post commands could have deleted the menu, which means we are dead
957 * and should go away.
958 */
959
960 if (menuPtr->tkwin == NULL) {
961 return TCL_OK;
962 }
963
964 /*
965 * Adjust the position of the menu if necessary to keep it visible on the
966 * screen. There are two special tricks to make this work right:
967 *
968 * 1. If a virtual root window manager is being used then the coordinates
969 * are in the virtual root window of menuPtr's parent; since the menu
970 * uses override-redirect mode it will be in the *real* root window for
971 * the screen, so we have to map the coordinates from the virtual root
972 * (if any) to the real root. Can't get the virtual root from the menu
973 * itself (it will never be seen by the wm) so use its parent instead
974 * (it would be better to have an an option that names a window to use
975 * for this...).
976 * 2. The menu may not have been mapped yet, so its current size might be
977 * the default 1x1. To compute how much space it needs, use its
978 * requested size, not its actual size.
979 */
980
981 Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
982 &vRootWidth, &vRootHeight);
983 vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
984 if (x > vRootX + vRootWidth) {
985 x = vRootX + vRootWidth;
986 }
987 if (x < vRootX) {
988 x = vRootX;
989 }
990 vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
991 if (y > vRootY + vRootHeight) {
992 y = vRootY + vRootHeight;
993 }
994 if (y < vRootY) {
995 y = vRootY;
996 }
997 Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
998 if (!Tk_IsMapped(menuPtr->tkwin)) {
999 Tk_MapWindow(menuPtr->tkwin);
1000 }
1001 TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
1002 return TCL_OK;
9091003 }
9101004
9111005 /*
17201814 }
17211815 windowWidth = x + indicatorSpace + labelWidth + accelWidth
17221816 + 2 * activeBorderWidth + borderWidth;
1723
17241817 windowHeight += borderWidth;
17251818
17261819 /*
9191 border = mbPtr->normalBorder;
9292 }
9393
94 if (mbPtr->image != None) {
94 if (mbPtr->image != NULL) {
9595 Tk_SizeOfImage(mbPtr->image, &width, &height);
9696 haveImage = 1;
9797 } else if (mbPtr->bitmap != None) {
357357 txtHeight = 0;
358358 avgWidth = 0;
359359
360 if (mbPtr->image != None) {
360 if (mbPtr->image != NULL) {
361361 Tk_SizeOfImage(mbPtr->image, &width, &height);
362362 haveImage = 1;
363363 } else if (mbPtr->bitmap != None) {
2727 #else
2828 # include <stdlib.h>
2929 #endif
30 #include <assert.h>
3031 #include <string.h>
3132 #include <sys/types.h>
3233 #include <sys/file.h>
4949 * the information isn't retrievable from the GC.
5050 */
5151
52 typedef struct ThreadSpecificData {
52 typedef struct {
5353 Region clipRegion; /* The clipping region, or None. */
5454 } ThreadSpecificData;
5555 static Tcl_ThreadDataKey dataKey;
6868 TkpFontPkgInit(
6969 TkMainInfo *mainPtr) /* The application being created. */
7070 {
71 static Tcl_Config cfg[] = {
71 static const Tcl_Config cfg[] = {
7272 { "fontsystem", "xft" },
7373 { 0,0 }
7474 };
936936
937937 doUnderlineStrikeout:
938938 if (tsdPtr->clipRegion != None) {
939 XftDrawSetClip(fontPtr->ftDraw, None);
939 XftDrawSetClip(fontPtr->ftDraw, NULL);
940940 }
941941 if (fontPtr->font.fa.underline != 0) {
942942 XFillRectangle(display, drawable, gc, xStart,
11821182
11831183 doUnderlineStrikeout:
11841184 if (tsdPtr->clipRegion != None) {
1185 XftDrawSetClip(fontPtr->ftDraw, None);
1185 XftDrawSetClip(fontPtr->ftDraw, NULL);
11861186 }
11871187 if (fontPtr->font.fa.underline || fontPtr->font.fa.overstrike) {
11881188 XPoint points[5];
2323 static void DisplayHorizontalScale(TkScale *scalePtr,
2424 Drawable drawable, XRectangle *drawnAreaPtr);
2525 static void DisplayHorizontalValue(TkScale *scalePtr,
26 Drawable drawable, double value, int top);
26 Drawable drawable, double value, int top,
27 const char *format);
2728 static void DisplayVerticalScale(TkScale *scalePtr,
2829 Drawable drawable, XRectangle *drawnAreaPtr);
2930 static void DisplayVerticalValue(TkScale *scalePtr,
30 Drawable drawable, double value, int rightEdge);
31 Drawable drawable, double value, int rightEdge,
32 const char *format);
3133
3234 /*
3335 *----------------------------------------------------------------------
149151 for (tickValue = scalePtr->fromValue; ;
150152 tickValue += tickInterval) {
151153 /*
152 * The TkRoundToResolution call gets rid of accumulated
154 * The TkRoundValueToResolution call gets rid of accumulated
153155 * round-off errors, if any.
154156 */
155157
156 tickValue = TkRoundToResolution(scalePtr, tickValue);
158 tickValue = TkRoundValueToResolution(scalePtr, tickValue);
157159 if (scalePtr->toValue >= scalePtr->fromValue) {
158160 if (tickValue > scalePtr->toValue) {
159161 break;
164166 }
165167 }
166168 DisplayVerticalValue(scalePtr, drawable, tickValue,
167 scalePtr->vertTickRightX);
169 scalePtr->vertTickRightX, scalePtr->tickFormat);
168170 }
169171 }
170172 }
175177
176178 if (scalePtr->showValue) {
177179 DisplayVerticalValue(scalePtr, drawable, scalePtr->value,
178 scalePtr->vertValueRightX);
180 scalePtr->vertValueRightX, scalePtr->valueFormat);
179181 }
180182
181183 /*
227229 Tk_GetFontMetrics(scalePtr->tkfont, &fm);
228230 Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
229231 scalePtr->tkfont, scalePtr->label,
230 scalePtr->labelLength, scalePtr->vertLabelX,
231 scalePtr->inset + (3*fm.ascent)/2);
232 scalePtr->labelLength, scalePtr->vertLabelX,
233 scalePtr->inset + (3 * fm.ascent) / 2);
232234 }
233235 }
234236
260262 double value, /* Y-coordinate of number to display,
261263 * specified in application coords, not in
262264 * pixels (we'll compute pixels). */
263 int rightEdge) /* X-coordinate of right edge of text,
265 int rightEdge, /* X-coordinate of right edge of text,
264266 * specified in pixels. */
267 const char *format) /* Format string to use for the value */
265268 {
266269 register Tk_Window tkwin = scalePtr->tkwin;
267270 int y, width, length;
270273
271274 Tk_GetFontMetrics(scalePtr->tkfont, &fm);
272275 y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2;
273 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) {
274 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
276 if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) {
277 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
275278 }
276279 length = (int) strlen(valueString);
277280 width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
281284 * the window.
282285 */
283286
284 if ((y - fm.ascent) < (scalePtr->inset + SPACING)) {
287 if (y - fm.ascent < scalePtr->inset + SPACING) {
285288 y = scalePtr->inset + SPACING + fm.ascent;
286289 }
287 if ((y + fm.descent) > (Tk_Height(tkwin) - scalePtr->inset - SPACING)) {
290 if (y + fm.descent > Tk_Height(tkwin) - scalePtr->inset - SPACING) {
288291 y = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent;
289292 }
290293 Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
323326 {
324327 register Tk_Window tkwin = scalePtr->tkwin;
325328 int x, y, width, height, shadowWidth;
326 double tickValue, tickInterval = scalePtr->tickInterval;
329 double tickInterval = scalePtr->tickInterval;
327330 Tk_3DBorder sliderBorder;
328331
329332 /*
347350
348351 if (tickInterval != 0) {
349352 char valueString[TCL_DOUBLE_SPACE];
350 double ticks, maxTicks;
353 double ticks, maxTicks, tickValue;
351354
352355 /*
353356 * Ensure that we will only draw enough of the tick values such
357360
358361 ticks = fabs((scalePtr->toValue - scalePtr->fromValue)
359362 / tickInterval);
360 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format,
361 scalePtr->fromValue) < 0) {
362 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
363 }
363 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat,
364 scalePtr->fromValue) < 0) {
365 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
366 }
364367 maxTicks = (double) Tk_Width(tkwin)
365368 / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);
366369 if (ticks > maxTicks) {
367 tickInterval *= (ticks / maxTicks);
370 tickInterval *= ticks / maxTicks;
368371 }
369 for (tickValue = scalePtr->fromValue; ;
370 tickValue += tickInterval) {
372 tickValue = scalePtr->fromValue;
373 while (1) {
371374 /*
372 * The TkRoundToResolution call gets rid of accumulated
375 * The TkRoundValueToResolution call gets rid of accumulated
373376 * round-off errors, if any.
374377 */
375378
376 tickValue = TkRoundToResolution(scalePtr, tickValue);
379 tickValue = TkRoundValueToResolution(scalePtr, tickValue);
377380 if (scalePtr->toValue >= scalePtr->fromValue) {
378381 if (tickValue > scalePtr->toValue) {
379382 break;
384387 }
385388 }
386389 DisplayHorizontalValue(scalePtr, drawable, tickValue,
387 scalePtr->horizTickY);
390 scalePtr->horizTickY, scalePtr->tickFormat);
391 tickValue += tickInterval;
388392 }
389393 }
390394 }
395399
396400 if (scalePtr->showValue) {
397401 DisplayHorizontalValue(scalePtr, drawable, scalePtr->value,
398 scalePtr->horizValueY);
402 scalePtr->horizValueY, scalePtr->valueFormat);
399403 }
400404
401405 /*
448452 Tk_GetFontMetrics(scalePtr->tkfont, &fm);
449453 Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
450454 scalePtr->tkfont, scalePtr->label,
451 scalePtr->labelLength, scalePtr->inset + fm.ascent/2,
452 scalePtr->horizLabelY + fm.ascent);
455 scalePtr->labelLength, scalePtr->inset + fm.ascent/2,
456 scalePtr->horizLabelY + fm.ascent);
453457 }
454458 }
455459
481485 double value, /* X-coordinate of number to display,
482486 * specified in application coords, not in
483487 * pixels (we'll compute pixels). */
484 int top) /* Y-coordinate of top edge of text, specified
488 int top, /* Y-coordinate of top edge of text, specified
485489 * in pixels. */
490 const char *format) /* Format string to use for the value */
486491 {
487492 register Tk_Window tkwin = scalePtr->tkwin;
488493 int x, y, length, width;
492497 x = TkScaleValueToPixel(scalePtr, value);
493498 Tk_GetFontMetrics(scalePtr->tkfont, &fm);
494499 y = top + fm.ascent;
495 if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) {
496 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
500 if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) {
501 valueString[TCL_DOUBLE_SPACE - 1] = '\0';
497502 }
498503 length = (int) strlen(valueString);
499504 width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
503508 * the window.
504509 */
505510
506 x -= (width)/2;
507 if (x < (scalePtr->inset + SPACING)) {
511 x -= width / 2;
512 if (x < scalePtr->inset + SPACING) {
508513 x = scalePtr->inset + SPACING;
509514 }
510515
561566 Tcl_Preserve(scalePtr);
562567 if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
563568 Tcl_Preserve(interp);
564 if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
565 scalePtr->value) < 0) {
566 string[TCL_DOUBLE_SPACE - 1] = '\0';
567 }
569 if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat,
570 scalePtr->value) < 0) {
571 string[TCL_DOUBLE_SPACE - 1] = '\0';
572 }
568573 Tcl_DStringInit(&buf);
569574 Tcl_DStringAppend(&buf, scalePtr->command, -1);
570575 Tcl_DStringAppend(&buf, " ", -1);
633638 gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap);
634639 } else {
635640 gc = Tk_GCForColor(
636 Tk_3DBorderColor(scalePtr->highlightBorder), pixmap);
641 Tk_3DBorderColor(scalePtr->highlightBorder), pixmap);
637642 }
638643 Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap);
639644 }
695700 if (y < sliderFirst) {
696701 return TROUGH1;
697702 }
698 if (y < (sliderFirst+scalePtr->sliderLength)) {
703 if (y < sliderFirst + scalePtr->sliderLength) {
699704 return SLIDER;
700705 }
701706 return TROUGH2;
715720 if (x < sliderFirst) {
716721 return TROUGH1;
717722 }
718 if (x < (sliderFirst+scalePtr->sliderLength)) {
723 if (x < sliderFirst + scalePtr->sliderLength) {
719724 return SLIDER;
720725 }
721726 return TROUGH2;
6464 {
6565 UnixScrollbar *scrollPtr = ckalloc(sizeof(UnixScrollbar));
6666
67 scrollPtr->troughGC = None;
68 scrollPtr->copyGC = None;
67 scrollPtr->troughGC = NULL;
68 scrollPtr->copyGC = NULL;
6969
7070 Tk_CreateEventHandler(tkwin,
7171 ExposureMask|StructureNotifyMask|FocusChangeMask,
365365 {
366366 UnixScrollbar *unixScrollPtr = (UnixScrollbar *)scrollPtr;
367367
368 if (unixScrollPtr->troughGC != None) {
368 if (unixScrollPtr->troughGC != NULL) {
369369 Tk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC);
370370 }
371 if (unixScrollPtr->copyGC != None) {
371 if (unixScrollPtr->copyGC != NULL) {
372372 Tk_FreeGC(scrollPtr->display, unixScrollPtr->copyGC);
373373 }
374374 }
405405
406406 gcValues.foreground = scrollPtr->troughColorPtr->pixel;
407407 new = Tk_GetGC(scrollPtr->tkwin, GCForeground, &gcValues);
408 if (unixScrollPtr->troughGC != None) {
408 if (unixScrollPtr->troughGC != NULL) {
409409 Tk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC);
410410 }
411411 unixScrollPtr->troughGC = new;
412 if (unixScrollPtr->copyGC == None) {
412 if (unixScrollPtr->copyGC == NULL) {
413413 gcValues.graphics_exposures = False;
414414 unixScrollPtr->copyGC = Tk_GetGC(scrollPtr->tkwin,
415415 GCGraphicsExposures, &gcValues);
2020 * offset of the next chunk of data to
2121 * transfer. */
2222 Tcl_EncodingState state; /* The encoding state needed across chunks. */
23 char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character
23 char buffer[4]; /* A buffer to hold part of a UTF character
2424 * that is split across chunks.*/
2525 } ConvertInfo;
2626
6767 * currently pending. */
6868 } IncrInfo;
6969
70 typedef struct ThreadSpecificData {
70 typedef struct {
7171 IncrInfo *pendingIncrs; /* List of all incr structures currently
7272 * active. */
7373 } ThreadSpecificData;
445445 * Preserve any left-over bytes.
446446 */
447447
448 if (srcLen > TCL_UTF_MAX) {
448 if (srcLen > 3) {
449449 Tcl_Panic("selection conversion left too many bytes unconverted");
450450 }
451451 memcpy(incrPtr->converts[i].buffer, src, (size_t) srcLen+1);
9696 * NULL means end of list. */
9797 } PendingCommand;
9898
99 typedef struct ThreadSpecificData {
99 typedef struct {
100100 PendingCommand *pendingCommands;
101101 /* List of all commands currently being waited
102102 * for. */
979979
980980 if (winPtr->classUid != NULL) {
981981 XClassHint *classPtr;
982 Tcl_DString name, class;
982 Tcl_DString name, ds;
983983
984984 Tcl_UtfToExternalDString(NULL, winPtr->nameUid, -1, &name);
985 Tcl_UtfToExternalDString(NULL, winPtr->classUid, -1, &class);
985 Tcl_UtfToExternalDString(NULL, winPtr->classUid, -1, &ds);
986986 classPtr = XAllocClassHint();
987987 classPtr->res_name = Tcl_DStringValue(&name);
988 classPtr->res_class = Tcl_DStringValue(&class);
988 classPtr->res_class = Tcl_DStringValue(&ds);
989989 XSetClassHint(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window,
990990 classPtr);
991991 XFree((char *) classPtr);
992992 Tcl_DStringFree(&name);
993 Tcl_DStringFree(&class);
993 Tcl_DStringFree(&ds);
994994 }
995995 }
996996
18701870 {
18711871 register WmInfo *wmPtr = winPtr->wmInfoPtr;
18721872 Window window;
1873 char buf[TCL_INTEGER_SPACE];
18731874
18741875 if (objc != 3) {
18751876 Tcl_WrongNumArgs(interp, 2, objv, "window");
18791880 if (window == None) {
18801881 window = Tk_WindowId((Tk_Window) winPtr);
18811882 }
1882 Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", (unsigned) window));
1883 sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)window);
1884 Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
18831885 return TCL_OK;
18841886 }
18851887
24432445 for (i = 3 + isDefault; i < objc; i++) {
24442446 photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i]));
24452447 if (photo == NULL) {
2446 Tcl_Free((char *) iconPropertyData);
2448 ckfree((char *) iconPropertyData);
2449 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
2450 "failed to create an iconphoto with image \"%s\"",
2451 Tcl_GetString(objv[i])));
2452 Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
24472453 return TCL_ERROR;
24482454 }
24492455 Tk_PhotoGetSize(photo, &width, &height);
32653271 ckfree(windows);
32663272 Tcl_SetObjResult(interp, resultObj);
32673273 return TCL_OK;
3274 } else {
3275 return TCL_ERROR;
32683276 }
32693277 } else {
32703278 Tk_Window relWin;
35233531 Tcl_Obj *const objv[]) /* Argument objects. */
35243532 {
35253533 register WmInfo *wmPtr = winPtr->wmInfoPtr;
3526 TkWindow *masterPtr = wmPtr->masterPtr;
3534 TkWindow *masterPtr = wmPtr->masterPtr, *w;
35273535 WmInfo *wmPtr2;
35283536
35293537 if ((objc != 3) && (objc != 4)) {
35923600 return TCL_ERROR;
35933601 }
35943602
3595 if (masterPtr == winPtr) {
3596 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3597 "can't make \"%s\" its own master", Tk_PathName(winPtr)));
3598 Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
3599 return TCL_ERROR;
3600 } else if (masterPtr != wmPtr->masterPtr) {
3603 for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
3604 w = (TkWindow *)w->wmInfoPtr->masterPtr) {
3605 if (w == winPtr) {
3606 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
3607 "setting \"%s\" as master creates a transient/master cycle",
3608 Tk_PathName(masterPtr)));
3609 Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
3610 return TCL_ERROR;
3611 }
3612 }
3613
3614 if (masterPtr != wmPtr->masterPtr) {
36013615 /*
36023616 * Remove old master map/unmap binding before setting the new
36033617 * master. The event handler will ensure that transient states
57845798 *----------------------------------------------------------------------
57855799 */
57865800
5801 static int PointInWindow(
5802 int x,
5803 int y,
5804 WmInfo *wmPtr)
5805 {
5806 XWindowChanges changes = wmPtr->winPtr->changes;
5807 return (x >= changes.x &&
5808 x < changes.x + changes.width &&
5809 y >= changes.y - wmPtr->menuHeight &&
5810 y < changes.y + changes.height);
5811 }
5812
57875813 Tk_Window
57885814 Tk_CoordsToWindow(
57895815 int rootX, int rootY, /* Coordinates of point in root window. If a
58545880 }
58555881 for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL;
58565882 wmPtr = wmPtr->nextPtr) {
5857 if (wmPtr->reparent == child) {
5858 goto gotToplevel;
5883 if (wmPtr->winPtr->mainPtr == NULL) {
5884 continue;
5885 }
5886 if (child == wmPtr->reparent) {
5887 if (PointInWindow(x, y, wmPtr)) {
5888 goto gotToplevel;
5889 } else {
5890
5891 /*
5892 * Return NULL if the point is in the title bar or border.
5893 */
5894
5895 return NULL;
5896 }
58595897 }
58605898 if (wmPtr->wrapperPtr != NULL) {
58615899 if (child == wmPtr->wrapperPtr->window) {
58625900 goto gotToplevel;
5863 }
5901 } else if (wmPtr->winPtr->flags & TK_EMBEDDED &&
5902 TkpGetOtherWindow(wmPtr->winPtr) == NULL) {
5903
5904 /*
5905 * This toplevel is embedded in a window belonging to
5906 * a different application.
5907 */
5908
5909 int rx, ry;
5910 Tk_GetRootCoords((Tk_Window) wmPtr->winPtr, &rx, &ry);
5911 childX -= rx;
5912 childY -= ry;
5913 goto gotToplevel;
5914 }
58645915 } else if (child == wmPtr->winPtr->window) {
58655916 goto gotToplevel;
58665917 }
58825933 handler = NULL;
58835934 }
58845935 winPtr = wmPtr->winPtr;
5885 if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
5886 return NULL;
5887 }
58885936
58895937 /*
58905938 * Step 3: at this point winPtr and wmPtr refer to the toplevel that
59415989 if (nextPtr == NULL) {
59425990 break;
59435991 }
5944 winPtr = nextPtr;
5945 x -= winPtr->changes.x;
5946 y -= winPtr->changes.y;
5947 if ((winPtr->flags & TK_CONTAINER)
5948 && (winPtr->flags & TK_BOTH_HALVES)) {
5992 x -= nextPtr->changes.x;
5993 y -= nextPtr->changes.y;
5994 if ((nextPtr->flags & TK_CONTAINER)
5995 && (nextPtr->flags & TK_BOTH_HALVES)) {
59495996 /*
59505997 * The window containing the point is a container, and the
59515998 * embedded application is in this same process. Switch over to
59525999 * the toplevel for the embedded application and start processing
59536000 * that toplevel from scratch.
59546001 */
5955
5956 winPtr = TkpGetOtherWindow(winPtr);
6002 winPtr = TkpGetOtherWindow(nextPtr);
59576003 if (winPtr == NULL) {
5958 return NULL;
6004 return (Tk_Window) nextPtr;
59596005 }
59606006 wmPtr = winPtr->wmInfoPtr;
59616007 childX = x;
59626008 childY = y;
59636009 goto gotToplevel;
5964 }
6010 } else {
6011 winPtr = nextPtr;
6012 }
6013 }
6014 if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
6015 return NULL;
59656016 }
59666017 return (Tk_Window) winPtr;
59676018 }
63866437 TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
63876438
63886439 window_ptr = windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
6440 if (windows == NULL) {
6441 return NULL;
6442 }
63896443
63906444 /*
63916445 * Special cases: If zero or one toplevels were mapped there is no need to
0 # This file is a Makefile for Tk. If it has the name "Makefile.in"
1 # then it is a template for a Makefile; to generate the actual Makefile,
2 # run "./configure", which is a configuration script generated by the
3 # "autoconf" program (constructs like "@foo@" will get replaced in the
4 # actual Makefile.
0 #
1 # This file is a Makefile for Tk. If it has the name "Makefile.in" then it
2 # is a template for a Makefile; to generate the actual Makefile, run
3 # "./configure", which is a configuration script generated by the "autoconf"
4 # program (constructs like "@foo@" will get replaced in the actual Makefile.
55
66 TCLVERSION = @TCL_VERSION@
77 TCLPATCHL = @TCL_PATCH_LEVEL@
88 VERSION = @TK_VERSION@
99 PATCH_LEVEL = @TK_PATCH_LEVEL@
1010
11 #----------------------------------------------------------------
12 # Things you can change to personalize the Makefile for your own
13 # site (you can make these changes in either Makefile.in or
14 # Makefile, but changes to Makefile will get lost if you re-run
15 # the configuration script).
16 #----------------------------------------------------------------
17
18 # Default top-level directories in which to install architecture-
19 # specific files (exec_prefix) and machine-independent files such
20 # as scripts (prefix). The values specified here may be overridden
21 # at configure-time with the --exec-prefix and --prefix options
22 # to the "configure" script.
11 #--------------------------------------------------------------------------
12 # Things you can change to personalize the Makefile for your own site (you can
13 # make these changes in either Makefile.in or Makefile, but changes to
14 # Makefile will get lost if you re-run the configuration script).
15 #--------------------------------------------------------------------------
16
17 # Default top-level directories in which to install architecture-specific
18 # files (exec_prefix) and machine-independent files such as scripts (prefix).
19 # The values specified here may be overridden at configure-time with the
20 # --exec-prefix and --prefix options to the "configure" script.
2321
2422 prefix = @prefix@
2523 exec_prefix = @exec_prefix@
2725 libdir = @libdir@
2826 includedir = @includedir@
2927 datarootdir = @datarootdir@
28 runstatedir = @runstatedir@
3029 mandir = @mandir@
3130
32 # The following definition can be set to non-null for special systems
33 # like AFS with replication. It allows the pathnames used for installation
34 # to be different than those used for actually reference files at
35 # run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix
36 # when installing files.
37 INSTALL_ROOT =
38
39 # Directory from which applications will reference the library of Tk
40 # scripts (note: you can set the TK_LIBRARY environment variable at
41 # run-time to override this value):
42 TK_LIBRARY = $(prefix)/lib/tk$(VERSION)
31 # The following definition can be set to non-null for special systems like AFS
32 # with replication. It allows the pathnames used for installation to be
33 # different than those used for actually reference files at run-time.
34 # INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files.
35 INSTALL_ROOT =
36
37 # Directory from which applications will reference the library of Tk scripts
38 # (note: you can set the TK_LIBRARY environment variable at run-time to
39 # override this value):
40 TK_LIBRARY = $(prefix)/lib/tk$(VERSION)
4341
4442 # Path to use at runtime to refer to LIB_INSTALL_DIR:
4543 LIB_RUNTIME_DIR = $(libdir)
5957 # Directory in which to (optionally) install the private tk headers:
6058 PRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)
6159
62 # Top-level directory for manual entries:
60 # Top-level directory in which to install manual entries:
6361 MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir)
6462
6563 # Directory in which to install manual entry for wish:
66 MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1
64 MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1
6765
6866 # Directory in which to install manual entries for Tk's C library
6967 # procedures:
70 MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3
71
72 # Directory in which to install manual entries for the built-in
73 # Tk commands:
74 MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann
68 MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3
69
70 # Directory in which to install manual entries for the built-in Tk commands:
71 MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann
7572
7673 # Libraries built with optimization switches have this additional extension
77 TK_DBGX = @TK_DBGX@
74 TK_DBGX = @TK_DBGX@
7875
7976 # Directory in which to install the pkgIndex.tcl file for loadable Tk
8077 PKG_INSTALL_DIR = $(LIB_INSTALL_DIR)/tk$(VERSION)$(TK_DBGX)
10097
10198 TCL_TOOL_DIR = @TCL_SRC_DIR@/tools
10299
100 SRC_DIR = @srcdir@
101 ROOT_DIR = @srcdir@/..
102 TOP_DIR = $(shell cd @srcdir@/..; pwd -W 2>/dev/null || pwd -P)
103 WIN_DIR = $(TOP_DIR)/win
104 UNIX_DIR = $(TOP_DIR)/unix
105 GENERIC_DIR = $(TOP_DIR)/generic
106 TTK_DIR = $(GENERIC_DIR)/ttk
107 BITMAP_DIR = $(TOP_DIR)/bitmaps
108 XLIB_DIR = $(TOP_DIR)/xlib
109 RC_DIR = $(WIN_DIR)/rc
110
103111 # Converts a POSIX path to a Windows native path.
104112 CYGPATH = @CYGPATH@
105113
107115 TCL_LIB_FILE = "$(shell $(CYGPATH) '@TCL_BIN_DIR@/@TCL_LIB_FILE@')"
108116 TCL_STUB_LIB_FILE = "$(shell $(CYGPATH) '@TCL_BIN_DIR@/@TCL_STUB_LIB_FILE@')"
109117
110 SRC_DIR = @srcdir@
111 ROOT_DIR = $(SRC_DIR)/..
112 WIN_DIR = $(SRC_DIR)
113 UNIX_DIR = $(SRC_DIR)/../unix
114 GENERIC_DIR = $(SRC_DIR)/../generic
115 TTK_DIR = $(GENERIC_DIR)/ttk
116 BITMAP_DIR = $(ROOT_DIR)/bitmaps
117 XLIB_DIR = $(ROOT_DIR)/xlib
118 RC_DIR = $(WIN_DIR)/rc
119
120 ROOT_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)' | sed 's!\\!/!g')
121 WIN_DIR_NATIVE = $(shell $(CYGPATH) '$(WIN_DIR)' | sed 's!\\!/!g')
122 GENERIC_DIR_NATIVE = $(shell $(CYGPATH) '$(GENERIC_DIR)' | sed 's!\\!/!g')
123 BITMAP_DIR_NATIVE = $(ROOT_DIR_NATIVE)/bitmaps
124 XLIB_DIR_NATIVE = $(ROOT_DIR_NATIVE)/xlib
125 RC_DIR_NATIVE = $(WIN_DIR_NATIVE)/rc
126 TCL_GENERIC_NATIVE = $(shell $(CYGPATH) '$(TCL_GENERIC_DIR)' | sed 's!\\!/!g')
127 TCL_PLATFORM_NATIVE = $(shell $(CYGPATH) '$(TCL_PLATFORM_DIR)' | sed 's!\\!/!g')
128 TCL_SRC_DIR_NATIVE = $(shell $(CYGPATH) '$(TCL_SRC_DIR)' | sed 's!\\!/!g')
118 ROOT_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)')
119 WIN_DIR_NATIVE = $(shell $(CYGPATH) '$(WIN_DIR)')
120 GENERIC_DIR_NATIVE = $(shell $(CYGPATH) '$(GENERIC_DIR)')
121 BITMAP_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)/bitmaps')
122 XLIB_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)/xlib')
123 RC_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)/rc')
124 TCL_GENERIC_NATIVE = $(shell $(CYGPATH) '$(TCL_GENERIC_DIR)')
125 TCL_PLATFORM_NATIVE = $(shell $(CYGPATH) '$(TCL_PLATFORM_DIR)')
126 TCL_SRC_DIR_NATIVE = $(shell $(CYGPATH) '$(TCL_SRC_DIR)')
129127
130128 DLLSUFFIX = @DLLSUFFIX@
131129 LIBSUFFIX = @LIBSUFFIX@
503501 done
504502
505503 install-libraries: libraries
506 @for i in $(INSTALL_ROOT)$(prefix)/lib \
507 $(INCLUDE_INSTALL_DIR) $(INCLUDE_INSTALL_DIR)/X11 \
508 $(SCRIPT_INSTALL_DIR) $(SCRIPT_INSTALL_DIR)/images \
509 $(SCRIPT_INSTALL_DIR)/msgs $(SCRIPT_INSTALL_DIR)/ttk; \
504 @for i in "$$($(CYGPATH) $(prefix)/lib)" \
505 "$(INCLUDE_INSTALL_DIR)" "$(INCLUDE_INSTALL_DIR)/X11" \
506 "$(SCRIPT_INSTALL_DIR)" "$(SCRIPT_INSTALL_DIR)/images" \
507 "$(SCRIPT_INSTALL_DIR)/msgs" "$(SCRIPT_INSTALL_DIR)/ttk"; \
510508 do \
511509 if [ ! -d $$i ] ; then \
512510 echo "Making directory $$i"; \
516514 fi; \
517515 done;
518516 @echo "Installing header files to $(INCLUDE_INSTALL_DIR)/";
519 @for i in $(GENERIC_DIR)/tk.h $(GENERIC_DIR)/tkPlatDecls.h \
520 $(GENERIC_DIR)/tkIntXlibDecls.h $(GENERIC_DIR)/tkDecls.h ; \
517 @for i in "$(GENERIC_DIR)/tk.h" "$(GENERIC_DIR)/tkPlatDecls.h" \
518 "$(GENERIC_DIR)/tkIntXlibDecls.h" "$(GENERIC_DIR)/tkDecls.h" ; \
521519 do \
522520 $(INSTALL_DATA) $$i $(INCLUDE_INSTALL_DIR); \
523521 done;
603601 fi; \
604602 done;
605603 @echo "Installing private header files to $(PRIVATE_INCLUDE_INSTALL_DIR)/";
606 @for i in $(GENERIC_DIR)/tkInt.h $(GENERIC_DIR)/tkIntDecls.h \
607 $(GENERIC_DIR)/tkIntPlatDecls.h $(GENERIC_DIR)/tkPort.h \
608 $(WIN_DIR)/tkWinPort.h $(WIN_DIR)/tkWinInt.h $(WIN_DIR)/tkWin.h; \
604 @for i in "$(GENERIC_DIR)/tkInt.h" "$(GENERIC_DIR)/tkIntDecls.h" \
605 "$(GENERIC_DIR)/tkIntPlatDecls.h" "$(GENERIC_DIR)/tkPort.h" \
606 "$(WIN_DIR)/tkWinPort.h" "$(WIN_DIR)/tkWinInt.h" "$(WIN_DIR)/tkWin.h"; \
609607 do \
610608 $(INSTALL_DATA) $$i $(PRIVATE_INCLUDE_INSTALL_DIR); \
611609 done;
1717 edit makefile.vc and adjust the path to Tcl accordingly.
1818
1919 Information about compiling for windows is maintained at:
20 http://www.tcl.tk/doc/howto/compile.html
20 https://www.tcl-lang.org/doc/howto/compile.html
13111311 TK_VERSION=8.6
13121312 TK_MAJOR_VERSION=8
13131313 TK_MINOR_VERSION=6
1314 TK_PATCH_LEVEL=".9"
1314 TK_PATCH_LEVEL=".10"
13151315 VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
13161316
13171317 #------------------------------------------------------------------------
30003000
30013001 echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
30023002 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
3003 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
3003 set x ${MAKE-make}
3004 ac_make=`echo "" | sed 'y,:./+-,___p_,'`
30043005 if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
30053006 echo $ECHO_N "(cached) $ECHO_C" >&6
30063007 else
30073008 cat >conftest.make <<\_ACEOF
3009 SHELL = /bin/sh
30083010 all:
3009 @echo 'ac_maketemp="$(MAKE)"'
3010 _ACEOF
3011 # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
3012 eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
3013 if test -n "$ac_maketemp"; then
3014 eval ac_cv_prog_make_${ac_make}_set=yes
3015 else
3016 eval ac_cv_prog_make_${ac_make}_set=no
3017 fi
3011 @echo '@@@%%%=$(MAKE)=@@@%%%'
3012 _ACEOF
3013 # GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
3014 case `${MAKE-make} -f conftest.make 2>/dev/null` in
3015 *@@@%%%=?*=@@@%%%*)
3016 eval ac_cv_prog_make_${ac_make}_set=yes;;
3017 *)
3018 eval ac_cv_prog_make_${ac_make}_set=no;;
3019 esac
30183020 rm -f conftest.make
30193021 fi
3020 if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
3022 if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
30213023 echo "$as_me:$LINENO: result: yes" >&5
30223024 echo "${ECHO_T}yes" >&6
30233025 SET_MAKE=
1313 TK_VERSION=8.6
1414 TK_MAJOR_VERSION=8
1515 TK_MINOR_VERSION=6
16 TK_PATCH_LEVEL=".9"
16 TK_PATCH_LEVEL=".10"
1717 VER=$TK_MAJOR_VERSION$TK_MINOR_VERSION
1818
1919 #------------------------------------------------------------------------
1616 # General usage:
1717 # nmake [-nologo] -f makefile.vc [TARGET|MACRODEF [TARGET|MACRODEF] [...]]
1818 #
19 # For MACRODEF, see TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md)
19 # For MACRODEF, see TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md)
2020 # or examine Sections 6-8 in rules.vc. This makefile has the following
2121 # values for the OPTS macro in addition to the ones described there.
2222 # noxp = If you do not have the uxtheme.h header then you
6565 # c:\tcl_src\win\>nmake -f makefile.vc test
6666 # Install Tk in location specified by INSTALLDIR macro
6767 # c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl
68 # Build release with PDF files
69 # c:\tcl_src\win\>nmake -f makefile.vc release OPTS=pdbs
68 # Build release with PDF files
69 # c:\tcl_src\win\>nmake -f makefile.vc release OPTS=pdbs
7070 # Build debug version
7171 # c:\tcl_src\win\>nmake -f makefile.vc release OPTS=symbols
7272 #
8282
8383 # We have a custom resource file
8484 RCFILE = tk.rc
85
86 USE_WIDECHAR_API = 0
8587
8688 # The rules.vc file does much of the hard work in terms of defining
8789 # the build configuration, macros, output directories etc.
301303 # defined in rules.vc
302304 PRJ_INCLUDES = -I"$(BITMAPDIR)" -I"$(XLIBDIR)"
303305
304 CONFIG_DEFS =-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 \
305 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 \
306 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 \
307 -DSUPPORT_CONFIG_EMBEDDED \
306 CONFIG_DEFS =/DSTDC_HEADERS=1 /DHAVE_SYS_TYPES_H=1 /DHAVE_SYS_STAT_H=1 \
307 /DHAVE_STDLIB_H=1 /DHAVE_STRING_H=1 /DHAVE_MEMORY_H=1 \
308 /DHAVE_STRINGS_H=1 /DHAVE_INTTYPES_H=1 \
309 /DSUPPORT_CONFIG_EMBEDDED /DUNICODE /D_UNICODE \
308310 !if $(HAVE_UXTHEME_H)
309 -DHAVE_UXTHEME_H=1 \
311 /DHAVE_UXTHEME_H=1 \
310312 !endif
311313 !if $(TTK_SQUARE_WIDGET)
312 -DTTK_SQUARE_WIDGET=1 \
313 !endif
314
315 PRJ_DEFINES = -DBUILD_ttk $(CONFIG_DEFS) -Dinline=__inline -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE
314 /DTTK_SQUARE_WIDGET=1 \
315 !endif
316
317 PRJ_DEFINES = /DBUILD_ttk $(CONFIG_DEFS) /Dinline=__inline /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
316318
317319 # Additional Link libraries needed beyond those in rules.vc
318320 PRJ_LIBS = netapi32.lib gdi32.lib user32.lib userenv.lib
335337 core: setup $(TKSTUBLIB) $(TKLIB)
336338 cwish: $(WISHC)
337339 install: install-binaries install-libraries install-docs
340 !if $(SYMBOLS)
341 install: install-pdbs
342 !endif
338343 tktest: setup $(TKTEST) $(CAT32)
339344
340345 setup: default-setup
449454
450455
451456 $(CAT32): $(_TCLDIR)\win\cat.c
452 $(cc32) $(cflags) $(crt) -D_CRT_NONSTDC_NO_DEPRECATE -DCONSOLE -Fo$(TMP_DIR)\ $?
453 $(CONEXECMD) -DCONSOLE -stack:16384 $(TMP_DIR)\cat.obj
457 $(cc32) $(cflags) $(crt) /D_CRT_NONSTDC_NO_DEPRECATE /DCONSOLE -Fo$(TMP_DIR)\ $?
458 $(CONEXECMD) /DCONSOLE -stack:16384 $(TMP_DIR)\cat.obj
454459 $(_VC_MANIFEST_EMBED_EXE)
455460
456461 #---------------------------------------------------------------------
515520 !endif
516521 # "emacs font-lock highlighting fix
517522
523 install-pdbs:
524 @echo Installing debug symbols
525 @$(CPY) "$(OUT_DIR)\*.pdb" "$(BIN_INSTALL_DIR)\"
526 # "emacs font-lock highlighting fix
527
518528 #---------------------------------------------------------------------
519529 # Special case object file targets
520530 #---------------------------------------------------------------------
521531
522 $(TMP_DIR)\testMain.obj: $(WINDIR)\winMain.c
523 $(cc32) $(appcflags_nostubs) -DTK_TEST \
524 -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
532 $(TMP_DIR)\testMain.obj: $(WIN_DIR)\winMain.c
533 $(cc32) $(appcflags_nostubs) /DTK_TEST \
534 /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
525535 -Fo$@ $?
526536
527537 $(TMP_DIR)\tkTest.obj: $(GENERICDIR)\tkTest.c
530540 $(TMP_DIR)\tkOldTest.obj: $(GENERICDIR)\tkOldTest.c
531541 $(cc32) $(appcflags_nostubs) -Fo$@ $?
532542
533 $(TMP_DIR)\tkWinTest.obj: $(WINDIR)\tkWinTest.c
543 $(TMP_DIR)\tkWinTest.obj: $(WIN_DIR)\tkWinTest.c
534544 $(cc32) $(appcflags_nostubs) -Fo$@ $?
535545
536546 $(TMP_DIR)\tkSquare.obj: $(GENERICDIR)\tkSquare.c
537547 $(cc32) $(appcflags_nostubs) -Fo$@ $?
538548
539 $(TMP_DIR)\winMain.obj: $(WINDIR)\winMain.c
549 $(TMP_DIR)\winMain.obj: $(WIN_DIR)\winMain.c
540550 $(cc32) $(appcflags_nostubs) \
541 -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
551 /DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \
542552 -Fo$@ $?
543553
544554 $(TMP_DIR)\tkMain2.obj: $(GENERICDIR)\tkMain.c
545 $(cc32) $(pkgcflags) -DTK_ASCII_MAIN -Fo$@ $?
555 $(cc32) $(pkgcflags) /DTK_ASCII_MAIN -Fo$@ $?
546556
547557 # The following objects are part of the stub library and should not
548558 # be built as DLL objects but none of the symbols should be exported
551561 $(TMP_DIR)\tkStubLib.obj : $(GENERICDIR)\tkStubLib.c
552562 $(cc32) $(stubscflags) -Fo$@ $?
553563
554
555 $(TMP_DIR)\wish.exe.manifest: $(WINDIR)\wish.exe.manifest.in
564 $(TMP_DIR)\ttkStubLib.obj : $(TTKDIR)\ttkStubLib.c
565 $(cc32) $(stubscflags) -Fo$@ $?
566
567 $(TMP_DIR)\wish.exe.manifest: $(WIN_DIR)\wish.exe.manifest.in
556568 @nmakehlp -s << $** >$@
557569 @MACHINE@ $(MACHINE:IX86=X86)
558570 @TK_WIN_VERSION@ $(DOTVERSION).0.0
572584 !else
573585 set TCL_LIBRARY=$(TCL_LIBRARY)
574586 $(TCLSH) $(TCLTOOLSDIR:\=/)/mkdepend.tcl -vc32 -out:"$(OUT_DIR)\depend.mk" \
575 -passthru:"-DBUILD_tk $(TK_INCLUDES)" $(GENERICDIR),$$(GENERICDIR) \
576 $(WINDIR),$$(WINDIR) $(TTKDIR),$$(TTKDIR) $(XLIBDIR),$$(XLIBDIR) \
587 -passthru:"/DBUILD_tk $(TK_INCLUDES)" $(GENERICDIR),$$(GENERICDIR) \
588 $(WIN_DIR),$$(WIN_DIR) $(TTKDIR),$$(TTKDIR) $(XLIBDIR),$$(XLIBDIR) \
577589 $(BITMAPDIR),$$(BITMAPDIR) @<<
578590 $(TKOBJS)
579591 <<
55 # compiler switches, defining common targets and macros. The Tcl makefile
66 # directly includes this. Extensions include it via "rules-ext.vc".
77 #
8 # See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for
8 # See TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md) for
99 # detailed documentation.
1010 #
1111 # See the file "license.terms" for information on usage and redistribution
2323 # For modifications that are not backward-compatible, you *must* change
2424 # the major version.
2525 RULES_VERSION_MAJOR = 1
26 RULES_VERSION_MINOR = 1
26 RULES_VERSION_MINOR = 4
2727
2828 # The PROJECT macro must be defined by parent makefile.
2929 !if "$(PROJECT)" == ""
161161 # COMPATDIR - source directory that holds compatibility sources
162162 # DOCDIR - source directory containing documentation files
163163 # GENERICDIR - platform-independent source directory
164 # WINDIR - Windows-specific source directory
164 # WIN_DIR - Windows-specific source directory
165165 # TESTDIR - directory containing test files
166166 # TOOLSDIR - directory containing build tools
167167 # _TCLDIR - root of the Tcl installation OR the Tcl sources. Not set
214214 DEMODIR = $(ROOT)\demos
215215 !endif
216216 !endif # ifndef DEMODIR
217 # Do NOT enclose WINDIR in a !ifndef because Windows always defines
218 # WINDIR env var to point to c:\windows!
219 # TBD - This is a potentially dangerous conflict, rename WINDIR to
220 # something else
221 WINDIR = $(ROOT)\win
217 # Do NOT use WINDIR because it is Windows internal environment
218 # variable to point to c:\windows!
219 WIN_DIR = $(ROOT)\win
222220
223221 !ifndef RCDIR
224 !if exist("$(WINDIR)\rc")
225 RCDIR = $(WINDIR)\rc
226 !else
227 RCDIR = $(WINDIR)
222 !if exist("$(WIN_DIR)\rc")
223 RCDIR = $(WIN_DIR)\rc
224 !else
225 RCDIR = $(WIN_DIR)
228226 !endif
229227 !endif
230228 RCDIR = $(RCDIR:/=\)
392390 !endif
393391
394392
395 # If INSTALLDIR set to tcl installation root dir then reset to the
396 # lib dir for installing extensions
393 # If INSTALLDIR set to Tcl installation root dir then reset to the
394 # lib dir for installing extensions
397395 !if exist("$(_INSTALLDIR)\include\tcl.h")
398396 _INSTALLDIR=$(_INSTALLDIR)\lib
399397 !endif
474472 MACHINE=$(ARCH)
475473 !endif
476474
475 #---------------------------------------------------------------
476 # The PLATFORM_IDENTIFY macro matches the values returned by
477 # the Tcl platform::identify command
478 !if "$(MACHINE)" == "AMD64"
479 PLATFORM_IDENTIFY = win32-x86_64
480 !else
481 PLATFORM_IDENTIFY = win32-ix86
482 !endif
483
484 # The MULTIPLATFORM macro controls whether binary extensions are installed
485 # in platform-specific directories. Intended to be set/used by extensions.
486 !ifndef MULTIPLATFORM_INSTALL
487 MULTIPLATFORM_INSTALL = 0
488 !endif
489
477490 #------------------------------------------------------------
478491 # Figure out the *host* architecture by reading the registry
479492
545558 # The following macros are set:
546559 # OPTIMIZATIONS - the compiler flags to be used for optimized builds
547560 # DEBUGFLAGS - the compiler flags to be used for debug builds
548 # LINKERFLAGS - Flags passed to the linker
561 # LINKERFLAGS - Flags passed to the linker
549562 #
550563 # Note that these are the compiler settings *available*, not those
551564 # that will be *used*. The latter depends on the OPTS macro settings
670683 # USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking
671684 # CONFIG_CHECK - 1 -> check current build configuration against Tcl
672685 # configuration (ignored for Tcl itself)
686 # _USE_64BIT_TIME_T - forces a build using 64-bit time_t for 32-bit build
687 # (CRT library should support this)
673688 # Further, LINKERFLAGS are modified based on above.
674689
675690 # Default values for all the above
731746
732747 !if [nmakehlp -f $(OPTS) "nothreads"]
733748 !message *** Compile explicitly for non-threaded tcl
734 TCL_THREADS = 0
749 TCL_THREADS = 0
735750 USE_THREAD_ALLOC= 0
736751 !else
737752 TCL_THREADS = 1
738753 USE_THREAD_ALLOC= 1
739754 !endif
740755
756 !if [nmakehlp -f $(OPTS) "time64bit"]
757 !message *** Force 64-bit time_t
758 _USE_64BIT_TIME_T = 1
759 !endif
760
761 # Yes, it's weird that the "symbols" option controls DEBUG and
762 # the "pdbs" option controls SYMBOLS. That's historical.
741763 !if [nmakehlp -f $(OPTS) "symbols"]
742764 !message *** Doing symbols
743765 DEBUG = 1
969991 # different compilers, build configurations etc.,
970992 #
971993 # Naming convention (suffixes):
972 # t = full thread support.
994 # t = full thread support. (Not used for Tcl >= 8.7)
973995 # s = static library (as opposed to an import library)
974996 # g = linked to the debug enabled C run-time.
975997 # x = special static build when it links to the dynamic C run-time.
10271049 !endif
10281050 !endif
10291051
1030 !if !$(TCL_THREADS)
1052 !if !$(TCL_THREADS) || $(TCL_VERSION) > 86
10311053 TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)
10321054 SUFX = $(SUFX:t=)
10331055 !endif
10601082 # Set up paths to various Tcl executables and libraries needed by extensions
10611083 !if $(DOING_TCL)
10621084
1063 TCLSHNAME = $(PROJECT)sh$(TCL_VERSION)$(SUFX).exe
1085 TCLSHNAME = $(PROJECT)sh$(VERSION)$(SUFX).exe
10641086 TCLSH = $(OUT_DIR)\$(TCLSHNAME)
10651087 TCLIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
10661088 TCLLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT)
10681090
10691091 TCLSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib
10701092 TCLSTUBLIB = $(OUT_DIR)\$(TCLSTUBLIBNAME)
1071 TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)"
1093 TCL_INCLUDES = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
10721094
10731095 !else # ! $(DOING_TCL)
10741096
10771099 # When building extensions, we need to locate tclsh. Depending on version
10781100 # of Tcl we are building against, this may or may not have a "t" suffix.
10791101 # Try various possibilities in turn.
1080 TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe
1081 !if !exist("$(TCLSH)") && $(TCL_THREADS)
1082 TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe
1083 !endif
1102 TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe
10841103 !if !exist("$(TCLSH)")
1085 TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe
1104 TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
10861105 !endif
10871106
10881107 TCLSTUBLIB = $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib
1089 TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib
1108 TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib
10901109 # When building extensions, may be linking against Tcl that does not add
10911110 # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
10921111 !if !exist("$(TCLIMPLIB)")
1093 TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib
1112 TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib
10941113 !endif
10951114 TCL_LIBRARY = $(_TCLDIR)\lib
10961115 TCLREGLIB = $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib
11001119
11011120 !else # Building against Tcl sources
11021121
1103 TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe
1104 !if !exist($(TCLSH)) && $(TCL_THREADS)
1105 TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe
1106 !endif
1122 TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe
11071123 !if !exist($(TCLSH))
1108 TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe
1124 TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe
11091125 !endif
11101126 TCLSTUBLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib
1111 TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib
1127 TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
11121128 # When building extensions, may be linking against Tcl that does not add
11131129 # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
11141130 !if !exist("$(TCLIMPLIB)")
1115 TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
1131 TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib
11161132 !endif
11171133 TCL_LIBRARY = $(_TCLDIR)\library
11181134 TCLREGLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib
11491165 TKSTUBLIB = $(OUT_DIR)\$(TKSTUBLIBNAME)
11501166 TKIMPLIB = $(OUT_DIR)\$(TKIMPLIBNAME)
11511167 TKLIB = $(OUT_DIR)\$(TKLIBNAME)
1152 TK_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)"
1168 TK_INCLUDES = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
11531169
11541170 !else # effectively NEED_TK
11551171
12081224 # SCRIPT_INSTALL_DIR - where scripts should be installed
12091225 # INCLUDE_INSTALL_DIR - where C include files should be installed
12101226 # DEMO_INSTALL_DIR - where demos should be installed
1211 # PRJ_INSTALL_DIR - where package will be installed (not set for tcl and tk)
1227 # PRJ_INSTALL_DIR - where package will be installed (not set for Tcl and Tk)
12121228
12131229 !if $(DOING_TCL) || $(DOING_TK)
12141230 LIB_INSTALL_DIR = $(_INSTALLDIR)\lib
12251241 !else # extension other than Tk
12261242
12271243 PRJ_INSTALL_DIR = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION)
1244 !if $(MULTIPLATFORM_INSTALL)
1245 LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY)
1246 BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY)
1247 !else
12281248 LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR)
12291249 BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR)
1250 !endif
12301251 DOC_INSTALL_DIR = $(PRJ_INSTALL_DIR)
12311252 SCRIPT_INSTALL_DIR = $(PRJ_INSTALL_DIR)
12321253 DEMO_INSTALL_DIR = $(PRJ_INSTALL_DIR)\demos
1233 INCLUDE_INSTALL_DIR = $(_TCLDIR)\include
1254 INCLUDE_INSTALL_DIR = $(_INSTALLDIR)\..\include
12341255
12351256 !endif
12361257
12551276 # baselibs - minimum Windows libraries required. Parent makefile can
12561277 # define PRJ_LIBS before including rules.rc if additional libs are needed
12571278
1258 OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS
1279 OPTDEFINES = /DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) /DSTDC_HEADERS
12591280
12601281 !if $(TCL_MEM_DEBUG)
1261 OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG
1282 OPTDEFINES = $(OPTDEFINES) /DTCL_MEM_DEBUG
12621283 !endif
12631284 !if $(TCL_COMPILE_DEBUG)
1264 OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS
1265 !endif
1266 !if $(TCL_THREADS)
1267 OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1
1268 !if $(USE_THREAD_ALLOC)
1269 OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1
1285 OPTDEFINES = $(OPTDEFINES) /DTCL_COMPILE_DEBUG /DTCL_COMPILE_STATS
1286 !endif
1287 !if $(TCL_THREADS) && $(TCL_VERSION) < 87
1288 OPTDEFINES = $(OPTDEFINES) /DTCL_THREADS=1
1289 !if $(USE_THREAD_ALLOC) && $(TCL_VERSION) < 87
1290 OPTDEFINES = $(OPTDEFINES) /DUSE_THREAD_ALLOC=1
12701291 !endif
12711292 !endif
12721293 !if $(STATIC_BUILD)
1273 OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD
1294 OPTDEFINES = $(OPTDEFINES) /DSTATIC_BUILD
12741295 !endif
12751296 !if $(TCL_NO_DEPRECATED)
1276 OPTDEFINES = $(OPTDEFINES) -DTCL_NO_DEPRECATED
1297 OPTDEFINES = $(OPTDEFINES) /DTCL_NO_DEPRECATED
12771298 !endif
12781299
12791300 !if $(USE_STUBS)
12801301 # Note we do not define USE_TCL_STUBS even when building tk since some
12811302 # test targets in tk do not use stubs
12821303 !if ! $(DOING_TCL)
1283 USE_STUBS_DEFS = -DUSE_TCL_STUBS -DUSE_TCLOO_STUBS
1304 USE_STUBS_DEFS = /DUSE_TCL_STUBS /DUSE_TCLOO_STUBS
12841305 !if $(NEED_TK)
1285 USE_STUBS_DEFS = $(USE_STUBS_DEFS) -DUSE_TK_STUBS
1306 USE_STUBS_DEFS = $(USE_STUBS_DEFS) /DUSE_TK_STUBS
12861307 !endif
12871308 !endif
12881309 !endif # USE_STUBS
12891310
12901311 !if !$(DEBUG)
1291 OPTDEFINES = $(OPTDEFINES) -DNDEBUG
1312 OPTDEFINES = $(OPTDEFINES) /DNDEBUG
12921313 !if $(OPTIMIZING)
1293 OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED
1314 OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_OPTIMIZED
12941315 !endif
12951316 !endif
12961317 !if $(PROFILE)
1297 OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_PROFILED
1318 OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_PROFILED
12981319 !endif
12991320 !if "$(MACHINE)" == "AMD64"
1300 OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DO64BIT
1321 OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_DO64BIT
13011322 !endif
13021323 !if $(VCVERSION) < 1300
1303 OPTDEFINES = $(OPTDEFINES) -DNO_STRTOI64
1324 OPTDEFINES = $(OPTDEFINES) /DNO_STRTOI64
1325 !endif
1326
1327 !if "$(_USE_64BIT_TIME_T)" == "1"
1328 OPTDEFINES = $(OPTDEFINES) /D_USE_64BIT_TIME_T
13041329 !endif
13051330
13061331 # _ATL_XP_TARGETING - Newer SDK's need this to build for XP
13071332 COMPILERFLAGS = /D_ATL_XP_TARGETING
1308
1309 # Following is primarily for the benefit of extensions. Tcl 8.5 builds
1310 # Tcl without /DUNICODE, while 8.6 builds with it defined. When building
1311 # an extension, it is advisable (but not mandated) to use the same Windows
1312 # API as the Tcl build. This is accordingly defaulted below. A particular
1313 # extension can override this by pre-definining USE_WIDECHAR_API.
1314 !ifndef USE_WIDECHAR_API
1315 !if $(TCL_VERSION) > 85
1316 USE_WIDECHAR_API = 1
1317 !else
1318 USE_WIDECHAR_API = 0
1319 !endif
1320 !endif
1321
1322 !if $(USE_WIDECHAR_API)
1323 COMPILERFLAGS = $(COMPILERFLAGS) /DUNICODE /D_UNICODE
1324 !endif
13251333
13261334 # Like the TEA system only set this non empty for non-Tk extensions
13271335 # Note: some extensions use PACKAGE_NAME and others use PACKAGE_TCLNAME
13281336 # so we pass both
13291337 !if !$(DOING_TCL) && !$(DOING_TK)
1330 PKGNAMEFLAGS = -DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
1331 -DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
1332 -DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
1333 -DMODULE_SCOPE=extern
1338 PKGNAMEFLAGS = /DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
1339 /DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \
1340 /DPACKAGE_VERSION="\"$(DOTVERSION)\"" \
1341 /DMODULE_SCOPE=extern
13341342 !endif
13351343
13361344 # crt picks the C run time based on selected OPTS
13771385
13781386 ### Common compiler options that are architecture specific
13791387 !if "$(MACHINE)" == "ARM"
1380 carch = -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
1388 carch = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
13811389 !else
13821390 carch =
13831391 !endif
13891397
13901398 INCLUDES = $(TCL_INCLUDES) $(TK_INCLUDES) $(PRJ_INCLUDES)
13911399 !if !$(DOING_TCL) && !$(DOING_TK)
1392 INCLUDES = $(INCLUDES) -I"$(GENERICDIR)" -I"$(WINDIR)" -I"$(COMPATDIR)"
1400 INCLUDES = $(INCLUDES) -I"$(GENERICDIR)" -I"$(WIN_DIR)" -I"$(COMPATDIR)"
13931401 !endif
13941402
13951403 # These flags are defined roughly in the order of the pre-reform
14051413 # BUILD_$(PROJECT) macro which should be defined only for the shared
14061414 # library *implementation* and not for its caller interface
14071415
1408 appcflags = $(cflags) $(crt) $(INCLUDES) $(TCL_DEFINES) $(PRJ_DEFINES) $(OPTDEFINES) $(USE_STUBS_DEFS)
14091416 appcflags_nostubs = $(cflags) $(crt) $(INCLUDES) $(TCL_DEFINES) $(PRJ_DEFINES) $(OPTDEFINES)
1410 pkgcflags = $(appcflags) $(PKGNAMEFLAGS) -DBUILD_$(PROJECT)
1411 pkgcflags_nostubs = $(appcflags_nostubs) $(PKGNAMEFLAGS) -DBUILD_$(PROJECT)
1417 appcflags = $(appcflags_nostubs) $(USE_STUBS_DEFS)
1418 pkgcflags = $(appcflags) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT)
1419 pkgcflags_nostubs = $(appcflags_nostubs) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT)
14121420
14131421 # stubscflags contains $(cflags) plus flags used for building a stubs
1414 # library for the package. Note: -DSTATIC_BUILD is defined in
1422 # library for the package. Note: /DSTATIC_BUILD is defined in
14151423 # $(OPTDEFINES) only if the OPTS configuration indicates a static
14161424 # library. However the stubs library is ALWAYS static hence included
14171425 # here irrespective of the OPTS setting.
14211429 # so we do not remove it from cflags. -GL may prevent extensions
14221430 # compiled with one VC version to fail to link against stubs library
14231431 # compiled with another VC version. Check for this and fix accordingly.
1424 stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) -Zl -DSTATIC_BUILD $(INCLUDES)
1425
1426 # Link flags
1432 stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) -Zl /DSTATIC_BUILD $(INCLUDES) $(USE_STUBS_DEFS)
1433
1434 # Link flags
14271435
14281436 !if $(DEBUG)
14291437 ldebug = -debug -debugtype:cv
14391447 ldebug= $(ldebug) -profile
14401448 !endif
14411449
1442 ### Declarations common to all linker versions
1450 ### Declarations common to all linker versions
14431451 lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)
14441452
14451453 !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900
14981506 GUIEXECMD = $(link32) $(guilflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs)
14991507 RESCMD = $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \
15001508 $(TCL_INCLUDES) \
1501 -DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
1502 -DCOMMAVERSION=$(DOTVERSION:.=,),0 \
1503 -DDOTVERSION=\"$(DOTVERSION)\" \
1504 -DVERSION=\"$(VERSION)\" \
1505 -DSUFX=\"$(SUFX)\" \
1506 -DPROJECT=\"$(PROJECT)\" \
1507 -DPRJLIBNAME=\"$(PRJLIBNAME)\"
1509 /DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \
1510 /DCOMMAVERSION=$(DOTVERSION:.=,),0 \
1511 /DDOTVERSION=\"$(DOTVERSION)\" \
1512 /DVERSION=\"$(VERSION)\" \
1513 /DSUFX=\"$(SUFX)\" \
1514 /DPROJECT=\"$(PROJECT)\" \
1515 /DPRJLIBNAME=\"$(PRJLIBNAME)\"
15081516
15091517 !ifndef DEFAULT_BUILD_TARGET
15101518 DEFAULT_BUILD_TARGET = $(PROJECT)
15121520
15131521 default-target: $(DEFAULT_BUILD_TARGET)
15141522
1523 !if $(MULTIPLATFORM_INSTALL)
1524 default-pkgindex:
1525 @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
1526 [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME)]] > $(OUT_DIR)\pkgIndex.tcl
1527 !else
15151528 default-pkgindex:
15161529 @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
15171530 [list load [file join $$dir $(PRJLIBNAME)]] > $(OUT_DIR)\pkgIndex.tcl
1531 !endif
15181532
15191533 default-pkgindex-tea:
15201534 @if exist $(ROOT)\pkgIndex.tcl.in nmakehlp -s << $(ROOT)\pkgIndex.tcl.in > $(OUT_DIR)\pkgIndex.tcl
15241538 @PKG_LIB_FILE@ $(PRJLIBNAME)
15251539 <<
15261540
1527
15281541 default-install: default-install-binaries default-install-libraries
1529
1542 !if $(SYMBOLS)
1543 default-install: default-install-pdbs
1544 !endif
1545
1546 # Again to deal with historical brokenness, there is some confusion
1547 # in terminlogy. For extensions, the "install-binaries" was used to
1548 # locate target directory for *binary shared libraries* and thus
1549 # the appropriate macro is LIB_INSTALL_DIR since BIN_INSTALL_DIR is
1550 # for executables (exes). On the other hand the "install-libraries"
1551 # target is for *scripts* and should have been called "install-scripts".
15301552 default-install-binaries: $(PRJLIB)
1531 @echo Installing binaries to '$(SCRIPT_INSTALL_DIR)'
1532 @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
1533 @$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL
1534
1535 default-install-libraries: $(OUT_DIR)\pkgIndex.tcl
1553 @echo Installing binaries to '$(LIB_INSTALL_DIR)'
1554 @if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
1555 @$(CPY) $(PRJLIB) "$(LIB_INSTALL_DIR)" >NUL
1556
1557 # Alias for default-install-scripts
1558 default-install-libraries: default-install-scripts
1559
1560 default-install-scripts: $(OUT_DIR)\pkgIndex.tcl
15361561 @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)'
15371562 @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)"
15381563 @echo Installing package index in '$(SCRIPT_INSTALL_DIR)'
15431568 @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)"
15441569 @$(CPY) $(PRJSTUBLIB) "$(SCRIPT_INSTALL_DIR)" >NUL
15451570
1571 default-install-pdbs:
1572 @echo Installing PDBs to '$(LIB_INSTALL_DIR)'
1573 @if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)"
1574 @$(CPY) "$(OUT_DIR)\*.pdb" "$(LIB_INSTALL_DIR)\"
1575
15461576 default-install-docs-html:
15471577 @echo Installing documentation files to '$(DOC_INSTALL_DIR)'
15481578 @if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)"
15611591 default-clean:
15621592 @echo Cleaning $(TMP_DIR)\* ...
15631593 @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR)
1564 @echo Cleaning $(WINDIR)\nmakehlp.obj, nmakehlp.exe ...
1565 @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj
1566 @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe
1567 @if exist $(WINDIR)\nmakehlp.out del $(WINDIR)\nmakehlp.out
1568 @echo Cleaning $(WINDIR)\nmhlp-out.txt ...
1569 @if exist $(WINDIR)\nmhlp-out.txt del $(WINDIR)\nmhlp-out.txt
1570 @echo Cleaning $(WINDIR)\_junk.pch ...
1571 @if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch
1572 @echo Cleaning $(WINDIR)\vercl.x, vercl.i ...
1573 @if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x
1574 @if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i
1575 @echo Cleaning $(WINDIR)\versions.vc, version.vc ...
1576 @if exist $(WINDIR)\versions.vc del $(WINDIR)\versions.vc
1577 @if exist $(WINDIR)\version.vc del $(WINDIR)\version.vc
1594 @echo Cleaning $(WIN_DIR)\nmakehlp.obj, nmakehlp.exe ...
1595 @if exist $(WIN_DIR)\nmakehlp.obj del $(WIN_DIR)\nmakehlp.obj
1596 @if exist $(WIN_DIR)\nmakehlp.exe del $(WIN_DIR)\nmakehlp.exe
1597 @if exist $(WIN_DIR)\nmakehlp.out del $(WIN_DIR)\nmakehlp.out
1598 @echo Cleaning $(WIN_DIR)\nmhlp-out.txt ...
1599 @if exist $(WIN_DIR)\nmhlp-out.txt del $(WIN_DIR)\nmhlp-out.txt
1600 @echo Cleaning $(WIN_DIR)\_junk.pch ...
1601 @if exist $(WIN_DIR)\_junk.pch del $(WIN_DIR)\_junk.pch
1602 @echo Cleaning $(WIN_DIR)\vercl.x, vercl.i ...
1603 @if exist $(WIN_DIR)\vercl.x del $(WIN_DIR)\vercl.x
1604 @if exist $(WIN_DIR)\vercl.i del $(WIN_DIR)\vercl.i
1605 @echo Cleaning $(WIN_DIR)\versions.vc, version.vc ...
1606 @if exist $(WIN_DIR)\versions.vc del $(WIN_DIR)\versions.vc
1607 @if exist $(WIN_DIR)\version.vc del $(WIN_DIR)\version.vc
15781608
15791609 default-hose: default-clean
15801610 @echo Hosing $(OUT_DIR)\* ...
16011631 @if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)"
16021632 $(DEBUGGER) $(TCLSH)
16031633
1604 # Generation of Windows version resource
1634 # Generation of Windows version resource
16051635 !ifdef RCFILE
16061636
16071637 # Note: don't use $** in below rule because there may be other dependencies
16401670 VALUE "OriginalFilename", PRJLIBNAME
16411671 VALUE "FileVersion", DOTVERSION
16421672 VALUE "ProductName", "Package " PROJECT " for Tcl"
1643 VALUE "ProductVersion", DOTVERSION
1673 VALUE "ProductVersion", DOTVERSION
16441674 END
16451675 END
16461676 BLOCK "VarFileInfo"
16661696 $<
16671697 <<
16681698
1669 {$(WINDIR)}.c{$(TMP_DIR)}.obj::
1699 {$(WIN_DIR)}.c{$(TMP_DIR)}.obj::
16701700 $(CCPKGCMD) @<<
16711701 $<
16721702 <<
16841714 {$(RCDIR)}.rc{$(TMP_DIR)}.res:
16851715 $(RESCMD) $<
16861716
1687 {$(WINDIR)}.rc{$(TMP_DIR)}.res:
1717 {$(WIN_DIR)}.rc{$(TMP_DIR)}.res:
16881718 $(RESCMD) $<
16891719
16901720 {$(TMP_DIR)}.rc{$(TMP_DIR)}.res:
17191749 !if defined(CORE_MACHINE) && "$(CORE_MACHINE)" != "$(MACHINE)"
17201750 !error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)).
17211751 !endif
1722 !if defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC)
1752 !if $(TCL_VERSION) < 87 && defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC)
17231753 !message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)).
17241754 !endif
17251755 !if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG)
443443 XNoOp(
444444 Display *display)
445445 {
446 display->request++;
446 display->request++;
447447 return 0;
448448 }
449449
450450 XAfterFunction
451451 XSynchronize(
452452 Display *display,
453 Bool bool)
454 {
455 display->request++;
453 Bool onoff)
454 {
455 display->request++;
456456 return NULL;
457457 }
458458
459459 int
460460 XSync(
461461 Display *display,
462 Bool bool)
463 {
464 display->request++;
462 Bool discard)
463 {
464 display->request++;
465465 return 0;
466466 }
467467
33 # Part of the nmake based build system for Tcl and its extensions.
44 # This file defines some standard targets for the convenience of extensions
55 # and can be optionally included by the extension makefile.
6 # See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for docs.
6 # See TIP 477 (https://core.tcl-lang.org/tips/doc/trunk/tip/477.md) for docs.
77
88 $(PROJECT): setup pkgindex $(PRJLIB)
99
126126 HDC dc = TkWinGetDrawableDC(display, drawable, &state);
127127 int half;
128128
129 if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT)) {
129 if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT)) {
130130 TkpGetShadows(borderPtr, tkwin);
131131 }
132132
221221 HDC dc = TkWinGetDrawableDC(display, drawable, &state);
222222 int topColor, bottomColor;
223223
224 if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT)) {
224 if ((borderPtr->lightGC == NULL) && (relief != TK_RELIEF_FLAT)) {
225225 TkpGetShadows(borderPtr, tkwin);
226226 }
227227
338338 int r, g, b;
339339 XGCValues gcValues;
340340
341 if (borderPtr->lightGC != None) {
341 if (borderPtr->lightGC != NULL) {
342342 return;
343343 }
344344
539539 {
540540 WinBorder *borderPtr = (WinBorder *) border;
541541
542 if (borderPtr->info.lightGC == None) {
542 if (borderPtr->info.lightGC == NULL) {
543543 TkpGetShadows(&borderPtr->info, tkwin);
544544 }
545545 switch (which) {
6262 * widget classes.
6363 */
6464
65 typedef struct ThreadSpecificData {
65 typedef struct {
6666 BITMAPINFOHEADER *boxesPtr; /* Information about the bitmap. */
6767 DWORD *boxesPalette; /* Pointer to color palette. */
6868 LPSTR boxesBits; /* Pointer to bitmap data. */
126126 HRSRC hrsrc;
127127 HGLOBAL hblk;
128128 LPBITMAPINFOHEADER newBitmap;
129 DWORD size;
129 size_t size;
130130 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
131131 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
132132
133 hrsrc = FindResource(module, TEXT("buttons"), RT_BITMAP);
133 hrsrc = FindResourceW(module, L"buttons", (LPWSTR) RT_BITMAP);
134134 if (hrsrc == NULL) {
135 Tcl_Panic("FindResource() failed for buttons bitmap resource, "
135 Tcl_Panic("FindResourceW() failed for buttons bitmap resource, "
136136 "resources in tk_base.rc must be linked into Tk dll or static executable");
137137 } else {
138138 hblk = LoadResource(module, hrsrc);
145145
146146 if (tsdPtr->boxesPtr != NULL && !(tsdPtr->boxesPtr->biWidth % 4)
147147 && !(tsdPtr->boxesPtr->biHeight % 2)) {
148 size = tsdPtr->boxesPtr->biSize + (1 << tsdPtr->boxesPtr->biBitCount)
149 * sizeof(RGBQUAD) + tsdPtr->boxesPtr->biSizeImage;
148 size = tsdPtr->boxesPtr->biSize
149 + (sizeof(RGBQUAD) << tsdPtr->boxesPtr->biBitCount)
150 + tsdPtr->boxesPtr->biSizeImage;
150151 newBitmap = ckalloc(size);
151152 memcpy(newBitmap, tsdPtr->boxesPtr, size);
152153 tsdPtr->boxesPtr = newBitmap;
155156 tsdPtr->boxesPalette = (DWORD*) (((LPSTR) tsdPtr->boxesPtr)
156157 + tsdPtr->boxesPtr->biSize);
157158 tsdPtr->boxesBits = ((LPSTR) tsdPtr->boxesPalette)
158 + ((1 << tsdPtr->boxesPtr->biBitCount) * sizeof(RGBQUAD));
159 + (sizeof(RGBQUAD) << tsdPtr->boxesPtr->biBitCount);
159160 } else {
160161 tsdPtr->boxesPtr = NULL;
161162 }
240241 {
241242 Window window;
242243 HWND parent;
243 const TCHAR *class;
244 LPCWSTR windowClass;
244245 WinButton *butPtr = (WinButton *)instanceData;
245246
246247 parent = Tk_GetHWND(parentWin);
247248 if (butPtr->info.type == TYPE_LABEL) {
248 class = TEXT("STATIC");
249 windowClass = L"STATIC";
249250 butPtr->style = SS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
250251 } else {
251 class = TEXT("BUTTON");
252 windowClass = L"BUTTON";
252253 butPtr->style = BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
253254 }
254 butPtr->hwnd = CreateWindow(class, NULL, butPtr->style,
255 butPtr->hwnd = CreateWindowW(windowClass, NULL, butPtr->style,
255256 Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),
256257 parent, NULL, Tk_GetHINSTANCE(), NULL);
257258 SetWindowPos(butPtr->hwnd, HWND_TOP, 0, 0, 0, 0,
258259 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
259 butPtr->oldProc = (WNDPROC)SetWindowLongPtr(butPtr->hwnd, GWLP_WNDPROC,
260 butPtr->oldProc = (WNDPROC)SetWindowLongPtrW(butPtr->hwnd, GWLP_WNDPROC,
260261 (LONG_PTR) ButtonProc);
261262
262263 window = Tk_AttachHWND(tkwin, butPtr->hwnd);
287288 HWND hwnd = winButPtr->hwnd;
288289
289290 if (hwnd) {
290 SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) winButPtr->oldProc);
291 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) winButPtr->oldProc);
291292 }
292293 }
293294
403404 * Compute width of default ring and offset for pushed buttons.
404405 */
405406
406 if (butPtr->type == TYPE_BUTTON) {
407 if (butPtr->type == TYPE_LABEL) {
408 defaultWidth = butPtr->highlightWidth;
409 offset = 0;
410 } else if (butPtr->type == TYPE_BUTTON) {
407411 defaultWidth = ((butPtr->defaultState == DEFAULT_ACTIVE)
408412 ? butPtr->highlightWidth : 0);
409413 offset = 1;
432436 * Display image or bitmap or text for button.
433437 */
434438
435 if (butPtr->image != None) {
439 if (butPtr->image != NULL) {
436440 Tk_SizeOfImage(butPtr->image, &width, &height);
437441 haveImage = 1;
438442 } else if (butPtr->bitmap != None) {
757761 butPtr->borderWidth, relief);
758762 }
759763 if (defaultWidth != 0) {
764 int highlightColor;
765
760766 dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state);
767 if (butPtr->type == TYPE_LABEL) {
768 highlightColor = (int) Tk_3DBorderColor(butPtr->highlightBorder)->pixel;
769 } else {
770 highlightColor = (int) butPtr->highlightColorPtr->pixel;
771 }
761772 TkWinFillRect(dc, 0, 0, Tk_Width(tkwin), defaultWidth,
762 (int) butPtr->highlightColorPtr->pixel);
773 highlightColor);
763774 TkWinFillRect(dc, 0, 0, defaultWidth, Tk_Height(tkwin),
764 (int) butPtr->highlightColorPtr->pixel);
775 highlightColor);
765776 TkWinFillRect(dc, 0, Tk_Height(tkwin) - defaultWidth,
766777 Tk_Width(tkwin), defaultWidth,
767 (int) butPtr->highlightColorPtr->pixel);
778 highlightColor);
768779 TkWinFillRect(dc, Tk_Width(tkwin) - defaultWidth, 0,
769780 defaultWidth, Tk_Height(tkwin),
770 (int) butPtr->highlightColorPtr->pixel);
781 highlightColor);
771782 TkWinReleaseDrawableDC(pixmap, dc, &state);
772783 }
773784
12881299 return 0;
12891300 }
12901301 }
1291
1302 /* FALLTHRU */
12921303 default:
12931304 if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
12941305 return result;
12951306 }
12961307 }
1297 return DefWindowProc(hwnd, message, wParam, lParam);
1308 return DefWindowProcW(hwnd, message, wParam, lParam);
12981309 }
12991310
13001311 /*
5454 Tcl_Encoding encoding;
5555 int result, locale, noBackslash = 0;
5656
57 if (!OpenClipboard(NULL)) {
58 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
59 "clipboard cannot be opened, another application grabbed it"));
60 Tcl_SetErrorCode(interp, "TK", "CLIPBOARD", "BUSY", NULL);
61 return TCL_ERROR;
62 }
5763 if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD"))
58 || (target != XA_STRING)
59 || !OpenClipboard(NULL)) {
64 || (target != XA_STRING)) {
6065 goto error;
6166 }
6267
7378 goto error;
7479 }
7580 data = GlobalLock(handle);
76 Tcl_DStringInit(&ds);
77 Tcl_UniCharToUtfDString((Tcl_UniChar *)data,
78 Tcl_UniCharLen((Tcl_UniChar *)data), &ds);
81 Tcl_WinTCharToUtf((LPCTSTR)data, -1, &ds);
7982 GlobalUnlock(handle);
8083 } else if (IsClipboardFormatAvailable(CF_TEXT)) {
8184 /*
145148 if (drop->fWide) {
146149 WCHAR *fname = (WCHAR *) ((char *) drop + drop->pFiles);
147150 Tcl_DString dsTmp;
148 int count = 0, len;
151 int count = 0;
152 size_t len;
149153
150154 while (*fname != 0) {
151155 if (count) {
152156 Tcl_DStringAppend(&ds, "\n", 1);
153157 }
154 len = Tcl_UniCharLen((Tcl_UniChar *) fname);
155 Tcl_DStringInit(&dsTmp);
156 Tcl_UniCharToUtfDString((Tcl_UniChar *) fname, len, &dsTmp);
158 len = wcslen(fname);
159 Tcl_WinTCharToUtf((LPCTSTR)fname, len * sizeof(WCHAR), &dsTmp);
157160 Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp),
158161 Tcl_DStringLength(&dsTmp));
159162 Tcl_DStringFree(&dsTmp);
323326 }
324327 *buffer = '\0';
325328
326 /*
327 * Depending on the platform, turn the data into Unicode or the system
328 * encoding before placing it on the clipboard.
329 */
330
331 #ifdef UNICODE
332 Tcl_DStringInit(&ds);
333 Tcl_WinUtfToTChar(rawText, -1, &ds);
334 ckfree(rawText);
335 handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
336 (unsigned) Tcl_DStringLength(&ds) + 2);
337 if (!handle) {
338 Tcl_DStringFree(&ds);
339 return;
340 }
341 buffer = GlobalLock(handle);
342 memcpy(buffer, Tcl_DStringValue(&ds),
343 (unsigned) Tcl_DStringLength(&ds) + 2);
344 GlobalUnlock(handle);
329 Tcl_DStringInit(&ds);
330 Tcl_WinUtfToTChar(rawText, -1, &ds);
331 ckfree(rawText);
332 handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
333 Tcl_DStringLength(&ds) + 2);
334 if (!handle) {
345335 Tcl_DStringFree(&ds);
346 SetClipboardData(CF_UNICODETEXT, handle);
347 #else
348 Tcl_UtfToExternalDString(NULL, rawText, -1, &ds);
349 ckfree(rawText);
350 handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
351 (unsigned) Tcl_DStringLength(&ds) + 1);
352 if (!handle) {
353 Tcl_DStringFree(&ds);
354 return;
355 }
356 buffer = GlobalLock(handle);
357 memcpy(buffer, Tcl_DStringValue(&ds),
358 (unsigned) Tcl_DStringLength(&ds) + 1);
359 GlobalUnlock(handle);
360 Tcl_DStringFree(&ds);
361 SetClipboardData(CF_TEXT, handle);
362 #endif
336 return;
337 }
338 buffer = GlobalLock(handle);
339 memcpy(buffer, Tcl_DStringValue(&ds),
340 Tcl_DStringLength(&ds) + 2);
341 GlobalUnlock(handle);
342 Tcl_DStringFree(&ds);
343 SetClipboardData(CF_UNICODETEXT, handle);
363344 }
364345
365346 /*
346346 color->blue = closeEntry.peBlue * 257;
347347 entry = closeEntry;
348348 if (index >= cmap->size) {
349 OutputDebugStringA("XAllocColor: Colormap is bigger than we thought");
349 OutputDebugStringW(L"XAllocColor: Colormap is bigger than we thought");
350350 }
351351 } else {
352352 cmap->size++;
7070 * The default cursor is used whenever no other cursor has been specified.
7171 */
7272
73 #define TK_DEFAULT_CURSOR IDC_ARROW
73 #define TK_DEFAULT_CURSOR (LPCWSTR)IDC_ARROW
7474
7575 /*
7676 *----------------------------------------------------------------------
144144
145145 for (namePtr = cursorNames; namePtr->name != NULL; namePtr++) {
146146 if (strcmp(namePtr->name, argv[0]) == 0) {
147 cursorPtr->winCursor = LoadCursor(NULL, namePtr->id);
147 cursorPtr->winCursor = LoadCursorW(NULL, (LPCWSTR) namePtr->id);
148148 break;
149149 }
150150 }
252252 TkWinCursor *winCursor = (TkWinCursor *) cursor;
253253
254254 if (winCursor == NULL || winCursor->winCursor == NULL) {
255 hcursor = LoadCursor(NULL, TK_DEFAULT_CURSOR);
255 hcursor = LoadCursorW(NULL, TK_DEFAULT_CURSOR);
256256 } else {
257257 hcursor = winCursor->winCursor;
258258 }
246246 #define DEF_MENU_ENTRY_ACTIVE_FG ((char *) NULL)
247247 #define DEF_MENU_ENTRY_ACCELERATOR ((char *) NULL)
248248 #define DEF_MENU_ENTRY_BG ((char *) NULL)
249 #define DEF_MENU_ENTRY_BITMAP None
249 #define DEF_MENU_ENTRY_BITMAP NULL
250250 #define DEF_MENU_ENTRY_COLUMN_BREAK "0"
251251 #define DEF_MENU_ENTRY_COMMAND ((char *) NULL)
252252 #define DEF_MENU_ENTRY_COMPOUND "none"
517517 #define DEF_CANVTEXT_FONT "TkDefaultFont"
518518
519519 /*
520 * Defaults for canvas items
521 * (arcs, bitmaps, lines, polygons, rectangles, and ovals):
522 */
523
524 #define DEF_CANVBMAP_FG NORMAL_FG
525 #define DEF_CANVITEM_OUTLINE NORMAL_FG
526
527 /*
520528 * Defaults for toplevels (most of the defaults for frames also apply
521529 * to toplevels):
522530 */
3939 #define BIF_NEWDIALOGSTYLE 0x0040
4040 #endif
4141
42 #ifndef BFFM_VALIDATEFAILED
43 #ifdef UNICODE
44 #define BFFM_VALIDATEFAILED 4
45 #else
46 #define BFFM_VALIDATEFAILED 3
47 #endif
48 #endif /* BFFM_VALIDATEFAILED */
49
50 typedef struct ThreadSpecificData {
42 #ifndef BFFM_VALIDATEFAILEDW
43 #define BFFM_VALIDATEFAILEDW 4
44 #endif /* BFFM_VALIDATEFAILEDW */
45
46 typedef struct {
5147 int debugFlag; /* Flags whether we should output debugging
5248 * information while displaying a builtin
5349 * dialog. */
119115 */
120116
121117 #define TkWinGetHInstance(from) \
122 ((HINSTANCE) GetWindowLongPtr((from), GWLP_HINSTANCE))
118 ((HINSTANCE) GetWindowLongPtrW((from), GWLP_HINSTANCE))
123119 #define TkWinGetUserData(from) \
124 GetWindowLongPtr((from), GWLP_USERDATA)
120 GetWindowLongPtrW((from), GWLP_USERDATA)
125121 #define TkWinSetUserData(to,what) \
126 SetWindowLongPtr((to), GWLP_USERDATA, (LPARAM)(what))
122 SetWindowLongPtrW((to), GWLP_USERDATA, (LPARAM)(what))
127123
128124 /*
129125 * The value of TK_MULTI_MAX_PATH dictates how many files can be retrieved
142138 */
143139
144140 typedef struct {
145 TCHAR initDir[MAX_PATH]; /* Initial folder to use */
146 TCHAR retDir[MAX_PATH]; /* Returned folder to use */
141 WCHAR initDir[MAX_PATH]; /* Initial folder to use */
142 WCHAR retDir[MAX_PATH]; /* Returned folder to use */
147143 Tcl_Interp *interp;
148144 int mustExist; /* True if file must exist to return from
149145 * callback */
160156 int dynFileBufferSize; /* Dynamic filename buffer size, stored to
161157 * avoid shrinking and expanding the buffer
162158 * when selection changes */
163 TCHAR *dynFileBuffer; /* Dynamic filename buffer */
159 WCHAR *dynFileBuffer; /* Dynamic filename buffer */
164160 } OFNData;
165161
166162 /*
179175 int confirmOverwrite; /* Confirm before overwriting */
180176 int mustExist; /* Used only for */
181177 int forceXPStyle; /* XXX - Force XP style even on newer systems */
182 TCHAR file[TK_MULTI_MAX_PATH]; /* File name
178 WCHAR file[TK_MULTI_MAX_PATH]; /* File name
183179 XXX - fixed size because it was so
184180 historically. Why not malloc'ed ?
185 XXX - also, TCHAR should really be WCHAR
186 because TkWinGetUnicodeEncoding is always
187 UCS2.
188181 */
189182 } OFNOpts;
190183
595588 LPARAM lParam);
596589 static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam);
597590 static void SetTkDialog(ClientData clientData);
598 static const char *ConvertExternalFilename(TCHAR *filename,
591 static const char *ConvertExternalFilename(WCHAR *filename,
599592 Tcl_DString *dsPtr);
600593 static void LoadShellProcs(void);
601594
643636 if (shell32_handle != NULL)
644637 return; /* We have already been through here. */
645638
646 shell32_handle = GetModuleHandle(TEXT("shell32.dll"));
639 shell32_handle = GetModuleHandleW(L"shell32.dll");
647640 if (shell32_handle == NULL) /* Should never happen but check anyways. */
648641 return;
649642
698691 DWORD nTime = GetTickCount() + 250;
699692
700693 while (GetTickCount() < nTime) {
701 PeekMessage(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE);
694 PeekMessageW(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE);
702695 }
703696 }
704697
760753 Tk_Window tkwin = clientData, parent;
761754 HWND hWnd;
762755 int i, oldMode, winCode, result;
763 CHOOSECOLOR chooseColor;
756 CHOOSECOLORW chooseColor;
764757 static int inited = 0;
765758 static COLORREF dwCustColors[16];
766759 static long oldColor; /* the color selected last time */
796789 chooseColor.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
797790 chooseColor.lCustData = (LPARAM) NULL;
798791 chooseColor.lpfnHook = (LPOFNHOOKPROC) ColorDlgHookProc;
799 chooseColor.lpTemplateName = (LPTSTR) interp;
792 chooseColor.lpTemplateName = (LPWSTR) interp;
800793
801794 for (i = 1; i < objc; i += 2) {
802795 int index;
848841 chooseColor.hwndOwner = hWnd;
849842
850843 oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
851 winCode = ChooseColor(&chooseColor);
844 winCode = ChooseColorW(&chooseColor);
852845 (void) Tcl_SetServiceMode(oldMode);
853846
854847 /*
928921 if ((title != NULL) && (title[0] != '\0')) {
929922 Tcl_DString ds;
930923
931 SetWindowText(hDlg, Tcl_WinUtfToTChar(title,-1,&ds));
924 SetWindowTextW(hDlg, (LPCWSTR)Tcl_WinUtfToTChar(title,-1,&ds));
932925 Tcl_DStringFree(&ds);
933926 }
934927 if (tsdPtr->debugFlag) {
14111404 normPath = Tcl_FSGetNormalizedPath(interp, iniDirPath);
14121405 /* XXX - Note on failures do not raise error, simply ignore ini dir */
14131406 if (normPath) {
1414 const WCHAR *nativePath;
1407 LPCWSTR nativePath;
14151408 Tcl_IncrRefCount(normPath);
14161409 nativePath = Tcl_FSGetNativePath(normPath); /* Points INTO normPath*/
14171410 if (nativePath) {
14441437
14451438 /*
14461439 * Clear interp result since it might have been set during the modal loop.
1447 * http://core.tcl.tk/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6
1440 * https://core.tcl-lang.org/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6
14481441 */
14491442 Tcl_ResetResult(interp);
14501443
15171510 Tcl_DString ftds;
15181511 Tcl_Obj *ftobj;
15191512
1520 Tcl_WinTCharToUtf(filterPtr[ftix-1].pszName, -1, &ftds);
1513 Tcl_WinTCharToUtf((LPCTSTR)filterPtr[ftix-1].pszName, -1, &ftds);
15211514 ftobj = Tcl_NewStringObj(Tcl_DStringValue(&ftds),
15221515 Tcl_DStringLength(&ftds));
15231516 Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL,
15711564 */
15721565 static int GetFileNameXP(Tcl_Interp *interp, OFNOpts *optsPtr, enum OFNOper oper)
15731566 {
1574 OPENFILENAME ofn;
1567 OPENFILENAMEW ofn;
15751568 OFNData ofnData;
15761569 int cdlgerr;
15771570 int filterIndex = 0, result = TCL_ERROR, winCode, oldMode;
16241617 */
16251618
16261619 ofnData.dynFileBufferSize = 512;
1627 ofnData.dynFileBuffer = ckalloc(512 * sizeof(TCHAR));
1620 ofnData.dynFileBuffer = ckalloc(512 * sizeof(WCHAR));
16281621 }
16291622
16301623 if (optsPtr->extObj != NULL) {
16321625 if (str[0] == '.')
16331626 ++str;
16341627 Tcl_WinUtfToTChar(str, -1, &extString);
1635 ofn.lpstrDefExt = (TCHAR *) Tcl_DStringValue(&extString);
1628 ofn.lpstrDefExt = (WCHAR *) Tcl_DStringValue(&extString);
16361629 }
16371630
16381631 Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString),
16391632 Tcl_DStringLength(&utfFilterString), &filterString);
1640 ofn.lpstrFilter = (TCHAR *) Tcl_DStringValue(&filterString);
1633 ofn.lpstrFilter = (WCHAR *) Tcl_DStringValue(&filterString);
16411634 ofn.nFilterIndex = filterIndex;
16421635
16431636 if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') {
16621655 }
16631656 Tcl_DStringFree(&cwd);
16641657 }
1665 ofn.lpstrInitialDir = (TCHAR *) Tcl_DStringValue(&dirString);
1658 ofn.lpstrInitialDir = (WCHAR *) Tcl_DStringValue(&dirString);
16661659
16671660 if (optsPtr->titleObj != NULL) {
16681661 Tcl_WinUtfToTChar(Tcl_GetString(optsPtr->titleObj), -1, &titleString);
1669 ofn.lpstrTitle = (TCHAR *) Tcl_DStringValue(&titleString);
1662 ofn.lpstrTitle = (WCHAR *) Tcl_DStringValue(&titleString);
16701663 }
16711664
16721665 /*
16751668
16761669 oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
16771670 if (oper != OFN_FILE_SAVE) {
1678 winCode = GetOpenFileName(&ofn);
1671 winCode = GetOpenFileNameW(&ofn);
16791672 } else {
1680 winCode = GetSaveFileName(&ofn);
1673 winCode = GetSaveFileNameW(&ofn);
16811674 }
16821675 Tcl_SetServiceMode(oldMode);
16831676 EatSpuriousMessageBugFix();
17131706 /*
17141707 * We now allow FNERR_BUFFERTOOSMALL when multiselection is enabled. The
17151708 * filename buffer has been dynamically allocated by the OFN dialog
1716 * procedure to accomodate all selected files.
1709 * procedure to accommodate all selected files.
17171710 */
17181711
17191712 if ((winCode != 0)
17311724 * first element is the directory path.
17321725 */
17331726
1734 TCHAR *files = ofnData.dynFileBuffer;
1727 WCHAR *files = ofnData.dynFileBuffer;
17351728 Tcl_Obj *returnList = Tcl_NewObj();
17361729 int count = 0;
17371730
19431936 if (notifyPtr->hdr.code == CDN_FILEOK ||
19441937 notifyPtr->hdr.code == CDN_SELCHANGE) {
19451938 int dirsize, selsize;
1946 TCHAR *buffer;
1939 WCHAR *buffer;
19471940 int buffersize;
19481941
19491942 /*
19561949 buffer = ofnData->dynFileBuffer;
19571950 hdlg = GetParent(hdlg);
19581951
1959 selsize = (int) SendMessage(hdlg, CDM_GETSPEC, 0, 0);
1960 dirsize = (int) SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0);
1952 selsize = (int) SendMessageW(hdlg, CDM_GETSPEC, 0, 0);
1953 dirsize = (int) SendMessageW(hdlg, CDM_GETFOLDERPATH, 0, 0);
19611954 buffersize = (selsize + dirsize + 1);
19621955
19631956 /*
19671960
19681961 if ((selsize > 1) && (dirsize > 0)) {
19691962 if (ofnData->dynFileBufferSize < buffersize) {
1970 buffer = ckrealloc(buffer, buffersize * sizeof(TCHAR));
1963 buffer = ckrealloc(buffer, buffersize * sizeof(WCHAR));
19711964 ofnData->dynFileBufferSize = buffersize;
19721965 ofnData->dynFileBuffer = buffer;
19731966 }
19741967
1975 SendMessage(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer);
1968 SendMessageW(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer);
19761969 buffer += dirsize;
19771970
1978 SendMessage(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer);
1971 SendMessageW(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer);
19791972
19801973 /*
19811974 * If there are multiple files, delete the quotes and change
19841977
19851978 if (buffer[0] == '"') {
19861979 BOOL findquote = TRUE;
1987 TCHAR *tmp = buffer;
1980 WCHAR *tmp = buffer;
19881981
19891982 while (*buffer != '\0') {
19901983 if (findquote) {
20132006 if (TCL_PATH_ABSOLUTE ==
20142007 Tcl_GetPathType(Tcl_DStringValue(&tmpfile))) {
20152008 /* re-get the full path to the start of the buffer */
2016 buffer = (TCHAR *) ofnData->dynFileBuffer;
2017 SendMessage(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer);
2009 buffer = (WCHAR *) ofnData->dynFileBuffer;
2010 SendMessageW(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer);
20182011 } else {
20192012 *(buffer-1) = '\\';
20202013 }
22942287 for (i = 0, filterPtr = flist.filters;
22952288 filterPtr;
22962289 filterPtr = filterPtr->next, ++i) {
2297 const char *sep;
2298 FileFilterClause *clausePtr;
2299 int nbytes;
2300
2301 /* Check if this entry should be shown as the default */
2302 if (initial && strcmp(initial, filterPtr->name) == 0)
2290 const char *sep;
2291 FileFilterClause *clausePtr;
2292 int nbytes;
2293
2294 /* Check if this entry should be shown as the default */
2295 if (initial && strcmp(initial, filterPtr->name) == 0)
23032296 initialIndex = i+1; /* Windows filter indices are 1-based */
23042297
2305 /* First stash away the text description of the pattern */
2298 /* First stash away the text description of the pattern */
23062299 Tcl_WinUtfToTChar(filterPtr->name, -1, &ds);
2307 nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
2308 nbytes += sizeof(WCHAR); /* Terminating \0 */
2309 dlgFilterPtr[i].pszName = ckalloc(nbytes);
2310 memmove((void *) dlgFilterPtr[i].pszName, Tcl_DStringValue(&ds), nbytes);
2311 Tcl_DStringFree(&ds);
2312
2313 /*
2314 * Loop through and join patterns with a ";" Each "clause"
2315 * corresponds to a single textual description (called typename)
2316 * in the tk_getOpenFile docs. Each such typename may occur
2317 * multiple times and all these form a single filter entry
2318 * with one clause per occurence. Further each clause may specify
2319 * multiple patterns. Hence the nested loop here.
2320 */
2321 sep = "";
2322 for (clausePtr=filterPtr->clauses ; clausePtr;
2323 clausePtr=clausePtr->next) {
2324 GlobPattern *globPtr;
2325 for (globPtr = clausePtr->patterns; globPtr;
2326 globPtr = globPtr->next) {
2327 Tcl_DStringAppend(&patterns, sep, -1);
2328 Tcl_DStringAppend(&patterns, globPtr->pattern, -1);
2329 sep = ";";
2330 }
2331 }
2332
2333 /* Again we need a Unicode form of the string */
2300 nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
2301 nbytes += sizeof(WCHAR); /* Terminating \0 */
2302 dlgFilterPtr[i].pszName = ckalloc(nbytes);
2303 memmove((void *) dlgFilterPtr[i].pszName, Tcl_DStringValue(&ds), nbytes);
2304 Tcl_DStringFree(&ds);
2305
2306 /*
2307 * Loop through and join patterns with a ";" Each "clause"
2308 * corresponds to a single textual description (called typename)
2309 * in the tk_getOpenFile docs. Each such typename may occur
2310 * multiple times and all these form a single filter entry
2311 * with one clause per occurence. Further each clause may specify
2312 * multiple patterns. Hence the nested loop here.
2313 */
2314 sep = "";
2315 for (clausePtr=filterPtr->clauses ; clausePtr;
2316 clausePtr=clausePtr->next) {
2317 GlobPattern *globPtr;
2318 for (globPtr = clausePtr->patterns; globPtr;
2319 globPtr = globPtr->next) {
2320 Tcl_DStringAppend(&patterns, sep, -1);
2321 Tcl_DStringAppend(&patterns, globPtr->pattern, -1);
2322 sep = ";";
2323 }
2324 }
2325
2326 /* Again we need a Unicode form of the string */
23342327 Tcl_WinUtfToTChar(Tcl_DStringValue(&patterns), -1, &ds);
2335 nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
2336 nbytes += sizeof(WCHAR); /* Terminating \0 */
2337 dlgFilterPtr[i].pszSpec = ckalloc(nbytes);
2338 memmove((void *)dlgFilterPtr[i].pszSpec, Tcl_DStringValue(&ds), nbytes);
2339 Tcl_DStringFree(&ds);
2340 Tcl_DStringFree(&patterns);
2341 }
2342
2343 if (initialIndex == 0)
2344 initialIndex = 1; /* If no default, show first entry */
2328 nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
2329 nbytes += sizeof(WCHAR); /* Terminating \0 */
2330 dlgFilterPtr[i].pszSpec = ckalloc(nbytes);
2331 memmove((void *)dlgFilterPtr[i].pszSpec, Tcl_DStringValue(&ds), nbytes);
2332 Tcl_DStringFree(&ds);
2333 Tcl_DStringSetLength(&patterns, 0);
2334 }
2335 Tcl_DStringFree(&patterns);
2336
2337 if (initialIndex == 0) {
2338 initialIndex = 1; /* If no default, show first entry */
2339 }
23452340 *initialIndexPtr = initialIndex;
23462341 *dlgFilterPtrPtr = dlgFilterPtr;
23472342 *countPtr = flist.numFilters;
24282423 int objc, /* Number of arguments. */
24292424 Tcl_Obj *const objv[]) /* Argument objects. */
24302425 {
2431 TCHAR path[MAX_PATH];
2426 WCHAR path[MAX_PATH];
24322427 int oldMode, result;
24332428 LPCITEMIDLIST pidl; /* Returned by browser */
2434 BROWSEINFO bInfo; /* Used by browser */
2429 BROWSEINFOW bInfo; /* Used by browser */
24352430 ChooseDir cdCBData; /* Structure to pass back and forth */
24362431 LPMALLOC pMalloc; /* Used by shell */
24372432 HWND hWnd;
2438 TCHAR saveDir[MAX_PATH];
2433 WCHAR saveDir[MAX_PATH];
24392434 Tcl_DString titleString; /* Title */
24402435 Tcl_DString tempString; /* temporary */
24412436 Tcl_Obj *objPtr;
24632458
24642459 utfDir = Tcl_DStringValue(&ofnOpts.utfDirString);
24652460 if (utfDir[0] != '\0') {
2466 const TCHAR *uniStr;
2461 LPCWSTR uniStr;
24672462
24682463 Tcl_WinUtfToTChar(Tcl_DStringValue(&ofnOpts.utfDirString), -1,
24692464 &tempString);
2470 uniStr = (TCHAR *) Tcl_DStringValue(&tempString);
2465 uniStr = (WCHAR *) Tcl_DStringValue(&tempString);
24712466
24722467 /* Convert possible relative path to full path to keep dialog happy. */
24732468
2474 GetFullPathName(uniStr, MAX_PATH, saveDir, NULL);
2475 _tcsncpy(cdCBData.initDir, saveDir, MAX_PATH);
2469 GetFullPathNameW(uniStr, MAX_PATH, saveDir, NULL);
2470 wcsncpy(cdCBData.initDir, saveDir, MAX_PATH);
24762471 }
24772472
24782473 /* XXX - rest of this (original) code has no error checks at all. */
24912486 bInfo.hwndOwner = hWnd;
24922487 bInfo.pszDisplayName = path;
24932488 bInfo.pidlRoot = NULL;
2494 if (_tcslen(cdCBData.initDir) == 0) {
2495 GetCurrentDirectory(MAX_PATH, cdCBData.initDir);
2489 if (wcslen(cdCBData.initDir) == 0) {
2490 GetCurrentDirectoryW(MAX_PATH, cdCBData.initDir);
24962491 }
24972492 bInfo.lParam = (LPARAM) &cdCBData;
24982493
24992494 if (ofnOpts.titleObj != NULL) {
2500 Tcl_WinUtfToTChar(Tcl_GetString(ofnOpts.titleObj), -1, &titleString);
2501 bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString);
2495 bInfo.lpszTitle = (LPCWSTR)Tcl_WinUtfToTChar(
2496 Tcl_GetString(ofnOpts.titleObj), -1, &titleString);
25022497 } else {
2503 bInfo.lpszTitle = TEXT("Please choose a directory, then select OK.");
2498 bInfo.lpszTitle = L"Please choose a directory, then select OK.";
25042499 }
25052500
25062501 /*
25332528 */
25342529
25352530 oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
2536 GetCurrentDirectory(MAX_PATH, saveDir);
2531 GetCurrentDirectoryW(MAX_PATH, saveDir);
25372532 if (SHGetMalloc(&pMalloc) == NOERROR) {
25382533 /*
25392534 * XXX - MSDN says CoInitialize must have been called before
25402535 * SHBrowseForFolder can be used but don't see that called anywhere.
25412536 */
2542 pidl = SHBrowseForFolder(&bInfo);
2537 pidl = SHBrowseForFolderW(&bInfo);
25432538
25442539 /*
25452540 * This is a fix for Windows 2000, which seems to modify the folder
25542549 */
25552550
25562551 if (pidl != NULL) {
2557 if (!SHGetPathFromIDList(pidl, path)) {
2552 if (!SHGetPathFromIDListW(pidl, path)) {
25582553 Tcl_SetObjResult(interp, Tcl_NewStringObj(
25592554 "error: not a file system folder", -1));
25602555 Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "PSEUDO", NULL);
25612556 }
25622557 pMalloc->lpVtbl->Free(pMalloc, (void *) pidl);
2563 } else if (_tcslen(cdCBData.retDir) > 0) {
2564 _tcscpy(path, cdCBData.retDir);
2558 } else if (wcslen(cdCBData.retDir) > 0) {
2559 wcscpy(path, cdCBData.retDir);
25652560 }
25662561 pMalloc->lpVtbl->Release(pMalloc);
25672562 }
2568 SetCurrentDirectory(saveDir);
2563 SetCurrentDirectoryW(saveDir);
25692564 Tcl_SetServiceMode(oldMode);
25702565
25712566 /*
26172612 LPARAM lParam,
26182613 LPARAM lpData)
26192614 {
2620 TCHAR selDir[MAX_PATH];
2615 WCHAR selDir[MAX_PATH];
26212616 ChooseDir *chooseDirSharedData = (ChooseDir *) lpData;
26222617 Tcl_DString tempString;
26232618 Tcl_DString initDirString;
2624 TCHAR string[MAX_PATH];
2619 WCHAR string[MAX_PATH];
26252620 ThreadSpecificData *tsdPtr =
26262621 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
26272622
26312626 }
26322627 chooseDirSharedData->retDir[0] = '\0';
26332628 switch (message) {
2634 case BFFM_VALIDATEFAILED:
2629 case BFFM_VALIDATEFAILEDW:
26352630 /*
26362631 * First save and check to see if it is a valid path name, if so then
26372632 * make that path the one shown in the window. Otherwise, it failed
26412636 * like ~ are converted correctly.
26422637 */
26432638
2644 Tcl_WinTCharToUtf((TCHAR *) lParam, -1, &initDirString);
2639 Tcl_WinTCharToUtf((LPCTSTR) lParam, -1, &initDirString);
26452640 if (Tcl_TranslateFileName(chooseDirSharedData->interp,
26462641 Tcl_DStringValue(&initDirString), &tempString) == NULL) {
26472642 /*
26552650 Tcl_DStringFree(&initDirString);
26562651 Tcl_WinUtfToTChar(Tcl_DStringValue(&tempString), -1, &initDirString);
26572652 Tcl_DStringFree(&tempString);
2658 _tcsncpy(string, (TCHAR *) Tcl_DStringValue(&initDirString),
2653 wcsncpy(string, (WCHAR *) Tcl_DStringValue(&initDirString),
26592654 MAX_PATH);
26602655 Tcl_DStringFree(&initDirString);
26612656
2662 if (SetCurrentDirectory(string) == 0) {
2657 if (SetCurrentDirectoryW(string) == 0) {
26632658
26642659 /*
26652660 * Get the full path name to the user entry, at this point it does
26672662 * it.
26682663 */
26692664
2670 GetFullPathName(string, MAX_PATH,
2665 GetFullPathNameW(string, MAX_PATH,
26712666 chooseDirSharedData->retDir, NULL);
26722667 if (chooseDirSharedData->mustExist) {
26732668 /*
26742669 * User HAS to select a valid directory.
26752670 */
26762671
2677 wsprintf(selDir, TEXT("Directory '%s' does not exist,\n")
2678 TEXT("please select or enter an existing directory."),
2672 wsprintfW(selDir, L"Directory '%s' does not exist,\n"
2673 L"please select or enter an existing directory.",
26792674 chooseDirSharedData->retDir);
2680 MessageBox(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK);
2675 MessageBoxW(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK);
26812676 chooseDirSharedData->retDir[0] = '\0';
26822677 return 1;
26832678 }
26872682 * directory in utfRetDir.
26882683 */
26892684
2690 GetCurrentDirectory(MAX_PATH, chooseDirSharedData->retDir);
2685 GetCurrentDirectoryW(MAX_PATH, chooseDirSharedData->retDir);
26912686 return 0;
26922687 }
26932688 return 0;
27022697 * Not called when user changes edit box directly.
27032698 */
27042699
2705 if (SHGetPathFromIDList((LPITEMIDLIST) lParam, selDir)) {
2706 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM) selDir);
2700 if (SHGetPathFromIDListW((LPITEMIDLIST) lParam, selDir)) {
2701 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM) selDir);
27072702 // enable the OK button
2708 SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
2703 SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
27092704 } else {
27102705 // disable the OK button
2711 SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0);
2706 SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0);
27122707 }
27132708 UpdateWindow(hwnd);
27142709 return 1;
27152710
27162711 case BFFM_INITIALIZED: {
27172712 /*
2718 * Directory browser intializing - tell it where to start from, user
2713 * Directory browser initializing - tell it where to start from, user
27192714 * specified parameter.
27202715 */
27212716
2722 TCHAR *initDir = chooseDirSharedData->initDir;
2723
2724 SetCurrentDirectory(initDir);
2717 WCHAR *initDir = chooseDirSharedData->initDir;
2718
2719 SetCurrentDirectoryW(initDir);
27252720
27262721 if (*initDir == '\\') {
27272722 /*
2728 * BFFM_SETSELECTION only understands UNC paths as pidls, so
2723 * BFFM_SETSELECTIONW only understands UNC paths as pidls, so
27292724 * convert path to pidl using IShellFolder interface.
27302725 */
27312726
27382733 ULONG ulCount, ulAttr;
27392734
27402735 if (SUCCEEDED(psfFolder->lpVtbl->ParseDisplayName(
2741 psfFolder, hwnd, NULL, (TCHAR *)
2736 psfFolder, hwnd, NULL, (WCHAR *)
27422737 initDir, &ulCount,&pidlMain,&ulAttr))
27432738 && (pidlMain != NULL)) {
2744 SendMessage(hwnd, BFFM_SETSELECTION, FALSE,
2739 SendMessageW(hwnd, BFFM_SETSELECTIONW, FALSE,
27452740 (LPARAM) pidlMain);
27462741 pMalloc->lpVtbl->Free(pMalloc, pidlMain);
27472742 }
27502745 pMalloc->lpVtbl->Release(pMalloc);
27512746 }
27522747 } else {
2753 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM) initDir);
2754 }
2755 SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
2748 SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) initDir);
2749 }
2750 SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
27562751 break;
27572752 }
27582753
28022797 ThreadSpecificData *tsdPtr =
28032798 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
28042799 Tcl_DString titleBuf, tmpBuf;
2805 const WCHAR *titlePtr, *tmpPtr;
2800 LPCWSTR titlePtr, tmpPtr;
28062801 const char *src;
28072802
28082803 defaultBtn = -1;
29102905
29112906 flags |= icon | type | MB_TASKMODAL | MB_SETFOREGROUND;
29122907
2913 tmpObj = messageObj ? Tcl_DuplicateObj(messageObj)
2914 : Tcl_NewUnicodeObj(NULL, 0);
2908 tmpObj = messageObj ? Tcl_DuplicateObj(messageObj) : Tcl_NewObj();
29152909 Tcl_IncrRefCount(tmpObj);
29162910 if (detailObj) {
2917 const Tcl_UniChar twoNL[] = { '\n', '\n' };
2918
2919 Tcl_AppendUnicodeToObj(tmpObj, twoNL, 2);
2911 Tcl_AppendStringsToObj(tmpObj, "\n\n", NULL);
29202912 Tcl_AppendObjToObj(tmpObj, detailObj);
29212913 }
29222914
29332925
29342926 tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL);
29352927 tsdPtr->hBigIcon = TkWinGetIcon(parent, ICON_BIG);
2936 tsdPtr->hMsgBoxHook = SetWindowsHookEx(WH_CBT, MsgBoxCBTProc, NULL,
2928 tsdPtr->hMsgBoxHook = SetWindowsHookExW(WH_CBT, MsgBoxCBTProc, NULL,
29372929 GetCurrentThreadId());
29382930 src = Tcl_GetString(tmpObj);
2939 tmpPtr = Tcl_WinUtfToTChar(src, tmpObj->length, &tmpBuf);
2931 tmpPtr = (LPCWSTR)Tcl_WinUtfToTChar(src, tmpObj->length, &tmpBuf);
29402932 if (titleObj != NULL) {
29412933 src = Tcl_GetString(titleObj);
2942 titlePtr = Tcl_WinUtfToTChar(src, titleObj->length, &titleBuf);
2934 titlePtr = (LPCWSTR)Tcl_WinUtfToTChar(src, titleObj->length, &titleBuf);
29432935 } else {
29442936 titlePtr = L"";
29452937 Tcl_DStringInit(&titleBuf);
29462938 }
2947 winCode = MessageBox(hWnd, tmpPtr, titlePtr, flags);
2939 winCode = MessageBoxW(hWnd, tmpPtr, titlePtr, flags);
29482940 Tcl_DStringFree(&titleBuf);
29492941 Tcl_DStringFree(&tmpBuf);
29502942 UnhookWindowsHookEx(tsdPtr->hMsgBoxHook);
29872979 if (WC_DIALOG == lpcbtcreate->lpcs->lpszClass) {
29882980 HWND hwnd = (HWND) wParam;
29892981
2990 SendMessage(hwnd, WM_SETICON, ICON_SMALL,
2982 SendMessageW(hwnd, WM_SETICON, ICON_SMALL,
29912983 (LPARAM) tsdPtr->hSmallIcon);
2992 SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon);
2984 SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon);
29932985 }
29942986 }
29952987
30213013 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
30223014 char buf[32];
30233015
3024 sprintf(buf, "0x%p", (HWND) clientData);
3016 sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)clientData);
30253017 Tcl_SetVar2(tsdPtr->debugInterp, "tk_dialog", NULL, buf, TCL_GLOBAL_ONLY);
30263018 }
30273019
30313023
30323024 static const char *
30333025 ConvertExternalFilename(
3034 TCHAR *filename,
3026 WCHAR *filename,
30353027 Tcl_DString *dsPtr)
30363028 {
30373029 char *p;
30383030
3039 Tcl_WinTCharToUtf(filename, -1, dsPtr);
3031 Tcl_WinTCharToUtf((LPCTSTR)filename, -1, dsPtr);
30403032 for (p = Tcl_DStringValue(dsPtr); *p != '\0'; p++) {
30413033 /*
30423034 * Change the pathname to the Tcl "normalized" pathname, where back
30663058 static Tcl_Obj *
30673059 GetFontObj(
30683060 HDC hdc,
3069 LOGFONT *plf)
3061 LOGFONTW *plf)
30703062 {
30713063 Tcl_DString ds;
30723064 Tcl_Obj *resObj;
30733065 int pt = 0;
30743066
30753067 resObj = Tcl_NewListObj(0, NULL);
3076 Tcl_WinTCharToUtf(plf->lfFaceName, -1, &ds);
3068 Tcl_WinTCharToUtf((LPCTSTR)plf->lfFaceName, -1, &ds);
30773069 Tcl_ListObjAppendElement(NULL, resObj,
30783070 Tcl_NewStringObj(Tcl_DStringValue(&ds), -1));
30793071 Tcl_DStringFree(&ds);
31023094 Tcl_Interp *interp,
31033095 Tcl_Obj *cmdObj,
31043096 HDC hdc,
3105 LOGFONT *logfontPtr)
3097 LOGFONTW *logfontPtr)
31063098 {
31073099 int objc;
31083100 Tcl_Obj **objv, **tmpv;
31613153
31623154 Tcl_WinUtfToTChar(Tcl_GetString(phd->titleObj), -1, &title);
31633155 if (Tcl_DStringLength(&title) > 0) {
3164 SetWindowText(hwndDlg, (LPCTSTR) Tcl_DStringValue(&title));
3156 SetWindowTextW(hwndDlg, (LPCWSTR) Tcl_DStringValue(&title));
31653157 }
31663158 Tcl_DStringFree(&title);
31673159 }
31943186 */
31953187
31963188 if (WM_COMMAND == msg && LOWORD(wParam) == 1026) {
3197 LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0}};
3189 LOGFONTW lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0}};
31983190 HDC hdc = GetDC(hwndDlg);
31993191
3200 SendMessage(hwndDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) &lf);
3192 SendMessageW(hwndDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) &lf);
32013193 if (phd && phd->cmdObj) {
32023194 ApplyLogfont(phd->interp, phd->cmdObj, hdc, &lf);
32033195 }
33503342 Tk_Window parent = Tk_NameToWindow(interp,
33513343 Tcl_GetString(objv[i+1]), tkwin);
33523344
3353 if (parent == None) {
3345 if (parent == NULL) {
33543346 return TCL_ERROR;
33553347 }
33563348 if (hdPtr->parentObj) {
34333425 {
34343426 Tcl_DString ds;
34353427 Tk_Window tkwin = clientData, parent;
3436 CHOOSEFONT cf;
3437 LOGFONT lf;
3428 CHOOSEFONTW cf;
3429 LOGFONTW lf;
34383430 HDC hdc;
34393431 HookData *hdPtr;
34403432 int r = TCL_OK, oldMode = 0;
34453437 if (hdPtr->parentObj) {
34463438 parent = Tk_NameToWindow(interp, Tcl_GetString(hdPtr->parentObj),
34473439 tkwin);
3448 if (parent == None) {
3440 if (parent == NULL) {
34493441 return TCL_ERROR;
34503442 }
34513443 }
34773469 fontPtr = (TkFont *) f;
34783470 cf.Flags |= CF_INITTOLOGFONTSTRUCT;
34793471 Tcl_WinUtfToTChar(fontPtr->fa.family, -1, &ds);
3480 _tcsncpy(lf.lfFaceName, (TCHAR *)Tcl_DStringValue(&ds),
3472 wcsncpy(lf.lfFaceName, (WCHAR *)Tcl_DStringValue(&ds),
34813473 LF_FACESIZE-1);
34823474 Tcl_DStringFree(&ds);
34833475 lf.lfFaceName[LF_FACESIZE-1] = 0;
35093501
35103502 if (TCL_OK == r) {
35113503 oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
3512 if (ChooseFont(&cf)) {
3504 if (ChooseFontW(&cf)) {
35133505 if (hdPtr->cmdObj) {
35143506 ApplyLogfont(hdPtr->interp, hdPtr->cmdObj, hdc, &lf);
35153507 }
102102
103103 typedef BOOL (CALLBACK *WinDrawFunc)(HDC dc, const POINT *points, int npoints);
104104
105 typedef struct ThreadSpecificData {
105 typedef struct {
106106 POINT *winPoints; /* Array of points that is reused. */
107107 int nWinPoints; /* Current size of point array. */
108108 } ThreadSpecificData;
14471447 rect.bottom = y + height;
14481448 oldColor = SetBkColor(dc, (COLORREF)pixel);
14491449 SetBkMode(dc, OPAQUE);
1450 ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
1450 ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
14511451 SetBkColor(dc, oldColor);
14521452 }
14531453
3333 * process. */
3434 } Container;
3535
36 typedef struct ThreadSpecificData {
36 typedef struct {
3737 Container *firstContainerPtr;
3838 /* First in list of all containers managed by
3939 * this process. */
159159 {
160160 if(!(winPtr->flags & TK_ALREADY_DEAD)) {
161161 HWND hwnd = (HWND)winPtr->privatePtr;
162 int state = SendMessage(hwnd, TK_STATE, -1, -1) - 1;
162 int state = SendMessageW(hwnd, TK_STATE, -1, -1) - 1;
163163
164164 if (state < 0 || state > 3) {
165165 state = NormalState;
282282 return TCL_ERROR;
283283 }
284284
285 id = SendMessage(hwnd, TK_INFO, TK_CONTAINER_VERIFY, 0);
285 id = SendMessageW(hwnd, TK_INFO, TK_CONTAINER_VERIFY, 0);
286286 if (id == PTR2INT(hwnd)) {
287 if (!SendMessage(hwnd, TK_INFO, TK_CONTAINER_ISAVAILABLE, 0)) {
287 if (!SendMessageW(hwnd, TK_INFO, TK_CONTAINER_ISAVAILABLE, 0)) {
288288 Tcl_SetObjResult(interp, Tcl_NewStringObj(
289289 "The container is already in use", -1));
290290 Tcl_SetErrorCode(interp, "TK", "EMBED", "IN_USE", NULL);
302302 * order to avoid bug 1096074 in future.
303303 */
304304
305 TCHAR msg[256];
306
307 wsprintf(msg, TEXT("Unable to get information of window \"%.40hs\". Attach to this\nwindow may have unpredictable results if it is not a valid container.\n\nPress Ok to proceed or Cancel to abort attaching."), string);
308 if (IDCANCEL == MessageBox(hwnd, msg, TEXT("Tk Warning"),
305 WCHAR msg[256];
306
307 wsprintfW(msg, L"Unable to get information of window \"%.40hs\". Attach to this\nwindow may have unpredictable results if it is not a valid container.\n\nPress Ok to proceed or Cancel to abort attaching.", string);
308 if (IDCANCEL == MessageBoxW(hwnd, msg, L"Tk Warning",
309309 MB_OKCANCEL | MB_ICONWARNING)) {
310310 Tcl_SetObjResult(interp, Tcl_NewStringObj(
311311 "Operation has been canceled", -1));
855855 Tk_Window tkwin = (Tk_Window)containerPtr->parentPtr;
856856
857857 if (eventPtr->type == ConfigureNotify) {
858
859 /*
860 * Send a ConfigureNotify to the embedded application.
861 */
862
863 if (containerPtr->embeddedPtr != NULL) {
864 TkDoConfigureNotify(containerPtr->embeddedPtr);
865 }
866
858867 /*
859868 * Resize the embedded window, if there is any.
860869 */
10081017 * it. */
10091018 {
10101019 HWND hwnd = GetParent(Tk_GetHWND(topLevelPtr->window));
1011 SendMessage(hwnd, TK_CLAIMFOCUS, (WPARAM) force, 0);
1020 SendMessageW(hwnd, TK_CLAIMFOCUS, (WPARAM) force, 0);
10121021 }
10131022
10141023 /*
10861095 break;
10871096 }
10881097 if (containerPtr->parentPtr == winPtr) {
1089 SendMessage(containerPtr->embeddedHWnd, WM_CLOSE, 0, 0);
1098 SendMessageW(containerPtr->embeddedHWnd, WM_CLOSE, 0, 0);
10901099 containerPtr->parentPtr = NULL;
10911100 containerPtr->embeddedPtr = NULL;
10921101 break;
00 /*
11 * tkWinFont.c --
22 *
3 * Contains the Windows implementation of the platform-independant font
3 * Contains the Windows implementation of the platform-independent font
44 * package interface.
55 *
66 * Copyright (c) 1994 Software Research Associates, Inc.
2727
2828 #define FONTMAP_SHIFT 10
2929
30 #define FONTMAP_PAGES (1 << (sizeof(Tcl_UniChar)*8 - FONTMAP_SHIFT))
3130 #define FONTMAP_BITSPERPAGE (1 << FONTMAP_SHIFT)
31 #define FONTMAP_PAGES (0x30000 / FONTMAP_BITSPERPAGE)
3232
3333 typedef struct FontFamily {
3434 struct FontFamily *nextPtr; /* Next in list of all known font families. */
4949 int isSymbolFont; /* Non-zero if this is a symbol font. */
5050 int isWideFont; /* 1 if this is a double-byte font, 0
5151 * otherwise. */
52 BOOL (WINAPI *textOutProc)(HDC hdc, int x, int y, TCHAR *str, int len);
52 BOOL (WINAPI *textOutProc)(HDC hdc, int x, int y, WCHAR *str, int len);
5353 /* The procedure to use to draw text after it
5454 * has been converted from UTF-8 to the
5555 * encoding of this font. */
56 BOOL (WINAPI *getTextExtentPoint32Proc)(HDC, TCHAR *, int, LPSIZE);
56 BOOL (WINAPI *getTextExtentPoint32Proc)(HDC, WCHAR *, int, LPSIZE);
5757 /* The procedure to use to measure text after
5858 * it has been converted from UTF-8 to the
5959 * encoding of this font. */
167167 {-1, NULL}
168168 };
169169
170 typedef struct ThreadSpecificData {
170 typedef struct {
171171 FontFamily *fontFamilyList; /* The list of font families that are
172172 * currently loaded. As screen fonts are
173173 * loaded, this list grows to hold information
176176 Tcl_HashTable uidTable;
177177 } ThreadSpecificData;
178178 static Tcl_ThreadDataKey dataKey;
179
180 /*
181 * Information cached about the system at startup time.
182 */
183
184 static Tcl_Encoding systemEncoding;
185179
186180 /*
187181 * Procedures used only in this file.
212206 SubFont *subFontPtr);
213207 static int CreateNamedSystemLogFont(Tcl_Interp *interp,
214208 Tk_Window tkwin, const char* name,
215 LOGFONT* logFontPtr);
209 LOGFONTW* logFontPtr);
216210 static int CreateNamedSystemFont(Tcl_Interp *interp,
217211 Tk_Window tkwin, const char* name, HFONT hFont);
218212 static int LoadFontRanges(HDC hdc, HFONT hFont,
228222 SubFont *subFontPtr, double angle);
229223 static inline void SwapLong(PULONG p);
230224 static inline void SwapShort(USHORT *p);
231 static int CALLBACK WinFontCanUseProc(ENUMLOGFONT *lfPtr,
225 static int CALLBACK WinFontCanUseProc(ENUMLOGFONTW *lfPtr,
232226 NEWTEXTMETRIC *tmPtr, int fontType,
233227 LPARAM lParam);
234 static int CALLBACK WinFontExistProc(ENUMLOGFONT *lfPtr,
228 static int CALLBACK WinFontExistProc(ENUMLOGFONTW *lfPtr,
235229 NEWTEXTMETRIC *tmPtr, int fontType,
236230 LPARAM lParam);
237 static int CALLBACK WinFontFamilyEnumProc(ENUMLOGFONT *lfPtr,
231 static int CALLBACK WinFontFamilyEnumProc(ENUMLOGFONTW *lfPtr,
238232 NEWTEXTMETRIC *tmPtr, int fontType,
239233 LPARAM lParam);
240234
261255 TkpFontPkgInit(
262256 TkMainInfo *mainPtr) /* The application being created. */
263257 {
264 systemEncoding = TkWinGetUnicodeEncoding();
265258 TkWinSetupSystemFonts(mainPtr);
266259 }
267260
330323 Tcl_Interp *interp,
331324 Tk_Window tkwin,
332325 const char* name,
333 LOGFONT* logFontPtr)
326 LOGFONTW* logFontPtr)
334327 {
335328 HFONT hFont;
336329 int r;
337330
338 hFont = CreateFontIndirect(logFontPtr);
331 hFont = CreateFontIndirectW(logFontPtr);
339332 r = CreateNamedSystemFont(interp, tkwin, name, hFont);
340333 DeleteObject((HGDIOBJ)hFont);
341334 return r;
391384 Tcl_Interp *interp;
392385 Tk_Window tkwin;
393386 const TkStateMap *mapPtr;
394 NONCLIENTMETRICS ncMetrics;
395 ICONMETRICS iconMetrics;
387 NONCLIENTMETRICSW ncMetrics;
388 ICONMETRICSW iconMetrics;
396389 HFONT hFont;
397390
398391 interp = (Tcl_Interp *) mainPtr->interp;
412405
413406 ZeroMemory(&ncMetrics, sizeof(ncMetrics));
414407 ncMetrics.cbSize = sizeof(ncMetrics);
415 if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
408 if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
416409 sizeof(ncMetrics), &ncMetrics, 0)) {
417410 CreateNamedSystemLogFont(interp, tkwin, "TkDefaultFont",
418411 &ncMetrics.lfMessageFont);
431424 }
432425
433426 iconMetrics.cbSize = sizeof(iconMetrics);
434 if (SystemParametersInfo(SPI_GETICONMETRICS, sizeof(iconMetrics),
427 if (SystemParametersInfoW(SPI_GETICONMETRICS, sizeof(iconMetrics),
435428 &iconMetrics, 0)) {
436429 CreateNamedSystemLogFont(interp, tkwin, "TkIconFont",
437430 &iconMetrics.lfFont);
443436 */
444437
445438 {
446 LOGFONT lfFixed = {
439 LOGFONTW lfFixed = {
447440 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
448 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, TEXT("")
441 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L""
449442 };
450443 long pointSize, dpi;
451444 HDC hdc = GetDC(NULL);
650643 * because it only exists under NT.
651644 */
652645
653 EnumFontFamilies(hdc, NULL, (FONTENUMPROC) WinFontFamilyEnumProc,
646 EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontFamilyEnumProc,
654647 (LPARAM) resultObj);
655648 ReleaseDC(hwnd, hdc);
656649 Tcl_SetObjResult(interp, resultObj);
658651
659652 static int CALLBACK
660653 WinFontFamilyEnumProc(
661 ENUMLOGFONT *lfPtr, /* Logical-font data. */
654 ENUMLOGFONTW *lfPtr, /* Logical-font data. */
662655 NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
663656 int fontType, /* Type of font (not used). */
664657 LPARAM lParam) /* Result object to hold result. */
665658 {
666 char *faceName = (char *) lfPtr->elfLogFont.lfFaceName;
667659 Tcl_Obj *resultObj = (Tcl_Obj *) lParam;
668660 Tcl_DString faceString;
669661
670 Tcl_ExternalToUtfDString(systemEncoding, faceName, -1, &faceString);
662 Tcl_WinTCharToUtf((LPCTSTR)lfPtr->elfLogFont.lfFaceName, -1, &faceString);
671663 Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(
672664 Tcl_DStringValue(&faceString), Tcl_DStringLength(&faceString)));
673665 Tcl_DStringFree(&faceString);
750742 * character */
751743 FontFamily *familyPtr = thisSubFontPtr->familyPtr;
752744 HFONT oldfont; /* Saved font from the device context */
753 TEXTMETRIC tm; /* Font metrics of the selected subfont */
745 TEXTMETRICW tm; /* Font metrics of the selected subfont */
754746
755747 /*
756748 * Get the font attributes.
757749 */
758750
759751 oldfont = SelectObject(hdc, thisSubFontPtr->hFont0);
760 GetTextMetrics(hdc, &tm);
752 GetTextMetricsW(hdc, &tm);
761753 SelectObject(hdc, oldfont);
762754 ReleaseDC(fontPtr->hwnd, hdc);
763755 faPtr->family = familyPtr->faceName;
857849 (int) (p - start), &runString);
858850 size.cx = 0;
859851 familyPtr->getTextExtentPoint32Proc(hdc,
860 (TCHAR *)Tcl_DStringValue(&runString),
852 (WCHAR *)Tcl_DStringValue(&runString),
861853 Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
862854 &size);
863855 Tcl_DStringFree(&runString);
884876 Tcl_UtfToExternalDString(familyPtr->encoding, start,
885877 (int) (p - start), &runString);
886878 size.cx = 0;
887 familyPtr->getTextExtentPoint32Proc(hdc, (TCHAR *) Tcl_DStringValue(&runString),
879 familyPtr->getTextExtentPoint32Proc(hdc, (WCHAR *) Tcl_DStringValue(&runString),
888880 Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
889881 &size);
890882 Tcl_DStringFree(&runString);
918910 Tcl_DStringAppend(&runString,buf,dstWrote);
919911 size.cx = 0;
920912 familyPtr->getTextExtentPoint32Proc(hdc,
921 (TCHAR *) Tcl_DStringValue(&runString),
913 (WCHAR *) Tcl_DStringValue(&runString),
922914 Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
923915 &size);
924916 if ((curX+size.cx) > maxLength) {
987979 }
988980
989981 *lengthPtr = curX;
990 return p - source;
982 return (int)(p - source);
991983 }
992984
993985 /*
11081100 HBRUSH oldBrush, stipple;
11091101 HBITMAP oldBitmap, bitmap;
11101102 HDC dcMem;
1111 TEXTMETRIC tm;
1103 TEXTMETRICW tm;
11121104 SIZE size;
11131105
11141106 if (twdPtr->type != TWD_BITMAP) {
11351127 */
11361128
11371129 GetTextExtentPointA(dcMem, source, numBytes, &size);
1138 GetTextMetrics(dcMem, &tm);
1130 GetTextMetricsW(dcMem, &tm);
11391131 size.cx -= tm.tmOverhang;
11401132 bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
11411133 oldBitmap = SelectObject(dcMem, bitmap);
11741166 } else {
11751167 HBITMAP oldBitmap, bitmap;
11761168 HDC dcMem;
1177 TEXTMETRIC tm;
1169 TEXTMETRICW tm;
11781170 SIZE size;
11791171
11801172 dcMem = CreateCompatibleDC(dc);
11891181 */
11901182
11911183 GetTextExtentPointA(dcMem, source, numBytes, &size);
1192 GetTextMetrics(dcMem, &tm);
1184 GetTextMetricsW(dcMem, &tm);
11931185 size.cx -= tm.tmOverhang;
11941186 bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
11951187 oldBitmap = SelectObject(dcMem, bitmap);
12561248 HBRUSH oldBrush, stipple;
12571249 HBITMAP oldBitmap, bitmap;
12581250 HDC dcMem;
1259 TEXTMETRIC tm;
1251 TEXTMETRICW tm;
12601252 SIZE size;
12611253
12621254 if (twdPtr->type != TWD_BITMAP) {
12831275 */
12841276
12851277 GetTextExtentPointA(dcMem, source, numBytes, &size);
1286 GetTextMetrics(dcMem, &tm);
1278 GetTextMetricsW(dcMem, &tm);
12871279 size.cx -= tm.tmOverhang;
12881280 bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
12891281 oldBitmap = SelectObject(dcMem, bitmap);
13221314 } else {
13231315 HBITMAP oldBitmap, bitmap;
13241316 HDC dcMem;
1325 TEXTMETRIC tm;
1317 TEXTMETRICW tm;
13261318 SIZE size;
13271319
13281320 dcMem = CreateCompatibleDC(dc);
13371329 */
13381330
13391331 GetTextExtentPointA(dcMem, source, numBytes, &size);
1340 GetTextMetrics(dcMem, &tm);
1332 GetTextMetricsW(dcMem, &tm);
13411333 size.cx -= tm.tmOverhang;
13421334 bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
13431335 oldBitmap = SelectObject(dcMem, bitmap);
14441436 Tcl_DString runString;
14451437 const char *p, *end, *next;
14461438 SubFont *lastSubFontPtr, *thisSubFontPtr;
1447 TEXTMETRIC tm;
1439 TEXTMETRICW tm;
14481440
14491441 lastSubFontPtr = &fontPtr->subFontArray[0];
14501442 oldFont = SelectFont(hdc, fontPtr, lastSubFontPtr, angle);
1451 GetTextMetrics(hdc, &tm);
1443 GetTextMetricsW(hdc, &tm);
14521444
14531445 end = source + numBytes;
14541446 for (p = source; p < end; ) {
14681460 Tcl_UtfToExternalDString(familyPtr->encoding, source,
14691461 (int) (p - source), &runString);
14701462 familyPtr->textOutProc(hdc, x-(tm.tmOverhang/2), y,
1471 (TCHAR *)Tcl_DStringValue(&runString),
1463 (WCHAR *)Tcl_DStringValue(&runString),
14721464 Tcl_DStringLength(&runString)>>familyPtr->isWideFont);
14731465 familyPtr->getTextExtentPoint32Proc(hdc,
1474 (TCHAR *)Tcl_DStringValue(&runString),
1466 (WCHAR *)Tcl_DStringValue(&runString),
14751467 Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
14761468 &size);
14771469 x += size.cx;
14801472 lastSubFontPtr = thisSubFontPtr;
14811473 source = p;
14821474 SelectFont(hdc, fontPtr, lastSubFontPtr, angle);
1483 GetTextMetrics(hdc, &tm);
1475 GetTextMetricsW(hdc, &tm);
14841476 }
14851477 p = next;
14861478 }
14891481 Tcl_UtfToExternalDString(familyPtr->encoding, source,
14901482 (int) (p - source), &runString);
14911483 familyPtr->textOutProc(hdc, x-(tm.tmOverhang/2), y,
1492 (TCHAR *)Tcl_DStringValue(&runString),
1484 (WCHAR *)Tcl_DStringValue(&runString),
14931485 Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
14941486 Tcl_DStringFree(&runString);
14951487 }
15501542 HFONT hFont, /* Windows token for font. */
15511543 int overstrike, /* The overstrike attribute of logfont used to
15521544 * allocate this font. For some reason, the
1553 * TEXTMETRICs may contain incorrect info in
1545 * TEXTMETRICWs may contain incorrect info in
15541546 * the tmStruckOut field. */
15551547 WinFont *fontPtr) /* Filled with information constructed from
15561548 * the above arguments. */
15581550 HDC hdc;
15591551 HWND hwnd;
15601552 HFONT oldFont;
1561 TEXTMETRIC tm;
1553 TEXTMETRICW tm;
15621554 Window window;
15631555 TkFontMetrics *fmPtr;
15641556 Tcl_Encoding encoding;
15651557 Tcl_DString faceString;
15661558 TkFontAttributes *faPtr;
1567 TCHAR buf[LF_FACESIZE];
1559 WCHAR buf[LF_FACESIZE];
15681560
15691561 window = Tk_WindowId(tkwin);
15701562 hwnd = (window == None) ? NULL : TkWinGetHWND(window);
15711563 hdc = GetDC(hwnd);
15721564 oldFont = SelectObject(hdc, hFont);
15731565
1574 GetTextMetrics(hdc, &tm);
1575
1576 /*
1577 * On any version NT, there may fonts with international names. Use the
1578 * NT-only Unicode version of GetTextFace to get the font's name. If we
1579 * used the ANSI version on a non-internationalized version of NT, we
1580 * would get a font name with '?' replacing all the international
1581 * characters.
1582 *
1583 * On a non-internationalized verson of 95, fonts with international names
1584 * are not allowed, so the ANSI version of GetTextFace will work. On an
1585 * internationalized version of 95, there may be fonts with international
1586 * names; the ANSI version will work, fetching the name in the
1587 * international system code page. Can't use the Unicode version of
1588 * GetTextFace because it only exists under NT.
1589 */
1590
1591 GetTextFace(hdc, LF_FACESIZE, buf);
1592 Tcl_ExternalToUtfDString(systemEncoding, (char *) buf, -1, &faceString);
1566 GetTextMetricsW(hdc, &tm);
1567
1568 GetTextFaceW(hdc, LF_FACESIZE, buf);
1569 Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &faceString);
15931570
15941571 fontPtr->font.fid = (Font) fontPtr;
15951572 fontPtr->hwnd = hwnd;
16181595
16191596 encoding = fontPtr->subFontArray[0].familyPtr->encoding;
16201597 if (encoding == TkWinGetUnicodeEncoding()) {
1621 GetCharWidth(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
1598 GetCharWidthW(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
16221599 } else {
16231600 GetCharWidthA(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
16241601 }
17601737 FontFamily *familyPtr;
17611738 Tcl_DString faceString;
17621739 Tcl_Encoding encoding;
1763 TCHAR buf[LF_FACESIZE];
1740 WCHAR buf[LF_FACESIZE];
17641741 ThreadSpecificData *tsdPtr =
17651742 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
17661743
17671744 hFont = SelectObject(hdc, hFont);
1768 GetTextFace(hdc, LF_FACESIZE, buf);
1769 Tcl_ExternalToUtfDString(systemEncoding, (char *) buf, -1, &faceString);
1745 GetTextFaceW(hdc, LF_FACESIZE, buf);
1746 Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &faceString);
17701747 faceName = Tk_GetUid(Tcl_DStringValue(&faceString));
17711748 Tcl_DStringFree(&faceString);
17721749 hFont = SelectObject(hdc, hFont);
18221799 }
18231800
18241801 if (encoding == NULL) {
1825 encoding = Tcl_GetEncoding(NULL, "unicode");
1802 encoding = TkWinGetUnicodeEncoding();
18261803 familyPtr->textOutProc =
1827 (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutW;
1804 (BOOL (WINAPI *)(HDC, int, int, WCHAR *, int)) TextOutW;
18281805 familyPtr->getTextExtentPoint32Proc =
1829 (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32W;
1806 (BOOL (WINAPI *)(HDC, WCHAR *, int, LPSIZE)) GetTextExtentPoint32W;
18301807 familyPtr->isWideFont = 1;
18311808 } else {
18321809 familyPtr->textOutProc =
1833 (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutA;
1810 (BOOL (WINAPI *)(HDC, int, int, WCHAR *, int)) TextOutA;
18341811 familyPtr->getTextExtentPoint32Proc =
1835 (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32A;
1812 (BOOL (WINAPI *)(HDC, WCHAR *, int, LPSIZE)) GetTextExtentPoint32A;
18361813 familyPtr->isWideFont = 0;
18371814 }
18381815
19421919 SubFont *subFontPtr;
19431920 Tcl_DString ds;
19441921
1945
1946 if ((ch < BASE_CHARS) || (ch >= 0x10000)) {
1922 if ((ch < BASE_CHARS) || (ch >= 0x30000)) {
19471923 return &fontPtr->subFontArray[0];
19481924 }
19491925
20282004 canUse.ch = ch;
20292005 canUse.subFontPtr = NULL;
20302006 canUse.subFontPtrPtr = subFontPtrPtr;
2031 EnumFontFamilies(hdc, NULL, (FONTENUMPROC) WinFontCanUseProc,
2007 EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontCanUseProc,
20322008 (LPARAM) &canUse);
20332009 subFontPtr = canUse.subFontPtr;
20342010
20502026
20512027 static int CALLBACK
20522028 WinFontCanUseProc(
2053 ENUMLOGFONT *lfPtr, /* Logical-font data. */
2029 ENUMLOGFONTW *lfPtr, /* Logical-font data. */
20542030 NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
20552031 int fontType, /* Type of font (not used). */
20562032 LPARAM lParam) /* Result object to hold result. */
20702046 fontPtr = canUsePtr->fontPtr;
20712047 nameTriedPtr = canUsePtr->nameTriedPtr;
20722048
2073 fallbackName = (char *) lfPtr->elfLogFont.lfFaceName;
2074 Tcl_ExternalToUtfDString(systemEncoding, fallbackName, -1, &faceString);
2075 fallbackName = Tcl_DStringValue(&faceString);
2049 fallbackName = Tcl_WinTCharToUtf((LPCTSTR)lfPtr->elfLogFont.lfFaceName, -1, &faceString);
20762050
20772051 if (SeenName(fallbackName, nameTriedPtr) == 0) {
20782052 subFontPtr = CanUseFallback(hdc, fontPtr, fallbackName, ch,
21152089 {
21162090 int row, bitOffset;
21172091
2092 if (ch < 0 || ch >= 0x30000) {
2093 return 0;
2094 }
2095
21182096 row = ch >> FONTMAP_SHIFT;
21192097 if (subFontPtr->fontMap[row] == NULL) {
21202098 FontMapLoadPage(subFontPtr, row);
21552133 {
21562134 int row, bitOffset;
21572135
2158 row = ch >> FONTMAP_SHIFT;
2159 if (subFontPtr->fontMap[row] == NULL) {
2160 FontMapLoadPage(subFontPtr, row);
2161 }
2162 bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
2163 subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
2136 if (ch >= 0 && ch < 0x30000) {
2137 row = ch >> FONTMAP_SHIFT;
2138 if (subFontPtr->fontMap[row] == NULL) {
2139 FontMapLoadPage(subFontPtr, row);
2140 }
2141 bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
2142 subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
2143 }
21642144 }
21652145
21662146 /*
21772157 * None.
21782158 *
21792159 * Side effects:
2180 * Mempry allocated.
2160 * Memory allocated.
21812161 *
21822162 *-------------------------------------------------------------------------
21832163 */
22442224 end = (row + 1) << FONTMAP_SHIFT;
22452225 for (i = row << FONTMAP_SHIFT; i < end; i++) {
22462226 if (Tcl_UtfToExternal(NULL, encoding, src,
2247 Tcl_UniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,
2227 TkUniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,
22482228 buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) {
22492229 continue;
22502230 }
24762456 {
24772457 Tcl_DString ds;
24782458 HFONT hFont;
2479 LOGFONT lf;
2459 LOGFONTW lf;
24802460
24812461 memset(&lf, 0, sizeof(lf));
24822462 lf.lfHeight = -pixelSize;
24932473 lf.lfQuality = DEFAULT_QUALITY;
24942474 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
24952475
2496 Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &ds);
2497 _tcsncpy(lf.lfFaceName, (TCHAR *)Tcl_DStringValue(&ds), LF_FACESIZE-1);
2476 Tcl_WinUtfToTChar(faceName, -1, &ds);
2477 wcsncpy(lf.lfFaceName, (WCHAR *)Tcl_DStringValue(&ds), LF_FACESIZE-1);
24982478 Tcl_DStringFree(&ds);
24992479 lf.lfFaceName[LF_FACESIZE-1] = 0;
2500 hFont = CreateFontIndirect(&lf);
2480 hFont = CreateFontIndirectW(&lf);
25012481 return hFont;
25022482 }
25032483
25442524 return 0;
25452525 }
25462526
2547 Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &faceString);
2527 Tcl_WinUtfToTChar(faceName, -1, &faceString);
25482528
25492529 /*
25502530 * If the family exists, WinFontExistProc() will be called and
25532533 * non-zero value.
25542534 */
25552535
2556 result = EnumFontFamilies(hdc, (TCHAR*) Tcl_DStringValue(&faceString),
2557 (FONTENUMPROC) WinFontExistProc, 0);
2536 result = EnumFontFamiliesW(hdc, (WCHAR*) Tcl_DStringValue(&faceString),
2537 (FONTENUMPROCW) WinFontExistProc, 0);
25582538 Tcl_DStringFree(&faceString);
25592539 return (result == 0);
25602540 }
25832563
25842564 static int CALLBACK
25852565 WinFontExistProc(
2586 ENUMLOGFONT *lfPtr, /* Logical-font data. */
2566 ENUMLOGFONTW *lfPtr, /* Logical-font data. */
25872567 NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
25882568 int fontType, /* Type of font (not used). */
25892569 LPARAM lParam) /* EnumFontData to hold result. */
125125 */
126126
127127 destPtr[3] = 0;
128 /* FALLTHRU */
128129 case 24:
129130 /*
130131 * Pixel is triplet: 0xBBGGRR.
346347
347348 size = sizeof(BITMAPINFO);
348349 if (depth <= 8) {
349 size += sizeof(unsigned short) * (1 << depth);
350 size += sizeof(unsigned short) << depth;
350351 }
351352 bmInfo = ckalloc(size);
352353
177177 TkWin32ErrorObj(
178178 HRESULT hrError)
179179 {
180 LPTSTR lpBuffer = NULL, p = NULL;
181 TCHAR sBuffer[30];
180 LPWSTR lpBuffer = NULL, p = NULL;
181 WCHAR sBuffer[30];
182182 Tcl_Obj* errPtr = NULL;
183 #ifdef _UNICODE
184183 Tcl_DString ds;
185 #endif
186
187 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
184
185 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
188186 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)hrError,
189 LANG_NEUTRAL, (LPTSTR)&lpBuffer, 0, NULL);
187 LANG_NEUTRAL, (LPWSTR)&lpBuffer, 0, NULL);
190188
191189 if (lpBuffer == NULL) {
192190 lpBuffer = sBuffer;
193 wsprintf(sBuffer, TEXT("Error Code: %08lX"), hrError);
194 }
195
196 if ((p = _tcsrchr(lpBuffer, TEXT('\r'))) != NULL) {
197 *p = TEXT('\0');
198 }
199
200 #ifdef _UNICODE
201 Tcl_WinTCharToUtf(lpBuffer, (int)wcslen(lpBuffer) * sizeof (WCHAR), &ds);
191 wsprintfW(sBuffer, L"Error Code: %08lX", hrError);
192 }
193
194 if ((p = wcsrchr(lpBuffer, '\r')) != NULL) {
195 *p = '\0';
196 }
197
198 Tcl_WinTCharToUtf((LPCTSTR)lpBuffer, -1, &ds);
202199 errPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
203200 Tcl_DStringFree(&ds);
204 #else
205 errPtr = Tcl_NewStringObj(lpBuffer, (int)strlen(lpBuffer));
206 #endif /* _UNICODE */
207201
208202 if (lpBuffer != sBuffer) {
209203 LocalFree((HLOCAL)lpBuffer);
116116 * The following macros define the class names for Tk Window types.
117117 */
118118
119 #define TK_WIN_TOPLEVEL_CLASS_NAME TEXT("TkTopLevel")
120 #define TK_WIN_CHILD_CLASS_NAME TEXT("TkChild")
119 #define TK_WIN_TOPLEVEL_CLASS_NAME L"TkTopLevel"
120 #define TK_WIN_CHILD_CLASS_NAME L"TkChild"
121121
122122 /*
123123 * The following variable is a translation table between X gc functions and
200200 MODULE_SCOPE int TkpWmGetState(TkWindow *winPtr);
201201
202202 /*
203 * The following is implemented in tkWinPointer.c and also used in tkWinWindow.c
204 */
205
206 MODULE_SCOPE void TkSetCursorPos(int x, int y);
207
208 /*
203209 * Common routines used in Windows implementation
204210 */
205211 MODULE_SCOPE Tcl_Obj * TkWin32ErrorObj(HRESULT hrError);
212218 */
213219
214220 #ifndef GetClassLongPtr
215 # define GetClassLongPtrA GetClassLongA
216221 # define GetClassLongPtrW GetClassLongW
217 # define SetClassLongPtrA SetClassLongA
218222 # define SetClassLongPtrW SetClassLongW
219 # ifdef UNICODE
220 # define GetClassLongPtr GetClassLongPtrW
221 # define SetClassLongPtr SetClassLongPtrW
222 # else
223 # define GetClassLongPtr GetClassLongPtrA
224 # define SetClassLongPtr SetClassLongPtrA
225 # endif /* !UNICODE */
226223 #endif /* !GetClassLongPtr */
227224 #ifndef GCLP_HICON
228225 # define GCLP_HICON GCL_HICON
232229 #endif /* !GCLP_HICONSM */
233230
234231 #ifndef GetWindowLongPtr
235 # define GetWindowLongPtrA GetWindowLongA
236232 # define GetWindowLongPtrW GetWindowLongW
237 # define SetWindowLongPtrA SetWindowLongA
238233 # define SetWindowLongPtrW SetWindowLongW
239 # ifdef UNICODE
240 # define GetWindowLongPtr GetWindowLongPtrW
241 # define SetWindowLongPtr SetWindowLongPtrW
242 # else
243 # define GetWindowLongPtr GetWindowLongPtrW
244 # define SetWindowLongPtr SetWindowLongPtrW
245 # endif /* !UNICODE */
246234 #endif /* !GetWindowLongPtr */
247235 #ifndef GWLP_WNDPROC
248236 #define GWLP_WNDPROC GWL_WNDPROC
1010 */
1111
1212 #include "tkWinInt.h"
13 #include "X11/XF86keysym.h"
1314
1415 /*
1516 * The keymap table holds mappings of Windows keycodes to X keysyms. If
2021 * like a worthwhile improvement to use the table.
2122 */
2223
23 #define MAX_KEYCODE 179 /* VK_MEDIA_PLAY_PAUSE is the last entry in our table below */
24 #define MAX_KEYCODE 183 /* VK_LAUNCH_APP2 is the last entry in our table below */
2425 /* cf. https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx */
2526
2627 static const KeySym keymap[] = {
27 NoSymbol, NoSymbol, NoSymbol, XK_Cancel, NoSymbol,
28 NoSymbol, NoSymbol, NoSymbol, XK_BackSpace, XK_Tab,
29 NoSymbol, NoSymbol, XK_Clear, XK_Return, NoSymbol,
30 NoSymbol, XK_Shift_L, XK_Control_L, XK_Alt_L, XK_Pause,
31 XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
32 NoSymbol, NoSymbol, XK_Escape, NoSymbol, NoSymbol,
33 NoSymbol, NoSymbol, XK_space, XK_Prior, XK_Next,
34 XK_End, XK_Home, XK_Left, XK_Up, XK_Right,
35 XK_Down, XK_Select, XK_Print, XK_Execute, NoSymbol,
36 XK_Insert, XK_Delete, XK_Help, NoSymbol, NoSymbol,
37 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
38 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
39 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
40 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
41 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
42 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
43 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
44 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
45 NoSymbol, XK_Win_L, XK_Win_R, XK_App, NoSymbol,
46 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
47 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
48 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
49 NoSymbol, NoSymbol, XK_F1, XK_F2, XK_F3,
50 XK_F4, XK_F5, XK_F6, XK_F7, XK_F8,
51 XK_F9, XK_F10, XK_F11, XK_F12, XK_F13,
52 XK_F14, XK_F15, XK_F16, XK_F17, XK_F18,
53 XK_F19, XK_F20, XK_F21, XK_F22, XK_F23,
54 XK_F24, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
55 NoSymbol, NoSymbol, NoSymbol, NoSymbol, XK_Num_Lock,
56 XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
28 NoSymbol, NoSymbol, NoSymbol, XK_Cancel, NoSymbol, /*0 0x0*/
29 NoSymbol, NoSymbol, NoSymbol, XK_BackSpace, XK_Tab, /*5 0x5*/
30 NoSymbol, NoSymbol, XK_Clear, XK_Return, NoSymbol, /*10 0xA*/
31 NoSymbol, XK_Shift_L, XK_Control_L, XK_Alt_L, XK_Pause, /*15 0xE*/
32 XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*20 0x14*/
33 NoSymbol, NoSymbol, XK_Escape, NoSymbol, NoSymbol, /*25 0x19*/
34 NoSymbol, NoSymbol, XK_space, XK_Prior, XK_Next, /*30 0x1E*/
35 XK_End, XK_Home, XK_Left, XK_Up, XK_Right, /*35 0x23*/
36 XK_Down, XK_Select, XK_Print, XK_Execute, NoSymbol, /*40 0x28*/
37 XK_Insert, XK_Delete, XK_Help, NoSymbol, NoSymbol, /*45 0x2D*/
38 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*50 0x32*/
39 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*55 0x37*/
40 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*60 0x3C*/
41 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*65 0x41*/
42 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*70 0x46*/
43 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*75 0x4B*/
44 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*80 0x50*/
45 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*85 0x55*/
46 NoSymbol, XK_Win_L, XK_Win_R, XK_App, NoSymbol, /*90 0x5A*/
47 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*95 0x5F*/
48 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*100 0x64*/
49 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*105 0x69*/
50 NoSymbol, NoSymbol, XK_F1, XK_F2, XK_F3, /*110 0x6E*/
51 XK_F4, XK_F5, XK_F6, XK_F7, XK_F8, /*115 0x73*/
52 XK_F9, XK_F10, XK_F11, XK_F12, XK_F13, /*120 0x78*/
53 XK_F14, XK_F15, XK_F16, XK_F17, XK_F18, /*125 0x7D*/
54 XK_F19, XK_F20, XK_F21, XK_F22, XK_F23, /*130 0x82*/
55 XK_F24, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*135 0x87*/
56 NoSymbol, NoSymbol, NoSymbol, NoSymbol, XK_Num_Lock, /*140 0x8C*/
57 XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*145 0x91*/
5758 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*150 0x96*/
58 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*155 0x9b*/
59 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*160 0xa0*/
60 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*165 0xa5*/
61 NoSymbol, NoSymbol, NoSymbol, XK_XF86AudioMute, XK_XF86AudioLowerVolume, /*170 0xaa*/
62 XK_XF86AudioRaiseVolume, XK_XF86AudioNext, XK_XF86AudioPrev, XK_XF86AudioStop, XK_XF86AudioPlay /*175 0xaf*/
59 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*155 0x9B*/
60 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*160 0xA0*/
61 NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, /*165 0xA5*/
62 NoSymbol, NoSymbol, NoSymbol, XF86XK_AudioMute, XF86XK_AudioLowerVolume, /*170 0xAA*/
63 XF86XK_AudioRaiseVolume, XF86XK_AudioNext, XF86XK_AudioPrev, XF86XK_AudioStop, XF86XK_AudioPlay, /*175 0xAF*/
64 XF86XK_Mail, XF86XK_AudioMedia, XF86XK_Launch0, XF86XK_Launch1 /*180 0xB4*/
6365 };
6466
6567 /*
121123
122124 if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))
123125 || (keysym == XK_Return) || (keysym == XK_Tab)) {
124 len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);
126 len = TkUniCharToUtf(keysym & 255, buf);
125127 Tcl_DStringAppend(dsPtr, buf, len);
126128 }
127129 }
185187 {
186188 BYTE keys[256];
187189 int result, deadkey, shift;
188 TCHAR buf[4];
189 unsigned int scancode = MapVirtualKey(keycode, 0);
190 WCHAR buf[4];
191 unsigned int scancode = MapVirtualKeyW(keycode, 0);
190192
191193 /*
192194 * Do not run keycodes of lock keys through ToUnicode(). One of ToUnicode()'s
200202 }
201203
202204 /*
203 * Use MapVirtualKey() to detect some dead keys.
204 */
205
206 if (MapVirtualKey(keycode, 2) > 0x7fffUL) {
205 * Use MapVirtualKeyW() to detect some dead keys.
206 */
207
208 if (MapVirtualKeyW(keycode, 2) > 0x7fffUL) {
207209 return XK_Multi_key;
208210 }
209211
260262 * Get information about the old char
261263 */
262264
263 deadkey = VkKeyScan(buf[0]);
265 deadkey = VkKeyScanW(buf[0]);
264266 shift = deadkey >> 8;
265267 deadkey &= 255;
266 scancode = MapVirtualKey(deadkey, 0);
268 scancode = MapVirtualKeyW(deadkey, 0);
267269
268270 /*
269271 * Set up a keyboard with proper modifier keys
571573 }
572574 }
573575 if (keySym >= 0x20) {
574 result = VkKeyScan((TCHAR) keySym);
576 result = VkKeyScanW((WCHAR) keySym);
575577 if (result != -1) {
576578 shift = result >> 8;
577579 if (shift & 1)
624626 }
625627 }
626628 if (keysym >= 0x20) {
627 result = VkKeyScan((TCHAR) keysym);
629 result = VkKeyScanW((WCHAR) keysym);
628630 if (result != -1) {
629631 return (KeyCode) (result & 0xff);
630632 }
1818 * The class of the window for popup menus.
1919 */
2020
21 #define MENU_CLASS_NAME TEXT("MenuWindowClass")
22 #define EMBEDDED_MENU_CLASS_NAME TEXT("EmbeddedMenuWindowClass")
21 #define MENU_CLASS_NAME L"MenuWindowClass"
22 #define EMBEDDED_MENU_CLASS_NAME L"EmbeddedMenuWindowClass"
2323
2424 /*
2525 * Used to align a windows bitmap inside a rectangle
8484
8585 static BOOL showMenuAccelerators;
8686
87 typedef struct ThreadSpecificData {
87 typedef struct {
8888 int inPostMenu; /* We cannot be re-entrant like X Windows. */
8989 WORD lastCommandID; /* The last command ID we allocated. */
9090 HWND menuHWND; /* A window to service popup-menu messages
572572 TkMenuEntry *mePtr;
573573 HMENU winMenuHdl = (HMENU) menuPtr->platformData;
574574 char *itemText = NULL;
575 const TCHAR *lpNewItem;
575 LPCWSTR lpNewItem;
576576 UINT flags;
577577 UINT itemID;
578578 int i, count, systemMenu = 0, base;
609609 if ((menuPtr->menuType == MENUBAR)
610610 || (menuPtr->menuFlags & MENU_SYSTEM_MENU)) {
611611 Tcl_WinUtfToTChar(itemText, -1, &translatedText);
612 lpNewItem = (const TCHAR *) Tcl_DStringValue(&translatedText);
612 lpNewItem = (LPCWSTR) Tcl_DStringValue(&translatedText);
613613 flags |= MF_STRING;
614614 } else {
615 lpNewItem = (LPCTSTR) mePtr;
615 lpNewItem = (LPCWSTR) mePtr;
616616 flags |= MF_OWNERDRAW;
617617 }
618618
715715 }
716716 }
717717 if (!systemMenu) {
718 InsertMenu(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);
718 InsertMenuW(winMenuHdl, 0xFFFFFFFF, flags, itemID, lpNewItem);
719719 }
720720 Tcl_DStringFree(&translatedText);
721721 if (itemText != NULL) {
742742 *
743743 * TkpPostMenu --
744744 *
745 * Posts a menu on the screen
745 * Posts a menu on the screen so that the top left corner of the
746 * specified entry is located at the point (x, y) in screen coordinates.
747 * If the entry parameter is negative, the upper left corner of the
748 * menu itself is placed at the point.
746749 *
747750 * Results:
748751 * None.
757760 TkpPostMenu(
758761 Tcl_Interp *interp,
759762 TkMenu *menuPtr,
760 int x, int y)
763 int x, int y, int index)
761764 {
762765 HMENU winMenuHdl = (HMENU) menuPtr->platformData;
763766 int result, flags;
769772 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
770773
771774 tsdPtr->inPostMenu++;
772
773775 CallPendingReconfigureImmediately(menuPtr);
774776
775777 result = TkPreprocessMenu(menuPtr);
776778 if (result != TCL_OK) {
777779 tsdPtr->inPostMenu--;
778780 return result;
781 }
782
783 if (index >= menuPtr->numEntries) {
784 index = menuPtr->numEntries - 1;
785 }
786 if (index >= 0) {
787 y -= menuPtr->entries[index]->y;
779788 }
780789
781790 /*
840849 /*
841850 *----------------------------------------------------------------------
842851 *
852 * TkpPostTearoffMenu --
853 *
854 * Posts a tearoff menu on the screen so that the top left corner of the
855 * specified entry is located at the point (x, y) in screen coordinates.
856 * If the index parameter is negative, the upper left corner of the menu
857 * itself is placed at the point. Adjusts the menu's position so that it
858 * fits on the screen, and maps and raises the menu.
859 *
860 * Results:
861 * Returns a standard Tcl Error.
862 *
863 * Side effects:
864 * The menu is posted.
865 *
866 *----------------------------------------------------------------------
867 */
868
869 int
870 TkpPostTearoffMenu(
871 Tcl_Interp *interp, /* The interpreter of the menu */
872 TkMenu *menuPtr, /* The menu we are posting */
873 int x, int y, int index) /* The root X,Y coordinates where we are
874 * posting */
875 {
876 int vRootX, vRootY, vRootWidth, vRootHeight;
877 int result;
878
879 if (index >= menuPtr->numEntries) {
880 index = menuPtr->numEntries - 1;
881 }
882 if (index >= 0) {
883 y -= menuPtr->entries[index]->y;
884 }
885
886 TkActivateMenuEntry(menuPtr, -1);
887 TkRecomputeMenu(menuPtr);
888 result = TkPostCommand(menuPtr);
889 if (result != TCL_OK) {
890 return result;
891 }
892
893 /*
894 * The post commands could have deleted the menu, which means we are dead
895 * and should go away.
896 */
897
898 if (menuPtr->tkwin == NULL) {
899 return TCL_OK;
900 }
901
902 /*
903 * Adjust the position of the menu if necessary to keep it visible on the
904 * screen. There are two special tricks to make this work right:
905 *
906 * 1. If a virtual root window manager is being used then the coordinates
907 * are in the virtual root window of menuPtr's parent; since the menu
908 * uses override-redirect mode it will be in the *real* root window for
909 * the screen, so we have to map the coordinates from the virtual root
910 * (if any) to the real root. Can't get the virtual root from the menu
911 * itself (it will never be seen by the wm) so use its parent instead
912 * (it would be better to have an an option that names a window to use
913 * for this...).
914 * 2. The menu may not have been mapped yet, so its current size might be
915 * the default 1x1. To compute how much space it needs, use its
916 * requested size, not its actual size.
917 */
918
919 Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
920 &vRootWidth, &vRootHeight);
921 vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
922 if (x > vRootX + vRootWidth) {
923 x = vRootX + vRootWidth;
924 }
925 if (x < vRootX) {
926 x = vRootX;
927 }
928 vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
929 if (y > vRootY + vRootHeight) {
930 y = vRootY + vRootHeight;
931 }
932 if (y < vRootY) {
933 y = vRootY;
934 }
935 Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
936 if (!Tk_IsMapped(menuPtr->tkwin)) {
937 Tk_MapWindow(menuPtr->tkwin);
938 }
939 TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
940 return TCL_OK;
941 }
942
943 /*
944 *----------------------------------------------------------------------
945 *
843946 * TkpMenuNewEntry --
844947 *
845948 * Adds a pointer to a new menu entry structure with the platform-
8991002 LRESULT lResult;
9001003
9011004 if (!TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam, &lResult)) {
902 lResult = DefWindowProc(hwnd, message, wParam, lParam);
1005 lResult = DefWindowProcW(hwnd, message, wParam, lParam);
9031006 }
9041007 return lResult;
9051008 }
9961099 if (lResult || (GetCapture() != hwnd)) {
9971100 break;
9981101 }
999
1102 /* FALLTHRU */
10001103 default:
1001 lResult = DefWindowProc(hwnd, message, wParam, lParam);
1104 lResult = DefWindowProcW(hwnd, message, wParam, lParam);
10021105 break;
10031106 }
10041107 return lResult;
11451248 if (hashEntryPtr != NULL) {
11461249 int i, len, underline;
11471250 Tcl_Obj *labelPtr;
1148 Tcl_UniChar *wlabel, menuChar;
1251 LPCWSTR wlabel;
1252 int menuChar;
1253 Tcl_DString ds;
11491254
11501255 *plResult = 0;
11511256 menuPtr = Tcl_GetHashValue(hashEntryPtr);
11531258 * Assume we have something directly convertable to Tcl_UniChar.
11541259 * True at least for wide systems.
11551260 */
1156 menuChar = Tcl_UniCharToUpper((Tcl_UniChar) LOWORD(*pwParam));
1157
1261 menuChar = Tcl_UniCharToUpper(LOWORD(*pwParam));
1262
1263 Tcl_DStringInit(&ds);
11581264 for (i = 0; i < menuPtr->numEntries; i++) {
11591265 underline = menuPtr->entries[i]->underline;
11601266 labelPtr = menuPtr->entries[i]->labelPtr;
11621268 /*
11631269 * Ensure we don't exceed the label length, then check
11641270 */
1165 wlabel = Tcl_GetUnicodeFromObj(labelPtr, &len);
1271 const char *src = Tcl_GetStringFromObj(labelPtr, &len);
1272
1273 Tcl_DStringFree(&ds);
1274 wlabel = (LPCWSTR) Tcl_WinUtfToTChar(src, len, &ds);
11661275 if ((underline < len) && (menuChar ==
11671276 Tcl_UniCharToUpper(wlabel[underline]))) {
11681277 *plResult = (2 << 16) | i;
11711280 }
11721281 }
11731282 }
1283 Tcl_DStringFree(&ds);
11741284 }
11751285 break;
11761286 }
16351745 SetTextColor(hdc, gc->foreground);
16361746
16371747 scratchDC = CreateCompatibleDC(hdc);
1638 bitmap = LoadBitmap(NULL, MAKEINTRESOURCE(bitmapID));
1748 bitmap = LoadBitmapW(NULL, (LPCWSTR)MAKEINTRESOURCE(bitmapID));
16391749
16401750 SelectObject(scratchDC, bitmap);
16411751 SetMapMode(scratchDC, GetMapMode(hdc));
19662076 if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
19672077 int len;
19682078
1969 /* do the unicode call just to prevent overruns */
1970 Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len);
2079 len = Tcl_GetCharLength(mePtr->labelPtr);
19712080 if (mePtr->underline < len) {
19722081 const char *label, *start, *end;
19732082
19892098 *
19902099 * This function is invoked when keys related to pulling down menus is
19912100 * pressed. The corresponding Windows events are generated and passed to
1992 * DefWindowProc if appropriate. This cmd is registered as tk::WinMenuKey
2101 * DefWindowProcW if appropriate. This cmd is registered as tk::WinMenuKey
19932102 * in the interp.
19942103 *
19952104 * Results:
20442153 if (eventPtr->type == KeyPress) {
20452154 switch (keySym) {
20462155 case XK_Alt_L:
2047 scanCode = MapVirtualKey(VK_LMENU, 0);
2048 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2156 scanCode = MapVirtualKeyW(VK_LMENU, 0);
2157 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
20492158 WM_SYSKEYDOWN, VK_MENU,
20502159 (int) (scanCode << 16) | (1 << 29));
20512160 break;
20522161 case XK_Alt_R:
2053 scanCode = MapVirtualKey(VK_RMENU, 0);
2054 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2162 scanCode = MapVirtualKeyW(VK_RMENU, 0);
2163 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
20552164 WM_SYSKEYDOWN, VK_MENU,
20562165 (int) (scanCode << 16) | (1 << 29) | (1 << 24));
20572166 break;
20582167 case XK_F10:
2059 scanCode = MapVirtualKey(VK_F10, 0);
2060 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2168 scanCode = MapVirtualKeyW(VK_F10, 0);
2169 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
20612170 WM_SYSKEYDOWN, VK_F10, (int) (scanCode << 16));
20622171 break;
20632172 default:
20642173 virtualKey = XKeysymToKeycode(winPtr->display, keySym);
2065 scanCode = MapVirtualKey(virtualKey, 0);
2174 scanCode = MapVirtualKeyW(virtualKey, 0);
20662175 if (0 != scanCode) {
20672176 XKeyEvent xkey = eventPtr->xkey;
2068 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2177 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
20692178 WM_SYSKEYDOWN, virtualKey,
20702179 (int) ((scanCode << 16) | (1 << 29)));
20712180 if (xkey.nbytes > 0) {
20722181 for (i = 0; i < xkey.nbytes; i++) {
2073 CallWindowProc(DefWindowProc,
2182 CallWindowProcW(DefWindowProcW,
20742183 Tk_GetHWND(Tk_WindowId(tkwin)), WM_SYSCHAR,
20752184 xkey.trans_chars[i],
20762185 (int) ((scanCode << 16) | (1 << 29)));
20812190 } else if (eventPtr->type == KeyRelease) {
20822191 switch (keySym) {
20832192 case XK_Alt_L:
2084 scanCode = MapVirtualKey(VK_LMENU, 0);
2085 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2193 scanCode = MapVirtualKeyW(VK_LMENU, 0);
2194 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
20862195 WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16)
20872196 | (1 << 29) | (1 << 30) | (1 << 31));
20882197 break;
20892198 case XK_Alt_R:
2090 scanCode = MapVirtualKey(VK_RMENU, 0);
2091 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2199 scanCode = MapVirtualKeyW(VK_RMENU, 0);
2200 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
20922201 WM_SYSKEYUP, VK_MENU, (int) (scanCode << 16) | (1 << 24)
20932202 | (1 << 29) | (1 << 30) | (1 << 31));
20942203 break;
20952204 case XK_F10:
2096 scanCode = MapVirtualKey(VK_F10, 0);
2097 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2205 scanCode = MapVirtualKeyW(VK_F10, 0);
2206 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
20982207 WM_SYSKEYUP, VK_F10,
20992208 (int) (scanCode << 16) | (1 << 30) | (1 << 31));
21002209 break;
21012210 default:
21022211 virtualKey = XKeysymToKeycode(winPtr->display, keySym);
2103 scanCode = MapVirtualKey(virtualKey, 0);
2212 scanCode = MapVirtualKeyW(virtualKey, 0);
21042213 if (0 != scanCode) {
2105 CallWindowProc(DefWindowProc, Tk_GetHWND(Tk_WindowId(tkwin)),
2214 CallWindowProcW(DefWindowProcW, Tk_GetHWND(Tk_WindowId(tkwin)),
21062215 WM_SYSKEYUP, virtualKey, (int) ((scanCode << 16)
21072216 | (1 << 29) | (1 << 30) | (1 << 31)));
21082217 }
23632472 XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
23642473 (unsigned) width, (unsigned) height);
23652474 } else if ((mePtr->image != NULL)
2366 && (menuPtr->disabledImageGC != None)) {
2475 && menuPtr->disabledImageGC) {
23672476 XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
23682477 leftEdge + imageXOffset,
23692478 (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),
28963005 GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont,
28973006 fmPtr, &width, &height);
28983007 menuPtr->entries[i]->height = height;
2899
29003008 } else {
29013009 /*
29023010 * For each entry, compute the height required by that particular
29543062 }
29553063 windowWidth = x + indicatorSpace + labelWidth + accelWidth
29563064 + 2 * activeBorderWidth + borderWidth;
2957
2958
29593065 windowHeight += borderWidth;
29603066
29613067 /*
31063212 MenuExitHandler(
31073213 ClientData clientData) /* Not used */
31083214 {
3109 UnregisterClass(MENU_CLASS_NAME, Tk_GetHINSTANCE());
3110 UnregisterClass(EMBEDDED_MENU_CLASS_NAME, Tk_GetHINSTANCE());
3215 UnregisterClassW(MENU_CLASS_NAME, Tk_GetHINSTANCE());
3216 UnregisterClassW(EMBEDDED_MENU_CLASS_NAME, Tk_GetHINSTANCE());
31113217 }
31123218
31133219 /*
32073313 HDC scratchDC;
32083314 int bold = 0;
32093315 int italic = 0;
3210 TEXTMETRIC tm;
3316 TEXTMETRICW tm;
32113317 int pointSize;
32123318 HFONT menuFont;
32133319 /* See: [Bug #3239768] tk8.4.19 (and later) WIN32 menu font support */
32143320 struct {
3215 NONCLIENTMETRICS metrics;
3321 NONCLIENTMETRICSW metrics;
32163322 #if (WINVER < 0x0600)
32173323 int padding;
32183324 #endif
32293335 defaultBorderWidth = GetSystemMetrics(SM_CYBORDER);
32303336 }
32313337
3232 scratchDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
3338 scratchDC = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
32333339 if (!firstTime) {
32343340 Tcl_DStringFree(&menuFontDString);
32353341 }
32433349 nc.metrics.cbSize -= sizeof(int);
32443350 }
32453351
3246 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nc.metrics.cbSize,
3352 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, nc.metrics.cbSize,
32473353 &nc.metrics, 0);
3248 menuFont = CreateFontIndirect(&nc.metrics.lfMenuFont);
3354 menuFont = CreateFontIndirectW(&nc.metrics.lfMenuFont);
32493355 SelectObject(scratchDC, menuFont);
3250 GetTextMetrics(scratchDC, &tm);
3356 GetTextMetricsW(scratchDC, &tm);
32513357 GetTextFaceA(scratchDC, LF_FACESIZE, faceName);
32523358 pointSize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
32533359 72, GetDeviceCaps(scratchDC, LOGPIXELSY));
33043410 */
33053411
33063412 showMenuAccelerators = TRUE;
3307 SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &showMenuAccelerators, 0);
3413 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &showMenuAccelerators, 0);
33083414 }
33093415
33103416 /*
33263432 void
33273433 TkpMenuInit(void)
33283434 {
3329 WNDCLASS wndClass;
3435 WNDCLASSW wndClass;
33303436
33313437 wndClass.style = CS_OWNDC;
33323438 wndClass.lpfnWndProc = TkWinMenuProc;
33383444 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
33393445 wndClass.lpszMenuName = NULL;
33403446 wndClass.lpszClassName = MENU_CLASS_NAME;
3341 if (!RegisterClass(&wndClass)) {
3447 if (!RegisterClassW(&wndClass)) {
33423448 Tcl_Panic("Failed to register menu window class");
33433449 }
33443450
33453451 wndClass.lpfnWndProc = TkWinEmbeddedMenuProc;
33463452 wndClass.lpszClassName = EMBEDDED_MENU_CLASS_NAME;
3347 if (!RegisterClass(&wndClass)) {
3453 if (!RegisterClassW(&wndClass)) {
33483454 Tcl_Panic("Failed to register embedded menu window class");
33493455 }
33503456
33753481 ThreadSpecificData *tsdPtr =
33763482 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
33773483
3378 tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, TEXT("MenuWindow"), WS_POPUP,
3484 tsdPtr->menuHWND = CreateWindowW(MENU_CLASS_NAME, L"MenuWindow", WS_POPUP,
33793485 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
33803486
33813487 if (!tsdPtr->menuHWND) {
33833489 }
33843490
33853491 tsdPtr->embeddedMenuHWND =
3386 CreateWindow(EMBEDDED_MENU_CLASS_NAME, TEXT("EmbeddedMenuWindow"),
3492 CreateWindowW(EMBEDDED_MENU_CLASS_NAME, L"EmbeddedMenuWindow",
33873493 WS_POPUP, 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL);
33883494
33893495 if (!tsdPtr->embeddedMenuHWND) {
9999 LPVOID lpMsgBuf;
100100
101101 repeatError = 1;
102 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
102 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
103103 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
104104 NULL, GetLastError(),
105105 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
106 (LPTSTR)&lpMsgBuf, 0, NULL)) {
107 MessageBox(NULL, (LPTSTR) lpMsgBuf,
108 TEXT("Tk_GetPixmap: Error from CreateDIBSection"),
106 (LPWSTR)&lpMsgBuf, 0, NULL)) {
107 MessageBoxW(NULL, (LPWSTR) lpMsgBuf,
108 L"Tk_GetPixmap: Error from CreateDIBSection",
109109 MB_OK | MB_ICONINFORMATION);
110110 LocalFree(lpMsgBuf);
111111 }
7979 }
8080 if (GetKeyState(VK_RBUTTON) & 0x8000) {
8181 state |= Button3Mask;
82 }
83 if (GetKeyState(VK_XBUTTON1) & 0x8000) {
84 state |= Button4Mask;
85 }
86 if (GetKeyState(VK_XBUTTON2) & 0x8000) {
87 state |= Button5Mask;
8288 }
8389 return state;
8490 }
329335 /*
330336 *----------------------------------------------------------------------
331337 *
332 * XWarpPointer --
333 *
334 * Move pointer to new location. This is not a complete implementation of
335 * this function.
338 * XWarpPointer, TkpWarpPointer --
339 *
340 * Move pointer to new location. Note that implementation of XWarpPointer
341 * is incomplete.
336342 *
337343 * Results:
338344 * None.
342348 *
343349 *----------------------------------------------------------------------
344350 */
351
352 /*
353 * TkSetCursorPos is a helper function replacing SetCursorPos since this
354 * latter Windows function appears to have been broken by Microsoft
355 * since Win10 Falls Creator Update - See ticket [69b48f427e] along with
356 * several other Internet reports about this breakage.
357 */
358
359 void TkSetCursorPos(
360 int x,
361 int y)
362 {
363 INPUT input;
364 int xscreen = (int)(GetSystemMetrics(SM_CXSCREEN) - 1);
365 int yscreen = (int)(GetSystemMetrics(SM_CYSCREEN) - 1);
366
367 input.type = INPUT_MOUSE;
368 input.mi.dx = (x * 65535 + xscreen/2) / xscreen;
369 input.mi.dy = (y * 65535 + yscreen/2) / yscreen;
370 input.mi.mouseData = 0;
371 input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
372 input.mi.time = 0;
373 input.mi.dwExtraInfo = 0;
374 SendInput(1, &input, sizeof(input));
375 }
345376
346377 int
347378 XWarpPointer(
358389 RECT r;
359390
360391 GetWindowRect(Tk_GetHWND(dest_w), &r);
361 SetCursorPos(r.left+dest_x, r.top+dest_y);
392 TkSetCursorPos(r.left+dest_x, r.top+dest_y);
362393 return Success;
363394 }
364395
370401 RECT r;
371402
372403 GetWindowRect(Tk_GetHWND(Tk_WindowId(dispPtr->warpWindow)), &r);
373 SetCursorPos(r.left + dispPtr->warpX, r.top + dispPtr->warpY);
404 TkSetCursorPos(r.left + dispPtr->warpX, r.top + dispPtr->warpY);
374405 } else {
375 SetCursorPos(dispPtr->warpX, dispPtr->warpY);
406 TkSetCursorPos(dispPtr->warpX, dispPtr->warpY);
376407 }
377408 }
378409
537568 }
538569
539570 /*
571 *----------------------------------------------------------------------
572 *
573 * TkpGetCapture --
574 *
575 * This function requests which window is capturing the mouse.
576 *
577 * Results:
578 * The return value is a pointer to the capture window, if there is
579 * one, otherwise it is NULL.
580 *
581 * Side effects:
582 * None.
583 *
584 *----------------------------------------------------------------------
585 */
586
587 Tk_Window
588 TkpGetCapture(void)
589 {
590 return Tk_HWNDToWindow(GetCapture());
591 }
592
593 /*
540594 * Local Variables:
541595 * mode: c
542596 * c-basic-offset: 4
2323 #include <wchar.h>
2424 #include <io.h>
2525 #include <stdlib.h>
26 #include <assert.h>
2627 #include <errno.h>
2728 #include <fcntl.h>
2829 #include <malloc.h>
8990 * See ticket [916c1095438eae56]: GetVersionExW triggers warnings
9091 */
9192 #if defined(_MSC_VER)
93 # pragma warning(disable:4267)
94 # pragma warning(disable:4244)
95 # pragma warning(disable:4311)
96 # pragma warning(disable:4312)
9297 # pragma warning(disable:4996)
9398 #endif
9499
5858 *----------------------------------------------------------------------
5959 */
6060
61 void
61 int
6262 TkDestroyRegion(
6363 TkRegion r)
6464 {
6565 DeleteObject((HRGN) r);
66 return Success;
6667 }
6768
6869 /*
8182 *----------------------------------------------------------------------
8283 */
8384
84 void
85 int
8586 TkClipBox(
8687 TkRegion r,
8788 XRectangle* rect_return)
9394 rect_return->y = (short) rect.top;
9495 rect_return->width = (short) (rect.right - rect.left);
9596 rect_return->height = (short) (rect.bottom - rect.top);
97 return Success;
9698 }
9799
98100 /*
111113 *----------------------------------------------------------------------
112114 */
113115
114 void
116 int
115117 TkIntersectRegion(
116118 TkRegion sra,
117119 TkRegion srb,
118120 TkRegion dr_return)
119121 {
120122 CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_AND);
123 return Success;
121124 }
122125
123126 /*
136139 *----------------------------------------------------------------------
137140 */
138141
139 void
142 int
140143 TkUnionRectWithRegion(
141144 XRectangle *rectangle,
142145 TkRegion src_region,
148151 CombineRgn((HRGN) dest_region_return, (HRGN) src_region,
149152 (HRGN) rectRgn, RGN_OR);
150153 DeleteObject(rectRgn);
154 return Success;
151155 }
152156
153157 /*
269273 *----------------------------------------------------------------------
270274 */
271275
272 void
276 int
273277 TkSubtractRegion(
274278 TkRegion sra,
275279 TkRegion srb,
276280 TkRegion dr_return)
277281 {
278282 CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_DIFF);
283 return Success;
279284 }
280285
281286 /*
222222 | SBS_HORZ;
223223 }
224224
225 scrollPtr->hwnd = CreateWindow(TEXT("SCROLLBAR"), NULL, style,
225 scrollPtr->hwnd = CreateWindowW(L"SCROLLBAR", NULL, style,
226226 Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),
227227 parent, NULL, Tk_GetHINSTANCE(), NULL);
228228
244244 }
245245
246246 scrollPtr->lastVertical = scrollPtr->info.vertical;
247 scrollPtr->oldProc = (WNDPROC)SetWindowLongPtr(scrollPtr->hwnd,
247 scrollPtr->oldProc = (WNDPROC)SetWindowLongPtrW(scrollPtr->hwnd,
248248 GWLP_WNDPROC, (LONG_PTR) ScrollbarProc);
249249 window = Tk_AttachHWND(tkwin, scrollPtr->hwnd);
250250
290290 if (scrollPtr->lastVertical != scrollPtr->info.vertical) {
291291 HWND hwnd = Tk_GetHWND(Tk_WindowId(tkwin));
292292
293 SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) scrollPtr->oldProc);
293 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR) scrollPtr->oldProc);
294294 DestroyWindow(hwnd);
295295
296296 CreateProc(tkwin, Tk_WindowId(Tk_Parent(tkwin)),
324324 HWND hwnd = winScrollPtr->hwnd;
325325
326326 if (hwnd) {
327 SetWindowLongPtr(hwnd, GWLP_WNDPROC, (INT_PTR) winScrollPtr->oldProc);
327 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (INT_PTR) winScrollPtr->oldProc);
328328 if (winScrollPtr->winFlags & IN_MODAL_LOOP) {
329329 ((TkWindow *)scrollPtr->tkwin)->flags |= TK_DONT_DESTROY_WINDOW;
330330 SetParent(hwnd, NULL);
567567 return result;
568568 }
569569 }
570 return CallWindowProc(scrollPtr->oldProc, hwnd, message, wParam, lParam);
570 return CallWindowProcW(scrollPtr->oldProc, hwnd, message, wParam, lParam);
571571 }
572572
573573 /*
149149 return "";
150150 }
151151 tsdPtr->initialized = 1;
152 TRACE("Initialized COM library for interp 0x%08X\n", (long)interp);
152 TRACE("Initialized COM library for interp 0x%" TCL_Z_MODIFIER "x\n", (size_t)interp);
153153 }
154154
155155 /*
253253 if (*p) {
254254 Tcl_DString ds;
255255
256 Tcl_WinTCharToUtf(p + 1, -1, &ds);
256 Tcl_WinTCharToUtf((LPCTSTR)(p + 1), -1, &ds);
257257 result = Tcl_ListObjAppendElement(interp,
258258 objList,
259259 Tcl_NewStringObj(Tcl_DStringValue(&ds),
783783
784784 ehr = VariantChangeType(&vResult, &vResult, 0, VT_BSTR);
785785 if (SUCCEEDED(ehr)) {
786 Tcl_WinTCharToUtf(vResult.bstrVal, (int) SysStringLen(vResult.bstrVal) *
786 Tcl_WinTCharToUtf((LPCTSTR)vResult.bstrVal, SysStringLen(vResult.bstrVal) *
787787 sizeof (WCHAR), &ds);
788788 Tcl_DStringResult(interp, &ds);
789789 }
796796
797797 if (hr == DISP_E_EXCEPTION && ei.bstrSource != NULL) {
798798 Tcl_Obj *opError, *opErrorCode, *opErrorInfo;
799 Tcl_WinTCharToUtf(ei.bstrSource, (int) SysStringLen(ei.bstrSource) *
799 Tcl_WinTCharToUtf((LPCTSTR)ei.bstrSource, SysStringLen(ei.bstrSource) *
800800 sizeof (WCHAR), &ds);
801801 opError = Tcl_NewStringObj(Tcl_DStringValue(&ds),
802802 Tcl_DStringLength(&ds));
384384 if (SUCCEEDED(hr) && obj->interp) {
385385 Tcl_Obj *scriptPtr;
386386
387 Tcl_WinTCharToUtf(vCmd.bstrVal, (int) SysStringLen(vCmd.bstrVal) *
387 Tcl_WinTCharToUtf((LPCTSTR)vCmd.bstrVal, SysStringLen(vCmd.bstrVal) *
388388 sizeof (WCHAR), &ds);
389389 scriptPtr =
390390 Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
439439 return hr;
440440 }
441441
442 Tcl_WinTCharToUtf(v.bstrVal, (int) SysStringLen(v.bstrVal) *
443 sizeof (WCHAR), &ds);
442 Tcl_WinTCharToUtf((LPCTSTR)v.bstrVal, SysStringLen(v.bstrVal) *
443 sizeof(WCHAR), &ds);
444444 scriptPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
445445 Tcl_DStringFree(&ds);
446446 Tcl_Preserve(interp);
146146 if (Tcl_IsShared(resultPtr)) {
147147 resultPtr = Tcl_DuplicateObj(resultPtr);
148148 }
149 length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
149 length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
150150 | FORMAT_MESSAGE_IGNORE_INSERTS
151151 | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,
152152 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *) wMsgPtrPtr,
174174 }
175175 msg = msgBuf;
176176 } else {
177 Tcl_Encoding encoding;
178177 char *msgPtr;
179178
180 encoding = Tcl_GetEncoding(NULL, "unicode");
181 Tcl_ExternalToUtfDString(encoding, (char *) wMsgPtr, -1, &ds);
182 Tcl_FreeEncoding(encoding);
179 Tcl_WinTCharToUtf((LPCTSTR)wMsgPtr, -1, &ds);
183180 LocalFree(wMsgPtr);
184181
185182 msgPtr = Tcl_DStringValue(&ds);
418415
419416 /*
420417 * testfindwindow title ?class?
421 * Find a Windows window using the FindWindow API call. This takes the window
418 * Find a Windows window using the FindWindowW API call. This takes the window
422419 * title and optionally the window class and if found returns the HWND and
423420 * raises an error if the window is not found.
424421 * eg: testfindwindow Console TkTopLevel
434431 int objc, /* Number of arguments. */
435432 Tcl_Obj *const objv[]) /* Argument values. */
436433 {
437 const TCHAR *title = NULL, *class = NULL;
434 LPCWSTR title = NULL, windowClass = NULL;
438435 Tcl_DString titleString, classString;
439436 HWND hwnd = NULL;
440437 int r = TCL_OK;
448445 return TCL_ERROR;
449446 }
450447
451 title = Tcl_WinUtfToTChar(Tcl_GetString(objv[1]), -1, &titleString);
448 title = (LPCWSTR)Tcl_WinUtfToTChar(Tcl_GetString(objv[1]), -1, &titleString);
452449 if (objc == 3) {
453 class = Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString);
450 windowClass = (LPCWSTR)Tcl_WinUtfToTChar(Tcl_GetString(objv[2]), -1, &classString);
454451 }
455452 if (title[0] == 0)
456453 title = NULL;
457 #if 0
458 hwnd = FindWindow(class, title);
459 #else
460454 /* We want find a window the belongs to us and not some other process */
461455 hwnd = NULL;
462456 myPid = GetCurrentProcessId();
463457 while (1) {
464458 DWORD pid, tid;
465 hwnd = FindWindowEx(NULL, hwnd, class, title);
459 hwnd = FindWindowExW(NULL, hwnd, windowClass, title);
466460 if (hwnd == NULL)
467461 break;
468462 tid = GetWindowThreadProcessId(hwnd, &pid);
475469 break; /* Found it */
476470 }
477471
478 #endif
479
480472 if (hwnd == NULL) {
481473 Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to find window: ", -1));
482474 AppendSystemError(interp, GetLastError());
483475 r = TCL_ERROR;
484476 } else {
485 Tcl_SetObjResult(interp, Tcl_NewLongObj(PTR2INT(hwnd)));
477 Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)(((size_t)hwnd) + 1) - 1));
486478 }
487479
488480 Tcl_DStringFree(&titleString);
498490 {
499491 Tcl_Obj *listObj = (Tcl_Obj *) lParam;
500492
501 Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewLongObj(PTR2INT(hwnd)));
493 Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewWideIntObj((Tcl_WideInt)(((size_t)hwnd) + 1) - 1));
502494 return TRUE;
503495 }
504496
509501 int objc,
510502 Tcl_Obj *const objv[])
511503 {
512 long hwnd;
504 Tcl_WideInt hwnd;
513505 Tcl_Obj *dictObj = NULL, *classObj = NULL, *textObj = NULL;
514506 Tcl_Obj *childrenObj = NULL;
515 TCHAR buf[512];
507 WCHAR buf[512];
516508 int cch, cchBuf = 256;
517509 Tcl_DString ds;
518510
521513 return TCL_ERROR;
522514 }
523515
524 if (Tcl_GetLongFromObj(interp, objv[1], &hwnd) != TCL_OK)
516 if (Tcl_GetWideIntFromObj(interp, objv[1], &hwnd) != TCL_OK)
525517 return TCL_ERROR;
526518
527 cch = GetClassName(INT2PTR(hwnd), buf, cchBuf);
519 cch = GetClassNameW(INT2PTR(hwnd), buf, cchBuf);
528520 if (cch == 0) {
529521 Tcl_SetObjResult(interp, Tcl_NewStringObj("failed to get class name: ", -1));
530522 AppendSystemError(interp, GetLastError());
531523 return TCL_ERROR;
532524 } else {
533525 Tcl_DString ds;
534 Tcl_WinTCharToUtf(buf, -1, &ds);
526 Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &ds);
535527 classObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
536528 Tcl_DStringFree(&ds);
537529 }
539531 dictObj = Tcl_NewDictObj();
540532 Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("class", 5), classObj);
541533 Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("id", 2),
542 Tcl_NewLongObj(GetWindowLongA(INT2PTR(hwnd), GWL_ID)));
543
544 cch = GetWindowText(INT2PTR(hwnd), (LPTSTR)buf, cchBuf);
545 Tcl_WinTCharToUtf(buf, cch * sizeof (WCHAR), &ds);
534 Tcl_NewWideIntObj(GetWindowLongPtrW(INT2PTR(hwnd), GWL_ID)));
535
536 cch = GetWindowTextW(INT2PTR(hwnd), buf, cchBuf);
537 Tcl_WinTCharToUtf((LPCTSTR)buf, cch * sizeof (WCHAR), &ds);
546538 textObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
547539 Tcl_DStringFree(&ds);
548540
549541 Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("text", 4), textObj);
550542 Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("parent", 6),
551 Tcl_NewLongObj(PTR2INT(GetParent((INT2PTR(hwnd))))));
543 Tcl_NewWideIntObj((Tcl_WideInt)(((size_t)GetParent((INT2PTR(hwnd)))) + 1) - 1));
552544
553545 childrenObj = Tcl_NewListObj(0, NULL);
554546 EnumChildWindows(INT2PTR(hwnd), EnumChildrenProc, (LPARAM)childrenObj);
1212 #include "tkWinInt.h"
1313 #include "tkBusy.h"
1414
15 typedef struct ThreadSpecificData {
15 typedef struct {
1616 int initialized; /* 0 means table below needs initializing. */
1717 Tcl_HashTable windowTable; /* The windowTable maps from HWND to Tk_Window
1818 * handles. */
169169 {
170170 HWND hwnd = (window) ? Tk_GetHWND(window) : 0;
171171
172 /*
173 * Use pointer representation, because Win64 is P64 (*not* LP64). Windows
174 * doesn't print the 0x for %p, so we do it.
175 * Bug 2026405: cygwin does output 0x for %p so test and recover.
176 */
177
178 sprintf(buf, "0x%p", hwnd);
179 if (buf[2] == '0' && buf[3] == 'x') {
180 sprintf(buf, "%p", hwnd);
181 }
172 sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)hwnd);
182173 }
183174
184175 /*
276267 * order.
277268 */
278269
279 hwnd = CreateWindowEx(WS_EX_NOPARENTNOTIFY, TK_WIN_CHILD_CLASS_NAME, NULL,
270 hwnd = CreateWindowExW(WS_EX_NOPARENTNOTIFY, TK_WIN_CHILD_CLASS_NAME, NULL,
280271 (DWORD) style, Tk_X(winPtr), Tk_Y(winPtr), Tk_Width(winPtr),
281272 Tk_Height(winPtr), parentWin, NULL, Tk_GetHINSTANCE(), NULL);
282273 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
881872 */
882873
883874 GetCursorPos(&point);
884 SetCursorPos(point.x, point.y);
875 TkSetCursorPos(point.x, point.y);
885876 }
886877
887878 /*
923914 */
924915
925916 GetCursorPos(&point);
926 SetCursorPos(point.x, point.y);
917 TkSetCursorPos(point.x, point.y);
927918 }
928919
929920 /*
952943 int style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
953944 DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_TOPMOST;
954945
955 hWnd = CreateWindowEx(exStyle, TK_WIN_CHILD_CLASS_NAME, NULL, style,
946 hWnd = CreateWindowExW(exStyle, TK_WIN_CHILD_CLASS_NAME, NULL, style,
956947 Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),
957948 hParent, NULL, Tk_GetHINSTANCE(), NULL);
958949 winPtr->window = Tk_AttachHWND(tkwin, hWnd);
366366 NULL, /* lostSlaveProc */
367367 };
368368
369 typedef struct ThreadSpecificData {
369 typedef struct {
370370 HPALETTE systemPalette; /* System palette; refers to the currently
371371 * installed foreground logical palette. */
372372 TkWindow *createWindow; /* Window that is being constructed. This
866866 if (!initialized) {
867867 Tcl_MutexLock(&winWmMutex);
868868 if (!initialized) {
869 WNDCLASS class;
869 WNDCLASSW windowClass;
870870
871871 initialized = 1;
872872
873 /*
874 * The only difference between WNDCLASSW and WNDCLASSA are in
875 * pointers, so we can use the generic structure WNDCLASS.
876 */
877
878 ZeroMemory(&class, sizeof(WNDCLASS));
879
880 class.style = CS_HREDRAW | CS_VREDRAW;
881 class.hInstance = Tk_GetHINSTANCE();
882 class.lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME;
883 class.lpfnWndProc = WmProc;
873 ZeroMemory(&windowClass, sizeof(WNDCLASSW));
874
875 windowClass.style = CS_HREDRAW | CS_VREDRAW;
876 windowClass.hInstance = Tk_GetHINSTANCE();
877 windowClass.lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME;
878 windowClass.lpfnWndProc = WmProc;
884879 if (titlebaricon == NULL) {
885 class.hIcon = LoadIcon(Tk_GetHINSTANCE(), TEXT("tk"));
880 windowClass.hIcon = LoadIconW(Tk_GetHINSTANCE(), L"tk");
886881 } else {
887 class.hIcon = GetIcon(titlebaricon, ICON_BIG);
888 if (class.hIcon == NULL) {
882 windowClass.hIcon = GetIcon(titlebaricon, ICON_BIG);
883 if (windowClass.hIcon == NULL) {
889884 return TCL_ERROR;
890885 }
891886
896891
897892 tsdPtr->iconPtr = titlebaricon;
898893 }
899 class.hCursor = LoadCursor(NULL, IDC_ARROW);
900
901 if (!RegisterClass(&class)) {
894 windowClass.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
895
896 if (!RegisterClassW(&windowClass)) {
902897 Tcl_Panic("Unable to register TkTopLevel class");
903898 }
904899 }
10171012
10181013 /*
10191014 * Don't check return result of SetClassLong() or
1020 * SetClassLongPtr() since they return the previously set value
1015 * SetClassLongPtrW() since they return the previously set value
10211016 * which is zero on the initial call or in an error case. The MSDN
10221017 * documentation does not indicate that the result needs to be
10231018 * checked.
10241019 */
10251020
1026 SetClassLongPtr(hwnd, GCLP_HICONSM,
1021 SetClassLongPtrW(hwnd, GCLP_HICONSM,
10271022 (LPARAM) GetIcon(titlebaricon, ICON_SMALL));
1028 SetClassLongPtr(hwnd, GCLP_HICON,
1023 SetClassLongPtrW(hwnd, GCLP_HICON,
10291024 (LPARAM) GetIcon(titlebaricon, ICON_BIG));
10301025 tsdPtr = (ThreadSpecificData *)
10311026 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
10701065 return TCL_ERROR;
10711066 }
10721067 }
1073 SendMessage(hwnd, WM_SETICON, ICON_SMALL,
1068 SendMessageW(hwnd, WM_SETICON, ICON_SMALL,
10741069 (LPARAM) GetIcon(titlebaricon, ICON_SMALL));
1075 SendMessage(hwnd, WM_SETICON, ICON_BIG,
1070 SendMessageW(hwnd, WM_SETICON, ICON_BIG,
10761071 (LPARAM) GetIcon(titlebaricon, ICON_BIG));
10771072
10781073 /*
11611156 * the window class.
11621157 */
11631158
1164 icon = (HICON) SendMessage(wmPtr->wrapper, WM_GETICON, iconsize,
1159 icon = (HICON) SendMessageW(wmPtr->wrapper, WM_GETICON, iconsize,
11651160 (LPARAM) NULL);
11661161 if (icon == (HICON) NULL) {
1167 icon = (HICON) GetClassLongPtr(wmPtr->wrapper,
1162 icon = (HICON) GetClassLongPtrW(wmPtr->wrapper,
11681163 (iconsize == ICON_BIG) ? GCLP_HICON : GCLP_HICONSM);
11691164 }
11701165 return icon;
12361231 */
12371232
12381233 if (lpIR == NULL) {
1239 SHFILEINFO sfiSM;
1234 SHFILEINFOW sfiSM;
12401235 Tcl_DString ds, ds2;
12411236 DWORD *res;
12421237 const char *file;
12471242 }
12481243 Tcl_WinUtfToTChar(file, -1, &ds2);
12491244 Tcl_DStringFree(&ds);
1250 res = (DWORD *)SHGetFileInfo((TCHAR *)Tcl_DStringValue(&ds2), 0, &sfiSM,
1245 res = (DWORD *)SHGetFileInfoW((WCHAR *)Tcl_DStringValue(&ds2), 0, &sfiSM,
12511246 sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_ICON);
12521247
12531248 if (res != 0) {
1254 SHFILEINFO sfi;
1249 SHFILEINFOW sfi;
12551250 unsigned size;
12561251
12571252 Tcl_ResetResult(interp);
1258 res = (DWORD *)SHGetFileInfo((TCHAR *)Tcl_DStringValue(&ds2), 0, &sfi,
1253 res = (DWORD *)SHGetFileInfoW((WCHAR *)Tcl_DStringValue(&ds2), 0, &sfi,
12591254 sizeof(SHFILEINFO), SHGFI_ICON);
12601255
12611256 /*
17481743 if (tsdPtr->createWindow) {
17491744 return tsdPtr->createWindow;
17501745 }
1751 return (TkWindow *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
1746 return (TkWindow *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
17521747 }
17531748
17541749 /*
18851880 }
18861881 tsdPtr->initialized = 0;
18871882
1888 UnregisterClass(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);
1883 UnregisterClassW(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance);
18891884 }
18901885
18911886 /*
21282123 Tcl_WinUtfToTChar(((wmPtr->title != NULL) ?
21292124 wmPtr->title : winPtr->nameUid), -1, &titleString);
21302125
2131 wmPtr->wrapper = CreateWindowEx(wmPtr->exStyle,
2126 wmPtr->wrapper = CreateWindowExW(wmPtr->exStyle,
21322127 TK_WIN_TOPLEVEL_CLASS_NAME,
2133 (LPCTSTR) Tcl_DStringValue(&titleString),
2128 (LPCWSTR) Tcl_DStringValue(&titleString),
21342129 wmPtr->style, x, y, width, height,
21352130 parentHWND, NULL, Tk_GetHINSTANCE(), NULL);
21362131 Tcl_DStringFree(&titleString);
2137 SetWindowLongPtr(wmPtr->wrapper, GWLP_USERDATA, (LONG_PTR) winPtr);
2132 SetWindowLongPtrW(wmPtr->wrapper, GWLP_USERDATA, (LONG_PTR) winPtr);
21382133 tsdPtr->createWindow = NULL;
21392134
21402135 if (wmPtr->exStyleConfig & WS_EX_LAYERED) {
21852180 * doesn't try to set the focus to the child window.
21862181 */
21872182
2188 SetWindowLongPtr(child, GWL_STYLE,
2183 SetWindowLongPtrW(child, GWL_STYLE,
21892184 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
21902185
21912186 if (winPtr->flags & TK_EMBEDDED) {
2192 SetWindowLongPtr(child, GWLP_WNDPROC, (LONG_PTR) TopLevelProc);
2187 SetWindowLongPtrW(child, GWLP_WNDPROC, (LONG_PTR) TopLevelProc);
21932188 }
21942189
21952190 SetParent(child, wmPtr->wrapper);
21962191 if (oldWrapper) {
21972192 hSmallIcon = (HICON)
2198 SendMessage(oldWrapper, WM_GETICON, ICON_SMALL, (LPARAM)NULL);
2193 SendMessageW(oldWrapper, WM_GETICON, ICON_SMALL, (LPARAM)NULL);
21992194 hBigIcon = (HICON)
2200 SendMessage(oldWrapper, WM_GETICON, ICON_BIG, (LPARAM) NULL);
2195 SendMessageW(oldWrapper, WM_GETICON, ICON_BIG, (LPARAM) NULL);
22012196 }
22022197
22032198 if (oldWrapper && (oldWrapper != wmPtr->wrapper)
22042199 && (oldWrapper != GetDesktopWindow())) {
2205 SetWindowLongPtr(oldWrapper, GWLP_USERDATA, (LONG_PTR) 0);
2200 SetWindowLongPtrW(oldWrapper, GWLP_USERDATA, (LONG_PTR) 0);
22062201
22072202 if (wmPtr->numTransients > 0) {
22082203 /*
22352230
22362231 wmPtr->flags &= ~WM_NEVER_MAPPED;
22372232 if (winPtr->flags & TK_EMBEDDED &&
2238 SendMessage(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0)) {
2239 SendMessage(wmPtr->wrapper, TK_GEOMETRYREQ,
2233 SendMessageW(wmPtr->wrapper, TK_ATTACHWINDOW, (WPARAM) child, 0)) {
2234 SendMessageW(wmPtr->wrapper, TK_GEOMETRYREQ,
22402235 Tk_ReqWidth((Tk_Window) winPtr),
22412236 Tk_ReqHeight((Tk_Window) winPtr));
2242 SendMessage(wmPtr->wrapper, TK_SETMENU, (WPARAM) wmPtr->hMenu,
2237 SendMessageW(wmPtr->wrapper, TK_SETMENU, (WPARAM) wmPtr->hMenu,
22432238 (LPARAM) Tk_GetMenuHWND((Tk_Window) winPtr));
22442239 }
22452240
22592254 wmPtr->hints.initial_state = state;
22602255
22612256 if (hSmallIcon != NULL) {
2262 SendMessage(wmPtr->wrapper, WM_SETICON, ICON_SMALL,
2257 SendMessageW(wmPtr->wrapper, WM_SETICON, ICON_SMALL,
22632258 (LPARAM) hSmallIcon);
22642259 }
22652260 if (hBigIcon != NULL) {
2266 SendMessage(wmPtr->wrapper, WM_SETICON, ICON_BIG, (LPARAM) hBigIcon);
2261 SendMessageW(wmPtr->wrapper, WM_SETICON, ICON_BIG, (LPARAM) hBigIcon);
22672262 }
22682263
22692264 /*
22752270 */
22762271
22772272 if (winPtr->flags & TK_EMBEDDED) {
2278 if (state+1 != SendMessage(wmPtr->wrapper, TK_STATE, state, 0)) {
2273 if (state+1 != SendMessageW(wmPtr->wrapper, TK_STATE, state, 0)) {
22792274 TkpWmSetState(winPtr, NormalState);
22802275 wmPtr->hints.initial_state = NormalState;
22812276 }
26242619 VisibilityChangeMask|StructureNotifyMask,
26252620 WmWaitVisibilityOrMapProc, wmPtr2->winPtr);
26262621 wmPtr2->masterPtr = NULL;
2627 if ((wmPtr2->wrapper != None)
2622 if ((wmPtr2->wrapper != NULL)
26282623 && !(wmPtr2->flags & (WM_NEVER_MAPPED))) {
26292624 UpdateWrapper(wmPtr2->winPtr);
26302625 }
27052700 }
27062701 } else {
27072702 if (wmPtr->wrapper != NULL) {
2708 SendMessage(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0);
2703 SendMessageW(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0);
27092704 }
27102705 }
27112706 if (wmPtr->iconPtr != NULL) {
31923187 */
31933188
31943189 if (!(wmPtr->exStyleConfig & WS_EX_LAYERED)) {
3195 SetWindowLongPtr(wmPtr->wrapper, GWL_EXSTYLE,
3190 SetWindowLongPtrW(wmPtr->wrapper, GWL_EXSTYLE,
31963191 *stylePtr);
31973192 }
31983193 SetLayeredWindowAttributes((HWND) wmPtr->wrapper,
35713566 return TCL_ERROR;
35723567 }
35733568 if (winPtr->flags & TK_EMBEDDED) {
3574 if (!SendMessage(wmPtr->wrapper, TK_DEICONIFY, 0, 0)) {
3569 if (!SendMessageW(wmPtr->wrapper, TK_DEICONIFY, 0, 0)) {
35753570 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
35763571 "can't deiconify %s: the container does not support the request",
35773572 winPtr->pathName));
37153710 {
37163711 register WmInfo *wmPtr = winPtr->wmInfoPtr;
37173712 HWND hwnd;
3713 char buf[TCL_INTEGER_SPACE];
37183714
37193715 if (objc != 3) {
37203716 Tcl_WrongNumArgs(interp, 2, objv, "window");
37273723 if (hwnd == NULL) {
37283724 hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) winPtr));
37293725 }
3730 Tcl_SetObjResult(interp, Tcl_ObjPrintf("0x%x", PTR2INT(hwnd)));
3726 sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)hwnd);
3727 Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
37313728 return TCL_OK;
37323729 }
37333730
37793776 height = winPtr->changes.height;
37803777 }
37813778 if (winPtr->flags & TK_EMBEDDED) {
3782 int result = SendMessage(wmPtr->wrapper, TK_MOVEWINDOW, -1, -1);
3779 int result = SendMessageW(wmPtr->wrapper, TK_MOVEWINDOW, -1, -1);
37833780
37843781 wmPtr->x = result >> 16;
37853782 wmPtr->y = result & 0x0000ffff;
41284125 return TCL_ERROR;
41294126 }
41304127 if (winPtr->flags & TK_EMBEDDED) {
4131 if (!SendMessage(wmPtr->wrapper, TK_ICONIFY, 0, 0)) {
4128 if (!SendMessageW(wmPtr->wrapper, TK_ICONIFY, 0, 0)) {
41324129 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
41334130 "can't iconify %s: the container does not support the request",
41344131 winPtr->pathName));
43704367 iconInfo.fIcon = TRUE;
43714368
43724369 /*
4373 * Create device-independant color bitmap.
4370 * Create device-independent color bitmap.
43744371 */
43754372
43764373 ZeroMemory(&bmInfo, sizeof bmInfo);
43864383 if (!iconInfo.hbmColor) {
43874384 ckfree(lpIR);
43884385 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
4389 "failed to create color bitmap for \"%s\"",
4386 "failed to create an iconphoto with image \"%s\"",
43904387 Tcl_GetString(objv[i])));
4391 Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "BITMAP", NULL);
4388 Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
43924389 return TCL_ERROR;
43934390 }
43944391
48214818 return TCL_ERROR;
48224819 }
48234820 if (winPtr->flags & TK_EMBEDDED) {
4824 curValue = SendMessage(wmPtr->wrapper, TK_OVERRIDEREDIRECT, -1, -1)-1;
4821 curValue = SendMessageW(wmPtr->wrapper, TK_OVERRIDEREDIRECT, -1, -1)-1;
48254822 if (curValue < 0) {
48264823 Tcl_SetObjResult(interp, Tcl_NewStringObj(
48274824 "Container does not support overrideredirect", -1));
48404837 }
48414838 if (curValue != boolean) {
48424839 if (winPtr->flags & TK_EMBEDDED) {
4843 SendMessage(wmPtr->wrapper, TK_OVERRIDEREDIRECT, boolean, 0);
4840 SendMessageW(wmPtr->wrapper, TK_OVERRIDEREDIRECT, boolean, 0);
48444841 } else {
48454842 /*
48464843 * Only do this if we are really changing value, because it causes
51975194
51985195 if (objc == 3) {
51995196 windows = TkWmStackorderToplevel(winPtr);
5200 if (windows == NULL) {
5201 Tcl_Panic("TkWmStackorderToplevel failed");
5202 }
5203
5204 resultObj = Tcl_NewObj();
5205 for (windowPtr = windows; *windowPtr ; windowPtr++) {
5206 Tcl_ListObjAppendElement(NULL, resultObj,
5207 TkNewWindowObj((Tk_Window) *windowPtr));
5208 }
5209 Tcl_SetObjResult(interp, resultObj);
5210 ckfree(windows);
5211 return TCL_OK;
5197 if (windows != NULL) {
5198 resultObj = Tcl_NewObj();
5199 for (windowPtr = windows; *windowPtr ; windowPtr++) {
5200 Tcl_ListObjAppendElement(NULL, resultObj,
5201 TkNewWindowObj((Tk_Window) *windowPtr));
5202 }
5203 Tcl_SetObjResult(interp, resultObj);
5204 ckfree(windows);
5205 return TCL_OK;
5206 } else {
5207 return TCL_ERROR;
5208 }
52125209 } else {
52135210 TkWindow *winPtr2, **winPtr2Ptr = &winPtr2;
52145211 int index1 = -1, index2 = -1, result;
53545351 Tcl_Panic("unexpected index");
53555352 }
53565353
5357 if (state+1 != SendMessage(wmPtr->wrapper, TK_STATE, state, 0)) {
5354 if (state+1 != SendMessageW(wmPtr->wrapper, TK_STATE, state, 0)) {
53585355 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
53595356 "can't change state of %s: the container does not support the request",
53605357 winPtr->pathName));
54075404 int state;
54085405
54095406 if (winPtr->flags & TK_EMBEDDED) {
5410 state = SendMessage(wmPtr->wrapper, TK_STATE, -1, -1) - 1;
5407 state = SendMessageW(wmPtr->wrapper, TK_STATE, -1, -1) - 1;
54115408 } else {
54125409 state = wmPtr->hints.initial_state;
54135410 }
54595456 }
54605457
54615458 if (winPtr->flags & TK_EMBEDDED) {
5462 wrapper = (HWND) SendMessage(wmPtr->wrapper, TK_GETFRAMEWID, 0, 0);
5459 wrapper = (HWND) SendMessageW(wmPtr->wrapper, TK_GETFRAMEWID, 0, 0);
54635460 } else {
54645461 wrapper = wmPtr->wrapper;
54655462 }
54665463 if (objc == 3) {
54675464 if (wrapper) {
5468 TCHAR buf[256];
5465 WCHAR buf[256];
54695466 Tcl_DString titleString;
54705467 int size = 256;
54715468
5472 GetWindowText(wrapper, buf, size);
5473 Tcl_WinTCharToUtf(buf, -1, &titleString);
5469 GetWindowTextW(wrapper, buf, size);
5470 Tcl_WinTCharToUtf((LPCTSTR)buf, -1, &titleString);
54745471 Tcl_SetObjResult(interp, Tcl_NewStringObj(
54755472 Tcl_DStringValue(&titleString),
54765473 Tcl_DStringLength(&titleString)));
54925489 Tcl_DString titleString;
54935490
54945491 Tcl_WinUtfToTChar(wmPtr->title, -1, &titleString);
5495 SetWindowText(wrapper, (LPCTSTR) Tcl_DStringValue(&titleString));
5492 SetWindowTextW(wrapper, (LPCWSTR) Tcl_DStringValue(&titleString));
54965493 Tcl_DStringFree(&titleString);
54975494 }
54985495 }
55255522 Tcl_Obj *const objv[]) /* Argument objects. */
55265523 {
55275524 register WmInfo *wmPtr = winPtr->wmInfoPtr;
5528 TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr;
5525 TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr, *w;
55295526 WmInfo *wmPtr2;
55305527
55315528 if ((objc != 3) && (objc != 4)) {
55835580 Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
55845581 return TCL_ERROR;
55855582 }
5586
5587 if (masterPtr == winPtr) {
5588 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
5589 "can't make \"%s\" its own master", Tk_PathName(winPtr)));
5590 Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
5591 return TCL_ERROR;
5592 } else if (masterPtr != wmPtr->masterPtr) {
5583 for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
5584 w = (TkWindow *)w->wmInfoPtr->masterPtr) {
5585 if (w == winPtr) {
5586 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
5587 "setting \"%s\" as master creates a transient/master cycle",
5588 Tk_PathName(masterPtr)));
5589 Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
5590 return TCL_ERROR;
5591 }
5592 }
5593 if (masterPtr != wmPtr->masterPtr) {
55935594 /*
55945595 * Remove old master map/unmap binding before setting the new
55955596 * master. The event handler will ensure that transient states
56635664 }
56645665
56655666 if (winPtr->flags & TK_EMBEDDED) {
5666 if (SendMessage(wmPtr->wrapper, TK_WITHDRAW, 0, 0) < 0) {
5667 if (SendMessageW(wmPtr->wrapper, TK_WITHDRAW, 0, 0) < 0) {
56675668 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
56685669 "can't withdraw %s: the container does not support the request",
56695670 Tcl_GetString(objv[2])));
59685969 wmPtr = winPtr->wmInfoPtr;
59695970 if (wmPtr) {
59705971 if ((winPtr->flags & TK_EMBEDDED) && (wmPtr->wrapper != NULL)) {
5971 SendMessage(wmPtr->wrapper, TK_GEOMETRYREQ, Tk_ReqWidth(tkwin),
5972 SendMessageW(wmPtr->wrapper, TK_GEOMETRYREQ, Tk_ReqWidth(tkwin),
59725973 Tk_ReqHeight(tkwin));
59735974 }
59745975 if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
61806181 * be ignored.
61816182 */
61826183
6183 SendMessage(wmPtr->wrapper, TK_MOVEWINDOW, x, y);
6184 SendMessage(wmPtr->wrapper, TK_GEOMETRYREQ, width, height);
6184 SendMessageW(wmPtr->wrapper, TK_MOVEWINDOW, x, y);
6185 SendMessageW(wmPtr->wrapper, TK_GEOMETRYREQ, width, height);
61856186 } else {
61866187 int reqHeight, reqWidth;
61876188 RECT windowRect;
68106811 (LPARAM) &pair) == 0) {
68116812 ckfree(windows);
68126813 windows = NULL;
6813 } else if (pair.windowPtr != (windows-1)) {
6814 Tcl_Panic("num matched toplevel windows does not equal num children");
68156814 }
68166815
68176816 done:
68766875 }
68776876
68786877 if (winPtr->flags & TK_EMBEDDED) {
6879 SendMessage(winPtr->wmInfoPtr->wrapper, TK_RAISEWINDOW,
6878 SendMessageW(winPtr->wmInfoPtr->wrapper, TK_RAISEWINDOW,
68806879 (WPARAM) insertAfter, aboveBelow);
68816880 } else {
68826881 TkWinSetWindowPos(hwnd, insertAfter, aboveBelow);
71027101 wmPtr->flags |= WM_UPDATE_PENDING|WM_MOVE_PENDING;
71037102 }
71047103 } else {
7105 SendMessage(wmPtr->wrapper, TK_SETMENU, (WPARAM) hMenu,
7104 SendMessageW(wmPtr->wrapper, TK_SETMENU, (WPARAM) hMenu,
71067105 (LPARAM) Tk_GetMenuHWND(tkwin));
71077106 }
71087107 }
74167415 SelectPalette(dc, oldPalette, TRUE);
74177416 RealizePalette(dc);
74187417 ReleaseDC(hwnd, dc);
7419 SendMessage(hwnd, WM_PALETTECHANGED, (WPARAM) hwnd, (LPARAM) NULL);
7418 SendMessageW(hwnd, WM_PALETTECHANGED, (WPARAM) hwnd, (LPARAM) NULL);
74207419 return TRUE;
74217420 }
74227421 } else {
78127811 winPtr->changes.height = pos->cy;
78137812 }
78147813 if (!(pos->flags & SWP_NOMOVE)) {
7815 long result = SendMessage(winPtr->wmInfoPtr->wrapper,
7814 long result = SendMessageW(winPtr->wmInfoPtr->wrapper,
78167815 TK_MOVEWINDOW, -1, -1);
78177816 winPtr->wmInfoPtr->x = winPtr->changes.x = result >> 16;
78187817 winPtr->wmInfoPtr->y = winPtr->changes.y = result & 0xffff;
80038002 * 2272]
80048003 */
80058004
8006 result = DefWindowProc(hwnd, message, wParam, lParam);
8005 result = DefWindowProcW(hwnd, message, wParam, lParam);
80078006 goto done;
80088007 }
80098008
80808079 HWND hMenuHWnd = Tk_GetEmbeddedMenuHWND((Tk_Window) winPtr);
80818080
80828081 if (hMenuHWnd) {
8083 if (SendMessage(hMenuHWnd, message, wParam, lParam)) {
8082 if (SendMessageW(hMenuHWnd, message, wParam, lParam)) {
80848083 goto done;
80858084 }
80868085 } else if (TkWinHandleMenuEvent(&hwnd, &message, &wParam, &lParam,
80998098 result = 0;
81008099 } else if (!Tk_TranslateWinEvent(child, message, wParam, lParam,
81018100 &result)) {
8102 result = DefWindowProc(hwnd, message, wParam, lParam);
8101 result = DefWindowProcW(hwnd, message, wParam, lParam);
81038102 }
81048103 } else {
8105 result = DefWindowProc(hwnd, message, wParam, lParam);
8104 result = DefWindowProcW(hwnd, message, wParam, lParam);
81068105 }
81078106
81088107 done:
86168615 register WmInfo *wmPtr = winPtr->wmInfoPtr;
86178616
86188617 if (winPtr->flags & TK_EMBEDDED) {
8619 int state = SendMessage(wmPtr->wrapper, TK_STATE, -1, -1) - 1;
8620
8621 SendMessage(wmPtr->wrapper, TK_SETMENU, 0, 0);
8622 SendMessage(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0);
8618 int state = SendMessageW(wmPtr->wrapper, TK_STATE, -1, -1) - 1;
8619
8620 SendMessageW(wmPtr->wrapper, TK_SETMENU, 0, 0);
8621 SendMessageW(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0);
86238622 winPtr->flags &= ~TK_EMBEDDED;
86248623 winPtr->privatePtr = NULL;
8625 wmPtr->wrapper = None;
8624 wmPtr->wrapper = NULL;
86268625 if (state >= 0 && state <= 3) {
86278626 wmPtr->hints.initial_state = state;
86288627 }
3535 #include <zmouse.h>
3636
3737 /*
38 * WM_MOUSEHWHEEL is normally defined by Winuser.h for Vista/2008 or later,
39 * but is also usable on 2000/XP if IntelliPoint drivers are installed.
40 */
41
42 #ifndef WM_MOUSEHWHEEL
43 #define WM_MOUSEHWHEEL 0x020E
44 #endif
45
46 /*
3847 * imm.h is needed by HandleIMEComposition
3948 */
4049
5968 static const char winScreenName[] = ":0"; /* Default name of windows display. */
6069 static HINSTANCE tkInstance = NULL; /* Application instance handle. */
6170 static int childClassInitialized; /* Registered child class? */
62 static WNDCLASS childClass; /* Window class for child windows. */
71 static WNDCLASSW childClass; /* Window class for child windows. */
6372 static int tkPlatformId = 0; /* version of Windows platform */
6473 static int tkWinTheme = 0; /* See TkWinGetPlatformTheme */
6574 static Tcl_Encoding keyInputEncoding = NULL;
7685 * specific date for threads.
7786 */
7887
79 typedef struct ThreadSpecificData {
88 typedef struct {
8089 TkDisplay *winDisplay; /* TkDisplay structure that represents Windows
8190 * screen. */
8291 int updatingClipboard; /* If 1, we are updating the clipboard. */
8392 int surrogateBuffer; /* Buffer for first of surrogate pair. */
84 DWORD wheelTickPrev; /* For high resolution wheels. */
85 short wheelAcc; /* For high resolution wheels. */
93 DWORD vWheelTickPrev; /* For high resolution wheels (vertical). */
94 DWORD hWheelTickPrev; /* For high resolution wheels (horizontal). */
95 short vWheelAcc; /* For high resolution wheels (vertical). */
96 short hWheelAcc; /* For high resolution wheels (horizontal). */
8697 } ThreadSpecificData;
8798 static Tcl_ThreadDataKey dataKey;
8899
126137 OSVERSIONINFOW os;
127138
128139 if (!buffer[0]) {
129 HANDLE handle = GetModuleHandle(TEXT("NTDLL"));
140 HANDLE handle = GetModuleHandleW(L"NTDLL");
130141 int(__stdcall *getversion)(void *) =
131142 (int(__stdcall *)(void *))GetProcAddress(handle, "RtlGetVersion");
132143 os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
167178 Tk_GetHINSTANCE(void)
168179 {
169180 if (tkInstance == NULL) {
170 tkInstance = GetModuleHandle(NULL);
181 tkInstance = GetModuleHandleW(NULL);
171182 }
172183 return tkInstance;
173184 }
247258 childClass.hIcon = NULL;
248259 childClass.hCursor = NULL;
249260
250 if (!RegisterClass(&childClass)) {
261 if (!RegisterClassW(&childClass)) {
251262 Tcl_Panic("Unable to register TkChild class");
252263 }
253264
255266 * Initialize input language info
256267 */
257268
258 if (GetLocaleInfo(LANGIDFROMLCID(PTR2INT(GetKeyboardLayout(0))),
269 if (GetLocaleInfoW(LANGIDFROMLCID(PTR2INT(GetKeyboardLayout(0))),
259270 LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
260 (LPTSTR) &lpCP, sizeof(lpCP)/sizeof(TCHAR))
271 (LPWSTR) &lpCP, sizeof(lpCP)/sizeof(WCHAR))
261272 && TranslateCharsetInfo(INT2PTR(lpCP), &lpCs, TCI_SRCCODEPAGE)) {
262273 UpdateInputLanguage((int) lpCs.ciCharset);
263274 }
297308
298309 if (childClassInitialized) {
299310 childClassInitialized = 0;
300 UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance);
311 UnregisterClassW(TK_WIN_CHILD_CLASS_NAME, hInstance);
301312 }
302313
303314 if (unicodeEncoding != NULL) {
353364 if ((os.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
354365 (os.dwMajorVersion == 5 && os.dwMinorVersion == 1)) {
355366 HKEY hKey;
356 LPCTSTR szSubKey = TEXT("Control Panel\\Appearance");
357 LPCTSTR szCurrent = TEXT("Current");
367 LPCWSTR szSubKey = L"Control Panel\\Appearance";
368 LPCWSTR szCurrent = L"Current";
358369 DWORD dwSize = 200;
359370 char pBuffer[200];
360371
361372 memset(pBuffer, 0, dwSize);
362 if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0L,
373 if (RegOpenKeyExW(HKEY_CURRENT_USER, szSubKey, 0L,
363374 KEY_READ, &hKey) != ERROR_SUCCESS) {
364375 tkWinTheme = TK_THEME_WIN_XP;
365376 } else {
366 RegQueryValueEx(hKey, szCurrent, NULL, NULL, (LPBYTE) pBuffer, &dwSize);
377 RegQueryValueExW(hKey, szCurrent, NULL, NULL, (LPBYTE) pBuffer, &dwSize);
367378 RegCloseKey(hKey);
368379 if (strcmp(pBuffer, "Windows Standard") == 0) {
369380 tkWinTheme = TK_THEME_WIN_CLASSIC;
489500 screen->root_visual->visualid = 0;
490501 if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
491502 screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE);
492 screen->root_visual->class = PseudoColor;
503 screen->root_visual->c_class = PseudoColor;
493504 screen->root_visual->red_mask = 0x0;
494505 screen->root_visual->green_mask = 0x0;
495506 screen->root_visual->blue_mask = 0x0;
496507 } else if (screen->root_depth == 4) {
497 screen->root_visual->class = StaticColor;
508 screen->root_visual->c_class = StaticColor;
498509 screen->root_visual->map_entries = 16;
499510 } else if (screen->root_depth == 8) {
500 screen->root_visual->class = StaticColor;
511 screen->root_visual->c_class = StaticColor;
501512 screen->root_visual->map_entries = 256;
502513 } else if (screen->root_depth == 12) {
503 screen->root_visual->class = TrueColor;
514 screen->root_visual->c_class = TrueColor;
504515 screen->root_visual->map_entries = 32;
505516 screen->root_visual->red_mask = 0xf0;
506517 screen->root_visual->green_mask = 0xf000;
507518 screen->root_visual->blue_mask = 0xf00000;
508519 } else if (screen->root_depth == 16) {
509 screen->root_visual->class = TrueColor;
520 screen->root_visual->c_class = TrueColor;
510521 screen->root_visual->map_entries = 64;
511522 screen->root_visual->red_mask = 0xf8;
512523 screen->root_visual->green_mask = 0xfc00;
513524 screen->root_visual->blue_mask = 0xf80000;
514525 } else if (screen->root_depth >= 24) {
515 screen->root_visual->class = TrueColor;
526 screen->root_visual->c_class = TrueColor;
516527 screen->root_visual->map_entries = 256;
517528 screen->root_visual->red_mask = 0xff;
518529 screen->root_visual->green_mask = 0xff00;
554565 Display *display;
555566 ThreadSpecificData *tsdPtr =
556567 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
568 DWORD initialWheelTick;
557569
558570 if (tsdPtr->winDisplay != NULL) {
559571 if (!strcmp(tsdPtr->winDisplay->display->display_name, display_name)) {
584596
585597 twdPtr = ckalloc(sizeof(TkWinDrawable));
586598 if (twdPtr == NULL) {
587 return None;
599 return NULL;
588600 }
589601 twdPtr->type = TWD_WINDOW;
590602 twdPtr->window.winPtr = NULL;
609621 ZeroMemory(tsdPtr->winDisplay, sizeof(TkDisplay));
610622 tsdPtr->winDisplay->display = display;
611623 tsdPtr->updatingClipboard = FALSE;
612 tsdPtr->wheelTickPrev = GetTickCount();
613 tsdPtr->wheelAcc = 0;
624 initialWheelTick = GetTickCount();
625 tsdPtr->vWheelTickPrev = initialWheelTick;
626 tsdPtr->hWheelTickPrev = initialWheelTick;
627 tsdPtr->vWheelAcc = 0;
628 tsdPtr->hWheelAcc = 0;
629
630 /*
631 * Key map info must be available immediately, because of "send event".
632 */
633 TkpInitKeymapInfo(tsdPtr->winDisplay);
614634
615635 return tsdPtr->winDisplay;
616636 }
759779 case WM_IME_COMPOSITION:
760780 result = 0;
761781 if (HandleIMEComposition(hwnd, lParam) == 0) {
762 result = DefWindowProc(hwnd, message, wParam, lParam);
782 result = DefWindowProcW(hwnd, message, wParam, lParam);
763783 }
764784 break;
765785
779799
780800 case WM_PAINT:
781801 GenerateXEvent(hwnd, message, wParam, lParam);
782 result = DefWindowProc(hwnd, message, wParam, lParam);
802 result = DefWindowProcW(hwnd, message, wParam, lParam);
783803 break;
784804
785805 case TK_CLAIMFOCUS:
816836
817837 default:
818838 if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) {
819 result = DefWindowProc(hwnd, message, wParam, lParam);
839 result = DefWindowProcW(hwnd, message, wParam, lParam);
820840 }
821841 break;
822842 }
897917 ? ((NMHDR*)lParam)->hwndFrom : (HWND) lParam;
898918
899919 if (target && target != hwnd) {
900 *resultPtr = SendMessage(target, message, wParam, lParam);
920 *resultPtr = SendMessageW(target, message, wParam, lParam);
901921 return 1;
902922 }
903923 break;
909929 case WM_MBUTTONDBLCLK:
910930 case WM_RBUTTONDOWN:
911931 case WM_RBUTTONDBLCLK:
932 case WM_XBUTTONDOWN:
933 case WM_XBUTTONDBLCLK:
912934 case WM_LBUTTONUP:
913935 case WM_MBUTTONUP:
914936 case WM_RBUTTONUP:
937 case WM_XBUTTONUP:
915938 case WM_MOUSEMOVE:
916939 Tk_PointerEvent(hwnd, (short) LOWORD(lParam), (short) HIWORD(lParam));
917940 return 1;
936959 case WM_SYSKEYUP:
937960 case WM_KEYUP:
938961 case WM_MOUSEWHEEL:
962 case WM_MOUSEHWHEEL:
939963 GenerateXEvent(hwnd, message, wParam, lParam);
940964 return 1;
941965 case WM_MENUCHAR:
9801004 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
9811005 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
9821006
983 if (message == WM_MOUSEWHEEL) {
1007 if ((message == WM_MOUSEWHEEL) || (message == WM_MOUSEHWHEEL)) {
9841008 union {LPARAM lParam; POINTS point;} root;
9851009 POINT pos;
9861010 root.lParam = lParam;
10951119 break;
10961120
10971121 case WM_MOUSEWHEEL:
1122 case WM_MOUSEHWHEEL:
10981123 case WM_CHAR:
10991124 case WM_UNICHAR:
11001125 case WM_SYSKEYDOWN:
11361161 switch (message) {
11371162 case WM_MOUSEWHEEL: {
11381163 /*
1139 * Support for high resolution wheels.
1164 * Support for high resolution wheels (vertical).
11401165 */
11411166
11421167 DWORD wheelTick = GetTickCount();
11431168
1144 if (wheelTick - tsdPtr->wheelTickPrev < 1500) {
1145 tsdPtr->wheelAcc += (short) HIWORD(wParam);
1169 if (wheelTick - tsdPtr->vWheelTickPrev < 1500) {
1170 tsdPtr->vWheelAcc += (short) HIWORD(wParam);
11461171 } else {
1147 tsdPtr->wheelAcc = (short) HIWORD(wParam);
1172 tsdPtr->vWheelAcc = (short) HIWORD(wParam);
11481173 }
1149 tsdPtr->wheelTickPrev = wheelTick;
1150 if (abs(tsdPtr->wheelAcc) < WHEEL_DELTA) {
1174 tsdPtr->vWheelTickPrev = wheelTick;
1175 if (abs(tsdPtr->vWheelAcc) < WHEEL_DELTA) {
11511176 return;
11521177 }
11531178
11621187 event.type = MouseWheelEvent;
11631188 event.xany.send_event = -1;
11641189 event.xkey.nbytes = 0;
1165 event.xkey.keycode = tsdPtr->wheelAcc / WHEEL_DELTA * WHEEL_DELTA;
1166 tsdPtr->wheelAcc = tsdPtr->wheelAcc % WHEEL_DELTA;
1190 event.xkey.keycode = tsdPtr->vWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
1191 tsdPtr->vWheelAcc = tsdPtr->vWheelAcc % WHEEL_DELTA;
1192 break;
1193 }
1194 case WM_MOUSEHWHEEL: {
1195 /*
1196 * Support for high resolution wheels (horizontal).
1197 */
1198
1199 DWORD wheelTick = GetTickCount();
1200
1201 if (wheelTick - tsdPtr->hWheelTickPrev < 1500) {
1202 tsdPtr->hWheelAcc -= (short) HIWORD(wParam);
1203 } else {
1204 tsdPtr->hWheelAcc = -((short) HIWORD(wParam));
1205 }
1206 tsdPtr->hWheelTickPrev = wheelTick;
1207 if (abs(tsdPtr->hWheelAcc) < WHEEL_DELTA) {
1208 return;
1209 }
1210
1211 /*
1212 * We have invented a new X event type to handle this event. It
1213 * still uses the KeyPress struct. However, the keycode field has
1214 * been overloaded to hold the zDelta of the wheel. Set nbytes to
1215 * 0 to prevent conversion of the keycode to a keysym in
1216 * TkpGetString. [Bug 1118340].
1217 */
1218
1219 event.type = MouseWheelEvent;
1220 event.xany.send_event = -1;
1221 event.xkey.nbytes = 0;
1222 event.xkey.state |= ShiftMask;
1223 event.xkey.keycode = tsdPtr->hWheelAcc / WHEEL_DELTA * WHEEL_DELTA;
1224 tsdPtr->hWheelAcc = tsdPtr->hWheelAcc % WHEEL_DELTA;
11671225 break;
11681226 }
11691227 case WM_SYSKEYDOWN:
12521310 if (IsDBCSLeadByte((BYTE) wParam)) {
12531311 MSG msg;
12541312
1255 if ((PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR,
1313 if ((PeekMessageW(&msg, NULL, WM_CHAR, WM_CHAR,
12561314 PM_NOREMOVE) != 0)
12571315 && (msg.message == WM_CHAR)) {
1258 GetMessage(&msg, NULL, WM_CHAR, WM_CHAR);
1316 GetMessageW(&msg, NULL, WM_CHAR, WM_CHAR);
12591317 event.xkey.nbytes = 2;
12601318 event.xkey.trans_chars[1] = (char) msg.wParam;
12611319 }
14771535 return;
14781536 }
14791537
1480 wsprintfA(codepage, "cp%d", charsetInfo.ciACP);
1538 sprintf(codepage, "cp%d", charsetInfo.ciACP);
14811539
14821540 if ((encoding = Tcl_GetEncoding(NULL, codepage)) == NULL) {
14831541 /*
15381596 TkWinGetUnicodeEncoding(void)
15391597 {
15401598 if (unicodeEncoding == NULL) {
1541 unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");
1599 unicodeEncoding = Tcl_GetEncoding(NULL, "utf-16");
1600 if (unicodeEncoding == NULL) {
1601 unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");
1602 }
15421603 }
15431604 return unicodeEncoding;
15441605 }
15541615 *
15551616 * When an Input Method Editor (IME) is ready to send input characters to
15561617 * an application, it sends a WM_IME_COMPOSITION message with the
1557 * GCS_RESULTSTR. However, The DefWindowProc() on English Windows 2000
1618 * GCS_RESULTSTR. However, The DefWindowProcW() on English Windows 2000
15581619 * arbitrarily converts all non-Latin-1 characters in the composition to
15591620 * "?".
15601621 *
15931654 return 0;
15941655 }
15951656
1596 n = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
1657 n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
15971658
15981659 if (n > 0) {
15991660 WCHAR *buff = (WCHAR *) ckalloc(n);
16011662 XEvent event;
16021663 int i;
16031664
1604 n = ImmGetCompositionString(hIMC, GCS_RESULTSTR, buff, (unsigned) n) / 2;
1665 n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, (unsigned) n) / 2;
16051666
16061667 /*
16071668 * Set up the fields pertinent to key event.
16861747 * TkWinResendEvent --
16871748 *
16881749 * This function converts an X event into a Windows event and invokes the
1689 * specified windo function.
1750 * specified window function.
16901751 *
16911752 * Results:
16921753 * A standard Windows result.
17241785 msg = WM_RBUTTONDOWN;
17251786 wparam = MK_RBUTTON;
17261787 break;
1788 case Button4:
1789 msg = WM_XBUTTONDOWN;
1790 wparam = MAKEWPARAM(MK_XBUTTON1, XBUTTON1);
1791 break;
1792 case Button5:
1793 msg = WM_XBUTTONDOWN;
1794 wparam = MAKEWPARAM(MK_XBUTTON2, XBUTTON2);
1795 break;
17271796 default:
17281797 return 0;
17291798 }
17371806 if (eventPtr->xbutton.state & Button3Mask) {
17381807 wparam |= MK_RBUTTON;
17391808 }
1809 if (eventPtr->xbutton.state & Button4Mask) {
1810 wparam |= MK_XBUTTON1;
1811 }
1812 if (eventPtr->xbutton.state & Button5Mask) {
1813 wparam |= MK_XBUTTON2;
1814 }
17401815 if (eventPtr->xbutton.state & ShiftMask) {
17411816 wparam |= MK_SHIFT;
17421817 }
17451820 }
17461821 lparam = MAKELPARAM((short) eventPtr->xbutton.x,
17471822 (short) eventPtr->xbutton.y);
1748 return CallWindowProc(wndproc, hwnd, msg, wparam, lparam);
1823 return CallWindowProcW(wndproc, hwnd, msg, wparam, lparam);
17491824 }
17501825
17511826 /*
6969 static HWND
7070 CreateThemeMonitorWindow(HINSTANCE hinst, Tcl_Interp *interp)
7171 {
72 WNDCLASSEX wc;
72 WNDCLASSEXW wc;
7373 HWND hwnd = NULL;
74 TCHAR title[32] = TEXT("TtkMonitorWindow");
75 TCHAR name[32] = TEXT("TtkMonitorClass");
74 WCHAR title[32] = L"TtkMonitorWindow";
75 WCHAR name[32] = L"TtkMonitorClass";
7676
77 wc.cbSize = sizeof(WNDCLASSEX);
77 wc.cbSize = sizeof(WNDCLASSEXW);
7878 wc.style = CS_HREDRAW | CS_VREDRAW;
7979 wc.lpfnWndProc = (WNDPROC)WndProc;
8080 wc.cbClsExtra = 0;
8181 wc.cbWndExtra = 0;
8282 wc.hInstance = hinst;
83 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
84 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
85 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
83 wc.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
84 wc.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
85 wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
8686 wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
8787 wc.lpszMenuName = name;
8888 wc.lpszClassName = name;
8989
90 if (RegisterClassEx(&wc)) {
91 hwnd = CreateWindow( name, title, WS_OVERLAPPEDWINDOW,
90 if (RegisterClassExW(&wc)) {
91 hwnd = CreateWindowW( name, title, WS_OVERLAPPEDWINDOW,
9292 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
9393 NULL, NULL, hinst, NULL );
94 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) interp);
94 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) interp);
9595 ShowWindow(hwnd, SW_HIDE);
9696 UpdateWindow(hwnd);
9797 }
108108 static LRESULT WINAPI
109109 WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
110110 {
111 Tcl_Interp *interp = (Tcl_Interp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
111 Tcl_Interp *interp = (Tcl_Interp *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
112112 Ttk_Theme theme;
113113
114114 switch (msg) {
136136 }
137137 break;
138138 }
139 return DefWindowProc(hwnd, msg, wp, lp);
139 return DefWindowProcW(hwnd, msg, wp, lp);
140140 }
141141
142142 /*
9898 * if we are running at least on Windows XP.
9999 */
100100 HINSTANCE handle;
101 *phlib = handle = LoadLibrary(TEXT("uxtheme.dll"));
101 *phlib = handle = LoadLibraryW(L"uxtheme.dll");
102102 if (handle != 0)
103103 {
104104 /*
454454 {
455455 Window win = Tk_WindowId(tkwin);
456456
457 if (win != None) {
457 if (win) {
458458 elementData->hwnd = Tk_GetHWND(win);
459459 } else {
460460 elementData->hwnd = elementData->procs->stubWindow;
828828 ElementData *elementData = clientData;
829829 RECT rc = {0, 0};
830830 HRESULT hr = S_OK;
831 const char *src;
832 int len;
833 Tcl_DString ds;
831834
832835 if (!InitElementData(elementData, tkwin, 0))
833836 return;
834837
838 src = Tcl_GetStringFromObj(element->textObj, &len);
839 Tcl_WinUtfToTChar(src, len, &ds);
835840 hr = elementData->procs->GetThemeTextExtent(
836841 elementData->hTheme,
837842 elementData->hDC,
838843 elementData->info->partId,
839844 Ttk_StateTableLookup(elementData->info->statemap, 0),
840 Tcl_GetUnicode(element->textObj),
845 (WCHAR *) Tcl_DStringValue(&ds),
841846 -1,
842847 DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX,
843848 NULL,
850855 if (*widthPtr < 80) *widthPtr = 80;
851856 if (*heightPtr < 20) *heightPtr = 20;
852857
858 Tcl_DStringFree(&ds);
853859 FreeElementData(elementData);
854860 }
855861
861867 ElementData *elementData = clientData;
862868 RECT rc = BoxToRect(b);
863869 HRESULT hr = S_OK;
870 const char *src;
871 int len;
872 Tcl_DString ds;
864873
865874 if (!InitElementData(elementData, tkwin, d))
866875 return;
867876
877 src = Tcl_GetStringFromObj(element->textObj, &len);
878 Tcl_WinUtfToTChar(src, len, &ds);
868879 hr = elementData->procs->DrawThemeText(
869880 elementData->hTheme,
870881 elementData->hDC,
871882 elementData->info->partId,
872883 Ttk_StateTableLookup(elementData->info->statemap, state),
873 Tcl_GetUnicode(element->textObj),
884 (WCHAR *) Tcl_DStringValue(&ds),
874885 -1,
875886 DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX,
876887 (state & TTK_STATE_DISABLED) ? DTT_GRAYED : 0,
877888 &rc);
889
890 Tcl_DStringFree(&ds);
878891 FreeElementData(elementData);
879892 }
880893
10481061 "SM_CXBORDER", "SM_CYBORDER", "SM_CXVSCROLL", "SM_CYVSCROLL",
10491062 "SM_CXHSCROLL", "SM_CYHSCROLL", "SM_CXMENUCHECK", "SM_CYMENUCHECK",
10501063 "SM_CXMENUSIZE", "SM_CYMENUSIZE", "SM_CXSIZE", "SM_CYSIZE", "SM_CXSMSIZE",
1051 "SM_CYSMSIZE"
1064 "SM_CYSMSIZE", NULL
10521065 };
10531066 int flags[] = {
10541067 SM_CXBORDER, SM_CYBORDER, SM_CXVSCROLL, SM_CYVSCROLL,
11011114 XPThemeData *themeData = clientData;
11021115 ElementInfo *elementPtr = NULL;
11031116 ClientData elementData;
1104 Tcl_UniChar *className;
1117 LPCWSTR className;
11051118 int partId = 0;
11061119 Ttk_StateTable *stateTable;
11071120 Ttk_Padding pad = {0, 0, 0, 0};
11101123 char *name;
11111124 LPWSTR wname;
11121125 Ttk_ElementSpec *elementSpec = &GenericElementSpec;
1126 Tcl_DString classBuf;
11131127
11141128 static const char *optionStrings[] =
11151129 { "-padding","-width","-height","-margins", "-syssize",
11271141 if (Tcl_GetIntFromObj(interp, objv[1], &partId) != TCL_OK) {
11281142 return TCL_ERROR;
11291143 }
1130 className = Tcl_GetUnicodeFromObj(objv[0], &length);
1144 name = Tcl_GetStringFromObj(objv[0], &length);
1145 className = (LPCWSTR) Tcl_WinUtfToTChar(name, length, &classBuf);
11311146
11321147 /* flags or padding */
11331148 if (objc > 3) {
11391154 "Missing value for \"%s\".",
11401155 Tcl_GetString(objv[i])));
11411156 Tcl_SetErrorCode(interp, "TTK", "VSAPI", "MISSING", NULL);
1142 return TCL_ERROR;
1157 goto retErr;
11431158 }
11441159 if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
11451160 sizeof(char *), "option", 0, &option) != TCL_OK)
1146 return TCL_ERROR;
1161 goto retErr;
11471162 switch (option) {
11481163 case O_PADDING:
11491164 if (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) {
1150 return TCL_ERROR;
1165 goto retErr;
11511166 }
11521167 break;
11531168 case O_MARGINS:
11541169 if (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) {
1155 return TCL_ERROR;
1170 goto retErr;
11561171 }
11571172 flags |= PAD_MARGINS;
11581173 break;
11591174 case O_WIDTH:
11601175 if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
1161 return TCL_ERROR;
1176 goto retErr;
11621177 }
11631178 pad.left = pad.right = tmp;
11641179 flags |= IGNORE_THEMESIZE;
11651180 break;
11661181 case O_HEIGHT:
11671182 if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
1168 return TCL_ERROR;
1183 goto retErr;
11691184 }
11701185 pad.top = pad.bottom = tmp;
11711186 flags |= IGNORE_THEMESIZE;
11721187 break;
11731188 case O_SYSSIZE:
11741189 if (GetSysFlagFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
1175 return TCL_ERROR;
1190 goto retErr;
11761191 }
11771192 elementSpec = &GenericSizedElementSpec;
11781193 flags |= (tmp & 0xFFFF);
11791194 break;
11801195 case O_HALFHEIGHT:
11811196 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
1182 return TCL_ERROR;
1197 goto retErr;
11831198 }
11841199 if (tmp)
11851200 flags |= HALF_HEIGHT;
11861201 break;
11871202 case O_HALFWIDTH:
11881203 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
1189 return TCL_ERROR;
1204 goto retErr;
11901205 }
11911206 if (tmp)
11921207 flags |= HALF_WIDTH;
12001215 Tcl_Obj **specs;
12011216 int n,j,count, status = TCL_OK;
12021217 if (Tcl_ListObjGetElements(interp, objv[2], &count, &specs) != TCL_OK)
1203 return TCL_ERROR;
1218 goto retErr;
12041219 /* we over-allocate to ensure there is a terminating entry */
12051220 stateTable = ckalloc(sizeof(Ttk_StateTable) * (count + 1));
12061221 memset(stateTable, 0, sizeof(Ttk_StateTable) * (count + 1));
12161231 }
12171232 if (status != TCL_OK) {
12181233 ckfree(stateTable);
1234 Tcl_DStringFree(&classBuf);
12191235 return status;
12201236 }
12211237 } else {
12361252 elementPtr->elementName = name;
12371253
12381254 /* set the class name to an allocated copy */
1239 wname = ckalloc(sizeof(WCHAR) * (length + 1));
1255 wname = ckalloc(Tcl_DStringLength(&classBuf) + sizeof(WCHAR));
12401256 wcscpy(wname, className);
12411257 elementPtr->className = wname;
12421258
12461262
12471263 Ttk_RegisterCleanup(interp, elementData, DestroyElementData);
12481264 Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));
1265 Tcl_DStringFree(&classBuf);
12491266 return TCL_OK;
1267
1268 retErr:
1269 Tcl_DStringFree(&classBuf);
1270 return TCL_ERROR;
12501271 }
12511272
12521273 /*----------------------------------------------------------------------
0 /***********************************************************
1
2 Copyright 1988, 1998 The Open Group
3
4 Permission to use, copy, modify, distribute, and sell this software and its
5 documentation for any purpose is hereby granted without fee, provided that
6 the above copyright notice appear in all copies and that both that
7 copyright notice and this permission notice appear in supporting
8 documentation.
9
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20 Except as contained in this notice, the name of The Open Group shall not be
21 used in advertising or otherwise to promote the sale, use or other dealings
22 in this Software without prior written authorization from The Open Group.
23
24
25 Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27 All Rights Reserved
28
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
36
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
44
45 ******************************************************************/
46
47 /*
48 * DEC private keysyms
49 * (29th bit set)
50 */
51
52 /* two-key compose sequence initiators, chosen to map to Latin1 characters */
53
54 #define DXK_ring_accent 0x1000FEB0
55 #define DXK_circumflex_accent 0x1000FE5E
56 #define DXK_cedilla_accent 0x1000FE2C
57 #define DXK_acute_accent 0x1000FE27
58 #define DXK_grave_accent 0x1000FE60
59 #define DXK_tilde 0x1000FE7E
60 #define DXK_diaeresis 0x1000FE22
61
62 /* special keysym for LK2** "Remove" key on editing keypad */
63
64 #define DXK_Remove 0x1000FF00 /* Remove */
0 /*
1
2 Copyright 1987, 1998 The Open Group
3
4 Permission to use, copy, modify, distribute, and sell this software and its
5 documentation for any purpose is hereby granted without fee, provided that
6 the above copyright notice appear in all copies and that both that
7 copyright notice and this permission notice appear in supporting
8 documentation.
9
10 The above copyright notice and this permission notice shall be included
11 in all copies or substantial portions of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
17 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19 OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall
22 not be used in advertising or otherwise to promote the sale, use or
23 other dealings in this Software without prior written authorization
24 from The Open Group.
25
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
27
28 All Rights Reserved
29
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the names of Hewlett Packard
35 or Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD
48 TO THIS SOFWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 PURPOSE. Hewlett-Packard shall not be liable for errors
51 contained herein or direct, indirect, special, incidental or
52 consequential damages in connection with the furnishing,
53 performance, or use of this material.
54
55 */
56
57 #ifndef _HPKEYSYM_H
58
59 #define _HPKEYSYM_H
60
61 #define hpXK_ClearLine 0x1000FF6F
62 #define hpXK_InsertLine 0x1000FF70
63 #define hpXK_DeleteLine 0x1000FF71
64 #define hpXK_InsertChar 0x1000FF72
65 #define hpXK_DeleteChar 0x1000FF73
66 #define hpXK_BackTab 0x1000FF74
67 #define hpXK_KP_BackTab 0x1000FF75
68 #define hpXK_Modelock1 0x1000FF48
69 #define hpXK_Modelock2 0x1000FF49
70 #define hpXK_Reset 0x1000FF6C
71 #define hpXK_System 0x1000FF6D
72 #define hpXK_User 0x1000FF6E
73 #define hpXK_mute_acute 0x100000A8
74 #define hpXK_mute_grave 0x100000A9
75 #define hpXK_mute_asciicircum 0x100000AA
76 #define hpXK_mute_diaeresis 0x100000AB
77 #define hpXK_mute_asciitilde 0x100000AC
78 #define hpXK_lira 0x100000AF
79 #define hpXK_guilder 0x100000BE
80 #define hpXK_Ydiaeresis 0x100000EE
81 #define hpXK_IO 0x100000EE
82 #define hpXK_longminus 0x100000F6
83 #define hpXK_block 0x100000FC
84
85
86 #ifndef _OSF_Keysyms
87 #define _OSF_Keysyms
88
89 #define osfXK_Copy 0x1004FF02
90 #define osfXK_Cut 0x1004FF03
91 #define osfXK_Paste 0x1004FF04
92 #define osfXK_BackTab 0x1004FF07
93 #define osfXK_BackSpace 0x1004FF08
94 #define osfXK_Clear 0x1004FF0B
95 #define osfXK_Escape 0x1004FF1B
96 #define osfXK_AddMode 0x1004FF31
97 #define osfXK_PrimaryPaste 0x1004FF32
98 #define osfXK_QuickPaste 0x1004FF33
99 #define osfXK_PageLeft 0x1004FF40
100 #define osfXK_PageUp 0x1004FF41
101 #define osfXK_PageDown 0x1004FF42
102 #define osfXK_PageRight 0x1004FF43
103 #define osfXK_Activate 0x1004FF44
104 #define osfXK_MenuBar 0x1004FF45
105 #define osfXK_Left 0x1004FF51
106 #define osfXK_Up 0x1004FF52
107 #define osfXK_Right 0x1004FF53
108 #define osfXK_Down 0x1004FF54
109 #define osfXK_EndLine 0x1004FF57
110 #define osfXK_BeginLine 0x1004FF58
111 #define osfXK_EndData 0x1004FF59
112 #define osfXK_BeginData 0x1004FF5A
113 #define osfXK_PrevMenu 0x1004FF5B
114 #define osfXK_NextMenu 0x1004FF5C
115 #define osfXK_PrevField 0x1004FF5D
116 #define osfXK_NextField 0x1004FF5E
117 #define osfXK_Select 0x1004FF60
118 #define osfXK_Insert 0x1004FF63
119 #define osfXK_Undo 0x1004FF65
120 #define osfXK_Menu 0x1004FF67
121 #define osfXK_Cancel 0x1004FF69
122 #define osfXK_Help 0x1004FF6A
123 #define osfXK_SelectAll 0x1004FF71
124 #define osfXK_DeselectAll 0x1004FF72
125 #define osfXK_Reselect 0x1004FF73
126 #define osfXK_Extend 0x1004FF74
127 #define osfXK_Restore 0x1004FF78
128 #define osfXK_Delete 0x1004FFFF
129
130 #endif /* _OSF_Keysyms */
131
132
133 /**************************************************************
134 * The use of the following macros is deprecated.
135 * They are listed below only for backwards compatibility.
136 */
137 #define XK_Reset 0x1000FF6C
138 #define XK_System 0x1000FF6D
139 #define XK_User 0x1000FF6E
140 #define XK_ClearLine 0x1000FF6F
141 #define XK_InsertLine 0x1000FF70
142 #define XK_DeleteLine 0x1000FF71
143 #define XK_InsertChar 0x1000FF72
144 #define XK_DeleteChar 0x1000FF73
145 #define XK_BackTab 0x1000FF74
146 #define XK_KP_BackTab 0x1000FF75
147 #define XK_Ext16bit_L 0x1000FF76
148 #define XK_Ext16bit_R 0x1000FF77
149 #define XK_mute_acute 0x100000a8
150 #define XK_mute_grave 0x100000a9
151 #define XK_mute_asciicircum 0x100000aa
152 #define XK_mute_diaeresis 0x100000ab
153 #define XK_mute_asciitilde 0x100000ac
154 #define XK_lira 0x100000af
155 #define XK_guilder 0x100000be
156 #ifndef XK_Ydiaeresis
157 #define XK_Ydiaeresis 0x100000ee
158 #endif
159 #define XK_IO 0x100000ee
160 #define XK_longminus 0x100000f6
161 #define XK_block 0x100000fc
162
163 #endif /* _HPKEYSYM_H */
0 /*
1 * Copyright (c) 1991, Oracle and/or its affiliates. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice (including the next
11 * paragraph) shall be included in all copies or substantial portions of the
12 * Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22 /************************************************************
23
24 Copyright 1991, 1998 The Open Group
25
26 Permission to use, copy, modify, distribute, and sell this software and its
27 documentation for any purpose is hereby granted without fee, provided that
28 the above copyright notice appear in all copies and that both that
29 copyright notice and this permission notice appear in supporting
30 documentation.
31
32 The above copyright notice and this permission notice shall be included in
33 all copies or substantial portions of the Software.
34
35 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
39 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41
42 Except as contained in this notice, the name of The Open Group shall not be
43 used in advertising or otherwise to promote the sale, use or other dealings
44 in this Software without prior written authorization from The Open Group.
45
46 ***********************************************************/
47
48 /*
49 * Floating Accent
50 */
51
52 #define SunXK_FA_Grave 0x1005FF00
53 #define SunXK_FA_Circum 0x1005FF01
54 #define SunXK_FA_Tilde 0x1005FF02
55 #define SunXK_FA_Acute 0x1005FF03
56 #define SunXK_FA_Diaeresis 0x1005FF04
57 #define SunXK_FA_Cedilla 0x1005FF05
58
59 /*
60 * Miscellaneous Functions
61 */
62
63 #define SunXK_F36 0x1005FF10 /* Labeled F11 */
64 #define SunXK_F37 0x1005FF11 /* Labeled F12 */
65
66 #define SunXK_Sys_Req 0x1005FF60
67 #define SunXK_Print_Screen 0x0000FF61 /* Same as XK_Print */
68
69 /*
70 * International & Multi-Key Character Composition
71 */
72
73 #define SunXK_Compose 0x0000FF20 /* Same as XK_Multi_key */
74 #define SunXK_AltGraph 0x0000FF7E /* Same as XK_Mode_switch */
75
76 /*
77 * Cursor Control
78 */
79
80 #define SunXK_PageUp 0x0000FF55 /* Same as XK_Prior */
81 #define SunXK_PageDown 0x0000FF56 /* Same as XK_Next */
82
83 /*
84 * Open Look Functions
85 */
86
87 #define SunXK_Undo 0x0000FF65 /* Same as XK_Undo */
88 #define SunXK_Again 0x0000FF66 /* Same as XK_Redo */
89 #define SunXK_Find 0x0000FF68 /* Same as XK_Find */
90 #define SunXK_Stop 0x0000FF69 /* Same as XK_Cancel */
91 #define SunXK_Props 0x1005FF70
92 #define SunXK_Front 0x1005FF71
93 #define SunXK_Copy 0x1005FF72
94 #define SunXK_Open 0x1005FF73
95 #define SunXK_Paste 0x1005FF74
96 #define SunXK_Cut 0x1005FF75
97
98 #define SunXK_PowerSwitch 0x1005FF76
99 #define SunXK_AudioLowerVolume 0x1005FF77
100 #define SunXK_AudioMute 0x1005FF78
101 #define SunXK_AudioRaiseVolume 0x1005FF79
102 #define SunXK_VideoDegauss 0x1005FF7A
103 #define SunXK_VideoLowerBrightness 0x1005FF7B
104 #define SunXK_VideoRaiseBrightness 0x1005FF7C
105 #define SunXK_PowerSwitchShift 0x1005FF7D
4040 /* Resources */
4141
4242 #ifdef _WIN64
43 typedef __int64 XID;
43 typedef unsigned __int64 XID;
4444 #else
4545 typedef unsigned long XID;
4646 #endif
7272 * RESERVED RESOURCE AND CONSTANT DEFINITIONS
7373 *****************************************************************/
7474
75 #define None 0L /* universal null resource or null atom */
75 #ifndef _WIN32
76 # define None 0L /* See bug [9e31fd9449] and below */
77 #endif
7678
7779 #define ParentRelative 1L /* background pixmap in CreateWindow
7880 and ChangeWindowAttributes */
178180
179181 #define ShiftMask (1<<0)
180182 #define LockMask (1<<1)
181 #define ControlMask (1<<2)
183 #ifndef _WIN32
184 # define ControlMask (1<<2) /* See bug [9e31fd9449] and below */
185 #endif
182186 #define Mod1Mask (1<<3)
183187 #define Mod2Mask (1<<4)
184188 #define Mod3Mask (1<<5)
185189 #define Mod4Mask (1<<6)
186190 #define Mod5Mask (1<<7)
191
192 /* See bug [9e31fd9449], this way prevents conflicts with Win32 headers */
193 #ifdef _WIN32
194 enum _Bug9e31fd9449 { None = 0, ControlMask = (1<<2) };
195 #endif
187196
188197 /* modifier names. Used to build a SetModifierMapping request or
189198 to read a GetModifierMapping request. These correspond to the
0 /*
1 * XFree86 vendor specific keysyms.
2 *
3 * The XFree86 keysym range is 0x10080001 - 0x1008FFFF.
4 *
5 * X.Org will not be adding to the XF86 set of keysyms, though they have
6 * been adopted and are considered a "standard" part of X keysym definitions.
7 * XFree86 never properly commented these keysyms, so we have done our
8 * best to explain the semantic meaning of these keys.
9 *
10 * XFree86 has removed their mail archives of the period, that might have
11 * shed more light on some of these definitions. Until/unless we resurrect
12 * these archives, these are from memory and usage.
13 */
14
15 /*
16 * ModeLock
17 *
18 * This one is old, and not really used any more since XKB offers this
19 * functionality.
20 */
21
22 #define XF86XK_ModeLock 0x1008FF01 /* Mode Switch Lock */
23
24 /* Backlight controls. */
25 #define XF86XK_MonBrightnessUp 0x1008FF02 /* Monitor/panel brightness */
26 #define XF86XK_MonBrightnessDown 0x1008FF03 /* Monitor/panel brightness */
27 #define XF86XK_KbdLightOnOff 0x1008FF04 /* Keyboards may be lit */
28 #define XF86XK_KbdBrightnessUp 0x1008FF05 /* Keyboards may be lit */
29 #define XF86XK_KbdBrightnessDown 0x1008FF06 /* Keyboards may be lit */
30 #define XF86XK_MonBrightnessCycle 0x1008FF07 /* Monitor/panel brightness */
31
32 /*
33 * Keys found on some "Internet" keyboards.
34 */
35 #define XF86XK_Standby 0x1008FF10 /* System into standby mode */
36 #define XF86XK_AudioLowerVolume 0x1008FF11 /* Volume control down */
37 #define XF86XK_AudioMute 0x1008FF12 /* Mute sound from the system */
38 #define XF86XK_AudioRaiseVolume 0x1008FF13 /* Volume control up */
39 #define XF86XK_AudioPlay 0x1008FF14 /* Start playing of audio > */
40 #define XF86XK_AudioStop 0x1008FF15 /* Stop playing audio */
41 #define XF86XK_AudioPrev 0x1008FF16 /* Previous track */
42 #define XF86XK_AudioNext 0x1008FF17 /* Next track */
43 #define XF86XK_HomePage 0x1008FF18 /* Display user's home page */
44 #define XF86XK_Mail 0x1008FF19 /* Invoke user's mail program */
45 #define XF86XK_Start 0x1008FF1A /* Start application */
46 #define XF86XK_Search 0x1008FF1B /* Search */
47 #define XF86XK_AudioRecord 0x1008FF1C /* Record audio application */
48
49 /* These are sometimes found on PDA's (e.g. Palm, PocketPC or elsewhere) */
50 #define XF86XK_Calculator 0x1008FF1D /* Invoke calculator program */
51 #define XF86XK_Memo 0x1008FF1E /* Invoke Memo taking program */
52 #define XF86XK_ToDoList 0x1008FF1F /* Invoke To Do List program */
53 #define XF86XK_Calendar 0x1008FF20 /* Invoke Calendar program */
54 #define XF86XK_PowerDown 0x1008FF21 /* Deep sleep the system */
55 #define XF86XK_ContrastAdjust 0x1008FF22 /* Adjust screen contrast */
56 #define XF86XK_RockerUp 0x1008FF23 /* Rocker switches exist up */
57 #define XF86XK_RockerDown 0x1008FF24 /* and down */
58 #define XF86XK_RockerEnter 0x1008FF25 /* and let you press them */
59
60 /* Some more "Internet" keyboard symbols */
61 #define XF86XK_Back 0x1008FF26 /* Like back on a browser */
62 #define XF86XK_Forward 0x1008FF27 /* Like forward on a browser */
63 #define XF86XK_Stop 0x1008FF28 /* Stop current operation */
64 #define XF86XK_Refresh 0x1008FF29 /* Refresh the page */
65 #define XF86XK_PowerOff 0x1008FF2A /* Power off system entirely */
66 #define XF86XK_WakeUp 0x1008FF2B /* Wake up system from sleep */
67 #define XF86XK_Eject 0x1008FF2C /* Eject device (e.g. DVD) */
68 #define XF86XK_ScreenSaver 0x1008FF2D /* Invoke screensaver */
69 #define XF86XK_WWW 0x1008FF2E /* Invoke web browser */
70 #define XF86XK_Sleep 0x1008FF2F /* Put system to sleep */
71 #define XF86XK_Favorites 0x1008FF30 /* Show favorite locations */
72 #define XF86XK_AudioPause 0x1008FF31 /* Pause audio playing */
73 #define XF86XK_AudioMedia 0x1008FF32 /* Launch media collection app */
74 #define XF86XK_MyComputer 0x1008FF33 /* Display "My Computer" window */
75 #define XF86XK_VendorHome 0x1008FF34 /* Display vendor home web site */
76 #define XF86XK_LightBulb 0x1008FF35 /* Light bulb keys exist */
77 #define XF86XK_Shop 0x1008FF36 /* Display shopping web site */
78 #define XF86XK_History 0x1008FF37 /* Show history of web surfing */
79 #define XF86XK_OpenURL 0x1008FF38 /* Open selected URL */
80 #define XF86XK_AddFavorite 0x1008FF39 /* Add URL to favorites list */
81 #define XF86XK_HotLinks 0x1008FF3A /* Show "hot" links */
82 #define XF86XK_BrightnessAdjust 0x1008FF3B /* Invoke brightness adj. UI */
83 #define XF86XK_Finance 0x1008FF3C /* Display financial site */
84 #define XF86XK_Community 0x1008FF3D /* Display user's community */
85 #define XF86XK_AudioRewind 0x1008FF3E /* "rewind" audio track */
86 #define XF86XK_BackForward 0x1008FF3F /* ??? */
87 #define XF86XK_Launch0 0x1008FF40 /* Launch Application */
88 #define XF86XK_Launch1 0x1008FF41 /* Launch Application */
89 #define XF86XK_Launch2 0x1008FF42 /* Launch Application */
90 #define XF86XK_Launch3 0x1008FF43 /* Launch Application */
91 #define XF86XK_Launch4 0x1008FF44 /* Launch Application */
92 #define XF86XK_Launch5 0x1008FF45 /* Launch Application */
93 #define XF86XK_Launch6 0x1008FF46 /* Launch Application */
94 #define XF86XK_Launch7 0x1008FF47 /* Launch Application */
95 #define XF86XK_Launch8 0x1008FF48 /* Launch Application */
96 #define XF86XK_Launch9 0x1008FF49 /* Launch Application */
97 #define XF86XK_LaunchA 0x1008FF4A /* Launch Application */
98 #define XF86XK_LaunchB 0x1008FF4B /* Launch Application */
99 #define XF86XK_LaunchC 0x1008FF4C /* Launch Application */
100 #define XF86XK_LaunchD 0x1008FF4D /* Launch Application */
101 #define XF86XK_LaunchE 0x1008FF4E /* Launch Application */
102 #define XF86XK_LaunchF 0x1008FF4F /* Launch Application */
103
104 #define XF86XK_ApplicationLeft 0x1008FF50 /* switch to application, left */
105 #define XF86XK_ApplicationRight 0x1008FF51 /* switch to application, right*/
106 #define XF86XK_Book 0x1008FF52 /* Launch bookreader */
107 #define XF86XK_CD 0x1008FF53 /* Launch CD/DVD player */
108 #define XF86XK_Calculater 0x1008FF54 /* Launch Calculater */
109 #define XF86XK_Clear 0x1008FF55 /* Clear window, screen */
110 #define XF86XK_Close 0x1008FF56 /* Close window */
111 #define XF86XK_Copy 0x1008FF57 /* Copy selection */
112 #define XF86XK_Cut 0x1008FF58 /* Cut selection */
113 #define XF86XK_Display 0x1008FF59 /* Output switch key */
114 #define XF86XK_DOS 0x1008FF5A /* Launch DOS (emulation) */
115 #define XF86XK_Documents 0x1008FF5B /* Open documents window */
116 #define XF86XK_Excel 0x1008FF5C /* Launch spread sheet */
117 #define XF86XK_Explorer 0x1008FF5D /* Launch file explorer */
118 #define XF86XK_Game 0x1008FF5E /* Launch game */
119 #define XF86XK_Go 0x1008FF5F /* Go to URL */
120 #define XF86XK_iTouch 0x1008FF60 /* Logitech iTouch- don't use */
121 #define XF86XK_LogOff 0x1008FF61 /* Log off system */
122 #define XF86XK_Market 0x1008FF62 /* ?? */
123 #define XF86XK_Meeting 0x1008FF63 /* enter meeting in calendar */
124 #define XF86XK_MenuKB 0x1008FF65 /* distinguish keyboard from PB */
125 #define XF86XK_MenuPB 0x1008FF66 /* distinguish PB from keyboard */
126 #define XF86XK_MySites 0x1008FF67 /* Favourites */
127 #define XF86XK_New 0x1008FF68 /* New (folder, document... */
128 #define XF86XK_News 0x1008FF69 /* News */
129 #define XF86XK_OfficeHome 0x1008FF6A /* Office home (old Staroffice)*/
130 #define XF86XK_Open 0x1008FF6B /* Open */
131 #define XF86XK_Option 0x1008FF6C /* ?? */
132 #define XF86XK_Paste 0x1008FF6D /* Paste */
133 #define XF86XK_Phone 0x1008FF6E /* Launch phone; dial number */
134 #define XF86XK_Q 0x1008FF70 /* Compaq's Q - don't use */
135 #define XF86XK_Reply 0x1008FF72 /* Reply e.g., mail */
136 #define XF86XK_Reload 0x1008FF73 /* Reload web page, file, etc. */
137 #define XF86XK_RotateWindows 0x1008FF74 /* Rotate windows e.g. xrandr */
138 #define XF86XK_RotationPB 0x1008FF75 /* don't use */
139 #define XF86XK_RotationKB 0x1008FF76 /* don't use */
140 #define XF86XK_Save 0x1008FF77 /* Save (file, document, state */
141 #define XF86XK_ScrollUp 0x1008FF78 /* Scroll window/contents up */
142 #define XF86XK_ScrollDown 0x1008FF79 /* Scrool window/contentd down */
143 #define XF86XK_ScrollClick 0x1008FF7A /* Use XKB mousekeys instead */
144 #define XF86XK_Send 0x1008FF7B /* Send mail, file, object */
145 #define XF86XK_Spell 0x1008FF7C /* Spell checker */
146 #define XF86XK_SplitScreen 0x1008FF7D /* Split window or screen */
147 #define XF86XK_Support 0x1008FF7E /* Get support (??) */
148 #define XF86XK_TaskPane 0x1008FF7F /* Show tasks */
149 #define XF86XK_Terminal 0x1008FF80 /* Launch terminal emulator */
150 #define XF86XK_Tools 0x1008FF81 /* toolbox of desktop/app. */
151 #define XF86XK_Travel 0x1008FF82 /* ?? */
152 #define XF86XK_UserPB 0x1008FF84 /* ?? */
153 #define XF86XK_User1KB 0x1008FF85 /* ?? */
154 #define XF86XK_User2KB 0x1008FF86 /* ?? */
155 #define XF86XK_Video 0x1008FF87 /* Launch video player */
156 #define XF86XK_WheelButton 0x1008FF88 /* button from a mouse wheel */
157 #define XF86XK_Word 0x1008FF89 /* Launch word processor */
158 #define XF86XK_Xfer 0x1008FF8A
159 #define XF86XK_ZoomIn 0x1008FF8B /* zoom in view, map, etc. */
160 #define XF86XK_ZoomOut 0x1008FF8C /* zoom out view, map, etc. */
161
162 #define XF86XK_Away 0x1008FF8D /* mark yourself as away */
163 #define XF86XK_Messenger 0x1008FF8E /* as in instant messaging */
164 #define XF86XK_WebCam 0x1008FF8F /* Launch web camera app. */
165 #define XF86XK_MailForward 0x1008FF90 /* Forward in mail */
166 #define XF86XK_Pictures 0x1008FF91 /* Show pictures */
167 #define XF86XK_Music 0x1008FF92 /* Launch music application */
168
169 #define XF86XK_Battery 0x1008FF93 /* Display battery information */
170 #define XF86XK_Bluetooth 0x1008FF94 /* Enable/disable Bluetooth */
171 #define XF86XK_WLAN 0x1008FF95 /* Enable/disable WLAN */
172 #define XF86XK_UWB 0x1008FF96 /* Enable/disable UWB */
173
174 #define XF86XK_AudioForward 0x1008FF97 /* fast-forward audio track */
175 #define XF86XK_AudioRepeat 0x1008FF98 /* toggle repeat mode */
176 #define XF86XK_AudioRandomPlay 0x1008FF99 /* toggle shuffle mode */
177 #define XF86XK_Subtitle 0x1008FF9A /* cycle through subtitle */
178 #define XF86XK_AudioCycleTrack 0x1008FF9B /* cycle through audio tracks */
179 #define XF86XK_CycleAngle 0x1008FF9C /* cycle through angles */
180 #define XF86XK_FrameBack 0x1008FF9D /* video: go one frame back */
181 #define XF86XK_FrameForward 0x1008FF9E /* video: go one frame forward */
182 #define XF86XK_Time 0x1008FF9F /* display, or shows an entry for time seeking */
183 #define XF86XK_Select 0x1008FFA0 /* Select button on joypads and remotes */
184 #define XF86XK_View 0x1008FFA1 /* Show a view options/properties */
185 #define XF86XK_TopMenu 0x1008FFA2 /* Go to a top-level menu in a video */
186
187 #define XF86XK_Red 0x1008FFA3 /* Red button */
188 #define XF86XK_Green 0x1008FFA4 /* Green button */
189 #define XF86XK_Yellow 0x1008FFA5 /* Yellow button */
190 #define XF86XK_Blue 0x1008FFA6 /* Blue button */
191
192 #define XF86XK_Suspend 0x1008FFA7 /* Sleep to RAM */
193 #define XF86XK_Hibernate 0x1008FFA8 /* Sleep to disk */
194 #define XF86XK_TouchpadToggle 0x1008FFA9 /* Toggle between touchpad/trackstick */
195 #define XF86XK_TouchpadOn 0x1008FFB0 /* The touchpad got switched on */
196 #define XF86XK_TouchpadOff 0x1008FFB1 /* The touchpad got switched off */
197
198 #define XF86XK_AudioMicMute 0x1008FFB2 /* Mute the Mic from the system */
199
200 #define XF86XK_Keyboard 0x1008FFB3 /* User defined keyboard related action */
201
202 #define XF86XK_WWAN 0x1008FFB4 /* Toggle WWAN (LTE, UMTS, etc.) radio */
203 #define XF86XK_RFKill 0x1008FFB5 /* Toggle radios on/off */
204
205 #define XF86XK_AudioPreset 0x1008FFB6 /* Select equalizer preset, e.g. theatre-mode */
206
207 #define XF86XK_RotationLockToggle 0x1008FFB7 /* Toggle screen rotation lock on/off */
208
209 /* Keys for special action keys (hot keys) */
210 /* Virtual terminals on some operating systems */
211 #define XF86XK_Switch_VT_1 0x1008FE01
212 #define XF86XK_Switch_VT_2 0x1008FE02
213 #define XF86XK_Switch_VT_3 0x1008FE03
214 #define XF86XK_Switch_VT_4 0x1008FE04
215 #define XF86XK_Switch_VT_5 0x1008FE05
216 #define XF86XK_Switch_VT_6 0x1008FE06
217 #define XF86XK_Switch_VT_7 0x1008FE07
218 #define XF86XK_Switch_VT_8 0x1008FE08
219 #define XF86XK_Switch_VT_9 0x1008FE09
220 #define XF86XK_Switch_VT_10 0x1008FE0A
221 #define XF86XK_Switch_VT_11 0x1008FE0B
222 #define XF86XK_Switch_VT_12 0x1008FE0C
223
224 #define XF86XK_Ungrab 0x1008FE20 /* force ungrab */
225 #define XF86XK_ClearGrab 0x1008FE21 /* kill application with grab */
226 #define XF86XK_Next_VMode 0x1008FE22 /* next video mode available */
227 #define XF86XK_Prev_VMode 0x1008FE23 /* prev. video mode available */
228 #define XF86XK_LogWindowTree 0x1008FE24 /* print window tree to log */
229 #define XF86XK_LogGrabInfo 0x1008FE25 /* print all active grabs to log */
529529 #endif
530530 #ifndef _XEVENT_
531531
532 #define XMaxTransChars 4
532 #define XMaxTransChars 7
533533
534534 /*
535535 * Definitions of specific events.
548548 unsigned int state; /* key or button mask */
549549 unsigned int keycode; /* detail */
550550 Bool same_screen; /* same screen flag */
551 char trans_chars[XMaxTransChars];
551 char trans_chars[XMaxTransChars];
552552 /* translated characters */
553 int nbytes;
553 unsigned char nbytes;
554554 } XKeyEvent;
555555 typedef XKeyEvent XKeyPressedEvent;
556556 typedef XKeyEvent XKeyReleasedEvent;
0 /******************************************************************
1 Copyright 1987 by Apollo Computer Inc., Chelmsford, Massachusetts.
2 Copyright 1989 by Hewlett-Packard Company.
3
4 All Rights Reserved
5
6 Permission to use, duplicate, change, and distribute this software and
7 its documentation for any purpose and without fee is granted, provided
8 that the above copyright notice appear in such copy and that this
9 copyright notice appear in all supporting documentation, and that the
10 names of Apollo Computer Inc., the Hewlett-Packard Company, or the X
11 Consortium not be used in advertising or publicity pertaining to
12 distribution of the software without written prior permission.
13
14 HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD
15 TO THIS SOFWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 PURPOSE. Hewlett-Packard shall not be liable for errors
18 contained herein or direct, indirect, special, incidental or
19 consequential damages in connection with the furnishing,
20 performance, or use of this material.
21
22 This software is not subject to any license of the American
23 Telephone and Telegraph Company or of the Regents of the
24 University of California.
25 ******************************************************************/
26
27 #define apXK_LineDel 0x1000FF00
28 #define apXK_CharDel 0x1000FF01
29 #define apXK_Copy 0x1000FF02
30 #define apXK_Cut 0x1000FF03
31 #define apXK_Paste 0x1000FF04
32 #define apXK_Move 0x1000FF05
33 #define apXK_Grow 0x1000FF06
34 #define apXK_Cmd 0x1000FF07
35 #define apXK_Shell 0x1000FF08
36 #define apXK_LeftBar 0x1000FF09
37 #define apXK_RightBar 0x1000FF0A
38 #define apXK_LeftBox 0x1000FF0B
39 #define apXK_RightBox 0x1000FF0C
40 #define apXK_UpBox 0x1000FF0D
41 #define apXK_DownBox 0x1000FF0E
42 #define apXK_Pop 0x1000FF0F
43 #define apXK_Read 0x1000FF10
44 #define apXK_Edit 0x1000FF11
45 #define apXK_Save 0x1000FF12
46 #define apXK_Exit 0x1000FF13
47 #define apXK_Repeat 0x1000FF14
48
49 #define apXK_KP_parenleft 0x1000FFA8
50 #define apXK_KP_parenright 0x1000FFA9
396396 #define XK_Otilde 0x0d5
397397 #define XK_Odiaeresis 0x0d6
398398 #define XK_multiply 0x0d7
399 #define XK_Oslash 0x0d8
399400 #define XK_Ooblique 0x0d8
400401 #define XK_Ugrave 0x0d9
401402 #define XK_Uacute 0x0da
839840 #define XK_Greek_EPSILONaccent 0x7a2
840841 #define XK_Greek_ETAaccent 0x7a3
841842 #define XK_Greek_IOTAaccent 0x7a4
843 #define XK_Greek_IOTAdieresis 0x7a5
842844 #define XK_Greek_IOTAdiaeresis 0x7a5
843845 #define XK_Greek_OMICRONaccent 0x7a7
844846 #define XK_Greek_UPSILONaccent 0x7a8
4949 static TkpClipMask *AllocClipMask(GC gc) {
5050 TkpClipMask *clip_mask = (TkpClipMask*) gc->clip_mask;
5151
52 if (clip_mask == None) {
52 if (clip_mask == NULL) {
5353 clip_mask = ckalloc(sizeof(TkpClipMask));
5454 gc->clip_mask = (Pixmap) clip_mask;
5555 #ifdef MAC_OSX_TK
116116 /*
117117 * In order to have room for a dash list, MAX_DASH_LIST_SIZE extra chars
118118 * are defined, which is invisible from the outside. The list is assumed
119 * to end with a 0-char, so this must be set explicitely during
119 * to end with a 0-char, so this must be set explicitly during
120120 * initialization.
121121 */
122122
124124
125125 gp = ckalloc(sizeof(XGCValues) + MAX_DASH_LIST_SIZE + gcCacheSize);
126126 if (!gp) {
127 return None;
127 return NULL;
128128 }
129129
130130 #define InitField(name,maskbit,default) \
267267 Display *d,
268268 GC gc)
269269 {
270 if (gc != None) {
270 if (gc != NULL) {
271271 FreeClipMask(gc);
272272 TkpFreeGCCache(gc);
273273 ckfree(gc);
452452 * None.
453453 *
454454 * Side effects:
455 * Allocates or dealloates a TkpClipMask.
456 *
457 *----------------------------------------------------------------------
458 */
459
460 void
455 * Allocates or deallocates a TkpClipMask.
456 *
457 *----------------------------------------------------------------------
458 */
459
460 int
461461 TkSetRegion(
462462 Display *display,
463463 GC gc,
464464 TkRegion r)
465465 {
466 if (r == None) {
467 Tcl_Panic("must not pass None to TkSetRegion for compatibility with X11; use XSetClipMask instead");
466 if (r == NULL) {
467 Tcl_Panic("must not pass NULL to TkSetRegion for compatibility with X11; use XSetClipMask instead");
468468 } else {
469469 TkpClipMask *clip_mask = AllocClipMask(gc);
470470
474474 TkpRetainRegion(r);
475475 #endif
476476 }
477 return Success;
477478 }
478479
479480 int
88 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
99 */
1010
11 #include <stdlib.h>
12 #include <tk.h>
13
14 #include <X11/Xlib.h>
15 #include <X11/Xutil.h>
16 #include <X11/Xatom.h>
11 #include "tkInt.h"
1712
1813 /*
1914 *----------------------------------------------------------------------
7469 info->visualid = info->visual->visualid;
7570 info->screen = 0;
7671 info->depth = info->visual->bits_per_rgb;
77 info->class = info->visual->class;
72 info->c_class = info->visual->c_class;
7873 info->colormap_size = info->visual->map_entries;
7974 info->bits_per_rgb = info->visual->bits_per_rgb;
8075 info->red_mask = info->visual->red_mask;
8883 || ((vinfo_mask & VisualDepthMask)
8984 && (vinfo_template->depth != info->depth))
9085 || ((vinfo_mask & VisualClassMask)
91 && (vinfo_template->class != info->class))
86 && (vinfo_template->c_class != info->c_class))
9287 || ((vinfo_mask & VisualColormapSizeMask)
9388 && (vinfo_template->colormap_size != info->colormap_size))
9489 || ((vinfo_mask & VisualBitsPerRGBMask)