summaryrefslogtreecommitdiffstats
path: root/mac
diff options
context:
space:
mode:
Diffstat (limited to 'mac')
-rw-r--r--mac/MW_TkHeader.pch129
-rw-r--r--mac/README299
-rw-r--r--mac/bugs.doc40
-rw-r--r--mac/tclets.tcl215
-rw-r--r--mac/tkMac.h53
-rw-r--r--mac/tkMacAppInit.c374
-rw-r--r--mac/tkMacApplication.r267
-rw-r--r--mac/tkMacBitmap.c268
-rw-r--r--mac/tkMacButton.c825
-rw-r--r--mac/tkMacClipboard.c293
-rw-r--r--mac/tkMacColor.c485
-rw-r--r--mac/tkMacCursor.c360
-rw-r--r--mac/tkMacCursors.r130
-rw-r--r--mac/tkMacDefault.h461
-rw-r--r--mac/tkMacDialog.c939
-rw-r--r--mac/tkMacDraw.c1130
-rw-r--r--mac/tkMacEmbed.c1116
-rw-r--r--mac/tkMacFont.c678
-rw-r--r--mac/tkMacHLEvents.c437
-rw-r--r--mac/tkMacInit.c240
-rw-r--r--mac/tkMacInt.h282
-rw-r--r--mac/tkMacKeyboard.c384
-rw-r--r--mac/tkMacLibrary.r510
-rw-r--r--mac/tkMacMDEF.c116
-rw-r--r--mac/tkMacMDEF.r45
-rw-r--r--mac/tkMacMenu.c3994
-rw-r--r--mac/tkMacMenu.r47
-rw-r--r--mac/tkMacMenubutton.c339
-rw-r--r--mac/tkMacMenus.c346
-rw-r--r--mac/tkMacPort.h145
-rw-r--r--mac/tkMacProlog.c61
-rw-r--r--mac/tkMacRegion.c217
-rw-r--r--mac/tkMacResource.r507
-rw-r--r--mac/tkMacScale.c603
-rw-r--r--mac/tkMacScrlbr.c1057
-rw-r--r--mac/tkMacSend.c358
-rw-r--r--mac/tkMacShLib.exp766
-rw-r--r--mac/tkMacSubwindows.c1227
-rw-r--r--mac/tkMacTest.c81
-rw-r--r--mac/tkMacWindowMgr.c1591
-rw-r--r--mac/tkMacWm.c4213
-rw-r--r--mac/tkMacXCursors.r961
-rw-r--r--mac/tkMacXStubs.c709
43 files changed, 27298 insertions, 0 deletions
diff --git a/mac/MW_TkHeader.pch b/mac/MW_TkHeader.pch
new file mode 100644
index 0000000..7b7e2a4
--- /dev/null
+++ b/mac/MW_TkHeader.pch
@@ -0,0 +1,129 @@
+/*
+ * MW_TkHeader.pch --
+ *
+ * This file is the source for a pre-compilied header that gets used
+ * for all files in the Tk projects. This make compilies go a bit
+ * faster. This file is only intended to be used in the MetroWerks
+ * CodeWarrior environment. It essentially acts as a place to set
+ * compiler flags. See MetroWerks documention for more details.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) MW_TkHeader.pch 1.26 97/11/20 19:37:29
+ */
+
+/*
+ * To use the compilied header you need to set the "Prefix file" in
+ * the "C/C++ Language" preference panel to point to the created
+ * compilied header. The name of the header depends on the
+ * architecture we are compiling for (see the code below). For
+ * example, for a 68k app the prefix file should be: MW_TclHeader68K.
+ */
+
+#if __POWERPC__
+#pragma precompile_target "MW_TkHeaderPPC"
+#elif __CFM68K__
+#pragma precompile_target "MW_TkHeaderCFM68K"
+#else
+#pragma precompile_target "MW_TkHeader68K"
+#endif
+
+/*
+ * Macintosh Tcl must be compiled with certain compiler options to
+ * ensure that it will work correctly. The following pragmas are
+ * used to ensure that those options are set correctly. An error
+ * will occur at compile time if they are not set correctly.
+ */
+
+#if !__option(enumsalwaysint)
+#error Tcl requires the Metrowerks setting "Enums always ints".
+#endif
+
+#if !defined(__POWERPC__)
+#if !__option(far_data)
+#error Tcl requires the Metrowerks setting "Far data".
+#endif
+#endif
+
+#if !defined(__POWERPC__)
+#if !__option(fourbyteints)
+#error Tcl requires the Metrowerks setting "4 byte ints".
+#endif
+#endif
+
+#if !defined(__POWERPC__)
+#if !__option(IEEEdoubles)
+#error Tcl requires the Metrowerks setting "8 byte doubles".
+#endif
+#endif
+
+/*
+ * The define is used most everywhere to tell Tk (or any Tk
+ * extensions) that we are compiling for the Macintosh platform.
+ */
+#define MAC_TCL
+
+/*
+ * The following defines are for the Xlib.h file to force
+ * it to generate prototypes in the way we need it. This is
+ * defined here in case X.h & company are ever included before
+ * tk.h.
+ */
+
+#define NeedFunctionPrototypes 1
+#define NeedWidePrototypes 0
+
+/*
+ * The following defines control the behavior of the Macintosh
+ * Universial Headers.
+ */
+
+#define SystemSevenOrLater 1
+#define STRICT_CONTROLS 0
+#define STRICT_WINDOWS 0
+
+/*
+ * The appearance manager has not yet been shiped by Apple (10/29/97).
+ * It's currently in beta testing which is why we were able to write
+ * some code that depends on it. If you have access to the appearance
+ * manager you can define the symbol HAVE_APPEARANCE below to compile
+ * the code that uses the new appearance manager.
+ */
+
+/* #define HAVE_APPEARANCE 1 */
+
+/*
+ * Define the following symbol if you want
+ * comprehensive debugging turned on.
+ */
+
+/* #define TCL_DEBUG */
+
+#ifdef TCL_DEBUG
+# define TCL_MEM_DEBUG
+# define TK_TEST
+# define TCL_TEST
+#endif
+
+/*
+ * Apple's Universal Headers 2.0 & 3.0 change alot of names and constants.
+ * We will switch to the new names as soon as we can be reasonably sure the
+ * number of people with older versions of CodeWarrior, who will then not be
+ * able to build Tcl/Tk, is negligible.
+ */
+
+#define OLDROUTINENAMES 1
+
+/*
+ * Place any includes below that will are needed by the majority of the
+ * and is OK to be in any file in the system.
+ */
+
+#include <tcl.h>
+#pragma export on
+#include "tk.h"
+#include "tkInt.h"
+#pragma export off
diff --git a/mac/README b/mac/README
new file mode 100644
index 0000000..3c8824a
--- /dev/null
+++ b/mac/README
@@ -0,0 +1,299 @@
+Tk 8.0 for Macintosh
+
+by Ray Johnson
+Sun Microsystems Laboratories
+rjohnson@eng.sun.com
+
+SCCS: @(#) README 1.30 97/11/20 22:06:57
+
+1. Introduction
+---------------
+
+This is the README file for the Macintosh version of the Tk
+extension for the Tcl scripting language. The file consists of
+information specific to the Macintosh version of Tcl and Tk. For more
+general information please read the README file in the main Tk
+directory.
+
+2. What's new?
+-------------
+
+Native Look & Feel!!! We now try really hard to support the
+Macintosh Look & Feel with Tcl/Tk 8.0. We aren't finished but
+it look pretty good. Let me know what are the most "un-mac like"
+problems and I'll fix them as quickly as I can.
+
+The button, checkbutton, radiobutton, and scrollbar widgets actually
+use the Mac toolbox controls. This means that they will track the
+look&feel if you use extension that change the appearance of
+applications (like Aaron.) We also use "system" colors so the default
+backgrounds etc. will also change colors. We plan to support this
+feature - so let me know if something doesn't work quite right.
+Unfortunantly, we are not able to change the colors of buttons under
+MacOS 8. We are working on a solution to this.
+In the meantime, if you really must have colored buttons, turn off the
+"System-wide platinum appearance" option in the Appearance Control Panel,
+and you will get the System 7, colorable, buttons back.
+
+We also now support native menus! By using the new -menu option
+on toplevels you can have a menubar that is cross platform. You
+can also place Tk menus in the Apple and Help menus! Check out
+the documentation for more details. Syd Polk <icepick@eng.sun.com> is
+the author of the new menu code. Feel free to contact him if you
+have questions or comments about the menu mechanism.
+
+The "tk_messageBox" command on the Macintosh is now much more
+mac-like. I'll probably still need to adjust this more - but it
+looks a hell of alot better than it did before.
+
+I've also added a command that allows you to get more native window
+styles. However, we have yet to decide on a cross platform solution
+to the problem of varying window styles. None the less, I thought
+it would be use full to add the capability in an unsupported means
+to tide you over until a better solution is available. The command
+is called "unsupported1". It can be used in the following way:
+
+ toplevel .foo; unsupported1 style .foo zoomDocProc
+
+The above command will create a document window with a zoom box.
+Type "unsupported1 style . ???" to get a list of the supported
+styles. The command works like "wm overrideredirect" - you must
+make the call before the window is mapped.
+
+As always - report the bugs you find - including asthetic ones
+in the look & feel of widgets.
+
+3. Mac specific features
+------------------------
+
+There are several features or enhancements in Tk that are unique to
+the Macintosh version of Tk. Here is a list of those features and
+pointers to where you can find more information about the feature.
+
+* The menu command has special rules for accessing the Macintosh
+ Apple and Help menus. See the menu.m man page for details.
+
+* If you have the special Tcl function "tkAboutDialog" defined, it
+ will be called instead of displaying the default About Box in the
+ console or other parts of the Wish application. See below for
+ details.
+
+* In addition to the standard X cursors, the Mac version of Tk will
+ let you use any Mac cursor that is named and installed in your
+ application. See the GetCursor.3 man page for details.
+
+* The wish application has a couple of hooks to know about the exit,
+ "open document" and "Do Script" Mac High Level events.
+ See below for details.
+
+* The command unsupported1 will allow you to set the style of new
+ toplevel windows on the Macintosh. It is not really supported.
+ See below for details.
+
+* In addition to the standard built-in bitmaps that Tk supports, the
+ Mac version of Tk allows you to use several Mac specific icons. See
+ the GetBitmap.3 man page for a complete list.
+
+* The send command does not yet work on the Macintosh. We hope to
+ have it available in Tk 8.1.
+
+* The -use and -container options almost work. The focus bugs that
+ were in Tk8.0 final have been fixed. But there are still some
+ known bugs that cause some major problems. Be careful, if you
+ decide to use these features. (See bugs.doc for details.)
+
+4. The Distribution
+-------------------
+
+Macintosh Tk is distributed in three different forms. This
+should make it easier to only download what you need. The
+packages are as follows:
+
+mactk8.0.sea.hqx
+
+ This distribution is a "binary" only release. It contains an
+ installer program that will install a 68k, PowerPC, or Fat
+ version of the "Wish" application. In addition, in installs
+ the Tcl & Tk libraries in the Extensions folder inside your
+ System Folder. (No "INIT"'s or Control Pannels are installed.)
+
+mactcltk-full-8.0.sea.hqx
+
+ This release contains the full release of Tcl and Tk for the
+ Macintosh plus the More Files package on which Macintosh Tcl and
+ Tk rely.
+
+mactk-source-8.0.sea.hqx
+
+ This release contains the complete source to Tk for the Macintosh
+ In addition, Metrowerks CodeWarrior libraries and project files
+ are included. However, you must already have the More Files
+ package to compile this code.
+
+5. Documentation
+----------------
+
+Two books are currently available for Tcl. Both provide a good
+introduction to the language. It is a good way to get started
+if you haven't used the language before:
+
+ Title: Tcl and the Tk Toolkit
+ Author: John K. Ousterhout
+ Publisher: Addison-Wesley
+ ISBN: 0-201-63337-X
+
+ Title: Practical Programming in Tcl and Tk
+ Author: Brent Welch
+ Publisher: Prentice Hall
+ ISBN: 0-13-182007-9
+
+The "doc" subdirectory contains reference in documentation
+in the "man" format found on most UNIX machines. Unfortunately,
+there is not a suitable way to view these pages on the Macintosh.
+A version suitable for viewing on the Macintosh has yet to be
+developed. We are working are having better documentation for
+the Macintosh platform in the future. However, if you have WWW
+access you may access the Man pages at the following URL:
+
+ http://sunscript.sun.com/man/tcl8.0/contents.html
+
+Other documentation and sample Tcl scripts can be found at
+the Tcl ftp site:
+
+ ftp://ftp.neosoft.com/tcl/
+
+The internet news group comp.lang.tcl is also a valuable
+source of information about Tcl. A mailing list is also
+available (see below).
+
+6. Compiling Tk
+---------------
+
+In order to compile Macintosh Tk you must have the
+following items:
+
+ CodeWarrior Pro 1 or higher (CodeWarrior release 9 or higher can work
+ and we have project files, but we are depricating support)
+ Mac Tcl 8.0 (source)
+ (which requires More Files 1.4.2 or 1.4.3)
+ Mac Tk 8.0 (source)
+
+The project files included with the Mac Tcl source should work
+fine. The only thing you may need to update are the access paths.
+As with Tcl, there is something in the initial release of the CW Pro 2
+linker that rendersthe CFM68K version of Wish very unstable. I am
+working with Metrowerks to resolve the issue.
+
+Special notes:
+
+* Check out the file bugs.doc for information about known bugs.
+
+* We are starting to support the new Appearance Manager that shipped
+ with MacOS 8. At this point, the only feature that we are using is
+ the API to Iconify windows (so that wm iconify will work). However,
+ as of the release of Tk8.0p1, the SDK from Apple is still in Beta, so
+ we cannot ship it. So support for the Appearance Manager is turned off
+ in the source version of Tk8.0p1.
+ If you want to build Tk, and want to get the Appearance Manager features,
+ then need to do the following:
+ 1) get the SDK from Apple
+ 2) Uncomment the #define HAVE_APPEARANCE line in tk8.0:mac:MW_TkHeader.pch
+ 3) Add the Appearance.lib to tk8.0:mac:TkShells.¼, and put the include
+ directory of the SDK on your path in this project, and TkLibraries.¼.
+
+7. About Dialog
+---------------
+
+There is now a way to replace the default dialog box for the Wish
+application. If you create the tcl procedure "tkAboutDialog" it will
+be called instead of creating the default dialog box. Your procedure
+is then responsible for displaying a window, removing it, etc. This
+interface is experimental and may change in the future - tell me what
+you think of it.
+
+8. Apple Events
+---------------
+
+Tcl/Tk currently doesn't have much in the way of support for Mac
+Apple Events. There is no way to send an apple event (although you
+could write an extension to do this) and no general purpose way to
+recieve apple events. However, there are a couple of hooks for
+dealing with some of the standard apple events.
+
+ exit - Generally, Tcl cleans up after it self when you exit.
+ However, your application may want to do application specifc
+ cleanup like saving a users data. To do this you can rename
+ the exit command to something else. Define your own exit
+ command to do whatever clean up you like and then call the
+ origional exit command. For example,
+
+ rename exit __exit
+ proc exit {} {
+ # Do your clean up hear
+ __exit
+ }
+
+ Both incoming quit events and hitting the Quit menu item
+ will call the exit command. However, don't expect you can
+ abort the exit. Tk may exit anyway if the exit command it
+ calls does not actually quit the application.
+
+ open - The other apple event Tk supports is the open event. The
+ open event is sent to Tk if, for example, you drop a file on
+ the Wish icon. If you define a Tcl procedure with the name
+ "tkOpenDocument" it will be invoked on any Open Document
+ events that the application receives. The a list of paths to
+ the various documents will be passed to the Tcl function.
+ Here is an example,
+
+ proc tkOpenDocument args {
+ foreach file $args {
+ # Deal with passed in file path
+ }
+ }
+
+ Note: This isn't every thing you need to do to make your
+ application dropable. You must still define a FREF resource
+ that makes sense for your application domain. (Out of the
+ box, you will not be able to drop files on the Wish
+ application. See the Inside Macintosh documentation for
+ details about the FREF resource.
+
+ do script - This is a way for external applications to drive MacTk, or
+ to recieve information from it. From AppleScript, you can say:
+
+ tell application "Wish8.0"
+ do script "console hide
+ pack [button .b1 -text {Hello world} -command exit]"
+ end tell
+
+ which will get Tk to run the canonical hello world application.
+
+8. unsupported1
+---------------
+
+The unsupported1 command is a short term hack we made available to
+allow you to set the window style of a new toplevel window. It works
+much like the "wm overrideredirect" and "wm transient" commands in
+that it must be run before the window it's being applied to is mapped.
+
+The syntax of the command is as follows:
+
+ unsupported1 style <window> ?style?
+
+The <window> must be a toplevel window. If the style is not given
+then the current style for the window is returned. If you want to set
+the style you must do so before the window gets mapped for the first
+time. The possible window styles include:
+
+ documentProc, dBoxProc, plainDBox, altDBoxProc,
+ movableDBoxProc, zoomDocProc, rDocProc, floatProc,
+ floatZoomProc, floatSideProc, or floatSideZoomProc
+
+NOTE: this is an unsupported command and it WILL go away in the
+future.
+
+
+If you have comments or Bug reports send them to:
+Jim Ingham
+jingham@eng.sun.com
diff --git a/mac/bugs.doc b/mac/bugs.doc
new file mode 100644
index 0000000..e522d8c
--- /dev/null
+++ b/mac/bugs.doc
@@ -0,0 +1,40 @@
+Known bug list for Tk 8.0 for Macintosh
+
+by Ray Johnson
+Sun Microsystems Laboratories
+rjohnson@eng.sun.com
+
+SCCS: @(#) bugs.doc 1.10 97/11/03 17:16:00
+
+We are now very close to passing the test suite for Tk. We are very
+interested in finding remaining bugs that still linger. Please let us
+know (and send us test cases) of any bugs you find.
+
+Known bugs:
+
+* Transient windows (set by wm transient) do not go away when the
+ master does.
+
+* Tearoff menus should be floating windows & floating windows should
+ float. They also shouldn't be resizable.
+
+* The -use and -container windows only work with other Tk windows in
+ the same process. Also, if you try really hard (for instance by binding
+ on Destroy of an embedded window and destroying the container's toplevel)
+ you can get Tk to crash. This should never be necessary, however, since
+ the destruction of the embedded window triggers the destruction of the
+ container, so you can watch that instead.
+ All the focus bugs in Tk8.0 have been fixed, however.
+
+* The send command is not yet implemented.
+
+* Drawing is not really correct. This shows up mostly in the canvas
+ when line widths are greater than one. Unfortunantly, this will not
+ be easy to fix.
+
+There are many other bugs. However, will no get listed until they
+are reported at least once. Send those bug reports in!
+
+
+
+Ray
diff --git a/mac/tclets.tcl b/mac/tclets.tcl
new file mode 100644
index 0000000..c8726a8
--- /dev/null
+++ b/mac/tclets.tcl
@@ -0,0 +1,215 @@
+# tclets.tcl --
+#
+# Drag & Drop Tclets
+# by Ray Johnson
+#
+# A simple way to create Tcl applications. This applications will copy a droped Tcl file
+# into a copy of a stub application (the user can pick). The file is placed into the
+# TEXT resource named "tclshrc" which is automatically executed on startup.
+#
+# SCCS: @(#) tclets.tcl 1.2 97/08/15 09:25:56
+#
+# Copyright (c) 1997 Sun Microsystems, Inc.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+
+# tkOpenDocument --
+#
+# This procedure is a called whenever Wish recieves an "Open" event. The
+# procedure must be named tkOpenDocument for this to work. Passed in files
+# are assumed to be Tcl files that the user wants to be made into Tclets.
+# (Only the first one is used.) The procedure then creates a copy of the
+# stub app and places the Tcl file in the new application's resource fork.
+#
+# Parameters:
+# args List of files
+#
+# Results:
+# One success a new Tclet is created.
+
+proc tkOpenDocument {args} {
+ global droped_to_start
+
+ # We only deal with the one file droped on the App
+ set tclFile [lindex $args 0]
+ set stub [GetStub]
+
+ # Give a helper screen to guide user
+ toplevel .helper -menu .bar
+ unsupported1 style .helper dBoxProc
+ message .helper.m -aspect 300 -text \
+ "Select the name & location of your target Tcl application."
+ pack .helper.m
+ wm geometry .helper +20+40
+ update idletasks
+
+ # Get the target file from the end user
+ set target [tk_getSaveFile]
+ destroy .helper
+ if {$target == ""} return
+
+ # Copy stub, copy the droped file into the stubs text resource
+ file copy $stub $target
+ set id [open $tclFile r]
+ set rid [resource open $target w]
+ resource write -name tclshrc -file $rid TEXT [read $id]
+ resource close $rid
+ close $id
+
+ # This is a hint to the start-up code - always set to true
+ set droped_to_start true
+}
+
+# GetStub --
+#
+# Get the location of our stub application. The value may be cached,
+# in the preferences file, or we may need to ask the user.
+#
+# Parameters:
+# None.
+#
+# Results:
+# A path to the stub application.
+
+proc GetStub {} {
+ global env stub_location
+
+ if {[info exists stub_location]} {
+ return $stub_location
+ }
+
+ set file $env(PREF_FOLDER)
+ append file "D&D Tclet Preferences"
+
+
+ if {[file exists $file]} {
+ uplevel #0 [list source $file]
+ if {[info exists stub_location] && [file exists $stub_location]} {
+ return $stub_location
+ }
+ }
+
+ SelectStub
+
+ if {[info exists stub_location]} {
+ return $stub_location
+ } else {
+ exit
+ }
+}
+
+# SelectStub --
+#
+# This procedure uses tk_getOpenFile to allow the user to select
+# the copy of "Wish" that is used as the basis for Tclets. The
+# result is stored in a preferences file.
+#
+# Parameters:
+# None.
+#
+# Results:
+# None. The prefernce file is updated.
+
+proc SelectStub {} {
+ global env stub_location
+
+ # Give a helper screen to guide user
+ toplevel .helper -menu .bar
+ unsupported1 style .helper dBoxProc
+ message .helper.m -aspect 300 -text \
+ "Select \"Wish\" stub to clone. A copy of this application will be made to create your Tclet." \
+
+ pack .helper.m
+ wm geometry .helper +20+40
+ update idletasks
+
+ set new_location [tk_getOpenFile]
+ destroy .helper
+ if {$new_location != ""} {
+ set stub_location $new_location
+ set file [file join $env(PREF_FOLDER) "D&D Tclet Preferences"]
+
+ set id [open $file w]
+ puts $id [list set stub_location $stub_location]
+ close $id
+ }
+}
+
+# CreateMenus --
+#
+# Create the menubar for this application.
+#
+# Parameters:
+# None.
+#
+# Results:
+# None.
+
+proc CreateMenus {} {
+ menu .bar
+ .bar add cascade -menu .bar.file -label File
+ .bar add cascade -menu .bar.apple
+ . configure -menu .bar
+
+ menu .bar.apple -tearoff 0
+ .bar.apple add command -label "About Drag & Drop Tclets..." -command {ShowAbout}
+
+ menu .bar.file -tearoff 0
+ .bar.file add command -label "Show Console..." -command {console show}
+ .bar.file add command -label "Select Wish Stub..." -command {SelectStub}
+ .bar.file add separator
+ .bar.file add command -label "Quit" -accel Command-Q -command exit
+}
+
+# ShowAbout --
+#
+# Show the about box for Drag & Drop Tclets.
+#
+# Parameters:
+# None.
+#
+# Results:
+# None.
+
+proc ShowAbout {} {
+ tk_messageBox -icon info -type ok -message \
+"Drag & Drop Tclets
+by Ray Johnson\n\n\
+Copyright (c) 1997 Sun Microsystems, Inc."
+}
+
+# Start --
+#
+# This procedure provides the main start-up code for the application.
+# It should be run first thing on start up. It will create the UI
+# and set up the rest of the state of the application.
+#
+# Parameters:
+# None.
+#
+# Results:
+# None.
+
+proc Start {} {
+ global droped_to_start
+
+ # Hide . & console - see if we ran as a droped item
+ wm geometry . 1x1-25000-25000
+ console hide
+
+ # Run update - if we get any drop events we know that we were
+ # started by a drag & drop - if so, we quit automatically when done
+ set droped_to_start false
+ update
+ if {$droped_to_start == "true"} {
+ exit
+ }
+
+ # We were not started by a drag & drop - create the UI
+ CreateMenus
+}
+
+# Now that everything is defined, lets start the app!
+Start
diff --git a/mac/tkMac.h b/mac/tkMac.h
new file mode 100644
index 0000000..ce41c81
--- /dev/null
+++ b/mac/tkMac.h
@@ -0,0 +1,53 @@
+/*
+ * tkMacInt.h --
+ *
+ * Declarations of Macintosh specific exported variables and procedures.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacInt.h 1.58 97/05/06 16:45:18
+ */
+
+#ifndef _TKMAC
+#define _TKMAC
+
+#include <Windows.h>
+
+/*
+ * "export" is a MetroWerks specific pragma. It flags the linker that
+ * any symbols that are defined when this pragma is on will be exported
+ * to shared libraries that link with this library.
+ */
+
+#pragma export on
+
+/*
+ * This variable is exported and can be used by extensions. It is the
+ * way Tk extensions should access the QD Globals. This is so Tk
+ * can support embedding itself in another window.
+ */
+
+EXTERN QDGlobalsPtr tcl_macQdPtr;
+
+/*
+ * The following functions are needed to create a shell, and so they must be exported
+ * from the Tk library. However, these are not the final form of these interfaces, so
+ * they are not currently supported as public interfaces.
+ */
+
+/*
+ * These functions are currently in tkMacInt.h. They are just copied over here
+ * so they can be exported.
+ */
+
+EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN void TkMacInitAppleEvents _ANSI_ARGS_((Tcl_Interp *interp));
+
+EXTERN int TkMacConvertEvent _ANSI_ARGS_((EventRecord *eventPtr));
+
+#pragma export reset
+
+#endif /* _TKMAC */
diff --git a/mac/tkMacAppInit.c b/mac/tkMacAppInit.c
new file mode 100644
index 0000000..ebc2c18
--- /dev/null
+++ b/mac/tkMacAppInit.c
@@ -0,0 +1,374 @@
+/*
+ * tkMacAppInit.c --
+ *
+ * Provides a version of the Tcl_AppInit procedure for the example shell.
+ *
+ * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacAppInit.c 1.35 97/07/28 11:18:55
+ */
+
+#include <Gestalt.h>
+#include <ToolUtils.h>
+#include <Fonts.h>
+#include <Dialogs.h>
+#include <SegLoad.h>
+#include <Traps.h>
+
+#include "tk.h"
+#include "tkInt.h"
+#include "tkMacInt.h"
+#include "tclMac.h"
+
+#ifdef TK_TEST
+EXTERN int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+#endif /* TK_TEST */
+
+#ifdef TCL_TEST
+EXTERN int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
+#endif /* TCL_TEST */
+
+Tcl_Interp *gStdoutInterp = NULL;
+
+int TkMacConvertEvent _ANSI_ARGS_((EventRecord *eventPtr));
+
+/*
+ * Prototypes for functions the ANSI library needs to link against.
+ */
+short InstallConsole _ANSI_ARGS_((short fd));
+void RemoveConsole _ANSI_ARGS_((void));
+long WriteCharsToConsole _ANSI_ARGS_((char *buff, long n));
+long ReadCharsFromConsole _ANSI_ARGS_((char *buff, long n));
+extern char * __ttyname _ANSI_ARGS_((long fildes));
+short SIOUXHandleOneEvent _ANSI_ARGS_((EventRecord *event));
+
+/*
+ * Prototypes for functions from the tkConsole.c file.
+ */
+
+EXTERN void TkConsoleCreate _ANSI_ARGS_((void));
+EXTERN int TkConsoleInit _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN void TkConsolePrint _ANSI_ARGS_((Tcl_Interp *interp,
+ int devId, char *buffer, long size));
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int MacintoshInit _ANSI_ARGS_((void));
+static int SetupMainInterp _ANSI_ARGS_((Tcl_Interp *interp));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * main --
+ *
+ * Main program for Wish.
+ *
+ * Results:
+ * None. This procedure never returns (it exits the process when
+ * it's done
+ *
+ * Side effects:
+ * This procedure initializes the wish world and then
+ * calls Tk_Main.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+main(
+ int argc, /* Number of arguments. */
+ char **argv) /* Array of argument strings. */
+{
+ char *newArgv[2];
+
+ if (MacintoshInit() != TCL_OK) {
+ Tcl_Exit(1);
+ }
+
+ argc = 1;
+ newArgv[0] = "Wish";
+ newArgv[1] = NULL;
+ Tk_Main(argc, newArgv, Tcl_AppInit);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_AppInit --
+ *
+ * This procedure performs application-specific initialization.
+ * Most applications, especially those that incorporate additional
+ * packages, will have their own version of this procedure.
+ *
+ * Results:
+ * Returns a standard Tcl completion code, and leaves an error
+ * message in interp->result if an error occurs.
+ *
+ * Side effects:
+ * Depends on the startup script.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_AppInit(
+ Tcl_Interp *interp) /* Interpreter for application. */
+{
+ if (Tcl_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (Tk_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit);
+
+ /*
+ * Call the init procedures for included packages. Each call should
+ * look like this:
+ *
+ * if (Mod_Init(interp) == TCL_ERROR) {
+ * return TCL_ERROR;
+ * }
+ *
+ * where "Mod" is the name of the module.
+ */
+
+#ifdef TCL_TEST
+ if (Tcltest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init,
+ (Tcl_PackageInitProc *) NULL);
+ if (TclObjTest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+#endif /* TCL_TEST */
+
+#ifdef TK_TEST
+ if (Tktest_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_StaticPackage(interp, "Tktest", Tktest_Init,
+ (Tcl_PackageInitProc *) NULL);
+#endif /* TK_TEST */
+
+ /*
+ * Call Tcl_CreateCommand for application-specific commands, if
+ * they weren't already created by the init procedures called above.
+ * Each call would look like this:
+ *
+ * Tcl_CreateCommand(interp, "tclName", CFuncCmd, NULL, NULL);
+ */
+
+ SetupMainInterp(interp);
+
+ /*
+ * Specify a user-specific startup script to invoke if the application
+ * is run interactively. On the Mac we can specifiy either a TEXT resource
+ * which contains the script or the more UNIX like file location
+ * may also used. (I highly recommend using the resource method.)
+ */
+
+ Tcl_SetVar(interp, "tcl_rcRsrcName", "tclshrc", TCL_GLOBAL_ONLY);
+ /* Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY); */
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacintoshInit --
+ *
+ * This procedure calls Mac specific initilization calls. Most of
+ * these calls must be made as soon as possible in the startup
+ * process.
+ *
+ * Results:
+ * Returns TCL_OK if everything went fine. If it didn't the
+ * application should probably fail.
+ *
+ * Side effects:
+ * Inits the application.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MacintoshInit()
+{
+ int i;
+ long result, mask = 0x0700; /* mask = system 7.x */
+
+#if GENERATING68K && !GENERATINGCFM
+ SetApplLimit(GetApplLimit() - (TK_MAC_68K_STACK_GROWTH));
+#endif
+ MaxApplZone();
+ for (i = 0; i < 4; i++) {
+ (void) MoreMasters();
+ }
+
+ /*
+ * Tk needs us to set the qd pointer it uses. This is needed
+ * so Tk doesn't have to assume the availablity of the qd global
+ * variable. Which in turn allows Tk to be used in code resources.
+ */
+ tcl_macQdPtr = &qd;
+
+ InitGraf(&tcl_macQdPtr->thePort);
+ InitFonts();
+ InitWindows();
+ InitMenus();
+ InitDialogs((long) NULL);
+ InitCursor();
+
+ /*
+ * Make sure we are running on system 7 or higher
+ */
+
+ if ((NGetTrapAddress(_Gestalt, ToolTrap) ==
+ NGetTrapAddress(_Unimplemented, ToolTrap))
+ || (((Gestalt(gestaltSystemVersion, &result) != noErr)
+ || (result < mask)))) {
+ panic("Tcl/Tk requires System 7 or higher.");
+ }
+
+ /*
+ * Make sure we have color quick draw
+ * (this means we can't run on 68000 macs)
+ */
+
+ if (((Gestalt(gestaltQuickdrawVersion, &result) != noErr)
+ || (result < gestalt32BitQD13))) {
+ panic("Tk requires Color QuickDraw.");
+ }
+
+
+ FlushEvents(everyEvent, 0);
+ SetEventMask(everyEvent);
+
+
+ Tcl_MacSetEventProc(TkMacConvertEvent);
+ TkConsoleCreate();
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetupMainInterp --
+ *
+ * This procedure calls initalization routines require a Tcl
+ * interp as an argument. This call effectively makes the passed
+ * iterpreter the "main" interpreter for the application.
+ *
+ * Results:
+ * Returns TCL_OK if everything went fine. If it didn't the
+ * application should probably fail.
+ *
+ * Side effects:
+ * More initilization.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetupMainInterp(
+ Tcl_Interp *interp)
+{
+ /*
+ * Initialize the console only if we are running as an interactive
+ * application.
+ */
+
+ TkMacInitAppleEvents(interp);
+ TkMacInitMenus(interp);
+
+ if (strcmp(Tcl_GetVar(interp, "tcl_interactive", TCL_GLOBAL_ONLY), "1")
+ == 0) {
+ if (TkConsoleInit(interp) == TCL_ERROR) {
+ goto error;
+ }
+ }
+
+ /*
+ * Attach the global interpreter to tk's expected global console
+ */
+
+ gStdoutInterp = interp;
+
+ return TCL_OK;
+
+error:
+ panic(interp->result);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InstallConsole, RemoveConsole, etc. --
+ *
+ * The following functions provide the UI for the console package.
+ * Users wishing to replace SIOUX with their own console package
+ * need only provide the four functions below in a library.
+ *
+ * Results:
+ * See SIOUX documentation for details.
+ *
+ * Side effects:
+ * See SIOUX documentation for details.
+ *
+ *----------------------------------------------------------------------
+ */
+
+short
+InstallConsole(short fd)
+{
+#pragma unused (fd)
+
+ return 0;
+}
+
+void
+RemoveConsole(void)
+{
+}
+
+long
+WriteCharsToConsole(char *buffer, long n)
+{
+ TkConsolePrint(gStdoutInterp, TCL_STDOUT, buffer, n);
+ return n;
+}
+
+long
+ReadCharsFromConsole(char *buffer, long n)
+{
+ return 0;
+}
+
+extern char *
+__ttyname(long fildes)
+{
+ static char *__devicename = "null device";
+
+ if (fildes >= 0 && fildes <= 2) {
+ return (__devicename);
+ }
+
+ return (0L);
+}
+
+short
+SIOUXHandleOneEvent(EventRecord *event)
+{
+ return 0;
+}
diff --git a/mac/tkMacApplication.r b/mac/tkMacApplication.r
new file mode 100644
index 0000000..365035d
--- /dev/null
+++ b/mac/tkMacApplication.r
@@ -0,0 +1,267 @@
+/*
+ * tkMacApplication.r --
+ *
+ * This file creates resources for use in the Wish application.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacApplication.r 1.3 97/11/03 17:16:24
+ */
+
+#include <Types.r>
+#include <SysTypes.r>
+#include <AEUserTermTypes.r>
+
+/*
+ * The folowing include and defines help construct
+ * the version string for Tcl.
+ */
+
+#define RESOURCE_INCLUDED
+#include "tk.h"
+
+#if (TK_RELEASE_LEVEL == 0)
+# define RELEASE_LEVEL alpha
+#elif (TK_RELEASE_LEVEL == 1)
+# define RELEASE_LEVEL beta
+#elif (TK_RELEASE_LEVEL == 2)
+# define RELEASE_LEVEL final
+#endif
+
+#if (TK_RELEASE_LEVEL == 2)
+# define MINOR_VERSION (TK_MINOR_VERSION * 16) + TK_RELEASE_SERIAL
+#else
+# define MINOR_VERSION TK_MINOR_VERSION * 16
+#endif
+
+#define RELEASE_CODE 0x00
+
+resource 'vers' (1) {
+ TK_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TK_PATCH_LEVEL,
+ TK_PATCH_LEVEL ", by Ray Johnson © 1993-1996" "\n" "Sun Microsystems Labratories"
+};
+
+resource 'vers' (2) {
+ TK_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TK_PATCH_LEVEL,
+ "Wish " TK_PATCH_LEVEL " © 1993-1996"
+};
+
+#define TK_APP_RESOURCES 128
+#define TK_APP_CREATOR 'WIsH'
+
+/*
+ * The 'BNDL' resource is the primary link between a file's
+ * creator/type and its icon. This resource acts for all Tcl shared
+ * libraries; other libraries will not need one and ought to use
+ * custom icons rather than new file types for a different appearance.
+ */
+
+resource 'BNDL' (TK_APP_RESOURCES, "Tk app bundle", purgeable)
+{
+ TK_APP_CREATOR,
+ 0,
+ {
+ 'FREF',
+ {
+ 0, TK_APP_RESOURCES,
+ 1, TK_APP_RESOURCES+1
+ },
+ 'ICN#',
+ {
+ 0, TK_APP_RESOURCES,
+ 1, TK_APP_RESOURCES+1
+ }
+ }
+};
+
+resource 'FREF' (TK_APP_RESOURCES, purgeable)
+{
+ 'APPL', 0, ""
+};
+resource 'FREF' (TK_APP_RESOURCES+1, purgeable)
+{
+ 'TEXT', 1, ""
+};
+
+type TK_APP_CREATOR as 'STR ';
+resource TK_APP_CREATOR (0, purgeable) {
+ "Wish " TK_PATCH_LEVEL " © 1996"
+};
+
+/*
+ * The 'kind' resource works with a 'BNDL' in Macintosh Easy Open
+ * to affect the text the Finder displays in the "kind" column and
+ * file info dialog. This information will be applied to all files
+ * with the listed creator and type.
+ */
+resource 'kind' (TK_APP_RESOURCES, "Tcl kind", purgeable) {
+ TK_APP_CREATOR,
+ 0, /* region = USA */
+ {
+ 'APPL', "Wish",
+ 'TEXT', "Tcl/Tk Script"
+ }
+};
+
+/*
+ * The following resource define the icon used by Tcl scripts. Any
+ * TEXT file with the creator of WIsH will get this icon.
+ */
+
+data 'icl4' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) {
+ $"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
+ $"000F 3333 3333 3333 3333 33FF 0000 0000"
+ $"000F 3333 3333 3333 3433 33F2 F000 0000"
+ $"000F 3333 3333 3333 7D43 33F2 2F00 0000"
+ $"000F 3333 3333 3335 5623 33F2 22F0 0000"
+ $"000F 3333 3333 3356 6343 33FF FFFF 0000"
+ $"000F 3333 3333 256F 5223 3333 333F 0000"
+ $"000F 3333 3333 D666 2433 3333 333F 0000"
+ $"000F 3333 3333 D5F6 6633 3333 333F 0000"
+ $"000F 3333 3332 5666 6733 3333 333F 0000"
+ $"000F 3333 3336 E56F 6633 3333 333F 0000"
+ $"000F 3333 3336 5656 5733 3333 333F 0000"
+ $"000F 3333 3336 E5B6 5233 3333 333F 0000"
+ $"000F 3333 3336 5ED6 3333 3333 333F 0000"
+ $"000F 3333 3376 6475 6233 3333 333F 0000"
+ $"000F 3333 333D 5D56 7333 3333 333F 0000"
+ $"000F 3333 3336 6C55 6333 3333 333F 0000"
+ $"000F 3333 3336 5C56 7333 3333 333F 0000"
+ $"000F 3333 3362 6CE6 D333 3333 333F 0000"
+ $"000F 3333 3336 5C65 6333 3333 333F 0000"
+ $"000F 3333 3336 EC5E 3333 3333 333F 0000"
+ $"000F 3333 3336 5C56 6333 3333 333F 0000"
+ $"000F 3333 3333 5C75 3333 3333 333F 0000"
+ $"000F 3333 3333 5DD6 3333 3333 333F 0000"
+ $"000F 3333 3333 3CDD 3333 3333 333F 0000"
+ $"000F 3333 3333 3303 3333 3333 333F 0000"
+ $"000F 3333 3333 3C33 3333 3333 333F 0000"
+ $"000F 3333 3333 3C33 3333 3333 333F 0000"
+ $"000F 3333 3333 3C33 3333 3333 333F 0000"
+ $"000F 3333 3333 3333 3333 3333 333F 0000"
+ $"000F 3333 3333 3333 3333 3333 333F 0000"
+ $"000F FFFF FFFF FFFF FFFF FFFF FFFF 0000"
+};
+
+data 'ICN#' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) {
+ $"1FFF FE00 1000 0300 1000 F280 1003 F240"
+ $"1003 E220 1007 E3F0 100F C010 100F C010"
+ $"100F C010 101F F010 101F F010 101F F010"
+ $"101F F010 101F F010 101D E010 101D E010"
+ $"101D E010 101D C010 101D C010 101D C010"
+ $"101D C010 100D 8010 100D 8010 100D 8010"
+ $"1005 8010 1002 0010 1002 0010 1002 0010"
+ $"1002 0010 1002 0010 1000 0010 1FFF FFF0"
+ $"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
+ $"1FFF FFE0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+ $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+ $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+ $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+ $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+ $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+ $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+};
+
+data 'ics#' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) {
+ $"7FF0 41D8 419C 4384 43C4 47C4 47C4 4784"
+ $"4684 4684 4284 4284 4104 4104 4104 7FFC"
+ $"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
+ $"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
+};
+
+data 'ics4' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) {
+ $"0FFF FFFF FFFF 0000 0F33 3333 53F2 F000"
+ $"0F33 3335 52FF FF00 0F33 33E6 3333 3F00"
+ $"0F33 3256 6333 3F00 0F33 3556 6333 3F00"
+ $"0F33 3A5E 3333 3F00 0F33 65D6 D333 3F00"
+ $"0F33 3655 5333 3F00 0F33 65C6 3333 3F00"
+ $"0F33 3EC5 E333 3F00 0F33 36C6 3333 3F00"
+ $"0F33 33CD 3333 3F00 0F33 33C3 3333 3F00"
+ $"0F33 33C3 3333 3F00 0FFF FFFF FFFF FF00"
+};
+
+/*
+ * The following resources define the icons for the Wish
+ * application.
+ */
+
+data 'icl4' (TK_APP_RESOURCES, "Tk App", purgeable) {
+ $"0000 0000 0000 000F 0000 0000 0000 0000"
+ $"0000 0000 0000 00FC F000 0000 0000 0000"
+ $"0000 0000 0000 0FCC CF66 0000 0000 0000"
+ $"0000 0000 0000 FCCC C556 0000 0000 0000"
+ $"0000 0000 000F CCCC 566F 0000 0000 0000"
+ $"0000 0000 00FC CCC5 6F5C F000 0000 0000"
+ $"0000 0000 0FCC CC66 66CC CF00 0000 0000"
+ $"0000 0000 FCCC CCD5 5666 CCF0 0000 0000"
+ $"0000 000F CCCC C656 5667 CCCF 0000 0000"
+ $"0000 00FC CCCC C6E5 5566 CCCC F000 0000"
+ $"0000 0FCC CCCC C656 5657 CCCC CF00 0000"
+ $"0000 FCCC CCCC C6E5 565C CCCC CCF0 0000"
+ $"000F CCCC CCCC C655 565C CCCC CCCF 0000"
+ $"00FC CCCC CCCC 7660 556C CCCC CCCC F000"
+ $"0FCC CCCC CCCC CD5D 567C CCCC CCCC CF00"
+ $"FCCC CCCC CCCC 6660 556C CCCC CCCC CCF0"
+ $"0FCC CCCC CCCC 665C 565C CCCC CCCC C0CF"
+ $"00FC CCCC CCCC 6660 E6DC CCCC CCCC CCF0"
+ $"000F CCCC CCCC C650 656C CCCC CCCC CF00"
+ $"0000 FCCC CCCC C6EC 5ECC CCCC CCCC F000"
+ $"0000 0FCC CCCC C650 566C CCCC CCCF 0000"
+ $"0000 00FC CCCC CC50 75CC CCCC CCF0 0000"
+ $"0000 000F CCCC CC50 56CC CCCC CF00 0000"
+ $"0000 0000 FCCC CCC0 5CCC CCCC F000 0000"
+ $"0000 0000 0FCC CCC0 CCCC CCCF 0000 0000"
+ $"0000 0000 00FC CCC0 CCCC CCF0 0000 0000"
+ $"0000 0000 000F CCC0 CCCC CF00 0000 0000"
+ $"0000 0000 0000 FCCC CCCC F000 0000 0000"
+ $"0000 0000 0000 0FCC CCCF 0000 0000 0000"
+ $"0000 0000 0000 00FC CCF0 0000 0000 0000"
+ $"0000 0000 0000 000F CF00 0000 0000 0000"
+ $"0000 0000 0000 0000 F000 0000 0000 0000"
+};
+
+data 'ICN#' (TK_APP_RESOURCES, "Tk App", purgeable) {
+ $"0001 0000 0002 8000 0004 7000 0008 7000"
+ $"0010 F000 0021 E800 0043 C400 0081 F200"
+ $"0107 F100 0207 F080 0407 F040 0807 E020"
+ $"1007 E010 200E E008 4002 E004 800E E002"
+ $"400E E001 200E C002 1006 E004 0806 C008"
+ $"0406 E010 0202 C020 0102 C040 0080 8080"
+ $"0041 0100 0021 0200 0011 0400 0009 0800"
+ $"0004 1000 0002 2000 0001 4000 0000 8000"
+ $"0001 0000 0003 8000 0007 F000 000F F000"
+ $"001F F000 003F F800 007F FC00 00FF FE00"
+ $"01FF FF00 03FF FF80 07FF FFC0 0FFF FFE0"
+ $"1FFF FFF0 3FFF FFF8 7FFF FFFC FFFF FFFE"
+ $"7FFF FFFF 3FFF FFFE 1FFF FFFC 0FFF FFF8"
+ $"07FF FFF0 03FF FFE0 01FF FFC0 00FF FF80"
+ $"007F FF00 003F FE00 001F FC00 000F F800"
+ $"0007 F000 0003 E000 0001 C000 0000 8000"
+};
+
+data 'ics#' (TK_APP_RESOURCES, "Tk App", purgeable) {
+ $"01C0 0260 04E0 09D0 1388 23C4 43C2 8281"
+ $"8282 4284 2188 1190 0920 0540 0280 0100"
+ $"01C0 03E0 07E0 0FF0 1FF8 3FFC 7FFE FFFF"
+ $"FFFE 7FFC 3FF8 1FF0 0FE0 07C0 0380 0100"
+};
+
+data 'ics4' (TK_APP_RESOURCES, "Tk App", purgeable) {
+ $"0000 000F C000 0000 0000 00FC 6600 0000"
+ $"0000 0FCC 6600 0000 0000 FCC6 66F0 0000"
+ $"000F CCD5 56CF 0000 00FC CC66 57CC F000"
+ $"0FCC CC65 56CC CF00 FCCC CC56 57CC CCF0"
+ $"0FCC CCC6 6CCC CCCF 00FC CCC6 5CCC CCF0"
+ $"000F CCC6 6CCC CF00 0000 FCCC 5CCC F000"
+ $"0000 0FCC CCCF 0000 0000 00FC CCF0 0000"
+ $"0000 000F CF00 0000 0000 0000 F000 0000"
+};
+
+
diff --git a/mac/tkMacBitmap.c b/mac/tkMacBitmap.c
new file mode 100644
index 0000000..fd08193
--- /dev/null
+++ b/mac/tkMacBitmap.c
@@ -0,0 +1,268 @@
+/*
+ * tkMacBitmap.c --
+ *
+ * This file handles the implementation of native bitmaps.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacBitmap.c 1.4 96/12/13 11:13:16
+ */
+
+#include "tkPort.h"
+#include "tk.h"
+#include "tkMacInt.h"
+
+#include <Icons.h>
+#include <Dialogs.h>
+#include <Resources.h>
+#include <Strings.h>
+
+/*
+ * Depending on the resource type there are different ways to
+ * draw native icons.
+ */
+#define TYPE1 0 /* Family icon suite. */
+#define TYPE2 1 /* ICON resource. */
+#define TYPE3 2 /* cicn resource. */
+
+/*
+ * This data structure describes the id and type of a given icon.
+ * It is used as the source for native icons.
+ */
+typedef struct {
+ int id; /* Resource Id for Icon. */
+ long int type; /* Type of icon. */
+} NativeIcon;
+
+/*
+ * This structure holds information about native bitmaps.
+ */
+
+typedef struct {
+ char *name; /* Name of icon. */
+ long int type; /* Type of icon. */
+ int id; /* Id of icon. */
+ int size; /* Size of icon. */
+} BuiltInIcon;
+
+/*
+ * This array mapps a string name to the supported builtin icons
+ * on the Macintosh.
+ */
+
+static BuiltInIcon builtInIcons[] = {
+ {"document", TYPE1, kGenericDocumentIconResource, 32},
+ {"stationery", TYPE1, kGenericStationeryIconResource, 32},
+ {"edition", TYPE1, kGenericEditionFileIconResource, 32},
+ {"application", TYPE1, kGenericApplicationIconResource, 32},
+ {"accessory", TYPE1, kGenericDeskAccessoryIconResource, 32},
+ {"folder", TYPE1, kGenericFolderIconResource, 32},
+ {"pfolder", TYPE1, kPrivateFolderIconResource, 32},
+ {"trash", TYPE1, kTrashIconResource, 32},
+ {"floppy", TYPE1, kFloppyIconResource, 32},
+ {"ramdisk", TYPE1, kGenericRAMDiskIconResource, 32},
+ {"cdrom", TYPE1, kGenericCDROMIconResource, 32},
+ {"preferences", TYPE1, kGenericPreferencesIconResource, 32},
+ {"querydoc", TYPE1, kGenericQueryDocumentIconResource, 32},
+ {"stop", TYPE2, kStopIcon, 32},
+ {"note", TYPE2, kNoteIcon, 32},
+ {"caution", TYPE2, kCautionIcon, 32},
+ {(char *) NULL, 0, 0, 0}
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDefineNativeBitmaps --
+ *
+ * Add native bitmaps.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurs then TCL_ERROR is
+ * returned and a message is left in interp->result.
+ *
+ * Side effects:
+ * "Name" is entered into the bitmap table and may be used from
+ * here on to refer to the given bitmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDefineNativeBitmaps()
+{
+ int new;
+ Tcl_HashEntry *predefHashPtr;
+ TkPredefBitmap *predefPtr;
+ char * name;
+ BuiltInIcon *builtInPtr;
+ NativeIcon *nativeIconPtr;
+
+ for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) {
+ name = Tk_GetUid(builtInPtr->name);
+ predefHashPtr = Tcl_CreateHashEntry(&tkPredefBitmapTable, name, &new);
+ if (!new) {
+ continue;
+ }
+ predefPtr = (TkPredefBitmap *) ckalloc(sizeof(TkPredefBitmap));
+ nativeIconPtr = (NativeIcon *) ckalloc(sizeof(NativeIcon));
+ nativeIconPtr->id = builtInPtr->id;
+ nativeIconPtr->type = builtInPtr->type;
+ predefPtr->source = (char *) nativeIconPtr;
+ predefPtr->width = builtInPtr->size;
+ predefPtr->height = builtInPtr->size;
+ predefPtr->native = 1;
+ Tcl_SetHashValue(predefHashPtr, predefPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateNativeBitmap --
+ *
+ * Add native bitmaps.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurs then TCL_ERROR is
+ * returned and a message is left in interp->result.
+ *
+ * Side effects:
+ * "Name" is entered into the bitmap table and may be used from
+ * here on to refer to the given bitmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+TkpCreateNativeBitmap(
+ Display *display,
+ char * source) /* Info about the icon to build. */
+{
+ Pixmap pix;
+ GWorldPtr destPort;
+ Rect destRect;
+ Handle icon;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ NativeIcon *nativeIconPtr;
+
+ pix = Tk_GetPixmap(display, None, 32, 32, 0);
+ destPort = TkMacGetDrawablePort(pix);
+
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ nativeIconPtr = (NativeIcon *) source;
+ SetRect(&destRect, 0, 0, 32, 32);
+ if (nativeIconPtr->type == TYPE1) {
+ RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
+
+ RGBForeColor(&white);
+ PaintRect(&destRect);
+ PlotIconID(&destRect, atAbsoluteCenter, ttNone, nativeIconPtr->id);
+ } else if (nativeIconPtr->type == TYPE2) {
+ icon = GetIcon(nativeIconPtr->id);
+ if (icon != NULL) {
+ RGBColor black = {0, 0, 0};
+
+ RGBForeColor(&black);
+ PlotIcon(&destRect, icon);
+ ReleaseResource(icon);
+ }
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+ return pix;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetNativeAppBitmap --
+ *
+ * Add native bitmaps.
+ *
+ * Results:
+ * A standard Tcl result. If an error occurs then TCL_ERROR is
+ * returned and a message is left in interp->result.
+ *
+ * Side effects:
+ * "Name" is entered into the bitmap table and may be used from
+ * here on to refer to the given bitmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+TkpGetNativeAppBitmap(
+ Display *display, /* The display. */
+ char *name, /* The name of the bitmap. */
+ int *width, /* The width & height of the bitmap. */
+ int *height)
+{
+ Pixmap pix;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ Rect destRect;
+ Handle resource;
+ int type;
+
+ c2pstr(name);
+ resource = GetNamedResource('cicn', (StringPtr) name);
+ if (resource != NULL) {
+ type = TYPE3;
+ } else {
+ resource = GetNamedResource('ICON', (StringPtr) name);
+ if (resource != NULL) {
+ type = TYPE2;
+ }
+ }
+ p2cstr((StringPtr) name);
+
+ if (resource == NULL) {
+ return NULL;
+ }
+
+ pix = Tk_GetPixmap(display, None, 32, 32, 0);
+ destPort = TkMacGetDrawablePort(pix);
+
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ SetRect(&destRect, 0, 0, 32, 32);
+ if (type == TYPE2) {
+ RGBColor black = {0, 0, 0};
+
+ RGBForeColor(&black);
+ PlotIcon(&destRect, resource);
+ ReleaseResource(resource);
+ } else if (type == TYPE3) {
+ RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
+ short id;
+ ResType theType;
+ Str255 dummy;
+
+ /*
+ * We need to first paint the background white. Also, for
+ * some reason we *must* use GetCIcon instead of GetNamedResource
+ * for PlotCIcon to work - so we use GetResInfo to get the id.
+ */
+ RGBForeColor(&white);
+ PaintRect(&destRect);
+ GetResInfo(resource, &id, &theType, dummy);
+ ReleaseResource(resource);
+ resource = (Handle) GetCIcon(id);
+ PlotCIcon(&destRect, (CIconHandle) resource);
+ DisposeCIcon((CIconHandle) resource);
+ }
+
+ *width = 32;
+ *height = 32;
+ SetGWorld(saveWorld, saveDevice);
+ return pix;
+}
diff --git a/mac/tkMacButton.c b/mac/tkMacButton.c
new file mode 100644
index 0000000..767baff
--- /dev/null
+++ b/mac/tkMacButton.c
@@ -0,0 +1,825 @@
+/*
+ * tkMacButton.c --
+ *
+ * This file implements the Macintosh specific portion of the
+ * button widgets.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacButton.c 1.18 97/11/20 18:27:21
+ */
+
+#include "tkButton.h"
+#include "tkMacInt.h"
+#include <Controls.h>
+#include <LowMem.h>
+
+/*
+ * Some defines used to control what type of control is drawn.
+ */
+
+#define DRAW_LABEL 0 /* Labels are treated genericly. */
+#define DRAW_CONTROL 1 /* Draw using the Native control. */
+#define DRAW_CUSTOM 2 /* Make our own button drawing. */
+
+/*
+ * The following structures are used to draw our controls. Rather than
+ * having many Mac controls we just use one control of each type and
+ * reuse them for all Tk widgets. When the windowRef variable is NULL
+ * it means none of the data structures have been allocated.
+ */
+
+static WindowRef windowRef = NULL;
+static CWindowRecord windowRecord;
+static ControlRef buttonHandle;
+static ControlRef checkHandle;
+static ControlRef radioHandle;
+static CCTabHandle buttonTabHandle;
+static CCTabHandle checkTabHandle;
+static CCTabHandle radioTabHandle;
+static PixMapHandle oldPixPtr;
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int UpdateControlColors _ANSI_ARGS_((TkButton *butPtr,
+ ControlRef controlHandle, CCTabHandle ccTabHandle,
+ RGBColor *saveColorPtr));
+static void DrawBufferedControl _ANSI_ARGS_((TkButton *butPtr,
+ GWorldPtr destPort));
+static void ChangeBackgroundWindowColor _ANSI_ARGS_((
+ WindowRef macintoshWindow, RGBColor rgbColor,
+ RGBColor *oldColor));
+static void ButtonExitProc _ANSI_ARGS_((ClientData clientData));
+
+/*
+ * The class procedure table for the button widgets.
+ */
+
+TkClassProcs tkpButtonProcs = {
+ NULL, /* createProc. */
+ TkButtonWorldChanged, /* geometryProc. */
+ NULL /* modalProc. */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateButton --
+ *
+ * Allocate a new TkButton structure.
+ *
+ * Results:
+ * Returns a newly allocated TkButton structure.
+ *
+ * Side effects:
+ * Registers an event handler for the widget.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkButton *
+TkpCreateButton(
+ Tk_Window tkwin)
+{
+ return (TkButton *) ckalloc(sizeof(TkButton));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDisplayButton --
+ *
+ * This procedure is invoked to display a button widget. It is
+ * normally invoked as an idle handler.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the button in its
+ * current mode. The REDRAW_PENDING flag is cleared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDisplayButton(
+ ClientData clientData) /* Information about widget. */
+{
+ TkButton *butPtr = (TkButton *) clientData;
+ Pixmap pixmap;
+ GC gc;
+ Tk_3DBorder border;
+ int x = 0; /* Initialization only needed to stop
+ * compiler warning. */
+ int y, relief;
+ register Tk_Window tkwin = butPtr->tkwin;
+ int width, height;
+ int offset; /* 0 means this is a normal widget. 1 means
+ * it is an image button, so we offset the
+ * image to make the button appear to move
+ * up and down as the relief changes. */
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ int drawType, borderWidth;
+
+ GetGWorld(&saveWorld, &saveDevice);
+
+ butPtr->flags &= ~REDRAW_PENDING;
+ if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ border = butPtr->normalBorder;
+ if ((butPtr->state == tkDisabledUid) && (butPtr->disabledFg != NULL)) {
+ gc = butPtr->disabledGC;
+ } else if ((butPtr->type == TYPE_BUTTON) && (butPtr->state == tkActiveUid)) {
+ gc = butPtr->activeTextGC;
+ border = butPtr->activeBorder;
+ } else {
+ gc = butPtr->normalTextGC;
+ }
+ if ((butPtr->flags & SELECTED) && (butPtr->state != tkActiveUid)
+ && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {
+ border = butPtr->selectBorder;
+ }
+
+ /*
+ * Override the relief specified for the button if this is a
+ * checkbutton or radiobutton and there's no indicator.
+ */
+
+ relief = butPtr->relief;
+ if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {
+ relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN
+ : TK_RELIEF_RAISED;
+ }
+
+ offset = ((butPtr->type == TYPE_BUTTON) &&
+ ((butPtr->image != NULL) || (butPtr->bitmap != None)));
+
+ /*
+ * In order to avoid screen flashes, this procedure redraws
+ * the button in a pixmap, then copies the pixmap to the
+ * screen in a single operation. This means that there's no
+ * point in time where the on-sreen image has been cleared.
+ */
+
+ pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
+ Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+
+
+ if (butPtr->type == TYPE_LABEL) {
+ drawType = DRAW_LABEL;
+ } else if (butPtr->type == TYPE_BUTTON) {
+ if ((butPtr->image == None) && (butPtr->bitmap == None)) {
+ drawType = DRAW_CONTROL;
+ } else {
+ drawType = DRAW_CUSTOM;
+ }
+ } else {
+ if (butPtr->indicatorOn) {
+ drawType = DRAW_CONTROL;
+ } else {
+ drawType = DRAW_CUSTOM;
+ }
+ }
+
+ /*
+ * Draw the native portion of the buttons. Start by creating the control
+ * if it doesn't already exist. Then configure the Macintosh control from
+ * the Tk info. Finally, we call Draw1Control to draw to the screen.
+ */
+
+ if (drawType == DRAW_CONTROL) {
+ borderWidth = 0;
+
+ /*
+ * This part uses Macintosh rather than Tk calls to draw
+ * to the screen. Make sure the ports etc. are set correctly.
+ */
+
+ destPort = TkMacGetDrawablePort(pixmap);
+ SetGWorld(destPort, NULL);
+ DrawBufferedControl(butPtr, destPort);
+ }
+
+ if ((drawType == DRAW_CUSTOM) || (drawType == DRAW_LABEL)) {
+ borderWidth = butPtr->borderWidth;
+ }
+
+ /*
+ * Display image or bitmap or text for button.
+ */
+
+ if (butPtr->image != None) {
+ Tk_SizeOfImage(butPtr->image, &width, &height);
+
+ imageOrBitmap:
+ TkComputeAnchor(butPtr->anchor, tkwin, 0, 0,
+ butPtr->indicatorSpace + width, height, &x, &y);
+ x += butPtr->indicatorSpace;
+
+ x += offset;
+ y += offset;
+ if (relief == TK_RELIEF_RAISED) {
+ x -= offset;
+ y -= offset;
+ } else if (relief == TK_RELIEF_SUNKEN) {
+ x += offset;
+ y += offset;
+ }
+ if (butPtr->image != NULL) {
+ if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {
+ Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height,
+ pixmap, x, y);
+ } else {
+ Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,
+ x, y);
+ }
+ } else {
+ XSetClipOrigin(butPtr->display, gc, x, y);
+ XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0,
+ (unsigned int) width, (unsigned int) height, x, y, 1);
+ XSetClipOrigin(butPtr->display, gc, 0, 0);
+ }
+ y += height/2;
+ } else if (butPtr->bitmap != None) {
+ Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
+ goto imageOrBitmap;
+ } else {
+ TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
+ butPtr->indicatorSpace + butPtr->textWidth, butPtr->textHeight,
+ &x, &y);
+
+ x += butPtr->indicatorSpace;
+
+ Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout,
+ x, y, 0, -1);
+ y += butPtr->textHeight/2;
+ }
+
+ /*
+ * If the button is disabled with a stipple rather than a special
+ * foreground color, generate the stippled effect. If the widget
+ * is selected and we use a different background color when selected,
+ * must temporarily modify the GC.
+ */
+
+ if ((butPtr->state == tkDisabledUid)
+ && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {
+ if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
+ && (butPtr->selectBorder != NULL)) {
+ XSetForeground(butPtr->display, butPtr->disabledGC,
+ Tk_3DBorderColor(butPtr->selectBorder)->pixel);
+ }
+ XFillRectangle(butPtr->display, pixmap, butPtr->disabledGC,
+ butPtr->inset, butPtr->inset,
+ (unsigned) (Tk_Width(tkwin) - 2*butPtr->inset),
+ (unsigned) (Tk_Height(tkwin) - 2*butPtr->inset));
+ if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
+ && (butPtr->selectBorder != NULL)) {
+ XSetForeground(butPtr->display, butPtr->disabledGC,
+ Tk_3DBorderColor(butPtr->normalBorder)->pixel);
+ }
+ }
+
+ /*
+ * Draw the border and traversal highlight last. This way, if the
+ * button's contents overflow they'll be covered up by the border.
+ */
+
+ if (relief != TK_RELIEF_FLAT) {
+ int inset = butPtr->highlightWidth;
+ Tk_Draw3DRectangle(tkwin, pixmap, border, inset, inset,
+ Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset,
+ butPtr->borderWidth, relief);
+ }
+
+ /*
+ * Copy the information from the off-screen pixmap onto the screen,
+ * then delete the pixmap.
+ */
+
+ XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin),
+ butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin),
+ (unsigned) Tk_Height(tkwin), 0, 0);
+ Tk_FreePixmap(butPtr->display, pixmap);
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpComputeButtonGeometry --
+ *
+ * After changes in a button's text or bitmap, this procedure
+ * recomputes the button's geometry and passes this information
+ * along to the geometry manager for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The button's window may change size.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpComputeButtonGeometry(
+ TkButton *butPtr) /* Button whose geometry may have changed. */
+{
+ int width, height, avgWidth;
+ Tk_FontMetrics fm;
+
+ if (butPtr->highlightWidth < 0) {
+ butPtr->highlightWidth = 0;
+ }
+ if ((butPtr->type == TYPE_BUTTON) && (butPtr->image == None)
+ && (butPtr->bitmap == None)) {
+ butPtr->inset = 0;
+ } else if ((butPtr->type != TYPE_LABEL) && butPtr->indicatorOn) {
+ butPtr->inset = 0;
+ } else {
+ butPtr->inset = butPtr->borderWidth;
+ }
+
+ /*
+ * The highlight width corresponds to the default ring on the Macintosh.
+ * As such, the highlight width is only added if the button is the default
+ * button. The actual width of the default ring is one less than the
+ * highlight width as there is also one pixel of spacing.
+ */
+
+ if (butPtr->defaultState != tkDisabledUid) {
+ butPtr->inset += butPtr->highlightWidth;
+ }
+ butPtr->indicatorSpace = 0;
+ if (butPtr->image != NULL) {
+ Tk_SizeOfImage(butPtr->image, &width, &height);
+ imageOrBitmap:
+ if (butPtr->width > 0) {
+ width = butPtr->width;
+ }
+ if (butPtr->height > 0) {
+ height = butPtr->height;
+ }
+ if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
+ butPtr->indicatorSpace = height;
+ if (butPtr->type == TYPE_CHECK_BUTTON) {
+ butPtr->indicatorDiameter = (65*height)/100;
+ } else {
+ butPtr->indicatorDiameter = (75*height)/100;
+ }
+ }
+ } else if (butPtr->bitmap != None) {
+ Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
+ goto imageOrBitmap;
+ } else {
+ Tk_FreeTextLayout(butPtr->textLayout);
+ butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
+ butPtr->text, -1, butPtr->wrapLength, butPtr->justify, 0,
+ &butPtr->textWidth, &butPtr->textHeight);
+
+ width = butPtr->textWidth;
+ height = butPtr->textHeight;
+ avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
+ Tk_GetFontMetrics(butPtr->tkfont, &fm);
+
+ if (butPtr->width > 0) {
+ width = butPtr->width * avgWidth;
+ }
+ if (butPtr->height > 0) {
+ height = butPtr->height * fm.linespace;
+ }
+ if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
+ butPtr->indicatorDiameter = fm.linespace;
+ if (butPtr->type == TYPE_CHECK_BUTTON) {
+ butPtr->indicatorDiameter = (80*butPtr->indicatorDiameter)/100;
+ }
+ butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;
+ }
+ }
+
+ /*
+ * When issuing the geometry request, add extra space for the indicator,
+ * if any, and for the border and padding, plus if this is an image two
+ * extra pixels so the display can be offset by 1 pixel in either
+ * direction for the raised or lowered effect.
+ */
+
+ if ((butPtr->image == NULL) && (butPtr->bitmap == None)) {
+ width += 2*butPtr->padX;
+ height += 2*butPtr->padY;
+ }
+ if ((butPtr->type == TYPE_BUTTON) &&
+ ((butPtr->image != NULL) || (butPtr->bitmap != None))) {
+ width += 2;
+ height += 2;
+ }
+ Tk_GeometryRequest(butPtr->tkwin, (int) (width + butPtr->indicatorSpace
+ + 2*butPtr->inset), (int) (height + 2*butPtr->inset));
+ Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyButton --
+ *
+ * Free data structures associated with the button control.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Restores the default control state.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyButton(
+ TkButton *butPtr)
+{
+ /* Do nothing. */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DrawBufferedControl --
+ *
+ * This function uses a dummy Macintosh window to allow
+ * drawing Mac controls to any GWorld (including off-screen
+ * bitmaps). In addition, this code may apply custom
+ * colors passed in the TkButton.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Control is to the GWorld. Static state created on
+ * first invocation of this routine.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DrawBufferedControl(
+ TkButton *butPtr, /* Tk button. */
+ GWorldPtr destPort) /* Off screen GWorld. */
+{
+ ControlRef controlHandle;
+ CCTabHandle ccTabHandle;
+ int windowColorChanged = false;
+ RGBColor saveBackColor;
+
+ if (windowRef == NULL) {
+ Rect geometry = {0, 0, 10, 10};
+ CWindowPeek windowList;
+
+ /*
+ * Create a dummy window that we can draw to. We will
+ * actually replace this windows bitmap with a the one
+ * we want to draw to at a later time. This window and
+ * the data structures attached to it are only deallocated
+ * on exit of the application.
+ */
+
+ windowRef = NewCWindow(NULL, &geometry, "\pempty", false,
+ zoomDocProc, (WindowRef) -1, true, 0);
+ if (windowRef == NULL) {
+ panic("Can't allocate buffer window.");
+ }
+
+ /*
+ * Now add the three standard controls to hidden window. We
+ * only create one of each and reuse them for every widget in
+ * Tk.
+ */
+
+ SetPort(windowRef);
+ buttonHandle = NewControl(windowRef, &geometry, "\p",
+ false, 1, 0, 1, pushButProc, (SInt32) 0);
+ checkHandle = NewControl(windowRef, &geometry, "\p",
+ false, 1, 0, 1, checkBoxProc, (SInt32) 0);
+ radioHandle = NewControl(windowRef, &geometry, "\p",
+ false, 1, 0, 1, radioButProc, (SInt32) 0);
+ ((CWindowPeek) windowRef)->visible = true;
+
+ buttonTabHandle = (CCTabHandle) NewHandle(sizeof(CtlCTab));
+ checkTabHandle = (CCTabHandle) NewHandle(sizeof(CtlCTab));
+ radioTabHandle = (CCTabHandle) NewHandle(sizeof(CtlCTab));
+
+ /*
+ * Remove our window from the window list. This way our
+ * applications and others will not be confused that this
+ * window exists - but no one knows about it.
+ */
+
+ windowList = (CWindowPeek) LMGetWindowList();
+ if (windowList == (CWindowPeek) windowRef) {
+ LMSetWindowList((WindowRef) windowList->nextWindow);
+ } else {
+ while ((windowList != NULL)
+ && (windowList->nextWindow != (CWindowPeek) windowRef)) {
+ windowList = windowList->nextWindow;
+ }
+ if (windowList != NULL) {
+ windowList->nextWindow = windowList->nextWindow->nextWindow;
+ }
+ }
+ ((CWindowPeek) windowRef)->nextWindow = NULL;
+
+ /*
+ * Create an exit handler to clean up this mess if we our
+ * unloaded etc. We need to remember the windows portPixMap
+ * so it isn't leaked.
+ *
+ * TODO: The ButtonExitProc doesn't currently work and the
+ * code it includes will crash the Mac on exit from Tk.
+
+ oldPixPtr = ((CWindowPeek) windowRef)->port.portPixMap;
+ Tcl_CreateExitHandler(ButtonExitProc, (ClientData) NULL);
+ */
+ }
+
+ /*
+ * Set up control in hidden window to match what we need
+ * to draw in the buffered window.
+ */
+
+ switch (butPtr->type) {
+ case TYPE_BUTTON:
+ controlHandle = buttonHandle;
+ ccTabHandle = buttonTabHandle;
+ break;
+ case TYPE_RADIO_BUTTON:
+ controlHandle = radioHandle;
+ ccTabHandle = radioTabHandle;
+ break;
+ case TYPE_CHECK_BUTTON:
+ controlHandle = checkHandle;
+ ccTabHandle = checkTabHandle;
+ break;
+ }
+ (**controlHandle).contrlRect.left = butPtr->inset;
+ (**controlHandle).contrlRect.top = butPtr->inset;
+ (**controlHandle).contrlRect.right = Tk_Width(butPtr->tkwin)
+ - butPtr->inset;
+ (**controlHandle).contrlRect.bottom = Tk_Height(butPtr->tkwin)
+ - butPtr->inset;
+ if ((**controlHandle).contrlVis != 255) {
+ (**controlHandle).contrlVis = 255;
+ }
+ if (butPtr->flags & SELECTED) {
+ (**controlHandle).contrlValue = 1;
+ } else {
+ (**controlHandle).contrlValue = 0;
+ }
+ if (butPtr->state == tkActiveUid) {
+ switch (butPtr->type) {
+ case TYPE_BUTTON:
+ (**controlHandle).contrlHilite = kControlButtonPart;
+ break;
+ case TYPE_RADIO_BUTTON:
+ (**controlHandle).contrlHilite = kControlRadioButtonPart;
+ break;
+ case TYPE_CHECK_BUTTON:
+ (**controlHandle).contrlHilite = kControlCheckBoxPart;
+ break;
+ }
+ } else if (butPtr->state == tkDisabledUid) {
+ (**controlHandle).contrlHilite = kControlInactivePart;
+ } else {
+ (**controlHandle).contrlHilite = kControlNoPart;
+ }
+
+ /*
+ * Now swap in the passed in GWorld for the portBits of our fake
+ * window. We also adjust various fields in the WindowRecord to make
+ * the system think this is a normal window.
+ */
+
+ ((CWindowPeek) windowRef)->port.portPixMap = destPort->portPixMap;
+ ((CWindowPeek) windowRef)->port.portRect = destPort->portRect;
+ RectRgn(((CWindowPeek) windowRef)->port.visRgn, &destPort->portRect);
+ RectRgn(((CWindowPeek) windowRef)->strucRgn, &destPort->portRect);
+ RectRgn(((CWindowPeek) windowRef)->updateRgn, &destPort->portRect);
+ RectRgn(((CWindowPeek) windowRef)->contRgn, &destPort->portRect);
+ PortChanged(windowRef);
+
+ /*
+ * Before we draw the control we must add the hidden window back to the
+ * main window list. Otherwise, radiobuttons and checkbuttons will draw
+ * incorrectly. I don't really know why - but clearly the control draw
+ * proc needs to have the controls window in the window list.
+ */
+
+ ((CWindowPeek) windowRef)->nextWindow = (CWindowPeek) LMGetWindowList();
+ LMSetWindowList(windowRef);
+
+ /*
+ * Now we can set the port to our doctered up window. We next need
+ * to muck with the colors for the port & window to draw the control
+ * with the proper Tk colors. If we need to we also draw a default
+ * ring for buttons.
+ */
+
+ SetPort(windowRef);
+ windowColorChanged = UpdateControlColors(butPtr, controlHandle,
+ ccTabHandle, &saveBackColor);
+ Draw1Control(controlHandle);
+ if ((butPtr->type == TYPE_BUTTON) &&
+ (butPtr->defaultState == tkActiveUid)) {
+ Rect box = (**controlHandle).contrlRect;
+ RGBColor rgbColor;
+
+ TkSetMacColor(butPtr->highlightColorPtr->pixel, &rgbColor);
+ RGBForeColor(&rgbColor);
+ PenSize(butPtr->highlightWidth - 1, butPtr->highlightWidth - 1);
+ InsetRect(&box, -butPtr->highlightWidth, -butPtr->highlightWidth);
+ FrameRoundRect(&box, 16, 16);
+ }
+ if (windowColorChanged) {
+ RGBColor dummyColor;
+ ChangeBackgroundWindowColor(windowRef, saveBackColor, &dummyColor);
+ }
+
+ /*
+ * Clean up: remove the hidden window from the main window list.
+ */
+
+ LMSetWindowList((WindowRef) ((CWindowPeek) windowRef)->nextWindow);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * UpdateControlColors --
+ *
+ * This function will review the colors used to display
+ * a Macintosh button. If any non-standard colors are
+ * used we create a custom palette for the button, populate
+ * with the colors for the button and install the palette.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Macintosh control may get a custom palette installed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+UpdateControlColors(
+ TkButton *butPtr,
+ ControlRef controlHandle,
+ CCTabHandle ccTabHandle,
+ RGBColor *saveColorPtr)
+{
+ XColor *xcolor;
+
+ xcolor = Tk_3DBorderColor(butPtr->normalBorder);
+
+ (**ccTabHandle).ccSeed = 0;
+ (**ccTabHandle).ccRider = 0;
+ (**ccTabHandle).ctSize = 3;
+ (**ccTabHandle).ctTable[0].value = cBodyColor;
+ TkSetMacColor(xcolor->pixel,
+ &(**ccTabHandle).ctTable[0].rgb);
+ (**ccTabHandle).ctTable[1].value = cTextColor;
+ TkSetMacColor(butPtr->normalFg->pixel,
+ &(**ccTabHandle).ctTable[1].rgb);
+ (**ccTabHandle).ctTable[2].value = cFrameColor;
+ TkSetMacColor(butPtr->highlightColorPtr->pixel,
+ &(**ccTabHandle).ctTable[2].rgb);
+ SetControlColor(controlHandle, ccTabHandle);
+
+ if (((xcolor->pixel >> 24) != CONTROL_BODY_PIXEL) &&
+ ((butPtr->type == TYPE_CHECK_BUTTON) ||
+ (butPtr->type == TYPE_RADIO_BUTTON))) {
+ RGBColor newColor;
+
+ TkSetMacColor(xcolor->pixel, &newColor);
+ ChangeBackgroundWindowColor((**controlHandle).contrlOwner,
+ newColor, saveColorPtr);
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ChangeBackgroundWindowColor --
+ *
+ * This procedure will change the background color entry
+ * in the Window's colortable. The system isn't notified
+ * of the change. This call should only be used to fool
+ * the drawing routines for checkboxes and radiobuttons.
+ * Any change should be temporary and be reverted after
+ * the widget is drawn.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Window's color table will be adjusted.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ChangeBackgroundWindowColor(
+ WindowRef macintoshWindow, /* A Mac window whose color to change. */
+ RGBColor rgbColor, /* The new RGB Color for the background. */
+ RGBColor *oldColor) /* The old color of the background. */
+{
+ AuxWinHandle auxWinHandle;
+ WCTabHandle winCTabHandle;
+ short ctIndex;
+ ColorSpecPtr rgbScan;
+
+ GetAuxWin(macintoshWindow, &auxWinHandle);
+ winCTabHandle = (WCTabHandle) ((**auxWinHandle).awCTable);
+
+ /*
+ * Scan through the color table until we find the content
+ * (background) color for the window. Don't tell the system
+ * about the change - it will generate damage and we will get
+ * into an infinite loop.
+ */
+
+ ctIndex = (**winCTabHandle).ctSize;
+ while (ctIndex > -1) {
+ rgbScan = ctIndex + (**winCTabHandle).ctTable;
+
+ if (rgbScan->value == wContentColor) {
+ *oldColor = rgbScan->rgb;
+ rgbScan->rgb = rgbColor;
+ break;
+ }
+ ctIndex--;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ButtonExitProc --
+ *
+ * This procedure is invoked just before the application exits.
+ * It frees all of the control handles, our dummy window, etc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ButtonExitProc(clientData)
+ ClientData clientData; /* Not used. */
+{
+ Rect pixRect = {0, 0, 10, 10};
+ Rect rgnRect = {0, 0, 0, 0};
+
+ /*
+ * Restore our dummy window to it's origional state by putting it
+ * back in the window list and restoring it's bits. The destroy
+ * the controls and window.
+ */
+
+ ((CWindowPeek) windowRef)->nextWindow = (CWindowPeek) LMGetWindowList();
+ LMSetWindowList(windowRef);
+ ((CWindowPeek) windowRef)->port.portPixMap = oldPixPtr;
+ ((CWindowPeek) windowRef)->port.portRect = pixRect;
+ RectRgn(((CWindowPeek) windowRef)->port.visRgn, &rgnRect);
+ RectRgn(((CWindowPeek) windowRef)->strucRgn, &rgnRect);
+ RectRgn(((CWindowPeek) windowRef)->updateRgn, &rgnRect);
+ RectRgn(((CWindowPeek) windowRef)->contRgn, &rgnRect);
+ PortChanged(windowRef);
+
+ DisposeControl(buttonHandle);
+ DisposeControl(checkHandle);
+ DisposeControl(radioHandle);
+ DisposeWindow(windowRef);
+ windowRef = NULL;
+}
diff --git a/mac/tkMacClipboard.c b/mac/tkMacClipboard.c
new file mode 100644
index 0000000..0c06f1d
--- /dev/null
+++ b/mac/tkMacClipboard.c
@@ -0,0 +1,293 @@
+/*
+ * tkMacClipboard.c --
+ *
+ * This file manages the clipboard for the Tk toolkit.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacClipboard.c 1.18 97/05/01 15:41:17
+ */
+
+#include "tkInt.h"
+#include "tkPort.h"
+#include "tkMacInt.h"
+
+#include <Scrap.h>
+#include <Events.h>
+
+#include "tkSelect.h"
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelGetSelection --
+ *
+ * Retrieve the specified selection from another process. For
+ * now, only fetching XA_STRING from CLIPBOARD is supported.
+ * Eventually other types should be allowed.
+ *
+ * Results:
+ * The return value is a standard Tcl return value.
+ * If an error occurs (such as no selection exists)
+ * then an error message is left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkSelGetSelection(
+ Tcl_Interp *interp, /* Interpreter to use for reporting
+ * errors. */
+ Tk_Window tkwin, /* Window on whose behalf to retrieve
+ * the selection (determines display
+ * from which to retrieve). */
+ Atom selection, /* Selection to retrieve. */
+ Atom target, /* Desired form in which selection
+ * is to be returned. */
+ Tk_GetSelProc *proc, /* Procedure to call to process the
+ * selection, once it has been retrieved. */
+ ClientData clientData) /* Arbitrary value to pass to proc. */
+{
+ int result;
+ long length, offset = 0;
+ Handle handle;
+
+ if ((selection == Tk_InternAtom(tkwin, "CLIPBOARD"))
+ && (target == XA_STRING)) {
+ /*
+ * Get the scrap from the Macintosh global clipboard.
+ */
+ handle = NewHandle(1);
+ length = GetScrap(handle, 'TEXT', &offset);
+ if (length > 0) {
+ SetHandleSize(handle, (Size) length + 1);
+ HLock(handle);
+ (*handle)[length] = '\0';
+
+ result = (*proc)(clientData, interp, *handle);
+
+ HUnlock(handle);
+ DisposeHandle(handle);
+ return result;
+ }
+
+ DisposeHandle(handle);
+ }
+
+ Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
+ " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target),
+ "\" not defined", (char *) NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetSelectionOwner --
+ *
+ * This function claims ownership of the specified selection.
+ * If the selection is CLIPBOARD, then we empty the system
+ * clipboard.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XSetSelectionOwner(
+ Display* display, /* X Display. */
+ Atom selection, /* What selection to own. */
+ Window owner, /* Window to be the owner. */
+ Time time) /* The current time? */
+{
+ Tk_Window tkwin;
+ TkDisplay *dispPtr;
+
+ /*
+ * This is a gross hack because the Tk_InternAtom interface is broken.
+ * It expects a Tk_Window, even though it only needs a Tk_Display.
+ */
+
+ tkwin = (Tk_Window)tkMainWindowList->winPtr;
+
+ if (selection == Tk_InternAtom(tkwin, "CLIPBOARD")) {
+
+ /*
+ * Only claim and empty the clipboard if we aren't already the
+ * owner of the clipboard.
+ */
+
+ dispPtr = tkMainWindowList->winPtr->dispPtr;
+ if (dispPtr->clipboardActive) {
+ return;
+ }
+ ZeroScrap();
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelUpdateClipboard --
+ *
+ * This function is called to force the clipboard to be updated
+ * after new data is added. On the Mac we don't need to do
+ * anything.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelUpdateClipboard(
+ TkWindow *winPtr, /* Window associated with clipboard. */
+ TkClipboardTarget *targetPtr) /* Info about the content. */
+{
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSelEventProc --
+ *
+ * This procedure is invoked whenever a selection-related
+ * event occurs.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Lots: depends on the type of event.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkSelEventProc(
+ Tk_Window tkwin, /* Window for which event was
+ * targeted. */
+ register XEvent *eventPtr) /* X event: either SelectionClear,
+ * SelectionRequest, or
+ * SelectionNotify. */
+{
+ if (eventPtr->type == SelectionClear) {
+ TkSelClearSelection(tkwin, eventPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelPropProc --
+ *
+ * This procedure is invoked when property-change events
+ * occur on windows not known to the toolkit. This is a stub
+ * function under Windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSelPropProc(
+ register XEvent *eventPtr) /* X PropertyChange event. */
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSuspendClipboard --
+ *
+ * Handle clipboard conversion as required by the suppend event.
+ * This function is also called on exit.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The local scrap is moved to the global scrap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSuspendClipboard()
+{
+ TkClipboardTarget *targetPtr;
+ TkClipboardBuffer *cbPtr;
+ TkDisplay *dispPtr;
+ char *buffer, *p, *endPtr, *buffPtr;
+ long length;
+
+ dispPtr = tkDisplayList;
+ if ((dispPtr == NULL) || !dispPtr->clipboardActive) {
+ return;
+ }
+
+ for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
+ targetPtr = targetPtr->nextPtr) {
+ if (targetPtr->type == XA_STRING)
+ break;
+ }
+ if (targetPtr != NULL) {
+ length = 0;
+ for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
+ cbPtr = cbPtr->nextPtr) {
+ length += cbPtr->length;
+ }
+
+ buffer = ckalloc(length);
+ buffPtr = buffer;
+ for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
+ cbPtr = cbPtr->nextPtr) {
+ for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
+ p < endPtr; p++) {
+ if (*p == '\n') {
+ *buffPtr++ = '\r';
+ } else {
+ *buffPtr++ = *p;
+ }
+ }
+ }
+
+ ZeroScrap();
+ PutScrap(length, 'TEXT', buffer);
+ ckfree(buffer);
+ }
+
+ /*
+ * The system now owns the scrap. We tell Tk that it has
+ * lost the selection so that it will look for it the next time
+ * it needs it. (Window list NULL if quiting.)
+ */
+
+ if (tkMainWindowList != NULL) {
+ Tk_ClearSelection((Tk_Window) tkMainWindowList->winPtr,
+ Tk_InternAtom((Tk_Window) tkMainWindowList->winPtr,
+ "CLIPBOARD"));
+ }
+
+ return;
+}
diff --git a/mac/tkMacColor.c b/mac/tkMacColor.c
new file mode 100644
index 0000000..56fe38d
--- /dev/null
+++ b/mac/tkMacColor.c
@@ -0,0 +1,485 @@
+/*
+ * tkMacColor.c --
+ *
+ * This file maintains a database of color values for the Tk
+ * toolkit, in order to avoid round-trips to the server to
+ * map color names to pixel values.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacColor.c 1.36 96/11/25 11:02:12
+ */
+
+#include <tkColor.h>
+#include "tkMacInt.h"
+
+#include <LowMem.h>
+#include <Palettes.h>
+#include <Quickdraw.h>
+
+/*
+ * Default Auxillary Control Record for all controls. This is cached once
+ * and is updated by the system. We use this to get the default system
+ * colors used by controls.
+ */
+static AuxCtlHandle defaultAuxCtlHandle = NULL;
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int GetControlPartColor _ANSI_ARGS_((short part, RGBColor *macColor));
+static int GetMenuPartColor _ANSI_ARGS_((int part, RGBColor *macColor));
+static int GetWindowPartColor _ANSI_ARGS_((short part, RGBColor *macColor));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetMacColor --
+ *
+ * Populates a Macintosh RGBColor structure from a X style
+ * pixel value.
+ *
+ * Results:
+ * Returns false if not a real pixel, true otherwise.
+ *
+ * Side effects:
+ * The variable macColor is updated to the pixels value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkSetMacColor(
+ unsigned long pixel, /* Pixel value to convert. */
+ RGBColor *macColor) /* Mac color struct to modify. */
+{
+ switch (pixel >> 24) {
+ case HIGHLIGHT_PIXEL:
+ LMGetHiliteRGB(macColor);
+ return true;
+ case HIGHLIGHT_TEXT_PIXEL:
+ LMGetHiliteRGB(macColor);
+ if ((macColor->red == 0) && (macColor->green == 0)
+ && (macColor->blue == 0)) {
+ macColor->red = macColor->green = macColor->blue = 0xFFFFFFFF;
+ } else {
+ macColor->red = macColor->green = macColor->blue = 0;
+ }
+ return true;
+ case CONTROL_TEXT_PIXEL:
+ GetControlPartColor(cTextColor, macColor);
+ return true;
+ case CONTROL_BODY_PIXEL:
+ GetControlPartColor(cBodyColor, macColor);
+ return true;
+ case CONTROL_FRAME_PIXEL:
+ GetControlPartColor(cFrameColor, macColor);
+ return true;
+ case WINDOW_BODY_PIXEL:
+ GetWindowPartColor(wContentColor, macColor);
+ return true;
+ case MENU_ACTIVE_PIXEL:
+ case MENU_ACTIVE_TEXT_PIXEL:
+ case MENU_BACKGROUND_PIXEL:
+ case MENU_DISABLED_PIXEL:
+ case MENU_TEXT_PIXEL:
+ GetMenuPartColor((pixel >> 24), macColor);
+ return true;
+ case PIXEL_MAGIC:
+ default:
+ macColor->blue = (unsigned short) ((pixel & 0xFF) << 8);
+ macColor->green = (unsigned short) (((pixel >> 8) & 0xFF) << 8);
+ macColor->red = (unsigned short) (((pixel >> 16) & 0xFF) << 8);
+ return true;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Stub functions --
+ *
+ * These functions are just stubs for functions that either
+ * don't make sense on the Mac or have yet to be implemented.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * These calls do nothing - which may not be expected.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Status
+XAllocColor(
+ Display *display, /* Display. */
+ Colormap map, /* Not used. */
+ XColor *colorPtr) /* XColor struct to modify. */
+{
+ display->request++;
+ colorPtr->pixel = TkpGetPixel(colorPtr);
+ return 1;
+}
+
+Colormap
+XCreateColormap(
+ Display *display, /* Display. */
+ Window window, /* X window. */
+ Visual *visual, /* Not used. */
+ int alloc) /* Not used. */
+{
+ static Colormap index = 1;
+
+ /*
+ * Just return a new value each time.
+ */
+ return index++;
+}
+
+void
+XFreeColormap(
+ Display* display, /* Display. */
+ Colormap colormap) /* Colormap. */
+{
+}
+
+void
+XFreeColors(
+ Display* display, /* Display. */
+ Colormap colormap, /* Colormap. */
+ unsigned long* pixels, /* Array of pixels. */
+ int npixels, /* Number of pixels. */
+ unsigned long planes) /* Number of pixel planes. */
+{
+ /*
+ * The Macintosh version of Tk uses TrueColor. Nothing
+ * needs to be done to release colors as there really is
+ * no colormap in the Tk sense.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetColor --
+ *
+ * Allocate a new TkColor for the color with the given name.
+ *
+ * Results:
+ * Returns a newly allocated TkColor, or NULL on failure.
+ *
+ * Side effects:
+ * May invalidate the colormap cache associated with tkwin upon
+ * allocating a new colormap entry. Allocates a new TkColor
+ * structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkColor *
+TkpGetColor(
+ Tk_Window tkwin, /* Window in which color will be used. */
+ Tk_Uid name) /* Name of color to allocated (in form
+ * suitable for passing to XParseColor). */
+{
+ Display *display = Tk_Display(tkwin);
+ Colormap colormap = Tk_Colormap(tkwin);
+ TkColor *tkColPtr;
+ XColor color;
+
+ /*
+ * Check to see if this is a system color. Otherwise, XParseColor
+ * will do all the work.
+ */
+ if (strncasecmp(name, "system", 6) == 0) {
+ int foundSystemColor = false;
+ RGBColor rgbValue;
+ char pixelCode;
+
+ if (!strcasecmp(name+6, "Highlight")) {
+ LMGetHiliteRGB(&rgbValue);
+ pixelCode = HIGHLIGHT_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "HighlightText")) {
+ LMGetHiliteRGB(&rgbValue);
+ if ((rgbValue.red == 0) && (rgbValue.green == 0)
+ && (rgbValue.blue == 0)) {
+ rgbValue.red = rgbValue.green = rgbValue.blue = 0xFFFFFFFF;
+ } else {
+ rgbValue.red = rgbValue.green = rgbValue.blue = 0;
+ }
+ pixelCode = HIGHLIGHT_TEXT_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "ButtonText")) {
+ GetControlPartColor(cTextColor, &rgbValue);
+ pixelCode = CONTROL_TEXT_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "ButtonFace")) {
+ GetControlPartColor(cBodyColor, &rgbValue);
+ pixelCode = CONTROL_BODY_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "ButtonFrame")) {
+ GetControlPartColor(cFrameColor, &rgbValue);
+ pixelCode = CONTROL_FRAME_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "WindowBody")) {
+ GetWindowPartColor(wContentColor, &rgbValue);
+ pixelCode = WINDOW_BODY_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "MenuActive")) {
+ GetMenuPartColor(MENU_ACTIVE_PIXEL, &rgbValue);
+ pixelCode = MENU_ACTIVE_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "MenuActiveText")) {
+ GetMenuPartColor(MENU_ACTIVE_TEXT_PIXEL, &rgbValue);
+ pixelCode = MENU_ACTIVE_TEXT_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "Menu")) {
+ GetMenuPartColor(MENU_BACKGROUND_PIXEL, &rgbValue);
+ pixelCode = MENU_BACKGROUND_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "MenuDisabled")) {
+ GetMenuPartColor(MENU_DISABLED_PIXEL, &rgbValue);
+ pixelCode = MENU_DISABLED_PIXEL;
+ foundSystemColor = true;
+ } else if (!strcasecmp(name+6, "MenuText")) {
+ GetMenuPartColor(MENU_TEXT_PIXEL, &rgbValue);
+ pixelCode = MENU_TEXT_PIXEL;
+ foundSystemColor = true;
+ }
+
+ if (foundSystemColor) {
+ color.red = rgbValue.red;
+ color.green = rgbValue.green;
+ color.blue = rgbValue.blue;
+ color.pixel = ((((((pixelCode << 8)
+ | ((color.red >> 8) & 0xff)) << 8)
+ | ((color.green >> 8) & 0xff)) << 8)
+ | ((color.blue >> 8) & 0xff));
+
+ tkColPtr = (TkColor *) ckalloc(sizeof(TkColor));
+ tkColPtr->color = color;
+ return tkColPtr;
+ }
+ }
+
+ if (XParseColor(display, colormap, name, &color) == 0) {
+ return (TkColor *) NULL;
+ }
+
+ tkColPtr = (TkColor *) ckalloc(sizeof(TkColor));
+ tkColPtr->color = color;
+
+ return tkColPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetColorByValue --
+ *
+ * Given a desired set of red-green-blue intensities for a color,
+ * locate a pixel value to use to draw that color in a given
+ * window.
+ *
+ * Results:
+ * The return value is a pointer to an TkColor structure that
+ * indicates the closest red, blue, and green intensities available
+ * to those specified in colorPtr, and also specifies a pixel
+ * value to use to draw in that color.
+ *
+ * Side effects:
+ * May invalidate the colormap cache for the specified window.
+ * Allocates a new TkColor structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkColor *
+TkpGetColorByValue(
+ Tk_Window tkwin, /* Window in which color will be used. */
+ XColor *colorPtr) /* Red, green, and blue fields indicate
+ * desired color. */
+{
+ TkColor *tkColPtr = (TkColor *) ckalloc(sizeof(TkColor));
+
+ tkColPtr->color.red = colorPtr->red;
+ tkColPtr->color.green = colorPtr->green;
+ tkColPtr->color.blue = colorPtr->blue;
+ tkColPtr->color.pixel = TkpGetPixel(&tkColPtr->color);
+ return tkColPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetControlPartColor --
+ *
+ * Given a part number this function will return the standard
+ * system default color for that part. It does this by looking
+ * in the system's 'cctb' resource.
+ *
+ * Results:
+ * True if a color is found, false otherwise.
+ *
+ * Side effects:
+ * If a color is found then the RGB variable will be changed to
+ * the parts color.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetControlPartColor(
+ short part, /* Part code. */
+ RGBColor *macColor) /* Pointer to Mac color. */
+{
+ short index;
+ CCTabHandle ccTab;
+
+ if (defaultAuxCtlHandle == NULL) {
+ GetAuxiliaryControlRecord(NULL, &defaultAuxCtlHandle);
+ }
+ ccTab = (**defaultAuxCtlHandle).acCTable;
+ if(ccTab && (ResError() == noErr)) {
+ for(index = 0; index <= (**ccTab).ctSize; index++) {
+ if((**ccTab).ctTable[index].value == part) {
+ *macColor = (**ccTab).ctTable[index].rgb;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetWindowPartColor --
+ *
+ * Given a part number this function will return the standard
+ * system default color for that part. It does this by looking
+ * in the system's 'wctb' resource.
+ *
+ * Results:
+ * True if a color is found, false otherwise.
+ *
+ * Side effects:
+ * If a color is found then the RGB variable will be changed to
+ * the parts color.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetWindowPartColor(
+ short part, /* Part code. */
+ RGBColor *macColor) /* Pointer to Mac color. */
+{
+ short index;
+ WCTabHandle wcTab;
+
+ wcTab = (WCTabHandle) GetResource('wctb', 0);
+ if(wcTab && (ResError() == noErr)) {
+ for(index = 0; index <= (**wcTab).ctSize; index++) {
+ if((**wcTab).ctTable[index].value == part) {
+ *macColor = (**wcTab).ctTable[index].rgb;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMenuPartColor --
+ *
+ * Given a magic pixel value, returns the RGB color associated
+ * with it by looking the value up in the system's 'mctb' resource.
+ *
+ * Results:
+ * True if a color is found, false otherwise.
+ *
+ * Side effects:
+ * If a color is found then the RGB variable will be changed to
+ * the parts color.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetMenuPartColor(
+ int pixel, /* The magic pixel value */
+ RGBColor *macColor) /* Pointer to Mac color */
+{
+ RGBColor backColor, foreColor;
+ GDHandle maxDevice;
+ Rect globalRect;
+ MCEntryPtr mcEntryPtr = GetMCEntry(0, 0);
+
+ switch (pixel) {
+ case MENU_ACTIVE_PIXEL:
+ if (mcEntryPtr == NULL) {
+ macColor->red = macColor->blue = macColor->green = 0;
+ } else {
+ *macColor = mcEntryPtr->mctRGB3;
+ }
+ return 1;
+ case MENU_ACTIVE_TEXT_PIXEL:
+ if (mcEntryPtr == NULL) {
+ macColor->red = macColor->blue = macColor->green = 0xFFFF;
+ } else {
+ *macColor = mcEntryPtr->mctRGB2;
+ }
+ return 1;
+ case MENU_BACKGROUND_PIXEL:
+ if (mcEntryPtr == NULL) {
+ macColor->red = macColor->blue = macColor->green = 0xFFFF;
+ } else {
+ *macColor = mcEntryPtr->mctRGB2;
+ }
+ return 1;
+ case MENU_DISABLED_PIXEL:
+ if (mcEntryPtr == NULL) {
+ backColor.red = backColor.blue = backColor.green = 0xFFFF;
+ foreColor.red = foreColor.blue = foreColor.green = 0x0000;
+ } else {
+ backColor = mcEntryPtr->mctRGB2;
+ foreColor = mcEntryPtr->mctRGB3;
+ }
+ SetRect(&globalRect, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
+ maxDevice = GetMaxDevice(&globalRect);
+ if (GetGray(maxDevice, &backColor, &foreColor)) {
+ *macColor = foreColor;
+ } else {
+
+ /*
+ * Pointer may have been moved by GetMaxDevice or GetGray.
+ */
+
+ mcEntryPtr = GetMCEntry(0,0);
+ if (mcEntryPtr == NULL) {
+ macColor->red = macColor->green = macColor->blue = 0x7777;
+ } else {
+ *macColor = mcEntryPtr->mctRGB2;
+ }
+ }
+ return 1;
+ case MENU_TEXT_PIXEL:
+ if (mcEntryPtr == NULL) {
+ macColor->red = macColor->green = macColor->blue = 0;
+ } else {
+ *macColor = mcEntryPtr->mctRGB3;
+ }
+ return 1;
+ }
+ return 0;
+}
diff --git a/mac/tkMacCursor.c b/mac/tkMacCursor.c
new file mode 100644
index 0000000..f221189
--- /dev/null
+++ b/mac/tkMacCursor.c
@@ -0,0 +1,360 @@
+/*
+ * tkMacCursor.c --
+ *
+ * This file contains Macintosh specific cursor related routines.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacCursor.c 1.20 97/09/17 19:33:13
+ */
+
+#include "tkPort.h"
+#include "tkInt.h"
+#include "tkMacInt.h"
+
+#include <Resources.h>
+#include <ToolUtils.h>
+#include <Strings.h>
+
+/*
+ * There are three different ways to set the cursor on the Mac.
+ */
+#define ARROW 0 /* The arrow cursor. */
+#define COLOR 1 /* Cursors of type crsr. */
+#define NORMAL 2 /* Cursors of type CURS. */
+
+/*
+ * The following data structure contains the system specific data
+ * necessary to control Windows cursors.
+ */
+
+typedef struct {
+ TkCursor info; /* Generic cursor info used by tkCursor.c */
+ Handle macCursor; /* Resource containing Macintosh cursor. */
+ int type; /* Type of Mac cursor: arrow, crsr, CURS */
+} TkMacCursor;
+
+/*
+ * The table below is used to map from the name of a predefined cursor
+ * to its resource identifier.
+ */
+
+static struct CursorName {
+ char *name;
+ int id;
+} cursorNames[] = {
+ {"ibeam", 1},
+ {"text", 1},
+ {"xterm", 1},
+ {"cross", 2},
+ {"crosshair", 2},
+ {"cross-hair", 2},
+ {"plus", 3},
+ {"watch", 4},
+ {"arrow", 5},
+ {NULL, 0}
+};
+
+/*
+ * Declarations of static variables used in this file.
+ */
+
+static TkMacCursor * gCurrentCursor = NULL; /* A pointer to the current
+ * cursor. */
+static int gResizeOverride = false; /* A boolean indicating wether
+ * we should use the resize
+ * cursor during installations. */
+
+/*
+ * Declarations of procedures local to this file
+ */
+
+static void FindCursorByName _ANSI_ARGS_ ((TkMacCursor *macCursorPtr,
+ char *string));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindCursorByName --
+ *
+ * Retrieve a system cursor by name, and fill the macCursorPtr
+ * structure. If the cursor cannot be found, the macCursor field
+ * will be NULL. The function first attempts to load a color
+ * cursor. If that fails it will attempt to load a black & white
+ * cursor.
+ *
+ * Results:
+ * Fills the macCursorPtr record.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+FindCursorByName(
+ TkMacCursor *macCursorPtr,
+ char *string)
+{
+ Handle resource;
+ Str255 curName;
+
+ curName[0] = strlen(string);
+ if (curName[0] > 255) {
+ return;
+ }
+
+ strcpy((char *) curName + 1, string);
+ resource = GetNamedResource('crsr', curName);
+
+ if (resource != NULL) {
+ short id;
+ Str255 theName;
+ ResType theType;
+
+ HLock(resource);
+ GetResInfo(resource, &id, &theType, theName);
+ HUnlock(resource);
+ macCursorPtr->macCursor = (Handle) GetCCursor(id);
+ macCursorPtr->type = COLOR;
+ }
+
+ if (resource == NULL) {
+ macCursorPtr->macCursor = GetNamedResource('CURS', curName);
+ macCursorPtr->type = NORMAL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetCursorByName --
+ *
+ * Retrieve a system cursor by name.
+ *
+ * Results:
+ * Returns a new cursor, or NULL on errors.
+ *
+ * Side effects:
+ * Allocates a new cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkCursor *
+TkGetCursorByName(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ Tk_Window tkwin, /* Window in which cursor will be used. */
+ Tk_Uid string) /* Description of cursor. See manual entry
+ * for details on legal syntax. */
+{
+ struct CursorName *namePtr;
+ TkMacCursor *macCursorPtr;
+
+ macCursorPtr = (TkMacCursor *) ckalloc(sizeof(TkMacCursor));
+ macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr;
+
+ /*
+ * To find a cursor we must first determine if it is one of the
+ * builtin cursors or the standard arrow cursor. Otherwise, we
+ * attempt to load the cursor as a named Mac resource.
+ */
+
+ for (namePtr = cursorNames; namePtr->name != NULL; namePtr++) {
+ if (strcmp(namePtr->name, string) == 0) {
+ break;
+ }
+ }
+
+
+ if (namePtr->name != NULL) {
+ if (namePtr->id == 5) {
+ macCursorPtr->macCursor = (Handle) -1;
+ macCursorPtr->type = ARROW;
+ } else {
+ macCursorPtr->macCursor = (Handle) GetCursor(namePtr->id);
+ macCursorPtr->type = NORMAL;
+ }
+ } else {
+ FindCursorByName(macCursorPtr, string);
+
+ if (macCursorPtr->macCursor == NULL) {
+ char **argv;
+ int argc, err;
+
+ /*
+ * The user may be trying to specify an XCursor with fore
+ * & back colors. We don't want this to be an error, so pick
+ * off the first word, and try again.
+ */
+
+ err = Tcl_SplitList(interp, string, &argc, &argv);
+ if (err == TCL_OK ) {
+ if (argc > 1) {
+ FindCursorByName(macCursorPtr, argv[0]);
+ }
+
+ ckfree((char *) argv);
+ }
+ }
+ }
+
+ if (macCursorPtr->macCursor == NULL) {
+ ckfree((char *)macCursorPtr);
+ Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"",
+ (char *) NULL);
+ return NULL;
+ } else {
+ return (TkCursor *) macCursorPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCreateCursorFromData --
+ *
+ * Creates a cursor from the source and mask bits.
+ *
+ * Results:
+ * Returns a new cursor, or NULL on errors.
+ *
+ * Side effects:
+ * Allocates a new cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkCursor *
+TkCreateCursorFromData(
+ Tk_Window tkwin, /* Window in which cursor will be used. */
+ char *source, /* Bitmap data for cursor shape. */
+ char *mask, /* Bitmap data for cursor mask. */
+ int width, int height, /* Dimensions of cursor. */
+ int xHot, int yHot, /* Location of hot-spot in cursor. */
+ XColor fgColor, /* Foreground color for cursor. */
+ XColor bgColor) /* Background color for cursor. */
+{
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFreeCursor --
+ *
+ * This procedure is called to release a cursor allocated by
+ * TkGetCursorByName.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor data structure is deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFreeCursor(
+ TkCursor *cursorPtr)
+{
+ TkMacCursor *macCursorPtr = (TkMacCursor *) cursorPtr;
+
+ switch (macCursorPtr->type) {
+ case COLOR:
+ DisposeCCursor((CCrsrHandle) macCursorPtr->macCursor);
+ break;
+ case NORMAL:
+ ReleaseResource(macCursorPtr->macCursor);
+ break;
+ }
+
+ if (macCursorPtr == gCurrentCursor) {
+ gCurrentCursor = NULL;
+ }
+
+ ckfree((char *) macCursorPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacInstallCursor --
+ *
+ * Installs either the current cursor as defined by TkpSetCursor
+ * or a resize cursor as the cursor the Macintosh should currently
+ * display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the Macintosh mouse cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacInstallCursor(
+ int resizeOverride)
+{
+ TkMacCursor *macCursorPtr = gCurrentCursor;
+ CCrsrHandle ccursor;
+ CursHandle cursor;
+
+ gResizeOverride = resizeOverride;
+
+ if (resizeOverride) {
+ cursor = (CursHandle) GetNamedResource('CURS', "\presize");
+ SetCursor(*cursor);
+ } else if (macCursorPtr == NULL || macCursorPtr->type == ARROW) {
+ SetCursor(&tcl_macQdPtr->arrow);
+ } else {
+ switch (macCursorPtr->type) {
+ case COLOR:
+ ccursor = (CCrsrHandle) macCursorPtr->macCursor;
+ SetCCursor(ccursor);
+ break;
+ case NORMAL:
+ cursor = (CursHandle) macCursorPtr->macCursor;
+ SetCursor(*cursor);
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetCursor --
+ *
+ * Set the current cursor and install it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the current cursor.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetCursor(
+ TkpCursor cursor)
+{
+ if (cursor == None) {
+ gCurrentCursor = NULL;
+ } else {
+ gCurrentCursor = (TkMacCursor *) cursor;
+ }
+
+ if (tkMacAppInFront) {
+ TkMacInstallCursor(gResizeOverride);
+ }
+}
diff --git a/mac/tkMacCursors.r b/mac/tkMacCursors.r
new file mode 100644
index 0000000..44ad02e
--- /dev/null
+++ b/mac/tkMacCursors.r
@@ -0,0 +1,130 @@
+/*
+ * tkMacCursors.r --
+ *
+ * This file defines a set of Macintosh cursor resources that
+ * are only available on the Macintosh platform.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacCursors.r 1.3 96/01/25 10:24:15
+ */
+
+/*
+ * These are resource definitions for Macintosh cursors.
+ * The are identified and loaded by the "name" of the
+ * cursor. However, the ids must be unique.
+ */
+
+data 'CURS' (1000, "hand") {
+ $"0180 1A70 2648 264A 124D 1249 6809 9801"
+ $"8802 4002 2002 2004 1004 0808 0408 0408"
+ $"0180 1BF0 3FF8 3FFA 1FFF 1FFF 6FFF FFFF"
+ $"FFFE 7FFE 3FFE 3FFC 1FFC 0FF8 07F8 07F8"
+ $"0009 0008"
+};
+
+data 'CURS' (1002, "bucket") {
+ $"0000 0000 0600 0980 0940 0B30 0D18 090C"
+ $"129C 212C 104C 088C 050C 0208 0000 0000"
+ $"0000 0000 0600 0980 09C0 0BF0 0FF8 0FFC"
+ $"1FFC 3FEC 1FCC 0F8C 070C 0208 0000 0000"
+ $"000D 000C"
+};
+
+data 'CURS' (1003, "cancel") {
+ $"0000 0000 0000 0000 3180 4A40 4A40 3F80"
+ $"0A00 3F80 4A40 4A46 3186 0000 0000 0000"
+ $"0000 0000 0000 3180 7BC0 FFE0 FFE0 7FC0"
+ $"3F80 7FC0 FFE6 FFEF 7BCF 3186 0000 0000"
+ $"0008 0005"
+};
+
+data 'CURS' (1004, "Resize") {
+ $"FFFF 8001 BF01 A181 A1F9 A18D A18D BF8D"
+ $"9F8D 880D 880D 880D 8FFD 87FD 8001 FFFF"
+ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
+ $"0008 0008"
+};
+
+data 'CURS' (1005, "eyedrop") {
+ $"000E 001F 001F 00FF 007E 00B8 0118 0228"
+ $"0440 0880 1100 2200 4400 4800 B000 4000"
+ $"000E 001F 001F 00FF 007E 00F8 01F8 03E8"
+ $"07C0 0F80 1F00 3E00 7C00 7800 F000 4000"
+ $"000F 0000"
+};
+
+data 'CURS' (1006, "eyedrop-full") {
+ $"000E 001F 001F 00FF 007E 00B8 0118 0328"
+ $"07C0 0F80 1F00 3E00 7C00 7800 F000 4000"
+ $"000E 001F 001F 00FF 007E 00F8 01F8 03E8"
+ $"07C0 0F80 1F00 3E00 7C00 7800 F000 4000"
+ $"000F 0000"
+};
+
+data 'CURS' (1007, "zoom-in") {
+ $"0780 1860 2790 5868 5028 A014 AFD4 AFD4"
+ $"A014 5028 5868 2798 187C 078E 0007 0003"
+ $"0780 1FE0 3FF0 7878 7038 E01C EFDC EFDC"
+ $"E01C 7038 7878 3FF8 1FFC 078E 0007 0003"
+ $"0007 0007"
+};
+
+data 'CURS' (1008, "zoom-out") {
+ $"0780 1860 2790 5868 5328 A314 AFD4 AFD4"
+ $"A314 5328 5868 2798 187C 078E 0007 0003"
+ $"0780 1FE0 3FF0 7878 7338 E31C EFDC EFDC"
+ $"E31C 7338 7878 3FF8 1FFC 078E 0007 0003"
+ $"0007 0007"
+};
+
+/*
+ * The following are resource definitions for color
+ * cursors on the Macintosh. If a color cursor and
+ * a black & white cursor are both defined with the
+ * same name preference will be given to the color
+ * cursors.
+ */
+
+data 'crsr' (1000, "hand") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0180 1A70 2648 264A 124D 1249"
+ $"6809 9801 8802 4002 2002 2004 1004 0808"
+ $"0408 0408 0180 1BF0 3FF8 3FFA 1FFF 1FFF"
+ $"6FFF FFFF FFFE 7FFE 3FFE 3FFC 1FFC 0FF8"
+ $"07F8 07F8 0008 0008 0000 0000 0000 0000"
+ $"0000 0000 8004 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0002 0001 0002 0000 0000 0000 00D2 0000"
+ $"0000 0003 C000 03CD 7F00 0D7D 75C0 0D7D"
+ $"75CC 035D 75F7 035D 75D7 3CD5 55D7 D7D5"
+ $"5557 D5D5 555C 3555 555C 0D55 555C 0D55"
+ $"5570 0355 5570 00D5 55C0 0035 55C0 0035"
+ $"55C0 0000 0000 0000 0002 0000 FFFF FFFF"
+ $"FFFF 0001 FFFF CCCC 9999 0003 0000 0000"
+ $"0000"
+};
+
+data 'crsr' (1001, "fist") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0DB0 124C"
+ $"100A 0802 1802 2002 2002 2004 1004 0808"
+ $"0408 0408 0000 0000 0000 0000 0DB0 1FFC"
+ $"1FFE 0FFE 1FFE 3FFE 3FFE 3FFC 1FFC 0FF8"
+ $"07F8 07F8 0008 0008 0000 0000 0000 0000"
+ $"0000 0000 8004 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0002 0001 0002 0000 0000 0000 00D2 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 00F3 CF00 035D 75F0 0355 55DC 00D5"
+ $"555C 03D5 555C 0D55 555C 0D55 555C 0D55"
+ $"5570 0355 5570 00D5 55C0 0035 55C0 0035"
+ $"55C0 0000 0000 0000 0002 0000 FFFF FFFF"
+ $"FFFF 0001 FFFF CCCC 9999 0003 0000 0000"
+ $"0000"
+};
+
diff --git a/mac/tkMacDefault.h b/mac/tkMacDefault.h
new file mode 100644
index 0000000..372d89b
--- /dev/null
+++ b/mac/tkMacDefault.h
@@ -0,0 +1,461 @@
+/*
+ * tkMacDefault.h --
+ *
+ * This file defines the defaults for all options for all of
+ * the Tk widgets.
+ *
+ * Copyright (c) 1991-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacDefault.h 1.48 97/10/09 17:45:04
+ */
+
+#ifndef _TKMACDEFAULT
+#define _TKMACDEFAULT
+
+/*
+ * The definitions below provide symbolic names for the default colors.
+ * NORMAL_BG - Normal background color.
+ * ACTIVE_BG - Background color when widget is active.
+ * SELECT_BG - Background color for selected text.
+ * SELECT_FG - Foreground color for selected text.
+ * TROUGH - Background color for troughs in scales and scrollbars.
+ * INDICATOR - Color for indicator when button is selected.
+ * DISABLED - Foreground color when widget is disabled.
+ */
+
+#define BLACK "Black"
+#define WHITE "White"
+
+#define NORMAL_BG "systemWindowBody"
+#define ACTIVE_BG "#ececec"
+#define SELECT_BG "systemHighlight"
+#define SELECT_FG "systemHighlightText"
+#define TROUGH "#c3c3c3"
+#define INDICATOR "#b03060"
+#define DISABLED "#a3a3a3"
+
+/*
+ * Defaults for labels, buttons, checkbuttons, and radiobuttons:
+ */
+
+#define DEF_BUTTON_ANCHOR "center"
+#define DEF_BUTTON_ACTIVE_BG_COLOR "systemButtonText"
+#define DEF_BUTTON_ACTIVE_BG_MONO BLACK
+#define DEF_BUTTON_ACTIVE_FG_COLOR "systemButtonFace"
+#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR
+#define DEF_BUTTON_ACTIVE_FG_MONO WHITE
+#define DEF_BUTTON_BG_COLOR "systemButtonFace"
+#define DEF_BUTTON_BG_MONO WHITE
+#define DEF_BUTTON_BITMAP ""
+#define DEF_BUTTON_BORDER_WIDTH "2"
+#define DEF_BUTTON_CURSOR ""
+#define DEF_BUTTON_COMMAND ""
+#define DEF_BUTTON_DEFAULT "disabled"
+#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED
+#define DEF_BUTTON_DISABLED_FG_MONO ""
+#define DEF_BUTTON_FG "systemButtonText"
+#define DEF_CHKRAD_FG DEF_BUTTON_FG
+#define DEF_BUTTON_FONT "system"
+#define DEF_BUTTON_HEIGHT "0"
+#define DEF_BUTTON_HIGHLIGHT_BG NORMAL_BG
+#define DEF_BUTTON_HIGHLIGHT "systemButtonFrame"
+#define DEF_LABEL_HIGHLIGHT_WIDTH "0"
+#define DEF_BUTTON_HIGHLIGHT_WIDTH "4"
+#define DEF_BUTTON_IMAGE (char *) NULL
+#define DEF_BUTTON_INDICATOR "1"
+#define DEF_BUTTON_JUSTIFY "center"
+#define DEF_BUTTON_OFF_VALUE "0"
+#define DEF_BUTTON_ON_VALUE "1"
+#define DEF_BUTTON_PADX "7"
+#define DEF_LABCHKRAD_PADX "1"
+#define DEF_BUTTON_PADY "3"
+#define DEF_LABCHKRAD_PADY "1"
+#define DEF_BUTTON_RELIEF "flat"
+#define DEF_LABCHKRAD_RELIEF "flat"
+#define DEF_BUTTON_SELECT_COLOR INDICATOR
+#define DEF_BUTTON_SELECT_MONO BLACK
+#define DEF_BUTTON_SELECT_IMAGE (char *) NULL
+#define DEF_BUTTON_STATE "normal"
+#define DEF_LABEL_TAKE_FOCUS "0"
+#define DEF_BUTTON_TAKE_FOCUS (char *) NULL
+#define DEF_BUTTON_TEXT ""
+#define DEF_BUTTON_TEXT_VARIABLE ""
+#define DEF_BUTTON_UNDERLINE "-1"
+#define DEF_BUTTON_VALUE ""
+#define DEF_BUTTON_WIDTH "0"
+#define DEF_BUTTON_WRAP_LENGTH "0"
+#define DEF_RADIOBUTTON_VARIABLE "selectedButton"
+#define DEF_CHECKBUTTON_VARIABLE ""
+
+/*
+ * Defaults for canvases:
+ */
+
+#define DEF_CANVAS_BG_COLOR NORMAL_BG
+#define DEF_CANVAS_BG_MONO WHITE
+#define DEF_CANVAS_BORDER_WIDTH "0"
+#define DEF_CANVAS_CLOSE_ENOUGH "1"
+#define DEF_CANVAS_CONFINE "1"
+#define DEF_CANVAS_CURSOR ""
+#define DEF_CANVAS_HEIGHT "7c"
+#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG
+#define DEF_CANVAS_HIGHLIGHT BLACK
+#define DEF_CANVAS_HIGHLIGHT_WIDTH "3"
+#define DEF_CANVAS_INSERT_BG BLACK
+#define DEF_CANVAS_INSERT_BD_COLOR "0"
+#define DEF_CANVAS_INSERT_BD_MONO "0"
+#define DEF_CANVAS_INSERT_OFF_TIME "300"
+#define DEF_CANVAS_INSERT_ON_TIME "600"
+#define DEF_CANVAS_INSERT_WIDTH "2"
+#define DEF_CANVAS_RELIEF "flat"
+#define DEF_CANVAS_SCROLL_REGION ""
+#define DEF_CANVAS_SELECT_COLOR SELECT_BG
+#define DEF_CANVAS_SELECT_MONO BLACK
+#define DEF_CANVAS_SELECT_BD_COLOR "1"
+#define DEF_CANVAS_SELECT_BD_MONO "0"
+#define DEF_CANVAS_SELECT_FG_COLOR BLACK
+#define DEF_CANVAS_SELECT_FG_MONO WHITE
+#define DEF_CANVAS_TAKE_FOCUS (char *) NULL
+#define DEF_CANVAS_WIDTH "10c"
+#define DEF_CANVAS_X_SCROLL_CMD ""
+#define DEF_CANVAS_X_SCROLL_INCREMENT "0"
+#define DEF_CANVAS_Y_SCROLL_CMD ""
+#define DEF_CANVAS_Y_SCROLL_INCREMENT "0"
+
+/*
+ * Defaults for entries:
+ */
+
+#define DEF_ENTRY_BG_COLOR NORMAL_BG
+#define DEF_ENTRY_BG_MONO WHITE
+/* #define DEF_ENTRY_BORDER_WIDTH "2" */
+#define DEF_ENTRY_BORDER_WIDTH "1"
+#define DEF_ENTRY_CURSOR "xterm"
+#define DEF_ENTRY_EXPORT_SELECTION "1"
+#define DEF_ENTRY_FONT "Helvetica 12"
+#define DEF_ENTRY_FG BLACK
+#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG
+#define DEF_ENTRY_HIGHLIGHT BLACK
+/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */
+#define DEF_ENTRY_HIGHLIGHT_WIDTH "0"
+#define DEF_ENTRY_INSERT_BG BLACK
+#define DEF_ENTRY_INSERT_BD_COLOR "0"
+#define DEF_ENTRY_INSERT_BD_MONO "0"
+#define DEF_ENTRY_INSERT_OFF_TIME "300"
+#define DEF_ENTRY_INSERT_ON_TIME "600"
+/* #define DEF_ENTRY_INSERT_WIDTH "2" */
+#define DEF_ENTRY_INSERT_WIDTH "1"
+#define DEF_ENTRY_JUSTIFY "left"
+/* #define DEF_ENTRY_RELIEF "sunken" */
+#define DEF_ENTRY_RELIEF "solid"
+#define DEF_ENTRY_SCROLL_COMMAND ""
+#define DEF_ENTRY_SELECT_COLOR SELECT_BG
+#define DEF_ENTRY_SELECT_MONO BLACK
+#define DEF_ENTRY_SELECT_BD_COLOR "1"
+#define DEF_ENTRY_SELECT_BD_MONO "0"
+#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG
+#define DEF_ENTRY_SELECT_FG_MONO WHITE
+#define DEF_ENTRY_SHOW (char *) NULL
+#define DEF_ENTRY_STATE "normal"
+#define DEF_ENTRY_TAKE_FOCUS (char *) NULL
+#define DEF_ENTRY_TEXT_VARIABLE ""
+#define DEF_ENTRY_WIDTH "20"
+
+/*
+ * Defaults for frames:
+ */
+
+#define DEF_FRAME_BG_COLOR NORMAL_BG
+#define DEF_FRAME_BG_MONO WHITE
+#define DEF_FRAME_BORDER_WIDTH "0"
+#define DEF_FRAME_CLASS "Frame"
+#define DEF_FRAME_COLORMAP ""
+#define DEF_FRAME_CONTAINER "0"
+#define DEF_FRAME_CURSOR ""
+#define DEF_FRAME_HEIGHT "0"
+#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG
+#define DEF_FRAME_HIGHLIGHT BLACK
+#define DEF_FRAME_HIGHLIGHT_WIDTH "0"
+#define DEF_FRAME_RELIEF "flat"
+#define DEF_FRAME_TAKE_FOCUS "0"
+#define DEF_FRAME_USE ""
+#define DEF_FRAME_VISUAL ""
+#define DEF_FRAME_WIDTH "0"
+
+/*
+ * Defaults for listboxes:
+ */
+
+#define DEF_LISTBOX_BG_COLOR NORMAL_BG
+#define DEF_LISTBOX_BG_MONO WHITE
+#define DEF_LISTBOX_BORDER_WIDTH "1"
+#define DEF_LISTBOX_CURSOR ""
+#define DEF_LISTBOX_EXPORT_SELECTION "1"
+#define DEF_LISTBOX_FONT "application"
+#define DEF_LISTBOX_FG BLACK
+#define DEF_LISTBOX_HEIGHT "10"
+#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG
+#define DEF_LISTBOX_HIGHLIGHT BLACK
+#define DEF_LISTBOX_HIGHLIGHT_WIDTH "0"
+#define DEF_LISTBOX_RELIEF "solid"
+#define DEF_LISTBOX_SCROLL_COMMAND ""
+#define DEF_LISTBOX_SELECT_COLOR SELECT_BG
+#define DEF_LISTBOX_SELECT_MONO BLACK
+#define DEF_LISTBOX_SELECT_BD "0"
+#define DEF_LISTBOX_SELECT_FG_COLOR SELECT_FG
+#define DEF_LISTBOX_SELECT_FG_MONO WHITE
+#define DEF_LISTBOX_SELECT_MODE "browse"
+#define DEF_LISTBOX_SET_GRID "0"
+#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL
+#define DEF_LISTBOX_WIDTH "20"
+
+/*
+ * Defaults for individual entries of menus:
+ */
+
+#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL
+#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL
+#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL
+#define DEF_MENU_ENTRY_BG (char *) NULL
+#define DEF_MENU_ENTRY_BITMAP None
+#define DEF_MENU_ENTRY_COLUMN_BREAK "0"
+#define DEF_MENU_ENTRY_COMMAND (char *) NULL
+#define DEF_MENU_ENTRY_FG (char *) NULL
+#define DEF_MENU_ENTRY_FONT (char *) NULL
+#define DEF_MENU_ENTRY_HIDE_MARGIN "0"
+#define DEF_MENU_ENTRY_IMAGE (char *) NULL
+#define DEF_MENU_ENTRY_INDICATOR "1"
+#define DEF_MENU_ENTRY_LABEL (char *) NULL
+#define DEF_MENU_ENTRY_MENU (char *) NULL
+#define DEF_MENU_ENTRY_OFF_VALUE "0"
+#define DEF_MENU_ENTRY_ON_VALUE "1"
+#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL
+#define DEF_MENU_ENTRY_STATE "normal"
+#define DEF_MENU_ENTRY_VALUE (char *) NULL
+#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL
+#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton"
+#define DEF_MENU_ENTRY_SELECT (char *) NULL
+#define DEF_MENU_ENTRY_UNDERLINE "-1"
+
+/*
+ * Defaults for menus overall:
+ */
+
+#define DEF_MENU_ACTIVE_BG_COLOR "SystemMenuActive"
+#define DEF_MENU_ACTIVE_BG_MONO BLACK
+#define DEF_MENU_ACTIVE_BORDER_WIDTH "0"
+#define DEF_MENU_ACTIVE_FG_COLOR "SystemMenuActiveText"
+#define DEF_MENU_ACTIVE_FG_MONO WHITE
+#define DEF_MENU_BG_COLOR "SystemMenu"
+#define DEF_MENU_BG_MONO WHITE
+#define DEF_MENU_BORDER_WIDTH "0"
+#define DEF_MENU_CURSOR "arrow"
+#define DEF_MENU_DISABLED_FG_COLOR "SystemMenuDisabled"
+#define DEF_MENU_DISABLED_FG_MONO ""
+#define DEF_MENU_FONT "system"
+#define DEF_MENU_FG "SystemMenuText"
+#define DEF_MENU_POST_COMMAND ""
+#define DEF_MENU_RELIEF "flat"
+#define DEF_MENU_SELECT_COLOR "SystemMenuActive"
+#define DEF_MENU_SELECT_MONO BLACK
+#define DEF_MENU_TAKE_FOCUS "0"
+#define DEF_MENU_TEAROFF "1"
+#define DEF_MENU_TEAROFF_CMD (char *) NULL
+#define DEF_MENU_TITLE ""
+#define DEF_MENU_TYPE "normal"
+
+/*
+ * Defaults for menubuttons:
+ */
+
+#define DEF_MENUBUTTON_ANCHOR "center"
+#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG
+#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK
+#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK
+#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE
+#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG
+#define DEF_MENUBUTTON_BG_MONO WHITE
+#define DEF_MENUBUTTON_BITMAP ""
+#define DEF_MENUBUTTON_BORDER_WIDTH "2"
+#define DEF_MENUBUTTON_CURSOR ""
+#define DEF_MENUBUTTON_DIRECTION "below"
+#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED
+#define DEF_MENUBUTTON_DISABLED_FG_MONO ""
+#define DEF_MENUBUTTON_FONT "system"
+#define DEF_MENUBUTTON_FG BLACK
+#define DEF_MENUBUTTON_HEIGHT "0"
+#define DEF_MENUBUTTON_HIGHLIGHT_BG NORMAL_BG
+#define DEF_MENUBUTTON_HIGHLIGHT BLACK
+#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0"
+#define DEF_MENUBUTTON_IMAGE (char *) NULL
+#define DEF_MENUBUTTON_INDICATOR "0"
+/* #define DEF_MENUBUTTON_JUSTIFY "center" */
+#define DEF_MENUBUTTON_JUSTIFY "left"
+#define DEF_MENUBUTTON_MENU ""
+#define DEF_MENUBUTTON_PADX "4p"
+#define DEF_MENUBUTTON_PADY "3p"
+#define DEF_MENUBUTTON_RELIEF "flat"
+#define DEF_MENUBUTTON_STATE "normal"
+#define DEF_MENUBUTTON_TAKE_FOCUS "0"
+#define DEF_MENUBUTTON_TEXT ""
+#define DEF_MENUBUTTON_TEXT_VARIABLE ""
+#define DEF_MENUBUTTON_UNDERLINE "-1"
+#define DEF_MENUBUTTON_WIDTH "0"
+#define DEF_MENUBUTTON_WRAP_LENGTH "0"
+
+/*
+ * Defaults for messages:
+ */
+
+#define DEF_MESSAGE_ANCHOR "center"
+#define DEF_MESSAGE_ASPECT "150"
+#define DEF_MESSAGE_BG_COLOR NORMAL_BG
+#define DEF_MESSAGE_BG_MONO WHITE
+#define DEF_MESSAGE_BORDER_WIDTH "2"
+#define DEF_MESSAGE_CURSOR ""
+#define DEF_MESSAGE_FG BLACK
+#define DEF_MESSAGE_FONT "system"
+#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG
+#define DEF_MESSAGE_HIGHLIGHT BLACK
+#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0"
+#define DEF_MESSAGE_JUSTIFY "left"
+#define DEF_MESSAGE_PADX "-1"
+#define DEF_MESSAGE_PADY "-1"
+#define DEF_MESSAGE_RELIEF "flat"
+#define DEF_MESSAGE_TAKE_FOCUS "0"
+#define DEF_MESSAGE_TEXT ""
+#define DEF_MESSAGE_TEXT_VARIABLE ""
+#define DEF_MESSAGE_WIDTH "0"
+
+/*
+ * Defaults for scales:
+ */
+
+#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG
+#define DEF_SCALE_ACTIVE_BG_MONO BLACK
+#define DEF_SCALE_BG_COLOR NORMAL_BG
+#define DEF_SCALE_BG_MONO WHITE
+#define DEF_SCALE_BIG_INCREMENT "0"
+#define DEF_SCALE_BORDER_WIDTH "2"
+#define DEF_SCALE_COMMAND ""
+#define DEF_SCALE_CURSOR ""
+#define DEF_SCALE_DIGITS "0"
+#define DEF_SCALE_FONT "system"
+#define DEF_SCALE_FG_COLOR BLACK
+#define DEF_SCALE_FG_MONO BLACK
+#define DEF_SCALE_FROM "0"
+#define DEF_SCALE_HIGHLIGHT_BG NORMAL_BG
+#define DEF_SCALE_HIGHLIGHT BLACK
+#define DEF_SCALE_HIGHLIGHT_WIDTH "0"
+#define DEF_SCALE_LABEL ""
+#define DEF_SCALE_LENGTH "100"
+#define DEF_SCALE_ORIENT "vertical"
+#define DEF_SCALE_RELIEF "flat"
+#define DEF_SCALE_REPEAT_DELAY "300"
+#define DEF_SCALE_REPEAT_INTERVAL "100"
+#define DEF_SCALE_RESOLUTION "1"
+#define DEF_SCALE_TROUGH_COLOR TROUGH
+#define DEF_SCALE_TROUGH_MONO WHITE
+#define DEF_SCALE_SHOW_VALUE "1"
+#define DEF_SCALE_SLIDER_LENGTH "30"
+#define DEF_SCALE_SLIDER_RELIEF "raised"
+#define DEF_SCALE_STATE "normal"
+#define DEF_SCALE_TAKE_FOCUS (char *) NULL
+#define DEF_SCALE_TICK_INTERVAL "0"
+#define DEF_SCALE_TO "100"
+#define DEF_SCALE_VARIABLE ""
+#define DEF_SCALE_WIDTH "15"
+
+/*
+ * Defaults for scrollbars:
+ */
+
+#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG
+#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK
+#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised"
+#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG
+#define DEF_SCROLLBAR_BG_MONO WHITE
+/* #define DEF_SCROLLBAR_BORDER_WIDTH "2" */
+#define DEF_SCROLLBAR_BORDER_WIDTH "0"
+#define DEF_SCROLLBAR_COMMAND ""
+#define DEF_SCROLLBAR_CURSOR ""
+#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1"
+#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG
+#define DEF_SCROLLBAR_HIGHLIGHT BLACK
+/* #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "2" */
+#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0"
+#define DEF_SCROLLBAR_JUMP "0"
+#define DEF_SCROLLBAR_ORIENT "vertical"
+/*#define DEF_SCROLLBAR_RELIEF "sunken" */
+#define DEF_SCROLLBAR_RELIEF "flat"
+#define DEF_SCROLLBAR_REPEAT_DELAY "300"
+#define DEF_SCROLLBAR_REPEAT_INTERVAL "100"
+#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL
+#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH
+#define DEF_SCROLLBAR_TROUGH_MONO WHITE
+/*#define DEF_SCROLLBAR_WIDTH "15" */
+#define DEF_SCROLLBAR_WIDTH "16"
+
+/*
+ * Defaults for texts:
+ */
+
+#define DEF_TEXT_BG_COLOR NORMAL_BG
+#define DEF_TEXT_BG_MONO WHITE
+#define DEF_TEXT_BORDER_WIDTH "0"
+#define DEF_TEXT_CURSOR "xterm"
+#define DEF_TEXT_FG BLACK
+#define DEF_TEXT_EXPORT_SELECTION "1"
+#define DEF_TEXT_FONT "Courier 12"
+#define DEF_TEXT_HEIGHT "24"
+#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG
+#define DEF_TEXT_HIGHLIGHT BLACK
+#define DEF_TEXT_HIGHLIGHT_WIDTH "3"
+#define DEF_TEXT_INSERT_BG BLACK
+#define DEF_TEXT_INSERT_BD_COLOR "0"
+#define DEF_TEXT_INSERT_BD_MONO "0"
+#define DEF_TEXT_INSERT_OFF_TIME "300"
+#define DEF_TEXT_INSERT_ON_TIME "600"
+#define DEF_TEXT_INSERT_WIDTH "1"
+#define DEF_TEXT_PADX "1"
+#define DEF_TEXT_PADY "1"
+#define DEF_TEXT_RELIEF "flat"
+#define DEF_TEXT_SELECT_COLOR SELECT_BG
+#define DEF_TEXT_SELECT_MONO BLACK
+#define DEF_TEXT_SELECT_BD_COLOR "1"
+#define DEF_TEXT_SELECT_BD_MONO "0"
+#define DEF_TEXT_SELECT_FG_COLOR SELECT_FG
+#define DEF_TEXT_SELECT_FG_MONO WHITE
+#define DEF_TEXT_SELECT_RELIEF "solid"
+#define DEF_TEXT_SET_GRID "0"
+#define DEF_TEXT_SPACING1 "0"
+#define DEF_TEXT_SPACING2 "0"
+#define DEF_TEXT_SPACING3 "0"
+#define DEF_TEXT_STATE "normal"
+#define DEF_TEXT_TABS ""
+#define DEF_TEXT_TAKE_FOCUS (char *) NULL
+#define DEF_TEXT_WIDTH "80"
+#define DEF_TEXT_WRAP "char"
+#define DEF_TEXT_XSCROLL_COMMAND ""
+#define DEF_TEXT_YSCROLL_COMMAND ""
+
+/*
+ * Defaults for canvas text:
+ */
+
+#define DEF_CANVTEXT_FONT "Helvetica 12"
+
+/*
+ * Defaults for toplevels (most of the defaults for frames also apply
+ * to toplevels):
+ */
+
+#define DEF_TOPLEVEL_CLASS "Toplevel"
+#define DEF_TOPLEVEL_MENU ""
+#define DEF_TOPLEVEL_SCREEN ""
+
+#endif /* _TKMACDEFAULT */
diff --git a/mac/tkMacDialog.c b/mac/tkMacDialog.c
new file mode 100644
index 0000000..43d11a5
--- /dev/null
+++ b/mac/tkMacDialog.c
@@ -0,0 +1,939 @@
+/*
+ * tkMacDialog.c --
+ *
+ * Contains the Mac implementation of the common dialog boxes.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacDialog.c 1.12 96/12/03 11:15:12
+ *
+ */
+
+#include <Gestalt.h>
+#include <Aliases.h>
+#include <Errors.h>
+#include <Strings.h>
+#include <MoreFiles.h>
+#include <MoreFilesExtras.h>
+#include <StandardFile.h>
+#include <ColorPicker.h>
+#include <Lowmem.h>
+#include "tkPort.h"
+#include "tkInt.h"
+#include "tclMacInt.h"
+#include "tkFileFilter.h"
+
+/*
+ * The following are ID's for resources that are defined in tkMacResource.r
+ */
+#define OPEN_BOX 130
+#define OPEN_POPUP 131
+#define OPEN_MENU 132
+#define OPEN_POPUP_ITEM 10
+
+#define SAVE_FILE 0
+#define OPEN_FILE 1
+
+#define MATCHED 0
+#define UNMATCHED 1
+
+/*
+ * The following structure is used in the GetFileName() function. It stored
+ * information about the file dialog and the file filters.
+ */
+typedef struct _OpenFileData {
+ Tcl_Interp * interp;
+ char * initialFile; /* default file to appear in the
+ * save dialog */
+ char * defExt; /* default extension (not used on the
+ * Mac) */
+ FileFilterList fl; /* List of file filters. */
+ SInt16 curType; /* The filetype currently being
+ * listed */
+ int isOpen; /* True if this is an Open dialog,
+ * false if it is a Save dialog. */
+ MenuHandle menu; /* Handle of the menu in the popup*/
+ short dialogId; /* resource ID of the dialog */
+ int popupId; /* resource ID of the popup */
+ short popupItem; /* item number of the popup in the
+ * dialog */
+ int usePopup; /* True if we show the popup menu (this
+ * is an open operation and the
+ * -filetypes option is set)
+ */
+} OpenFileData;
+
+static pascal Boolean FileFilterProc _ANSI_ARGS_((CInfoPBPtr pb,
+ void *myData));
+static int GetFileName _ANSI_ARGS_ ((
+ ClientData clientData, Tcl_Interp *interp,
+ int argc, char **argv, int isOpen ));
+static Boolean MatchOneType _ANSI_ARGS_((CInfoPBPtr pb,
+ OpenFileData * myDataPtr, FileFilter * filterPtr));
+static pascal short OpenHookProc _ANSI_ARGS_((short item,
+ DialogPtr theDialog, OpenFileData * myDataPtr));
+static int ParseFileDlgArgs _ANSI_ARGS_ ((Tcl_Interp * interp,
+ OpenFileData * myDataPtr, int argc, char ** argv,
+ int isOpen));
+
+/*
+ * Filter and hook functions used by the tk_getOpenFile and tk_getSaveFile
+ * commands.
+ */
+
+static FileFilterYDUPP openFilter = NULL;
+static DlgHookYDUPP openHook = NULL;
+static DlgHookYDUPP saveHook = NULL;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EvalArgv --
+ *
+ * Invokes the Tcl procedure with the arguments. argv[0] is set by
+ * the caller of this function. It may be different than cmdName.
+ * The TCL command will see argv[0], not cmdName, as its name if it
+ * invokes [lindex [info level 0] 0]
+ *
+ * Results:
+ * TCL_ERROR if the command does not exist and cannot be autoloaded.
+ * Otherwise, return the result of the evaluation of the command.
+ *
+ * Side effects:
+ * The command may be autoloaded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+EvalArgv(
+ Tcl_Interp *interp, /* Current interpreter. */
+ char * cmdName, /* Name of the TCL command to call */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ Tcl_CmdInfo cmdInfo;
+
+ if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
+ char * cmdArgv[2];
+
+ /*
+ * This comand is not in the interpreter yet -- looks like we
+ * have to auto-load it
+ */
+ if (!Tcl_GetCommandInfo(interp, "auto_load", &cmdInfo)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "cannot execute command \"auto_load\"",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ cmdArgv[0] = "auto_load";
+ cmdArgv[1] = cmdName;
+
+ if ((*cmdInfo.proc)(cmdInfo.clientData, interp, 2, cmdArgv)!= TCL_OK){
+ return TCL_ERROR;
+ }
+
+ if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "cannot auto-load command \"",
+ cmdName, "\"",NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ return (*cmdInfo.proc)(cmdInfo.clientData, interp, argc, argv);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ChooseColorCmd --
+ *
+ * This procedure implements the color dialog box for the Mac
+ * platform. See the user documentation for details on what it
+ * does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_ChooseColorCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ Tk_Window parent = Tk_MainWindow(interp);
+ char * colorStr = NULL;
+ XColor * colorPtr = NULL;
+ char * title = "Choose a color:";
+ int i, version;
+ long response = 0;
+ OSErr err = noErr;
+ char buff[40];
+ static RGBColor in;
+ static inited = 0;
+
+ /*
+ * Use the gestalt manager to determine how to bring
+ * up the color picker. If versin 2.0 isn't available
+ * we can assume version 1.0 is available as it comes with
+ * Color Quickdraw which Tk requires to run at all.
+ */
+
+ err = Gestalt(gestaltColorPicker, &response);
+ if ((err == noErr) || (response == 0x0200L)) {
+ version = 2;
+ } else {
+ version = 1;
+ }
+
+ for (i=1; i<argc; i+=2) {
+ int v = i+1;
+ int len = strlen(argv[i]);
+
+ if (strncmp(argv[i], "-initialcolor", len)==0) {
+ if (v==argc) {goto arg_missing;}
+
+ colorStr = argv[v];
+ } else if (strncmp(argv[i], "-parent", len)==0) {
+ if (v==argc) {goto arg_missing;}
+
+ parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
+ if (parent == NULL) {
+ return TCL_ERROR;
+ }
+ } else if (strncmp(argv[i], "-title", len)==0) {
+ if (v==argc) {goto arg_missing;}
+
+ title = argv[v];
+ } else {
+ Tcl_AppendResult(interp, "unknown option \"",
+ argv[i], "\", must be -initialcolor, -parent or -title",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (colorStr) {
+ colorPtr = Tk_GetColor(interp, parent, colorStr);
+ if (colorPtr == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ if (!inited) {
+ inited = 1;
+ in.red = 0xffff;
+ in.green = 0xffff;
+ in.blue = 0xffff;
+ }
+ if (colorPtr) {
+ in.red = colorPtr->red;
+ in.green = colorPtr->green;
+ in.blue = colorPtr->blue;
+ }
+
+ if (version == 1) {
+ /*
+ * Use version 1.0 of the color picker
+ */
+
+ RGBColor out;
+ Str255 prompt;
+ Point point = {-1, -1};
+
+ prompt[0] = strlen(title);
+ strncpy((char*) prompt+1, title, 255);
+
+ if (GetColor(point, prompt, &in, &out)) {
+ /*
+ * user selected a color
+ */
+ sprintf(buff, "#%02x%02x%02x", out.red >> 8, out.green >> 8,
+ out.blue >> 8);
+ Tcl_SetResult(interp, buff, TCL_VOLATILE);
+
+ /*
+ * Save it for the next time
+ */
+ in.red = out.red;
+ in.green = out.green;
+ in.blue = out.blue;
+ } else {
+ Tcl_ResetResult(interp);
+ }
+ } else {
+ /*
+ * Version 2.0 of the color picker is available. Let's use it
+ */
+ ColorPickerInfo cpinfo;
+
+ cpinfo.theColor.profile = 0L;
+ cpinfo.theColor.color.rgb.red = in.red;
+ cpinfo.theColor.color.rgb.green = in.green;
+ cpinfo.theColor.color.rgb.blue = in.blue;
+ cpinfo.dstProfile = 0L;
+ cpinfo.flags = CanModifyPalette | CanAnimatePalette;
+ cpinfo.placeWhere = kDeepestColorScreen;
+ cpinfo.pickerType = 0L;
+ cpinfo.eventProc = NULL;
+ cpinfo.colorProc = NULL;
+ cpinfo.colorProcData = NULL;
+
+ cpinfo.prompt[0] = strlen(title);
+ strncpy((char*)cpinfo.prompt+1, title, 255);
+
+ if ((PickColor(&cpinfo) == noErr) && cpinfo.newColorChosen) {
+ sprintf(buff, "#%02x%02x%02x",
+ cpinfo.theColor.color.rgb.red >> 8,
+ cpinfo.theColor.color.rgb.green >> 8,
+ cpinfo.theColor.color.rgb.blue >> 8);
+ Tcl_SetResult(interp, buff, TCL_VOLATILE);
+
+ in.blue = cpinfo.theColor.color.rgb.red;
+ in.green = cpinfo.theColor.color.rgb.green;
+ in.blue = cpinfo.theColor.color.rgb.blue;
+ } else {
+ Tcl_ResetResult(interp);
+ }
+ }
+
+ if (colorPtr) {
+ Tk_FreeColor(colorPtr);
+ }
+
+ return TCL_OK;
+
+ arg_missing:
+ Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
+ NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetOpenFileCmd --
+ *
+ * This procedure implements the "open file" dialog box for the
+ * Mac platform. See the user documentation for details on what
+ * it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See user documentation.
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetOpenFileCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ return GetFileName(clientData, interp, argc, argv, OPEN_FILE);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetSaveFileCmd --
+ *
+ * Same as Tk_GetOpenFileCmd but opens a "save file" dialog box
+ * instead
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See user documentation.
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetSaveFileCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ return GetFileName(clientData, interp, argc, argv, SAVE_FILE);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetFileName --
+ *
+ * Calls the Mac file dialog functions for the user to choose a
+ * file to or save.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * If the user selects a file, the native pathname of the file
+ * is returned in interp->result. Otherwise an empty string
+ * is returned in interp->result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetFileName(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv, /* Argument strings. */
+ int isOpen) /* true if we should call GetOpenFileName(),
+ * false if we should call GetSaveFileName() */
+{
+ int code = TCL_OK;
+ int i;
+ OpenFileData myData, *myDataPtr;
+ StandardFileReply reply;
+ Point mypoint;
+ Str255 str;
+
+ myDataPtr = &myData;
+
+ if (openFilter == NULL) {
+ openFilter = NewFileFilterYDProc(FileFilterProc);
+ openHook = NewDlgHookYDProc(OpenHookProc);
+ saveHook = NewDlgHookYDProc(OpenHookProc);
+ }
+
+ /*
+ * 1. Parse the arguments.
+ */
+ if (ParseFileDlgArgs(interp, myDataPtr, argc, argv, isOpen)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * 2. Set the items in the file types popup.
+ */
+
+ /*
+ * Delete all the entries inside the popup menu, in case there's any
+ * left overs from previous invocation of this command
+ */
+
+ if (myDataPtr->usePopup) {
+ FileFilter * filterPtr;
+
+ for (i=CountMItems(myDataPtr->menu); i>0; i--) {
+ /*
+ * The item indices are one based. Also, if we delete from
+ * the beginning, the items may be re-numbered. So we
+ * delete from the end
+ */
+ DeleteMenuItem(myDataPtr->menu, i);
+ }
+
+ if (myDataPtr->fl.filters) {
+ for (filterPtr=myDataPtr->fl.filters; filterPtr;
+ filterPtr=filterPtr->next) {
+ strncpy((char*)str+1, filterPtr->name, 254);
+ str[0] = strlen(filterPtr->name);
+ AppendMenu(myDataPtr->menu, (ConstStr255Param) str);
+ }
+ } else {
+ myDataPtr->usePopup = 0;
+ }
+ }
+
+ /*
+ * 3. Call the toolbox file dialog function.
+ */
+ SetPt(&mypoint, -1, -1);
+ TkpSetCursor(NULL);
+
+ if (myDataPtr->isOpen) {
+ if (myDataPtr->usePopup) {
+ CustomGetFile(openFilter, (short) -1, NULL, &reply,
+ myDataPtr->dialogId,
+ mypoint, openHook, NULL, NULL, NULL, (void*)myDataPtr);
+ } else {
+ StandardGetFile(NULL, -1, NULL, &reply);
+ }
+ } else {
+ Str255 prompt, def;
+
+ strcpy((char*)prompt+1, "Save as");
+ prompt[0] = strlen("Save as");
+ if (myDataPtr->initialFile) {
+ strncpy((char*)def+1, myDataPtr->initialFile, 254);
+ def[0] = strlen(myDataPtr->initialFile);
+ } else {
+ def[0] = 0;
+ }
+ if (myDataPtr->usePopup) {
+ /*
+ * Currently this never gets called because we don't use
+ * popup for the save dialog.
+ */
+ CustomPutFile(prompt, def, &reply, myDataPtr->dialogId, mypoint,
+ saveHook, NULL, NULL, NULL, myDataPtr);
+ } else {
+ StandardPutFile(prompt, def, &reply);
+ }
+ }
+
+ Tcl_ResetResult(interp);
+ if (reply.sfGood) {
+ int length;
+ Handle pathHandle = NULL;
+ char * pathName = NULL;
+
+ FSpPathFromLocation(&reply.sfFile, &length, &pathHandle);
+
+ if (pathHandle != NULL) {
+ HLock(pathHandle);
+ pathName = (char *) ckalloc((unsigned) (length + 1));
+ strcpy(pathName, *pathHandle);
+ HUnlock(pathHandle);
+ DisposeHandle(pathHandle);
+
+ /*
+ * Return the full pathname of the selected file
+ */
+
+ Tcl_SetResult(interp, pathName, TCL_DYNAMIC);
+ }
+ }
+
+ done:
+ TkFreeFileFilters(&myDataPtr->fl);
+ return code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ParseFileDlgArgs --
+ *
+ * Parses the arguments passed to tk_getOpenFile and tk_getSaveFile.
+ *
+ * Results:
+ * A standard TCL return value.
+ *
+ * Side effects:
+ * The OpenFileData structure is initialized and modified according
+ * to the arguments.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ParseFileDlgArgs(
+ Tcl_Interp * interp, /* Current interpreter. */
+ OpenFileData * myDataPtr, /* Information about the file dialog */
+ int argc, /* Number of arguments */
+ char ** argv, /* Argument strings */
+ int isOpen) /* TRUE if this is an "open" dialog */
+{
+ int i;
+
+ myDataPtr->interp = interp;
+ myDataPtr->initialFile = NULL;
+ myDataPtr->curType = 0;
+
+ TkInitFileFilters(&myDataPtr->fl);
+
+ if (isOpen) {
+ myDataPtr->isOpen = 1;
+ myDataPtr->usePopup = 1;
+ myDataPtr->menu = GetMenu(OPEN_MENU);
+ myDataPtr->dialogId = OPEN_BOX;
+ myDataPtr->popupId = OPEN_POPUP;
+ myDataPtr->popupItem = OPEN_POPUP_ITEM;
+ if (myDataPtr->menu == NULL) {
+ Debugger();
+ }
+ } else {
+ myDataPtr->isOpen = 0;
+ myDataPtr->usePopup = 0;
+ }
+
+ for (i=1; i<argc; i+=2) {
+ int v = i+1;
+ int len = strlen(argv[i]);
+
+ if (strncmp(argv[i], "-defaultextension", len)==0) {
+ if (v==argc) {goto arg_missing;}
+
+ myDataPtr->defExt = argv[v];
+ }
+ else if (strncmp(argv[i], "-filetypes", len)==0) {
+ if (v==argc) {goto arg_missing;}
+
+ if (TkGetFileFilters(interp, &myDataPtr->fl,argv[v],0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ else if (strncmp(argv[i], "-initialdir", len)==0) {
+ FSSpec dirSpec;
+ char * dirName;
+ Tcl_DString dstring;
+ long dirID;
+ OSErr err;
+ Boolean isDirectory;
+
+ if (v==argc) {goto arg_missing;}
+
+ if (Tcl_TranslateFileName(interp, argv[v], &dstring) == NULL) {
+ return TCL_ERROR;
+ }
+ dirName = dstring.string;
+ if (FSpLocationFromPath(strlen(dirName), dirName, &dirSpec) !=
+ noErr) {
+ Tcl_AppendResult(interp, "bad directory \"", argv[v],
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory);
+ if ((err != noErr) || !isDirectory) {
+ Tcl_AppendResult(interp, "bad directory \"", argv[v],
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * Make sure you negate -dirSpec.vRefNum because the standard file
+ * package wants it that way !
+ */
+ LMSetSFSaveDisk(-dirSpec.vRefNum);
+ LMSetCurDirStore(dirID);
+ Tcl_DStringFree(&dstring);
+ }
+ else if (strncmp(argv[i], "-initialfile", len)==0) {
+ if (v==argc) {goto arg_missing;}
+
+ myDataPtr->initialFile = argv[v];
+ }
+ else if (strncmp(argv[i], "-parent", len)==0) {
+ /*
+ * Ignored on the Mac, but make sure that it's a valid window
+ * pathname
+ */
+ Tk_Window parent;
+
+ if (v==argc) {goto arg_missing;}
+
+ parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
+ if (parent == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ else if (strncmp(argv[i], "-title", len)==0) {
+ if (v==argc) {goto arg_missing;}
+
+ /*
+ * This option is ignored on the Mac because the Mac file
+ * dialog do not support titles.
+ */
+ }
+ else {
+ Tcl_AppendResult(interp, "unknown option \"",
+ argv[i], "\", must be -defaultextension, ",
+ "-filetypes, -initialdir, -initialfile, -parent or -title",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ return TCL_OK;
+
+ arg_missing:
+ Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
+ NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OpenHookProc --
+ *
+ * Gets called for various events that occur in the file dialog box.
+ * Initializes the popup menu or rebuild the file list depending on
+ * the type of the event.
+ *
+ * Results:
+ * A standard result understood by the Mac file dialog event dispatcher.
+ *
+ * Side effects:
+ * The contents in the file dialog may be changed depending on
+ * the type of the event.
+ *----------------------------------------------------------------------
+ */
+
+static pascal short
+OpenHookProc(
+ short item, /* Event description. */
+ DialogPtr theDialog, /* The dialog where the event occurs. */
+ OpenFileData * myDataPtr) /* Information about the file dialog. */
+{
+ short ignore;
+ Rect rect;
+ Handle handle;
+ int newType;
+
+ switch (item) {
+ case sfHookFirstCall:
+ if (myDataPtr->usePopup) {
+ /*
+ * Set the popup list to display the selected type.
+ */
+ GetDialogItem(theDialog, myDataPtr->popupItem,
+ &ignore, &handle, &rect);
+ SetControlValue((ControlRef) handle, myDataPtr->curType + 1);
+ }
+ return sfHookNullEvent;
+
+ case OPEN_POPUP_ITEM:
+ if (myDataPtr->usePopup) {
+ GetDialogItem(theDialog, myDataPtr->popupItem,
+ &ignore, &handle, &rect);
+ newType = GetCtlValue((ControlRef) handle) - 1;
+ if (myDataPtr->curType != newType) {
+ if (newType<0 || newType>myDataPtr->fl.numFilters) {
+ /*
+ * Sanity check. Looks like the user selected an
+ * non-existent menu item?? Don't do anything.
+ */
+ } else {
+ myDataPtr->curType = newType;
+ }
+ return sfHookRebuildList;
+ }
+ }
+ break;
+ }
+
+ return item;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileFilterProc --
+ *
+ * Filters files according to file types. Get called whenever the
+ * file list needs to be updated inside the dialog box.
+ *
+ * Results:
+ * Returns MATCHED if the file should be shown in the listbox, returns
+ * UNMATCHED otherwise.
+ *
+ * Side effects:
+ * If MATCHED is returned, the file is shown in the listbox.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal Boolean
+FileFilterProc(
+ CInfoPBPtr pb, /* Information about the file */
+ void *myData) /* Client data for this file dialog */
+{
+ int i;
+ OpenFileData * myDataPtr = (OpenFileData*)myData;
+ FileFilter * filterPtr;
+
+ if (myDataPtr->fl.numFilters == 0) {
+ /*
+ * No types have been specified. List all files by default
+ */
+ return MATCHED;
+ }
+
+ if (pb->dirInfo.ioFlAttrib & 0x10) {
+ /*
+ * This is a directory: always show it
+ */
+ return MATCHED;
+ }
+
+ if (myDataPtr->usePopup) {
+ i = myDataPtr->curType;
+ for (filterPtr=myDataPtr->fl.filters; filterPtr && i>0; i--) {
+ filterPtr = filterPtr->next;
+ }
+ if (filterPtr) {
+ return MatchOneType(pb, myDataPtr, filterPtr);
+ } else {
+ return UNMATCHED;
+ }
+ } else {
+ /*
+ * We are not using the popup menu. In this case, the file is
+ * considered matched if it matches any of the file filters.
+ */
+
+ for (filterPtr=myDataPtr->fl.filters; filterPtr;
+ filterPtr=filterPtr->next) {
+ if (MatchOneType(pb, myDataPtr, filterPtr) == MATCHED) {
+ return MATCHED;
+ }
+ }
+ return UNMATCHED;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MatchOneType --
+ *
+ * Match a file with one file type in the list of file types.
+ *
+ * Results:
+ * Returns MATCHED if the file matches with the file type; returns
+ * UNMATCHED otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Boolean
+MatchOneType(
+ CInfoPBPtr pb, /* Information about the file */
+ OpenFileData * myDataPtr, /* Information about this file dialog */
+ FileFilter * filterPtr) /* Match the file described by pb against
+ * this filter */
+{
+ FileFilterClause * clausePtr;
+
+ /*
+ * A file matches with a file type if it matches with at least one
+ * clause of the type.
+ *
+ * If the clause has both glob patterns and ostypes, the file must
+ * match with at least one pattern AND at least one ostype.
+ *
+ * If the clause has glob patterns only, the file must match with at least
+ * one pattern.
+ *
+ * If the clause has mac types only, the file must match with at least
+ * one mac type.
+ *
+ * If the clause has neither glob patterns nor mac types, it's
+ * considered an error.
+ */
+
+ for (clausePtr=filterPtr->clauses; clausePtr; clausePtr=clausePtr->next) {
+ int macMatched = 0;
+ int globMatched = 0;
+ GlobPattern * globPtr;
+ MacFileType * mfPtr;
+
+ if (clausePtr->patterns == NULL) {
+ globMatched = 1;
+ }
+ if (clausePtr->macTypes == NULL) {
+ macMatched = 1;
+ }
+
+ for (globPtr=clausePtr->patterns; globPtr; globPtr=globPtr->next) {
+ char filename[256];
+ int len;
+ char * p, *q, *ext;
+
+ if (pb->hFileInfo.ioNamePtr == NULL) {
+ continue;
+ }
+ p = (char*)(pb->hFileInfo.ioNamePtr);
+ len = p[0];
+ strncpy(filename, p+1, len);
+ filename[len] = '\0';
+ ext = globPtr->pattern;
+
+ if (ext[0] == '\0') {
+ /*
+ * We don't want any extensions: OK if the filename doesn't
+ * have "." in it
+ */
+ for (q=filename; *q; q++) {
+ if (*q == '.') {
+ goto glob_unmatched;
+ }
+ }
+ goto glob_matched;
+ }
+
+ if (Tcl_StringMatch(filename, ext)) {
+ goto glob_matched;
+ } else {
+ goto glob_unmatched;
+ }
+
+ glob_unmatched:
+ continue;
+
+ glob_matched:
+ globMatched = 1;
+ break;
+ }
+
+ for (mfPtr=clausePtr->macTypes; mfPtr; mfPtr=mfPtr->next) {
+ if (pb->hFileInfo.ioFlFndrInfo.fdType == mfPtr->type) {
+ macMatched = 1;
+ break;
+ }
+ }
+
+ if (globMatched && macMatched) {
+ return MATCHED;
+ }
+ }
+
+ return UNMATCHED;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MessageBoxCmd --
+ *
+ * This procedure implements the MessageBox window for the
+ * Mac platform. See the user documentation for details on what
+ * it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_MessageBoxCmd(
+ ClientData clientData, /* Main window associated with interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ return EvalArgv(interp, "tkMessageBox", argc, argv);
+}
diff --git a/mac/tkMacDraw.c b/mac/tkMacDraw.c
new file mode 100644
index 0000000..9624041
--- /dev/null
+++ b/mac/tkMacDraw.c
@@ -0,0 +1,1130 @@
+/*
+ * tkMacDraw.c --
+ *
+ * This file contains functions that preform drawing to
+ * Xlib windows. Most of the functions simple emulate
+ * Xlib functions.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacDraw.c 1.55 97/11/20 18:28:56
+ */
+
+#include "tkInt.h"
+#include "X.h"
+#include "Xlib.h"
+#include <stdio.h>
+#include <tcl.h>
+
+#include <Windows.h>
+#include <Fonts.h>
+#include <QDOffscreen.h>
+#include "tkMacInt.h"
+
+#ifndef PI
+# define PI 3.14159265358979323846
+#endif
+
+/*
+ * Temporary regions that can be reused.
+ */
+static RgnHandle tmpRgn = NULL;
+static RgnHandle tmpRgn2 = NULL;
+
+static PixPatHandle gPenPat = NULL;
+
+/*
+ * Prototypes for functions used only in this file.
+ */
+static unsigned char InvertByte _ANSI_ARGS_((unsigned char data));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCopyArea --
+ *
+ * Copies data from one drawable to another using block transfer
+ * routines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Data is moved from a window or bitmap to a second window or
+ * bitmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XCopyArea(
+ Display* display, /* Display. */
+ Drawable src, /* Source drawable. */
+ Drawable dest, /* Destination drawable. */
+ GC gc, /* GC to use. */
+ int src_x, /* X & Y, width & height */
+ int src_y, /* define the source rectangle */
+ unsigned int width, /* the will be copied. */
+ unsigned int height,
+ int dest_x, /* Dest X & Y on dest rect. */
+ int dest_y)
+{
+ Rect srcRect, destRect;
+ BitMapPtr srcBit, destBit;
+ MacDrawable *srcDraw = (MacDrawable *) src;
+ MacDrawable *destDraw = (MacDrawable *) dest;
+ GWorldPtr srcPort, destPort;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ short tmode;
+ RGBColor origForeColor, origBackColor, whiteColor, blackColor;
+
+ destPort = TkMacGetDrawablePort(dest);
+ srcPort = TkMacGetDrawablePort(src);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+ GetForeColor(&origForeColor);
+ GetBackColor(&origBackColor);
+ whiteColor.red = 0;
+ whiteColor.blue = 0;
+ whiteColor.green = 0;
+ RGBForeColor(&whiteColor);
+ blackColor.red = 0xFFFF;
+ blackColor.blue = 0xFFFF;
+ blackColor.green = 0xFFFF;
+ RGBBackColor(&blackColor);
+
+
+ TkMacSetUpClippingRgn(dest);
+
+ /*
+ * We will change the clip rgn in this routine, so we need to
+ * be able to restore it when we exit.
+ */
+
+ if (tmpRgn2 == NULL) {
+ tmpRgn2 = NewRgn();
+ }
+ GetClip(tmpRgn2);
+
+ if (((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) {
+ RgnHandle clipRgn = (RgnHandle)
+ ((TkpClipMask*)gc->clip_mask)->value.region;
+
+ int xOffset, yOffset;
+
+ if (tmpRgn == NULL) {
+ tmpRgn = NewRgn();
+ }
+
+ xOffset = destDraw->xOff + gc->clip_x_origin;
+ yOffset = destDraw->yOff + gc->clip_y_origin;
+
+ OffsetRgn(clipRgn, xOffset, yOffset);
+
+ GetClip(tmpRgn);
+ SectRgn(tmpRgn, clipRgn, tmpRgn);
+
+ SetClip(tmpRgn);
+
+ OffsetRgn(clipRgn, -xOffset, -yOffset);
+ }
+
+ srcBit = &((GrafPtr) srcPort)->portBits;
+ destBit = &((GrafPtr) destPort)->portBits;
+ SetRect(&srcRect, (short) (srcDraw->xOff + src_x),
+ (short) (srcDraw->yOff + src_y),
+ (short) (srcDraw->xOff + src_x + width),
+ (short) (srcDraw->yOff + src_y + height));
+ SetRect(&destRect, (short) (destDraw->xOff + dest_x),
+ (short) (destDraw->yOff + dest_y),
+ (short) (destDraw->xOff + dest_x + width),
+ (short) (destDraw->yOff + dest_y + height));
+ tmode = srcCopy;
+
+ CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
+ RGBForeColor(&origForeColor);
+ RGBBackColor(&origBackColor);
+ SetClip(tmpRgn2);
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCopyPlane --
+ *
+ * Copies a bitmap from a source drawable to a destination
+ * drawable. The plane argument specifies which bit plane of
+ * the source contains the bitmap. Note that this implementation
+ * ignores the gc->function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the destination drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XCopyPlane(
+ Display* display, /* Display. */
+ Drawable src, /* Source drawable. */
+ Drawable dest, /* Destination drawable. */
+ GC gc, /* The GC to use. */
+ int src_x, /* X, Y, width & height */
+ int src_y, /* define the source rect. */
+ unsigned int width,
+ unsigned int height,
+ int dest_x, /* X & Y on dest where we will copy. */
+ int dest_y,
+ unsigned long plane) /* Which plane to copy. */
+{
+ Rect srcRect, destRect;
+ BitMapPtr srcBit, destBit, maskBit;
+ MacDrawable *srcDraw = (MacDrawable *) src;
+ MacDrawable *destDraw = (MacDrawable *) dest;
+ GWorldPtr srcPort, destPort, maskPort;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ RGBColor macColor;
+ TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
+ short tmode;
+
+ destPort = TkMacGetDrawablePort(dest);
+ srcPort = TkMacGetDrawablePort(src);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(dest);
+
+ srcBit = &((GrafPtr) srcPort)->portBits;
+ destBit = &((GrafPtr) destPort)->portBits;
+ SetRect(&srcRect, (short) (srcDraw->xOff + src_x),
+ (short) (srcDraw->yOff + src_y),
+ (short) (srcDraw->xOff + src_x + width),
+ (short) (srcDraw->yOff + src_y + height));
+ SetRect(&destRect, (short) (destDraw->xOff + dest_x),
+ (short) (destDraw->yOff + dest_y),
+ (short) (destDraw->xOff + dest_x + width),
+ (short) (destDraw->yOff + dest_y + height));
+ tmode = srcOr;
+ tmode = srcCopy + transparent;
+
+ if (TkSetMacColor(gc->foreground, &macColor) == true) {
+ RGBForeColor(&macColor);
+ }
+
+ if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) {
+
+ /*
+ * Case 1: opaque bitmaps.
+ */
+
+ TkSetMacColor(gc->background, &macColor);
+ RGBBackColor(&macColor);
+ tmode = srcCopy;
+ CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
+ } else if (clipPtr->type == TKP_CLIP_PIXMAP) {
+ if (clipPtr->value.pixmap == src) {
+ /*
+ * Case 2: transparent bitmaps. If it's color we ignore
+ * the forecolor.
+ */
+ if ((**(srcPort->portPixMap)).pixelSize == 1) {
+ tmode = srcOr;
+ } else {
+ tmode = transparent;
+ }
+ CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
+ } else {
+ /*
+ * Case 3: two arbitrary bitmaps.
+ */
+ tmode = srcCopy;
+ maskPort = TkMacGetDrawablePort(clipPtr->value.pixmap);
+ maskBit = &((GrafPtr) maskPort)->portBits;
+ CopyDeepMask(srcBit, maskBit, destBit, &srcRect, &srcRect, &destRect, tmode, NULL);
+ }
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPutImage --
+ *
+ * Copies a subimage from an in-memory image to a rectangle of
+ * of the specified drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws the image on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkPutImage(
+ unsigned long *colors, /* Unused on Macintosh. */
+ int ncolors, /* Unused on Macintosh. */
+ Display* display, /* Display. */
+ Drawable d, /* Drawable to place image on. */
+ GC gc, /* GC to use. */
+ XImage* image, /* Image to place. */
+ int src_x, /* Source X & Y. */
+ int src_y,
+ int dest_x, /* Destination X & Y. */
+ int dest_y,
+ unsigned int width, /* Same width & height for both */
+ unsigned int height) /* distination and source. */
+{
+ MacDrawable *destDraw = (MacDrawable *) d;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ int i, j;
+ BitMap bitmap;
+ char *newData = NULL;
+ Rect destRect, srcRect;
+
+ destPort = TkMacGetDrawablePort(d);
+ SetRect(&destRect, dest_x, dest_y, dest_x + width, dest_y + height);
+ SetRect(&srcRect, src_x, src_y, src_x + width, src_y + height);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ if (image->depth == 1) {
+
+ /*
+ * This code assumes a pixel depth of 1
+ */
+
+ bitmap.bounds.top = bitmap.bounds.left = 0;
+ bitmap.bounds.right = (short) image->width;
+ bitmap.bounds.bottom = (short) image->height;
+ if ((image->bytes_per_line % 2) == 1) {
+ char *newPtr, *oldPtr;
+ newData = (char *) ckalloc(image->height *
+ (image->bytes_per_line + 1));
+ newPtr = newData;
+ oldPtr = image->data;
+ for (i = 0; i < image->height; i++) {
+ for (j = 0; j < image->bytes_per_line; j++) {
+ *newPtr = InvertByte((unsigned char) *oldPtr);
+ newPtr++, oldPtr++;
+ }
+ *newPtr = 0;
+ newPtr++;
+ }
+ bitmap.baseAddr = newData;
+ bitmap.rowBytes = image->bytes_per_line + 1;
+ } else {
+ newData = (char *) ckalloc(image->height * image->bytes_per_line);
+ for (i = 0; i < image->height * image->bytes_per_line; i++) {
+ newData[i] = InvertByte((unsigned char) image->data[i]);
+ }
+ bitmap.baseAddr = newData;
+ bitmap.rowBytes = image->bytes_per_line;
+ }
+
+ CopyBits(&bitmap, &((GrafPtr) destPort)->portBits,
+ &srcRect, &destRect, srcCopy, NULL);
+
+ } else {
+ /* Color image */
+ PixMap pixmap;
+
+ pixmap.bounds.left = 0;
+ pixmap.bounds.top = 0;
+ pixmap.bounds.right = (short) image->width;
+ pixmap.bounds.bottom = (short) image->height;
+ pixmap.pixelType = RGBDirect;
+ pixmap.pmVersion = 4; /* 32bit clean */
+ pixmap.packType = 0;
+ pixmap.packSize = 0;
+ pixmap.hRes = 0x00480000;
+ pixmap.vRes = 0x00480000;
+ pixmap.pixelSize = 32;
+ pixmap.cmpCount = 3;
+ pixmap.cmpSize = 8;
+ pixmap.planeBytes = 0;
+ pixmap.pmTable = NULL;
+ pixmap.pmReserved = 0;
+ pixmap.baseAddr = image->data;
+ pixmap.rowBytes = image->bytes_per_line | 0x8000;
+
+ CopyBits((BitMap *) &pixmap, &((GrafPtr) destPort)->portBits,
+ &srcRect, &destRect, srcCopy, NULL);
+ }
+
+ if (newData != NULL) {
+ ckfree(newData);
+ }
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillRectangles --
+ *
+ * Fill multiple rectangular areas in the given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws onto the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillRectangles(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ XRectangle *rectangles, /* Rectangle array. */
+ int n_rectangels) /* Number of rectangles. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ Rect theRect;
+ int i;
+
+ destPort = TkMacGetDrawablePort(d);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ TkMacSetUpGraphicsPort(gc);
+
+ for (i=0; i<n_rectangels; i++) {
+ theRect.left = (short) (macWin->xOff + rectangles[i].x);
+ theRect.top = (short) (macWin->yOff + rectangles[i].y);
+ theRect.right = (short) (theRect.left + rectangles[i].width);
+ theRect.bottom = (short) (theRect.top + rectangles[i].height);
+ FillCRect(&theRect, gPenPat);
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawLines --
+ *
+ * Draw connected lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders a series of connected lines.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawLines(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ XPoint* points, /* Array of points. */
+ int npoints, /* Number of points. */
+ int mode) /* Line drawing mode. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ CGrafPtr saveWorld;
+ GWorldPtr destPort;
+ GDHandle saveDevice;
+ int i;
+
+ destPort = TkMacGetDrawablePort(d);
+
+ display->request++;
+ if (npoints < 2) {
+ return; /* TODO: generate BadValue error. */
+ }
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ TkMacSetUpGraphicsPort(gc);
+
+ ShowPen();
+
+ PenPixPat(gPenPat);
+ MoveTo((short) (macWin->xOff + points[0].x),
+ (short) (macWin->yOff + points[0].y));
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModeOrigin) {
+ LineTo((short) (macWin->xOff + points[i].x),
+ (short) (macWin->yOff + points[i].y));
+ } else {
+ Line((short) (macWin->xOff + points[i].x),
+ (short) (macWin->yOff + points[i].y));
+ }
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawSegments --
+ *
+ * Draw unconnected lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders a series of connected lines.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void XDrawSegments(
+ Display *display,
+ Drawable d,
+ GC gc,
+ XSegment *segments,
+ int nsegments)
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ CGrafPtr saveWorld;
+ GWorldPtr destPort;
+ GDHandle saveDevice;
+ int i;
+
+ destPort = TkMacGetDrawablePort(d);
+
+ display->request++;
+
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ TkMacSetUpGraphicsPort(gc);
+
+ ShowPen();
+
+ PenPixPat(gPenPat);
+ for (i = 0; i < nsegments; i++) {
+ MoveTo((short) (macWin->xOff + segments[i].x1),
+ (short) (macWin->yOff + segments[i].y1));
+ LineTo((short) (macWin->xOff + segments[i].x2),
+ (short) (macWin->yOff + segments[i].y2));
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillPolygon --
+ *
+ * Draws a filled polygon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a filled polygon on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillPolygon(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ XPoint* points, /* Array of points. */
+ int npoints, /* Number of points. */
+ int shape, /* Shape to draw. */
+ int mode) /* Drawing mode. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ PolyHandle polygon;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ int i;
+
+ destPort = TkMacGetDrawablePort(d);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ TkMacSetUpGraphicsPort(gc);
+
+ PenNormal();
+ polygon = OpenPoly();
+
+ MoveTo((short) (macWin->xOff + points[0].x),
+ (short) (macWin->yOff + points[0].y));
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModePrevious) {
+ Line((short) (macWin->xOff + points[i].x),
+ (short) (macWin->yOff + points[i].y));
+ } else {
+ LineTo((short) (macWin->xOff + points[i].x),
+ (short) (macWin->yOff + points[i].y));
+ }
+ }
+
+ ClosePoly();
+
+ FillCPoly(polygon, gPenPat);
+
+ KillPoly(polygon);
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawRectangle --
+ *
+ * Draws a rectangle.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a rectangle on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawRectangle(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ int x, /* Upper left corner. */
+ int y,
+ unsigned int width, /* Width & height of rect. */
+ unsigned int height)
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ Rect theRect;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(d);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ TkMacSetUpGraphicsPort(gc);
+
+ theRect.left = (short) (macWin->xOff + x);
+ theRect.top = (short) (macWin->yOff + y);
+ theRect.right = (short) (theRect.left + width);
+ theRect.bottom = (short) (theRect.top + height);
+
+ ShowPen();
+ PenPixPat(gPenPat);
+ FrameRect(&theRect);
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawArc --
+ *
+ * Draw an arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws an arc on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawArc(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ int x, /* Upper left of */
+ int y, /* bounding rect. */
+ unsigned int width, /* Width & height. */
+ unsigned int height,
+ int angle1, /* Staring angle of arc. */
+ int angle2) /* Ending angle of arc. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ Rect theRect;
+ short start, extent;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(d);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ TkMacSetUpGraphicsPort(gc);
+
+ theRect.left = (short) (macWin->xOff + x);
+ theRect.top = (short) (macWin->yOff + y);
+ theRect.right = (short) (theRect.left + width);
+ theRect.bottom = (short) (theRect.top + height);
+ start = (short) (90 - (angle1 / 64));
+ extent = (short) (-(angle2 / 64));
+
+ ShowPen();
+ PenPixPat(gPenPat);
+ FrameArc(&theRect, start, extent);
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillArc --
+ *
+ * Draw a filled arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a filled arc on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillArc(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ int x, /* Upper left of */
+ int y, /* bounding rect. */
+ unsigned int width, /* Width & height. */
+ unsigned int height,
+ int angle1, /* Staring angle of arc. */
+ int angle2) /* Ending angle of arc. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ Rect theRect;
+ short start, extent;
+ PolyHandle polygon;
+ double sin1, cos1, sin2, cos2, angle;
+ double boxWidth, boxHeight;
+ double vertex[2], center1[2], center2[2];
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(d);
+
+ display->request++;
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(d);
+
+ TkMacSetUpGraphicsPort(gc);
+
+ theRect.left = (short) (macWin->xOff + x);
+ theRect.top = (short) (macWin->yOff + y);
+ theRect.right = (short) (theRect.left + width);
+ theRect.bottom = (short) (theRect.top + height);
+ start = (short) (90 - (angle1 / 64));
+ extent = (short) (- (angle2 / 64));
+
+ if (gc->arc_mode == ArcChord) {
+ boxWidth = theRect.right - theRect.left;
+ boxHeight = theRect.bottom - theRect.top;
+ angle = -(angle1/64.0)*PI/180.0;
+ sin1 = sin(angle);
+ cos1 = cos(angle);
+ angle -= (angle2/64.0)*PI/180.0;
+ sin2 = sin(angle);
+ cos2 = cos(angle);
+ vertex[0] = (theRect.left + theRect.right)/2.0;
+ vertex[1] = (theRect.top + theRect.bottom)/2.0;
+ center1[0] = vertex[0] + cos1*boxWidth/2.0;
+ center1[1] = vertex[1] + sin1*boxHeight/2.0;
+ center2[0] = vertex[0] + cos2*boxWidth/2.0;
+ center2[1] = vertex[1] + sin2*boxHeight/2.0;
+
+ polygon = OpenPoly();
+ MoveTo((short) ((theRect.left + theRect.right)/2),
+ (short) ((theRect.top + theRect.bottom)/2));
+
+ LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5));
+ LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5));
+ ClosePoly();
+
+ ShowPen();
+ FillCArc(&theRect, start, extent, gPenPat);
+ FillCPoly(polygon, gPenPat);
+
+ KillPoly(polygon);
+ } else {
+ ShowPen();
+ FillCArc(&theRect, start, extent, gPenPat);
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkScrollWindow --
+ *
+ * Scroll a rectangle of the specified window and accumulate
+ * a damage region.
+ *
+ * Results:
+ * Returns 0 if the scroll genereated no additional damage.
+ * Otherwise, sets the region that needs to be repainted after
+ * scrolling and returns 1.
+ *
+ * Side effects:
+ * Scrolls the bits in the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkScrollWindow(
+ Tk_Window tkwin, /* The window to be scrolled. */
+ GC gc, /* GC for window to be scrolled. */
+ int x, /* Position rectangle to be scrolled. */
+ int y,
+ int width,
+ int height,
+ int dx, /* Distance rectangle should be moved. */
+ int dy,
+ TkRegion damageRgn) /* Region to accumulate damage in. */
+{
+ MacDrawable *destDraw = (MacDrawable *) Tk_WindowId(tkwin);
+ RgnHandle rgn = (RgnHandle) damageRgn;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ Rect srcRect, scrollRect;
+
+ destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
+
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
+
+ /*
+ * Due to the implementation below the behavior may be differnt
+ * than X in certain cases that should never occur in Tk. The
+ * scrollRect is the source rect extended by the offset (the union
+ * of the source rect and the offset rect). Everything
+ * in the extended scrollRect is scrolled. On X, it's possible
+ * to "skip" over an area if the offset makes the source and
+ * destination rects disjoint and non-aligned.
+ */
+
+ SetRect(&srcRect, (short) (destDraw->xOff + x),
+ (short) (destDraw->yOff + y),
+ (short) (destDraw->xOff + x + width),
+ (short) (destDraw->yOff + y + height));
+ scrollRect = srcRect;
+ if (dx < 0) {
+ scrollRect.left += dx;
+ } else {
+ scrollRect.right += dx;
+ }
+ if (dy < 0) {
+ scrollRect.top += dy;
+ } else {
+ scrollRect.bottom += dy;
+ }
+
+ /*
+ * Adjust clip region so that we don't copy any windows
+ * that may overlap us.
+ */
+ RectRgn(rgn, &srcRect);
+ DiffRgn(rgn, destPort->visRgn, rgn);
+ OffsetRgn(rgn, dx, dy);
+ DiffRgn(destPort->clipRgn, rgn, destPort->clipRgn);
+ SetEmptyRgn(rgn);
+
+ /*
+ * When a menu is up, the Mac does not expect drawing to occur and
+ * does not clip out the menu. We have to do it ourselves. This
+ * is pretty gross.
+ */
+
+ if (tkUseMenuCascadeRgn == 1) {
+ Point scratch = {0, 0};
+ MacDrawable *macDraw = (MacDrawable *) Tk_WindowId(tkwin);
+
+ LocalToGlobal(&scratch);
+ CopyRgn(tkMenuCascadeRgn, rgn);
+ OffsetRgn(rgn, -scratch.h, -scratch.v);
+ DiffRgn(destPort->clipRgn, rgn, destPort->clipRgn);
+ SetEmptyRgn(rgn);
+ macDraw->toplevel->flags |= TK_DRAWN_UNDER_MENU;
+ }
+
+ ScrollRect(&scrollRect, dx, dy, rgn);
+
+ SetGWorld(saveWorld, saveDevice);
+
+ /*
+ * Fortunantly, the region returned by ScrollRect is symanticlly
+ * the same as what we need to return in this function. If the
+ * region is empty we return zero to denote that no damage was
+ * created.
+ */
+ if (EmptyRgn(rgn)) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacSetUpGraphicsPort --
+ *
+ * Set up the graphics port from the given GC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The current port is adjusted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacSetUpGraphicsPort(
+ GC gc) /* GC to apply to current port. */
+{
+ RGBColor macColor;
+
+ if (gPenPat == NULL) {
+ gPenPat = NewPixPat();
+ }
+
+ if (TkSetMacColor(gc->foreground, &macColor) == true) {
+ /* TODO: cache RGBPats for preformace - measure gains... */
+ MakeRGBPat(gPenPat, &macColor);
+ }
+
+ PenNormal();
+ if(gc->function == GXxor) {
+ PenMode(patXor);
+ }
+ if (gc->line_width > 1) {
+ PenSize(gc->line_width, gc->line_width);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacSetUpClippingRgn --
+ *
+ * Set up the clipping region so that drawing only occurs on the
+ * specified X subwindow.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clipping region in the current port is changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacSetUpClippingRgn(
+ Drawable drawable) /* Drawable to update. */
+{
+ MacDrawable *macDraw = (MacDrawable *) drawable;
+
+ if (macDraw->winPtr != NULL) {
+ if (macDraw->flags & TK_CLIP_INVALID) {
+ TkMacUpdateClipRgn(macDraw->winPtr);
+ }
+
+ /*
+ * When a menu is up, the Mac does not expect drawing to occur and
+ * does not clip out the menu. We have to do it ourselves. This
+ * is pretty gross.
+ */
+
+ if (macDraw->clipRgn != NULL) {
+ if (tkUseMenuCascadeRgn == 1) {
+ Point scratch = {0, 0};
+ GDHandle saveDevice;
+ GWorldPtr saveWorld;
+
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(TkMacGetDrawablePort(drawable), NULL);
+ LocalToGlobal(&scratch);
+ SetGWorld(saveWorld, saveDevice);
+ if (tmpRgn == NULL) {
+ tmpRgn = NewRgn();
+ }
+ CopyRgn(tkMenuCascadeRgn, tmpRgn);
+ OffsetRgn(tmpRgn, -scratch.h, -scratch.v);
+ DiffRgn(macDraw->clipRgn, tmpRgn, tmpRgn);
+ SetClip(tmpRgn);
+ macDraw->toplevel->flags |= TK_DRAWN_UNDER_MENU;
+ } else {
+ SetClip(macDraw->clipRgn);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacMakeStippleMap --
+ *
+ * Given a drawable and a stipple pattern this function draws the
+ * pattern repeatedly over the drawable. The drawable can then
+ * be used as a mask for bit-bliting a stipple pattern over an
+ * object.
+ *
+ * Results:
+ * A BitMap data structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+BitMapPtr
+TkMacMakeStippleMap(
+ Drawable drawable, /* Window to apply stipple. */
+ Drawable stipple) /* The stipple pattern. */
+{
+ MacDrawable *destDraw = (MacDrawable *) drawable;
+ GWorldPtr destPort;
+ BitMapPtr bitmapPtr;
+ int width, height, stippleHeight, stippleWidth;
+ int i, j;
+ char * data;
+ Rect bounds;
+
+ destPort = TkMacGetDrawablePort(drawable);
+ width = destPort->portRect.right - destPort->portRect.left;
+ height = destPort->portRect.bottom - destPort->portRect.top;
+
+ bitmapPtr = (BitMap *) ckalloc(sizeof(BitMap));
+ data = (char *) ckalloc(height * ((width / 8) + 1));
+ bitmapPtr->bounds.top = bitmapPtr->bounds.left = 0;
+ bitmapPtr->bounds.right = (short) width;
+ bitmapPtr->bounds.bottom = (short) height;
+ bitmapPtr->baseAddr = data;
+ bitmapPtr->rowBytes = (width / 8) + 1;
+
+ destPort = TkMacGetDrawablePort(stipple);
+ stippleWidth = destPort->portRect.right - destPort->portRect.left;
+ stippleHeight = destPort->portRect.bottom - destPort->portRect.top;
+
+ for (i = 0; i < height; i += stippleHeight) {
+ for (j = 0; j < width; j += stippleWidth) {
+ bounds.left = j;
+ bounds.top = i;
+ bounds.right = j + stippleWidth;
+ bounds.bottom = i + stippleHeight;
+
+ CopyBits(&((GrafPtr) destPort)->portBits, bitmapPtr,
+ &((GrafPtr) destPort)->portRect, &bounds, srcCopy, NULL);
+ }
+ }
+ return bitmapPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvertByte --
+ *
+ * This function reverses the bits in the passed in Byte of data.
+ *
+ * Results:
+ * The incoming byte in reverse bit order.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static unsigned char
+InvertByte(
+ unsigned char data) /* Byte of data. */
+{
+ unsigned char i;
+ unsigned char mask = 1, result = 0;
+
+ for (i = (1 << 7); i != 0; i /= 2) {
+ if (data & mask) {
+ result |= i;
+ }
+ mask = mask << 1;
+ }
+ return result;
+}
diff --git a/mac/tkMacEmbed.c b/mac/tkMacEmbed.c
new file mode 100644
index 0000000..7a73b54
--- /dev/null
+++ b/mac/tkMacEmbed.c
@@ -0,0 +1,1116 @@
+/*
+ * tkMacEmbed.c --
+ *
+ * This file contains platform-specific procedures for theMac to provide
+ * basic operations needed for application embedding (where one
+ * application can use as its main window an internal window from
+ * some other application).
+ * Currently only Toplevel embedding within the same Tk application is
+ * allowed on the Macintosh.
+ *
+ * Copyright (c) 1996-97 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacEmbed.c 1.6 97/10/31 17:20:22
+ */
+
+#include "tkInt.h"
+#include "tkPort.h"
+#include "X.h"
+#include "Xlib.h"
+#include <stdio.h>
+
+#include <Windows.h>
+#include <QDOffscreen.h>
+#include "tkMacInt.h"
+
+/*
+ * One of the following structures exists for each container in this
+ * application. It keeps track of the container window and its
+ * associated embedded window.
+ */
+
+typedef struct Container {
+ Window parent; /* The Mac Drawable for the parent of
+ * the pair (the container). */
+ TkWindow *parentPtr; /* Tk's information about the container,
+ * or NULL if the container isn't
+ * in this process. */
+ Window embedded; /* The MacDrawable for the embedded
+ * window. Starts off as None, but
+ * gets filled in when the window is
+ * eventually created. */
+ TkWindow *embeddedPtr; /* Tk's information about the embedded
+ * window, or NULL if the
+ * embedded application isn't in
+ * this process. */
+ struct Container *nextPtr; /* Next in list of all containers in
+ * this process. */
+} Container;
+
+static Container *firstContainerPtr = NULL;
+ /* First in list of all containers
+ * managed by this process. */
+
+/*
+ * Prototypes for static procedures defined in this file:
+ */
+
+static void ContainerEventProc _ANSI_ARGS_((
+ ClientData clientData, XEvent *eventPtr));
+static void EmbeddedEventProc _ANSI_ARGS_((
+ ClientData clientData, XEvent *eventPtr));
+static void EmbedActivateProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static void EmbedFocusProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static void EmbedGeometryRequest _ANSI_ARGS_((
+ Container * containerPtr, int width, int height));
+static void EmbedSendConfigure _ANSI_ARGS_((
+ Container *containerPtr));
+static void EmbedStructureProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static void EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr));
+
+/* WARNING - HACK */
+static void GenerateFocusEvents _ANSI_ARGS_((TkWindow *sourcePtr,
+ TkWindow *destPtr));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMakeWindow --
+ *
+ * Creates an X Window (Mac subwindow).
+ *
+ * Results:
+ * The window id is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Window
+TkpMakeWindow(
+ TkWindow *winPtr,
+ Window parent)
+{
+ MacDrawable *macWin;
+ XEvent event;
+
+ /*
+ * If this window is marked as embedded then
+ * the window structure should have already been
+ * created in the TkpUseWindow function.
+ */
+
+ if (Tk_IsEmbedded(winPtr)) {
+ return (Window) winPtr->privatePtr;
+ }
+
+ /*
+ * Allocate sub window
+ */
+
+ macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable));
+ if (macWin == NULL) {
+ winPtr->privatePtr = NULL;
+ return None;
+ }
+ macWin->winPtr = winPtr;
+ winPtr->privatePtr = macWin;
+ macWin->clipRgn = NewRgn();
+ macWin->aboveClipRgn = NewRgn();
+ macWin->referenceCount = 0;
+ macWin->flags = TK_CLIP_INVALID;
+
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+
+ /*
+ *This will be set when we are mapped.
+ */
+
+ macWin->portPtr = (GWorldPtr) NULL;
+ macWin->toplevel = macWin;
+ macWin->xOff = 0;
+ macWin->yOff = 0;
+ } else {
+ macWin->portPtr = NULL;
+ macWin->xOff = winPtr->parentPtr->privatePtr->xOff +
+ winPtr->parentPtr->changes.border_width +
+ winPtr->changes.x;
+ macWin->yOff = winPtr->parentPtr->privatePtr->yOff +
+ winPtr->parentPtr->changes.border_width +
+ winPtr->changes.y;
+ macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;
+ }
+
+ macWin->toplevel->referenceCount++;
+
+ /*
+ * TODO: need general solution for visibility events.
+ */
+ event.xany.serial = Tk_Display(winPtr)->request;
+ event.xany.send_event = False;
+ event.xany.display = Tk_Display(winPtr);
+
+ event.xvisibility.type = VisibilityNotify;
+ event.xvisibility.window = (Window) macWin;;
+ event.xvisibility.state = VisibilityUnobscured;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
+ return (Window) macWin;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpUseWindow --
+ *
+ * This procedure causes a Tk window to use a given X window as
+ * its parent window, rather than the root window for the screen.
+ * It is invoked by an embedded application to specify the window
+ * in which it is embedded.
+ *
+ * Results:
+ * The return value is normally TCL_OK. If an error occurs (such
+ * as string not being a valid window spec), then the return value
+ * is TCL_ERROR and an error message is left in interp->result if
+ * interp is non-NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpUseWindow(
+ Tcl_Interp *interp, /* If not NULL, used for error reporting
+ * if string is bogus. */
+ Tk_Window tkwin, /* Tk window that does not yet have an
+ * associated X window. */
+ char *string) /* String identifying an X window to use
+ * for tkwin; must be an integer value. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ MacDrawable *parent, *macWin;
+ Container *containerPtr;
+ XEvent event;
+ int result;
+
+ if (winPtr->window != None) {
+ panic("TkpUseWindow: X window already assigned");
+ }
+
+ /*
+ * Decode the container pointer, and look for it among the
+ *list of available containers.
+ *
+ * N.B. For now, we are limiting the containers to be in the same Tk
+ * application as tkwin, since otherwise they would not be in our list
+ * of containers.
+ *
+ */
+
+ if (Tcl_GetInt(interp, string, &result) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ parent = (MacDrawable *) result;
+
+ /*
+ * Save information about the container and the embedded window
+ * in a Container structure. Currently, there must already be an existing
+ * Container structure, since we only allow the case where both container
+ * and embedded app. are in the same process.
+ */
+
+ for (containerPtr = firstContainerPtr; containerPtr != NULL;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->parent == (Window) parent) {
+ winPtr->flags |= TK_BOTH_HALVES;
+ containerPtr->parentPtr->flags |= TK_BOTH_HALVES;
+ break;
+ }
+ }
+
+ /*
+ * We should not get to this code until we start to allow
+ * embedding in other applications.
+ */
+
+ if (containerPtr == NULL) {
+ Tcl_AppendResult(interp, "The window ID ", string,
+ " does not correspond to a valid Tk Window.",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make the embedded window.
+ */
+
+ macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable));
+ if (macWin == NULL) {
+ winPtr->privatePtr = NULL;
+ return TCL_ERROR;
+ }
+
+ macWin->winPtr = winPtr;
+ winPtr->privatePtr = macWin;
+ macWin->clipRgn = NewRgn();
+ macWin->aboveClipRgn = NewRgn();
+ macWin->referenceCount = 0;
+ macWin->flags = TK_CLIP_INVALID;
+
+ winPtr->flags |= TK_EMBEDDED;
+
+ /*
+ * Make a copy of the TK_EMBEDDED flag, since sometimes
+ * we need this to get the port after the TkWindow structure
+ * has been freed.
+ */
+
+ macWin->flags |= TK_EMBEDDED;
+
+ /*
+ * The portPtr will be NULL for an embedded window.
+ * Always use TkMacGetDrawablePort to get the portPtr.
+ * It will correctly find the container's port.
+ */
+
+ macWin->portPtr = (GWorldPtr) NULL;
+
+ macWin->toplevel = macWin;
+ macWin->xOff = parent->winPtr->privatePtr->xOff +
+ parent->winPtr->changes.border_width +
+ winPtr->changes.x;
+ macWin->yOff = parent->winPtr->privatePtr->yOff +
+ parent->winPtr->changes.border_width +
+ winPtr->changes.y;
+
+ macWin->toplevel->referenceCount++;
+
+ /*
+ * Finish filling up the container structure with the embedded window's
+ * information.
+ */
+
+ containerPtr->embedded = (Window) macWin;
+ containerPtr->embeddedPtr = macWin->winPtr;
+
+ /*
+ * TODO: need general solution for visibility events.
+ */
+
+ event.xany.serial = Tk_Display(winPtr)->request;
+ event.xany.send_event = False;
+ event.xany.display = Tk_Display(winPtr);
+
+ event.xvisibility.type = VisibilityNotify;
+ event.xvisibility.window = (Window) macWin;;
+ event.xvisibility.state = VisibilityUnobscured;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
+ /*
+ * Create an event handler to clean up the Container structure when
+ * tkwin is eventually deleted.
+ */
+
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
+ (ClientData) winPtr);
+
+
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMakeContainer --
+ *
+ * This procedure is called to indicate that a particular window
+ * will be a container for an embedded application. This changes
+ * certain aspects of the window's behavior, such as whether it
+ * will receive events anymore.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMakeContainer(
+ Tk_Window tkwin) /* Token for a window that is about to
+ * become a container. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ Container *containerPtr;
+
+ /*
+ * Register the window as a container so that, for example, we can
+ * make sure the argument to -use is valid.
+ */
+
+
+ Tk_MakeWindowExist(tkwin);
+ containerPtr = (Container *) ckalloc(sizeof(Container));
+ containerPtr->parent = Tk_WindowId(tkwin);
+ containerPtr->parentPtr = winPtr;
+ containerPtr->embedded = None;
+ containerPtr->embeddedPtr = NULL;
+ containerPtr->nextPtr = firstContainerPtr;
+ firstContainerPtr = containerPtr;
+ winPtr->flags |= TK_CONTAINER;
+
+ /*
+ * Request SubstructureNotify events so that we can find out when
+ * the embedded application creates its window or attempts to
+ * resize it. Also watch Configure events on the container so that
+ * we can resize the child to match. Also, pass activate events from
+ * the container down to the embedded toplevel.
+ */
+
+ Tk_CreateEventHandler(tkwin,
+ SubstructureNotifyMask|SubstructureRedirectMask,
+ ContainerEventProc, (ClientData) winPtr);
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc,
+ (ClientData) containerPtr);
+ Tk_CreateEventHandler(tkwin, ActivateMask, EmbedActivateProc,
+ (ClientData) containerPtr);
+ Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc,
+ (ClientData) containerPtr);
+
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacContainerId --
+ *
+ * Given an embedded window, this procedure returns the MacDrawable
+ * identifier for the associated container window.
+ *
+ * Results:
+ * The return value is the MacDrawable for winPtr's
+ * container window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MacDrawable *
+TkMacContainerId(winPtr)
+ TkWindow *winPtr; /* Tk's structure for an embedded window. */
+{
+ Container *containerPtr;
+
+ for (containerPtr = firstContainerPtr; containerPtr != NULL;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->embeddedPtr == winPtr) {
+ return (MacDrawable *) containerPtr->parent;
+ }
+ }
+ panic("TkMacContainerId couldn't find window");
+ return None;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacGetHostToplevel --
+ *
+ * Given the TkWindow, return the MacDrawable for the outermost
+ * toplevel containing it. This will be a real Macintosh window.
+ *
+ * Results:
+ * Returns a MacDrawable corresponding to a Macintosh Toplevel
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MacDrawable *
+TkMacGetHostToplevel(
+ TkWindow *winPtr) /* Tk's structure for a window. */
+{
+ TkWindow *contWinPtr, *topWinPtr;
+
+ topWinPtr = winPtr->privatePtr->toplevel->winPtr;
+ if (!Tk_IsEmbedded(topWinPtr)) {
+ return winPtr->privatePtr->toplevel;
+ } else {
+ contWinPtr = TkpGetOtherWindow(topWinPtr);
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ if (contWinPtr != NULL) {
+ return TkMacGetHostToplevel(contWinPtr);
+ } else {
+ return None;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpClaimFocus --
+ *
+ * This procedure is invoked when someone asks for the input focus
+ * to be put on a window in an embedded application, but the
+ * application doesn't currently have the focus. It requests the
+ * input focus from the container application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The input focus may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpClaimFocus(
+ TkWindow *topLevelPtr, /* Top-level window containing desired
+ * focus window; should be embedded. */
+ int force) /* One means that the container should
+ * claim the focus if it doesn't
+ * currently have it. */
+{
+ XEvent event;
+ Container *containerPtr;
+
+ if (!(topLevelPtr->flags & TK_EMBEDDED)) {
+ return;
+ }
+
+ for (containerPtr = firstContainerPtr;
+ containerPtr->embeddedPtr != topLevelPtr;
+ containerPtr = containerPtr->nextPtr) {
+ /* Empty loop body. */
+ }
+
+
+ event.xfocus.type = FocusIn;
+ event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display);
+ event.xfocus.send_event = 1;
+ event.xfocus.display = topLevelPtr->display;
+ event.xfocus.window = containerPtr->parent;
+ event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
+ event.xfocus.detail = force;
+ Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpTestembedCmd --
+ *
+ * This procedure implements the "testembed" command. It returns
+ * some or all of the information in the list pointed to by
+ * firstContainerPtr.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpTestembedCmd(
+ ClientData clientData, /* Main window for application. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ int all;
+ Container *containerPtr;
+ Tcl_DString dString;
+ char buffer[50];
+
+ if ((argc > 1) && (strcmp(argv[1], "all") == 0)) {
+ all = 1;
+ } else {
+ all = 0;
+ }
+ Tcl_DStringInit(&dString);
+ for (containerPtr = firstContainerPtr; containerPtr != NULL;
+ containerPtr = containerPtr->nextPtr) {
+ Tcl_DStringStartSublist(&dString);
+ if (containerPtr->parent == None) {
+ Tcl_DStringAppendElement(&dString, "");
+ } else {
+ if (all) {
+ sprintf(buffer, "0x%x", (int) containerPtr->parent);
+ Tcl_DStringAppendElement(&dString, buffer);
+ } else {
+ Tcl_DStringAppendElement(&dString, "XXX");
+ }
+ }
+ if (containerPtr->parentPtr == NULL) {
+ Tcl_DStringAppendElement(&dString, "");
+ } else {
+ Tcl_DStringAppendElement(&dString,
+ containerPtr->parentPtr->pathName);
+ }
+ if (containerPtr->embedded == None) {
+ Tcl_DStringAppendElement(&dString, "");
+ } else {
+ if (all) {
+ sprintf(buffer, "0x%x", (int) containerPtr->embedded);
+ Tcl_DStringAppendElement(&dString, buffer);
+ } else {
+ Tcl_DStringAppendElement(&dString, "XXX");
+ }
+ }
+ if (containerPtr->embeddedPtr == NULL) {
+ Tcl_DStringAppendElement(&dString, "");
+ } else {
+ Tcl_DStringAppendElement(&dString,
+ containerPtr->embeddedPtr->pathName);
+ }
+ Tcl_DStringEndSublist(&dString);
+ }
+ Tcl_DStringResult(interp, &dString);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpRedirectKeyEvent --
+ *
+ * This procedure is invoked when a key press or release event
+ * arrives for an application that does not believe it owns the
+ * input focus. This can happen because of embedding; for example,
+ * X can send an event to an embedded application when the real
+ * focus window is in the container application and is an ancestor
+ * of the container. This procedure's job is to forward the event
+ * back to the application where it really belongs.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The event may get sent to a different application.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpRedirectKeyEvent(
+ TkWindow *winPtr, /* Window to which the event was originally
+ * reported. */
+ XEvent *eventPtr) /* X event to redirect (should be KeyPress
+ * or KeyRelease). */
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetOtherWindow --
+ *
+ * If both the container and embedded window are in the same
+ * process, this procedure will return either one, given the other.
+ *
+ * Results:
+ * If winPtr is a container, the return value is the token for the
+ * embedded window, and vice versa. If the "other" window isn't in
+ * this process, NULL is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow *
+TkpGetOtherWindow(
+ TkWindow *winPtr) /* Tk's structure for a container or
+ * embedded window. */
+{
+ Container *containerPtr;
+
+ /*
+ * TkpGetOtherWindow returns NULL if both windows are not
+ * in the same process...
+ */
+
+ if (!(winPtr->flags & TK_BOTH_HALVES)) {
+ return NULL;
+ }
+
+ for (containerPtr = firstContainerPtr; containerPtr != NULL;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->embeddedPtr == winPtr) {
+ return containerPtr->parentPtr;
+ } else if (containerPtr->parentPtr == winPtr) {
+ return containerPtr->embeddedPtr;
+ }
+ }
+ return NULL;
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * EmbeddedEventProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher when various
+ * useful events are received for a window that is embedded in
+ * another application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Our internal state gets cleaned up when an embedded window is
+ * destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EmbeddedEventProc(clientData, eventPtr)
+ ClientData clientData; /* Token for container window. */
+ XEvent *eventPtr; /* ResizeRequest event. */
+{
+ TkWindow *winPtr = (TkWindow *) clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ EmbedWindowDeleted(winPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ContainerEventProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher when various
+ * useful events are received for the children of a container
+ * window. It forwards relevant information, such as geometry
+ * requests, from the events into the container's application.
+ *
+ * NOTE: on the Mac, only the DestroyNotify branch is ever taken.
+ * We don't synthesize the other events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the event. For example, when ConfigureRequest events
+ * occur, geometry information gets set for the container window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ContainerEventProc(clientData, eventPtr)
+ ClientData clientData; /* Token for container window. */
+ XEvent *eventPtr; /* ResizeRequest event. */
+{
+ TkWindow *winPtr = (TkWindow *) clientData;
+ Container *containerPtr;
+ Tk_ErrorHandler errHandler;
+
+ /*
+ * Ignore any X protocol errors that happen in this procedure
+ * (almost any operation could fail, for example, if the embedded
+ * application has deleted its window).
+ */
+
+ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
+ -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL);
+
+ /*
+ * Find the Container structure associated with the parent window.
+ */
+
+ for (containerPtr = firstContainerPtr;
+ containerPtr->parent != eventPtr->xmaprequest.parent;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr == NULL) {
+ panic("ContainerEventProc couldn't find Container record");
+ }
+ }
+
+ if (eventPtr->type == CreateNotify) {
+ /*
+ * A new child window has been created in the container. Record
+ * its id in the Container structure (if more than one child is
+ * created, just remember the last one and ignore the earlier
+ * ones).
+ */
+
+ containerPtr->embedded = eventPtr->xcreatewindow.window;
+ } else if (eventPtr->type == ConfigureRequest) {
+ if ((eventPtr->xconfigurerequest.x != 0)
+ || (eventPtr->xconfigurerequest.y != 0)) {
+ /*
+ * The embedded application is trying to move itself, which
+ * isn't legal. At this point, the window hasn't actually
+ * moved, but we need to send it a ConfigureNotify event to
+ * let it know that its request has been denied. If the
+ * embedded application was also trying to resize itself, a
+ * ConfigureNotify will be sent by the geometry management
+ * code below, so we don't need to do anything. Otherwise,
+ * generate a synthetic event.
+ */
+
+ if ((eventPtr->xconfigurerequest.width == winPtr->changes.width)
+ && (eventPtr->xconfigurerequest.height
+ == winPtr->changes.height)) {
+ EmbedSendConfigure(containerPtr);
+ }
+ }
+ EmbedGeometryRequest(containerPtr,
+ eventPtr->xconfigurerequest.width,
+ eventPtr->xconfigurerequest.height);
+ } else if (eventPtr->type == MapRequest) {
+ /*
+ * The embedded application's map request was ignored and simply
+ * passed on to us, so we have to map the window for it to appear
+ * on the screen.
+ */
+
+ XMapWindow(eventPtr->xmaprequest.display,
+ eventPtr->xmaprequest.window);
+ } else if (eventPtr->type == DestroyNotify) {
+ /*
+ * The embedded application is gone. Destroy the container window.
+ */
+
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ }
+ Tk_DeleteErrorHandler(errHandler);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EmbedStructureProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher when
+ * a container window owned by this application gets resized
+ * (and also at several other times that we don't care about).
+ * This procedure reflects the size change in the embedded
+ * window that corresponds to the container.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The embedded window gets resized to match the container.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EmbedStructureProc(clientData, eventPtr)
+ ClientData clientData; /* Token for container window. */
+ XEvent *eventPtr; /* ResizeRequest event. */
+{
+ Container *containerPtr = (Container *) clientData;
+ Tk_ErrorHandler errHandler;
+
+ if (eventPtr->type == ConfigureNotify) {
+ if (containerPtr->embedded != None) {
+ /*
+ * Ignore errors, since the embedded application could have
+ * deleted its window.
+ */
+
+ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
+ -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL);
+ Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0,
+ (unsigned int) Tk_Width(
+ (Tk_Window) containerPtr->parentPtr),
+ (unsigned int) Tk_Height(
+ (Tk_Window) containerPtr->parentPtr));
+ Tk_DeleteErrorHandler(errHandler);
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ EmbedWindowDeleted(containerPtr->parentPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EmbedActivateProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher when
+ * Activate and Deactivate events occur for a container window owned
+ * by this application. It is responsible for forwarding an activate
+ * event down into the embedded toplevel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The X focus may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EmbedActivateProc(clientData, eventPtr)
+ ClientData clientData; /* Token for container window. */
+ XEvent *eventPtr; /* ResizeRequest event. */
+{
+ Container *containerPtr = (Container *) clientData;
+
+ if (containerPtr->embeddedPtr != NULL) {
+
+ if (eventPtr->type == ActivateNotify) {
+ TkGenerateActivateEvents(containerPtr->embeddedPtr, 1);
+ } else if (eventPtr->type == DeactivateNotify) {
+ TkGenerateActivateEvents(containerPtr->embeddedPtr, 0);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EmbedFocusProc --
+ *
+ * This procedure is invoked by the Tk event dispatcher when
+ * FocusIn and FocusOut events occur for a container window owned
+ * by this application. It is responsible for moving the focus
+ * back and forth between a container application and an embedded
+ * application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The X focus may change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EmbedFocusProc(clientData, eventPtr)
+ ClientData clientData; /* Token for container window. */
+ XEvent *eventPtr; /* ResizeRequest event. */
+{
+ Container *containerPtr = (Container *) clientData;
+ Display *display;
+ XEvent event;
+
+ if (containerPtr->embeddedPtr != NULL) {
+ display = Tk_Display(containerPtr->parentPtr);
+ event.xfocus.serial = LastKnownRequestProcessed(display);
+ event.xfocus.send_event = false;
+ event.xfocus.display = display;
+ event.xfocus.mode = NotifyNormal;
+ event.xfocus.window = containerPtr->embedded;
+
+ if (eventPtr->type == FocusIn) {
+ /*
+ * The focus just arrived at the container. Change the X focus
+ * to move it to the embedded application, if there is one.
+ * Ignore X errors that occur during this operation (it's
+ * possible that the new focus window isn't mapped).
+ */
+
+ event.xfocus.detail = NotifyNonlinear;
+ event.xfocus.type = FocusIn;
+
+ } else if (eventPtr->type == FocusOut) {
+ /* When the container gets a FocusOut event, it has to tell the embedded app
+ * that it has lost the focus.
+ */
+
+ event.xfocus.type = FocusOut;
+ event.xfocus.detail = NotifyNonlinear;
+ }
+
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_MARK);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EmbedGeometryRequest --
+ *
+ * This procedure is invoked when an embedded application requests
+ * a particular size. It processes the request (which may or may
+ * not actually honor the request) and reflects the results back
+ * to the embedded application.
+ *
+ * NOTE: On the Mac, this is a stub, since we don't synthesize
+ * ConfigureRequest events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If we deny the child's size change request, a Configure event
+ * is synthesized to let the child know how big it ought to be.
+ * Events get processed while we're waiting for the geometry
+ * managers to do their thing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EmbedGeometryRequest(containerPtr, width, height)
+ Container *containerPtr; /* Information about the embedding. */
+ int width, height; /* Size that the child has requested. */
+{
+ TkWindow *winPtr = containerPtr->parentPtr;
+
+ /*
+ * Forward the requested size into our geometry management hierarchy
+ * via the container window. We need to send a Configure event back
+ * to the embedded application if we decide not to honor its
+ * request; to make this happen, process all idle event handlers
+ * synchronously here (so that the geometry managers have had a
+ * chance to do whatever they want to do), and if the window's size
+ * didn't change then generate a configure event.
+ */
+
+ Tk_GeometryRequest((Tk_Window) winPtr, width, height);
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {
+ /* Empty loop body. */
+ }
+ if ((winPtr->changes.width != width)
+ || (winPtr->changes.height != height)) {
+ EmbedSendConfigure(containerPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EmbedSendConfigure --
+ *
+ * This is currently a stub. It is called to notify an
+ * embedded application of its current size and location. This
+ * procedure is called when the embedded application made a
+ * geometry request that we did not grant, so that the embedded
+ * application knows that its geometry didn't change after all.
+ * It is a response to ConfigureRequest events, which we do not
+ * currently synthesize on the Mac
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EmbedSendConfigure(containerPtr)
+ Container *containerPtr; /* Information about the embedding. */
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EmbedWindowDeleted --
+ *
+ * This procedure is invoked when a window involved in embedding
+ * (as either the container or the embedded application) is
+ * destroyed. It cleans up the Container structure for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Container structure may be freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+EmbedWindowDeleted(winPtr)
+ TkWindow *winPtr; /* Tk's information about window that
+ * was deleted. */
+{
+ Container *containerPtr, *prevPtr;
+
+ /*
+ * Find the Container structure for this window. Delete the
+ * information about the embedded application and free the container's
+ * record.
+ */
+
+ prevPtr = NULL;
+ containerPtr = firstContainerPtr;
+ while (1) {
+ if (containerPtr->embeddedPtr == winPtr) {
+
+ /*
+ * We also have to destroy our parent, to clean up the container.
+ * Fabricate an event to do this.
+ */
+
+ if (containerPtr->parentPtr != NULL &&
+ containerPtr->parentPtr->flags & TK_BOTH_HALVES) {
+ XEvent event;
+
+ event.xany.serial =
+ Tk_Display(containerPtr->parentPtr)->request;
+ event.xany.send_event = False;
+ event.xany.display = Tk_Display(containerPtr->parentPtr);
+
+ event.xany.type = DestroyNotify;
+ event.xany.window = containerPtr->parent;
+ event.xdestroywindow.event = containerPtr->parent;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_HEAD);
+
+ }
+
+ containerPtr->embedded = None;
+ containerPtr->embeddedPtr = NULL;
+
+ break;
+ }
+ if (containerPtr->parentPtr == winPtr) {
+ containerPtr->parentPtr = NULL;
+ break;
+ }
+ prevPtr = containerPtr;
+ containerPtr = containerPtr->nextPtr;
+ }
+ if ((containerPtr->embeddedPtr == NULL)
+ && (containerPtr->parentPtr == NULL)) {
+ if (prevPtr == NULL) {
+ firstContainerPtr = containerPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = containerPtr->nextPtr;
+ }
+ ckfree((char *) containerPtr);
+ }
+}
+
diff --git a/mac/tkMacFont.c b/mac/tkMacFont.c
new file mode 100644
index 0000000..8619880
--- /dev/null
+++ b/mac/tkMacFont.c
@@ -0,0 +1,678 @@
+/*
+ * tkMacFont.c --
+ *
+ * Contains the Macintosh implementation of the platform-independant
+ * font package interface.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS:@(#) tkMacFont.c 1.52 97/11/20 18:29:51
+ */
+
+#include <Windows.h>
+#include <Strings.h>
+#include <Fonts.h>
+#include <Resources.h>
+
+#include "tkMacInt.h"
+#include "tkFont.h"
+#include "tkPort.h"
+
+/*
+ * The following structure represents the Macintosh's' implementation of a
+ * font.
+ */
+
+typedef struct MacFont {
+ TkFont font; /* Stuff used by generic font package. Must
+ * be first in structure. */
+ short family;
+ short size;
+ short style;
+} MacFont;
+
+static GWorldPtr gWorld = NULL;
+
+static TkFont * AllocMacFont _ANSI_ARGS_((TkFont *tkfont,
+ Tk_Window tkwin, int family, int size, int style));
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpGetNativeFont --
+ *
+ * Map a platform-specific native font name to a TkFont.
+ *
+ * Results:
+ * The return value is a pointer to a TkFont that represents the
+ * native font. If a native font by the given name could not be
+ * found, the return value is NULL.
+ *
+ * Every call to this procedure returns a new TkFont structure,
+ * even if the name has already been seen before. The caller should
+ * call TkpDeleteFont() when the font is no longer needed.
+ *
+ * The caller is responsible for initializing the memory associated
+ * with the generic TkFont when this function returns and releasing
+ * the contents of the generics TkFont before calling TkpDeleteFont().
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+TkFont *
+TkpGetNativeFont(
+ Tk_Window tkwin, /* For display where font will be used. */
+ CONST char *name) /* Platform-specific font name. */
+{
+ short family;
+
+ if (strcmp(name, "system") == 0) {
+ family = GetSysFont();
+ } else if (strcmp(name, "application") == 0) {
+ family = GetAppFont();
+ } else {
+ return NULL;
+ }
+
+ return AllocMacFont(NULL, tkwin, family, 0, 0);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpGetFontFromAttributes --
+ *
+ * Given a desired set of attributes for a font, find a font with
+ * the closest matching attributes.
+ *
+ * Results:
+ * The return value is a pointer to a TkFont that represents the
+ * font with the desired attributes. If a font with the desired
+ * attributes could not be constructed, some other font will be
+ * substituted automatically.
+ *
+ * Every call to this procedure returns a new TkFont structure,
+ * even if the specified attributes have already been seen before.
+ * The caller should call TkpDeleteFont() to free the platform-
+ * specific data when the font is no longer needed.
+ *
+ * The caller is responsible for initializing the memory associated
+ * with the generic TkFont when this function returns and releasing
+ * the contents of the generic TkFont before calling TkpDeleteFont().
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+TkFont *
+TkpGetFontFromAttributes(
+ TkFont *tkFontPtr, /* If non-NULL, store the information in
+ * this existing TkFont structure, rather than
+ * allocating a new structure to hold the
+ * font; the existing contents of the font
+ * will be released. If NULL, a new TkFont
+ * structure is allocated. */
+ Tk_Window tkwin, /* For display where font will be used. */
+ CONST TkFontAttributes *faPtr) /* Set of attributes to match. */
+{
+ char buf[257];
+ size_t len;
+ short family, size, style;
+
+ if (faPtr->family == NULL) {
+ family = 0;
+ } else {
+ CONST char *familyName;
+
+ familyName = faPtr->family;
+ if (strcasecmp(familyName, "Times New Roman") == 0) {
+ familyName = "Times";
+ } else if (strcasecmp(familyName, "Courier New") == 0) {
+ familyName = "Courier";
+ } else if (strcasecmp(familyName, "Arial") == 0) {
+ familyName = "Helvetica";
+ }
+
+ len = strlen(familyName);
+ if (len > 255) {
+ len = 255;
+ }
+ buf[0] = (char) len;
+ memcpy(buf + 1, familyName, len);
+ buf[len + 1] = '\0';
+ GetFNum((StringPtr) buf, &family);
+ }
+
+ size = faPtr->pointsize;
+ if (size <= 0) {
+ size = GetDefFontSize();
+ }
+
+ style = 0;
+ if (faPtr->weight != TK_FW_NORMAL) {
+ style |= bold;
+ }
+ if (faPtr->slant != TK_FS_ROMAN) {
+ style |= italic;
+ }
+ if (faPtr->underline) {
+ style |= underline;
+ }
+
+ return AllocMacFont(tkFontPtr, tkwin, family, size, style);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpDeleteFont --
+ *
+ * Called to release a font allocated by TkpGetNativeFont() or
+ * TkpGetFontFromAttributes(). The caller should have already
+ * released the fields of the TkFont that are used exclusively by
+ * the generic TkFont code.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * TkFont is deallocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkpDeleteFont(
+ TkFont *tkFontPtr) /* Token of font to be deleted. */
+{
+ ckfree((char *) tkFontPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkpGetFontFamilies --
+ *
+ * Return information about the font families that are available
+ * on the display of the given window.
+ *
+ * Results:
+ * interp->result is modified to hold a list of all the available
+ * font families.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+TkpGetFontFamilies(
+ Tcl_Interp *interp, /* Interp to hold result. */
+ Tk_Window tkwin) /* For display to query. */
+{
+ MenuHandle fontMenu;
+ int i;
+ char itemText[257];
+
+ fontMenu = NewMenu(1, "\px");
+ AddResMenu(fontMenu, 'FONT');
+
+ for (i = 1; i < CountMItems(fontMenu); i++) {
+ /*
+ * Each item is a pascal string. Convert it to C and append.
+ */
+ GetMenuItemText(fontMenu, i, (unsigned char *) itemText);
+ itemText[itemText[0] + 1] = '\0';
+ Tcl_AppendElement(interp, &itemText[1]);
+ }
+ DisposeMenu(fontMenu);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkMacIsCharacterMissing --
+ *
+ * Given a tkFont and a character determines whether the character has
+ * a glyph defined in the font or not. Note that this is potentially
+ * not compatible with Mac OS 8 as it looks at the font handle
+ * structure directly. Looks into the character array of the font
+ * handle to determine whether the glyph is defined or not.
+ *
+ * Results:
+ * Returns a 1 if the character is missing, a 0 if it is not.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkMacIsCharacterMissing(
+ Tk_Font tkfont, /* The font we are looking in. */
+ unsigned int searchChar) /* The character we are looking for. */
+{
+ MacFont *fontPtr = (MacFont *) tkfont;
+ FMInput fm;
+ FontRec **fontRecHandle;
+
+ fm.family = fontPtr->family;
+ fm.size = fontPtr->size;
+ fm.face = fontPtr->style;
+ fm.needBits = 0;
+ fm.device = 0;
+ fm.numer.h = fm.numer.v = fm.denom.h = fm.denom.v = 1;
+
+ /*
+ * This element of the FMOutput structure was changed between the 2.0 & 3.0
+ * versions of the Universal Headers.
+ */
+
+#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
+ fontRecHandle = (FontRec **) FMSwapFont(&fm)->fontResult;
+#else
+ fontRecHandle = (FontRec **) FMSwapFont(&fm)->fontHandle;
+#endif
+ return *(short *) ((long) &(*fontRecHandle)->owTLoc
+ + ((long)((*fontRecHandle)->owTLoc + searchChar
+ - (*fontRecHandle)->firstChar) * sizeof(short))) == -1;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_MeasureChars --
+ *
+ * Determine the number of characters from the string that will fit
+ * in the given horizontal span. The measurement is done under the
+ * assumption that Tk_DrawChars() will be used to actually display
+ * the characters.
+ *
+ * Results:
+ * The return value is the number of characters from source that
+ * fit into the span that extends from 0 to maxLength. *lengthPtr is
+ * filled with the x-coordinate of the right edge of the last
+ * character that did fit.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Tk_MeasureChars(
+ Tk_Font tkfont, /* Font in which characters will be drawn. */
+ CONST char *source, /* Characters to be displayed. Need not be
+ * '\0' terminated. */
+ int numChars, /* Maximum number of characters to consider
+ * from source string. */
+ int maxLength, /* If > 0, maxLength specifies the longest
+ * permissible line length; don't consider any
+ * character that would cross this
+ * x-position. If <= 0, then line length is
+ * unbounded and the flags argument is
+ * ignored. */
+ int flags, /* Various flag bits OR-ed together:
+ * TK_PARTIAL_OK means include the last char
+ * which only partially fit on this line.
+ * TK_WHOLE_WORDS means stop on a word
+ * boundary, if possible.
+ * TK_AT_LEAST_ONE means return at least one
+ * character even if no characters fit. */
+ int *lengthPtr) /* Filled with x-location just after the
+ * terminating character. */
+{
+ short staticWidths[128];
+ short *widths;
+ CONST char *p, *term;
+ int curX, termX, curIdx, sawNonSpace;
+ MacFont *fontPtr;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+
+ if (numChars == 0) {
+ *lengthPtr = 0;
+ return 0;
+ }
+
+ if (gWorld == NULL) {
+ Rect rect = {0, 0, 1, 1};
+
+ if (NewGWorld(&gWorld, 0, &rect, NULL, NULL, 0) != noErr) {
+ panic("NewGWorld failed in Tk_MeasureChars");
+ }
+ }
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(gWorld, NULL);
+
+ fontPtr = (MacFont *) tkfont;
+ TextFont(fontPtr->family);
+ TextSize(fontPtr->size);
+ TextFace(fontPtr->style);
+
+ if (maxLength <= 0) {
+ *lengthPtr = TextWidth(source, 0, numChars);
+ SetGWorld(saveWorld, saveDevice);
+ return numChars;
+ }
+
+ if (numChars > maxLength) {
+ /*
+ * Assume that all chars are at least 1 pixel wide, so there's no
+ * need to measure more characters than there are pixels. This
+ * assumption could be refined to an iterative approach that would
+ * use that as a starting point and try more chars if necessary (if
+ * there actually were some zero-width chars).
+ */
+
+ numChars = maxLength;
+ }
+ if (numChars > SHRT_MAX) {
+ /*
+ * If they are trying to measure more than 32767 chars at one time,
+ * it would require several separate measurements.
+ */
+
+ numChars = SHRT_MAX;
+ }
+
+ widths = staticWidths;
+ if (numChars >= sizeof(staticWidths) / sizeof(staticWidths[0])) {
+ widths = (short *) ckalloc((numChars + 1) * sizeof(short));
+ }
+
+ MeasureText((short) numChars, source, widths);
+
+ if (widths[numChars] <= maxLength) {
+ curX = widths[numChars];
+ curIdx = numChars;
+ } else {
+ p = term = source;
+ curX = termX = 0;
+
+ sawNonSpace = !isspace(UCHAR(*p));
+ for (curIdx = 1; ; curIdx++) {
+ if (isspace(UCHAR(*p))) {
+ if (sawNonSpace) {
+ term = p;
+ termX = widths[curIdx - 1];
+ sawNonSpace = 0;
+ }
+ } else {
+ sawNonSpace = 1;
+ }
+ if (widths[curIdx] > maxLength) {
+ curIdx--;
+ curX = widths[curIdx];
+ break;
+ }
+ p++;
+ }
+ if (flags & TK_PARTIAL_OK) {
+ curIdx++;
+ curX = widths[curIdx];
+ }
+ if ((curIdx == 0) && (flags & TK_AT_LEAST_ONE)) {
+ /*
+ * The space was too small to hold even one character. Since at
+ * least one character must always fit on a line, return the width
+ * of the first character.
+ */
+
+ curX = TextWidth(source, 0, 1);
+ curIdx = 1;
+ } else if (flags & TK_WHOLE_WORDS) {
+ /*
+ * Break at last word that fits on the line.
+ */
+
+ if ((flags & TK_AT_LEAST_ONE) && (term == source)) {
+ /*
+ * The space was too small to hold an entire word. This
+ * is the only word on the line, so just return the part of th
+ * word that fit.
+ */
+
+ ;
+ } else {
+ curIdx = term - source;
+ curX = termX;
+ }
+ }
+ }
+
+ if (widths != staticWidths) {
+ ckfree((char *) widths);
+ }
+
+ *lengthPtr = curX;
+
+ SetGWorld(saveWorld, saveDevice);
+
+ return curIdx;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_DrawChars --
+ *
+ * Draw a string of characters on the screen.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets drawn on the screen.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Tk_DrawChars(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Tk_Font tkfont, /* Font in which characters will be drawn;
+ * must be the same as font used in GC. */
+ CONST char *source, /* Characters to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are
+ * not stripped out, they will be displayed as
+ * regular printing characters. */
+ int numChars, /* Number of characters in string. */
+ int x, int y) /* Coordinates at which to place origin of
+ * string when drawing. */
+{
+ MacFont *fontPtr;
+ MacDrawable *macWin;
+ RGBColor macColor, origColor;
+ GWorldPtr destPort;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ short txFont, txFace, txSize;
+ BitMapPtr stippleMap;
+
+ fontPtr = (MacFont *) tkfont;
+ macWin = (MacDrawable *) drawable;
+
+ destPort = TkMacGetDrawablePort(drawable);
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ TkMacSetUpClippingRgn(drawable);
+ TkMacSetUpGraphicsPort(gc);
+
+ txFont = tcl_macQdPtr->thePort->txFont;
+ txFace = tcl_macQdPtr->thePort->txFace;
+ txSize = tcl_macQdPtr->thePort->txSize;
+ GetForeColor(&origColor);
+
+ if ((gc->fill_style == FillStippled
+ || gc->fill_style == FillOpaqueStippled)
+ && gc->stipple != None) {
+ Pixmap pixmap;
+ GWorldPtr bufferPort;
+
+ stippleMap = TkMacMakeStippleMap(drawable, gc->stipple);
+
+ pixmap = Tk_GetPixmap(display, drawable,
+ stippleMap->bounds.right, stippleMap->bounds.bottom, 0);
+
+ bufferPort = TkMacGetDrawablePort(pixmap);
+ SetGWorld(bufferPort, NULL);
+
+ TextFont(fontPtr->family);
+ TextSize(fontPtr->size);
+ TextFace(fontPtr->style);
+
+ if (TkSetMacColor(gc->foreground, &macColor) == true) {
+ RGBForeColor(&macColor);
+ }
+
+ ShowPen();
+ MoveTo((short) 0, (short) 0);
+ FillRect(&stippleMap->bounds, &tcl_macQdPtr->white);
+ MoveTo((short) x, (short) y);
+ DrawText(source, 0, (short) numChars);
+
+ SetGWorld(destPort, NULL);
+ CopyDeepMask(&((GrafPtr) bufferPort)->portBits, stippleMap,
+ &((GrafPtr) destPort)->portBits, &stippleMap->bounds,
+ &stippleMap->bounds, &((GrafPtr) destPort)->portRect,
+ srcOr, NULL);
+
+ /* TODO: this doesn't work quite right - it does a blend. you can't
+ * draw white text when you have a stipple.
+ */
+
+ Tk_FreePixmap(display, pixmap);
+ ckfree(stippleMap->baseAddr);
+ ckfree((char *)stippleMap);
+ } else {
+ TextFont(fontPtr->family);
+ TextSize(fontPtr->size);
+ TextFace(fontPtr->style);
+
+ if (TkSetMacColor(gc->foreground, &macColor) == true) {
+ RGBForeColor(&macColor);
+ }
+
+ ShowPen();
+ MoveTo((short) (macWin->xOff + x), (short) (macWin->yOff + y));
+ DrawText(source, 0, (short) numChars);
+ }
+
+ TextFont(txFont);
+ TextSize(txSize);
+ TextFace(txFace);
+ RGBForeColor(&origColor);
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AllocMacFont --
+ *
+ * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
+ * Allocates and intializes the memory for a new TkFont that
+ * wraps the platform-specific data.
+ *
+ * Results:
+ * Returns pointer to newly constructed TkFont.
+ *
+ * The caller is responsible for initializing the fields of the
+ * TkFont that are used exclusively by the generic TkFont code, and
+ * for releasing those fields before calling TkpDeleteFont().
+ *
+ * Side effects:
+ * Memory allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static TkFont *
+AllocMacFont(
+ TkFont *tkFontPtr, /* If non-NULL, store the information in
+ * this existing TkFont structure, rather than
+ * allocating a new structure to hold the
+ * font; the existing contents of the font
+ * will be released. If NULL, a new TkFont
+ * structure is allocated. */
+ Tk_Window tkwin, /* For display where font will be used. */
+ int family, /* Macintosh font family. */
+ int size, /* Point size for Macintosh font. */
+ int style) /* Macintosh style bits. */
+{
+ char buf[257];
+ FontInfo fi;
+ MacFont *fontPtr;
+ TkFontAttributes *faPtr;
+ TkFontMetrics *fmPtr;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+
+ if (gWorld == NULL) {
+ Rect rect = {0, 0, 1, 1};
+
+ if (NewGWorld(&gWorld, 0, &rect, NULL, NULL, 0) != noErr) {
+ panic("NewGWorld failed in AllocMacFont");
+ }
+ }
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(gWorld, NULL);
+
+ if (tkFontPtr == NULL) {
+ fontPtr = (MacFont *) ckalloc(sizeof(MacFont));
+ } else {
+ fontPtr = (MacFont *) tkFontPtr;
+ }
+
+ fontPtr->font.fid = (Font) fontPtr;
+
+ faPtr = &fontPtr->font.fa;
+ GetFontName(family, (StringPtr) buf);
+ buf[UCHAR(buf[0]) + 1] = '\0';
+ faPtr->family = Tk_GetUid(buf + 1);
+ faPtr->pointsize = size;
+ faPtr->weight = (style & bold) ? TK_FW_BOLD : TK_FW_NORMAL;
+ faPtr->slant = (style & italic) ? TK_FS_ITALIC : TK_FS_ROMAN;
+ faPtr->underline = ((style & underline) != 0);
+ faPtr->overstrike = 0;
+
+ fmPtr = &fontPtr->font.fm;
+ TextFont(family);
+ TextSize(size);
+ TextFace(style);
+ GetFontInfo(&fi);
+ fmPtr->ascent = fi.ascent;
+ fmPtr->descent = fi.descent;
+ fmPtr->maxWidth = fi.widMax;
+ fmPtr->fixed = (CharWidth('i') == CharWidth('w'));
+
+ fontPtr->family = (short) family;
+ fontPtr->size = (short) size;
+ fontPtr->style = (short) style;
+
+ SetGWorld(saveWorld, saveDevice);
+
+ return (TkFont *) fontPtr;
+}
+
diff --git a/mac/tkMacHLEvents.c b/mac/tkMacHLEvents.c
new file mode 100644
index 0000000..39f7836
--- /dev/null
+++ b/mac/tkMacHLEvents.c
@@ -0,0 +1,437 @@
+/*
+ * tkMacHLEvents.c --
+ *
+ * Implements high level event support for the Macintosh. Currently,
+ * the only event that really does anything is the Quit event.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacHLEvents.c 1.21 97/09/17 17:19:00
+ */
+
+#include "tcl.h"
+#include "tclMacInt.h"
+#include "tkMacInt.h"
+
+#include <Aliases.h>
+#include <AppleEvents.h>
+#include <SegLoad.h>
+#include <ToolUtils.h>
+
+/*
+ * This is a Tcl_Event structure that the Quit AppleEvent handler
+ * uses to schedule the tkReallyKillMe function.
+ */
+
+typedef struct KillEvent {
+ Tcl_Event header; /* Information that is standard for
+ * all events. */
+ Tcl_Interp *interp; /* Interp that was passed to the
+ * Quit AppleEvent */
+} KillEvent;
+
+/*
+ * Static functions used only in this file.
+ */
+
+static pascal OSErr QuitHandler _ANSI_ARGS_((AppleEvent* event,
+ AppleEvent* reply, long refcon));
+static pascal OSErr OappHandler _ANSI_ARGS_((AppleEvent* event,
+ AppleEvent* reply, long refcon));
+static pascal OSErr OdocHandler _ANSI_ARGS_((AppleEvent* event,
+ AppleEvent* reply, long refcon));
+static pascal OSErr PrintHandler _ANSI_ARGS_((AppleEvent* event,
+ AppleEvent* reply, long refcon));
+static pascal OSErr ScriptHandler _ANSI_ARGS_((AppleEvent* event,
+ AppleEvent* reply, long refcon));
+static int MissedAnyParameters _ANSI_ARGS_((AppleEvent *theEvent));
+static int ReallyKillMe _ANSI_ARGS_((Tcl_Event *eventPtr, int flags));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacInitAppleEvents --
+ *
+ * Initilize the Apple Events on the Macintosh. This registers the
+ * core event handlers.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacInitAppleEvents(
+ Tcl_Interp *interp) /* Interp to handle basic events. */
+{
+ OSErr err;
+ AEEventHandlerUPP OappHandlerUPP, OdocHandlerUPP,
+ PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP;
+
+ /*
+ * Install event handlers for the core apple events.
+ */
+ QuitHandlerUPP = NewAEEventHandlerProc(QuitHandler);
+ err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
+ QuitHandlerUPP, (long) interp, false);
+
+ OappHandlerUPP = NewAEEventHandlerProc(OappHandler);
+ err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
+ OappHandlerUPP, (long) interp, false);
+
+ OdocHandlerUPP = NewAEEventHandlerProc(OdocHandler);
+ err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
+ OdocHandlerUPP, (long) interp, false);
+
+ PrintHandlerUPP = NewAEEventHandlerProc(PrintHandler);
+ err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
+ PrintHandlerUPP, (long) interp, false);
+
+ if (interp != NULL) {
+ ScriptHandlerUPP = NewAEEventHandlerProc(ScriptHandler);
+ err = AEInstallEventHandler('misc', 'dosc',
+ ScriptHandlerUPP, (long) interp, false);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacDoHLEvent --
+ *
+ * Dispatch incomming highlevel events.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the incoming event.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacDoHLEvent(
+ EventRecord *theEvent)
+{
+ AEProcessAppleEvent(theEvent);
+
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * QuitHandler, OappHandler, etc. --
+ *
+ * These are the core Apple event handlers. Only the Quit event does
+ * anything interesting.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal OSErr
+QuitHandler(
+ AppleEvent *theAppleEvent,
+ AppleEvent *reply,
+ long handlerRefcon)
+{
+ Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
+ KillEvent *eventPtr;
+
+ /*
+ * Call the exit command from the event loop, since you are not supposed
+ * to call ExitToShell in an Apple Event Handler. We put this at the head
+ * of Tcl's event queue because this message usually comes when the Mac is
+ * shutting down, and we want to kill the shell as quickly as possible.
+ */
+
+ eventPtr = (KillEvent *) ckalloc(sizeof(KillEvent));
+ eventPtr->header.proc = ReallyKillMe;
+ eventPtr->interp = interp;
+
+ Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);
+
+ return noErr;
+}
+
+static pascal OSErr
+OappHandler(
+ AppleEvent *theAppleEvent,
+ AppleEvent *reply,
+ long handlerRefcon)
+{
+ return noErr;
+}
+
+static pascal OSErr
+OdocHandler(
+ AppleEvent *theAppleEvent,
+ AppleEvent *reply,
+ long handlerRefcon)
+{
+ Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
+ AEDescList fileSpecList;
+ FSSpec file;
+ OSErr err;
+ DescType type;
+ Size actual;
+ long count;
+ AEKeyword keyword;
+ long index;
+ Tcl_DString command;
+ Tcl_DString pathName;
+ Tcl_CmdInfo dummy;
+
+ /*
+ * Don't bother if we don't have an interp or
+ * the open document procedure doesn't exist.
+ */
+
+ if ((interp == NULL) ||
+ (Tcl_GetCommandInfo(interp, "tkOpenDocument", &dummy)) == 0) {
+ return noErr;
+ }
+
+ /*
+ * If we get any errors wil retrieving our parameters
+ * we just return with no error.
+ */
+
+ err = AEGetParamDesc(theAppleEvent, keyDirectObject,
+ typeAEList, &fileSpecList);
+ if (err != noErr) {
+ return noErr;
+ }
+
+ err = MissedAnyParameters(theAppleEvent);
+ if (err != noErr) {
+ return noErr;
+ }
+
+ err = AECountItems(&fileSpecList, &count);
+ if (err != noErr) {
+ return noErr;
+ }
+
+ Tcl_DStringInit(&command);
+ Tcl_DStringInit(&pathName);
+ Tcl_DStringAppend(&command, "tkOpenDocument", -1);
+ for (index = 1; index <= count; index++) {
+ int length;
+ Handle fullPath;
+
+ Tcl_DStringSetLength(&pathName, 0);
+ err = AEGetNthPtr(&fileSpecList, index, typeFSS,
+ &keyword, &type, (Ptr) &file, sizeof(FSSpec), &actual);
+ if ( err != noErr ) {
+ continue;
+ }
+
+ err = FSpPathFromLocation(&file, &length, &fullPath);
+ HLock(fullPath);
+ Tcl_DStringAppend(&pathName, *fullPath, length);
+ HUnlock(fullPath);
+ DisposeHandle(fullPath);
+
+ Tcl_DStringAppendElement(&command, pathName.string);
+ }
+
+ Tcl_GlobalEval(interp, command.string);
+
+ Tcl_DStringFree(&command);
+ Tcl_DStringFree(&pathName);
+ return noErr;
+}
+
+static pascal OSErr
+PrintHandler(
+ AppleEvent *theAppleEvent,
+ AppleEvent *reply,
+ long handlerRefcon)
+{
+ return noErr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DoScriptHandler --
+ *
+ * This handler process the do script event.
+ *
+ * Results:
+ * Scedules the given event to be processed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pascal OSErr
+ScriptHandler(
+ AppleEvent *theAppleEvent,
+ AppleEvent *reply,
+ long handlerRefcon)
+{
+ OSErr theErr;
+ AEDescList theDesc;
+ int tclErr = -1;
+ Tcl_Interp *interp;
+ char errString[128];
+
+ interp = (Tcl_Interp *) handlerRefcon;
+
+ /*
+ * The do script event receives one parameter that should be data or a file.
+ */
+ theErr = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard,
+ &theDesc);
+ if (theErr != noErr) {
+ sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", theErr);
+ theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString,
+ strlen(errString));
+ } else if (MissedAnyParameters(theAppleEvent)) {
+ sprintf(errString, "AEDoScriptHandler: extra parameters");
+ AEPutParamPtr(reply, keyErrorString, typeChar, errString,
+ strlen(errString));
+ theErr = -1771;
+ } else {
+ if (theDesc.descriptorType == (DescType)'TEXT') {
+ short length, i;
+
+ length = GetHandleSize(theDesc.dataHandle);
+ SetHandleSize(theDesc.dataHandle, length + 1);
+ *(*theDesc.dataHandle + length) = '\0';
+ for (i=0; i<length; i++) {
+ if ((*theDesc.dataHandle)[i] == '\r') {
+ (*theDesc.dataHandle)[i] = '\n';
+ }
+ }
+
+ HLock(theDesc.dataHandle);
+ tclErr = Tcl_GlobalEval(interp, *theDesc.dataHandle);
+ HUnlock(theDesc.dataHandle);
+ } else if (theDesc.descriptorType == (DescType)'alis') {
+ Boolean dummy;
+ FSSpec theFSS;
+ Handle fullPath;
+ int length;
+
+ theErr = ResolveAlias(NULL, (AliasHandle)theDesc.dataHandle,
+ &theFSS, &dummy);
+ if (theErr == noErr) {
+ FSpPathFromLocation(&theFSS, &length, &fullPath);
+ HLock(fullPath);
+ Tcl_EvalFile(interp, *fullPath);
+ HUnlock(fullPath);
+ DisposeHandle(fullPath);
+ } else {
+ sprintf(errString, "AEDoScriptHandler: file not found");
+ AEPutParamPtr(reply, keyErrorString, typeChar,
+ errString, strlen(errString));
+ }
+ } else {
+ sprintf(errString,
+ "AEDoScriptHandler: invalid script type '%-4.4s', must be 'alis' or 'TEXT'",
+ &theDesc.descriptorType);
+ AEPutParamPtr(reply, keyErrorString, typeChar,
+ errString, strlen(errString));
+ theErr = -1770;
+ }
+ }
+
+ /*
+ * If we actually go to run Tcl code - put the result in the reply.
+ */
+ if (tclErr >= 0) {
+ if (tclErr == TCL_OK) {
+ AEPutParamPtr(reply, keyDirectObject, typeChar,
+ interp->result, strlen(interp->result));
+ } else {
+ AEPutParamPtr(reply, keyErrorString, typeChar,
+ interp->result, strlen(interp->result));
+ AEPutParamPtr(reply, keyErrorNumber, typeInteger,
+ (Ptr) &tclErr, sizeof(int));
+ }
+ }
+
+ AEDisposeDesc(&theDesc);
+
+ return theErr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReallyKillMe --
+ *
+ * This proc tries to kill the shell by running exit, and if that
+ * has not succeeded (e.g. because someone has renamed the exit
+ * command), calls Tcl_Exit to really kill the shell. Called from
+ * an event scheduled by the "Quit" AppleEvent handler.
+ *
+ * Results:
+ * Kills the shell.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+ReallyKillMe(Tcl_Event *eventPtr, int flags)
+{
+ Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp;
+ if (interp != NULL) {
+ Tcl_GlobalEval(interp, "exit");
+ }
+ Tcl_Exit(0);
+
+ return 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MissedAnyParameters --
+ *
+ * Checks to see if parameters are still left in the event.
+ *
+ * Results:
+ * True or false.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MissedAnyParameters(
+ AppleEvent *theEvent)
+{
+ DescType returnedType;
+ Size actualSize;
+ OSErr err;
+
+ err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr, typeWildCard,
+ &returnedType, NULL, 0, &actualSize);
+
+ return (err != errAEDescNotFound);
+}
diff --git a/mac/tkMacInit.c b/mac/tkMacInit.c
new file mode 100644
index 0000000..bb1f8b3
--- /dev/null
+++ b/mac/tkMacInit.c
@@ -0,0 +1,240 @@
+/*
+ * tkMacInit.c --
+ *
+ * This file contains Mac-specific interpreter initialization
+ * functions.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacInit.c 1.30 96/12/17 15:20:16
+ */
+
+#include <Resources.h>
+#include <Files.h>
+#include <TextUtils.h>
+#include <Strings.h>
+#include "tkInt.h"
+#include "tkMacInt.h"
+#include "tclMacInt.h"
+
+/*
+ * The following global is used by various parts of Tk to access
+ * information in the global qd variable. It is provided as a pointer
+ * in the AppInit because we don't assume that Tk is running as an
+ * application. For example, Tk could be a plugin and may not have
+ * access to the qd variable. This mechanism provides a way for the
+ * container application to give a pointer to the qd variable.
+ */
+
+QDGlobalsPtr tcl_macQdPtr = NULL;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpInit --
+ *
+ * Performs Mac-specific interpreter initialization related to the
+ * tk_library variable.
+ *
+ * Results:
+ * A standard Tcl completion code (TCL_OK or TCL_ERROR). Also
+ * leaves information in interp->result.
+ *
+ * Side effects:
+ * Sets "tk_library" Tcl variable, runs initialization scripts
+ * for Tk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpInit(
+ Tcl_Interp *interp) /* Interp to initialize. */
+{
+ char *libDir, *tempPath;
+ Tcl_DString path;
+ int result;
+
+ /*
+ * The following does not work with
+ * safe interps because file exists is restricted.
+ * to be fixed using [interp issafe] like in Unix & Windows.
+ */
+ static char initCmd[] =
+ "if [file exists $tk_library:tk.tcl] {\n\
+ source $tk_library:tk.tcl\n\
+ source $tk_library:button.tcl\n\
+ source $tk_library:entry.tcl\n\
+ source $tk_library:listbox.tcl\n\
+ source $tk_library:menu.tcl\n\
+ source $tk_library:scale.tcl\n\
+ source $tk_library:scrlbar.tcl\n\
+ source $tk_library:text.tcl\n\
+ source $tk_library:comdlg.tcl\n\
+ source $tk_library:msgbox.tcl\n\
+ } else {\n\
+ set msg \"can't find tk resource or $tk_library:tk.tcl;\"\n\
+ append msg \" perhaps you need to\\ninstall Tk or set your \"\n\
+ append msg \"TK_LIBRARY environment variable?\"\n\
+ error $msg\n\
+ }";
+
+ Tcl_DStringInit(&path);
+
+ /*
+ * The tk_library path can be found in several places. Here is the order
+ * in which the are searched.
+ * 1) the variable may already exist
+ * 2) env array
+ * 3) System Folder:Extensions:Tool Command Language:
+ */
+
+ libDir = Tcl_GetVar(interp, "tk_library", TCL_GLOBAL_ONLY);
+ if (libDir == NULL) {
+ libDir = Tcl_GetVar2(interp, "env", "TK_LIBRARY", TCL_GLOBAL_ONLY);
+ }
+ if (libDir == NULL) {
+ tempPath = Tcl_GetVar2(interp, "env", "EXT_FOLDER", TCL_GLOBAL_ONLY);
+ if (tempPath != NULL) {
+ Tcl_DString libPath;
+
+ Tcl_JoinPath(1, &tempPath, &path);
+
+ Tcl_DStringInit(&libPath);
+ Tcl_DStringAppend(&libPath, ":Tool Command Language:tk", -1);
+ Tcl_DStringAppend(&libPath, TK_VERSION, -1);
+ Tcl_JoinPath(1, &libPath.string, &path);
+ Tcl_DStringFree(&libPath);
+ libDir = path.string;
+ }
+ }
+ if (libDir == NULL) {
+ libDir = "no library";
+ }
+
+ /*
+ * Assign path to the global Tcl variable tcl_library.
+ */
+ Tcl_SetVar(interp, "tk_library", libDir, TCL_GLOBAL_ONLY);
+ Tcl_DStringFree(&path);
+
+ /*
+ * Source the needed Tk libraries from the resource
+ * fork of the application.
+ */
+ result = Tcl_MacEvalResource(interp, "tk", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "button", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "entry", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "listbox", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "menu", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "scale", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "scrollbar", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "text", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "dialog", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "focus", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "optionMenu", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "palette", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "tearoff", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "tkerror", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "comdlg", 0, NULL);
+ result |= Tcl_MacEvalResource(interp, "msgbox", 0, NULL);
+
+ if (result != TCL_OK) {
+ result = Tcl_Eval(interp, initCmd);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetAppName --
+ *
+ * Retrieves the name of the current application from a platform
+ * specific location. On the Macintosh we look to see if the
+ * App Name is specified in a resource. If not, the application
+ * name is the root of the tail of the path contained in the tcl
+ * variable argv0.
+ *
+ * Results:
+ * Returns the application name in the given Tcl_DString.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpGetAppName(
+ Tcl_Interp *interp, /* The main interpreter. */
+ Tcl_DString *namePtr) /* A previously initialized Tcl_DString. */
+{
+ int argc;
+ char **argv = NULL, *name, *p;
+ Handle h = NULL;
+
+ h = GetNamedResource('STR ', "\pTk App Name");
+ if (h != NULL) {
+ HLock(h);
+ Tcl_DStringAppend(namePtr, (*h)+1, **h);
+ HUnlock(h);
+ ReleaseResource(h);
+ return;
+ }
+
+ name = Tcl_GetVar(interp, "argv0", TCL_GLOBAL_ONLY);
+ if (name != NULL) {
+ Tcl_SplitPath(name, &argc, &argv);
+ if (argc > 0) {
+ name = argv[argc-1];
+ p = strrchr(name, '.');
+ if (p != NULL) {
+ *p = '\0';
+ }
+ } else {
+ name = NULL;
+ }
+ }
+ if ((name == NULL) || (*name == 0)) {
+ name = "tk";
+ }
+ Tcl_DStringAppend(namePtr, name, -1);
+ if (argv != NULL) {
+ ckfree((char *)argv);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDisplayWarning --
+ *
+ * This routines is called from Tk_Main to display warning
+ * messages that occur during startup.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Displays a message box.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDisplayWarning(
+ char *msg, /* Message to be displayed. */
+ char *title) /* Title of warning. */
+{
+ Tcl_DString ds;
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, title, -1);
+ Tcl_DStringAppend(&ds, ": ", -1);
+ Tcl_DStringAppend(&ds, msg, -1);
+ panic(Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+}
diff --git a/mac/tkMacInt.h b/mac/tkMacInt.h
new file mode 100644
index 0000000..fcb8174
--- /dev/null
+++ b/mac/tkMacInt.h
@@ -0,0 +1,282 @@
+/*
+ * tkMacInt.h --
+ *
+ * Declarations of Macintosh specific shared variables and procedures.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacInt.h 1.67 97/11/20 18:30:38
+ */
+
+#ifndef _TKMACINT
+#define _TKMACINT
+
+#include "tkInt.h"
+#include "tkPort.h"
+
+#ifndef _TKMAC
+# include "tkMac.h"
+#endif /* _TKMAC */
+
+
+#include <AppleEvents.h>
+#include <Windows.h>
+#include <QDOffscreen.h>
+#include <Menus.h>
+
+#define TK_MAC_68K_STACK_GROWTH (256*1024)
+
+struct TkWindowPrivate {
+ TkWindow *winPtr; /* Ptr to tk window or NULL if Pixmap */
+ GWorldPtr portPtr; /* Either WindowRef or off screen world */
+ int xOff; /* X offset from toplevel window */
+ int yOff; /* Y offset from toplevel window */
+ RgnHandle clipRgn; /* Visable region of window */
+ RgnHandle aboveClipRgn; /* Visable region of window & it's children */
+ int referenceCount; /* Don't delete toplevel until children are
+ * gone. */
+ struct TkWindowPrivate *toplevel; /* Pointer to the toplevel
+ * datastruct. */
+ int flags; /* Various state see defines below. */
+};
+typedef struct TkWindowPrivate MacDrawable;
+
+/*
+ * This list is used to keep track of toplevel windows that have a Mac
+ * window attached. This is useful for several things, not the least
+ * of which is maintaining floating windows.
+ */
+
+typedef struct TkMacWindowList {
+ struct TkMacWindowList *nextPtr; /* The next window in the list. */
+ TkWindow *winPtr; /* This window */
+} TkMacWindowList;
+
+/*
+ * Defines use for the flags field of the MacDrawable data structure.
+ */
+
+#define TK_SCROLLBAR_GROW 1
+#define TK_CLIP_INVALID 2
+#define TK_HOST_EXISTS 4
+#define TK_DRAWN_UNDER_MENU 8
+
+/*
+ * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags
+ * This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the
+ * TkWindow structure for the window, but in the MacWin. This way we can still tell
+ * what the correct port is after the TKWindow structure has been freed. This
+ * actually happens when you bind destroy of a toplevel to Destroy of a child.
+ */
+
+/*
+ * Defines used for TkMacInvalidateWindow
+ */
+
+#define TK_WINDOW_ONLY 0
+#define TK_PARENT_WINDOW 1
+
+/*
+ * Accessor for the privatePtr flags field for the TK_HOST_EXISTS field
+ */
+
+#define TkMacHostToplevelExists(tkwin) \
+ (((TkWindow *) (tkwin))->privatePtr->toplevel->flags & TK_HOST_EXISTS)
+
+/*
+ * Defines use for the flags argument to TkGenWMConfigureEvent.
+ */
+
+#define TK_LOCATION_CHANGED 1
+#define TK_SIZE_CHANGED 2
+#define TK_BOTH_CHANGED 3
+
+/*
+ * Variables shared among various Mac Tk modules but are not
+ * exported to the outside world.
+ */
+
+extern int tkMacAppInFront;
+
+/*
+ * Globals shared among Macintosh Tk
+ */
+
+extern MenuHandle tkAppleMenu; /* Handle to the Apple Menu */
+extern MenuHandle tkFileMenu; /* Handles to menus */
+extern MenuHandle tkEditMenu; /* Handles to menus */
+extern RgnHandle tkMenuCascadeRgn; /* A region to clip with. */
+extern int tkUseMenuCascadeRgn; /* If this is 1, clipping code
+ * should intersect tkMenuCascadeRgn
+ * before drawing occurs.
+ * tkMenuCascadeRgn will only
+ * be valid when the value of this
+ * variable is 1. */
+extern TkMacWindowList *tkMacWindowListPtr;
+ /* The list of toplevels */
+
+/*
+ * The following types and defines are for MDEF support.
+ */
+
+#if STRUCTALIGNMENTSUPPORTED
+#pragma options align=mac8k
+#endif
+typedef struct TkMenuLowMemGlobals {
+ long menuDisable; /* A combination of the menu and the item
+ * that the mouse is currently over. */
+ short menuTop; /* Where in global coords the top of the
+ * menu is. */
+ short menuBottom; /* Where in global coords the bottom of
+ * the menu is. */
+ Rect itemRect; /* This is the rectangle of the currently
+ * selected item. */
+ short scrollFlag; /* This is used by the MDEF and the
+ * Menu Manager to control when scrolling
+ * starts. With hierarchicals, an
+ * mChooseMsg can come before an
+ * mDrawMsg, and scrolling should not
+ * occur until after the mDrawMsg.
+ * The mDrawMsg sets this flag;
+ * mChooseMsg checks the flag and
+ * does not scroll if it is set;
+ * and then resets the flag. */
+} TkMenuLowMemGlobals;
+#if STRUCTALIGNMENTSUPPORTED
+#pragma options align=reset
+#endif
+
+typedef pascal void (*TkMenuDefProcPtr) (short message, MenuHandle theMenu,
+ Rect *menuRectPtr, Point hitPt, short *whichItemPtr,
+ TkMenuLowMemGlobals *globalsPtr);
+enum {
+ tkUppMenuDefProcInfo = kPascalStackBased
+ | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
+ | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(MenuRef)))
+ | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Rect*)))
+ | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(Point)))
+ | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(short*)))
+ | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(TkMenuLowMemGlobals *)))
+};
+
+#if GENERATINGCFM
+typedef UniversalProcPtr TkMenuDefUPP;
+#else
+typedef TkMenuDefProcPtr TkMenuDefUPP;
+#endif
+
+#if GENERATINGCFM
+#define TkNewMenuDefProc(userRoutine) \
+ (TkMenuDefUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), \
+ tkUppMenuDefProcInfo, GetCurrentArchitecture())
+#else
+#define TkNewMenuDefProc(userRoutine) \
+ ((TkMenuDefUPP) (userRoutine))
+#endif
+
+#if GENERATINGCFM
+#define TkCallMenuDefProc(userRoutine, message, theMenu, menuRectPtr, hitPt, \
+ whichItemPtr, globalsPtr) \
+ CallUniversalProc((UniversalProcPtr)(userRoutine), TkUppMenuDefProcInfo, \
+ (message), (theMenu), (menuRectPtr), (hitPt), (whichItemPtr), \
+ (globalsPtr))
+#else
+#define TkCallMenuDefProc(userRoutine, message, theMenu, menuRectPtr, hitPt, \
+ whichItemPtr, globalsPtr) \
+ (*(userRoutine))((message), (theMenu), (menuRectPtr), (hitPt), \
+ (whichItemPtr), (globalsPtr))
+#endif
+
+/*
+ * Internal procedures shared among Macintosh Tk modules but not exported
+ * to the outside world:
+ */
+
+extern int HandleWMEvent _ANSI_ARGS_((EventRecord *theEvent));
+extern void TkAboutDlg _ANSI_ARGS_((void));
+extern void TkCreateMacEventSource _ANSI_ARGS_((void));
+extern void TkFontList _ANSI_ARGS_((Tcl_Interp *interp,
+ Display *display));
+extern Window TkGetTransientMaster _ANSI_ARGS_((TkWindow *winPtr));
+extern int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y,
+ Window window, unsigned int state));
+extern int TkGetCharPositions _ANSI_ARGS_((
+ XFontStruct *font_struct, char *string,
+ int count, short *buffer));
+extern void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin));
+extern void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin,
+ int x, int y, int width, int height, int flags));
+extern unsigned int TkMacButtonKeyState _ANSI_ARGS_((void));
+extern void TkMacClearMenubarActive _ANSI_ARGS_((void));
+extern int TkMacConvertEvent _ANSI_ARGS_((EventRecord *eventPtr));
+extern int TkMacDispatchMenuEvent _ANSI_ARGS_((int menuID,
+ int index));
+extern void TkMacInstallCursor _ANSI_ARGS_((int resizeOverride));
+extern int TkMacConvertTkEvent _ANSI_ARGS_((EventRecord *eventPtr,
+ Window window));
+extern void TkMacHandleTearoffMenu _ANSI_ARGS_((void));
+extern void tkMacInstallMWConsole _ANSI_ARGS_((
+ Tcl_Interp *interp));
+extern void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow *winPtr));
+extern void TkMacDoHLEvent _ANSI_ARGS_((EventRecord *theEvent));
+extern void TkMacFontInfo _ANSI_ARGS_((Font fontId, short *family,
+ short *style, short *size));
+extern Time TkMacGenerateTime _ANSI_ARGS_(());
+extern GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable));
+extern TkWindow * TkMacGetScrollbarGrowWindow _ANSI_ARGS_((
+ TkWindow *winPtr));
+extern Window TkMacGetXWindow _ANSI_ARGS_((WindowRef macWinPtr));
+extern int TkMacGrowToplevel _ANSI_ARGS_((WindowRef whichWindow,
+ Point start));
+extern void TkMacHandleMenuSelect _ANSI_ARGS_((long mResult,
+ int optionKeyPressed));
+extern void TkMacInitAppleEvents _ANSI_ARGS_((Tcl_Interp *interp));
+extern void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp *interp));
+extern void TkMacInvalidateWindow _ANSI_ARGS_((MacDrawable *macWin, int flag));
+extern int TkMacIsCharacterMissing _ANSI_ARGS_((Tk_Font tkfont,
+ unsigned int searchChar));
+extern void TkMacMakeRealWindowExist _ANSI_ARGS_((
+ TkWindow *winPtr));
+extern BitMapPtr TkMacMakeStippleMap(Drawable, Drawable);
+extern void TkMacMenuClick _ANSI_ARGS_((void));
+extern void TkMacRegisterOffScreenWindow _ANSI_ARGS_((Window window,
+ GWorldPtr portPtr));
+extern int TkMacResizable _ANSI_ARGS_((TkWindow *winPtr));
+extern void TkMacSetEmbedRgn _ANSI_ARGS_((TkWindow *winPtr, RgnHandle rgn));
+extern void TkMacSetHelpMenuItemCount _ANSI_ARGS_((void));
+extern void TkMacSetScrollbarGrow _ANSI_ARGS_((TkWindow *winPtr,
+ int flag));
+extern void TkMacSetUpClippingRgn _ANSI_ARGS_((Drawable drawable));
+extern void TkMacSetUpGraphicsPort _ANSI_ARGS_((GC gc));
+extern void TkMacUpdateClipRgn _ANSI_ARGS_((TkWindow *winPtr));
+extern void TkMacUnregisterMacWindow _ANSI_ARGS_((GWorldPtr portPtr));
+extern int TkMacUseMenuID _ANSI_ARGS_((short macID));
+extern RgnHandle TkMacVisableClipRgn _ANSI_ARGS_((TkWindow *winPtr));
+extern void TkMacWinBounds _ANSI_ARGS_((TkWindow *winPtr,
+ Rect *geometry));
+extern void TkMacWindowOffset _ANSI_ARGS_((WindowRef wRef,
+ int *xOffset, int *yOffset));
+extern void TkResumeClipboard _ANSI_ARGS_((void));
+extern int TkSetMacColor _ANSI_ARGS_((unsigned long pixel,
+ RGBColor *macColor));
+extern void TkSetWMName _ANSI_ARGS_((TkWindow *winPtr,
+ Tk_Uid titleUid));
+extern void TkSuspendClipboard _ANSI_ARGS_((void));
+extern int TkWMGrowToplevel _ANSI_ARGS_((WindowRef whichWindow,
+ Point start));
+extern int TkMacZoomToplevel _ANSI_ARGS_((WindowPtr whichWindow,
+ Point where, short zoomPart));
+extern Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin,
+ int rootX, int rootY, int *newX, int *newY));
+extern MacDrawable * TkMacContainerId _ANSI_ARGS_((TkWindow *winPtr));
+extern MacDrawable * TkMacGetHostToplevel _ANSI_ARGS_((TkWindow *winPtr));
+/*
+ * The following prototypes need to go into tkMac.h
+ */
+EXTERN void Tk_UpdatePointer _ANSI_ARGS_((Tk_Window tkwin,
+ int x, int y, int state));
+
+#endif /* _TKMACINT */
diff --git a/mac/tkMacKeyboard.c b/mac/tkMacKeyboard.c
new file mode 100644
index 0000000..a1dfad8
--- /dev/null
+++ b/mac/tkMacKeyboard.c
@@ -0,0 +1,384 @@
+/*
+ * tkMacKeyboard.c --
+ *
+ * Routines to support keyboard events on the Macintosh.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacKeyboard.c 1.14 96/08/15 15:34:00
+ */
+
+#include "tkInt.h"
+#include "Xlib.h"
+#include "keysym.h"
+
+#include <Events.h>
+#include <Script.h>
+
+typedef struct {
+ short keycode; /* Macintosh keycode */
+ KeySym keysym; /* X windows Keysym */
+} KeyInfo;
+
+static KeyInfo keyArray[] = {
+ {0x4C, XK_Return},
+ {0x24, XK_Return},
+ {0x33, XK_BackSpace},
+ {0x75, XK_Delete},
+ {0x30, XK_Tab},
+ {0x74, XK_Page_Up},
+ {0x79, XK_Page_Down},
+ {0x73, XK_Home},
+ {0x77, XK_End},
+ {0x7B, XK_Left},
+ {0x7C, XK_Right},
+ {0x7E, XK_Up},
+ {0x7D, XK_Down},
+ {0x72, XK_Help},
+ {0x35, XK_Escape},
+ {0x47, XK_Clear},
+ {0, 0}
+};
+
+static KeyInfo vituralkeyArray[] = {
+ {122, XK_F1},
+ {120, XK_F2},
+ {99, XK_F3},
+ {118, XK_F4},
+ {96, XK_F5},
+ {97, XK_F6},
+ {98, XK_F7},
+ {100, XK_F8},
+ {101, XK_F9},
+ {109, XK_F10},
+ {103, XK_F11},
+ {111, XK_F12},
+ {105, XK_F13},
+ {107, XK_F14},
+ {113, XK_F15},
+ {0, 0}
+};
+
+static int initialized = 0;
+static Tcl_HashTable keycodeTable; /* keyArray hashed by keycode value. */
+static Tcl_HashTable vkeyTable; /* vituralkeyArray hashed by virtual
+ keycode value. */
+static Ptr KCHRPtr; /* Pointer to 'KCHR' resource. */
+
+/*
+ * Prototypes for static functions used in this file.
+ */
+static void InitKeyMaps _ANSI_ARGS_((void));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitKeyMaps --
+ *
+ * Creates hash tables used by some of the functions in this file.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allocates memory & creates some hash tables.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitKeyMaps()
+{
+ register Tcl_HashEntry *hPtr;
+ register KeyInfo *kPtr;
+ int dummy;
+
+ Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
+ for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
+ hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
+ &dummy);
+ Tcl_SetHashValue(hPtr, kPtr->keysym);
+ }
+ Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
+ for (kPtr = vituralkeyArray; kPtr->keycode != 0; kPtr++) {
+ hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
+ &dummy);
+ Tcl_SetHashValue(hPtr, kPtr->keysym);
+ }
+ KCHRPtr = (Ptr) GetScriptManagerVariable(smKCHRCache);
+ initialized = 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XKeycodeToKeysym --
+ *
+ * Translate from a system-dependent keycode to a
+ * system-independent keysym.
+ *
+ * Results:
+ * Returns the translated keysym, or NoSymbol on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeySym
+XKeycodeToKeysym(
+ Display* display,
+ KeyCode keycode,
+ int index)
+{
+ register Tcl_HashEntry *hPtr;
+ register char c;
+ char virtualKey;
+ int newKeycode;
+ unsigned long dummy, newChar;
+
+ if (!initialized) {
+ InitKeyMaps();
+ }
+
+ c = keycode & charCodeMask;
+ virtualKey = (keycode & keyCodeMask) >> 8;
+
+ /*
+ * When determining what keysym to produce we firt check to see if
+ * the key is a function key. We then check to see if the character
+ * is another non-printing key. Finally, we return the key syms
+ * for all ASCI chars.
+ */
+ if (c == 0x10) {
+ hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) virtualKey);
+ if (hPtr != NULL) {
+ return (KeySym) Tcl_GetHashValue(hPtr);
+ }
+ }
+
+
+ hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
+ if (hPtr != NULL) {
+ return (KeySym) Tcl_GetHashValue(hPtr);
+ }
+
+ /*
+ * Recompute the character based on the Shift key only.
+ * TODO: The index may also specify the NUM_LOCK.
+ */
+ newKeycode = virtualKey;
+ if (index & 0x01) {
+ newKeycode += 0x0200;
+ }
+ dummy = 0;
+ newChar = KeyTranslate(KCHRPtr, (short) newKeycode, &dummy);
+ c = newChar & charCodeMask;
+
+ if (c >= XK_space && c < XK_asciitilde) {
+ return c;
+ }
+
+ return NoSymbol;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XLookupString --
+ *
+ * Retrieve the string equivalent for the given keyboard event.
+ *
+ * Results:
+ * Returns the number of characters stored in buffer_return.
+ *
+ * Side effects:
+ * Retrieves the characters stored in the event and inserts them
+ * into buffer_return.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XLookupString(
+ XKeyEvent* event_struct,
+ char* buffer_return,
+ int bytes_buffer,
+ KeySym* keysym_return,
+ XComposeStatus* status_in_out)
+{
+ register Tcl_HashEntry *hPtr;
+ char string[3];
+ char virtualKey;
+ char c;
+
+ if (!initialized) {
+ InitKeyMaps();
+ }
+
+ c = event_struct->keycode & charCodeMask;
+ string[0] = c;
+ string[1] = '\0';
+
+ /*
+ * Just return NULL if the character is a function key or another
+ * non-printing key.
+ */
+ if (c == 0x10) {
+ string[0] = '\0';
+ } else {
+ virtualKey = (event_struct->keycode & keyCodeMask) >> 8;
+ hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
+ if (hPtr != NULL) {
+ string[0] = '\0';
+ }
+ }
+
+ if (buffer_return != NULL) {
+ strncpy(buffer_return, string, bytes_buffer);
+ }
+
+ return strlen(string);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XGetModifierMapping --
+ *
+ * Fetch the current keycodes used as modifiers.
+ *
+ * Results:
+ * Returns a new modifier map.
+ *
+ * Side effects:
+ * Allocates a new modifier map data structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XModifierKeymap *
+XGetModifierMapping(
+ Display* display)
+{
+ XModifierKeymap * modmap;
+
+ modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
+ modmap->max_keypermod = 0;
+ modmap->modifiermap = NULL;
+ return modmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFreeModifiermap --
+ *
+ * Deallocate a modifier map that was created by
+ * XGetModifierMapping.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees the datastructure referenced by modmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFreeModifiermap(
+ XModifierKeymap *modmap)
+{
+ if (modmap->modifiermap != NULL) {
+ ckfree((char *) modmap->modifiermap);
+ }
+ ckfree((char *) modmap);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XKeysymToString, XStringToKeysym --
+ *
+ * These X window functions map Keysyms to strings & strings to
+ * keysyms. However, Tk already does this for the most common keysyms.
+ * Therefor, these functions only need to support keysyms that will be
+ * specific to the Macintosh. Currently, there are none.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+XKeysymToString(
+ KeySym keysym)
+{
+ return NULL;
+}
+
+KeySym
+XStringToKeysym(
+ const char* string)
+{
+ return NoSymbol;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XKeysymToKeycode --
+ *
+ * The function XKeysymToKeycode is only used by tkTest.c and
+ * currently only implementes the support for keys used in the
+ * Tk test suite.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeyCode
+XKeysymToKeycode(
+ Display* display,
+ KeySym keysym)
+{
+ KeyCode keycode = 0;
+ char virtualKeyCode = 0;
+
+ if ((keysym >= XK_space) && (XK_asciitilde)) {
+ if (keysym == 'a') {
+ virtualKeyCode = 0x00;
+ } else if (keysym == 'b' || keysym == 'B') {
+ virtualKeyCode = 0x0B;
+ } else if (keysym == 'c') {
+ virtualKeyCode = 0x08;
+ } else if (keysym == 'x' || keysym == 'X') {
+ virtualKeyCode = 0x07;
+ } else if (keysym == 'z') {
+ virtualKeyCode = 0x06;
+ } else if (keysym == ' ') {
+ virtualKeyCode = 0x31;
+ } else if (keysym == XK_Return) {
+ virtualKeyCode = 0x24;
+ keysym = '\r';
+ }
+ keycode = keysym + ((virtualKeyCode << 8) & keyCodeMask);
+ }
+
+ return keycode;
+}
diff --git a/mac/tkMacLibrary.r b/mac/tkMacLibrary.r
new file mode 100644
index 0000000..c86954a
--- /dev/null
+++ b/mac/tkMacLibrary.r
@@ -0,0 +1,510 @@
+/*
+ * tkMacLibrary.r --
+ *
+ * This file creates resources for use in most Tk applications.
+ * This is designed to be an example of using the Tcl/Tk
+ * libraries in a Macintosh Application.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacLibrary.r 1.9 97/11/20 18:31:20
+ */
+
+/*
+ * New style DLOG templates have an extra field for the positioning
+ * options for the Dialog Box. We will not use this, for now, so we
+ * turn it off here.
+ */
+
+#define DLOG_RezTemplateVersion 0
+
+#include <Types.r>
+#include <SysTypes.r>
+#include <AEUserTermTypes.r>
+
+/*
+ * The folowing include and defines help construct
+ * the version string for Tcl.
+ */
+
+#define RESOURCE_INCLUDED
+#include <tcl.h>
+#include "tk.h"
+
+#if (TK_RELEASE_LEVEL == 0)
+# define RELEASE_LEVEL alpha
+#elif (TK_RELEASE_LEVEL == 1)
+# define RELEASE_LEVEL beta
+#elif (TK_RELEASE_LEVEL == 2)
+# define RELEASE_LEVEL final
+#endif
+
+#if (TK_RELEASE_LEVEL == 2)
+# define MINOR_VERSION (TK_MINOR_VERSION * 16) + TK_RELEASE_SERIAL
+#else
+# define MINOR_VERSION TK_MINOR_VERSION * 16
+#endif
+
+#define RELEASE_CODE 0x00
+
+resource 'vers' (1) {
+ TK_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TK_PATCH_LEVEL,
+ TK_PATCH_LEVEL ", by Ray Johnson © 1993-1996" "\n" "Sun Microsystems Labratories"
+};
+
+resource 'vers' (2) {
+ TK_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TK_PATCH_LEVEL,
+ "Tk Library " TK_PATCH_LEVEL " © 1993-1996"
+};
+
+#define TK_LIBRARY_RESOURCES 3000
+/*
+ * The -16397 string will be displayed by Finder when a user
+ * tries to open the shared library. The string should
+ * give the user a little detail about the library's capabilities
+ * and enough information to install the library in the correct location.
+ * A similar string should be placed in all shared libraries.
+ */
+resource 'STR ' (-16397, purgeable) {
+ "Tk Library\n\n"
+ "This is the library needed to run Tcl/Tk programs. "
+ "To work properly, it should be placed in the ŒTool Command Language¹ folder "
+ "within the Extensions folder."
+};
+
+
+/*
+ * We now load the Tk library into the resource fork of the library.
+ */
+
+read 'TEXT' (TK_LIBRARY_RESOURCES+1, "tk", purgeable)
+ "::library:tk.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+2, "button", purgeable)
+ "::library:button.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+3, "dialog", purgeable)
+ "::library:dialog.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+4, "entry", purgeable)
+ "::library:entry.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+5, "focus", purgeable)
+ "::library:focus.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+6, "listbox", purgeable)
+ "::library:listbox.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+7, "menu", purgeable)
+ "::library:menu.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+8, "optionMenu", purgeable)
+ "::library:optMenu.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+9, "palette", purgeable)
+ "::library:palette.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+10, "scale", purgeable)
+ "::library:scale.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+11, "scrollbar", purgeable)
+ "::library:scrlbar.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+12, "tearoff", purgeable)
+ "::library:tearoff.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+13, "text", purgeable)
+ "::library:text.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+14, "tkerror", purgeable)
+ "::library:bgerror.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+15, "Console", purgeable)
+ "::library:console.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+16, "msgbox", purgeable, preload)
+ "::library:msgbox.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+17, "comdlg", purgeable, preload)
+ "::library:comdlg.tcl";
+read 'TEXT' (TK_LIBRARY_RESOURCES+18, "prolog", purgeable, preload)
+ "::library:prolog.ps";
+
+/*
+ * The following two resources define the default "About Box" for Mac Tk.
+ * This dialog appears if the "About Tk..." menu item is selected from
+ * the Apple menu. This dialog may be overridden by defining a Tcl procedure
+ * with the name of "tkAboutDialog". If this procedure is defined the
+ * default dialog will not be shown and the Tcl procedure is expected to
+ * create and manage an About Dialog box.
+ */
+
+data 'DLOG' (128, "Default About Box", purgeable) {
+ $"0055 006B 00F3 0196 0001 0100 0100 0000"
+ $"0000 0081 0000 280A"
+};
+
+resource 'DITL' (129, "About Box", purgeable) {
+ {
+ {128, 128, 148, 186}, Button {enabled, "Ok"},
+ { 14, 108, 117, 298}, StaticText {disabled,
+ "Wish - Windowing Shell" "\n" "based on Tcl "
+ TCL_PATCH_LEVEL " & Tk " TK_PATCH_LEVEL "\n\n" "Ray Johnson"
+ "Sun Microsystems Labs" "\n" "ray.johnson@eng.sun.com"},
+ { 11, 24, 111, 92}, Picture {enabled, 128}
+ }
+};
+
+data 'PICT' (128, purgeable) {
+ $"13A4 0000 0000 0064 0044 0011 02FF 0C00"
+ $"FFFE 0000 0048 0000 0048 0000 0000 0000"
+ $"0064 0044 0000 0000 0001 000A 0000 0000"
+ $"0064 0044 0099 8044 0000 0000 0064 0044"
+ $"0000 0000 0000 0000 0048 0000 0048 0000"
+ $"0000 0008 0001 0008 0000 0000 0108 00D8"
+ $"0000 0000 0001 5A5A 8000 00FF 3736 FF00"
+ $"FF00 FF00 3535 FF00 FF00 CC00 3434 FF00"
+ $"FF00 9900 3333 FF00 FF00 6600 3736 FF00"
+ $"FF00 3300 3535 FF00 FF00 0000 3434 FF00"
+ $"CC00 FF00 3333 FF00 CC00 CC00 3736 FF00"
+ $"CC00 9900 3535 FF00 CC00 6600 FAFA FF00"
+ $"CC00 3300 3333 FF00 CC00 0000 3130 FF00"
+ $"9900 FF00 2F2F FF00 9900 CC00 FAFA FF00"
+ $"9900 9900 F9F9 FF00 9900 6600 3130 FF00"
+ $"9900 3300 2F2F FF00 9900 0000 2E2E FF00"
+ $"6600 FF00 F9F9 FF00 6600 CC00 3130 FF00"
+ $"6600 9900 2F2F FF00 6600 6600 2E2E FF00"
+ $"6600 3300 2D2D FF00 6600 0000 3130 FF00"
+ $"3300 FF00 2F2F FF00 3300 CC00 2E2E FF00"
+ $"3300 9900 2D2D FF00 3300 6600 3130 FF00"
+ $"3300 3300 2F2F FF00 3300 0000 2E2E FF00"
+ $"0000 FF00 2D2D FF00 0000 CC00 3130 FF00"
+ $"0000 9900 2F2F FF00 0000 6600 2E2E FF00"
+ $"0000 3300 2DF8 FF00 0000 0000 2B2A CC00"
+ $"FF00 FF00 2929 CC00 FF00 CC00 2828 CC00"
+ $"FF00 9900 27F8 CC00 FF00 6600 2B2A CC00"
+ $"FF00 3300 2929 CC00 FF00 0000 2828 CC00"
+ $"CC00 FF00 2727 CC00 CC00 CC00 2B2A CC00"
+ $"CC00 9900 2929 CC00 CC00 6600 2828 CC00"
+ $"CC00 3300 2727 CC00 CC00 0000 2B2A CC00"
+ $"9900 FF00 2929 CC00 9900 CC00 2828 CC00"
+ $"9900 9900 2727 CC00 9900 6600 DBDB CC00"
+ $"9900 3300 4747 CC00 9900 0000 4646 CC00"
+ $"6600 FF00 4545 CC00 6600 CC00 DBDB CC00"
+ $"6600 9900 4747 CC00 6600 6600 4646 CC00"
+ $"6600 3300 4545 CC00 6600 0000 DBDB CC00"
+ $"3300 FF00 4747 CC00 3300 CC00 4646 CC00"
+ $"3300 9900 4545 CC00 3300 6600 DBDB CC00"
+ $"3300 3300 4141 CC00 3300 0000 4040 CC00"
+ $"0000 FF00 3F3F CC00 0000 CC00 4342 CC00"
+ $"0000 9900 4141 CC00 0000 6600 4040 CC00"
+ $"0000 3300 3F3F CC00 0000 0000 4342 9900"
+ $"FF00 FF00 4141 9900 FF00 CC00 4040 9900"
+ $"FF00 9900 3F3F 9900 FF00 6600 4342 9900"
+ $"FF00 3300 4141 9900 FF00 0000 4040 9900"
+ $"CC00 FF00 3F3F 9900 CC00 CC00 4342 9900"
+ $"CC00 9900 4141 9900 CC00 6600 4040 9900"
+ $"CC00 3300 3F3F 9900 CC00 0000 4342 9900"
+ $"9900 FF00 4141 9900 9900 CC00 4040 9900"
+ $"9900 9900 3F3F 9900 9900 6600 3D3C 9900"
+ $"9900 3300 3B3B 9900 9900 0000 3A3A 9900"
+ $"6600 FF00 3939 9900 6600 CC00 3D3C 9900"
+ $"6600 9900 3B3B 9900 6600 6600 3A3A 9900"
+ $"6600 3300 3939 9900 6600 0000 3D3C 9900"
+ $"3300 FF00 3B3B 9900 3300 CC00 3A3A 9900"
+ $"3300 9900 3939 9900 3300 6600 3D3C 9900"
+ $"3300 3300 3B3B 9900 3300 0000 3A3A 9900"
+ $"0000 FF00 3939 9900 0000 CC00 3D3C 9900"
+ $"0000 9900 3B3B 9900 0000 6600 3A3A 9900"
+ $"0000 3300 3939 9900 0000 0000 3D3C 6600"
+ $"FF00 FF00 3B3B 6600 FF00 CC00 3A3A 6600"
+ $"FF00 9900 3939 6600 FF00 6600 3D3C 6600"
+ $"FF00 3300 3B3B 6600 FF00 0000 3A3A 6600"
+ $"CC00 FF00 3939 6600 CC00 CC00 3736 6600"
+ $"CC00 9900 3535 6600 CC00 6600 3434 6600"
+ $"CC00 3300 3333 6600 CC00 0000 3736 6600"
+ $"9900 FF00 3535 6600 9900 CC00 3434 6600"
+ $"9900 9900 3333 6600 9900 6600 3736 6600"
+ $"9900 3300 3535 6600 9900 0000 3434 6600"
+ $"6600 FF00 3333 6600 6600 CC00 3736 6600"
+ $"6600 9900 3535 6600 6600 6600 3434 6600"
+ $"6600 3300 3333 6600 6600 0000 3736 6600"
+ $"3300 FF00 3535 6600 3300 CC00 3434 6600"
+ $"3300 9900 3333 6600 3300 6600 3736 6600"
+ $"3300 3300 3535 6600 3300 0000 3434 6600"
+ $"0000 FF00 3333 6600 0000 CC00 3130 6600"
+ $"0000 9900 2F2F 6600 0000 6600 2E2E 6600"
+ $"0000 3300 F9F9 6600 0000 0000 3130 3300"
+ $"FF00 FF00 2F2F 3300 FF00 CC00 2E2E 3300"
+ $"FF00 9900 F9F9 3300 FF00 6600 3130 3300"
+ $"FF00 3300 2F2F 3300 FF00 0000 2E2E 3300"
+ $"CC00 FF00 2D2D 3300 CC00 CC00 3130 3300"
+ $"CC00 9900 2F2F 3300 CC00 6600 2E2E 3300"
+ $"CC00 3300 2D2D 3300 CC00 0000 3130 3300"
+ $"9900 FF00 2F2F 3300 9900 CC00 2E2E 3300"
+ $"9900 9900 2D2D 3300 9900 6600 3130 3300"
+ $"9900 3300 2F2F 3300 9900 0000 2E2E 3300"
+ $"6600 FF00 2DF8 3300 6600 CC00 2B2A 3300"
+ $"6600 9900 2929 3300 6600 6600 2828 3300"
+ $"6600 3300 27F8 3300 6600 0000 2B2A 3300"
+ $"3300 FF00 2929 3300 3300 CC00 2828 3300"
+ $"3300 9900 2727 3300 3300 6600 2B2A 3300"
+ $"3300 3300 2929 3300 3300 0000 2828 3300"
+ $"0000 FF00 2727 3300 0000 CC00 2B2A 3300"
+ $"0000 9900 2929 3300 0000 6600 2828 3300"
+ $"0000 3300 2727 3300 0000 0000 4948 0000"
+ $"FF00 FF00 4747 0000 FF00 CC00 4646 0000"
+ $"FF00 9900 4545 0000 FF00 6600 4948 0000"
+ $"FF00 3300 4747 0000 FF00 0000 4646 0000"
+ $"CC00 FF00 4545 0000 CC00 CC00 4948 0000"
+ $"CC00 9900 4747 0000 CC00 6600 4646 0000"
+ $"CC00 3300 4545 0000 CC00 0000 4342 0000"
+ $"9900 FF00 4141 0000 9900 CC00 4040 0000"
+ $"9900 9900 3F3F 0000 9900 6600 4342 0000"
+ $"9900 3300 4141 0000 9900 0000 4040 0000"
+ $"6600 FF00 3F3F 0000 6600 CC00 4342 0000"
+ $"6600 9900 4141 0000 6600 6600 4040 0000"
+ $"6600 3300 3F3F 0000 6600 0000 4342 0000"
+ $"3300 FF00 4141 0000 3300 CC00 4040 0000"
+ $"3300 9900 3F3F 0000 3300 6600 4342 0000"
+ $"3300 3300 4141 0000 3300 0000 4040 0000"
+ $"0000 FF00 3F3F 0000 0000 CC00 4342 0000"
+ $"0000 9900 4141 0000 0000 6600 4040 0000"
+ $"0000 3300 3F3F EE00 0000 0000 3D3C DD00"
+ $"0000 0000 3B3B BB00 0000 0000 3A3A AA00"
+ $"0000 0000 3939 8800 0000 0000 3D3C 7700"
+ $"0000 0000 3B3B 5500 0000 0000 3A3A 4400"
+ $"0000 0000 3939 2200 0000 0000 3D3C 1100"
+ $"0000 0000 3B3B 0000 EE00 0000 3A3A 0000"
+ $"DD00 0000 3939 0000 BB00 0000 3D3C 0000"
+ $"AA00 0000 3B3B 0000 8800 0000 3A3A 0000"
+ $"7700 0000 3939 0000 5500 0000 3D3C 0000"
+ $"4400 0000 3B3B 0000 2200 0000 3A3A 0000"
+ $"1100 0000 3939 0000 0000 EE00 3D3C 0000"
+ $"0000 DD00 3B3B 0000 0000 BB00 3A3A 0000"
+ $"0000 AA00 3939 0000 0000 8800 3D3C 0000"
+ $"0000 7700 3B3B 0000 0000 5500 3A3A 0000"
+ $"0000 4400 3939 0000 0000 2200 3736 0000"
+ $"0000 1100 3535 EE00 EE00 EE00 3434 DD00"
+ $"DD00 DD00 3333 BB00 BB00 BB00 3736 AA00"
+ $"AA00 AA00 3535 8800 8800 8800 3434 7700"
+ $"7700 7700 3333 5500 5500 5500 3736 4400"
+ $"4400 4400 3535 2200 2200 2200 3434 1100"
+ $"1100 1100 3333 0000 0000 0000 0000 0000"
+ $"0064 0044 0000 0000 0064 0044 0000 000A"
+ $"0000 0000 0064 0044 02BD 0013 E800 01F5"
+ $"F6FE 07FE 0E02 3232 33FD 3900 0EE6 001D"
+ $"FC00 01F5 F5FE 0700 08FE 0E02 3232 33FE"
+ $"3900 3AFC 40F2 4102 4033 07E9 0017 0100"
+ $"0EFC 40DC 4102 390E F5F5 0002 F5F5 F6FE"
+ $"0702 0E07 0016 0100 32D5 4104 4039 0E32"
+ $"33FD 3900 3AFC 40FC 4101 3200 0801 000E"
+ $"C141 010E 0008 0100 0EC1 4101 0800 0801"
+ $"000E C141 0107 0008 0100 0EC1 4101 0700"
+ $"0901 0007 C241 0240 F500 0E01 0007 E841"
+ $"0147 47DD 4102 4000 0012 0100 07F0 4100"
+ $"47FA 4101 3B3B DD41 0240 0000 1901 0007"
+ $"F141 0C47 3B0B 3B47 4141 4711 0505 3B47"
+ $"DF41 023A 0000 1701 00F6 F041 010B 0BFE"
+ $"4105 473B 0505 113B DE41 0239 0000 1A02"
+ $"00F5 40F3 410C 473B 053B 4741 4741 0B0B"
+ $"3B47 47DE 4102 3900 0018 0200 F540 F341"
+ $"0247 110B FE41 0447 1105 4147 DC41 0233"
+ $"0000 1B02 0000 40F3 4103 4711 1147 FE41"
+ $"0205 3547 F741 FD47 E941 0232 0000 1E02"
+ $"0000 40F2 4106 113B 4741 4735 0BF7 4106"
+ $"4741 390E 0E40 47EA 4102 0E00 0021 0200"
+ $"0040 F241 0711 3B47 4141 0B35 47F9 4102"
+ $"4740 07FE 0002 F640 47EB 4102 0E00 0023"
+ $"0200 0040 F341 0847 3541 4147 3B05 4147"
+ $"FA41 0947 3AF6 00F5 4F55 F50E 47EB 4102"
+ $"0700 0022 0200 003A F341 0147 3BFE 4101"
+ $"0B0B F941 0547 3AF5 0055 C8FE CE01 5640"
+ $"EB41 0207 0000 1F02 0000 39F0 4104 4741"
+ $"053B 47FB 4104 4740 F5F5 A4FC CE01 C85D"
+ $"EB41 02F6 0000 1F02 0000 39F0 4104 473B"
+ $"0541 47FC 4104 4740 07F6 C8FA CE00 64EC"
+ $"4103 40F5 0000 1C02 0000 39F0 4102 4711"
+ $"0BFA 4103 4708 2AC8 FACE 0164 D8EC 4100"
+ $"40FE 0025 0200 0039 EF41 020B 3B47 FC41"
+ $"0347 0FF5 A4FB CE02 C887 D8FC 41FE 47FC"
+ $"4100 47F9 4100 3AFE 0028 0200 0039 EF41"
+ $"020B 3B47 FD41 0347 3900 A4FA CE00 ABFA"
+ $"4109 3B11 3B41 4147 3B0B 3B47 FA41 0039"
+ $"FE00 2402 0000 33F1 4102 4741 0BFA 4101"
+ $"0779 F9CE 0064 FA41 0235 050B FD41 010B"
+ $"0BF9 4100 39FE 0028 0200 0032 F141 0247"
+ $"3B0B FC41 0247 39F6 F9CE 0187 D8FB 4103"
+ $"4741 050B FE41 0247 110B F941 0039 FE00"
+ $"2C02 0000 32F1 4102 473B 11FB 4101 0879"
+ $"FACE 05AA 4041 4147 47FE 410A 4741 0511"
+ $"4741 4147 3511 47FA 4100 32FE 002F 0200"
+ $"000E F141 0347 3B11 47FE 4103 4740 F6C8"
+ $"FACE 0564 D841 4039 39FE 4104 473B 053B"
+ $"47FE 4102 3541 47FA 4100 0EFE 0027 0200"
+ $"000E F141 0347 3B3B 47FE 4102 470F 79FA"
+ $"CE0C 8741 4032 F500 003A 4741 473B 05F2"
+ $"4100 0EFE 0027 0200 000E F141 0347 3B3B"
+ $"47FD 4101 0EA4 FACE 01AB AAFE C808 7900"
+ $"3947 4147 110B 47F3 4100 07FE 001C 0200"
+ $"000E EA41 0240 2BC8 F5CE 0881 0033 4741"
+ $"410B 3B47 F341 0007 FE00 1A02 0000 08EB"
+ $"4102 473A 55F4 CE06 5D00 3947 4741 0BF1"
+ $"4100 F6FE 001C 0200 0007 EB41 0247 3979"
+ $"F4CE 0739 0039 4747 3511 47F3 4101 40F5"
+ $"FE00 1C02 0000 07EB 4102 4739 A4F5 CE08"
+ $"AB0E 0040 4741 1141 47F3 4100 40FD 001B"
+ $"0200 0007 EB41 0247 39A4 F5CE 0787 0707"
+ $"4147 4111 47F2 4100 40FD 001B 0200 0007"
+ $"EB41 0247 39C8 F5CE 0763 F532 4747 3B3B"
+ $"47F2 4100 3AFD 001A 0300 00F6 40EC 4102"
+ $"4739 C8F5 CE05 39F5 4047 413B F041 0039"
+ $"FD00 1C03 0000 F540 EB41 0140 C8FD CE01"
+ $"C8A4 FCCE 03AB 080E 47ED 4100 39FD 001A"
+ $"FE00 0040 EB41 0040 FCCE 01A4 C8FC CE03"
+ $"FA07 4047 ED41 0032 FD00 1AFE 0000 40EA"
+ $"4100 AAFE CE02 87F9 C8FC CE02 560F 47EC"
+ $"4100 32FD 0019 FE00 0040 EA41 00AB FECE"
+ $"0264 56C8 FDCE 01C8 32EA 4100 0EFD 001B"
+ $"FE00 0040 ED41 030E 4047 87FE CE01 4055"
+ $"FCCE 01FA 40EA 4100 08FD 001A FE00 003A"
+ $"ED41 0807 0740 FBCE CEAB 3979 FDCE 00AB"
+ $"E841 0007 FD00 1CFE 0000 3AED 4108 0700"
+ $"F6A4 CECE 8733 79FD CE02 4147 47EA 4100"
+ $"07FD 001E FE00 0039 ED41 0807 2AA4 C8CE"
+ $"CE88 0E9D FECE 0364 1C39 39EB 4101 40F5"
+ $"FD00 1CFE 0000 39ED 4101 074F FDCE 0264"
+ $"F7A4 FECE 03AB 80F6 07EB 4100 40FC 001C"
+ $"FE00 0039 ED41 0108 79FE CE03 AB40 2BA4"
+ $"FCCE 02F7 0E47 EC41 0040 FC00 1CFE 0000"
+ $"39ED 4101 0879 FECE 03AB 40F6 C8FC CE02"
+ $"F615 47EC 4100 40FC 001E FE00 003A EE41"
+ $"0247 0E79 FECE 03AB 40F5 C8FD CE03 A4F5"
+ $"3A47 EC41 0040 FC00 1EFE 0000 3AEE 4102"
+ $"470E 56FE CE03 FB3A F6C8 FDCE 0280 F540"
+ $"EB41 0140 F5FD 001E FE00 0040 EE41 0947"
+ $"0F56 CECE C888 39F6 C8FD CE02 5601 40EB"
+ $"4101 40F5 FD00 1CFE 0000 40EE 4109 4739"
+ $"32CE CEC8 8839 2AC8 FDCE 0156 07E9 4100"
+ $"F6FD 001B FE00 0040 EE41 0847 3A32 CECE"
+ $"C864 152A FCCE 0132 07E9 4100 07FD 001A"
+ $"FE00 0040 ED41 0740 32AB CEC8 6439 4EFC"
+ $"CE01 3A07 E941 0007 FD00 1D03 0000 F540"
+ $"ED41 0740 0EAB CECE 640F 4EFD CE03 AB40"
+ $"0840 EA41 0007 FD00 1B03 0000 F540 EC41"
+ $"060F 81CE CE64 334E FDCE 02AB 400E E941"
+ $"000E FD00 1C02 0000 F6EC 4107 4715 FACE"
+ $"CE64 334E FDCE 0387 0F0E 47EA 4100 0EFD"
+ $"001C 0200 0007 EC41 0747 16F9 CEC8 6433"
+ $"4EFD CE03 6308 4047 EA41 000E FD00 1A02"
+ $"0000 07EB 4106 40F9 CEC8 6439 4EFD CE02"
+ $"3940 47E9 4100 32FD 001B 0200 0007 EA41"
+ $"0539 CECE 8839 F6FE CE04 AB41 4139 40EA"
+ $"4100 32FD 001C 0200 0007 EB41 0E47 3AC8"
+ $"CE88 39F6 C8CE CE64 15F6 F540 EA41 0033"
+ $"FD00 1A02 0000 07EA 410C 40A4 CE87 392A"
+ $"C8CE AB41 40F8 F6E9 4100 39FD 001B 0200"
+ $"000E EB41 0D47 41AB C887 39F5 C8CE ABAB"
+ $"CEA4 07E9 4100 39FD 001C 0200 000E ED41"
+ $"0947 3939 4787 C8AB 40F5 C8FD CE01 A40E"
+ $"E941 0039 FD00 1D02 0000 0EED 4109 473A"
+ $"0007 80CE AB40 F5C8 FDCE 0255 0E47 EA41"
+ $"0039 FD00 1B02 0000 0EEB 4107 0779 C8CE"
+ $"CE40 F6A4 FDCE 022B 3947 EA41 003A FD00"
+ $"1C02 0000 0EEC 4102 4739 79FE CE02 6407"
+ $"A4FE CE02 A407 40E9 4100 40FD 001A 0200"
+ $"0032 EA41 0632 A4CE CE88 0879 FECE 02F9"
+ $"0F47 E941 0040 FD00 1A02 0000 32EB 4107"
+ $"4740 F7C8 CE87 0E79 FECE 0132 40E8 4100"
+ $"40FD 0019 0200 0033 EA41 0B47 40F8 C8AB"
+ $"0E55 CECE 8015 47E8 4100 40FD 0017 0200"
+ $"0033 E941 0847 40F9 A439 4FCE CE5D E641"
+ $"0140 F5FE 0014 0200 0039 E841 0647 64FB"
+ $"392B C8AB E441 00F6 FE00 1102 0000 39E5"
+ $"4103 40F6 8764 E441 0007 FE00 1E02 0000"
+ $"39EB 4102 3A0E 0EFD 4102 0740 47F6 4104"
+ $"400F 0839 47F4 4100 07FE 0027 0200 0039"
+ $"FB41 0147 47F2 4102 0800 40FE 4102 0839"
+ $"47FC 4101 4747 FC41 0339 0039 47F4 4100"
+ $"07FE 0029 0200 0039 FB41 0140 39F3 4109"
+ $"470E F540 4141 470E 3347 FC41 0139 3AFD"
+ $"4104 4739 0039 47F4 4100 08FE 0036 0200"
+ $"003A FC41 0347 0E00 40FC 4102 4741 40FC"
+ $"4109 470E F540 4141 4733 0E47 FE41 0447"
+ $"4000 0E47 FE41 0447 3900 3941 FE40 F741"
+ $"000E FE00 3A02 0000 3AFD 410E 4740 0700"
+ $"0E40 4741 4147 390E 390E 40FE 4108 470E"
+ $"F540 4141 4739 0EFC 4103 0F00 0739 FE41"
+ $"0747 3900 3940 080F 39F7 4100 0EFE 0035"
+ $"0200 0040 FB41 020E 0040 FE41 0D47 4000"
+ $"3941 0032 4741 4147 0EF5 40FE 4101 4008"
+ $"FC41 023A 000E FD41 0547 3900 3939 33F5"
+ $"4100 0EFE 0039 0200 0040 FC41 0347 0E00"
+ $"40FE 4106 4732 0040 4139 40FE 4103 470E"
+ $"F540 FD41 0108 40FE 4104 4740 000E 47FE"
+ $"4106 4739 0007 F540 47F6 4100 32FE 003A"
+ $"0200 0040 FC41 0C47 0E00 4047 4141 470E"
+ $"0040 4747 FD41 0347 0EF5 40FE 410A 470E"
+ $"3947 4141 4740 000E 47FE 4107 4739 000E"
+ $"0007 4147 F741 0032 FE00 3802 0000 40FC"
+ $"4102 470E 00FD 4106 4739 003A 4740 39FE"
+ $"4102 470E F5FD 410A 4733 3347 4141 4740"
+ $"000E 47FE 4106 4739 0039 3900 0EF6 4100"
+ $"33FE 003A 0200 F540 FC41 0447 3200 0E39"
+ $"FD41 0B0E 0E40 333A 4741 413A 07F5 39FE"
+ $"4102 473A 0EFD 410F 40F5 0733 4041 4140"
+ $"0E00 0E40 0700 0E40 F841 0039 FE00 2902"
+ $"00F5 40FA 4101 3939 FB41 023A 3A40 FD41"
+ $"FD40 FD41 0240 0E40 FD41 0240 3940 FD41"
+ $"FA40 F741 0039 FE00 2A01 00F6 F941 0147"
+ $"47FB 4101 4747 FB41 0147 47FB 4101 3940"
+ $"FD41 0147 47FB 4100 47FE 4100 47F6 4100"
+ $"39FE 000D 0100 07E1 4100 40E4 4100 3AFE"
+ $"0009 0100 07C3 4100 3AFE 0009 0100 07C3"
+ $"4100 40FE 0009 0100 07C3 4100 40FE 0009"
+ $"0100 07C3 4100 40FE 000A 0100 0EC3 4103"
+ $"40F5 0000 0901 000E C241 02F6 0000 0901"
+ $"000E C241 0207 0000 0901 000E C241 0207"
+ $"0000 1101 000E ED41 FE40 003A F940 E241"
+ $"0207 0000 2B01 0032 F941 FE40 FE39 0632"
+ $"0E0E 0707 F6F5 F800 02F5 F5F6 FB07 FB0E"
+ $"0332 3233 33FB 3901 3A3A FB40 0207 0000"
+ $"0E0A 000E 3939 320E 0E07 07F6 F5C8 0002"
+ $"BD00 00FF"
+};
+
+/*
+ * Here is the custom file open dialog. This dialog is used instead of
+ * the default file dialog if the -filetypes flag is specified.
+ */
+
+#define DLOG_RezTemplateVersion 0
+
+resource 'DLOG' (130, purgeable) {
+ {0, 0, 195, 344}, dBoxProc, invisible, noGoAway, 0,
+ 130, ""
+};
+
+resource 'DITL' (130, "File Open Box", purgeable) {
+ {
+ {135, 252, 155, 332}, Button {enabled, "Open"},
+ {104, 252, 124, 332}, Button {enabled, "Cancel"},
+ { 0, 0, 0, 0}, HelpItem {disabled, HMScanhdlg {130}},
+ { 8, 235, 24, 337}, UserItem {enabled},
+ { 32, 252, 52, 332}, Button {enabled, "Eject"},
+ { 60, 252, 80, 332}, Button {enabled, "Desktop"},
+ { 29, 12, 159, 230}, UserItem {enabled},
+ { 6, 12, 25, 230}, UserItem {enabled},
+ { 91, 251, 92, 333}, Picture {disabled, 11},
+ {168, 20, 187, 300}, Control {enabled, 131}
+ }
+};
+
+resource 'CNTL' (131, "File Types menu", purgeable) {
+ {168, 20, 187, 300},
+ popupTitleLeftJust,
+ visible,
+ 80,
+ 132,
+ popupMenuCDEFProc,
+ 0,
+ "File Type:"
+};
+
+
+resource 'MENU' (132, preload) {
+ 132,
+ textMenuProc,
+ 0xFFFF, enabled, "", {}
+};
diff --git a/mac/tkMacMDEF.c b/mac/tkMacMDEF.c
new file mode 100644
index 0000000..f7ce485
--- /dev/null
+++ b/mac/tkMacMDEF.c
@@ -0,0 +1,116 @@
+/*
+ * TkMacMDEF.c --
+ *
+ * This module is implements the MDEF for tkMenus. The address of the
+ * real entry proc will be blasted into the MDEF.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacMDEF.c 1.5 97/07/11 %V%
+ */
+
+#define MAC_TCL
+#define NeedFunctionPrototypes 1
+#define NeedWidePrototypes 0
+
+#include <Menus.h>
+#include <LowMem.h>
+#include "tkMacInt.h"
+
+
+/*
+ * The following structure is built from assembly equates in MPW 3.0
+ * AIncludes file: "Private.a." We're forced to update several locations not
+ * documented in "Inside Mac" to make our MDEF behave properly with hierarchical
+ * menus.
+ */
+
+#if STRUCTALIGNMENTSUPPORTED
+#pragma options align=mac68k
+#endif
+typedef struct mbPrivate {
+ Byte unknown[6];
+ Rect mbItemRect; /* rect of currently chosen menu item */
+} mbPrivate;
+#if STRUCTALIGNMENTSUPPORTED
+#pragma options align=reset
+#endif
+
+/*
+ * We are forced to update a low-memory global to get cascades to work. This
+ * global does not have a LMEquate associated with it.
+ */
+
+#define SELECTRECT (*(Rect *)0x09fa) /* Menu select seems to need this */
+#define MBSAVELOC (*(short *)0x0B5C) /* address of handle to mbarproc private data redefined below */
+
+pascal void main _ANSI_ARGS_((short message,
+ MenuHandle menu, Rect *menuRect,
+ Point hitPt, short *whichItem));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacStdMenu --
+ *
+ * The dispatch routine called by the system to handle menu drawing,
+ * scrolling, etc. This is a stub; the address of the real routine
+ * is blasted in. The real routine will be a UniversalProcPtr,
+ * which will give the real dispatch routine in Tk globals
+ * and the like.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This routine causes menus to be drawn and will certainly allocate
+ * memory as a result. Also, the menu can scroll up and down, and
+ * various other interface actions can take place
+ *
+ *----------------------------------------------------------------------
+ */
+
+pascal void
+main(
+ short message, /* What action are we taking? */
+ MenuHandle menu, /* The menu we are working with */
+ Rect *menuRect, /* A pointer to the rect we are working with */
+ Point hitPt, /* Where the mouse was hit for appropriate
+ * messages. */
+ short *whichItemPtr) /* Output result. Which item was hit by
+ * the user? */
+{
+ /*
+ * The constant 'MDEF' is what will be punched during menu intialization.
+ */
+
+ TkMenuDefProcPtr procPtr = (TkMenuDefProcPtr) 'MDEF';
+ TkMenuLowMemGlobals globals;
+ short oldItem;
+
+ globals.menuDisable = LMGetMenuDisable();
+ globals.menuTop = LMGetTopMenuItem();
+ globals.menuBottom = LMGetAtMenuBottom();
+ if (MBSAVELOC == -1) {
+ globals.itemRect = (**(mbPrivate***)&MBSAVELOC)->mbItemRect;
+ }
+ if (message == mChooseMsg) {
+ oldItem = *whichItemPtr;
+ }
+
+ TkCallMenuDefProc(procPtr, message, menu, menuRect, hitPt, whichItemPtr,
+ &globals);
+
+ LMSetMenuDisable(globals.menuDisable);
+ LMSetTopMenuItem(globals.menuTop);
+ LMSetAtMenuBottom(globals.menuBottom);
+ if ((message == mChooseMsg) && (oldItem != *whichItemPtr)
+ && (MBSAVELOC != -1)) {
+ (**(mbPrivate***)&MBSAVELOC)->mbItemRect = globals.itemRect;
+ SELECTRECT = globals.itemRect;
+ }
+}
diff --git a/mac/tkMacMDEF.r b/mac/tkMacMDEF.r
new file mode 100644
index 0000000..5c18104
--- /dev/null
+++ b/mac/tkMacMDEF.r
@@ -0,0 +1,45 @@
+/*
+ * tkMacMDEF.r --
+ *
+ * This file contains the actual MDEF. Since this is not likely to
+ * change much, this seems the easiest method to use. The address
+ * of the routine descriptor is written into offset 0x24 hex, and
+ * then when the MDEF is called, the Mixed Mode Manager will take
+ * care of the setup.
+ *
+ * This file also contains the icons 'SICN' used by the menu code
+ * in menu items.
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacMDEF.r 1.6 97/07/11 18:09:47
+ */
+
+#include <Types.r>
+
+/*
+ * This code was generated by a project file and will not need to be changed.
+ * It is just a stub. The address of the real MDEF handler will be blasted
+ * in.
+ */
+
+data 'MDEF' (591, preload) {
+ $"600A 0000 4D44 4546 024F 0000 4EFA 0004" /* `...MDEF.O..Nú.. */
+ $"4E75 4E56 FFEE 48E7 1830 362E 0018 246E" /* NuNVÿîHç.06...$n */
+ $"0008 267C 4D44 4546 594F 2EB8 0B54 201F" /* ..&|MDEFYO.¸.T . */
+ $"2D40 FFEE 554F 3EB8 0A0A 301F 3D40 FFF2" /* -@ÿîUO>¸..0.=@ÿò */
+ $"554F 3EB8 0A0C 301F 3D40 FFF4 0C78 FFFF" /* UO>¸..0.=@ÿô.xÿÿ */
+ $"0B5C 6612 2078 0B5C 2050 2D68 0006 FFF6" /* .\f. x.\ P-h..ÿö */
+ $"2D68 000A FFFA 0C43 0001 6602 3812 3F03" /* -h..ÿú.C..f.8.?. */
+ $"2F2E 0014 2F2E 0010 2F2E 000C 2F0A 486E" /* /.../.../.../.Hn */
+ $"FFEE 4E93 2F2E FFEE 21DF 0B54 3F2E FFF2" /* ÿîN“/.ÿî!ß.T?.ÿò */
+ $"31DF 0A0A 3F2E FFF4 31DF 0A0C 0C43 0001" /* 1ß..?.ÿô1ß...C.. */
+ $"662A B852 6726 0C78 FFFF 0B5C 671E 2078" /* f*¸Rg&.xÿÿ.\g. x */
+ $"0B5C 2050 216E FFF6 0006 216E FFFA 000A" /* .\ P!nÿö..!nÿú.. */
+ $"21EE FFF6 09FA 21EE FFFA 09FE 4CDF 0C18" /* !îÿöÆú!îÿúÆþLß.. */
+ $"4E5E 205F 4FEF 0012 4ED0 846D 6169 6E00" /* N^ _Oï..NЄmain. */
+ $"0000" /* .. */
+};
diff --git a/mac/tkMacMenu.c b/mac/tkMacMenu.c
new file mode 100644
index 0000000..33bb82b
--- /dev/null
+++ b/mac/tkMacMenu.c
@@ -0,0 +1,3994 @@
+/*
+ * tkMacMenu.c --
+ *
+ * This module implements the Mac-platform specific features of menus.
+ *
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacMenu.c 1.107 97/11/20 18:33:09
+ */
+
+#include <Menus.h>
+#include <OSUtils.h>
+#include <Palettes.h>
+#include <Resources.h>
+#include <string.h>
+#include <ToolUtils.h>
+#include <Balloons.h>
+#undef Status
+#include <Devices.h>
+#include "tkMenu.h"
+#include "tkMacInt.h"
+#include "tkMenuButton.h"
+
+typedef struct MacMenu {
+ MenuHandle menuHdl; /* The Menu Manager data structure. */
+ Rect menuRect; /* The rectangle as calculated in the
+ * MDEF. This is used to figure ou the
+ * clipping rgn before we push
+ * the <<MenuSelect>> virtual binding
+ * through. */
+} MacMenu;
+
+/*
+ * Various geometry definitions:
+ */
+
+#define CASCADE_ARROW_HEIGHT 10
+#define CASCADE_ARROW_WIDTH 8
+#define DECORATION_BORDER_WIDTH 2
+#define MAC_MARGIN_WIDTH 8
+
+/*
+ * The following are constants relating to the SICNs used for drawing the MDEF.
+ */
+
+#define SICN_RESOURCE_NUMBER 128
+
+#define SICN_HEIGHT 16
+#define SICN_ROWS 2
+#define CASCADE_ICON_WIDTH 7
+#define SHIFT_ICON_WIDTH 10
+#define OPTION_ICON_WIDTH 16
+#define CONTROL_ICON_WIDTH 12
+#define COMMAND_ICON_WIDTH 10
+
+#define CASCADE_ARROW 0
+#define SHIFT_ICON 1
+#define OPTION_ICON 2
+#define CONTROL_ICON 3
+#define COMMAND_ICON 4
+#define DOWN_ARROW 5
+#define UP_ARROW 6
+
+/*
+ * Platform specific flags for menu entries
+ *
+ * ENTRY_COMMAND_ACCEL Indicates the entry has the command key
+ * in its accelerator string.
+ * ENTRY_OPTION_ACCEL Indicates the entry has the option key
+ * in its accelerator string.
+ * ENTRY_SHIFT_ACCEL Indicates the entry has the shift key
+ * in its accelerator string.
+ * ENTRY_CONTROL_ACCEL Indicates the entry has the control key
+ * in its accelerator string.
+ */
+
+#define ENTRY_COMMAND_ACCEL ENTRY_PLATFORM_FLAG1
+#define ENTRY_OPTION_ACCEL ENTRY_PLATFORM_FLAG2
+#define ENTRY_SHIFT_ACCEL ENTRY_PLATFORM_FLAG3
+#define ENTRY_CONTROL_ACCEL ENTRY_PLATFORM_FLAG4
+#define ENTRY_ACCEL_MASK (ENTRY_COMMAND_ACCEL | ENTRY_OPTION_ACCEL \
+ | ENTRY_SHIFT_ACCEL | ENTRY_CONTROL_ACCEL)
+
+/*
+ * This structure is used to keep track of subfields within Macintosh menu
+ * items.
+ */
+
+typedef struct EntryGeometry {
+ int accelTextStart; /* Offset into the accel string where
+ * the text starts. Everything before
+ * this is modifier key descriptions.
+ */
+ int modifierWidth; /* Width of modifier symbols. */
+ int accelTextWidth; /* Width of the text after the modifier
+ * keys. */
+ int nonAccelMargin; /* The width of the margin for entries
+ * without accelerators. */
+} EntryGeometry;
+
+/*
+ * Structure to keep track of toplevel windows and their menubars.
+ */
+
+typedef struct TopLevelMenubarList {
+ struct TopLevelMenubarList *nextPtr;
+ /* The next window in the list. */
+ Tk_Window tkwin; /* The toplevel window. */
+ TkMenu *menuPtr; /* The menu associated with this
+ * toplevel. */
+} TopLevelMenubarList;
+
+/*
+ * Platform-specific flags for menus.
+ *
+ * MENU_APPLE_MENU 0 indicates a custom Apple menu has
+ * not been installed; 1 a custom Apple
+ * menu has been installed.
+ * MENU_HELP_MENU 0 indicates a custom Help menu has
+ * not been installed; 1 a custom Help
+ * menu has been installed.
+ * MENU_RECONFIGURE_PENDING 1 indicates that an idle handler has
+ * been scheduled to reconfigure the
+ * Macintosh MenuHandle.
+ */
+
+#define MENU_APPLE_MENU MENU_PLATFORM_FLAG1
+#define MENU_HELP_MENU MENU_PLATFORM_FLAG2
+#define MENU_RECONFIGURE_PENDING MENU_PLATFORM_FLAG3
+
+#define CASCADE_CMD (0x1b)
+ /* The special command char for cascade
+ * menus. */
+#define SEPARATOR_TEXT "\p(-"
+ /* The text for a menu separator. */
+
+#define MENUBAR_REDRAW_PENDING 1
+
+RgnHandle tkMenuCascadeRgn = NULL;
+ /* The region to clip drawing to when the
+ * MDEF is up. */
+int tkUseMenuCascadeRgn = 0; /* If this is 1, clipping code
+ * should intersect tkMenuCascadeRgn
+ * before drawing occurs.
+ * tkMenuCascadeRgn will only
+ * be valid when the value of this
+ * variable is 1. */
+
+static Tcl_HashTable commandTable;
+ /* The list of menuInstancePtrs associated with
+ * menu ids */
+static short currentAppleMenuID;
+ /* The id of the current Apple menu. 0 for
+ * none. */
+static short currentHelpMenuID; /* The id of the current Help menu. 0 for
+ * none. */
+static Tcl_Interp *currentMenuBarInterp;
+ /* The interpreter of the window that owns
+ * the current menubar. */
+static char *currentMenuBarName;
+ /* Malloced. Name of current menu in menu bar.
+ * NULL if no menu set. TO DO: make this a
+ * DString. */
+static Tk_Window currentMenuBarOwner;
+ /* Which window owns the current menu bar. */
+static int helpItemCount; /* The number of items in the help menu.
+ * -1 means that the help menu is
+ * unavailable. This does not include
+ * the automatically generated separator. */
+static int inPostMenu; /* We cannot be re-entrant like X
+ * windows. */
+static short lastMenuID; /* To pass to NewMenu; need to figure out
+ * a good way to do this. */
+static unsigned char lastCascadeID;
+ /* Cascades have to have ids that are
+ * less than 256. */
+static MacDrawable macMDEFDrawable;
+ /* Drawable for use by MDEF code */
+static MDEFScrollFlag = 0; /* Used so that popups don't scroll too soon. */
+static int menuBarFlags; /* Used for whether the menu bar needs
+ * redrawing or not. */
+static TkMenuDefUPP menuDefProc;/* The routine descriptor to the MDEF proc.
+ * The MDEF is needed to draw menus with
+ * non-standard attributes and to support
+ * tearoff menus. */
+static struct TearoffSelect {
+ TkMenu *menuPtr; /* The menu that is torn off */
+ Point point; /* The point to place the new menu */
+ Rect excludeRect; /* We don't want to drag tearoff highlights
+ * when we are in this menu */
+} tearoffStruct;
+
+static RgnHandle totalMenuRgn = NULL;
+ /* Used to update windows which have been
+ * obscured by menus. */
+static RgnHandle utilRgn = NULL;/* Used when creating the region that is to
+ * be clipped out while the MDEF is active. */
+
+static TopLevelMenubarList *windowListPtr;
+ /* A list of windows that have menubars set. */
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static void CompleteIdlers _ANSI_ARGS_((TkMenu *menuPtr));
+static void DrawMenuBarWhenIdle _ANSI_ARGS_((
+ ClientData clientData));
+static void DrawMenuEntryAccelerator _ANSI_ARGS_((
+ TkMenu *menuPtr, TkMenuEntry *mePtr,
+ Drawable d, GC gc, Tk_Font tkfont,
+ CONST Tk_FontMetrics *fmPtr,
+ Tk_3DBorder activeBorder, int x, int y,
+ int width, int height, int drawArrow));
+static void DrawMenuEntryBackground _ANSI_ARGS_((
+ TkMenu *menuPtr, TkMenuEntry *mePtr,
+ Drawable d, Tk_3DBorder activeBorder,
+ Tk_3DBorder bgBorder, int x, int y,
+ int width, int heigth));
+static void DrawMenuEntryIndicator _ANSI_ARGS_((
+ TkMenu *menuPtr, TkMenuEntry *mePtr,
+ Drawable d, GC gc, GC indicatorGC,
+ Tk_Font tkfont,
+ CONST Tk_FontMetrics *fmPtr, int x, int y,
+ int width, int height));
+static void DrawMenuEntryLabel _ANSI_ARGS_((
+ TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d,
+ GC gc, Tk_Font tkfont,
+ CONST Tk_FontMetrics *fmPtr, int x, int y,
+ int width, int height));
+static void DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr,
+ TkMenuEntry *mePtr, Drawable d, GC gc,
+ Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
+ int x, int y, int width, int height));
+static void DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr,
+ TkMenuEntry *mePtr, Drawable d, GC gc,
+ Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
+ int x, int y, int width, int height));
+static void FixMDEF _ANSI_ARGS_((void));
+static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr,
+ TkMenuEntry *mePtr, Tk_Font tkfont,
+ CONST Tk_FontMetrics *fmPtr, int *modWidthPtr,
+ int *textWidthPtr, int *heightPtr));
+static void GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr,
+ Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
+ int *widthPtr, int *heightPtr));
+static void GetMenuIndicatorGeometry _ANSI_ARGS_((
+ TkMenu *menuPtr, TkMenuEntry *mePtr,
+ Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
+ int *widthPtr, int *heightPtr));
+static void GetMenuSeparatorGeometry _ANSI_ARGS_((
+ TkMenu *menuPtr, TkMenuEntry *mePtr,
+ Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr,
+ int *widthPtr, int *heightPtr));
+static void GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr,
+ TkMenuEntry *mePtr, Tk_Font tkfont,
+ CONST Tk_FontMetrics *fmPtr, int *widthPtr,
+ int *heightPtr));
+static int GetNewID _ANSI_ARGS_((Tcl_Interp *interp,
+ TkMenu *menuInstPtr, int cascade,
+ short *menuIDPtr));
+static char FindMarkCharacter _ANSI_ARGS_((TkMenuEntry *mePtr));
+static void FreeID _ANSI_ARGS_((short menuID));
+static void InvalidateMDEFRgns _ANSI_ARGS_((void));
+static void MenuDefProc _ANSI_ARGS_((short message,
+ MenuHandle menu, Rect *menuRectPtr,
+ Point hitPt, short *whichItem,
+ TkMenuLowMemGlobals *globalsPtr));
+static void MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr));
+static void ReconfigureIndividualMenu _ANSI_ARGS_((
+ TkMenu *menuPtr, MenuHandle macMenuHdl,
+ int base));
+static void ReconfigureMacintoshMenu _ANSI_ARGS_ ((
+ ClientData clientData));
+static void RecursivelyClearActiveMenu _ANSI_ARGS_((
+ TkMenu *menuPtr));
+static void RecursivelyDeleteMenu _ANSI_ARGS_((
+ TkMenu *menuPtr));
+static void RecursivelyInsertMenu _ANSI_ARGS_((
+ TkMenu *menuPtr));
+static void SetDefaultMenubar _ANSI_ARGS_((void));
+static int SetMenuCascade _ANSI_ARGS_((TkMenu *menuPtr));
+static void SetMenuIndicator _ANSI_ARGS_((TkMenuEntry *mePtr));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacUseID --
+ *
+ * Take the ID out of the available list for new menus. Used by the
+ * default menu bar's menus so that they do not get created at the tk
+ * level. See GetNewID for more information.
+ *
+ * Results:
+ * Returns TCL_OK if the id was not in use. Returns TCL_ERROR if the
+ * id was in use.
+ *
+ * Side effects:
+ * A hash table entry in the command table is created with a NULL
+ * value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacUseMenuID(
+ short macID) /* The id to take out of the table */
+{
+ Tcl_HashEntry *commandEntryPtr;
+ int newEntry;
+
+ TkMenuInit();
+ commandEntryPtr = Tcl_CreateHashEntry(&commandTable, (char *) macID,
+ &newEntry);
+ if (newEntry == 1) {
+ Tcl_SetHashValue(commandEntryPtr, NULL);
+ return TCL_OK;
+ } else {
+ return TCL_ERROR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetNewID --
+ *
+ * Allocates a new menu id and marks it in use. Each menu on the
+ * mac must be designated by a unique id, which is a short. In
+ * addition, some ids are reserved by the system. Since Tk uses
+ * mostly dynamic menus, we must allocate and free these ids on
+ * the fly. We use the id as a key into a hash table; if there
+ * is no hash entry, we know that we can use the id.
+ *
+ * Results:
+ * Returns TCL_OK if succesful; TCL_ERROR if there are no more
+ * ids of the appropriate type to allocate. menuIDPtr contains
+ * the new id if succesful.
+ *
+ * Side effects:
+ * An entry is created for the menu in the command hash table,
+ * and the hash entry is stored in the appropriate field in the
+ * menu data structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GetNewID(
+ Tcl_Interp *interp, /* Used for error reporting */
+ TkMenu *menuPtr, /* The menu we are working with */
+ int cascade, /* 0 if we are working with a normal menu;
+ 1 if we are working with a cascade */
+ short *menuIDPtr) /* The resulting id */
+{
+ int found = 0;
+ int newEntry;
+ Tcl_HashEntry *commandEntryPtr;
+ short returnID = *menuIDPtr;
+
+ /*
+ * The following code relies on shorts and unsigned chars wrapping
+ * when the highest value is incremented. Also, the values between
+ * 236 and 255 inclusive are reserved for DA's by the Mac OS.
+ */
+
+ if (!cascade) {
+ short curID = lastMenuID + 1;
+ if (curID == 236) {
+ curID = 256;
+ }
+
+ while (curID != lastMenuID) {
+ commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
+ (char *) curID, &newEntry);
+ if (newEntry == 1) {
+ found = 1;
+ lastMenuID = returnID = curID;
+ break;
+ }
+ curID++;
+ if (curID == 236) {
+ curID = 256;
+ }
+ }
+ } else {
+
+ /*
+ * Cascade ids must be between 0 and 235 only, so they must be
+ * dealt with separately.
+ */
+
+ unsigned char curID = lastCascadeID + 1;
+ if (curID == 236) {
+ curID = 0;
+ }
+
+ while (curID != lastCascadeID) {
+ commandEntryPtr = Tcl_CreateHashEntry(&commandTable,
+ (char *) curID, &newEntry);
+ if (newEntry == 1) {
+ found = 1;
+ lastCascadeID = returnID = curID;
+ break;
+ }
+ curID++;
+ if (curID == 236) {
+ curID = 0;
+ }
+ }
+ }
+
+ if (found) {
+ Tcl_SetHashValue(commandEntryPtr, (char *) menuPtr);
+ *menuIDPtr = returnID;
+ return TCL_OK;
+ } else {
+ Tcl_AppendResult(interp, "No more menus can be allocated.",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeID --
+ *
+ * Marks the id as free.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The hash table entry for the ID is cleared.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeID(
+ short menuID) /* The id to free */
+{
+ Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable,
+ (char *) menuID);
+
+ if (entryPtr != NULL) {
+ Tcl_DeleteHashEntry(entryPtr);
+ }
+ if (menuID == currentAppleMenuID) {
+ currentAppleMenuID = 0;
+ }
+ if (menuID == currentHelpMenuID) {
+ currentHelpMenuID = 0;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpNewMenu --
+ *
+ * Gets a new blank menu. Only the platform specific options are filled
+ * in.
+ *
+ * Results:
+ * Returns a standard TCL error.
+ *
+ * Side effects:
+ * Allocates a Macintosh menu handle and puts in the platformData
+ * field of the menuPtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpNewMenu(
+ TkMenu *menuPtr) /* The common structure we are making the
+ * platform structure for. */
+{
+ short menuID;
+ Str255 itemText;
+ int length;
+ MenuHandle macMenuHdl;
+ int error = TCL_OK;
+
+ error = GetNewID(menuPtr->interp, menuPtr, 0, &menuID);
+ if (error != TCL_OK) {
+ return error;
+ }
+ length = strlen(Tk_PathName(menuPtr->tkwin));
+ memmove(&itemText[1], Tk_PathName(menuPtr->tkwin),
+ (length > 230) ? 230 : length);
+ itemText[0] = (length > 230) ? 230 : length;
+ macMenuHdl = NewMenu(menuID, itemText);
+#ifdef GENERATINGCFM
+ {
+ Handle mdefProc = GetResource('MDEF', 591);
+ Handle sicnHandle = GetResource('SICN', SICN_RESOURCE_NUMBER);
+ if ((mdefProc != NULL) && (sicnHandle != NULL)) {
+ (*macMenuHdl)->menuProc = mdefProc;
+ }
+ }
+#endif
+ menuPtr->platformData = (TkMenuPlatformData) ckalloc(sizeof(MacMenu));
+ ((MacMenu *) menuPtr->platformData)->menuHdl = macMenuHdl;
+ SetRect(&((MacMenu *) menuPtr->platformData)->menuRect, 0, 0, 0, 0);
+
+ if ((currentMenuBarInterp == menuPtr->interp)
+ && (currentMenuBarName != NULL)) {
+ Tk_Window parentWin = Tk_Parent(menuPtr->tkwin);
+
+ if (strcmp(currentMenuBarName, Tk_PathName(parentWin)) == 0) {
+ if ((strcmp(Tk_PathName(menuPtr->tkwin)
+ + strlen(Tk_PathName(parentWin)), ".apple") == 0)
+ || (strcmp(Tk_PathName(menuPtr->tkwin)
+ + strlen(Tk_PathName(parentWin)), ".help") == 0)) {
+ if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
+ menuBarFlags |= MENUBAR_REDRAW_PENDING;
+ }
+ }
+ }
+ }
+
+ menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyMenu --
+ *
+ * Destroys platform-specific menu structures.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All platform-specific allocations are freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyMenu(
+ TkMenu *menuPtr) /* The common menu structure */
+{
+ MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
+
+ if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
+ Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
+ menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
+ }
+
+ if ((*macMenuHdl)->menuID == currentHelpMenuID) {
+ MenuHandle helpMenuHdl;
+
+ if ((HMGetHelpMenuHandle(&helpMenuHdl) == noErr)
+ && (helpMenuHdl != NULL)) {
+ int i, count = CountMItems(helpMenuHdl);
+
+ for (i = helpItemCount; i <= count; i++) {
+ DeleteMenuItem(helpMenuHdl, helpItemCount);
+ }
+ }
+ currentHelpMenuID = 0;
+ }
+
+ if (menuPtr->platformData != NULL) {
+ DeleteMenu((*macMenuHdl)->menuID);
+ FreeID((*macMenuHdl)->menuID);
+ DisposeMenu(macMenuHdl);
+ ckfree((char *) menuPtr->platformData);
+ menuPtr->platformData = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetMenuCascade --
+ *
+ * Does any cleanup to change a menu from a normal to a cascade.
+ *
+ * Results:
+ * Standard Tcl error.
+ *
+ * Side effects:
+ * The mac menu id is reset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetMenuCascade(
+ TkMenu* menuPtr) /* The menu we are setting up to be a
+ * cascade. */
+{
+ MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
+ short newMenuID, menuID = (*macMenuHdl)->menuID;
+ int error = TCL_OK;
+
+ if (menuID >= 256) {
+ error = GetNewID(menuPtr->interp, menuPtr, 1, &newMenuID);
+ if (error == TCL_OK) {
+ FreeID(menuID);
+ (*macMenuHdl)->menuID = newMenuID;
+ }
+ }
+ return error;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyMenuEntry --
+ *
+ * Cleans up platform-specific menu entry items.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * All platform-specific allocations are freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyMenuEntry(
+ TkMenuEntry *mePtr) /* The common structure for the menu
+ * entry. */
+{
+ TkMenu *menuPtr = mePtr->menuPtr;
+
+ ckfree((char *) mePtr->platformEntryData);
+ if ((menuPtr->platformData != NULL)
+ && !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
+ menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEntryText --
+ *
+ * Given a menu entry, gives back the text that should go in it.
+ * Separators should be done by the caller, as they have to be
+ * handled specially.
+ *
+ * Results:
+ * itemText points to the new text for the item.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetEntryText(
+ TkMenuEntry *mePtr, /* A pointer to the menu entry. */
+ Str255 itemText) /* The pascal string containing the text */
+{
+ if (mePtr->type == TEAROFF_ENTRY) {
+ strcpy((char *)itemText, (const char *)"\p(Tear-off)");
+ } else if (mePtr->imageString != NULL) {
+ strcpy((char *)itemText, (const char *)"\p(Image)");
+ } else if (mePtr->bitmap != None) {
+ strcpy((char *)itemText, (const char *)"\p(Pixmap)");
+ } else if (mePtr->label == NULL || mePtr->labelLength == 0) {
+
+ /*
+ * The Mac menu manager does not like null strings.
+ */
+
+ strcpy((char *)itemText, (const char *)"\p ");
+ } else {
+ char *text = mePtr->label;
+ int i;
+
+ itemText[0] = 0;
+ for (i = 1; (*text != '\0') && (i <= 230); i++, text++) {
+ if ((*text == '.')
+ && (*(text + 1) != '\0') && (*(text + 1) == '.')
+ && (*(text + 2) != '\0') && (*(text + 2) == '.')) {
+ itemText[i] = 'É';
+ text += 2;
+ } else {
+ itemText[i] = *text;
+ }
+ itemText[0] += 1;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindMarkCharacter --
+ *
+ * Finds the Macintosh mark character based on the font of the
+ * item. We calculate a good mark character based on the font
+ * that this item is rendered in.
+ *
+ * We try the following special mac characters. If none of them
+ * are present, just use the check mark.
+ * '' - Check mark character
+ * '¥' - Bullet character
+ * '' - Filled diamond
+ * '×' - Hollow diamond
+ * 'Ñ' = Long dash ("em dash")
+ * '-' = short dash (minus, "en dash");
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * New item is added to platform menu
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char
+FindMarkCharacter(
+ TkMenuEntry *mePtr) /* The entry we are finding the character
+ * for. */
+{
+ char markChar;
+ Tk_Font tkfont = (mePtr->tkfont == NULL) ? mePtr->menuPtr->tkfont
+ : mePtr->tkfont;
+
+ if (!TkMacIsCharacterMissing(tkfont, '')) {
+ markChar = '';
+ } else if (!TkMacIsCharacterMissing(tkfont, '¥')) {
+ markChar = '¥';
+ } else if (!TkMacIsCharacterMissing(tkfont, '')) {
+ markChar = '';
+ } else if (!TkMacIsCharacterMissing(tkfont, '×')) {
+ markChar = '×';
+ } else if (!TkMacIsCharacterMissing(tkfont, 'Ñ')) {
+ markChar = 'Ñ';
+ } else if (!TkMacIsCharacterMissing(tkfont, '-')) {
+ markChar = '-';
+ } else {
+ markChar = '';
+ }
+ return markChar;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetMenuIndicator --
+ *
+ * Sets the Macintosh mark character based on the font of the
+ * item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * New item is added to platform menu
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetMenuIndicator(
+ TkMenuEntry *mePtr) /* The entry we are setting */
+{
+ TkMenu *menuPtr = mePtr->menuPtr;
+ MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
+ char markChar;
+
+ /*
+ * There can be no indicators on menus that are not checkbuttons
+ * or radiobuttons. However, we should go ahead and set them
+ * so that menus look right when they are displayed. We should
+ * not set cascade entries, however, as the mark character
+ * means something different for cascade items on the Mac.
+ * Also, we do reflect the tearOff menu items in the Mac menu
+ * handle, so we ignore them.
+ */
+
+ if (mePtr->type == CASCADE_ENTRY) {
+ return;
+ }
+
+ if (((mePtr->type == RADIO_BUTTON_ENTRY)
+ || (mePtr->type == CHECK_BUTTON_ENTRY))
+ && (mePtr->indicatorOn)
+ && (mePtr->entryFlags & ENTRY_SELECTED)) {
+ markChar = FindMarkCharacter(mePtr);
+ } else {
+ markChar = 0;
+ }
+ SetItemMark(macMenuHdl, mePtr->index + 1, markChar);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetMenuTitle --
+ *
+ * Sets title of menu so that the text displays correctly in menubar.
+ * This code directly manipulates menu handle data. This code
+ * was originally part of an ancient Apple Developer Response mail.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menu handle will change size depending on the length of the
+ * title
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetMenuTitle(
+ MenuHandle menuHdl, /* The menu we are setting the title of. */
+ char *title) /* The C string to set the title to. */
+{
+ int oldLength, newLength, oldHandleSize, dataLength;
+ Ptr menuDataPtr;
+
+ menuDataPtr = (Ptr) (*menuHdl)->menuData;
+
+ if (strncmp(title, menuDataPtr + 1, menuDataPtr[0]) != 0) {
+ newLength = strlen(title) + 1;
+ oldLength = menuDataPtr[0] + 1;
+ oldHandleSize = GetHandleSize((Handle) menuHdl);
+ dataLength = oldHandleSize - (sizeof(MenuInfo) - sizeof(Str255))
+ - oldLength;
+ if (newLength > oldLength) {
+ SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength
+ - oldLength));
+ menuDataPtr = (Ptr) (*menuHdl)->menuData;
+ }
+
+ BlockMove(menuDataPtr + oldLength, menuDataPtr + newLength,
+ dataLength);
+ BlockMove(title, menuDataPtr + 1, newLength - 1);
+ menuDataPtr[0] = newLength - 1;
+
+ if (newLength < oldLength) {
+ SetHandleSize((Handle) menuHdl, oldHandleSize + (newLength
+ - oldLength));
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpConfigureMenuEntry --
+ *
+ * Processes configurations for menu entries.
+ *
+ * Results:
+ * Returns standard TCL result. If TCL_ERROR is returned, then
+ * interp->result contains an error message.
+ *
+ * Side effects:
+ * Configuration information get set for mePtr; old resources
+ * get freed, if any need it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpConfigureMenuEntry(
+ register TkMenuEntry *mePtr) /* Information about menu entry; may
+ * or may not already have values for
+ * some fields. */
+{
+ TkMenu *menuPtr = mePtr->menuPtr;
+ int index = mePtr->index;
+ MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
+ MenuHandle helpMenuHdl = NULL;
+
+ /*
+ * Cascade menus have to have menu IDs of less than 256. So
+ * we need to change the child menu if this has been configured
+ * for a cascade item.
+ */
+
+ if (mePtr->type == CASCADE_ENTRY) {
+ if ((mePtr->childMenuRefPtr != NULL)
+ && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
+ MenuHandle childMenuHdl = ((MacMenu *) mePtr
+ ->childMenuRefPtr->menuPtr->platformData)->menuHdl;
+
+ if (childMenuHdl != NULL) {
+ int error = SetMenuCascade(mePtr->childMenuRefPtr->menuPtr);
+
+ if (error != TCL_OK) {
+ return error;
+ }
+
+ if (menuPtr->menuType == MENUBAR) {
+ SetMenuTitle(childMenuHdl, mePtr->label);
+ }
+ }
+ }
+ }
+
+ /*
+ * We need to parse the accelerator string. If it has the strings
+ * for Command, Control, Shift or Option, we need to flag it
+ * so we can draw the symbols for it. We also need to precalcuate
+ * the position of the first real character we are drawing.
+ */
+
+ if (0 == mePtr->accelLength) {
+ ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart = -1;
+ } else {
+ char *accelString = mePtr->accel;
+ mePtr->entryFlags |= ~ENTRY_ACCEL_MASK;
+
+ while (1) {
+ if ((0 == strncasecmp("Control", accelString, 6))
+ && (('-' == accelString[6]) || ('+' == accelString[6]))) {
+ mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
+ accelString += 7;
+ } else if ((0 == strncasecmp("Ctrl", accelString, 4))
+ && (('-' == accelString[4]) || ('+' == accelString[4]))) {
+ mePtr->entryFlags |= ENTRY_CONTROL_ACCEL;
+ accelString += 5;
+ } else if ((0 == strncasecmp("Shift", accelString, 5))
+ && (('-' == accelString[5]) || ('+' == accelString[5]))) {
+ mePtr->entryFlags |= ENTRY_SHIFT_ACCEL;
+ accelString += 6;
+ } else if ((0 == strncasecmp("Option", accelString, 6))
+ && (('-' == accelString[6]) || ('+' == accelString[6]))) {
+ mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
+ accelString += 7;
+ } else if ((0 == strncasecmp("Opt", accelString, 3))
+ && (('-' == accelString[3]) || ('+' == accelString[3]))) {
+ mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
+ accelString += 4;
+ } else if ((0 == strncasecmp("Command", accelString, 7))
+ && (('-' == accelString[7]) || ('+' == accelString[7]))) {
+ mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
+ accelString += 8;
+ } else if ((0 == strncasecmp("Cmd", accelString, 3))
+ && (('-' == accelString[3]) || ('+' == accelString[3]))) {
+ mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
+ accelString += 4;
+ } else if ((0 == strncasecmp("Alt", accelString, 3))
+ && (('-' == accelString[3]) || ('+' == accelString[3]))) {
+ mePtr->entryFlags |= ENTRY_OPTION_ACCEL;
+ accelString += 4;
+ } else if ((0 == strncasecmp("Meta", accelString, 4))
+ && (('-' == accelString[4]) || ('+' == accelString[4]))) {
+ mePtr->entryFlags |= ENTRY_COMMAND_ACCEL;
+ accelString += 5;
+ } else {
+ break;
+ }
+ }
+
+ ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart
+ = ((long) accelString - (long) mePtr->accel);
+ }
+
+ if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
+ menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReconfigureIndividualMenu --
+ *
+ * This routine redoes the guts of the menu. It works from
+ * a base item and offset, so that a regular menu will
+ * just have all of its items added, but the help menu will
+ * have all of its items appended after the apple-defined
+ * items.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Macintosh menu handle is updated
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ReconfigureIndividualMenu(
+ TkMenu *menuPtr, /* The menu we are affecting. */
+ MenuHandle macMenuHdl, /* The macintosh menu we are affecting.
+ * Will not necessarily be
+ * menuPtr->platformData because this could
+ * be the help menu. */
+ int base) /* The last index that we do not want
+ * touched. 0 for normal menus;
+ * helpMenuItemCount for help menus. */
+{
+ int count;
+ int index;
+ TkMenuEntry *mePtr;
+ Str255 itemText;
+ int parentDisabled = 0;
+
+ for (mePtr = menuPtr->menuRefPtr->parentEntryPtr; mePtr != NULL;
+ mePtr = mePtr->nextCascadePtr) {
+ if (strcmp(Tk_PathName(menuPtr->tkwin), mePtr->name) == 0) {
+ if (mePtr->state == tkDisabledUid) {
+ parentDisabled = 1;
+ }
+ break;
+ }
+ }
+
+ /*
+ * First, we get rid of all of the old items.
+ */
+
+ count = CountMItems(macMenuHdl);
+ for (index = base; index < count; index++) {
+ DeleteMenuItem(macMenuHdl, base + 1);
+ }
+
+ count = menuPtr->numEntries;
+
+ for (index = 1; index <= count; index++) {
+ mePtr = menuPtr->entries[index - 1];
+
+ /*
+ * We have to do separators separately because SetMenuItemText
+ * does not parse meta-characters.
+ */
+
+ if (mePtr->type == SEPARATOR_ENTRY) {
+ AppendMenu(macMenuHdl, SEPARATOR_TEXT);
+ } else {
+ GetEntryText(mePtr, itemText);
+ AppendMenu(macMenuHdl, "\px");
+ SetMenuItemText(macMenuHdl, base + index, itemText);
+
+ /*
+ * Set enabling and disabling correctly.
+ */
+
+ if (parentDisabled || (mePtr->state == tkDisabledUid)) {
+ DisableItem(macMenuHdl, base + index);
+ } else {
+ EnableItem(macMenuHdl, base + index);
+ }
+
+ /*
+ * Set the check mark for check entries and radio entries.
+ */
+
+ SetItemMark(macMenuHdl, base + index, 0);
+ if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY)) {
+ CheckItem(macMenuHdl, base + index, (mePtr->entryFlags
+ & ENTRY_SELECTED) && (mePtr->indicatorOn));
+ if ((mePtr->indicatorOn)
+ && (mePtr->entryFlags & ENTRY_SELECTED)) {
+ SetItemMark(macMenuHdl, base + index,
+ FindMarkCharacter(mePtr));
+ }
+ }
+
+ if (mePtr->type == CASCADE_ENTRY) {
+ if ((mePtr->childMenuRefPtr != NULL)
+ && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
+ MenuHandle childMenuHdl =
+ ((MacMenu *) mePtr->childMenuRefPtr
+ ->menuPtr->platformData)->menuHdl;
+
+ if (childMenuHdl == NULL) {
+ childMenuHdl = ((MacMenu *) mePtr->childMenuRefPtr
+ ->menuPtr->platformData)->menuHdl;
+ }
+ if (childMenuHdl != NULL) {
+ SetItemMark(macMenuHdl, base + index,
+ (*childMenuHdl)->menuID);
+ SetItemCmd(macMenuHdl, base + index, CASCADE_CMD);
+ }
+ /*
+ * If we changed the highligthing of this menu, its
+ * children all have to be reconfigured so that
+ * their state will be reflected in the menubar.
+ */
+
+ if (!(mePtr->childMenuRefPtr->menuPtr->menuFlags
+ & MENU_RECONFIGURE_PENDING)) {
+ mePtr->childMenuRefPtr->menuPtr->menuFlags
+ |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
+ (ClientData) mePtr->childMenuRefPtr->menuPtr);
+ }
+ }
+ }
+
+ if ((mePtr->type != CASCADE_ENTRY)
+ && (ENTRY_COMMAND_ACCEL
+ == (mePtr->entryFlags & ENTRY_ACCEL_MASK))) {
+ SetItemCmd(macMenuHdl, index, mePtr
+ ->accel[((EntryGeometry *)mePtr->platformEntryData)
+ ->accelTextStart]);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReconfigureMacintoshMenu --
+ *
+ * Rebuilds the Macintosh MenuHandle items from the menu. Called
+ * usually as an idle handler, but can be called synchronously
+ * if the menu is about to be posted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Configuration information get set for mePtr; old resources
+ * get freed, if any need it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ReconfigureMacintoshMenu(
+ ClientData clientData) /* Information about menu entry; may
+ * or may not already have values for
+ * some fields. */
+{
+ TkMenu *menuPtr = (TkMenu *) clientData;
+ MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
+ MenuHandle helpMenuHdl = NULL;
+
+ menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING;
+
+ if (NULL == macMenuHdl) {
+ return;
+ }
+
+ ReconfigureIndividualMenu(menuPtr, macMenuHdl, 0);
+
+ if (menuPtr->menuFlags & MENU_APPLE_MENU) {
+ AddResMenu(macMenuHdl, 'DRVR');
+ }
+
+ if ((*macMenuHdl)->menuID == currentHelpMenuID) {
+ HMGetHelpMenuHandle(&helpMenuHdl);
+ if (helpMenuHdl != NULL) {
+ ReconfigureIndividualMenu(menuPtr, helpMenuHdl, helpItemCount);
+ }
+ }
+
+ if (menuPtr->menuType == MENUBAR) {
+ if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
+ menuBarFlags |= MENUBAR_REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CompleteIdlers --
+ *
+ * Completes all idle handling so that the menus are in sync when
+ * the user invokes them with the mouse.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Macintosh menu handles are flushed out.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+CompleteIdlers(
+ TkMenu *menuPtr) /* The menu we are completing. */
+{
+ int i;
+
+ if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) {
+ Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr);
+ ReconfigureMacintoshMenu((ClientData) menuPtr);
+ }
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
+ if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
+ && (menuPtr->entries[i]->childMenuRefPtr->menuPtr
+ != NULL)) {
+ CompleteIdlers(menuPtr->entries[i]->childMenuRefPtr
+ ->menuPtr);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpPostMenu --
+ *
+ * Posts a menu on the screen
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menu is posted and handled.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpPostMenu(
+ Tcl_Interp *interp, /* The interpreter this menu lives in */
+ TkMenu *menuPtr, /* The menu we are posting */
+ int x, /* The global x-coordinate of the top, left-
+ * hand corner of where the menu is supposed
+ * to be posted. */
+ int y) /* The global y-coordinate */
+{
+ MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl;
+ long popUpResult;
+ int result;
+ int oldMode;
+
+ if (inPostMenu) {
+ Tcl_AppendResult(interp,
+ "Cannot call post menu while already posting menu",
+ (char *) NULL);
+ result = TCL_ERROR;
+ } else {
+ Window dummyWin;
+ unsigned int state;
+ int dummy, mouseX, mouseY;
+ short menuID;
+ Window window;
+ int oldWidth = menuPtr->totalWidth;
+ Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
+
+ inPostMenu++;
+
+ result = TkPreprocessMenu(menuPtr);
+ if (result != TCL_OK) {
+ inPostMenu--;
+ return result;
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means
+ * we are dead and should go away.
+ */
+
+ if (menuPtr->tkwin == NULL) {
+ inPostMenu--;
+ return TCL_OK;
+ }
+
+ CompleteIdlers(menuPtr);
+ if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL);
+ DrawMenuBarWhenIdle((ClientData *) NULL);
+ }
+
+ if (NULL == parentWindow) {
+ tearoffStruct.excludeRect.top = tearoffStruct.excludeRect.left
+ = tearoffStruct.excludeRect.bottom
+ = tearoffStruct.excludeRect.right = SHRT_MAX;
+ } else {
+ int left, top;
+
+ Tk_GetRootCoords(parentWindow, &left, &top);
+ tearoffStruct.excludeRect.left = left;
+ tearoffStruct.excludeRect.top = top;
+ tearoffStruct.excludeRect.right = left + Tk_Width(parentWindow);
+ tearoffStruct.excludeRect.bottom = top + Tk_Height(parentWindow);
+ if (Tk_Class(parentWindow) == Tk_GetUid("Menubutton")) {
+ TkWindow *parentWinPtr = (TkWindow *) parentWindow;
+ TkMenuButton *mbPtr =
+ (TkMenuButton *) parentWinPtr->instanceData;
+ int menuButtonWidth = Tk_Width(parentWindow)
+ - 2 * (mbPtr->highlightWidth + mbPtr->borderWidth + 1);
+ menuPtr->totalWidth = menuButtonWidth > menuPtr->totalWidth
+ ? menuButtonWidth : menuPtr->totalWidth;
+ }
+ }
+
+ InsertMenu(macMenuHdl, -1);
+ RecursivelyInsertMenu(menuPtr);
+ CountMItems(macMenuHdl);
+
+ FixMDEF();
+ oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ popUpResult = PopUpMenuSelect(macMenuHdl, y, x, menuPtr->active);
+ Tcl_SetServiceMode(oldMode);
+
+ menuPtr->totalWidth = oldWidth;
+ RecursivelyDeleteMenu(menuPtr);
+ DeleteMenu((*macMenuHdl)->menuID);
+
+ /*
+ * Simulate the mouse up.
+ */
+
+ XQueryPointer(NULL, None, &dummyWin, &dummyWin, &mouseX,
+ &mouseY, &dummy, &dummy, &state);
+ window = Tk_WindowId(menuPtr->tkwin);
+ TkGenerateButtonEvent(mouseX, mouseY, window, state);
+
+ /*
+ * Dispatch the command.
+ */
+
+ menuID = HiWord(popUpResult);
+ if (menuID != 0) {
+ result = TkMacDispatchMenuEvent(menuID, LoWord(popUpResult));
+ } else {
+ TkMacHandleTearoffMenu();
+ result = TCL_OK;
+ }
+ InvalidateMDEFRgns();
+ RecursivelyClearActiveMenu(menuPtr);
+
+ inPostMenu--;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuNewEntry --
+ *
+ * Adds a pointer to a new menu entry structure with the platform-
+ * specific fields filled in. The Macintosh uses the
+ * platformEntryData field of the TkMenuEntry record to store
+ * geometry information.
+ *
+ * Results:
+ * Standard TCL error.
+ *
+ * Side effects:
+ * Storage gets allocated. New menu entry data is put into the
+ * platformEntryData field of the mePtr.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpMenuNewEntry(
+ TkMenuEntry *mePtr) /* The menu we are adding an entry to */
+{
+ EntryGeometry *geometryPtr =
+ (EntryGeometry *) ckalloc(sizeof(EntryGeometry));
+ TkMenu *menuPtr = mePtr->menuPtr;
+
+ geometryPtr->accelTextStart = 0;
+ geometryPtr->accelTextWidth = 0;
+ geometryPtr->nonAccelMargin = 0;
+ geometryPtr->modifierWidth = 0;
+ mePtr->platformEntryData = (TkMenuPlatformEntryData) geometryPtr;
+ if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) {
+ menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ *
+ * DrawMenuBarWhenIdle --
+ *
+ * Update the menu bar next time there is an idle event.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Menu bar is redrawn.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawMenuBarWhenIdle(
+ ClientData clientData) /* ignored here */
+{
+ TkMenuReferences *menuRefPtr;
+ TkMenu *appleMenuPtr, *helpMenuPtr;
+ MenuHandle macMenuHdl;
+ Tcl_HashEntry *hashEntryPtr;
+
+ /*
+ * We need to clear the apple and help menus of any extra items.
+ */
+
+ if (currentAppleMenuID != 0) {
+ hashEntryPtr = Tcl_FindHashEntry(&commandTable,
+ (char *) currentAppleMenuID);
+ appleMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
+ TkpDestroyMenu(appleMenuPtr);
+ TkpNewMenu(appleMenuPtr);
+ appleMenuPtr->menuFlags &= ~MENU_APPLE_MENU;
+ appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
+ (ClientData) appleMenuPtr);
+ }
+
+ if (currentHelpMenuID != 0) {
+ hashEntryPtr = Tcl_FindHashEntry(&commandTable,
+ (char *) currentHelpMenuID);
+ helpMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr);
+ TkpDestroyMenu(helpMenuPtr);
+ TkpNewMenu(helpMenuPtr);
+ helpMenuPtr->menuFlags &= ~MENU_HELP_MENU;
+ helpMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
+ (ClientData) helpMenuPtr);
+ }
+
+ /*
+ * We need to find the clone of this menu that is the menubar.
+ * Once we do that, for every cascade in the menu, we need to
+ * insert the Mac menu in the Mac menubar. Finally, we need
+ * to redraw the menubar.
+ */
+
+ menuRefPtr = NULL;
+ if (currentMenuBarName != NULL) {
+ menuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
+ currentMenuBarName);
+ }
+ if (menuRefPtr != NULL) {
+ TkMenu *menuPtr, *menuBarPtr;
+ TkMenu *cascadeMenuPtr;
+ char *appleMenuName, *helpMenuName;
+ int appleIndex = -1, helpIndex = -1;
+ int i;
+
+ menuPtr = menuRefPtr->menuPtr;
+ if (menuPtr != NULL) {
+ TkMenuReferences *specialMenuRefPtr;
+ TkMenuEntry *specialEntryPtr;
+
+ appleMenuName = ckalloc(strlen(currentMenuBarName)
+ + 1 + strlen(".apple") + 1);
+ sprintf(appleMenuName, "%s.apple",
+ Tk_PathName(menuPtr->tkwin));
+ specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
+ appleMenuName);
+ if ((specialMenuRefPtr != NULL)
+ && (specialMenuRefPtr->menuPtr != NULL)) {
+ for (specialEntryPtr
+ = specialMenuRefPtr->parentEntryPtr;
+ specialEntryPtr != NULL;
+ specialEntryPtr
+ = specialEntryPtr->nextCascadePtr) {
+ if (specialEntryPtr->menuPtr == menuPtr) {
+ appleIndex = specialEntryPtr->index;
+ break;
+ }
+ }
+ }
+ ckfree(appleMenuName);
+
+ helpMenuName = ckalloc(strlen(currentMenuBarName)
+ + 1 + strlen(".help") + 1);
+ sprintf(helpMenuName, "%s.help",
+ Tk_PathName(menuPtr->tkwin));
+ specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
+ helpMenuName);
+ if ((specialMenuRefPtr != NULL)
+ && (specialMenuRefPtr->menuPtr != NULL)) {
+ for (specialEntryPtr
+ = specialMenuRefPtr->parentEntryPtr;
+ specialEntryPtr != NULL;
+ specialEntryPtr
+ = specialEntryPtr->nextCascadePtr) {
+ if (specialEntryPtr->menuPtr == menuPtr) {
+ helpIndex = specialEntryPtr->index;
+ break;
+ }
+ }
+ }
+ ckfree(helpMenuName);
+
+ }
+
+ for (menuBarPtr = menuPtr;
+ (menuBarPtr != NULL)
+ && (menuBarPtr->menuType != MENUBAR);
+ menuBarPtr = menuBarPtr->nextInstancePtr) {
+
+ /*
+ * Null loop body.
+ */
+
+ }
+
+ if (menuBarPtr == NULL) {
+ SetDefaultMenubar();
+ } else {
+ if (menuBarPtr->tearOff != menuPtr->tearOff) {
+ if (menuBarPtr->tearOff) {
+ appleIndex = (-1 == appleIndex) ? appleIndex
+ : appleIndex + 1;
+ helpIndex = (-1 == helpIndex) ? helpIndex
+ : helpIndex + 1;
+ } else {
+ appleIndex = (-1 == appleIndex) ? appleIndex
+ : appleIndex - 1;
+ helpIndex = (-1 == helpIndex) ? helpIndex
+ : helpIndex - 1;
+ }
+ }
+ ClearMenuBar();
+
+ if (appleIndex == -1) {
+ InsertMenu(tkAppleMenu, 0);
+ currentAppleMenuID = 0;
+ } else {
+ short appleID;
+ appleMenuPtr = menuBarPtr->entries[appleIndex]
+ ->childMenuRefPtr->menuPtr;
+ TkpDestroyMenu(appleMenuPtr);
+ GetNewID(appleMenuPtr->interp, appleMenuPtr, 0,
+ &appleID);
+ macMenuHdl = NewMenu(appleID, "\p\024");
+ appleMenuPtr->platformData =
+ (TkMenuPlatformData) ckalloc(sizeof(MacMenu));
+ ((MacMenu *)appleMenuPtr->platformData)->menuHdl
+ = macMenuHdl;
+ SetRect(&((MacMenu *) appleMenuPtr->platformData)->menuRect,
+ 0, 0, 0, 0);
+ appleMenuPtr->menuFlags |= MENU_APPLE_MENU;
+ if (!(appleMenuPtr->menuFlags
+ & MENU_RECONFIGURE_PENDING)) {
+ appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
+ (ClientData) appleMenuPtr);
+ }
+ InsertMenu(macMenuHdl, 0);
+ RecursivelyInsertMenu(appleMenuPtr);
+ currentAppleMenuID = appleID;
+ }
+ if (helpIndex == -1) {
+ currentHelpMenuID = 0;
+ }
+
+ for (i = 0; i < menuBarPtr->numEntries; i++) {
+ if (i == appleIndex) {
+ if (menuBarPtr->entries[i]->state == tkDisabledUid) {
+ DisableItem(((MacMenu *) menuBarPtr->entries[i]
+ ->childMenuRefPtr->menuPtr
+ ->platformData)->menuHdl,
+ 0);
+ } else {
+ EnableItem(((MacMenu *) menuBarPtr->entries[i]
+ ->childMenuRefPtr->menuPtr
+ ->platformData)->menuHdl,
+ 0);
+ }
+ continue;
+ } else if (i == helpIndex) {
+ TkMenu *helpMenuPtr = menuBarPtr->entries[i]
+ ->childMenuRefPtr->menuPtr;
+ MenuHandle helpMenuHdl = NULL;
+
+ if (helpMenuPtr == NULL) {
+ continue;
+ }
+ helpMenuPtr->menuFlags |= MENU_HELP_MENU;
+ if (!(helpMenuPtr->menuFlags
+ & MENU_RECONFIGURE_PENDING)) {
+ helpMenuPtr->menuFlags
+ |= MENU_RECONFIGURE_PENDING;
+ Tcl_DoWhenIdle(ReconfigureMacintoshMenu,
+ (ClientData) helpMenuPtr);
+ }
+ macMenuHdl =
+ ((MacMenu *) helpMenuPtr->platformData)->menuHdl;
+ currentHelpMenuID = (*macMenuHdl)->menuID;
+ } else if (menuBarPtr->entries[i]->type
+ == CASCADE_ENTRY) {
+ if ((menuBarPtr->entries[i]->childMenuRefPtr != NULL)
+ && menuBarPtr->entries[i]->childMenuRefPtr
+ ->menuPtr != NULL) {
+ cascadeMenuPtr = menuBarPtr->entries[i]
+ ->childMenuRefPtr->menuPtr;
+ macMenuHdl = ((MacMenu *) cascadeMenuPtr
+ ->platformData)->menuHdl;
+ DeleteMenu((*macMenuHdl)->menuID);
+ InsertMenu(macMenuHdl, 0);
+ RecursivelyInsertMenu(cascadeMenuPtr);
+ if (menuBarPtr->entries[i]->state == tkDisabledUid) {
+ DisableItem(((MacMenu *) menuBarPtr->entries[i]
+ ->childMenuRefPtr->menuPtr
+ ->platformData)->menuHdl,
+ 0);
+ } else {
+ EnableItem(((MacMenu *) menuBarPtr->entries[i]
+ ->childMenuRefPtr->menuPtr
+ ->platformData)->menuHdl,
+ 0);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ SetDefaultMenubar();
+ }
+ DrawMenuBar();
+ menuBarFlags &= ~MENUBAR_REDRAW_PENDING;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecursivelyInsertMenu --
+ *
+ * Puts all of the cascades of this menu in the Mac hierarchical list.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menubar is changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RecursivelyInsertMenu(
+ TkMenu *menuPtr) /* All of the cascade items in this menu
+ * will be inserted into the mac menubar. */
+{
+ int i;
+ TkMenu *cascadeMenuPtr;
+ MenuHandle macMenuHdl;
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
+ if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
+ && (menuPtr->entries[i]->childMenuRefPtr->menuPtr
+ != NULL)) {
+ cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr;
+ macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
+ InsertMenu(macMenuHdl, -1);
+ RecursivelyInsertMenu(cascadeMenuPtr);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecursivelyDeleteMenu --
+ *
+ * Takes all of the cascades of this menu out of the Mac hierarchical
+ * list.
+ *
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menubar is changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RecursivelyDeleteMenu(
+ TkMenu *menuPtr) /* All of the cascade items in this menu
+ * will be inserted into the mac menubar. */
+{
+ int i;
+ TkMenu *cascadeMenuPtr;
+ MenuHandle macMenuHdl;
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ if (menuPtr->entries[i]->type == CASCADE_ENTRY) {
+ if ((menuPtr->entries[i]->childMenuRefPtr != NULL)
+ && (menuPtr->entries[i]->childMenuRefPtr->menuPtr
+ != NULL)) {
+ cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr;
+ macMenuHdl = ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl;
+ DeleteMenu((*macMenuHdl)->menuID);
+ RecursivelyInsertMenu(cascadeMenuPtr);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetDefaultMenubar --
+ *
+ * Puts the Apple, File and Edit menus into the Macintosh menubar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menubar is changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SetDefaultMenubar()
+{
+ if (currentMenuBarName != NULL) {
+ ckfree(currentMenuBarName);
+ currentMenuBarName = NULL;
+ }
+ currentMenuBarOwner = NULL;
+ ClearMenuBar();
+ InsertMenu(tkAppleMenu, 0);
+ InsertMenu(tkFileMenu, 0);
+ InsertMenu(tkEditMenu, 0);
+ if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
+ menuBarFlags |= MENUBAR_REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetMainMenubar --
+ *
+ * Puts the menu associated with a window into the menubar. Should
+ * only be called when the window is in front.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menubar is changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetMainMenubar(
+ Tcl_Interp *interp, /* The interpreter of the application */
+ Tk_Window tkwin, /* The frame we are setting up */
+ char *menuName) /* The name of the menu to put in front.
+ * If NULL, use the default menu bar.
+ */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ WindowRef macWindowPtr = (WindowRef) TkMacGetDrawablePort(winPtr->window);
+
+ if ((macWindowPtr == NULL) || (macWindowPtr != FrontWindow())) {
+ return;
+ }
+
+ if ((currentMenuBarInterp != interp)
+ || (currentMenuBarOwner != tkwin)
+ || (currentMenuBarName == NULL)
+ || (menuName == NULL)
+ || (strcmp(menuName, currentMenuBarName) != 0)) {
+ Tk_Window searchWindow;
+ TopLevelMenubarList *listPtr;
+
+ if (currentMenuBarName != NULL) {
+ ckfree(currentMenuBarName);
+ }
+
+ if (menuName == NULL) {
+ searchWindow = tkwin;
+ if (strcmp(Tk_Class(searchWindow), "Menu") == 0) {
+ TkMenuReferences *menuRefPtr;
+
+ menuRefPtr = TkFindMenuReferences(interp, Tk_PathName(tkwin));
+ if (menuRefPtr != NULL) {
+ TkMenu *menuPtr = menuRefPtr->menuPtr;
+ if (menuPtr != NULL) {
+ menuPtr = menuPtr->masterMenuPtr;
+ searchWindow = menuPtr->tkwin;
+ }
+ }
+ }
+ for (; searchWindow != NULL;
+ searchWindow = Tk_Parent(searchWindow)) {
+
+ for (listPtr = windowListPtr; listPtr != NULL;
+ listPtr = listPtr->nextPtr) {
+ if (listPtr->tkwin == searchWindow) {
+ break;
+ }
+ }
+ if (listPtr != NULL) {
+ menuName = Tk_PathName(listPtr->menuPtr->masterMenuPtr->tkwin);
+ break;
+ }
+ }
+ }
+
+ if (menuName == NULL) {
+ currentMenuBarName = NULL;
+ } else {
+ currentMenuBarName = ckalloc(strlen(menuName) + 1);
+ strcpy(currentMenuBarName, menuName);
+ }
+ currentMenuBarOwner = tkwin;
+ currentMenuBarInterp = interp;
+ }
+ if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL);
+ menuBarFlags |= MENUBAR_REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetWindowMenuBar --
+ *
+ * Associates a given menu with a window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * On Windows and UNIX, associates the platform menu with the
+ * platform window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetWindowMenuBar(
+ Tk_Window tkwin, /* The window we are setting the menu in */
+ TkMenu *menuPtr) /* The menu we are setting */
+{
+ TopLevelMenubarList *listPtr, *prevPtr;
+
+ /*
+ * Remove any existing reference to this window.
+ */
+
+ for (prevPtr = NULL, listPtr = windowListPtr;
+ listPtr != NULL;
+ prevPtr = listPtr, listPtr = listPtr->nextPtr) {
+ if (listPtr->tkwin == tkwin) {
+ break;
+ }
+ }
+
+ if (listPtr != NULL) {
+ if (prevPtr != NULL) {
+ prevPtr->nextPtr = listPtr->nextPtr;
+ } else {
+ windowListPtr = listPtr->nextPtr;
+ }
+ ckfree((char *) listPtr);
+ }
+
+ if (menuPtr != NULL) {
+ listPtr = (TopLevelMenubarList *) ckalloc(sizeof(TopLevelMenubarList));
+ listPtr->nextPtr = windowListPtr;
+ windowListPtr = listPtr;
+ listPtr->tkwin = tkwin;
+ listPtr->menuPtr = menuPtr;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacDispatchMenuEvent --
+ *
+ * Given a menu id and an item, dispatches the command associated
+ * with it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands get executed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacDispatchMenuEvent(
+ int menuID, /* The menu id of the menu we are invoking */
+ int index) /* The one-based index of the item that was
+ * selected. */
+{
+ int result = TCL_OK;
+ if (menuID != 0) {
+ if (menuID == kHMHelpMenuID) {
+ if (currentMenuBarOwner != NULL) {
+ TkMenuReferences *helpMenuRef;
+ char *helpMenuName = ckalloc(strlen(currentMenuBarName)
+ + strlen(".help") + 1);
+ sprintf(helpMenuName, "%s.help", currentMenuBarName);
+ helpMenuRef = TkFindMenuReferences(currentMenuBarInterp,
+ helpMenuName);
+ ckfree(helpMenuName);
+ if ((helpMenuRef != NULL) && (helpMenuRef->menuPtr != NULL)) {
+ int newIndex = index - helpItemCount - 1;
+ result = TkInvokeMenu(currentMenuBarInterp,
+ helpMenuRef->menuPtr, newIndex);
+ }
+ }
+ } else {
+ Tcl_HashEntry *commandEntryPtr =
+ Tcl_FindHashEntry(&commandTable, (char *) menuID);
+ TkMenu *menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
+ if ((currentAppleMenuID == menuID)
+ && (index > menuPtr->numEntries + 1)) {
+ Str255 itemText;
+
+ GetMenuItemText(GetMenuHandle(menuID), index, itemText);
+ OpenDeskAcc(itemText);
+ result = TCL_OK;
+ } else {
+ result = TkInvokeMenu(menuPtr->interp, menuPtr, index - 1);
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMenuIndicatorGeometry --
+ *
+ * Gets the width and height of the indicator area of a menu.
+ *
+ * Results:
+ * widthPtr and heightPtr are set.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetMenuIndicatorGeometry (
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are measuring */
+ Tk_Font tkfont, /* Precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* Precalculated font metrics */
+ int *widthPtr, /* The resulting width */
+ int *heightPtr) /* The resulting height */
+{
+ char markChar;
+
+ *heightPtr = fmPtr->linespace;
+
+ markChar = (char) FindMarkCharacter(mePtr);
+ *widthPtr = Tk_TextWidth(tkfont, &markChar, 1) + 4;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMenuAccelGeometry --
+ *
+ * Gets the width and height of the accelerator area of a menu.
+ *
+ * Results:
+ * widthPtr and heightPtr are set.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetMenuAccelGeometry (
+ TkMenu *menuPtr, /* The menu we are measuring */
+ TkMenuEntry *mePtr, /* The entry we are measuring */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
+ int *modWidthPtr, /* The width of all of the key
+ * modifier symbols. */
+ int *textWidthPtr, /* The resulting width */
+ int *heightPtr) /* The resulting height */
+{
+ *heightPtr = fmPtr->linespace;
+ *modWidthPtr = 0;
+ if (mePtr->type == CASCADE_ENTRY) {
+ *textWidthPtr = SICN_HEIGHT;
+ *modWidthPtr = Tk_TextWidth(tkfont, "W", 1);
+ } else if (0 == mePtr->accelLength) {
+ *textWidthPtr = 0;
+ } else {
+
+ if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
+ *textWidthPtr = Tk_TextWidth(tkfont, mePtr->accel,
+ mePtr->accelLength);
+ } else {
+ int emWidth = Tk_TextWidth(tkfont, "W", 1) + 1;
+ if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
+ int width = Tk_TextWidth(tkfont, mePtr->accel,
+ mePtr->accelLength);
+ *textWidthPtr = emWidth;
+ if (width < emWidth) {
+ *modWidthPtr = 0;
+ } else {
+ *modWidthPtr = width - emWidth;
+ }
+ } else {
+ int length = ((EntryGeometry *)mePtr->platformEntryData)
+ ->accelTextStart;
+ if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
+ *modWidthPtr += CONTROL_ICON_WIDTH;
+ }
+ if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
+ *modWidthPtr += SHIFT_ICON_WIDTH;
+ }
+ if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
+ *modWidthPtr += OPTION_ICON_WIDTH;
+ }
+ if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
+ *modWidthPtr += COMMAND_ICON_WIDTH;
+ }
+ if (1 == (mePtr->accelLength - length)) {
+ *textWidthPtr = emWidth;
+ } else {
+ *textWidthPtr += Tk_TextWidth(tkfont, mePtr->accel
+ + length, mePtr->accelLength - length);
+ }
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetTearoffEntryGeometry --
+ *
+ * Gets the width and height of of a tearoff entry.
+ *
+ * Results:
+ * widthPtr and heightPtr are set.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetTearoffEntryGeometry (
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are measuring */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
+ int *widthPtr, /* The resulting width */
+ int *heightPtr) /* The resulting height */
+{
+ if ((GetResource('MDEF', 591) == NULL) &&
+ (menuPtr->menuType == MASTER_MENU)) {
+ *heightPtr = fmPtr->linespace;
+ *widthPtr = 0;
+ } else {
+ *widthPtr = *heightPtr = 0;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMenuSeparatorGeometry --
+ *
+ * Gets the width and height of menu separator.
+ *
+ * Results:
+ * widthPtr and heightPtr are set.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetMenuSeparatorGeometry(
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are measuring */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalcualted font metrics */
+ int *widthPtr, /* The resulting width */
+ int *heightPtr) /* The resulting height */
+{
+ *widthPtr = 0;
+ *heightPtr = fmPtr->linespace;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawMenuEntryIndicator --
+ *
+ * This procedure draws the indicator part of a menu.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawMenuEntryIndicator(
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are drawing */
+ Drawable d, /* The drawable we are drawing */
+ GC gc, /* The GC we are drawing with */
+ GC indicatorGC, /* The GC to use for the indicator */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
+ int x, /* topleft hand corner of entry */
+ int y, /* topleft hand corner of entry */
+ int width, /* width of entry */
+ int height) /* height of entry */
+{
+ if (((mePtr->type == CHECK_BUTTON_ENTRY) ||
+ (mePtr->type == RADIO_BUTTON_ENTRY))
+ && (mePtr->indicatorOn)
+ && (mePtr->entryFlags & ENTRY_SELECTED)) {
+ int baseline;
+ short markShort;
+ char markChar;
+
+ baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
+ GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl,
+ mePtr->index + 1, &markShort);
+ if (markShort != 0) {
+ markChar = (char) markShort;
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, &markChar, 1,
+ x + 2, baseline);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawSICN --
+ *
+ * Given a resource id and an index, loads the appropriate SICN
+ * and draws it into a given drawable using the given gc.
+ *
+ * Results:
+ * Returns 1 if the SICN was found, 0 if not found.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+DrawSICN(
+ int resourceID, /* The resource # of the SICN table */
+ int index, /* The index into the SICN table of the
+ * icon we want. */
+ Drawable d, /* What we are drawing into */
+ GC gc, /* The GC to draw with */
+ int x, /* The left hand coord of the SICN */
+ int y) /* The top coord of the SICN */
+{
+ Handle sicnHandle = (Handle) GetResource('SICN', SICN_RESOURCE_NUMBER);
+
+ if (NULL == sicnHandle) {
+ return 0;
+ } else {
+ BitMap sicnBitmap;
+ Rect destRect;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ BitMapPtr destBitMap;
+ RGBColor origForeColor, origBackColor, foreColor, backColor;
+
+ HLock(sicnHandle);
+ destPort = TkMacGetDrawablePort(d);
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+ TkMacSetUpClippingRgn(d);
+ TkMacSetUpGraphicsPort(gc);
+ GetForeColor(&origForeColor);
+ GetBackColor(&origBackColor);
+
+ if (TkSetMacColor(gc->foreground, &foreColor) == true) {
+ RGBForeColor(&foreColor);
+ }
+
+ if (TkSetMacColor(gc->background, &backColor) == true) {
+ RGBBackColor(&backColor);
+ }
+
+ SetRect(&destRect, x, y, x + SICN_HEIGHT, y + SICN_HEIGHT);
+ sicnBitmap.baseAddr = (Ptr) (*sicnHandle) + index * SICN_HEIGHT
+ * SICN_ROWS;
+ sicnBitmap.rowBytes = SICN_ROWS;
+ SetRect(&sicnBitmap.bounds, 0, 0, 16, 16);
+ destBitMap = &((GrafPtr) destPort)->portBits;
+ CopyBits(&sicnBitmap, destBitMap, &sicnBitmap.bounds, &destRect,
+ destPort->txMode, NULL);
+ HUnlock(sicnHandle);
+ RGBForeColor(&origForeColor);
+ RGBBackColor(&origBackColor);
+ SetGWorld(saveWorld, saveDevice);
+ return 1;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawMenuEntryAccelerator --
+ *
+ * This procedure draws the accelerator part of a menu. We
+ * need to decide what to draw here. Should we replace strings
+ * like "Control", "Command", etc?
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawMenuEntryAccelerator(
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are drawing */
+ Drawable d, /* The drawable we are drawing in */
+ GC gc, /* The gc to draw into */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
+ Tk_3DBorder activeBorder, /* border for menu background */
+ int x, /* The left side of the entry */
+ int y, /* The top of the entry */
+ int width, /* The width of the entry */
+ int height, /* The height of the entry */
+ int drawArrow) /* Whether or not to draw cascade arrow */
+{
+ if (mePtr->type == CASCADE_ENTRY) {
+ if (0 == DrawSICN(SICN_RESOURCE_NUMBER, CASCADE_ARROW, d, gc,
+ x + width - SICN_HEIGHT, (y + (height / 2))
+ - (SICN_HEIGHT / 2))) {
+ XPoint points[3];
+ Tk_Window tkwin = menuPtr->tkwin;
+
+ if (mePtr->type == CASCADE_ENTRY) {
+ points[0].x = width - menuPtr->activeBorderWidth
+ - MAC_MARGIN_WIDTH - CASCADE_ARROW_WIDTH;
+ points[0].y = y + (height - CASCADE_ARROW_HEIGHT)/2;
+ points[1].x = points[0].x;
+ points[1].y = points[0].y + CASCADE_ARROW_HEIGHT;
+ points[2].x = points[0].x + CASCADE_ARROW_WIDTH;
+ points[2].y = points[0].y + CASCADE_ARROW_HEIGHT/2;
+ Tk_Fill3DPolygon(menuPtr->tkwin, d, activeBorder, points,
+ 3, DECORATION_BORDER_WIDTH, TK_RELIEF_FLAT);
+ }
+ }
+ } else if (mePtr->accelLength != 0) {
+ int leftEdge = x + width;
+ int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
+
+ if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) {
+ leftEdge -= ((EntryGeometry *) mePtr->platformEntryData)
+ ->accelTextWidth;
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel,
+ mePtr->accelLength, leftEdge, baseline);
+ } else {
+ EntryGeometry *geometryPtr =
+ (EntryGeometry *) mePtr->platformEntryData;
+ int length = mePtr->accelLength - geometryPtr->accelTextStart;
+
+ leftEdge -= geometryPtr->accelTextWidth;
+ if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) {
+ leftEdge -= geometryPtr->modifierWidth;
+ }
+
+ Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->accel
+ + geometryPtr->accelTextStart, length, leftEdge, baseline);
+
+ if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) {
+ leftEdge -= COMMAND_ICON_WIDTH;
+ DrawSICN(SICN_RESOURCE_NUMBER, COMMAND_ICON, d, gc,
+ leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
+ }
+
+ if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) {
+ leftEdge -= OPTION_ICON_WIDTH;
+ DrawSICN(SICN_RESOURCE_NUMBER, OPTION_ICON, d, gc,
+ leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
+ }
+
+ if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) {
+ leftEdge -= SHIFT_ICON_WIDTH;
+ DrawSICN(SICN_RESOURCE_NUMBER, SHIFT_ICON, d, gc,
+ leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
+ }
+
+ if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) {
+ leftEdge -= CONTROL_ICON_WIDTH;
+ DrawSICN(SICN_RESOURCE_NUMBER, CONTROL_ICON, d, gc,
+ leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawMenuSeparator --
+ *
+ * The menu separator is drawn.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawMenuSeparator(
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are drawing */
+ Drawable d, /* The drawable we are drawing into */
+ GC gc, /* The gc we are drawing with */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
+ int x, /* left coordinate of entry */
+ int y, /* top coordinate of entry */
+ int width, /* width of entry */
+ int height) /* height of entry */
+{
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(d);
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+ TkMacSetUpClippingRgn(d);
+
+ /*
+ * We don't want to use the text GC for drawing the separator. It
+ * needs to be the same color as disabled items.
+ */
+
+ TkMacSetUpGraphicsPort(mePtr->disabledGC != None ? mePtr->disabledGC
+ : menuPtr->disabledGC);
+
+ MoveTo(x, y + (height / 2));
+ Line(width, 0);
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuDefProc --
+ *
+ * This routine is the MDEF handler for Tk. It receives all messages
+ * for the menu and dispatches them.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This routine causes menus to be drawn and will certainly allocate
+ * memory as a result. Also, the menu can scroll up and down, and
+ * various other interface actions can take place.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MenuDefProc(
+ short message, /* What action are we taking? */
+ MenuHandle menu, /* The menu we are working with */
+ Rect *menuRectPtr, /* A pointer to the rect for the
+ * whole menu. */
+ Point hitPt, /* Where the mouse was clicked for
+ * the appropriate messages. */
+ short *whichItem, /* Output result. Which item was
+ * hit by the user? */
+ TkMenuLowMemGlobals *globalsPtr) /* The low mem globals we have
+ * to change */
+{
+#define SCREEN_MARGIN 5
+ TkMenu *menuPtr;
+ TkMenuEntry *parentEntryPtr;
+ Tcl_HashEntry *commandEntryPtr;
+ GrafPtr windowMgrPort;
+ Tk_Font tkfont;
+ Tk_FontMetrics fontMetrics, entryMetrics;
+ Tk_FontMetrics *fmPtr;
+ TkMenuEntry *mePtr;
+ int i;
+ int maxMenuHeight;
+ int oldItem;
+ int newItem = -1;
+ GDHandle device;
+ Rect itemRect;
+ short windowPart;
+ WindowRef whichWindow;
+ RGBColor bgColor;
+ RGBColor fgColor;
+ RGBColor origFgColor;
+ PenState origPenState;
+ Rect dragRect;
+ Rect scratchRect = {-32768, -32768, 32767, 32767};
+ RgnHandle oldClipRgn;
+ TkMenuReferences *menuRefPtr;
+ TkMenu *searchMenuPtr;
+ Rect menuClipRect;
+
+ HLock((Handle) menu);
+ commandEntryPtr = Tcl_FindHashEntry(&commandTable,
+ (char *) (*menu)->menuID);
+ HUnlock((Handle) menu);
+ menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr);
+
+ switch (message) {
+ case mSizeMsg:
+ GetWMgrPort(&windowMgrPort);
+ maxMenuHeight = windowMgrPort->portRect.bottom
+ - windowMgrPort->portRect.top
+ - GetMBarHeight() - SCREEN_MARGIN;
+ (*menu)->menuWidth = menuPtr->totalWidth;
+ (*menu)->menuHeight = maxMenuHeight < menuPtr->totalHeight ?
+ maxMenuHeight : menuPtr->totalHeight;
+ break;
+
+ case mDrawMsg:
+
+ /*
+ * Store away the menu rectangle so we can keep track of the
+ * different regions that the menu obscures.
+ */
+
+ ((MacMenu *) menuPtr->platformData)->menuRect = *menuRectPtr;
+ if (tkMenuCascadeRgn == NULL) {
+ tkMenuCascadeRgn = NewRgn();
+ }
+ if (utilRgn == NULL) {
+ utilRgn = NewRgn();
+ }
+ if (totalMenuRgn == NULL) {
+ totalMenuRgn = NewRgn();
+ }
+ SetEmptyRgn(tkMenuCascadeRgn);
+ for (searchMenuPtr = menuPtr; searchMenuPtr != NULL; ) {
+ RectRgn(utilRgn,
+ &((MacMenu *) searchMenuPtr->platformData)->menuRect);
+ InsetRgn(utilRgn, -1, -1);
+ UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
+ OffsetRgn(utilRgn, 1, 1);
+ UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn);
+
+ if (searchMenuPtr->menuRefPtr->parentEntryPtr != NULL) {
+ searchMenuPtr = searchMenuPtr->menuRefPtr
+ ->parentEntryPtr->menuPtr;
+ } else {
+ break;
+ }
+ if (searchMenuPtr->menuType == MENUBAR) {
+ break;
+ }
+ }
+ UnionRgn(totalMenuRgn, tkMenuCascadeRgn, totalMenuRgn);
+ SetEmptyRgn(utilRgn);
+
+ /*
+ * Next, figure out scrolling information.
+ */
+
+ GetGWorld(&macMDEFDrawable.portPtr, &device);
+ menuClipRect = *menuRectPtr;
+ if ((menuClipRect.bottom - menuClipRect.top)
+ < menuPtr->totalHeight) {
+ if (globalsPtr->menuTop < menuRectPtr->top) {
+ DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW,
+ (Drawable) &macMDEFDrawable,
+ menuPtr->textGC,
+ menuRectPtr->left
+ + menuPtr->entries[1]->indicatorSpace,
+ menuRectPtr->top);
+ menuClipRect.top += SICN_HEIGHT;
+ }
+ if ((globalsPtr->menuTop + menuPtr->totalHeight)
+ > menuRectPtr->bottom) {
+ DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
+ (Drawable) &macMDEFDrawable,
+ menuPtr->textGC,
+ menuRectPtr->left
+ + menuPtr->entries[1]->indicatorSpace,
+ menuRectPtr->bottom - SICN_HEIGHT);
+ menuClipRect.bottom -= SICN_HEIGHT;
+ }
+ GetClip(utilRgn);
+ }
+
+ /*
+ * Now, actually draw the menu. Don't draw entries that
+ * are higher than the top arrow, and don't draw entries
+ * that are lower than the bottom.
+ */
+
+ Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ if (globalsPtr->menuTop + mePtr->y + mePtr->height
+ < menuClipRect.top) {
+ continue;
+ } else if (globalsPtr->menuTop + mePtr->y
+ > menuClipRect.bottom) {
+ continue;
+ }
+ ClipRect(&menuClipRect);
+ if (mePtr->tkfont == NULL) {
+ fmPtr = &fontMetrics;
+ tkfont = menuPtr->tkfont;
+ } else {
+ tkfont = mePtr->tkfont;
+ Tk_GetFontMetrics(tkfont, &entryMetrics);
+ fmPtr = &entryMetrics;
+ }
+ TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
+ tkfont, fmPtr, menuRectPtr->left + mePtr->x,
+ globalsPtr->menuTop + mePtr->y,
+ (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
+ menuPtr->totalWidth - mePtr->x : mePtr->width,
+ menuPtr->entries[i]->height, 0, 1);
+ }
+ globalsPtr->menuBottom = globalsPtr->menuTop
+ + menuPtr->totalHeight;
+ if (!EmptyRgn(utilRgn)) {
+ SetClip(utilRgn);
+ SetEmptyRgn(utilRgn);
+ }
+ MDEFScrollFlag = 1;
+ break;
+
+ case mChooseMsg: {
+ int hasTopScroll, hasBottomScroll;
+ enum {
+ DONT_SCROLL, DOWN_SCROLL, UP_SCROLL
+ } scrollDirection;
+ Rect updateRect;
+ short scrollAmt;
+ RGBColor origForeColor, origBackColor, foreColor, backColor;
+
+ GetGWorld(&macMDEFDrawable.portPtr, &device);
+ GetForeColor(&origForeColor);
+ GetBackColor(&origBackColor);
+
+ if (TkSetMacColor(menuPtr->textGC->foreground,
+ &foreColor) == true) {
+ RGBForeColor(&foreColor);
+ }
+ if (TkSetMacColor(menuPtr->textGC->background,
+ &backColor) == true) {
+ RGBBackColor(&backColor);
+ }
+
+ /*
+ * Find out which item was hit. If it is the same as the old item,
+ * we don't need to do anything.
+ */
+
+ oldItem = *whichItem - 1;
+
+ if (PtInRect(hitPt, menuRectPtr)) {
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ itemRect.left = menuRectPtr->left + mePtr->x;
+ itemRect.top = globalsPtr->menuTop + mePtr->y;
+ if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {
+ itemRect.right = itemRect.left + menuPtr->totalWidth
+ - mePtr->x;
+ } else {
+ itemRect.right = itemRect.left + mePtr->width;
+ }
+ itemRect.bottom = itemRect.top
+ + menuPtr->entries[i]->height;
+ if (PtInRect(hitPt, &itemRect)) {
+ if ((mePtr->type == SEPARATOR_ENTRY)
+ || (mePtr->state == tkDisabledUid)) {
+ newItem = -1;
+ } else {
+ TkMenuEntry *cascadeEntryPtr;
+ int parentDisabled = 0;
+
+ for (cascadeEntryPtr
+ = menuPtr->menuRefPtr->parentEntryPtr;
+ cascadeEntryPtr != NULL;
+ cascadeEntryPtr
+ = cascadeEntryPtr->nextCascadePtr) {
+ if (strcmp(cascadeEntryPtr->name,
+ Tk_PathName(menuPtr->tkwin)) == 0) {
+ if (cascadeEntryPtr->state
+ == tkDisabledUid) {
+ parentDisabled = 1;
+ }
+ break;
+ }
+ }
+ if (parentDisabled) {
+ newItem = -1;
+ } else {
+ newItem = i;
+ if ((mePtr->type == CASCADE_ENTRY)
+ && (oldItem != newItem)) {
+ globalsPtr->itemRect = itemRect;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Now we need to take care of scrolling the menu.
+ */
+
+ hasTopScroll = globalsPtr->menuTop < menuRectPtr->top;
+ hasBottomScroll = globalsPtr->menuBottom > menuRectPtr->bottom;
+ scrollDirection = DONT_SCROLL;
+ if (hasTopScroll
+ && (hitPt.v < menuRectPtr->top + SICN_HEIGHT)) {
+ newItem = -1;
+ scrollDirection = DOWN_SCROLL;
+ } else if (hasBottomScroll
+ && (hitPt.v > menuRectPtr->bottom - SICN_HEIGHT)) {
+ newItem = -1;
+ scrollDirection = UP_SCROLL;
+ }
+ menuClipRect = *menuRectPtr;
+ if (hasTopScroll) {
+ menuClipRect.top += SICN_HEIGHT;
+ }
+ if (hasBottomScroll) {
+ menuClipRect.bottom -= SICN_HEIGHT;
+ }
+ if (MDEFScrollFlag) {
+ scrollDirection = DONT_SCROLL;
+ MDEFScrollFlag = 0;
+ }
+ GetClip(utilRgn);
+ ClipRect(&menuClipRect);
+
+ if (oldItem != newItem) {
+ if (oldItem >= 0) {
+ mePtr = menuPtr->entries[oldItem];
+ tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
+ Tk_GetFontMetrics(tkfont, &fontMetrics);
+ TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
+ tkfont, &fontMetrics,
+ menuRectPtr->left + mePtr->x,
+ globalsPtr->menuTop + mePtr->y,
+ (mePtr->entryFlags & ENTRY_LAST_COLUMN)
+ ? menuPtr->totalWidth - mePtr->x
+ : mePtr->width, mePtr->height, 0, 1);
+ }
+ if (newItem != -1) {
+ int oldActiveItem = menuPtr->active;
+
+ mePtr = menuPtr->entries[newItem];
+ if (mePtr->state != tkDisabledUid) {
+ TkActivateMenuEntry(menuPtr, newItem);
+ }
+ tkfont = mePtr->tkfont ? mePtr->tkfont : menuPtr->tkfont;
+ Tk_GetFontMetrics(tkfont, &fontMetrics);
+ TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
+ tkfont, &fontMetrics,
+ menuRectPtr->left + mePtr->x,
+ globalsPtr->menuTop + mePtr->y,
+ (mePtr->entryFlags & ENTRY_LAST_COLUMN)
+ ? menuPtr->totalWidth - mePtr->x
+ : mePtr->width, mePtr->height,
+ 0, 1);
+ }
+
+ tkUseMenuCascadeRgn = 1;
+ MenuSelectEvent(menuPtr);
+ Tcl_ServiceAll();
+ tkUseMenuCascadeRgn = 0;
+ if (mePtr->state != tkDisabledUid) {
+ TkActivateMenuEntry(menuPtr, -1);
+ }
+ *whichItem = newItem + 1;
+ }
+ globalsPtr->menuDisable = ((*menu)->menuID << 16) | (newItem + 1);
+
+ if (scrollDirection == UP_SCROLL) {
+ scrollAmt = menuClipRect.bottom - hitPt.v;
+ if (scrollAmt < menuRectPtr->bottom
+ - globalsPtr->menuBottom) {
+ scrollAmt = menuRectPtr->bottom - globalsPtr->menuBottom;
+ }
+ if (!hasTopScroll && ((globalsPtr->menuTop + scrollAmt) < menuRectPtr->top)) {
+ SetRect(&updateRect, menuRectPtr->left,
+ globalsPtr->menuTop, menuRectPtr->right,
+ globalsPtr->menuTop + SICN_HEIGHT);
+ EraseRect(&updateRect);
+ DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW,
+ (Drawable) &macMDEFDrawable,
+ menuPtr->textGC, menuRectPtr->left
+ + menuPtr->entries[1]->indicatorSpace,
+ menuRectPtr->top);
+ menuClipRect.top += SICN_HEIGHT;
+ }
+ } else if (scrollDirection == DOWN_SCROLL) {
+ scrollAmt = menuClipRect.top - hitPt.v;
+ if (scrollAmt > menuRectPtr->top - globalsPtr->menuTop) {
+ scrollAmt = menuRectPtr->top - globalsPtr->menuTop;
+ }
+ if (!hasBottomScroll && ((globalsPtr->menuBottom + scrollAmt)
+ > menuRectPtr->bottom)) {
+ SetRect(&updateRect, menuRectPtr->left,
+ globalsPtr->menuBottom - SICN_HEIGHT,
+ menuRectPtr->right, globalsPtr->menuBottom);
+ EraseRect(&updateRect);
+ DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW,
+ (Drawable) &macMDEFDrawable,
+ menuPtr->textGC, menuRectPtr->left
+ + menuPtr->entries[1]->indicatorSpace,
+ menuRectPtr->bottom - SICN_HEIGHT);
+ menuClipRect.bottom -= SICN_HEIGHT;
+ }
+ }
+ if (scrollDirection != DONT_SCROLL) {
+ RgnHandle updateRgn = NewRgn();
+ ScrollRect(&menuClipRect, 0, scrollAmt, updateRgn);
+ updateRect = (*updateRgn)->rgnBBox;
+ DisposeRgn(updateRgn);
+ globalsPtr->menuTop += scrollAmt;
+ globalsPtr->menuBottom += scrollAmt;
+ if (globalsPtr->menuTop == menuRectPtr->top) {
+ updateRect.top -= SICN_HEIGHT;
+ }
+ if (globalsPtr->menuBottom == menuRectPtr->bottom) {
+ updateRect.bottom += SICN_HEIGHT;
+ }
+ ClipRect(&updateRect);
+ EraseRect(&updateRect);
+ Tk_GetFontMetrics(menuPtr->tkfont, &fontMetrics);
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ if (globalsPtr->menuTop + mePtr->y + mePtr->height
+ < updateRect.top) {
+ continue;
+ } else if (globalsPtr->menuTop + mePtr->y
+ > updateRect.bottom) {
+ continue;
+ }
+ if (mePtr->tkfont == NULL) {
+ fmPtr = &fontMetrics;
+ tkfont = menuPtr->tkfont;
+ } else {
+ tkfont = mePtr->tkfont;
+ Tk_GetFontMetrics(tkfont, &entryMetrics);
+ fmPtr = &entryMetrics;
+ }
+ TkpDrawMenuEntry(mePtr, (Drawable) &macMDEFDrawable,
+ tkfont, fmPtr, menuRectPtr->left + mePtr->x,
+ globalsPtr->menuTop + mePtr->y,
+ (mePtr->entryFlags & ENTRY_LAST_COLUMN) ?
+ menuPtr->totalWidth - mePtr->x : mePtr->width,
+ menuPtr->entries[i]->height, 0, 1);
+ }
+ }
+
+ SetClip(utilRgn);
+ SetEmptyRgn(utilRgn);
+ RGBForeColor(&origForeColor);
+ RGBBackColor(&origBackColor);
+
+ /*
+ * If the menu is a tearoff, and the mouse is outside the menu,
+ * we need to draw the drag rectangle.
+ *
+ * In order for tearoffs to work properly, we need to set
+ * the active member of the containing menubar.
+ */
+
+ menuRefPtr = TkFindMenuReferences(menuPtr->interp,
+ Tk_PathName(menuPtr->tkwin));
+ if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr != NULL)) {
+ for (parentEntryPtr = menuRefPtr->parentEntryPtr;
+ strcmp(parentEntryPtr->name,
+ Tk_PathName(menuPtr->tkwin)) == 0;
+ parentEntryPtr = parentEntryPtr->nextCascadePtr) {
+ }
+ if (parentEntryPtr != NULL) {
+ TkActivateMenuEntry(parentEntryPtr->menuPtr,
+ parentEntryPtr->index);
+ }
+ }
+
+ if (menuPtr->tearOff) {
+ scratchRect = *menuRectPtr;
+ if (tearoffStruct.menuPtr == NULL) {
+ scratchRect.top -= 10;
+ scratchRect.bottom += 10;
+ scratchRect.left -= 10;
+ scratchRect.right += 10;
+ }
+
+ windowPart = FindWindow(hitPt, &whichWindow);
+ if ((windowPart != inMenuBar) && (newItem == -1)
+ && (hitPt.v != 0) && (hitPt.h != 0)
+ && (!PtInRect(hitPt, &scratchRect))
+ && (!PtInRect(hitPt, &tearoffStruct.excludeRect))) {
+/*
+ * This is the second argument to the Toolbox Delay function. It changed
+ * from long to unsigned long between Universal Headers 2.0 & 3.0
+ */
+#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300)
+ long dummy;
+#else
+ unsigned long dummy;
+#endif
+ oldClipRgn = NewRgn();
+ GetClip(oldClipRgn);
+ GetForeColor(&origFgColor);
+ GetPenState(&origPenState);
+ GetForeColor(&fgColor);
+ GetBackColor(&bgColor);
+ GetGray(device, &bgColor, &fgColor);
+ RGBForeColor(&fgColor);
+ SetRect(&scratchRect, -32768, -32768, 32767, 32767);
+ ClipRect(&scratchRect);
+
+ dragRect = *menuRectPtr;
+ tearoffStruct.menuPtr = menuPtr;
+
+ PenMode(srcXor);
+ dragRect = *menuRectPtr;
+ OffsetRect(&dragRect, -dragRect.left, -dragRect.top);
+ OffsetRect(&dragRect, tearoffStruct.point.h,
+ tearoffStruct.point.v);
+ if ((dragRect.top != 0) && (dragRect.left != 0)) {
+ FrameRect(&dragRect);
+ Delay(1, &dummy);
+ FrameRect(&dragRect);
+ }
+ tearoffStruct.point = hitPt;
+
+ SetClip(oldClipRgn);
+ DisposeRgn(oldClipRgn);
+ RGBForeColor(&origFgColor);
+ SetPenState(&origPenState);
+ } else {
+ tearoffStruct.menuPtr = NULL;
+ tearoffStruct.point.h = tearoffStruct.point.v = 0;
+ }
+ } else {
+ tearoffStruct.menuPtr = NULL;
+ tearoffStruct.point.h = tearoffStruct.point.v = 0;
+ }
+
+ break;
+ }
+
+ case mPopUpMsg:
+
+ /*
+ * Note that for some oddball reason, h and v are reversed in the
+ * point given to us by the MDEF.
+ */
+
+ oldItem = *whichItem;
+ if (oldItem >= menuPtr->numEntries) {
+ oldItem = -1;
+ }
+ GetWMgrPort(&windowMgrPort);
+ maxMenuHeight = windowMgrPort->portRect.bottom
+ - windowMgrPort->portRect.top
+ - GetMBarHeight() - SCREEN_MARGIN;
+ if (menuPtr->totalHeight > maxMenuHeight) {
+ menuRectPtr->top = GetMBarHeight();
+ } else {
+ menuRectPtr->top = hitPt.h;
+ if (oldItem >= 0) {
+ menuRectPtr->top -= menuPtr->entries[oldItem]->y;
+ }
+ if (menuRectPtr->top + menuPtr->totalHeight > maxMenuHeight) {
+ menuRectPtr->top -= maxMenuHeight - menuPtr->totalHeight;
+ }
+ }
+ menuRectPtr->left = hitPt.v;
+ menuRectPtr->right = menuRectPtr->left + menuPtr->totalWidth;
+ menuRectPtr->bottom = menuRectPtr->top +
+ ((maxMenuHeight < menuPtr->totalHeight)
+ ? maxMenuHeight : menuPtr->totalHeight);
+ if (menuRectPtr->top == GetMBarHeight()) {
+ *whichItem = hitPt.h;
+ } else {
+ *whichItem = menuRectPtr->top;
+ }
+ break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacHandleTearoffMenu() --
+ *
+ * This routine sees if the MDEF has set a menu and a mouse position
+ * for tearing off and makes a tearoff menu if it has.
+ *
+ * Results:
+ * menuPtr->interp will have the result of the tearoff command.
+ *
+ * Side effects:
+ * A new tearoff menu is created if it is supposed to be.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacHandleTearoffMenu(void)
+{
+ if (tearoffStruct.menuPtr != NULL) {
+ Tcl_DString tearoffCmdStr;
+ char intString[20];
+ short windowPart;
+ WindowRef whichWindow;
+
+ windowPart = FindWindow(tearoffStruct.point, &whichWindow);
+
+ if (windowPart != inMenuBar) {
+ Tcl_DStringInit(&tearoffCmdStr);
+ Tcl_DStringAppendElement(&tearoffCmdStr, "tkTearOffMenu");
+ Tcl_DStringAppendElement(&tearoffCmdStr,
+ Tk_PathName(tearoffStruct.menuPtr->tkwin));
+ sprintf(intString, "%d", tearoffStruct.point.h);
+ Tcl_DStringAppendElement(&tearoffCmdStr, intString);
+ sprintf(intString, "%d", tearoffStruct.point.v);
+ Tcl_DStringAppendElement(&tearoffCmdStr, intString);
+ Tcl_Eval(tearoffStruct.menuPtr->interp,
+ Tcl_DStringValue(&tearoffCmdStr));
+ Tcl_DStringFree(&tearoffCmdStr);
+ tearoffStruct.menuPtr = NULL;
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpInitializeMenuBindings --
+ *
+ * For every interp, initializes the bindings for Windows
+ * menus. Does nothing on Mac or XWindows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * C-level bindings are setup for the interp which will
+ * handle Alt-key sequences for menus without beeping
+ * or interfering with user-defined Alt-key bindings.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpInitializeMenuBindings(interp, bindingTable)
+ Tcl_Interp *interp; /* The interpreter to set. */
+ Tk_BindingTable bindingTable; /* The table to add to. */
+{
+ /*
+ * Nothing to do.
+ */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpComputeMenubarGeometry --
+ *
+ * This procedure is invoked to recompute the size and
+ * layout of a menu that is a menubar clone.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Fields of menu entries are changed to reflect their
+ * current positions, and the size of the menu window
+ * itself may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpComputeMenubarGeometry(menuPtr)
+ TkMenu *menuPtr; /* Structure describing menu. */
+{
+ TkpComputeStandardMenuGeometry(menuPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawTearoffEntry --
+ *
+ * This procedure draws the background part of a menu.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+DrawTearoffEntry(
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are drawing */
+ Drawable d, /* The drawable we are drawing into */
+ GC gc, /* The gc we are drawing with */
+ Tk_Font tkfont, /* The font we are drawing with */
+ CONST Tk_FontMetrics *fmPtr, /* The metrics we are drawing with */
+ int x, /* Left edge of entry. */
+ int y, /* Top edge of entry. */
+ int width, /* Width of entry. */
+ int height) /* Height of entry. */
+{
+ XPoint points[2];
+ int margin, segmentWidth, maxX;
+
+ if ((menuPtr->menuType != MASTER_MENU) || (GetResource('MDEF', 591) != NULL)) {
+ return;
+ }
+
+ margin = (fmPtr->ascent + fmPtr->descent)/2;
+ points[0].x = x;
+ points[0].y = y + height/2;
+ points[1].y = points[0].y;
+ segmentWidth = 6;
+ maxX = width - 1;
+
+ while (points[0].x < maxX) {
+ points[1].x = points[0].x + segmentWidth;
+ if (points[1].x > maxX) {
+ points[1].x = maxX;
+ }
+ Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1,
+ TK_RELIEF_RAISED);
+ points[0].x += 2*segmentWidth;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacSetHelpMenuItemCount --
+ *
+ * Has to be called after the first call to InsertMenu. Sets
+ * up the global variable for the number of items in the
+ * unmodified help menu.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the global helpItemCount.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacSetHelpMenuItemCount()
+{
+ MenuHandle helpMenuHandle;
+
+ if ((HMGetHelpMenuHandle(&helpMenuHandle) != noErr)
+ || (helpMenuHandle == NULL)) {
+ helpItemCount = -1;
+ } else {
+ helpItemCount = CountMItems(helpMenuHandle);
+ DeleteMenuItem(helpMenuHandle, helpItemCount);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacMenuClick --
+ *
+ * Prepares a menubar for MenuSelect or MenuKey.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any pending configurations of the menubar are completed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacMenuClick()
+{
+ TkMenu *menuPtr;
+ TkMenuReferences *menuRefPtr;
+
+ if ((currentMenuBarInterp != NULL) && (currentMenuBarName != NULL)) {
+ menuRefPtr = TkFindMenuReferences(currentMenuBarInterp,
+ currentMenuBarName);
+ for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr;
+ menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) {
+ if (menuPtr->menuType == MENUBAR) {
+ CompleteIdlers(menuPtr);
+ break;
+ }
+ }
+ }
+
+ if (menuBarFlags & MENUBAR_REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL);
+ DrawMenuBarWhenIdle((ClientData *) NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDrawMenuEntry --
+ *
+ * Draws the given menu entry at the given coordinates with the
+ * given attributes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * X Server commands are executed to display the menu entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDrawMenuEntry(
+ TkMenuEntry *mePtr, /* The entry to draw */
+ Drawable d, /* What to draw into */
+ Tk_Font tkfont, /* Precalculated font for menu */
+ CONST Tk_FontMetrics *menuMetricsPtr,
+ /* Precalculated metrics for menu */
+ int x, /* X-coordinate of topleft of entry */
+ int y, /* Y-coordinate of topleft of entry */
+ int width, /* Width of the entry rectangle */
+ int height, /* Height of the current rectangle */
+ int strictMotif, /* Boolean flag */
+ int drawArrow) /* Whether or not to draw the cascade
+ * arrow for cascade items. Only applies
+ * to Windows. */
+{
+ GC gc, indicatorGC;
+ TkMenu *menuPtr = mePtr->menuPtr;
+ Tk_3DBorder bgBorder, activeBorder;
+ CONST Tk_FontMetrics *fmPtr;
+ Tk_FontMetrics entryMetrics;
+ int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0;
+ int adjustedY = y + padY;
+ int adjustedHeight = height - 2 * padY;
+
+ /*
+ * Choose the gc for drawing the foreground part of the entry.
+ */
+
+ if ((mePtr->state == tkActiveUid)
+ && !strictMotif) {
+ gc = mePtr->activeGC;
+ if (gc == NULL) {
+ gc = menuPtr->activeGC;
+ }
+ } else {
+ TkMenuEntry *cascadeEntryPtr;
+ int parentDisabled = 0;
+
+ for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
+ cascadeEntryPtr != NULL;
+ cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
+ if (strcmp(cascadeEntryPtr->name,
+ Tk_PathName(menuPtr->tkwin)) == 0) {
+ if (cascadeEntryPtr->state == tkDisabledUid) {
+ parentDisabled = 1;
+ }
+ break;
+ }
+ }
+
+ if (((parentDisabled || (mePtr->state == tkDisabledUid)))
+ && (menuPtr->disabledFg != NULL)) {
+ gc = mePtr->disabledGC;
+ if (gc == NULL) {
+ gc = menuPtr->disabledGC;
+ }
+ } else {
+ gc = mePtr->textGC;
+ if (gc == NULL) {
+ gc = menuPtr->textGC;
+ }
+ }
+ }
+ indicatorGC = mePtr->indicatorGC;
+ if (indicatorGC == NULL) {
+ indicatorGC = menuPtr->indicatorGC;
+ }
+
+ bgBorder = mePtr->border;
+ if (bgBorder == NULL) {
+ bgBorder = menuPtr->border;
+ }
+ if (strictMotif) {
+ activeBorder = bgBorder;
+ } else {
+ activeBorder = mePtr->activeBorder;
+ if (activeBorder == NULL) {
+ activeBorder = menuPtr->activeBorder;
+ }
+ }
+
+ if (mePtr->tkfont == NULL) {
+ fmPtr = menuMetricsPtr;
+ } else {
+ tkfont = mePtr->tkfont;
+ Tk_GetFontMetrics(tkfont, &entryMetrics);
+ fmPtr = &entryMetrics;
+ }
+
+ /*
+ * Need to draw the entire background, including padding. On Unix,
+ * for menubars, we have to draw the rest of the entry taking
+ * into account the padding.
+ */
+
+ DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder,
+ bgBorder, x, y, width, height);
+
+ if (mePtr->type == SEPARATOR_ENTRY) {
+ DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont,
+ fmPtr, x, adjustedY, width, adjustedHeight);
+ } else if (mePtr->type == TEAROFF_ENTRY) {
+ DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY,
+ width, adjustedHeight);
+ } else {
+ DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x,
+ adjustedY, width, adjustedHeight);
+ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr,
+ activeBorder, x, adjustedY, width, adjustedHeight, drawArrow);
+ if (!mePtr->hideMargin) {
+ DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont,
+ fmPtr, x, adjustedY, width, adjustedHeight);
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpComputeStandardMenuGeometry --
+ *
+ * This procedure is invoked to recompute the size and
+ * layout of a menu that is not a menubar clone.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Fields of menu entries are changed to reflect their
+ * current positions, and the size of the menu window
+ * itself may be changed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpComputeStandardMenuGeometry(
+ TkMenu *menuPtr) /* Structure describing menu. */
+{
+ Tk_Font tkfont;
+ Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
+ int x, y, height, modifierWidth, labelWidth, indicatorSpace;
+ int windowWidth, windowHeight, accelWidth, maxAccelTextWidth;
+ int i, j, lastColumnBreak, maxModifierWidth, maxWidth, nonAccelMargin;
+ int maxNonAccelMargin, maxEntryWithAccelWidth, maxEntryWithoutAccelWidth;
+ int entryWidth, maxIndicatorSpace;
+ TkMenuEntry *mePtr, *columnEntryPtr;
+ EntryGeometry *geometryPtr;
+
+ if (menuPtr->tkwin == NULL) {
+ return;
+ }
+
+ x = y = menuPtr->borderWidth;
+ indicatorSpace = labelWidth = accelWidth = maxAccelTextWidth = 0;
+ windowHeight = windowWidth = maxWidth = lastColumnBreak = 0;
+ maxModifierWidth = nonAccelMargin = maxNonAccelMargin = 0;
+ maxEntryWithAccelWidth = maxEntryWithoutAccelWidth = 0;
+ maxIndicatorSpace = 0;
+
+ /*
+ * On the Mac especially, getting font metrics can be quite slow,
+ * so we want to do it intelligently. We are going to precalculate
+ * them and pass them down to all of the measuring and drawing
+ * routines. We will measure the font metrics of the menu once.
+ * If an entry does not have its own font set, then we give
+ * the geometry/drawing routines the menu's font and metrics.
+ * If an entry has its own font, we will measure that font and
+ * give all of the geometry/drawing the entry's font and metrics.
+ */
+
+ Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
+
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ tkfont = mePtr->tkfont;
+ if (tkfont == NULL) {
+ tkfont = menuPtr->tkfont;
+ fmPtr = &menuMetrics;
+ } else {
+ Tk_GetFontMetrics(tkfont, &entryMetrics);
+ fmPtr = &entryMetrics;
+ }
+
+ if ((i > 0) && mePtr->columnBreak) {
+ if (maxIndicatorSpace != 0) {
+ maxIndicatorSpace += 2;
+ }
+ for (j = lastColumnBreak; j < i; j++) {
+ columnEntryPtr = menuPtr->entries[j];
+ geometryPtr =
+ (EntryGeometry *) columnEntryPtr->platformEntryData;
+
+ columnEntryPtr->indicatorSpace = maxIndicatorSpace;
+ columnEntryPtr->width = maxIndicatorSpace + maxWidth
+ + 2 * menuPtr->activeBorderWidth;
+ geometryPtr->accelTextWidth = maxAccelTextWidth;
+ geometryPtr->modifierWidth = maxModifierWidth;
+ columnEntryPtr->x = x;
+ columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
+ if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
+ geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
+ - maxEntryWithAccelWidth;
+ if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
+ geometryPtr->nonAccelMargin = maxNonAccelMargin;
+ }
+ } else {
+ geometryPtr->nonAccelMargin = 0;
+ }
+ }
+ x += maxIndicatorSpace + maxWidth + 2 * menuPtr->borderWidth;
+ windowWidth = x;
+ maxWidth = maxIndicatorSpace = maxAccelTextWidth = 0;
+ maxModifierWidth = maxNonAccelMargin = maxEntryWithAccelWidth = 0;
+ maxEntryWithoutAccelWidth = 0;
+ lastColumnBreak = i;
+ y = menuPtr->borderWidth;
+ }
+
+ if (mePtr->type == SEPARATOR_ENTRY) {
+ GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont,
+ fmPtr, &entryWidth, &height);
+ mePtr->height = height;
+ } else if (mePtr->type == TEAROFF_ENTRY) {
+ GetTearoffEntryGeometry(menuPtr, mePtr, tkfont,
+ fmPtr, &entryWidth, &height);
+ mePtr->height = height;
+ } else {
+
+ /*
+ * For each entry, compute the height required by that
+ * particular entry, plus three widths: the width of the
+ * label, the width to allow for an indicator to be displayed
+ * to the left of the label (if any), and the width of the
+ * accelerator to be displayed to the right of the label
+ * (if any). These sizes depend, of course, on the type
+ * of the entry.
+ */
+
+ GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &labelWidth,
+ &height);
+ mePtr->height = height;
+
+ if (mePtr->type == CASCADE_ENTRY) {
+ GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr,
+ &modifierWidth, &accelWidth, &height);
+ nonAccelMargin = 0;
+ } else if (mePtr->accelLength == 0) {
+ nonAccelMargin = mePtr->hideMargin ? 0
+ : Tk_TextWidth(tkfont, "m", 1);
+ accelWidth = modifierWidth = 0;
+ } else {
+ labelWidth += Tk_TextWidth(tkfont, "m", 1);
+ GetMenuAccelGeometry(menuPtr, mePtr, tkfont,
+ fmPtr, &modifierWidth, &accelWidth, &height);
+ if (height > mePtr->height) {
+ mePtr->height = height;
+ }
+ nonAccelMargin = 0;
+ }
+
+ if (!(mePtr->hideMargin)) {
+ GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont,
+ fmPtr, &indicatorSpace, &height);
+ if (height > mePtr->height) {
+ mePtr->height = height;
+ }
+ } else {
+ indicatorSpace = 0;
+ }
+
+ if (nonAccelMargin > maxNonAccelMargin) {
+ maxNonAccelMargin = nonAccelMargin;
+ }
+ if (accelWidth > maxAccelTextWidth) {
+ maxAccelTextWidth = accelWidth;
+ }
+ if (modifierWidth > maxModifierWidth) {
+ maxModifierWidth = modifierWidth;
+ }
+ if (indicatorSpace > maxIndicatorSpace) {
+ maxIndicatorSpace = indicatorSpace;
+ }
+
+ entryWidth = labelWidth + modifierWidth + accelWidth
+ + nonAccelMargin;
+
+ if (entryWidth > maxWidth) {
+ maxWidth = entryWidth;
+ }
+
+ if (mePtr->accelLength > 0) {
+ if (entryWidth > maxEntryWithAccelWidth) {
+ maxEntryWithAccelWidth = entryWidth;
+ }
+ } else {
+ if (entryWidth > maxEntryWithoutAccelWidth) {
+ maxEntryWithoutAccelWidth = entryWidth;
+ }
+ }
+
+ mePtr->height += 2 * menuPtr->activeBorderWidth;
+ }
+ mePtr->y = y;
+ y += menuPtr->entries[i]->height + menuPtr->borderWidth;
+ if (y > windowHeight) {
+ windowHeight = y;
+ }
+ }
+
+ for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
+ columnEntryPtr = menuPtr->entries[j];
+ geometryPtr = (EntryGeometry *) columnEntryPtr->platformEntryData;
+
+ columnEntryPtr->indicatorSpace = maxIndicatorSpace;
+ columnEntryPtr->width = maxIndicatorSpace + maxWidth
+ + 2 * menuPtr->activeBorderWidth;
+ geometryPtr->accelTextWidth = maxAccelTextWidth;
+ geometryPtr->modifierWidth = maxModifierWidth;
+ columnEntryPtr->x = x;
+ columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
+ if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) {
+ geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth
+ - maxEntryWithAccelWidth;
+ if (geometryPtr->nonAccelMargin > maxNonAccelMargin) {
+ geometryPtr->nonAccelMargin = maxNonAccelMargin;
+ }
+ } else {
+ geometryPtr->nonAccelMargin = 0;
+ }
+ }
+ windowWidth = x + maxIndicatorSpace + maxWidth
+ + 2 * menuPtr->activeBorderWidth + menuPtr->borderWidth;
+ windowHeight += menuPtr->borderWidth;
+
+ /*
+ * The X server doesn't like zero dimensions, so round up to at least
+ * 1 (a zero-sized menu should never really occur, anyway).
+ */
+
+ if (windowWidth <= 0) {
+ windowWidth = 1;
+ }
+ if (windowHeight <= 0) {
+ windowHeight = 1;
+ }
+ menuPtr->totalWidth = windowWidth;
+ menuPtr->totalHeight = windowHeight;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawMenuEntryLabel --
+ *
+ * This procedure draws the label part of a menu.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawMenuEntryLabel(
+ TkMenu *menuPtr, /* The menu we are drawing */
+ TkMenuEntry *mePtr, /* The entry we are drawing */
+ Drawable d, /* What we are drawing into */
+ GC gc, /* The gc we are drawing into */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */
+ int x, /* left edge */
+ int y, /* right edge */
+ int width, /* width of entry */
+ int height) /* height of entry */
+{
+ int baseline;
+ int indicatorSpace = mePtr->indicatorSpace;
+ int leftEdge = x + indicatorSpace;
+ int imageHeight, imageWidth;
+
+ /*
+ * Draw label or bitmap or image for entry.
+ */
+
+ baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2;
+ if (mePtr->image != NULL) {
+ Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
+ if ((mePtr->selectImage != NULL)
+ && (mePtr->entryFlags & ENTRY_SELECTED)) {
+ Tk_RedrawImage(mePtr->selectImage, 0, 0,
+ imageWidth, imageHeight, d, leftEdge,
+ (int) (y + (mePtr->height - imageHeight)/2));
+ } else {
+ Tk_RedrawImage(mePtr->image, 0, 0, imageWidth,
+ imageHeight, d, leftEdge,
+ (int) (y + (mePtr->height - imageHeight)/2));
+ }
+ } else if (mePtr->bitmap != None) {
+ int width, height;
+
+ Tk_SizeOfBitmap(menuPtr->display,
+ mePtr->bitmap, &width, &height);
+ XCopyPlane(menuPtr->display,
+ mePtr->bitmap, d,
+ gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge,
+ (int) (y + (mePtr->height - height)/2), 1);
+ } else {
+ if (mePtr->labelLength > 0) {
+ Str255 itemText;
+
+ GetEntryText(mePtr, itemText);
+ Tk_DrawChars(menuPtr->display, d, gc,
+ tkfont, (char *) itemText + 1, itemText[0],
+ leftEdge, baseline);
+/* TkpDrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y,
+ width, height);*/
+ }
+ }
+
+ if (mePtr->state == tkDisabledUid) {
+ if (menuPtr->disabledFg == NULL) {
+ XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
+ (unsigned) width, (unsigned) height);
+ } else if ((mePtr->image != NULL)
+ && (menuPtr->disabledImageGC != None)) {
+ XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
+ leftEdge,
+ (int) (y + (mePtr->height - imageHeight)/2),
+ (unsigned) imageWidth, (unsigned) imageHeight);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawMenuEntryBackground --
+ *
+ * This procedure draws the background part of a menu.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menu in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawMenuEntryBackground(
+ TkMenu *menuPtr, /* The menu we are drawing. */
+ TkMenuEntry *mePtr, /* The entry we are drawing. */
+ Drawable d, /* What we are drawing into */
+ Tk_3DBorder activeBorder, /* Border for active items */
+ Tk_3DBorder bgBorder, /* Border for the background */
+ int x, /* left edge */
+ int y, /* top edge */
+ int width, /* width of rectangle to draw */
+ int height) /* height of rectangle to draw */
+{
+ if (mePtr->state == tkActiveUid) {
+ bgBorder = activeBorder;
+ }
+ Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder,
+ x, y, width, height, 0, TK_RELIEF_FLAT);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetMenuLabelGeometry --
+ *
+ * Figures out the size of the label portion of a menu item.
+ *
+ * Results:
+ * widthPtr and heightPtr are filled in with the correct geometry
+ * information.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetMenuLabelGeometry(
+ TkMenuEntry *mePtr, /* The entry we are computing */
+ Tk_Font tkfont, /* The precalculated font */
+ CONST Tk_FontMetrics *fmPtr, /* The precalculated metrics */
+ int *widthPtr, /* The resulting width of the label
+ * portion */
+ int *heightPtr) /* The resulting height of the label
+ * portion */
+{
+ TkMenu *menuPtr = mePtr->menuPtr;
+
+ if (mePtr->image != NULL) {
+ Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr);
+ } else if (mePtr->bitmap != (Pixmap) NULL) {
+ Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr);
+ } else {
+ *heightPtr = fmPtr->linespace;
+
+ if (mePtr->label != NULL) {
+ Str255 itemText;
+
+ GetEntryText(mePtr, itemText);
+ *widthPtr = Tk_TextWidth(tkfont, (char *) itemText + 1,
+ itemText[0]);
+ } else {
+ *widthPtr = 0;
+ }
+ }
+ *heightPtr += 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MenuSelectEvent --
+ *
+ * Generates a "MenuSelect" virtual event. This can be used to
+ * do context-sensitive menu help.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Places a virtual event on the event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MenuSelectEvent(
+ TkMenu *menuPtr) /* the menu we have selected. */
+{
+ XVirtualEvent event;
+ Point where;
+
+ event.type = VirtualEvent;
+ event.serial = menuPtr->display->request;
+ event.send_event = false;
+ event.display = menuPtr->display;
+ Tk_MakeWindowExist(menuPtr->tkwin);
+ event.event = Tk_WindowId(menuPtr->tkwin);
+ event.root = XRootWindow(menuPtr->display, 0);
+ event.subwindow = None;
+ event.time = TkpGetMS();
+
+ GetMouse(&where);
+ event.x_root = where.h;
+ event.y_root = where.v;
+ event.state = TkMacButtonKeyState();
+ event.same_screen = true;
+ event.name = Tk_GetUid("MenuSelect");
+ Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RecursivelyClearActiveMenu --
+ *
+ * Recursively clears the active entry in the menu's cascade hierarchy.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Generates <<MenuSelect>> virtual events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+RecursivelyClearActiveMenu(
+ TkMenu *menuPtr) /* The menu to reset. */
+{
+ int i;
+ TkMenuEntry *mePtr;
+
+ TkActivateMenuEntry(menuPtr, -1);
+ MenuSelectEvent(menuPtr);
+ for (i = 0; i < menuPtr->numEntries; i++) {
+ mePtr = menuPtr->entries[i];
+ if (mePtr->type == CASCADE_ENTRY) {
+ if ((mePtr->childMenuRefPtr != NULL)
+ && (mePtr->childMenuRefPtr->menuPtr != NULL)) {
+ RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InvalidateMDEFRgns --
+ *
+ * Invalidates the regions covered by menus that did redrawing and
+ * might be damaged.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Generates Mac update events for affected windows.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+InvalidateMDEFRgns(void) {
+ GDHandle saveDevice;
+ GWorldPtr saveWorld, destPort;
+ Point scratch;
+ MacDrawable *macDraw;
+ TkMacWindowList *listPtr;
+
+ if (totalMenuRgn == NULL) {
+ return;
+ }
+
+ GetGWorld(&saveWorld, &saveDevice);
+ for (listPtr = tkMacWindowListPtr ; listPtr != NULL;
+ listPtr = listPtr->nextPtr) {
+ macDraw = (MacDrawable *) Tk_WindowId(listPtr->winPtr);
+ if (macDraw->flags & TK_DRAWN_UNDER_MENU) {
+ destPort = TkMacGetDrawablePort(Tk_WindowId(listPtr->winPtr));
+ SetGWorld(destPort, NULL);
+ scratch.h = scratch.v = 0;
+ GlobalToLocal(&scratch);
+ OffsetRgn(totalMenuRgn, scratch.v, scratch.h);
+ InvalRgn(totalMenuRgn);
+ OffsetRgn(totalMenuRgn, -scratch.v, -scratch.h);
+ macDraw->flags &= ~TK_DRAWN_UNDER_MENU;
+ }
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+ SetEmptyRgn(totalMenuRgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacClearMenubarActive --
+ *
+ * Recursively clears the active entry in the current menubar hierarchy.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Generates <<MenuSelect>> virtual events.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacClearMenubarActive(void) {
+ TkMenuReferences *menuBarRefPtr;
+
+ if (currentMenuBarName != NULL) {
+ menuBarRefPtr = TkFindMenuReferences(currentMenuBarInterp,
+ currentMenuBarName);
+ if ((menuBarRefPtr != NULL) && (menuBarRefPtr->menuPtr != NULL)) {
+ TkMenu *menuPtr;
+
+ for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL;
+ menuPtr = menuPtr->nextInstancePtr) {
+ if (menuPtr->menuType == MENUBAR) {
+ RecursivelyClearActiveMenu(menuPtr);
+ }
+ }
+ }
+ }
+ InvalidateMDEFRgns();
+ FixMDEF();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuNotifyToplevelCreate --
+ *
+ * This routine reconfigures the menu and the clones indicated by
+ * menuName becuase a toplevel has been created and any system
+ * menus need to be created. Only applicable to Windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An idle handler is set up to do the reconfiguration.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuNotifyToplevelCreate(
+ Tcl_Interp *interp, /* The interp the menu lives in. */
+ char *menuName) /* The name of the menu to
+ * reconfigure. */
+{
+ /*
+ * Nothing to do.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FixMDEF --
+ *
+ * Loads the MDEF and blasts our routine descriptor into it.
+ * We have to set up the MDEF. This is pretty slimy. The real MDEF
+ * resource is 68K code. All this code does is call another procedure.
+ * When the application in launched, a dummy value for the procedure
+ * is compiled into the MDEF. We are going to replace that dummy
+ * value with a routine descriptor. When the routine descriptor
+ * is invoked, the globals and everything will be setup, and we
+ * can do what we need. This will not work from 68K or CFM 68k
+ * currently, so we will conditional compile this until we
+ * figure it out.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allcates a hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FixMDEF(void)
+{
+#ifdef GENERATINGCFM
+ Handle MDEFHandle = GetResource('MDEF', 591);
+ Handle SICNHandle = GetResource('SICN', SICN_RESOURCE_NUMBER);
+ if ((MDEFHandle != NULL) && (SICNHandle != NULL)) {
+ MoveHHi(MDEFHandle);
+ HLock(MDEFHandle);
+ menuDefProc = TkNewMenuDefProc(MenuDefProc);
+ memmove((void *) (((long) (*MDEFHandle)) + 0x24), &menuDefProc, 4);
+ }
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMenuInit --
+ *
+ * Initializes Mac-specific menu data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allcates a hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMenuInit(void)
+{
+ lastMenuID = 256;
+ Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS);
+ currentMenuBarOwner = NULL;
+ tearoffStruct.menuPtr = NULL;
+ currentAppleMenuID = 0;
+ currentHelpMenuID = 0;
+ currentMenuBarInterp = NULL;
+ currentMenuBarName = NULL;
+ windowListPtr = NULL;
+}
diff --git a/mac/tkMacMenu.r b/mac/tkMacMenu.r
new file mode 100644
index 0000000..9952cea
--- /dev/null
+++ b/mac/tkMacMenu.r
@@ -0,0 +1,47 @@
+/*
+ * tkMacMenu.r --
+ *
+ * Resources needed by menus.
+ *
+ * This file also contains the icons 'SICN' used by the menu code
+ * in menu items.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacMenu.r 1.1 97/07/11 18:06:27
+ */
+
+#include <Types.r>
+
+/*
+ * Icons used in menu items.
+ */
+
+resource 'SICN' (128, preload) {
+ { /* array: 7 elements */
+ /* [1] */
+ $"0000 0000 8000 C000 E000 F000 F800 FC00"
+ $"F800 F000 E000 C000 80",
+ /* [2] */
+ $"0000 0000 0000 0800 1400 2200 4100 8080"
+ $"E380 2200 2200 2200 3E",
+ /* [3] */
+ $"0000 0000 0000 0000 0000 F8F0 C4F0 F270"
+ $"0900 0480 0270 0130 00F0",
+ /* [4] */
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 E4E0 CE60 1B00 3180",
+ /* [5] */
+ $"0000 0000 0000 0000 6300 9480 9480 7F00"
+ $"1400 7F00 9480 9480 63",
+ /* [6] */
+ $"0000 0000 0000 0000 0000 3FF8 1FF0 0FE0"
+ $"07C0 0380 01",
+ /* [7] */
+ $"0000 0000 0000 0000 0000 0100 0380 07C0"
+ $"0FE0 1FF0 3FF8"
+ }
+};
diff --git a/mac/tkMacMenubutton.c b/mac/tkMacMenubutton.c
new file mode 100644
index 0000000..42b8d2b
--- /dev/null
+++ b/mac/tkMacMenubutton.c
@@ -0,0 +1,339 @@
+/*
+ * tkMacMenubutton.c --
+ *
+ * This file implements the Macintosh specific portion of the
+ * menubutton widget.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacMenubutton.c 1.4 97/01/03 13:55:19
+ */
+
+#include "tkMenubutton.h"
+#include "tkMacInt.h"
+#include <Controls.h>
+
+#define kShadowOffset (3) /* amount to offset shadow from frame */
+#define kTriangleWidth (11) /* width of the triangle */
+#define kTriangleHeight (6) /* height of the triangle */
+#define kTriangleMargin (5) /* margin around triangle */
+
+/*
+ * Declaration of Unix specific button structure.
+ */
+
+typedef struct MacMenuButton {
+ TkMenuButton info; /* Generic button info. */
+} MacMenuButton;
+
+/*
+ * The structure below defines menubutton class behavior by means of
+ * procedures that can be invoked from generic window code.
+ */
+
+TkClassProcs tkpMenubuttonClass = {
+ NULL, /* createProc. */
+ TkMenuButtonWorldChanged, /* geometryProc. */
+ NULL /* modalProc. */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateMenuButton --
+ *
+ * Allocate a new TkMenuButton structure.
+ *
+ * Results:
+ * Returns a newly allocated TkMenuButton structure.
+ *
+ * Side effects:
+ * Registers an event handler for the widget.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkMenuButton *
+TkpCreateMenuButton(
+ Tk_Window tkwin)
+{
+ MacMenuButton *butPtr = (MacMenuButton *)ckalloc(sizeof(MacMenuButton));
+
+ return (TkMenuButton *) butPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDisplayMenuButton --
+ *
+ * This procedure is invoked to display a menubutton widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the menubutton in its
+ * current mode.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDisplayMenuButton(
+ ClientData clientData) /* Information about widget. */
+{
+ TkMenuButton *mbPtr = (TkMenuButton *) clientData;
+ GC gc;
+ Tk_3DBorder border;
+ int x = 0; /* Initialization needed only to stop
+ * compiler warning. */
+ int y;
+ Tk_Window tkwin = mbPtr->tkwin;
+ int width, height;
+ MacMenuButton * macMBPtr = (MacMenuButton *) mbPtr;
+ GWorldPtr destPort;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ MacDrawable *macDraw;
+
+ mbPtr->flags &= ~REDRAW_PENDING;
+ if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ GetGWorld(&saveWorld, &saveDevice);
+ destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
+ SetGWorld(destPort, NULL);
+ macDraw = (MacDrawable *) Tk_WindowId(tkwin);
+
+ if ((mbPtr->state == tkDisabledUid) && (mbPtr->disabledFg != NULL)) {
+ gc = mbPtr->disabledGC;
+ } else if ((mbPtr->state == tkActiveUid) && !Tk_StrictMotif(mbPtr->tkwin)) {
+ gc = mbPtr->activeTextGC;
+ } else {
+ gc = mbPtr->normalTextGC;
+ }
+ border = mbPtr->normalBorder;
+
+ /*
+ * In order to avoid screen flashes, this procedure redraws
+ * the menu button in a pixmap, then copies the pixmap to the
+ * screen in a single operation. This means that there's no
+ * point in time where the on-sreen image has been cleared.
+ */
+
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+
+ /*
+ * Display image or bitmap or text for button.
+ */
+
+ if (mbPtr->image != None) {
+ Tk_SizeOfImage(mbPtr->image, &width, &height);
+
+ imageOrBitmap:
+ TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,
+ width + mbPtr->indicatorWidth, height, &x, &y);
+ if (mbPtr->image != NULL) {
+ Tk_RedrawImage(mbPtr->image, 0, 0, width, height,
+ Tk_WindowId(tkwin), x, y);
+ } else {
+ XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin),
+ gc, 0, 0, (unsigned) width, (unsigned) height, x, y, 1);
+ }
+ } else if (mbPtr->bitmap != None) {
+ Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
+ goto imageOrBitmap;
+ } else {
+ TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY,
+ mbPtr->textWidth + mbPtr->indicatorWidth, mbPtr->textHeight,
+ &x, &y);
+ Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc,
+ mbPtr->textLayout, x, y, 0, -1);
+ }
+
+ /*
+ * If the menu button is disabled with a stipple rather than a special
+ * foreground color, generate the stippled effect.
+ */
+
+ if ((mbPtr->state == tkDisabledUid)
+ && ((mbPtr->disabledFg == NULL) || (mbPtr->image != NULL))) {
+ XFillRectangle(mbPtr->display, Tk_WindowId(tkwin), mbPtr->disabledGC,
+ mbPtr->inset, mbPtr->inset,
+ (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset),
+ (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset));
+ }
+
+ /*
+ * Draw the cascade indicator for the menu button on the
+ * right side of the window, if desired.
+ */
+
+ if (mbPtr->indicatorOn) {
+ int w, h, i;
+ Rect r;
+
+ r.left = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset
+ - mbPtr->indicatorWidth;
+ r.top = macDraw->yOff + Tk_Height(tkwin)/2
+ - mbPtr->indicatorHeight/2;
+ r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset
+ - kTriangleMargin;
+ r.bottom = macDraw->yOff + Tk_Height(tkwin)/2
+ + mbPtr->indicatorHeight/2;
+
+ h = mbPtr->indicatorHeight;
+ w = mbPtr->indicatorWidth - 1 - kTriangleMargin;
+ for (i = 0; i < h; i++) {
+ MoveTo(r.left + i, r.top + i);
+ LineTo(r.left + i + w, r.top + i);
+ w -= 2;
+ }
+ }
+
+ /*
+ * Draw the border and traversal highlight last. This way, if the
+ * menu button's contents overflow onto the border they'll be covered
+ * up by the border.
+ */
+
+ TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
+ if (mbPtr->borderWidth > 0) {
+ Rect r;
+
+ r.left = macDraw->xOff + mbPtr->highlightWidth + mbPtr->borderWidth;
+ r.top = macDraw->yOff + mbPtr->highlightWidth + mbPtr->borderWidth;
+ r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->highlightWidth
+ - mbPtr->borderWidth;
+ r.bottom = macDraw->yOff + Tk_Height(tkwin) - mbPtr->highlightWidth
+ - mbPtr->borderWidth;
+ FrameRect(&r);
+
+ PenSize(mbPtr->borderWidth - 1, mbPtr->borderWidth - 1);
+ MoveTo(r.right, r.top + kShadowOffset);
+ LineTo(r.right, r.bottom);
+ LineTo(r.left + kShadowOffset, r.bottom);
+ }
+
+ if (mbPtr->state == tkDisabledUid) {
+ }
+
+ if (mbPtr->highlightWidth != 0) {
+ GC gc;
+
+ if (mbPtr->flags & GOT_FOCUS) {
+ gc = Tk_GCForColor(mbPtr->highlightColorPtr, Tk_WindowId(tkwin));
+ } else {
+ gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, Tk_WindowId(tkwin));
+ }
+ Tk_DrawFocusHighlight(tkwin, gc, mbPtr->highlightWidth,
+ Tk_WindowId(tkwin));
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyMenuButton --
+ *
+ * Free data structures associated with the menubutton control.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Restores the default control state.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyMenuButton(
+ TkMenuButton *mbPtr)
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpComputeMenuButtonGeometry --
+ *
+ * After changes in a menu button's text or bitmap, this procedure
+ * recomputes the menu button's geometry and passes this information
+ * along to the geometry manager for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The menu button's window may change size.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpComputeMenuButtonGeometry(mbPtr)
+ register TkMenuButton *mbPtr; /* Widget record for menu button. */
+{
+ int width, height, mm, pixels;
+
+ mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth;
+ if (mbPtr->image != None) {
+ Tk_SizeOfImage(mbPtr->image, &width, &height);
+ if (mbPtr->width > 0) {
+ width = mbPtr->width;
+ }
+ if (mbPtr->height > 0) {
+ height = mbPtr->height;
+ }
+ } else if (mbPtr->bitmap != None) {
+ Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
+ if (mbPtr->width > 0) {
+ width = mbPtr->width;
+ }
+ if (mbPtr->height > 0) {
+ height = mbPtr->height;
+ }
+ } else {
+ Tk_FreeTextLayout(mbPtr->textLayout);
+ mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text,
+ -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth,
+ &mbPtr->textHeight);
+ width = mbPtr->textWidth;
+ height = mbPtr->textHeight;
+ if (mbPtr->width > 0) {
+ width = mbPtr->width * Tk_TextWidth(mbPtr->tkfont, "0", 1);
+ }
+ if (mbPtr->height > 0) {
+ Tk_FontMetrics fm;
+
+ Tk_GetFontMetrics(mbPtr->tkfont, &fm);
+ height = mbPtr->height * fm.linespace;
+ }
+ width += 2*mbPtr->padX;
+ height += 2*mbPtr->padY;
+ }
+
+ if (mbPtr->indicatorOn) {
+ mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin));
+ pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin));
+ mbPtr->indicatorHeight= kTriangleHeight;
+ mbPtr->indicatorWidth = kTriangleWidth + kTriangleMargin;
+ width += mbPtr->indicatorWidth;
+ } else {
+ mbPtr->indicatorHeight = 0;
+ mbPtr->indicatorWidth = 0;
+ }
+
+ Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset),
+ (int) (height + 2*mbPtr->inset));
+ Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset);
+}
diff --git a/mac/tkMacMenus.c b/mac/tkMacMenus.c
new file mode 100644
index 0000000..6eaf0ae
--- /dev/null
+++ b/mac/tkMacMenus.c
@@ -0,0 +1,346 @@
+/*
+ * tkMacMenus.c --
+ *
+ * These calls set up and manage the menubar for the
+ * Macintosh version of Tk.
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacMenus.c 1.38 97/10/31 17:37:03
+ */
+
+#include "tcl.h"
+#include "tclMacInt.h"
+#include "tk.h"
+#include "tkInt.h"
+#include "tkMacInt.h"
+
+/*
+ * The define Status defined by Xlib.h conflicts with the function Status
+ * defined by Devices.h. We undefine it here to compile.
+ */
+#undef Status
+#include <Devices.h>
+#include <Menus.h>
+#include <Memory.h>
+#include <SegLoad.h>
+#include <StandardFile.h>
+#include <ToolUtils.h>
+#include <Balloons.h>
+
+#define kAppleMenu 256
+#define kAppleAboutItem 1
+#define kFileMenu 2
+#define kEditMenu 3
+
+#define kSourceItem 1
+#define kCloseItem 2
+#define kQuitItem 4
+
+#define EDIT_CUT 1
+#define EDIT_COPY 2
+#define EDIT_PASTE 3
+#define EDIT_CLEAR 4
+
+MenuHandle tkAppleMenu;
+MenuHandle tkFileMenu;
+MenuHandle tkEditMenu;
+
+static Tcl_Interp * gInterp; /* Interpreter for this application. */
+
+static void GenerateEditEvent _ANSI_ARGS_((int flag));
+static void SourceDialog _ANSI_ARGS_((void));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacHandleMenuSelect --
+ *
+ * Handles events that occur in the Menu bar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacHandleMenuSelect(
+ long mResult,
+ int optionKeyPressed)
+{
+ short theItem = LoWord(mResult);
+ short theMenu = HiWord(mResult);
+ Str255 name;
+ Tk_Window tkwin;
+ Window window;
+
+ if (mResult == 0) {
+ TkMacHandleTearoffMenu();
+ TkMacClearMenubarActive();
+ return;
+ }
+
+ switch (theMenu) {
+
+ case kAppleMenu:
+ switch (theItem) {
+ case kAppleAboutItem:
+ {
+ Tcl_CmdInfo dummy;
+
+ if (optionKeyPressed || gInterp == NULL ||
+ Tcl_GetCommandInfo(gInterp,
+ "tkAboutDialog", &dummy) == 0) {
+ TkAboutDlg();
+ } else {
+ Tcl_Eval(gInterp, "tkAboutDialog");
+ }
+ break;
+ }
+ default:
+ GetItem(tkAppleMenu, theItem, name);
+ HiliteMenu(0);
+ OpenDeskAcc(name);
+ return;
+ }
+ break;
+ case kFileMenu:
+ switch (theItem) {
+ case kSourceItem:
+ /* TODO: source script */
+ SourceDialog();
+ break;
+ case kCloseItem:
+ /* Send close event */
+ window = TkMacGetXWindow(FrontWindow());
+ tkwin = Tk_IdToWindow(tkDisplayList->display, window);
+ TkGenWMDestroyEvent(tkwin);
+ break;
+ case kQuitItem:
+ /* Exit */
+ if (optionKeyPressed || gInterp == NULL) {
+ Tcl_Exit(0);
+ } else {
+ Tcl_Eval(gInterp, "exit");
+ }
+ break;
+ }
+ break;
+ case kEditMenu:
+ /*
+ * This implementation just send keysyms
+ * the Tk thinks are associated with function keys that
+ * do Cut, Copy & Paste on a Sun keyboard.
+ */
+ GenerateEditEvent(theItem);
+ break;
+ default:
+ TkMacDispatchMenuEvent(theMenu, theItem);
+ TkMacClearMenubarActive();
+ break;
+ }
+
+ /*
+ * Finally we unhighlight the menu.
+ */
+ HiliteMenu(0);
+} /* TkMacHandleMenuSelect */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacInitMenus --
+ *
+ * This procedure initializes the Macintosh menu bar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacInitMenus(
+ Tcl_Interp *interp)
+{
+ gInterp = interp;
+
+ /*
+ * At this point, InitMenus() should have already been called.
+ */
+
+ if (TkMacUseMenuID(256) != TCL_OK) {
+ panic("Menu ID 256 is already in use!");
+ }
+ tkAppleMenu = NewMenu(256, "\p\024");
+ if (tkAppleMenu == NULL) {
+ panic("memory - menus");
+ }
+ InsertMenu(tkAppleMenu, 0);
+ AppendMenu(tkAppleMenu, "\pAbout Tcl & TkÉ");
+ AppendMenu(tkAppleMenu, "\p(-");
+ AddResMenu(tkAppleMenu, 'DRVR');
+
+ if (TkMacUseMenuID(kFileMenu) != TCL_OK) {
+ panic("Menu ID %d is already in use!", kFileMenu);
+ }
+ tkFileMenu = NewMenu(kFileMenu, "\pFile");
+ if (tkFileMenu == NULL) {
+ panic("memory - menus");
+ }
+ InsertMenu(tkFileMenu, 0);
+ AppendMenu(tkFileMenu, "\pSourceÉ");
+ AppendMenu(tkFileMenu, "\pClose/W");
+ AppendMenu(tkFileMenu, "\p(-");
+ AppendMenu(tkFileMenu, "\pQuit/Q");
+
+ if (TkMacUseMenuID(kEditMenu) != TCL_OK) {
+ panic("Menu ID %d is already in use!", kEditMenu);
+ }
+ tkEditMenu = NewMenu(kEditMenu, "\pEdit");
+ if (tkEditMenu == NULL) {
+ panic("memory - menus");
+ }
+ InsertMenu(tkEditMenu, 0);
+ AppendMenu(tkEditMenu, "\pCut/X");
+ AppendMenu(tkEditMenu, "\pCopy/C");
+ AppendMenu(tkEditMenu, "\pPaste/V");
+ AppendMenu(tkEditMenu, "\pClear");
+ if (TkMacUseMenuID(kHMHelpMenuID) != TCL_OK) {
+ panic("Help menu ID %s is already in use!", kHMHelpMenuID);
+ }
+
+ DrawMenuBar();
+ TkMacSetHelpMenuItemCount();
+
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateEditEvent --
+ *
+ * Takes an edit menu item and posts the corasponding a virtual
+ * event to Tk's event queue.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May place events of queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateEditEvent(
+ int flag)
+{
+ XVirtualEvent event;
+ Point where;
+ Tk_Window tkwin;
+ Window window;
+
+ window = TkMacGetXWindow(FrontWindow());
+ tkwin = Tk_IdToWindow(tkDisplayList->display, window);
+ tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr;
+ if (tkwin == NULL) {
+ return;
+ }
+
+ event.type = VirtualEvent;
+ event.serial = Tk_Display(tkwin)->request;
+ event.send_event = false;
+ event.display = Tk_Display(tkwin);
+ event.event = Tk_WindowId(tkwin);
+ event.root = XRootWindow(Tk_Display(tkwin), 0);
+ event.subwindow = None;
+ event.time = TkpGetMS();
+
+ GetMouse(&where);
+ tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v,
+ &event.x, &event.y);
+ LocalToGlobal(&where);
+ event.x_root = where.h;
+ event.y_root = where.v;
+ event.state = TkMacButtonKeyState();
+ event.same_screen = true;
+
+ switch (flag) {
+ case EDIT_CUT:
+ event.name = Tk_GetUid("Cut");
+ break;
+
+ case EDIT_COPY:
+ event.name = Tk_GetUid("Copy");
+ break;
+
+ case EDIT_PASTE:
+ event.name = Tk_GetUid("Paste");
+ break;
+
+ case EDIT_CLEAR:
+ event.name = Tk_GetUid("Clear");
+ break;
+ }
+ Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SourceDialog --
+ *
+ * Presents a dialog to the user for selecting a Tcl file. The
+ * selected file will be sourced into the main interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SourceDialog()
+{
+ StandardFileReply reply;
+ OSType fileTypes[1];
+ OSErr err;
+ int length, result;
+ Handle path;
+
+ if (gInterp == NULL) {
+ return;
+ }
+
+ fileTypes[0] = 'TEXT';
+ StandardGetFile(NULL, 1, fileTypes, &reply);
+ if (reply.sfGood == false) {
+ return;
+ }
+
+ err = FSpPathFromLocation(&reply.sfFile, &length, &path);
+ if (err == noErr) {
+ HLock(path);
+ result = Tcl_EvalFile(gInterp, *path);
+ HUnlock(path);
+ DisposeHandle(path);
+ }
+ if (result == TCL_ERROR) {
+ Tcl_BackgroundError(gInterp);
+ }
+}
diff --git a/mac/tkMacPort.h b/mac/tkMacPort.h
new file mode 100644
index 0000000..733e745
--- /dev/null
+++ b/mac/tkMacPort.h
@@ -0,0 +1,145 @@
+/*
+ * tkMacPort.h --
+ *
+ * This file is included by all of the Tk C files. It contains
+ * information that may be configuration-dependent, such as
+ * #includes for system include files and a few other things.
+ *
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacPort.h 1.52 97/07/28 11:18:59
+ */
+
+#ifndef _TKMACPORT
+#define _TKMACPORT
+
+/*
+ * Macro to use instead of "void" for arguments that must have
+ * type "void *" in ANSI C; maps them to type "char *" in
+ * non-ANSI systems. This macro may be used in some of the include
+ * files below, which is why it is defined here.
+ */
+
+#ifndef VOID
+# ifdef __STDC__
+# define VOID void
+# else
+# define VOID char
+# endif
+#endif
+
+#ifndef _TCL
+# include <tcl.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tclMath.h"
+#include <ctype.h>
+#include <limits.h>
+
+#include <Xlib.h>
+#include <cursorfont.h>
+#include <keysym.h>
+#include <Xatom.h>
+#include <Xfuncproto.h>
+#include <Xutil.h>
+
+/*
+ * Not all systems declare the errno variable in errno.h. so this
+ * file does it explicitly.
+ */
+
+extern int errno;
+
+/*
+ * Define "NBBY" (number of bits per byte) if it's not already defined.
+ */
+
+#ifndef NBBY
+# define NBBY 8
+#endif
+
+/*
+ * Declarations for various library procedures that may not be declared
+ * in any other header file.
+ */
+
+extern void panic _ANSI_ARGS_(TCL_VARARGS(char *, string));
+extern int strcasecmp _ANSI_ARGS_((CONST char *s1,
+ CONST char *s2));
+extern int strncasecmp _ANSI_ARGS_((CONST char *s1,
+ CONST char *s2, size_t n));
+
+/*
+ * Defines for X functions that are used by Tk but are treated as
+ * no-op functions on the Macintosh.
+ */
+
+#define XFlush(display)
+#define XFree(data) {if ((data) != NULL) ckfree((char *) (data));}
+#define XGrabServer(display)
+#define XNoOp(display) {display->request++;}
+#define XUngrabServer(display)
+#define XSynchronize(display, bool) {display->request++;}
+#define XSync(display, bool) {display->request++;}
+#define XVisualIDFromVisual(visual) (visual->visualid)
+
+/*
+ * The following functions are not used on the Mac, so we stub it out.
+ */
+
+#define TkFreeWindowId(dispPtr,w)
+#define TkInitXId(dispPtr)
+#define TkpCmapStressed(tkwin,colormap) (0)
+#define TkpFreeColor(tkColPtr)
+#define TkSetPixmapColormap(p,c) {}
+#define Tk_FreeXId(display,xid)
+#define TkpSync(display)
+
+/*
+ * The following macro returns the pixel value that corresponds to the
+ * RGB values in the given XColor structure.
+ */
+
+#define PIXEL_MAGIC ((unsigned char) 0x69)
+#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
+ | (((p)->red >> 8) & 0xff)) << 8) \
+ | (((p)->green >> 8) & 0xff)) << 8) \
+ | (((p)->blue >> 8) & 0xff))
+
+/*
+ * This macro stores a representation of the window handle in a string.
+ */
+
+#define TkpPrintWindowId(buf,w) \
+ sprintf((buf), "0x%x", (unsigned int) (w))
+
+/*
+ * TkpScanWindowId is just an alias for Tcl_GetInt on Unix.
+ */
+
+#define TkpScanWindowId(i,s,wp) \
+ Tcl_GetInt((i),(s),(wp))
+
+/*
+ * Magic pixel values for dynamic (or active) colors.
+ */
+
+#define HIGHLIGHT_PIXEL 31
+#define HIGHLIGHT_TEXT_PIXEL 33
+#define CONTROL_TEXT_PIXEL 35
+#define CONTROL_BODY_PIXEL 37
+#define CONTROL_FRAME_PIXEL 39
+#define WINDOW_BODY_PIXEL 41
+#define MENU_ACTIVE_PIXEL 43
+#define MENU_ACTIVE_TEXT_PIXEL 45
+#define MENU_BACKGROUND_PIXEL 47
+#define MENU_DISABLED_PIXEL 49
+#define MENU_TEXT_PIXEL 51
+
+#endif /* _TKMACPORT */
diff --git a/mac/tkMacProlog.c b/mac/tkMacProlog.c
new file mode 100644
index 0000000..21cf67c
--- /dev/null
+++ b/mac/tkMacProlog.c
@@ -0,0 +1,61 @@
+/*
+ * tkMacProlog.c --
+ *
+ * Implements a method on the Macintosh to get the prolog
+ * from the resource fork of our application (or the shared
+ * library).
+ *
+ * Copyright (c) 1996-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacProlog.c 1.6 97/05/21 10:01:07
+ */
+
+#include "tkInt.h"
+#include "tclMacInt.h"
+#include <Resources.h>
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetNativeProlog --
+ *
+ * Locate and load the postscript prolog from the resource
+ * fork of the application. If it can't be found then we
+ * will try looking for the file in the system folder.
+ *
+ * Results:
+ * A standard Tcl Result. If everything is OK the prolog
+ * will be located in the result string of the interpreter.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkGetNativeProlog(
+ Tcl_Interp *interp) /* Places the prolog in the result. */
+{
+ Handle resource;
+ char *stringPtr;
+ int releaseIt;
+
+
+ resource = Tcl_MacFindResource(interp, 'TEXT', "prolog", -1,
+ NULL, &releaseIt);
+
+ if (resource != NULL) {
+ stringPtr = Tcl_MacConvertTextResource(resource);
+ Tcl_SetResult(interp, stringPtr, TCL_DYNAMIC);
+ if (releaseIt) {
+ ReleaseResource(resource);
+ }
+ return TCL_OK;
+ } else {
+ return TkGetProlog(interp);
+ }
+}
diff --git a/mac/tkMacRegion.c b/mac/tkMacRegion.c
new file mode 100644
index 0000000..534624c
--- /dev/null
+++ b/mac/tkMacRegion.c
@@ -0,0 +1,217 @@
+/*
+ * tkMacRegion.c --
+ *
+ * Implements X window calls for manipulating regions
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacRegion.c 1.9 96/12/03 11:46:50
+ */
+
+#include "tkInt.h"
+#include "X.h"
+#include "Xlib.h"
+
+#include <Windows.h>
+#include <QDOffscreen.h>
+
+/*
+ * Temporary region that can be reused.
+ */
+static RgnHandle tmpRgn = NULL;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkCreateRegion --
+ *
+ * Implements the equivelent of the X window function
+ * XCreateRegion. See X window documentation for more details.
+ *
+ * Results:
+ * Returns an allocated region handle.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkRegion
+TkCreateRegion()
+{
+ RgnHandle rgn;
+
+ rgn = NewRgn();
+ return (TkRegion) rgn;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDestroyRegion --
+ *
+ * Implements the equivelent of the X window function
+ * XDestroyRegion. See X window documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkDestroyRegion(
+ TkRegion r)
+{
+ RgnHandle rgn = (RgnHandle) r;
+
+ DisposeRgn(rgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkIntersectRegion --
+ *
+ * Implements the equivilent of the X window function
+ * XIntersectRegion. See X window documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkIntersectRegion(
+ TkRegion sra,
+ TkRegion srb,
+ TkRegion dr_return)
+{
+ RgnHandle srcRgnA = (RgnHandle) sra;
+ RgnHandle srcRgnB = (RgnHandle) srb;
+ RgnHandle destRgn = (RgnHandle) dr_return;
+
+ SectRgn(srcRgnA, srcRgnB, destRgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUnionRectWithRegion --
+ *
+ * Implements the equivelent of the X window function
+ * XUnionRectWithRegion. See X window documentation for more
+ * details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkUnionRectWithRegion(
+ XRectangle* rectangle,
+ TkRegion src_region,
+ TkRegion dest_region_return)
+{
+ RgnHandle srcRgn = (RgnHandle) src_region;
+ RgnHandle destRgn = (RgnHandle) dest_region_return;
+
+ if (tmpRgn == NULL) {
+ tmpRgn = NewRgn();
+ }
+ SetRectRgn(tmpRgn, rectangle->x, rectangle->y,
+ rectangle->x + rectangle->width, rectangle->y + rectangle->height);
+ UnionRgn(srcRgn, tmpRgn, destRgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkRectInRegion --
+ *
+ * Implements the equivelent of the X window function
+ * XRectInRegion. See X window documentation for more details.
+ *
+ * Results:
+ * Returns one of: RectangleOut, RectangleIn, RectanglePart.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkRectInRegion(
+ TkRegion region,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ RgnHandle rgn = (RgnHandle) region;
+ RgnHandle rectRgn, destRgn;
+ int result;
+
+ rectRgn = NewRgn();
+ destRgn = NewRgn();
+ SetRectRgn(rectRgn, x, y, x + width, y + height);
+ SectRgn(rgn, rectRgn, destRgn);
+ if (EmptyRgn(destRgn)) {
+ result = RectangleOut;
+ } else if (EqualRgn(rgn, destRgn)) {
+ result = RectangleIn;
+ } else {
+ result = RectanglePart;
+ }
+ DisposeRgn(rectRgn);
+ DisposeRgn(destRgn);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkClipBox --
+ *
+ * Implements the equivelent of the X window function XClipBox.
+ * See X window documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkClipBox(
+ TkRegion r,
+ XRectangle* rect_return)
+{
+ RgnHandle rgn = (RgnHandle) r;
+
+ rect_return->x = (**rgn).rgnBBox.left;
+ rect_return->y = (**rgn).rgnBBox.top;
+ rect_return->width = (**rgn).rgnBBox.right - (**rgn).rgnBBox.left;
+ rect_return->height = (**rgn).rgnBBox.bottom - (**rgn).rgnBBox.top;
+}
diff --git a/mac/tkMacResource.r b/mac/tkMacResource.r
new file mode 100644
index 0000000..23a2000
--- /dev/null
+++ b/mac/tkMacResource.r
@@ -0,0 +1,507 @@
+/*
+ * tkMacResources.r --
+ *
+ * This file creates resources for use in a simple shell.
+ * This is designed to be an example of using the Tcl/Tk
+ * libraries in a Macintosh Application.
+ *
+ * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacResource.r 1.35 97/11/03 17:16:34
+ */
+
+/*
+ * We define SystemSevenOrLater so that our dialogs may use the
+ * auto center feature.
+ */
+#define SystemSevenOrLater 1
+
+#include <Types.r>
+#include <SysTypes.r>
+
+/*
+ * The folowing include and defines help construct
+ * the version string for Tcl.
+ */
+
+#define RESOURCE_INCLUDED
+#include "tcl.h"
+#include "tk.h"
+
+#if (TK_RELEASE_LEVEL == 0)
+# define RELEASE_LEVEL alpha
+#elif (TK_RELEASE_LEVEL == 1)
+# define RELEASE_LEVEL beta
+#elif (TK_RELEASE_LEVEL == 2)
+# define RELEASE_LEVEL final
+#endif
+
+#if (TK_RELEASE_LEVEL == 2)
+# define MINOR_VERSION (TK_MINOR_VERSION * 16) + TK_RELEASE_SERIAL
+#else
+# define MINOR_VERSION TK_MINOR_VERSION * 16
+#endif
+
+resource 'vers' (1) {
+ TK_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TK_PATCH_LEVEL,
+ TK_PATCH_LEVEL ", by Ray Johnson © 1993-1996" "\n" "Sun Microsystems Labratories"
+};
+
+resource 'vers' (2) {
+ TK_MAJOR_VERSION, MINOR_VERSION,
+ RELEASE_LEVEL, 0x00, verUS,
+ TK_PATCH_LEVEL,
+ "Wish " TK_PATCH_LEVEL " © 1993-1996"
+};
+
+
+/*
+ * The mechanisim below loads Tcl source into the resource fork of the
+ * application. The example below creates a TEXT resource named
+ * "Init" from the file "init.tcl". This allows applications to use
+ * Tcl to define the behavior of the application without having to
+ * require some predetermined file structure - all needed Tcl "files"
+ * are located within the application. To source a file for the
+ * resource fork the source command has been modified to support
+ * sourcing from resources. In the below case "source -rsrc {Init}"
+ * will load the TEXT resource named "Init".
+ */
+
+read 'TEXT' (0, "Init", purgeable, preload)
+ ":::tcl" TCL_VERSION ":library:init.tcl";
+read 'TEXT' (1, "History", purgeable, preload)
+ ":::tcl" TCL_VERSION ":library:history.tcl";
+read 'TEXT' (2, "Word", purgeable,preload)
+ ":::tcl" TCL_VERSION ":library:word.tcl";
+
+read 'TEXT' (10, "tk", purgeable, preload) "::library:tk.tcl";
+read 'TEXT' (11, "button", purgeable, preload) "::library:button.tcl";
+read 'TEXT' (12, "dialog", purgeable, preload) "::library:dialog.tcl";
+read 'TEXT' (13, "entry", purgeable, preload) "::library:entry.tcl";
+read 'TEXT' (14, "focus", purgeable, preload) "::library:focus.tcl";
+read 'TEXT' (15, "listbox", purgeable, preload) "::library:listbox.tcl";
+read 'TEXT' (16, "menu", purgeable, preload) "::library:menu.tcl";
+read 'TEXT' (17, "optionMenu", purgeable, preload) "::library:optMenu.tcl";
+read 'TEXT' (18, "palette", purgeable, preload) "::library:palette.tcl";
+read 'TEXT' (19, "scale", purgeable, preload) "::library:scale.tcl";
+read 'TEXT' (20, "scrollbar", purgeable, preload) "::library:scrlbar.tcl";
+read 'TEXT' (21, "tearoff", purgeable, preload) "::library:tearoff.tcl";
+read 'TEXT' (22, "text", purgeable, preload) "::library:text.tcl";
+read 'TEXT' (23, "tkerror", purgeable, preload) "::library:bgerror.tcl";
+read 'TEXT' (24, "Console", purgeable, preload) "::library:console.tcl";
+read 'TEXT' (25, "msgbox", purgeable, preload) "::library:msgbox.tcl";
+read 'TEXT' (26, "comdlg", purgeable, preload) "::library:comdlg.tcl";
+read 'TEXT' (27, "prolog", purgeable, preload) "::library:prolog.ps";
+
+
+/*
+ * The following resource is used when creating the 'env' variable in
+ * the Macintosh environment. The creation mechanisim looks for the
+ * 'STR#' resource named "Tcl Environment Variables" rather than a
+ * specific resource number. (In other words, feel free to change the
+ * resource id if it conflicts with your application.) Each string in
+ * the resource must be of the form "KEYWORD=SOME STRING". See Tcl
+ * documentation for futher information about the env variable.
+ */
+
+/* A good example of something you may want to set is:
+ * "TCL_LIBRARY=My disk:etc."
+ */
+
+resource 'STR#' (128, "Tcl Environment Variables") {
+ { "SCHEDULE_NAME=Agent Controller Schedule",
+ "SCHEDULE_PATH=Lozoya:System Folder:Tcl Lib:Tcl-Scheduler"
+ };
+};
+
+/*
+ * The following two resources define the default "About Box" for Mac Tk.
+ * This dialog appears if the "About Tk..." menu item is selected from
+ * the Apple menu. This dialog may be overridden by defining a Tcl procedure
+ * with the name of "tkAboutDialog". If this procedure is defined the
+ * default dialog will not be shown and the Tcl procedure is expected to
+ * create and manage an About Dialog box.
+ */
+
+resource 'DLOG' (128, "Default About Box", purgeable) {
+ {85, 107, 243, 406}, dBoxProc, visible, goAway, 0,
+ 128, "", centerMainScreen
+};
+
+resource 'DITL' (128, "About Box", purgeable) {
+ {
+ {128, 128, 148, 186}, Button {enabled, "Ok"},
+ { 14, 108, 117, 310}, StaticText {disabled,
+ "Wish - Windowing Shell" "\n" "based on Tcl "
+ TCL_PATCH_LEVEL " & Tk " TK_PATCH_LEVEL "\n\n" "Ray Johnson" "\n"
+ "Sun Microsystems Labs" "\n" "ray.johnson@eng.sun.com"},
+ { 11, 24, 111, 92}, Picture {enabled, 128}
+ }
+};
+
+data 'PICT' (128) {
+ $"13A4 0000 0000 0064 0044 0011 02FF 0C00"
+ $"FFFE 0000 0048 0000 0048 0000 0000 0000"
+ $"0064 0044 0000 0000 0001 000A 0000 0000"
+ $"0064 0044 0099 8044 0000 0000 0064 0044"
+ $"0000 0000 0000 0000 0048 0000 0048 0000"
+ $"0000 0008 0001 0008 0000 0000 0108 00D8"
+ $"0000 0000 0001 5A5A 8000 00FF 3736 FF00"
+ $"FF00 FF00 3535 FF00 FF00 CC00 3434 FF00"
+ $"FF00 9900 3333 FF00 FF00 6600 3736 FF00"
+ $"FF00 3300 3535 FF00 FF00 0000 3434 FF00"
+ $"CC00 FF00 3333 FF00 CC00 CC00 3736 FF00"
+ $"CC00 9900 3535 FF00 CC00 6600 FAFA FF00"
+ $"CC00 3300 3333 FF00 CC00 0000 3130 FF00"
+ $"9900 FF00 2F2F FF00 9900 CC00 FAFA FF00"
+ $"9900 9900 F9F9 FF00 9900 6600 3130 FF00"
+ $"9900 3300 2F2F FF00 9900 0000 2E2E FF00"
+ $"6600 FF00 F9F9 FF00 6600 CC00 3130 FF00"
+ $"6600 9900 2F2F FF00 6600 6600 2E2E FF00"
+ $"6600 3300 2D2D FF00 6600 0000 3130 FF00"
+ $"3300 FF00 2F2F FF00 3300 CC00 2E2E FF00"
+ $"3300 9900 2D2D FF00 3300 6600 3130 FF00"
+ $"3300 3300 2F2F FF00 3300 0000 2E2E FF00"
+ $"0000 FF00 2D2D FF00 0000 CC00 3130 FF00"
+ $"0000 9900 2F2F FF00 0000 6600 2E2E FF00"
+ $"0000 3300 2DF8 FF00 0000 0000 2B2A CC00"
+ $"FF00 FF00 2929 CC00 FF00 CC00 2828 CC00"
+ $"FF00 9900 27F8 CC00 FF00 6600 2B2A CC00"
+ $"FF00 3300 2929 CC00 FF00 0000 2828 CC00"
+ $"CC00 FF00 2727 CC00 CC00 CC00 2B2A CC00"
+ $"CC00 9900 2929 CC00 CC00 6600 2828 CC00"
+ $"CC00 3300 2727 CC00 CC00 0000 2B2A CC00"
+ $"9900 FF00 2929 CC00 9900 CC00 2828 CC00"
+ $"9900 9900 2727 CC00 9900 6600 DBDB CC00"
+ $"9900 3300 4747 CC00 9900 0000 4646 CC00"
+ $"6600 FF00 4545 CC00 6600 CC00 DBDB CC00"
+ $"6600 9900 4747 CC00 6600 6600 4646 CC00"
+ $"6600 3300 4545 CC00 6600 0000 DBDB CC00"
+ $"3300 FF00 4747 CC00 3300 CC00 4646 CC00"
+ $"3300 9900 4545 CC00 3300 6600 DBDB CC00"
+ $"3300 3300 4141 CC00 3300 0000 4040 CC00"
+ $"0000 FF00 3F3F CC00 0000 CC00 4342 CC00"
+ $"0000 9900 4141 CC00 0000 6600 4040 CC00"
+ $"0000 3300 3F3F CC00 0000 0000 4342 9900"
+ $"FF00 FF00 4141 9900 FF00 CC00 4040 9900"
+ $"FF00 9900 3F3F 9900 FF00 6600 4342 9900"
+ $"FF00 3300 4141 9900 FF00 0000 4040 9900"
+ $"CC00 FF00 3F3F 9900 CC00 CC00 4342 9900"
+ $"CC00 9900 4141 9900 CC00 6600 4040 9900"
+ $"CC00 3300 3F3F 9900 CC00 0000 4342 9900"
+ $"9900 FF00 4141 9900 9900 CC00 4040 9900"
+ $"9900 9900 3F3F 9900 9900 6600 3D3C 9900"
+ $"9900 3300 3B3B 9900 9900 0000 3A3A 9900"
+ $"6600 FF00 3939 9900 6600 CC00 3D3C 9900"
+ $"6600 9900 3B3B 9900 6600 6600 3A3A 9900"
+ $"6600 3300 3939 9900 6600 0000 3D3C 9900"
+ $"3300 FF00 3B3B 9900 3300 CC00 3A3A 9900"
+ $"3300 9900 3939 9900 3300 6600 3D3C 9900"
+ $"3300 3300 3B3B 9900 3300 0000 3A3A 9900"
+ $"0000 FF00 3939 9900 0000 CC00 3D3C 9900"
+ $"0000 9900 3B3B 9900 0000 6600 3A3A 9900"
+ $"0000 3300 3939 9900 0000 0000 3D3C 6600"
+ $"FF00 FF00 3B3B 6600 FF00 CC00 3A3A 6600"
+ $"FF00 9900 3939 6600 FF00 6600 3D3C 6600"
+ $"FF00 3300 3B3B 6600 FF00 0000 3A3A 6600"
+ $"CC00 FF00 3939 6600 CC00 CC00 3736 6600"
+ $"CC00 9900 3535 6600 CC00 6600 3434 6600"
+ $"CC00 3300 3333 6600 CC00 0000 3736 6600"
+ $"9900 FF00 3535 6600 9900 CC00 3434 6600"
+ $"9900 9900 3333 6600 9900 6600 3736 6600"
+ $"9900 3300 3535 6600 9900 0000 3434 6600"
+ $"6600 FF00 3333 6600 6600 CC00 3736 6600"
+ $"6600 9900 3535 6600 6600 6600 3434 6600"
+ $"6600 3300 3333 6600 6600 0000 3736 6600"
+ $"3300 FF00 3535 6600 3300 CC00 3434 6600"
+ $"3300 9900 3333 6600 3300 6600 3736 6600"
+ $"3300 3300 3535 6600 3300 0000 3434 6600"
+ $"0000 FF00 3333 6600 0000 CC00 3130 6600"
+ $"0000 9900 2F2F 6600 0000 6600 2E2E 6600"
+ $"0000 3300 F9F9 6600 0000 0000 3130 3300"
+ $"FF00 FF00 2F2F 3300 FF00 CC00 2E2E 3300"
+ $"FF00 9900 F9F9 3300 FF00 6600 3130 3300"
+ $"FF00 3300 2F2F 3300 FF00 0000 2E2E 3300"
+ $"CC00 FF00 2D2D 3300 CC00 CC00 3130 3300"
+ $"CC00 9900 2F2F 3300 CC00 6600 2E2E 3300"
+ $"CC00 3300 2D2D 3300 CC00 0000 3130 3300"
+ $"9900 FF00 2F2F 3300 9900 CC00 2E2E 3300"
+ $"9900 9900 2D2D 3300 9900 6600 3130 3300"
+ $"9900 3300 2F2F 3300 9900 0000 2E2E 3300"
+ $"6600 FF00 2DF8 3300 6600 CC00 2B2A 3300"
+ $"6600 9900 2929 3300 6600 6600 2828 3300"
+ $"6600 3300 27F8 3300 6600 0000 2B2A 3300"
+ $"3300 FF00 2929 3300 3300 CC00 2828 3300"
+ $"3300 9900 2727 3300 3300 6600 2B2A 3300"
+ $"3300 3300 2929 3300 3300 0000 2828 3300"
+ $"0000 FF00 2727 3300 0000 CC00 2B2A 3300"
+ $"0000 9900 2929 3300 0000 6600 2828 3300"
+ $"0000 3300 2727 3300 0000 0000 4948 0000"
+ $"FF00 FF00 4747 0000 FF00 CC00 4646 0000"
+ $"FF00 9900 4545 0000 FF00 6600 4948 0000"
+ $"FF00 3300 4747 0000 FF00 0000 4646 0000"
+ $"CC00 FF00 4545 0000 CC00 CC00 4948 0000"
+ $"CC00 9900 4747 0000 CC00 6600 4646 0000"
+ $"CC00 3300 4545 0000 CC00 0000 4342 0000"
+ $"9900 FF00 4141 0000 9900 CC00 4040 0000"
+ $"9900 9900 3F3F 0000 9900 6600 4342 0000"
+ $"9900 3300 4141 0000 9900 0000 4040 0000"
+ $"6600 FF00 3F3F 0000 6600 CC00 4342 0000"
+ $"6600 9900 4141 0000 6600 6600 4040 0000"
+ $"6600 3300 3F3F 0000 6600 0000 4342 0000"
+ $"3300 FF00 4141 0000 3300 CC00 4040 0000"
+ $"3300 9900 3F3F 0000 3300 6600 4342 0000"
+ $"3300 3300 4141 0000 3300 0000 4040 0000"
+ $"0000 FF00 3F3F 0000 0000 CC00 4342 0000"
+ $"0000 9900 4141 0000 0000 6600 4040 0000"
+ $"0000 3300 3F3F EE00 0000 0000 3D3C DD00"
+ $"0000 0000 3B3B BB00 0000 0000 3A3A AA00"
+ $"0000 0000 3939 8800 0000 0000 3D3C 7700"
+ $"0000 0000 3B3B 5500 0000 0000 3A3A 4400"
+ $"0000 0000 3939 2200 0000 0000 3D3C 1100"
+ $"0000 0000 3B3B 0000 EE00 0000 3A3A 0000"
+ $"DD00 0000 3939 0000 BB00 0000 3D3C 0000"
+ $"AA00 0000 3B3B 0000 8800 0000 3A3A 0000"
+ $"7700 0000 3939 0000 5500 0000 3D3C 0000"
+ $"4400 0000 3B3B 0000 2200 0000 3A3A 0000"
+ $"1100 0000 3939 0000 0000 EE00 3D3C 0000"
+ $"0000 DD00 3B3B 0000 0000 BB00 3A3A 0000"
+ $"0000 AA00 3939 0000 0000 8800 3D3C 0000"
+ $"0000 7700 3B3B 0000 0000 5500 3A3A 0000"
+ $"0000 4400 3939 0000 0000 2200 3736 0000"
+ $"0000 1100 3535 EE00 EE00 EE00 3434 DD00"
+ $"DD00 DD00 3333 BB00 BB00 BB00 3736 AA00"
+ $"AA00 AA00 3535 8800 8800 8800 3434 7700"
+ $"7700 7700 3333 5500 5500 5500 3736 4400"
+ $"4400 4400 3535 2200 2200 2200 3434 1100"
+ $"1100 1100 3333 0000 0000 0000 0000 0000"
+ $"0064 0044 0000 0000 0064 0044 0000 000A"
+ $"0000 0000 0064 0044 02BD 0013 E800 01F5"
+ $"F6FE 07FE 0E02 3232 33FD 3900 0EE6 001D"
+ $"FC00 01F5 F5FE 0700 08FE 0E02 3232 33FE"
+ $"3900 3AFC 40F2 4102 4033 07E9 0017 0100"
+ $"0EFC 40DC 4102 390E F5F5 0002 F5F5 F6FE"
+ $"0702 0E07 0016 0100 32D5 4104 4039 0E32"
+ $"33FD 3900 3AFC 40FC 4101 3200 0801 000E"
+ $"C141 010E 0008 0100 0EC1 4101 0800 0801"
+ $"000E C141 0107 0008 0100 0EC1 4101 0700"
+ $"0901 0007 C241 0240 F500 0E01 0007 E841"
+ $"0147 47DD 4102 4000 0012 0100 07F0 4100"
+ $"47FA 4101 3B3B DD41 0240 0000 1901 0007"
+ $"F141 0C47 3B0B 3B47 4141 4711 0505 3B47"
+ $"DF41 023A 0000 1701 00F6 F041 010B 0BFE"
+ $"4105 473B 0505 113B DE41 0239 0000 1A02"
+ $"00F5 40F3 410C 473B 053B 4741 4741 0B0B"
+ $"3B47 47DE 4102 3900 0018 0200 F540 F341"
+ $"0247 110B FE41 0447 1105 4147 DC41 0233"
+ $"0000 1B02 0000 40F3 4103 4711 1147 FE41"
+ $"0205 3547 F741 FD47 E941 0232 0000 1E02"
+ $"0000 40F2 4106 113B 4741 4735 0BF7 4106"
+ $"4741 390E 0E40 47EA 4102 0E00 0021 0200"
+ $"0040 F241 0711 3B47 4141 0B35 47F9 4102"
+ $"4740 07FE 0002 F640 47EB 4102 0E00 0023"
+ $"0200 0040 F341 0847 3541 4147 3B05 4147"
+ $"FA41 0947 3AF6 00F5 4F55 F50E 47EB 4102"
+ $"0700 0022 0200 003A F341 0147 3BFE 4101"
+ $"0B0B F941 0547 3AF5 0055 C8FE CE01 5640"
+ $"EB41 0207 0000 1F02 0000 39F0 4104 4741"
+ $"053B 47FB 4104 4740 F5F5 A4FC CE01 C85D"
+ $"EB41 02F6 0000 1F02 0000 39F0 4104 473B"
+ $"0541 47FC 4104 4740 07F6 C8FA CE00 64EC"
+ $"4103 40F5 0000 1C02 0000 39F0 4102 4711"
+ $"0BFA 4103 4708 2AC8 FACE 0164 D8EC 4100"
+ $"40FE 0025 0200 0039 EF41 020B 3B47 FC41"
+ $"0347 0FF5 A4FB CE02 C887 D8FC 41FE 47FC"
+ $"4100 47F9 4100 3AFE 0028 0200 0039 EF41"
+ $"020B 3B47 FD41 0347 3900 A4FA CE00 ABFA"
+ $"4109 3B11 3B41 4147 3B0B 3B47 FA41 0039"
+ $"FE00 2402 0000 33F1 4102 4741 0BFA 4101"
+ $"0779 F9CE 0064 FA41 0235 050B FD41 010B"
+ $"0BF9 4100 39FE 0028 0200 0032 F141 0247"
+ $"3B0B FC41 0247 39F6 F9CE 0187 D8FB 4103"
+ $"4741 050B FE41 0247 110B F941 0039 FE00"
+ $"2C02 0000 32F1 4102 473B 11FB 4101 0879"
+ $"FACE 05AA 4041 4147 47FE 410A 4741 0511"
+ $"4741 4147 3511 47FA 4100 32FE 002F 0200"
+ $"000E F141 0347 3B11 47FE 4103 4740 F6C8"
+ $"FACE 0564 D841 4039 39FE 4104 473B 053B"
+ $"47FE 4102 3541 47FA 4100 0EFE 0027 0200"
+ $"000E F141 0347 3B3B 47FE 4102 470F 79FA"
+ $"CE0C 8741 4032 F500 003A 4741 473B 05F2"
+ $"4100 0EFE 0027 0200 000E F141 0347 3B3B"
+ $"47FD 4101 0EA4 FACE 01AB AAFE C808 7900"
+ $"3947 4147 110B 47F3 4100 07FE 001C 0200"
+ $"000E EA41 0240 2BC8 F5CE 0881 0033 4741"
+ $"410B 3B47 F341 0007 FE00 1A02 0000 08EB"
+ $"4102 473A 55F4 CE06 5D00 3947 4741 0BF1"
+ $"4100 F6FE 001C 0200 0007 EB41 0247 3979"
+ $"F4CE 0739 0039 4747 3511 47F3 4101 40F5"
+ $"FE00 1C02 0000 07EB 4102 4739 A4F5 CE08"
+ $"AB0E 0040 4741 1141 47F3 4100 40FD 001B"
+ $"0200 0007 EB41 0247 39A4 F5CE 0787 0707"
+ $"4147 4111 47F2 4100 40FD 001B 0200 0007"
+ $"EB41 0247 39C8 F5CE 0763 F532 4747 3B3B"
+ $"47F2 4100 3AFD 001A 0300 00F6 40EC 4102"
+ $"4739 C8F5 CE05 39F5 4047 413B F041 0039"
+ $"FD00 1C03 0000 F540 EB41 0140 C8FD CE01"
+ $"C8A4 FCCE 03AB 080E 47ED 4100 39FD 001A"
+ $"FE00 0040 EB41 0040 FCCE 01A4 C8FC CE03"
+ $"FA07 4047 ED41 0032 FD00 1AFE 0000 40EA"
+ $"4100 AAFE CE02 87F9 C8FC CE02 560F 47EC"
+ $"4100 32FD 0019 FE00 0040 EA41 00AB FECE"
+ $"0264 56C8 FDCE 01C8 32EA 4100 0EFD 001B"
+ $"FE00 0040 ED41 030E 4047 87FE CE01 4055"
+ $"FCCE 01FA 40EA 4100 08FD 001A FE00 003A"
+ $"ED41 0807 0740 FBCE CEAB 3979 FDCE 00AB"
+ $"E841 0007 FD00 1CFE 0000 3AED 4108 0700"
+ $"F6A4 CECE 8733 79FD CE02 4147 47EA 4100"
+ $"07FD 001E FE00 0039 ED41 0807 2AA4 C8CE"
+ $"CE88 0E9D FECE 0364 1C39 39EB 4101 40F5"
+ $"FD00 1CFE 0000 39ED 4101 074F FDCE 0264"
+ $"F7A4 FECE 03AB 80F6 07EB 4100 40FC 001C"
+ $"FE00 0039 ED41 0108 79FE CE03 AB40 2BA4"
+ $"FCCE 02F7 0E47 EC41 0040 FC00 1CFE 0000"
+ $"39ED 4101 0879 FECE 03AB 40F6 C8FC CE02"
+ $"F615 47EC 4100 40FC 001E FE00 003A EE41"
+ $"0247 0E79 FECE 03AB 40F5 C8FD CE03 A4F5"
+ $"3A47 EC41 0040 FC00 1EFE 0000 3AEE 4102"
+ $"470E 56FE CE03 FB3A F6C8 FDCE 0280 F540"
+ $"EB41 0140 F5FD 001E FE00 0040 EE41 0947"
+ $"0F56 CECE C888 39F6 C8FD CE02 5601 40EB"
+ $"4101 40F5 FD00 1CFE 0000 40EE 4109 4739"
+ $"32CE CEC8 8839 2AC8 FDCE 0156 07E9 4100"
+ $"F6FD 001B FE00 0040 EE41 0847 3A32 CECE"
+ $"C864 152A FCCE 0132 07E9 4100 07FD 001A"
+ $"FE00 0040 ED41 0740 32AB CEC8 6439 4EFC"
+ $"CE01 3A07 E941 0007 FD00 1D03 0000 F540"
+ $"ED41 0740 0EAB CECE 640F 4EFD CE03 AB40"
+ $"0840 EA41 0007 FD00 1B03 0000 F540 EC41"
+ $"060F 81CE CE64 334E FDCE 02AB 400E E941"
+ $"000E FD00 1C02 0000 F6EC 4107 4715 FACE"
+ $"CE64 334E FDCE 0387 0F0E 47EA 4100 0EFD"
+ $"001C 0200 0007 EC41 0747 16F9 CEC8 6433"
+ $"4EFD CE03 6308 4047 EA41 000E FD00 1A02"
+ $"0000 07EB 4106 40F9 CEC8 6439 4EFD CE02"
+ $"3940 47E9 4100 32FD 001B 0200 0007 EA41"
+ $"0539 CECE 8839 F6FE CE04 AB41 4139 40EA"
+ $"4100 32FD 001C 0200 0007 EB41 0E47 3AC8"
+ $"CE88 39F6 C8CE CE64 15F6 F540 EA41 0033"
+ $"FD00 1A02 0000 07EA 410C 40A4 CE87 392A"
+ $"C8CE AB41 40F8 F6E9 4100 39FD 001B 0200"
+ $"000E EB41 0D47 41AB C887 39F5 C8CE ABAB"
+ $"CEA4 07E9 4100 39FD 001C 0200 000E ED41"
+ $"0947 3939 4787 C8AB 40F5 C8FD CE01 A40E"
+ $"E941 0039 FD00 1D02 0000 0EED 4109 473A"
+ $"0007 80CE AB40 F5C8 FDCE 0255 0E47 EA41"
+ $"0039 FD00 1B02 0000 0EEB 4107 0779 C8CE"
+ $"CE40 F6A4 FDCE 022B 3947 EA41 003A FD00"
+ $"1C02 0000 0EEC 4102 4739 79FE CE02 6407"
+ $"A4FE CE02 A407 40E9 4100 40FD 001A 0200"
+ $"0032 EA41 0632 A4CE CE88 0879 FECE 02F9"
+ $"0F47 E941 0040 FD00 1A02 0000 32EB 4107"
+ $"4740 F7C8 CE87 0E79 FECE 0132 40E8 4100"
+ $"40FD 0019 0200 0033 EA41 0B47 40F8 C8AB"
+ $"0E55 CECE 8015 47E8 4100 40FD 0017 0200"
+ $"0033 E941 0847 40F9 A439 4FCE CE5D E641"
+ $"0140 F5FE 0014 0200 0039 E841 0647 64FB"
+ $"392B C8AB E441 00F6 FE00 1102 0000 39E5"
+ $"4103 40F6 8764 E441 0007 FE00 1E02 0000"
+ $"39EB 4102 3A0E 0EFD 4102 0740 47F6 4104"
+ $"400F 0839 47F4 4100 07FE 0027 0200 0039"
+ $"FB41 0147 47F2 4102 0800 40FE 4102 0839"
+ $"47FC 4101 4747 FC41 0339 0039 47F4 4100"
+ $"07FE 0029 0200 0039 FB41 0140 39F3 4109"
+ $"470E F540 4141 470E 3347 FC41 0139 3AFD"
+ $"4104 4739 0039 47F4 4100 08FE 0036 0200"
+ $"003A FC41 0347 0E00 40FC 4102 4741 40FC"
+ $"4109 470E F540 4141 4733 0E47 FE41 0447"
+ $"4000 0E47 FE41 0447 3900 3941 FE40 F741"
+ $"000E FE00 3A02 0000 3AFD 410E 4740 0700"
+ $"0E40 4741 4147 390E 390E 40FE 4108 470E"
+ $"F540 4141 4739 0EFC 4103 0F00 0739 FE41"
+ $"0747 3900 3940 080F 39F7 4100 0EFE 0035"
+ $"0200 0040 FB41 020E 0040 FE41 0D47 4000"
+ $"3941 0032 4741 4147 0EF5 40FE 4101 4008"
+ $"FC41 023A 000E FD41 0547 3900 3939 33F5"
+ $"4100 0EFE 0039 0200 0040 FC41 0347 0E00"
+ $"40FE 4106 4732 0040 4139 40FE 4103 470E"
+ $"F540 FD41 0108 40FE 4104 4740 000E 47FE"
+ $"4106 4739 0007 F540 47F6 4100 32FE 003A"
+ $"0200 0040 FC41 0C47 0E00 4047 4141 470E"
+ $"0040 4747 FD41 0347 0EF5 40FE 410A 470E"
+ $"3947 4141 4740 000E 47FE 4107 4739 000E"
+ $"0007 4147 F741 0032 FE00 3802 0000 40FC"
+ $"4102 470E 00FD 4106 4739 003A 4740 39FE"
+ $"4102 470E F5FD 410A 4733 3347 4141 4740"
+ $"000E 47FE 4106 4739 0039 3900 0EF6 4100"
+ $"33FE 003A 0200 F540 FC41 0447 3200 0E39"
+ $"FD41 0B0E 0E40 333A 4741 413A 07F5 39FE"
+ $"4102 473A 0EFD 410F 40F5 0733 4041 4140"
+ $"0E00 0E40 0700 0E40 F841 0039 FE00 2902"
+ $"00F5 40FA 4101 3939 FB41 023A 3A40 FD41"
+ $"FD40 FD41 0240 0E40 FD41 0240 3940 FD41"
+ $"FA40 F741 0039 FE00 2A01 00F6 F941 0147"
+ $"47FB 4101 4747 FB41 0147 47FB 4101 3940"
+ $"FD41 0147 47FB 4100 47FE 4100 47F6 4100"
+ $"39FE 000D 0100 07E1 4100 40E4 4100 3AFE"
+ $"0009 0100 07C3 4100 3AFE 0009 0100 07C3"
+ $"4100 40FE 0009 0100 07C3 4100 40FE 0009"
+ $"0100 07C3 4100 40FE 000A 0100 0EC3 4103"
+ $"40F5 0000 0901 000E C241 02F6 0000 0901"
+ $"000E C241 0207 0000 0901 000E C241 0207"
+ $"0000 1101 000E ED41 FE40 003A F940 E241"
+ $"0207 0000 2B01 0032 F941 FE40 FE39 0632"
+ $"0E0E 0707 F6F5 F800 02F5 F5F6 FB07 FB0E"
+ $"0332 3233 33FB 3901 3A3A FB40 0207 0000"
+ $"0E0A 000E 3939 320E 0E07 07F6 F5C8 0002"
+ $"BD00 00FF"
+};
+
+/*
+ * Here is the custom file open dialog. This dialog is used instead of
+ * the default file dialog if the -filetypes flag is specified.
+ */
+
+resource 'DLOG' (130, purgeable) {
+ {0, 0, 195, 344}, dBoxProc, invisible, noGoAway, 0,
+ 130, "", noAutoCenter
+};
+
+resource 'DITL' (130, "File Open Box", purgeable) {
+ {
+ {135, 252, 155, 332}, Button {enabled, "Open"},
+ {104, 252, 124, 332}, Button {enabled, "Cancel"},
+ { 0, 0, 0, 0}, HelpItem {disabled, HMScanhdlg {130}},
+ { 8, 235, 24, 337}, UserItem {enabled},
+ { 32, 252, 52, 332}, Button {enabled, "Eject"},
+ { 60, 252, 80, 332}, Button {enabled, "Desktop"},
+ { 29, 12, 159, 230}, UserItem {enabled},
+ { 6, 12, 25, 230}, UserItem {enabled},
+ { 91, 251, 92, 333}, Picture {disabled, 11},
+ {168, 20, 187, 300}, Control {enabled, 131}
+ }
+};
+
+resource 'CNTL' (131, "File Types menu", purgeable) {
+ {168, 20, 187, 300},
+ popupTitleLeftJust,
+ visible,
+ 80,
+ 132,
+ popupMenuCDEFProc,
+ 0,
+ "File Type:"
+};
+
+
+resource 'MENU' (132, preload) {
+ 132,
+ textMenuProc,
+ 0xFFFF, enabled, "", {}
+};
diff --git a/mac/tkMacScale.c b/mac/tkMacScale.c
new file mode 100644
index 0000000..292a064
--- /dev/null
+++ b/mac/tkMacScale.c
@@ -0,0 +1,603 @@
+/*
+ * tkMacScale.c --
+ *
+ * This file implements the Macintosh specific portion of the
+ * scale widget.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacScale.c 1.3 96/10/17 13:16:18
+ */
+
+#include "tkScale.h"
+#include "tkInt.h"
+#include <Controls.h>
+#include "tkMacInt.h"
+
+/*
+ * Defines used in this file.
+ */
+#define slider 1110
+#define inSlider 1
+#define inInc 2
+#define inDecr 3
+
+/*
+ * Declaration of Macintosh specific scale structure.
+ */
+
+typedef struct MacScale {
+ TkScale info; /* Generic scale info. */
+ int flags; /* Flags. */
+ ControlRef scaleHandle; /* Handle to the Scale control struct. */
+} MacScale;
+
+/*
+ * Globals uses locally in this file.
+ */
+static ControlActionUPP scaleActionProc = NULL; /* Pointer to func. */
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static void MacScaleEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static pascal void ScaleActionProc _ANSI_ARGS_((ControlRef theControl,
+ ControlPartCode partCode));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateScale --
+ *
+ * Allocate a new TkScale structure.
+ *
+ * Results:
+ * Returns a newly allocated TkScale structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkScale *
+TkpCreateScale(tkwin)
+ Tk_Window tkwin;
+{
+ MacScale *macScalePtr;;
+
+ macScalePtr = (MacScale *) ckalloc(sizeof(MacScale));
+ macScalePtr->scaleHandle = NULL;
+ if (scaleActionProc == NULL) {
+ scaleActionProc = NewControlActionProc(ScaleActionProc);
+ }
+
+ Tk_CreateEventHandler(tkwin, ButtonPressMask,
+ MacScaleEventProc, (ClientData) macScalePtr);
+
+ return (TkScale *) macScalePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyScale --
+ *
+ * Free Macintosh specific resources.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The slider control is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyScale(scalePtr)
+ TkScale *scalePtr;
+{
+ MacScale *macScalePtr = (MacScale *) scalePtr;
+
+ /*
+ * Free Macintosh control.
+ */
+ if (macScalePtr->scaleHandle != NULL) {
+ DisposeControl(macScalePtr->scaleHandle);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDisplayScale --
+ *
+ * This procedure is invoked as an idle handler to redisplay
+ * the contents of a scale widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The scale gets redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDisplayScale(clientData)
+ ClientData clientData; /* Widget record for scale. */
+{
+ TkScale *scalePtr = (TkScale *) clientData;
+ Tk_Window tkwin = scalePtr->tkwin;
+ Tcl_Interp *interp = scalePtr->interp;
+ int result;
+ char string[PRINT_CHARS];
+ MacScale *macScalePtr = (MacScale *) clientData;
+ Rect r;
+ WindowRef windowRef;
+ GWorldPtr destPort;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ MacDrawable *macDraw;
+
+ if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
+ goto done;
+ }
+
+ /*
+ * Invoke the scale's command if needed.
+ */
+
+ Tcl_Preserve((ClientData) scalePtr);
+ if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
+ Tcl_Preserve((ClientData) interp);
+ sprintf(string, scalePtr->format, scalePtr->value);
+ result = Tcl_VarEval(interp, scalePtr->command, " ", string,
+ (char *) NULL);
+ if (result != TCL_OK) {
+ Tcl_AddErrorInfo(interp, "\n (command executed by scale)");
+ Tcl_BackgroundError(interp);
+ }
+ Tcl_Release((ClientData) interp);
+ }
+ scalePtr->flags &= ~INVOKE_COMMAND;
+ if (scalePtr->tkwin == NULL) {
+ Tcl_Release((ClientData) scalePtr);
+ return;
+ }
+ Tcl_Release((ClientData) scalePtr);
+
+ /*
+ * Now handle the part of redisplay that is the same for
+ * horizontal and vertical scales: border and traversal
+ * highlight.
+ */
+
+ if (scalePtr->highlightWidth != 0) {
+ GC gc;
+
+ if (scalePtr->flags & GOT_FOCUS) {
+ gc = Tk_GCForColor(scalePtr->highlightColorPtr, Tk_WindowId(tkwin));
+ } else {
+ gc = Tk_GCForColor(scalePtr->highlightBgColorPtr, Tk_WindowId(tkwin));
+ }
+ Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, Tk_WindowId(tkwin));
+ }
+ Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scalePtr->bgBorder,
+ scalePtr->highlightWidth, scalePtr->highlightWidth,
+ Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
+ Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
+ scalePtr->borderWidth, scalePtr->relief);
+
+ /*
+ * Set up port for drawing Macintosh control.
+ */
+ macDraw = (MacDrawable *) Tk_WindowId(tkwin);
+ destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+ TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
+
+ /*
+ * Create Macintosh control.
+ */
+ if (macScalePtr->scaleHandle == NULL) {
+ r.left = r.top = 0;
+ r.right = r.bottom = 1;
+ /* TODO: initial value. */
+ /* 16*slider+4 */
+ macScalePtr->scaleHandle = NewControl((WindowRef) destPort,
+ &r, "\p", false, (short) 35, 0, 1000,
+ 16*slider, (SInt32) macScalePtr);
+
+ /*
+ * If we are foremost than make us active.
+ */
+ if ((WindowPtr) destPort == FrontWindow()) {
+ macScalePtr->flags |= ACTIVE;
+ }
+ }
+ windowRef = (**macScalePtr->scaleHandle).contrlOwner;
+
+ /*
+ * We can't use the Macintosh commands SizeControl and MoveControl as these
+ * calls will also cause a redraw which in our case will also cause
+ * flicker. To avoid this we adjust the control record directly. The
+ * Draw1Control command appears to just draw where ever the control says to
+ * draw so this seems right.
+ *
+ * NOTE: changing the control record directly may not work when
+ * Apple releases the Copland version of the MacOS in late 1996.
+ */
+
+ (**macScalePtr->scaleHandle).contrlRect.left = macDraw->xOff + scalePtr->inset;
+ (**macScalePtr->scaleHandle).contrlRect.top = macDraw->yOff + scalePtr->inset;
+ (**macScalePtr->scaleHandle).contrlRect.right = macDraw->xOff + Tk_Width(tkwin)
+ - scalePtr->inset;
+ (**macScalePtr->scaleHandle).contrlRect.bottom = macDraw->yOff +
+ Tk_Height(tkwin) - scalePtr->inset;
+
+ /*
+ * Set the thumb and resolution etc.
+ */
+ (**macScalePtr->scaleHandle).contrlMin = (SInt16) scalePtr->toValue;
+ (**macScalePtr->scaleHandle).contrlMax = (SInt16) scalePtr->fromValue;
+ (**macScalePtr->scaleHandle).contrlValue = (SInt16) scalePtr->value;
+
+ /*
+ * Finally draw the control.
+ */
+ (**macScalePtr->scaleHandle).contrlVis = 255;
+ (**macScalePtr->scaleHandle).contrlHilite = 0;
+ Draw1Control(macScalePtr->scaleHandle);
+
+ SetGWorld(saveWorld, saveDevice);
+
+ done:
+ scalePtr->flags &= ~REDRAW_ALL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpScaleElement --
+ *
+ * Determine which part of a scale widget lies under a given
+ * point.
+ *
+ * Results:
+ * The return value is either TROUGH1, SLIDER, TROUGH2, or
+ * OTHER, depending on which of the scale's active elements
+ * (if any) is under the point at (x,y).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpScaleElement(scalePtr, x, y)
+ TkScale *scalePtr; /* Widget record for scale. */
+ int x, y; /* Coordinates within scalePtr's window. */
+{
+ MacScale *macScalePtr = (MacScale *) scalePtr;
+ ControlPartCode part;
+ Point where;
+ Rect bounds;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(Tk_WindowId(scalePtr->tkwin));
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+
+ /*
+ * All of the calculations in this procedure mirror those in
+ * DisplayScrollbar. Be sure to keep the two consistent.
+ */
+
+ TkMacWinBounds((TkWindow *) scalePtr->tkwin, &bounds);
+ where.h = x + bounds.left;
+ where.v = y + bounds.top;
+ part = TestControl(macScalePtr->scaleHandle, where);
+
+ SetGWorld(saveWorld, saveDevice);
+
+ switch (part) {
+ case inSlider:
+ return SLIDER;
+ case inInc:
+ if (scalePtr->vertical) {
+ return TROUGH1;
+ } else {
+ return TROUGH2;
+ }
+ case inDecr:
+ if (scalePtr->vertical) {
+ return TROUGH2;
+ } else {
+ return TROUGH1;
+ }
+ default:
+ return OTHER;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpSetScaleValue --
+ *
+ * This procedure changes the value of a scale and invokes
+ * a Tcl command to reflect the current position of a scale
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Tcl command is invoked, and an additional error-processing
+ * command may also be invoked. The scale's slider is redrawn.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpSetScaleValue(scalePtr, value, setVar, invokeCommand)
+ register TkScale *scalePtr; /* Info about widget. */
+ double value; /* New value for scale. Gets adjusted
+ * if it's off the scale. */
+ int setVar; /* Non-zero means reflect new value through
+ * to associated variable, if any. */
+ int invokeCommand; /* Non-zero means invoked -command option
+ * to notify of new value, 0 means don't. */
+{
+ char string[PRINT_CHARS];
+
+ value = TkRoundToResolution(scalePtr, value);
+ if ((value < scalePtr->fromValue)
+ ^ (scalePtr->toValue < scalePtr->fromValue)) {
+ value = scalePtr->fromValue;
+ }
+ if ((value > scalePtr->toValue)
+ ^ (scalePtr->toValue < scalePtr->fromValue)) {
+ value = scalePtr->toValue;
+ }
+ if (scalePtr->flags & NEVER_SET) {
+ scalePtr->flags &= ~NEVER_SET;
+ } else if (scalePtr->value == value) {
+ return;
+ }
+ scalePtr->value = value;
+ if (invokeCommand) {
+ scalePtr->flags |= INVOKE_COMMAND;
+ }
+ TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
+
+ if (setVar && (scalePtr->varName != NULL)) {
+ sprintf(string, scalePtr->format, scalePtr->value);
+ scalePtr->flags |= SETTING_VAR;
+ Tcl_SetVar(scalePtr->interp, scalePtr->varName, string,
+ TCL_GLOBAL_ONLY);
+ scalePtr->flags &= ~SETTING_VAR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpPixelToValue --
+ *
+ * Given a pixel within a scale window, return the scale
+ * reading corresponding to that pixel.
+ *
+ * Results:
+ * A double-precision scale reading. If the value is outside
+ * the legal range for the scale then it's rounded to the nearest
+ * end of the scale.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double
+TkpPixelToValue(scalePtr, x, y)
+ register TkScale *scalePtr; /* Information about widget. */
+ int x, y; /* Coordinates of point within
+ * window. */
+{
+ double value, pixelRange;
+
+ if (scalePtr->vertical) {
+ pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength
+ - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ value = y;
+ } else {
+ pixelRange = Tk_Width(scalePtr->tkwin) - scalePtr->sliderLength
+ - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ value = x;
+ }
+
+ if (pixelRange <= 0) {
+ /*
+ * Not enough room for the slider to actually slide: just return
+ * the scale's current value.
+ */
+
+ return scalePtr->value;
+ }
+ value -= scalePtr->sliderLength/2 + scalePtr->inset
+ + scalePtr->borderWidth;
+ value /= pixelRange;
+ if (value < 0) {
+ value = 0;
+ }
+ if (value > 1) {
+ value = 1;
+ }
+ value = scalePtr->fromValue +
+ value * (scalePtr->toValue - scalePtr->fromValue);
+ return TkRoundToResolution(scalePtr, value);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpValueToPixel --
+ *
+ * Given a reading of the scale, return the x-coordinate or
+ * y-coordinate corresponding to that reading, depending on
+ * whether the scale is vertical or horizontal, respectively.
+ *
+ * Results:
+ * An integer value giving the pixel location corresponding
+ * to reading. The value is restricted to lie within the
+ * defined range for the scale.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpValueToPixel(scalePtr, value)
+ register TkScale *scalePtr; /* Information about widget. */
+ double value; /* Reading of the widget. */
+{
+ int y, pixelRange;
+ double valueRange;
+
+ valueRange = scalePtr->toValue - scalePtr->fromValue;
+ pixelRange = (scalePtr->vertical ? Tk_Height(scalePtr->tkwin)
+ : Tk_Width(scalePtr->tkwin)) - scalePtr->sliderLength
+ - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ if (valueRange == 0) {
+ y = 0;
+ } else {
+ y = (int) ((value - scalePtr->fromValue) * pixelRange
+ / valueRange + 0.5);
+ if (y < 0) {
+ y = 0;
+ } else if (y > pixelRange) {
+ y = pixelRange;
+ }
+ }
+ y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth;
+ return y;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * MacScaleEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for
+ * ButtonPress events on scales.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get
+ * cleaned up. When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+MacScaleEventProc(clientData, eventPtr)
+ ClientData clientData; /* Information about window. */
+ XEvent *eventPtr; /* Information about event. */
+{
+ MacScale *macScalePtr = (MacScale *) clientData;
+ Point where;
+ Rect bounds;
+ int part, x, y, dummy;
+ unsigned int state;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ Window dummyWin;
+
+ /*
+ * To call Macintosh control routines we must have the port
+ * set to the window containing the control. We will then test
+ * which part of the control was hit and act accordingly.
+ */
+ destPort = TkMacGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin));
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+ TkMacSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin));
+
+ TkMacWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds);
+ where.h = eventPtr->xbutton.x + bounds.left;
+ where.v = eventPtr->xbutton.y + bounds.top;
+ part = TestControl(macScalePtr->scaleHandle, where);
+ if (part == 0) {
+ return;
+ }
+
+ part = TrackControl(macScalePtr->scaleHandle, where, scaleActionProc);
+
+ /*
+ * Update the value for the widget.
+ */
+ macScalePtr->info.value = (**macScalePtr->scaleHandle).contrlValue;
+ /* TkpSetScaleValue(&macScalePtr->info, macScalePtr->info.value, 1, 0); */
+
+ /*
+ * The TrackControl call will "eat" the ButtonUp event. We now
+ * generate a ButtonUp event so Tk will unset implicit grabs etc.
+ */
+ GetMouse(&where);
+ XQueryPointer(NULL, None, &dummyWin, &dummyWin, &x,
+ &y, &dummy, &dummy, &state);
+ TkGenerateButtonEvent(x, y, Tk_WindowId(macScalePtr->info.tkwin), state);
+
+ SetGWorld(saveWorld, saveDevice);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleActionProc --
+ *
+ * Callback procedure used by the Macintosh toolbox call
+ * TrackControl. This call will update the display while
+ * the scrollbar is being manipulated by the user.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May change the display.
+ *
+ *--------------------------------------------------------------
+ */
+
+static pascal void
+ScaleActionProc(ControlRef theControl, ControlPartCode partCode)
+ /* ControlRef theControl; /* Handle to scrollbat control */
+ /* ControlPartCode partCode; /* Part of scrollbar that was "hit" */
+{
+ register int value;
+ register TkScale *scalePtr = (TkScale *) GetCRefCon(theControl);
+
+ value = (**theControl).contrlValue;
+ TkpSetScaleValue(scalePtr, value, 1, 1);
+ Tcl_Preserve((ClientData) scalePtr);
+ Tcl_DoOneEvent(TCL_IDLE_EVENTS);
+ Tcl_Release((ClientData) scalePtr);
+}
+
diff --git a/mac/tkMacScrlbr.c b/mac/tkMacScrlbr.c
new file mode 100644
index 0000000..c76daec
--- /dev/null
+++ b/mac/tkMacScrlbr.c
@@ -0,0 +1,1057 @@
+/*
+ * tkMacScrollbar.c --
+ *
+ * This file implements the Macintosh specific portion of the scrollbar
+ * widget. The Macintosh scrollbar may also draw a windows grow
+ * region under certain cases.
+ *
+ * Copyright (c) 1996 by Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacScrlbr.c 1.9 96/12/10 20:04:39
+ */
+
+#include "tkScrollbar.h"
+#include "tkMacInt.h"
+#include <Controls.h>
+
+/*
+ * The following definitions should really be in MacOS
+ * header files. They are included here as this is the only
+ * file that needs the declarations.
+ */
+typedef pascal void (*ThumbActionFunc)(void);
+
+#if GENERATINGCFM
+typedef UniversalProcPtr ThumbActionUPP;
+#else
+typedef ThumbActionFunc ThumbActionUPP;
+#endif
+
+enum {
+ uppThumbActionProcInfo = kPascalStackBased
+};
+
+#if GENERATINGCFM
+#define NewThumbActionProc(userRoutine) \
+ (ThumbActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppThumbActionProcInfo, GetCurrentArchitecture())
+#else
+#define NewThumbActionProc(userRoutine) \
+ ((ThumbActionUPP) (userRoutine))
+#endif
+
+/*
+ * Minimum slider length, in pixels (designed to make sure that the slider
+ * is always easy to grab with the mouse).
+ */
+
+#define MIN_SLIDER_LENGTH 5
+
+/*
+ * Declaration of Windows specific scrollbar structure.
+ */
+
+typedef struct MacScrollbar {
+ TkScrollbar info; /* Generic scrollbar info. */
+ ControlRef sbHandle; /* Handle to the Scrollbar control struct. */
+ int macFlags; /* Various flags; see below. */
+} MacScrollbar;
+
+/*
+ * Flag bits for scrollbars on the Mac:
+ *
+ * ALREADY_DEAD: Non-zero means this scrollbar has been
+ * destroyed, but has not been cleaned up.
+ * IN_MODAL_LOOP: Non-zero means this scrollbar is in the middle
+ * of a modal loop.
+ * ACTIVE: Non-zero means this window is currently
+ * active (in the foreground).
+ * FLUSH_TOP: Flush with top of Mac window.
+ * FLUSH_BOTTOM: Flush with bottom of Mac window.
+ * FLUSH_RIGHT: Flush with right of Mac window.
+ * FLUSH_LEFT: Flush with left of Mac window.
+ * SCROLLBAR_GROW: Non-zero means this window draws the grow
+ * region for the toplevel window.
+ * AUTO_ADJUST: Non-zero means we automatically adjust
+ * the size of the widget to align correctly
+ * along a Mac window.
+ * DRAW_GROW: Non-zero means we draw the grow region.
+ */
+
+#define ALREADY_DEAD 1
+#define IN_MODAL_LOOP 2
+#define ACTIVE 4
+#define FLUSH_TOP 8
+#define FLUSH_BOTTOM 16
+#define FLUSH_RIGHT 32
+#define FLUSH_LEFT 64
+#define SCROLLBAR_GROW 128
+#define AUTO_ADJUST 256
+#define DRAW_GROW 512
+
+/*
+ * Globals uses locally in this file.
+ */
+static ControlActionUPP scrollActionProc = NULL; /* Pointer to func. */
+static ThumbActionUPP thumbActionProc = NULL; /* Pointer to func. */
+static TkScrollbar *activeScrollPtr = NULL; /* Non-null when in thumb */
+ /* proc. */
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static pascal void ScrollbarActionProc _ANSI_ARGS_((ControlRef theControl,
+ ControlPartCode partCode));
+static int ScrollbarBindProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, XEvent *eventPtr,
+ Tk_Window tkwin, KeySym keySym));
+static void ScrollbarEventProc _ANSI_ARGS_((
+ ClientData clientData, XEvent *eventPtr));
+static pascal void ThumbActionProc _ANSI_ARGS_((void));
+static void UpdateControlValues _ANSI_ARGS_((MacScrollbar *macScrollPtr));
+
+/*
+ * The class procedure table for the scrollbar widget.
+ */
+
+TkClassProcs tkpScrollbarProcs = {
+ NULL, /* createProc. */
+ NULL, /* geometryProc. */
+ NULL /* modalProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCreateScrollbar --
+ *
+ * Allocate a new TkScrollbar structure.
+ *
+ * Results:
+ * Returns a newly allocated TkScrollbar structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkScrollbar *
+TkpCreateScrollbar(
+ Tk_Window tkwin) /* New Tk Window. */
+{
+ MacScrollbar * macScrollPtr;
+ TkWindow *winPtr = (TkWindow *)tkwin;
+
+ if (scrollActionProc == NULL) {
+ scrollActionProc = NewControlActionProc(ScrollbarActionProc);
+ thumbActionProc = NewThumbActionProc(ThumbActionProc);
+ }
+
+ macScrollPtr = (MacScrollbar *) ckalloc(sizeof(MacScrollbar));
+ macScrollPtr->sbHandle = NULL;
+ macScrollPtr->macFlags = 0;
+
+ Tk_CreateEventHandler(tkwin, ActivateMask|ExposureMask|
+ StructureNotifyMask|FocusChangeMask,
+ ScrollbarEventProc, (ClientData) macScrollPtr);
+
+ if (!Tcl_GetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL)) {
+ Tcl_SetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL,
+ (ClientData)1);
+ TkCreateBindingProcedure(winPtr->mainPtr->interp,
+ winPtr->mainPtr->bindingTable,
+ (ClientData)Tk_GetUid("Scrollbar"), "<ButtonPress>",
+ ScrollbarBindProc, NULL, NULL);
+ }
+
+ return (TkScrollbar *) macScrollPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpDisplayScrollbar --
+ *
+ * This procedure redraws the contents of a scrollbar window.
+ * It is invoked as a do-when-idle handler, so it only runs
+ * when there's nothing else for the application to do.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information appears on the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpDisplayScrollbar(
+ ClientData clientData) /* Information about window. */
+{
+ register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
+ register MacScrollbar *macScrollPtr = (MacScrollbar *) clientData;
+ register Tk_Window tkwin = scrollPtr->tkwin;
+
+ MacDrawable *macDraw;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ WindowRef windowRef;
+
+ if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ goto done;
+ }
+
+ /*
+ * Draw the focus or any 3D relief we may have.
+ */
+ if (scrollPtr->highlightWidth != 0) {
+ GC gc;
+
+ if (scrollPtr->flags & GOT_FOCUS) {
+ gc = Tk_GCForColor(scrollPtr->highlightColorPtr,
+ Tk_WindowId(tkwin));
+ } else {
+ gc = Tk_GCForColor(scrollPtr->highlightBgColorPtr,
+ Tk_WindowId(tkwin));
+ }
+ Tk_DrawFocusHighlight(tkwin, gc, scrollPtr->highlightWidth,
+ Tk_WindowId(tkwin));
+ }
+ Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scrollPtr->bgBorder,
+ scrollPtr->highlightWidth, scrollPtr->highlightWidth,
+ Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
+ Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
+ scrollPtr->borderWidth, scrollPtr->relief);
+
+ /*
+ * Set up port for drawing Macintosh control.
+ */
+ macDraw = (MacDrawable *) Tk_WindowId(tkwin);
+ destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+ TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
+
+ if (macScrollPtr->sbHandle == NULL) {
+ Rect r;
+
+ r.left = r.top = 0;
+ r.right = r.bottom = 1;
+ macScrollPtr->sbHandle = NewControl((WindowRef) destPort, &r, "\p",
+ false, (short) 500, 0, 1000,
+ scrollBarProc, (SInt32) scrollPtr);
+
+ /*
+ * If we are foremost than make us active.
+ */
+ if ((WindowPtr) destPort == FrontWindow()) {
+ macScrollPtr->macFlags |= ACTIVE;
+ }
+ }
+
+ /*
+ * Update the control values before we draw.
+ */
+ windowRef = (**macScrollPtr->sbHandle).contrlOwner;
+ UpdateControlValues(macScrollPtr);
+
+ if (macScrollPtr->macFlags & ACTIVE) {
+ Draw1Control(macScrollPtr->sbHandle);
+ if (macScrollPtr->macFlags & DRAW_GROW) {
+ DrawGrowIcon(windowRef);
+ }
+ } else {
+ (**macScrollPtr->sbHandle).contrlHilite = 255;
+ Draw1Control(macScrollPtr->sbHandle);
+ if (macScrollPtr->macFlags & DRAW_GROW) {
+ DrawGrowIcon(windowRef);
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), scrollPtr->bgBorder,
+ Tk_Width(tkwin) - 13, Tk_Height(tkwin) - 13,
+ Tk_Width(tkwin), Tk_Height(tkwin),
+ 0, TK_RELIEF_FLAT);
+ }
+ }
+
+ SetGWorld(saveWorld, saveDevice);
+
+ done:
+ scrollPtr->flags &= ~REDRAW_PENDING;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpConfigureScrollbar --
+ *
+ * This procedure is called after the generic code has finished
+ * processing configuration options, in order to configure
+ * platform specific options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpConfigureScrollbar(scrollPtr)
+ register TkScrollbar *scrollPtr; /* Information about widget; may or
+ * may not already have values for
+ * some fields. */
+{
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpComputeScrollbarGeometry --
+ *
+ * After changes in a scrollbar's size or configuration, this
+ * procedure recomputes various geometry information used in
+ * displaying the scrollbar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The scrollbar will be displayed differently.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpComputeScrollbarGeometry(
+ register TkScrollbar *scrollPtr) /* Scrollbar whose geometry may
+ * have changed. */
+{
+ MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
+ int width, fieldLength, adjust = 0;
+
+ if (scrollPtr->highlightWidth < 0) {
+ scrollPtr->highlightWidth = 0;
+ }
+ scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
+ width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin)
+ : Tk_Height(scrollPtr->tkwin);
+ scrollPtr->arrowLength = width - 2*scrollPtr->inset + 1;
+ fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
+ : Tk_Width(scrollPtr->tkwin))
+ - 2*(scrollPtr->arrowLength + scrollPtr->inset);
+ if (fieldLength < 0) {
+ fieldLength = 0;
+ }
+ scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;
+ scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;
+
+ /*
+ * Adjust the slider so that some piece of it is always
+ * displayed in the scrollbar and so that it has at least
+ * a minimal width (so it can be grabbed with the mouse).
+ */
+
+ if (scrollPtr->sliderFirst > (fieldLength - 2*scrollPtr->borderWidth)) {
+ scrollPtr->sliderFirst = fieldLength - 2*scrollPtr->borderWidth;
+ }
+ if (scrollPtr->sliderFirst < 0) {
+ scrollPtr->sliderFirst = 0;
+ }
+ if (scrollPtr->sliderLast < (scrollPtr->sliderFirst
+ + MIN_SLIDER_LENGTH)) {
+ scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
+ }
+ if (scrollPtr->sliderLast > fieldLength) {
+ scrollPtr->sliderLast = fieldLength;
+ }
+ scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset;
+ scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset;
+
+ /*
+ * Register the desired geometry for the window (leave enough space
+ * for the two arrows plus a minimum-size slider, plus border around
+ * the whole window, if any). Then arrange for the window to be
+ * redisplayed.
+ */
+
+ if (scrollPtr->vertical) {
+ if ((macScrollPtr->macFlags & AUTO_ADJUST) &&
+ (macScrollPtr->macFlags & (FLUSH_RIGHT|FLUSH_LEFT))) {
+ adjust--;
+ }
+ Tk_GeometryRequest(scrollPtr->tkwin,
+ scrollPtr->width + 2*scrollPtr->inset + adjust,
+ 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
+ + scrollPtr->inset));
+ } else {
+ if ((macScrollPtr->macFlags & AUTO_ADJUST) &&
+ (macScrollPtr->macFlags & (FLUSH_TOP|FLUSH_BOTTOM))) {
+ adjust--;
+ }
+ Tk_GeometryRequest(scrollPtr->tkwin,
+ 2*(scrollPtr->arrowLength + scrollPtr->borderWidth
+ + scrollPtr->inset), scrollPtr->width + 2*scrollPtr->inset + adjust);
+ }
+ Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDestroyScrollbar --
+ *
+ * Free data structures associated with the scrollbar control.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDestroyScrollbar(
+ TkScrollbar *scrollPtr) /* Scrollbar to destroy. */
+{
+ MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr;
+
+ if (macScrollPtr->sbHandle != NULL) {
+ if (!(macScrollPtr->macFlags & IN_MODAL_LOOP)) {
+ DisposeControl(macScrollPtr->sbHandle);
+ macScrollPtr->sbHandle = NULL;
+ }
+ }
+ macScrollPtr->macFlags |= ALREADY_DEAD;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpScrollbarPosition --
+ *
+ * Determine the scrollbar element corresponding to a
+ * given position.
+ *
+ * Results:
+ * One of TOP_ARROW, TOP_GAP, etc., indicating which element
+ * of the scrollbar covers the position given by (x, y). If
+ * (x,y) is outside the scrollbar entirely, then OUTSIDE is
+ * returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkpScrollbarPosition(
+ TkScrollbar *scrollPtr, /* Scrollbar widget record. */
+ int x, int y) /* Coordinates within scrollPtr's
+ * window. */
+{
+ MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
+ GWorldPtr destPort;
+ int length, width, tmp, inactive = false;
+ ControlPartCode part;
+ Point where;
+ Rect bounds;
+
+ if (scrollPtr->vertical) {
+ length = Tk_Height(scrollPtr->tkwin);
+ width = Tk_Width(scrollPtr->tkwin);
+ } else {
+ tmp = x;
+ x = y;
+ y = tmp;
+ length = Tk_Width(scrollPtr->tkwin);
+ width = Tk_Height(scrollPtr->tkwin);
+ }
+
+ if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset))
+ || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) {
+ return OUTSIDE;
+ }
+
+ /*
+ * All of the calculations in this procedure mirror those in
+ * DisplayScrollbar. Be sure to keep the two consistent. On the
+ * Macintosh we use the OS call TestControl to do this mapping.
+ * For TestControl to work, the scrollbar must be active and must
+ * be in the current port.
+ */
+
+ destPort = TkMacGetDrawablePort(Tk_WindowId(scrollPtr->tkwin));
+ SetGWorld(destPort, NULL);
+ UpdateControlValues(macScrollPtr);
+ if ((**macScrollPtr->sbHandle).contrlHilite == 255) {
+ inactive = true;
+ (**macScrollPtr->sbHandle).contrlHilite = 0;
+ }
+
+ TkMacWinBounds((TkWindow *) scrollPtr->tkwin, &bounds);
+ where.h = x + bounds.left;
+ where.v = y + bounds.top;
+ part = TestControl(((MacScrollbar *) scrollPtr)->sbHandle, where);
+ if (inactive) {
+ (**macScrollPtr->sbHandle).contrlHilite = 255;
+ }
+ switch (part) {
+ case inUpButton:
+ return TOP_ARROW;
+ case inPageUp:
+ return TOP_GAP;
+ case inThumb:
+ return SLIDER;
+ case inPageDown:
+ return BOTTOM_GAP;
+ case inDownButton:
+ return BOTTOM_ARROW;
+ default:
+ return OUTSIDE;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ThumbActionProc --
+ *
+ * Callback procedure used by the Macintosh toolbox call
+ * TrackControl. This call is used to track the thumb of
+ * the scrollbar. Unlike the ScrollbarActionProc function
+ * this function is called once and basically takes over
+ * tracking the scrollbar from the control. This is done
+ * to avoid conflicts with what the control plans to draw.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May change the display.
+ *
+ *--------------------------------------------------------------
+ */
+
+static pascal void
+ThumbActionProc()
+{
+ register TkScrollbar *scrollPtr = activeScrollPtr;
+ register MacScrollbar *macScrollPtr = (MacScrollbar *) activeScrollPtr;
+ Tcl_DString cmdString;
+ Rect nullRect = {0,0,0,0};
+ int origValue, trackBarPin;
+ double thumbWidth, newFirstFraction, trackBarSize;
+ char vauleString[40];
+ Point currentPoint = { 0, 0 };
+ Point lastPoint = { 0, 0 };
+ Rect trackRect;
+ Tcl_Interp *interp;
+
+ if (scrollPtr == NULL) {
+ return;
+ }
+
+ Tcl_DStringInit(&cmdString);
+
+ /*
+ * First compute values that will remain constant during the tracking
+ * of the thumb. The variable trackBarSize is the length of the scrollbar
+ * minus the 2 arrows and half the width of the thumb on both sides
+ * (3 * arrowLength). The variable trackBarPin is the lower starting point
+ * of the drag region.
+ *
+ * Note: the arrowLength is equal to the thumb width of a Mac scrollbar.
+ */
+ origValue = GetControlValue(macScrollPtr->sbHandle);
+ trackRect = (**macScrollPtr->sbHandle).contrlRect;
+ if (scrollPtr->vertical == true) {
+ trackBarSize = (double) (trackRect.bottom - trackRect.top
+ - (scrollPtr->arrowLength * 3));
+ trackBarPin = trackRect.top + scrollPtr->arrowLength
+ + (scrollPtr->arrowLength / 2);
+ InsetRect(&trackRect, -25, -113);
+
+ } else {
+ trackBarSize = (double) (trackRect.right - trackRect.left
+ - (scrollPtr->arrowLength * 3));
+ trackBarPin = trackRect.left + scrollPtr->arrowLength
+ + (scrollPtr->arrowLength / 2);
+ InsetRect(&trackRect, -113, -25);
+ }
+
+ /*
+ * Track the mouse while the button is held down. If the mouse is moved,
+ * we calculate the value that should be passed to the "command" part of
+ * the scrollbar.
+ */
+ while (StillDown()) {
+ GetMouse(&currentPoint);
+ if (EqualPt(currentPoint, lastPoint)) {
+ continue;
+ }
+ lastPoint = currentPoint;
+
+ /*
+ * Calculating this value is a little tricky. We need to calculate a
+ * value for where the thumb would be in a Motif widget (variable
+ * thumb). This value is what the "command" expects and is what will
+ * be resent to the scrollbar to update its value.
+ */
+ thumbWidth = scrollPtr->lastFraction - scrollPtr->firstFraction;
+ if (PtInRect(currentPoint, &trackRect)) {
+ if (scrollPtr->vertical == true) {
+ newFirstFraction = (1.0 - thumbWidth) *
+ ((double) (currentPoint.v - trackBarPin) / trackBarSize);
+ } else {
+ newFirstFraction = (1.0 - thumbWidth) *
+ ((double) (currentPoint.h - trackBarPin) / trackBarSize);
+ }
+ } else {
+ newFirstFraction = ((double) origValue / 1000.0)
+ * (1.0 - thumbWidth);
+ }
+
+ sprintf(vauleString, "%g", newFirstFraction);
+
+ Tcl_DStringSetLength(&cmdString, 0);
+ Tcl_DStringAppend(&cmdString, scrollPtr->command,
+ scrollPtr->commandSize);
+ Tcl_DStringAppendElement(&cmdString, "moveto");
+ Tcl_DStringAppendElement(&cmdString, vauleString);
+
+ interp = scrollPtr->interp;
+ Tcl_Preserve((ClientData) interp);
+ Tcl_GlobalEval(interp, cmdString.string);
+ Tcl_Release((ClientData) interp);
+
+ Tcl_DStringSetLength(&cmdString, 0);
+ Tcl_DStringAppend(&cmdString, "update idletasks",
+ strlen("update idletasks"));
+ Tcl_Preserve((ClientData) interp);
+ Tcl_GlobalEval(interp, cmdString.string);
+ Tcl_Release((ClientData) interp);
+ }
+
+ /*
+ * This next bit of code is a bit of a hack - but needed. The problem is
+ * that the control wants to draw the drag outline if the control value
+ * changes during the drag (which it does). What we do here is change the
+ * clip region to hide this drawing from the user.
+ */
+ ClipRect(&nullRect);
+
+ Tcl_DStringFree(&cmdString);
+ return;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScrollbarActionProc --
+ *
+ * Callback procedure used by the Macintosh toolbox call
+ * TrackControl. This call will update the display while
+ * the scrollbar is being manipulated by the user.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May change the display.
+ *
+ *--------------------------------------------------------------
+ */
+
+static pascal void
+ScrollbarActionProc(
+ ControlRef theControl, /* Handle to scrollbat control */
+ ControlPartCode partCode) /* Part of scrollbar that was "hit" */
+{
+ register TkScrollbar *scrollPtr = (TkScrollbar *) GetCRefCon(theControl);
+ Tcl_DString cmdString;
+
+ Tcl_DStringInit(&cmdString);
+ Tcl_DStringAppend(&cmdString, scrollPtr->command,
+ scrollPtr->commandSize);
+
+ if (partCode == inUpButton || partCode == inDownButton) {
+ Tcl_DStringAppendElement(&cmdString, "scroll");
+ Tcl_DStringAppendElement(&cmdString,
+ (partCode == inUpButton ) ? "-1" : "1");
+ Tcl_DStringAppendElement(&cmdString, "unit");
+ } else if (partCode == inPageUp || partCode == inPageDown) {
+ Tcl_DStringAppendElement(&cmdString, "scroll");
+ Tcl_DStringAppendElement(&cmdString,
+ (partCode == inPageUp ) ? "-1" : "1");
+ Tcl_DStringAppendElement(&cmdString, "page");
+ }
+ Tcl_Preserve((ClientData) scrollPtr->interp);
+ Tcl_DStringAppend(&cmdString, "; update idletasks",
+ strlen("; update idletasks"));
+ Tcl_GlobalEval(scrollPtr->interp, cmdString.string);
+ Tcl_Release((ClientData) scrollPtr->interp);
+
+ Tcl_DStringFree(&cmdString);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScrollbarBindProc --
+ *
+ * This procedure is invoked when the default <ButtonPress>
+ * binding on the Scrollbar bind tag fires.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The event enters a modal loop.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ScrollbarBindProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interp with binding. */
+ XEvent *eventPtr, /* X event that triggered binding. */
+ Tk_Window tkwin, /* Target window for event. */
+ KeySym keySym) /* The KeySym if a key event. */
+{
+ TkWindow *winPtr = (TkWindow*)tkwin;
+ TkScrollbar *scrollPtr = (TkScrollbar *) winPtr->instanceData;
+ MacScrollbar *macScrollPtr = (MacScrollbar *) winPtr->instanceData;
+
+ Tcl_Preserve((ClientData)scrollPtr);
+ macScrollPtr->macFlags |= IN_MODAL_LOOP;
+
+ if (eventPtr->type == ButtonPress) {
+ Point where;
+ Rect bounds;
+ int part, x, y, dummy;
+ unsigned int state;
+ CGrafPtr saveWorld;
+ GDHandle saveDevice;
+ GWorldPtr destPort;
+ Window window;
+
+ /*
+ * To call Macintosh control routines we must have the port
+ * set to the window containing the control. We will then test
+ * which part of the control was hit and act accordingly.
+ */
+ destPort = TkMacGetDrawablePort(Tk_WindowId(scrollPtr->tkwin));
+ GetGWorld(&saveWorld, &saveDevice);
+ SetGWorld(destPort, NULL);
+ TkMacSetUpClippingRgn(Tk_WindowId(scrollPtr->tkwin));
+
+ TkMacWinBounds((TkWindow *) scrollPtr->tkwin, &bounds);
+ where.h = eventPtr->xbutton.x + bounds.left;
+ where.v = eventPtr->xbutton.y + bounds.top;
+ part = TestControl(macScrollPtr->sbHandle, where);
+ if (part == inThumb && scrollPtr->jump == false) {
+ /*
+ * Case 1: In thumb, no jump scrolling. Call track control
+ * with the thumb action proc which will do most of the work.
+ * Set the global activeScrollPtr to the current control
+ * so the callback may have access to it.
+ */
+ activeScrollPtr = scrollPtr;
+ part = TrackControl(macScrollPtr->sbHandle, where,
+ (ControlActionUPP) thumbActionProc);
+ activeScrollPtr = NULL;
+ } else if (part == inThumb) {
+ /*
+ * Case 2: in thumb with jump scrolling. Call TrackControl
+ * with a NULL action proc. Use the new value of the control
+ * to set update the control.
+ */
+ part = TrackControl(macScrollPtr->sbHandle, where, NULL);
+ if (part == inThumb) {
+ double newFirstFraction, thumbWidth;
+ Tcl_DString cmdString;
+ char vauleString[TCL_DOUBLE_SPACE];
+
+ /*
+ * The following calculation takes the new control
+ * value and maps it to what Tk needs for its variable
+ * thumb size representation.
+ */
+ thumbWidth = scrollPtr->lastFraction
+ - scrollPtr->firstFraction;
+ newFirstFraction = (1.0 - thumbWidth) *
+ ((double) GetControlValue(macScrollPtr->sbHandle) / 1000.0);
+ sprintf(vauleString, "%g", newFirstFraction);
+
+ Tcl_DStringInit(&cmdString);
+ Tcl_DStringAppend(&cmdString, scrollPtr->command,
+ strlen(scrollPtr->command));
+ Tcl_DStringAppendElement(&cmdString, "moveto");
+ Tcl_DStringAppendElement(&cmdString, vauleString);
+ Tcl_DStringAppend(&cmdString, "; update idletasks",
+ strlen("; update idletasks"));
+
+ interp = scrollPtr->interp;
+ Tcl_Preserve((ClientData) interp);
+ Tcl_GlobalEval(interp, cmdString.string);
+ Tcl_Release((ClientData) interp);
+ Tcl_DStringFree(&cmdString);
+ }
+ } else if (part != 0) {
+ /*
+ * Case 3: in any other part of the scrollbar. We call
+ * TrackControl with the scrollActionProc which will do
+ * most all the work.
+ */
+ TrackControl(macScrollPtr->sbHandle, where, scrollActionProc);
+ HiliteControl(macScrollPtr->sbHandle, 0);
+ }
+
+ /*
+ * The TrackControl call will "eat" the ButtonUp event. We now
+ * generate a ButtonUp event so Tk will unset implicit grabs etc.
+ */
+ GetMouse(&where);
+ XQueryPointer(NULL, None, &window, &window, &x,
+ &y, &dummy, &dummy, &state);
+ window = Tk_WindowId(scrollPtr->tkwin);
+ TkGenerateButtonEvent(x, y, window, state);
+
+ SetGWorld(saveWorld, saveDevice);
+ }
+
+ if (macScrollPtr->sbHandle && (macScrollPtr->macFlags & ALREADY_DEAD)) {
+ DisposeControl(macScrollPtr->sbHandle);
+ macScrollPtr->sbHandle = NULL;
+ }
+ macScrollPtr->macFlags &= ~IN_MODAL_LOOP;
+ Tcl_Release((ClientData)scrollPtr);
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScrollbarEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various
+ * events on scrollbars.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get
+ * cleaned up. When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScrollbarEventProc(
+ ClientData clientData, /* Information about window. */
+ XEvent *eventPtr) /* Information about event. */
+{
+ TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
+ MacScrollbar *macScrollPtr = (MacScrollbar *) clientData;
+
+ if (eventPtr->type == UnmapNotify) {
+ TkMacSetScrollbarGrow((TkWindow *) scrollPtr->tkwin, false);
+ } else if (eventPtr->type == ActivateNotify) {
+ macScrollPtr->macFlags |= ACTIVE;
+ TkScrollbarEventuallyRedraw((ClientData) scrollPtr);
+ } else if (eventPtr->type == DeactivateNotify) {
+ macScrollPtr->macFlags &= ~ACTIVE;
+ TkScrollbarEventuallyRedraw((ClientData) scrollPtr);
+ } else {
+ TkScrollbarEventProc(clientData, eventPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * UpdateControlValues --
+ *
+ * This procedure updates the Macintosh scrollbar control
+ * to display the values defined by the Tk scrollbar.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The Macintosh control is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+UpdateControlValues(
+ MacScrollbar *macScrollPtr) /* Scrollbar data struct. */
+{
+ TkScrollbar *scrollPtr = (TkScrollbar *) macScrollPtr;
+ Tk_Window tkwin = scrollPtr->tkwin;
+ MacDrawable * macDraw = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
+ WindowRef windowRef = (**macScrollPtr->sbHandle).contrlOwner;
+ double middle;
+ int drawGrowRgn = false;
+ int flushRight = false;
+ int flushBottom = false;
+
+ /*
+ * We can't use the Macintosh commands SizeControl and MoveControl as these
+ * calls will also cause a redraw which in our case will also cause
+ * flicker. To avoid this we adjust the control record directly. The
+ * Draw1Control command appears to just draw where ever the control says to
+ * draw so this seems right.
+ *
+ * NOTE: changing the control record directly may not work when
+ * Apple releases the Copland version of the MacOS (or when hell is cold).
+ */
+
+ (**macScrollPtr->sbHandle).contrlRect.left = macDraw->xOff + scrollPtr->inset;
+ (**macScrollPtr->sbHandle).contrlRect.top = macDraw->yOff + scrollPtr->inset;
+ (**macScrollPtr->sbHandle).contrlRect.right = macDraw->xOff + Tk_Width(tkwin)
+ - scrollPtr->inset;
+ (**macScrollPtr->sbHandle).contrlRect.bottom = macDraw->yOff +
+ Tk_Height(tkwin) - scrollPtr->inset;
+
+ /*
+ * To make Tk applications look more like Macintosh applications without
+ * requiring additional work by the Tk developer we do some cute tricks.
+ * The first trick plays with the size of the widget to get it to overlap
+ * with the side of the window by one pixel (we don't do this if the placer
+ * is the geometry manager). The second trick shrinks the scrollbar if it
+ * it covers the area of the grow region ao the scrollbar can also draw
+ * the grow region if need be.
+ */
+ if (!strcmp(macDraw->winPtr->geomMgrPtr->name, "place")) {
+ macScrollPtr->macFlags &= AUTO_ADJUST;
+ } else {
+ macScrollPtr->macFlags |= AUTO_ADJUST;
+ }
+ /* TODO: use accessor function!!! */
+ if (windowRef->portRect.left == (**macScrollPtr->sbHandle).contrlRect.left) {
+ if (macScrollPtr->macFlags & AUTO_ADJUST) {
+ (**macScrollPtr->sbHandle).contrlRect.left--;
+ }
+ if (!(macScrollPtr->macFlags & FLUSH_LEFT)) {
+ macScrollPtr->macFlags |= FLUSH_LEFT;
+ if (scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+ } else if (macScrollPtr->macFlags & FLUSH_LEFT) {
+ macScrollPtr->macFlags &= ~FLUSH_LEFT;
+ if (scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+
+ if (windowRef->portRect.top == (**macScrollPtr->sbHandle).contrlRect.top) {
+ if (macScrollPtr->macFlags & AUTO_ADJUST) {
+ (**macScrollPtr->sbHandle).contrlRect.top--;
+ }
+ if (!(macScrollPtr->macFlags & FLUSH_TOP)) {
+ macScrollPtr->macFlags |= FLUSH_TOP;
+ if (! scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+ } else if (macScrollPtr->macFlags & FLUSH_TOP) {
+ macScrollPtr->macFlags &= ~FLUSH_TOP;
+ if (! scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+
+ if (windowRef->portRect.right == (**macScrollPtr->sbHandle).contrlRect.right) {
+ flushRight = true;
+ if (macScrollPtr->macFlags & AUTO_ADJUST) {
+ (**macScrollPtr->sbHandle).contrlRect.right++;
+ }
+ if (!(macScrollPtr->macFlags & FLUSH_RIGHT)) {
+ macScrollPtr->macFlags |= FLUSH_RIGHT;
+ if (scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+ } else if (macScrollPtr->macFlags & FLUSH_RIGHT) {
+ macScrollPtr->macFlags &= ~FLUSH_RIGHT;
+ if (scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+
+ if (windowRef->portRect.bottom == (**macScrollPtr->sbHandle).contrlRect.bottom) {
+ flushBottom = true;
+ if (macScrollPtr->macFlags & AUTO_ADJUST) {
+ (**macScrollPtr->sbHandle).contrlRect.bottom++;
+ }
+ if (!(macScrollPtr->macFlags & FLUSH_BOTTOM)) {
+ macScrollPtr->macFlags |= FLUSH_BOTTOM;
+ if (! scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+ } else if (macScrollPtr->macFlags & FLUSH_BOTTOM) {
+ macScrollPtr->macFlags &= ~FLUSH_BOTTOM;
+ if (! scrollPtr->vertical) {
+ TkpComputeScrollbarGeometry(scrollPtr);
+ }
+ }
+
+ /*
+ * If the scrollbar is flush against the bottom right hand coner then
+ * it may need to draw the grow region for the window so we let the
+ * wm code know about this scrollbar. We don't actually draw the grow
+ * region, however, unless we are currently resizable.
+ */
+ macScrollPtr->macFlags &= ~DRAW_GROW;
+ if (flushBottom && flushRight) {
+ TkMacSetScrollbarGrow((TkWindow *) tkwin, true);
+ if (TkMacResizable(macDraw->toplevel->winPtr)) {
+ if (scrollPtr->vertical) {
+ (**macScrollPtr->sbHandle).contrlRect.bottom -= 14;
+ } else {
+ (**macScrollPtr->sbHandle).contrlRect.right -= 14;
+ }
+ macScrollPtr->macFlags |= DRAW_GROW;
+ }
+ } else {
+ TkMacSetScrollbarGrow((TkWindow *) tkwin, false);
+ }
+
+ /*
+ * Given the Tk parameters for the fractions of the start and
+ * end of the thumb, the following calculation determines the
+ * location for the fixed sized Macintosh thumb.
+ */
+ middle = scrollPtr->firstFraction / (scrollPtr->firstFraction +
+ (1.0 - scrollPtr->lastFraction));
+
+ (**macScrollPtr->sbHandle).contrlValue = (short) (middle * 1000);
+ if ((**macScrollPtr->sbHandle).contrlHilite == 0 ||
+ (**macScrollPtr->sbHandle).contrlHilite == 255) {
+ if (scrollPtr->firstFraction == 0.0 &&
+ scrollPtr->lastFraction == 1.0) {
+ (**macScrollPtr->sbHandle).contrlHilite = 255;
+ } else {
+ (**macScrollPtr->sbHandle).contrlHilite = 0;
+ }
+ }
+ if ((**macScrollPtr->sbHandle).contrlVis != 255) {
+ (**macScrollPtr->sbHandle).contrlVis = 255;
+ }
+}
diff --git a/mac/tkMacSend.c b/mac/tkMacSend.c
new file mode 100644
index 0000000..85065ac
--- /dev/null
+++ b/mac/tkMacSend.c
@@ -0,0 +1,358 @@
+/*
+ * tkMacSend.c --
+ *
+ * This file provides procedures that implement the "send"
+ * command, allowing commands to be passed from interpreter
+ * to interpreter. This current implementation for the Mac
+ * has most functionality stubed out.
+ *
+ * Copyright (c) 1989-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacSend.c 1.7 96/12/03 11:48:27
+ */
+
+#include "tkPort.h"
+#include "tkInt.h"
+
+ /*
+ * The following structure is used to keep track of the
+ * interpreters registered by this process.
+ */
+
+typedef struct RegisteredInterp {
+ char *name; /* Interpreter's name (malloc-ed). */
+ Tcl_Interp *interp; /* Interpreter associated with
+ * name. */
+ TkWindow *winPtr; /* Main window for the application. */
+ struct RegisteredInterp *nextPtr;
+ /* Next in list of names associated
+ * with interps in this process.
+ * NULL means end of list. */
+} RegisteredInterp;
+
+static RegisteredInterp *registry = NULL;
+/* List of all interpreters
+ * registered by this process. */
+
+/*
+ * A registry of all interpreters for a display is kept in a
+ * property "InterpRegistry" on the root window of the display.
+ * It is organized as a series of zero or more concatenated strings
+ * (in no particular order), each of the form
+ * window space name '\0'
+ * where "window" is the hex id of the comm. window to use to talk
+ * to an interpreter named "name".
+ *
+ * When the registry is being manipulated by an application (e.g. to
+ * add or remove an entry), it is loaded into memory using a structure
+ * of the following type:
+ */
+
+typedef struct NameRegistry {
+ TkDisplay *dispPtr; /* Display from which the registry was
+ * read. */
+ int locked; /* Non-zero means that the display was
+ * locked when the property was read in. */
+ int modified; /* Non-zero means that the property has
+ * been modified, so it needs to be written
+ * out when the NameRegistry is closed. */
+ unsigned long propLength; /* Length of the property, in bytes. */
+ char *property; /* The contents of the property. See format
+ * above; this is *not* terminated by the
+ * first null character. Dynamically
+ * allocated. */
+ int allocedByX; /* Non-zero means must free property with
+ * XFree; zero means use ckfree. */
+} NameRegistry;
+
+ /*
+ * When a result is being awaited from a sent command, one of
+ * the following structures is present on a list of all outstanding
+ * sent commands. The information in the structure is used to
+ * process the result when it arrives. You're probably wondering
+ * how there could ever be multiple outstanding sent commands.
+ * This could happen if interpreters invoke each other recursively.
+ * It's unlikely, but possible.
+ */
+
+typedef struct PendingCommand {
+ int serial; /* Serial number expected in
+ * result. */
+ TkDisplay *dispPtr; /* Display being used for communication. */
+ char *target; /* Name of interpreter command is
+ * being sent to. */
+ Window commWindow; /* Target's communication window. */
+ Tk_TimerToken timeout; /* Token for timer handler used to check
+ * up on target during long sends. */
+ Tcl_Interp *interp; /* Interpreter from which the send
+ * was invoked. */
+ int code; /* Tcl return code for command
+ * will be stored here. */
+ char *result; /* String result for command (malloc'ed),
+ * or NULL. */
+ char *errorInfo; /* Information for "errorInfo" variable,
+ * or NULL (malloc'ed). */
+ char *errorCode; /* Information for "errorCode" variable,
+ * or NULL (malloc'ed). */
+ int gotResponse; /* 1 means a response has been received,
+ * 0 means the command is still outstanding. */
+ struct PendingCommand *nextPtr;
+ /* Next in list of all outstanding
+ * commands. NULL means end of
+ * list. */
+} PendingCommand;
+
+static PendingCommand *pendingCommands = NULL;
+/* List of all commands currently
+ * being waited for. */
+
+ /*
+ * The information below is used for communication between processes
+ * during "send" commands. Each process keeps a private window, never
+ * even mapped, with one property, "Comm". When a command is sent to
+ * an interpreter, the command is appended to the comm property of the
+ * communication window associated with the interp's process. Similarly,
+ * when a result is returned from a sent command, it is also appended
+ * to the comm property.
+ *
+ * Each command and each result takes the form of ASCII text. For a
+ * command, the text consists of a zero character followed by several
+ * null-terminated ASCII strings. The first string consists of the
+ * single letter "c". Subsequent strings have the form "option value"
+ * where the following options are supported:
+ *
+ * -r commWindow serial
+ *
+ * This option means that a response should be sent to the window
+ * whose X identifier is "commWindow" (in hex), and the response should
+ * be identified with the serial number given by "serial" (in decimal).
+ * If this option isn't specified then the send is asynchronous and
+ * no response is sent.
+ *
+ * -n name
+ * "Name" gives the name of the application for which the command is
+ * intended. This option must be present.
+ *
+ * -s script
+ *
+ * "Script" is the script to be executed. This option must be present.
+ *
+ * The options may appear in any order. The -n and -s options must be
+ * present, but -r may be omitted for asynchronous RPCs. For compatibility
+ * with future releases that may add new features, there may be additional
+ * options present; as long as they start with a "-" character, they will
+ * be ignored.
+ *
+ * A result also consists of a zero character followed by several null-
+ * terminated ASCII strings. The first string consists of the single
+ * letter "r". Subsequent strings have the form "option value" where
+ * the following options are supported:
+ *
+ * -s serial
+ *
+ * Identifies the command for which this is the result. It is the
+ * same as the "serial" field from the -s option in the command. This
+ * option must be present.
+ *
+ * -c code
+ *
+ * "Code" is the completion code for the script, in decimal. If the
+ * code is omitted it defaults to TCL_OK.
+ *
+ * -r result
+ *
+ * "Result" is the result string for the script, which may be either
+ * a result or an error message. If this field is omitted then it
+ * defaults to an empty string.
+ *
+ * -i errorInfo
+ *
+ * "ErrorInfo" gives a string with which to initialize the errorInfo
+ * variable. This option may be omitted; it is ignored unless the
+ * completion code is TCL_ERROR.
+ *
+ * -e errorCode
+ *
+ * "ErrorCode" gives a string with with to initialize the errorCode
+ * variable. This option may be omitted; it is ignored unless the
+ * completion code is TCL_ERROR.
+ *
+ * Options may appear in any order, and only the -s option must be
+ * present. As with commands, there may be additional options besides
+ * these; unknown options are ignored.
+ */
+
+ /*
+ * The following variable is the serial number that was used in the
+ * last "send" command. It is exported only for testing purposes.
+ */
+
+int tkSendSerial = 0;
+
+ /*
+ * Maximum size property that can be read at one time by
+ * this module:
+ */
+
+#define MAX_PROP_WORDS 100000
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int AppendErrorProc _ANSI_ARGS_((ClientData clientData,
+ XErrorEvent *errorPtr));
+static void AppendPropCarefully _ANSI_ARGS_((Display *display,
+ Window window, Atom property, char *value,
+ int length, PendingCommand *pendingPtr));
+static void DeleteProc _ANSI_ARGS_((ClientData clientData));
+static void RegAddName _ANSI_ARGS_((NameRegistry *regPtr,
+ char *name, Window commWindow));
+static void RegClose _ANSI_ARGS_((NameRegistry *regPtr));
+static void RegDeleteName _ANSI_ARGS_((NameRegistry *regPtr,
+ char *name));
+static Window RegFindName _ANSI_ARGS_((NameRegistry *regPtr,
+ char *name));
+static NameRegistry * RegOpen _ANSI_ARGS_((Tcl_Interp *interp,
+ TkWindow *winPtr, int lock));
+static void SendEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static int SendInit _ANSI_ARGS_((Tcl_Interp *interp,
+ TkWindow *winPtr));
+static Bool SendRestrictProc _ANSI_ARGS_((Display *display,
+ XEvent *eventPtr, char *arg));
+static int ServerSecure _ANSI_ARGS_((TkDisplay *dispPtr));
+static void TimeoutProc _ANSI_ARGS_((ClientData clientData));
+static int ValidateName _ANSI_ARGS_((TkDisplay *dispPtr,
+ char *name, Window commWindow, int oldOK));
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SetAppName --
+ *
+ * This procedure is called to associate an ASCII name with a Tk
+ * application. If the application has already been named, the
+ * name replaces the old one.
+ *
+ * Results:
+ * The return value is the name actually given to the application.
+ * This will normally be the same as name, but if name was already
+ * in use for an application then a name of the form "name #2" will
+ * be chosen, with a high enough number to make the name unique.
+ *
+ * Side effects:
+ * Registration info is saved, thereby allowing the "send" command
+ * to be used later to invoke commands in the application. In
+ * addition, the "send" command is created in the application's
+ * interpreter. The registration will be removed automatically
+ * if the interpreter is deleted or the "send" command is removed.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+Tk_SetAppName(
+ Tk_Window tkwin, /* Token for any window in the application
+ * to be named: it is just used to identify
+ * the application and the display. */
+ char *name) /* The name that will be used to
+ * refer to the interpreter in later
+ * "send" commands. Must be globally
+ * unique. */
+{
+ return name;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SendCmd --
+ *
+ * This procedure is invoked to process the "send" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_SendCmd(
+ ClientData clientData, /* Information about sender (only
+ * dispPtr field is used). */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ Tcl_SetResult(interp, "Send not yet implemented", TCL_STATIC);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetInterpNames --
+ *
+ * This procedure is invoked to fetch a list of all the
+ * interpreter names currently registered for the display
+ * of a particular window.
+ *
+ * Results:
+ * A standard Tcl return value. Interp->result will be set
+ * to hold a list of all the interpreter names defined for
+ * tkwin's display. If an error occurs, then TCL_ERROR
+ * is returned and interp->result will hold an error message.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkGetInterpNames(
+ Tcl_Interp *interp, /* Interpreter for returning a result. */
+ Tk_Window tkwin) /* Window whose display is to be used
+ * for the lookup. */
+{
+ Tcl_SetResult(interp, "Send not yet implemented", TCL_STATIC);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SendInit --
+ *
+ * This procedure is called to initialize the
+ * communication channels for sending commands and
+ * receiving results.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets up various data structures and windows.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+SendInit(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting
+ * (no errors are ever returned, but the
+ * interpreter is needed anyway). */
+ TkWindow *winPtr) /* Window that identifies the display to
+ * initialize. */
+{
+ return TCL_OK;
+}
diff --git a/mac/tkMacShLib.exp b/mac/tkMacShLib.exp
new file mode 100644
index 0000000..0c28a4c
--- /dev/null
+++ b/mac/tkMacShLib.exp
@@ -0,0 +1,766 @@
+MacMoveWindow
+TkAboutDlg
+TkActivateMenuEntry
+TkAllocWindow
+TkBTreeCharTagged
+TkBTreeCharsInLine
+TkBTreeCheck
+TkBTreeCreate
+TkBTreeDeleteChars
+TkBTreeDestroy
+TkBTreeFindLine
+TkBTreeGetTags
+TkBTreeInsertChars
+TkBTreeLineIndex
+TkBTreeLinkSegment
+TkBTreeNextLine
+TkBTreeNextTag
+TkBTreeNumLines
+TkBTreePrevTag
+TkBTreePreviousLine
+TkBTreeStartSearch
+TkBTreeStartSearchBack
+TkBTreeTag
+TkBTreeUnlinkSegment
+TkBezierPoints
+TkBezierScreenPoints
+TkBindDeadWindow
+TkBindEventProc
+TkBindFree
+TkBindInit
+TkButtonWorldChanged
+TkCanvPostscriptCmd
+TkChangeEventWindow
+TkClipBox
+TkClipInit
+TkComputeAnchor
+TkConsoleCreate
+TkConsoleInit
+TkConsolePrint
+TkCopyAndGlobalEval
+TkCreateBindingProcedure
+TkCreateCursorFromData
+TkCreateFrame
+TkCreateMainWindow
+TkCreateMenuReferences
+TkCreateNamedFont
+TkCreateRegion
+TkCurrentTime
+TkDeadAppCmd
+TkDeleteAllImages
+TkDestroyMenu
+TkDestroyRegion
+TkDoConfigureNotify
+TkEventDeadWindow
+TkEventuallyRecomputeMenu
+TkEventuallyRedrawMenu
+TkEventuallyRedrawScale
+TkFillPolygon
+TkFindMenuReferences
+TkFindStateNum
+TkFindStateString
+TkFocusDeadWindow
+TkFocusFilterEvent
+TkFocusKeyEvent
+TkFontPkgFree
+TkFontPkgInit
+TkFreeBindingTags
+TkFreeCursor
+TkFreeFileFilters
+TkFreeMenuReferences
+TkGenWMConfigureEvent
+TkGenWMDestroyEvent
+TkGenerateActivateEvents
+TkGenerateButtonEvent
+TkGetBitmapData
+TkGetButtPoints
+TkGetCursorByName
+TkGetDefaultScreenName
+TkGetDisplay
+TkGetDisplayOf
+TkGetFileFilters
+TkGetInterpNames
+TkGetMenuHashTable
+TkGetMenuIndex
+TkGetMiterPoints
+TkGetNativeProlog
+TkGetPointerCoords
+TkGetProlog
+TkGetServerInfo
+TkGetTransientMaster
+TkGrabDeadWindow
+TkGrabState
+TkInOutEvents
+TkIncludePoint
+TkInitFileFilters
+TkInitFontAttributes
+TkIntersectRegion
+TkInvokeButton
+TkInvokeMenu
+TkKeysymToString
+TkLineToArea
+TkLineToPoint
+TkMacButtonKeyState
+TkMacClearMenubarActive
+TkMacConvertEvent
+TkMacConvertTkEvent
+TkMacDispatchMenuEvent
+TkMacDoHLEvent
+TkMacGenerateTime
+TkMacGetDrawablePort
+TkMacGetScrollbarGrowWindow
+TkMacGetXWindow
+TkMacGrowToplevel
+TkMacHandleMenuSelect
+TkMacHandleTearoffMenu
+TkMacInitAppleEvents
+TkMacInitMenus
+TkMacInstallCursor
+TkMacInvalClipRgns
+TkMacInvalidateWindow
+TkMacIsCharacterMissing
+TkMacMakeRealWindowExist
+TkMacMakeStippleMap
+TkMacMenuClick
+TkMacRegisterOffScreenWindow
+TkMacResizable
+TkMacSetEmbedRgn
+TkMacSetHelpMenuItemCount
+TkMacSetScrollbarGrow
+TkMacSetUpClippingRgn
+TkMacSetUpGraphicsPort
+TkMacUnregisterMacWindow
+TkMacUpdateClipRgn
+TkMacUseMenuID
+TkMacVisableClipRgn
+TkMacWinBounds
+TkMacWindowOffset
+TkMacXAddPixel
+TkMacXDestroyImage
+TkMacXGetPixel
+TkMacXPutPixel
+TkMacXSubImage
+TkMacZoomToplevel
+TkMakeBezierCurve
+TkMakeBezierPostscript
+TkMakeMenuWindow
+TkMenuButtonWorldChanged
+TkMenuConfigureDrawOptions
+TkMenuConfigureEntryDrawOptions
+TkMenuEntryFreeDrawOptions
+TkMenuEventProc
+TkMenuFreeDrawOptions
+TkMenuImageProc
+TkMenuInit
+TkMenuInitializeDrawingFields
+TkMenuInitializeEntryDrawingFields
+TkMenuSelectImageProc
+TkNewMenuName
+TkOptionClassChanged
+TkOptionDeadWindow
+TkOvalToArea
+TkOvalToPoint
+TkParseXLFD
+TkPointerDeadWindow
+TkPointerEvent
+TkPolygonToArea
+TkPolygonToPoint
+TkPositionInTree
+TkPostCommand
+TkPostSubmenu
+TkPostTearoffMenu
+TkPreprocessMenu
+TkPutImage
+TkQueueEventForAllChildren
+TkRecomputeMenu
+TkRectInRegion
+TkRoundToResolution
+TkScrollWindow
+TkScrollbarEventProc
+TkScrollbarEventuallyRedraw
+TkSelClearSelection
+TkSelDeadWindow
+TkSelDefaultSelection
+TkSelEventProc
+TkSelGetSelection
+TkSelInit
+TkSelPropProc
+TkSelUpdateClipboard
+TkSetClassProcs
+TkSetMacColor
+TkSetRegion
+TkSetWMName
+TkSetWindowMenuBar
+TkStringToKeysym
+TkSuspendClipboard
+TkTextBindProc
+TkTextChanged
+TkTextCharBbox
+TkTextCharLayoutProc
+TkTextCreateDInfo
+TkTextCreateTag
+TkTextDLineInfo
+TkTextEventuallyRepick
+TkTextFreeDInfo
+TkTextFreeTag
+TkTextGetIndex
+TkTextGetTabs
+TkTextImageCmd
+TkTextImageIndex
+TkTextIndexBackChars
+TkTextIndexCmp
+TkTextIndexForwChars
+TkTextIndexToSeg
+TkTextInsertDisplayProc
+TkTextLostSelection
+TkTextMakeIndex
+TkTextMarkCmd
+TkTextMarkNameToIndex
+TkTextMarkSegToIndex
+TkTextPickCurrent
+TkTextPixelIndex
+TkTextPrintIndex
+TkTextRedrawRegion
+TkTextRedrawTag
+TkTextRelayoutWindow
+TkTextScanCmd
+TkTextSeeCmd
+TkTextSegToOffset
+TkTextSetMark
+TkTextSetYView
+TkTextTagCmd
+TkTextWindowCmd
+TkTextWindowIndex
+TkTextXviewCmd
+TkTextYviewCmd
+TkThickPolyLineToArea
+TkUnionRectWithRegion
+TkUnsupported1Cmd
+TkWmAddToColormapWindows
+TkWmDeadWindow
+TkWmFocusToplevel
+TkWmMapWindow
+TkWmNewWindow
+TkWmProtocolEventProc
+TkWmRemoveFromColormapWindows
+TkWmRestackToplevel
+TkWmSetClass
+TkWmUnmapWindow
+Tk_3DBorderColor
+Tk_3DBorderGC
+Tk_3DHorizontalBevel
+Tk_3DVerticalBevel
+Tk_AddOption
+Tk_BellCmd
+Tk_BindCmd
+Tk_BindEvent
+Tk_BindtagsCmd
+Tk_ButtonCmd
+Tk_CanvasCmd
+Tk_CanvasDrawableCoords
+Tk_CanvasEventuallyRedraw
+Tk_CanvasGetCoord
+Tk_CanvasGetTextInfo
+Tk_CanvasPsBitmap
+Tk_CanvasPsColor
+Tk_CanvasPsFont
+Tk_CanvasPsPath
+Tk_CanvasPsStipple
+Tk_CanvasPsY
+Tk_CanvasSetStippleOrigin
+Tk_CanvasTagsParseProc
+Tk_CanvasTagsPrintProc
+Tk_CanvasTkwin
+Tk_CanvasWindowCoords
+Tk_ChangeWindowAttributes
+Tk_CharBbox
+Tk_CheckbuttonCmd
+Tk_ChooseColorCmd
+Tk_ClearSelection
+Tk_ClipboardAppend
+Tk_ClipboardClear
+Tk_ClipboardCmd
+Tk_ComputeTextLayout
+Tk_ConfigureInfo
+Tk_ConfigureValue
+Tk_ConfigureWidget
+Tk_ConfigureWindow
+Tk_CoordsToWindow
+Tk_CreateBinding
+Tk_CreateBindingTable
+Tk_CreateErrorHandler
+Tk_CreateEventHandler
+Tk_CreateGenericHandler
+Tk_CreateImageType
+Tk_CreateItemType
+Tk_CreatePhotoImageFormat
+Tk_CreateSelHandler
+Tk_CreateWindow
+Tk_CreateWindowFromPath
+Tk_DefineBitmap
+Tk_DefineCursor
+Tk_DeleteAllBindings
+Tk_DeleteBinding
+Tk_DeleteBindingTable
+Tk_DeleteErrorHandler
+Tk_DeleteEventHandler
+Tk_DeleteGenericHandler
+Tk_DeleteImage
+Tk_DeleteSelHandler
+Tk_DestroyCmd
+Tk_DestroyWindow
+Tk_DisplayName
+Tk_DistanceToTextLayout
+Tk_Draw3DPolygon
+Tk_Draw3DRectangle
+Tk_DrawChars
+Tk_DrawFocusHighlight
+Tk_DrawTextLayout
+Tk_EntryCmd
+Tk_EventCmd
+Tk_Fill3DPolygon
+Tk_Fill3DRectangle
+Tk_FindPhoto
+Tk_FocusCmd
+Tk_FontId
+Tk_FontObjCmd
+Tk_FrameCmd
+Tk_Free3DBorder
+Tk_FreeBitmap
+Tk_FreeColor
+Tk_FreeColormap
+Tk_FreeCursor
+Tk_FreeFont
+Tk_FreeGC
+Tk_FreeImage
+Tk_FreeOptions
+Tk_FreePixmap
+Tk_FreeTextLayout
+Tk_GCForColor
+Tk_GeometryRequest
+Tk_Get3DBorder
+Tk_GetAllBindings
+Tk_GetAnchor
+Tk_GetAtomName
+Tk_GetBinding
+Tk_GetBitmap
+Tk_GetBitmapFromData
+Tk_GetCapStyle
+Tk_GetColor
+Tk_GetColorByValue
+Tk_GetColormap
+Tk_GetCursor
+Tk_GetCursorFromData
+Tk_GetFont
+Tk_GetFontFromObj
+Tk_GetFontMetrics
+Tk_GetGC
+Tk_GetImage
+Tk_GetItemTypes
+Tk_GetJoinStyle
+Tk_GetJustify
+Tk_GetNumMainWindows
+Tk_GetOpenFileCmd
+Tk_GetOption
+Tk_GetPixels
+Tk_GetPixmap
+Tk_GetRelief
+Tk_GetRootCoords
+Tk_GetSaveFileCmd
+Tk_GetScreenMM
+Tk_GetScrollInfo
+Tk_GetSelection
+Tk_GetUid
+Tk_GetVRootGeometry
+Tk_GetVisual
+Tk_Grab
+Tk_GrabCmd
+Tk_GridCmd
+Tk_HandleEvent
+Tk_IdToWindow
+Tk_ImageChanged
+Tk_ImageCmd
+Tk_Init
+Tk_InternAtom
+Tk_IntersectTextLayout
+Tk_LabelCmd
+Tk_ListboxCmd
+Tk_LowerCmd
+Tk_Main
+Tk_MainLoop
+Tk_MainWindow
+Tk_MaintainGeometry
+Tk_MakeWindowExist
+Tk_ManageGeometry
+Tk_MapWindow
+Tk_MeasureChars
+Tk_MenuCmd
+Tk_MenubuttonCmd
+Tk_MessageBoxCmd
+Tk_MessageCmd
+Tk_MoveResizeWindow
+Tk_MoveToplevelWindow
+Tk_MoveWindow
+Tk_NameOf3DBorder
+Tk_NameOfAnchor
+Tk_NameOfBitmap
+Tk_NameOfCapStyle
+Tk_NameOfColor
+Tk_NameOfCursor
+Tk_NameOfFont
+Tk_NameOfImage
+Tk_NameOfJoinStyle
+Tk_NameOfJustify
+Tk_NameOfRelief
+Tk_NameToWindow
+Tk_OptionCmd
+Tk_OwnSelection
+Tk_PackCmd
+Tk_ParseArgv
+Tk_PhotoBlank
+Tk_PhotoExpand
+Tk_PhotoGetImage
+Tk_PhotoGetSize
+Tk_PhotoPutBlock
+Tk_PhotoPutZoomedBlock
+Tk_PhotoSetSize
+Tk_PlaceCmd
+Tk_PointToChar
+Tk_PostscriptFontName
+Tk_PreserveColormap
+Tk_QueueWindowEvent
+Tk_RadiobuttonCmd
+Tk_RaiseCmd
+Tk_RedrawImage
+Tk_ResizeWindow
+Tk_RestackWindow
+Tk_RestrictEvents
+Tk_SafeInit
+Tk_ScaleCmd
+Tk_ScrollbarCmd
+Tk_SelectionCmd
+Tk_SendCmd
+Tk_SetAppName
+Tk_SetBackgroundFromBorder
+Tk_SetClass
+Tk_SetGrid
+Tk_SetInternalBorder
+Tk_SetWindowBackground
+Tk_SetWindowBackgroundPixmap
+Tk_SetWindowBorder
+Tk_SetWindowBorderPixmap
+Tk_SetWindowBorderWidth
+Tk_SetWindowColormap
+Tk_SetWindowVisual
+Tk_SizeOfBitmap
+Tk_SizeOfImage
+Tk_StrictMotif
+Tk_TextCmd
+Tk_TextLayoutToPostscript
+Tk_TextWidth
+Tk_TkObjCmd
+Tk_TkwaitCmd
+Tk_TopCoordsToWindow
+Tk_ToplevelCmd
+Tk_UndefineCursor
+Tk_UnderlineChars
+Tk_UnderlineTextLayout
+Tk_Ungrab
+Tk_UnmaintainGeometry
+Tk_UnmapWindow
+Tk_UnsetGrid
+Tk_UpdateCmd
+Tk_UpdatePointer
+Tk_WinfoObjCmd
+Tk_WmCmd
+TkpChangeFocus
+TkpClaimFocus
+TkpCloseDisplay
+TkpComputeButtonGeometry
+TkpComputeMenuButtonGeometry
+TkpComputeMenubarGeometry
+TkpComputeScrollbarGeometry
+TkpComputeStandardMenuGeometry
+TkpConfigureMenuEntry
+TkpConfigureScrollbar
+TkpCreateButton
+TkpCreateMenuButton
+TkpCreateNativeBitmap
+TkpCreateScale
+TkpCreateScrollbar
+TkpDefineNativeBitmaps
+TkpDeleteFont
+TkpDestroyButton
+TkpDestroyMenu
+TkpDestroyMenuButton
+TkpDestroyMenuEntry
+TkpDestroyScale
+TkpDestroyScrollbar
+TkpDisplayButton
+TkpDisplayMenuButton
+TkpDisplayScale
+TkpDisplayScrollbar
+TkpDisplayWarning
+TkpDrawMenuEntry
+TkpFindWindow
+TkpFreeBorder
+TkpGetAppName
+TkpGetBorder
+TkpGetColor
+TkpGetColorByValue
+TkpGetFontFamilies
+TkpGetFontFromAttributes
+TkpGetMS
+TkpGetNativeAppBitmap
+TkpGetNativeFont
+TkpGetOtherWindow
+TkpGetShadows
+TkpInit
+TkpInitializeMenuBindings
+TkpMakeContainer
+TkpMakeWindow
+TkpMenuInit
+TkpMenuNewEntry
+TkpNewMenu
+TkpOpenDisplay
+TkpPixelToValue
+TkpPostMenu
+TkpRedirectKeyEvent
+TkpScaleElement
+TkpScrollbarPosition
+TkpSetCapture
+TkpSetCursor
+TkpSetMainMenubar
+TkpSetScaleValue
+TkpSetWindowMenuBar
+TkpTestembedCmd
+TkpUseWindow
+TkpValueToPixel
+TkpWindowWasRecentlyDeleted
+XAllocColor
+XAllocSizeHints
+XBell
+XChangeGC
+XChangeProperty
+XChangeWindowAttributes
+XConfigureWindow
+XCopyArea
+XCopyPlane
+XCreateBitmapFromData
+XCreateColormap
+XCreateGC
+XCreateImage
+XDefineCursor
+XDestroyWindow
+XDrawArc
+XDrawLine
+XDrawLines
+XDrawRectangle
+XFillArc
+XFillPolygon
+XFillRectangle
+XFillRectangles
+XForceScreenSaver
+XFreeColormap
+XFreeColors
+XFreeGC
+XFreeModifiermap
+XGContextFromGC
+XGetAtomName
+XGetGeometry
+XGetImage
+XGetModifierMapping
+XGetVisualInfo
+XGetWindowProperty
+XGrabKeyboard
+XGrabPointer
+XInternAtom
+XKeycodeToKeysym
+XKeysymToKeycode
+XKeysymToString
+XLookupString
+XMapWindow
+XMoveResizeWindow
+XMoveWindow
+XParseColor
+XQueryPointer
+XRaiseWindow
+XReadBitmapFile
+XRefreshKeyboardMapping
+XResizeWindow
+XRootWindow
+XSelectInput
+XSendEvent
+XSetArcMode
+XSetBackground
+XSetClipMask
+XSetClipOrigin
+XSetErrorHandler
+XSetFillRule
+XSetFillStyle
+XSetFont
+XSetForeground
+XSetFunction
+XSetIconName
+XSetInputFocus
+XSetLineAttributes
+XSetSelectionOwner
+XSetStipple
+XSetTSOrigin
+XSetWMNormalHints
+XSetWindowBackground
+XSetWindowBackgroundPixmap
+XSetWindowBorder
+XSetWindowBorderPixmap
+XSetWindowBorderWidth
+XSetWindowColormap
+XStringToKeysym
+XUngrabKeyboard
+XUngrabPointer
+XUnmapWindow
+_Aldata
+_Assert
+_Atcount
+_Atfuns
+_Clocale
+_Closreg
+_Costate
+_Daysto
+_Dbl
+_Defloc
+_Environ
+_Environ1
+_Fgpos
+_Files
+_Flt
+_Fopen
+_Foprep
+_Fread
+_Freeloc
+_Frprep
+_Fspos
+_Fwprep
+_Fwrite
+_Genld
+_Gentime
+_Getdst
+_Getfld
+_Getfloat
+_Getint
+_Getloc
+_Getmem
+_Getstr
+_Gettime
+_Getzone
+_Isdst
+_Ldbl
+_Ldtob
+_Litob
+_Locale
+_Locsum
+_Loctab
+_Locterm
+_Locvar
+_MWERKS_Atcount
+_MWERKS_Atfuns
+_Makeloc
+_Makestab
+_Makewct
+_Mbcurmax
+_Mbstate
+_Mbtowc
+_Nnl
+_PJP_C_Copyright
+_Printf
+_Putfld
+_Putstr
+_Puttxt
+_Randseed
+_Readloc
+_Scanf
+_Setloc
+_Skip
+_Stdin
+_Stdout
+_Stod
+_Stof
+_Stoflt
+_Stold
+_Strerror
+_Strftime
+_Strxfrm
+_Times
+_Tolower
+_Toupper
+_Ttotm
+_WCostate
+_Wcstate
+_Wctob
+_Wctomb
+_Wctrans
+_Wctype
+_XInitImageFuncPtrs
+__CheckForSystem7
+__RemoveConsoleHandler__
+__aborting
+__ctopstring
+__getcreator
+__gettype
+__myraise
+__system7present
+_atexit
+_exit
+_fcreator
+_ftype
+pendingPtr
+tclFocusDebug
+tcl_macQdPtr
+tkActiveUid
+tkAppleMenu
+tkArcType
+tkBTreeDebug
+tkBitmapImageType
+tkBitmapType
+tkDisabledUid
+tkDisplayList
+tkEditMenu
+tkFileMenu
+tkImageType
+tkImgFmtGIF
+tkImgFmtPPM
+tkLineType
+tkMacAppInFront
+tkMacFocusWin
+tkMainWindowList
+tkMenuConfigSpecs
+tkMenuEntryConfigSpecs
+tkNormalUid
+tkOvalType
+tkPhotoImageType
+tkPolygonType
+tkPredefBitmapTable
+tkRectangleType
+tkSendSerial
+tkTextCharType
+tkTextCharUid
+tkTextDebug
+tkTextDisabledUid
+tkTextLeftMarkType
+tkTextNoneUid
+tkTextNormalUid
+tkTextRightMarkType
+tkTextToggleOffType
+tkTextToggleOnType
+tkTextType
+tkTextWordUid
+tkWindowType
+tkpButtonConfigSpecs
+tkpButtonProcs
+tkpMenubuttonClass
+tkpScrollbarConfigSpecs
+tkpScrollbarProcs
+#TclMacInitializeFragment
+#TclMacTerminateFragment
+#__initialize
+#__ptmf_null
+#__terminate
diff --git a/mac/tkMacSubwindows.c b/mac/tkMacSubwindows.c
new file mode 100644
index 0000000..65c1a7e
--- /dev/null
+++ b/mac/tkMacSubwindows.c
@@ -0,0 +1,1227 @@
+/*
+ * tkMacSubwindows.c --
+ *
+ * Implements subwindows for the macintosh version of Tk.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacSubwindows.c 1.81 97/10/29 11:46:54
+ */
+
+#include "tkInt.h"
+#include "X.h"
+#include "Xlib.h"
+#include <stdio.h>
+
+#include <Windows.h>
+#include <QDOffscreen.h>
+#include "tkMacInt.h"
+
+/*
+ * Temporary region that can be reused.
+ */
+static RgnHandle tmpRgn = NULL;
+
+static void UpdateOffsets _ANSI_ARGS_((TkWindow *winPtr, int deltaX, int deltaY));
+
+void MacMoveWindow _ANSI_ARGS_((WindowRef window, int x, int y));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDestroyWindow --
+ *
+ * Dealocates the given X Window.
+ *
+ * Results:
+ * The window id is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDestroyWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ GWorldPtr destPort;
+
+ /*
+ * Remove any dangling pointers that may exist if
+ * the window we are deleting is being tracked by
+ * the grab code.
+ */
+
+ TkPointerDeadWindow(macWin->winPtr);
+ macWin->toplevel->referenceCount--;
+
+
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ DisposeRgn(macWin->clipRgn);
+ DisposeRgn(macWin->aboveClipRgn);
+
+ /*
+ * Delete the Mac window and remove it from the windowTable.
+ * The window could be NULL if the window was never mapped.
+ * However, we don't do this for embedded windows, they don't
+ * go in the window list, and they do not own their portPtr's.
+ */
+
+ if (!(Tk_IsEmbedded(macWin->winPtr))) {
+ destPort = TkMacGetDrawablePort(window);
+ if (destPort != NULL) {
+ TkMacWindowList *listPtr, *prevPtr;
+
+ TkMacUnregisterMacWindow(destPort);
+ DisposeWindow((WindowRef) destPort);
+
+ for (listPtr = tkMacWindowListPtr, prevPtr = NULL;
+ tkMacWindowListPtr != NULL;
+ prevPtr = listPtr, listPtr = listPtr->nextPtr) {
+ if (listPtr->winPtr == macWin->winPtr) {
+ if (prevPtr == NULL) {
+ tkMacWindowListPtr = listPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = listPtr->nextPtr;
+ }
+ ckfree((char *) listPtr);
+ break;
+ }
+ }
+ }
+ }
+
+ macWin->portPtr = NULL;
+
+ /*
+ * Delay deletion of a toplevel data structure untill all
+ * children have been deleted.
+ */
+ if (macWin->toplevel->referenceCount == 0) {
+ ckfree((char *) macWin->toplevel);
+ }
+ } else {
+ destPort = TkMacGetDrawablePort(window);
+ if (destPort != NULL) {
+ SetGWorld(destPort, NULL);
+ TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW);
+ }
+ if (macWin->winPtr->parentPtr != NULL) {
+ TkMacInvalClipRgns(macWin->winPtr->parentPtr);
+ }
+ DisposeRgn(macWin->clipRgn);
+ DisposeRgn(macWin->aboveClipRgn);
+
+ if (macWin->toplevel->referenceCount == 0) {
+ ckfree((char *) macWin->toplevel);
+ }
+ ckfree((char *) macWin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMapWindow --
+ *
+ * Map the given X Window to the screen. See X window documentation
+ * for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The subwindow or toplevel may appear on the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XMapWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ XEvent event;
+ GWorldPtr destPort;
+
+ /*
+ * Under certain situations it's possible for this function to be
+ * called before the toplevel window it's associated with has actually
+ * been mapped. In that case we need to create the real Macintosh
+ * window now as this function as well as other X functions assume that
+ * the portPtr is valid.
+ */
+ if (!TkMacHostToplevelExists(macWin->toplevel->winPtr)) {
+ TkMacMakeRealWindowExist(macWin->toplevel->winPtr);
+ }
+ destPort = TkMacGetDrawablePort(window);
+
+ display->request++;
+ macWin->winPtr->flags |= TK_MAPPED;
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ ShowWindow((WindowRef) destPort);
+ }
+
+ /*
+ * We only need to send the MapNotify event
+ * for toplevel windows.
+ */
+ event.xany.serial = display->request;
+ event.xany.send_event = False;
+ event.xany.display = display;
+
+ event.xmap.window = window;
+ event.xmap.type = MapNotify;
+ event.xmap.event = window;
+ event.xmap.override_redirect = macWin->winPtr->atts.override_redirect;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ } else {
+ TkMacInvalClipRgns(macWin->winPtr->parentPtr);
+ }
+
+ /*
+ * Generate damage for that area of the window
+ */
+ SetGWorld(destPort, NULL);
+ TkMacUpdateClipRgn(macWin->winPtr);
+ TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XUnmapWindow --
+ *
+ * Unmap the given X Window to the screen. See X window
+ * documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The subwindow or toplevel may be removed from the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XUnmapWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ XEvent event;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(window);
+
+ display->request++;
+ macWin->winPtr->flags &= ~TK_MAPPED;
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ HideWindow((WindowRef) destPort);
+ }
+
+ /*
+ * We only need to send the UnmapNotify event
+ * for toplevel windows.
+ */
+ event.xany.serial = display->request;
+ event.xany.send_event = False;
+ event.xany.display = display;
+
+ event.xunmap.type = UnmapNotify;
+ event.xunmap.window = window;
+ event.xunmap.event = window;
+ event.xunmap.from_configure = false;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ } else {
+ /*
+ * Generate damage for that area of the window.
+ */
+ SetGWorld(destPort, NULL);
+ TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW); /* TODO: may not be valid */
+ TkMacInvalClipRgns(macWin->winPtr->parentPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XResizeWindow --
+ *
+ * Resize a given X window. See X windows documentation for
+ * further details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XResizeWindow(
+ Display* display, /* Display. */
+ Window window, /* Window. */
+ unsigned int width,
+ unsigned int height)
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(window);
+ if (destPort == NULL) {
+ return;
+ }
+
+ display->request++;
+ SetPort((GrafPtr) destPort);
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ /*
+ * NOTE: we are not adding the new space to the update
+ * region. It is currently assumed that Tk will need
+ * to completely redraw anway.
+ */
+ SizeWindow((WindowRef) destPort,
+ (short) width, (short) height, false);
+ TkMacInvalidateWindow(macWin, TK_WINDOW_ONLY);
+ TkMacInvalClipRgns(macWin->winPtr);
+ } else {
+ /* TODO: update all xOff & yOffs */
+ int deltaX, deltaY, parentBorderwidth;
+ MacDrawable *macParent = macWin->winPtr->parentPtr->privatePtr;
+
+ /*
+ * Find the Parent window -
+ * For an embedded window this will be its container.
+ */
+
+ if (Tk_IsEmbedded(macWin->winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->winPtr);
+ if (contWinPtr == NULL) {
+ panic("XMoveResizeWindow could not find container");
+ }
+ macParent = contWinPtr->privatePtr;
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ } else {
+ macParent = macWin->winPtr->parentPtr->privatePtr;
+ if (macParent == NULL) {
+ return; /* TODO: Probably should be a panic */
+ }
+ }
+
+ TkMacInvalClipRgns(macParent->winPtr);
+ TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW);
+
+ deltaX = - macWin->xOff;
+ deltaY = - macWin->yOff;
+
+ /*
+ * If macWin->winPtr is an embedded window, don't offset by its
+ * parent's borderwidth...
+ */
+
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
+ } else {
+ parentBorderwidth = 0;
+ }
+ deltaX += macParent->xOff + parentBorderwidth +
+ macWin->winPtr->changes.x;
+ deltaY += macParent->yOff + parentBorderwidth +
+ macWin->winPtr->changes.y;
+
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMoveResizeWindow --
+ *
+ * Move or resize a given X window. See X windows documentation
+ * for further details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XMoveResizeWindow(
+ Display* display, /* Display. */
+ Window window, /* Window. */
+ int x, int y,
+ unsigned int width,
+ unsigned int height)
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(window);
+ if (destPort == NULL) {
+ return;
+ }
+
+ SetPort((GrafPtr) destPort);
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ /*
+ * NOTE: we are not adding the new space to the update
+ * region. It is currently assumed that Tk will need
+ * to completely redraw anway.
+ */
+
+ SizeWindow((WindowRef) destPort,
+ (short) width, (short) height, false);
+ MacMoveWindow((WindowRef) destPort, x, y);
+
+ /* TODO: is the following right? */
+ TkMacInvalidateWindow(macWin, TK_WINDOW_ONLY);
+ TkMacInvalClipRgns(macWin->winPtr);
+ } else {
+ int deltaX, deltaY, parentBorderwidth;
+ Rect bounds;
+ MacDrawable *macParent;
+
+ /*
+ * Find the Parent window -
+ * For an embedded window this will be its container.
+ */
+
+ if (Tk_IsEmbedded(macWin->winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->winPtr);
+ if (contWinPtr == NULL) {
+ panic("XMoveResizeWindow could not find container");
+ }
+ macParent = contWinPtr->privatePtr;
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+
+ } else {
+ macParent = macWin->winPtr->parentPtr->privatePtr;
+ if (macParent == NULL) {
+ return; /* TODO: Probably should be a panic */
+ }
+ }
+
+ TkMacInvalClipRgns(macParent->winPtr);
+ TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW);
+
+ deltaX = - macWin->xOff;
+ deltaY = - macWin->yOff;
+
+ /*
+ * If macWin->winPtr is an embedded window, don't offset by its
+ * parent's borderwidth...
+ */
+
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
+ } else {
+ parentBorderwidth = 0;
+ }
+ deltaX += macParent->xOff + parentBorderwidth +
+ macWin->winPtr->changes.x;
+ deltaY += macParent->yOff + parentBorderwidth +
+ macWin->winPtr->changes.y;
+
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ TkMacWinBounds(macWin->winPtr, &bounds);
+ InvalRect(&bounds);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMoveWindow --
+ *
+ * Move a given X window. See X windows documentation for further
+ * details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XMoveWindow(
+ Display* display, /* Display. */
+ Window window, /* Window. */
+ int x,
+ int y)
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(window);
+ if (destPort == NULL) {
+ return;
+ }
+
+ SetPort((GrafPtr) destPort);
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ /*
+ * NOTE: we are not adding the new space to the update
+ * region. It is currently assumed that Tk will need
+ * to completely redraw anway.
+ */
+ MacMoveWindow((WindowRef) destPort, x, y);
+
+ /* TODO: is the following right? */
+ TkMacInvalidateWindow(macWin, TK_WINDOW_ONLY);
+ TkMacInvalClipRgns(macWin->winPtr);
+ } else {
+ int deltaX, deltaY, parentBorderwidth;
+ Rect bounds;
+ MacDrawable *macParent;
+
+ /*
+ * Find the Parent window -
+ * For an embedded window this will be its container.
+ */
+
+ if (Tk_IsEmbedded(macWin->winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->winPtr);
+ if (contWinPtr == NULL) {
+ panic("XMoveWindow could not find container");
+ }
+ macParent = contWinPtr->privatePtr;
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ } else {
+ macParent = macWin->winPtr->parentPtr->privatePtr;
+ if (macParent == NULL) {
+ return; /* TODO: Probably should be a panic */
+ }
+ }
+
+ TkMacInvalClipRgns(macParent->winPtr);
+ TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW);
+
+ deltaX = - macWin->xOff;
+ deltaY = - macWin->yOff;
+
+ /*
+ * If macWin->winPtr is an embedded window, don't offset by its
+ * parent's borderwidth...
+ */
+
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
+ } else {
+ parentBorderwidth = 0;
+ }
+ deltaX += macParent->xOff + parentBorderwidth +
+ macWin->winPtr->changes.x;
+ deltaY += macParent->yOff + parentBorderwidth +
+ macWin->winPtr->changes.y;
+
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ TkMacWinBounds(macWin->winPtr, &bounds);
+ InvalRect(&bounds);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XRaiseWindow --
+ *
+ * Change the stacking order of a window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the stacking order of the specified window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XRaiseWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+
+ display->request++;
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ TkWmRestackToplevel(macWin->winPtr, Above, NULL);
+ } else {
+ /* TODO: this should generate damage */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XConfigureWindow --
+ *
+ * Change the size, position, stacking, or border of the specified
+ * window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the attributes of the specified window. Note that we
+ * ignore the passed in values and use the values stored in the
+ * TkWindow data structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XConfigureWindow(
+ Display* display, /* Display. */
+ Window w, /* Window. */
+ unsigned int value_mask,
+ XWindowChanges* values)
+{
+ MacDrawable *macWin = (MacDrawable *) w;
+ TkWindow *winPtr = macWin->winPtr;
+
+ display->request++;
+
+ /*
+ * Change the shape and/or position of the window.
+ */
+
+ if (value_mask & (CWX|CWY|CWWidth|CWHeight)) {
+ XMoveResizeWindow(display, w, winPtr->changes.x, winPtr->changes.y,
+ winPtr->changes.width, winPtr->changes.height);
+ }
+
+ /*
+ * Change the stacking order of the window. Tk actuall keeps all
+ * the information we need for stacking order. All we need to do
+ * is make sure the clipping regions get updated and generate damage
+ * that will ensure things get drawn correctly.
+ */
+
+ if (value_mask & CWStackMode) {
+ Rect bounds;
+ GWorldPtr destPort;
+
+ destPort = TkMacGetDrawablePort(w);
+ if (destPort != NULL) {
+ SetPort((GrafPtr) destPort);
+ TkMacInvalClipRgns(winPtr->parentPtr);
+ TkMacWinBounds(winPtr, &bounds);
+ InvalRect(&bounds);
+ }
+ }
+
+ /* TkGenWMMoveRequestEvent(macWin->winPtr,
+ macWin->winPtr->changes.x, macWin->winPtr->changes.y); */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacUpdateClipRgn --
+ *
+ * This function updates the cliping regions for a given window
+ * and all of its children. Once updated the TK_CLIP_INVALID flag
+ * in the subwindow data structure is unset. The TK_CLIP_INVALID
+ * flag should always be unset before any drawing is attempted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clip regions for the window and its children are updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacUpdateClipRgn(
+ TkWindow *winPtr)
+{
+ RgnHandle rgn;
+ int x, y;
+ TkWindow *win2Ptr;
+
+ if (winPtr == NULL) {
+ return;
+ }
+
+ if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
+ rgn = winPtr->privatePtr->aboveClipRgn;
+ if (tmpRgn == NULL) {
+ tmpRgn = NewRgn();
+ }
+
+ /*
+ * Start with a region defined by the window bounds.
+ */
+
+ x = winPtr->privatePtr->xOff;
+ y = winPtr->privatePtr->yOff;
+ SetRectRgn(rgn, (short) x, (short) y,
+ (short) (winPtr->changes.width + x),
+ (short) (winPtr->changes.height + y));
+
+ /*
+ * Clip away the area of any windows that may obscure this
+ * window.
+ * For a non-toplevel window, first, clip to the parents visable
+ * clip region.
+ * Second, clip away any siblings that are higher in the
+ * stacking order.
+ * For an embedded toplevel, just clip to the container's visible
+ * clip region. Remember, we only allow one contained window
+ * in a frame, and don't support any other widgets in the frame either.
+ * This is not currently enforced, however.
+ */
+
+ if (!Tk_IsTopLevel(winPtr)) {
+ TkMacUpdateClipRgn(winPtr->parentPtr);
+ SectRgn(rgn,
+ winPtr->parentPtr->privatePtr->aboveClipRgn, rgn);
+
+ win2Ptr = winPtr->nextPtr;
+ while (win2Ptr != NULL) {
+ if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
+ win2Ptr = win2Ptr->nextPtr;
+ continue;
+ }
+ x = win2Ptr->privatePtr->xOff;
+ y = win2Ptr->privatePtr->yOff;
+ SetRectRgn(tmpRgn, (short) x, (short) y,
+ (short) (win2Ptr->changes.width + x),
+ (short) (win2Ptr->changes.height + y));
+ DiffRgn(rgn, tmpRgn, rgn);
+
+ win2Ptr = win2Ptr->nextPtr;
+ }
+ } else if (Tk_IsEmbedded(winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(winPtr);
+
+ if (contWinPtr != NULL) {
+ TkMacUpdateClipRgn(contWinPtr);
+ SectRgn(rgn,
+ contWinPtr->privatePtr->aboveClipRgn, rgn);
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+
+ /*
+ * The final clip region is the aboveClip region (or visable
+ * region) minus all the children of this window.
+ * Alternatively, if the window is a container, we must also
+ * subtract the region of the embedded window.
+ */
+
+ rgn = winPtr->privatePtr->clipRgn;
+ CopyRgn(winPtr->privatePtr->aboveClipRgn, rgn);
+
+ win2Ptr = winPtr->childList;
+ while (win2Ptr != NULL) {
+ if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
+ win2Ptr = win2Ptr->nextPtr;
+ continue;
+ }
+ x = win2Ptr->privatePtr->xOff;
+ y = win2Ptr->privatePtr->yOff;
+ SetRectRgn(tmpRgn, (short) x, (short) y,
+ (short) (win2Ptr->changes.width + x),
+ (short) (win2Ptr->changes.height + y));
+ DiffRgn(rgn, tmpRgn, rgn);
+
+ win2Ptr = win2Ptr->nextPtr;
+ }
+
+ if (Tk_IsContainer(winPtr)) {
+ win2Ptr = TkpGetOtherWindow(winPtr);
+ if (win2Ptr != NULL) {
+ if (Tk_IsMapped(win2Ptr)) {
+ x = win2Ptr->privatePtr->xOff;
+ y = win2Ptr->privatePtr->yOff;
+ SetRectRgn(tmpRgn, (short) x, (short) y,
+ (short) (win2Ptr->changes.width + x),
+ (short) (win2Ptr->changes.height + y));
+ DiffRgn(rgn, tmpRgn, rgn);
+ }
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+
+ winPtr->privatePtr->flags &= ~TK_CLIP_INVALID;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacVisableClipRgn --
+ *
+ * This function returnd the Macintosh cliping region for the
+ * given window. A NULL Rgn means the window is not visable.
+ *
+ * Results:
+ * The region.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+RgnHandle
+TkMacVisableClipRgn(
+ TkWindow *winPtr)
+{
+ if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
+ TkMacUpdateClipRgn(winPtr);
+ }
+
+ return winPtr->privatePtr->clipRgn;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacInvalidateWindow --
+ *
+ * This function makes the window as invalid will generate damage
+ * for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Damage is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacInvalidateWindow(
+ MacDrawable *macWin, /* Make window that's causing damage. */
+ int flag) /* Should be TK_WINDOW_ONLY or
+ * TK_PARENT_WINDOW */
+{
+
+ if (flag == TK_WINDOW_ONLY) {
+ InvalRgn(macWin->clipRgn);
+ } else {
+ if (!EmptyRgn(macWin->aboveClipRgn)) {
+ InvalRgn(macWin->aboveClipRgn);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacGetDrawablePort --
+ *
+ * This function returns the Graphics Port for a given X drawable.
+ *
+ * Results:
+ * A GWorld pointer. Either an off screen pixmap or a Window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+GWorldPtr
+TkMacGetDrawablePort(
+ Drawable drawable)
+{
+ MacDrawable *macWin = (MacDrawable *) drawable;
+
+ if (macWin == NULL) {
+ return NULL;
+ }
+
+ /*
+ * This is NULL for off-screen pixmaps. Then the portPtr
+ * always points to the off-screen port, and we don't
+ * have to worry about containment
+ */
+
+ if (macWin->clipRgn == NULL) {
+ return macWin->portPtr;
+ }
+
+ /*
+ * If the Drawable is in an embedded window, use the Port of its container.
+ *
+ * TRICKY POINT: we can have cases when a toplevel is being destroyed
+ * where the winPtr for the toplevel has been freed, but the children
+ * are not all the way destroyed. The children will call this function
+ * as they are being destroyed, but Tk_IsEmbedded will return garbage.
+ * So we check the copy of the TK_EMBEDDED flag we put into the
+ * toplevel's macWin flags.
+ */
+
+ if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
+ return macWin->toplevel->portPtr;
+ } else {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
+
+ if (contWinPtr != NULL) {
+ return TkMacGetDrawablePort((Drawable) contWinPtr->privatePtr);
+ } else {
+ panic("TkMacGetDrawablePort couldn't find container");
+ return NULL;
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacInvalClipRgns --
+ *
+ * This function invalidates the clipping regions for a given
+ * window and all of its children. This function should be
+ * called whenever changes are made to subwindows that would
+ * effect the size or position of windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cliping regions for the window and its children are
+ * mark invalid. (Make sure they are valid before drawing.)
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacInvalClipRgns(
+ TkWindow *winPtr)
+{
+ TkWindow *childPtr;
+
+ /*
+ * If already marked we can stop because all
+ * decendants will also already be marked.
+ */
+ if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
+ return;
+ }
+
+ winPtr->privatePtr->flags |= TK_CLIP_INVALID;
+
+ /*
+ * Invalidate clip regions for all children &
+ * their decendants - unless the child is a toplevel.
+ */
+ childPtr = winPtr->childList;
+ while (childPtr != NULL) {
+ if (!Tk_IsTopLevel(childPtr) && Tk_IsMapped(childPtr)) {
+ TkMacInvalClipRgns(childPtr);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+
+ /*
+ * Also, if the window is a container, mark its embedded window
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+
+ if (childPtr != NULL && Tk_IsMapped(childPtr)) {
+ TkMacInvalClipRgns(childPtr);
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacWinBounds --
+ *
+ * Given a Tk window this function determines the windows
+ * bounds in relation to the Macintosh window's coordinate
+ * system. This is also the same coordinate system as the
+ * Tk toplevel window in which this window is contained.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacWinBounds(
+ TkWindow *winPtr,
+ Rect *bounds)
+{
+ bounds->left = (short) winPtr->privatePtr->xOff;
+ bounds->top = (short) winPtr->privatePtr->yOff;
+ bounds->right = (short) (winPtr->privatePtr->xOff +
+ winPtr->changes.width);
+ bounds->bottom = (short) (winPtr->privatePtr->yOff +
+ winPtr->changes.height);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacMoveWindow --
+ *
+ * A replacement for the Macintosh MoveWindow function. This
+ * function adjusts the inputs to MoveWindow to offset the root of
+ * the window system. This has the effect of making the coords
+ * refer to the window dressing rather than the top of the content.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Moves the Macintosh window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+MacMoveWindow(
+ WindowRef window,
+ int x,
+ int y)
+{
+ int xOffset, yOffset;
+
+ TkMacWindowOffset(window, &xOffset, &yOffset);
+ MoveWindow((WindowRef) window,
+ (short) (x + xOffset), (short) (y + yOffset), false);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateOffsets --
+ *
+ * Updates the X & Y offsets of the given TkWindow from the
+ * TopLevel it is a decendant of.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The xOff & yOff fields for the Mac window datastructure
+ * is updated to the proper offset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateOffsets(
+ TkWindow *winPtr,
+ int deltaX,
+ int deltaY)
+{
+ TkWindow *childPtr;
+
+ if (winPtr->privatePtr == NULL) {
+ /*
+ * We havn't called Tk_MakeWindowExist for this window yet. The
+ * offset information will be postponed and calulated at that
+ * time. (This will usually only happen when a mapped parent is
+ * being moved but has child windows that have yet to be mapped.)
+ */
+ return;
+ }
+
+ winPtr->privatePtr->xOff += deltaX;
+ winPtr->privatePtr->yOff += deltaY;
+
+ childPtr = winPtr->childList;
+ while (childPtr != NULL) {
+ if (!Tk_IsTopLevel(childPtr)) {
+ UpdateOffsets(childPtr, deltaX, deltaY);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+ if (childPtr != NULL) {
+ UpdateOffsets(childPtr,deltaX,deltaY);
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetPixmap --
+ *
+ * Creates an in memory drawing surface.
+ *
+ * Results:
+ * Returns a handle to a new pixmap.
+ *
+ * Side effects:
+ * Allocates a new Macintosh GWorld.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+Tk_GetPixmap(
+ Display *display, /* Display for new pixmap (can be null). */
+ Drawable d, /* Drawable where pixmap will be used (ignored). */
+ int width, /* Dimensions of pixmap. */
+ int height,
+ int depth) /* Bits per pixel for pixmap. */
+{
+ QDErr err;
+ GWorldPtr gWorld;
+ Rect bounds;
+ MacDrawable *macPix;
+ PixMapHandle pixels;
+
+ if (display != NULL) {
+ display->request++;
+ }
+ macPix = (MacDrawable *) ckalloc(sizeof(MacDrawable));
+ macPix->winPtr = NULL;
+ macPix->xOff = 0;
+ macPix->yOff = 0;
+ macPix->clipRgn = NULL;
+ macPix->aboveClipRgn = NULL;
+ macPix->referenceCount = 0;
+ macPix->toplevel = NULL;
+ macPix->flags = 0;
+
+ bounds.top = bounds.left = 0;
+ bounds.right = (short) width;
+ bounds.bottom = (short) height;
+ if (depth != 1) {
+ depth = 0;
+ }
+
+ /*
+ * Allocate memory for the off screen pixmap. If we fail
+ * try again from system memory. Eventually, we may have
+ * to panic.
+ */
+ err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, 0);
+ if (err != noErr) {
+ err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, useTempMem);
+ }
+ if (err != noErr) {
+ panic("Out of memory: NewGWorld failed in Tk_GetPixmap");
+ }
+
+ /*
+ * Lock down the pixels so they don't move out from under us.
+ */
+ pixels = GetGWorldPixMap(gWorld);
+ LockPixels(pixels);
+ macPix->portPtr = gWorld;
+
+ return (Pixmap) macPix;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreePixmap --
+ *
+ * Release the resources associated with a pixmap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Deletes the Macintosh GWorld created by Tk_GetPixmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreePixmap(
+ Display *display, /* Display. */
+ Pixmap pixmap) /* Pixmap to destroy */
+{
+ MacDrawable *macPix = (MacDrawable *) pixmap;
+ PixMapHandle pixels;
+
+ display->request++;
+ pixels = GetGWorldPixMap(macPix->portPtr);
+ UnlockPixels(pixels);
+ DisposeGWorld(macPix->portPtr);
+ ckfree((char *) macPix);
+}
+
diff --git a/mac/tkMacTest.c b/mac/tkMacTest.c
new file mode 100644
index 0000000..46a7bb1
--- /dev/null
+++ b/mac/tkMacTest.c
@@ -0,0 +1,81 @@
+/*
+ * tkMacTest.c --
+ *
+ * Contains commands for platform specific tests for
+ * the Macintosh platform.
+ *
+ * Copyright (c) 1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacTest.c 1.2 96/12/15 14:34:00
+ */
+
+#include <Types.h>
+
+/*
+ * Forward declarations of procedures defined later in this file:
+ */
+
+int TkplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp));
+static int DebuggerCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int argc, char **argv));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkplatformtestInit --
+ *
+ * Defines commands that test platform specific functionality for
+ * Unix platforms.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Defines new commands.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkplatformtestInit(
+ Tcl_Interp *interp) /* Interpreter to add commands to. */
+{
+ /*
+ * Add commands for platform specific tests on MacOS here.
+ */
+
+ Tcl_CreateCommand(interp, "debugger", DebuggerCmd,
+ (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DebuggerCmd --
+ *
+ * This procedure simply calls the low level debugger.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DebuggerCmd(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ int argc, /* Not used. */
+ char **argv) /* Not used. */
+{
+ Debugger();
+ return TCL_OK;
+}
diff --git a/mac/tkMacWindowMgr.c b/mac/tkMacWindowMgr.c
new file mode 100644
index 0000000..7c8206c
--- /dev/null
+++ b/mac/tkMacWindowMgr.c
@@ -0,0 +1,1591 @@
+/*
+ * tkMacWindowMgr.c --
+ *
+ * Implements common window manager functions for the Macintosh.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacWindowMgr.c 1.59 97/11/20 18:56:39
+ */
+
+#include <Events.h>
+#include <Dialogs.h>
+#include <EPPC.h>
+#include <Windows.h>
+#include <ToolUtils.h>
+#include <DiskInit.h>
+#include <LowMem.h>
+#include <Timer.h>
+#include <Sound.h>
+
+#include "tkInt.h"
+#include "tkPort.h"
+#include "tkMacInt.h"
+
+#define TK_DEFAULT_ABOUT 128
+
+/*
+ * Declarations of global variables defined in this file.
+ */
+
+int tkMacAppInFront = true; /* Boolean variable for determining
+ * if we are the frontmost app. */
+
+/*
+ * Non-standard event types that can be passed to HandleEvent.
+ * These are defined and used by Netscape's plugin architecture.
+ */
+#define getFocusEvent (osEvt + 16)
+#define loseFocusEvent (osEvt + 17)
+#define adjustCursorEvent (osEvt + 18)
+
+/*
+ * Declarations of static variables used in this file.
+ */
+
+static int gEatButtonUp = 0; /* 1 if we need to eat the next
+ * up event */
+static Tk_Window gGrabWinPtr = NULL; /* Current grab window, NULL if no grab. */
+static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */
+static RgnHandle gDamageRgn = NULL; /* Damage region used for handling
+ * screen updates. */
+/*
+ * Forward declarations of procedures used in this file.
+ */
+
+static void BringWindowForward _ANSI_ARGS_((WindowRef wRef));
+static int CheckEventsAvail _ANSI_ARGS_((void));
+static int GenerateActivateEvents _ANSI_ARGS_((EventRecord *eventPtr,
+ Window window));
+static int GenerateFocusEvent _ANSI_ARGS_((EventRecord *eventPtr,
+ Window window));
+static int GenerateKeyEvent _ANSI_ARGS_((EventRecord *eventPtr,
+ Window window));
+static int GenerateUpdateEvent _ANSI_ARGS_((EventRecord *eventPtr,
+ Window window));
+static void GenerateUpdates _ANSI_ARGS_((RgnHandle updateRgn,
+ TkWindow *winPtr));
+static int GeneratePollingEvents _ANSI_ARGS_((void));
+static int GeneratePollingEvents2 _ANSI_ARGS_((Window window));
+static OSErr TellWindowDefProcToCalcRegions _ANSI_ARGS_((WindowRef wRef));
+static int WindowManagerMouse _ANSI_ARGS_((EventRecord *theEvent,
+ Window window));
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WindowManagerMouse --
+ *
+ * This function determines if a button event is a "Window Manager"
+ * function or an event that should be passed to Tk's event
+ * queue.
+ *
+ * Results:
+ * Return true if event was placed on Tk's event queue.
+ *
+ * Side effects:
+ * Depends on where the button event occurs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WindowManagerMouse(
+ EventRecord *eventPtr, /* Macintosh event record. */
+ Window window) /* Window pointer. */
+{
+ WindowRef whichWindow, frontWindow;
+ Tk_Window tkwin;
+ Point where, where2;
+ int xOffset, yOffset;
+ short windowPart;
+
+ frontWindow = FrontWindow();
+
+ /*
+ * The window manager only needs to know about mouse down events
+ * and sometimes we need to "eat" the mouse up. Otherwise, we
+ * just pass the event to Tk.
+ */
+ if (eventPtr->what == mouseUp) {
+ if (gEatButtonUp) {
+ gEatButtonUp = false;
+ return false;
+ }
+ return TkGenerateButtonEvent(eventPtr->where.h, eventPtr->where.v,
+ window, TkMacButtonKeyState());
+ }
+
+ windowPart = FindWindow(eventPtr->where, &whichWindow);
+ tkwin = Tk_IdToWindow(tkDisplayList->display, window);
+ switch (windowPart) {
+ case inSysWindow:
+ SystemClick(eventPtr, (GrafPort *) whichWindow);
+ return false;
+ case inDrag:
+ if (whichWindow != frontWindow) {
+ if (!(eventPtr->modifiers & cmdKey)) {
+ if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
+ SysBeep(1);
+ return false;
+ }
+ }
+ }
+
+ /*
+ * Call DragWindow to move the window around. It will
+ * also eat the mouse up event.
+ */
+ SetPort((GrafPort *) whichWindow);
+ where.h = where.v = 0;
+ LocalToGlobal(&where);
+ DragWindow(whichWindow, eventPtr->where,
+ &tcl_macQdPtr->screenBits.bounds);
+ gEatButtonUp = false;
+
+ where2.h = where2.v = 0;
+ LocalToGlobal(&where2);
+ if (EqualPt(where, where2)) {
+ return false;
+ }
+
+ TkMacWindowOffset(whichWindow, &xOffset, &yOffset);
+ where2.h -= xOffset;
+ where2.v -= yOffset;
+ TkGenWMConfigureEvent(tkwin, where2.h, where2.v,
+ -1, -1, TK_LOCATION_CHANGED);
+ return true;
+ case inGrow:
+ case inContent:
+ if (whichWindow != frontWindow ) {
+ /*
+ * This click moves the window forward. We don't want
+ * the corasponding mouse-up to be reported to the application
+ * or else it will mess up some Tk scripts.
+ */
+ if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
+ SysBeep(1);
+ return false;
+ }
+ BringWindowForward(whichWindow);
+ gEatButtonUp = true;
+ SetPort((GrafPort *) whichWindow);
+ return false;
+ } else {
+ /*
+ * Generally the content region is the domain of Tk
+ * sub-windows. However, one exception is the grow
+ * region. A button down in this area will be handled
+ * by the window manager. Note: this means that Tk
+ * may not get button down events in this area!
+ */
+
+ if (TkMacGrowToplevel(whichWindow, eventPtr->where) == true) {
+ return true;
+ } else {
+ return TkGenerateButtonEvent(eventPtr->where.h,
+ eventPtr->where.v, window, TkMacButtonKeyState());
+ }
+ }
+ case inGoAway:
+ if (TrackGoAway( whichWindow, eventPtr->where)) {
+ if (tkwin == NULL) {
+ return false;
+ }
+ TkGenWMDestroyEvent(tkwin);
+ return true;
+ }
+ return false;
+ case inMenuBar:
+ {
+ int oldMode;
+ KeyMap theKeys;
+
+ GetKeys(theKeys);
+ oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ TkMacClearMenubarActive();
+ TkMacHandleMenuSelect(MenuSelect(eventPtr->where),
+ theKeys[1] & 4);
+ Tcl_SetServiceMode(oldMode);
+ return true; /* TODO: may not be on event on queue. */
+ }
+ case inZoomIn:
+ case inZoomOut:
+ if (TkMacZoomToplevel(whichWindow, eventPtr->where, windowPart)
+ == true) {
+ return true;
+ } else {
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkAboutDlg --
+ *
+ * Displays the default Tk About box. This code uses Macintosh
+ * resources to define the content of the About Box.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkAboutDlg()
+{
+ DialogPtr aboutDlog;
+ short itemHit = -9;
+
+ aboutDlog = GetNewDialog(128, NULL, (void*)(-1));
+
+ if (!aboutDlog) {
+ return;
+ }
+
+ SelectWindow((WindowRef) aboutDlog);
+
+ while (itemHit != 1) {
+ ModalDialog( NULL, &itemHit);
+ }
+ DisposDialog(aboutDlog);
+ aboutDlog = NULL;
+
+ SelectWindow(FrontWindow());
+
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateUpdateEvent --
+ *
+ * Given a Macintosh update event this function generates all the
+ * X update events needed by Tk.
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GenerateUpdateEvent(
+ EventRecord *eventPtr, /* Incoming Mac event */
+ Window window) /* Root X window for event. */
+{
+ WindowRef macWindow;
+ register TkWindow *winPtr;
+
+ winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
+
+ if (winPtr == NULL) {
+ return false;
+ }
+
+ if (gDamageRgn == NULL) {
+ gDamageRgn = NewRgn();
+ }
+
+ /*
+ * After the call to BeginUpdate the visable region (visRgn) of the
+ * window is equal to the intersection of the real visable region and
+ * the update region for this event. We use this region in all of our
+ * calculations.
+ */
+
+ if (eventPtr->message != NULL) {
+ macWindow = (WindowRef) TkMacGetDrawablePort(window);
+ BeginUpdate(macWindow);
+ GenerateUpdates(macWindow->visRgn, winPtr);
+ EndUpdate(macWindow);
+ return true;
+ } else {
+ /*
+ * This event didn't come from the system. This might
+ * occur if we are running from inside of Netscape.
+ * In this we shouldn't call BeginUpdate as the vis region
+ * may be NULL.
+ */
+ RgnHandle rgn;
+ Rect bounds;
+
+ rgn = NewRgn();
+ TkMacWinBounds(winPtr, &bounds);
+ RectRgn(rgn, &bounds);
+ GenerateUpdates(rgn, winPtr);
+ DisposeRgn(rgn);
+ return true;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateUpdates --
+ *
+ * Given a Macintosh update region and a Tk window this function
+ * geneates a X damage event for the window if it is within the
+ * update region. The function will then recursivly have each
+ * damaged window generate damage events for its child windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateUpdates(
+ RgnHandle updateRgn,
+ TkWindow *winPtr)
+{
+ TkWindow *childPtr;
+ XEvent event;
+ Rect bounds;
+
+ TkMacWinBounds(winPtr, &bounds);
+
+ if (bounds.top > (*updateRgn)->rgnBBox.bottom ||
+ (*updateRgn)->rgnBBox.top > bounds.bottom ||
+ bounds.left > (*updateRgn)->rgnBBox.right ||
+ (*updateRgn)->rgnBBox.left > bounds.right ||
+ !RectInRgn(&bounds, updateRgn)) {
+ return;
+ }
+
+ event.xany.serial = Tk_Display(winPtr)->request;
+ event.xany.send_event = false;
+ event.xany.window = Tk_WindowId(winPtr);
+ event.xany.display = Tk_Display(winPtr);
+
+ event.type = Expose;
+
+ /*
+ * Compute the bounding box of the area that the damage occured in.
+ */
+
+ /*
+ * CopyRgn(TkMacVisableClipRgn(winPtr), rgn);
+ * TODO: this call doesn't work doing resizes!!!
+ */
+ RectRgn(gDamageRgn, &bounds);
+ SectRgn(gDamageRgn, updateRgn, gDamageRgn);
+ OffsetRgn(gDamageRgn, -bounds.left, -bounds.top);
+ event.xexpose.x = (**gDamageRgn).rgnBBox.left;
+ event.xexpose.y = (**gDamageRgn).rgnBBox.top;
+ event.xexpose.width = (**gDamageRgn).rgnBBox.right -
+ (**gDamageRgn).rgnBBox.left;
+ event.xexpose.height = (**gDamageRgn).rgnBBox.bottom -
+ (**gDamageRgn).rgnBBox.top;
+ event.xexpose.count = 0;
+
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
+ /*
+ * Generate updates for the children of this window
+ */
+
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
+ continue;
+ }
+
+ GenerateUpdates(updateRgn, childPtr);
+ }
+
+ /*
+ * Generate updates for any contained windows
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+ if (childPtr != NULL && Tk_IsMapped(childPtr)) {
+ GenerateUpdates(updateRgn, childPtr);
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGenerateButtonEvent --
+ *
+ * Given a global x & y position and the button key status this
+ * procedure generates the appropiate X button event. It also
+ * handles the state changes needed to implement implicit grabs.
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ * Grab state may also change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkGenerateButtonEvent(
+ int x, /* X location of mouse */
+ int y, /* Y location of mouse */
+ Window window, /* X Window containing button event. */
+ unsigned int state) /* Button Key state suitable for X event */
+{
+ WindowRef whichWin, frontWin;
+ Point where;
+ Tk_Window tkwin;
+ int dummy;
+
+ /*
+ * ButtonDown events will always occur in the front
+ * window. ButtonUp events, however, may occur anywhere
+ * on the screen. ButtonUp events should only be sent
+ * to Tk if in the front window or during an implicit grab.
+ */
+ where.h = x;
+ where.v = y;
+ FindWindow(where, &whichWin);
+ frontWin = FrontWindow();
+
+ if ((frontWin == NULL) || (frontWin != whichWin && gGrabWinPtr == NULL)) {
+ return false;
+ }
+
+ tkwin = Tk_IdToWindow(tkDisplayList->display, window);
+
+ GlobalToLocal(&where);
+ if (tkwin != NULL) {
+ tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v, &dummy, &dummy);
+ }
+
+ Tk_UpdatePointer(tkwin, x, y, state);
+
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateActivateEvents --
+ *
+ * Generate Activate/Deactivate events from a Macintosh Activate
+ * event. Note, the activate-on-foreground bit must be set in the
+ * SIZE flags to ensure we get Activate/Deactivate in addition to
+ * Susspend/Resume events.
+ *
+ * Results:
+ * Returns true if events were generate.
+ *
+ * Side effects:
+ * Queue events on Tk's event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GenerateActivateEvents(
+ EventRecord *eventPtr, /* Incoming Mac event */
+ Window window) /* Root X window for event. */
+{
+ TkWindow *winPtr;
+
+ winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
+ if (winPtr == NULL || winPtr->window == None) {
+ return false;
+ }
+
+ TkGenerateActivateEvents(winPtr,
+ (eventPtr->modifiers & activeFlag) ? 1 : 0);
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XSetInputFocus --
+ *
+ * Change the focus window for the application.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XSetInputFocus(
+ Display* display,
+ Window focus,
+ int revert_to,
+ Time time)
+{
+ /*
+ * Don't need to do a thing. Tk manages the focus for us.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpChangeFocus --
+ *
+ * This procedure is a stub on the Mac because we always own the
+ * focus if we are a front most application.
+ *
+ * Results:
+ * The return value is the serial number of the command that
+ * changed the focus. It may be needed by the caller to filter
+ * out focus change events that were queued before the command.
+ * If the procedure doesn't actually change the focus then
+ * it returns 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpChangeFocus(winPtr, force)
+ TkWindow *winPtr; /* Window that is to receive the X focus. */
+ int force; /* Non-zero means claim the focus even
+ * if it didn't originally belong to
+ * topLevelPtr's application. */
+{
+ /*
+ * We don't really need to do anything on the Mac. Tk will
+ * keep all this state for us.
+ */
+
+ if (winPtr->atts.override_redirect) {
+ return 0;
+ }
+
+ /*
+ * Remember the current serial number for the X server and issue
+ * a dummy server request. This marks the position at which we
+ * changed the focus, so we can distinguish FocusIn and FocusOut
+ * events on either side of the mark.
+ */
+
+ return NextRequest(winPtr->display);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateFocusEvent --
+ *
+ * Generate FocusIn/FocusOut events from a Macintosh Activate
+ * event. Note, the activate-on-foreground bit must be set in
+ * the SIZE flags to ensure we get Activate/Deactivate in addition
+ * to Susspend/Resume events.
+ *
+ * Results:
+ * Returns true if events were generate.
+ *
+ * Side effects:
+ * Queue events on Tk's event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GenerateFocusEvent(
+ EventRecord *eventPtr, /* Incoming Mac event */
+ Window window) /* Root X window for event. */
+{
+ XEvent event;
+ Tk_Window tkwin;
+
+ tkwin = Tk_IdToWindow(tkDisplayList->display, window);
+ if (tkwin == NULL) {
+ return false;
+ }
+
+ /*
+ * Generate FocusIn and FocusOut events. This event
+ * is only sent to the toplevel window.
+ */
+
+ if (eventPtr->modifiers & activeFlag) {
+ event.xany.type = FocusIn;
+ } else {
+ event.xany.type = FocusOut;
+ }
+
+ event.xany.serial = tkDisplayList->display->request;
+ event.xany.send_event = False;
+ event.xfocus.display = tkDisplayList->display;
+ event.xfocus.window = window;
+ event.xfocus.mode = NotifyNormal;
+ event.xfocus.detail = NotifyDetailNone;
+
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateKeyEvent --
+ *
+ * Given Macintosh keyUp, keyDown & autoKey events this function
+ * generates the appropiate X key events. The window that is passed
+ * should represent the frontmost window - which will recieve the
+ * event.
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GenerateKeyEvent(
+ EventRecord *eventPtr, /* Incoming Mac event */
+ Window window) /* Root X window for event. */
+{
+ Point where;
+ Tk_Window tkwin;
+ XEvent event;
+
+ /*
+ * The focus must be in the FrontWindow on the Macintosh.
+ * We then query Tk to determine the exact Tk window
+ * that owns the focus.
+ */
+
+ tkwin = Tk_IdToWindow(tkDisplayList->display, window);
+ tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr;
+ if (tkwin == NULL) {
+ return false;
+ }
+
+ where.v = eventPtr->where.v;
+ where.h = eventPtr->where.h;
+
+ event.xany.send_event = False;
+ event.xkey.same_screen = true;
+ event.xkey.subwindow = None;
+ event.xkey.time = TkpGetMS();
+
+ event.xkey.x_root = where.h;
+ event.xkey.y_root = where.v;
+ GlobalToLocal(&where);
+ Tk_TopCoordsToWindow(tkwin, where.h, where.v,
+ &event.xkey.x, &event.xkey.y);
+ event.xkey.keycode = eventPtr->message;
+
+ event.xany.serial = Tk_Display(tkwin)->request;
+ event.xkey.window = Tk_WindowId(tkwin);
+ event.xkey.display = Tk_Display(tkwin);
+ event.xkey.root = XRootWindow(Tk_Display(tkwin), 0);
+ event.xkey.state = TkMacButtonKeyState();
+
+ if (eventPtr->what == keyDown) {
+ event.xany.type = KeyPress;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ } else if (eventPtr->what == keyUp) {
+ event.xany.type = KeyRelease;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ } else {
+ /*
+ * Autokey events send multiple XKey events.
+ *
+ * Note: the last KeyRelease will always be missed with
+ * this scheme. However, most Tk scripts don't look for
+ * KeyUp events so we should be OK.
+ */
+ event.xany.type = KeyRelease;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ event.xany.type = KeyPress;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ }
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GeneratePollingEvents --
+ *
+ * This function polls the mouse position and generates X Motion,
+ * Enter & Leave events. The cursor is also updated at this
+ * time.
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ * The cursor may be changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GeneratePollingEvents()
+{
+ Tk_Window tkwin, rootwin;
+ Window window;
+ WindowRef whichwindow, frontWin;
+ Point whereLocal, whereGlobal;
+ Boolean inContentRgn;
+ short part;
+ int local_x, local_y;
+ int generatedEvents = false;
+
+ /*
+ * First we get the current mouse position and determine
+ * what Tk window the mouse is over (if any).
+ */
+ frontWin = FrontWindow();
+ if (frontWin == NULL) {
+ return false;
+ }
+ SetPort((GrafPort *) frontWin);
+
+ GetMouse(&whereLocal);
+ whereGlobal = whereLocal;
+ LocalToGlobal(&whereGlobal);
+
+ part = FindWindow(whereGlobal, &whichwindow);
+ inContentRgn = (part == inContent || part == inGrow);
+
+ if ((frontWin != whichwindow) || !inContentRgn) {
+ tkwin = NULL;
+ } else {
+ window = TkMacGetXWindow(whichwindow);
+ rootwin = Tk_IdToWindow(tkDisplayList->display, window);
+ if (rootwin == NULL) {
+ tkwin = NULL;
+ } else {
+ tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v,
+ &local_x, &local_y);
+ }
+ }
+
+ /*
+ * The following call will generate the appropiate X events and
+ * adjust any state that Tk must remember.
+ */
+
+ if ((tkwin == NULL) && (gGrabWinPtr != NULL)) {
+ tkwin = gGrabWinPtr;
+ }
+ Tk_UpdatePointer(tkwin, whereGlobal.h, whereGlobal.v,
+ TkMacButtonKeyState());
+
+ /*
+ * Finally, we make sure the proper cursor is installed. The installation
+ * is polled to 1) make our resize hack work, and 2) make sure we have the
+ * proper cursor even if someone else changed the cursor out from under
+ * us.
+ */
+ if ((gGrabWinPtr == NULL) && (part == inGrow) &&
+ TkMacResizable((TkWindow *) tkwin) &&
+ (TkMacGetScrollbarGrowWindow((TkWindow *) tkwin) == NULL)) {
+ TkMacInstallCursor(1);
+ } else {
+ TkMacInstallCursor(0);
+ }
+
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GeneratePollingEvents2 --
+ *
+ * This function polls the mouse position and generates X Motion,
+ * Enter & Leave events. The cursor is also updated at this
+ * time. NOTE: this version is for Netscape!!!
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Additional events may be place on the Tk event queue.
+ * The cursor may be changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GeneratePollingEvents2(
+ Window window)
+{
+ Tk_Window tkwin, rootwin;
+ WindowRef whichwindow, frontWin;
+ Point whereLocal, whereGlobal;
+ int local_x, local_y;
+ int generatedEvents = false;
+ Rect bounds;
+
+ /*
+ * First we get the current mouse position and determine
+ * what Tk window the mouse is over (if any).
+ */
+ frontWin = FrontWindow();
+ if (frontWin == NULL) {
+ return false;
+ }
+ SetPort((GrafPort *) frontWin);
+
+ GetMouse(&whereLocal);
+ whereGlobal = whereLocal;
+ LocalToGlobal(&whereGlobal);
+
+ /*
+ * Determine if we are in a Tk window or not.
+ */
+ whichwindow = (WindowRef) TkMacGetDrawablePort(window);
+ if (whichwindow != frontWin) {
+ tkwin = NULL;
+ } else {
+ rootwin = Tk_IdToWindow(tkDisplayList->display, window);
+ TkMacWinBounds((TkWindow *) rootwin, &bounds);
+ if (!PtInRect(whereLocal, &bounds)) {
+ tkwin = NULL;
+ } else {
+ tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v,
+ &local_x, &local_y);
+ }
+ }
+
+ /*
+ * The following call will generate the appropiate X events and
+ * adjust any state that Tk must remember.
+ */
+
+ if ((tkwin == NULL) && (gGrabWinPtr != NULL)) {
+ tkwin = gGrabWinPtr;
+ }
+ Tk_UpdatePointer(tkwin, whereGlobal.h, whereGlobal.v,
+ TkMacButtonKeyState());
+
+ /*
+ * Finally, we make sure the proper cursor is installed. The installation
+ * is polled to 1) make our resize hack work, and 2) make sure we have the
+ * proper cursor even if someone else changed the cursor out from under
+ * us.
+ */
+ TkMacInstallCursor(0);
+
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacButtonKeyState --
+ *
+ * Returns the current state of the button & modifier keys.
+ *
+ * Results:
+ * A bitwise inclusive OR of a subset of the following:
+ * Button1Mask, ShiftMask, LockMask, ControlMask, Mod?Mask,
+ * Mod?Mask.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+unsigned int
+TkMacButtonKeyState()
+{
+ unsigned int state = 0;
+ KeyMap theKeys;
+
+ if (Button() & !gEatButtonUp) {
+ state |= Button1Mask;
+ }
+
+ GetKeys(theKeys);
+
+ if (theKeys[1] & 2) {
+ state |= LockMask;
+ }
+
+ if (theKeys[1] & 1) {
+ state |= ShiftMask;
+ }
+
+ if (theKeys[1] & 8) {
+ state |= ControlMask;
+ }
+
+ if (theKeys[1] & 32768) {
+ state |= Mod1Mask; /* command key */
+ }
+
+ if (theKeys[1] & 4) {
+ state |= Mod2Mask; /* option key */
+ }
+
+ return state;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XGrabKeyboard --
+ *
+ * Simulates a keyboard grab by setting the focus.
+ *
+ * Results:
+ * Always returns GrabSuccess.
+ *
+ * Side effects:
+ * Sets the keyboard focus to the specified window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XGrabKeyboard(
+ Display* display,
+ Window grab_window,
+ Bool owner_events,
+ int pointer_mode,
+ int keyboard_mode,
+ Time time)
+{
+ gKeyboardWinPtr = Tk_IdToWindow(display, grab_window);
+ return GrabSuccess;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XUngrabKeyboard --
+ *
+ * Releases the simulated keyboard grab.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the keyboard focus back to the value before the grab.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XUngrabKeyboard(
+ Display* display,
+ Time time)
+{
+ gKeyboardWinPtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XQueryPointer --
+ *
+ * Check the current state of the mouse. This is not a complete
+ * implementation of this function. It only computes the root
+ * coordinates and the current mask.
+ *
+ * Results:
+ * Sets root_x_return, root_y_return, and mask_return. Returns
+ * true on success.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+XQueryPointer(
+ Display* display,
+ Window w,
+ Window* root_return,
+ Window* child_return,
+ int* root_x_return,
+ int* root_y_return,
+ int* win_x_return,
+ int* win_y_return,
+ unsigned int* mask_return)
+{
+ Point where;
+
+ GetMouse(&where);
+ LocalToGlobal(&where);
+ *root_x_return = where.h;
+ *root_y_return = where.v;
+ *mask_return = TkMacButtonKeyState();
+ return True;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacGenerateTime --
+ *
+ * Returns the total number of ticks from startup This function
+ * is used to generate the time of generated X events.
+ *
+ * Results:
+ * Returns the current time (ticks from startup).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Time
+TkMacGenerateTime()
+{
+ return (Time) LMGetTicks();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacConvertEvent --
+ *
+ * This function converts a Macintosh event into zero or more
+ * Tcl events.
+ *
+ * Results:
+ * Returns 1 if event added to Tcl queue, 0 otherwse.
+ *
+ * Side effects:
+ * May add events to Tcl's event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacConvertEvent(
+ EventRecord *eventPtr)
+{
+ WindowRef whichWindow;
+ Window window;
+ int eventFound = false;
+
+ switch (eventPtr->what) {
+ case nullEvent:
+ case adjustCursorEvent:
+ if (GeneratePollingEvents()) {
+ eventFound = true;
+ }
+ break;
+ case updateEvt:
+ whichWindow = (WindowRef)eventPtr->message;
+ window = TkMacGetXWindow(whichWindow);
+ if (GenerateUpdateEvent(eventPtr, window)) {
+ eventFound = true;
+ }
+ break;
+ case mouseDown:
+ case mouseUp:
+ FindWindow(eventPtr->where, &whichWindow);
+ window = TkMacGetXWindow(whichWindow);
+ if (WindowManagerMouse(eventPtr, window)) {
+ eventFound = true;
+ }
+ break;
+ case autoKey:
+ case keyDown:
+ /*
+ * Handle menu-key events here. If it is *not*
+ * a menu key - just fall through to handle as a
+ * normal key event.
+ */
+ if ((eventPtr->modifiers & cmdKey) == cmdKey) {
+ long menuResult;
+ int oldMode;
+
+ oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+ menuResult = MenuKey(eventPtr->message & charCodeMask);
+ Tcl_SetServiceMode(oldMode);
+
+ if (HiWord(menuResult) != 0) {
+ TkMacHandleMenuSelect(menuResult, false);
+ break;
+ }
+ }
+ case keyUp:
+ whichWindow = FrontWindow();
+ window = TkMacGetXWindow(whichWindow);
+ eventFound |= GenerateKeyEvent(eventPtr, window);
+ break;
+ case activateEvt:
+ window = TkMacGetXWindow((WindowRef) eventPtr->message);
+ eventFound |= GenerateActivateEvents(eventPtr, window);
+ eventFound |= GenerateFocusEvent(eventPtr, window);
+ break;
+ case getFocusEvent:
+ eventPtr->modifiers |= activeFlag;
+ window = TkMacGetXWindow((WindowRef) eventPtr->message);
+ eventFound |= GenerateFocusEvent(eventPtr, window);
+ break;
+ case loseFocusEvent:
+ eventPtr->modifiers &= ~activeFlag;
+ window = TkMacGetXWindow((WindowRef) eventPtr->message);
+ eventFound |= GenerateFocusEvent(eventPtr, window);
+ break;
+ case kHighLevelEvent:
+ TkMacDoHLEvent(eventPtr);
+ /* TODO: should return true if events were placed on event queue. */
+ break;
+ case osEvt:
+ /*
+ * Do clipboard conversion.
+ */
+ switch ((eventPtr->message & osEvtMessageMask) >> 24) {
+ case mouseMovedMessage:
+ if (GeneratePollingEvents()) {
+ eventFound = true;
+ }
+ break;
+ case suspendResumeMessage:
+ if (!(eventPtr->message & resumeFlag)) {
+ TkSuspendClipboard();
+ }
+ tkMacAppInFront = (eventPtr->message & resumeFlag);
+ break;
+ }
+ break;
+ case diskEvt:
+ /*
+ * Disk insertion.
+ */
+ if (HiWord(eventPtr->message) != noErr) {
+ Point pt;
+
+ DILoad();
+ pt.v = pt.h = 120; /* parameter ignored in sys 7 */
+ DIBadMount(pt, eventPtr->message);
+ DIUnload();
+ }
+ break;
+ }
+
+ return eventFound;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacConvertTkEvent --
+ *
+ * This function converts a Macintosh event into zero or more
+ * Tcl events.
+ *
+ * Results:
+ * Returns 1 if event added to Tcl queue, 0 otherwse.
+ *
+ * Side effects:
+ * May add events to Tcl's event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacConvertTkEvent(
+ EventRecord *eventPtr,
+ Window window)
+{
+ int eventFound = false;
+ Point where;
+
+ switch (eventPtr->what) {
+ case nullEvent:
+ case adjustCursorEvent:
+ if (GeneratePollingEvents2(window)) {
+ eventFound = true;
+ }
+ break;
+ case updateEvt:
+ if (GenerateUpdateEvent(eventPtr, window)) {
+ eventFound = true;
+ }
+ break;
+ case mouseDown:
+ case mouseUp:
+ GetMouse(&where);
+ LocalToGlobal(&where);
+ eventFound |= TkGenerateButtonEvent(where.h, where.v,
+ window, TkMacButtonKeyState());
+ break;
+ case autoKey:
+ case keyDown:
+ /*
+ * Handle menu-key events here. If it is *not*
+ * a menu key - just fall through to handle as a
+ * normal key event.
+ */
+ if ((eventPtr->modifiers & cmdKey) == cmdKey) {
+ long menuResult = MenuKey(eventPtr->message & charCodeMask);
+
+ if (HiWord(menuResult) != 0) {
+ TkMacHandleMenuSelect(menuResult, false);
+ break;
+ }
+ }
+ case keyUp:
+ eventFound |= GenerateKeyEvent(eventPtr, window);
+ break;
+ case activateEvt:
+ eventFound |= GenerateActivateEvents(eventPtr, window);
+ eventFound |= GenerateFocusEvent(eventPtr, window);
+ break;
+ case getFocusEvent:
+ eventPtr->modifiers |= activeFlag;
+ eventFound |= GenerateFocusEvent(eventPtr, window);
+ break;
+ case loseFocusEvent:
+ eventPtr->modifiers &= ~activeFlag;
+ eventFound |= GenerateFocusEvent(eventPtr, window);
+ break;
+ case kHighLevelEvent:
+ TkMacDoHLEvent(eventPtr);
+ /* TODO: should return true if events were placed on event queue. */
+ break;
+ case osEvt:
+ /*
+ * Do clipboard conversion.
+ */
+ switch ((eventPtr->message & osEvtMessageMask) >> 24) {
+ case mouseMovedMessage:
+ if (GeneratePollingEvents2(window)) {
+ eventFound = true;
+ }
+ break;
+ case suspendResumeMessage:
+ if (!(eventPtr->message & resumeFlag)) {
+ TkSuspendClipboard();
+ }
+ tkMacAppInFront = (eventPtr->message & resumeFlag);
+ break;
+ }
+ break;
+ case diskEvt:
+ /*
+ * Disk insertion.
+ */
+ if (HiWord(eventPtr->message) != noErr) {
+ Point pt;
+
+ DILoad();
+ pt.v = pt.h = 120; /* parameter ignored in sys 7 */
+ DIBadMount(pt, eventPtr->message);
+ DIUnload();
+ }
+ break;
+ }
+
+ return eventFound;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckEventsAvail --
+ *
+ * Checks to see if events are available on the Macintosh queue.
+ * This function looks for both queued events (eg. key & button)
+ * and generated events (update).
+ *
+ * Results:
+ * True is events exist, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CheckEventsAvail()
+{
+ QHdrPtr evPtr;
+ WindowPeek macWinPtr;
+
+ evPtr = GetEvQHdr();
+ if (evPtr->qHead != NULL) {
+ return true;
+ }
+
+ macWinPtr = (WindowPeek) FrontWindow();
+ while (macWinPtr != NULL) {
+ if (!EmptyRgn(macWinPtr->updateRgn)) {
+ return true;
+ }
+ macWinPtr = macWinPtr->nextWindow;
+ }
+ return false;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetCapture --
+ *
+ * This function captures the mouse so that all future events
+ * will be reported to this window, even if the mouse is outside
+ * the window. If the specified window is NULL, then the mouse
+ * is released.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the capture flag and captures the mouse.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetCapture(
+ TkWindow *winPtr) /* Capture window, or NULL. */
+{
+ while ((winPtr != NULL) && !Tk_IsTopLevel(winPtr)) {
+ winPtr = winPtr->parentPtr;
+ }
+ gGrabWinPtr = (Tk_Window) winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacWindowOffset --
+ *
+ * Determines the x and y offset from the orgin of the toplevel
+ * window dressing (the structure region, ie. title bar) and the
+ * orgin of the content area.
+ *
+ * Results:
+ * The x & y offset in pixels.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacWindowOffset(
+ WindowRef wRef,
+ int *xOffset,
+ int *yOffset)
+{
+ OSErr err = noErr;
+ WindowPeek wPeek = (WindowPeek) wRef;
+ RgnHandle strucRgn = wPeek->strucRgn;
+ RgnHandle contRgn = wPeek->contRgn;
+ Rect strucRect, contRect;
+
+ if (!EmptyRgn(strucRgn) && !EmptyRgn(contRgn)) {
+ strucRect = (**strucRgn).rgnBBox;
+ contRect = (**contRgn).rgnBBox;
+ } else {
+ /*
+ * The current window's regions are not up to date.
+ * Probably because the window isn't visable. What we
+ * will do is save the old regions, have the window calculate
+ * what the regions should be, and then restore it self.
+ */
+ strucRgn = NewRgn( );
+ contRgn = NewRgn( );
+
+ if (!strucRgn || !contRgn) {
+ err = MemError( );
+ } else {
+ CopyRgn(wPeek->strucRgn, strucRgn);
+ CopyRgn(wPeek->contRgn, contRgn);
+
+ if (!(err = TellWindowDefProcToCalcRegions(wRef))) {
+ strucRect = (**(wPeek->strucRgn)).rgnBBox;
+ contRect = (**(wPeek->contRgn)).rgnBBox;
+ }
+
+ CopyRgn(strucRgn, wPeek->strucRgn);
+ CopyRgn(contRgn, wPeek->contRgn);
+ }
+
+ if (contRgn) {
+ DisposeRgn(contRgn);
+ }
+
+ if (strucRgn) {
+ DisposeRgn(strucRgn);
+ }
+ }
+
+ if (!err) {
+ *xOffset = contRect.left - strucRect.left;
+ *yOffset = contRect.top - strucRect.top;
+ } else {
+ *xOffset = 0;
+ *yOffset = 0;
+ }
+
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TellWindowDefProcToCalcRegions --
+ *
+ * Force a Macintosh window to recalculate it's content and
+ * structure regions.
+ *
+ * Results:
+ * An OS error.
+ *
+ * Side effects:
+ * The windows content and structure regions may be updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static OSErr
+TellWindowDefProcToCalcRegions(
+ WindowRef wRef)
+{
+ OSErr err = noErr;
+ SInt8 hState;
+ Handle wdef = ((WindowPeek) wRef)->windowDefProc;
+
+ /*
+ * Load and lock the window definition procedure for
+ * the window.
+ */
+ hState = HGetState(wdef);
+ if (!(err = MemError())) {
+ LoadResource(wdef);
+ if (!(err = ResError())) {
+ MoveHHi(wdef);
+ err = MemError();
+ if (err == memLockedErr) {
+ err = noErr;
+ } else if (!err) {
+ HLock(wdef);
+ err = MemError();
+ }
+ }
+ }
+
+ /*
+ * Assuming there are no errors we now call the window definition
+ * procedure to tell it to calculate the regions for the window.
+ */
+
+ if (err == noErr) {
+ (void) CallWindowDefProc((UniversalProcPtr) *wdef,
+ GetWVariant(wRef), wRef, wCalcRgns, 0);
+
+ HSetState(wdef, hState);
+ if (!err) {
+ err = MemError();
+ }
+ }
+
+ return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * BringWindowForward --
+ *
+ * Bring this background window to the front. We also set state
+ * so Tk thinks the button is currently up.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is brought forward.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+BringWindowForward(
+ WindowRef wRef)
+{
+ SelectWindow(wRef);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetMS --
+ *
+ * Return a relative time in milliseconds. It doesn't matter
+ * when the epoch was.
+ *
+ * Results:
+ * Number of milliseconds.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+unsigned long
+TkpGetMS()
+{
+ long long * int64Ptr;
+ UnsignedWide micros;
+
+ Microseconds(&micros);
+ int64Ptr = (long long *) &micros;
+
+ /*
+ * We need 64 bit math to do this. This is available in CW 11
+ * and on. Other's will need to use a different scheme.
+ */
+
+ *int64Ptr /= 1000;
+
+ return (long) *int64Ptr;
+}
diff --git a/mac/tkMacWm.c b/mac/tkMacWm.c
new file mode 100644
index 0000000..56c4b8a
--- /dev/null
+++ b/mac/tkMacWm.c
@@ -0,0 +1,4213 @@
+/*
+ * tkMacWm.c --
+ *
+ * This module takes care of the interactions between a Tk-based
+ * application and the window manager. Among other things, it
+ * implements the "wm" command and passes geometry information
+ * to the window manager.
+ *
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacWm.c 1.72 97/10/29 13:27:30
+ */
+
+#include <Gestalt.h>
+#include <QDOffscreen.h>
+#include <Windows.h>
+#include <ToolUtils.h>
+
+#include "tkPort.h"
+#include "tkInt.h"
+#include "tkMacInt.h"
+#include <errno.h>
+#include "tkScrollbar.h"
+
+/*
+ * If HAVE_APPEARANCE is defined in MW_TkHeader.pch then we must have the
+ * Appearance manager header & library. If so we can use these new API's to
+ * have the iconify code do the right thing.
+ */
+
+#ifdef HAVE_APPEARANCE
+# include <Appearance.h>
+#endif
+
+/*
+ * A data structure of the following type holds information for
+ * each window manager protocol (such as WM_DELETE_WINDOW) for
+ * which a handler (i.e. a Tcl command) has been defined for a
+ * particular top-level window.
+ */
+
+typedef struct ProtocolHandler {
+ Atom protocol; /* Identifies the protocol. */
+ struct ProtocolHandler *nextPtr;
+ /* Next in list of protocol handlers for
+ * the same top-level window, or NULL for
+ * end of list. */
+ Tcl_Interp *interp; /* Interpreter in which to invoke command. */
+ char command[4]; /* Tcl command to invoke when a client
+ * message for this protocol arrives.
+ * The actual size of the structure varies
+ * to accommodate the needs of the actual
+ * command. THIS MUST BE THE LAST FIELD OF
+ * THE STRUCTURE. */
+} ProtocolHandler;
+
+#define HANDLER_SIZE(cmdLength) \
+((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength))
+
+/*
+ * A data structure of the following type holds window-manager-related
+ * information for each top-level window in an application.
+ */
+
+typedef struct TkWmInfo {
+ TkWindow *winPtr; /* Pointer to main Tk information for
+ * this window. */
+ Window reparent; /* If the window has been reparented, this
+ * gives the ID of the ancestor of the window
+ * that is a child of the root window (may
+ * not be window's immediate parent). If
+ * the window isn't reparented, this has the
+ * value None. */
+ Tk_Uid titleUid; /* Title to display in window caption. If
+ * NULL, use name of widget. */
+ Tk_Uid iconName; /* Name to display in icon. */
+ Window master; /* Master window for TRANSIENT_FOR property,
+ * or None. */
+ XWMHints hints; /* Various pieces of information for
+ * window manager. */
+ char *leaderName; /* Path name of leader of window group
+ * (corresponds to hints.window_group).
+ * Malloc-ed. Note: this field doesn't
+ * get updated if leader is destroyed. */
+ char *masterWindowName; /* Path name of window specified as master
+ * in "wm transient" command, or NULL.
+ * Malloc-ed. Note: this field doesn't
+ * get updated if masterWindowName is
+ * destroyed. */
+ Tk_Window icon; /* Window to use as icon for this window,
+ * or NULL. */
+ Tk_Window iconFor; /* Window for which this window is icon, or
+ * NULL if this isn't an icon for anyone. */
+
+ /*
+ * Information used to construct an XSizeHints structure for
+ * the window manager:
+ */
+
+ int sizeHintsFlags; /* Flags word for XSizeHints structure.
+ * If the PBaseSize flag is set then the
+ * window is gridded; otherwise it isn't
+ * gridded. */
+ int minWidth, minHeight; /* Minimum dimensions of window, in
+ * grid units, not pixels. */
+ int maxWidth, maxHeight; /* Maximum dimensions of window, in
+ * grid units, not pixels. */
+ Tk_Window gridWin; /* Identifies the window that controls
+ * gridding for this top-level, or NULL if
+ * the top-level isn't currently gridded. */
+ int widthInc, heightInc; /* Increments for size changes (# pixels
+ * per step). */
+ struct {
+ int x; /* numerator */
+ int y; /* denominator */
+ } minAspect, maxAspect; /* Min/max aspect ratios for window. */
+ int reqGridWidth, reqGridHeight;
+ /* The dimensions of the window (in
+ * grid units) requested through
+ * the geometry manager. */
+ int gravity; /* Desired window gravity. */
+
+ /*
+ * Information used to manage the size and location of a window.
+ */
+
+ int width, height; /* Desired dimensions of window, specified
+ * in grid units. These values are
+ * set by the "wm geometry" command and by
+ * ConfigureNotify events (for when wm
+ * resizes window). -1 means user hasn't
+ * requested dimensions. */
+ int x, y; /* Desired X and Y coordinates for window.
+ * These values are set by "wm geometry",
+ * plus by ConfigureNotify events (when wm
+ * moves window). These numbers are
+ * different than the numbers stored in
+ * winPtr->changes because (a) they could be
+ * measured from the right or bottom edge
+ * of the screen (see WM_NEGATIVE_X and
+ * WM_NEGATIVE_Y flags) and (b) if the window
+ * has been reparented then they refer to the
+ * parent rather than the window itself. */
+ int parentWidth, parentHeight;
+ /* Width and height of reparent, in pixels
+ * *including border*. If window hasn't been
+ * reparented then these will be the outer
+ * dimensions of the window, including
+ * border. */
+ int xInParent, yInParent; /* Offset of window within reparent, measured
+ * from upper-left outer corner of parent's
+ * border to upper-left outer corner of child's
+ * border. If not reparented then these are
+ * zero. */
+ int configWidth, configHeight;
+ /* Dimensions passed to last request that we
+ * issued to change geometry of window. Used
+ * to eliminate redundant resize operations. */
+
+ /*
+ * Information about the virtual root window for this top-level,
+ * if there is one.
+ */
+
+ Window vRoot; /* Virtual root window for this top-level,
+ * or None if there is no virtual root
+ * window (i.e. just use the screen's root). */
+ int vRootX, vRootY; /* Position of the virtual root inside the
+ * root window. If the WM_VROOT_OFFSET_STALE
+ * flag is set then this information may be
+ * incorrect and needs to be refreshed from
+ * the X server. If vRoot is None then these
+ * values are both 0. */
+ unsigned int vRootWidth, vRootHeight;
+ /* Dimensions of the virtual root window.
+ * If vRoot is None, gives the dimensions
+ * of the containing screen. This information
+ * is never stale, even though vRootX and
+ * vRootY can be. */
+
+ /*
+ * List of children of the toplevel which have private colormaps.
+ */
+
+ TkWindow **cmapList; /* Array of window with private colormaps. */
+ int cmapCount; /* Number of windows in array. */
+
+ /*
+ * Miscellaneous information.
+ */
+
+ ProtocolHandler *protPtr; /* First in list of protocol handlers for
+ * this window (NULL means none). */
+ int cmdArgc; /* Number of elements in cmdArgv below. */
+ char **cmdArgv; /* Array of strings to store in the
+ * WM_COMMAND property. NULL means nothing
+ * available. */
+ char *clientMachine; /* String to store in WM_CLIENT_MACHINE
+ * property, or NULL. */
+ int flags; /* Miscellaneous flags, defined below. */
+
+ /*
+ * Macintosh information.
+ */
+ int style; /* Native window style. */
+ TkWindow *scrollWinPtr; /* Ptr to scrollbar handling grow widget. */
+} WmInfo;
+
+
+/*
+ * Flag values for WmInfo structures:
+ *
+ * WM_NEVER_MAPPED - non-zero means window has never been
+ * mapped; need to update all info when
+ * window is first mapped.
+ * WM_UPDATE_PENDING - non-zero means a call to UpdateGeometryInfo
+ * has already been scheduled for this
+ * window; no need to schedule another one.
+ * WM_NEGATIVE_X - non-zero means x-coordinate is measured in
+ * pixels from right edge of screen, rather
+ * than from left edge.
+ * WM_NEGATIVE_Y - non-zero means y-coordinate is measured in
+ * pixels up from bottom of screen, rather than
+ * down from top.
+ * WM_UPDATE_SIZE_HINTS - non-zero means that new size hints need to be
+ * propagated to window manager.
+ * WM_SYNC_PENDING - set to non-zero while waiting for the window
+ * manager to respond to some state change.
+ * WM_VROOT_OFFSET_STALE - non-zero means that (x,y) offset information
+ * about the virtual root window is stale and
+ * needs to be fetched fresh from the X server.
+ * WM_ABOUT_TO_MAP - non-zero means that the window is about to
+ * be mapped by TkWmMapWindow. This is used
+ * by UpdateGeometryInfo to modify its behavior.
+ * WM_MOVE_PENDING - non-zero means the application has requested
+ * a new position for the window, but it hasn't
+ * been reflected through the window manager
+ * yet.
+ * WM_COLORMAPS_EXPLICIT - non-zero means the colormap windows were
+ * set explicitly via "wm colormapwindows".
+ * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows"
+ * was called the top-level itself wasn't
+ * specified, so we added it implicitly at
+ * the end of the list.
+ * WM_WIDTH_NOT_RESIZABLE - non-zero means that we're not supposed to
+ * allow the user to change the width of the
+ * window (controlled by "wm resizable"
+ * command).
+ * WM_HEIGHT_NOT_RESIZABLE - non-zero means that we're not supposed to
+ * allow the user to change the height of the
+ * window (controlled by "wm resizable"
+ * command).
+ */
+
+#define WM_NEVER_MAPPED 1
+#define WM_UPDATE_PENDING 2
+#define WM_NEGATIVE_X 4
+#define WM_NEGATIVE_Y 8
+#define WM_UPDATE_SIZE_HINTS 0x10
+#define WM_SYNC_PENDING 0x20
+#define WM_VROOT_OFFSET_STALE 0x40
+#define WM_ABOUT_TO_MAP 0x100
+#define WM_MOVE_PENDING 0x200
+#define WM_COLORMAPS_EXPLICIT 0x400
+#define WM_ADDED_TOPLEVEL_COLORMAP 0x800
+#define WM_WIDTH_NOT_RESIZABLE 0x1000
+#define WM_HEIGHT_NOT_RESIZABLE 0x2000
+
+/*
+ * This is a list of all of the toplevels that have been mapped so far. It is
+ * used by the menu code to inval windows that were damaged by menus, and will
+ * eventually also be used to keep track of floating windows.
+ */
+
+TkMacWindowList *tkMacWindowListPtr = NULL;
+
+/*
+ * The variable below is used to enable or disable tracing in this
+ * module. If tracing is enabled, then information is printed on
+ * standard output about interesting interactions with the window
+ * manager.
+ */
+
+static int wmTracing = 0;
+
+/*
+ * The following structure is the official type record for geometry
+ * management of top-level windows.
+ */
+
+static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
+ Tk_Window tkwin));
+
+static Tk_GeomMgr wmMgrType = {
+ "wm", /* name */
+ TopLevelReqProc, /* requestProc */
+ (Tk_GeomLostSlaveProc *) NULL, /* lostSlaveProc */
+};
+
+/*
+ * Hash table for Mac Window -> TkWindow mapping.
+ */
+
+static Tcl_HashTable windowTable;
+static int windowHashInit = false;
+
+void MacMoveWindow(WindowRef window, int x, int y);
+
+/*
+ * Forward declarations for procedures defined in this file:
+ */
+
+static int HaveAppearance _ANSI_ARGS_((void));
+static void InitialWindowBounds _ANSI_ARGS_((TkWindow *winPtr,
+ Rect *geometry));
+static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,
+ char *string, TkWindow *winPtr));
+static void TopLevelEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
+ Tk_Window tkwin));
+static void UpdateGeometryInfo _ANSI_ARGS_((
+ ClientData clientData));
+static void UpdateSizeHints _ANSI_ARGS_((TkWindow *winPtr));
+static void UpdateVRootGeometry _ANSI_ARGS_((WmInfo *wmPtr));
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkWmNewWindow --
+ *
+ * This procedure is invoked whenever a new top-level
+ * window is created. Its job is to initialize the WmInfo
+ * structure for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A WmInfo structure gets allocated and initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkWmNewWindow(
+ TkWindow *winPtr) /* Newly-created top-level window. */
+{
+ register WmInfo *wmPtr;
+
+ wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));
+ wmPtr->winPtr = winPtr;
+ wmPtr->reparent = None;
+ wmPtr->titleUid = NULL;
+ wmPtr->iconName = NULL;
+ wmPtr->master = None;
+ wmPtr->hints.flags = InputHint | StateHint;
+ wmPtr->hints.input = True;
+ wmPtr->hints.initial_state = NormalState;
+ wmPtr->hints.icon_pixmap = None;
+ wmPtr->hints.icon_window = None;
+ wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
+ wmPtr->hints.icon_mask = None;
+ wmPtr->hints.window_group = None;
+ wmPtr->leaderName = NULL;
+ wmPtr->masterWindowName = NULL;
+ wmPtr->icon = NULL;
+ wmPtr->iconFor = NULL;
+ wmPtr->sizeHintsFlags = 0;
+ wmPtr->minWidth = wmPtr->minHeight = 1;
+
+ /*
+ * Default the maximum dimensions to the size of the display, minus
+ * a guess about how space is needed for window manager decorations.
+ */
+
+ wmPtr->maxWidth = DisplayWidth(winPtr->display, winPtr->screenNum) - 15;
+ wmPtr->maxHeight = DisplayHeight(winPtr->display, winPtr->screenNum) - 30;
+ wmPtr->gridWin = NULL;
+ wmPtr->widthInc = wmPtr->heightInc = 1;
+ wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
+ wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;
+ wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1;
+ wmPtr->gravity = NorthWestGravity;
+ wmPtr->width = -1;
+ wmPtr->height = -1;
+ wmPtr->x = winPtr->changes.x;
+ wmPtr->y = winPtr->changes.y;
+ wmPtr->parentWidth = winPtr->changes.width
+ + 2*winPtr->changes.border_width;
+ wmPtr->parentHeight = winPtr->changes.height
+ + 2*winPtr->changes.border_width;
+ wmPtr->xInParent = 0;
+ wmPtr->yInParent = 0;
+ wmPtr->cmapList = NULL;
+ wmPtr->cmapCount = 0;
+ wmPtr->configWidth = -1;
+ wmPtr->configHeight = -1;
+ wmPtr->vRoot = None;
+ wmPtr->protPtr = NULL;
+ wmPtr->cmdArgv = NULL;
+ wmPtr->clientMachine = NULL;
+ wmPtr->flags = WM_NEVER_MAPPED;
+ wmPtr->style = zoomDocProc;
+ wmPtr->scrollWinPtr = NULL;
+ winPtr->wmInfoPtr = wmPtr;
+
+ UpdateVRootGeometry(wmPtr);
+
+ /*
+ * Tk must monitor structure events for top-level windows, in order
+ * to detect size and position changes caused by window managers.
+ */
+
+ Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,
+ TopLevelEventProc, (ClientData) winPtr);
+
+ /*
+ * Arrange for geometry requests to be reflected from the window
+ * to the window manager.
+ */
+
+ Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkWmMapWindow --
+ *
+ * This procedure is invoked to map a top-level window. This
+ * module gets a chance to update all window-manager-related
+ * information in properties before the window manager sees
+ * the map event and checks the properties. It also gets to
+ * decide whether or not to even map the window after all.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Properties of winPtr may get updated to provide up-to-date
+ * information to the window manager. The window may also get
+ * mapped, but it may not be if this procedure decides that
+ * isn't appropriate (e.g. because the window is withdrawn).
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkWmMapWindow(
+ TkWindow *winPtr) /* Top-level window that's about to
+ * be mapped. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Point where = {0, 0};
+ int xOffset, yOffset;
+ int firstMap = false;
+ MacDrawable *macWin;
+
+ if (wmPtr->flags & WM_NEVER_MAPPED) {
+ wmPtr->flags &= ~WM_NEVER_MAPPED;
+ firstMap = true;
+
+ /*
+ * Create the underlying Mac window for this Tk window.
+ */
+ macWin = (MacDrawable *) winPtr->window;
+ if (!TkMacHostToplevelExists(winPtr)) {
+ TkMacMakeRealWindowExist(winPtr);
+ }
+
+ /*
+ * Generate configure event when we first map the window.
+ */
+ LocalToGlobal(&where);
+ TkMacWindowOffset((WindowRef) TkMacGetDrawablePort((Drawable) macWin),
+ &xOffset, &yOffset);
+ where.h -= xOffset;
+ where.v -= yOffset;
+ TkGenWMConfigureEvent((Tk_Window) winPtr,
+ where.h, where.v, -1, -1, TK_LOCATION_CHANGED);
+
+ /*
+ * This is the first time this window has ever been mapped.
+ * Store all the window-manager-related information for the
+ * window.
+ */
+
+ if (wmPtr->titleUid == NULL) {
+ wmPtr->titleUid = winPtr->nameUid;
+ }
+
+ if (!Tk_IsEmbedded(winPtr)) {
+ TkSetWMName(winPtr, wmPtr->titleUid);
+ }
+
+ TkWmSetClass(winPtr);
+
+ if (wmPtr->iconName != NULL) {
+ XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);
+ }
+
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ }
+ if (wmPtr->hints.initial_state == WithdrawnState) {
+ return;
+ }
+
+ /*
+ * TODO: we need to display a window if it's iconic on creation.
+ */
+
+ if (wmPtr->hints.initial_state == IconicState) {
+ return;
+ }
+
+ /*
+ * Update geometry information.
+ */
+ wmPtr->flags |= WM_ABOUT_TO_MAP;
+ if (wmPtr->flags & WM_UPDATE_PENDING) {
+ Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
+ }
+ UpdateGeometryInfo((ClientData) winPtr);
+ wmPtr->flags &= ~WM_ABOUT_TO_MAP;
+
+ /*
+ * Map the window.
+ */
+
+ XMapWindow(winPtr->display, winPtr->window);
+
+ /*
+ * Now that the window is visable we can determine the offset
+ * from the window's content orgin to the window's decorative
+ * orgin (structure orgin).
+ */
+ TkMacWindowOffset((WindowRef) TkMacGetDrawablePort(Tk_WindowId(winPtr)),
+ &wmPtr->xInParent, &wmPtr->yInParent);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkWmUnmapWindow --
+ *
+ * This procedure is invoked to unmap a top-level window.
+ * On the Macintosh all we do is call XUnmapWindow.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Unmaps the window.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkWmUnmapWindow(
+ TkWindow *winPtr) /* Top-level window that's about to
+ * be mapped. */
+{
+ XUnmapWindow(winPtr->display, winPtr->window);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkWmDeadWindow --
+ *
+ * This procedure is invoked when a top-level window is
+ * about to be deleted. It cleans up the wm-related data
+ * structures for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The WmInfo structure for winPtr gets freed up.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkWmDeadWindow(winPtr)
+ TkWindow *winPtr; /* Top-level window that's being deleted. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ WmInfo *wmPtr2;
+
+ if (wmPtr == NULL) {
+ return;
+ }
+ if (wmPtr->hints.flags & IconPixmapHint) {
+ Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
+ }
+ if (wmPtr->hints.flags & IconMaskHint) {
+ Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
+ }
+ if (wmPtr->leaderName != NULL) {
+ ckfree(wmPtr->leaderName);
+ }
+ if (wmPtr->masterWindowName != NULL) {
+ ckfree(wmPtr->masterWindowName);
+ }
+ if (wmPtr->icon != NULL) {
+ wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ wmPtr2->iconFor = NULL;
+ }
+ if (wmPtr->iconFor != NULL) {
+ wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
+ wmPtr2->icon = NULL;
+ wmPtr2->hints.flags &= ~IconWindowHint;
+ }
+ while (wmPtr->protPtr != NULL) {
+ ProtocolHandler *protPtr;
+
+ protPtr = wmPtr->protPtr;
+ wmPtr->protPtr = protPtr->nextPtr;
+ Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
+ }
+ if (wmPtr->cmdArgv != NULL) {
+ ckfree((char *) wmPtr->cmdArgv);
+ }
+ if (wmPtr->clientMachine != NULL) {
+ ckfree((char *) wmPtr->clientMachine);
+ }
+ if (wmPtr->flags & WM_UPDATE_PENDING) {
+ Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
+ }
+ ckfree((char *) wmPtr);
+ winPtr->wmInfoPtr = NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkWmSetClass --
+ *
+ * This procedure is invoked whenever a top-level window's
+ * class is changed. If the window has been mapped then this
+ * procedure updates the window manager property for the
+ * class. If the window hasn't been mapped, the update is
+ * deferred until just before the first mapping.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A window property may get updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkWmSetClass(
+ TkWindow *winPtr) /* Newly-created top-level window. */
+{
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_WmCmd --
+ *
+ * This procedure is invoked to process the "wm" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+Tk_WmCmd(
+ ClientData clientData, /* Main window associated with
+ * interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ Tk_Window tkwin = (Tk_Window) clientData;
+ TkWindow *winPtr;
+ register WmInfo *wmPtr;
+ int c;
+ size_t length;
+
+ if (argc < 2) {
+ wrongNumArgs:
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ argv[0], " option window ?arg ...?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ c = argv[1][0];
+ length = strlen(argv[1]);
+ if ((c == 't') && (strncmp(argv[1], "tracing", length) == 0)
+ && (length >= 3)) {
+ if ((argc != 2) && (argc != 3)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " tracing ?boolean?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 2) {
+ interp->result = (wmTracing) ? "on" : "off";
+ return TCL_OK;
+ }
+ return Tcl_GetBoolean(interp, argv[2], &wmTracing);
+ }
+
+ if (argc < 3) {
+ goto wrongNumArgs;
+ }
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ Tcl_AppendResult(interp, "window \"", winPtr->pathName,
+ "\" isn't a top-level window", (char *) NULL);
+ return TCL_ERROR;
+ }
+ wmPtr = winPtr->wmInfoPtr;
+ if ((c == 'a') && (strncmp(argv[1], "aspect", length) == 0)) {
+ int numer1, denom1, numer2, denom2;
+
+ if ((argc != 3) && (argc != 7)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " aspect window ?minNumer minDenom ",
+ "maxNumer maxDenom?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->sizeHintsFlags & PAspect) {
+ sprintf(interp->result, "%d %d %d %d", wmPtr->minAspect.x,
+ wmPtr->minAspect.y, wmPtr->maxAspect.x,
+ wmPtr->maxAspect.y);
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ wmPtr->sizeHintsFlags &= ~PAspect;
+ } else {
+ if ((Tcl_GetInt(interp, argv[3], &numer1) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[4], &denom1) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[5], &numer2) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[6], &denom2) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
+ (denom2 <= 0)) {
+ interp->result = "aspect number can't be <= 0";
+ return TCL_ERROR;
+ }
+ wmPtr->minAspect.x = numer1;
+ wmPtr->minAspect.y = denom1;
+ wmPtr->maxAspect.x = numer2;
+ wmPtr->maxAspect.y = denom2;
+ wmPtr->sizeHintsFlags |= PAspect;
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ goto updateGeom;
+ } else if ((c == 'c') && (strncmp(argv[1], "client", length) == 0)
+ && (length >= 2)) {
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " client window ?name?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->clientMachine != NULL) {
+ interp->result = wmPtr->clientMachine;
+ }
+ return TCL_OK;
+ }
+ if (argv[3][0] == 0) {
+ if (wmPtr->clientMachine != NULL) {
+ ckfree((char *) wmPtr->clientMachine);
+ wmPtr->clientMachine = NULL;
+ }
+ return TCL_OK;
+ }
+ if (wmPtr->clientMachine != NULL) {
+ ckfree((char *) wmPtr->clientMachine);
+ }
+ wmPtr->clientMachine = (char *)
+ ckalloc((unsigned) (strlen(argv[3]) + 1));
+ strcpy(wmPtr->clientMachine, argv[3]);
+ } else if ((c == 'c') && (strncmp(argv[1], "colormapwindows", length) == 0)
+ && (length >= 3)) {
+ TkWindow **cmapList;
+ TkWindow *winPtr2;
+ int i, windowArgc, gotToplevel;
+ char **windowArgv;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " colormapwindows window ?windowList?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ for (i = 0; i < wmPtr->cmapCount; i++) {
+ if ((i == (wmPtr->cmapCount-1))
+ && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
+ break;
+ }
+ Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName);
+ }
+ return TCL_OK;
+ }
+ if (Tcl_SplitList(interp, argv[3], &windowArgc, &windowArgv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ cmapList = (TkWindow **) ckalloc((unsigned)
+ ((windowArgc+1)*sizeof(TkWindow*)));
+ for (i = 0; i < windowArgc; i++) {
+ winPtr2 = (TkWindow *) Tk_NameToWindow(interp, windowArgv[i],
+ tkwin);
+ if (winPtr2 == NULL) {
+ ckfree((char *) cmapList);
+ ckfree((char *) windowArgv);
+ return TCL_ERROR;
+ }
+ if (winPtr2 == winPtr) {
+ gotToplevel = 1;
+ }
+ if (winPtr2->window == None) {
+ Tk_MakeWindowExist((Tk_Window) winPtr2);
+ }
+ cmapList[i] = winPtr2;
+ }
+ if (!gotToplevel) {
+ wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
+ cmapList[windowArgc] = winPtr;
+ windowArgc++;
+ } else {
+ wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
+ }
+ wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
+ if (wmPtr->cmapList != NULL) {
+ ckfree((char *)wmPtr->cmapList);
+ }
+ wmPtr->cmapList = cmapList;
+ wmPtr->cmapCount = windowArgc;
+ ckfree((char *) windowArgv);
+
+ /*
+ * On the Macintosh all of this is just an excercise
+ * in compatability as we don't support colormaps. If
+ * we did they would be installed here.
+ */
+
+ return TCL_OK;
+ } else if ((c == 'c') && (strncmp(argv[1], "command", length) == 0)
+ && (length >= 3)) {
+ int cmdArgc;
+ char **cmdArgv;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " command window ?value?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->cmdArgv != NULL) {
+ interp->result = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv);
+ interp->freeProc = (Tcl_FreeProc *) free;
+ }
+ return TCL_OK;
+ }
+ if (argv[3][0] == 0) {
+ if (wmPtr->cmdArgv != NULL) {
+ ckfree((char *) wmPtr->cmdArgv);
+ wmPtr->cmdArgv = NULL;
+ }
+ return TCL_OK;
+ }
+ if (Tcl_SplitList(interp, argv[3], &cmdArgc, &cmdArgv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (wmPtr->cmdArgv != NULL) {
+ ckfree((char *) wmPtr->cmdArgv);
+ }
+ wmPtr->cmdArgc = cmdArgc;
+ wmPtr->cmdArgv = cmdArgv;
+ } else if ((c == 'd') && (strncmp(argv[1], "deiconify", length) == 0)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " deiconify window\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't deiconify ", argv[2],
+ ": it is an icon for ", winPtr->pathName, (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName,
+ ": it is an embedded window", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * TODO: may not want to call this function - look at Map events gened.
+ */
+
+ TkpWmSetState(winPtr, NormalState);
+ } else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0)
+ && (length >= 2)) {
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " focusmodel window ?active|passive?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ interp->result = wmPtr->hints.input ? "passive" : "active";
+ return TCL_OK;
+ }
+ c = argv[3][0];
+ length = strlen(argv[3]);
+ if ((c == 'a') && (strncmp(argv[3], "active", length) == 0)) {
+ wmPtr->hints.input = False;
+ } else if ((c == 'p') && (strncmp(argv[3], "passive", length) == 0)) {
+ wmPtr->hints.input = True;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", argv[3],
+ "\": must be active or passive", (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else if ((c == 'f') && (strncmp(argv[1], "frame", length) == 0)
+ && (length >= 2)) {
+ Window window;
+
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " frame window\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ window = wmPtr->reparent;
+ if (window == None) {
+ window = Tk_WindowId((Tk_Window) winPtr);
+ }
+ sprintf(interp->result, "0x%x", (unsigned int) window);
+ } else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0)
+ && (length >= 2)) {
+ char xSign, ySign;
+ int width, height;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " geometry window ?newGeometry?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
+ ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
+ if (wmPtr->gridWin != NULL) {
+ width = wmPtr->reqGridWidth + (winPtr->changes.width
+ - winPtr->reqWidth)/wmPtr->widthInc;
+ height = wmPtr->reqGridHeight + (winPtr->changes.height
+ - winPtr->reqHeight)/wmPtr->heightInc;
+ } else {
+ width = winPtr->changes.width;
+ height = winPtr->changes.height;
+ }
+ sprintf(interp->result, "%dx%d%c%d%c%d", width, height,
+ xSign, wmPtr->x, ySign, wmPtr->y);
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ wmPtr->width = -1;
+ wmPtr->height = -1;
+ goto updateGeom;
+ }
+ return ParseGeometry(interp, argv[3], winPtr);
+ } else if ((c == 'g') && (strncmp(argv[1], "grid", length) == 0)
+ && (length >= 3)) {
+ int reqWidth, reqHeight, widthInc, heightInc;
+
+ if ((argc != 3) && (argc != 7)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " grid window ?baseWidth baseHeight ",
+ "widthInc heightInc?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->sizeHintsFlags & PBaseSize) {
+ sprintf(interp->result, "%d %d %d %d", wmPtr->reqGridWidth,
+ wmPtr->reqGridHeight, wmPtr->widthInc,
+ wmPtr->heightInc);
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ /*
+ * Turn off gridding and reset the width and height
+ * to make sense as ungridded numbers.
+ */
+
+ wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
+ if (wmPtr->width != -1) {
+ wmPtr->width = winPtr->reqWidth + (wmPtr->width
+ - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ wmPtr->height = winPtr->reqHeight + (wmPtr->height
+ - wmPtr->reqGridHeight)*wmPtr->heightInc;
+ }
+ wmPtr->widthInc = 1;
+ wmPtr->heightInc = 1;
+ } else {
+ if ((Tcl_GetInt(interp, argv[3], &reqWidth) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[4], &reqHeight) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[5], &widthInc) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[6], &heightInc) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (reqWidth < 0) {
+ interp->result = "baseWidth can't be < 0";
+ return TCL_ERROR;
+ }
+ if (reqHeight < 0) {
+ interp->result = "baseHeight can't be < 0";
+ return TCL_ERROR;
+ }
+ if (widthInc < 0) {
+ interp->result = "widthInc can't be < 0";
+ return TCL_ERROR;
+ }
+ if (heightInc < 0) {
+ interp->result = "heightInc can't be < 0";
+ return TCL_ERROR;
+ }
+ Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
+ heightInc);
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ goto updateGeom;
+ } else if ((c == 'g') && (strncmp(argv[1], "group", length) == 0)
+ && (length >= 3)) {
+ Tk_Window tkwin2;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " group window ?pathName?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->hints.flags & WindowGroupHint) {
+ interp->result = wmPtr->leaderName;
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ wmPtr->hints.flags &= ~WindowGroupHint;
+ if (wmPtr->leaderName != NULL) {
+ ckfree(wmPtr->leaderName);
+ }
+ wmPtr->leaderName = NULL;
+ } else {
+ tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
+ if (tkwin2 == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_MakeWindowExist(tkwin2);
+ wmPtr->hints.window_group = Tk_WindowId(tkwin2);
+ wmPtr->hints.flags |= WindowGroupHint;
+ wmPtr->leaderName = ckalloc((unsigned) (strlen(argv[3])+1));
+ strcpy(wmPtr->leaderName, argv[3]);
+ }
+ } else if ((c == 'i') && (strncmp(argv[1], "iconbitmap", length) == 0)
+ && (length >= 5)) {
+ Pixmap pixmap;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " iconbitmap window ?bitmap?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->hints.flags & IconPixmapHint) {
+ interp->result = Tk_NameOfBitmap(winPtr->display,
+ wmPtr->hints.icon_pixmap);
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ if (wmPtr->hints.icon_pixmap != None) {
+ Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
+ }
+ wmPtr->hints.flags &= ~IconPixmapHint;
+ } else {
+ pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr,
+ Tk_GetUid(argv[3]));
+ if (pixmap == None) {
+ return TCL_ERROR;
+ }
+ wmPtr->hints.icon_pixmap = pixmap;
+ wmPtr->hints.flags |= IconPixmapHint;
+ }
+ } else if ((c == 'i') && (strncmp(argv[1], "iconify", length) == 0)
+ && (length >= 5)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " iconify window\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
+ "\": override-redirect flag is set", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->master != None) {
+ Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
+ "\": it is a transient", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't iconify ", argv[2],
+ ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
+ ": it is an embedded window", (char *) NULL);
+ return TCL_ERROR;
+ }
+ TkpWmSetState(winPtr, IconicState);
+ } else if ((c == 'i') && (strncmp(argv[1], "iconmask", length) == 0)
+ && (length >= 5)) {
+ Pixmap pixmap;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " iconmask window ?bitmap?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->hints.flags & IconMaskHint) {
+ interp->result = Tk_NameOfBitmap(winPtr->display,
+ wmPtr->hints.icon_mask);
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ if (wmPtr->hints.icon_mask != None) {
+ Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
+ }
+ wmPtr->hints.flags &= ~IconMaskHint;
+ } else {
+ pixmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[3]));
+ if (pixmap == None) {
+ return TCL_ERROR;
+ }
+ wmPtr->hints.icon_mask = pixmap;
+ wmPtr->hints.flags |= IconMaskHint;
+ }
+ } else if ((c == 'i') && (strncmp(argv[1], "iconname", length) == 0)
+ && (length >= 5)) {
+ if (argc > 4) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " iconname window ?newName?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ interp->result = (wmPtr->iconName != NULL) ? wmPtr->iconName : "";
+ return TCL_OK;
+ } else {
+ wmPtr->iconName = Tk_GetUid(argv[3]);
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName);
+ }
+ }
+ } else if ((c == 'i') && (strncmp(argv[1], "iconposition", length) == 0)
+ && (length >= 5)) {
+ int x, y;
+
+ if ((argc != 3) && (argc != 5)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " iconposition window ?x y?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->hints.flags & IconPositionHint) {
+ sprintf(interp->result, "%d %d", wmPtr->hints.icon_x,
+ wmPtr->hints.icon_y);
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ wmPtr->hints.flags &= ~IconPositionHint;
+ } else {
+ if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){
+ return TCL_ERROR;
+ }
+ wmPtr->hints.icon_x = x;
+ wmPtr->hints.icon_y = y;
+ wmPtr->hints.flags |= IconPositionHint;
+ }
+ } else if ((c == 'i') && (strncmp(argv[1], "iconwindow", length) == 0)
+ && (length >= 5)) {
+ Tk_Window tkwin2;
+ WmInfo *wmPtr2;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " iconwindow window ?pathName?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->icon != NULL) {
+ interp->result = Tk_PathName(wmPtr->icon);
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ wmPtr->hints.flags &= ~IconWindowHint;
+ if (wmPtr->icon != NULL) {
+ wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ wmPtr2->iconFor = NULL;
+ wmPtr2->hints.initial_state = WithdrawnState;
+ }
+ wmPtr->icon = NULL;
+ } else {
+ tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
+ if (tkwin2 == NULL) {
+ return TCL_ERROR;
+ }
+ if (!Tk_IsTopLevel(tkwin2)) {
+ Tcl_AppendResult(interp, "can't use ", argv[3],
+ " as icon window: not at top level", (char *) NULL);
+ return TCL_ERROR;
+ }
+ wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
+ if (wmPtr2->iconFor != NULL) {
+ Tcl_AppendResult(interp, argv[3], " is already an icon for ",
+ Tk_PathName(wmPtr2->iconFor), (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->icon != NULL) {
+ WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ wmPtr3->iconFor = NULL;
+ }
+ Tk_MakeWindowExist(tkwin2);
+ wmPtr->hints.icon_window = Tk_WindowId(tkwin2);
+ wmPtr->hints.flags |= IconWindowHint;
+ wmPtr->icon = tkwin2;
+ wmPtr2->iconFor = (Tk_Window) winPtr;
+ if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
+ /*
+ * Don't have iconwindows on the Mac. We just withdraw.
+ */
+
+ Tk_UnmapWindow(tkwin2);
+ }
+ }
+ } else if ((c == 'm') && (strncmp(argv[1], "maxsize", length) == 0)
+ && (length >= 2)) {
+ int width, height;
+ if ((argc != 3) && (argc != 5)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " maxsize window ?width height?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ sprintf(interp->result, "%d %d", wmPtr->maxWidth,
+ wmPtr->maxHeight);
+ return TCL_OK;
+ }
+ if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ wmPtr->maxWidth = width;
+ wmPtr->maxHeight = height;
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ goto updateGeom;
+ } else if ((c == 'm') && (strncmp(argv[1], "minsize", length) == 0)
+ && (length >= 2)) {
+ int width, height;
+ if ((argc != 3) && (argc != 5)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " minsize window ?width height?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ sprintf(interp->result, "%d %d", wmPtr->minWidth,
+ wmPtr->minHeight);
+ return TCL_OK;
+ }
+ if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
+ || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ wmPtr->minWidth = width;
+ wmPtr->minHeight = height;
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ goto updateGeom;
+ } else if ((c == 'o')
+ && (strncmp(argv[1], "overrideredirect", length) == 0)) {
+ int boolean;
+ XSetWindowAttributes atts;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " overrideredirect window ?boolean?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ interp->result = "1";
+ } else {
+ interp->result = "0";
+ }
+ return TCL_OK;
+ }
+ if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ atts.override_redirect = (boolean) ? True : False;
+ Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
+ &atts);
+ wmPtr->style = (boolean) ? plainDBox : documentProc;
+ } else if ((c == 'p') && (strncmp(argv[1], "positionfrom", length) == 0)
+ && (length >= 2)) {
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " positionfrom window ?user/program?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->sizeHintsFlags & USPosition) {
+ interp->result = "user";
+ } else if (wmPtr->sizeHintsFlags & PPosition) {
+ interp->result = "program";
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);
+ } else {
+ c = argv[3][0];
+ length = strlen(argv[3]);
+ if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
+ wmPtr->sizeHintsFlags &= ~PPosition;
+ wmPtr->sizeHintsFlags |= USPosition;
+ } else if ((c == 'p') &&
+ (strncmp(argv[3], "program", length) == 0)) {
+ wmPtr->sizeHintsFlags &= ~USPosition;
+ wmPtr->sizeHintsFlags |= PPosition;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", argv[3],
+ "\": must be program or user", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ goto updateGeom;
+ } else if ((c == 'p') && (strncmp(argv[1], "protocol", length) == 0)
+ && (length >= 2)) {
+ register ProtocolHandler *protPtr, *prevPtr;
+ Atom protocol;
+ int cmdLength;
+
+ if ((argc < 3) || (argc > 5)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " protocol window ?name? ?command?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ /*
+ * Return a list of all defined protocols for the window.
+ */
+ for (protPtr = wmPtr->protPtr; protPtr != NULL;
+ protPtr = protPtr->nextPtr) {
+ Tcl_AppendElement(interp,
+ Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol));
+ }
+ return TCL_OK;
+ }
+ protocol = Tk_InternAtom((Tk_Window) winPtr, argv[3]);
+ if (argc == 4) {
+ /*
+ * Return the command to handle a given protocol.
+ */
+ for (protPtr = wmPtr->protPtr; protPtr != NULL;
+ protPtr = protPtr->nextPtr) {
+ if (protPtr->protocol == protocol) {
+ interp->result = protPtr->command;
+ return TCL_OK;
+ }
+ }
+ return TCL_OK;
+ }
+
+ /*
+ * Delete any current protocol handler, then create a new
+ * one with the specified command, unless the command is
+ * empty.
+ */
+
+ for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;
+ prevPtr = protPtr, protPtr = protPtr->nextPtr) {
+ if (protPtr->protocol == protocol) {
+ if (prevPtr == NULL) {
+ wmPtr->protPtr = protPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = protPtr->nextPtr;
+ }
+ Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
+ break;
+ }
+ }
+ cmdLength = strlen(argv[4]);
+ if (cmdLength > 0) {
+ protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength));
+ protPtr->protocol = protocol;
+ protPtr->nextPtr = wmPtr->protPtr;
+ wmPtr->protPtr = protPtr;
+ protPtr->interp = interp;
+ strcpy(protPtr->command, argv[4]);
+ }
+ } else if ((c == 'r') && (strncmp(argv[1], "resizable", length) == 0)) {
+ int width, height;
+
+ if ((argc != 3) && (argc != 5)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " resizable window ?width height?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ sprintf(interp->result, "%d %d",
+ (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,
+ (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);
+ return TCL_OK;
+ }
+ if ((Tcl_GetBoolean(interp, argv[3], &width) != TCL_OK)
+ || (Tcl_GetBoolean(interp, argv[4], &height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (width) {
+ wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;
+ } else {
+ wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
+ }
+ if (height) {
+ wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;
+ } else {
+ wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ if (wmPtr->scrollWinPtr != NULL) {
+ TkScrollbarEventuallyRedraw(
+ (TkScrollbar *) wmPtr->scrollWinPtr->instanceData);
+ }
+ goto updateGeom;
+ } else if ((c == 's') && (strncmp(argv[1], "sizefrom", length) == 0)
+ && (length >= 2)) {
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " sizefrom window ?user|program?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->sizeHintsFlags & USSize) {
+ interp->result = "user";
+ } else if (wmPtr->sizeHintsFlags & PSize) {
+ interp->result = "program";
+ }
+ return TCL_OK;
+ }
+ if (*argv[3] == '\0') {
+ wmPtr->sizeHintsFlags &= ~(USSize|PSize);
+ } else {
+ c = argv[3][0];
+ length = strlen(argv[3]);
+ if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
+ wmPtr->sizeHintsFlags &= ~PSize;
+ wmPtr->sizeHintsFlags |= USSize;
+ } else if ((c == 'p')
+ && (strncmp(argv[3], "program", length) == 0)) {
+ wmPtr->sizeHintsFlags &= ~USSize;
+ wmPtr->sizeHintsFlags |= PSize;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", argv[3],
+ "\": must be program or user", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ goto updateGeom;
+ } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
+ && (length >= 2)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " state window\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->iconFor != NULL) {
+ interp->result = "icon";
+ } else {
+ switch (wmPtr->hints.initial_state) {
+ case NormalState:
+ interp->result = "normal";
+ break;
+ case IconicState:
+ interp->result = "iconic";
+ break;
+ case WithdrawnState:
+ interp->result = "withdrawn";
+ break;
+ case ZoomState:
+ interp->result = "zoomed";
+ break;
+ }
+ }
+ } else if ((c == 't') && (strncmp(argv[1], "title", length) == 0)
+ && (length >= 2)) {
+ if (argc > 4) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " title window ?newTitle?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ interp->result = (wmPtr->titleUid != NULL) ? wmPtr->titleUid
+ : winPtr->nameUid;
+ return TCL_OK;
+ } else {
+ wmPtr->titleUid = Tk_GetUid(argv[3]);
+ if (!(wmPtr->flags & WM_NEVER_MAPPED) && !Tk_IsEmbedded(winPtr)) {
+ TkSetWMName(winPtr, wmPtr->titleUid);
+ }
+ }
+ } else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0)
+ && (length >= 3)) {
+ Tk_Window master;
+
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " transient window ?master?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ if (wmPtr->master != None) {
+ interp->result = wmPtr->masterWindowName;
+ }
+ return TCL_OK;
+ }
+ if (argv[3][0] == '\0') {
+ wmPtr->master = None;
+ if (wmPtr->masterWindowName != NULL) {
+ ckfree(wmPtr->masterWindowName);
+ }
+ wmPtr->masterWindowName = NULL;
+ wmPtr->style = documentProc;
+ } else {
+ master = Tk_NameToWindow(interp, argv[3], tkwin);
+ if (master == NULL) {
+ return TCL_ERROR;
+ }
+ Tk_MakeWindowExist(master);
+ wmPtr->master = Tk_WindowId(master);
+ wmPtr->masterWindowName = ckalloc((unsigned) (strlen(argv[3])+1));
+ strcpy(wmPtr->masterWindowName, argv[3]);
+ wmPtr->style = plainDBox;
+ }
+ } else if ((c == 'w') && (strncmp(argv[1], "withdraw", length) == 0)) {
+ if (argc != 3) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " withdraw window\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't withdraw ", argv[2],
+ ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ TkpWmSetState(winPtr, WithdrawnState);
+ } else {
+ Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],
+ "\": must be aspect, client, command, deiconify, ",
+ "focusmodel, frame, geometry, grid, group, iconbitmap, ",
+ "iconify, iconmask, iconname, iconposition, ",
+ "iconwindow, maxsize, minsize, overrideredirect, ",
+ "positionfrom, protocol, resizable, sizefrom, state, title, ",
+ "transient, or withdraw",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+
+ updateGeom:
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetGrid --
+ *
+ * This procedure is invoked by a widget when it wishes to set a grid
+ * coordinate system that controls the size of a top-level window.
+ * It provides a C interface equivalent to the "wm grid" command and
+ * is usually asscoiated with the -setgrid option.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Grid-related information will be passed to the window manager, so
+ * that the top-level window associated with tkwin will resize on
+ * even grid units. If some other window already controls gridding
+ * for the top-level window then this procedure call has no effect.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_SetGrid(
+ Tk_Window tkwin, /* Token for window. New window mgr info
+ * will be posted for the top-level window
+ * associated with this window. */
+ int reqWidth, /* Width (in grid units) corresponding to
+ * the requested geometry for tkwin. */
+ int reqHeight, /* Height (in grid units) corresponding to
+ * the requested geometry for tkwin. */
+ int widthInc, int heightInc)/* Pixel increments corresponding to a
+ * change of one grid unit. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ register WmInfo *wmPtr;
+
+ /*
+ * Find the top-level window for tkwin, plus the window manager
+ * information.
+ */
+
+ while (!(winPtr->flags & TK_TOP_LEVEL)) {
+ winPtr = winPtr->parentPtr;
+ }
+ wmPtr = winPtr->wmInfoPtr;
+
+ if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {
+ return;
+ }
+
+ if ((wmPtr->reqGridWidth == reqWidth)
+ && (wmPtr->reqGridHeight == reqHeight)
+ && (wmPtr->widthInc == widthInc)
+ && (wmPtr->heightInc == heightInc)
+ && ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc))
+ == PBaseSize|PResizeInc)) {
+ return;
+ }
+
+ /*
+ * If gridding was previously off, then forget about any window
+ * size requests made by the user or via "wm geometry": these are
+ * in pixel units and there's no easy way to translate them to
+ * grid units since the new requested size of the top-level window in
+ * pixels may not yet have been registered yet (it may filter up
+ * the hierarchy in DoWhenIdle handlers). However, if the window
+ * has never been mapped yet then just leave the window size alone:
+ * assume that it is intended to be in grid units but just happened
+ * to have been specified before this procedure was called.
+ */
+
+ if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) {
+ wmPtr->width = -1;
+ wmPtr->height = -1;
+ }
+
+ /*
+ * Set the new gridding information, and start the process of passing
+ * all of this information to the window manager.
+ */
+
+ wmPtr->gridWin = tkwin;
+ wmPtr->reqGridWidth = reqWidth;
+ wmPtr->reqGridHeight = reqHeight;
+ wmPtr->widthInc = widthInc;
+ wmPtr->heightInc = heightInc;
+ wmPtr->sizeHintsFlags |= PBaseSize|PResizeInc;
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_UnsetGrid --
+ *
+ * This procedure cancels the effect of a previous call
+ * to Tk_SetGrid.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If tkwin currently controls gridding for its top-level window,
+ * gridding is cancelled for that top-level window; if some other
+ * window controls gridding then this procedure has no effect.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_UnsetGrid(
+ Tk_Window tkwin) /* Token for window that is currently
+ * controlling gridding. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ register WmInfo *wmPtr;
+
+ /*
+ * Find the top-level window for tkwin, plus the window manager
+ * information.
+ */
+
+ while (!(winPtr->flags & TK_TOP_LEVEL)) {
+ winPtr = winPtr->parentPtr;
+ }
+ wmPtr = winPtr->wmInfoPtr;
+ if (tkwin != wmPtr->gridWin) {
+ return;
+ }
+
+ wmPtr->gridWin = NULL;
+ wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
+ if (wmPtr->width != -1) {
+ wmPtr->width = winPtr->reqWidth + (wmPtr->width
+ - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ wmPtr->height = winPtr->reqHeight + (wmPtr->height
+ - wmPtr->reqGridHeight)*wmPtr->heightInc;
+ }
+ wmPtr->widthInc = 1;
+ wmPtr->heightInc = 1;
+
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TopLevelEventProc --
+ *
+ * This procedure is invoked when a top-level (or other externally-
+ * managed window) is restructured in any way.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Tk's internal data structures for the window get modified to
+ * reflect the structural change.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TopLevelEventProc(
+ ClientData clientData, /* Window for which event occurred. */
+ XEvent *eventPtr) /* Event that just happened. */
+{
+ register TkWindow *winPtr = (TkWindow *) clientData;
+
+ winPtr->wmInfoPtr->flags |= WM_VROOT_OFFSET_STALE;
+ if (eventPtr->type == DestroyNotify) {
+ Tk_ErrorHandler handler;
+
+ if (!(winPtr->flags & TK_ALREADY_DEAD)) {
+ /*
+ * A top-level window was deleted externally (e.g., by the window
+ * manager). This is probably not a good thing, but cleanup as
+ * best we can. The error handler is needed because
+ * Tk_DestroyWindow will try to destroy the window, but of course
+ * it's already gone.
+ */
+
+ handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
+ (Tk_ErrorProc *) NULL, (ClientData) NULL);
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ Tk_DeleteErrorHandler(handler);
+ }
+ if (wmTracing) {
+ printf("TopLevelEventProc: %s deleted\n", winPtr->pathName);
+ }
+ } else if (eventPtr->type == ReparentNotify) {
+ panic("recieved unwanted reparent event");
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TopLevelReqProc --
+ *
+ * This procedure is invoked by the geometry manager whenever
+ * the requested size for a top-level window is changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arrange for the window to be resized to satisfy the request
+ * (this happens as a when-idle action).
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static void
+TopLevelReqProc(
+ ClientData dummy, /* Not used. */
+ Tk_Window tkwin) /* Information about window. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ WmInfo *wmPtr;
+
+ wmPtr = winPtr->wmInfoPtr;
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateGeometryInfo --
+ *
+ * This procedure is invoked when a top-level window is first
+ * mapped, and also as a when-idle procedure, to bring the
+ * geometry and/or position of a top-level window back into
+ * line with what has been requested by the user and/or widgets.
+ * This procedure doesn't return until the window manager has
+ * responded to the geometry change.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window's size and location may change, unless the WM prevents
+ * that from happening.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateGeometryInfo(
+ ClientData clientData) /* Pointer to the window's record. */
+{
+ register TkWindow *winPtr = (TkWindow *) clientData;
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int x, y, width, height;
+ unsigned long serial;
+
+ wmPtr->flags &= ~WM_UPDATE_PENDING;
+
+ /*
+ * Compute the new size for the top-level window. See the
+ * user documentation for details on this, but the size
+ * requested depends on (a) the size requested internally
+ * by the window's widgets, (b) the size requested by the
+ * user in a "wm geometry" command or via wm-based interactive
+ * resizing (if any), and (c) whether or not the window is
+ * gridded. Don't permit sizes <= 0 because this upsets
+ * the X server.
+ */
+
+ if (wmPtr->width == -1) {
+ width = winPtr->reqWidth;
+ } else if (wmPtr->gridWin != NULL) {
+ width = winPtr->reqWidth
+ + (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ } else {
+ width = wmPtr->width;
+ }
+ if (width <= 0) {
+ width = 1;
+ }
+ if (wmPtr->height == -1) {
+ height = winPtr->reqHeight;
+ } else if (wmPtr->gridWin != NULL) {
+ height = winPtr->reqHeight
+ + (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc;
+ } else {
+ height = wmPtr->height;
+ }
+ if (height <= 0) {
+ height = 1;
+ }
+
+ /*
+ * Compute the new position for the upper-left pixel of the window's
+ * decorative frame. This is tricky, because we need to include the
+ * border widths supplied by a reparented parent in this calculation,
+ * but can't use the parent's current overall size since that may
+ * change as a result of this code.
+ */
+
+ if (wmPtr->flags & WM_NEGATIVE_X) {
+ x = wmPtr->vRootWidth - wmPtr->x
+ - (width + (wmPtr->parentWidth - winPtr->changes.width));
+ } else {
+ x = wmPtr->x;
+ }
+ if (wmPtr->flags & WM_NEGATIVE_Y) {
+ y = wmPtr->vRootHeight - wmPtr->y
+ - (height + (wmPtr->parentHeight - winPtr->changes.height));
+ } else {
+ y = wmPtr->y;
+ }
+
+ /*
+ * If the window's size is going to change and the window is
+ * supposed to not be resizable by the user, then we have to
+ * update the size hints. There may also be a size-hint-update
+ * request pending from somewhere else, too.
+ */
+
+ if (((width != winPtr->changes.width)
+ || (height != winPtr->changes.height))
+ && (wmPtr->gridWin == NULL)
+ && ((wmPtr->sizeHintsFlags & (PMinSize|PMaxSize)) == 0)) {
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ }
+ if (wmPtr->flags & WM_UPDATE_SIZE_HINTS) {
+ UpdateSizeHints(winPtr);
+ }
+
+ /*
+ * Reconfigure the window if it isn't already configured correctly.
+ * A few tricky points:
+ *
+ * 1. If the window is embedded and the container is also in this
+ * process, don't actually reconfigure the window; just pass the
+ * desired size on to the container. Also, zero out any position
+ * information, since embedded windows are not allowed to move.
+ * 2. Sometimes the window manager will give us a different size
+ * than we asked for (e.g. mwm has a minimum size for windows), so
+ * base the size check on what we *asked for* last time, not what we
+ * got.
+ * 3. Don't move window unless a new position has been requested for
+ * it. This is because of "features" in some window managers (e.g.
+ * twm, as of 4/24/91) where they don't interpret coordinates
+ * according to ICCCM. Moving a window to its current location may
+ * cause it to shift position on the screen.
+ */
+
+ if (Tk_IsEmbedded(winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(winPtr);
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ if (contWinPtr != NULL) {
+ /*
+ * This window is embedded and the container is also in this
+ * process, so we don't need to do anything special about the
+ * geometry, except to make sure that the desired size is known
+ * by the container. Also, zero out any position information,
+ * since embedded windows are not allowed to move.
+ */
+
+ wmPtr->x = wmPtr->y = 0;
+ wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
+ Tk_GeometryRequest((Tk_Window) contWinPtr, width, height);
+ }
+ return;
+ }
+ serial = NextRequest(winPtr->display);
+ if (wmPtr->flags & WM_MOVE_PENDING) {
+ wmPtr->configWidth = width;
+ wmPtr->configHeight = height;
+ if (wmTracing) {
+ printf(
+ "UpdateGeometryInfo moving to %d %d, resizing to %d x %d,\n",
+ x, y, width, height);
+ }
+ Tk_MoveResizeWindow((Tk_Window) winPtr, x, y, (unsigned) width,
+ (unsigned) height);
+ } else if ((width != wmPtr->configWidth)
+ || (height != wmPtr->configHeight)) {
+ wmPtr->configWidth = width;
+ wmPtr->configHeight = height;
+ if (wmTracing) {
+ printf("UpdateGeometryInfo resizing to %d x %d\n", width, height);
+ }
+ Tk_ResizeWindow((Tk_Window) winPtr, (unsigned) width,
+ (unsigned) height);
+ } else {
+ return;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * UpdateSizeHints --
+ *
+ * This procedure is called to update the window manager's
+ * size hints information from the information in a WmInfo
+ * structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Properties get changed for winPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+UpdateSizeHints(
+ TkWindow *winPtr)
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ XSizeHints *hintsPtr;
+
+ wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS;
+
+ hintsPtr = XAllocSizeHints();
+ if (hintsPtr == NULL) {
+ return;
+ }
+
+ /*
+ * Compute the pixel-based sizes for the various fields in the
+ * size hints structure, based on the grid-based sizes in
+ * our structure.
+ */
+
+ if (wmPtr->gridWin != NULL) {
+ hintsPtr->base_width = winPtr->reqWidth
+ - (wmPtr->reqGridWidth * wmPtr->widthInc);
+ if (hintsPtr->base_width < 0) {
+ hintsPtr->base_width = 0;
+ }
+ hintsPtr->base_height = winPtr->reqHeight
+ - (wmPtr->reqGridHeight * wmPtr->heightInc);
+ if (hintsPtr->base_height < 0) {
+ hintsPtr->base_height = 0;
+ }
+ hintsPtr->min_width = hintsPtr->base_width
+ + (wmPtr->minWidth * wmPtr->widthInc);
+ hintsPtr->min_height = hintsPtr->base_height
+ + (wmPtr->minHeight * wmPtr->heightInc);
+ hintsPtr->max_width = hintsPtr->base_width
+ + (wmPtr->maxWidth * wmPtr->widthInc);
+ hintsPtr->max_height = hintsPtr->base_height
+ + (wmPtr->maxHeight * wmPtr->heightInc);
+ } else {
+ hintsPtr->min_width = wmPtr->minWidth;
+ hintsPtr->min_height = wmPtr->minHeight;
+ hintsPtr->max_width = wmPtr->maxWidth;
+ hintsPtr->max_height = wmPtr->maxHeight;
+ hintsPtr->base_width = 0;
+ hintsPtr->base_height = 0;
+ }
+ hintsPtr->width_inc = wmPtr->widthInc;
+ hintsPtr->height_inc = wmPtr->heightInc;
+ hintsPtr->min_aspect.x = wmPtr->minAspect.x;
+ hintsPtr->min_aspect.y = wmPtr->minAspect.y;
+ hintsPtr->max_aspect.x = wmPtr->maxAspect.x;
+ hintsPtr->max_aspect.y = wmPtr->maxAspect.y;
+ hintsPtr->win_gravity = wmPtr->gravity;
+ hintsPtr->flags = wmPtr->sizeHintsFlags | PMinSize | PMaxSize;
+
+ /*
+ * If the window isn't supposed to be resizable, then set the
+ * minimum and maximum dimensions to be the same.
+ */
+
+ if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
+ if (wmPtr->width >= 0) {
+ hintsPtr->min_width = wmPtr->width;
+ } else {
+ hintsPtr->min_width = winPtr->reqWidth;
+ }
+ hintsPtr->max_width = hintsPtr->min_width;
+ }
+ if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
+ if (wmPtr->height >= 0) {
+ hintsPtr->min_height = wmPtr->height;
+ } else {
+ hintsPtr->min_height = winPtr->reqHeight;
+ }
+ hintsPtr->max_height = hintsPtr->min_height;
+ }
+
+ XSetWMNormalHints(winPtr->display, winPtr->window, hintsPtr);
+
+ XFree((char *) hintsPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ParseGeometry --
+ *
+ * This procedure parses a geometry string and updates
+ * information used to control the geometry of a top-level
+ * window.
+ *
+ * Results:
+ * A standard Tcl return value, plus an error message in
+ * interp->result if an error occurs.
+ *
+ * Side effects:
+ * The size and/or location of winPtr may change.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ParseGeometry(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ char *string, /* String containing new geometry. Has the
+ * standard form "=wxh+x+y". */
+ TkWindow *winPtr) /* Pointer to top-level window whose
+ * geometry is to be changed. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int x, y, width, height, flags;
+ char *end;
+ register char *p = string;
+
+ /*
+ * The leading "=" is optional.
+ */
+
+ if (*p == '=') {
+ p++;
+ }
+
+ /*
+ * Parse the width and height, if they are present. Don't
+ * actually update any of the fields of wmPtr until we've
+ * successfully parsed the entire geometry string.
+ */
+
+ width = wmPtr->width;
+ height = wmPtr->height;
+ x = wmPtr->x;
+ y = wmPtr->y;
+ flags = wmPtr->flags;
+ if (isdigit(UCHAR(*p))) {
+ width = strtoul(p, &end, 10);
+ p = end;
+ if (*p != 'x') {
+ goto error;
+ }
+ p++;
+ if (!isdigit(UCHAR(*p))) {
+ goto error;
+ }
+ height = strtoul(p, &end, 10);
+ p = end;
+ }
+
+ /*
+ * Parse the X and Y coordinates, if they are present.
+ */
+
+ if (*p != '\0') {
+ flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
+ if (*p == '-') {
+ flags |= WM_NEGATIVE_X;
+ } else if (*p != '+') {
+ goto error;
+ }
+ x = strtol(p+1, &end, 10);
+ p = end;
+ if (*p == '-') {
+ flags |= WM_NEGATIVE_Y;
+ } else if (*p != '+') {
+ goto error;
+ }
+ y = strtol(p+1, &end, 10);
+ if (*end != '\0') {
+ goto error;
+ }
+
+ /*
+ * Assume that the geometry information came from the user,
+ * unless an explicit source has been specified. Otherwise
+ * most window managers assume that the size hints were
+ * program-specified and they ignore them.
+ */
+
+ if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) {
+ wmPtr->sizeHintsFlags |= USPosition;
+ flags |= WM_UPDATE_SIZE_HINTS;
+ }
+ }
+
+ /*
+ * Everything was parsed OK. Update the fields of *wmPtr and
+ * arrange for the appropriate information to be percolated out
+ * to the window manager at the next idle moment.
+ */
+
+ wmPtr->width = width;
+ wmPtr->height = height;
+ if ((x != wmPtr->x) || (y != wmPtr->y)
+ || ((flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y))
+ != (wmPtr->flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y)))) {
+ wmPtr->x = x;
+ wmPtr->y = y;
+ flags |= WM_MOVE_PENDING;
+ }
+ wmPtr->flags = flags;
+
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+ return TCL_OK;
+
+ error:
+ Tcl_AppendResult(interp, "bad geometry specifier \"",
+ string, "\"", (char *) NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetRootCoords --
+ *
+ * Given a token for a window, this procedure traces through the
+ * window's lineage to find the (virtual) root-window coordinates
+ * corresponding to point (0,0) in the window.
+ *
+ * Results:
+ * The locations pointed to by xPtr and yPtr are filled in with
+ * the root coordinates of the (0,0) point in tkwin. If a virtual
+ * root window is in effect for the window, then the coordinates
+ * in the virtual root are returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_GetRootCoords(
+ Tk_Window tkwin, /* Token for window. */
+ int *xPtr, /* Where to store x-displacement of (0,0). */
+ int *yPtr) /* Where to store y-displacement of (0,0). */
+{
+ int x, y;
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ /*
+ * Search back through this window's parents all the way to a
+ * top-level window, combining the offsets of each window within
+ * its parent.
+ */
+
+ x = y = 0;
+ while (1) {
+ x += winPtr->changes.x + winPtr->changes.border_width;
+ y += winPtr->changes.y + winPtr->changes.border_width;
+ if (winPtr->flags & TK_TOP_LEVEL) {
+ if (!(Tk_IsEmbedded(winPtr))) {
+ x += winPtr->wmInfoPtr->xInParent;
+ y += winPtr->wmInfoPtr->yInParent;
+ break;
+ } else {
+ TkWindow *otherPtr;
+
+ otherPtr = TkpGetOtherWindow(winPtr);
+ if (otherPtr != NULL) {
+ /*
+ * The container window is in the same application.
+ * Query its coordinates.
+ */
+ winPtr = otherPtr;
+
+ /*
+ * Remember to offset by the container window here,
+ * since at the end of this if branch, we will
+ * pop out to the container's parent...
+ */
+
+ x += winPtr->changes.x + winPtr->changes.border_width;
+ y += winPtr->changes.y + winPtr->changes.border_width;
+
+ } else {
+
+ /*
+ * NOTE: Here we should handle
+ * out of process embedding.
+ */
+
+ break;
+ }
+ }
+ }
+ winPtr = winPtr->parentPtr;
+ }
+ *xPtr = x;
+ *yPtr = y;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_CoordsToWindow --
+ *
+ * This is a Macintosh specific implementation of this function.
+ * Given the root coordinates of a point, this procedure returns
+ * the token for the top-most window covering that point, if
+ * there exists such a window in this application.
+ *
+ * Results:
+ * The return result is either a token for the window corresponding
+ * to rootX and rootY, or else NULL to indicate that there is no such
+ * window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_CoordsToWindow(
+ int rootX, int rootY, /* Coordinates of point in root window. If
+ * a virtual-root window manager is in use,
+ * these coordinates refer to the virtual
+ * root, not the real root. */
+ Tk_Window tkwin) /* Token for any window in application;
+ * used to identify the display. */
+{
+ WindowPtr whichWin;
+ Point where;
+ Window rootChild;
+ register TkWindow *winPtr, *childPtr;
+ TkWindow *nextPtr; /* Coordinates of highest child found so
+ * far that contains point. */
+ int x, y; /* Coordinates in winPtr. */
+ int tmpx, tmpy, bd;
+
+ /*
+ * Step 1: find the top-level window that contains the desired point.
+ */
+
+ where.h = rootX;
+ where.v = rootY;
+ FindWindow(where, &whichWin);
+ if (whichWin == NULL) {
+ return NULL;
+ }
+ rootChild = TkMacGetXWindow(whichWin);
+ winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, rootChild);
+ if (winPtr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Step 2: work down through the hierarchy underneath this window.
+ * At each level, scan through all the children to find the highest
+ * one in the stacking order that contains the point. Then repeat
+ * the whole process on that child.
+ */
+
+ x = rootX - winPtr->wmInfoPtr->xInParent;
+ y = rootY - winPtr->wmInfoPtr->yInParent;
+ while (1) {
+ x -= winPtr->changes.x;
+ y -= winPtr->changes.y;
+ nextPtr = NULL;
+
+ /*
+ * Container windows cannot have children. So if it is a container,
+ * look there, otherwise inspect the children.
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+ if (childPtr != NULL) {
+ if (Tk_IsMapped(childPtr)) {
+ tmpx = x - childPtr->changes.x;
+ tmpy = y - childPtr->changes.y;
+ bd = childPtr->changes.border_width;
+
+ if ((tmpx >= -bd) && (tmpy >= -bd)
+ && (tmpx < (childPtr->changes.width + bd))
+ && (tmpy < (childPtr->changes.height + bd))) {
+ nextPtr = childPtr;
+ }
+ }
+ }
+
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ } else {
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ if (!Tk_IsMapped(childPtr) ||
+ (childPtr->flags & TK_TOP_LEVEL)) {
+ continue;
+ }
+ tmpx = x - childPtr->changes.x;
+ tmpy = y - childPtr->changes.y;
+ bd = childPtr->changes.border_width;
+ if ((tmpx >= -bd) && (tmpy >= -bd)
+ && (tmpx < (childPtr->changes.width + bd))
+ && (tmpy < (childPtr->changes.height + bd))) {
+ nextPtr = childPtr;
+ }
+ }
+ }
+ if (nextPtr == NULL) {
+ break;
+ }
+ winPtr = nextPtr;
+ }
+ return (Tk_Window) winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_TopCoordsToWindow --
+ *
+ * Given a Tk Window, and coordinates of a point relative to that window
+ * this procedure returns the top-most child of the window (excluding
+ * toplevels) covering that point, if there exists such a window in this
+ * application.
+ * It also sets newX, and newY to the coords of the point relative to the
+ * window returned.
+ *
+ * Results:
+ * The return result is either a token for the window corresponding
+ * to rootX and rootY, or else NULL to indicate that there is no such
+ * window. newX and newY are also set to the coords of the point relative
+ * to the returned window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+Tk_TopCoordsToWindow(
+ Tk_Window tkwin, /* Token for a Tk Window which defines the;
+ * coordinates for rootX & rootY */
+ int rootX, int rootY, /* Coordinates of a point in tkWin. */
+ int *newX, int *newY) /* Coordinates of point in the upperMost child of
+ * tkWin containing (rootX,rootY) */
+{
+ register TkWindow *winPtr, *childPtr;
+ TkWindow *nextPtr; /* Coordinates of highest child found so
+ * far that contains point. */
+ int x, y; /* Coordinates in winPtr. */
+ Window *children; /* Children of winPtr, or NULL. */
+
+ winPtr = (TkWindow *) tkwin;
+ x = rootX;
+ y = rootY;
+ while (1) {
+ nextPtr = NULL;
+ children = NULL;
+
+ /*
+ * Container windows cannot have children. So if it is a container,
+ * look there, otherwise inspect the children.
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+ if (childPtr != NULL) {
+ if (Tk_IsMapped(childPtr) &&
+ (x > childPtr->changes.x &&
+ x < childPtr->changes.x +
+ childPtr->changes.width) &&
+ (y > childPtr->changes.y &&
+ y < childPtr->changes.y +
+ childPtr->changes.height)) {
+ nextPtr = childPtr;
+ }
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ } else {
+
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ if (!Tk_IsMapped(childPtr) ||
+ (childPtr->flags & TK_TOP_LEVEL)) {
+ continue;
+ }
+ if (x < childPtr->changes.x || y < childPtr->changes.y) {
+ continue;
+ }
+ if (x > childPtr->changes.x + childPtr->changes.width ||
+ y > childPtr->changes.y + childPtr->changes.height) {
+ continue;
+ }
+ nextPtr = childPtr;
+ }
+ }
+ if (nextPtr == NULL) {
+ break;
+ }
+ winPtr = nextPtr;
+ x -= winPtr->changes.x;
+ y -= winPtr->changes.y;
+ }
+ *newX = x;
+ *newY = y;
+ return (Tk_Window) winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateVRootGeometry --
+ *
+ * This procedure is called to update all the virtual root
+ * geometry information in wmPtr.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The vRootX, vRootY, vRootWidth, and vRootHeight fields in
+ * wmPtr are filled with the most up-to-date information.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateVRootGeometry(
+ WmInfo *wmPtr) /* Window manager information to be
+ * updated. The wmPtr->vRoot field must
+ * be valid. */
+{
+ TkWindow *winPtr = wmPtr->winPtr;
+ unsigned int bd, dummy;
+ Window dummy2;
+ Status status;
+ Tk_ErrorHandler handler;
+
+ /*
+ * If this isn't a virtual-root window manager, just return information
+ * about the screen.
+ */
+
+ wmPtr->flags &= ~WM_VROOT_OFFSET_STALE;
+ if (wmPtr->vRoot == None) {
+ noVRoot:
+ wmPtr->vRootX = wmPtr->vRootY = 0;
+ wmPtr->vRootWidth = DisplayWidth(winPtr->display, winPtr->screenNum);
+ wmPtr->vRootHeight = DisplayHeight(winPtr->display, winPtr->screenNum);
+ return;
+ }
+
+ /*
+ * Refresh the virtual root information if it's out of date.
+ */
+
+ handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
+ (Tk_ErrorProc *) NULL, (ClientData) NULL);
+ status = XGetGeometry(winPtr->display, wmPtr->vRoot,
+ &dummy2, &wmPtr->vRootX, &wmPtr->vRootY,
+ &wmPtr->vRootWidth, &wmPtr->vRootHeight, &bd, &dummy);
+ if (wmTracing) {
+ printf("UpdateVRootGeometry: x = %d, y = %d, width = %d, ",
+ wmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth);
+ printf("height = %d, status = %d\n", wmPtr->vRootHeight, status);
+ }
+ Tk_DeleteErrorHandler(handler);
+ if (status == 0) {
+ /*
+ * The virtual root is gone! Pretend that it never existed.
+ */
+
+ wmPtr->vRoot = None;
+ goto noVRoot;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetVRootGeometry --
+ *
+ * This procedure returns information about the virtual root
+ * window corresponding to a particular Tk window.
+ *
+ * Results:
+ * The values at xPtr, yPtr, widthPtr, and heightPtr are set
+ * with the offset and dimensions of the root window corresponding
+ * to tkwin. If tkwin is being managed by a virtual root window
+ * manager these values correspond to the virtual root window being
+ * used for tkwin; otherwise the offsets will be 0 and the
+ * dimensions will be those of the screen.
+ *
+ * Side effects:
+ * Vroot window information is refreshed if it is out of date.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_GetVRootGeometry(
+ Tk_Window tkwin, /* Window whose virtual root is to be
+ * queried. */
+ int *xPtr, int *yPtr, /* Store x and y offsets of virtual root
+ * here. */
+ int *widthPtr, /* Store dimensions of virtual root here. */
+ int *heightPtr)
+{
+ WmInfo *wmPtr;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ /*
+ * Find the top-level window for tkwin, and locate the window manager
+ * information for that window.
+ */
+
+ while (!(winPtr->flags & TK_TOP_LEVEL)) {
+ winPtr = winPtr->parentPtr;
+ }
+ wmPtr = winPtr->wmInfoPtr;
+
+ /*
+ * Make sure that the geometry information is up-to-date, then copy
+ * it out to the caller.
+ */
+
+ if (wmPtr->flags & WM_VROOT_OFFSET_STALE) {
+ UpdateVRootGeometry(wmPtr);
+ }
+ *xPtr = wmPtr->vRootX;
+ *yPtr = wmPtr->vRootY;
+ *widthPtr = wmPtr->vRootWidth;
+ *heightPtr = wmPtr->vRootHeight;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MoveToplevelWindow --
+ *
+ * This procedure is called instead of Tk_MoveWindow to adjust
+ * the x-y location of a top-level window. It delays the actual
+ * move to a later time and keeps window-manager information
+ * up-to-date with the move
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is eventually moved so that its upper-left corner
+ * (actually, the upper-left corner of the window's decorative
+ * frame, if there is one) is at (x,y).
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_MoveToplevelWindow(
+ Tk_Window tkwin, /* Window to move. */
+ int x, int y) /* New location for window (within
+ * parent). */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ panic("Tk_MoveToplevelWindow called with non-toplevel window");
+ }
+ wmPtr->x = x;
+ wmPtr->y = y;
+ wmPtr->flags |= WM_MOVE_PENDING;
+ wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
+ if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) {
+ wmPtr->sizeHintsFlags |= USPosition;
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ }
+
+ /*
+ * If the window has already been mapped, must bring its geometry
+ * up-to-date immediately, otherwise an event might arrive from the
+ * server that would overwrite wmPtr->x and wmPtr->y and lose the
+ * new position.
+ */
+
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ if (wmPtr->flags & WM_UPDATE_PENDING) {
+ Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
+ }
+ UpdateGeometryInfo((ClientData) winPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWmProtocolEventProc --
+ *
+ * This procedure is called by the Tk_HandleEvent whenever a
+ * ClientMessage event arrives whose type is "WM_PROTOCOLS".
+ * This procedure handles the message from the window manager
+ * in an appropriate fashion.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on what sort of handler, if any, was set up for the
+ * protocol.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkWmProtocolEventProc(
+ TkWindow *winPtr, /* Window to which the event was sent. */
+ XEvent *eventPtr) /* X event. */
+{
+ WmInfo *wmPtr;
+ register ProtocolHandler *protPtr;
+ Tcl_Interp *interp;
+ Atom protocol;
+ int result;
+
+ wmPtr = winPtr->wmInfoPtr;
+ if (wmPtr == NULL) {
+ return;
+ }
+ protocol = (Atom) eventPtr->xclient.data.l[0];
+ for (protPtr = wmPtr->protPtr; protPtr != NULL;
+ protPtr = protPtr->nextPtr) {
+ if (protocol == protPtr->protocol) {
+ Tcl_Preserve((ClientData) protPtr);
+ interp = protPtr->interp;
+ Tcl_Preserve((ClientData) interp);
+ result = Tcl_GlobalEval(interp, protPtr->command);
+ if (result != TCL_OK) {
+ Tcl_AddErrorInfo(interp, "\n (command for \"");
+ Tcl_AddErrorInfo(interp,
+ Tk_GetAtomName((Tk_Window) winPtr, protocol));
+ Tcl_AddErrorInfo(interp, "\" window manager protocol)");
+ Tk_BackgroundError(interp);
+ }
+ Tcl_Release((ClientData) interp);
+ Tcl_Release((ClientData) protPtr);
+ return;
+ }
+ }
+
+ /*
+ * No handler was present for this protocol. If this is a
+ * WM_DELETE_WINDOW message then just destroy the window.
+ */
+
+ if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) {
+ Tk_DestroyWindow((Tk_Window) winPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWmRestackToplevel --
+ *
+ * This procedure restacks a top-level window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * WinPtr gets restacked as specified by aboveBelow and otherPtr.
+ * This procedure doesn't return until the restack has taken
+ * effect and the ConfigureNotify event for it has been received.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkWmRestackToplevel(
+ TkWindow *winPtr, /* Window to restack. */
+ int aboveBelow, /* Gives relative position for restacking;
+ * must be Above or Below. */
+ TkWindow *otherPtr) /* Window relative to which to restack;
+ * if NULL, then winPtr gets restacked
+ * above or below *all* siblings. */
+{
+ WmInfo *wmPtr;
+ WindowPeek macWindow, otherMacWindow, frontWindow;
+
+ wmPtr = winPtr->wmInfoPtr;
+
+ /*
+ * Get the mac window. Make sure it exists & is mapped.
+ */
+
+ if (winPtr->window == None) {
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ }
+ if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
+
+ /*
+ * Can't set stacking order properly until the window is on the
+ * screen (mapping it may give it a reparent window), so make sure
+ * it's on the screen.
+ */
+
+ TkWmMapWindow(winPtr);
+ }
+ macWindow = (WindowPeek) TkMacGetDrawablePort(winPtr->window);
+
+ /*
+ * Get the window in which a raise or lower is in relation to.
+ */
+ if (otherPtr != NULL) {
+ if (otherPtr->window == None) {
+ Tk_MakeWindowExist((Tk_Window) otherPtr);
+ }
+ if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
+ TkWmMapWindow(otherPtr);
+ }
+ otherMacWindow = (WindowPeek) TkMacGetDrawablePort(otherPtr->window);
+ } else {
+ otherMacWindow = NULL;
+ }
+
+ frontWindow = (WindowPeek) FrontWindow();
+ if (aboveBelow == Above) {
+ if (macWindow == frontWindow) {
+ /*
+ * Do nothing - it's already at the top.
+ */
+ } else if (otherMacWindow == frontWindow || otherMacWindow == NULL) {
+ /*
+ * Raise the window to the top. If the window is visable then
+ * we also make it the active window.
+ */
+
+ if (wmPtr->hints.initial_state == WithdrawnState) {
+ BringToFront((WindowPtr) macWindow);
+ } else {
+ SelectWindow((WindowPtr) macWindow);
+ }
+ } else {
+ /*
+ * Find the window to be above. (Front window will actually be the
+ * window to be behind.) Front window is NULL if no other windows.
+ */
+ while (frontWindow != NULL &&
+ frontWindow->nextWindow != otherMacWindow) {
+ frontWindow = frontWindow->nextWindow;
+ }
+ if (frontWindow != NULL) {
+ SendBehind((WindowPtr) macWindow, (WindowPtr) frontWindow);
+ }
+ }
+ } else {
+ /*
+ * Send behind. If it was in front find another window to make active.
+ */
+ if (macWindow == frontWindow) {
+ if (macWindow->nextWindow != NULL) {
+ SelectWindow((WindowPtr) macWindow->nextWindow);
+ }
+ }
+ SendBehind((WindowPtr) macWindow, (WindowPtr) otherMacWindow);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWmAddToColormapWindows --
+ *
+ * This procedure is called to add a given window to the
+ * WM_COLORMAP_WINDOWS property for its top-level, if it
+ * isn't already there. It is invoked by the Tk code that
+ * creates a new colormap, in order to make sure that colormap
+ * information is propagated to the window manager by default.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * WinPtr's window gets added to the WM_COLORMAP_WINDOWS
+ * property of its nearest top-level ancestor, unless the
+ * colormaps have been set explicitly with the
+ * "wm colormapwindows" command.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkWmAddToColormapWindows(
+ TkWindow *winPtr) /* Window with a non-default colormap.
+ * Should not be a top-level window. */
+{
+ TkWindow *topPtr;
+ TkWindow **oldPtr, **newPtr;
+ int count, i;
+
+ if (winPtr->window == None) {
+ return;
+ }
+
+ for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {
+ if (topPtr == NULL) {
+ /*
+ * Window is being deleted. Skip the whole operation.
+ */
+
+ return;
+ }
+ if (topPtr->flags & TK_TOP_LEVEL) {
+ break;
+ }
+ }
+ if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) {
+ return;
+ }
+
+ /*
+ * Make sure that the window isn't already in the list.
+ */
+
+ count = topPtr->wmInfoPtr->cmapCount;
+ oldPtr = topPtr->wmInfoPtr->cmapList;
+
+ for (i = 0; i < count; i++) {
+ if (oldPtr[i] == winPtr) {
+ return;
+ }
+ }
+
+ /*
+ * Make a new bigger array and use it to reset the property.
+ * Automatically add the toplevel itself as the last element
+ * of the list.
+ */
+
+ newPtr = (TkWindow **) ckalloc((unsigned) ((count+2)*sizeof(TkWindow*)));
+ if (count > 0) {
+ memcpy(newPtr, oldPtr, count * sizeof(TkWindow*));
+ }
+ if (count == 0) {
+ count++;
+ }
+ newPtr[count-1] = winPtr;
+ newPtr[count] = topPtr;
+ if (oldPtr != NULL) {
+ ckfree((char *) oldPtr);
+ }
+
+ topPtr->wmInfoPtr->cmapList = newPtr;
+ topPtr->wmInfoPtr->cmapCount = count+1;
+
+ /*
+ * On the Macintosh all of this is just an excercise
+ * in compatability as we don't support colormaps. If
+ * we did they would be installed here.
+ */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWmRemoveFromColormapWindows --
+ *
+ * This procedure is called to remove a given window from the
+ * WM_COLORMAP_WINDOWS property for its top-level. It is invoked
+ * when windows are deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * WinPtr's window gets removed from the WM_COLORMAP_WINDOWS
+ * property of its nearest top-level ancestor, unless the
+ * top-level itself is being deleted too.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkWmRemoveFromColormapWindows(
+ TkWindow *winPtr) /* Window that may be present in
+ * WM_COLORMAP_WINDOWS property for its
+ * top-level. Should not be a top-level
+ * window. */
+{
+ TkWindow *topPtr;
+ TkWindow **oldPtr;
+ int count, i, j;
+
+ for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) {
+ if (topPtr == NULL) {
+ /*
+ * Ancestors have been deleted, so skip the whole operation.
+ * Seems like this can't ever happen?
+ */
+
+ return;
+ }
+ if (topPtr->flags & TK_TOP_LEVEL) {
+ break;
+ }
+ }
+ if (topPtr->flags & TK_ALREADY_DEAD) {
+ /*
+ * Top-level is being deleted, so there's no need to cleanup
+ * the WM_COLORMAP_WINDOWS property.
+ */
+
+ return;
+ }
+
+ /*
+ * Find the window and slide the following ones down to cover
+ * it up.
+ */
+
+ count = topPtr->wmInfoPtr->cmapCount;
+ oldPtr = topPtr->wmInfoPtr->cmapList;
+ for (i = 0; i < count; i++) {
+ if (oldPtr[i] == winPtr) {
+ for (j = i ; j < count-1; j++) {
+ oldPtr[j] = oldPtr[j+1];
+ }
+ topPtr->wmInfoPtr->cmapCount = count - 1;
+ break;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetPointerCoords --
+ *
+ * Fetch the position of the mouse pointer.
+ *
+ * Results:
+ * *xPtr and *yPtr are filled in with the (virtual) root coordinates
+ * of the mouse pointer for tkwin's display. If the pointer isn't
+ * on tkwin's screen, then -1 values are returned for both
+ * coordinates. The argument tkwin must be a toplevel window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkGetPointerCoords(
+ Tk_Window tkwin, /* Toplevel window that identifies screen
+ * on which lookup is to be done. */
+ int *xPtr, int *yPtr) /* Store pointer coordinates here. */
+{
+ Point where;
+
+ GetMouse(&where);
+ LocalToGlobal(&where);
+ *xPtr = where.h;
+ *yPtr = where.v;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitialWindowBounds --
+ *
+ * This function calculates the initial bounds for a new Mac
+ * toplevel window. Unless the geometry is specified by the user
+ * this code will auto place the windows in a cascade diagonially
+ * across the main monitor of the Mac.
+ *
+ * Results:
+ * The bounds are returned in geometry.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitialWindowBounds(
+ TkWindow *winPtr, /* Window to get initial bounds for. */
+ Rect *geometry) /* On return the initial bounds. */
+{
+ int x, y;
+ static int defaultX = 5;
+ static int defaultY = 45;
+
+ if (!(winPtr->wmInfoPtr->sizeHintsFlags & (USPosition | PPosition))) {
+ /*
+ * We will override the program & hopefully place the
+ * window in a "better" location.
+ */
+
+ if (((tcl_macQdPtr->screenBits.bounds.right - defaultX) < 30) ||
+ ((tcl_macQdPtr->screenBits.bounds.bottom - defaultY) < 30)) {
+ defaultX = 5;
+ defaultY = 45;
+ }
+ x = defaultX;
+ y = defaultY;
+ defaultX += 20;
+ defaultY += 20;
+ } else {
+ x = winPtr->wmInfoPtr->x;
+ y = winPtr->wmInfoPtr->y;
+ }
+
+ geometry->left = x;
+ geometry->top = y;
+ geometry->right = x + winPtr->changes.width;
+ geometry->bottom = y + winPtr->changes.height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacResizable --
+ *
+ * This function determines if the passed in window is part of
+ * a toplevel window that is resizable. If the window is
+ * resizable in the x, y or both directions, true is returned.
+ *
+ * Results:
+ * True if resizable, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacResizable(
+ TkWindow *winPtr) /* Tk window or NULL. */
+{
+ WmInfo *wmPtr;
+
+ if (winPtr == NULL) {
+ return false;
+ }
+ while (winPtr->wmInfoPtr == NULL) {
+ winPtr = winPtr->parentPtr;
+ }
+
+ wmPtr = winPtr->wmInfoPtr;
+ if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&
+ (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacGrowToplevel --
+ *
+ * The function is invoked when the user clicks in the grow region
+ * of a Tk window. The function will handle the dragging
+ * procedure and not return until completed. Finally, the function
+ * may place information Tk's event queue is the window was resized.
+ *
+ * Results:
+ * True if events were placed on event queue, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacGrowToplevel(
+ WindowPtr whichWindow,
+ Point start)
+{
+ Point where = start;
+
+ GlobalToLocal(&where);
+ if (where.h > (whichWindow->portRect.right - 16) &&
+ where.v > (whichWindow->portRect.bottom - 16)) {
+
+ Window window;
+ TkWindow *winPtr;
+ WmInfo *wmPtr;
+ Rect bounds;
+ long growResult;
+
+ window = TkMacGetXWindow(whichWindow);
+ winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
+ wmPtr = winPtr->wmInfoPtr;
+
+ /* TODO: handle grid size options. */
+ if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) &&
+ (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) {
+ return false;
+ }
+ if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
+ bounds.left = bounds.right = winPtr->changes.width;
+ } else {
+ bounds.left = (wmPtr->minWidth < 64) ? 64 : wmPtr->minWidth;
+ bounds.right = (wmPtr->maxWidth < 64) ? 64 : wmPtr->maxWidth;
+ }
+ if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
+ bounds.top = bounds.bottom = winPtr->changes.height;
+ } else {
+ bounds.top = (wmPtr->minHeight < 64) ? 64 : wmPtr->minHeight;
+ bounds.bottom = (wmPtr->maxHeight < 64) ? 64 : wmPtr->maxHeight;
+ }
+
+ growResult = GrowWindow(whichWindow, start, &bounds);
+
+ if (growResult != 0) {
+ SizeWindow(whichWindow,
+ LoWord(growResult), HiWord(growResult), true);
+ SetPort(whichWindow);
+ InvalRect(&whichWindow->portRect); /* TODO: may not be needed */
+ TkMacInvalClipRgns(winPtr);
+ TkGenWMConfigureEvent((Tk_Window) winPtr, -1, -1,
+ (int) LoWord(growResult), (int) HiWord(growResult),
+ TK_SIZE_CHANGED);
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSetWMName --
+ *
+ * Set the title for a toplevel window. If the window is embedded,
+ * do not change the window title.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The title of the window is changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkSetWMName(
+ TkWindow *winPtr,
+ Tk_Uid titleUid)
+{
+ Str255 pTitle;
+ GWorldPtr macWin;
+
+ if (Tk_IsEmbedded(winPtr)) {
+ return;
+ }
+
+ macWin = TkMacGetDrawablePort(winPtr->window);
+
+ strcpy((char *) pTitle + 1, titleUid);
+ pTitle[0] = strlen(titleUid);
+ SetWTitle((WindowPtr) macWin, pTitle);
+}
+
+void
+TkGenWMDestroyEvent(
+ Tk_Window tkwin)
+{
+ XEvent event;
+
+ event.xany.serial = Tk_Display(tkwin)->request;
+ event.xany.send_event = False;
+ event.xany.display = Tk_Display(tkwin);
+
+ event.xclient.window = Tk_WindowId(tkwin);
+ event.xclient.type = ClientMessage;
+ event.xclient.message_type = Tk_InternAtom(tkwin, "WM_PROTOCOLS");
+ event.xclient.format = 32;
+ event.xclient.data.l[0] = Tk_InternAtom(tkwin, "WM_DELETE_WINDOW");
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGenWMConfigureEvent --
+ *
+ * Generate a ConfigureNotify event for Tk. Depending on the
+ * value of flag the values of width/height, x/y, or both may
+ * be changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A ConfigureNotify event is sent to Tk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkGenWMConfigureEvent(
+ Tk_Window tkwin,
+ int x,
+ int y,
+ int width,
+ int height,
+ int flags)
+{
+ XEvent event;
+ WmInfo *wmPtr;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (tkwin == NULL) {
+ return;
+ }
+
+ event.type = ConfigureNotify;
+ event.xconfigure.serial = Tk_Display(tkwin)->request;
+ event.xconfigure.send_event = False;
+ event.xconfigure.display = Tk_Display(tkwin);
+ event.xconfigure.event = Tk_WindowId(tkwin);
+ event.xconfigure.window = Tk_WindowId(tkwin);
+ event.xconfigure.border_width = winPtr->changes.border_width;
+ event.xconfigure.override_redirect = winPtr->atts.override_redirect;
+ if (winPtr->changes.stack_mode == Above) {
+ event.xconfigure.above = winPtr->changes.sibling;
+ } else {
+ event.xconfigure.above = None;
+ }
+
+ if (flags & TK_LOCATION_CHANGED) {
+ event.xconfigure.x = x;
+ event.xconfigure.y = y;
+ } else {
+ event.xconfigure.x = Tk_X(tkwin);
+ event.xconfigure.y = Tk_Y(tkwin);
+ x = Tk_X(tkwin);
+ y = Tk_Y(tkwin);
+ }
+ if (flags & TK_SIZE_CHANGED) {
+ event.xconfigure.width = width;
+ event.xconfigure.height = height;
+ } else {
+ event.xconfigure.width = Tk_Width(tkwin);
+ event.xconfigure.height = Tk_Height(tkwin);
+ width = Tk_Width(tkwin);
+ height = Tk_Height(tkwin);
+ }
+
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
+ /*
+ * Update window manager information.
+ */
+ if (Tk_IsTopLevel(winPtr)) {
+ wmPtr = winPtr->wmInfoPtr;
+ if (flags & TK_LOCATION_CHANGED) {
+ wmPtr->x = x;
+ wmPtr->y = y;
+ wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
+ }
+ if ((flags & TK_SIZE_CHANGED) &&
+ ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {
+ if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) {
+ /*
+ * Don't set external width, since the user didn't change it
+ * from what the widgets asked for.
+ */
+ } else {
+ if (wmPtr->gridWin != NULL) {
+ wmPtr->width = wmPtr->reqGridWidth
+ + (width - winPtr->reqWidth)/wmPtr->widthInc;
+ if (wmPtr->width < 0) {
+ wmPtr->width = 0;
+ }
+ } else {
+ wmPtr->width = width;
+ }
+ }
+ if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) {
+ /*
+ * Don't set external height, since the user didn't change it
+ * from what the widgets asked for.
+ */
+ } else {
+ if (wmPtr->gridWin != NULL) {
+ wmPtr->height = wmPtr->reqGridHeight
+ + (height - winPtr->reqHeight)/wmPtr->heightInc;
+ if (wmPtr->height < 0) {
+ wmPtr->height = 0;
+ }
+ } else {
+ wmPtr->height = height;
+ }
+ }
+ wmPtr->configWidth = width;
+ wmPtr->configHeight = height;
+ }
+ }
+
+ /*
+ * Now set up the changes structure. Under X we wait for the
+ * ConfigureNotify to set these values. On the Mac we know imediatly that
+ * this is what we want - so we just set them. However, we need to
+ * make sure the windows clipping region is marked invalid so the
+ * change is visable to the subwindow.
+ */
+ winPtr->changes.x = x;
+ winPtr->changes.y = y;
+ winPtr->changes.width = width;
+ winPtr->changes.height = height;
+ TkMacInvalClipRgns(winPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetTransientMaster --
+ *
+ * If the passed window has the TRANSIENT_FOR property set this
+ * will return the master window. Otherwise it will return None.
+ *
+ * Results:
+ * The master window or None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Window
+TkGetTransientMaster(
+ TkWindow *winPtr)
+{
+ if (winPtr->wmInfoPtr != NULL) {
+ return winPtr->wmInfoPtr->master;
+ }
+ return None;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacGetXWindow --
+ *
+ * Returns the X window Id associated with the given WindowRef.
+ *
+ * Results:
+ * The window id is returned. None is returned if not a Tk window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Window
+TkMacGetXWindow(
+ WindowRef macWinPtr)
+{
+ register Tcl_HashEntry *hPtr;
+
+ if ((macWinPtr == NULL) || !windowHashInit) {
+ return None;
+ }
+ hPtr = Tcl_FindHashEntry(&windowTable, (char *) macWinPtr);
+ if (hPtr == NULL) {
+ return None;
+ }
+ return (Window) Tcl_GetHashValue(hPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacZoomToplevel --
+ *
+ * The function is invoked when the user clicks in the zoom region
+ * of a Tk window. The function will handle the mouse tracking
+ * for the interaction. If the window is to be zoomed the window
+ * size is changed and events are generated to let Tk know what
+ * happened.
+ *
+ * Results:
+ * True if events were placed on event queue, false otherwise.
+ *
+ * Side effects:
+ * The window may be resized & events placed on Tk's queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacZoomToplevel(
+ WindowPtr whichWindow, /* The Macintosh window to zoom. */
+ Point where, /* The current mouse position. */
+ short zoomPart) /* Either inZoomIn or inZoomOut */
+{
+ Window window;
+ Tk_Window tkwin;
+ Point location = {0, 0};
+ int xOffset, yOffset;
+ WmInfo *wmPtr;
+
+ SetPort(whichWindow);
+ if (!TrackBox(whichWindow, where, zoomPart)) {
+ return false;
+ }
+
+ /*
+ * We should now zoom the window (as long as it's one of ours). We
+ * also need to generate an event to let Tk know that the window size
+ * has changed.
+ */
+ window = TkMacGetXWindow(whichWindow);
+ tkwin = Tk_IdToWindow(tkDisplayList->display, window);
+ if (tkwin == NULL) {
+ return false;
+ }
+
+ /*
+ * The following block of code works around a bug in the window
+ * definition for Apple's floating windows. The zoom behavior is
+ * broken - we must manually set the standard state (by default
+ * it's something like 1x1) and we must swap the zoomPart manually
+ * otherwise we always get the same zoomPart and nothing happens.
+ */
+ wmPtr = ((TkWindow *) tkwin)->wmInfoPtr;
+ if (wmPtr->style >= floatProc && wmPtr->style <= floatSideZoomGrowProc) {
+ if (zoomPart == inZoomIn) {
+ Rect zoomRect = tcl_macQdPtr->screenBits.bounds;
+ InsetRect(&zoomRect, 60, 60);
+ SetWindowStandardState(whichWindow, &zoomRect);
+ zoomPart = inZoomOut;
+ } else {
+ zoomPart = inZoomIn;
+ }
+ }
+
+ ZoomWindow(whichWindow, zoomPart, false);
+ InvalRect(&whichWindow->portRect);
+ TkMacInvalClipRgns((TkWindow *) tkwin);
+
+ LocalToGlobal(&location);
+ TkMacWindowOffset(whichWindow, &xOffset, &yOffset);
+ location.h -= xOffset;
+ location.v -= yOffset;
+ TkGenWMConfigureEvent(tkwin, location.h, location.v,
+ whichWindow->portRect.right - whichWindow->portRect.left,
+ whichWindow->portRect.bottom - whichWindow->portRect.top,
+ TK_BOTH_CHANGED);
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUnsupported1Cmd --
+ *
+ * This procedure is invoked to process the "unsupported1" Tcl
+ * command. This command allows you to set the style of decoration
+ * for a Macintosh window.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * Changes the style of a new Mac window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+TkUnsupported1Cmd(
+ ClientData clientData, /* Main window associated with
+ * interpreter. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int argc, /* Number of arguments. */
+ char **argv) /* Argument strings. */
+{
+ Tk_Window tkwin = (Tk_Window) clientData;
+ TkWindow *winPtr;
+ register WmInfo *wmPtr;
+ int c;
+ size_t length;
+
+ if (argc < 3) {
+ wrongNumArgs:
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ argv[0], " option window ?arg ...?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ Tcl_AppendResult(interp, "window \"", winPtr->pathName,
+ "\" isn't a top-level window", (char *) NULL);
+ return TCL_ERROR;
+ }
+ wmPtr = winPtr->wmInfoPtr;
+ c = argv[1][0];
+ length = strlen(argv[1]);
+ if ((c == 's') && (strncmp(argv[1], "style", length) == 0)) {
+ if ((argc != 3) && (argc != 4)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0], " style window ?windowStyle?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (argc == 3) {
+ switch (wmPtr->style) {
+ case noGrowDocProc:
+ case documentProc:
+ interp->result = "documentProc";
+ break;
+ case dBoxProc:
+ interp->result = "dBoxProc";
+ break;
+ case plainDBox:
+ interp->result = "plainDBox";
+ break;
+ case altDBoxProc:
+ interp->result = "altDBoxProc";
+ break;
+ case movableDBoxProc:
+ interp->result = "movableDBoxProc";
+ break;
+ case zoomDocProc:
+ case zoomNoGrow:
+ interp->result = "zoomDocProc";
+ break;
+ case rDocProc:
+ interp->result = "rDocProc";
+ break;
+ case floatProc:
+ case floatGrowProc:
+ interp->result = "floatProc";
+ break;
+ case floatZoomProc:
+ case floatZoomGrowProc:
+ interp->result = "floatZoomProc";
+ break;
+ case floatSideProc:
+ case floatSideGrowProc:
+ interp->result = "floatSideProc";
+ break;
+ case floatSideZoomProc:
+ case floatSideZoomGrowProc:
+ interp->result = "floatSideZoomProc";
+ break;
+ default:
+ panic("invalid style");
+ }
+ return TCL_OK;
+ }
+ if (strcmp(argv[3], "documentProc") == 0) {
+ wmPtr->style = documentProc;
+ } else if (strcmp(argv[3], "noGrowDocProc") == 0) {
+ wmPtr->style = documentProc;
+ } else if (strcmp(argv[3], "dBoxProc") == 0) {
+ wmPtr->style = dBoxProc;
+ } else if (strcmp(argv[3], "plainDBox") == 0) {
+ wmPtr->style = plainDBox;
+ } else if (strcmp(argv[3], "altDBoxProc") == 0) {
+ wmPtr->style = altDBoxProc;
+ } else if (strcmp(argv[3], "movableDBoxProc") == 0) {
+ wmPtr->style = movableDBoxProc;
+ } else if (strcmp(argv[3], "zoomDocProc") == 0) {
+ wmPtr->style = zoomDocProc;
+ } else if (strcmp(argv[3], "zoomNoGrow") == 0) {
+ wmPtr->style = zoomNoGrow;
+ } else if (strcmp(argv[3], "rDocProc") == 0) {
+ wmPtr->style = rDocProc;
+ } else if (strcmp(argv[3], "floatProc") == 0) {
+ wmPtr->style = floatGrowProc;
+ } else if (strcmp(argv[3], "floatGrowProc") == 0) {
+ wmPtr->style = floatGrowProc;
+ } else if (strcmp(argv[3], "floatZoomProc") == 0) {
+ wmPtr->style = floatZoomGrowProc;
+ } else if (strcmp(argv[3], "floatZoomGrowProc") == 0) {
+ wmPtr->style = floatZoomGrowProc;
+ } else if (strcmp(argv[3], "floatSideProc") == 0) {
+ wmPtr->style = floatSideGrowProc;
+ } else if (strcmp(argv[3], "floatSideGrowProc") == 0) {
+ wmPtr->style = floatSideGrowProc;
+ } else if (strcmp(argv[3], "floatSideZoomProc") == 0) {
+ wmPtr->style = floatSideZoomGrowProc;
+ } else if (strcmp(argv[3], "floatSideZoomGrowProc") == 0) {
+ wmPtr->style = floatSideZoomGrowProc;
+ } else {
+ Tcl_AppendResult(interp, "bad style: should be documentProc, ",
+ "dBoxProc, plainDBox, altDBoxProc, movableDBoxProc, ",
+ "zoomDocProc, rDocProc, floatProc, floatZoomProc, ",
+ "floatSideProc, or floatSideZoomProc",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],
+ "\": must be style",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpMakeMenuWindow --
+ *
+ * Configure the window to be either a undecorated pull-down
+ * (or pop-up) menu, or as a toplevel floating menu (palette).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the style bit used to create a new Mac toplevel.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpMakeMenuWindow(
+ Tk_Window tkwin, /* New window. */
+ int transient) /* 1 means menu is only posted briefly as
+ * a popup or pulldown or cascade. 0 means
+ * menu is always visible, e.g. as a
+ * floating menu. */
+{
+ if (transient) {
+ ((TkWindow *) tkwin)->wmInfoPtr->style = plainDBox;
+ } else {
+ ((TkWindow *) tkwin)->wmInfoPtr->style = floatProc;
+ ((TkWindow *) tkwin)->wmInfoPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
+ ((TkWindow *) tkwin)->wmInfoPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacMakeRealWindowExist --
+ *
+ * This function finally creates the real Macintosh window that
+ * the Mac actually understands.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A new Macintosh toplevel is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacMakeRealWindowExist(
+ TkWindow *winPtr) /* Tk window. */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ WindowRef newWindow = NULL;
+ MacDrawable *macWin;
+ Rect geometry;
+ Tcl_HashEntry *valueHashPtr;
+ int new;
+ TkMacWindowList *listPtr;
+
+ if (TkMacHostToplevelExists(winPtr)) {
+ return;
+ }
+
+ macWin = (MacDrawable *) winPtr->window;
+
+ /*
+ * If this is embedded, make sure its container's toplevel exists,
+ * then return...
+ */
+
+ if (Tk_IsEmbedded(winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(winPtr);
+ if (contWinPtr != NULL) {
+ TkMacMakeRealWindowExist(contWinPtr->privatePtr->toplevel->winPtr);
+ macWin->flags |= TK_HOST_EXISTS;
+ return;
+ } else {
+ panic("TkMacMakeRealWindowExist could not find container");
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+
+ InitialWindowBounds(winPtr, &geometry);
+
+ newWindow = NewCWindow(NULL, &geometry, "\ptemp", false,
+ (short) wmPtr->style, (WindowRef) -1, true, 0);
+ if (newWindow == NULL) {
+ panic("couldn't allocate new Mac window");
+ }
+
+ /*
+ * Add this window to the list of toplevel windows.
+ */
+
+ listPtr = (TkMacWindowList *) ckalloc(sizeof(TkMacWindowList));
+ listPtr->nextPtr = tkMacWindowListPtr;
+ listPtr->winPtr = winPtr;
+ tkMacWindowListPtr = listPtr;
+
+ macWin->portPtr = (GWorldPtr) newWindow;
+ MacMoveWindow(newWindow, (int) geometry.left, (int) geometry.top);
+ SetPort((GrafPtr) newWindow);
+
+ if (!windowHashInit) {
+ Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS);
+ windowHashInit = true;
+ }
+ valueHashPtr = Tcl_CreateHashEntry(&windowTable,
+ (char *) newWindow, &new);
+ if (!new) {
+ panic("same macintosh window allocated twice!");
+ }
+ Tcl_SetHashValue(valueHashPtr, macWin);
+
+ macWin->flags |= TK_HOST_EXISTS;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacRegisterOffScreenWindow --
+ *
+ * This function adds the passed in Off Screen Port to the
+ * hash table that maps Mac windows to root X windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An entry is added to the windowTable hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacRegisterOffScreenWindow(
+ Window window, /* Window structure. */
+ GWorldPtr portPtr) /* Pointer to a Mac GWorld. */
+{
+ WindowRef newWindow = NULL;
+ MacDrawable *macWin;
+ Tcl_HashEntry *valueHashPtr;
+ int new;
+
+ macWin = (MacDrawable *) window;
+ if (!windowHashInit) {
+ Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS);
+ windowHashInit = true;
+ }
+ valueHashPtr = Tcl_CreateHashEntry(&windowTable,
+ (char *) portPtr, &new);
+ if (!new) {
+ panic("same macintosh window allocated twice!");
+ }
+ Tcl_SetHashValue(valueHashPtr, macWin);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacUnregisterMacWindow --
+ *
+ * Given a macintosh port window, this function removes the
+ * association between this window and the root X window that
+ * Tk cares about.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An entry is removed from the windowTable hash table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacUnregisterMacWindow(
+ GWorldPtr portPtr) /* Pointer to a Mac GWorld. */
+{
+ if (!windowHashInit) {
+ panic("TkMacUnregisterMacWindow: unmapping before inited");;
+ }
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&windowTable,
+ (char *) portPtr));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacSetScrollbarGrow --
+ *
+ * Sets a flag for a toplevel window indicating that the passed
+ * Tk scrollbar window will display the grow region for the
+ * toplevel window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A flag is set int windows toplevel parent.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacSetScrollbarGrow(
+ TkWindow *winPtr, /* Tk scrollbar window. */
+ int flag) /* Boolean value true or false. */
+{
+ if (flag) {
+ winPtr->privatePtr->toplevel->flags |= TK_SCROLLBAR_GROW;
+ winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = winPtr;
+ } else if (winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr
+ == winPtr) {
+ winPtr->privatePtr->toplevel->flags &= ~TK_SCROLLBAR_GROW;
+ winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacGetScrollbarGrowWindow --
+ *
+ * Tests to see if a given window's toplevel window contains a
+ * scrollbar that will draw the GrowIcon for the window.
+ *
+ * Results:
+ * Boolean value.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow *
+TkMacGetScrollbarGrowWindow(
+ TkWindow *winPtr) /* Tk window. */
+{
+ TkWindow *scrollWinPtr;
+
+ if (winPtr == NULL) {
+ return NULL;
+ }
+ scrollWinPtr =
+ winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr;
+ if (winPtr != NULL) {
+ /*
+ * We need to confirm the window exists.
+ */
+ if ((Tk_Window) scrollWinPtr !=
+ Tk_IdToWindow(winPtr->display, winPtr->window)) {
+ scrollWinPtr = NULL;
+ }
+ }
+ return scrollWinPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWmFocusToplevel --
+ *
+ * This is a utility procedure invoked by focus-management code. It
+ * exists because of the extra wrapper windows that exist under
+ * Unix; its job is to map from wrapper windows to the
+ * corresponding toplevel windows. On PCs and Macs there are no
+ * wrapper windows so no mapping is necessary; this procedure just
+ * determines whether a window is a toplevel or not.
+ *
+ * Results:
+ * If winPtr is a toplevel window, returns the pointer to the
+ * window; otherwise returns NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow *
+TkWmFocusToplevel(
+ TkWindow *winPtr) /* Window that received a focus-related
+ * event. */
+{
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ return NULL;
+ }
+ return winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetWrapperWindow --
+ *
+ * This is a utility procedure invoked by focus-management code. It
+ * maps to the wrapper for a top-level, which is just the same
+ * as the top-level on Macs and PCs.
+ *
+ * Results:
+ * If winPtr is a toplevel window, returns the pointer to the
+ * window; otherwise returns NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow *
+TkpGetWrapperWindow(
+ TkWindow *winPtr) /* Window that received a focus-related
+ * event. */
+{
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ return NULL;
+ }
+ return winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpWmSetState --
+ *
+ * Sets the window manager state for the wrapper window of a
+ * given toplevel window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May maximize, minimize, restore, or withdraw a window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpWmSetState(winPtr, state)
+ TkWindow *winPtr; /* Toplevel window to operate on. */
+ int state; /* One of IconicState, ZoomState, NormalState,
+ * or WithdrawnState. */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ GWorldPtr macWin;
+
+ wmPtr->hints.initial_state = state;
+ if (wmPtr->flags & WM_NEVER_MAPPED) {
+ return;
+ }
+
+ macWin = TkMacGetDrawablePort(winPtr->window);
+
+ if (state == WithdrawnState) {
+ Tk_UnmapWindow((Tk_Window) winPtr);
+ } else if (state == IconicState) {
+ Tk_UnmapWindow((Tk_Window) winPtr);
+#ifdef HAVE_APPEARANCE
+ if (HaveAppearance()) {
+ /*
+ * The window always gets unmapped. However, if we can show the
+ * icon version of the window (collapsed) we make the window visable
+ * and then collapse it.
+ *
+ * TODO: This approach causes flashing!
+ */
+
+ if (IsWindowCollapsable((WindowRef) macWin)) {
+ ShowWindow((WindowRef) macWin);
+ CollapseWindow((WindowPtr) macWin, true);
+ }
+ }
+#endif
+ } else if (state == NormalState) {
+ Tk_MapWindow((Tk_Window) winPtr);
+#ifdef HAVE_APPEARANCE
+ if (HaveAppearance()) {
+ CollapseWindow((WindowPtr) macWin, false);
+ }
+#endif
+ } else if (state == ZoomState) {
+ /* TODO: need to support zoomed windows */
+ }
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * HaveAppearance --
+ *
+ * Determine if the appearance manager is available on this Mac.
+ * We cache the result so future calls are fast.
+ *
+ * Results:
+ * True if the appearance manager is present, false otherwise.
+ *
+ * Side effects:
+ * Calls Gestalt to query system values.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HaveAppearance()
+{
+ static initialized = false;
+ static int haveAppearance = false;
+ long response = 0;
+ OSErr err = noErr;
+
+#ifdef HAVE_APPEARANCE
+ if (!initialized) {
+ err = Gestalt(gestaltAppearanceAttr, &response);
+ if (err == noErr) {
+ haveAppearance = true;
+ }
+ }
+#endif
+
+ return haveAppearance;
+}
diff --git a/mac/tkMacXCursors.r b/mac/tkMacXCursors.r
new file mode 100644
index 0000000..29ddc3e
--- /dev/null
+++ b/mac/tkMacXCursors.r
@@ -0,0 +1,961 @@
+/*
+ * tkMacXCursors.r --
+ *
+ * This file defines a set of Macintosh cursor resources that
+ * emulate the X cursor set. All of these cursors were
+ * constructed and donated by Grant Neufeld. (gneufeld@ccs.carleton.ca)
+ *
+ *
+ * Copyright (c) 1995-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacXCursors.r 1.4 96/01/11 13:18:22
+ */
+
+/*
+ * All of the X cursors are defined as 'CURS' resources. However, a
+ * subset of the X cursors are also defined as 'crsr' resources. Tk
+ * will attempt to first use the color cursors ('crsr') if it doesn't
+ * exist it will attempt to use the black & white cursor ('CURS').
+ */
+
+data 'CURS' (3000, "X_cursor") {
+ $"E007 F00F F81F 7C3E 3E7C 1FF8 0FF0 07E0"
+ $"07E0 0FF0 1FF8 3E7C 7C3E F81F F00F E007"
+ $"0000 6006 700E 381C 1C38 0E70 07E0 03C0"
+ $"03C0 07E0 0E70 1C38 381C 700E 6006 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3001, "arrow") {
+ $"0000 0006 001E 007C 01FC 07F8 00F8 01F0"
+ $"03B0 0720 0E20 1C00 3800 7000 2000 0000"
+ $"0007 001F 007F 01FE 07FE 1FFC 7FFC 03F8"
+ $"07F8 0FF0 1F70 3E60 7C60 F840 7040 2000"
+ $"0001 000E"
+};
+
+data 'CURS' (3002, "based_arrow_down") {
+ $"0000 0000 0000 1FE0 0000 1FE0 0300 0300"
+ $"0300 0B40 0780 0300 0000 0000 0000 0000"
+ $"0000 0000 0000 1FE0 0000 1FE0 0780 0780"
+ $"3FF0 1FE0 0FC0 0780 0300 0000 0000 0000"
+ $"000B 0006"
+};
+
+data 'CURS' (3003, "based_arrow_up") {
+ $"0000 0000 0000 0000 0300 0780 0B40 0300"
+ $"0300 0300 1FE0 0000 1FE0 0000 0000 0000"
+ $"0000 0000 0000 0300 0780 0FC0 1FE0 3FF0"
+ $"0780 0780 1FE0 0000 1FE0 0000 0000 0000"
+ $"0004 0006"
+};
+
+data 'CURS' (3004, "boat") {
+ $"0000 0000 0000 0000 0100 03C0 8460 FFFF"
+ $"0018 0020 0040 FFC0 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0100 03C0 87E0 FFFF"
+ $"FFF8 FFE0 FFC0 FFC0 0000 0000 0000 0000"
+ $"0007 000F"
+};
+
+data 'CURS' (3005, "bogosity") {
+ $"0000 711C 1110 1110 1110 7FFC 5114 5114"
+ $"5114 5114 7FFC 1110 1110 1110 711C 0000"
+ $"0000 0000 0000 0000 0000 7FFC 7FFC 7FFC"
+ $"7FFC 7FFC 7FFC 0000 0000 0000 0000 0000"
+ $"0001 0007"
+};
+
+data 'CURS' (3006, "bottom_left_corner") {
+ $"0000 0000 0000 0000 C000 C020 C840 C880"
+ $"C900 CA00 CC00 CFC0 C000 C000 FFF0 FFF0"
+ $"0000 0000 0000 0000 0000 0020 0840 0880"
+ $"0900 0A00 0C00 0FC0 0000 0000 0000 0000"
+ $"000F 0000"
+};
+
+data 'CURS' (3007, "bottom_right_corner") {
+ $"0000 0000 0000 0000 0003 0403 0213 0113"
+ $"0093 0053 0033 03F3 0003 0003 0FFF 0FFF"
+ $"0000 0000 0000 0000 0000 0400 0210 0110"
+ $"0090 0050 0030 03F0 0000 0000 0000 0000"
+ $"000F 000F"
+};
+
+data 'CURS' (3008, "bottom_side") {
+ $"0000 0000 0100 0100 0100 0100 0100 1110"
+ $"0920 0540 0380 0100 0000 7FFC 7FFC 0000"
+ $"0000 0000 0100 0100 0100 0100 0100 1110"
+ $"0920 0540 0380 0100 0000 0000 0000 0000"
+ $"000B 0007"
+};
+
+data 'CURS' (3009, "bottom_tee") {
+ $"0000 0000 0000 0180 0180 0180 0180 0180"
+ $"0180 0180 7FFE 7FFE 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"000B 0007"
+};
+
+data 'CURS' (3010, "box_spiral") {
+ $"FFFE 8000 BFFE A002 AFFA A80A ABEA AA2A"
+ $"AAAA ABAA A82A AFEA A00A BFFA 8002 FFFE"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0008 0008"
+};
+
+data 'CURS' (3011, "center_ptr") {
+ $"0000 0300 0300 0780 0780 0FC0 0FC0 1FE0"
+ $"1FE0 3330 2310 0300 0300 0300 0300 0000"
+ $"0300 0780 0780 0FC0 0FC0 1FE0 1FE0 3FF0"
+ $"3FF0 7FF8 77B8 6798 0780 0780 0780 0780"
+ $"0001 0006"
+};
+
+data 'CURS' (3012, "circle") {
+ $"0000 03C0 0FF0 1FF8 3C3C 381C 700E 700E"
+ $"700E 700E 381C 3C3C 1FF8 0FF0 03C0 0000"
+ $"03C0 0FF0 1FF8 3FFC 7FFE 7C3E F81F F81F"
+ $"F81F F81F 7C3E 7FFE 3FFC 1FF8 0FF0 03C0"
+ $"0007 0007"
+};
+
+data 'CURS' (3013, "clock") {
+ $"1FF8 33CC 6466 4992 4F12 4422 63C6 3FFC"
+ $"2994 2994 2994 2BD4 6996 781E 7FFE 7FFE"
+ $"1FF8 3FFC 7FFE 7FFE 7FFE 7FFE 7FFE 3FFC"
+ $"3FFC 3FFC 3FFC 3FFC 7FFE 7FFE 7FFE 7FFE"
+ $"0004 0008"
+};
+
+data 'CURS' (3014, "coffee_mug") {
+ $"03F8 0C06 1001 1C07 33F9 7001 D001 9001"
+ $"960D DA55 7A55 36ED 10A1 1001 0802 07FC"
+ $"03F8 0FFE 1FFF 1FFF 3FFF 7FFF FFFF FFFF"
+ $"FFFF FFFF 7FFF 3FFF 1FFF 1FFF 0FFE 07FC"
+ $"0004 0003"
+};
+
+data 'CURS' (3015, "cross") {
+ $"0280 0280 0280 0280 0280 0280 FEFE 0000"
+ $"FEFE 0280 0280 0280 0280 0280 0280 0000"
+ $"0380 0380 0380 0380 0380 0380 FFFE FFFE"
+ $"FFFE 0380 0380 0380 0380 0380 0380 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3016, "cross_reverse") {
+ $"4284 A28A 5294 2AA8 16D0 0AA0 FD7E 0280"
+ $"FD7E 0AA0 16D0 2AA8 5294 A28A 4284 0000"
+ $"4384 E38E 739C 3BB8 1FF0 0FE0 FFFE FFFE"
+ $"FFFE 0FE0 1FF0 3BB8 739C E38E 4384 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3017, "crosshair") {
+ $"0100 0100 0100 0100 0100 0100 0100 FEFE"
+ $"0100 0100 0100 0100 0100 0100 0100 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3018, "diamond_cross") {
+ $"0280 06C0 0AA0 1290 2288 4284 FEFE 0000"
+ $"FEFE 4284 2288 1290 0AA0 06C0 0280 0000"
+ $"0280 06C0 0EE0 1EF0 3EF8 7EFC FEFE 0000"
+ $"FEFE 7EFC 3EF8 1EF0 0EE0 06C0 0280 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3019, "dot") {
+ $"0000 0000 0780 1FE0 1FE0 3FF0 3FF0 3FF0"
+ $"3FF0 1FE0 1FE0 0780 0000 0000 0000 0000"
+ $"0000 0780 1FE0 3FF0 3FF0 7FF8 7FF8 7FF8"
+ $"7FF8 3FF0 3FF0 1FE0 0780 0000 0000 0000"
+ $"0006 0006"
+};
+
+data 'CURS' (3020, "dotbox") {
+ $"0000 0000 3FFC 2004 2004 2004 2004 2184"
+ $"2184 2004 2004 2004 2004 3FFC 0000 0000"
+ $"0000 0000 3FFC 3FFC 300C 300C 318C 33CC"
+ $"33CC 318C 300C 300C 3FFC 3FFC 0000 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3021, "double_arrow") {
+ $"0000 0180 03C0 07E0 0DB0 1998 0180 0180"
+ $"0180 0180 1998 0DB0 07E0 03C0 0180 0000"
+ $"0180 03C0 07E0 0FF0 1FF8 3FFC 3BDC 03C0"
+ $"03C0 3BDC 3FFC 1FF8 0FF0 07E0 03C0 0180"
+ $"0007 0007"
+};
+
+data 'CURS' (3022, "draft_large") {
+ $"0000 0002 000C 003C 00F8 03F8 0FF0 00F0"
+ $"0160 0260 0440 0840 1000 2000 4000 0000"
+ $"0003 000F 003E 00FE 03FC 0FFC 3FF8 FFF8"
+ $"03F0 07F0 0EE0 1CE0 38C0 70C0 E080 4080"
+ $"0001 000E"
+};
+
+data 'CURS' (3023, "draft_small") {
+ $"0000 0002 000C 003C 00F8 03F8 0070 00B0"
+ $"0120 0220 0400 0800 1000 2000 4000 0000"
+ $"0003 000F 003E 00FE 03FC 0FFC 3FF8 01F8"
+ $"03F0 0770 0E60 1C60 3840 7040 E000 4000"
+ $"0001 000E"
+};
+
+data 'CURS' (3024, "draped_box") {
+ $"0000 0000 3FFC 2244 2664 2C34 381C 2184"
+ $"2184 381C 2C34 2664 2244 3FFC 0000 0000"
+ $"0000 0000 3FFC 3E7C 3E7C 3C3C 399C 23C4"
+ $"23C4 399C 3C3C 3E7C 3E7C 3FFC 0000 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3025, "exchange") {
+ $"0000 47C0 6FE0 7C30 4810 4C00 7E00 0000"
+ $"0000 00FC 0064 1024 187C 0FEC 07C4 0000"
+ $"C7C0 EFE0 FFF0 FFF8 FC38 FE10 FF00 FF80"
+ $"03FE 01FE 10FE 387E 3FFE 1FFE 0FEE 07C6"
+ $"0007 0007"
+};
+
+data 'CURS' (3026, "fleur") {
+ $"0000 0180 03C0 07E0 0180 1188 318C 7FFE"
+ $"7FFE 318C 1188 0180 07E0 03C0 0180 0000"
+ $"0180 03C0 07E0 0FF0 17E8 3BDC 7FFE FFFF"
+ $"FFFF 7FFE 3BDC 17E8 0FF0 07E0 03C0 0180"
+ $"0007 0007"
+};
+
+data 'CURS' (3027, "gobbler") {
+ $"0000 0078 0070 4036 4FB0 7FF0 7E30 7C30"
+ $"3038 00F0 0FE0 0400 0400 0400 0F00 0000"
+ $"00FC 00FC E0FF FFFF FFFF FFF8 FFF8 FFF8"
+ $"FFFC 7FFC 3FF8 1FF0 0E00 1F80 1F80 1F80"
+ $"0003 000E"
+};
+
+data 'CURS' (3028, "gumby") {
+ $"3F00 10C0 C820 EAA0 C820 CBA0 F838 383E"
+ $"0826 0826 092E 0926 0920 1110 2108 3EF8"
+ $"3F00 1FC0 CFE0 EFE0 CFE0 CFE0 FFF8 3FFE"
+ $"0FE6 0FE6 0FEE 0FE6 0FE0 1FF0 3FF8 3EF8"
+ $"0000 0002"
+};
+
+data 'CURS' (3029, "hand1") {
+ $"000C 003C 00F0 01E0 03C0 07E0 0FF0 2FE0"
+ $"7FF0 5FF0 07E0 07C0 4A00 6200 3400 1800"
+ $"000C 003C 00F0 01E0 03C0 07E0 0FF0 2FE0"
+ $"7FF0 7FF0 7FE0 7FC0 7E00 7E00 3C00 1800"
+ $"0000 000D"
+};
+
+data 'CURS' (3030, "hand2") {
+ $"0000 3FC0 4020 3F10 0808 0708 0808 0714"
+ $"0822 0641 0182 0124 0088 0050 0020 0000"
+ $"0000 3FC0 7FE0 3FF0 0FF8 07F8 0FF8 07FC"
+ $"0FFE 07FF 01FE 01FC 00F8 0070 0020 0000"
+ $"0002 0001"
+};
+
+data 'CURS' (3031, "heart") {
+ $"0000 3EF8 638C C106 8002 8002 8002 8002"
+ $"C006 600C 3018 1830 0C60 06C0 0380 0000"
+ $"0000 3EF8 7FFC FFFE FFFE FFFE FFFE FFFE"
+ $"FFFE 7FFC 3FF8 1FF0 0FE0 07C0 0380 0000"
+ $"0003 0007"
+};
+
+data 'CURS' (3032, "icon") {
+ $"FFFF D555 AAAB D555 A00B D005 A00B D005"
+ $"A00B D005 A00B D005 AAAB D555 AAAB FFFF"
+ $"FFFF FFFF FFFF FFFF F00F F00F F00F F00F"
+ $"F00F F00F F00F F00F FFFF FFFF FFFF FFFF"
+ $"0007 0007"
+};
+
+data 'CURS' (3033, "iron_cross") {
+ $"0000 3FFC 1FF8 4FF2 67E6 73CE 799E 7FFE"
+ $"7FFE 799E 73CE 67E6 4FF2 1FF8 3FFC 0000"
+ $"7FFE 7FFE FFFF FFFF FFFF FFFF FFFF FFFF"
+ $"FFFF FFFF FFFF FFFF FFFF FFFF 7FFE 7FFE"
+ $"0007 0006"
+};
+
+data 'CURS' (3034, "left_ptr") {
+ $"0000 0800 0C00 0E00 0F00 0F80 0FC0 0FE0"
+ $"0FF0 0F80 0D80 08C0 00C0 0060 0060 0000"
+ $"1800 1C00 1E00 1F00 1F80 1FC0 1FE0 1FF0"
+ $"1FF8 1FFC 1FC0 1DE0 19E0 10F0 00F0 0070"
+ $"0001 0004"
+};
+
+data 'CURS' (3035, "left_side") {
+ $"0000 6000 6000 6080 6100 6200 6400 6FFC"
+ $"6400 6200 6100 6080 6000 6000 0000 0000"
+ $"0000 0000 0000 0080 0100 0200 0400 0FFC"
+ $"0400 0200 0100 0080 0000 0000 0000 0000"
+ $"0007 0004"
+};
+
+data 'CURS' (3036, "left_tee") {
+ $"0000 0C00 0C00 0C00 0C00 0C00 0C00 0FF8"
+ $"0FF8 0C00 0C00 0C00 0C00 0C00 0C00 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0007 0004"
+};
+
+data 'CURS' (3037, "leftbutton") {
+ $"8002 7FFC 7FFC 4444 4554 4554 4554 4554"
+ $"4444 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 8002"
+ $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE"
+ $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE"
+ $"0004 0003"
+};
+
+data 'CURS' (3038, "ll_angle") {
+ $"0000 0000 0000 0C00 0C00 0C00 0C00 0C00"
+ $"0C00 0C00 0FF8 0FF8 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"000B 0004"
+};
+
+data 'CURS' (3039, "lr_angle") {
+ $"0000 0000 0000 0030 0030 0030 0030 0030"
+ $"0030 0030 1FF0 1FF0 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"000B 000B"
+};
+
+data 'CURS' (3040, "man") {
+ $"0380 1EF0 0280 8100 4387 244B 1D70 0540"
+ $"0440 0280 0440 0920 1290 1450 783C F83F"
+ $"0380 1FF0 0380 8100 4387 27CB 1FF0 07C0"
+ $"07C0 0380 07C0 0FE0 1EF0 1C70 783C F83F"
+ $"0001 0007"
+};
+
+data 'CURS' (3041, "middlebutton") {
+ $"8002 7FFC 7FFC 4444 5454 5454 5454 5454"
+ $"4444 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 8002"
+ $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE"
+ $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE"
+ $"0004 0007"
+};
+
+data 'CURS' (3042, "mouse") {
+ $"0600 0100 0180 0FF0 1008 17E8 1428 1428"
+ $"17E8 1008 1008 1008 1008 1008 1008 0FF0"
+ $"0600 0100 0180 0FF0 1FF8 1FF8 1FF8 1FF8"
+ $"1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 0FF0"
+ $"0000 0000"
+};
+
+data 'CURS' (3043, "pencil") {
+ $"0000 00F0 0088 0108 0190 0270 0220 0440"
+ $"0440 0880 0880 1100 1E00 1C00 1800 1000"
+ $"0000 00F0 00F8 01F8 01F0 03F0 03E0 07C0"
+ $"07C0 0F80 0F80 1F00 1E00 1C00 1800 1000"
+ $"000F 0003"
+};
+
+data 'CURS' (3044, "pirate") {
+ $"03C0 07E0 0FF0 1998 1998 0FF0 07E0 03C0"
+ $"43C2 43C3 2184 1C38 03C0 0FF1 781F 4002"
+ $"07E0 0FF0 1FF8 3FFC 3FFC 1FF8 0FF0 47E2"
+ $"E7E7 E7E7 7FFF 3FFC 1FF9 7FFF FFFF F81F"
+ $"000A 0007"
+};
+
+data 'CURS' (3045, "plus") {
+ $"0000 0000 0000 0180 0180 0180 0180 1FF8"
+ $"1FF8 0180 0180 0180 0180 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3046, "question_arrow") {
+ $"07C0 0FE0 1C70 1830 1C30 0C70 00E0 03C0"
+ $"0380 0280 0280 0EE0 06C0 0380 0100 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 3FF8 1FF0 0FE0 07C0 0380 0100"
+ $"000E 0007"
+};
+
+data 'CURS' (3047, "right_ptr") {
+ $"0000 0010 0030 0070 00F0 01F0 03F0 07F0"
+ $"0FF0 01F0 01B0 0310 0300 0600 0600 0000"
+ $"0018 0038 0078 00F8 01F8 03F8 07F8 0FF8"
+ $"1FF8 3FF8 03F8 07B8 0798 0F08 0F00 0E00"
+ $"0001 000B"
+};
+
+data 'CURS' (3048, "right_side") {
+ $"0000 0000 0006 0006 0106 0086 0046 0026"
+ $"3FF6 0026 0046 0086 0106 0006 0006 0000"
+ $"0000 0000 0000 0000 0100 0080 0040 0020"
+ $"3FF0 0020 0040 0080 0100 0000 0000 0000"
+ $"0008 000B"
+};
+
+data 'CURS' (3049, "right_tee") {
+ $"0000 0030 0030 0030 0030 0030 0030 1FF0"
+ $"1FF0 0030 0030 0030 0030 0030 0030 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0007 000A"
+};
+
+data 'CURS' (3050, "rightbutton") {
+ $"8002 7FFC 7FFC 4444 5544 5544 5544 5544"
+ $"4444 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 8002"
+ $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE"
+ $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE"
+ $"0004 0003"
+};
+
+data 'CURS' (3051, "rtl_logo") {
+ $"0000 7FFE 4022 4022 4022 7FE2 4422 4422"
+ $"4422 4422 47FE 4402 4402 4402 7FFE 0000"
+ $"0000 7FFE 7FFE 6076 7FF6 7FF6 7C36 6C36"
+ $"6C36 6C3E 6FFE 6FFE 6E06 7FFE 7FFE 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3052, "sailboat") {
+ $"0000 0040 0040 0160 0160 0360 0370 0770"
+ $"0770 0F78 0F78 1F78 1F7C 3E38 0000 0000"
+ $"0040 00E0 01E0 03F0 03F0 07F0 07F8 0FF8"
+ $"0FF8 1FFC 1FFC 3FFC 3FFE 7F7C 7E38 0000"
+ $"000C 0008"
+};
+
+data 'CURS' (3053, "sb_down_arrow") {
+ $"0280 0280 0280 0280 0280 0280 0280 0280"
+ $"0280 0280 0280 0FE0 07C0 0380 0100 0000"
+ $"0380 0380 0380 0380 0380 0380 0380 0380"
+ $"0380 0380 0380 1FF0 0FE0 07C0 0380 0100"
+ $"000E 0007"
+};
+
+data 'CURS' (3054, "sb_h_double_arrow") {
+ $"0000 0000 0000 0000 0810 1818 3FFC 781E"
+ $"3FFC 1818 0810 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0810 1818 381C 7FFE FFFF"
+ $"7FFE 381C 1818 0810 0000 0000 0000 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3055, "sb_left_arrow") {
+ $"0000 0000 0000 0000 0800 1800 3FFF 7800"
+ $"3FFF 1800 0800 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0800 1800 3800 7FFF FFFF"
+ $"7FFF 3800 1800 0800 0000 0000 0000 0000"
+ $"0007 0001"
+};
+
+data 'CURS' (3056, "sb_right_arrow") {
+ $"0000 0000 0000 0000 0000 0010 0018 FFFC"
+ $"001E FFFC 0018 0010 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0010 0018 001C FFFE"
+ $"FFFF FFFE 001C 0018 0010 0000 0000 0000"
+ $"0008 000E"
+};
+
+data 'CURS' (3057, "sb_up_arrow") {
+ $"0000 0080 01C0 03E0 07F0 0140 0140 0140"
+ $"0140 0140 0140 0140 0140 0140 0140 0140"
+ $"0080 01C0 03E0 07F0 0FF8 01C0 01C0 01C0"
+ $"01C0 01C0 01C0 01C0 01C0 01C0 01C0 01C0"
+ $"0001 0008"
+};
+
+data 'CURS' (3058, "sb_v_double_arrow") {
+ $"0000 0100 0380 07C0 0FE0 0280 0280 0280"
+ $"0280 0280 0280 0FE0 07C0 0380 0100 0000"
+ $"0100 0380 07C0 0FE0 1FF0 0380 0380 0380"
+ $"0380 0380 0380 1FF0 0FE0 07C0 0380 0100"
+ $"0007 0007"
+};
+
+data 'CURS' (3059, "shuttle") {
+ $"0020 0070 00F8 01DE 05DE 09DE 11DE 11DE"
+ $"11DE 11DE 31DE 71DE FDDE 1888 0078 0030"
+ $"0020 0070 00F8 01FE 07FE 0FFE 1FFE 1FFE"
+ $"1FFE 1FFE 3FFE 7FFE FFFE 18F8 0078 0030"
+ $"0000 000A"
+};
+
+data 'CURS' (3060, "sizing") {
+ $"0000 7F80 4000 4000 4000 47E0 4420 4422"
+ $"4422 0422 07E2 0012 000A 0006 01FE 0000"
+ $"FFC0 FFC0 FFC0 E000 EFF0 EFF0 EC37 EC37"
+ $"EC37 EC37 0FF7 0FFF 001F 03FF 03FF 03FF"
+ $"000E 000E"
+};
+
+data 'CURS' (3061, "spider") {
+ $"2010 1020 1020 0840 0840 8787 6798 1FE0"
+ $"1FE0 6798 8787 0840 0840 1020 1020 2010"
+ $"7038 3870 3870 1CE0 9FE7 EFDF FFFF 7FF8"
+ $"7FF8 FFFF EFDF 9FE7 1CE0 3870 3870 7038"
+ $"0007 0007"
+};
+
+data 'CURS' (3062, "spraycan") {
+ $"0018 0040 0D18 1E40 1A18 3F00 2100 3900"
+ $"2900 3900 2900 3900 3900 2100 2100 3F00"
+ $"0000 0000 0C00 1E00 1E00 3F00 3F00 3F00"
+ $"3F00 3F00 3F00 3F00 3F00 3F00 3F00 3F00"
+ $"0002 0007"
+};
+
+data 'CURS' (3063, "star") {
+ $"0100 0280 0280 0280 0440 0440 0440 3938"
+ $"C006 3838 0920 1290 2448 2828 3018 2008"
+ $"0100 0380 0380 0380 07C0 07C0 07C0 3FF8"
+ $"FFFE 3FF8 0FE0 1EF0 3C78 3838 3018 2008"
+ $"0007 0007"
+};
+
+data 'CURS' (3064, "target") {
+ $"0000 0380 0FE0 1C70 3018 600C C106 C286"
+ $"C106 600C 3018 1C70 0FE0 0380 0000 0000"
+ $"0000 0380 0FE0 1FF0 3C78 701C E38E E38E"
+ $"E38E 701C 3C78 1FF0 0FE0 0380 0000 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3065, "tcross") {
+ $"0100 0100 0100 0100 0100 0100 0100 FFFE"
+ $"0100 0100 0100 0100 0100 0100 0100 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0007 0007"
+};
+
+data 'CURS' (3066, "top_left_arrow") {
+ $"0000 6000 7800 3E00 3F80 1FE0 1E00 0D00"
+ $"0C80 0440 0420 0010 0008 0004 0000 0000"
+ $"E000 F800 FE00 7F80 7FE0 3FF8 3FFE 1F80"
+ $"1FC0 0EE0 0E70 0638 061C 020E 0204 0000"
+ $"0001 0001"
+};
+
+data 'CURS' (3067, "top_left_corner") {
+ $"FFF0 FFF0 C000 C000 CFC0 CC00 CA00 C900"
+ $"C880 C840 C020 C000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0FC0 0C00 0A00 0900"
+ $"0880 0840 0020 0000 0000 0000 0000 0000"
+ $"0000 0000"
+};
+
+data 'CURS' (3068, "top_right_corner") {
+ $"0FFF 0FFF 0003 0003 03F3 0033 0053 0093"
+ $"0113 0213 0403 0003 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 03F0 0030 0050 0090"
+ $"0110 0210 0400 0000 0000 0000 0000 0000"
+ $"0000 000F"
+};
+
+data 'CURS' (3069, "top_side") {
+ $"0000 7FFC 7FFC 0000 0100 0380 0540 0920"
+ $"1110 0100 0100 0100 0100 0100 0000 0000"
+ $"0000 0000 0000 0000 0100 0380 0540 0920"
+ $"1110 0100 0100 0100 0100 0100 0000 0000"
+ $"0004 0007"
+};
+
+data 'CURS' (3070, "top_tee") {
+ $"0000 0000 0000 0000 7FFE 7FFE 0180 0180"
+ $"0180 0180 0180 0180 0180 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0004 0007"
+};
+
+data 'CURS' (3071, "trek") {
+ $"0100 0000 0380 07C0 0FE0 0EE0 0FE0 07C0"
+ $"0380 0100 0BA0 0D60 0920 0820 0820 0000"
+ $"0000 0380 07C0 0FE0 1FF0 1FF0 1FF0 0FE0"
+ $"07C0 0BA0 1FF0 1FF0 1FF0 1D70 1C70 0820"
+ $"0000 0007"
+};
+
+data 'CURS' (3072, "ul_angle") {
+ $"0000 0000 0000 0FF8 0FF8 0C00 0C00 0C00"
+ $"0C00 0C00 0C00 0C00 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0003 0004"
+};
+
+data 'CURS' (3073, "umbrella") {
+ $"0000 0890 0228 49A6 27C8 1930 610C 0100"
+ $"0100 0100 0100 0100 0140 0140 0080 0000"
+ $"0000 0FF0 1FF8 7FFE 7FFC FFFE FBBE E38E"
+ $"0380 0380 0380 03C0 03E0 03E0 01C0 0080"
+ $"0004 0007"
+};
+
+data 'CURS' (3074, "ur_angle") {
+ $"0000 0000 0000 0000 1FF0 1FF0 0030 0030"
+ $"0030 0030 0030 0030 0030 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0004 000B"
+};
+
+data 'CURS' (3075, "watch") {
+ $"07E0 07E0 07E0 07E0 0810 1088 1088 108C"
+ $"138C 1008 1008 0810 07E0 07E0 07E0 07E0"
+ $"07E0 07E0 07E0 07E0 0FF0 1FF8 1FF8 1FFC"
+ $"1FFC 1FF8 1FF8 0FF0 07E0 07E0 07E0 07E0"
+ $"0008 000D"
+};
+
+data 'CURS' (3076, "xterm") {
+ $"0C60 0280 0100 0100 0100 0100 0100 0100"
+ $"0100 0100 0100 0100 0100 0100 0280 0C60"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"000B 0007"
+};
+
+/*
+ * The following are color versions of some of the
+ * cursors defined above. The color cursors will be
+ * used if the exist in preference to the black & white
+ * cursors.
+ */
+
+data 'crsr' (3004, "boat", purgeable) {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0100 03C0"
+ $"8460 FFFF 0018 0020 0040 FFC0 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0100 03C0"
+ $"87E0 FFFF FFF8 FFE0 FFC0 FFC0 0000 0000"
+ $"0000 0000 0007 000F 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 000F 0000 0000 0000 00FF FF00"
+ $"0000 F000 0F32 25F0 0000 6FFF FFFF FFFF"
+ $"FFFF 2222 2222 221F F000 2222 2222 21F0"
+ $"0000 3333 3333 4F00 0000 FFFF FFFF FF00"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0007 0000 FFFF FFFF"
+ $"FFFF 0001 BBBB BBBB BBBB 0002 EEEE EEEE"
+ $"EEEE 0003 DDDD DDDD DDDD 0004 CCCC CCCC"
+ $"CCCC 0005 4444 4444 4444 0006 1111 1111"
+ $"1111 000F 0000 0000 0000"
+};
+
+data 'crsr' (3013, "clock") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 1FF8 33CC 6466 4992 4F12 4422"
+ $"63C6 3FFC 2994 2994 2994 2BD4 6996 781E"
+ $"7FFE 7FFE 1FF8 3FFC 7FFE 7FFE 7FFE 7FFE"
+ $"7FFE 3FFC 3FFC 3FFC 3FFC 3FFC 7FFE 7FFE"
+ $"7FFE 7FFE 0004 0008 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 000F FFFF FFFF F000 00F6 05FF FF50"
+ $"6F00 0F60 5F00 56F5 06F0 0F00 F021 F30F"
+ $"00F0 0F00 F6F1 000F 00F0 0F00 5F00 00F5"
+ $"00F0 0F60 05FF FF50 06F0 00FF FFFF FFFF"
+ $"FF00 00F0 F001 100F 0F00 00F0 F001 100F"
+ $"0F00 00F0 F021 120F 0F00 00F0 F01F F10F"
+ $"0F00 0FF0 F021 120F 0FF0 0FF4 F500 005F"
+ $"4FF0 0FFF FFFF FFFF FFF0 0FFF FFFF FFFF"
+ $"FFF0 0000 0000 0000 0007 0000 FFFF FFFF"
+ $"FFFF 0001 4444 4444 4444 0002 AAAA AAAA"
+ $"AAAA 0003 EEEE EEEE EEEE 0004 5555 5555"
+ $"5555 0005 DDDD DDDD DDDD 0006 7777 7777"
+ $"7777 000F 0000 0000 0000"
+};
+
+data 'crsr' (3014, "coffee_mug") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 03F8 0C06 1001 1C07 33F9 7001"
+ $"D001 9001 960D DA55 7A55 36ED 10A1 1001"
+ $"0802 07FC 03F8 0FFE 1FFF 1FFF 3FFF 7FFF"
+ $"FFFF FFFF FFFF FFFF 7FFF 3FFF 1FFF 1FFF"
+ $"0FFE 07FC 0004 0003 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 00FF FFFF F000 0000 FF42 2222"
+ $"4FF0 000F 4221 1111 224F 000F FF11 1111"
+ $"1FFF 00FF 24FF FFFF F42F 0F5F 2222 2222"
+ $"222F F52F 2222 2222 222F F40F 2222 2222"
+ $"222F F40F 4FF2 2224 FF2F F52F F2F2 2F2F"
+ $"2F2F 0F5F F2F2 535F 2F2F 00FF 4FF2 F3F4"
+ $"FF2F 000F 2222 F2F2 222F 000F 4222 2222"
+ $"224F 0000 F422 2222 24F0 0000 0FFF FFFF"
+ $"FF00 0000 0000 0000 0006 0000 FFFF FFFF"
+ $"FFFF 0001 CCCC 9999 6666 0002 CCCC CCCC"
+ $"FFFF 0003 3333 3333 6666 0004 9999 9999"
+ $"FFFF 0005 6666 6666 CCCC 000F 0000 0000"
+ $"0000"
+};
+
+data 'crsr' (3027, "gobbler") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0000 0078 0070 4036 4FB0 7FF0"
+ $"7E30 7C30 3038 00F0 0FE0 0400 0400 0400"
+ $"0F00 0000 00FC 00FC E0FF FFFF FFFF FFF8"
+ $"FFF8 FFF8 FFFC 7FFC 3FF8 1FF0 0E00 1F80"
+ $"1F80 1F80 0003 000E 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 0222"
+ $"2000 0000 0000 0111 0000 0300 0000 0011"
+ $"0220 0100 1616 1011 0000 0361 6111 1111"
+ $"0000 0111 1114 4415 0000 0311 1144 4451"
+ $"0000 0011 4444 4415 1000 0004 4444 5151"
+ $"0000 0000 1515 1510 0000 0000 0200 0000"
+ $"0000 0000 0300 0000 0000 0000 0200 0000"
+ $"0000 0000 2323 0000 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0006 0000 FFFF FFFF"
+ $"FFFF 0001 CCCC 9999 6666 0002 DDDD 0000"
+ $"0000 0003 FFFF 6666 3333 0004 CCCC CCCC"
+ $"CCCC 0005 8888 8888 8888 0006 FFFF CCCC"
+ $"9999"
+};
+
+data 'crsr' (3028, "gumby") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 3F00 10C0 C820 EAA0 C820 CBA0"
+ $"F838 383E 0826 0826 092E 0926 0920 1110"
+ $"2108 3EF8 3F00 1FC0 CFE0 EFE0 CFE0 CFE0"
+ $"FFF8 3FFE 0FE6 0FE6 0FEE 0FE6 0FE0 1FF0"
+ $"3FF8 3EF8 0000 0002 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 00FF FFFF 0000 0000 000F 1212 FF00"
+ $"0000 FF00 F131 31F0 0000 FFF0 F3F3 F3F0"
+ $"0000 FF00 F131 31F0 0000 FF00 F2FF F2F0"
+ $"0000 4FFF F121 21FF F000 00FF F212 12FF"
+ $"FF40 0000 F121 21F0 0FF0 0000 F212 12F0"
+ $"0FF0 0000 F12F 21F0 FFF0 0000 F21F 12F0"
+ $"0FF0 0000 F12F 21F0 0000 000F 121F 121F"
+ $"0000 00F1 212F 2121 F000 00FF FFF0 FFFF"
+ $"F000 0000 0000 0000 0005 0000 FFFF FFFF"
+ $"FFFF 0001 0000 BBBB 0000 0002 CCCC CCCC"
+ $"CCCC 0003 AAAA AAAA AAAA 0004 4444 4444"
+ $"4444 000F 0000 0000 0000"
+};
+
+data 'crsr' (3031, "heart") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0000 3EF8 638C C106 8002 8002"
+ $"8002 8002 C006 600C 3018 1830 0C60 06C0"
+ $"0380 0000 0000 3EF8 7FFC FFFE FFFE FFFE"
+ $"FFFE FFFE FFFE 7FFC 3FF8 1FF0 0FE0 07C0"
+ $"0380 0000 0003 0007 0000 0000 0000 0000"
+ $"0000 0000 8004 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0002 0001 0002 0000 0000 0000 00D2 0000"
+ $"0000 0000 0000 0FFC FFC0 3AAB AA70 E99B"
+ $"999C E665 A65C E999 999C E666 665C E999"
+ $"999C D666 665C 3599 9970 0D66 65C0 0359"
+ $"9700 00D6 5C00 0035 7000 000F C000 0000"
+ $"0000 0000 0000 0000 0003 0000 FFFF FFFF"
+ $"FFFF 0001 DDDD 0000 0000 0002 FFFF 6666"
+ $"CCCC 0003 0000 0000 0000"
+};
+
+data 'crsr' (3042, "mouse", purgeable) {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 BE00 0100 0180 0FF0 1008 17E8"
+ $"1428 1428 17E8 1008 1008 1008 1008 1008"
+ $"1008 0FF0 FE00 0100 0180 0FF0 1FF8 1FF8"
+ $"1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 1FF8"
+ $"1FF8 0FF0 0001 0007 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 1379 4AF0 0000 0000 0000 000F 0000"
+ $"0000 0000 000F F000 0000 0000 FFFF FFFF"
+ $"0000 000F 2111 1112 F000 000F 3655 5563"
+ $"F000 000F 3513 1351 F000 000F 3533 3351"
+ $"F000 000F 3655 5561 F000 000F 3311 1111"
+ $"F000 000F 3333 3333 F000 000F 3333 3333"
+ $"F000 000F 2222 2222 F000 000F 8888 8888"
+ $"F000 000F 7888 8887 F000 0000 FFFF FFFF"
+ $"0000 0000 0000 0000 000B 0000 FFFF FFFF"
+ $"FFFF 0001 EEEE EEEE EEEE 0002 CCCC CCCC"
+ $"CCCC 0003 DDDD DDDD DDDD 0004 4444 4444"
+ $"4444 0005 2222 2222 2222 0006 5555 5555"
+ $"5555 0007 AAAA AAAA AAAA 0008 BBBB BBBB"
+ $"BBBB 0009 7777 7777 7777 000A 1111 1111"
+ $"1111 000F 0000 0000 0000"
+};
+
+data 'crsr' (3043, "pencil", purgeable) {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0000 00F0 0088 0108 0190 0270"
+ $"0220 0440 0440 0880 0880 1100 1E00 1C00"
+ $"1800 1000 0000 00F0 00F8 01F8 01F0 03F0"
+ $"03E0 07C0 07C0 0F80 0F80 1F00 1E00 1C00"
+ $"1800 1000 000F 0003 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 0000 0000 0000 0000 0000 FFFF"
+ $"0000 0000 0000 F404 F000 0000 000F 4042"
+ $"F000 0000 000F F42F 0000 0000 00F5 3FFF"
+ $"0000 0000 00F3 52F0 0000 0000 0F35 1F00"
+ $"0000 0000 0F53 2F00 0000 0000 F532 F000"
+ $"0000 0000 F312 F000 0000 000F 352F 0000"
+ $"0000 000F FFF0 0000 0000 000F FF00 0000"
+ $"0000 000F F000 0000 0000 000F 0000 0000"
+ $"0000 0000 0000 0000 0006 0000 FFFF FFFF"
+ $"FFFF 0001 CCCC CCCC CCCC 0002 8888 8888"
+ $"8888 0003 FFFF FFFF 0000 0004 DDDD 0000"
+ $"0000 0005 FFFF 6666 3333 000F 0000 0000"
+ $"0000"
+};
+
+data 'crsr' (3059, "shuttle") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0020 0070 00F8 01DE 05DE 09DE"
+ $"11DE 11DE 11DE 11DE 31DE 71DE FDDE 1888"
+ $"0078 0030 0020 0070 00F8 01FE 07FE 0FFE"
+ $"1FFE 1FFE 1FFE 1FFE 3FFE 7FFE FFFE 18F8"
+ $"0078 0030 0000 000A 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 0000 00F0 0000 0000 0000 0F3F"
+ $"0000 0000 0000 F343 F000 0000 000F 3404"
+ $"3FF0 0000 0F4F 3404 3FF0 0000 F55F 3404"
+ $"3FF0 000F 505F 3404 3FF0 000F 005F 3404"
+ $"3FF0 000F 005F 3404 3FF0 000F 005F 3404"
+ $"3FF0 00F3 005F 3404 3FF0 0F33 505F 3404"
+ $"3FF0 FFF3 3F4F 3404 3FF0 000F F000 1222"
+ $"1000 0000 0000 0111 1000 0000 0000 0011"
+ $"0000 0000 0000 0000 0006 0000 FFFF FFFF"
+ $"FFFF 0001 FFFF 6666 3333 0002 DDDD 0000"
+ $"0000 0003 4444 4444 4444 0004 8888 8888"
+ $"8888 0005 DDDD DDDD DDDD 000F 0000 0000"
+ $"0000"
+};
+
+data 'crsr' (3062, "spraycan") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0018 0040 0D18 1E40 1A18 3F00"
+ $"2100 3900 2900 3900 2900 3900 3900 2100"
+ $"2100 3F00 0000 0000 0C00 1E00 1E00 3F00"
+ $"3F00 3F00 3F00 3F00 3F00 3F00 3F00 3F00"
+ $"3F00 3F00 0002 0007 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 0000 0005 2000 0000 0000 0460"
+ $"0000 0000 FF1F 6005 2000 000F 33F0 0460"
+ $"0000 000F 10F0 0005 2000 00FF FFFF 0000"
+ $"0000 00F8 170F 0000 0000 00F5 F70F 0000"
+ $"0000 00FA F70F 0000 0000 00F9 F70F 0000"
+ $"0000 00FA F70F 0000 0000 00F9 F70F 0000"
+ $"0000 00F5 F70F 0000 0000 00F8 170F 0000"
+ $"0000 00F8 170F 0000 0000 00FF FFFF 0000"
+ $"0000 0000 0000 0000 000B 0000 FFFF FFFF"
+ $"FFFF 0001 AAAA AAAA AAAA 0002 7777 7777"
+ $"7777 0003 5555 5555 5555 0004 2222 2222"
+ $"2222 0005 4444 4444 4444 0006 BBBB BBBB"
+ $"BBBB 0007 DDDD DDDD DDDD 0008 EEEE EEEE"
+ $"EEEE 0009 6666 6666 CCCC 000A CCCC CCCC"
+ $"FFFF 000F 0000 0000 0000"
+};
+
+data 'crsr' (3063, "star") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0100 0280 0280 0280 0440 0440"
+ $"0440 3938 C006 3838 0920 1290 2448 2828"
+ $"3018 2008 0100 0380 0380 0380 07C0 07C0"
+ $"07C0 3FF8 FFFE 3FF8 0FE0 1EF0 3C78 3838"
+ $"3018 2008 0007 0007 0000 0000 0000 0000"
+ $"0000 0000 8004 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0002 0001 0002 0000 0000 0000 00D2 0000"
+ $"0000 0003 0000 000D C000 000D C000 000D"
+ $"C000 0035 7000 0035 7000 0035 7000 0FD7"
+ $"5FC0 F555 557C 0FD5 5FC0 00D7 5C00 035C"
+ $"D700 0D70 35C0 0DC0 0DC0 0F00 03C0 0C00"
+ $"00C0 0000 0000 0000 0002 0000 FFFF FFFF"
+ $"FFFF 0001 FFFF FFFF 0000 0003 0000 0000"
+ $"0000"
+};
+
+data 'crsr' (3071, "trek") {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 0100 0000 0380 07C0 0FE0 0EE0"
+ $"0FE0 07C0 0380 0100 0BA0 0D60 0920 0820"
+ $"0820 0000 0000 0380 07C0 0FE0 1FF0 1FF0"
+ $"1FF0 0FE0 07C0 0BA0 1FF0 1FF0 1FF0 1D70"
+ $"1C70 0820 0000 0007 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 0005 0000 0000 0000 0005 0000"
+ $"0000 0000 00FF F000 0000 0000 0F31 3F00"
+ $"0000 0000 F322 23F0 0000 0000 F110 11F0"
+ $"0000 0000 F311 13F0 0000 0000 0F31 3F00"
+ $"0000 0000 00FF F000 0000 0000 000F 0000"
+ $"0000 0000 F0FF F0F0 0000 0000 FF0F 0FF0"
+ $"0000 0000 400F 0040 0000 0000 4000 0040"
+ $"0000 0000 4000 0040 0000 0000 0000 0000"
+ $"0000 0000 0000 0000 0006 0000 FFFF FFFF"
+ $"FFFF 0001 EEEE EEEE EEEE 0002 9999 9999"
+ $"FFFF 0003 DDDD DDDD DDDD 0004 3333 3333"
+ $"6666 0005 DDDD 0000 0000 000F 0000 0000"
+ $"0000"
+};
+
+data 'crsr' (3075, "watch", purgeable) {
+ $"8001 0000 0060 0000 0092 0000 0000 0000"
+ $"0000 0000 07E0 07E0 07E0 07E0 0810 1088"
+ $"1088 108C 138C 1008 1008 0810 07E0 07E0"
+ $"07E0 07E0 07E0 07E0 07E0 07E0 0FF0 1FF8"
+ $"1FF8 1FF8 1FF8 1FF8 1FF8 0FF0 07E0 07E0"
+ $"07E0 07E0 0008 000D 0000 0000 0000 0000"
+ $"0000 0000 8008 0000 0000 0010 0010 0000"
+ $"0000 0000 0000 0048 0000 0048 0000 0000"
+ $"0004 0001 0004 0000 0000 0000 0112 0000"
+ $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0"
+ $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0"
+ $"0000 0000 F020 202F 0000 000F 0222 F221"
+ $"F000 000F 2222 F123 F000 000F 0222 F121"
+ $"FF00 000F 22FF F123 FF00 000F 0222 2221"
+ $"F000 000F 2222 2213 F000 0000 F131 313F"
+ $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0"
+ $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0"
+ $"0000 0000 0000 0000 0004 0000 FFFF FFFF"
+ $"FFFF 0001 CCCC CCCC CCCC 0002 EEEE EEEE"
+ $"EEEE 0003 BBBB BBBB BBBB 000F 0000 0000"
+ $"0000"
+};
+
diff --git a/mac/tkMacXStubs.c b/mac/tkMacXStubs.c
new file mode 100644
index 0000000..f1042c2
--- /dev/null
+++ b/mac/tkMacXStubs.c
@@ -0,0 +1,709 @@
+/*
+ * tkMacXStubs.c --
+ *
+ * This file contains most of the X calls called by Tk. Many of
+ * these calls are just stubs and either don't make sense on the
+ * Macintosh or thier implamentation just doesn't do anything. Other
+ * calls will eventually be moved into other files.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkMacXStubs.c 1.87 97/11/20 18:35:29
+ */
+
+#include "tkInt.h"
+#include <X.h>
+#include <Xlib.h>
+#include <stdio.h>
+#include <tcl.h>
+
+#include <Xatom.h>
+
+#include <Windows.h>
+#include <Fonts.h>
+#include <QDOffscreen.h>
+#include <ToolUtils.h>
+#include <Sound.h>
+#include "tkMacInt.h"
+
+/*
+ * Because this file is still under major development Debugger statements are
+ * used through out this file. The define TCL_DEBUG will decide whether
+ * the debugger statements actually call the debugger or not.
+ */
+
+#ifndef TCL_DEBUG
+# define Debugger()
+#endif
+
+#define ROOT_ID 10
+
+/*
+ * Declarations of static variables used in this file.
+ */
+
+static TkDisplay *gMacDisplay = NULL; /* Macintosh display. */
+static char *macScreenName = "Macintosh:0";
+ /* Default name of macintosh display. */
+
+/*
+ * Forward declarations of procedures used in this file.
+ */
+
+static XID MacXIdAlloc _ANSI_ARGS_((Display *display));
+static int DefaultErrorHandler _ANSI_ARGS_((Display* display,
+ XErrorEvent* err_evt));
+
+/*
+ * Other declrations
+ */
+
+int TkMacXDestroyImage _ANSI_ARGS_((XImage *image));
+unsigned long TkMacXGetPixel _ANSI_ARGS_((XImage *image, int x, int y));
+int TkMacXPutPixel _ANSI_ARGS_((XImage *image, int x, int y,
+ unsigned long pixel));
+XImage *TkMacXSubImage _ANSI_ARGS_((XImage *image, int x, int y,
+ unsigned int width, unsigned int height));
+int TkMacXAddPixel _ANSI_ARGS_((XImage *image, long value));
+int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpOpenDisplay --
+ *
+ * Create the Display structure and fill it with device
+ * specific information.
+ *
+ * Results:
+ * Returns a Display structure on success or NULL on failure.
+ *
+ * Side effects:
+ * Allocates a new Display structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkDisplay *
+TkpOpenDisplay(
+ char *display_name)
+{
+ Display *display;
+ Screen *screen;
+ GDHandle graphicsDevice;
+
+ if (gMacDisplay != NULL) {
+ if (strcmp(gMacDisplay->display->display_name, display_name) == 0) {
+ return gMacDisplay;
+ } else {
+ return NULL;
+ }
+ }
+
+ graphicsDevice = GetMainDevice();
+ display = (Display *) ckalloc(sizeof(Display));
+ display->resource_alloc = MacXIdAlloc;
+ screen = (Screen *) ckalloc(sizeof(Screen) * 2);
+ display->default_screen = 0;
+ display->request = 0;
+ display->nscreens = 1;
+ display->screens = screen;
+ display->display_name = macScreenName;
+ display->qlen = 0;
+
+ screen->root = ROOT_ID;
+ screen->display = display;
+ screen->root_depth = (*(*graphicsDevice)->gdPMap)->cmpSize *
+ (*(*graphicsDevice)->gdPMap)->cmpCount;
+ screen->height = (*graphicsDevice)->gdRect.bottom -
+ (*graphicsDevice)->gdRect.top;
+ screen->width = (*graphicsDevice)->gdRect.right -
+ (*graphicsDevice)->gdRect.left;
+
+ screen->mwidth = (screen->width * 254 + 360) / 720;
+ screen->mheight = (screen->height * 254 + 360) / 720;
+ screen->black_pixel = 0x00000000;
+ screen->white_pixel = 0x00FFFFFF;
+ screen->root_visual = (Visual *) ckalloc(sizeof(Visual));
+ screen->root_visual->visualid = 0;
+ screen->root_visual->class = TrueColor;
+ screen->root_visual->red_mask = 0x00FF0000;
+ screen->root_visual->green_mask = 0x0000FF00;
+ screen->root_visual->blue_mask = 0x000000FF;
+ screen->root_visual->bits_per_rgb = 24;
+ screen->root_visual->map_entries = 2 ^ 8;
+
+ gMacDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay));
+ gMacDisplay->display = display;
+ return gMacDisplay;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpCloseDisplay --
+ *
+ * Deallocates a display structure created by TkpOpenDisplay.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpCloseDisplay(
+ TkDisplay *displayPtr)
+{
+ Display *display = displayPtr->display;
+ if (gMacDisplay != displayPtr) {
+ panic("TkpCloseDisplay: tried to call TkpCloseDisplay on bad display");
+ }
+
+ /*
+ * Make sure that the local scrap is transfered to the global
+ * scrap if needed.
+ */
+
+ TkSuspendClipboard();
+
+ gMacDisplay = NULL;
+ if (display->screens != (Screen *) NULL) {
+ if (display->screens->root_visual != (Visual *) NULL) {
+ ckfree((char *) display->screens->root_visual);
+ }
+ ckfree((char *) display->screens);
+ }
+ ckfree((char *) display);
+ ckfree((char *) displayPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacXIdAlloc --
+ *
+ * This procedure is invoked by Xlib as the resource allocator
+ * for a display.
+ *
+ * Results:
+ * The return value is an X resource identifier that isn't currently
+ * in use.
+ *
+ * Side effects:
+ * The identifier is removed from the stack of free identifiers,
+ * if it was previously on the stack.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static XID
+MacXIdAlloc(
+ Display *display) /* Display for which to allocate. */
+{
+ static long int cur_id = 100;
+ /*
+ * Some special XIds are reserved
+ * - this is why we start at 100
+ */
+
+ return ++cur_id;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpWindowWasRecentlyDeleted --
+ *
+ * Tries to determine whether the given window was recently deleted.
+ * Called from the generic code error handler to attempt to deal with
+ * async BadWindow errors under some circumstances.
+ *
+ * Results:
+ * Always 0, we do not keep this information on the Mac, so we do not
+ * know whether the window was destroyed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpWindowWasRecentlyDeleted(
+ Window win,
+ TkDisplay *dispPtr)
+{
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DefaultErrorHandler --
+ *
+ * This procedure is the default X error handler. Tk uses it's
+ * own error handler so this call should never be called.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This function will call panic and exit.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DefaultErrorHandler(
+ Display* display,
+ XErrorEvent* err_evt)
+{
+ /*
+ * This call should never be called. Tk replaces
+ * it with its own error handler.
+ */
+ panic("Warning hit bogus error handler!");
+ return 0;
+}
+
+
+char *
+XGetAtomName(
+ Display * display,
+ Atom atom)
+{
+ display->request++;
+ return NULL;
+}
+
+int
+_XInitImageFuncPtrs(XImage *image)
+{
+ return 0;
+}
+
+XErrorHandler
+XSetErrorHandler(
+ XErrorHandler handler)
+{
+ return DefaultErrorHandler;
+}
+
+Window
+XRootWindow(Display *display, int screen_number)
+{
+ display->request++;
+ return ROOT_ID;
+}
+
+XImage *
+XGetImage(display, d, x, y, width, height, plane_mask, format)
+ Display *display;
+ Drawable d;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned long plane_mask;
+ int format;
+{
+ Debugger();
+ return NULL;
+}
+
+int
+XGetGeometry(display, d, root_return, x_return, y_return, width_return,
+ height_return, border_width_return, depth_return)
+ Display* display;
+ Drawable d;
+ Window* root_return;
+ int* x_return;
+ int* y_return;
+ unsigned int* width_return;
+ unsigned int* height_return;
+ unsigned int* border_width_return;
+ unsigned int* depth_return;
+{
+ /* Used in tkCanvPs.c & wm code */
+ Debugger();
+ return 0;
+}
+
+void
+XChangeProperty(
+ Display* display,
+ Window w,
+ Atom property,
+ Atom type,
+ int format,
+ int mode,
+ _Xconst unsigned char* data,
+ int nelements)
+{
+ Debugger();
+}
+
+void
+XSelectInput(
+ Display* display,
+ Window w,
+ long event_mask)
+{
+ Debugger();
+}
+
+void
+XBell(
+ Display* display,
+ int percent)
+{
+ SysBeep(percent);
+}
+
+void
+XSetWMNormalHints(
+ Display* display,
+ Window w,
+ XSizeHints* hints)
+{
+ /*
+ * Do nothing. Shouldn't even be called.
+ */
+}
+
+XSizeHints *
+XAllocSizeHints()
+{
+ /*
+ * Always return NULL. Tk code checks to see if NULL
+ * is returned & does nothing if it is.
+ */
+
+ return NULL;
+}
+
+XImage *
+XCreateImage(
+ Display* display,
+ Visual* visual,
+ unsigned int depth,
+ int format,
+ int offset,
+ char* data,
+ unsigned int width,
+ unsigned int height,
+ int bitmap_pad,
+ int bytes_per_line)
+{
+ XImage *ximage;
+
+ display->request++;
+ ximage = (XImage *) ckalloc(sizeof(XImage));
+
+ ximage->height = height;
+ ximage->width = width;
+ ximage->depth = depth;
+ ximage->xoffset = offset;
+ ximage->format = format;
+ ximage->data = data;
+ ximage->bitmap_pad = bitmap_pad;
+ if (bytes_per_line == 0) {
+ ximage->bytes_per_line = width * 4; /* assuming 32 bits per pixel */
+ } else {
+ ximage->bytes_per_line = bytes_per_line;
+ }
+
+ if (format == ZPixmap) {
+ ximage->bits_per_pixel = 32;
+ ximage->bitmap_unit = 32;
+ } else {
+ ximage->bits_per_pixel = 1;
+ ximage->bitmap_unit = 8;
+ }
+ ximage->byte_order = LSBFirst;
+ ximage->bitmap_bit_order = LSBFirst;
+ ximage->red_mask = 0x00FF0000;
+ ximage->green_mask = 0x0000FF00;
+ ximage->blue_mask = 0x000000FF;
+
+ ximage->f.destroy_image = TkMacXDestroyImage;
+ ximage->f.get_pixel = TkMacXGetPixel;
+ ximage->f.put_pixel = TkMacXPutPixel;
+ ximage->f.sub_image = TkMacXSubImage;
+ ximage->f.add_pixel = TkMacXAddPixel;
+
+ return ximage;
+}
+
+GContext
+XGContextFromGC(
+ GC gc)
+{
+ /* TODO - currently a no-op */
+ return 0;
+}
+
+Status
+XSendEvent(
+ Display* display,
+ Window w,
+ Bool propagate,
+ long event_mask,
+ XEvent* event_send)
+{
+ Debugger();
+ return 0;
+}
+
+int
+XGetWindowProperty(
+ Display *display,
+ Window w,
+ Atom property,
+ long long_offset,
+ long long_length,
+ Bool delete,
+ Atom req_type,
+ Atom *actual_type_return,
+ int *actual_format_return,
+ unsigned long *nitems_return,
+ unsigned long *bytes_after_return,
+ unsigned char ** prop_return)
+{
+ display->request++;
+ *actual_type_return = None;
+ *actual_format_return = *bytes_after_return = 0;
+ *nitems_return = 0;
+ return 0;
+}
+
+void
+XRefreshKeyboardMapping()
+{
+ /* used by tkXEvent.c */
+ Debugger();
+}
+
+void
+XSetIconName(
+ Display* display,
+ Window w,
+ const char *icon_name)
+{
+ /*
+ * This is a no-op, no icon name for Macs.
+ */
+ display->request++;
+}
+
+void
+XForceScreenSaver(
+ Display* display,
+ int mode)
+{
+ /*
+ * This function is just a no-op. It is defined to
+ * reset the screen saver. However, there is no real
+ * way to do this on a Mac. Let me know if there is!
+ */
+ display->request++;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetServerInfo --
+ *
+ * Given a window, this procedure returns information about
+ * the window server for that window. This procedure provides
+ * the guts of the "winfo server" command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkGetServerInfo(
+ Tcl_Interp *interp, /* The server information is returned in
+ * this interpreter's result. */
+ Tk_Window tkwin) /* Token for window; this selects a
+ * particular display and server. */
+{
+ char buffer[50], buffer2[50];
+
+ sprintf(buffer, "X%dR%d ", ProtocolVersion(Tk_Display(tkwin)),
+ ProtocolRevision(Tk_Display(tkwin)));
+ sprintf(buffer2, " %d", VendorRelease(Tk_Display(tkwin)));
+ Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)),
+ buffer2, (char *) NULL);
+}
+/*
+ * Image stuff
+ */
+
+int
+TkMacXDestroyImage(
+ XImage *image)
+{
+ Debugger();
+ return 0;
+}
+
+unsigned long
+TkMacXGetPixel(
+ XImage *image,
+ int x,
+ int y)
+{
+ Debugger();
+ return 0;
+}
+
+int
+TkMacXPutPixel(
+ XImage *image,
+ int x,
+ int y,
+ unsigned long pixel)
+{
+ /* Debugger(); */
+ return 0;
+}
+
+XImage *
+TkMacXSubImage(
+ XImage *image,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ Debugger();
+ return NULL;
+}
+
+int
+TkMacXAddPixel(
+ XImage *image,
+ long value)
+{
+ Debugger();
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XChangeWindowAttributes, XSetWindowBackground,
+ * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap,
+ * XSetWindowBorderWidth, XSetWindowColormap
+ *
+ * These functions are all no-ops. They all have equivilent
+ * Tk calls that should always be used instead.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XChangeWindowAttributes(
+ Display* display,
+ Window w,
+ unsigned long value_mask,
+ XSetWindowAttributes* attributes)
+{
+}
+
+void
+XSetWindowBackground(
+ Display *display,
+ Window window,
+ unsigned long value)
+{
+}
+
+void
+XSetWindowBackgroundPixmap(
+ Display* display,
+ Window w,
+ Pixmap background_pixmap)
+{
+}
+
+void
+XSetWindowBorder(
+ Display* display,
+ Window w,
+ unsigned long border_pixel)
+{
+}
+
+void
+XSetWindowBorderPixmap(
+ Display* display,
+ Window w,
+ Pixmap border_pixmap)
+{
+}
+
+void
+XSetWindowBorderWidth(
+ Display* display,
+ Window w,
+ unsigned int width)
+{
+}
+
+void
+XSetWindowColormap(
+ Display* display,
+ Window w,
+ Colormap colormap)
+{
+ Debugger();
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetDefaultScreenName --
+ *
+ * Returns the name of the screen that Tk should use during
+ * initialization.
+ *
+ * Results:
+ * Returns a statically allocated string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TkGetDefaultScreenName(
+ Tcl_Interp *interp, /* Not used. */
+ char *screenName) /* If NULL, use default string. */
+{
+ if ((screenName == NULL) || (screenName[0] == '\0')) {
+ screenName = macScreenName;
+ }
+ return screenName;
+}