diff --git a/ChangeLog b/ChangeLog index 2c1ca70..f01946a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ A NOTE ON THE CHANGELOG: Starting in early 2011, Tk source code has been under the management of -fossil, hosted at http://core.tcl-lang.org/tk/ . Fossil presents a "Timeline" +fossil, hosted at https://core.tcl-lang.org/tk/ . Fossil presents a "Timeline" view of changes made that is superior in every way to a hand edited log file. Because of this, many Tk developers are now out of the habit of maintaining this log file. You may still find useful things in it, but the Timeline is diff --git a/ChangeLog.2002 b/ChangeLog.2002 index b523e7d..b27b92b 100644 --- a/ChangeLog.2002 +++ b/ChangeLog.2002 @@ -5218,7 +5218,7 @@ 2000-05-31 Eric Melski * library/bgerror.tcl: Improved bgerror based on work by Donal - K. Fellows; no longer dependant on tk_dialog; features a + K. Fellows; no longer dependent on tk_dialog; features a Windows-esque "Details" button, and a customizable extra function button that allows the user to (for example) save the stack trace to a file. diff --git a/README b/README deleted file mode 100644 index 0c41c9c..0000000 --- a/README +++ /dev/null @@ -1,41 +0,0 @@ -README: Tk - This is the Tk 8.6.9 source distribution. - http://sourceforge.net/projects/tcl/files/Tcl/ - You can get any source release of Tk from the URL above. - -1. Introduction ---------------- - -This directory contains the sources and documentation for Tk, an X11 -toolkit implemented with the Tcl scripting language. - -For details on features, incompatibilities, and potential problems with -this release, see the Tcl/Tk 8.6 Web page at - - http://www.tcl-lang.org/software/tcltk/8.6.html - -or refer to the "changes" file in this directory, which contains a -historical record of all changes to Tk. - -Tk is maintained, enhanced, and distributed freely by the Tcl community. -Source code development and tracking of bug reports and feature requests -takes place at: - - http://core.tcl-lang.org/tk/ - -with the Tcl Developer Xchange at: - - http://www.tcl-lang.org/ - -Tk is a freely available open source package. You can do virtually -anything you like with it, such as modifying it, redistributing it, -and selling it either in whole or in part. See the file -"license.terms" for complete information. - -2. See Tcl README ------------------ - -Please see the README file that comes with the associated Tcl release -for more information. There are pointers there to extensive -documentation. In addition, there are additional README files -in the subdirectories of this distribution. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c989637 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# README: Tk + +This is the **Tk 8.6.10** source distribution. + +You can get any source release of Tk from [our distribution +site](https://sourceforge.net/projects/tcl/files/Tcl/). + + +## 1. Introduction + +This directory contains the sources and documentation for Tk, a +cross-platform GUI toolkit implemented with the Tcl scripting language. + +For details on features, incompatibilities, and potential problems with +this release, see [the Tcl/Tk 8.6 Web page](https://www.tcl.tk/software/tcltk/8.6.html) +or refer to the "changes" file in this directory, which contains a +historical record of all changes to Tk. + +Tk is maintained, enhanced, and distributed freely by the Tcl community. +Source code development and tracking of bug reports and feature requests +takes place at [core.tcl-lang.org](https://core.tcl-lang.org/). +Tcl/Tk release and mailing list services are [hosted by +SourceForge](https://sourceforge.net/projects/tcl/) +with the Tcl Developer Xchange hosted at +[www.tcl-lang.org](https://www.tcl-lang.org). + +Tk is a freely available open source package. You can do virtually +anything you like with it, such as modifying it, redistributing it, +and selling it either in whole or in part. See the file +`license.terms` for complete information. + +## 2. See Tcl README.md + +Please see the README.md file that comes with the associated Tcl release +for more information. There are pointers there to extensive +documentation. In addition, there are additional README files +in the subdirectories of this distribution. diff --git a/changes b/changes index 29e992a..aea39f3 100644 --- a/changes +++ b/changes @@ -7072,7 +7072,7 @@ 2013-08-25 (bug fix)[3016181] Cocoa: [destroy $scrollbar] => crash (goddard) ---- Released 8.6.1, September 19, 2013 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.1, September 19, 2013 --- https://core.tcl-lang.org/tk/ for details 2013-10-27 (bug fix) OSX drawing lags (deily,steffen,walzer) @@ -7120,7 +7120,7 @@ 2014-08-01 (bug fix) OSX font config crash (rob@bitkeeper) ---- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.2, August 27, 2014 --- https://core.tcl-lang.org/tk/ for details 2014-08-27 (bug) Cocoa: Crash after [$button destroy] (walzer) @@ -7144,7 +7144,7 @@ 2014-11-07 (bug)[3529885] [scale] handling of negative resolution (vogel) ---- Released 8.6.3, November 12, 2014 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.3, November 12, 2014 --- https://core.tcl-lang.org/tk/ for details 2014-11-14 (bug)[d43a10] shimmer-related crash in [tk_getOpenFile] (nadkarni) @@ -7166,7 +7166,7 @@ Tk Cocoa 2.0: App Store enabled (walzer,culler,desmera,owen,nyberg,reincke) *** POTENTIAL INCOMPATIBILITY *** ---- Released 8.6.4, March 12, 2015 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.4, March 12, 2015 --- https://core.tcl-lang.org/tk/ for details 2015-03-10 (bug) Cocoa: premature image free crash (walzer) @@ -7265,7 +7265,7 @@ Tk Cocoa 2.0: More drawing internals refinements (culler,walzer) ---- Released 8.6.5, February 29, 2016 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.5, February 29, 2016 --- https://core.tcl-lang.org/tk/ for details 2016-03-07 (bug)[3137232] spinbox teardown hygiene (vogel) @@ -7312,7 +7312,7 @@ 2016-07-21 (bug)[450bb0] Aqua: memory corruption from [tk busy] (porter) ---- Released 8.6.6, July 27, 2016 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.6, July 27, 2016 --- https://core.tcl-lang.org/tk/ for details 2016-08-23 (bug)[a2abc4] Wrong warp cursor position on 2nd display (vogel) @@ -7414,7 +7414,7 @@ 2017-08-08 (bug)[4966ca] Scidb race in notebook tab selection (cramer) ---- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.7, August 9, 2017 --- https://core.tcl-lang.org/tk/ for details 2017-08-24 (bug)[f1a3ca] Memory leak in [text] B-tree (edhume3) @@ -7494,7 +7494,7 @@ 2017-12-18 (bug)[b77626] Make [tk busy -cursor] silent no-op on macOS (vogel) ---- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tk/ for details +--- Released 8.6.8, December 22, 2017 --- https://core.tcl-lang.org/tk/ for details 2017-12-31 (bug)[aa7679] crash using window after master destroyed (vogel) @@ -7568,4 +7568,133 @@ 2018-11-04 (bug)[6b22d4] [treeview] binding fix (ohagan) -- Released 8.6.9, November 16, 2018 - http://core.tcl-lang.org/tk/ for details - +- Released 8.6.9, November 16, 2018 - https://core.tcl-lang.org/tk/ for details + +2018-11-19 (bug)[0a9c91] crash in text-11a.22 (vogel) + +2018-11-20 (bug)[9705d1] crash activating "Alt" theme (culler) + +2018-11-24 (bug)[e3b954] cursor offset at full screen display (culler) + +2019-01-04 (bug)[18a4ba] cross-platform [winfo containing] (culler) + +2019-01-08 (feature) local grab on Mac OSX (culler) + +2019-01-10 (build) 'None', 'ControlMask' symbol conflicts (nijtmans) + +2019-01-20 (bug)[509caf] [treeview tag configure] regression (mcdonald,vogel) + +2019-01-26 (bug)[3003895] [scale] res rounds and -from (tischler,pieper,vogel) + +2019-02-02 (new)[TIP 533] [$mb post x y idx] (culler,vogel) + +2019-02-08 (bug)[1529659] embed toplevel blocks outer menu (culler) + +2019-02-10 (bug)[8814bd] crash in [NSMenu size] (culler) + +2019-02-13 (bug)[b389df] Aqua: mouse position on dual screen (culler) + +2019-02-23 (bug)[56a182] Aqua: [tk_getOpenFile] causes off-screen toplevels (culler,walzer) + +2019-02-23 (bug)[9771ae] Aqua: workaround incompatible transient window models (culler,walzer) + +2019-03-01 (bug)[1951ab] Prevent transient window cycles (crashed on Aqua) (culler,vogel) + *** POTENTIAL INCOMPATIBILITY *** + +2019-03-04 (bug)[4da219] Incomplete read of multi-image GIF (oehlmann) + +2019-03-14 (bug)[609e00] Aqua: wrong coords from MouseWheel binding (vogel,culler) + +2019-03-25 (bug)[48c394] Aqua: recompute text layout for empty string (culler) + +2019-03-31 (new)[TIP 535] Precision of ::scale widget tick mark values (vogel) + *** POTENTIAL INCOMPATIBILITY *** + +2019-03-31 (bug)[da3914] [$treeview identify element] failure (ulfalizer,vogel) + +2019-04-06 (bug)[897ffe] Prevent cross-manager loops of geom management (culler,vogel) + +2019-04-11 (new) Apple Dark Mode support (culler) + +2019-04-14 (new) Aqua: Use color names consistent with NSColor (culler) + *** POTENTIAL INCOMPATIBILITY *** + +2019-04-14 (new) Aqua: [tk::unsupported::MacWindowStyle isdark] (culler) + +2019-04-19 (bug)[368fa4] Prevent toggle of hidden treeview indicators (ulfalizer,vogel) + +2019-04-24 (bug)[4d2e8d] Aqua: notebook pane redraws (culler) + +2019-04-24 (bug)[928652] Apply TIP 533 for ttk::menubutton (culler,vogel) + +2019-04-24 (bug)[1001070] X-platform rework of label options -highlight* (seal,culler,vogel) + +2019-04-28 (bug)[6286fd] checkbutton handling of -selectcolor (ralfixx) + +2019-04-30 (bug)[4f9a99] Win: crash in [style element create] (oehlman,vogel) + +2019-05-08 (bug) Ttk scrolling bugs, see tests treeview-9.1, entry-3.[3-6] (vogel) + +2019-05-08 (bug)[51b4b1] Aqua: combobox use native ttk scrollbar (bll,vogel) + *** POTENTIAL INCOMPATIBILITY *** + +2019-05-18 (new)[eb2996] Win: support for horizontal scrolling (chavez,vogel) + +2019-05-26 (new)[TIP 541] [combobox current] support "end" index (vogel) + +2019-05-26 (bug)[2a6c62] <> trigger on item delete (vogel) + +2019-06-05 (bug)[9ebc6f] Aqua: fix incorrect reports of mouse coords (chavez, culler) + +2019-06-14 (bug)[436ad6] Corrected Aqua regressions in [wm manage] (walzer, culler) + +2019-06-15 (bug)[75b8fb] Crash with some [event generate]d (leunissen,vogel) + +2019-06-15 (new)[TIP 536] New tk::mac::* commands for IPC on Mac OSX (walzer) + +2019-07-13 (bug)[4566e2] Aqua: Make default background color of Tk and Ttk agree (walzer,culler) + *** POTENTIAL INCOMPATIBILITY *** + +2019-07-16 (bug)[5ddeca] Stop app switching exposing withdrawn windows as zombies (culler) + +2019-07-25 (new)[1fb7af] Win support for buttons 4 and 5 (chavez,vogel,nijtmans) + +2019-08-18 (new) Refactor all MouseWheel bindings (nijtmans) + *** POTENTIAL INCOMPATIBILITY *** + +2019-08-21 (bug)[c8ccd1] up array key in [text] takes to index 1.0 (ulfalizer,vogel) + +2019-08-28 (new)[TIP 532] Tk event loop rewrite to prevent ring overflow (cramer) + *** POTENTIAL INCOMPATIBILITY *** + +2019-08-28 (bug)[943d5e] Win: embedded widget destruction cancels window resize (nemethi,vogel,nijtmans) + +2019-09-12 (bug)[2834776] Stop disabled spinbox from generating <> & <> (vogel) + +2019-09-24 (bug)[96bce5] Aqua: Prevent crash drawing 1x1 rounded rectangles (bll,culler) + +2019-10-03 (bug)[3ed5b6] Win: root window position with highlightthickness>0 (leunissem,vogel,nijtmans) + +2019-10-09 (bug)[a01b6f7] Workaround XWayland bug reporting screen width (werner,nijtmans) + +2019-10-10 (bug) Aqua: Prevent crash deactivating menu during menu deletion (culler) + +2019-10-21 (bug)[aea00b] Aqua: Better handling of resolution changes (chavez, culler) + +2019-10-25 (bug)[b82bd4] Fix [style configure -compound] (culler,vogel) + +2019-10-27 (bug)[f7a4f7] Aqua: embedded toplevel, forced focus and mouse coords (naaus,culler) + +2019-11-13 (new) Win: keycodes Mail, AudioMedia, Launch0, Launch1 (nijtmans) + +2019-11-15 (bug)[69b48f] failing test textTag-18.1 (vogel) + +2019-11-17 (bug)[c4abd2] panic in stackorder command (culler) + +2019-11-17 (bug)[53d280] [wm iconphoto] crash on empty image (culler) + +2019-11-17 [90d555] workaround NSFontManager bad selections (culler) + +2019-11-19 (new) Partial Emoji support in text displays (nijtmans,culler) + +- Released 8.6.10, Nov 21, 2019 - https://core.tcl-lang.org/tk/ for details diff --git a/doc/CanvTkwin.3 b/doc/CanvTkwin.3 index d53c5b1..3534989 100644 --- a/doc/CanvTkwin.3 +++ b/doc/CanvTkwin.3 @@ -144,7 +144,7 @@ .PP .CS static const Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc, - Tk_CanvasTagsPrintProc, (ClientData) NULL + Tk_CanvasTagsPrintProc, NULL }; static const Tk_ConfigSpec configSpecs[] = { diff --git a/doc/CrtCmHdlr.3 b/doc/CrtCmHdlr.3 index 98b93f7..bcc9493 100644 --- a/doc/CrtCmHdlr.3 +++ b/doc/CrtCmHdlr.3 @@ -31,7 +31,7 @@ The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR; this mechanism only works in programs that dispatch events through \fBTk_HandleEvent\fR (or through other Tk procedures that -call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or +call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or \fBTk_MainLoop\fR). .PP \fIProc\fR should have arguments and result that match the diff --git a/doc/CrtGenHdlr.3 b/doc/CrtGenHdlr.3 index c2161d1..671d105 100644 --- a/doc/CrtGenHdlr.3 +++ b/doc/CrtGenHdlr.3 @@ -38,7 +38,7 @@ The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR; this mechanism only works in programs that dispatch events through \fBTk_HandleEvent\fR (or through other Tk procedures that -call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or +call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or \fBTk_MainLoop\fR). .PP \fIProc\fR should have arguments and result that match the diff --git a/doc/EventHndlr.3 b/doc/EventHndlr.3 index 97857fb..d06de86 100644 --- a/doc/EventHndlr.3 +++ b/doc/EventHndlr.3 @@ -38,7 +38,7 @@ The callback to \fIproc\fR will be made by \fBTk_HandleEvent\fR; this mechanism only works in programs that dispatch events through \fBTk_HandleEvent\fR (or through other Tk procedures that -call \fBTk_HandleEvent\fR, such as \fBTk_DoOneEvent\fR or +call \fBTk_HandleEvent\fR, such as \fBTcl_DoOneEvent\fR or \fBTk_MainLoop\fR). .PP \fIProc\fR should have arguments and result that match the diff --git a/doc/GetScroll.3 b/doc/GetScroll.3 index abd0880..a71986d 100644 --- a/doc/GetScroll.3 +++ b/doc/GetScroll.3 @@ -15,10 +15,10 @@ \fB#include \fR .sp int -\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, dblPtr, intPtr\fB)\fR +\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, fractionPtr, stepsPtr\fB)\fR .sp int -\fBTk_GetScrollInfo(\fIinterp, argc, argv, dblPtr, intPtr\fB)\fR +\fBTk_GetScrollInfo(\fIinterp, argc, argv, fractionPtr, stepsPtr\fB)\fR .SH ARGUMENTS .AS "Tcl_Interp" *fractionPtr .AP Tcl_Interp *interp in diff --git a/doc/HandleEvent.3 b/doc/HandleEvent.3 index bc293b6..38b5660 100644 --- a/doc/HandleEvent.3 +++ b/doc/HandleEvent.3 @@ -25,7 +25,7 @@ .PP \fBTk_HandleEvent\fR is a lower-level procedure that deals with window events. It is called by \fBTcl_ServiceEvent\fR (and indirectly by -\fBTk_DoOneEvent\fR), and in a few other cases within Tk. +\fBTcl_DoOneEvent\fR), and in a few other cases within Tk. It makes callbacks to any window event handlers (created by calls to \fBTk_CreateEventHandler\fR) that match \fIeventPtr\fR and then returns. In some cases diff --git a/doc/MoveToplev.3 b/doc/MoveToplev.3 index effed29..00bbaa5 100644 --- a/doc/MoveToplev.3 +++ b/doc/MoveToplev.3 @@ -46,6 +46,6 @@ When \fBTk_MoveToplevelWindow\fR is called it does not immediately pass on the new desired location to the window manager; it defers this action until all other outstanding work has been completed, -using the \fBTk_DoWhenIdle\fR mechanism. +using the \fBTcl_DoWhenIdle\fR mechanism. .SH KEYWORDS position, top-level window, window manager diff --git a/doc/NameOfImg.3 b/doc/NameOfImg.3 index 78332db..8c191ce 100644 --- a/doc/NameOfImg.3 +++ b/doc/NameOfImg.3 @@ -3,7 +3,7 @@ '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH Tk_NameOfImage 3 4.0 Tk "Tk Library Procedures" .so man.macros .BS @@ -14,10 +14,10 @@ \fB#include \fR .sp const char * -\fBTk_NameOfImage\fR(\fItypePtr\fR) +\fBTk_NameOfImage\fR(\fIimageMaster\fR) .SH ARGUMENTS -.AS Tk_ImageMaster *masterPtr -.AP Tk_ImageMaster *masterPtr in +.AS Tk_ImageMaster imageMaster +.AP Tk_ImageMaster imageMaster in Token for image, which was passed to image manager's \fIcreateProc\fR when the image was created. .BE diff --git a/doc/ParseArgv.3 b/doc/ParseArgv.3 index 3a9bd49..7749d92 100644 --- a/doc/ParseArgv.3 +++ b/doc/ParseArgv.3 @@ -314,14 +314,14 @@ Tk_ArgvInfo argTable[] = { {"\-X", TK_ARGV_CONSTANT, (char *) 1, (char *) &debugFlag, "Turn on debugging printfs"}, - {"\-N", TK_ARGV_INT, (char *) NULL, (char *) &numReps, + {"\-N", TK_ARGV_INT, NULL, (char *) &numReps, "Number of repetitions"}, - {"\-of", TK_ARGV_STRING, (char *) NULL, (char *) &fileName, + {"\-of", TK_ARGV_STRING, NULL, (char *) &fileName, "Name of file for output"}, - {"x", TK_ARGV_REST, (char *) NULL, (char *) &exec, + {"x", TK_ARGV_REST, NULL, (char *) &exec, "File to exec, followed by any arguments (must be last argument)."}, - {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL, - (char *) NULL} + {NULL, TK_ARGV_END, NULL, NULL, + NULL} }; main(argc, argv) diff --git a/doc/RestrictEv.3 b/doc/RestrictEv.3 index eb1f040..22014a7 100644 --- a/doc/RestrictEv.3 +++ b/doc/RestrictEv.3 @@ -30,7 +30,7 @@ .PP This procedure is useful in certain situations where applications are only prepared to receive certain X events. After -\fBTk_RestrictEvents\fR is called, \fBTk_DoOneEvent\fR (and +\fBTk_RestrictEvents\fR is called, \fBTcl_DoOneEvent\fR (and hence \fBTk_MainLoop\fR) will filter X input events through \fIproc\fR. \fIProc\fR indicates whether a given event is to be processed immediately, deferred until some @@ -48,7 +48,7 @@ information it needs to filter events. The \fIeventPtr\fR points to an event under consideration. \fIProc\fR returns a restrict action (enumerated type \fBTk_RestrictAction\fR) that indicates what -\fBTk_DoOneEvent\fR should do with the event. If the return value is +\fBTcl_DoOneEvent\fR should do with the event. If the return value is \fBTK_PROCESS_EVENT\fR, then the event will be handled immediately. If the return value is \fBTK_DEFER_EVENT\fR, then the event will be left on the event queue for later processing. If the return value is @@ -74,6 +74,6 @@ \fBXWindowEvent\fR, but these procedures cannot be used because Tk keeps its own event queue that is separate from the X event queue. Instead, call \fBTk_RestrictEvents\fR to set up a filter, -then call \fBTk_DoOneEvent\fR to retrieve the desired event(s). +then call \fBTcl_DoOneEvent\fR to retrieve the desired event(s). .SH KEYWORDS delay, event, filter, restriction diff --git a/doc/SetClassProcs.3 b/doc/SetClassProcs.3 index 58618da..99eb81c 100644 --- a/doc/SetClassProcs.3 +++ b/doc/SetClassProcs.3 @@ -56,7 +56,7 @@ will be identical to the \fIinstanceData\fR parameter passed to \fBTk_SetClassProcs\fR. .PP -\fIcreateProc\fR is used to create platform-dependant windows. It is +\fIcreateProc\fR is used to create platform-dependent windows. It is invoked by \fBTk_MakeWindowExist\fR. \fIcreateProc\fR should have arguments and results that match the type \fBTk_ClassCreateProc\fR: .CS diff --git a/doc/bind.n b/doc/bind.n index c260bce..1ecae86 100644 --- a/doc/bind.n +++ b/doc/bind.n @@ -5,7 +5,7 @@ '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -'\" +'\" .TH bind n 8.0 Tk "Tk Built-In Commands" .so man.macros .BS @@ -566,8 +566,8 @@ If a virtual-root window manager is being used then the substituted values are the corresponding x-coordinate and y-coordinate in the virtual root. Valid only for -\fBButtonPress\fR, \fBButtonRelease\fR, \fBKeyPress\fR, \fBKeyRelease\fR, -and \fBMotion\fR events. +\fBButtonPress\fR, \fBButtonRelease\fR, \fBEnter\fR, \fBKeyPress\fR, +\fBKeyRelease\fR, \fBLeave\fR and \fBMotion\fR events. Same meaning as \fB%x\fR and \fB%y\fR, except relative to the (virtual) root window. .LP @@ -638,11 +638,11 @@ .IP (c) if the modifiers specified in one pattern are a subset of the modifiers in another pattern, then the pattern with more modifiers -is more specific. +is more specific; .IP (d) a virtual event whose physical pattern matches the sequence is less specific than the same physical pattern that is not associated with a -virtual event. +virtual event; .IP (e) given a sequence that matches two or more virtual events, one of the virtual events will be chosen, but the order is undefined. diff --git a/doc/canvas.n b/doc/canvas.n index 5b65283..7dbfd19 100644 --- a/doc/canvas.n +++ b/doc/canvas.n @@ -1219,10 +1219,10 @@ Specifies the color to be used to fill item's area. in its normal, active, and disabled states, \fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR. -If \fIcolor\fR is an empty string (the default), -then the item will not be filled. For the line item, it specifies the color of the line drawn. For the text item, it specifies the foreground color of the text. +If \fIcolor\fR is an empty string (the default for all canvas items +except line and text), then the item will not be filled. .TP \fB\-outline \fIcolor\fR .TP @@ -1233,8 +1233,8 @@ This option specifies the color that should be used to draw the outline of the item in its normal, active and disabled states. \fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR. -This option defaults to \fBblack\fR. If \fIcolor\fR is specified -as an empty string then no outline is drawn for the item. +If \fIcolor\fR is specified as an empty string then no outline is drawn +for the item. .TP \fB\-offset \fIoffset\fR . @@ -1442,8 +1442,7 @@ Specifies the color to use for each of the bitmap's .QW 1 valued pixels in its normal, active and disabled states. -\fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR and -defaults to \fBblack\fR. +\fIColor\fR may have any of the forms accepted by \fBTk_GetColor\fR. .SS "IMAGE ITEMS" .PP Items of type \fBimage\fR are used to display images on a diff --git a/doc/colors.n b/doc/colors.n index dc7007b..7a7b5b3 100644 --- a/doc/colors.n +++ b/doc/colors.n @@ -784,9 +784,10 @@ .TP \fBMac OS X\fR . -On Mac OS X, the following additional system colors are available -(note that the actual color values depend on the currently active OS theme, -and typically many of these will in fact be patterns rather than pure colors): +On macOS, the following additional system colors are available. +This first group contains all colors available in the HIToolbox library. +(Note that in some cases the actual color values may depend on the +current Appearance.) .RS .DS systemActiveAreaFill @@ -900,6 +901,7 @@ systemScrollBarDelimiterInactive systemSecondaryGroupBoxBackground systemSecondaryHighlightColor +systemSelectedTabTextColor systemSheetBackground systemSheetBackgroundOpaque systemSheetBackgroundTransparent @@ -925,7 +927,40 @@ systemWindowHeaderInactiveText .DE .RE +. +The second group of MacOS colors below are based on Apple's "semantic" +NScolors. On OSX 10.14 (Mojave) and later these colors change value +when Dark Mode is enabled. However, the change is only observable +when the Apple window manager is drawing to the screen. So the +\fBwinfo rgb\fR command will return the color coordinates used in the +standard Aqua mode, even if Dark Mode has been selected in the system +preferences. The numbered systemWindowBackgroundColors are used in +the \fBttk::notebook\fR and \fBttk::labelframe\fR widgets to provide a +contrasting background. Each numbered color constrasts with its +predecessor. +.RS +.DS +systemControlAccentColor +systemControlTextColor +systemDisabledControlTextColor +systemLabelColor +systemSelectedTextBackgroundColor +systemSelectedTextColor +systemTextBackgroundColor +systemTextColor +systemWindowBackgroundColor +systemWindowBackgroundColor1 +systemWindowBackgroundColor2 +systemWindowBackgroundColor3 +systemWindowBackgroundColor4 +systemWindowBackgroundColor5 +systemWindowBackgroundColor6 +systemWindowBackgroundColor7 +.DE +.RE .TP + + \fBWindows\fR . On Windows, the following additional system colors are available diff --git a/doc/event.n b/doc/event.n index 5109794..9ab48e5 100644 --- a/doc/event.n +++ b/doc/event.n @@ -239,7 +239,8 @@ .TP \fB\-time\fI integer\fR \fIInteger\fR must be an integer value; it specifies the \fItime\fR field -for the event. +for the event. Additonally the special value \fBcurrent\fR is allowed, +this value will be substituted by the current event time. Valid for \fBKeyPress\fR, \fBKeyRelease\fR, \fBButtonPress\fR, \fBButtonRelease\fR, \fBEnter\fR, \fBLeave\fR, \fBMotion\fR, and \fBProperty\fR events. diff --git a/doc/frame.n b/doc/frame.n index 72a22db..f2fbd96 100644 --- a/doc/frame.n +++ b/doc/frame.n @@ -99,21 +99,25 @@ name is the same as the path name of the frame's window. This command may be used to invoke various operations on the widget. It has the following general form: +.PP .CS \fIpathName option \fR?\fIarg arg ...\fR? .CE +.PP \fIPathName\fR is the name of the command, which is the same as the frame widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact behavior of the command. The following commands are possible for frame widgets: .TP \fIpathName \fBcget\fR \fIoption\fR +. Returns the current value of the configuration option given by \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBframe\fR command. .TP \fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR? +. Query or modify the configuration options of the widget. If no \fIoption\fR is specified, returns a list describing all of the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for diff --git a/doc/grab.n b/doc/grab.n index a6d0d19..c45e26a 100644 --- a/doc/grab.n +++ b/doc/grab.n @@ -60,6 +60,16 @@ The \fBfocus\fR command is still used to determine which window in the application receives the keyboard events. The keyboard grab is released when the grab is released. +.PP +On macOS a global grab affects all windows created by one Tk process. +No window in that process other than the grab window can even be +focused, hence no other window receives key or mouse events. A local +grab on macOS affects all windows created by one Tcl interpreter. It +is possible to focus any window belonging to the Tk process during a +local grab but the grab window is the only window created by its +interpreter which receives key or mouse events. Windows belonging to the +same process but created by different interpreters continue to receive +key and mouse events normally. .PP Grabs apply to particular displays. If an application has windows on multiple displays then it can establish a separate grab on each diff --git a/doc/grid.n b/doc/grid.n index c558071..eb658e7 100644 --- a/doc/grid.n +++ b/doc/grid.n @@ -441,7 +441,7 @@ .PP .CS button .b \-text "Foo" -entry .e \-variable foo +entry .e \-textvariable foo ; set foo "Hello World!" label .l \-text "This is a fairly long piece of text" \fBgrid\fR .b .e .l \-sticky ew diff --git a/doc/keysyms.n b/doc/keysyms.n index 512c1a6..d5822a6 100644 --- a/doc/keysyms.n +++ b/doc/keysyms.n @@ -18,908 +18,941 @@ be valid on all platforms, and some keysyms are also available on platforms that have a different native name for that key. For example, on Unix systems, the presence -of a particular keysym is dependant on the configuration of the +of a particular keysym is dependent on the configuration of the keyboard modifier map. This list shows keysyms along with their decimal and hexadecimal values. .PP .CS -space 32 0x0020 -exclam 33 0x0021 -quotedbl 34 0x0022 -numbersign 35 0x0023 -dollar 36 0x0024 -percent 37 0x0025 -ampersand 38 0x0026 -quoteright 39 0x0027 -parenleft 40 0x0028 -parenright 41 0x0029 -asterisk 42 0x002a -plus 43 0x002b -comma 44 0x002c -minus 45 0x002d -period 46 0x002e -slash 47 0x002f -0 48 0x0030 -1 49 0x0031 -2 50 0x0032 -3 51 0x0033 -4 52 0x0034 -5 53 0x0035 -6 54 0x0036 -7 55 0x0037 -8 56 0x0038 -9 57 0x0039 -colon 58 0x003a -semicolon 59 0x003b -less 60 0x003c -equal 61 0x003d -greater 62 0x003e -question 63 0x003f -at 64 0x0040 -A 65 0x0041 -B 66 0x0042 -C 67 0x0043 -D 68 0x0044 -E 69 0x0045 -F 70 0x0046 -G 71 0x0047 -H 72 0x0048 -I 73 0x0049 -J 74 0x004a -K 75 0x004b -L 76 0x004c -M 77 0x004d -N 78 0x004e -O 79 0x004f -P 80 0x0050 -Q 81 0x0051 -R 82 0x0052 -S 83 0x0053 -T 84 0x0054 -U 85 0x0055 -V 86 0x0056 -W 87 0x0057 -X 88 0x0058 -Y 89 0x0059 -Z 90 0x005a -bracketleft 91 0x005b -backslash 92 0x005c -bracketright 93 0x005d -asciicircum 94 0x005e -underscore 95 0x005f -quoteleft 96 0x0060 -a 97 0x0061 -b 98 0x0062 -c 99 0x0063 -d 100 0x0064 -e 101 0x0065 -f 102 0x0066 -g 103 0x0067 -h 104 0x0068 -i 105 0x0069 -j 106 0x006a -k 107 0x006b -l 108 0x006c -m 109 0x006d -n 110 0x006e -o 111 0x006f -p 112 0x0070 -q 113 0x0071 -r 114 0x0072 -s 115 0x0073 -t 116 0x0074 -u 117 0x0075 -v 118 0x0076 -w 119 0x0077 -x 120 0x0078 -y 121 0x0079 -z 122 0x007a -braceleft 123 0x007b -bar 124 0x007c -braceright 125 0x007d -asciitilde 126 0x007e -nobreakspace 160 0x00a0 -exclamdown 161 0x00a1 -cent 162 0x00a2 -sterling 163 0x00a3 -currency 164 0x00a4 -yen 165 0x00a5 -brokenbar 166 0x00a6 -section 167 0x00a7 -diaeresis 168 0x00a8 -copyright 169 0x00a9 -ordfeminine 170 0x00aa -guillemotleft 171 0x00ab -notsign 172 0x00ac -hyphen 173 0x00ad -registered 174 0x00ae -macron 175 0x00af -degree 176 0x00b0 -plusminus 177 0x00b1 -twosuperior 178 0x00b2 -threesuperior 179 0x00b3 -acute 180 0x00b4 -mu 181 0x00b5 -paragraph 182 0x00b6 -periodcentered 183 0x00b7 -cedilla 184 0x00b8 -onesuperior 185 0x00b9 -masculine 186 0x00ba -guillemotright 187 0x00bb -onequarter 188 0x00bc -onehalf 189 0x00bd -threequarters 190 0x00be -questiondown 191 0x00bf -Agrave 192 0x00c0 -Aacute 193 0x00c1 -Acircumflex 194 0x00c2 -Atilde 195 0x00c3 -Adiaeresis 196 0x00c4 -Aring 197 0x00c5 -AE 198 0x00c6 -Ccedilla 199 0x00c7 -Egrave 200 0x00c8 -Eacute 201 0x00c9 -Ecircumflex 202 0x00ca -Ediaeresis 203 0x00cb -Igrave 204 0x00cc -Iacute 205 0x00cd -Icircumflex 206 0x00ce -Idiaeresis 207 0x00cf -Eth 208 0x00d0 -Ntilde 209 0x00d1 -Ograve 210 0x00d2 -Oacute 211 0x00d3 -Ocircumflex 212 0x00d4 -Otilde 213 0x00d5 -Odiaeresis 214 0x00d6 -multiply 215 0x00d7 -Ooblique 216 0x00d8 -Ugrave 217 0x00d9 -Uacute 218 0x00da -Ucircumflex 219 0x00db -Udiaeresis 220 0x00dc -Yacute 221 0x00dd -Thorn 222 0x00de -ssharp 223 0x00df -agrave 224 0x00e0 -aacute 225 0x00e1 -acircumflex 226 0x00e2 -atilde 227 0x00e3 -adiaeresis 228 0x00e4 -aring 229 0x00e5 -ae 230 0x00e6 -ccedilla 231 0x00e7 -egrave 232 0x00e8 -eacute 233 0x00e9 -ecircumflex 234 0x00ea -ediaeresis 235 0x00eb -igrave 236 0x00ec -iacute 237 0x00ed -icircumflex 238 0x00ee -idiaeresis 239 0x00ef -eth 240 0x00f0 -ntilde 241 0x00f1 -ograve 242 0x00f2 -oacute 243 0x00f3 -ocircumflex 244 0x00f4 -otilde 245 0x00f5 -odiaeresis 246 0x00f6 -division 247 0x00f7 -oslash 248 0x00f8 -ugrave 249 0x00f9 -uacute 250 0x00fa -ucircumflex 251 0x00fb -udiaeresis 252 0x00fc -yacute 253 0x00fd -thorn 254 0x00fe -ydiaeresis 255 0x00ff -Aogonek 417 0x01a1 -breve 418 0x01a2 -Lstroke 419 0x01a3 -Lcaron 421 0x01a5 -Sacute 422 0x01a6 -Scaron 425 0x01a9 -Scedilla 426 0x01aa -Tcaron 427 0x01ab -Zacute 428 0x01ac +space 32 0x20 +exclam 33 0x21 +quotedbl 34 0x22 +numbersign 35 0x23 +dollar 36 0x24 +percent 37 0x25 +ampersand 38 0x26 +apostrophe 39 0x27 +parenleft 40 0x28 +parenright 41 0x29 +asterisk 42 0x2A +plus 43 0x2B +comma 44 0x2C +minus 45 0x2D +period 46 0x2E +slash 47 0x2F +0 48 0x30 +1 49 0x31 +2 50 0x32 +3 51 0x33 +4 52 0x34 +5 53 0x35 +6 54 0x36 +7 55 0x37 +8 56 0x38 +9 57 0x39 +colon 58 0x3A +semicolon 59 0x3B +less 60 0x3C +equal 61 0x3D +greater 62 0x3E +question 63 0x3F +at 64 0x40 +A 65 0x41 +B 66 0x42 +C 67 0x43 +D 68 0x44 +E 69 0x45 +F 70 0x46 +G 71 0x47 +H 72 0x48 +I 73 0x49 +J 74 0x4A +K 75 0x4B +L 76 0x4C +M 77 0x4D +N 78 0x4E +O 79 0x4F +P 80 0x50 +Q 81 0x51 +R 82 0x52 +S 83 0x53 +T 84 0x54 +U 85 0x55 +V 86 0x56 +W 87 0x57 +X 88 0x58 +Y 89 0x59 +Z 90 0x5A +bracketleft 91 0x5B +backslash 92 0x5C +bracketright 93 0x5D +asciicircum 94 0x5E +underscore 95 0x5F +grave 96 0x60 +a 97 0x61 +b 98 0x62 +c 99 0x63 +d 100 0x64 +e 101 0x65 +f 102 0x66 +g 103 0x67 +h 104 0x68 +i 105 0x69 +j 106 0x6A +k 107 0x6B +l 108 0x6C +m 109 0x6D +n 110 0x6E +o 111 0x6F +p 112 0x70 +q 113 0x71 +r 114 0x72 +s 115 0x73 +t 116 0x74 +u 117 0x75 +v 118 0x76 +w 119 0x77 +x 120 0x78 +y 121 0x79 +z 122 0x7A +braceleft 123 0x7B +bar 124 0x7C +braceright 125 0x7D +asciitilde 126 0x7E +nobreakspace 160 0xA0 +exclamdown 161 0xA1 +cent 162 0xA2 +sterling 163 0xA3 +currency 164 0xA4 +yen 165 0xA5 +brokenbar 166 0xA6 +section 167 0xA7 +diaeresis 168 0xA8 +copyright 169 0xA9 +ordfeminine 170 0xAA +guillemotleft 171 0xAB +notsign 172 0xAC +hyphen 173 0xAD +registered 174 0xAE +macron 175 0xAF +degree 176 0xB0 +plusminus 177 0xB1 +twosuperior 178 0xB2 +threesuperior 179 0xB3 +acute 180 0xB4 +mu 181 0xB5 +paragraph 182 0xB6 +periodcentered 183 0xB7 +cedilla 184 0xB8 +onesuperior 185 0xB9 +masculine 186 0xBA +guillemotright 187 0xBB +onequarter 188 0xBC +onehalf 189 0xBD +threequarters 190 0xBE +questiondown 191 0xBF +Agrave 192 0xC0 +Aacute 193 0xC1 +Acircumflex 194 0xC2 +Atilde 195 0xC3 +Adiaeresis 196 0xC4 +Aring 197 0xC5 +AE 198 0xC6 +Ccedilla 199 0xC7 +Egrave 200 0xC8 +Eacute 201 0xC9 +Ecircumflex 202 0xCA +Ediaeresis 203 0xCB +Igrave 204 0xCC +Iacute 205 0xCD +Icircumflex 206 0xCE +Idiaeresis 207 0xCF +ETH 208 0xD0 +Ntilde 209 0xD1 +Ograve 210 0xD2 +Oacute 211 0xD3 +Ocircumflex 212 0xD4 +Otilde 213 0xD5 +Odiaeresis 214 0xD6 +multiply 215 0xD7 +Oslash 216 0xD8 +Ugrave 217 0xD9 +Uacute 218 0xDA +Ucircumflex 219 0xDB +Udiaeresis 220 0xDC +Yacute 221 0xDD +THORN 222 0xDE +ssharp 223 0xDF +agrave 224 0xE0 +aacute 225 0xE1 +acircumflex 226 0xE2 +atilde 227 0xE3 +adiaeresis 228 0xE4 +aring 229 0xE5 +ae 230 0xE6 +ccedilla 231 0xE7 +egrave 232 0xE8 +eacute 233 0xE9 +ecircumflex 234 0xEA +ediaeresis 235 0xEB +igrave 236 0xEC +iacute 237 0xED +icircumflex 238 0xEE +idiaeresis 239 0xEF +eth 240 0xF0 +ntilde 241 0xF1 +ograve 242 0xF2 +oacute 243 0xF3 +ocircumflex 244 0xF4 +otilde 245 0xF5 +odiaeresis 246 0xF6 +division 247 0xF7 +oslash 248 0xF8 +ugrave 249 0xF9 +uacute 250 0xFA +ucircumflex 251 0xFB +udiaeresis 252 0xFC +yacute 253 0xFD +thorn 254 0xFE +ydiaeresis 255 0xFF +Aogonek 417 0x1A1 +breve 418 0x1A2 +Lstroke 419 0x1A3 +Lcaron 421 0x1A5 +Sacute 422 0x1A6 +Scaron 425 0x1A9 +Scedilla 426 0x1AA +Tcaron 427 0x1AB +Zacute 428 0x1AC .CE .CS -Zcaron 430 0x01ae -Zabovedot 431 0x01af -aogonek 433 0x01b1 -ogonek 434 0x01b2 -lstroke 435 0x01b3 -lcaron 437 0x01b5 -sacute 438 0x01b6 -caron 439 0x01b7 -scaron 441 0x01b9 -scedilla 442 0x01ba -tcaron 443 0x01bb -zacute 444 0x01bc -doubleacute 445 0x01bd -zcaron 446 0x01be -zabovedot 447 0x01bf -Racute 448 0x01c0 -Abreve 451 0x01c3 -Cacute 454 0x01c6 -Ccaron 456 0x01c8 -Eogonek 458 0x01ca -Ecaron 460 0x01cc -Dcaron 463 0x01cf -Nacute 465 0x01d1 -Ncaron 466 0x01d2 -Odoubleacute 469 0x01d5 -Rcaron 472 0x01d8 -Uring 473 0x01d9 -Udoubleacute 475 0x01db -Tcedilla 478 0x01de -racute 480 0x01e0 -abreve 483 0x01e3 -cacute 486 0x01e6 -ccaron 488 0x01e8 -eogonek 490 0x01ea -ecaron 492 0x01ec -dcaron 495 0x01ef -nacute 497 0x01f1 -ncaron 498 0x01f2 -odoubleacute 501 0x01f5 -rcaron 504 0x01f8 -uring 505 0x01f9 -udoubleacute 507 0x01fb -tcedilla 510 0x01fe -abovedot 511 0x01ff -Hstroke 673 0x02a1 -Hcircumflex 678 0x02a6 -Iabovedot 681 0x02a9 -Gbreve 683 0x02ab -Jcircumflex 684 0x02ac -hstroke 689 0x02b1 -hcircumflex 694 0x02b6 -idotless 697 0x02b9 -gbreve 699 0x02bb -jcircumflex 700 0x02bc -Cabovedot 709 0x02c5 -Ccircumflex 710 0x02c6 -Gabovedot 725 0x02d5 -Gcircumflex 728 0x02d8 -Ubreve 733 0x02dd -Scircumflex 734 0x02de -cabovedot 741 0x02e5 -ccircumflex 742 0x02e6 -gabovedot 757 0x02f5 -gcircumflex 760 0x02f8 -ubreve 765 0x02fd -scircumflex 766 0x02fe -kappa 930 0x03a2 -Rcedilla 931 0x03a3 -Itilde 933 0x03a5 -Lcedilla 934 0x03a6 -Emacron 938 0x03aa -Gcedilla 939 0x03ab -Tslash 940 0x03ac -rcedilla 947 0x03b3 -itilde 949 0x03b5 -lcedilla 950 0x03b6 -emacron 954 0x03ba -gacute 955 0x03bb -tslash 956 0x03bc -ENG 957 0x03bd -eng 959 0x03bf -Amacron 960 0x03c0 -Iogonek 967 0x03c7 -Eabovedot 972 0x03cc -Imacron 975 0x03cf -Ncedilla 977 0x03d1 -Omacron 978 0x03d2 -Kcedilla 979 0x03d3 -Uogonek 985 0x03d9 -Utilde 989 0x03dd -Umacron 990 0x03de -amacron 992 0x03e0 -iogonek 999 0x03e7 -eabovedot 1004 0x03ec -imacron 1007 0x03ef -ncedilla 1009 0x03f1 -omacron 1010 0x03f2 -kcedilla 1011 0x03f3 -uogonek 1017 0x03f9 -utilde 1021 0x03fd -umacron 1022 0x03fe -overline 1150 0x047e -kana_fullstop 1185 0x04a1 -kana_openingbracket 1186 0x04a2 -kana_closingbracket 1187 0x04a3 -kana_comma 1188 0x04a4 -kana_middledot 1189 0x04a5 -kana_WO 1190 0x04a6 -kana_a 1191 0x04a7 -kana_i 1192 0x04a8 -kana_u 1193 0x04a9 -kana_e 1194 0x04aa -kana_o 1195 0x04ab -kana_ya 1196 0x04ac -kana_yu 1197 0x04ad -kana_yo 1198 0x04ae -kana_tu 1199 0x04af -prolongedsound 1200 0x04b0 -kana_A 1201 0x04b1 -kana_I 1202 0x04b2 -kana_U 1203 0x04b3 -kana_E 1204 0x04b4 -kana_O 1205 0x04b5 -kana_KA 1206 0x04b6 -kana_KI 1207 0x04b7 -kana_KU 1208 0x04b8 -kana_KE 1209 0x04b9 -kana_KO 1210 0x04ba -kana_SA 1211 0x04bb -kana_SHI 1212 0x04bc -kana_SU 1213 0x04bd -kana_SE 1214 0x04be -kana_SO 1215 0x04bf -kana_TA 1216 0x04c0 -kana_TI 1217 0x04c1 -kana_TU 1218 0x04c2 -kana_TE 1219 0x04c3 -kana_TO 1220 0x04c4 -kana_NA 1221 0x04c5 -kana_NI 1222 0x04c6 -kana_NU 1223 0x04c7 -kana_NE 1224 0x04c8 -kana_NO 1225 0x04c9 -kana_HA 1226 0x04ca -kana_HI 1227 0x04cb -kana_HU 1228 0x04cc -kana_HE 1229 0x04cd -kana_HO 1230 0x04ce -kana_MA 1231 0x04cf -kana_MI 1232 0x04d0 -kana_MU 1233 0x04d1 -kana_ME 1234 0x04d2 -kana_MO 1235 0x04d3 -kana_YA 1236 0x04d4 -kana_YU 1237 0x04d5 -kana_YO 1238 0x04d6 -kana_RA 1239 0x04d7 -kana_RI 1240 0x04d8 -kana_RU 1241 0x04d9 -kana_RE 1242 0x04da -kana_RO 1243 0x04db -kana_WA 1244 0x04dc -kana_N 1245 0x04dd -voicedsound 1246 0x04de -semivoicedsound 1247 0x04df -Arabic_comma 1452 0x05ac -Arabic_semicolon 1467 0x05bb -Arabic_question_mark 1471 0x05bf -Arabic_hamza 1473 0x05c1 -Arabic_maddaonalef 1474 0x05c2 -Arabic_hamzaonalef 1475 0x05c3 -Arabic_hamzaonwaw 1476 0x05c4 -Arabic_hamzaunderalef 1477 0x05c5 -Arabic_hamzaonyeh 1478 0x05c6 -Arabic_alef 1479 0x05c7 -Arabic_beh 1480 0x05c8 -Arabic_tehmarbuta 1481 0x05c9 -Arabic_teh 1482 0x05ca -Arabic_theh 1483 0x05cb -Arabic_jeem 1484 0x05cc -Arabic_hah 1485 0x05cd -Arabic_khah 1486 0x05ce -Arabic_dal 1487 0x05cf -Arabic_thal 1488 0x05d0 -Arabic_ra 1489 0x05d1 -Arabic_zain 1490 0x05d2 -Arabic_seen 1491 0x05d3 -Arabic_sheen 1492 0x05d4 -Arabic_sad 1493 0x05d5 -Arabic_dad 1494 0x05d6 -Arabic_tah 1495 0x05d7 -Arabic_zah 1496 0x05d8 -Arabic_ain 1497 0x05d9 -Arabic_ghain 1498 0x05da -Arabic_tatweel 1504 0x05e0 -Arabic_feh 1505 0x05e1 -Arabic_qaf 1506 0x05e2 -Arabic_kaf 1507 0x05e3 -Arabic_lam 1508 0x05e4 -Arabic_meem 1509 0x05e5 +Zcaron 430 0x1AE +Zabovedot 431 0x1AF +aogonek 433 0x1B1 +ogonek 434 0x1B2 +lstroke 435 0x1B3 +lcaron 437 0x1B5 +sacute 438 0x1B6 +caron 439 0x1B7 +scaron 441 0x1B9 +scedilla 442 0x1BA +tcaron 443 0x1BB +zacute 444 0x1BC +doubleacute 445 0x1BD +zcaron 446 0x1BE +zabovedot 447 0x1BF +Racute 448 0x1C0 +Abreve 451 0x1C3 +Lacute 453 0x1C5 +Cacute 454 0x1C6 +Ccaron 456 0x1C8 +Eogonek 458 0x1CA +Ecaron 460 0x1CC +Dcaron 463 0x1CF +Dstroke 464 0x1D0 +Nacute 465 0x1D1 +Ncaron 466 0x1D2 +Odoubleacute 469 0x1D5 +Rcaron 472 0x1D8 +Uring 473 0x1D9 +Udoubleacute 475 0x1DB +Tcedilla 478 0x1DE +racute 480 0x1E0 +abreve 483 0x1E3 +lacute 485 0x1E5 +cacute 486 0x1E6 +ccaron 488 0x1E8 +eogonek 490 0x1EA +ecaron 492 0x1EC +dcaron 495 0x1EF +dstroke 496 0x1F0 +nacute 497 0x1F1 +ncaron 498 0x1F2 +odoubleacute 501 0x1F5 +rcaron 504 0x1F8 +uring 505 0x1F9 +udoubleacute 507 0x1FB +tcedilla 510 0x1FE +abovedot 511 0x1FF +Hstroke 673 0x2A1 +Hcircumflex 678 0x2A6 +Iabovedot 681 0x2A9 +Gbreve 683 0x2AB +Jcircumflex 684 0x2AC +hstroke 689 0x2B1 +hcircumflex 694 0x2B6 +idotless 697 0x2B9 +gbreve 699 0x2BB +jcircumflex 700 0x2BC +Cabovedot 709 0x2C5 +Ccircumflex 710 0x2C6 +Gabovedot 725 0x2D5 +Gcircumflex 728 0x2D8 +Ubreve 733 0x2DD +Scircumflex 734 0x2DE +cabovedot 741 0x2E5 +ccircumflex 742 0x2E6 +gabovedot 757 0x2F5 +gcircumflex 760 0x2F8 +ubreve 765 0x2FD +scircumflex 766 0x2FE +kra 930 0x3A2 +Rcedilla 931 0x3A3 +Itilde 933 0x3A5 +Lcedilla 934 0x3A6 +Emacron 938 0x3AA +Gcedilla 939 0x3AB +Tslash 940 0x3AC +rcedilla 947 0x3B3 +itilde 949 0x3B5 +lcedilla 950 0x3B6 +emacron 954 0x3BA +gcedilla 955 0x3BB +tslash 956 0x3BC +ENG 957 0x3BD +eng 959 0x3BF +Amacron 960 0x3C0 +Iogonek 967 0x3C7 +Eabovedot 972 0x3CC +Imacron 975 0x3CF +Ncedilla 977 0x3D1 +Omacron 978 0x3D2 +Kcedilla 979 0x3D3 +Uogonek 985 0x3D9 +Utilde 989 0x3DD +Umacron 990 0x3DE +amacron 992 0x3E0 +iogonek 999 0x3E7 +eabovedot 1004 0x3EC +imacron 1007 0x3EF +ncedilla 1009 0x3F1 +omacron 1010 0x3F2 +kcedilla 1011 0x3F3 +uogonek 1017 0x3F9 +utilde 1021 0x3FD +umacron 1022 0x3FE +overline 1150 0x47E +kana_fullstop 1185 0x4A1 +kana_openingbracket 1186 0x4A2 +kana_closingbracket 1187 0x4A3 +kana_comma 1188 0x4A4 +kana_conjunctive 1189 0x4A5 +kana_WO 1190 0x4A6 +kana_a 1191 0x4A7 +kana_i 1192 0x4A8 +kana_u 1193 0x4A9 +kana_e 1194 0x4AA +kana_o 1195 0x4AB +kana_ya 1196 0x4AC +kana_yu 1197 0x4AD +kana_yo 1198 0x4AE +kana_tsu 1199 0x4AF +prolongedsound 1200 0x4B0 +kana_A 1201 0x4B1 +kana_I 1202 0x4B2 +kana_U 1203 0x4B3 +kana_E 1204 0x4B4 +kana_O 1205 0x4B5 +kana_KA 1206 0x4B6 +kana_KI 1207 0x4B7 +kana_KU 1208 0x4B8 +kana_KE 1209 0x4B9 +kana_KO 1210 0x4BA +kana_SA 1211 0x4BB +kana_SHI 1212 0x4BC +kana_SU 1213 0x4BD +kana_SE 1214 0x4BE +kana_SO 1215 0x4BF +kana_TA 1216 0x4C0 +kana_CHI 1217 0x4C1 +kana_TSU 1218 0x4C2 +kana_TE 1219 0x4C3 +kana_TO 1220 0x4C4 +kana_NA 1221 0x4C5 +kana_NI 1222 0x4C6 +kana_NU 1223 0x4C7 +kana_NE 1224 0x4C8 +kana_NO 1225 0x4C9 +kana_HA 1226 0x4CA +kana_HI 1227 0x4CB +kana_FU 1228 0x4CC +kana_HE 1229 0x4CD +kana_HO 1230 0x4CE +kana_MA 1231 0x4CF +kana_MI 1232 0x4D0 +kana_MU 1233 0x4D1 +kana_ME 1234 0x4D2 +kana_MO 1235 0x4D3 +kana_YA 1236 0x4D4 +kana_YU 1237 0x4D5 +kana_YO 1238 0x4D6 +kana_RA 1239 0x4D7 +kana_RI 1240 0x4D8 +kana_RU 1241 0x4D9 +kana_RE 1242 0x4DA +kana_RO 1243 0x4DB +kana_WA 1244 0x4DC +kana_N 1245 0x4DD +voicedsound 1246 0x4DE +semivoicedsound 1247 0x4DF +Arabic_comma 1452 0x5AC +Arabic_semicolon 1467 0x5BB +Arabic_question_mark 1471 0x5BF +Arabic_hamza 1473 0x5C1 +Arabic_maddaonalef 1474 0x5C2 +Arabic_hamzaonalef 1475 0x5C3 +Arabic_hamzaonwaw 1476 0x5C4 +Arabic_hamzaunderalef 1477 0x5C5 +Arabic_hamzaonyeh 1478 0x5C6 +Arabic_alef 1479 0x5C7 +Arabic_beh 1480 0x5C8 +Arabic_tehmarbuta 1481 0x5C9 +Arabic_teh 1482 0x5CA +Arabic_theh 1483 0x5CB +Arabic_jeem 1484 0x5CC +Arabic_hah 1485 0x5CD +Arabic_khah 1486 0x5CE +Arabic_dal 1487 0x5CF +Arabic_thal 1488 0x5D0 +Arabic_ra 1489 0x5D1 +Arabic_zain 1490 0x5D2 +Arabic_seen 1491 0x5D3 +Arabic_sheen 1492 0x5D4 +Arabic_sad 1493 0x5D5 +Arabic_dad 1494 0x5D6 +Arabic_tah 1495 0x5D7 +Arabic_zah 1496 0x5D8 +Arabic_ain 1497 0x5D9 +Arabic_ghain 1498 0x5DA +Arabic_tatweel 1504 0x5E0 +Arabic_feh 1505 0x5E1 +Arabic_qaf 1506 0x5E2 +Arabic_kaf 1507 0x5E3 +Arabic_lam 1508 0x5E4 +Arabic_meem 1509 0x5E5 .CE .CS -Arabic_noon 1510 0x05e6 -Arabic_heh 1511 0x05e7 -Arabic_waw 1512 0x05e8 -Arabic_alefmaksura 1513 0x05e9 -Arabic_yeh 1514 0x05ea -Arabic_fathatan 1515 0x05eb -Arabic_dammatan 1516 0x05ec -Arabic_kasratan 1517 0x05ed -Arabic_fatha 1518 0x05ee -Arabic_damma 1519 0x05ef -Arabic_kasra 1520 0x05f0 -Arabic_shadda 1521 0x05f1 -Arabic_sukun 1522 0x05f2 -Serbian_dje 1697 0x06a1 -Macedonia_gje 1698 0x06a2 -Cyrillic_io 1699 0x06a3 -Ukranian_je 1700 0x06a4 -Macedonia_dse 1701 0x06a5 -Ukranian_i 1702 0x06a6 -Ukranian_yi 1703 0x06a7 -Serbian_je 1704 0x06a8 -Serbian_lje 1705 0x06a9 -Serbian_nje 1706 0x06aa -Serbian_tshe 1707 0x06ab -Macedonia_kje 1708 0x06ac -Byelorussian_shortu 1710 0x06ae -Serbian_dze 1711 0x06af -numerosign 1712 0x06b0 -Serbian_DJE 1713 0x06b1 -Macedonia_GJE 1714 0x06b2 -Cyrillic_IO 1715 0x06b3 -Ukranian_JE 1716 0x06b4 -Macedonia_DSE 1717 0x06b5 -Ukranian_I 1718 0x06b6 -Ukranian_YI 1719 0x06b7 -Serbian_JE 1720 0x06b8 -Serbian_LJE 1721 0x06b9 -Serbian_NJE 1722 0x06ba -Serbian_TSHE 1723 0x06bb -Macedonia_KJE 1724 0x06bc -Byelorussian_SHORTU 1726 0x06be -Serbian_DZE 1727 0x06bf -Cyrillic_yu 1728 0x06c0 -Cyrillic_a 1729 0x06c1 -Cyrillic_be 1730 0x06c2 -Cyrillic_tse 1731 0x06c3 -Cyrillic_de 1732 0x06c4 -Cyrillic_ie 1733 0x06c5 -Cyrillic_ef 1734 0x06c6 -Cyrillic_ghe 1735 0x06c7 -Cyrillic_ha 1736 0x06c8 -Cyrillic_i 1737 0x06c9 -Cyrillic_shorti 1738 0x06ca -Cyrillic_ka 1739 0x06cb -Cyrillic_el 1740 0x06cc -Cyrillic_em 1741 0x06cd -Cyrillic_en 1742 0x06ce -Cyrillic_o 1743 0x06cf -Cyrillic_pe 1744 0x06d0 -Cyrillic_ya 1745 0x06d1 -Cyrillic_er 1746 0x06d2 -Cyrillic_es 1747 0x06d3 -Cyrillic_te 1748 0x06d4 -Cyrillic_u 1749 0x06d5 -Cyrillic_zhe 1750 0x06d6 -Cyrillic_ve 1751 0x06d7 -Cyrillic_softsign 1752 0x06d8 -Cyrillic_yeru 1753 0x06d9 -Cyrillic_ze 1754 0x06da -Cyrillic_sha 1755 0x06db -Cyrillic_e 1756 0x06dc -Cyrillic_shcha 1757 0x06dd -Cyrillic_che 1758 0x06de -Cyrillic_hardsign 1759 0x06df -Cyrillic_YU 1760 0x06e0 -Cyrillic_A 1761 0x06e1 -Cyrillic_BE 1762 0x06e2 -Cyrillic_TSE 1763 0x06e3 -Cyrillic_DE 1764 0x06e4 -Cyrillic_IE 1765 0x06e5 -Cyrillic_EF 1766 0x06e6 -Cyrillic_GHE 1767 0x06e7 -Cyrillic_HA 1768 0x06e8 -Cyrillic_I 1769 0x06e9 -Cyrillic_SHORTI 1770 0x06ea -Cyrillic_KA 1771 0x06eb -Cyrillic_EL 1772 0x06ec -Cyrillic_EM 1773 0x06ed -Cyrillic_EN 1774 0x06ee -Cyrillic_O 1775 0x06ef -Cyrillic_PE 1776 0x06f0 -Cyrillic_YA 1777 0x06f1 -Cyrillic_ER 1778 0x06f2 -Cyrillic_ES 1779 0x06f3 -Cyrillic_TE 1780 0x06f4 -Cyrillic_U 1781 0x06f5 -Cyrillic_ZHE 1782 0x06f6 -Cyrillic_VE 1783 0x06f7 -Cyrillic_SOFTSIGN 1784 0x06f8 -Cyrillic_YERU 1785 0x06f9 -Cyrillic_ZE 1786 0x06fa -Cyrillic_SHA 1787 0x06fb -Cyrillic_E 1788 0x06fc -Cyrillic_SHCHA 1789 0x06fd -Cyrillic_CHE 1790 0x06fe -Cyrillic_HARDSIGN 1791 0x06ff -Greek_ALPHAaccent 1953 0x07a1 -Greek_EPSILONaccent 1954 0x07a2 -Greek_ETAaccent 1955 0x07a3 -Greek_IOTAaccent 1956 0x07a4 -Greek_IOTAdiaeresis 1957 0x07a5 -Greek_IOTAaccentdiaeresis 1958 0x07a6 -Greek_OMICRONaccent 1959 0x07a7 -Greek_UPSILONaccent 1960 0x07a8 -Greek_UPSILONdieresis 1961 0x07a9 -Greek_UPSILONaccentdieresis 1962 0x07aa -Greek_OMEGAaccent 1963 0x07ab -Greek_alphaaccent 1969 0x07b1 -Greek_epsilonaccent 1970 0x07b2 -Greek_etaaccent 1971 0x07b3 -Greek_iotaaccent 1972 0x07b4 -Greek_iotadieresis 1973 0x07b5 -Greek_iotaaccentdieresis 1974 0x07b6 -Greek_omicronaccent 1975 0x07b7 -Greek_upsilonaccent 1976 0x07b8 -Greek_upsilondieresis 1977 0x07b9 -Greek_upsilonaccentdieresis 1978 0x07ba -Greek_omegaaccent 1979 0x07bb -Greek_ALPHA 1985 0x07c1 -Greek_BETA 1986 0x07c2 -Greek_GAMMA 1987 0x07c3 -Greek_DELTA 1988 0x07c4 -Greek_EPSILON 1989 0x07c5 -Greek_ZETA 1990 0x07c6 -Greek_ETA 1991 0x07c7 -Greek_THETA 1992 0x07c8 -Greek_IOTA 1993 0x07c9 -Greek_KAPPA 1994 0x07ca -Greek_LAMBDA 1995 0x07cb -Greek_MU 1996 0x07cc -Greek_NU 1997 0x07cd -Greek_XI 1998 0x07ce -Greek_OMICRON 1999 0x07cf -Greek_PI 2000 0x07d0 -Greek_RHO 2001 0x07d1 -Greek_SIGMA 2002 0x07d2 -Greek_TAU 2004 0x07d4 -Greek_UPSILON 2005 0x07d5 -Greek_PHI 2006 0x07d6 -Greek_CHI 2007 0x07d7 -Greek_PSI 2008 0x07d8 -Greek_OMEGA 2009 0x07d9 -Greek_alpha 2017 0x07e1 -Greek_beta 2018 0x07e2 -Greek_gamma 2019 0x07e3 -Greek_delta 2020 0x07e4 -Greek_epsilon 2021 0x07e5 -Greek_zeta 2022 0x07e6 -Greek_eta 2023 0x07e7 -Greek_theta 2024 0x07e8 -Greek_iota 2025 0x07e9 -Greek_kappa 2026 0x07ea -Greek_lambda 2027 0x07eb -Greek_mu 2028 0x07ec -Greek_nu 2029 0x07ed -Greek_xi 2030 0x07ee -Greek_omicron 2031 0x07ef -Greek_pi 2032 0x07f0 -Greek_rho 2033 0x07f1 -Greek_sigma 2034 0x07f2 -Greek_finalsmallsigma 2035 0x07f3 -Greek_tau 2036 0x07f4 -Greek_upsilon 2037 0x07f5 -Greek_phi 2038 0x07f6 -Greek_chi 2039 0x07f7 -Greek_psi 2040 0x07f8 -Greek_omega 2041 0x07f9 -leftradical 2209 0x08a1 -topleftradical 2210 0x08a2 -horizconnector 2211 0x08a3 -topintegral 2212 0x08a4 -botintegral 2213 0x08a5 -vertconnector 2214 0x08a6 -topleftsqbracket 2215 0x08a7 -botleftsqbracket 2216 0x08a8 -toprightsqbracket 2217 0x08a9 -botrightsqbracket 2218 0x08aa -topleftparens 2219 0x08ab -botleftparens 2220 0x08ac -toprightparens 2221 0x08ad -botrightparens 2222 0x08ae -leftmiddlecurlybrace 2223 0x08af -rightmiddlecurlybrace 2224 0x08b0 -topleftsummation 2225 0x08b1 -botleftsummation 2226 0x08b2 -topvertsummationconnector 2227 0x08b3 -botvertsummationconnector 2228 0x08b4 -toprightsummation 2229 0x08b5 -botrightsummation 2230 0x08b6 -rightmiddlesummation 2231 0x08b7 +Arabic_noon 1510 0x5E6 +Arabic_ha 1511 0x5E7 +Arabic_waw 1512 0x5E8 +Arabic_alefmaksura 1513 0x5E9 +Arabic_yeh 1514 0x5EA +Arabic_fathatan 1515 0x5EB +Arabic_dammatan 1516 0x5EC +Arabic_kasratan 1517 0x5ED +Arabic_fatha 1518 0x5EE +Arabic_damma 1519 0x5EF +Arabic_kasra 1520 0x5F0 +Arabic_shadda 1521 0x5F1 +Arabic_sukun 1522 0x5F2 +Serbian_dje 1697 0x6A1 +Macedonia_gje 1698 0x6A2 +Cyrillic_io 1699 0x6A3 +Ukrainian_ie 1700 0x6A4 +Macedonia_dse 1701 0x6A5 +Ukrainian_i 1702 0x6A6 +Ukrainian_yi 1703 0x6A7 +Cyrillic_je 1704 0x6A8 +Cyrillic_lje 1705 0x6A9 +Cyrillic_nje 1706 0x6AA +Serbian_tshe 1707 0x6AB +Macedonia_kje 1708 0x6AC +Byelorussian_shortu 1710 0x6AE +Cyrillic_dzhe 1711 0x6AF +numerosign 1712 0x6B0 +Serbian_DJE 1713 0x6B1 +Macedonia_GJE 1714 0x6B2 +Cyrillic_IO 1715 0x6B3 +Ukrainian_IE 1716 0x6B4 +Macedonia_DSE 1717 0x6B5 +Ukrainian_I 1718 0x6B6 +Ukrainian_YI 1719 0x6B7 +Cyrillic_JE 1720 0x6B8 +Cyrillic_LJE 1721 0x6B9 +Cyrillic_NJE 1722 0x6BA +Serbian_TSHE 1723 0x6BB +Macedonia_KJE 1724 0x6BC +Byelorussian_SHORTU 1726 0x6BE +Cyrillic_DZHE 1727 0x6BF +Cyrillic_yu 1728 0x6C0 +Cyrillic_a 1729 0x6C1 +Cyrillic_be 1730 0x6C2 +Cyrillic_tse 1731 0x6C3 +Cyrillic_de 1732 0x6C4 +Cyrillic_ie 1733 0x6C5 +Cyrillic_ef 1734 0x6C6 +Cyrillic_ghe 1735 0x6C7 +Cyrillic_ha 1736 0x6C8 +Cyrillic_i 1737 0x6C9 +Cyrillic_shorti 1738 0x6CA +Cyrillic_ka 1739 0x6CB +Cyrillic_el 1740 0x6CC +Cyrillic_em 1741 0x6CD +Cyrillic_en 1742 0x6CE +Cyrillic_o 1743 0x6CF +Cyrillic_pe 1744 0x6D0 +Cyrillic_ya 1745 0x6D1 +Cyrillic_er 1746 0x6D2 +Cyrillic_es 1747 0x6D3 +Cyrillic_te 1748 0x6D4 +Cyrillic_u 1749 0x6D5 +Cyrillic_zhe 1750 0x6D6 +Cyrillic_ve 1751 0x6D7 +Cyrillic_softsign 1752 0x6D8 +Cyrillic_yeru 1753 0x6D9 +Cyrillic_ze 1754 0x6DA +Cyrillic_sha 1755 0x6DB +Cyrillic_e 1756 0x6DC +Cyrillic_shcha 1757 0x6DD +Cyrillic_che 1758 0x6DE +Cyrillic_hardsign 1759 0x6DF +Cyrillic_YU 1760 0x6E0 +Cyrillic_A 1761 0x6E1 +Cyrillic_BE 1762 0x6E2 +Cyrillic_TSE 1763 0x6E3 +Cyrillic_DE 1764 0x6E4 +Cyrillic_IE 1765 0x6E5 +Cyrillic_EF 1766 0x6E6 +Cyrillic_GHE 1767 0x6E7 +Cyrillic_HA 1768 0x6E8 +Cyrillic_I 1769 0x6E9 +Cyrillic_SHORTI 1770 0x6EA +Cyrillic_KA 1771 0x6EB +Cyrillic_EL 1772 0x6EC +Cyrillic_EM 1773 0x6ED +Cyrillic_EN 1774 0x6EE +Cyrillic_O 1775 0x6EF +Cyrillic_PE 1776 0x6F0 +Cyrillic_YA 1777 0x6F1 +Cyrillic_ER 1778 0x6F2 +Cyrillic_ES 1779 0x6F3 +Cyrillic_TE 1780 0x6F4 +Cyrillic_U 1781 0x6F5 +Cyrillic_ZHE 1782 0x6F6 +Cyrillic_VE 1783 0x6F7 +Cyrillic_SOFTSIGN 1784 0x6F8 +Cyrillic_YERU 1785 0x6F9 +Cyrillic_ZE 1786 0x6FA +Cyrillic_SHA 1787 0x6FB +Cyrillic_E 1788 0x6FC +Cyrillic_SHCHA 1789 0x6FD +Cyrillic_CHE 1790 0x6FE +Cyrillic_HARDSIGN 1791 0x6FF +Greek_ALPHAaccent 1953 0x7A1 +Greek_EPSILONaccent 1954 0x7A2 +Greek_ETAaccent 1955 0x7A3 +Greek_IOTAaccent 1956 0x7A4 +Greek_IOTAdieresis 1957 0x7A5 +Greek_IOTAaccentdiaeresis 1958 0x7A6 +Greek_OMICRONaccent 1959 0x7A7 +Greek_UPSILONaccent 1960 0x7A8 +Greek_UPSILONdieresis 1961 0x7A9 +Greek_UPSILONaccentdieresis 1962 0x7AA +Greek_OMEGAaccent 1963 0x7AB +Greek_accentdieresis 1966 0x7AE +Greek_horizbar 1967 0x7AF +Greek_alphaaccent 1969 0x7B1 +Greek_epsilonaccent 1970 0x7B2 +Greek_etaaccent 1971 0x7B3 +Greek_iotaaccent 1972 0x7B4 +Greek_iotadieresis 1973 0x7B5 +Greek_iotaaccentdieresis 1974 0x7B6 +Greek_omicronaccent 1975 0x7B7 +Greek_upsilonaccent 1976 0x7B8 +Greek_upsilondieresis 1977 0x7B9 +Greek_upsilonaccentdieresis 1978 0x7BA +Greek_omegaaccent 1979 0x7BB +Greek_ALPHA 1985 0x7C1 +Greek_BETA 1986 0x7C2 +Greek_GAMMA 1987 0x7C3 +Greek_DELTA 1988 0x7C4 +Greek_EPSILON 1989 0x7C5 +Greek_ZETA 1990 0x7C6 +Greek_ETA 1991 0x7C7 +Greek_THETA 1992 0x7C8 +Greek_IOTA 1993 0x7C9 +Greek_KAPPA 1994 0x7CA +Greek_LAMDA 1995 0x7CB +Greek_MU 1996 0x7CC +Greek_NU 1997 0x7CD +Greek_XI 1998 0x7CE +Greek_OMICRON 1999 0x7CF +Greek_PI 2000 0x7D0 +Greek_RHO 2001 0x7D1 +Greek_SIGMA 2002 0x7D2 +Greek_TAU 2004 0x7D4 +Greek_UPSILON 2005 0x7D5 +Greek_PHI 2006 0x7D6 +Greek_CHI 2007 0x7D7 +Greek_PSI 2008 0x7D8 +Greek_OMEGA 2009 0x7D9 +Greek_alpha 2017 0x7E1 +Greek_beta 2018 0x7E2 +Greek_gamma 2019 0x7E3 +Greek_delta 2020 0x7E4 +Greek_epsilon 2021 0x7E5 +Greek_zeta 2022 0x7E6 +Greek_eta 2023 0x7E7 +Greek_theta 2024 0x7E8 +Greek_iota 2025 0x7E9 +Greek_kappa 2026 0x7EA +Greek_lamda 2027 0x7EB +Greek_mu 2028 0x7EC +Greek_nu 2029 0x7ED +Greek_xi 2030 0x7EE +Greek_omicron 2031 0x7EF +Greek_pi 2032 0x7F0 +Greek_rho 2033 0x7F1 +Greek_sigma 2034 0x7F2 +Greek_finalsmallsigma 2035 0x7F3 +Greek_tau 2036 0x7F4 +Greek_upsilon 2037 0x7F5 +Greek_phi 2038 0x7F6 +Greek_chi 2039 0x7F7 +Greek_psi 2040 0x7F8 +Greek_omega 2041 0x7F9 +leftradical 2209 0x8A1 +topleftradical 2210 0x8A2 +horizconnector 2211 0x8A3 +topintegral 2212 0x8A4 +botintegral 2213 0x8A5 +vertconnector 2214 0x8A6 +topleftsqbracket 2215 0x8A7 +botleftsqbracket 2216 0x8A8 +toprightsqbracket 2217 0x8A9 +botrightsqbracket 2218 0x8AA +topleftparens 2219 0x8AB +botleftparens 2220 0x8AC +toprightparens 2221 0x8AD +botrightparens 2222 0x8AE +leftmiddlecurlybrace 2223 0x8AF +rightmiddlecurlybrace 2224 0x8B0 +topleftsummation 2225 0x8B1 +botleftsummation 2226 0x8B2 +topvertsummationconnector 2227 0x8B3 +botvertsummationconnector 2228 0x8B4 +toprightsummation 2229 0x8B5 +botrightsummation 2230 0x8B6 +rightmiddlesummation 2231 0x8B7 .CE .CS -lessthanequal 2236 0x08bc -notequal 2237 0x08bd -greaterthanequal 2238 0x08be -integral 2239 0x08bf -therefore 2240 0x08c0 -variation 2241 0x08c1 -infinity 2242 0x08c2 -nabla 2245 0x08c5 -approximate 2248 0x08c8 -similarequal 2249 0x08c9 -ifonlyif 2253 0x08cd -implies 2254 0x08ce -identical 2255 0x08cf -radical 2262 0x08d6 -includedin 2266 0x08da -includes 2267 0x08db -intersection 2268 0x08dc -union 2269 0x08dd -logicaland 2270 0x08de -logicalor 2271 0x08df -partialderivative 2287 0x08ef -function 2294 0x08f6 -leftarrow 2299 0x08fb -uparrow 2300 0x08fc -rightarrow 2301 0x08fd -downarrow 2302 0x08fe -blank 2527 0x09df -soliddiamond 2528 0x09e0 -checkerboard 2529 0x09e1 -ht 2530 0x09e2 -ff 2531 0x09e3 -cr 2532 0x09e4 -lf 2533 0x09e5 -nl 2536 0x09e8 -vt 2537 0x09e9 -lowrightcorner 2538 0x09ea -uprightcorner 2539 0x09eb -upleftcorner 2540 0x09ec -lowleftcorner 2541 0x09ed -crossinglines 2542 0x09ee -horizlinescan1 2543 0x09ef -horizlinescan3 2544 0x09f0 -horizlinescan5 2545 0x09f1 -horizlinescan7 2546 0x09f2 -horizlinescan9 2547 0x09f3 -leftt 2548 0x09f4 -rightt 2549 0x09f5 -bott 2550 0x09f6 -topt 2551 0x09f7 -vertbar 2552 0x09f8 -emspace 2721 0x0aa1 -enspace 2722 0x0aa2 -em3space 2723 0x0aa3 -em4space 2724 0x0aa4 -digitspace 2725 0x0aa5 -punctspace 2726 0x0aa6 -thinspace 2727 0x0aa7 -hairspace 2728 0x0aa8 -emdash 2729 0x0aa9 -endash 2730 0x0aaa -signifblank 2732 0x0aac -ellipsis 2734 0x0aae -doubbaselinedot 2735 0x0aaf -onethird 2736 0x0ab0 -twothirds 2737 0x0ab1 -onefifth 2738 0x0ab2 -twofifths 2739 0x0ab3 -threefifths 2740 0x0ab4 -fourfifths 2741 0x0ab5 -onesixth 2742 0x0ab6 -fivesixths 2743 0x0ab7 -careof 2744 0x0ab8 -figdash 2747 0x0abb -leftanglebracket 2748 0x0abc -decimalpoint 2749 0x0abd -rightanglebracket 2750 0x0abe -marker 2751 0x0abf -oneeighth 2755 0x0ac3 -threeeighths 2756 0x0ac4 -fiveeighths 2757 0x0ac5 -seveneighths 2758 0x0ac6 -trademark 2761 0x0ac9 -signaturemark 2762 0x0aca -trademarkincircle 2763 0x0acb -leftopentriangle 2764 0x0acc -rightopentriangle 2765 0x0acd -emopencircle 2766 0x0ace -emopenrectangle 2767 0x0acf -leftsinglequotemark 2768 0x0ad0 -rightsinglequotemark 2769 0x0ad1 -leftdoublequotemark 2770 0x0ad2 -rightdoublequotemark 2771 0x0ad3 -prescription 2772 0x0ad4 -minutes 2774 0x0ad6 -seconds 2775 0x0ad7 -latincross 2777 0x0ad9 -hexagram 2778 0x0ada -filledrectbullet 2779 0x0adb -filledlefttribullet 2780 0x0adc -filledrighttribullet 2781 0x0add -emfilledcircle 2782 0x0ade -emfilledrect 2783 0x0adf -enopencircbullet 2784 0x0ae0 -enopensquarebullet 2785 0x0ae1 -openrectbullet 2786 0x0ae2 -opentribulletup 2787 0x0ae3 -opentribulletdown 2788 0x0ae4 -openstar 2789 0x0ae5 -enfilledcircbullet 2790 0x0ae6 -enfilledsqbullet 2791 0x0ae7 -filledtribulletup 2792 0x0ae8 -filledtribulletdown 2793 0x0ae9 -leftpointer 2794 0x0aea -rightpointer 2795 0x0aeb -club 2796 0x0aec -diamond 2797 0x0aed -heart 2798 0x0aee -maltesecross 2800 0x0af0 -dagger 2801 0x0af1 -doubledagger 2802 0x0af2 -checkmark 2803 0x0af3 -ballotcross 2804 0x0af4 -musicalsharp 2805 0x0af5 -musicalflat 2806 0x0af6 -malesymbol 2807 0x0af7 -femalesymbol 2808 0x0af8 -telephone 2809 0x0af9 -telephonerecorder 2810 0x0afa -phonographcopyright 2811 0x0afb -caret 2812 0x0afc -singlelowquotemark 2813 0x0afd -doublelowquotemark 2814 0x0afe -cursor 2815 0x0aff -leftcaret 2979 0x0ba3 -rightcaret 2982 0x0ba6 -downcaret 2984 0x0ba8 -upcaret 2985 0x0ba9 -overbar 3008 0x0bc0 -downtack 3010 0x0bc2 -upshoe 3011 0x0bc3 -downstile 3012 0x0bc4 -underbar 3014 0x0bc6 -jot 3018 0x0bca -quad 3020 0x0bcc -uptack 3022 0x0bce -circle 3023 0x0bcf -upstile 3027 0x0bd3 -downshoe 3030 0x0bd6 -rightshoe 3032 0x0bd8 -leftshoe 3034 0x0bda -lefttack 3036 0x0bdc -righttack 3068 0x0bfc -hebrew_aleph 3296 0x0ce0 -hebrew_beth 3297 0x0ce1 -hebrew_gimmel 3298 0x0ce2 -hebrew_daleth 3299 0x0ce3 -hebrew_he 3300 0x0ce4 -hebrew_waw 3301 0x0ce5 -hebrew_zayin 3302 0x0ce6 -hebrew_het 3303 0x0ce7 -hebrew_teth 3304 0x0ce8 -hebrew_yod 3305 0x0ce9 -hebrew_finalkaph 3306 0x0cea -hebrew_kaph 3307 0x0ceb -hebrew_lamed 3308 0x0cec -hebrew_finalmem 3309 0x0ced -hebrew_mem 3310 0x0cee -hebrew_finalnun 3311 0x0cef -hebrew_nun 3312 0x0cf0 -hebrew_samekh 3313 0x0cf1 -hebrew_ayin 3314 0x0cf2 -hebrew_finalpe 3315 0x0cf3 -hebrew_pe 3316 0x0cf4 -hebrew_finalzadi 3317 0x0cf5 -hebrew_zadi 3318 0x0cf6 -hebrew_kuf 3319 0x0cf7 -hebrew_resh 3320 0x0cf8 -hebrew_shin 3321 0x0cf9 -hebrew_taf 3322 0x0cfa -BackSpace 65288 0xff08 -Tab 65289 0xff09 -Linefeed 65290 0xff0a -Clear 65291 0xff0b -Return 65293 0xff0d -Pause 65299 0xff13 -Scroll_Lock 65300 0xff14 -Sys_Req 65301 0xff15 -Escape 65307 0xff1b -Multi_key 65312 0xff20 -Kanji 65313 0xff21 -Home 65360 0xff50 -Left 65361 0xff51 -Up 65362 0xff52 -Right 65363 0xff53 -Down 65364 0xff54 -Prior 65365 0xff55 -Next 65366 0xff56 -End 65367 0xff57 -Begin 65368 0xff58 -Win_L 65371 0xff5b -Win_R 65372 0xff5c +lessthanequal 2236 0x8BC +notequal 2237 0x8BD +greaterthanequal 2238 0x8BE +integral 2239 0x8BF +therefore 2240 0x8C0 +variation 2241 0x8C1 +infinity 2242 0x8C2 +nabla 2245 0x8C5 +approximate 2248 0x8C8 +similarequal 2249 0x8C9 +ifonlyif 2253 0x8CD +implies 2254 0x8CE +identical 2255 0x8CF +radical 2262 0x8D6 +includedin 2266 0x8DA +includes 2267 0x8DB +intersection 2268 0x8DC +union 2269 0x8DD +logicaland 2270 0x8DE +logicalor 2271 0x8DF +partialderivative 2287 0x8EF +function 2294 0x8F6 +leftarrow 2299 0x8FB +uparrow 2300 0x8FC +rightarrow 2301 0x8FD +downarrow 2302 0x8FE +blank 2527 0x9DF +soliddiamond 2528 0x9E0 +checkerboard 2529 0x9E1 +ht 2530 0x9E2 +ff 2531 0x9E3 +cr 2532 0x9E4 +lf 2533 0x9E5 +nl 2536 0x9E8 +vt 2537 0x9E9 +lowrightcorner 2538 0x9EA +uprightcorner 2539 0x9EB +upleftcorner 2540 0x9EC +lowleftcorner 2541 0x9ED +crossinglines 2542 0x9EE +horizlinescan1 2543 0x9EF +horizlinescan3 2544 0x9F0 +horizlinescan5 2545 0x9F1 +horizlinescan7 2546 0x9F2 +horizlinescan9 2547 0x9F3 +leftt 2548 0x9F4 +rightt 2549 0x9F5 +bott 2550 0x9F6 +topt 2551 0x9F7 +vertbar 2552 0x9F8 +emspace 2721 0xAA1 +enspace 2722 0xAA2 +em3space 2723 0xAA3 +em4space 2724 0xAA4 +digitspace 2725 0xAA5 +punctspace 2726 0xAA6 +thinspace 2727 0xAA7 +hairspace 2728 0xAA8 +emdash 2729 0xAA9 +endash 2730 0xAAA +signifblank 2732 0xAAC +ellipsis 2734 0xAAE +doubbaselinedot 2735 0xAAF +onethird 2736 0xAB0 +twothirds 2737 0xAB1 +onefifth 2738 0xAB2 +twofifths 2739 0xAB3 +threefifths 2740 0xAB4 +fourfifths 2741 0xAB5 +onesixth 2742 0xAB6 +fivesixths 2743 0xAB7 +careof 2744 0xAB8 +figdash 2747 0xABB +leftanglebracket 2748 0xABC +decimalpoint 2749 0xABD +rightanglebracket 2750 0xABE +marker 2751 0xABF +oneeighth 2755 0xAC3 +threeeighths 2756 0xAC4 +fiveeighths 2757 0xAC5 +seveneighths 2758 0xAC6 +trademark 2761 0xAC9 +signaturemark 2762 0xACA +trademarkincircle 2763 0xACB +leftopentriangle 2764 0xACC +rightopentriangle 2765 0xACD +emopencircle 2766 0xACE +emopenrectangle 2767 0xACF +leftsinglequotemark 2768 0xAD0 +rightsinglequotemark 2769 0xAD1 +leftdoublequotemark 2770 0xAD2 +rightdoublequotemark 2771 0xAD3 +prescription 2772 0xAD4 +minutes 2774 0xAD6 +seconds 2775 0xAD7 +latincross 2777 0xAD9 +hexagram 2778 0xADA +filledrectbullet 2779 0xADB +filledlefttribullet 2780 0xADC +filledrighttribullet 2781 0xADD +emfilledcircle 2782 0xADE +emfilledrect 2783 0xADF +enopencircbullet 2784 0xAE0 +enopensquarebullet 2785 0xAE1 +openrectbullet 2786 0xAE2 +opentribulletup 2787 0xAE3 +opentribulletdown 2788 0xAE4 +openstar 2789 0xAE5 +enfilledcircbullet 2790 0xAE6 +enfilledsqbullet 2791 0xAE7 +filledtribulletup 2792 0xAE8 +filledtribulletdown 2793 0xAE9 +leftpointer 2794 0xAEA +rightpointer 2795 0xAEB +club 2796 0xAEC +diamond 2797 0xAED +heart 2798 0xAEE +maltesecross 2800 0xAF0 +dagger 2801 0xAF1 +doubledagger 2802 0xAF2 +checkmark 2803 0xAF3 +ballotcross 2804 0xAF4 +musicalsharp 2805 0xAF5 +musicalflat 2806 0xAF6 +malesymbol 2807 0xAF7 +femalesymbol 2808 0xAF8 +telephone 2809 0xAF9 +telephonerecorder 2810 0xAFA +phonographcopyright 2811 0xAFB +caret 2812 0xAFC +singlelowquotemark 2813 0xAFD +doublelowquotemark 2814 0xAFE +cursor 2815 0xAFF +leftcaret 2979 0xBA3 +rightcaret 2982 0xBA6 +downcaret 2984 0xBA8 +upcaret 2985 0xBA9 +overbar 3008 0xBC0 +downtack 3010 0xBC2 +upshoe 3011 0xBC3 +downstile 3012 0xBC4 +underbar 3014 0xBC6 +jot 3018 0xBCA +quad 3020 0xBCC +uptack 3022 0xBCE +circle 3023 0xBCF +upstile 3027 0xBD3 +downshoe 3030 0xBD6 +rightshoe 3032 0xBD8 +leftshoe 3034 0xBDA +lefttack 3036 0xBDC +righttack 3068 0xBFC +hebrew_doublelowline 3295 0xCDF +hebrew_aleph 3296 0xCE0 +hebrew_bet 3297 0xCE1 +hebrew_gimel 3298 0xCE2 +hebrew_dalet 3299 0xCE3 +hebrew_he 3300 0xCE4 +hebrew_waw 3301 0xCE5 +hebrew_zain 3302 0xCE6 +hebrew_chet 3303 0xCE7 +hebrew_tet 3304 0xCE8 +hebrew_yod 3305 0xCE9 +hebrew_finalkaph 3306 0xCEA +hebrew_kaph 3307 0xCEB +hebrew_lamed 3308 0xCEC +hebrew_finalmem 3309 0xCED +hebrew_mem 3310 0xCEE +hebrew_finalnun 3311 0xCEF +hebrew_nun 3312 0xCF0 +hebrew_samech 3313 0xCF1 +hebrew_ayin 3314 0xCF2 +hebrew_finalpe 3315 0xCF3 +hebrew_pe 3316 0xCF4 +hebrew_finalzade 3317 0xCF5 +hebrew_zade 3318 0xCF6 +hebrew_qoph 3319 0xCF7 +hebrew_resh 3320 0xCF8 +hebrew_shin 3321 0xCF9 +hebrew_taw 3322 0xCFA +BackSpace 65288 0xFF08 +Tab 65289 0xFF09 +Linefeed 65290 0xFF0A +Clear 65291 0xFF0B +Return 65293 0xFF0D +Pause 65299 0xFF13 +Scroll_Lock 65300 0xFF14 +Sys_Req 65301 0xFF15 +Escape 65307 0xFF1B +Multi_key 65312 0xFF20 +Kanji 65313 0xFF21 +Muhenkan 65314 0xFF22 +Henkan_Mode 65315 0xFF23 +Romaji 65316 0xFF24 +Hiragana 65317 0xFF25 +Katakana 65318 0xFF26 +Hiragana_Katakana 65319 0xFF27 +Zenkaku 65320 0xFF28 +Hankaku 65321 0xFF29 +Zenkaku_Hankaku 65322 0xFF2A +Touroku 65323 0xFF2B +Massyo 65324 0xFF2C +Kana_Lock 65325 0xFF2D +Kana_Shift 65326 0xFF2E +Eisu_Shift 65327 0xFF2F +Eisu_toggle 65328 0xFF30 +Home 65360 0xFF50 +Left 65361 0xFF51 +Up 65362 0xFF52 +Right 65363 0xFF53 +Down 65364 0xFF54 +Prior 65365 0xFF55 +Next 65366 0xFF56 +End 65367 0xFF57 +Begin 65368 0xFF58 +Win_L 65371 0xFF5B +Win_R 65372 0xFF5C .CE .CS -App 65373 0xff5d -Select 65376 0xff60 -Print 65377 0xff61 -Execute 65378 0xff62 -Insert 65379 0xff63 -Undo 65381 0xff65 -Redo 65382 0xff66 -Menu 65383 0xff67 -Find 65384 0xff68 -Cancel 65385 0xff69 -Help 65386 0xff6a -Break 65387 0xff6b -Hebrew_switch 65406 0xff7e -Num_Lock 65407 0xff7f -KP_Space 65408 0xff80 -KP_Tab 65417 0xff89 -KP_Enter 65421 0xff8d -KP_F1 65425 0xff91 -KP_F2 65426 0xff92 -KP_F3 65427 0xff93 -KP_F4 65428 0xff94 -KP_Multiply 65450 0xffaa -KP_Add 65451 0xffab -KP_Separator 65452 0xffac -KP_Subtract 65453 0xffad -KP_Decimal 65454 0xffae -KP_Divide 65455 0xffaf -KP_0 65456 0xffb0 -KP_1 65457 0xffb1 -KP_2 65458 0xffb2 -KP_3 65459 0xffb3 -KP_4 65460 0xffb4 -KP_5 65461 0xffb5 -KP_6 65462 0xffb6 -KP_7 65463 0xffb7 -KP_8 65464 0xffb8 -KP_9 65465 0xffb9 -KP_Equal 65469 0xffbd -F1 65470 0xffbe -F2 65471 0xffbf -F3 65472 0xffc0 -F4 65473 0xffc1 -F5 65474 0xffc2 -F6 65475 0xffc3 -F7 65476 0xffc4 -F8 65477 0xffc5 -F9 65478 0xffc6 -F10 65479 0xffc7 -L1 65480 0xffc8 -L2 65481 0xffc9 -L3 65482 0xffca -L4 65483 0xffcb -L5 65484 0xffcc -L6 65485 0xffcd -L7 65486 0xffce -L8 65487 0xffcf -L9 65488 0xffd0 -L10 65489 0xffd1 -R1 65490 0xffd2 -R2 65491 0xffd3 -R3 65492 0xffd4 -R4 65493 0xffd5 -R5 65494 0xffd6 -R6 65495 0xffd7 -R7 65496 0xffd8 -R8 65497 0xffd9 -R9 65498 0xffda -R10 65499 0xffdb -R11 65500 0xffdc -R12 65501 0xffdd -F33 65502 0xffde -R14 65503 0xffdf -R15 65504 0xffe0 -Shift_L 65505 0xffe1 -Shift_R 65506 0xffe2 -Control_L 65507 0xffe3 -Control_R 65508 0xffe4 -Caps_Lock 65509 0xffe5 -Shift_Lock 65510 0xffe6 -Meta_L 65511 0xffe7 -Meta_R 65512 0xffe8 -Alt_L 65513 0xffe9 -Alt_R 65514 0xffea -Super_L 65515 0xffeb -Super_R 65516 0xffec -Hyper_L 65517 0xffed -Hyper_R 65518 0xffee -Delete 65535 0xffff +App 65373 0xFF5D +Select 65376 0xFF60 +Print 65377 0xFF61 +Execute 65378 0xFF62 +Insert 65379 0xFF63 +Undo 65381 0xFF65 +Redo 65382 0xFF66 +Menu 65383 0xFF67 +Find 65384 0xFF68 +Cancel 65385 0xFF69 +Help 65386 0xFF6A +Break 65387 0xFF6B +Mode_switch 65406 0xFF7E +Num_Lock 65407 0xFF7F +KP_Space 65408 0xFF80 +KP_Tab 65417 0xFF89 +KP_Enter 65421 0xFF8D +KP_F1 65425 0xFF91 +KP_F2 65426 0xFF92 +KP_F3 65427 0xFF93 +KP_F4 65428 0xFF94 +KP_Home 65429 0xFF95 +KP_Left 65430 0xFF96 +KP_Up 65431 0xFF97 +KP_Right 65432 0xFF98 +KP_Down 65433 0xFF99 +KP_Prior 65434 0xFF9A +KP_Next 65435 0xFF9B +KP_End 65436 0xFF9C +KP_Begin 65437 0xFF9D +KP_Insert 65438 0xFF9E +KP_Delete 65439 0xFF9F +KP_Multiply 65450 0xFFAA +KP_Add 65451 0xFFAB +KP_Separator 65452 0xFFAC +KP_Subtract 65453 0xFFAD +KP_Decimal 65454 0xFFAE +KP_Divide 65455 0xFFAF +KP_0 65456 0xFFB0 +KP_1 65457 0xFFB1 +KP_2 65458 0xFFB2 +KP_3 65459 0xFFB3 +KP_4 65460 0xFFB4 +KP_5 65461 0xFFB5 +KP_6 65462 0xFFB6 +KP_7 65463 0xFFB7 +KP_8 65464 0xFFB8 +KP_9 65465 0xFFB9 +KP_Equal 65469 0xFFBD +F1 65470 0xFFBE +F2 65471 0xFFBF +F3 65472 0xFFC0 +F4 65473 0xFFC1 +F5 65474 0xFFC2 +F6 65475 0xFFC3 +F7 65476 0xFFC4 +F8 65477 0xFFC5 +F9 65478 0xFFC6 +F10 65479 0xFFC7 +F11 65480 0xFFC8 +F12 65481 0xFFC9 +F13 65482 0xFFCA +F14 65483 0xFFCB +F15 65484 0xFFCC +F16 65485 0xFFCD +F17 65486 0xFFCE +F18 65487 0xFFCF +F19 65488 0xFFD0 +F20 65489 0xFFD1 +F21 65490 0xFFD2 +F22 65491 0xFFD3 +F23 65492 0xFFD4 +F24 65493 0xFFD5 +F25 65494 0xFFD6 +F26 65495 0xFFD7 +F27 65496 0xFFD8 +F28 65497 0xFFD9 +F29 65498 0xFFDA +F30 65499 0xFFDB +F31 65500 0xFFDC +F32 65501 0xFFDD +F33 65502 0xFFDE +F34 65503 0xFFDF +F35 65504 0xFFE0 +Shift_L 65505 0xFFE1 +Shift_R 65506 0xFFE2 +Control_L 65507 0xFFE3 +Control_R 65508 0xFFE4 +Caps_Lock 65509 0xFFE5 +Shift_Lock 65510 0xFFE6 +Meta_L 65511 0xFFE7 +Meta_R 65512 0xFFE8 +Alt_L 65513 0xFFE9 +Alt_R 65514 0xFFEA +Super_L 65515 0xFFEB +Super_R 65516 0xFFEC +Hyper_L 65517 0xFFED +Hyper_R 65518 0xFFEE +Delete 65535 0xFFFF XF86AudioLowerVolume 269025041 0x1008FF11 XF86AudioMute 269025042 0x1008FF12 XF86AudioRaiseVolume 269025043 0x1008FF13 diff --git a/doc/menu.n b/doc/menu.n index 5742e23..338ce6a 100644 --- a/doc/menu.n +++ b/doc/menu.n @@ -264,7 +264,10 @@ menubar whenever the window's menubar is in front. The first items in the menu are provided by Mac OS X, and the names of the current toplevels are automatically appended after all the Tk-defined items and -a separator. +a separator. The Window menu on the Mac also allows toggling the +window into a fullscreen state, and managing a tabbed window interface +(multiple windows grouped into a single window) if supported by that +version of the operating system. .PP When Tk sees a .menubar.help menu on the Macintosh, the menu's contents are appended to the standard Help menu of the user's menubar whenever @@ -467,18 +470,19 @@ bindings normally take care of this before invoking the \fBinvoke\fR widget command. .TP -\fIpathName \fBpost \fIx y\fR +\fIpathName \fBpost \fIx y\fR ?\fIindex\fR? . Arrange for the menu to be displayed on the screen at the root-window -coordinates given by \fIx\fR and \fIy\fR. These coordinates are -adjusted if necessary to guarantee that the entire menu is visible on -the screen. This command normally returns an empty string. -If the \fB\-postcommand\fR option has been specified, then its value is -executed as a Tcl script before posting the menu and the result of -that script is returned as the result of the \fBpost\fR widget -command. -If an error returns while executing the command, then the error is -returned without posting the menu. +coordinates given by \fIx\fR and \fIy\fR. If an index is specified +the menu will be located so that the entry with that index is +displayed at the point. These coordinates are adjusted if necessary to +guarantee that the entire menu is visible on the screen. This command +normally returns an empty string. If the \fB\-postcommand\fR option +has been specified, then its value is executed as a Tcl script before +posting the menu and the result of that script is returned as the +result of the \fBpost\fR widget command. If an error returns while +executing the command, then the error is returned without posting the +menu. .TP \fIpathName \fBpostcascade \fIindex\fR . diff --git a/doc/panedwindow.n b/doc/panedwindow.n index 40997a9..9fc2b72 100644 --- a/doc/panedwindow.n +++ b/doc/panedwindow.n @@ -331,7 +331,7 @@ (rightmost or bottommost) pane in the window. .PP Unlike slave windows managed by e.g. pack or grid, the panes managed by a -panedwindow do not change width or height to accomodate changes in the +panedwindow do not change width or height to accommodate changes in the requested widths or heights of the panes, once these have become mapped. Therefore it may be advisable, particularly when creating layouts interactively, to not add a pane to the panedwindow widget until after the diff --git a/doc/scale.n b/doc/scale.n index 6b960ce..b1f1981 100644 --- a/doc/scale.n +++ b/doc/scale.n @@ -55,7 +55,7 @@ .OP \-resolution resolution Resolution A real value specifying the resolution for the scale. If this value is greater than zero then the scale's value will always be -rounded to an even multiple of this value, as will tick marks and +rounded to an even multiple of this value, as will the endpoints of the scale. If the value is less than zero then no rounding occurs. Defaults to 1 (i.e., the value will be integral). .OP \-showvalue showValue ShowValue @@ -78,7 +78,7 @@ .OP \-tickinterval tickInterval TickInterval Must be a real value. Determines the spacing between numerical -tick marks displayed below or to the left of the slider. +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. If 0, no tick marks will be displayed. .OP \-to to To Specifies a real value corresponding diff --git a/doc/tk_mac.n b/doc/tk_mac.n index f29ef2f..87c43aa 100644 --- a/doc/tk_mac.n +++ b/doc/tk_mac.n @@ -13,6 +13,8 @@ tk::mac \- Access Mac-Specific Functionality on OS X from Tk .SH SYNOPSIS .nf +\fB::tk::mac::DoScriptFile\fR +\fB::tk::mac::DoScriptText\fR \fB::tk::mac::ShowPreferences\fR \fB::tk::mac::OpenApplication\fR \fB::tk::mac::ReopenApplication\fR @@ -22,6 +24,9 @@ \fB::tk::mac::OnHide\fR \fB::tk::mac::OnShow\fR \fB::tk::mac::ShowHelp\fR +\fB::tk::mac::PerformService\fR +\fB::tk::mac::LaunchURL \fIURL...\fR +\fB::tk::mac::GetAppPath\fR \fB::tk::mac::standardAboutPanel\fR @@ -30,6 +35,7 @@ \fB::tk::mac::antialiasedtext \fInumber\fR \fB::tk::mac::useThemedToplevel \fIboolean\fR + \fB::tk::mac::iconBitmap \fIname width height \-kind value\fR .fi .BE @@ -39,6 +45,20 @@ events that applications should respond to. These events are mapped by Tk to calls to commands in the \fB::tk::mac\fR namespace; unless otherwise noted, if the command is absent, no action will be taken. +.TP +\fB::tk::mac::DoScriptFile\fR +. +The default Apple Event handler for AEDoScriptHandler. This command +executes a Tcl file when an AppleScript sends a +.QW "do script" +command to Wish with a file path as a parameter. +.TP +\fB::tk::mac::DoScriptText\fR +. +The default Apple Event handler for AEDoScriptHandler. This command +executes Tcl code when an AppleScript sends a +.QW "do script" +command to Wish with Tcl code or a Tcl procedure as a parameter. .TP \fB::tk::mac::ShowPreferences\fR . @@ -61,7 +81,7 @@ \fB::tk::mac::OpenApplication\fR . If a proc of this name is defined, this proc fill fire when your application -is intially opened. It is the default Apple Event handler for +is initially opened. It is the default Apple Event handler for kAEOpenApplication, .QW oapp . .TP @@ -110,9 +130,8 @@ If a proc of this name is defined it is the default Apple Event handler for kAEPrintDocuments, .QW pdoc , -the Apple Event sent when your application is asked to print one or more -documents (e.g., via the Print menu item in the Finder). It works the same -way as \fBtk::mac::OpenDocument\fR in terms of arguments. +the Apple Event sent when your application is asked to print a +document. It takes a single absolute file path as an argument. .TP \fB::tk::mac::Quit\fR . @@ -141,7 +160,57 @@ platform-specific standard Help menu item .QW "YourApp Help" performs the default Cocoa action of showing the Help Book configured in the -application's Info.plist (or displaying an alert if no Help Book is set). +application's Info.plist (or displaying an alert if no Help Book is +set). +.TP +\fB::tk::mac::PerformService\fR +. +Executes a Tcl procedure called from the macOS +.QW Services +menu in the Application menu item. The +.QW Services +menu item allows for inter-application communication; data from one +application, such as selected text, can be sent to another application +for processing, for example to Safari as a search item for Google, or +to TextEdit to be appended to a file. An example of the proc is below, +and should be rewritten in an application script for customization: +.RS +.PP +.CS +proc ::tk::mac::PerformService {} { + set data [clipboard get] + $w insert end $data +} +.CE +.RE +Note that the mechanism for retrieving the data is from the clipboard; +there is no other supported way to obtain the data. If the Services +process is not desired, the NSServices keys can be deleted from +the application's Info.plist file. The underlying code supporting this +command also allows the text, entry and ttk::entry widgets to access +services from other applications via the Services menu. The NSPortName +key in Wish's Info.plist file is currently set as +.QW "Wish" +; if a developer changes the name of the Wish executable to something + else, this key should be modified with the same name. +.TP +\fB::tk::mac::LaunchURL \fIURL...\fR +. +If defined, launches a URL within Tk. This would be used if a Tk +application wants to handle a URL itself, such as displaying data from +an RSS feed, rather than launching a default application to handle the +URL, although it can defined as such. Wish includes a stub URL scheme +of +.QW foo:// +in the CFBundleURLSchemes key of its Info.plist file; this should be customized for the specific URL +scheme the developer wants to support. +.TP +\fB::tk::mac::GetAppPath\fR +. +Returns the current applications's file path. +.TP + + .SH "ADDITIONAL DIALOGS" .PP The Aqua/Mac OS X defines additional dialogs that applications should diff --git a/doc/toplevel.n b/doc/toplevel.n index 271d9f1..84fab14 100644 --- a/doc/toplevel.n +++ b/doc/toplevel.n @@ -104,9 +104,9 @@ and relief. The \fBtoplevel\fR command returns the path name of the new window. .PP -A toplevel is similar to a frame except that it is created as a +A toplevel is similar to a \fBframe\fR except that it is created as a top-level window: its X parent is the root window of a screen -rather than the logical parent from its path name. The primary +rather than the logical parent from its Tk path name. The primary purpose of a toplevel is to serve as a container for dialog boxes and other collections of widgets. The only visible features of a toplevel are its background color and an optional 3-D border @@ -117,21 +117,25 @@ name is the same as the path name of the toplevel's window. This command may be used to invoke various operations on the widget. It has the following general form: +.PP .CS \fIpathName option \fR?\fIarg arg ...\fR? .CE +.PP \fIPathName\fR is the name of the command, which is the same as the toplevel widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact behavior of the command. The following commands are possible for toplevel widgets: .TP \fIpathName \fBcget \fIoption\fR +. Returns the current value of the configuration option given by \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBtoplevel\fR command. .TP \fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? +. Query or modify the configuration options of the widget. If no \fIoption\fR is specified, returns a list describing all of the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for @@ -148,8 +152,10 @@ .PP When a new toplevel is created, it has no default event bindings: toplevels are not intended to be interactive. +.PP +Be aware that bindings on toplevels may receive events from subwidgets. .SH "SEE ALSO" -frame(n) +bind(n), bindtags(n), frame(n), wm(n) .SH KEYWORDS toplevel, widget '\" Local Variables: diff --git a/doc/ttk_Geometry.3 b/doc/ttk_Geometry.3 index 61015c5..09d59e0 100644 --- a/doc/ttk_Geometry.3 +++ b/doc/ttk_Geometry.3 @@ -212,7 +212,7 @@ .PP \fBTtk_GetBorderFromObj\fR is the same as \fBTtk_GetPaddingFromObj\fR except that the lengths are specified as integers -(i.e., resolution-dependant values like \fI3m\fR are not allowed). +(i.e., resolution-dependent values like \fI3m\fR are not allowed). .PP \fBTtk_GetStickyFromObj\fR converts the string in \fIobjPtr\fR to a \fIsticky\fR bitmask. The string contains zero or more diff --git a/doc/ttk_button.n b/doc/ttk_button.n index cf47a1a..cf42e28 100644 --- a/doc/ttk_button.n +++ b/doc/ttk_button.n @@ -72,6 +72,8 @@ .br \fB\-bordercolor\fP \fIcolor\fP .br +\fB\-compound\fP \fIcompound\fP +.br \fB\-darkcolor\fP \fIcolor\fP .br \fB\-foreground\fP \fIcolor\fP diff --git a/doc/ttk_checkbutton.n b/doc/ttk_checkbutton.n index a18a886..c78dc0e 100644 --- a/doc/ttk_checkbutton.n +++ b/doc/ttk_checkbutton.n @@ -80,6 +80,8 @@ .PP \fB\-background\fP \fIcolor\fP .br +\fB\-compound\fP \fIcompound\fP +.br \fB\-foreground\fP \fIcolor\fP .br \fB\-indicatorbackground\fP \fIcolor\fP diff --git a/doc/ttk_combobox.n b/doc/ttk_combobox.n index 9c01409..9d0bcc6 100644 --- a/doc/ttk_combobox.n +++ b/doc/ttk_combobox.n @@ -67,7 +67,9 @@ .TP \fIpathName \fBcurrent\fR ?\fInewIndex\fR? If \fInewIndex\fR is supplied, sets the combobox value -to the element at position \fInewIndex\fR in the list of \fB\-values\fR. +to the element at position \fInewIndex\fR in the list of \fB\-values\fR +(in addition to integers, the \fBend\fR index is supported and indicates +the last element of the list). Otherwise, returns the index of the current value in the list of \fB\-values\fR or \fB\-1\fR if the current value does not appear in the list. .TP @@ -124,6 +126,8 @@ .PP \fB\-arrowcolor\fP \fIcolor\fP .br +\fB\-arrowsize\fP \fIamount\fP +.br \fB\-background\fP \fIcolor\fP .br \fB\-bordercolor\fP \fIcolor\fP diff --git a/doc/ttk_entry.n b/doc/ttk_entry.n index d752670..adc4f16 100644 --- a/doc/ttk_entry.n +++ b/doc/ttk_entry.n @@ -222,52 +222,13 @@ Returns 0 if validation fails, 1 if it succeeds. Sets or clears the \fBinvalid\fR state accordingly. See \fBVALIDATION\fR below for more details. -.TP -\fIpathName \fBxview \fIargs\fR -This command is used to query and change the horizontal position of the -text in the widget's window. It can take any of the following -forms: -.RS -.TP -\fIpathName \fBxview\fR -Returns a list containing two elements. -Each element is a real fraction between 0 and 1; together they describe -the horizontal span that is visible in the window. -For example, if the first element is .2 and the second element is .6, -20% of the entry's text is off-screen to the left, the middle 40% is visible -in the window, and 40% of the text is off-screen to the right. -These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR -option. -.TP -\fIpathName \fBxview\fR \fIindex\fR -Adjusts the view in the window so that the character given by \fIindex\fR -is displayed at the left edge of the window. -.TP -\fIpathName \fBxview moveto\fI fraction\fR -Adjusts the view in the window so that the character \fIfraction\fR of the -way through the text appears at the left edge of the window. -\fIFraction\fR must be a fraction between 0 and 1. -.TP -\fIpathName \fBxview scroll \fInumber what\fR -This command shifts the view in the window left or right according to -\fInumber\fR and \fIwhat\fR. -\fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. -'\" or an abbreviation of one of these, but we don't document that. -If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by -\fInumber\fR average-width characters on the display; if it is -\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. -If \fInumber\fR is negative then characters farther to the left -become visible; if it is positive then characters farther to the right -become visible. -.RE .PP The entry widget also supports the following generic \fBttk::widget\fR widget subcommands (see \fIttk::widget(n)\fR for details): .DS .ta 5.5c 11c \fBcget\fR \fBconfigure\fR \fBidentify\fR -\fBinstate\fR \fBstate\fR +\fBinstate\fR \fBstate\fR \fBxview\fR .DE .SH VALIDATION .PP @@ -472,7 +433,9 @@ .PP \fB\-background\fP \fIcolor\fP .RS -When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP. +For backwards compatibility, when using the aqua theme (for macOS), this +option behaves as an alias for the \fB\-fieldbackground\fP provided that no +value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored. .RE \fB\-bordercolor\fP \fIcolor\fP .br @@ -480,8 +443,6 @@ .br \fB\-fieldbackground\fP \fIcolor\fP .RS -Does not work with the aqua theme (Mac OS X). -.br Some themes use a graphical background and their field background colors cannot be changed. .RE \fB\-foreground\fP \fIcolor\fP diff --git a/doc/ttk_frame.n b/doc/ttk_frame.n index 8702592..b02035e 100644 --- a/doc/ttk_frame.n +++ b/doc/ttk_frame.n @@ -23,6 +23,7 @@ .SH "WIDGET-SPECIFIC OPTIONS" .OP \-borderwidth borderWidth BorderWidth The desired width of the widget border. Defaults to 0. +May be ignored depending on the theme used. .OP \-relief relief Relief One of the standard Tk border styles: \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, @@ -53,11 +54,17 @@ are: .PP \fB\-background\fP \fIcolor\fP +.br +\fB\-relief\fP \fIrelief\fP .PP Some options are only available for specific themes. .PP See the \fBttk::style\fP manual page for information on how to configure ttk styles. +.SH BINDINGS +.PP +When a new \fBttk::frame\fR is created, it has no default event bindings; +\fBttk::frame\fRs are not intended to be interactive. .SH "SEE ALSO" ttk::widget(n), ttk::labelframe(n), frame(n) .SH "KEYWORDS" diff --git a/doc/ttk_intro.n b/doc/ttk_intro.n index bc3cd69..07e071b 100644 --- a/doc/ttk_intro.n +++ b/doc/ttk_intro.n @@ -13,7 +13,7 @@ .SH "OVERVIEW" .PP The Tk themed widget set is based on a revised and enhanced version -of TIP #48 (http://tip.tcl.tk/48) specified style engine. +of TIP #48 (https://tip.tcl-lang.org/48) specified style engine. The main concepts are described below. The basic idea is to separate, to the extent possible, the code implementing a widget's behavior from diff --git a/doc/ttk_label.n b/doc/ttk_label.n index aae95e6..871fab7 100644 --- a/doc/ttk_label.n +++ b/doc/ttk_label.n @@ -49,9 +49,6 @@ Valid values are \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, \fBsolid\fR, and \fBsunken\fR. -.OP \-text text Text -Specifies a text string to be displayed inside the widget -(unless overridden by \fB\-textvariable\fR). .OP \-wraplength wrapLength WrapLength Specifies the maximum line length (in pixels). If this option is less than or equal to zero, @@ -74,6 +71,8 @@ .PP \fB\-background\fP \fIcolor\fP .br +\fB\-compound\fP \fIcompound\fP +.br \fB\-foreground\fP \fIcolor\fP .br \fB\-font\fP \fIfont\fP diff --git a/doc/ttk_labelframe.n b/doc/ttk_labelframe.n index 12f0b89..9e42781 100644 --- a/doc/ttk_labelframe.n +++ b/doc/ttk_labelframe.n @@ -30,6 +30,10 @@ .\" XXX: \fBflat\fR, \fBgroove\fR, \fBraised\fR, \fBridge\fR, .\" XXX: \fBsolid\fR, or \fBsunken\fR. .\" XXX: Default is theme-dependent. +.OP \-height height Height +If specified, the widget's requested height in pixels. +(See \fIttk::frame(n)\fR for further notes on \fB\-width\fR and +\fB\-height\fR). .OP \-labelanchor labelAnchor LabelAnchor Specifies where to place the label. Allowed values are (clockwise from the top upper left corner): @@ -40,6 +44,12 @@ .\" and specifies which side the label should be placed on; .\" the remaining characters specify how the label is aligned on that side. .\" NOTE: Now allows other values as well; leave this undocumented for now +.OP \-labelwidget labelWidget LabelWidget +The name of a widget to use for the label. +If set, overrides the \fB\-text\fR option. +The \fB\-labelwidget\fR must be a child of the \fBlabelframe\fR widget +or one of the \fBlabelframe\fR's ancestors, and must belong to the +same top-level widget as the \fBlabelframe\fR. .OP \-text text Text Specifies the text of the label. .OP \-underline underline Underline @@ -48,18 +58,8 @@ The underlined character is used for mnemonic activation. Mnemonic activation for a \fBttk::labelframe\fR sets the keyboard focus to the first child of the \fBttk::labelframe\fR widget. -.OP \-labelwidget labelWidget LabelWidget -The name of a widget to use for the label. -If set, overrides the \fB\-text\fR option. -The \fB\-labelwidget\fR must be a child of the \fBlabelframe\fR widget -or one of the \fBlabelframe\fR's ancestors, and must belong to the -same top-level widget as the \fBlabelframe\fR. .OP \-width width Width If specified, the widget's requested width in pixels. -.OP \-height height Height -If specified, the widget's requested height in pixels. -(See \fIttk::frame(n)\fR for further notes on \fB\-width\fR and -\fB\-height\fR). .SH "WIDGET COMMAND" .PP Supports the standard widget commands diff --git a/doc/ttk_menubutton.n b/doc/ttk_menubutton.n index 76d3829..0d80c1e 100644 --- a/doc/ttk_menubutton.n +++ b/doc/ttk_menubutton.n @@ -58,6 +58,8 @@ .br \fB\-background\fP \fIcolor\fP .br +\fB\-compound\fP \fIcompound\fP +.br \fB\-foreground\fP \fIcolor\fP .br \fB\-font\fP \fIfont\fP diff --git a/doc/ttk_notebook.n b/doc/ttk_notebook.n index 19416b5..ae32a44 100644 --- a/doc/ttk_notebook.n +++ b/doc/ttk_notebook.n @@ -242,6 +242,8 @@ .br \fB\-bordercolor\fP \fIcolor\fP .br +\fB\-compound\fP \fIcompound\fP +.br \fB\-expand\fP \fIpadding\fP .RS Defines how much the tab grows in size. Usually used with the diff --git a/doc/ttk_progressbar.n b/doc/ttk_progressbar.n index 1687123..5d6316a 100644 --- a/doc/ttk_progressbar.n +++ b/doc/ttk_progressbar.n @@ -49,9 +49,11 @@ that is, the progress bar completes one .QW cycle when the \fB\-value\fR increases by \fB\-maximum\fR. +If \fB\-variable\fR is set to an existing variable, specifying \fB\-value\fR +has no effect (the variable value takes precedence). .OP \-variable variable Variable The name of a global Tcl variable which is linked to the \fB\-value\fR. -If specified, the \fB\-value\fR of the progress bar is +If specified to an existing variable, the \fB\-value\fR of the progress bar is automatically set to the value of the variable whenever the latter is modified. .SH "WIDGET COMMAND" diff --git a/doc/ttk_radiobutton.n b/doc/ttk_radiobutton.n index 1344ae2..2dc84be 100644 --- a/doc/ttk_radiobutton.n +++ b/doc/ttk_radiobutton.n @@ -77,6 +77,8 @@ .PP \fB\-background\fP \fIcolor\fP .br +\fB\-compound\fP \fIcompound\fP +.br \fB\-foreground\fP \fIcolor\fP .br \fB\-indicatorbackground\fP \fIcolor\fP diff --git a/doc/ttk_scale.n b/doc/ttk_scale.n index 4e16999..aa851b9 100644 --- a/doc/ttk_scale.n +++ b/doc/ttk_scale.n @@ -42,6 +42,8 @@ This value may be either less than or greater than the \fB\-from\fR option. .OP \-value value Value Specifies the current floating-point value of the variable. +If \fB\-variable\fR is set to an existing variable, specifying \fB\-value\fR +has no effect (the variable value takes precedence). .OP \-variable variable Variable Specifies the name of a global variable to link to the scale. Whenever the value of the variable changes, the scale will update to reflect this value. @@ -93,7 +95,7 @@ is omitted. .SH "STYLING OPTIONS" .PP -The class name for a \fBttk::scale\fP is \fBTProgressbar\fP. +The class name for a \fBttk::scale\fP is \fBTScale\fP. .PP Dynamic states: \fBactive\fP. .PP diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index 49681a1..bd80760 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -76,7 +76,7 @@ .SH "INTERNAL COMMANDS" .PP The following widget commands are used internally -by the TScrollbar widget class bindings. +by the \fBTScrollbar\fP widget class bindings. .TP \fIpathName \fBdelta \fIdeltaX deltaY\fR Returns a real number indicating the fractional change in @@ -153,6 +153,7 @@ grid $f.hsb \-row 1 \-column 0 \-sticky nsew grid columnconfigure $f 0 \-weight 1 grid rowconfigure $f 0 \-weight 1 +pack $f .CE .SH "STYLING OPTIONS" .PP @@ -160,20 +161,25 @@ .PP Dynamic states: \fBactive\fP, \fBdisabled\fP. .PP -\fBTScrollbar\fP styling options configurable with \fBttk::style\fP -are: +\fBTScrollbar\fP (or more specifically \fBVertical.TScrollbar\fP and +\fBHorizontal.TScrollbar\fP) styling options that are configurable with +\fBttk::style\fP are: .PP \fB\-arrowcolor\fP \fIcolor\fP +.br +\fB\-arrowsize\fP \fIamount\fP .br \fB\-background\fP \fIcolor\fP .br \fB\-bordercolor\fP \fIcolor\fP .br -\fB\-darkcolor\fP \fIcolor\fP +\fB\-darkcolor\fP \fIcolor\fP (color of the dark part of the 3D relief) .br \fB\-foreground\fP \fIcolor\fP .br -\fB\-lightcolor\fP \fIcolor\fP +\fB\-gripcount\fP \fIcount\fP (number of lines on the thumb) +.br +\fB\-lightcolor\fP \fIcolor\fP (color of the light part of the 3D relief) .br \fB\-troughcolor\fP \fIcolor\fP .PP diff --git a/doc/ttk_spinbox.n b/doc/ttk_spinbox.n index 325d4d8..9ae9881 100644 --- a/doc/ttk_spinbox.n +++ b/doc/ttk_spinbox.n @@ -95,16 +95,16 @@ .br \fB\-background\fP \fIcolor\fP .RS -When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP. +For backwards compatibility, when using the aqua theme (for macOS), this +option behaves as an alias for the \fB\-fieldbackground\fP provided that no +value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored. .RE \fB\-bordercolor\fP \fIcolor\fP .br \fB\-darkcolor\fP \fIcolor\fP .br \fB\-fieldbackground\fP \fIcolor\fP -.RS -Does not work with the aqua theme (Mac OS X). -.RE +.br \fB\-foreground\fP \fIcolor\fP .br \fB\-lightcolor\fP \fIcolor\fP diff --git a/doc/ttk_style.n b/doc/ttk_style.n index 985e3cd..db80d95 100644 --- a/doc/ttk_style.n +++ b/doc/ttk_style.n @@ -15,7 +15,7 @@ .SH NOTES .PP See also the Tcl'2004 conference presentation, -available at http://tktable.sourceforge.net/tile/tile-tcl2004.pdf +available at https://tktable.sourceforge.net/tile/tile-tcl2004.pdf .SH DEFINITIONS .PP Each widget is assigned a \fIstyle\fR, diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n index b81bc62..2deb5b5 100644 --- a/doc/ttk_treeview.n +++ b/doc/ttk_treeview.n @@ -133,25 +133,29 @@ For example, [\fI$pathname \fBcolumn #\fIn \fB\-id\fR] returns the data column associated with display column #\fIn\fR. .TP -\fB\-anchor\fR +\fB\-anchor \fIanchor\fR Specifies how the text in this column should be aligned -with respect to the cell. One of +with respect to the cell. \fIAnchor\fR is one of \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR, \fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR. .TP -\fB\-minwidth\fR +\fB\-minwidth \fIminwidth\fR The minimum width of the column in pixels. The treeview widget will not make the column any smaller than \fB\-minwidth\fR when the widget is resized or the user drags a +column separator. Default is 20 pixels. +.TP +\fB\-stretch \fIboolean\fR +Specifies whether or not the column width should be adjusted +when the widget is resized or the user drags a column separator. +\fIBoolean\fR may have any of the forms accepted by \fBTcl_GetBoolean\fR. +By default columns are stretchable. +.TP +\fB\-width \fIwidth\fR +The width of the column in pixels. Default is 200 pixels. The specified +column width may be changed by Tk in order to honor \fB\-stretch\fR +and/or \fB\-minwidth\fR, or when the widget is resized or the user drags a column separator. -.TP -\fB\-stretch\fR -Specifies whether or not the column's width should be adjusted -when the widget is resized. -.TP -\fB\-width \fIw\fR -The width of the column in pixels. Default is something reasonable, -probably 200 or so. .PP Use \fIpathname column #0\fR to configure the tree column. .RE @@ -231,7 +235,7 @@ Returns the item ID of the item at position \fIy\fR. .TP \fIpathname \fBidentify column \fIx y\fR -Returns the data column identifier of the cell at position \fIx\fR. +Returns the display column identifier of the cell at position \fIx\fR. The tree column has ID \fB#0\fR. .TP \fIpathname \fBidentify element \fIx y\fR @@ -388,12 +392,13 @@ If \fItag\fR is not present for a particular item, then the \fB\-tags\fR for that item are unchanged. .RE -.TP -\fIpathName \fBxview \fIargs\fR -Standard command for horizontal scrolling; see \fIwidget(n)\fR. -.TP -\fIpathName \fByview \fIargs\fR -Standard command for vertical scrolling; see \fIttk::widget(n)\fR. +.PP +The treeview widget also supports the following generic \fBttk::widget\fR +widget subcommands (see \fIttk::widget(n)\fR for details): +.DS +.ta 5.5c 11c +\fBxview\fR \fByview\fR +.DE .SH "ITEM OPTIONS" .PP The following item options may be specified for items @@ -434,6 +439,9 @@ Specifies the item image, in case the item's \fB\-image\fR option is empty. .\" .PP .\" \fI(@@@ TODO: sort out order of precedence for options)\fR +.PP +Tag priority is decided by the creation order: tags created first receive +higher priority. .SH "COLUMN IDENTIFIERS" .PP Column identifiers take any of the following forms: diff --git a/doc/ttk_widget.n b/doc/ttk_widget.n index ad90e99..281ce74 100644 --- a/doc/ttk_widget.n +++ b/doc/ttk_widget.n @@ -192,6 +192,84 @@ If \fIstateSpec\fR is not specified, returns a list of the currently-enabled state flags. .RE +.TP +\fIpathName \fBxview \fIargs\fR +This command is used to query and change the horizontal position of the +content in the widget's window. It can take any of the following +forms: +.RS +.TP +\fIpathName \fBxview\fR +Returns a list containing two elements. +Each element is a real fraction between 0 and 1; together they describe +the horizontal span that is visible in the window. +For example, if the first element is .2 and the second element is .6, +20% of the widget's content is off-screen to the left, the middle 40% is visible +in the window, and 40% of the content is off-screen to the right. +These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR +option. +.TP +\fIpathName \fBxview\fR \fIindex\fR +Adjusts the view in the window so that the content given by \fIindex\fR +is displayed at the left edge of the window. +.TP +\fIpathName \fBxview moveto\fI fraction\fR +Adjusts the view in the window so that the character \fIfraction\fR of the +way through the content appears at the left edge of the window. +\fIFraction\fR must be a fraction between 0 and 1. +.TP +\fIpathName \fBxview scroll \fInumber what\fR +This command shifts the view in the window left or right according to +\fInumber\fR and \fIwhat\fR. +\fINumber\fR must be an integer. +\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. +'\" or an abbreviation of one of these, but we don't document that. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by +\fInumber\fR average-width characters on the display; if it is +\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then characters farther to the left +become visible; if it is positive then characters farther to the right +become visible. +.RE +.TP +\fIpathName \fByview \fIargs\fR +This command is used to query and change the vertical position of the +content in the widget's window. It can take any of the following +forms: +.RS +.TP +\fIpathName \fByview\fR +Returns a list containing two elements. +Each element is a real fraction between 0 and 1; together they describe +the vertical span that is visible in the window. +For example, if the first element is .2 and the second element is .6, +20% of the widget's content is off-screen to the top, the middle 40% is visible +in the window, and 40% of the content is off-screen to the bottom. +These are the same values passed to scrollbars via the \fB\-yscrollcommand\fR +option. +.TP +\fIpathName \fByview\fR \fIindex\fR +Adjusts the view in the window so that the content given by \fIindex\fR +is displayed at the top edge of the window. +.TP +\fIpathName \fByview moveto\fI fraction\fR +Adjusts the view in the window so that the item \fIfraction\fR of the +way through the content appears at the top edge of the window. +\fIFraction\fR must be a fraction between 0 and 1. +.TP +\fIpathName \fByview scroll \fInumber what\fR +This command shifts the view in the window up or down according to +\fInumber\fR and \fIwhat\fR. +\fINumber\fR must be an integer. +\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. +'\" or an abbreviation of one of these, but we don't document that. +If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by +\fInumber\fR average-width characters on the display; if it is +\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then items farther to the top +become visible; if it is positive then items farther to the bottom +become visible. +.RE .SH "WIDGET STATES" The widget state is a bitmap of independent state flags. Widget state flags include: diff --git a/doc/winfo.n b/doc/winfo.n index 5008448..a833e31 100644 --- a/doc/winfo.n +++ b/doc/winfo.n @@ -73,6 +73,9 @@ screen of the application's main window. If no window in this application contains the point then an empty string is returned. +An empty string is also returned if the point lies in the title bar +or border of its highest containing toplevel in this application. +(Note that with some window managers the borders may be invisible.) In selecting the containing window, children are given higher priority than parents and among siblings the highest one in the stacking order is chosen. diff --git a/doc/wm.n b/doc/wm.n index e7aedf7..a137d06 100644 --- a/doc/wm.n +++ b/doc/wm.n @@ -710,20 +710,21 @@ .TP \fBwm transient \fIwindow\fR ?\fImaster\fR? . -If \fImaster\fR is specified, then the window manager is informed -that \fIwindow\fR is a transient window (e.g. pull-down menu) working -on behalf of \fImaster\fR (where \fImaster\fR is the -path name for a top-level window). If \fImaster\fR -is specified as an empty string then \fIwindow\fR is marked as not -being a transient window any more. Otherwise the command -returns the path name of \fIwindow\fR's current master, or an -empty string if \fIwindow\fR is not currently a transient window. -A transient window will mirror state changes in the master and -inherit the state of the master when initially mapped. It is an -error to attempt to make a window a transient of itself. -The window manager may also decorate a transient window differently, removing -some features normally present (e.g., minimize and maximize buttons) though -this is entirely at the discretion of the window manager. +If \fImaster\fR is specified, then the window manager is informed that +\fIwindow\fR is a transient window (e.g. pull-down menu) working on +behalf of \fImaster\fR (where \fImaster\fR is the path name for a +top-level window). If \fImaster\fR is specified as an empty string +then \fIwindow\fR is marked as not being a transient window any more. +Otherwise the command returns the path name of \fIwindow\fR's current +master, or an empty string if \fIwindow\fR is not currently a +transient window. A transient window will mirror state changes in the +master and inherit the state of the master when initially mapped. The +directed graph with an edge from each transient to its master must be +acyclic. In particular, it is an error to attempt to make a window a +transient of itself. The window manager may also decorate a transient +window differently, removing some features normally present (e.g., +minimize and maximize buttons) though this is entirely at the +discretion of the window manager. .TP \fBwm withdraw \fIwindow\fR . diff --git a/generic/ks_names.h b/generic/ks_names.h index 9f49130..3577390 100644 --- a/generic/ks_names.h +++ b/generic/ks_names.h @@ -4,11 +4,11 @@ * Note that this should be done manually only, because in some cases * keysymdefs.h defines the same integer for multiple keysyms, e.g.: * - * #define XK_Greek_LAMDA 0x7cb - * #define XK_Greek_LAMBDA 0x7cb + * #define XK_Greek_LAMDA 0x7CB + * #define XK_Greek_LAMBDA 0x7CB * - * #define XK_Cyrillic_DZHE 0x6bf - * #define XK_Serbian_DZE 0x6bf (deprecated) + * #define XK_Cyrillic_DZHE 0x6BF + * #define XK_Serbian_DZE 0x6BF (deprecated) * */ { "BackSpace", 0xFF08 }, @@ -23,13 +23,31 @@ { "Delete", 0xFFFF }, { "Multi_key", 0xFF20 }, { "Kanji", 0xFF21 }, +{ "Muhenkan", 0xFF22 }, +{ "Henkan_Mode", 0xFF23 }, +{ "Henkan", 0xFF23 }, +{ "Romaji", 0xFF24 }, +{ "Hiragana", 0xFF25 }, +{ "Katakana", 0xFF26 }, +{ "Hiragana_Katakana", 0xFF27 }, +{ "Zenkaku", 0xFF28 }, +{ "Hankaku", 0xFF29 }, +{ "Zenkaku_Hankaku", 0xFF2A }, +{ "Touroku", 0xFF2B }, +{ "Massyo", 0xFF2C }, +{ "Kana_Lock", 0xFF2D }, +{ "Kana_Shift", 0xFF2E }, +{ "Eisu_Shift", 0xFF2F }, +{ "Eisu_toggle", 0xFF30 }, { "Home", 0xFF50 }, { "Left", 0xFF51 }, { "Up", 0xFF52 }, { "Right", 0xFF53 }, { "Down", 0xFF54 }, { "Prior", 0xFF55 }, +{ "Page_Up", 0xFF55 }, { "Next", 0xFF56 }, +{ "Page_Down", 0xFF56 }, { "End", 0xFF57 }, { "Begin", 0xFF58 }, { "Win_L", 0xFF5B }, @@ -56,6 +74,19 @@ { "KP_F2", 0xFF92 }, { "KP_F3", 0xFF93 }, { "KP_F4", 0xFF94 }, +{ "KP_Home", 0xFF95 }, +{ "KP_Left", 0xFF96 }, +{ "KP_Up", 0xFF97 }, +{ "KP_Right", 0xFF98 }, +{ "KP_Down", 0xFF99 }, +{ "KP_Prior", 0xFF9A }, +{ "KP_Page_Up", 0xFF9A }, +{ "KP_Next", 0xFF9B }, +{ "KP_Page_Down", 0xFF9B }, +{ "KP_End", 0xFF9C }, +{ "KP_Begin", 0xFF9D }, +{ "KP_Insert", 0xFF9E }, +{ "KP_Delete", 0xFF9F }, { "KP_Equal", 0xFFBD }, { "KP_Multiply", 0xFFAA }, { "KP_Add", 0xFFAB }, @@ -147,789 +178,848 @@ { "Super_R", 0xFFEC }, { "Hyper_L", 0xFFED }, { "Hyper_R", 0xFFEE }, -{ "space", 0x020 }, -{ "exclam", 0x021 }, -{ "quotedbl", 0x022 }, -{ "numbersign", 0x023 }, -{ "dollar", 0x024 }, -{ "percent", 0x025 }, -{ "ampersand", 0x026 }, -{ "quoteright", 0x027 }, -{ "parenleft", 0x028 }, -{ "parenright", 0x029 }, -{ "asterisk", 0x02a }, -{ "plus", 0x02b }, -{ "comma", 0x02c }, -{ "minus", 0x02d }, -{ "period", 0x02e }, -{ "slash", 0x02f }, -{ "0", 0x030 }, -{ "1", 0x031 }, -{ "2", 0x032 }, -{ "3", 0x033 }, -{ "4", 0x034 }, -{ "5", 0x035 }, -{ "6", 0x036 }, -{ "7", 0x037 }, -{ "8", 0x038 }, -{ "9", 0x039 }, -{ "colon", 0x03a }, -{ "semicolon", 0x03b }, -{ "less", 0x03c }, -{ "equal", 0x03d }, -{ "greater", 0x03e }, -{ "question", 0x03f }, -{ "at", 0x040 }, -{ "A", 0x041 }, -{ "B", 0x042 }, -{ "C", 0x043 }, -{ "D", 0x044 }, -{ "E", 0x045 }, -{ "F", 0x046 }, -{ "G", 0x047 }, -{ "H", 0x048 }, -{ "I", 0x049 }, -{ "J", 0x04a }, -{ "K", 0x04b }, -{ "L", 0x04c }, -{ "M", 0x04d }, -{ "N", 0x04e }, -{ "O", 0x04f }, -{ "P", 0x050 }, -{ "Q", 0x051 }, -{ "R", 0x052 }, -{ "S", 0x053 }, -{ "T", 0x054 }, -{ "U", 0x055 }, -{ "V", 0x056 }, -{ "W", 0x057 }, -{ "X", 0x058 }, -{ "Y", 0x059 }, -{ "Z", 0x05a }, -{ "bracketleft", 0x05b }, -{ "backslash", 0x05c }, -{ "bracketright", 0x05d }, -{ "asciicircum", 0x05e }, -{ "underscore", 0x05f }, -{ "quoteleft", 0x060 }, -{ "a", 0x061 }, -{ "b", 0x062 }, -{ "c", 0x063 }, -{ "d", 0x064 }, -{ "e", 0x065 }, -{ "f", 0x066 }, -{ "g", 0x067 }, -{ "h", 0x068 }, -{ "i", 0x069 }, -{ "j", 0x06a }, -{ "k", 0x06b }, -{ "l", 0x06c }, -{ "m", 0x06d }, -{ "n", 0x06e }, -{ "o", 0x06f }, -{ "p", 0x070 }, -{ "q", 0x071 }, -{ "r", 0x072 }, -{ "s", 0x073 }, -{ "t", 0x074 }, -{ "u", 0x075 }, -{ "v", 0x076 }, -{ "w", 0x077 }, -{ "x", 0x078 }, -{ "y", 0x079 }, -{ "z", 0x07a }, -{ "braceleft", 0x07b }, -{ "bar", 0x07c }, -{ "braceright", 0x07d }, -{ "asciitilde", 0x07e }, -{ "nobreakspace", 0x0a0 }, -{ "exclamdown", 0x0a1 }, -{ "cent", 0x0a2 }, -{ "sterling", 0x0a3 }, -{ "currency", 0x0a4 }, -{ "yen", 0x0a5 }, -{ "brokenbar", 0x0a6 }, -{ "section", 0x0a7 }, -{ "diaeresis", 0x0a8 }, -{ "copyright", 0x0a9 }, -{ "ordfeminine", 0x0aa }, -{ "guillemotleft", 0x0ab }, -{ "notsign", 0x0ac }, -{ "hyphen", 0x0ad }, -{ "registered", 0x0ae }, -{ "macron", 0x0af }, -{ "degree", 0x0b0 }, -{ "plusminus", 0x0b1 }, -{ "twosuperior", 0x0b2 }, -{ "threesuperior", 0x0b3 }, -{ "acute", 0x0b4 }, -{ "mu", 0x0b5 }, -{ "paragraph", 0x0b6 }, -{ "periodcentered", 0x0b7 }, -{ "cedilla", 0x0b8 }, -{ "onesuperior", 0x0b9 }, -{ "masculine", 0x0ba }, -{ "guillemotright", 0x0bb }, -{ "onequarter", 0x0bc }, -{ "onehalf", 0x0bd }, -{ "threequarters", 0x0be }, -{ "questiondown", 0x0bf }, -{ "Agrave", 0x0c0 }, -{ "Aacute", 0x0c1 }, -{ "Acircumflex", 0x0c2 }, -{ "Atilde", 0x0c3 }, -{ "Adiaeresis", 0x0c4 }, -{ "Aring", 0x0c5 }, -{ "AE", 0x0c6 }, -{ "Ccedilla", 0x0c7 }, -{ "Egrave", 0x0c8 }, -{ "Eacute", 0x0c9 }, -{ "Ecircumflex", 0x0ca }, -{ "Ediaeresis", 0x0cb }, -{ "Igrave", 0x0cc }, -{ "Iacute", 0x0cd }, -{ "Icircumflex", 0x0ce }, -{ "Idiaeresis", 0x0cf }, -{ "Eth", 0x0d0 }, -{ "Ntilde", 0x0d1 }, -{ "Ograve", 0x0d2 }, -{ "Oacute", 0x0d3 }, -{ "Ocircumflex", 0x0d4 }, -{ "Otilde", 0x0d5 }, -{ "Odiaeresis", 0x0d6 }, -{ "multiply", 0x0d7 }, -{ "Ooblique", 0x0d8 }, -{ "Ugrave", 0x0d9 }, -{ "Uacute", 0x0da }, -{ "Ucircumflex", 0x0db }, -{ "Udiaeresis", 0x0dc }, -{ "Yacute", 0x0dd }, -{ "Thorn", 0x0de }, -{ "ssharp", 0x0df }, -{ "agrave", 0x0e0 }, -{ "aacute", 0x0e1 }, -{ "acircumflex", 0x0e2 }, -{ "atilde", 0x0e3 }, -{ "adiaeresis", 0x0e4 }, -{ "aring", 0x0e5 }, -{ "ae", 0x0e6 }, -{ "ccedilla", 0x0e7 }, -{ "egrave", 0x0e8 }, -{ "eacute", 0x0e9 }, -{ "ecircumflex", 0x0ea }, -{ "ediaeresis", 0x0eb }, -{ "igrave", 0x0ec }, -{ "iacute", 0x0ed }, -{ "icircumflex", 0x0ee }, -{ "idiaeresis", 0x0ef }, -{ "eth", 0x0f0 }, -{ "ntilde", 0x0f1 }, -{ "ograve", 0x0f2 }, -{ "oacute", 0x0f3 }, -{ "ocircumflex", 0x0f4 }, -{ "otilde", 0x0f5 }, -{ "odiaeresis", 0x0f6 }, -{ "division", 0x0f7 }, -{ "oslash", 0x0f8 }, -{ "ugrave", 0x0f9 }, -{ "uacute", 0x0fa }, -{ "ucircumflex", 0x0fb }, -{ "udiaeresis", 0x0fc }, -{ "yacute", 0x0fd }, -{ "thorn", 0x0fe }, -{ "ydiaeresis", 0x0ff }, -{ "Aogonek", 0x1a1 }, -{ "breve", 0x1a2 }, -{ "Lstroke", 0x1a3 }, -{ "Lcaron", 0x1a5 }, -{ "Sacute", 0x1a6 }, -{ "Scaron", 0x1a9 }, -{ "Scedilla", 0x1aa }, -{ "Tcaron", 0x1ab }, -{ "Zacute", 0x1ac }, -{ "Zcaron", 0x1ae }, -{ "Zabovedot", 0x1af }, -{ "aogonek", 0x1b1 }, -{ "ogonek", 0x1b2 }, -{ "lstroke", 0x1b3 }, -{ "lcaron", 0x1b5 }, -{ "sacute", 0x1b6 }, -{ "caron", 0x1b7 }, -{ "scaron", 0x1b9 }, -{ "scedilla", 0x1ba }, -{ "tcaron", 0x1bb }, -{ "zacute", 0x1bc }, -{ "doubleacute", 0x1bd }, -{ "zcaron", 0x1be }, -{ "zabovedot", 0x1bf }, -{ "Racute", 0x1c0 }, -{ "Abreve", 0x1c3 }, -{ "Cacute", 0x1c6 }, -{ "Ccaron", 0x1c8 }, -{ "Eogonek", 0x1ca }, -{ "Ecaron", 0x1cc }, -{ "Dcaron", 0x1cf }, -{ "Nacute", 0x1d1 }, -{ "Ncaron", 0x1d2 }, -{ "Odoubleacute", 0x1d5 }, -{ "Rcaron", 0x1d8 }, -{ "Uring", 0x1d9 }, -{ "Udoubleacute", 0x1db }, -{ "Tcedilla", 0x1de }, -{ "racute", 0x1e0 }, -{ "abreve", 0x1e3 }, -{ "cacute", 0x1e6 }, -{ "ccaron", 0x1e8 }, -{ "eogonek", 0x1ea }, -{ "ecaron", 0x1ec }, -{ "dcaron", 0x1ef }, -{ "nacute", 0x1f1 }, -{ "ncaron", 0x1f2 }, -{ "odoubleacute", 0x1f5 }, -{ "udoubleacute", 0x1fb }, -{ "rcaron", 0x1f8 }, -{ "uring", 0x1f9 }, -{ "tcedilla", 0x1fe }, -{ "abovedot", 0x1ff }, -{ "Hstroke", 0x2a1 }, -{ "Hcircumflex", 0x2a6 }, -{ "Iabovedot", 0x2a9 }, -{ "Gbreve", 0x2ab }, -{ "Jcircumflex", 0x2ac }, -{ "hstroke", 0x2b1 }, -{ "hcircumflex", 0x2b6 }, -{ "idotless", 0x2b9 }, -{ "gbreve", 0x2bb }, -{ "jcircumflex", 0x2bc }, -{ "Cabovedot", 0x2c5 }, -{ "Ccircumflex", 0x2c6 }, -{ "Gabovedot", 0x2d5 }, -{ "Gcircumflex", 0x2d8 }, -{ "Ubreve", 0x2dd }, -{ "Scircumflex", 0x2de }, -{ "cabovedot", 0x2e5 }, -{ "ccircumflex", 0x2e6 }, -{ "gabovedot", 0x2f5 }, -{ "gcircumflex", 0x2f8 }, -{ "ubreve", 0x2fd }, -{ "scircumflex", 0x2fe }, -{ "kappa", 0x3a2 }, -{ "Rcedilla", 0x3a3 }, -{ "Itilde", 0x3a5 }, -{ "Lcedilla", 0x3a6 }, -{ "Emacron", 0x3aa }, -{ "Gcedilla", 0x3ab }, -{ "Tslash", 0x3ac }, -{ "rcedilla", 0x3b3 }, -{ "itilde", 0x3b5 }, -{ "lcedilla", 0x3b6 }, -{ "emacron", 0x3ba }, -{ "gacute", 0x3bb }, -{ "tslash", 0x3bc }, -{ "ENG", 0x3bd }, -{ "eng", 0x3bf }, -{ "Amacron", 0x3c0 }, -{ "Iogonek", 0x3c7 }, -{ "Eabovedot", 0x3cc }, -{ "Imacron", 0x3cf }, -{ "Ncedilla", 0x3d1 }, -{ "Omacron", 0x3d2 }, -{ "Kcedilla", 0x3d3 }, -{ "Uogonek", 0x3d9 }, -{ "Utilde", 0x3dd }, -{ "Umacron", 0x3de }, -{ "amacron", 0x3e0 }, -{ "iogonek", 0x3e7 }, -{ "eabovedot", 0x3ec }, -{ "imacron", 0x3ef }, -{ "ncedilla", 0x3f1 }, -{ "omacron", 0x3f2 }, -{ "kcedilla", 0x3f3 }, -{ "uogonek", 0x3f9 }, -{ "utilde", 0x3fd }, -{ "umacron", 0x3fe }, -{ "overline", 0x47e }, -{ "kana_fullstop", 0x4a1 }, -{ "kana_openingbracket", 0x4a2 }, -{ "kana_closingbracket", 0x4a3 }, -{ "kana_comma", 0x4a4 }, -{ "kana_middledot", 0x4a5 }, -{ "kana_WO", 0x4a6 }, -{ "kana_a", 0x4a7 }, -{ "kana_i", 0x4a8 }, -{ "kana_u", 0x4a9 }, -{ "kana_e", 0x4aa }, -{ "kana_o", 0x4ab }, -{ "kana_ya", 0x4ac }, -{ "kana_yu", 0x4ad }, -{ "kana_yo", 0x4ae }, -{ "kana_tu", 0x4af }, -{ "prolongedsound", 0x4b0 }, -{ "kana_A", 0x4b1 }, -{ "kana_I", 0x4b2 }, -{ "kana_U", 0x4b3 }, -{ "kana_E", 0x4b4 }, -{ "kana_O", 0x4b5 }, -{ "kana_KA", 0x4b6 }, -{ "kana_KI", 0x4b7 }, -{ "kana_KU", 0x4b8 }, -{ "kana_KE", 0x4b9 }, -{ "kana_KO", 0x4ba }, -{ "kana_SA", 0x4bb }, -{ "kana_SHI", 0x4bc }, -{ "kana_SU", 0x4bd }, -{ "kana_SE", 0x4be }, -{ "kana_SO", 0x4bf }, -{ "kana_TA", 0x4c0 }, -{ "kana_TI", 0x4c1 }, -{ "kana_TU", 0x4c2 }, -{ "kana_TE", 0x4c3 }, -{ "kana_TO", 0x4c4 }, -{ "kana_NA", 0x4c5 }, -{ "kana_NI", 0x4c6 }, -{ "kana_NU", 0x4c7 }, -{ "kana_NE", 0x4c8 }, -{ "kana_NO", 0x4c9 }, -{ "kana_HA", 0x4ca }, -{ "kana_HI", 0x4cb }, -{ "kana_HU", 0x4cc }, -{ "kana_HE", 0x4cd }, -{ "kana_HO", 0x4ce }, -{ "kana_MA", 0x4cf }, -{ "kana_MI", 0x4d0 }, -{ "kana_MU", 0x4d1 }, -{ "kana_ME", 0x4d2 }, -{ "kana_MO", 0x4d3 }, -{ "kana_YA", 0x4d4 }, -{ "kana_YU", 0x4d5 }, -{ "kana_YO", 0x4d6 }, -{ "kana_RA", 0x4d7 }, -{ "kana_RI", 0x4d8 }, -{ "kana_RU", 0x4d9 }, -{ "kana_RE", 0x4da }, -{ "kana_RO", 0x4db }, -{ "kana_WA", 0x4dc }, -{ "kana_N", 0x4dd }, -{ "voicedsound", 0x4de }, -{ "semivoicedsound", 0x4df }, +{ "space", 0x20 }, +{ "exclam", 0x21 }, +{ "quotedbl", 0x22 }, +{ "numbersign", 0x23 }, +{ "dollar", 0x24 }, +{ "percent", 0x25 }, +{ "ampersand", 0x26 }, +{ "apostrophe", 0x27 }, +{ "quoteright", 0x27 }, +{ "parenleft", 0x28 }, +{ "parenright", 0x29 }, +{ "asterisk", 0x2A }, +{ "plus", 0x2B }, +{ "comma", 0x2C }, +{ "minus", 0x2D }, +{ "period", 0x2E }, +{ "slash", 0x2F }, +{ "0", 0x30 }, +{ "1", 0x31 }, +{ "2", 0x32 }, +{ "3", 0x33 }, +{ "4", 0x34 }, +{ "5", 0x35 }, +{ "6", 0x36 }, +{ "7", 0x37 }, +{ "8", 0x38 }, +{ "9", 0x39 }, +{ "colon", 0x3A }, +{ "semicolon", 0x3B }, +{ "less", 0x3C }, +{ "equal", 0x3D }, +{ "greater", 0x3E }, +{ "question", 0x3F }, +{ "at", 0x40 }, +{ "A", 0x41 }, +{ "B", 0x42 }, +{ "C", 0x43 }, +{ "D", 0x44 }, +{ "E", 0x45 }, +{ "F", 0x46 }, +{ "G", 0x47 }, +{ "H", 0x48 }, +{ "I", 0x49 }, +{ "J", 0x4A }, +{ "K", 0x4B }, +{ "L", 0x4C }, +{ "M", 0x4D }, +{ "N", 0x4E }, +{ "O", 0x4F }, +{ "P", 0x50 }, +{ "Q", 0x51 }, +{ "R", 0x52 }, +{ "S", 0x53 }, +{ "T", 0x54 }, +{ "U", 0x55 }, +{ "V", 0x56 }, +{ "W", 0x57 }, +{ "X", 0x58 }, +{ "Y", 0x59 }, +{ "Z", 0x5A }, +{ "bracketleft", 0x5B }, +{ "backslash", 0x5C }, +{ "bracketright", 0x5D }, +{ "asciicircum", 0x5E }, +{ "underscore", 0x5F }, +{ "grave", 0x60 }, +{ "quoteleft", 0x60 }, +{ "a", 0x61 }, +{ "b", 0x62 }, +{ "c", 0x63 }, +{ "d", 0x64 }, +{ "e", 0x65 }, +{ "f", 0x66 }, +{ "g", 0x67 }, +{ "h", 0x68 }, +{ "i", 0x69 }, +{ "j", 0x6A }, +{ "k", 0x6B }, +{ "l", 0x6C }, +{ "m", 0x6D }, +{ "n", 0x6E }, +{ "o", 0x6F }, +{ "p", 0x70 }, +{ "q", 0x71 }, +{ "r", 0x72 }, +{ "s", 0x73 }, +{ "t", 0x74 }, +{ "u", 0x75 }, +{ "v", 0x76 }, +{ "w", 0x77 }, +{ "x", 0x78 }, +{ "y", 0x79 }, +{ "z", 0x7A }, +{ "braceleft", 0x7B }, +{ "bar", 0x7C }, +{ "braceright", 0x7D }, +{ "asciitilde", 0x7E }, +{ "nobreakspace", 0xA0 }, +{ "exclamdown", 0xA1 }, +{ "cent", 0xA2 }, +{ "sterling", 0xA3 }, +{ "currency", 0xA4 }, +{ "yen", 0xA5 }, +{ "brokenbar", 0xA6 }, +{ "section", 0xA7 }, +{ "diaeresis", 0xA8 }, +{ "copyright", 0xA9 }, +{ "ordfeminine", 0xAA }, +{ "guillemotleft", 0xAB }, +{ "notsign", 0xAC }, +{ "hyphen", 0xAD }, +{ "registered", 0xAE }, +{ "macron", 0xAF }, +{ "degree", 0xB0 }, +{ "plusminus", 0xB1 }, +{ "twosuperior", 0xB2 }, +{ "threesuperior", 0xB3 }, +{ "acute", 0xB4 }, +{ "mu", 0xB5 }, +{ "paragraph", 0xB6 }, +{ "periodcentered", 0xB7 }, +{ "cedilla", 0xB8 }, +{ "onesuperior", 0xB9 }, +{ "masculine", 0xBA }, +{ "guillemotright", 0xBB }, +{ "onequarter", 0xBC }, +{ "onehalf", 0xBD }, +{ "threequarters", 0xBE }, +{ "questiondown", 0xBF }, +{ "Agrave", 0xC0 }, +{ "Aacute", 0xC1 }, +{ "Acircumflex", 0xC2 }, +{ "Atilde", 0xC3 }, +{ "Adiaeresis", 0xC4 }, +{ "Aring", 0xC5 }, +{ "AE", 0xC6 }, +{ "Ccedilla", 0xC7 }, +{ "Egrave", 0xC8 }, +{ "Eacute", 0xC9 }, +{ "Ecircumflex", 0xCA }, +{ "Ediaeresis", 0xCB }, +{ "Igrave", 0xCC }, +{ "Iacute", 0xCD }, +{ "Icircumflex", 0xCE }, +{ "Idiaeresis", 0xCF }, +{ "ETH", 0xD0 }, +{ "Eth", 0xD0 }, +{ "Ntilde", 0xD1 }, +{ "Ograve", 0xD2 }, +{ "Oacute", 0xD3 }, +{ "Ocircumflex", 0xD4 }, +{ "Otilde", 0xD5 }, +{ "Odiaeresis", 0xD6 }, +{ "multiply", 0xD7 }, +{ "Oslash", 0xD8 }, +{ "Ooblique", 0xD8 }, +{ "Ugrave", 0xD9 }, +{ "Uacute", 0xDA }, +{ "Ucircumflex", 0xDB }, +{ "Udiaeresis", 0xDC }, +{ "Yacute", 0xDD }, +{ "THORN", 0xDE }, +{ "Thorn", 0xDE }, +{ "ssharp", 0xDF }, +{ "agrave", 0xE0 }, +{ "aacute", 0xE1 }, +{ "acircumflex", 0xE2 }, +{ "atilde", 0xE3 }, +{ "adiaeresis", 0xE4 }, +{ "aring", 0xE5 }, +{ "ae", 0xE6 }, +{ "ccedilla", 0xE7 }, +{ "egrave", 0xE8 }, +{ "eacute", 0xE9 }, +{ "ecircumflex", 0xEA }, +{ "ediaeresis", 0xEB }, +{ "igrave", 0xEC }, +{ "iacute", 0xED }, +{ "icircumflex", 0xEE }, +{ "idiaeresis", 0xEF }, +{ "eth", 0xF0 }, +{ "ntilde", 0xF1 }, +{ "ograve", 0xF2 }, +{ "oacute", 0xF3 }, +{ "ocircumflex", 0xF4 }, +{ "otilde", 0xF5 }, +{ "odiaeresis", 0xF6 }, +{ "division", 0xF7 }, +{ "oslash", 0xF8 }, +{ "ugrave", 0xF9 }, +{ "uacute", 0xFA }, +{ "ucircumflex", 0xFB }, +{ "udiaeresis", 0xFC }, +{ "yacute", 0xFD }, +{ "thorn", 0xFE }, +{ "ydiaeresis", 0xFF }, +{ "Aogonek", 0x1A1 }, +{ "breve", 0x1A2 }, +{ "Lstroke", 0x1A3 }, +{ "Lcaron", 0x1A5 }, +{ "Sacute", 0x1A6 }, +{ "Scaron", 0x1A9 }, +{ "Scedilla", 0x1AA }, +{ "Tcaron", 0x1AB }, +{ "Zacute", 0x1AC }, +{ "Zcaron", 0x1AE }, +{ "Zabovedot", 0x1AF }, +{ "aogonek", 0x1B1 }, +{ "ogonek", 0x1B2 }, +{ "lstroke", 0x1B3 }, +{ "lcaron", 0x1B5 }, +{ "sacute", 0x1B6 }, +{ "caron", 0x1B7 }, +{ "scaron", 0x1B9 }, +{ "scedilla", 0x1BA }, +{ "tcaron", 0x1BB }, +{ "zacute", 0x1BC }, +{ "doubleacute", 0x1BD }, +{ "zcaron", 0x1BE }, +{ "zabovedot", 0x1BF }, +{ "Racute", 0x1C0 }, +{ "Abreve", 0x1C3 }, +{ "Lacute", 0x1C5 }, +{ "Cacute", 0x1C6 }, +{ "Ccaron", 0x1C8 }, +{ "Eogonek", 0x1CA }, +{ "Ecaron", 0x1CC }, +{ "Dcaron", 0x1CF }, +{ "Dstroke", 0x1D0 }, +{ "Nacute", 0x1D1 }, +{ "Ncaron", 0x1D2 }, +{ "Odoubleacute", 0x1D5 }, +{ "Rcaron", 0x1D8 }, +{ "Uring", 0x1D9 }, +{ "Udoubleacute", 0x1DB }, +{ "Tcedilla", 0x1DE }, +{ "racute", 0x1E0 }, +{ "abreve", 0x1E3 }, +{ "lacute", 0x1E5 }, +{ "cacute", 0x1E6 }, +{ "ccaron", 0x1E8 }, +{ "eogonek", 0x1EA }, +{ "ecaron", 0x1EC }, +{ "dcaron", 0x1EF }, +{ "dstroke", 0x1F0 }, +{ "nacute", 0x1F1 }, +{ "ncaron", 0x1F2 }, +{ "odoubleacute", 0x1F5 }, +{ "rcaron", 0x1F8 }, +{ "uring", 0x1F9 }, +{ "udoubleacute", 0x1FB }, +{ "tcedilla", 0x1FE }, +{ "abovedot", 0x1FF }, +{ "Hstroke", 0x2A1 }, +{ "Hcircumflex", 0x2A6 }, +{ "Iabovedot", 0x2A9 }, +{ "Gbreve", 0x2AB }, +{ "Jcircumflex", 0x2AC }, +{ "hstroke", 0x2B1 }, +{ "hcircumflex", 0x2B6 }, +{ "idotless", 0x2B9 }, +{ "gbreve", 0x2BB }, +{ "jcircumflex", 0x2BC }, +{ "Cabovedot", 0x2C5 }, +{ "Ccircumflex", 0x2C6 }, +{ "Gabovedot", 0x2D5 }, +{ "Gcircumflex", 0x2D8 }, +{ "Ubreve", 0x2DD }, +{ "Scircumflex", 0x2DE }, +{ "cabovedot", 0x2E5 }, +{ "ccircumflex", 0x2E6 }, +{ "gabovedot", 0x2F5 }, +{ "gcircumflex", 0x2F8 }, +{ "ubreve", 0x2FD }, +{ "scircumflex", 0x2FE }, +{ "kra", 0x3A2 }, +{ "kappa", 0x3A2 }, +{ "Rcedilla", 0x3A3 }, +{ "Itilde", 0x3A5 }, +{ "Lcedilla", 0x3A6 }, +{ "Emacron", 0x3AA }, +{ "Gcedilla", 0x3AB }, +{ "Tslash", 0x3AC }, +{ "rcedilla", 0x3B3 }, +{ "itilde", 0x3B5 }, +{ "lcedilla", 0x3B6 }, +{ "emacron", 0x3BA }, +{ "gcedilla", 0x3BB }, +{ "gacute", 0x3BB }, +{ "tslash", 0x3BC }, +{ "ENG", 0x3BD }, +{ "eng", 0x3BF }, +{ "Amacron", 0x3C0 }, +{ "Iogonek", 0x3C7 }, +{ "Eabovedot", 0x3CC }, +{ "Imacron", 0x3CF }, +{ "Ncedilla", 0x3D1 }, +{ "Omacron", 0x3D2 }, +{ "Kcedilla", 0x3D3 }, +{ "Uogonek", 0x3D9 }, +{ "Utilde", 0x3DD }, +{ "Umacron", 0x3DE }, +{ "amacron", 0x3E0 }, +{ "iogonek", 0x3E7 }, +{ "eabovedot", 0x3EC }, +{ "imacron", 0x3EF }, +{ "ncedilla", 0x3F1 }, +{ "omacron", 0x3F2 }, +{ "kcedilla", 0x3F3 }, +{ "uogonek", 0x3F9 }, +{ "utilde", 0x3FD }, +{ "umacron", 0x3FE }, +{ "overline", 0x47E }, +{ "kana_fullstop", 0x4A1 }, +{ "kana_openingbracket", 0x4A2 }, +{ "kana_closingbracket", 0x4A3 }, +{ "kana_comma", 0x4A4 }, +{ "kana_conjunctive", 0x4A5 }, +{ "kana_middledot", 0x4A5 }, +{ "kana_WO", 0x4A6 }, +{ "kana_a", 0x4A7 }, +{ "kana_i", 0x4A8 }, +{ "kana_u", 0x4A9 }, +{ "kana_e", 0x4AA }, +{ "kana_o", 0x4AB }, +{ "kana_ya", 0x4AC }, +{ "kana_yu", 0x4AD }, +{ "kana_yo", 0x4AE }, +{ "kana_tsu", 0x4AF }, +{ "kana_tu", 0x4AF }, +{ "prolongedsound", 0x4B0 }, +{ "kana_A", 0x4B1 }, +{ "kana_I", 0x4B2 }, +{ "kana_U", 0x4B3 }, +{ "kana_E", 0x4B4 }, +{ "kana_O", 0x4B5 }, +{ "kana_KA", 0x4B6 }, +{ "kana_KI", 0x4B7 }, +{ "kana_KU", 0x4B8 }, +{ "kana_KE", 0x4B9 }, +{ "kana_KO", 0x4BA }, +{ "kana_SA", 0x4BB }, +{ "kana_SHI", 0x4BC }, +{ "kana_SU", 0x4BD }, +{ "kana_SE", 0x4BE }, +{ "kana_SO", 0x4BF }, +{ "kana_TA", 0x4C0 }, +{ "kana_CHI", 0x4C1 }, +{ "kana_TI", 0x4C1 }, +{ "kana_TSU", 0x4C2 }, +{ "kana_TU", 0x4C2 }, +{ "kana_TE", 0x4C3 }, +{ "kana_TO", 0x4C4 }, +{ "kana_NA", 0x4C5 }, +{ "kana_NI", 0x4C6 }, +{ "kana_NU", 0x4C7 }, +{ "kana_NE", 0x4C8 }, +{ "kana_NO", 0x4C9 }, +{ "kana_HA", 0x4CA }, +{ "kana_HI", 0x4CB }, +{ "kana_FU", 0x4CC }, +{ "kana_HU", 0x4CC }, +{ "kana_HE", 0x4CD }, +{ "kana_HO", 0x4CE }, +{ "kana_MA", 0x4CF }, +{ "kana_MI", 0x4D0 }, +{ "kana_MU", 0x4D1 }, +{ "kana_ME", 0x4D2 }, +{ "kana_MO", 0x4D3 }, +{ "kana_YA", 0x4D4 }, +{ "kana_YU", 0x4D5 }, +{ "kana_YO", 0x4D6 }, +{ "kana_RA", 0x4D7 }, +{ "kana_RI", 0x4D8 }, +{ "kana_RU", 0x4D9 }, +{ "kana_RE", 0x4DA }, +{ "kana_RO", 0x4DB }, +{ "kana_WA", 0x4DC }, +{ "kana_N", 0x4DD }, +{ "voicedsound", 0x4DE }, +{ "semivoicedsound", 0x4DF }, { "kana_switch", 0xFF7E }, -{ "Arabic_comma", 0x5ac }, -{ "Arabic_semicolon", 0x5bb }, -{ "Arabic_question_mark", 0x5bf }, -{ "Arabic_hamza", 0x5c1 }, -{ "Arabic_maddaonalef", 0x5c2 }, -{ "Arabic_hamzaonalef", 0x5c3 }, -{ "Arabic_hamzaonwaw", 0x5c4 }, -{ "Arabic_hamzaunderalef", 0x5c5 }, -{ "Arabic_hamzaonyeh", 0x5c6 }, -{ "Arabic_alef", 0x5c7 }, -{ "Arabic_beh", 0x5c8 }, -{ "Arabic_tehmarbuta", 0x5c9 }, -{ "Arabic_teh", 0x5ca }, -{ "Arabic_theh", 0x5cb }, -{ "Arabic_jeem", 0x5cc }, -{ "Arabic_hah", 0x5cd }, -{ "Arabic_khah", 0x5ce }, -{ "Arabic_dal", 0x5cf }, -{ "Arabic_thal", 0x5d0 }, -{ "Arabic_ra", 0x5d1 }, -{ "Arabic_zain", 0x5d2 }, -{ "Arabic_seen", 0x5d3 }, -{ "Arabic_sheen", 0x5d4 }, -{ "Arabic_sad", 0x5d5 }, -{ "Arabic_dad", 0x5d6 }, -{ "Arabic_tah", 0x5d7 }, -{ "Arabic_zah", 0x5d8 }, -{ "Arabic_ain", 0x5d9 }, -{ "Arabic_ghain", 0x5da }, -{ "Arabic_tatweel", 0x5e0 }, -{ "Arabic_feh", 0x5e1 }, -{ "Arabic_qaf", 0x5e2 }, -{ "Arabic_kaf", 0x5e3 }, -{ "Arabic_lam", 0x5e4 }, -{ "Arabic_meem", 0x5e5 }, -{ "Arabic_noon", 0x5e6 }, -{ "Arabic_heh", 0x5e7 }, -{ "Arabic_waw", 0x5e8 }, -{ "Arabic_alefmaksura", 0x5e9 }, -{ "Arabic_yeh", 0x5ea }, -{ "Arabic_fathatan", 0x5eb }, -{ "Arabic_dammatan", 0x5ec }, -{ "Arabic_kasratan", 0x5ed }, -{ "Arabic_fatha", 0x5ee }, -{ "Arabic_damma", 0x5ef }, -{ "Arabic_kasra", 0x5f0 }, -{ "Arabic_shadda", 0x5f1 }, -{ "Arabic_sukun", 0x5f2 }, +{ "Arabic_comma", 0x5AC }, +{ "Arabic_semicolon", 0x5BB }, +{ "Arabic_question_mark", 0x5BF }, +{ "Arabic_hamza", 0x5C1 }, +{ "Arabic_maddaonalef", 0x5C2 }, +{ "Arabic_hamzaonalef", 0x5C3 }, +{ "Arabic_hamzaonwaw", 0x5C4 }, +{ "Arabic_hamzaunderalef", 0x5C5 }, +{ "Arabic_hamzaonyeh", 0x5C6 }, +{ "Arabic_alef", 0x5C7 }, +{ "Arabic_beh", 0x5C8 }, +{ "Arabic_tehmarbuta", 0x5C9 }, +{ "Arabic_teh", 0x5CA }, +{ "Arabic_theh", 0x5CB }, +{ "Arabic_jeem", 0x5CC }, +{ "Arabic_hah", 0x5CD }, +{ "Arabic_khah", 0x5CE }, +{ "Arabic_dal", 0x5CF }, +{ "Arabic_thal", 0x5D0 }, +{ "Arabic_ra", 0x5D1 }, +{ "Arabic_zain", 0x5D2 }, +{ "Arabic_seen", 0x5D3 }, +{ "Arabic_sheen", 0x5D4 }, +{ "Arabic_sad", 0x5D5 }, +{ "Arabic_dad", 0x5D6 }, +{ "Arabic_tah", 0x5D7 }, +{ "Arabic_zah", 0x5D8 }, +{ "Arabic_ain", 0x5D9 }, +{ "Arabic_ghain", 0x5DA }, +{ "Arabic_tatweel", 0x5E0 }, +{ "Arabic_feh", 0x5E1 }, +{ "Arabic_qaf", 0x5E2 }, +{ "Arabic_kaf", 0x5E3 }, +{ "Arabic_lam", 0x5E4 }, +{ "Arabic_meem", 0x5E5 }, +{ "Arabic_noon", 0x5E6 }, +{ "Arabic_ha", 0x5E7 }, +{ "Arabic_heh", 0x5E7 }, +{ "Arabic_waw", 0x5E8 }, +{ "Arabic_alefmaksura", 0x5E9 }, +{ "Arabic_yeh", 0x5EA }, +{ "Arabic_fathatan", 0x5EB }, +{ "Arabic_dammatan", 0x5EC }, +{ "Arabic_kasratan", 0x5ED }, +{ "Arabic_fatha", 0x5EE }, +{ "Arabic_damma", 0x5EF }, +{ "Arabic_kasra", 0x5F0 }, +{ "Arabic_shadda", 0x5F1 }, +{ "Arabic_sukun", 0x5F2 }, { "Arabic_switch", 0xFF7E }, -{ "Serbian_dje", 0x6a1 }, -{ "Macedonia_gje", 0x6a2 }, -{ "Cyrillic_io", 0x6a3 }, -{ "Ukranian_je", 0x6a4 }, -{ "Macedonia_dse", 0x6a5 }, -{ "Ukranian_i", 0x6a6 }, -{ "Ukranian_yi", 0x6a7 }, -{ "Serbian_je", 0x6a8 }, -{ "Serbian_lje", 0x6a9 }, -{ "Serbian_nje", 0x6aa }, -{ "Serbian_tshe", 0x6ab }, -{ "Macedonia_kje", 0x6ac }, -{ "Byelorussian_shortu", 0x6ae }, -{ "Serbian_dze", 0x6af }, -{ "numerosign", 0x6b0 }, -{ "Serbian_DJE", 0x6b1 }, -{ "Macedonia_GJE", 0x6b2 }, -{ "Cyrillic_IO", 0x6b3 }, -{ "Ukranian_JE", 0x6b4 }, -{ "Macedonia_DSE", 0x6b5 }, -{ "Ukranian_I", 0x6b6 }, -{ "Ukranian_YI", 0x6b7 }, -{ "Serbian_JE", 0x6b8 }, -{ "Serbian_LJE", 0x6b9 }, -{ "Serbian_NJE", 0x6ba }, -{ "Serbian_TSHE", 0x6bb }, -{ "Macedonia_KJE", 0x6bc }, -{ "Byelorussian_SHORTU", 0x6be }, -{ "Serbian_DZE", 0x6bf }, -{ "Cyrillic_yu", 0x6c0 }, -{ "Cyrillic_a", 0x6c1 }, -{ "Cyrillic_be", 0x6c2 }, -{ "Cyrillic_tse", 0x6c3 }, -{ "Cyrillic_de", 0x6c4 }, -{ "Cyrillic_ie", 0x6c5 }, -{ "Cyrillic_ef", 0x6c6 }, -{ "Cyrillic_ghe", 0x6c7 }, -{ "Cyrillic_ha", 0x6c8 }, -{ "Cyrillic_i", 0x6c9 }, -{ "Cyrillic_shorti", 0x6ca }, -{ "Cyrillic_ka", 0x6cb }, -{ "Cyrillic_el", 0x6cc }, -{ "Cyrillic_em", 0x6cd }, -{ "Cyrillic_en", 0x6ce }, -{ "Cyrillic_o", 0x6cf }, -{ "Cyrillic_pe", 0x6d0 }, -{ "Cyrillic_ya", 0x6d1 }, -{ "Cyrillic_er", 0x6d2 }, -{ "Cyrillic_es", 0x6d3 }, -{ "Cyrillic_te", 0x6d4 }, -{ "Cyrillic_u", 0x6d5 }, -{ "Cyrillic_zhe", 0x6d6 }, -{ "Cyrillic_ve", 0x6d7 }, -{ "Cyrillic_softsign", 0x6d8 }, -{ "Cyrillic_yeru", 0x6d9 }, -{ "Cyrillic_ze", 0x6da }, -{ "Cyrillic_sha", 0x6db }, -{ "Cyrillic_e", 0x6dc }, -{ "Cyrillic_shcha", 0x6dd }, -{ "Cyrillic_che", 0x6de }, -{ "Cyrillic_hardsign", 0x6df }, -{ "Cyrillic_YU", 0x6e0 }, -{ "Cyrillic_A", 0x6e1 }, -{ "Cyrillic_BE", 0x6e2 }, -{ "Cyrillic_TSE", 0x6e3 }, -{ "Cyrillic_DE", 0x6e4 }, -{ "Cyrillic_IE", 0x6e5 }, -{ "Cyrillic_EF", 0x6e6 }, -{ "Cyrillic_GHE", 0x6e7 }, -{ "Cyrillic_HA", 0x6e8 }, -{ "Cyrillic_I", 0x6e9 }, -{ "Cyrillic_SHORTI", 0x6ea }, -{ "Cyrillic_KA", 0x6eb }, -{ "Cyrillic_EL", 0x6ec }, -{ "Cyrillic_EM", 0x6ed }, -{ "Cyrillic_EN", 0x6ee }, -{ "Cyrillic_O", 0x6ef }, -{ "Cyrillic_PE", 0x6f0 }, -{ "Cyrillic_YA", 0x6f1 }, -{ "Cyrillic_ER", 0x6f2 }, -{ "Cyrillic_ES", 0x6f3 }, -{ "Cyrillic_TE", 0x6f4 }, -{ "Cyrillic_U", 0x6f5 }, -{ "Cyrillic_ZHE", 0x6f6 }, -{ "Cyrillic_VE", 0x6f7 }, -{ "Cyrillic_SOFTSIGN", 0x6f8 }, -{ "Cyrillic_YERU", 0x6f9 }, -{ "Cyrillic_ZE", 0x6fa }, -{ "Cyrillic_SHA", 0x6fb }, -{ "Cyrillic_E", 0x6fc }, -{ "Cyrillic_SHCHA", 0x6fd }, -{ "Cyrillic_CHE", 0x6fe }, -{ "Cyrillic_HARDSIGN", 0x6ff }, -{ "Greek_ALPHAaccent", 0x7a1 }, -{ "Greek_EPSILONaccent", 0x7a2 }, -{ "Greek_ETAaccent", 0x7a3 }, -{ "Greek_IOTAaccent", 0x7a4 }, -{ "Greek_IOTAdiaeresis", 0x7a5 }, -{ "Greek_IOTAaccentdiaeresis", 0x7a6 }, -{ "Greek_OMICRONaccent", 0x7a7 }, -{ "Greek_UPSILONaccent", 0x7a8 }, -{ "Greek_UPSILONdieresis", 0x7a9 }, -{ "Greek_UPSILONaccentdieresis", 0x7aa }, -{ "Greek_OMEGAaccent", 0x7ab }, -{ "Greek_alphaaccent", 0x7b1 }, -{ "Greek_epsilonaccent", 0x7b2 }, -{ "Greek_etaaccent", 0x7b3 }, -{ "Greek_iotaaccent", 0x7b4 }, -{ "Greek_iotadieresis", 0x7b5 }, -{ "Greek_iotaaccentdieresis", 0x7b6 }, -{ "Greek_omicronaccent", 0x7b7 }, -{ "Greek_upsilonaccent", 0x7b8 }, -{ "Greek_upsilondieresis", 0x7b9 }, -{ "Greek_upsilonaccentdieresis", 0x7ba }, -{ "Greek_omegaaccent", 0x7bb }, -{ "Greek_ALPHA", 0x7c1 }, -{ "Greek_BETA", 0x7c2 }, -{ "Greek_GAMMA", 0x7c3 }, -{ "Greek_DELTA", 0x7c4 }, -{ "Greek_EPSILON", 0x7c5 }, -{ "Greek_ZETA", 0x7c6 }, -{ "Greek_ETA", 0x7c7 }, -{ "Greek_THETA", 0x7c8 }, -{ "Greek_IOTA", 0x7c9 }, -{ "Greek_KAPPA", 0x7ca }, -{ "Greek_LAMBDA", 0x7cb }, -{ "Greek_MU", 0x7cc }, -{ "Greek_NU", 0x7cd }, -{ "Greek_XI", 0x7ce }, -{ "Greek_OMICRON", 0x7cf }, -{ "Greek_PI", 0x7d0 }, -{ "Greek_RHO", 0x7d1 }, -{ "Greek_SIGMA", 0x7d2 }, -{ "Greek_TAU", 0x7d4 }, -{ "Greek_UPSILON", 0x7d5 }, -{ "Greek_PHI", 0x7d6 }, -{ "Greek_CHI", 0x7d7 }, -{ "Greek_PSI", 0x7d8 }, -{ "Greek_OMEGA", 0x7d9 }, -{ "Greek_alpha", 0x7e1 }, -{ "Greek_beta", 0x7e2 }, -{ "Greek_gamma", 0x7e3 }, -{ "Greek_delta", 0x7e4 }, -{ "Greek_epsilon", 0x7e5 }, -{ "Greek_zeta", 0x7e6 }, -{ "Greek_eta", 0x7e7 }, -{ "Greek_theta", 0x7e8 }, -{ "Greek_iota", 0x7e9 }, -{ "Greek_kappa", 0x7ea }, -{ "Greek_lambda", 0x7eb }, -{ "Greek_mu", 0x7ec }, -{ "Greek_nu", 0x7ed }, -{ "Greek_xi", 0x7ee }, -{ "Greek_omicron", 0x7ef }, -{ "Greek_pi", 0x7f0 }, -{ "Greek_rho", 0x7f1 }, -{ "Greek_sigma", 0x7f2 }, -{ "Greek_finalsmallsigma", 0x7f3 }, -{ "Greek_tau", 0x7f4 }, -{ "Greek_upsilon", 0x7f5 }, -{ "Greek_phi", 0x7f6 }, -{ "Greek_chi", 0x7f7 }, -{ "Greek_psi", 0x7f8 }, -{ "Greek_omega", 0x7f9 }, +{ "Serbian_dje", 0x6A1 }, +{ "Macedonia_gje", 0x6A2 }, +{ "Cyrillic_io", 0x6A3 }, +{ "Ukrainian_ie", 0x6A4 }, +{ "Ukranian_je", 0x6A4 }, +{ "Macedonia_dse", 0x6A5 }, +{ "Ukrainian_i", 0x6A6 }, +{ "Ukranian_i", 0x6A6 }, +{ "Ukrainian_yi", 0x6A7 }, +{ "Ukranian_yi", 0x6A7 }, +{ "Cyrillic_je", 0x6A8 }, +{ "Serbian_je", 0x6A8 }, +{ "Cyrillic_lje", 0x6A9 }, +{ "Serbian_lje", 0x6A9 }, +{ "Cyrillic_nje", 0x6AA }, +{ "Serbian_nje", 0x6AA }, +{ "Serbian_tshe", 0x6AB }, +{ "Macedonia_kje", 0x6AC }, +{ "Ukrainian_ghe_with_upturn", 0x6AD }, +{ "Byelorussian_shortu", 0x6AE }, +{ "Cyrillic_dzhe", 0x6AF }, +{ "Serbian_dze", 0x6AF }, +{ "numerosign", 0x6B0 }, +{ "Serbian_DJE", 0x6B1 }, +{ "Macedonia_GJE", 0x6B2 }, +{ "Cyrillic_IO", 0x6B3 }, +{ "Ukrainian_IE", 0x6B4 }, +{ "Ukranian_JE", 0x6B4 }, +{ "Macedonia_DSE", 0x6B5 }, +{ "Ukrainian_I", 0x6B6 }, +{ "Ukranian_I", 0x6B6 }, +{ "Ukrainian_YI", 0x6B7 }, +{ "Ukranian_YI", 0x6B7 }, +{ "Cyrillic_JE", 0x6B8 }, +{ "Serbian_JE", 0x6B8 }, +{ "Cyrillic_LJE", 0x6B9 }, +{ "Serbian_LJE", 0x6B9 }, +{ "Cyrillic_NJE", 0x6BA }, +{ "Serbian_NJE", 0x6BA }, +{ "Serbian_TSHE", 0x6BB }, +{ "Macedonia_KJE", 0x6BC }, +{ "Ukrainian_GHE_WITH_UPTURN", 0x6BD }, +{ "Byelorussian_SHORTU", 0x6BE }, +{ "Cyrillic_DZHE", 0x6BF }, +{ "Serbian_DZE", 0x6BF }, +{ "Cyrillic_yu", 0x6C0 }, +{ "Cyrillic_a", 0x6C1 }, +{ "Cyrillic_be", 0x6C2 }, +{ "Cyrillic_tse", 0x6C3 }, +{ "Cyrillic_de", 0x6C4 }, +{ "Cyrillic_ie", 0x6C5 }, +{ "Cyrillic_ef", 0x6C6 }, +{ "Cyrillic_ghe", 0x6C7 }, +{ "Cyrillic_ha", 0x6C8 }, +{ "Cyrillic_i", 0x6C9 }, +{ "Cyrillic_shorti", 0x6CA }, +{ "Cyrillic_ka", 0x6CB }, +{ "Cyrillic_el", 0x6CC }, +{ "Cyrillic_em", 0x6CD }, +{ "Cyrillic_en", 0x6CE }, +{ "Cyrillic_o", 0x6CF }, +{ "Cyrillic_pe", 0x6D0 }, +{ "Cyrillic_ya", 0x6D1 }, +{ "Cyrillic_er", 0x6D2 }, +{ "Cyrillic_es", 0x6D3 }, +{ "Cyrillic_te", 0x6D4 }, +{ "Cyrillic_u", 0x6D5 }, +{ "Cyrillic_zhe", 0x6D6 }, +{ "Cyrillic_ve", 0x6D7 }, +{ "Cyrillic_softsign", 0x6D8 }, +{ "Cyrillic_yeru", 0x6D9 }, +{ "Cyrillic_ze", 0x6DA }, +{ "Cyrillic_sha", 0x6DB }, +{ "Cyrillic_e", 0x6DC }, +{ "Cyrillic_shcha", 0x6DD }, +{ "Cyrillic_che", 0x6DE }, +{ "Cyrillic_hardsign", 0x6DF }, +{ "Cyrillic_YU", 0x6E0 }, +{ "Cyrillic_A", 0x6E1 }, +{ "Cyrillic_BE", 0x6E2 }, +{ "Cyrillic_TSE", 0x6E3 }, +{ "Cyrillic_DE", 0x6E4 }, +{ "Cyrillic_IE", 0x6E5 }, +{ "Cyrillic_EF", 0x6E6 }, +{ "Cyrillic_GHE", 0x6E7 }, +{ "Cyrillic_HA", 0x6E8 }, +{ "Cyrillic_I", 0x6E9 }, +{ "Cyrillic_SHORTI", 0x6EA }, +{ "Cyrillic_KA", 0x6EB }, +{ "Cyrillic_EL", 0x6EC }, +{ "Cyrillic_EM", 0x6ED }, +{ "Cyrillic_EN", 0x6EE }, +{ "Cyrillic_O", 0x6EF }, +{ "Cyrillic_PE", 0x6F0 }, +{ "Cyrillic_YA", 0x6F1 }, +{ "Cyrillic_ER", 0x6F2 }, +{ "Cyrillic_ES", 0x6F3 }, +{ "Cyrillic_TE", 0x6F4 }, +{ "Cyrillic_U", 0x6F5 }, +{ "Cyrillic_ZHE", 0x6F6 }, +{ "Cyrillic_VE", 0x6F7 }, +{ "Cyrillic_SOFTSIGN", 0x6F8 }, +{ "Cyrillic_YERU", 0x6F9 }, +{ "Cyrillic_ZE", 0x6FA }, +{ "Cyrillic_SHA", 0x6FB }, +{ "Cyrillic_E", 0x6FC }, +{ "Cyrillic_SHCHA", 0x6FD }, +{ "Cyrillic_CHE", 0x6FE }, +{ "Cyrillic_HARDSIGN", 0x6FF }, +{ "Greek_ALPHAaccent", 0x7A1 }, +{ "Greek_EPSILONaccent", 0x7A2 }, +{ "Greek_ETAaccent", 0x7A3 }, +{ "Greek_IOTAaccent", 0x7A4 }, +{ "Greek_IOTAdieresis", 0x7A5 }, +{ "Greek_IOTAdiaeresis", 0x7A5 }, +{ "Greek_IOTAaccentdiaeresis", 0x7A6 }, +{ "Greek_OMICRONaccent", 0x7A7 }, +{ "Greek_UPSILONaccent", 0x7A8 }, +{ "Greek_UPSILONdieresis", 0x7A9 }, +{ "Greek_UPSILONaccentdieresis", 0x7AA }, +{ "Greek_OMEGAaccent", 0x7AB }, +{ "Greek_accentdieresis", 0x7AE }, +{ "Greek_horizbar", 0x7AF }, +{ "Greek_alphaaccent", 0x7B1 }, +{ "Greek_epsilonaccent", 0x7B2 }, +{ "Greek_etaaccent", 0x7B3 }, +{ "Greek_iotaaccent", 0x7B4 }, +{ "Greek_iotadieresis", 0x7B5 }, +{ "Greek_iotaaccentdieresis", 0x7B6 }, +{ "Greek_omicronaccent", 0x7B7 }, +{ "Greek_upsilonaccent", 0x7B8 }, +{ "Greek_upsilondieresis", 0x7B9 }, +{ "Greek_upsilonaccentdieresis", 0x7BA }, +{ "Greek_omegaaccent", 0x7BB }, +{ "Greek_ALPHA", 0x7C1 }, +{ "Greek_BETA", 0x7C2 }, +{ "Greek_GAMMA", 0x7C3 }, +{ "Greek_DELTA", 0x7C4 }, +{ "Greek_EPSILON", 0x7C5 }, +{ "Greek_ZETA", 0x7C6 }, +{ "Greek_ETA", 0x7C7 }, +{ "Greek_THETA", 0x7C8 }, +{ "Greek_IOTA", 0x7C9 }, +{ "Greek_KAPPA", 0x7CA }, +{ "Greek_LAMDA", 0x7CB }, +{ "Greek_LAMBDA", 0x7CB }, +{ "Greek_MU", 0x7CC }, +{ "Greek_NU", 0x7CD }, +{ "Greek_XI", 0x7CE }, +{ "Greek_OMICRON", 0x7CF }, +{ "Greek_PI", 0x7D0 }, +{ "Greek_RHO", 0x7D1 }, +{ "Greek_SIGMA", 0x7D2 }, +{ "Greek_TAU", 0x7D4 }, +{ "Greek_UPSILON", 0x7D5 }, +{ "Greek_PHI", 0x7D6 }, +{ "Greek_CHI", 0x7D7 }, +{ "Greek_PSI", 0x7D8 }, +{ "Greek_OMEGA", 0x7D9 }, +{ "Greek_alpha", 0x7E1 }, +{ "Greek_beta", 0x7E2 }, +{ "Greek_gamma", 0x7E3 }, +{ "Greek_delta", 0x7E4 }, +{ "Greek_epsilon", 0x7E5 }, +{ "Greek_zeta", 0x7E6 }, +{ "Greek_eta", 0x7E7 }, +{ "Greek_theta", 0x7E8 }, +{ "Greek_iota", 0x7E9 }, +{ "Greek_kappa", 0x7EA }, +{ "Greek_lamda", 0x7EB }, +{ "Greek_lambda", 0x7EB }, +{ "Greek_mu", 0x7EC }, +{ "Greek_nu", 0x7ED }, +{ "Greek_xi", 0x7EE }, +{ "Greek_omicron", 0x7EF }, +{ "Greek_pi", 0x7F0 }, +{ "Greek_rho", 0x7F1 }, +{ "Greek_sigma", 0x7F2 }, +{ "Greek_finalsmallsigma", 0x7F3 }, +{ "Greek_tau", 0x7F4 }, +{ "Greek_upsilon", 0x7F5 }, +{ "Greek_phi", 0x7F6 }, +{ "Greek_chi", 0x7F7 }, +{ "Greek_psi", 0x7F8 }, +{ "Greek_omega", 0x7F9 }, { "Greek_switch", 0xFF7E }, -{ "leftradical", 0x8a1 }, -{ "topleftradical", 0x8a2 }, -{ "horizconnector", 0x8a3 }, -{ "topintegral", 0x8a4 }, -{ "botintegral", 0x8a5 }, -{ "vertconnector", 0x8a6 }, -{ "topleftsqbracket", 0x8a7 }, -{ "botleftsqbracket", 0x8a8 }, -{ "toprightsqbracket", 0x8a9 }, -{ "botrightsqbracket", 0x8aa }, -{ "topleftparens", 0x8ab }, -{ "botleftparens", 0x8ac }, -{ "toprightparens", 0x8ad }, -{ "botrightparens", 0x8ae }, -{ "leftmiddlecurlybrace", 0x8af }, -{ "rightmiddlecurlybrace", 0x8b0 }, -{ "topleftsummation", 0x8b1 }, -{ "botleftsummation", 0x8b2 }, -{ "topvertsummationconnector", 0x8b3 }, -{ "botvertsummationconnector", 0x8b4 }, -{ "toprightsummation", 0x8b5 }, -{ "botrightsummation", 0x8b6 }, -{ "rightmiddlesummation", 0x8b7 }, -{ "lessthanequal", 0x8bc }, -{ "notequal", 0x8bd }, -{ "greaterthanequal", 0x8be }, -{ "integral", 0x8bf }, -{ "therefore", 0x8c0 }, -{ "variation", 0x8c1 }, -{ "infinity", 0x8c2 }, -{ "nabla", 0x8c5 }, -{ "approximate", 0x8c8 }, -{ "similarequal", 0x8c9 }, -{ "ifonlyif", 0x8cd }, -{ "implies", 0x8ce }, -{ "identical", 0x8cf }, -{ "radical", 0x8d6 }, -{ "includedin", 0x8da }, -{ "includes", 0x8db }, -{ "intersection", 0x8dc }, -{ "union", 0x8dd }, -{ "logicaland", 0x8de }, -{ "logicalor", 0x8df }, -{ "partialderivative", 0x8ef }, -{ "function", 0x8f6 }, -{ "leftarrow", 0x8fb }, -{ "uparrow", 0x8fc }, -{ "rightarrow", 0x8fd }, -{ "downarrow", 0x8fe }, -{ "blank", 0x9df }, -{ "soliddiamond", 0x9e0 }, -{ "checkerboard", 0x9e1 }, -{ "ht", 0x9e2 }, -{ "ff", 0x9e3 }, -{ "cr", 0x9e4 }, -{ "lf", 0x9e5 }, -{ "nl", 0x9e8 }, -{ "vt", 0x9e9 }, -{ "lowrightcorner", 0x9ea }, -{ "uprightcorner", 0x9eb }, -{ "upleftcorner", 0x9ec }, -{ "lowleftcorner", 0x9ed }, -{ "crossinglines", 0x9ee }, -{ "horizlinescan1", 0x9ef }, -{ "horizlinescan3", 0x9f0 }, -{ "horizlinescan5", 0x9f1 }, -{ "horizlinescan7", 0x9f2 }, -{ "horizlinescan9", 0x9f3 }, -{ "leftt", 0x9f4 }, -{ "rightt", 0x9f5 }, -{ "bott", 0x9f6 }, -{ "topt", 0x9f7 }, -{ "vertbar", 0x9f8 }, -{ "emspace", 0xaa1 }, -{ "enspace", 0xaa2 }, -{ "em3space", 0xaa3 }, -{ "em4space", 0xaa4 }, -{ "digitspace", 0xaa5 }, -{ "punctspace", 0xaa6 }, -{ "thinspace", 0xaa7 }, -{ "hairspace", 0xaa8 }, -{ "emdash", 0xaa9 }, -{ "endash", 0xaaa }, -{ "signifblank", 0xaac }, -{ "ellipsis", 0xaae }, -{ "doubbaselinedot", 0xaaf }, -{ "onethird", 0xab0 }, -{ "twothirds", 0xab1 }, -{ "onefifth", 0xab2 }, -{ "twofifths", 0xab3 }, -{ "threefifths", 0xab4 }, -{ "fourfifths", 0xab5 }, -{ "onesixth", 0xab6 }, -{ "fivesixths", 0xab7 }, -{ "careof", 0xab8 }, -{ "figdash", 0xabb }, -{ "leftanglebracket", 0xabc }, -{ "decimalpoint", 0xabd }, -{ "rightanglebracket", 0xabe }, -{ "marker", 0xabf }, -{ "oneeighth", 0xac3 }, -{ "threeeighths", 0xac4 }, -{ "fiveeighths", 0xac5 }, -{ "seveneighths", 0xac6 }, -{ "trademark", 0xac9 }, -{ "signaturemark", 0xaca }, -{ "trademarkincircle", 0xacb }, -{ "leftopentriangle", 0xacc }, -{ "rightopentriangle", 0xacd }, -{ "emopencircle", 0xace }, -{ "emopenrectangle", 0xacf }, -{ "leftsinglequotemark", 0xad0 }, -{ "rightsinglequotemark", 0xad1 }, -{ "leftdoublequotemark", 0xad2 }, -{ "rightdoublequotemark", 0xad3 }, -{ "prescription", 0xad4 }, -{ "minutes", 0xad6 }, -{ "seconds", 0xad7 }, -{ "latincross", 0xad9 }, -{ "hexagram", 0xada }, -{ "filledrectbullet", 0xadb }, -{ "filledlefttribullet", 0xadc }, -{ "filledrighttribullet", 0xadd }, -{ "emfilledcircle", 0xade }, -{ "emfilledrect", 0xadf }, -{ "enopencircbullet", 0xae0 }, -{ "enopensquarebullet", 0xae1 }, -{ "openrectbullet", 0xae2 }, -{ "opentribulletup", 0xae3 }, -{ "opentribulletdown", 0xae4 }, -{ "openstar", 0xae5 }, -{ "enfilledcircbullet", 0xae6 }, -{ "enfilledsqbullet", 0xae7 }, -{ "filledtribulletup", 0xae8 }, -{ "filledtribulletdown", 0xae9 }, -{ "leftpointer", 0xaea }, -{ "rightpointer", 0xaeb }, -{ "club", 0xaec }, -{ "diamond", 0xaed }, -{ "heart", 0xaee }, -{ "maltesecross", 0xaf0 }, -{ "dagger", 0xaf1 }, -{ "doubledagger", 0xaf2 }, -{ "checkmark", 0xaf3 }, -{ "ballotcross", 0xaf4 }, -{ "musicalsharp", 0xaf5 }, -{ "musicalflat", 0xaf6 }, -{ "malesymbol", 0xaf7 }, -{ "femalesymbol", 0xaf8 }, -{ "telephone", 0xaf9 }, -{ "telephonerecorder", 0xafa }, -{ "phonographcopyright", 0xafb }, -{ "caret", 0xafc }, -{ "singlelowquotemark", 0xafd }, -{ "doublelowquotemark", 0xafe }, -{ "cursor", 0xaff }, -{ "leftcaret", 0xba3 }, -{ "rightcaret", 0xba6 }, -{ "downcaret", 0xba8 }, -{ "upcaret", 0xba9 }, -{ "overbar", 0xbc0 }, -{ "downtack", 0xbc2 }, -{ "upshoe", 0xbc3 }, -{ "downstile", 0xbc4 }, -{ "underbar", 0xbc6 }, -{ "jot", 0xbca }, -{ "quad", 0xbcc }, -{ "uptack", 0xbce }, -{ "circle", 0xbcf }, -{ "upstile", 0xbd3 }, -{ "downshoe", 0xbd6 }, -{ "rightshoe", 0xbd8 }, -{ "leftshoe", 0xbda }, -{ "lefttack", 0xbdc }, -{ "righttack", 0xbfc }, -{ "hebrew_aleph", 0xce0 }, -{ "hebrew_beth", 0xce1 }, -{ "hebrew_gimmel", 0xce2 }, -{ "hebrew_daleth", 0xce3 }, -{ "hebrew_he", 0xce4 }, -{ "hebrew_waw", 0xce5 }, -{ "hebrew_zayin", 0xce6 }, -{ "hebrew_het", 0xce7 }, -{ "hebrew_teth", 0xce8 }, -{ "hebrew_yod", 0xce9 }, -{ "hebrew_finalkaph", 0xcea }, -{ "hebrew_kaph", 0xceb }, -{ "hebrew_lamed", 0xcec }, -{ "hebrew_finalmem", 0xced }, -{ "hebrew_mem", 0xcee }, -{ "hebrew_finalnun", 0xcef }, -{ "hebrew_nun", 0xcf0 }, -{ "hebrew_samekh", 0xcf1 }, -{ "hebrew_ayin", 0xcf2 }, -{ "hebrew_finalpe", 0xcf3 }, -{ "hebrew_pe", 0xcf4 }, -{ "hebrew_finalzadi", 0xcf5 }, -{ "hebrew_zadi", 0xcf6 }, -{ "hebrew_kuf", 0xcf7 }, -{ "hebrew_resh", 0xcf8 }, -{ "hebrew_shin", 0xcf9 }, -{ "hebrew_taf", 0xcfa }, +{ "leftradical", 0x8A1 }, +{ "topleftradical", 0x8A2 }, +{ "horizconnector", 0x8A3 }, +{ "topintegral", 0x8A4 }, +{ "botintegral", 0x8A5 }, +{ "vertconnector", 0x8A6 }, +{ "topleftsqbracket", 0x8A7 }, +{ "botleftsqbracket", 0x8A8 }, +{ "toprightsqbracket", 0x8A9 }, +{ "botrightsqbracket", 0x8AA }, +{ "topleftparens", 0x8AB }, +{ "botleftparens", 0x8AC }, +{ "toprightparens", 0x8AD }, +{ "botrightparens", 0x8AE }, +{ "leftmiddlecurlybrace", 0x8AF }, +{ "rightmiddlecurlybrace", 0x8B0 }, +{ "topleftsummation", 0x8B1 }, +{ "botleftsummation", 0x8B2 }, +{ "topvertsummationconnector", 0x8B3 }, +{ "botvertsummationconnector", 0x8B4 }, +{ "toprightsummation", 0x8B5 }, +{ "botrightsummation", 0x8B6 }, +{ "rightmiddlesummation", 0x8B7 }, +{ "lessthanequal", 0x8BC }, +{ "notequal", 0x8BD }, +{ "greaterthanequal", 0x8BE }, +{ "integral", 0x8BF }, +{ "therefore", 0x8C0 }, +{ "variation", 0x8C1 }, +{ "infinity", 0x8C2 }, +{ "nabla", 0x8C5 }, +{ "approximate", 0x8C8 }, +{ "similarequal", 0x8C9 }, +{ "ifonlyif", 0x8CD }, +{ "implies", 0x8CE }, +{ "identical", 0x8CF }, +{ "radical", 0x8D6 }, +{ "includedin", 0x8DA }, +{ "includes", 0x8DB }, +{ "intersection", 0x8DC }, +{ "union", 0x8DD }, +{ "logicaland", 0x8DE }, +{ "logicalor", 0x8DF }, +{ "partialderivative", 0x8EF }, +{ "function", 0x8F6 }, +{ "leftarrow", 0x8FB }, +{ "uparrow", 0x8FC }, +{ "rightarrow", 0x8FD }, +{ "downarrow", 0x8FE }, +{ "blank", 0x9DF }, +{ "soliddiamond", 0x9E0 }, +{ "checkerboard", 0x9E1 }, +{ "ht", 0x9E2 }, +{ "ff", 0x9E3 }, +{ "cr", 0x9E4 }, +{ "lf", 0x9E5 }, +{ "nl", 0x9E8 }, +{ "vt", 0x9E9 }, +{ "lowrightcorner", 0x9EA }, +{ "uprightcorner", 0x9EB }, +{ "upleftcorner", 0x9EC }, +{ "lowleftcorner", 0x9ED }, +{ "crossinglines", 0x9EE }, +{ "horizlinescan1", 0x9EF }, +{ "horizlinescan3", 0x9F0 }, +{ "horizlinescan5", 0x9F1 }, +{ "horizlinescan7", 0x9F2 }, +{ "horizlinescan9", 0x9F3 }, +{ "leftt", 0x9F4 }, +{ "rightt", 0x9F5 }, +{ "bott", 0x9F6 }, +{ "topt", 0x9F7 }, +{ "vertbar", 0x9F8 }, +{ "emspace", 0xAA1 }, +{ "enspace", 0xAA2 }, +{ "em3space", 0xAA3 }, +{ "em4space", 0xAA4 }, +{ "digitspace", 0xAA5 }, +{ "punctspace", 0xAA6 }, +{ "thinspace", 0xAA7 }, +{ "hairspace", 0xAA8 }, +{ "emdash", 0xAA9 }, +{ "endash", 0xAAA }, +{ "signifblank", 0xAAC }, +{ "ellipsis", 0xAAE }, +{ "doubbaselinedot", 0xAAF }, +{ "onethird", 0xAB0 }, +{ "twothirds", 0xAB1 }, +{ "onefifth", 0xAB2 }, +{ "twofifths", 0xAB3 }, +{ "threefifths", 0xAB4 }, +{ "fourfifths", 0xAB5 }, +{ "onesixth", 0xAB6 }, +{ "fivesixths", 0xAB7 }, +{ "careof", 0xAB8 }, +{ "figdash", 0xABB }, +{ "leftanglebracket", 0xABC }, +{ "decimalpoint", 0xABD }, +{ "rightanglebracket", 0xABE }, +{ "marker", 0xABF }, +{ "oneeighth", 0xAC3 }, +{ "threeeighths", 0xAC4 }, +{ "fiveeighths", 0xAC5 }, +{ "seveneighths", 0xAC6 }, +{ "trademark", 0xAC9 }, +{ "signaturemark", 0xACA }, +{ "trademarkincircle", 0xACB }, +{ "leftopentriangle", 0xACC }, +{ "rightopentriangle", 0xACD }, +{ "emopencircle", 0xACE }, +{ "emopenrectangle", 0xACF }, +{ "leftsinglequotemark", 0xAD0 }, +{ "rightsinglequotemark", 0xAD1 }, +{ "leftdoublequotemark", 0xAD2 }, +{ "rightdoublequotemark", 0xAD3 }, +{ "prescription", 0xAD4 }, +{ "permille", 0xAD5 }, +{ "minutes", 0xAD6 }, +{ "seconds", 0xAD7 }, +{ "latincross", 0xAD9 }, +{ "hexagram", 0xADA }, +{ "filledrectbullet", 0xADB }, +{ "filledlefttribullet", 0xADC }, +{ "filledrighttribullet", 0xADD }, +{ "emfilledcircle", 0xADE }, +{ "emfilledrect", 0xADF }, +{ "enopencircbullet", 0xAE0 }, +{ "enopensquarebullet", 0xAE1 }, +{ "openrectbullet", 0xAE2 }, +{ "opentribulletup", 0xAE3 }, +{ "opentribulletdown", 0xAE4 }, +{ "openstar", 0xAE5 }, +{ "enfilledcircbullet", 0xAE6 }, +{ "enfilledsqbullet", 0xAE7 }, +{ "filledtribulletup", 0xAE8 }, +{ "filledtribulletdown", 0xAE9 }, +{ "leftpointer", 0xAEA }, +{ "rightpointer", 0xAEB }, +{ "club", 0xAEC }, +{ "diamond", 0xAED }, +{ "heart", 0xAEE }, +{ "maltesecross", 0xAF0 }, +{ "dagger", 0xAF1 }, +{ "doubledagger", 0xAF2 }, +{ "checkmark", 0xAF3 }, +{ "ballotcross", 0xAF4 }, +{ "musicalsharp", 0xAF5 }, +{ "musicalflat", 0xAF6 }, +{ "malesymbol", 0xAF7 }, +{ "femalesymbol", 0xAF8 }, +{ "telephone", 0xAF9 }, +{ "telephonerecorder", 0xAFA }, +{ "phonographcopyright", 0xAFB }, +{ "caret", 0xAFC }, +{ "singlelowquotemark", 0xAFD }, +{ "doublelowquotemark", 0xAFE }, +{ "cursor", 0xAFF }, +{ "leftcaret", 0xBA3 }, +{ "rightcaret", 0xBA6 }, +{ "downcaret", 0xBA8 }, +{ "upcaret", 0xBA9 }, +{ "overbar", 0xBC0 }, +{ "downtack", 0xBC2 }, +{ "upshoe", 0xBC3 }, +{ "downstile", 0xBC4 }, +{ "underbar", 0xBC6 }, +{ "jot", 0xBCA }, +{ "quad", 0xBCC }, +{ "uptack", 0xBCE }, +{ "circle", 0xBCF }, +{ "upstile", 0xBD3 }, +{ "downshoe", 0xBD6 }, +{ "rightshoe", 0xBD8 }, +{ "leftshoe", 0xBDA }, +{ "lefttack", 0xBDC }, +{ "righttack", 0xBFC }, +{ "hebrew_doublelowline", 0xCDF }, +{ "hebrew_aleph", 0xCE0 }, +{ "hebrew_bet", 0xCE1 }, +{ "hebrew_beth", 0xCE1 }, +{ "hebrew_gimel", 0xCE2 }, +{ "hebrew_gimmel", 0xCE2 }, +{ "hebrew_dalet", 0xCE3 }, +{ "hebrew_daleth", 0xCE3 }, +{ "hebrew_he", 0xCE4 }, +{ "hebrew_waw", 0xCE5 }, +{ "hebrew_zain", 0xCE6 }, +{ "hebrew_zayin", 0xCE6 }, +{ "hebrew_chet", 0xCE7 }, +{ "hebrew_het", 0xCE7 }, +{ "hebrew_tet", 0xCE8 }, +{ "hebrew_teth", 0xCE8 }, +{ "hebrew_yod", 0xCE9 }, +{ "hebrew_finalkaph", 0xCEA }, +{ "hebrew_kaph", 0xCEB }, +{ "hebrew_lamed", 0xCEC }, +{ "hebrew_finalmem", 0xCED }, +{ "hebrew_mem", 0xCEE }, +{ "hebrew_finalnun", 0xCEF }, +{ "hebrew_nun", 0xCF0 }, +{ "hebrew_samech", 0xCF1 }, +{ "hebrew_samekh", 0xCF1 }, +{ "hebrew_ayin", 0xCF2 }, +{ "hebrew_finalpe", 0xCF3 }, +{ "hebrew_pe", 0xCF4 }, +{ "hebrew_finalzade", 0xCF5 }, +{ "hebrew_finalzadi", 0xCF5 }, +{ "hebrew_zade", 0xCF6 }, +{ "hebrew_zadi", 0xCF6 }, +{ "hebrew_qoph", 0xCF7 }, +{ "hebrew_kuf", 0xCF7 }, +{ "hebrew_resh", 0xCF8 }, +{ "hebrew_shin", 0xCF9 }, +{ "hebrew_taw", 0xCFA }, +{ "hebrew_taf", 0xCFA }, { "Hebrew_switch", 0xFF7E }, +{ "XF86ModeLock", 0x1008FF01 }, +{ "XF86MonBrightnessUp", 0x1008FF02 }, +{ "XF86MonBrightnessDown", 0x1008FF03 }, +{ "XF86KbdLightOnOff", 0x1008FF04 }, +{ "XF86KbdBrightnessUp", 0x1008FF05 }, +{ "XF86KbdBrightnessDown", 0x1008FF06 }, +{ "XF86MonBrightnessCycle", 0x1008FF07 }, +{ "XF86Standby", 0x1008FF10 }, { "XF86AudioLowerVolume", 0x1008FF11 }, { "XF86AudioMute", 0x1008FF12 }, { "XF86AudioRaiseVolume", 0x1008FF13 }, @@ -937,3 +1027,171 @@ { "XF86AudioStop", 0x1008FF15 }, { "XF86AudioPrev", 0x1008FF16 }, { "XF86AudioNext", 0x1008FF17 }, +{ "XF86HomePage", 0x1008FF18 }, +{ "XF86Mail", 0x1008FF19 }, +{ "XF86Start", 0x1008FF1A }, +{ "XF86Search", 0x1008FF1B }, +{ "XF86AudioRecord", 0x1008FF1C }, +{ "XF86Calculator", 0x1008FF1D }, +{ "XF86Memo", 0x1008FF1E }, +{ "XF86ToDoList", 0x1008FF1F }, +{ "XF86Calendar", 0x1008FF20 }, +{ "XF86PowerDown", 0x1008FF21 }, +{ "XF86ContrastAdjust", 0x1008FF22 }, +{ "XF86RockerUp", 0x1008FF23 }, +{ "XF86RockerDown", 0x1008FF24 }, +{ "XF86RockerEnter", 0x1008FF25 }, +{ "XF86Back", 0x1008FF26 }, +{ "XF86Forward", 0x1008FF27 }, +{ "XF86Stop", 0x1008FF28 }, +{ "XF86Refresh", 0x1008FF29 }, +{ "XF86PowerOff", 0x1008FF2A }, +{ "XF86WakeUp", 0x1008FF2B }, +{ "XF86Eject", 0x1008FF2C }, +{ "XF86ScreenSaver", 0x1008FF2D }, +{ "XF86WWW", 0x1008FF2E }, +{ "XF86Sleep", 0x1008FF2F }, +{ "XF86Favorites", 0x1008FF30 }, +{ "XF86AudioPause", 0x1008FF31 }, +{ "XF86AudioMedia", 0x1008FF32 }, +{ "XF86MyComputer", 0x1008FF33 }, +{ "XF86VendorHome", 0x1008FF34 }, +{ "XF86LightBulb", 0x1008FF35 }, +{ "XF86Shop", 0x1008FF36 }, +{ "XF86History", 0x1008FF37 }, +{ "XF86OpenURL", 0x1008FF38 }, +{ "XF86AddFavorite", 0x1008FF39 }, +{ "XF86HotLinks", 0x1008FF3A }, +{ "XF86BrightnessAdjust", 0x1008FF3B }, +{ "XF86Finance", 0x1008FF3C }, +{ "XF86Community", 0x1008FF3D }, +{ "XF86AudioRewind", 0x1008FF3E }, +{ "XF86BackForward", 0x1008FF3F }, +{ "XF86Launch0", 0x1008FF40 }, +{ "XF86Launch1", 0x1008FF41 }, +{ "XF86Launch2", 0x1008FF42 }, +{ "XF86Launch3", 0x1008FF43 }, +{ "XF86Launch4", 0x1008FF44 }, +{ "XF86Launch5", 0x1008FF45 }, +{ "XF86Launch6", 0x1008FF46 }, +{ "XF86Launch7", 0x1008FF47 }, +{ "XF86Launch8", 0x1008FF48 }, +{ "XF86Launch9", 0x1008FF49 }, +{ "XF86LaunchA", 0x1008FF4A }, +{ "XF86LaunchB", 0x1008FF4B }, +{ "XF86LaunchC", 0x1008FF4C }, +{ "XF86LaunchD", 0x1008FF4D }, +{ "XF86LaunchE", 0x1008FF4E }, +{ "XF86LaunchF", 0x1008FF4F }, +{ "XF86ApplicationLeft", 0x1008FF50 }, +{ "XF86ApplicationRight", 0x1008FF51 }, +{ "XF86Book", 0x1008FF52 }, +{ "XF86CD", 0x1008FF53 }, +{ "XF86Calculater", 0x1008FF54 }, +{ "XF86Clear", 0x1008FF55 }, +{ "XF86Close", 0x1008FF56 }, +{ "XF86Copy", 0x1008FF57 }, +{ "XF86Cut", 0x1008FF58 }, +{ "XF86Display", 0x1008FF59 }, +{ "XF86DOS", 0x1008FF5A }, +{ "XF86Documents", 0x1008FF5B }, +{ "XF86Excel", 0x1008FF5C }, +{ "XF86Explorer", 0x1008FF5D }, +{ "XF86Game", 0x1008FF5E }, +{ "XF86Go", 0x1008FF5F }, +{ "XF86iTouch", 0x1008FF60 }, +{ "XF86LogOff", 0x1008FF61 }, +{ "XF86Market", 0x1008FF62 }, +{ "XF86Meeting", 0x1008FF63 }, +{ "XF86MenuKB", 0x1008FF65 }, +{ "XF86MenuPB", 0x1008FF66 }, +{ "XF86MySites", 0x1008FF67 }, +{ "XF86New", 0x1008FF68 }, +{ "XF86News", 0x1008FF69 }, +{ "XF86OfficeHome", 0x1008FF6A }, +{ "XF86Open", 0x1008FF6B }, +{ "XF86Option", 0x1008FF6C }, +{ "XF86Paste", 0x1008FF6D }, +{ "XF86Phone", 0x1008FF6E }, +{ "XF86Q", 0x1008FF70 }, +{ "XF86Reply", 0x1008FF72 }, +{ "XF86Reload", 0x1008FF73 }, +{ "XF86RotateWindows", 0x1008FF74 }, +{ "XF86RotationPB", 0x1008FF75 }, +{ "XF86RotationKB", 0x1008FF76 }, +{ "XF86Save", 0x1008FF77 }, +{ "XF86ScrollUp", 0x1008FF78 }, +{ "XF86ScrollDown", 0x1008FF79 }, +{ "XF86ScrollClick", 0x1008FF7A }, +{ "XF86Send", 0x1008FF7B }, +{ "XF86Spell", 0x1008FF7C }, +{ "XF86SplitScreen", 0x1008FF7D }, +{ "XF86Support", 0x1008FF7E }, +{ "XF86TaskPane", 0x1008FF7F }, +{ "XF86Terminal", 0x1008FF80 }, +{ "XF86Tools", 0x1008FF81 }, +{ "XF86Travel", 0x1008FF82 }, +{ "XF86UserPB", 0x1008FF84 }, +{ "XF86User1KB", 0x1008FF85 }, +{ "XF86User2KB", 0x1008FF86 }, +{ "XF86Video", 0x1008FF87 }, +{ "XF86WheelButton", 0x1008FF88 }, +{ "XF86Word", 0x1008FF89 }, +{ "XF86Xfer", 0x1008FF8A }, +{ "XF86ZoomIn", 0x1008FF8B }, +{ "XF86ZoomOut", 0x1008FF8C }, +{ "XF86Away", 0x1008FF8D }, +{ "XF86Messenger", 0x1008FF8E }, +{ "XF86WebCam", 0x1008FF8F }, +{ "XF86MailForward", 0x1008FF90 }, +{ "XF86Pictures", 0x1008FF91 }, +{ "XF86Music", 0x1008FF92 }, +{ "XF86Battery", 0x1008FF93 }, +{ "XF86Bluetooth", 0x1008FF94 }, +{ "XF86WLAN", 0x1008FF95 }, +{ "XF86UWB", 0x1008FF96 }, +{ "XF86AudioForward", 0x1008FF97 }, +{ "XF86AudioRepeat", 0x1008FF98 }, +{ "XF86AudioRandomPlay", 0x1008FF99 }, +{ "XF86Subtitle", 0x1008FF9A }, +{ "XF86AudioCycleTrack", 0x1008FF9B }, +{ "XF86CycleAngle", 0x1008FF9C }, +{ "XF86FrameBack", 0x1008FF9D }, +{ "XF86FrameForward", 0x1008FF9E }, +{ "XF86Time", 0x1008FF9F }, +{ "XF86Select", 0x1008FFA0 }, +{ "XF86View", 0x1008FFA1 }, +{ "XF86TopMenu", 0x1008FFA2 }, +{ "XF86Red", 0x1008FFA3 }, +{ "XF86Green", 0x1008FFA4 }, +{ "XF86Yellow", 0x1008FFA5 }, +{ "XF86Blue", 0x1008FFA6 }, +{ "XF86Suspend", 0x1008FFA7 }, +{ "XF86Hibernate", 0x1008FFA8 }, +{ "XF86TouchpadToggle", 0x1008FFA9 }, +{ "XF86TouchpadOn", 0x1008FFB0 }, +{ "XF86TouchpadOff", 0x1008FFB1 }, +{ "XF86AudioMicMute", 0x1008FFB2 }, +{ "XF86Keyboard", 0x1008FFB3 }, +{ "XF86WWAN", 0x1008FFB4 }, +{ "XF86RFKill", 0x1008FFB5 }, +{ "XF86AudioPreset", 0x1008FFB6 }, +{ "XF86RotationLockToggle", 0x1008FFB7 }, +{ "XF86Switch_VT_1", 0x1008FE01 }, +{ "XF86Switch_VT_2", 0x1008FE02 }, +{ "XF86Switch_VT_3", 0x1008FE03 }, +{ "XF86Switch_VT_4", 0x1008FE04 }, +{ "XF86Switch_VT_5", 0x1008FE05 }, +{ "XF86Switch_VT_6", 0x1008FE06 }, +{ "XF86Switch_VT_7", 0x1008FE07 }, +{ "XF86Switch_VT_8", 0x1008FE08 }, +{ "XF86Switch_VT_9", 0x1008FE09 }, +{ "XF86Switch_VT_10", 0x1008FE0A }, +{ "XF86Switch_VT_11", 0x1008FE0B }, +{ "XF86Switch_VT_12", 0x1008FE0C }, +{ "XF86Ungrab", 0x1008FE20 }, +{ "XF86ClearGrab", 0x1008FE21 }, +{ "XF86Next_VMode", 0x1008FE22 }, +{ "XF86Prev_VMode", 0x1008FE23 }, +{ "XF86LogWindowTree", 0x1008FE24 }, +{ "XF86LogGrabInfo", 0x1008FE25 }, diff --git a/generic/tk.h b/generic/tk.h index c94882c..ce5902d 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -75,10 +75,10 @@ #define TK_MAJOR_VERSION 8 #define TK_MINOR_VERSION 6 #define TK_RELEASE_LEVEL TCL_FINAL_RELEASE -#define TK_RELEASE_SERIAL 9 +#define TK_RELEASE_SERIAL 10 #define TK_VERSION "8.6" -#define TK_PATCH_LEVEL "8.6.9" +#define TK_PATCH_LEVEL "8.6.10" /* * A special definition used to allow this header file to be included from @@ -92,13 +92,14 @@ #ifndef RC_INVOKED -#ifndef _XLIB_H +#if !defined(_XLIB_H) && !defined(_X11_XLIB_H_) # include # ifdef MAC_OSX_TK # include # endif #endif -#ifdef __STDC__ +#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \ + || defined(__cplusplus) || defined(_MSC_VER) || defined(__ICC) # include #endif @@ -266,10 +267,10 @@ * Computes number of bytes from beginning of structure to a given field. */ -#ifdef offsetof #define Tk_Offset(type, field) ((int) offsetof(type, field)) -#else -#define Tk_Offset(type, field) ((int) ((char *) &((type *) 0)->field)) +/* Workaround for platforms missing offsetof(), e.g. VC++ 6.0 */ +#ifndef offsetof +# define offsetof(type, field) ((size_t) ((char *) &((type *) 0)->field)) #endif /* @@ -676,7 +677,7 @@ * request. */ Display *display; /* Display the event was read from. */ Window event; /* Window on which event was requested. */ - Window root; /* Root window that the event occured on. */ + Window root; /* Root window that the event occurred on. */ Window subwindow; /* Child window. */ Time time; /* Milliseconds. */ int x, y; /* Pointer x, y coordinates in event @@ -813,10 +814,11 @@ int internalBorderBottom; int minReqWidth; int minReqHeight; - char *dummy20; /* geometryMaster */ #ifdef TK_USE_INPUT_METHODS - int dummy21; + int dummy20; #endif /* TK_USE_INPUT_METHODS */ + char *dummy21; /* geomMgrName */ + Tk_Window dummy22; /* maintainerPtr */ } Tk_FakeWin; /* diff --git a/generic/tk3d.c b/generic/tk3d.c index 87ddf76..987bace 100644 --- a/generic/tk3d.c +++ b/generic/tk3d.c @@ -236,9 +236,9 @@ borderPtr->darkColorPtr = NULL; borderPtr->lightColorPtr = NULL; borderPtr->shadow = None; - borderPtr->bgGC = None; - borderPtr->darkGC = None; - borderPtr->lightGC = None; + borderPtr->bgGC = NULL; + borderPtr->darkGC = NULL; + borderPtr->lightGC = NULL; borderPtr->hashPtr = hashPtr; borderPtr->nextPtr = existingBorderPtr; Tcl_SetHashValue(hashPtr, borderPtr); @@ -374,7 +374,7 @@ { TkBorder * borderPtr = (TkBorder *) border; - if ((borderPtr->lightGC == None) && (which != TK_3D_FLAT_GC)) { + if ((borderPtr->lightGC == NULL) && (which != TK_3D_FLAT_GC)) { TkpGetShadows(borderPtr, tkwin); } if (which == TK_3D_FLAT_GC) { @@ -391,7 +391,7 @@ * compilers happy. */ - return (GC) None; + return NULL; } /* @@ -439,13 +439,13 @@ if (borderPtr->shadow != None) { Tk_FreeBitmap(display, borderPtr->shadow); } - if (borderPtr->bgGC != None) { + if (borderPtr->bgGC != NULL) { Tk_FreeGC(display, borderPtr->bgGC); } - if (borderPtr->darkGC != None) { + if (borderPtr->darkGC != NULL) { Tk_FreeGC(display, borderPtr->darkGC); } - if (borderPtr->lightGC != None) { + if (borderPtr->lightGC != NULL) { Tk_FreeGC(display, borderPtr->lightGC); } if (prevPtr == borderPtr) { @@ -765,7 +765,7 @@ int i, lightOnLeft, dx, dy, parallel, pointsSeen; Display *display = Tk_Display(tkwin); - if (borderPtr->lightGC == None) { + if (borderPtr->lightGC == NULL) { TkpGetShadows(borderPtr, tkwin); } @@ -1315,7 +1315,7 @@ * * Side effects: * If no error occurs, a blank internal format for a border value is - * intialized. The final form cannot be done without a Tk_Window. + * initialized. The final form cannot be done without a Tk_Window. * *---------------------------------------------------------------------- */ diff --git a/generic/tk3d.h b/generic/tk3d.h index 891e927..ec7f7c7 100644 --- a/generic/tk3d.h +++ b/generic/tk3d.h @@ -54,10 +54,10 @@ GC bgGC; /* Used (if necessary) to draw areas in the * background color. */ GC darkGC; /* Used to draw darker parts of the border. - * None means the shadow colors haven't been + * NULL means the shadow colors haven't been * allocated yet.*/ GC lightGC; /* Used to draw lighter parts of the border. - * None means the shadow colors haven't been + * NULL means the shadow colors haven't been * allocated yet. */ Tcl_HashEntry *hashPtr; /* Entry in borderTable (needed in order to * delete structure). */ diff --git a/generic/tkArray.h b/generic/tkArray.h new file mode 100644 index 0000000..65693fe --- /dev/null +++ b/generic/tkArray.h @@ -0,0 +1,610 @@ +/* + * tkArray.h -- + * + * An array is a sequence of items, stored in a contiguous memory region. + * Random access to any item is very fast. New items can be either appended + * or prepended. An array may be traversed in the forward or backward direction. + * + * Copyright (c) 2018-2019 by Gregor Cramer. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +/* + * Note that this file will not be included in header files, it is the purpose + * of this file to be included in source files only. Thus we are not using the + * prefix "Tk_" here for functions, because all the functions have private scope. + */ + +/* + * ------------------------------------------------------------------------------- + * Use the array in the following way: + * ------------------------------------------------------------------------------- + * typedef struct { int key, value; } Pair; + * TK_PTR_ARRAY_DEFINE(MyArray, Pair); + * MyArray *arr = NULL; + * if (MyArray_IsEmpty(arr)) { + * MyArray_Append(&arr, MakePair(1, 2)); + * MyArray_Append(&arr, MakePair(2, 3)); + * for (i = 0; i < MyArray_Size(arr); ++i) { + * Pair *p = MyArray_Get(arr, i); + * printf("%d -> %d\n", p->key, p->value); + * ckfree(p); + * } + * MyArray_Free(&arr); + * assert(arr == NULL); + * } + * ------------------------------------------------------------------------------- + * Or with aggregated elements: + * ------------------------------------------------------------------------------- + * typedef struct { int key, value; } Pair; + * TK_ARRAY_DEFINE(MyArray, Pair); + * Pair p1 = { 1, 2 }; + * Pair p2 = { 2, 3 }; + * MyArray *arr = NULL; + * if (MyArray_IsEmpty(arr)) { + * MyArray_Append(&arr, p1); + * MyArray_Append(&arr, p2); + * for (i = 0; i < MyArray_Size(arr); ++i) { + * const Pair *p = MyArray_Get(arr, i); + * printf("%d -> %d\n", p->key, p->value); + * } + * MyArray_Free(&arr); + * assert(arr == NULL); + * } + * ------------------------------------------------------------------------------- + */ + +/*************************************************************************/ +/* + * Two array types will be provided: + * Use TK_ARRAY_DEFINE if your array is aggregating the elements. Use + * TK_PTR_ARRAY_DEFINE if your array contains pointers to elements. But + * in latter case the array is not responsible for the lifetime of the + * elements. + */ +/*************************************************************************/ +/* + * Array_ElemSize: Returns the memory size for one array element. + */ +/*************************************************************************/ +/* + * Array_BufferSize: Returns the memory size for given number of elements. + */ +/*************************************************************************/ +/* + * Array_IsEmpty: Array is empty? + */ +/*************************************************************************/ +/* + * Array_Size: Number of elements in array. + */ +/*************************************************************************/ +/* + * Array_Capacity: Capacity of given array. This is the maximal number of + * elements fitting into current array memory without resizing the buffer. + */ +/*************************************************************************/ +/* + * Array_SetSize: Set array size, new size must not exceed the capacity of + * the array. This function has to be used with care when increasing the + * array size. + */ +/*************************************************************************/ +/* + * Array_First: Returns position of first element in array. Given array + * may be NULL. + */ +/*************************************************************************/ +/* + * Array_Last: Returns position after last element in array. Given array + * may be empty. + */ +/*************************************************************************/ +/* + * Array_Front: Returns first element in array. Given array must not be + * empty. + */ +/*************************************************************************/ +/* + * Array_Back: Returns last element in array. Given array must not be + * empty. + */ +/*************************************************************************/ +/* + * Array_Resize: Resize buffer of array for given number of elements. The + * array may grow or shrink. Note that this function is not initializing + * the increased buffer. + */ +/*************************************************************************/ +/* + * Array_ResizeAndClear: Resize buffer of array for given number of + * elements. The array may grow or shrink. The increased memory will be + * filled with zeroes. + */ +/*************************************************************************/ +/* + * Array_Clear: Fill specified range with zeroes. + */ +/*************************************************************************/ +/* + * Array_Free: Resize array to size zero. This function will release the + * array buffer. + */ +/*************************************************************************/ +/* + * Array_Append: Insert given element after end of array. + */ +/*************************************************************************/ +/* + * Array_PopBack: Shrink array by one element. Given array must not be + * empty. + */ +/*************************************************************************/ +/* + * Array_Get: Random access to array element at given position. The given + * index must not exceed current array size. + */ +/*************************************************************************/ +/* + * Array_Set: Replace array element at given position with new value. The + * given index must not exceed current array size. + */ +/*************************************************************************/ +/* + * Array_Find: Return index position of element which matches given + * argument. If not found then -1 will be returned. + */ +/*************************************************************************/ + +#ifndef TK_ARRAY_DEFINED +#define TK_ARRAY_DEFINED + +#include "tkInt.h" + +#if defined(__GNUC__) || defined(__clang__) +# define __TK_ARRAY_UNUSED __attribute__((unused)) +#else +# define __TK_ARRAY_UNUSED +#endif + +#define TK_ARRAY_DEFINE(AT, ElemType) /* AT = type of array */ \ +/* ------------------------------------------------------------------------- */ \ +typedef struct AT { \ + size_t size; \ + size_t capacity; \ + ElemType buf[1]; \ +} AT; \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Init(AT *arr) \ +{ \ + assert(arr); \ + arr->size = 0; \ + arr->capacity = 0; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_ElemSize() \ +{ \ + return sizeof(ElemType); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_BufferSize(size_t numElems) \ +{ \ + return numElems*sizeof(ElemType); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static int \ +AT##_IsEmpty(const AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return !arr || arr->size == 0u; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_Size(const AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->size : 0u; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_Capacity(const AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->capacity : 0u; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_First(AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->buf : NULL; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_Last(AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->buf + arr->size : NULL; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_Front(AT *arr) \ +{ \ + assert(arr); \ + assert(arr->size != 0xdeadbeef); \ + assert(!AT##_IsEmpty(arr)); \ + return &arr->buf[0]; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_Back(AT *arr) \ +{ \ + assert(arr); \ + assert(arr->size != 0xdeadbeef); \ + assert(!AT##_IsEmpty(arr)); \ + return &arr->buf[arr->size - 1]; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Resize(AT **arrp, size_t newSize) \ +{ \ + assert(arrp); \ + assert(!*arrp || (*arrp)->size != 0xdeadbeef); \ + if (newSize == 0) { \ + assert(!*arrp || ((*arrp)->size = 0xdeadbeef)); \ + ckfree(*arrp); \ + *arrp = NULL; \ + } else { \ + int init = *arrp == NULL; \ + size_t memSize = AT##_BufferSize(newSize - 1) + sizeof(AT); \ + *arrp = ckrealloc(*arrp, memSize); \ + if (init) { \ + (*arrp)->size = 0; \ + } else if (newSize < (*arrp)->size) { \ + (*arrp)->size = newSize; \ + } \ + (*arrp)->capacity = newSize; \ + } \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Clear(AT *arr, size_t from, size_t to) \ +{ \ + assert(arr); \ + assert(arr->size != 0xdeadbeef); \ + assert(to <= AT##_Capacity(arr)); \ + assert(from <= to); \ + memset(arr->buf + from, 0, AT##_BufferSize(to - from)); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_ResizeAndClear(AT **arrp, size_t newSize) \ +{ \ + size_t oldCapacity; \ + assert(arrp); \ + oldCapacity = *arrp ? (*arrp)->capacity : 0; \ + AT##_Resize(arrp, newSize); \ + if (newSize > oldCapacity) { \ + AT##_Clear(*arrp, oldCapacity, newSize); \ + } \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_SetSize(AT *arr, size_t newSize) \ +{ \ + assert(newSize <= AT##_Capacity(arr)); \ + assert(!arr || arr->size != 0xdeadbeef); \ + if (arr) { \ + arr->size = newSize; \ + } \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Append(AT **arrp, ElemType *elem) \ +{ \ + assert(arrp); \ + if (!*arrp) { \ + AT##_Resize(arrp, 1); \ + } else if ((*arrp)->size == (*arrp)->capacity) { \ + AT##_Resize(arrp, (*arrp)->capacity + ((*arrp)->capacity + 1)/2); \ + } \ + (*arrp)->buf[(*arrp)->size++] = *elem; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_PopBack(AT *arr) \ +{ \ + assert(!AT##_IsEmpty(arr)); \ + return arr->size -= 1; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_Get(const AT *arr, size_t at) \ +{ \ + assert(arr); \ + assert(at < AT##_Size(arr)); \ + return (ElemType *) &arr->buf[at]; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Set(AT *arr, size_t at, ElemType *elem) \ +{ \ + assert(arr); \ + assert(at < AT##_Size(arr)); \ + arr->buf[at] = *elem; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Free(AT **arrp) \ +{ \ + AT##_Resize(arrp, 0); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static int \ +AT##_Find(const AT *arr, const ElemType *elem) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + if (arr) { \ + const ElemType *buf = arr->buf; \ + size_t i; \ + for (i = 0; i < arr->size; ++i) { \ + if (memcmp(&buf[i], elem, sizeof(ElemType)) == 0) { \ + return (int) i; \ + } \ + } \ + } \ + return -1; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static int \ +AT##_Contains(const AT *arr, const ElemType *elem) \ +{ \ + return AT##_Find(arr, elem) != -1; \ +} \ +/* ------------------------------------------------------------------------- */ + +#define TK_PTR_ARRAY_DEFINE(AT, ElemType) /* AT = type of array */ \ +/* ------------------------------------------------------------------------- */ \ +typedef struct AT { \ + size_t size; \ + size_t capacity; \ + ElemType *buf[1]; \ +} AT; \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_ElemSize() \ +{ \ + return sizeof(ElemType); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_BufferSize(size_t numElems) \ +{ \ + return numElems*sizeof(ElemType *); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static int \ +AT##_IsEmpty(const AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return !arr || arr->size == 0; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType ** \ +AT##_First(AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->buf : NULL; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType ** \ +AT##_Last(AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->buf + arr->size : NULL; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_Front(AT *arr) \ +{ \ + assert(arr); \ + assert(arr->size != 0xdeadbeef); \ + assert(!AT##_IsEmpty(arr)); \ + return arr->buf[0]; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_Back(AT *arr) \ +{ \ + assert(arr); \ + assert(arr->size != 0xdeadbeef); \ + assert(!AT##_IsEmpty(arr)); \ + return arr->buf[arr->size - 1]; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_Size(const AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->size : 0; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_Capacity(const AT *arr) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + return arr ? arr->capacity : 0; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Resize(AT **arrp, size_t newCapacity) \ +{ \ + assert(arrp); \ + assert(!*arrp || (*arrp)->size != 0xdeadbeef); \ + if (newCapacity == 0) { \ + assert(!*arrp || ((*arrp)->size = 0xdeadbeef)); \ + ckfree(*arrp); \ + *arrp = NULL; \ + } else { \ + int init = *arrp == NULL; \ + size_t memSize = AT##_BufferSize(newCapacity - 1) + sizeof(AT); \ + *arrp = ckrealloc(*arrp, memSize); \ + if (init) { \ + (*arrp)->size = 0; \ + } else if (newCapacity < (*arrp)->size) { \ + (*arrp)->size = newCapacity; \ + } \ + (*arrp)->capacity = newCapacity; \ + } \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Clear(AT *arr, size_t from, size_t to) \ +{ \ + assert(arr); \ + assert(arr->size != 0xdeadbeef); \ + assert(to <= AT##_Capacity(arr)); \ + assert(from <= to); \ + memset(arr->buf + from, 0, AT##_BufferSize(to - from)); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_ResizeAndClear(AT **arrp, size_t newCapacity) \ +{ \ + size_t oldCapacity; \ + assert(arrp); \ + oldCapacity = *arrp ? (*arrp)->capacity : 0; \ + AT##_Resize(arrp, newCapacity); \ + if (newCapacity > oldCapacity) { \ + AT##_Clear(*arrp, oldCapacity, newCapacity); \ + } \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_SetSize(AT *arr, size_t newSize) \ +{ \ + assert(arr); \ + assert(newSize <= AT##_Capacity(arr)); \ + arr->size = newSize; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Append(AT **arrp, ElemType *elem) \ +{ \ + assert(arrp); \ + if (!*arrp) { \ + AT##_Resize(arrp, 1); \ + } else if ((*arrp)->size == (*arrp)->capacity) { \ + AT##_Resize(arrp, (*arrp)->capacity + ((*arrp)->capacity + 1)/2); \ + } \ + (*arrp)->buf[(*arrp)->size++] = elem; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static size_t \ +AT##_PopBack(AT *arr) \ +{ \ + assert(!AT##_IsEmpty(arr)); \ + return arr->size -= 1; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static ElemType * \ +AT##_Get(const AT *arr, size_t at) \ +{ \ + assert(arr); \ + assert(at < AT##_Size(arr)); \ + return arr->buf[at]; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Set(AT *arr, size_t at, ElemType *elem) \ +{ \ + assert(arr); \ + assert(at < AT##_Size(arr)); \ + arr->buf[at] = elem; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static void \ +AT##_Free(AT **arrp) \ +{ \ + AT##_Resize(arrp, 0); \ +} \ + \ +__TK_ARRAY_UNUSED \ +static int \ +AT##_Find(const AT *arr, const ElemType *elem) \ +{ \ + assert(!arr || arr->size != 0xdeadbeef); \ + if (arr) { \ + ElemType *const *buf = arr->buf; \ + size_t i; \ + for (i = 0; i < arr->size; ++i) { \ + if (buf[i] == elem) { \ + return (int) i; \ + } \ + } \ + } \ + return -1; \ +} \ + \ +__TK_ARRAY_UNUSED \ +static int \ +AT##_Contains(const AT *arr, const ElemType *elem) \ +{ \ + return AT##_Find(arr, elem) != -1; \ +} \ +/* ------------------------------------------------------------------------- */ + +#endif /* TK_ARRAY_DEFINED */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 105 + * End: + * vi:set ts=8 sw=4: + */ diff --git a/generic/tkBind.c b/generic/tkBind.c index af5306b..f65d2ee 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -7,21 +7,40 @@ * Copyright (c) 1989-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998 by Scriptics Corporation. + * Copyright (c) 2018-2019 by Gregor Cramer. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" - -#ifdef _WIN32 +#include "tkDList.h" +#include "tkArray.h" + +#if defined(_WIN32) #include "tkWinInt.h" #elif defined(MAC_OSX_TK) #include "tkMacOSXInt.h" -#else +#else /* if defined(__unix__) */ #include "tkUnixInt.h" #endif +#ifdef NDEBUG +# define DEBUG(expr) +#else +# define DEBUG(expr) expr +#endif + +#ifdef _MSC_VER +/* + * Earlier versions of MSVC don't know snprintf, but _snprintf is compatible. + * Note that sprintf is deprecated. + */ +# define snprintf _snprintf +#endif + +#define SIZE_OF_ARRAY(arr) (sizeof(arr)/sizeof(arr[0])) + /* * File structure: * @@ -29,8 +48,7 @@ * * Init/Free this package. * - * Tcl "bind" command (actually located in tkCmds.c) core implementation, plus - * helpers. + * Tcl "bind" command (actually located in tkCmds.c) core implementation, plus helpers. * * Tcl "event" command implementation, plus helpers. * @@ -38,21 +56,129 @@ * * Non-package-specific helpers. */ + +/* + * In old implementation (the one that used an event ring), and <1><1> were + * equivalent sequences. However it is logical to give higher precedence. + * This can be achieved by setting PREFER_MOST_SPECIALIZED_EVENT to 1. + */ + +#ifndef PREFER_MOST_SPECIALIZED_EVENT +# define PREFER_MOST_SPECIALIZED_EVENT 0 +#endif + +/* + * Traditionally motion events can be combined with buttons in this way: . + * However it should be allowed to express this as in addition. This can be + * achieved by setting SUPPORT_ADDITIONAL_MOTION_SYNTAX to 1. + */ + +#ifndef SUPPORT_ADDITIONAL_MOTION_SYNTAX +# define SUPPORT_ADDITIONAL_MOTION_SYNTAX 0 /* set to 1 if wanted */ +#endif + +/* + * The output for motion events is of the type . This can be changed to become + * instead by setting PRINT_SHORT_MOTION_SYNTAX to 1, however this would be a + * backwards incompatibility. + */ + +#ifndef PRINT_SHORT_MOTION_SYNTAX +# define PRINT_SHORT_MOTION_SYNTAX 0 /* set to 1 if wanted */ +#endif + +#if !SUPPORT_ADDITIONAL_MOTION_SYNTAX +# undef PRINT_SHORT_MOTION_SYNTAX +# define PRINT_SHORT_MOTION_SYNTAX 0 +#endif + +/* + * For debugging only, normally set to zero. + */ + +#ifdef SUPPORT_DEBUGGING +# undef SUPPORT_DEBUGGING +#endif +#define SUPPORT_DEBUGGING 0 + +/* + * Test validity of PSEntry items. + */ + +# define TEST_PSENTRY(psPtr) psPtr->number != 0xdeadbeef +# define MARK_PSENTRY(psPtr) psPtr->number = 0xdeadbeef /* * The following union is used to hold the detail information from an XEvent * (including Tk's XVirtualEvent extension). */ +typedef KeySym Info; + typedef union { - KeySym keySym; /* KeySym that corresponds to xkey.keycode. */ - int button; /* Button that was pressed (xbutton.button). */ - Tk_Uid name; /* Tk_Uid of virtual event. */ - ClientData clientData; /* Used when type of Detail is unknown, and to - * ensure that all bytes of Detail are - * initialized when this structure is used in - * a hash key. */ + Info info; /* This either corresponds to xkey.keycode, or to xbutton.button, + * or is meaningless, depending on event type. */ + Tk_Uid name; /* Tk_Uid of virtual event. */ } Detail; + +/* + * We need an extended event definition. + */ + +typedef struct { + XEvent xev; /* The original event from server. */ + Detail detail; /* Additional information (for hashing). */ + unsigned countAny; /* Count of multi-events, like multi-clicks, or repeated key pressing, + * this count does not depend on detail (keySym or button). */ + unsigned countDetailed; + /* Count of multi-events, like multi-clicks, or repeated key pressing, + * this count considers the detail (keySym or button). */ +} Event; + +/* + * We need a structure providing a list of pattern sequences. + */ + +typedef unsigned EventMask; +typedef unsigned long ModMask; + +struct PatSeq; /* forward declaration */ + +/* We need this array for bookkeeping the last matching modifier mask per pattern. */ +TK_ARRAY_DEFINE(PSModMaskArr, ModMask); + +typedef struct PSEntry { + TK_DLIST_LINKS(PSEntry); /* Makes this struct a double linked list; must be first entry. */ + Window window; /* Window of last match. */ + struct PatSeq* psPtr; /* Pointer to pattern sequence. */ + PSModMaskArr *lastModMaskArr; + /* Last matching modifier mask per pattern (except last pattern). + * Only needed if pattern sequence is not single (more than one + * pattern), and if one of these patterns contains a non-zero + * modifier mask. */ + unsigned count; /* Only promote to next level if this count has reached count of + * pattern. */ + unsigned expired:1; /* Whether this entry is expired, this means it has to be removed + * from promotion list. */ + unsigned keepIt:1; /* Whether to keep this entry, even if expired. */ +} PSEntry; + +/* Defining the whole PSList_* stuff (list of PSEntry items). */ +TK_DLIST_DEFINE(PSList, PSEntry); + +/* Don't keep larger arrays of modifier masks inside PSEntry. */ +#define MAX_MOD_MASK_ARR_SIZE 8 + +/* + * Maps and lookup tables from an event to a list of patterns that match that event. + */ + +typedef struct { + Tcl_HashTable patternTable; /* Keys are PatternTableKey structs, values are (PatSeq *). */ + Tcl_HashTable listTable; /* Keys are PatternTableKey structs, values are (PSList *). */ + PSList entryPool; /* Contains free (unused) list items. */ + unsigned number; /* Needed for enumeration of pattern sequences. */ +} LookupTables; /* * The structure below represents a binding table. A binding table represents @@ -65,49 +191,21 @@ * application with separate event bindings for each (for example, each canvas * widget has a separate binding table for associating events with the items * in the canvas). - * - * Note: it is probably a bad idea to reduce EVENT_BUFFER_SIZE much below 30. - * To see this, consider a triple mouse button click while the Shift key is - * down (and auto-repeating). There may be as many as 3 auto-repeat events - * after each mouse button press or release (see the first large comment block - * within Tk_BindEvent for more on this), for a total of 20 events to cover - * the three button presses and two intervening releases. If you reduce - * EVENT_BUFFER_SIZE too much, shift multi-clicks will be lost. - */ - -/* - * NOTE: The changes which were needed to make Tk work on OSX 10.14 (Mojave) - * also demand that the event ring be a bit bigger. It might be wise to - * augment the current double-click pattern matching by adding a new - * DoubleClick modifier bit which could be set based on the clickCount of the - * Apple NSEvent object. - */ - -#ifndef TK_MAC_OSX - #define EVENT_BUFFER_SIZE 45 -#else - #define EVENT_BUFFER_SIZE 30 -#endif + */ + +/* defining the whole Promotion_* stuff (array of PSList entries) */ +TK_ARRAY_DEFINE(PromArr, PSList); typedef struct Tk_BindingTable_ { - XEvent eventRing[EVENT_BUFFER_SIZE]; - /* Circular queue of recent events (higher - * indices are for more recent events). */ - Detail detailRing[EVENT_BUFFER_SIZE]; - /* "Detail" information (keySym, button, - * Tk_Uid, or 0) for each entry in - * eventRing. */ - int curEvent; /* Index in eventRing of most recent event. - * Newer events have higher indices. */ - Tcl_HashTable patternTable; /* Used to map from an event to a list of - * patterns that may match that event. Keys - * are PatternTableKey structs, values are - * (PatSeq *). */ - Tcl_HashTable objectTable; /* Used to map from an object to a list of - * patterns associated with that object. Keys - * are ClientData, values are (PatSeq *). */ - Tcl_Interp *interp; /* Interpreter in which commands are - * executed. */ + Event eventInfo[TK_LASTEVENT]; + /* Containing the most recent event for every event type. */ + PromArr *promArr; /* Contains the promoted pattern sequences. */ + Event *curEvent; /* Pointing to most recent event. */ + ModMask curModMask; /* Containing the current modifier mask. */ + LookupTables lookupTables; /* Containing hash tables for fast lookup. */ + Tcl_HashTable objectTable; /* Used to map from an object to a list of patterns associated with + * that object. Keys are ClientData, values are (PatSeq *). */ + Tcl_Interp *interp; /* Interpreter in which commands are executed. */ } BindingTable; /* @@ -124,15 +222,10 @@ */ typedef struct { - Tcl_HashTable patternTable; /* Used to map from a physical event to a list - * of patterns that may match that event. Keys - * are PatternTableKey structs, values are - * (PatSeq *). */ - Tcl_HashTable nameTable; /* Used to map a virtual event name to the - * array of physical events that can trigger - * it. Keys are the Tk_Uid names of the - * virtual events, values are PhysicalsOwned - * structs. */ + LookupTables lookupTables; /* Providing fast lookup tables to lists of pattern sequences. */ + Tcl_HashTable nameTable; /* Used to map a virtual event name to the array of physical events + * that can trigger it. Keys are the Tk_Uid names of the virtual + * events, values are PhysOwned structs. */ } VirtualEventTable; /* @@ -151,36 +244,43 @@ */ typedef struct { - ClientData object; /* For binding table, identifies the binding - * tag of the object (or class of objects) - * relative to which the event occurred. For - * virtual event table, always NULL. */ - int type; /* Type of event (from X). */ - Detail detail; /* Additional information, such as keysym, - * button, Tk_Uid, or 0 if nothing - * additional. */ + ClientData object; /* For binding table, identifies the binding tag of the object + * (or class of objects) relative to which the event occurred. + * For virtual event table, always NULL. */ + unsigned type; /* Type of event (from X). */ + Detail detail; /* Additional information, such as keysym, button, Tk_Uid, or zero + * if nothing additional. */ } PatternTableKey; /* * The following structure defines a pattern, which is matched against X * events as part of the process of converting X events into Tcl commands. + * + * For technical reasons we do not use 'union Detail', although this would + * be possible, instead 'info' and 'name' are both included. */ typedef struct { - int eventType; /* Type of X event, e.g. ButtonPress. */ - int needMods; /* Mask of modifiers that must be present (0 - * means no modifiers are required). */ - Detail detail; /* Additional information that must match - * event. Normally this is 0, meaning no - * additional information must match. For - * KeyPress and KeyRelease events, a keySym - * may be specified to select a particular - * keystroke (0 means any keystrokes). For - * button events, specifies a particular - * button (0 means any buttons are OK). For - * virtual events, specifies the Tk_Uid of the - * virtual event name (never 0). */ + unsigned eventType; /* Type of X event, e.g. ButtonPress. */ + unsigned count; /* Multi-event count, e.g. double-clicks, triple-clicks, etc. */ + ModMask modMask; /* Mask of modifiers that must be present (zero means no modifiers + * are required). */ + Info info; /* Additional information that must match event. Normally this is zero, + * meaning no additional information must match. For KeyPress and + * KeyRelease events, it may be specified to select a particular + * keystroke (zero means any keystrokes). For button events, specifies + * a particular button (zero means any buttons are OK). */ + Tk_Uid name; /* Specifies the Tk_Uid of the virtual event name. NULL if not a + * virtual event. */ } TkPattern; + +/* + * The following structure keeps track of all the virtual events that are + * associated with a particular physical event. It is pointed to by the 'owners' + * field in a PatSeq in the patternTable of a virtual event table. + */ + +TK_PTR_ARRAY_DEFINE(VirtOwners, Tcl_HashEntry); /* define array of hash entries */ /* * The following structure defines a pattern sequence, which consists of one @@ -201,78 +301,63 @@ */ typedef struct PatSeq { - int numPats; /* Number of patterns in sequence (usually - * 1). */ - char *script; /* Binding script to evaluate when sequence - * matches (ckalloc()ed) */ - int flags; /* Miscellaneous flag values; see below for - * definitions. */ - struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences that - * have the same initial pattern. NULL means - * end of list. */ - Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the initial - * pattern. This is the head of the list of - * which nextSeqPtr forms a part. */ - struct VirtualOwners *voPtr;/* In a binding table, always NULL. In a - * virtual event table, identifies the array - * of virtual events that can be triggered by - * this event. */ - struct PatSeq *nextObjPtr; /* In a binding table, next in list of all - * pattern sequences for the same object (NULL - * for end of list). Needed to implement - * Tk_DeleteAllBindings. In a virtual event - * table, always NULL. */ - TkPattern pats[1]; /* Array of "numPats" patterns. Only one - * element is declared here but in actuality - * enough space will be allocated for - * "numPats" patterns. To match, pats[0] must - * match event n, pats[1] must match event - * n-1, etc. */ + unsigned numPats; /* Number of patterns in sequence (usually 1). */ + unsigned count; /* Total number of repetition counts, summed over count in TkPattern. */ + unsigned number; /* Needed for the decision whether a binding is less recently defined + * than another, it is guaranteed that the most recently bound event + * has the highest number. */ + unsigned added:1; /* Is this pattern sequence already added to lookup table? */ + unsigned modMaskUsed:1; /* Does at least one pattern contain a non-zero modifier mask? */ + DEBUG(unsigned owned:1;) /* For debugging purposes. */ + char *script; /* Binding script to evaluate when sequence matches (ckalloc()ed) */ + Tcl_Obj* object; /* Token for object with which binding is associated. For virtual + * event table this is NULL. */ + struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences that have the same initial + * pattern. NULL means end of list. */ + Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the initial pattern. This is the + * head of the list of which nextSeqPtr forms a part. */ + union { + VirtOwners *owners; /* In a binding table it has no meaning. In a virtual event table, + * identifies the array of virtual events that can be triggered + * by this event. */ + struct PatSeq *nextObj; /* In a binding table, next in list of all pattern sequences for + * the same object (NULL for end of list). Needed to implement + * Tk_DeleteAllBindings. In a virtual event table it has no meaning. */ + } ptr; + TkPattern pats[1]; /* Array of "numPats" patterns. Only one element is declared here + * but in actuality enough space will be allocated for "numPats" + * patterns (but usually 1). */ } PatSeq; /* - * Flag values for PatSeq structures: - * - * PAT_NEARBY 1 means that all of the events matching this sequence - * must occur with nearby X and Y mouse coordinates and - * close in time. This is typically used to restrict - * multiple button presses. - */ - -#define PAT_NEARBY 0x1 + * Compute memory size of struct PatSeq with given pattern size. + * The caller must be sure that pattern size is greater than zero. + */ +#define PATSEQ_MEMSIZE(numPats) (sizeof(PatSeq) + (numPats - 1)*sizeof(TkPattern)) /* * Constants that define how close together two events must be in milliseconds * or pixels to meet the PAT_NEARBY constraint: */ -#define NEARBY_PIXELS 5 -#define NEARBY_MS 500 - -/* - * The following structure keeps track of all the virtual events that are - * associated with a particular physical event. It is pointed to by the voPtr - * field in a PatSeq in the patternTable of a virtual event table. - */ - -typedef struct VirtualOwners { - int numOwners; /* Number of virtual events to trigger. */ - Tcl_HashEntry *owners[1]; /* Array of pointers to entries in nameTable. - * Enough space will actually be allocated for - * numOwners hash entries. */ -} VirtualOwners; +#define NEARBY_PIXELS 5 +#define NEARBY_MS 500 + +/* + * Needed as "no-number" constant for integers. The value of this constant is + * outside of integer range (type "int"). (Unfortunatly current version of + * Tcl/Tk does not provide C99 integer support.) + */ + +#define NO_NUMBER (((Tcl_WideInt) (~ (unsigned) 0)) + 1) /* * The following structure is used in the nameTable of a virtual event table * to associate a virtual event with all the physical events that can trigger * it. */ -typedef struct { - int numOwned; /* Number of physical events owned. */ - PatSeq *patSeqs[1]; /* Array of pointers to physical event - * patterns. Enough space will actually be - * allocated to hold numOwned. */ -} PhysicalsOwned; + +TK_PTR_ARRAY_DEFINE(PhysOwned, PatSeq); /* define array of pattern seqs */ /* * One of the following structures exists for each interpreter. This structure @@ -282,11 +367,9 @@ */ typedef struct { - TkDisplay *curDispPtr; /* Display for last binding command invoked in - * this application. */ + TkDisplay *curDispPtr; /* Display for last binding command invoked in this application. */ int curScreenIndex; /* Index of screen for last binding command */ - int bindingDepth; /* Number of active instances of Tk_BindEvent - * in this application. */ + unsigned bindingDepth; /* Number of active instances of Tk_BindEvent in this application. */ } ScreenInfo; /* @@ -296,13 +379,13 @@ typedef struct TkBindInfo_ { VirtualEventTable virtualEventTable; - /* The virtual events that exist in this - * interpreter. */ - ScreenInfo screenInfo; /* Keeps track of the current display and - * screen, so it can be restored after a - * binding has executed. */ - int deleted; /* 1 the application has been deleted but the - * structure has been preserved. */ + /* The virtual events that exist in this interpreter. */ + ScreenInfo screenInfo; /* Keeps track of the current display and screen, so it can be + * restored after a binding has executed. */ + int deleted; /* 1 if the application has been deleted but the structure has been + * preserved. */ + Time lastEventTime; /* Needed for time measurement. */ + Time lastCurrentTime; /* Needed for time measurement. */ } BindInfo; /* @@ -317,7 +400,7 @@ #ifdef REDO_KEYSYM_LOOKUP typedef struct { - const char *name; /* Name of keysym. */ + const char *name; /* Name of keysym. */ KeySym value; /* Numeric identifier for keysym. */ } KeySymInfo; static const KeySymInfo keyArray[] = { @@ -326,17 +409,9 @@ #endif {NULL, 0} }; -static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */ -static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */ +static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */ +static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */ #endif /* REDO_KEYSYM_LOOKUP */ - -/* - * Set to non-zero when the package-wide static variables have been - * initialized. - */ - -static int initialized = 0; -TCL_DECLARE_MUTEX(bindMutex) /* * A hash table is kept to map from the string names of event modifiers to @@ -346,29 +421,24 @@ */ typedef struct { - const char *name; /* Name of modifier. */ - int mask; /* Button/modifier mask value, such as - * Button1Mask. */ - int flags; /* Various flags; see below for - * definitions. */ + const char *name; /* Name of modifier. */ + ModMask mask; /* Button/modifier mask value, such as Button1Mask. */ + unsigned flags; /* Various flags; see below for definitions. */ } ModInfo; /* * Flags for ModInfo structures: * - * DOUBLE - Non-zero means duplicate this event, - * e.g. for double-clicks. - * TRIPLE - Non-zero means triplicate this event, - * e.g. for triple-clicks. - * QUADRUPLE - Non-zero means quadruple this event, - * e.g. for 4-fold-clicks. + * DOUBLE - Non-zero means duplicate this event, e.g. for double-clicks. + * TRIPLE - Non-zero means triplicate this event, e.g. for triple-clicks. + * QUADRUPLE - Non-zero means quadruple this event, e.g. for 4-fold-clicks. * MULT_CLICKS - Combination of all of above. */ -#define DOUBLE 1 -#define TRIPLE 2 -#define QUADRUPLE 4 -#define MULT_CLICKS 7 +#define DOUBLE (1<<0) +#define TRIPLE (1<<1) +#define QUADRUPLE (1<<2) +#define MULT_CLICKS (DOUBLE|TRIPLE|QUADRUPLE) static const ModInfo modArray[] = { {"Control", ControlMask, 0}, @@ -416,9 +486,8 @@ typedef struct { const char *name; /* Name of event. */ - int type; /* Event type for X, such as ButtonPress. */ - int eventMask; /* Mask bits (for XSelectInput) for this event - * type. */ + unsigned type; /* Event type for X, such as ButtonPress. */ + unsigned eventMask; /* Mask bits (for XSelectInput) for this event type. */ } EventInfo; /* @@ -434,10 +503,8 @@ {"KeyRelease", KeyRelease, KeyPressMask|KeyReleaseMask}, {"Button", ButtonPress, ButtonPressMask}, {"ButtonPress", ButtonPress, ButtonPressMask}, - {"ButtonRelease", ButtonRelease, - ButtonPressMask|ButtonReleaseMask}, - {"Motion", MotionNotify, - ButtonPressMask|PointerMotionMask}, + {"ButtonRelease", ButtonRelease, ButtonPressMask|ButtonReleaseMask}, + {"Motion", MotionNotify, ButtonPressMask|PointerMotionMask}, {"Enter", EnterNotify, EnterWindowMask}, {"Leave", LeaveNotify, LeaveWindowMask}, {"FocusIn", FocusIn, FocusChangeMask}, @@ -465,6 +532,8 @@ }; static Tcl_HashTable eventTable; +static int eventArrayIndex[TK_LASTEVENT]; + /* * The defines and table below are used to classify events into various * groups. The reason for this is that logically identical fields (e.g. @@ -473,29 +542,29 @@ * information from events. */ -#define KEY 0x1 -#define BUTTON 0x2 -#define MOTION 0x4 -#define CROSSING 0x8 -#define FOCUS 0x10 -#define EXPOSE 0x20 -#define VISIBILITY 0x40 -#define CREATE 0x80 -#define DESTROY 0x100 -#define UNMAP 0x200 -#define MAP 0x400 -#define REPARENT 0x800 -#define CONFIG 0x1000 -#define GRAVITY 0x2000 -#define CIRC 0x4000 -#define PROP 0x8000 -#define COLORMAP 0x10000 -#define VIRTUAL 0x20000 -#define ACTIVATE 0x40000 -#define MAPREQ 0x80000 -#define CONFIGREQ 0x100000 -#define RESIZEREQ 0x200000 -#define CIRCREQ 0x400000 +#define KEY (1<<0) +#define BUTTON (1<<1) +#define MOTION (1<<2) +#define CROSSING (1<<3) +#define FOCUS (1<<4) +#define EXPOSE (1<<5) +#define VISIBILITY (1<<6) +#define CREATE (1<<7) +#define DESTROY (1<<8) +#define UNMAP (1<<9) +#define MAP (1<<10) +#define REPARENT (1<<11) +#define CONFIG (1<<12) +#define GRAVITY (1<<13) +#define CIRC (1<<14) +#define PROP (1<<15) +#define COLORMAP (1<<16) +#define VIRTUAL (1<<17) +#define ACTIVATE (1<<18) +#define MAPREQ (1<<19) +#define CONFIGREQ (1<<20) +#define RESIZEREQ (1<<21) +#define CIRCREQ (1<<22) #define KEY_BUTTON_MOTION_VIRTUAL (KEY|BUTTON|MOTION|VIRTUAL) #define KEY_BUTTON_MOTION_CROSSING (KEY|BUTTON|MOTION|VIRTUAL|CROSSING) @@ -548,11 +617,11 @@ */ static const TkStateMap queuePosition[] = { - {-1, "now"}, - {TCL_QUEUE_HEAD, "head"}, - {TCL_QUEUE_MARK, "mark"}, - {TCL_QUEUE_TAIL, "tail"}, - {-2, NULL} + {-1, "now"}, + {TCL_QUEUE_HEAD, "head"}, + {TCL_QUEUE_MARK, "mark"}, + {TCL_QUEUE_TAIL, "tail"}, + {-2, NULL} }; /* @@ -583,8 +652,8 @@ }; static const TkStateMap circPlace[] = { - {PlaceOnTop, "PlaceOnTop"}, - {PlaceOnBottom, "PlaceOnBottom"}, + {PlaceOnTop, "PlaceOnTop"}, + {PlaceOnBottom, "PlaceOnBottom"}, {-1, NULL} }; @@ -596,12 +665,12 @@ }; static const TkStateMap configureRequestDetail[] = { - {None, "None"}, - {Above, "Above"}, - {Below, "Below"}, - {BottomIf, "BottomIf"}, - {TopIf, "TopIf"}, - {Opposite, "Opposite"}, + {None, "None"}, + {Above, "Above"}, + {Below, "Below"}, + {BottomIf, "BottomIf"}, + {TopIf, "TopIf"}, + {Opposite, "Opposite"}, {-1, NULL} }; @@ -611,47 +680,516 @@ {-1, NULL} }; +DEBUG(static int countTableItems = 0;) +DEBUG(static int countEntryItems = 0;) +DEBUG(static int countListItems = 0;) +DEBUG(static int countBindItems = 0;) +DEBUG(static int countSeqItems = 0;) + /* * Prototypes for local functions defined in this file: */ -static void ChangeScreen(Tcl_Interp *interp, char *dispName, - int screenIndex); -static int CreateVirtualEvent(Tcl_Interp *interp, - VirtualEventTable *vetPtr, char *virtString, - const char *eventString); -static int DeleteVirtualEvent(Tcl_Interp *interp, - VirtualEventTable *vetPtr, char *virtString, - const char *eventString); +static void ChangeScreen(Tcl_Interp *interp, char *dispName, int screenIndex); +static int CreateVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, + char *virtString, const char *eventString); +static int DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, + char *virtString, const char *eventString); static void DeleteVirtualEventTable(VirtualEventTable *vetPtr); -static void ExpandPercents(TkWindow *winPtr, const char *before, - XEvent *eventPtr,KeySym keySym, - unsigned int scriptCount, Tcl_DString *dsPtr); -static PatSeq * FindSequence(Tcl_Interp *interp, - Tcl_HashTable *patternTablePtr, ClientData object, - const char *eventString, int create, - int allowVirtual, unsigned long *maskPtr); -static void GetAllVirtualEvents(Tcl_Interp *interp, - VirtualEventTable *vetPtr); -static char * GetField(char *p, char *copy, int size); -static Tcl_Obj * GetPatternObj(PatSeq *psPtr); -static int GetVirtualEvent(Tcl_Interp *interp, - VirtualEventTable *vetPtr, Tcl_Obj *virtName); -static Tk_Uid GetVirtualEventUid(Tcl_Interp *interp, - char *virtString); +static void ExpandPercents(TkWindow *winPtr, const char *before, Event *eventPtr, + unsigned scriptCount, Tcl_DString *dsPtr); +static PatSeq * FindSequence(Tcl_Interp *interp, LookupTables *lookupTables, + ClientData object, const char *eventString, int create, + int allowVirtual, EventMask *maskPtr); +static void GetAllVirtualEvents(Tcl_Interp *interp, VirtualEventTable *vetPtr); +static const char * GetField(const char *p, char *copy, unsigned size); +static Tcl_Obj * GetPatternObj(const PatSeq *psPtr); +static int GetVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, + Tcl_Obj *virtName); +static Tk_Uid GetVirtualEventUid(Tcl_Interp *interp, char *virtString); static int HandleEventGenerate(Tcl_Interp *interp, Tk_Window main, int objc, Tcl_Obj *const objv[]); static void InitVirtualEventTable(VirtualEventTable *vetPtr); -static PatSeq * MatchPatterns(TkDisplay *dispPtr, - BindingTable *bindPtr, PatSeq *psPtr, - PatSeq *bestPtr, ClientData *objectPtr, - PatSeq **sourcePtrPtr); +static PatSeq * MatchPatterns(TkDisplay *dispPtr, Tk_BindingTable bindPtr, PSList *psList, + PSList *psSuccList, unsigned patIndex, const Event *eventPtr, + ClientData object, PatSeq **physPtrPtr); static int NameToWindow(Tcl_Interp *interp, Tk_Window main, Tcl_Obj *objPtr, Tk_Window *tkwinPtr); -static int ParseEventDescription(Tcl_Interp *interp, - const char **eventStringPtr, TkPattern *patPtr, - unsigned long *eventMaskPtr); +static unsigned ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr, + TkPattern *patPtr, EventMask *eventMaskPtr); static void DoWarp(ClientData clientData); +static PSList * GetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr, + Tcl_Obj *object, int onlyConsiderDetailedEvents); +static void ClearLookupTable(LookupTables *lookupTables, ClientData object); +static void ClearPromotionLists(Tk_BindingTable bindPtr, ClientData object); +static PSEntry * MakeListEntry(PSList *pool, PatSeq *psPtr, int needModMasks); +static void RemovePatSeqFromLookup(LookupTables *lookupTables, PatSeq *psPtr); +static void RemovePatSeqFromPromotionLists(Tk_BindingTable bindPtr, PatSeq *psPtr); +static PatSeq * DeletePatSeq(PatSeq *psPtr); +static void InsertPatSeq(LookupTables *lookupTables, PatSeq *psPtr); +#if SUPPORT_DEBUGGING +void TkpDumpPS(const PatSeq *psPtr); +void TkpDumpPSList(const PSList *psList); +#endif + +/* + * Some useful helper functions. + */ +#ifdef SUPPORT_DEBUGGING +static int BindCount = 0; +#endif + +static unsigned Max(unsigned a, unsigned b) { return a < b ? b : a; } +static int Abs(int n) { return n < 0 ? -n : n; } +static int IsOdd(int n) { return n & 1; } + +static int TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; } +static int TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; } + +static int +IsSubsetOf( + ModMask lhsMask, /* this is a subset */ + ModMask rhsMask) /* of this bit field? */ +{ + return (lhsMask & rhsMask) == lhsMask; +} + +static const char* +SkipSpaces( + const char* s) +{ + assert(s); + while (isspace(UCHAR(*s))) + ++s; + return s; +} + +static const char* +SkipFieldDelims( + const char* s) +{ + assert(s); + while (*s == '-' || isspace(UCHAR(*s))) { + ++s; + } + return s; +} + +static unsigned +GetButtonNumber( + const char *field) +{ + assert(field); + return (field[0] >= '1' && field[0] <= '5' && field[1] == '\0') ? field[0] - '0' : 0; +} + +static Time +CurrentTimeInMilliSecs() +{ + Tcl_Time now; + Tcl_GetTime(&now); + return ((Time) now.sec)*1000 + ((Time) now.usec)/1000; +} + +static Info +GetInfo( + const PatSeq *psPtr, + unsigned index) +{ + assert(psPtr); + assert(index < psPtr->numPats); + + return psPtr->pats[index].info; +} + +static unsigned +GetCount( + const PatSeq *psPtr, + unsigned index) +{ + assert(psPtr); + assert(index < psPtr->numPats); + + return psPtr->pats[index].count; +} + +static int +CountSpecialized( + const PatSeq *fstMatchPtr, + const PatSeq *sndMatchPtr) +{ + int fstCount = 0; + int sndCount = 0; + unsigned i; + + assert(fstMatchPtr); + assert(sndMatchPtr); + + for (i = 0; i < fstMatchPtr->numPats; ++i) { + if (GetInfo(fstMatchPtr, i)) { fstCount += GetCount(fstMatchPtr, i); } + } + for (i = 0; i < sndMatchPtr->numPats; ++i) { + if (GetInfo(sndMatchPtr, i)) { sndCount += GetCount(sndMatchPtr, i); } + } + + return sndCount - fstCount; +} + +static int +MatchEventNearby( + const XEvent *lhs, /* previous button event */ + const XEvent *rhs) /* current button event */ +{ + assert(lhs); + assert(rhs); + assert(lhs->type == ButtonPress || lhs->type == ButtonRelease); + assert(lhs->type == rhs->type); + + /* assert: lhs->xbutton.time <= rhs->xbutton.time */ + + return TestNearbyTime(rhs->xbutton.time, lhs->xbutton.time) + && TestNearbyCoords(rhs->xbutton.x_root, lhs->xbutton.x_root) + && TestNearbyCoords(rhs->xbutton.y_root, lhs->xbutton.y_root); +} + +static int +MatchEventRepeat( + const XEvent *lhs, /* previous key event */ + const XEvent *rhs) /* current key event */ +{ + assert(lhs); + assert(rhs); + assert(lhs->type == KeyPress || lhs->type == KeyRelease); + assert(lhs->type == rhs->type); + + /* assert: lhs->xkey.time <= rhs->xkey.time */ + return TestNearbyTime(rhs->xkey.time, lhs->xkey.time); +} + +static void +FreePatSeq( + PatSeq *psPtr) +{ + assert(psPtr); + assert(!psPtr->owned); + DEBUG(MARK_PSENTRY(psPtr);) + ckfree(psPtr->script); + if (!psPtr->object) { + VirtOwners_Free(&psPtr->ptr.owners); + } + ckfree(psPtr); + DEBUG(countSeqItems -= 1;) +} + +static void +RemoveListEntry( + PSList *pool, + PSEntry *psEntry) +{ + assert(pool); + assert(psEntry); + + if (PSModMaskArr_Capacity(psEntry->lastModMaskArr) > MAX_MOD_MASK_ARR_SIZE) { + PSModMaskArr_Free(&psEntry->lastModMaskArr); + } + PSList_Remove(psEntry); + PSList_Append(pool, psEntry); +} + +static void +ClearList( + PSList *psList, + PSList *pool, + ClientData object) +{ + assert(psList); + assert(pool); + + if (object) { + PSEntry *psEntry; + PSEntry *psNext; + + for (psEntry = PSList_First(psList); psEntry; psEntry = psNext) { + psNext = PSList_Next(psEntry); + if (psEntry->psPtr->object == object) { + RemoveListEntry(pool, psEntry); + } + } + } else { + PSList_Move(pool, psList); + } +} + +static PSEntry * +FreePatSeqEntry( + PSList *pool, + PSEntry *entry) +{ + PSEntry *next = PSList_Next(entry); + PSModMaskArr_Free(&entry->lastModMaskArr); + ckfree(entry); + return next; +} + +static unsigned +ResolveModifiers( + TkDisplay *dispPtr, + unsigned modMask) +{ + assert(dispPtr); + + if (dispPtr->metaModMask) { + if (modMask & META_MASK) { + modMask &= ~(ModMask)META_MASK; + modMask |= dispPtr->metaModMask; + } + } + if (dispPtr->altModMask) { + if (modMask & ALT_MASK) { + modMask &= ~(ModMask)ALT_MASK; + modMask |= dispPtr->altModMask; + } + } + + return modMask; +} + +static int +ButtonNumberFromState( + unsigned state) +{ + if (!(state & ALL_BUTTONS)) { return 0; } + if (state & Button1Mask) { return 1; } + if (state & Button2Mask) { return 2; } + if (state & Button3Mask) { return 3; } + if (state & Button4Mask) { return 4; } + return 5; +} + +static void +SetupPatternKey( + PatternTableKey *key, + const PatSeq *psPtr) +{ + const TkPattern *patPtr; + + assert(key); + assert(psPtr); + + /* otherwise on some systems the key contains uninitialized bytes */ + memset(key, 0, sizeof(PatternTableKey)); + + patPtr = psPtr->pats; + assert(!patPtr->info || !patPtr->name); + + key->object = psPtr->object; + key->type = patPtr->eventType; + if (patPtr->info) { + key->detail.info = patPtr->info; + } else { + key->detail.name = patPtr->name; + } +} + +/* + *-------------------------------------------------------------- + * + * MakeListEntry -- + * + * Makes new entry item for lookup table. We are using a + * pool of items, this avoids superfluous memory allocation/ + * deallocation. + * + * Results: + * New entry item. + * + * Side effects: + * Memory allocated. + * + *-------------------------------------------------------------- + */ + +static PSEntry * +MakeListEntry( + PSList *pool, + PatSeq *psPtr, + int needModMasks) +{ + PSEntry *newEntry = NULL; + + assert(pool); + assert(psPtr); + assert(psPtr->numPats > 0); + assert(TEST_PSENTRY(psPtr)); + + if (PSList_IsEmpty(pool)) { + newEntry = ckalloc(sizeof(PSEntry)); + newEntry->lastModMaskArr = NULL; + DEBUG(countEntryItems += 1;) + } else { + newEntry = PSList_First(pool); + PSList_RemoveHead(pool); + } + + if (!needModMasks) { + PSModMaskArr_SetSize(newEntry->lastModMaskArr, 0); + } else { + if (PSModMaskArr_Capacity(newEntry->lastModMaskArr) < psPtr->numPats - 1) { + PSModMaskArr_Resize(&newEntry->lastModMaskArr, psPtr->numPats - 1); + } + PSModMaskArr_SetSize(newEntry->lastModMaskArr, psPtr->numPats - 1); + } + + newEntry->psPtr = psPtr; + newEntry->window = None; + newEntry->expired = 0; + newEntry->keepIt = 1; + newEntry->count = 1; + DEBUG(psPtr->owned = 0;) + + return newEntry; +} + +/* + *-------------------------------------------------------------- + * + * GetLookupForEvent -- + * + * Get specific pattern sequence table for given event. + * + * Results: + * Specific pattern sequence table for given event. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static PSList * +GetLookupForEvent( + LookupTables* lookupTables, + const Event *eventPtr, + Tcl_Obj *object, + int onlyConsiderDetailedEvents) +{ + PatternTableKey key; + Tcl_HashEntry *hPtr; + + assert(lookupTables); + assert(eventPtr); + + /* otherwise on some systems the key contains uninitialized bytes */ + memset(&key, 0, sizeof(PatternTableKey)); + + if (onlyConsiderDetailedEvents) { + switch (eventPtr->xev.type) { + case ButtonPress: /* fallthru */ + case ButtonRelease: key.detail.info = eventPtr->xev.xbutton.button; break; + case MotionNotify: key.detail.info = ButtonNumberFromState(eventPtr->xev.xmotion.state); break; + case KeyPress: /* fallthru */ + case KeyRelease: key.detail.info = eventPtr->detail.info; break; + case VirtualEvent: key.detail.name = eventPtr->detail.name; break; + } + if (!key.detail.name) { + assert(!key.detail.info); + return NULL; + } + } + + key.object = object; + key.type = eventPtr->xev.type; + hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key); + return hPtr ? Tcl_GetHashValue(hPtr) : NULL; +} + +/* + *-------------------------------------------------------------- + * + * ClearLookupTable -- + * + * Clear lookup table in given binding table, but only those + * bindings associated to given object. If object is NULL + * then remove all entries. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +static void +ClearLookupTable( + LookupTables *lookupTables, + ClientData object) +{ + Tcl_HashSearch search; + Tcl_HashEntry *hPtr; + Tcl_HashEntry *nextPtr; + PSList *pool = &lookupTables->entryPool; + + assert(lookupTables); + + for (hPtr = Tcl_FirstHashEntry(&lookupTables->listTable, &search); hPtr; hPtr = nextPtr) { + PSList *psList; + + nextPtr = Tcl_NextHashEntry(&search); + + if (object) { + const PatternTableKey *key = Tcl_GetHashKey(&lookupTables->listTable, hPtr); + if (key->object != object) { + continue; + } + Tcl_DeleteHashEntry(hPtr); + } + + psList = Tcl_GetHashValue(hPtr); + PSList_Move(pool, psList); + ckfree(psList); + DEBUG(countListItems -= 1;) + } +} + +/* + *-------------------------------------------------------------- + * + * ClearPromotionLists -- + * + * Clear all the lists holding the promoted pattern + * sequences, which belongs to given object. If object + * is NULL then remove all patterns. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +ClearPromotionLists( + Tk_BindingTable bindPtr, + ClientData object) +{ + unsigned newArraySize = 0; + unsigned i; + + assert(bindPtr); + + for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) { + PSList *psList = PromArr_Get(bindPtr->promArr, i); + ClearList(psList, &bindPtr->lookupTables.entryPool, object); + if (!PSList_IsEmpty(psList)) { + newArraySize = i + 1; + } + } + + PromArr_SetSize(bindPtr->promArr, newArraySize); +} /* *--------------------------------------------------------------------------- @@ -671,15 +1209,96 @@ *--------------------------------------------------------------------------- */ +/* + * Windoze compiler does not allow the definition of these static variables inside a function, + * otherwise this should belong to function TkBindInit(). + */ +TCL_DECLARE_MUTEX(bindMutex); +static int initialized = 0; + void TkBindInit( TkMainInfo *mainPtr) /* The newly created application. */ { BindInfo *bindInfoPtr; - if (sizeof(XEvent) < sizeof(XVirtualEvent)) { - Tcl_Panic("TkBindInit: virtual events can't be supported"); - } + assert(mainPtr); + + /* otherwise virtual events can't be supported */ + assert(sizeof(XEvent) >= sizeof(XVirtualEvent)); + + /* type of TkPattern.info is well defined? */ + assert(sizeof(Info) >= sizeof(KeySym)); + assert(sizeof(Info) >= sizeof(unsigned)); + + /* ensure that our matching algorithm is working (when testing detail) */ + assert(sizeof(Detail) == sizeof(Tk_Uid)); + + /* test that constant NO_NUMBER is indeed out of integer range */ + assert(sizeof(NO_NUMBER) > sizeof(int)); + assert(((int) NO_NUMBER) == 0 && NO_NUMBER != 0); + + /* test expected indices of Button1..Button5, otherwise our button handling is not working */ + assert(Button1 == 1 && Button2 == 2 && Button3 == 3 && Button4 == 4 && Button5 == 5); + assert(Button2Mask == (Button1Mask << 1)); + assert(Button3Mask == (Button1Mask << 2)); + assert(Button4Mask == (Button1Mask << 3)); + assert(Button5Mask == (Button1Mask << 4)); + + /* test expected values of button motion masks, otherwise our button handling is not working */ + assert(Button1MotionMask == Button1Mask); + assert(Button2MotionMask == Button2Mask); + assert(Button3MotionMask == Button3Mask); + assert(Button4MotionMask == Button4Mask); + assert(Button5MotionMask == Button5Mask); + + /* because we expect zero if keySym is empty */ + assert(NoSymbol == 0L); + + /* this must be a union, not a struct, otherwise comparison with NULL will not work */ + assert(Tk_Offset(Detail, name) == Tk_Offset(Detail, info)); + + /* we use some constraints about X*Event */ + assert(Tk_Offset(XButtonEvent, time) == Tk_Offset(XMotionEvent, time)); + assert(Tk_Offset(XButtonEvent, x_root) == Tk_Offset(XMotionEvent, x_root)); + assert(Tk_Offset(XButtonEvent, y_root) == Tk_Offset(XMotionEvent, y_root)); + assert(Tk_Offset(XCreateWindowEvent, border_width) == Tk_Offset(XConfigureEvent, border_width)); + assert(Tk_Offset(XCreateWindowEvent, width) == Tk_Offset(XConfigureEvent, width)); + assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XCirculateRequestEvent, window)); + assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XConfigureEvent, window)); + assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XGravityEvent, window)); + assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XMapEvent, window)); + assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XReparentEvent, window)); + assert(Tk_Offset(XCreateWindowEvent, window) == Tk_Offset(XUnmapEvent, window)); + assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XConfigureEvent, x)); + assert(Tk_Offset(XCreateWindowEvent, x) == Tk_Offset(XGravityEvent, x)); + assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XConfigureEvent, y)); + assert(Tk_Offset(XCreateWindowEvent, y) == Tk_Offset(XGravityEvent, y)); + assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XEnterWindowEvent, time)); + assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XLeaveWindowEvent, time)); + assert(Tk_Offset(XCrossingEvent, time) == Tk_Offset(XKeyEvent, time)); + assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XButtonEvent, root)); + assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XCrossingEvent, root)); + assert(Tk_Offset(XKeyEvent, root) == Tk_Offset(XMotionEvent, root)); + assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XButtonEvent, state)); + assert(Tk_Offset(XKeyEvent, state) == Tk_Offset(XMotionEvent, state)); + assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XButtonEvent, subwindow)); + assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XCrossingEvent, subwindow)); + assert(Tk_Offset(XKeyEvent, subwindow) == Tk_Offset(XMotionEvent, subwindow)); + assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XButtonEvent, time)); + assert(Tk_Offset(XKeyEvent, time) == Tk_Offset(XMotionEvent, time)); + assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XButtonEvent, x)); + assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XCrossingEvent, x)); + assert(Tk_Offset(XKeyEvent, x) == Tk_Offset(XMotionEvent, x)); + assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XButtonEvent, x_root)); + assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XCrossingEvent, x_root)); + assert(Tk_Offset(XKeyEvent, x_root) == Tk_Offset(XMotionEvent, x_root)); + assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XButtonEvent, y)); + assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XCrossingEvent, y)); + assert(Tk_Offset(XKeyEvent, y) == Tk_Offset(XMotionEvent, y)); + assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XButtonEvent, y_root)); + assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XCrossingEvent, y_root)); + assert(Tk_Offset(XKeyEvent, y_root) == Tk_Offset(XMotionEvent, y_root)); /* * Initialize the static data structures used by the binding package. They @@ -693,33 +1312,46 @@ const ModInfo *modPtr; const EventInfo *eiPtr; int newEntry; + unsigned i; #ifdef REDO_KEYSYM_LOOKUP const KeySymInfo *kPtr; Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS); Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS); - for (kPtr = keyArray; kPtr->name != NULL; kPtr++) { + for (kPtr = keyArray; kPtr->name; ++kPtr) { hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &newEntry); Tcl_SetHashValue(hPtr, kPtr->value); - hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value, - &newEntry); + hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value, &newEntry); if (newEntry) { Tcl_SetHashValue(hPtr, kPtr->name); } } #endif /* REDO_KEYSYM_LOOKUP */ + for (i = 0; i < SIZE_OF_ARRAY(eventArrayIndex); ++i) { + eventArrayIndex[i] = -1; + } + for (i = 0; i < SIZE_OF_ARRAY(eventArray); ++i) { + unsigned type = eventArray[i].type; + assert(type < TK_LASTEVENT); + assert(type > 0 || i == SIZE_OF_ARRAY(eventArray) - 1); + if (type > 0 && eventArrayIndex[type] == -1) { + eventArrayIndex[type] = i; + } + } + Tcl_InitHashTable(&modTable, TCL_STRING_KEYS); - for (modPtr = modArray; modPtr->name != NULL; modPtr++) { + for (modPtr = modArray; modPtr->name; ++modPtr) { hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &newEntry); Tcl_SetHashValue(hPtr, modPtr); } Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS); - for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) { + for (eiPtr = eventArray; eiPtr->name; ++eiPtr) { hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &newEntry); Tcl_SetHashValue(hPtr, eiPtr); } + initialized = 1; } Tcl_MutexUnlock(&bindMutex); @@ -733,7 +1365,10 @@ bindInfoPtr->screenInfo.curScreenIndex = -1; bindInfoPtr->screenInfo.bindingDepth = 0; bindInfoPtr->deleted = 0; + bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); + bindInfoPtr->lastEventTime = 0; mainPtr->bindInfo = bindInfoPtr; + DEBUG(countBindItems += 1;) TkpInitializeMenuBindings(mainPtr->interp, mainPtr->bindingTable); } @@ -761,14 +1396,21 @@ { BindInfo *bindInfoPtr; + assert(mainPtr); + Tk_DeleteBindingTable(mainPtr->bindingTable); mainPtr->bindingTable = NULL; - bindInfoPtr = mainPtr->bindInfo; DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable); bindInfoPtr->deleted = 1; Tcl_EventuallyFree(bindInfoPtr, TCL_DYNAMIC); mainPtr->bindInfo = NULL; + + DEBUG(countBindItems -= 1;) + assert(countBindItems > 0 || countTableItems == 0); + assert(countBindItems > 0 || countEntryItems == 0); + assert(countBindItems > 0 || countListItems == 0); + assert(countBindItems > 0 || countSeqItems == 0); } /* @@ -790,23 +1432,28 @@ Tk_BindingTable Tk_CreateBindingTable( - Tcl_Interp *interp) /* Interpreter to associate with the binding - * table: commands are executed in this - * interpreter. */ + Tcl_Interp *interp) /* Interpreter to associate with the binding table: commands are + * executed in this interpreter. */ { BindingTable *bindPtr = ckalloc(sizeof(BindingTable)); - int i; + unsigned i; + + assert(interp); + DEBUG(countTableItems += 1;) /* * Create and initialize a new binding table. */ - for (i = 0; i < EVENT_BUFFER_SIZE; i++) { - bindPtr->eventRing[i].type = -1; - } - bindPtr->curEvent = 0; - Tcl_InitHashTable(&bindPtr->patternTable, - sizeof(PatternTableKey)/sizeof(int)); + memset(bindPtr, 0, sizeof(BindingTable)); + for (i = 0; i < SIZE_OF_ARRAY(bindPtr->eventInfo); ++i) { + bindPtr->eventInfo[i].xev.type = -1; + } + bindPtr->curEvent = bindPtr->eventInfo; /* do not assign NULL */ + bindPtr->lookupTables.number = 0; + PromArr_ResizeAndClear(&bindPtr->promArr, 2); + Tcl_InitHashTable(&bindPtr->lookupTables.listTable, sizeof(PatternTableKey)/sizeof(int)); + Tcl_InitHashTable(&bindPtr->lookupTables.patternTable, sizeof(PatternTableKey)/sizeof(int)); Tcl_InitHashTable(&bindPtr->objectTable, TCL_ONE_WORD_KEYS); bindPtr->interp = interp; return bindPtr; @@ -833,32 +1480,100 @@ Tk_DeleteBindingTable( Tk_BindingTable bindPtr) /* Token for the binding table to destroy. */ { - PatSeq *psPtr, *nextPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; + + assert(bindPtr); /* * Find and delete all of the patterns associated with the binding table. */ - for (hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = nextPtr) { + hPtr = Tcl_FirstHashEntry(&bindPtr->lookupTables.patternTable, &search); + for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) { + PatSeq *nextPtr; + PatSeq *psPtr; + + for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) { + assert(TEST_PSENTRY(psPtr)); nextPtr = psPtr->nextSeqPtr; - ckfree(psPtr->script); - ckfree(psPtr); - } - } + FreePatSeq(psPtr); + } + } + + /* + * Don't forget to release lookup elements. + */ + + ClearLookupTable(&bindPtr->lookupTables, NULL); + ClearPromotionLists(bindPtr, NULL); + PromArr_Free(&bindPtr->promArr); + DEBUG(countEntryItems -= PSList_Size(&bindPtr->lookupTables.entryPool);) + PSList_Traverse(&bindPtr->lookupTables.entryPool, FreePatSeqEntry); /* * Clean up the rest of the information associated with the binding table. */ - Tcl_DeleteHashTable(&bindPtr->patternTable); + Tcl_DeleteHashTable(&bindPtr->lookupTables.patternTable); + Tcl_DeleteHashTable(&bindPtr->lookupTables.listTable); Tcl_DeleteHashTable(&bindPtr->objectTable); + ckfree(bindPtr); + DEBUG(countTableItems -= 1;) } +/* + *-------------------------------------------------------------- + * + * InsertPatSeq -- + * + * Insert given pattern sequence into lookup table for fast + * access. + * + * Results: + * None. + * + * Side effects: + * Memory allocated. + * + *-------------------------------------------------------------- + */ + +static void +InsertPatSeq( + LookupTables *lookupTables, + PatSeq *psPtr) +{ + assert(lookupTables); + assert(psPtr); + assert(TEST_PSENTRY(psPtr)); + assert(psPtr->numPats >= 1u); + + if (!(psPtr->added)) { + PatternTableKey key; + Tcl_HashEntry *hPtr; + int isNew; + PSList *psList; + PSEntry *psEntry; + + SetupPatternKey(&key, psPtr); + hPtr = Tcl_CreateHashEntry(&lookupTables->listTable, (char *) &key, &isNew); + + if (isNew) { + psList = ckalloc(sizeof(PSList)); + PSList_Init(psList); + Tcl_SetHashValue(hPtr, psList); + DEBUG(countListItems += 1;) + } else { + psList = Tcl_GetHashValue(hPtr); + } + + psEntry = MakeListEntry(&lookupTables->entryPool, psPtr, 0); + PSList_Append(psList, psEntry); + psPtr->added = 1; + } +} /* *-------------------------------------------------------------- * @@ -887,35 +1602,50 @@ Tk_CreateBinding( Tcl_Interp *interp, /* Used for error reporting. */ Tk_BindingTable bindPtr, /* Table in which to create binding. */ - ClientData object, /* Token for object with which binding is - * associated. */ - const char *eventString, /* String describing event sequence that - * triggers binding. */ - const char *script, /* Contains Tcl script to execute when - * binding triggers. */ - int append) /* 0 means replace any existing binding for - * eventString; 1 means append to that - * binding. If the existing binding is for a - * callback function and not a Tcl command - * string, the existing binding will always be - * replaced. */ + ClientData object, /* Token for object with which binding is associated. */ + const char *eventString, /* String describing event sequence that triggers binding. */ + const char *script, /* Contains Tcl script to execute when binding triggers. */ + int append) /* 0 means replace any existing binding for eventString; + * 1 means append to that binding. If the existing binding is + * for a callback function and not a Tcl command string, the + * existing binding will always be replaced. */ { PatSeq *psPtr; - unsigned long eventMask; - char *newStr, *oldStr; + EventMask eventMask; + char *oldStr; + char *newStr; + + assert(bindPtr); + assert(object); + assert(eventString); + assert(script); + + psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, + !!*script, 1, &eventMask); if (!*script) { + assert(!psPtr || psPtr->added); /* Silently ignore empty scripts -- see SF#3006842 */ - return 1; - } - psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString, - 1, 1, &eventMask); - if (psPtr == NULL) { + return eventMask; + } + if (!psPtr) { return 0; } - if (psPtr->script == NULL) { + assert(TEST_PSENTRY(psPtr)); + + if (psPtr->numPats > PromArr_Capacity(bindPtr->promArr)) { + /* + * We have to increase the size of array containing the lists of promoted sequences. + * Normally the maximal size is 1, only in very seldom cases a bigger size is needed. + * Note that for technical reasons the capacity should be one higher than the expected + * maximal size. + */ + PromArr_ResizeAndClear(&bindPtr->promArr, psPtr->numPats); + } + + if (!psPtr->script) { + Tcl_HashEntry *hPtr; int isNew; - Tcl_HashEntry *hPtr; /* * This pattern sequence was just created. Link the pattern into the @@ -923,33 +1653,28 @@ * these bindings will all automatically be deleted. */ - hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, - &isNew); - if (isNew) { - psPtr->nextObjPtr = NULL; - } else { - psPtr->nextObjPtr = Tcl_GetHashValue(hPtr); - } + hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, &isNew); + psPtr->ptr.nextObj = isNew ? NULL : Tcl_GetHashValue(hPtr); Tcl_SetHashValue(hPtr, psPtr); + InsertPatSeq(&bindPtr->lookupTables, psPtr); } oldStr = psPtr->script; - if ((append != 0) && (oldStr != NULL)) { - size_t length1 = strlen(oldStr), length2 = strlen(script); + if (append && oldStr) { + size_t length1 = strlen(oldStr); + size_t length2 = strlen(script); newStr = ckalloc(length1 + length2 + 2); memcpy(newStr, oldStr, length1); newStr[length1] = '\n'; - memcpy(newStr+length1+1, script, length2+1); + memcpy(newStr + length1 + 1, script, length2 + 1); } else { size_t length = strlen(script); newStr = ckalloc(length + 1); - memcpy(newStr, script, length+1); - } - if (oldStr != NULL) { - ckfree(oldStr); - } + memcpy(newStr, script, length + 1); + } + ckfree(oldStr); psPtr->script = newStr; return eventMask; } @@ -976,66 +1701,51 @@ Tk_DeleteBinding( Tcl_Interp *interp, /* Used for error reporting. */ Tk_BindingTable bindPtr, /* Table in which to delete binding. */ - ClientData object, /* Token for object with which binding is - * associated. */ - const char *eventString) /* String describing event sequence that - * triggers binding. */ -{ - PatSeq *psPtr, *prevPtr; - unsigned long eventMask; - Tcl_HashEntry *hPtr; - - psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString, - 0, 1, &eventMask); - if (psPtr == NULL) { + ClientData object, /* Token for object with which binding is associated. */ + const char *eventString) /* String describing event sequence that triggers binding. */ +{ + PatSeq *psPtr; + + assert(bindPtr); + assert(object); + assert(eventString); + + psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL); + if (!psPtr) { Tcl_ResetResult(interp); - return TCL_OK; - } - - /* - * Unlink the binding from the list for its object, then from the list for - * its pattern. - */ - - hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object); - if (hPtr == NULL) { - Tcl_Panic("Tk_DeleteBinding couldn't find object table entry"); - } - prevPtr = Tcl_GetHashValue(hPtr); - if (prevPtr == psPtr) { - Tcl_SetHashValue(hPtr, psPtr->nextObjPtr); } else { - for ( ; ; prevPtr = prevPtr->nextObjPtr) { - if (prevPtr == NULL) { - Tcl_Panic("Tk_DeleteBinding couldn't find on object list"); - } - if (prevPtr->nextObjPtr == psPtr) { - prevPtr->nextObjPtr = psPtr->nextObjPtr; - break; - } - } - } - prevPtr = Tcl_GetHashValue(psPtr->hPtr); - if (prevPtr == psPtr) { - if (psPtr->nextSeqPtr == NULL) { - Tcl_DeleteHashEntry(psPtr->hPtr); + Tcl_HashEntry *hPtr; + PatSeq *prevPtr; + + assert(TEST_PSENTRY(psPtr)); + + /* + * Unlink the binding from the list for its object. + */ + + if (!(hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) { + Tcl_Panic("Tk_DeleteBinding couldn't find object table entry"); + } + prevPtr = Tcl_GetHashValue(hPtr); + if (prevPtr == psPtr) { + Tcl_SetHashValue(hPtr, psPtr->ptr.nextObj); } else { - Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr); - } - } else { - for ( ; ; prevPtr = prevPtr->nextSeqPtr) { - if (prevPtr == NULL) { - Tcl_Panic("Tk_DeleteBinding couldn't find on hash chain"); - } - if (prevPtr->nextSeqPtr == psPtr) { - prevPtr->nextSeqPtr = psPtr->nextSeqPtr; - break; - } - } - } - - ckfree(psPtr->script); - ckfree(psPtr); + for ( ; ; prevPtr = prevPtr->ptr.nextObj) { + if (!prevPtr) { + Tcl_Panic("Tk_DeleteBinding couldn't find on object list"); + } + if (prevPtr->ptr.nextObj == psPtr) { + prevPtr->ptr.nextObj = psPtr->ptr.nextObj; + break; + } + } + } + + RemovePatSeqFromLookup(&bindPtr->lookupTables, psPtr); + RemovePatSeqFromPromotionLists(bindPtr, psPtr); + DeletePatSeq(psPtr); + } + return TCL_OK; } @@ -1064,20 +1774,18 @@ Tk_GetBinding( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tk_BindingTable bindPtr, /* Table in which to look for binding. */ - ClientData object, /* Token for object with which binding is - * associated. */ - const char *eventString) /* String describing event sequence that - * triggers binding. */ -{ - PatSeq *psPtr; - unsigned long eventMask; - - psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString, - 0, 1, &eventMask); - if (psPtr == NULL) { - return NULL; - } - return psPtr->script; + ClientData object, /* Token for object with which binding is associated. */ + const char *eventString) /* String describing event sequence that triggers binding. */ +{ + const PatSeq *psPtr; + + assert(bindPtr); + assert(object); + assert(eventString); + + psPtr = FindSequence(interp, &bindPtr->lookupTables, object, eventString, 0, 1, NULL); + assert(!psPtr || TEST_PSENTRY(psPtr)); + return psPtr ? psPtr->script : NULL; } /* @@ -1106,26 +1814,171 @@ Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ ClientData object) /* Token for object. */ { - PatSeq *psPtr; Tcl_HashEntry *hPtr; - Tcl_Obj *resultObj; - - hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object); - if (hPtr == NULL) { - return; - } - - resultObj = Tcl_NewObj(); - for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; - psPtr = psPtr->nextObjPtr) { + + assert(bindPtr); + assert(object); + + if ((hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) { + const PatSeq *psPtr; + Tcl_Obj *resultObj = Tcl_NewObj(); + /* - * For each binding, output information about each of the patterns in - * its sequence. + * For each binding, output information about each of the patterns in its sequence. */ - Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(psPtr)); - } - Tcl_SetObjResult(interp, resultObj); + for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = psPtr->ptr.nextObj) { + assert(TEST_PSENTRY(psPtr)); + Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(psPtr)); + } + Tcl_SetObjResult(interp, resultObj); + } +} + +/* + *-------------------------------------------------------------- + * + * RemovePatSeqFromLookup -- + * + * Remove given pattern sequence from lookup tables. This + * can be required before deleting the pattern sequence. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +RemovePatSeqFromLookup( + LookupTables *lookupTables, /* Remove from this lookup tables. */ + PatSeq *psPtr) /* Remove this pattern sequence. */ +{ + PatternTableKey key; + Tcl_HashEntry *hPtr; + + assert(lookupTables); + assert(psPtr); + + SetupPatternKey(&key, psPtr); + + if ((hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key))) { + PSList *psList = Tcl_GetHashValue(hPtr); + PSEntry *psEntry; + + TK_DLIST_FOREACH(psEntry, psList) { + if (psEntry->psPtr == psPtr) { + psPtr->added = 0; + RemoveListEntry(&lookupTables->entryPool, psEntry); + return; + } + } + } + + assert(!"couldn't find pattern sequence in lookup"); +} + +/* + *-------------------------------------------------------------- + * + * RemovePatSeqFromPromotionLists -- + * + * Remove given pattern sequence from promotion lists. This + * can be required before deleting the pattern sequence. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +RemovePatSeqFromPromotionLists( + Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ + PatSeq *psPtr) /* Remove this pattern sequence. */ +{ + unsigned i; + + assert(bindPtr); + assert(psPtr); + + for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) { + PSList *psList = PromArr_Get(bindPtr->promArr, i); + PSEntry *psEntry; + + TK_DLIST_FOREACH(psEntry, psList) { + if (psEntry->psPtr == psPtr) { + RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry); + break; + } + } + } +} + +/* + *-------------------------------------------------------------- + * + * DeletePatSeq -- + * + * Delete given pattern sequence. Possibly it is required + * to invoke RemovePatSeqFromLookup(), and RemovePatSeqFromPromotionLists() + * before. + * + * Results: + * Pointer to succeeding pattern sequence. + * + * Side effects: + * Deallocation of memory. + * + *-------------------------------------------------------------- + */ + +static PatSeq * +DeletePatSeq( + PatSeq *psPtr) /* Delete this pattern sequence. */ +{ + PatSeq *prevPtr; + PatSeq *nextPtr; + + assert(psPtr); + assert(!psPtr->added); + assert(!psPtr->owned); + + prevPtr = Tcl_GetHashValue(psPtr->hPtr); + nextPtr = psPtr->ptr.nextObj; + + /* + * Be sure to remove each binding from its hash chain in the pattern + * table. If this is the last pattern in the chain, then delete the + * hash entry too. + */ + + if (prevPtr == psPtr) { + if (!psPtr->nextSeqPtr) { + Tcl_DeleteHashEntry(psPtr->hPtr); + } else { + Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr); + } + } else { + for ( ; ; prevPtr = prevPtr->nextSeqPtr) { + if (!prevPtr) { + Tcl_Panic("DeletePatSeq couldn't find on hash chain"); + } + if (prevPtr->nextSeqPtr == psPtr) { + prevPtr->nextSeqPtr = psPtr->nextSeqPtr; + break; + } + } + } + + FreePatSeq(psPtr); + return nextPtr; } /* @@ -1150,45 +2003,30 @@ Tk_BindingTable bindPtr, /* Table in which to delete bindings. */ ClientData object) /* Token for object. */ { - PatSeq *psPtr, *prevPtr; + PatSeq *psPtr; PatSeq *nextPtr; Tcl_HashEntry *hPtr; - hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object); - if (hPtr == NULL) { + assert(bindPtr); + assert(object); + + if (!(hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object))) { return; } - for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; - psPtr = nextPtr) { - nextPtr = psPtr->nextObjPtr; - - /* - * Be sure to remove each binding from its hash chain in the pattern - * table. If this is the last pattern in the chain, then delete the - * hash entry too. - */ - - prevPtr = Tcl_GetHashValue(psPtr->hPtr); - if (prevPtr == psPtr) { - if (psPtr->nextSeqPtr == NULL) { - Tcl_DeleteHashEntry(psPtr->hPtr); - } else { - Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr); - } - } else { - for ( ; ; prevPtr = prevPtr->nextSeqPtr) { - if (prevPtr == NULL) { - Tcl_Panic("Tk_DeleteAllBindings couldn't find on hash chain"); - } - if (prevPtr->nextSeqPtr == psPtr) { - prevPtr->nextSeqPtr = psPtr->nextSeqPtr; - break; - } - } - } - ckfree(psPtr->script); - ckfree(psPtr); - } + + /* + * Don't forget to clear lookup tables. + */ + + ClearLookupTable(&bindPtr->lookupTables, object); + ClearPromotionLists(bindPtr, object); + + for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) { + assert(TEST_PSENTRY(psPtr)); + DEBUG(psPtr->added = 0;) + nextPtr = DeletePatSeq(psPtr); + } + Tcl_DeleteHashEntry(hPtr); } @@ -1217,41 +2055,138 @@ *--------------------------------------------------------------------------- */ +/* helper function */ +static void +ResetCounters( + Event *eventInfo, + unsigned eventType, + Window window) +{ + Event *curEvent; + + assert(eventInfo); + curEvent = eventInfo + eventType; + + if (curEvent->xev.xany.window == window) { + curEvent->xev.xany.window = None; + eventInfo[eventType].countAny = 0; + eventInfo[eventType].countDetailed = 0; + } +} + +/* helper function */ +static int +IsBetterMatch( + const PatSeq *fstMatchPtr, + const PatSeq *sndMatchPtr) /* this is a better match? */ +{ + int diff; + + if (!sndMatchPtr) { return 0; } + if (!fstMatchPtr) { return 1; } + + diff = CountSpecialized(fstMatchPtr, sndMatchPtr); + if (diff > 0) { return 1; } + if (diff < 0) { return 0; } + +#if PREFER_MOST_SPECIALIZED_EVENT + { /* local scope */ +#define M (Tcl_WideUInt)1000000 + static const Tcl_WideUInt weight[5] = { 0, 1, M, M*M, M*M*M }; +#undef M + Tcl_WideUInt fstCount = 0; + Tcl_WideUInt sndCount = 0; + unsigned i; + + /* + * Count the most high-ordered patterns. + * + * (This computation assumes that a sequence does not contain more than + * 1,000,000 single patterns. It can be precluded that in practice this + * assumption will not be violated.) + */ + + for (i = 0; i < fstMatchPtr->numPats; ++i) { + assert(GetCount(fstMatchPtr, i) < SIZE_OF_ARRAY(weight)); + fstCount += weight[GetCount(fstMatchPtr, i)]; + } + for (i = 0; i < sndMatchPtr->numPats; ++i) { + assert(GetCount(sndMatchPtr, i) < SIZE_OF_ARRAY(weight)); + sndCount += weight[GetCount(sndMatchPtr, i)]; + } + if (sndCount > fstCount) { return 1; } + if (sndCount < fstCount) { return 0; } + } +#endif + + return sndMatchPtr->number > fstMatchPtr->number; +} + void Tk_BindEvent( Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ XEvent *eventPtr, /* What actually happened. */ - Tk_Window tkwin, /* Window on display where event occurred - * (needed in order to locate display - * information). */ - int numObjects, /* Number of objects at *objectPtr. */ - ClientData *objectPtr) /* Array of one or more objects to check for a - * matching binding. */ -{ + Tk_Window tkwin, /* Window on display where event occurred (needed in order to + * locate display information). */ + int numObjects, /* Number of objects at *objArr. */ + ClientData *objArr) /* Array of one or more objects to check for a matching binding. */ +{ + Tcl_Interp *interp; + ScreenInfo *screenPtr; TkDisplay *dispPtr; - ScreenInfo *screenPtr; + TkDisplay *oldDispPtr; + Event *curEvent; + TkWindow *winPtr = (TkWindow *) tkwin; BindInfo *bindInfoPtr; - TkDisplay *oldDispPtr; - XEvent *ringPtr; - PatSeq *vMatchDetailList, *vMatchNoDetailList; - int flags, oldScreen; - unsigned int scriptCount; - Tcl_Interp *interp; + Tcl_InterpState interpState; + LookupTables *physTables; + PatSeq *psPtr[2]; + PatSeq *matchPtrBuf[32]; + PatSeq **matchPtrArr = matchPtrBuf; + PSList *psl[2]; Tcl_DString scripts; - Tcl_InterpState interpState; - Detail detail; - char *p, *end; - TkWindow *winPtr = (TkWindow *) tkwin; - PatternTableKey key; + const char *p; + const char *end; + unsigned scriptCount; + int oldScreen; + unsigned flags; + unsigned arraySize; + unsigned newArraySize; + unsigned i, k; + + assert(bindPtr); + assert(eventPtr); + assert(tkwin); + assert(numObjects >= 0); /* * Ignore events on windows that don't have names: these are windows like * wrapper windows that shouldn't be visible to the application. */ - if (winPtr->pathName == NULL) { + if (!winPtr->pathName) { return; } + + flags = flagArray[eventPtr->type]; + + /* + * Ignore event types which are not in flagArray and all zeroes there. + */ + + if (eventPtr->type >= TK_LASTEVENT || !flags) { + return; + } + + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { + bindPtr->curModMask = eventPtr->xkey.state; + } else if (flags & CROSSING) { + bindPtr->curModMask = eventPtr->xcrossing.state; + } + + dispPtr = ((TkWindow *) tkwin)->dispPtr; + bindInfoPtr = winPtr->mainPtr->bindInfo; + curEvent = bindPtr->eventInfo + eventPtr->type; /* * Ignore the event completely if it is an Enter, Leave, FocusIn, or @@ -1260,205 +2195,339 @@ * children to visible to bindings on the parent: this would cause * problems for mega-widgets, since the internal structure of a * mega-widget isn't supposed to be visible to people watching the parent. + * + * Furthermore we have to compute current time, needed for "event generate". */ - if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) { + switch (eventPtr->type) { + case EnterNotify: + case LeaveNotify: + if (eventPtr->xcrossing.time) { + bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); + bindInfoPtr->lastEventTime = eventPtr->xcrossing.time; + } if (eventPtr->xcrossing.detail == NotifyInferior) { return; } - } - if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) { + break; + case FocusIn: + case FocusOut: if (eventPtr->xfocus.detail == NotifyInferior) { return; } + break; + case KeyPress: + case KeyRelease: { + int reset = 1; + + if (eventPtr->xkey.time) { + bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); + bindInfoPtr->lastEventTime = eventPtr->xkey.time; + } + /* modifier keys should not influence button events */ + for (i = 0; i < (unsigned) dispPtr->numModKeyCodes; ++i) { + if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) { + reset = 0; + } + } + if (reset) { + /* reset repetition count for button events */ + bindPtr->eventInfo[ButtonPress].countAny = 0; + bindPtr->eventInfo[ButtonPress].countDetailed = 0; + bindPtr->eventInfo[ButtonRelease].countAny = 0; + bindPtr->eventInfo[ButtonRelease].countDetailed = 0; + } + break; + } + case ButtonPress: + case ButtonRelease: + /* reset repetition count for key events */ + bindPtr->eventInfo[KeyPress].countAny = 0; + bindPtr->eventInfo[KeyPress].countDetailed = 0; + bindPtr->eventInfo[KeyRelease].countAny = 0; + bindPtr->eventInfo[KeyRelease].countDetailed = 0; + /* fallthru */ + case MotionNotify: + if (eventPtr->xmotion.time) { + bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); + bindInfoPtr->lastEventTime = eventPtr->xmotion.time; + } + break; + case PropertyNotify: + if (eventPtr->xproperty.time) { + bindInfoPtr->lastCurrentTime = CurrentTimeInMilliSecs(); + bindInfoPtr->lastEventTime = eventPtr->xproperty.time; + } + break; + case DestroyNotify: + ResetCounters(bindPtr->eventInfo, KeyPress, eventPtr->xany.window); + ResetCounters(bindPtr->eventInfo, KeyRelease, eventPtr->xany.window); + ResetCounters(bindPtr->eventInfo, ButtonPress, eventPtr->xany.window); + ResetCounters(bindPtr->eventInfo, ButtonRelease, eventPtr->xany.window); + break; } /* - * Ignore event types which are not in flagArray and all zeroes there. - * Most notably, NoExpose events can fill the ring buffer and disturb - * (thus masking out) event sequences of interest. + * Now check whether this is a repeating event (multi-click, repeated key press, and so on). */ - if ((eventPtr->type >= TK_LASTEVENT) || !flagArray[eventPtr->type]) { - return; - } - - dispPtr = ((TkWindow *) tkwin)->dispPtr; - bindInfoPtr = winPtr->mainPtr->bindInfo; + /* NOTE: if curEvent is not yet set, then the following cannot match: */ + if (curEvent->xev.xany.window == eventPtr->xany.window) { + switch (eventPtr->type) { + case KeyPress: + case KeyRelease: + if (MatchEventRepeat(&curEvent->xev, eventPtr)) { + if (curEvent->xev.xkey.keycode == eventPtr->xkey.keycode) { + ++curEvent->countDetailed; + } else { + curEvent->countDetailed = 1; + } + ++curEvent->countAny; + } else { + curEvent->countAny = curEvent->countDetailed = 1; + } + break; + case ButtonPress: + case ButtonRelease: + if (MatchEventNearby(&curEvent->xev, eventPtr)) { + if (curEvent->xev.xbutton.button == eventPtr->xbutton.button) { + ++curEvent->countDetailed; + } else { + curEvent->countDetailed = 1; + } + ++curEvent->countAny; + } else { + curEvent->countAny = curEvent->countDetailed = 1; + } + break; + case EnterNotify: + case LeaveNotify: + if (TestNearbyTime(eventPtr->xcrossing.time, curEvent->xev.xcrossing.time)) { + ++curEvent->countAny; + } else { + curEvent->countAny = 1; + } + break; + case PropertyNotify: + if (TestNearbyTime(eventPtr->xproperty.time, curEvent->xev.xproperty.time)) { + ++curEvent->countAny; + } else { + curEvent->countAny = 1; + } + break; + default: + ++curEvent->countAny; + break; + } + } else { + curEvent->countAny = curEvent->countDetailed = 1; + } /* - * Add the new event to the ring of saved events for the binding table. - * Two tricky points: - * - * 1. Combine consecutive MotionNotify events. Do this by putting the new - * event *on top* of the previous event. - * 2. If a modifier key is held down, it auto-repeats to generate - * continuous KeyPress and KeyRelease events. These can flush the event - * ring so that valuable information is lost (such as repeated button - * clicks). To handle this, check for the special case of a modifier - * KeyPress arriving when the previous two events are a KeyRelease and - * KeyPress of the same key. If this happens, mark the most recent - * event (the KeyRelease) invalid and put the new event on top of the - * event before that (the KeyPress). + * Now update the details. */ - if ((eventPtr->type == MotionNotify) - && (bindPtr->eventRing[bindPtr->curEvent].type == MotionNotify)) { - /* - * Don't advance the ring pointer. - */ - } else if (eventPtr->type == KeyPress) { - int i; - - for (i = 0; ; i++) { - if (i >= dispPtr->numModKeyCodes) { - goto advanceRingPointer; - } - if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) { - break; - } - } - ringPtr = &bindPtr->eventRing[bindPtr->curEvent]; - if ((ringPtr->type != KeyRelease) - || (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) { - goto advanceRingPointer; - } - if (bindPtr->curEvent <= 0) { - i = EVENT_BUFFER_SIZE - 1; + curEvent->xev = *eventPtr; + if (flags & KEY) { + curEvent->detail.info = TkpGetKeySym(dispPtr, eventPtr); + } else if (flags & BUTTON) { + curEvent->detail.info = eventPtr->xbutton.button; + } else if (flags & MOTION) { + curEvent->detail.info = ButtonNumberFromState(eventPtr->xmotion.state); + } else if (flags & VIRTUAL) { + curEvent->detail.name = ((XVirtualEvent *) eventPtr)->name; + } + + bindPtr->curEvent = curEvent; + physTables = &bindPtr->lookupTables; + scriptCount = 0; + arraySize = 0; + Tcl_DStringInit(&scripts); + + if ((size_t) numObjects > SIZE_OF_ARRAY(matchPtrBuf)) { + /* it's unrealistic that the buffer size is too small, but who knows? */ + matchPtrArr = ckalloc(numObjects*sizeof(matchPtrArr[0])); + } + memset(matchPtrArr, 0, numObjects*sizeof(matchPtrArr[0])); + + if (!PromArr_IsEmpty(bindPtr->promArr)) { + for (k = 0; k < (unsigned) numObjects; ++k) { + psl[1] = PromArr_Last(bindPtr->promArr); + psl[0] = psl[1] - 1; + + /* + * Loop over all promoted bindings, finding the longest matching one. + * + * Note that we must process all lists, because all matching patterns + * have to be promoted. Normally at most one list will be processed, and + * usually this list only contains one or two patterns. + */ + + for (i = PromArr_Size(bindPtr->promArr); i > 0; --i, --psl[0], --psl[1]) { + psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psl[1], i, curEvent, objArr[k], NULL); + + if (IsBetterMatch(matchPtrArr[k], psPtr[0])) { + /* we will process it later, because we still may find a pattern with better match */ + matchPtrArr[k] = psPtr[0]; + } + if (!PSList_IsEmpty(psl[1])) { + /* we have promoted sequences, adjust array size */ + arraySize = Max(i + 1, arraySize); + } + } + } + } + + /* + * 1. Look for bindings for the specific detail (button and key events). + * 2. Look for bindings without detail. + */ + + for (k = 0; k < (unsigned) numObjects; ++k) { + PSList *psSuccList = PromArr_First(bindPtr->promArr); + PatSeq *bestPtr; + + psl[0] = GetLookupForEvent(physTables, curEvent, objArr[k], 1); + psl[1] = GetLookupForEvent(physTables, curEvent, objArr[k], 0); + + assert(psl[0] == NULL || psl[0] != psl[1]); + + psPtr[0] = MatchPatterns(dispPtr, bindPtr, psl[0], psSuccList, 0, curEvent, objArr[k], NULL); + psPtr[1] = MatchPatterns(dispPtr, bindPtr, psl[1], psSuccList, 0, curEvent, objArr[k], NULL); + + if (!PSList_IsEmpty(psSuccList)) { + /* we have promoted sequences, adjust array size */ + arraySize = Max(1u, arraySize); + } + + bestPtr = psPtr[0] ? psPtr[0] : psPtr[1]; + + if (matchPtrArr[k]) { + if (IsBetterMatch(matchPtrArr[k], bestPtr)) { + matchPtrArr[k] = bestPtr; + } else { + /* + * We've already found a higher level match, nevertheless it was required to + * process the level zero patterns because of possible promotions. + */ + } + /* + * Now we have to catch up the processing of the script. + */ } else { - i = bindPtr->curEvent - 1; - } - ringPtr = &bindPtr->eventRing[i]; - if ((ringPtr->type != KeyPress) - || (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) { - goto advanceRingPointer; - } - bindPtr->eventRing[bindPtr->curEvent].type = -1; - bindPtr->curEvent = i; - } else { - - advanceRingPointer: - bindPtr->curEvent++; - if (bindPtr->curEvent >= EVENT_BUFFER_SIZE) { - bindPtr->curEvent = 0; - } - } - ringPtr = &bindPtr->eventRing[bindPtr->curEvent]; - memcpy(ringPtr, eventPtr, sizeof(XEvent)); - detail.clientData = 0; - flags = flagArray[ringPtr->type]; - if (flags & KEY) { - detail.keySym = TkpGetKeySym(dispPtr, ringPtr); - if (detail.keySym == NoSymbol) { - detail.keySym = 0; - } - } else if (flags & BUTTON) { - detail.button = ringPtr->xbutton.button; - } else if (flags & VIRTUAL) { - detail.name = ((XVirtualEvent *) ringPtr)->name; - } - bindPtr->detailRing[bindPtr->curEvent] = detail; + /* + * We have to look whether we can find a better match in virtual table, provided that we + * don't have a higher level match. + */ + + matchPtrArr[k] = bestPtr; + + if (eventPtr->type != VirtualEvent) { + LookupTables *virtTables = &bindInfoPtr->virtualEventTable.lookupTables; + PatSeq *matchPtr = matchPtrArr[k]; + PatSeq *mPtr; + PSList *psl[2]; + + /* + * Note that virtual events cannot promote. + */ + + psl[0] = GetLookupForEvent(virtTables, curEvent, NULL, 1); + psl[1] = GetLookupForEvent(virtTables, curEvent, NULL, 0); + + assert(psl[0] == NULL || psl[0] != psl[1]); + + mPtr = MatchPatterns(dispPtr, bindPtr, psl[0], NULL, 0, curEvent, objArr[k], &matchPtr); + if (mPtr) { + matchPtrArr[k] = matchPtr; + matchPtr = mPtr; + } + if (MatchPatterns(dispPtr, bindPtr, psl[1], NULL, 0, curEvent, objArr[k], &matchPtr)) { + matchPtrArr[k] = matchPtr; + } + } + } + + if (matchPtrArr[k]) { + ExpandPercents(winPtr, matchPtrArr[k]->script, curEvent, scriptCount++, &scripts); + /* nul is added to the scripts string to separate the various scripts */ + Tcl_DStringAppend(&scripts, "", 1); + } + } + + PromArr_SetSize(bindPtr->promArr, arraySize); /* - * Find out if there are any virtual events that correspond to this - * physical event (or sequence of physical events). + * Remove expired pattern sequences. */ - vMatchDetailList = NULL; - vMatchNoDetailList = NULL; - memset(&key, 0, sizeof(key)); - - if (ringPtr->type != VirtualEvent) { - Tcl_HashTable *veptPtr = &bindInfoPtr->virtualEventTable.patternTable; - Tcl_HashEntry *hPtr; - - key.object = NULL; - key.type = ringPtr->type; - key.detail = detail; - - hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key); - if (hPtr != NULL) { - vMatchDetailList = Tcl_GetHashValue(hPtr); - } - - if (key.detail.clientData != 0) { - key.detail.clientData = 0; - hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key); - if (hPtr != NULL) { - vMatchNoDetailList = Tcl_GetHashValue(hPtr); - } - } - } - - /* - * Loop over all the binding tags, finding the binding script or callback - * for each one. Append all of the binding scripts, with %-sequences - * expanded, to "scripts", with null characters separating the scripts for - * each object. - */ - - scriptCount = 0; - Tcl_DStringInit(&scripts); - - for ( ; numObjects > 0; numObjects--, objectPtr++) { - PatSeq *matchPtr = NULL, *sourcePtr = NULL; - Tcl_HashEntry *hPtr; - - /* - * Match the new event against those recorded in the pattern table, - * saving the longest matching pattern. For events with details - * (button and key events), look for a binding for the specific key or - * button. First see if the event matches a physical event that the - * object is interested in, then look for a virtual event. - */ - - key.object = *objectPtr; - key.type = ringPtr->type; - key.detail = detail; - hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); - if (hPtr != NULL) { - matchPtr = MatchPatterns(dispPtr, bindPtr, Tcl_GetHashValue(hPtr), - matchPtr, NULL, &sourcePtr); - } - - if (vMatchDetailList != NULL) { - matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchDetailList, - matchPtr, objectPtr, &sourcePtr); - } - - /* - * If no match was found, look for a binding for all keys or buttons - * (detail of 0). Again, first match on a virtual event. - */ - - if ((detail.clientData != 0) && (matchPtr == NULL)) { - key.detail.clientData = 0; - hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); - if (hPtr != NULL) { - matchPtr = MatchPatterns(dispPtr, bindPtr, - Tcl_GetHashValue(hPtr), matchPtr, NULL, &sourcePtr); - } - - if (vMatchNoDetailList != NULL) { - matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchNoDetailList, - matchPtr, objectPtr, &sourcePtr); - } - } - - if (matchPtr != NULL) { - ExpandPercents(winPtr, sourcePtr->script, eventPtr, - detail.keySym, scriptCount++, &scripts); + for (i = 0, newArraySize = 0; i < arraySize; ++i) { + PSList *psList = PromArr_Get(bindPtr->promArr, i); + PSEntry *psEntry; + PSEntry *psNext; + + for (psEntry = PSList_First(psList); psEntry; psEntry = psNext) { + const TkPattern *patPtr; + + assert(i + 1 < psEntry->psPtr->numPats); + + psNext = PSList_Next(psEntry); + patPtr = &psEntry->psPtr->pats[i + 1]; /* - * A "" is added to the scripts string to separate the various - * scripts that should be invoked. + * We have to remove the following entries from promotion list (but + * only if we don't want to keep it): + * ------------------------------------------------------------------ + * 1) It is marked as expired (see MatchPatterns()). + * 2) If we have a Key event, and current entry is matching a Button. + * 3) If we have a Button event, and current entry is matching a Key. + * 4) If we have a detailed event, current entry it is also detailed, + * we have matching event types, but the details are different. + * 5) Current entry has been matched with a different window. */ - Tcl_DStringAppend(&scripts, "", 1); - } - } + if (psEntry->keepIt) { + assert(!psEntry->expired); + psEntry->keepIt = 0; + } else if (psEntry->expired + || psEntry->window != curEvent->xev.xany.window + || (patPtr->info + && curEvent->detail.info + && patPtr->eventType == (unsigned) curEvent->xev.type + && patPtr->info != curEvent->detail.info)) { + RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry); + } else { + switch (patPtr->eventType) { + case ButtonPress: + case ButtonRelease: + if (curEvent->xev.type == KeyPress || curEvent->xev.type == KeyRelease) { + RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry); + } + break; + case KeyPress: + case KeyRelease: + if (curEvent->xev.type == ButtonPress || curEvent->xev.type == ButtonRelease) { + RemoveListEntry(&bindPtr->lookupTables.entryPool, psEntry); + } + break; + } + } + } + + if (!PSList_IsEmpty(psList)) { + /* we still have promoted sequences, adjust array size */ + newArraySize = Max(i + 1, newArraySize); + } + } + + PromArr_SetSize(bindPtr->promArr, newArraySize); + + if (matchPtrArr != matchPtrBuf) { + ckfree(matchPtrArr); + } + if (Tcl_DStringLength(&scripts) == 0) { - return; + return; /* nothing to do */ } /* @@ -1489,15 +2558,12 @@ screenPtr = &bindInfoPtr->screenInfo; oldDispPtr = screenPtr->curDispPtr; oldScreen = screenPtr->curScreenIndex; - if ((dispPtr != screenPtr->curDispPtr) - || (Tk_ScreenNumber(tkwin) != screenPtr->curScreenIndex)) { + + if (dispPtr != screenPtr->curDispPtr || Tk_ScreenNumber(tkwin) != screenPtr->curScreenIndex) { screenPtr->curDispPtr = dispPtr; screenPtr->curScreenIndex = Tk_ScreenNumber(tkwin); ChangeScreen(interp, dispPtr->name, screenPtr->curScreenIndex); } - - p = Tcl_DStringValue(&scripts); - end = p + Tcl_DStringLength(&scripts); /* * Be careful when dereferencing screenPtr or bindInfoPtr. If we evaluate @@ -1506,12 +2572,13 @@ */ Tcl_Preserve(bindInfoPtr); - while (p < end) { - int len = (int) strlen(p); + + for (p = Tcl_DStringValue(&scripts), end = p + Tcl_DStringLength(&scripts); p < end; ) { + unsigned len = strlen(p); int code; if (!bindInfoPtr->deleted) { - screenPtr->bindingDepth++; + ++screenPtr->bindingDepth; } Tcl_AllowExceptions(interp); @@ -1519,38 +2586,30 @@ p += len + 1; if (!bindInfoPtr->deleted) { - screenPtr->bindingDepth--; - } - if (code != TCL_OK) { - if (code == TCL_CONTINUE) { - /* - * Do nothing: just go on to the next command. - */ - } else if (code == TCL_BREAK) { - break; - } else { + --screenPtr->bindingDepth; + } + if (code != TCL_OK && code != TCL_CONTINUE) { + if (code != TCL_BREAK) { Tcl_AddErrorInfo(interp, "\n (command bound to event)"); Tcl_BackgroundException(interp, code); - break; - } - } - } - - if (!bindInfoPtr->deleted && (screenPtr->bindingDepth != 0) - && ((oldDispPtr != screenPtr->curDispPtr) - || (oldScreen != screenPtr->curScreenIndex))) { + } + break; + } + } + + if (!bindInfoPtr->deleted + && screenPtr->bindingDepth > 0 + && (oldDispPtr != screenPtr->curDispPtr || oldScreen != screenPtr->curScreenIndex)) { /* * Some other binding script is currently executing, but its screen is * no longer current. Change the current display back again. */ - screenPtr->curDispPtr = oldDispPtr; screenPtr->curScreenIndex = oldScreen; ChangeScreen(interp, oldDispPtr->name, oldScreen); } - (void) Tcl_RestoreInterpState(interp, interpState); + Tcl_RestoreInterpState(interp, interpState); Tcl_DStringFree(&scripts); - Tcl_Release(bindInfoPtr); } @@ -1559,346 +2618,269 @@ * * MatchPatterns -- * - * Given a list of pattern sequences and a list of recent events, return - * the pattern sequence that best matches the event list, if there is + * Given a list of pattern sequences and the recent event, return + * the pattern sequence that best matches this event, if there is * one. * - * This function is used in two different ways. In the simplest use, - * "object" is NULL and psPtr is a list of pattern sequences, each of - * which corresponds to a binding. In this case, the function finds the - * pattern sequences that match the event list and returns the most - * specific of those, if there is more than one. - * - * In the second case, psPtr is a list of pattern sequences, each of - * which corresponds to a definition for a virtual binding. In order for - * one of these sequences to "match", it must match the events (as above) - * but in addition there must be a binding for its associated virtual - * event on the current object. The "object" argument indicates which - * object the binding must be for. - * * Results: - - * The return value is NULL if bestPtr is NULL and no pattern matches the - * recent events from bindPtr. Otherwise the return value is the most - * specific pattern sequence among bestPtr and all those at psPtr that - * match the event list and object. If a pattern sequence other than - * bestPtr is returned, then *bestCommandPtr is filled in with a pointer - * to the command from the best sequence. + * + * The return value is NULL if no match is found. Otherwise the + * return value is the most specific pattern sequence among all + * those that match the event table. * * Side effects: * None. * *---------------------------------------------------------------------- */ + +/* helper function */ +static int +VirtPatIsBound( + Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ + PatSeq *psPtr, /* Test this pattern. */ + ClientData object, /* Check for this binding tag. */ + PatSeq **physPtrPtr) /* Input: the best physical event. + * Output: the physical event associated with matching virtual event. */ +{ + PatternTableKey key; + const struct VirtOwners *owners; + unsigned i; + + assert(bindPtr); + assert(psPtr); + assert(!psPtr->object); + assert(physPtrPtr); + + if (*physPtrPtr) { + const TkPattern *physPatPtr = (*physPtrPtr)->pats; + const TkPattern *virtPatPtr = psPtr->pats; + + if (physPatPtr->info || !virtPatPtr->info) { + if (IsSubsetOf(virtPatPtr->modMask, physPatPtr->modMask)) { + return 0; /* we cannot surpass this match */ + } + } + } + + /* otherwise on some systems the key contains uninitialized bytes */ + memset(&key, 0, sizeof(key)); + + key.object = object; + key.type = VirtualEvent; + owners = psPtr->ptr.owners; + + for (i = 0; i < VirtOwners_Size(owners); ++i) { + Tcl_HashEntry *hPtr = VirtOwners_Get(owners, i); + + key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr, hPtr); + + if ((hPtr = Tcl_FindHashEntry(&bindPtr->lookupTables.patternTable, (char *) &key))) { + /* The physical event matches this virtual event's definition. */ + *physPtrPtr = (PatSeq *) Tcl_GetHashValue(hPtr); + return 1; + } + } + + return 0; +} + +/* helper function */ +static int +Compare( + const PatSeq *fstMatchPtr, + const PatSeq *sndMatchPtr) /* most recent match */ +{ + int diff; + + if (!fstMatchPtr) { return +1; } + assert(sndMatchPtr); + diff = CountSpecialized(fstMatchPtr, sndMatchPtr); + return diff ? diff : (int) sndMatchPtr->count - (int) fstMatchPtr->count; +} + +/* helper function */ +static int +CompareModMasks( + const PSModMaskArr *fstModMaskArr, + const PSModMaskArr *sndModMaskArr, + ModMask fstModMask, + ModMask sndModMask) +{ + int fstCount = 0; + int sndCount = 0; + int i; + + if (PSModMaskArr_IsEmpty(fstModMaskArr)) { + if (!PSModMaskArr_IsEmpty(sndModMaskArr)) { + for (i = PSModMaskArr_Size(sndModMaskArr) - 1; i >= 0; --i) { + if (*PSModMaskArr_Get(sndModMaskArr, i)) { + ++sndCount; + } + } + } + } else if (PSModMaskArr_IsEmpty(sndModMaskArr)) { + for (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) { + if (*PSModMaskArr_Get(fstModMaskArr, i)) { + ++fstCount; + } + } + } else { + assert(PSModMaskArr_Size(fstModMaskArr) == PSModMaskArr_Size(sndModMaskArr)); + + for (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) { + ModMask fstModMask = *PSModMaskArr_Get(fstModMaskArr, i); + ModMask sndModMask = *PSModMaskArr_Get(sndModMaskArr, i); + + if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; } + if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; } + } + } + + /* Finally compare modifier masks of last pattern. */ + + if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; } + if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; } + + return fstCount - sndCount; +} static PatSeq * MatchPatterns( TkDisplay *dispPtr, /* Display from which the event came. */ - BindingTable *bindPtr, /* Information about binding table, such as - * ring of recent events. */ - PatSeq *psPtr, /* List of pattern sequences. */ - PatSeq *bestPtr, /* The best match seen so far, from a previous - * call to this function. NULL means no prior - * best match. */ - ClientData *objectPtr, /* If NULL, the sequences at psPtr correspond - * to "normal" bindings. If non-NULL, the - * sequences at psPtr correspond to virtual - * bindings; in order to match each sequence - * must correspond to a virtual binding for - * which a binding exists for object in - * bindPtr. */ - PatSeq **sourcePtrPtr) /* Filled with the pattern sequence that - * contains the eventProc and clientData - * associated with the best match. If this - * differs from the return value, it is the - * virtual event that most closely matched the - * return value (a physical event). Not - * modified unless a result other than bestPtr - * is returned. */ -{ - PatSeq *matchPtr, *bestSourcePtr, *sourcePtr; - - bestSourcePtr = *sourcePtrPtr; - - /* - * Iterate over all the pattern sequences. - */ - - for ( ; psPtr != NULL; psPtr = psPtr->nextSeqPtr) { - XEvent *eventPtr = &bindPtr->eventRing[bindPtr->curEvent]; - Detail *detailPtr = &bindPtr->detailRing[bindPtr->curEvent]; - TkPattern *patPtr = psPtr->pats; - Window window = eventPtr->xany.window; - int patCount, ringCount, flags, state, modMask, i; - - /* - * Iterate over all the patterns in a sequence to be sure that they - * all match. - */ - - patCount = psPtr->numPats; - ringCount = EVENT_BUFFER_SIZE; - while (patCount > 0) { - if (ringCount <= 0) { - goto nextSequence; - } - if (eventPtr->xany.type != patPtr->eventType) { - /* - * Most of the event types are considered superfluous in that - * they are ignored if they occur in the middle of a pattern - * sequence and have mismatching types. The only ones that - * cannot be ignored are ButtonPress and ButtonRelease events - * (if the next event in the pattern is a KeyPress or - * KeyRelease) and KeyPress and KeyRelease events (if the next - * pattern event is a ButtonPress or ButtonRelease). Here are - * some tricky cases to consider: - * 1. Double-Button or Double-Key events. - * 2. Double-ButtonRelease or Double-KeyRelease events. - * 3. The arrival of various events like Enter and Leave and - * FocusIn and GraphicsExpose between two button presses or - * key presses. - * 4. Modifier keys like Shift and Control shouldn't generate - * conflicts with button events. - */ - - if ((patPtr->eventType == KeyPress) - || (patPtr->eventType == KeyRelease)) { - if ((eventPtr->xany.type == ButtonPress) - || (eventPtr->xany.type == ButtonRelease)) { - goto nextSequence; - } - } else if ((patPtr->eventType == ButtonPress) - || (patPtr->eventType == ButtonRelease)) { - if ((eventPtr->xany.type == KeyPress) - || (eventPtr->xany.type == KeyRelease)) { + Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ + PSList *psList, /* List of potentially matching patterns, can be NULL. */ + PSList *psSuccList, /* Add all matching higher-level pattern sequences to this list. + * Can be NULL. */ + unsigned patIndex, /* Match only this tag in sequence. */ + const Event *curEvent, /* Match this event. */ + ClientData object, /* Check for this binding tag. */ + PatSeq **physPtrPtr) /* Input: the best physical event; NULL if we test physical events. + * Output: the associated physical event for the best matching virtual + * event; NULL when we match physical events. */ +{ + Window window; + PSEntry *psEntry; + PatSeq *bestPtr; + PatSeq *bestPhysPtr; + ModMask bestModMask; + const PSModMaskArr *bestModMaskArr = NULL; + + assert(dispPtr); + assert(bindPtr); + assert(curEvent); + + if (!psList) { + return NULL; + } + + bestModMask = 0; + bestPtr = NULL; + bestPhysPtr = NULL; + window = curEvent->xev.xany.window; + + for (psEntry = PSList_First(psList); psEntry; psEntry = PSList_Next(psEntry)) { + if (patIndex == 0 || psEntry->window == window) { + PatSeq* psPtr = psEntry->psPtr; + + assert(TEST_PSENTRY(psPtr)); + assert((psPtr->object == NULL) == (physPtrPtr != NULL)); + assert(psPtr->object || patIndex == 0); + assert(psPtr->numPats > patIndex); + + if (psPtr->object + ? psPtr->object == object + : VirtPatIsBound(bindPtr, psPtr, object, physPtrPtr)) { + TkPattern *patPtr = psPtr->pats + patIndex; + + if (patPtr->eventType == (unsigned) curEvent->xev.type + && (curEvent->xev.type != CreateNotify + || curEvent->xev.xcreatewindow.parent == window) + && (!patPtr->name || patPtr->name == curEvent->detail.name) + && (!patPtr->info || patPtr->info == curEvent->detail.info)) { + /* + * Resolve the modifier mask for Alt and Mod keys. Unfortunately this + * cannot be done in ParseEventDescription, otherwise this function would + * be the better place. + */ + ModMask modMask = ResolveModifiers(dispPtr, patPtr->modMask); + ModMask curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask); + + psEntry->expired = 1; /* remove it from promotion list */ + + if ((modMask & ~curModMask) == 0) { + unsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny; + + if (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) { + PSModMaskArr_Set(psEntry->lastModMaskArr, patIndex, &modMask); + } + /* - * Ignore key events if they are modifier keys. + * This pattern is finally matching. */ - for (i = 0; i < dispPtr->numModKeyCodes; i++) { - if (dispPtr->modKeyCodes[i] - == eventPtr->xkey.keycode) { + if (psPtr->numPats == patIndex + 1) { + if (patPtr->count <= count) { /* - * This key is a modifier key, so ignore it. + * This is also a final pattern. + * We always prefer the pattern with better match. + * If completely equal than prefer most recently defined pattern. */ - goto nextEvent; + int cmp = Compare(bestPtr, psPtr); + + if (cmp == 0) { + cmp = CompareModMasks(psEntry->lastModMaskArr, bestModMaskArr, + modMask, bestModMask); + } + + if (cmp > 0 || (cmp == 0 && bestPtr->number < psPtr->number)) { + bestPtr = psPtr; + bestModMask = modMask; + bestModMaskArr = psEntry->lastModMaskArr; + if (physPtrPtr) { + bestPhysPtr = *physPtrPtr; + } + } + } else { + DEBUG(psEntry->expired = 0;) + psEntry->keepIt = 1; /* don't remove it from promotion list */ } - } - goto nextSequence; - } - } - goto nextEvent; - } - if (eventPtr->xany.type == CreateNotify - && eventPtr->xcreatewindow.parent != window) { - goto nextSequence; - } else if (eventPtr->xany.window != window) { - goto nextSequence; - } - - /* - * Note: it's important for the keysym check to go before the - * modifier check, so we can ignore unwanted modifier keys before - * choking on the modifier check. - */ - - if ((patPtr->detail.clientData != 0) - && (patPtr->detail.clientData != detailPtr->clientData)) { - /* - * The detail appears not to match. However, if the event is a - * KeyPress for a modifier key then just ignore the event. - * Otherwise event sequences like "aD" never match because the - * shift key goes down between the "a" and the "D". - */ - - if (eventPtr->xany.type == KeyPress) { - for (i = 0; i < dispPtr->numModKeyCodes; i++) { - if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) { - goto nextEvent; + } else if (psSuccList) { + /* + * Not a final pattern, but matching, so promote it to next level. + * But do not promote if count of current pattern is not yet reached. + */ + if (patPtr->count == psEntry->count) { + PSEntry *psNewEntry; + + assert(!patPtr->name); + psNewEntry = MakeListEntry( + &bindPtr->lookupTables.entryPool, psPtr, psPtr->modMaskUsed); + if (!PSModMaskArr_IsEmpty(psNewEntry->lastModMaskArr)) { + PSModMaskArr_Set(psNewEntry->lastModMaskArr, patIndex, &modMask); + } + assert(psNewEntry->keepIt); + assert(psNewEntry->count == 1u); + PSList_Append(psSuccList, psNewEntry); + psNewEntry->window = window; /* bind to current window */ + } else { + assert(psEntry->count < patPtr->count); + DEBUG(psEntry->expired = 0;) + psEntry->count += 1; + psEntry->keepIt = 1; /* don't remove it from promotion list */ + } } } } - goto nextSequence; - } - flags = flagArray[eventPtr->type]; - if (flags & KEY_BUTTON_MOTION_VIRTUAL) { - state = eventPtr->xkey.state; - } else if (flags & CROSSING) { - state = eventPtr->xcrossing.state; - } else { - state = 0; - } - if (patPtr->needMods != 0) { - modMask = patPtr->needMods; - if ((modMask & META_MASK) && (dispPtr->metaModMask != 0)) { - modMask = (modMask & ~META_MASK) | dispPtr->metaModMask; - } - if ((modMask & ALT_MASK) && (dispPtr->altModMask != 0)) { - modMask = (modMask & ~ALT_MASK) | dispPtr->altModMask; - } - - if ((state & META_MASK) && (dispPtr->metaModMask != 0)) { - state = (state & ~META_MASK) | dispPtr->metaModMask; - } - if ((state & ALT_MASK) && (dispPtr->altModMask != 0)) { - state = (state & ~ALT_MASK) | dispPtr->altModMask; - } - - if ((state & modMask) != modMask) { - goto nextSequence; - } - } - if (psPtr->flags & PAT_NEARBY) { - XEvent *firstPtr = &bindPtr->eventRing[bindPtr->curEvent]; - long timeDiff; - - timeDiff = ((long)firstPtr->xkey.time - - (long)eventPtr->xkey.time); - if ((firstPtr->xkey.x_root - < (eventPtr->xkey.x_root - NEARBY_PIXELS)) - || (firstPtr->xkey.x_root - > (eventPtr->xkey.x_root + NEARBY_PIXELS)) - || (firstPtr->xkey.y_root - < (eventPtr->xkey.y_root - NEARBY_PIXELS)) - || (firstPtr->xkey.y_root - > (eventPtr->xkey.y_root + NEARBY_PIXELS)) - || (timeDiff > NEARBY_MS)) { - goto nextSequence; - } - } - patPtr++; - patCount--; - nextEvent: - if (eventPtr == bindPtr->eventRing) { - eventPtr = &bindPtr->eventRing[EVENT_BUFFER_SIZE-1]; - detailPtr = &bindPtr->detailRing[EVENT_BUFFER_SIZE-1]; - } else { - eventPtr--; - detailPtr--; - } - ringCount--; - } - - matchPtr = psPtr; - sourcePtr = psPtr; - - if (objectPtr != NULL) { - int iVirt; - VirtualOwners *voPtr; - PatternTableKey key; - - /* - * The sequence matches the physical constraints. Is this object - * interested in any of the virtual events that correspond to this - * sequence? - */ - - voPtr = psPtr->voPtr; - - memset(&key, 0, sizeof(key)); - key.object = *objectPtr; - key.type = VirtualEvent; - key.detail.clientData = 0; - - for (iVirt = 0; iVirt < voPtr->numOwners; iVirt++) { - Tcl_HashEntry *hPtr = voPtr->owners[iVirt]; - - key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr, - hPtr); - hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, - (char *) &key); - if (hPtr != NULL) { - /* - * This tag is interested in this virtual event and its - * corresponding physical event is a good match with the - * virtual event's definition. - */ - - PatSeq *virtMatchPtr = Tcl_GetHashValue(hPtr); - - if ((virtMatchPtr->numPats != 1) - || (virtMatchPtr->nextSeqPtr != NULL)) { - Tcl_Panic("MatchPattern: badly constructed virtual event"); - } - sourcePtr = virtMatchPtr; - goto match; - } - } - - /* - * The physical event matches a virtual event's definition, but - * the tag isn't interested in it. - */ - - goto nextSequence; - } - match: - - /* - * This sequence matches. If we've already got another match, pick - * whichever is most specific. Detail is most important, then - * needMods. - */ - - if (bestPtr != NULL) { - TkPattern *patPtr2; - - if (matchPtr->numPats != bestPtr->numPats) { - if (bestPtr->numPats > matchPtr->numPats) { - goto nextSequence; - } else { - goto newBest; - } - } - for (i = 0, patPtr = matchPtr->pats, patPtr2 = bestPtr->pats; - i < matchPtr->numPats; i++, patPtr++, patPtr2++) { - if (patPtr->detail.clientData != patPtr2->detail.clientData) { - if (patPtr->detail.clientData == 0) { - goto nextSequence; - } else { - goto newBest; - } - } - if (patPtr->needMods != patPtr2->needMods) { - if ((patPtr->needMods & patPtr2->needMods) - == patPtr->needMods) { - goto nextSequence; - } else if ((patPtr->needMods & patPtr2->needMods) - == patPtr2->needMods) { - goto newBest; - } - } - } - - /* - * Tie goes to current best pattern. - * - * (1) For virtual vs. virtual, the least recently defined virtual - * wins, because virtuals are examined in order of definition. - * This order is _not_ guaranteed in the documentation. - * - * (2) For virtual vs. physical, the physical wins because all the - * physicals are examined before the virtuals. This order is - * guaranteed in the documentation. - * - * (3) For physical vs. physical pattern, the most recently - * defined physical wins, because physicals are examined in - * reverse order of definition. This order is guaranteed in the - * documentation. - */ - - goto nextSequence; - } - newBest: - bestPtr = matchPtr; - bestSourcePtr = sourcePtr; - - nextSequence: - continue; - } - - *sourcePtrPtr = bestSourcePtr; + } + } + } + + if (bestPhysPtr) { + assert(physPtrPtr); + *physPtrPtr = bestPhysPtr; + } return bestPtr; } @@ -1922,49 +2904,43 @@ static void ExpandPercents( - TkWindow *winPtr, /* Window where event occurred: needed to get - * input context. */ - const char *before, /* Command containing percent expressions to - * be replaced. */ - XEvent *eventPtr, /* X event containing information to be used - * in % replacements. */ - KeySym keySym, /* KeySym: only relevant for KeyPress and - * KeyRelease events). */ - unsigned int scriptCount, /* The number of script-based binding patterns - * matched so far for this event. */ - Tcl_DString *dsPtr) /* Dynamic string in which to append new - * command. */ -{ - int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl - * list element. */ - int number, flags, length; -#define NUM_SIZE 40 - const char *string; + TkWindow *winPtr, /* Window where event occurred: needed to get input context. */ + const char *before, /* Command containing percent expressions to be replaced. */ + Event *eventPtr, /* Event containing information to be used in % replacements. */ + unsigned scriptCount, /* The number of script-based binding patterns matched so far for + * this event. */ + Tcl_DString *dsPtr) /* Dynamic string in which to append new command. */ +{ + unsigned flags; Tcl_DString buf; - char numStorage[NUM_SIZE+1]; + XEvent *evPtr; + + assert(winPtr); + assert(before); + assert(eventPtr); + assert(dsPtr); Tcl_DStringInit(&buf); - - if (eventPtr->type < TK_LASTEVENT) { - flags = flagArray[eventPtr->type]; - } else { - flags = 0; - } + evPtr = &eventPtr->xev; + flags = (evPtr->type < TK_LASTEVENT) ? flagArray[evPtr->type] : 0; while (1) { + char numStorage[TCL_INTEGER_SPACE]; + const char *string; + Tcl_WideInt number; + /* * Find everything up to the next % character and append it to the * result string. */ - for (string = before; (*string != 0) && (*string != '%'); string++) { - /* Empty loop body. */ - } + for (string = before; *string && *string != '%'; ++string) + ; if (string != before) { - Tcl_DStringAppend(dsPtr, before, (int) (string-before)); + Tcl_DStringAppend(dsPtr, before, string - before); before = string; } - if (*before == 0) { + if (!*before) { break; } @@ -1972,328 +2948,277 @@ * There's a percent sequence here. Process it. */ - number = 0; + number = NO_NUMBER; string = "??"; + switch (before[1]) { case '#': - number = eventPtr->xany.serial; - goto doNumber; + number = evPtr->xany.serial; + break; case 'a': if (flags & CONFIG) { - TkpPrintWindowId(numStorage, eventPtr->xconfigure.above); + TkpPrintWindowId(numStorage, evPtr->xconfigure.above); string = numStorage; } - goto doString; + break; case 'b': if (flags & BUTTON) { - number = eventPtr->xbutton.button; - goto doNumber; - } - goto doString; + number = evPtr->xbutton.button; + } + break; case 'c': if (flags & EXPOSE) { - number = eventPtr->xexpose.count; - goto doNumber; - } - goto doString; + number = evPtr->xexpose.count; + } + break; case 'd': if (flags & (CROSSING|FOCUS)) { - if (flags & FOCUS) { - number = eventPtr->xfocus.detail; - } else { - number = eventPtr->xcrossing.detail; - } - string = TkFindStateString(notifyDetail, number); + int detail = (flags & FOCUS) ? evPtr->xfocus.detail : evPtr->xcrossing.detail; + string = TkFindStateString(notifyDetail, detail); } else if (flags & CONFIGREQ) { - if (eventPtr->xconfigurerequest.value_mask & CWStackMode) { - string = TkFindStateString(configureRequestDetail, - eventPtr->xconfigurerequest.detail); + if (evPtr->xconfigurerequest.value_mask & CWStackMode) { + string = TkFindStateString(configureRequestDetail, evPtr->xconfigurerequest.detail); } else { string = ""; } } else if (flags & VIRTUAL) { - XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr; - - if (vePtr->user_data != NULL) { - string = Tcl_GetString(vePtr->user_data); - } else { - string = ""; - } - } - goto doString; + XVirtualEvent *vePtr = (XVirtualEvent *) evPtr; + string = vePtr->user_data ? Tcl_GetString(vePtr->user_data) : ""; + } + break; case 'f': if (flags & CROSSING) { - number = eventPtr->xcrossing.focus; - goto doNumber; - } - goto doString; + number = evPtr->xcrossing.focus; + } + break; case 'h': if (flags & EXPOSE) { - number = eventPtr->xexpose.height; + number = evPtr->xexpose.height; } else if (flags & CONFIG) { - number = eventPtr->xconfigure.height; + number = evPtr->xconfigure.height; } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.height; + number = evPtr->xcreatewindow.height; } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.height; + number = evPtr->xconfigurerequest.height; } else if (flags & RESIZEREQ) { - number = eventPtr->xresizerequest.height; - } else { - goto doString; - } - goto doNumber; + number = evPtr->xresizerequest.height; + } + break; case 'i': if (flags & CREATE) { - TkpPrintWindowId(numStorage, eventPtr->xcreatewindow.window); + TkpPrintWindowId(numStorage, evPtr->xcreatewindow.window); } else if (flags & CONFIGREQ) { - TkpPrintWindowId(numStorage, - eventPtr->xconfigurerequest.window); + TkpPrintWindowId(numStorage, evPtr->xconfigurerequest.window); } else if (flags & MAPREQ) { - TkpPrintWindowId(numStorage, eventPtr->xmaprequest.window); + TkpPrintWindowId(numStorage, evPtr->xmaprequest.window); } else { - TkpPrintWindowId(numStorage, eventPtr->xany.window); + TkpPrintWindowId(numStorage, evPtr->xany.window); } string = numStorage; - goto doString; + break; case 'k': - if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) { - number = eventPtr->xkey.keycode; - goto doNumber; - } - goto doString; + if ((flags & KEY) && evPtr->type != MouseWheelEvent) { + number = evPtr->xkey.keycode; + } + break; case 'm': if (flags & CROSSING) { - number = eventPtr->xcrossing.mode; - string = TkFindStateString(notifyMode, number); + string = TkFindStateString(notifyMode, evPtr->xcrossing.mode); } else if (flags & FOCUS) { - number = eventPtr->xfocus.mode; - string = TkFindStateString(notifyMode, number); - } - goto doString; + string = TkFindStateString(notifyMode, evPtr->xfocus.mode); + } + break; case 'o': if (flags & CREATE) { - number = eventPtr->xcreatewindow.override_redirect; + number = evPtr->xcreatewindow.override_redirect; } else if (flags & MAP) { - number = eventPtr->xmap.override_redirect; + number = evPtr->xmap.override_redirect; } else if (flags & REPARENT) { - number = eventPtr->xreparent.override_redirect; + number = evPtr->xreparent.override_redirect; } else if (flags & CONFIG) { - number = eventPtr->xconfigure.override_redirect; - } else { - goto doString; - } - goto doNumber; + number = evPtr->xconfigure.override_redirect; + } + break; case 'p': if (flags & CIRC) { - string = TkFindStateString(circPlace, - eventPtr->xcirculate.place); + string = TkFindStateString(circPlace, evPtr->xcirculate.place); } else if (flags & CIRCREQ) { - string = TkFindStateString(circPlace, - eventPtr->xcirculaterequest.place); - } - goto doString; + string = TkFindStateString(circPlace, evPtr->xcirculaterequest.place); + } + break; case 's': if (flags & KEY_BUTTON_MOTION_VIRTUAL) { - number = eventPtr->xkey.state; - goto doNumber; + number = evPtr->xkey.state; } else if (flags & CROSSING) { - number = eventPtr->xcrossing.state; - goto doNumber; + number = evPtr->xcrossing.state; } else if (flags & PROP) { - string = TkFindStateString(propNotify, - eventPtr->xproperty.state); + string = TkFindStateString(propNotify, evPtr->xproperty.state); } else if (flags & VISIBILITY) { - string = TkFindStateString(visNotify, - eventPtr->xvisibility.state); - } - goto doString; + string = TkFindStateString(visNotify, evPtr->xvisibility.state); + } + break; case 't': if (flags & KEY_BUTTON_MOTION_VIRTUAL) { - number = (int) eventPtr->xkey.time; + number = (int) evPtr->xkey.time; } else if (flags & CROSSING) { - number = (int) eventPtr->xcrossing.time; + number = (int) evPtr->xcrossing.time; } else if (flags & PROP) { - number = (int) eventPtr->xproperty.time; - } else { - goto doString; - } - goto doNumber; + number = (int) evPtr->xproperty.time; + } + break; case 'v': - number = eventPtr->xconfigurerequest.value_mask; - goto doNumber; + number = evPtr->xconfigurerequest.value_mask; + break; case 'w': if (flags & EXPOSE) { - number = eventPtr->xexpose.width; + number = evPtr->xexpose.width; } else if (flags & CONFIG) { - number = eventPtr->xconfigure.width; + number = evPtr->xconfigure.width; } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.width; + number = evPtr->xcreatewindow.width; } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.width; + number = evPtr->xconfigurerequest.width; } else if (flags & RESIZEREQ) { - number = eventPtr->xresizerequest.width; - } else { - goto doString; - } - goto doNumber; + number = evPtr->xresizerequest.width; + } + break; case 'x': if (flags & KEY_BUTTON_MOTION_VIRTUAL) { - number = eventPtr->xkey.x; + number = evPtr->xkey.x; } else if (flags & CROSSING) { - number = eventPtr->xcrossing.x; + number = evPtr->xcrossing.x; } else if (flags & EXPOSE) { - number = eventPtr->xexpose.x; + number = evPtr->xexpose.x; } else if (flags & (CREATE|CONFIG|GRAVITY)) { - number = eventPtr->xcreatewindow.x; + number = evPtr->xcreatewindow.x; } else if (flags & REPARENT) { - number = eventPtr->xreparent.x; + number = evPtr->xreparent.x; } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.x; + number = evPtr->xcreatewindow.x; } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.x; - } else { - goto doString; - } - goto doNumber; + number = evPtr->xconfigurerequest.x; + } + break; case 'y': if (flags & KEY_BUTTON_MOTION_VIRTUAL) { - number = eventPtr->xkey.y; + number = evPtr->xkey.y; } else if (flags & EXPOSE) { - number = eventPtr->xexpose.y; + number = evPtr->xexpose.y; } else if (flags & (CREATE|CONFIG|GRAVITY)) { - number = eventPtr->xcreatewindow.y; + number = evPtr->xcreatewindow.y; } else if (flags & REPARENT) { - number = eventPtr->xreparent.y; + number = evPtr->xreparent.y; } else if (flags & CROSSING) { - number = eventPtr->xcrossing.y; + number = evPtr->xcrossing.y; } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.y; + number = evPtr->xcreatewindow.y; } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.y; - } else { - goto doString; - } - goto doNumber; + number = evPtr->xconfigurerequest.y; + } + break; case 'A': - if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) { + if ((flags & KEY) && evPtr->type != MouseWheelEvent) { Tcl_DStringFree(&buf); - string = TkpGetString(winPtr, eventPtr, &buf); - } - goto doString; + string = TkpGetString(winPtr, evPtr, &buf); + } + break; case 'B': if (flags & CREATE) { - number = eventPtr->xcreatewindow.border_width; + number = evPtr->xcreatewindow.border_width; } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.border_width; + number = evPtr->xconfigurerequest.border_width; } else if (flags & CONFIG) { - number = eventPtr->xconfigure.border_width; - } else { - goto doString; - } - goto doNumber; + number = evPtr->xconfigure.border_width; + } + break; case 'D': /* * This is used only by the MouseWheel event. */ - - if ((flags & KEY) && (eventPtr->type == MouseWheelEvent)) { - number = eventPtr->xkey.keycode; - goto doNumber; - } - goto doString; + if ((flags & KEY) && evPtr->type == MouseWheelEvent) { + number = evPtr->xkey.keycode; + } + break; case 'E': - number = (int) eventPtr->xany.send_event; - goto doNumber; + number = (int) evPtr->xany.send_event; + break; case 'K': - if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) { - const char *name = TkKeysymToString(keySym); - - if (name != NULL) { + if ((flags & KEY) && evPtr->type != MouseWheelEvent) { + const char *name = TkKeysymToString(eventPtr->detail.info); + if (name) { string = name; } } - goto doString; + break; case 'M': number = scriptCount; - goto doNumber; + break; case 'N': - if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) { - number = (int) keySym; - goto doNumber; - } - goto doString; + if ((flags & KEY) && evPtr->type != MouseWheelEvent) { + number = (int) eventPtr->detail.info; + } + break; case 'P': if (flags & PROP) { - string = Tk_GetAtomName((Tk_Window) winPtr, - eventPtr->xproperty.atom); - } - goto doString; + string = Tk_GetAtomName((Tk_Window) winPtr, evPtr->xproperty.atom); + } + break; case 'R': if (flags & KEY_BUTTON_MOTION_CROSSING) { - TkpPrintWindowId(numStorage, eventPtr->xkey.root); + TkpPrintWindowId(numStorage, evPtr->xkey.root); string = numStorage; } - goto doString; + break; case 'S': if (flags & KEY_BUTTON_MOTION_CROSSING) { - TkpPrintWindowId(numStorage, eventPtr->xkey.subwindow); + TkpPrintWindowId(numStorage, evPtr->xkey.subwindow); string = numStorage; } - goto doString; + break; case 'T': - number = eventPtr->type; - goto doNumber; + number = evPtr->type; + break; case 'W': { - Tk_Window tkwin; - - tkwin = Tk_IdToWindow(eventPtr->xany.display, - eventPtr->xany.window); - if (tkwin != NULL) { + Tk_Window tkwin = Tk_IdToWindow(evPtr->xany.display, evPtr->xany.window); + if (tkwin) { string = Tk_PathName(tkwin); - } else { - string = "??"; - } - goto doString; + } + break; } case 'X': if (flags & KEY_BUTTON_MOTION_CROSSING) { - - number = eventPtr->xkey.x_root; - Tk_IdToWindow(eventPtr->xany.display, - eventPtr->xany.window); - goto doNumber; - } - goto doString; + number = evPtr->xkey.x_root; + } + break; case 'Y': if (flags & KEY_BUTTON_MOTION_CROSSING) { - - number = eventPtr->xkey.y_root; - Tk_IdToWindow(eventPtr->xany.display, - eventPtr->xany.window); - goto doNumber; - } - goto doString; + number = evPtr->xkey.y_root; + } + break; default: numStorage[0] = before[1]; numStorage[1] = '\0'; string = numStorage; - goto doString; - } - - doNumber: - sprintf(numStorage, "%d", number); - string = numStorage; - - doString: - spaceNeeded = Tcl_ScanElement(string, &cvtFlags); - length = Tcl_DStringLength(dsPtr); - Tcl_DStringSetLength(dsPtr, length + spaceNeeded); - spaceNeeded = Tcl_ConvertElement(string, - Tcl_DStringValue(dsPtr) + length, - cvtFlags | TCL_DONT_USE_BRACES); - Tcl_DStringSetLength(dsPtr, length + spaceNeeded); - before += 2; - } + break; + } + + if (number != NO_NUMBER) { + snprintf(numStorage, sizeof(numStorage), "%d", (int) number); + string = numStorage; + } + { /* local scope */ + int cvtFlags; + unsigned spaceNeeded = Tcl_ScanElement(string, &cvtFlags); + unsigned length = Tcl_DStringLength(dsPtr); + + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + spaceNeeded = Tcl_ConvertElement( + string, Tcl_DStringValue(dsPtr) + length, cvtFlags | TCL_DONT_USE_BRACES); + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + before += 2; + } + } + Tcl_DStringFree(&buf); } @@ -2324,15 +3249,13 @@ char *dispName, /* Name of new display. */ int screenIndex) /* Index of new screen. */ { - Tcl_Obj *cmdObj = Tcl_ObjPrintf("::tk::ScreenChanged %s.%d", - dispName, screenIndex); + Tcl_Obj *cmdObj = Tcl_ObjPrintf("::tk::ScreenChanged %s.%d", dispName, screenIndex); int code; Tcl_IncrRefCount(cmdObj); code = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL); if (code != TCL_OK) { - Tcl_AddErrorInfo(interp, - "\n (changing screen in event binding)"); + Tcl_AddErrorInfo(interp, "\n (changing screen in event binding)"); Tcl_BackgroundException(interp, code); } Tcl_DecrRefCount(cmdObj); @@ -2365,38 +3288,48 @@ int index, i; char *name; const char *event; - Tk_Window tkwin = clientData; - TkBindInfo bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo; - VirtualEventTable *vetPtr = &bindInfo->virtualEventTable; - static const char *const optionStrings[] = { - "add", "delete", "generate", "info", - NULL - }; - enum options { - EVENT_ADD, EVENT_DELETE, EVENT_GENERATE, EVENT_INFO - }; - + Tk_Window tkwin; + TkBindInfo bindInfo; + VirtualEventTable *vetPtr; + + static const char *const optionStrings[] = { "add", "delete", "generate", "info", NULL }; + enum options { EVENT_ADD, EVENT_DELETE, EVENT_GENERATE, EVENT_INFO }; + + assert(clientData); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, - sizeof(char *), "option", 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct( + interp, objv[1], optionStrings, sizeof(char *), "option", 0, &index) != TCL_OK) { +#ifdef SUPPORT_DEBUGGING + if (strcmp(Tcl_GetString(objv[1]), "debug") == 0) { + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "debug number"); + return TCL_ERROR; + } + Tcl_GetIntFromObj(interp, objv[2], &BindCount); + return TCL_OK; + } +#endif return TCL_ERROR; } + + tkwin = (Tk_Window) clientData; + bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo; + vetPtr = &bindInfo->virtualEventTable; switch ((enum options) index) { case EVENT_ADD: if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "virtual sequence ?sequence ...?"); + Tcl_WrongNumArgs(interp, 2, objv, "virtual sequence ?sequence ...?"); return TCL_ERROR; } name = Tcl_GetString(objv[2]); - for (i = 3; i < objc; i++) { + for (i = 3; i < objc; ++i) { event = Tcl_GetString(objv[i]); - if (CreateVirtualEvent(interp, vetPtr, name, event) != TCL_OK) { + if (!CreateVirtualEvent(interp, vetPtr, name, event)) { return TCL_ERROR; } } @@ -2410,7 +3343,7 @@ if (objc == 3) { return DeleteVirtualEvent(interp, vetPtr, name, NULL); } - for (i = 3; i < objc; i++) { + for (i = 3; i < objc; ++i) { event = Tcl_GetString(objv[i]); if (DeleteVirtualEvent(interp, vetPtr, name, event) != TCL_OK) { return TCL_ERROR; @@ -2419,8 +3352,7 @@ break; case EVENT_GENERATE: if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "window event ?-option value ...?"); + Tcl_WrongNumArgs(interp, 2, objv, "window event ?-option value ...?"); return TCL_ERROR; } return HandleEventGenerate(interp, tkwin, objc - 2, objv + 2); @@ -2428,12 +3360,12 @@ if (objc == 2) { GetAllVirtualEvents(interp, vetPtr); return TCL_OK; - } else if (objc == 3) { + } + if (objc == 3) { return GetVirtualEvent(interp, vetPtr, objv[2]); - } else { - Tcl_WrongNumArgs(interp, 2, objv, "?virtual?"); - return TCL_ERROR; - } + } + Tcl_WrongNumArgs(interp, 2, objv, "?virtual?"); + return TCL_ERROR; } return TCL_OK; } @@ -2457,12 +3389,14 @@ static void InitVirtualEventTable( - VirtualEventTable *vetPtr) /* Pointer to virtual event table. Memory is - * supplied by the caller. */ -{ - Tcl_InitHashTable(&vetPtr->patternTable, - sizeof(PatternTableKey) / sizeof(int)); + VirtualEventTable *vetPtr) /* Pointer to virtual event table. Memory is supplied by the caller. */ +{ + assert(vetPtr); + memset(vetPtr, 0, sizeof(*vetPtr)); + Tcl_InitHashTable(&vetPtr->lookupTables.patternTable, sizeof(PatternTableKey)/sizeof(int)); + Tcl_InitHashTable(&vetPtr->lookupTables.listTable, sizeof(PatternTableKey)/sizeof(int)); Tcl_InitHashTable(&vetPtr->nameTable, TCL_ONE_WORD_KEYS); + PSList_Init(&vetPtr->lookupTables.entryPool); } /* @@ -2488,24 +3422,33 @@ { Tcl_HashEntry *hPtr; Tcl_HashSearch search; - PatSeq *psPtr, *nextPtr; - - hPtr = Tcl_FirstHashEntry(&vetPtr->patternTable, &search); - for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - psPtr = Tcl_GetHashValue(hPtr); - for ( ; psPtr != NULL; psPtr = nextPtr) { + + assert(vetPtr); + + hPtr = Tcl_FirstHashEntry(&vetPtr->lookupTables.patternTable, &search); + for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) { + PatSeq *nextPtr; + PatSeq *psPtr; + + for (psPtr = Tcl_GetHashValue(hPtr); psPtr; psPtr = nextPtr) { + assert(TEST_PSENTRY(psPtr)); nextPtr = psPtr->nextSeqPtr; - ckfree(psPtr->voPtr); - ckfree(psPtr); - } - } - Tcl_DeleteHashTable(&vetPtr->patternTable); + DEBUG(psPtr->owned = 0;) + FreePatSeq(psPtr); + } + } + Tcl_DeleteHashTable(&vetPtr->lookupTables.patternTable); hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search); - for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) { ckfree(Tcl_GetHashValue(hPtr)); } Tcl_DeleteHashTable(&vetPtr->nameTable); + Tcl_DeleteHashTable(&vetPtr->lookupTables.listTable); + + ClearLookupTable(&vetPtr->lookupTables, NULL); + DEBUG(countEntryItems -= PSList_Size(&vetPtr->lookupTables.entryPool);) + PSList_Traverse(&vetPtr->lookupTables.entryPool, FreePatSeqEntry); } /* @@ -2533,31 +3476,30 @@ Tcl_Interp *interp, /* Used for error reporting. */ VirtualEventTable *vetPtr, /* Table in which to augment virtual event. */ char *virtString, /* Name of new virtual event. */ - const char *eventString) /* String describing physical event that - * triggers virtual event. */ + const char *eventString) /* String describing physical event that triggers virtual event. */ { PatSeq *psPtr; int dummy; Tcl_HashEntry *vhPtr; - unsigned long eventMask; - PhysicalsOwned *poPtr; - VirtualOwners *voPtr; + PhysOwned *owned; Tk_Uid virtUid; - virtUid = GetVirtualEventUid(interp, virtString); - if (virtUid == NULL) { - return TCL_ERROR; + assert(vetPtr); + assert(virtString); + assert(eventString); + + if (!(virtUid = GetVirtualEventUid(interp, virtString))) { + return 0; } /* * Find/create physical event */ - psPtr = FindSequence(interp, &vetPtr->patternTable, NULL, eventString, - 1, 0, &eventMask); - if (psPtr == NULL) { - return TCL_ERROR; - } + if (!(psPtr = FindSequence(interp, &vetPtr->lookupTables, NULL, eventString, 1, 0, NULL))) { + return 0; + } + assert(TEST_PSENTRY(psPtr)); /* * Find/create virtual event. @@ -2569,47 +3511,18 @@ * Make virtual event own the physical event. */ - poPtr = Tcl_GetHashValue(vhPtr); - if (poPtr == NULL) { - poPtr = ckalloc(sizeof(PhysicalsOwned)); - poPtr->numOwned = 0; - } else { - /* - * See if this virtual event is already defined for this physical - * event and just return if it is. - */ - - int i; - - for (i = 0; i < poPtr->numOwned; i++) { - if (poPtr->patSeqs[i] == psPtr) { - return TCL_OK; - } - } - poPtr = ckrealloc(poPtr, sizeof(PhysicalsOwned) - + poPtr->numOwned * sizeof(PatSeq *)); - } - Tcl_SetHashValue(vhPtr, poPtr); - poPtr->patSeqs[poPtr->numOwned] = psPtr; - poPtr->numOwned++; - - /* - * Make physical event so it can trigger the virtual event. - */ - - voPtr = psPtr->voPtr; - if (voPtr == NULL) { - voPtr = ckalloc(sizeof(VirtualOwners)); - voPtr->numOwners = 0; - } else { - voPtr = ckrealloc(voPtr, sizeof(VirtualOwners) - + voPtr->numOwners * sizeof(Tcl_HashEntry *)); - } - psPtr->voPtr = voPtr; - voPtr->owners[voPtr->numOwners] = vhPtr; - voPtr->numOwners++; - - return TCL_OK; + owned = Tcl_GetHashValue(vhPtr); + + if (!PhysOwned_Contains(owned, psPtr)) { + PhysOwned_Append(&owned, psPtr); + Tcl_SetHashValue(vhPtr, owned); + DEBUG(psPtr->owned = 1;) + InsertPatSeq(&vetPtr->lookupTables, psPtr); + /* Make physical event so it can trigger the virtual event. */ + VirtOwners_Append(&psPtr->ptr.owners, vhPtr); + } + + return 1; } /* @@ -2639,32 +3552,32 @@ DeleteVirtualEvent( Tcl_Interp *interp, /* Used for error reporting. */ VirtualEventTable *vetPtr, /* Table in which to delete event. */ - char *virtString, /* String describing event sequence that - * triggers binding. */ - const char *eventString) /* The event sequence that should be deleted, - * or NULL to delete all event sequences for - * the entire virtual event. */ + char *virtString, /* String describing event sequence that triggers binding. */ + const char *eventString) /* The event sequence that should be deleted, or NULL to delete + * all event sequences for the entire virtual event. */ { int iPhys; Tk_Uid virtUid; Tcl_HashEntry *vhPtr; - PhysicalsOwned *poPtr; - PatSeq *eventPSPtr; - - virtUid = GetVirtualEventUid(interp, virtString); - if (virtUid == NULL) { + PhysOwned *owned; + const PatSeq *eventPSPtr; + PatSeq *lastElemPtr; + + assert(vetPtr); + assert(virtString); + + if (!(virtUid = GetVirtualEventUid(interp, virtString))) { return TCL_ERROR; } - vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid); - if (vhPtr == NULL) { + if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) { return TCL_OK; } - poPtr = Tcl_GetHashValue(vhPtr); + owned = Tcl_GetHashValue(vhPtr); eventPSPtr = NULL; - if (eventString != NULL) { - unsigned long eventMask; + if (eventString) { + LookupTables *lookupTables = &vetPtr->lookupTables; /* * Delete only the specific physical event associated with the virtual @@ -2672,102 +3585,75 @@ * event doesn't own that physical event, return w/o doing anything. */ - eventPSPtr = FindSequence(interp, &vetPtr->patternTable, NULL, - eventString, 0, 0, &eventMask); - if (eventPSPtr == NULL) { + eventPSPtr = FindSequence(interp, lookupTables, NULL, eventString, 0, 0, NULL); + if (!eventPSPtr) { const char *string = Tcl_GetString(Tcl_GetObjResult(interp)); - - return (string[0] != '\0') ? TCL_ERROR : TCL_OK; - } - } - - for (iPhys = poPtr->numOwned; --iPhys >= 0; ) { - PatSeq *psPtr = poPtr->patSeqs[iPhys]; - - if ((eventPSPtr == NULL) || (psPtr == eventPSPtr)) { - int iVirt; - VirtualOwners *voPtr; + return string[0] ? TCL_ERROR : TCL_OK; + } + } + + for (iPhys = PhysOwned_Size(owned); --iPhys >= 0; ) { + PatSeq *psPtr = PhysOwned_Get(owned, iPhys); + + assert(TEST_PSENTRY(psPtr)); + + if (!eventPSPtr || psPtr == eventPSPtr) { + VirtOwners *owners = psPtr->ptr.owners; + int iVirt = VirtOwners_Find(owners, vhPtr); + + assert(iVirt != -1); /* otherwise we couldn't find owner, and this should not happen */ /* * Remove association between this physical event and the given * virtual event that it triggers. */ - voPtr = psPtr->voPtr; - for (iVirt = 0; iVirt < voPtr->numOwners; iVirt++) { - if (voPtr->owners[iVirt] == vhPtr) { - break; - } - } - if (iVirt == voPtr->numOwners) { - Tcl_Panic("DeleteVirtualEvent: couldn't find owner"); - } - voPtr->numOwners--; - if (voPtr->numOwners == 0) { - /* - * Removed last reference to this physical event, so remove it - * from physical->virtual map. - */ - - PatSeq *prevPtr = Tcl_GetHashValue(psPtr->hPtr); - - if (prevPtr == psPtr) { - if (psPtr->nextSeqPtr == NULL) { - Tcl_DeleteHashEntry(psPtr->hPtr); - } else { - Tcl_SetHashValue(psPtr->hPtr, - psPtr->nextSeqPtr); - } - } else { - for ( ; ; prevPtr = prevPtr->nextSeqPtr) { - if (prevPtr == NULL) { - Tcl_Panic("DeleteVirtualEvent couldn't find on hash chain"); - } - if (prevPtr->nextSeqPtr == psPtr) { - prevPtr->nextSeqPtr = psPtr->nextSeqPtr; - break; - } - } - } - ckfree(psPtr->voPtr); - ckfree(psPtr); - } else { + if (VirtOwners_Size(owners) > 1) { /* * This physical event still triggers some other virtual * event(s). Consolidate the list of virtual owners for this * physical event so it no longer triggers the given virtual * event. */ - - voPtr->owners[iVirt] = voPtr->owners[voPtr->numOwners]; + VirtOwners_Set(owners, iVirt, VirtOwners_Back(owners)); + VirtOwners_PopBack(owners); + } else { + /* + * Removed last reference to this physical event, so remove it + * from lookup table. + */ + DEBUG(psPtr->owned = 0;) + RemovePatSeqFromLookup(&vetPtr->lookupTables, psPtr); + DeletePatSeq(psPtr); } /* * Now delete the virtual event's reference to the physical event. */ - poPtr->numOwned--; - if (eventPSPtr != NULL && poPtr->numOwned != 0) { + lastElemPtr = PhysOwned_Back(owned); + + if (PhysOwned_PopBack(owned) > 0 && eventPSPtr) { /* * Just deleting this one physical event. Consolidate list of * owned physical events and return. */ - - poPtr->patSeqs[iPhys] = poPtr->patSeqs[poPtr->numOwned]; + if ((size_t) iPhys < PhysOwned_Size(owned)) { + PhysOwned_Set(owned, iPhys, lastElemPtr); + } return TCL_OK; } } } - if (poPtr->numOwned == 0) { + if (PhysOwned_IsEmpty(owned)) { /* * All the physical events for this virtual event were deleted, either * because there was only one associated physical event or because the * caller was deleting the entire virtual event. Now the virtual event * itself should be deleted. */ - - ckfree(poPtr); + PhysOwned_Free(&owned); Tcl_DeleteHashEntry(vhPtr); } return TCL_OK; @@ -2802,26 +3688,26 @@ Tcl_Obj *virtName) /* String describing virtual event. */ { Tcl_HashEntry *vhPtr; - int iPhys; - PhysicalsOwned *poPtr; + unsigned iPhys; + const PhysOwned *owned; Tk_Uid virtUid; Tcl_Obj *resultObj; - virtUid = GetVirtualEventUid(interp, Tcl_GetString(virtName)); - if (virtUid == NULL) { + assert(vetPtr); + assert(virtName); + + if (!(virtUid = GetVirtualEventUid(interp, Tcl_GetString(virtName)))) { return TCL_ERROR; } - vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid); - if (vhPtr == NULL) { + if (!(vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid))) { return TCL_OK; } resultObj = Tcl_NewObj(); - poPtr = Tcl_GetHashValue(vhPtr); - for (iPhys = 0; iPhys < poPtr->numOwned; iPhys++) { - Tcl_ListObjAppendElement(NULL, resultObj, - GetPatternObj(poPtr->patSeqs[iPhys])); + owned = Tcl_GetHashValue(vhPtr); + for (iPhys = 0; iPhys < PhysOwned_Size(owned); ++iPhys) { + Tcl_ListObjAppendElement(NULL, resultObj, GetPatternObj(PhysOwned_Get(owned, iPhys))); } Tcl_SetObjResult(interp, resultObj); @@ -2855,11 +3741,13 @@ Tcl_HashSearch search; Tcl_Obj *resultObj; + assert(vetPtr); + resultObj = Tcl_NewObj(); hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search); - for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf( - "<<%s>>", (char *) Tcl_GetHashKey(hPtr->tablePtr, hPtr))); + for ( ; hPtr; hPtr = Tcl_NextHashEntry(&search)) { + Tcl_Obj* msg = Tcl_ObjPrintf("<<%s>>", (char *) Tcl_GetHashKey(hPtr->tablePtr, hPtr)); + Tcl_ListObjAppendElement(NULL, resultObj, msg); } Tcl_SetObjResult(interp, resultObj); } @@ -2906,16 +3794,24 @@ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - union {XEvent general; XVirtualEvent virtual;} event; + union { XEvent general; XVirtualEvent virtual; } event; + const char *p; - const char *name, *windowName; - int count, flags, synch, i, number, warp; + const char *name; + const char *windowName; Tcl_QueuePosition pos; TkPattern pat; - Tk_Window tkwin, tkwin2; + Tk_Window tkwin; + Tk_Window tkwin2; TkWindow *mainPtr; - unsigned long eventMask; + EventMask eventMask; Tcl_Obj *userDataObj; + int synch; + int warp; + unsigned count; + unsigned flags; + int number; + unsigned i; static const char *const fieldStrings[] = { "-when", "-above", "-borderwidth", "-button", @@ -2925,7 +3821,7 @@ "-place", "-root", "-rootx", "-rooty", "-sendevent", "-serial", "-state", "-subwindow", "-time", "-warp", "-width", "-window", - "-x", "-y", NULL + "-x", "-y", NULL }; enum field { EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON, @@ -2938,42 +3834,39 @@ EVENT_X, EVENT_Y }; + assert(mainWin); + windowName = Tcl_GetString(objv[0]); if (!windowName[0]) { tkwin = mainWin; - } else if (NameToWindow(interp, mainWin, objv[0], &tkwin) != TCL_OK) { + } else if (!NameToWindow(interp, mainWin, objv[0], &tkwin)) { return TCL_ERROR; } mainPtr = (TkWindow *) mainWin; - if ((tkwin == NULL) - || (mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) { + if (!tkwin || mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "window id \"%s\" doesn't exist in this application", Tcl_GetString(objv[0]))); - Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW", - Tcl_GetString(objv[0]), NULL); + Tcl_SetErrorCode(interp, "TK", "LOOKUP", "WINDOW", Tcl_GetString(objv[0]), NULL); return TCL_ERROR; } name = Tcl_GetString(objv[1]); - p = name; eventMask = 0; userDataObj = NULL; - count = ParseEventDescription(interp, &p, &pat, &eventMask); - if (count == 0) { + if ((count = ParseEventDescription(interp, &p, &pat, &eventMask)) == 0) { return TCL_ERROR; } - if (count != 1) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Double or Triple modifier not allowed", -1)); + if (count != 1u) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("Double, Triple, or Quadruple modifier not allowed", -1)); Tcl_SetErrorCode(interp, "TK", "EVENT", "BAD_MODIFIER", NULL); return TCL_ERROR; } - if (*p != '\0') { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "only one event specification allowed", -1)); + if (*p) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("only one event specification allowed", -1)); Tcl_SetErrorCode(interp, "TK", "EVENT", "MULTIPLE", NULL); return TCL_ERROR; } @@ -2981,12 +3874,11 @@ memset(&event, 0, sizeof(event)); event.general.xany.type = pat.eventType; event.general.xany.serial = NextRequest(Tk_Display(tkwin)); - event.general.xany.send_event = False; + event.general.xany.send_event = 0; if (windowName[0]) { event.general.xany.window = Tk_WindowId(tkwin); } else { - event.general.xany.window = - RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin)); + event.general.xany.window = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin)); } event.general.xany.display = Tk_Display(tkwin); @@ -2995,18 +3887,17 @@ /* * Event DestroyNotify should be generated by destroying the window. */ - Tk_DestroyWindow(tkwin); return TCL_OK; } if (flags & KEY_BUTTON_MOTION_VIRTUAL) { - event.general.xkey.state = pat.needMods; - if ((flags & KEY) && (event.general.xany.type != MouseWheelEvent)) { - TkpSetKeycodeAndState(tkwin, pat.detail.keySym, &event.general); + event.general.xkey.state = pat.modMask; + if ((flags & KEY) && event.general.xany.type != MouseWheelEvent) { + TkpSetKeycodeAndState(tkwin, pat.info, &event.general); } else if (flags & BUTTON) { - event.general.xbutton.button = pat.detail.button; + event.general.xbutton.button = pat.info; } else if (flags & VIRTUAL) { - event.virtual.name = pat.detail.name; + event.virtual.name = pat.name; } } if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) { @@ -3018,21 +3909,21 @@ event.general.xkey.y_root = -1; } - if (event.general.xany.type == FocusIn - || event.general.xany.type == FocusOut) { + if (event.general.xany.type == FocusIn || event.general.xany.type == FocusOut) { event.general.xany.send_event = GENERATED_FOCUS_EVENT_MAGIC; } /* - * Process the remaining arguments to fill in additional fields of the - * event. + * Process the remaining arguments to fill in additional fields of the event. */ synch = 1; warp = 0; pos = TCL_QUEUE_TAIL; - for (i = 2; i < objc; i += 2) { + + for (i = 2; i < (unsigned) objc; i += 2) { Tcl_Obj *optionPtr, *valuePtr; + int badOpt = 0; int index; optionPtr = objv[i]; @@ -3042,7 +3933,7 @@ sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } - if (objc & 1) { + if (IsOdd(objc)) { /* * This test occurs after Tcl_GetIndexFromObj() so that "event * generate