Import Upstream version 2.7.18
200
Mac/BuildScript/README.rst
Normal file
@@ -0,0 +1,200 @@
|
||||
Building a Python Mac OS X distribution
|
||||
=======================================
|
||||
|
||||
WARNING
|
||||
-------
|
||||
|
||||
The instructions in this README are incomplete and not up-to-date.
|
||||
In particular, they do not explain how to create a modern flat installer
|
||||
package from the now obsolete bundle-format installer package produced
|
||||
by ``build-installer.py``.
|
||||
|
||||
The ``build-installer.py`` script creates Python distributions, including
|
||||
certain third-party libraries as necessary. It builds a complete
|
||||
framework-based Python out-of-tree, installs it in a funny place with
|
||||
$DESTROOT, massages that installation to remove .pyc files and such, creates
|
||||
an Installer package from the installation plus other files in ``resources``
|
||||
and ``scripts`` and placed that on a ``.dmg`` disk image.
|
||||
|
||||
This installers built by this script are legacy bundle installers that have
|
||||
been supported from the early days of OS X. In particular, they are supported
|
||||
on OS X 10.3.9, the earliest supported release for builds from this script.
|
||||
|
||||
Beginning with Python 2.7.9, PSF practice is to build two installer variants
|
||||
using the newer flat package format, supported on 10.5+, and signed with the
|
||||
builder's Apple developer key, allowing downloaded packages to satisfy Apple's
|
||||
default Gatekeeper policy (e.g. starting with 10.8, Apple store downloads and
|
||||
Apple developer ID signed apps and installer packages). The process for
|
||||
transforming the output build artifacts into signed flat packages is not
|
||||
yet integrated into ``build-installer.py``.
|
||||
|
||||
1. 32-bit-only, i386 and PPC universal, capable on running on all machines
|
||||
supported by Mac OS X 10.5 through (at least) 10.10::
|
||||
|
||||
/usr/bin/python build-installer.py \
|
||||
--sdk-path=/Developer/SDKs/MacOSX10.5.sdk \
|
||||
--universal-archs=32-bit \
|
||||
--dep-target=10.5
|
||||
|
||||
- builds the following third-party libraries
|
||||
|
||||
* libcrypto and libssl from OpenSSL 1.0.1
|
||||
* NCurses 5.9
|
||||
* SQLite 3.28.0
|
||||
* Oracle Sleepycat DB 4.8 (Python 2.x only)
|
||||
|
||||
- uses system-supplied versions of third-party libraries
|
||||
|
||||
* readline module links with Apple BSD editline (libedit)
|
||||
|
||||
- requires ActiveState ``Tcl/Tk 8.4`` (currently 8.4.20) to be installed for building
|
||||
|
||||
- recommended build environment:
|
||||
|
||||
* Mac OS X 10.5.8 Intel or PPC
|
||||
* Xcode 3.1.4
|
||||
* ``MacOSX10.5`` SDK
|
||||
* ``MACOSX_DEPLOYMENT_TARGET=10.5``
|
||||
* Apple ``gcc-4.2``
|
||||
* bootstrap non-framework Python 2.7 for documentation build with
|
||||
Sphinx (as of 2.7.9)
|
||||
|
||||
- alternate build environments:
|
||||
|
||||
* Mac OS X 10.6.8 with Xcode 3.2.6
|
||||
- need to change ``/System/Library/Frameworks/{Tcl,Tk}.framework/Version/Current`` to ``8.4``
|
||||
* Note Xcode 4.* does not support building for PPC so cannot be used for this build
|
||||
|
||||
2. 64-bit / 32-bit, x86_64 and i386 universal, for OS X 10.6 (and later)::
|
||||
|
||||
/usr/bin/python build-installer.py \
|
||||
--sdk-path=/Developer/SDKs/MacOSX10.6.sdk \
|
||||
--universal-archs=intel \
|
||||
--dep-target=10.6
|
||||
|
||||
- builds the following third-party libraries
|
||||
|
||||
* NCurses 5.9 (http://bugs.python.org/issue15037)
|
||||
* SQLite 3.7.13
|
||||
* Oracle Sleepycat DB 4.8 (Python 2.x only)
|
||||
|
||||
- uses system-supplied versions of third-party libraries
|
||||
|
||||
* libcrypto and libssl from Apple OpenSSL 0.9.8
|
||||
* readline module links with Apple BSD editline (libedit)
|
||||
|
||||
- requires ActiveState Tcl/Tk 8.5.15 (or later) to be installed for building
|
||||
|
||||
- recommended build environment:
|
||||
|
||||
* Mac OS X 10.6.8 (or later)
|
||||
* Xcode 3.2.6
|
||||
* ``MacOSX10.6`` SDK
|
||||
* ``MACOSX_DEPLOYMENT_TARGET=10.6``
|
||||
* Apple ``gcc-4.2``
|
||||
* bootstrap non-framework Python 2.7 for documentation build with
|
||||
Sphinx (as of 2.7.9)
|
||||
|
||||
- alternate build environments:
|
||||
|
||||
* none. Xcode 4.x currently supplies two C compilers.
|
||||
``llvm-gcc-4.2.1`` has been found to miscompile Python 3.3.x and
|
||||
produce a non-functional Python executable. As it appears to be
|
||||
considered a migration aid by Apple and is not likely to be fixed,
|
||||
its use should be avoided. The other compiler, ``clang``, has been
|
||||
undergoing rapid development. While it appears to have become
|
||||
production-ready in the most recent Xcode 5 releases, the versions
|
||||
available on the deprecated Xcode 4.x for 10.6 were early releases
|
||||
and did not receive the level of exposure in production environments
|
||||
that the Xcode 3 gcc-4.2 compiler has had.
|
||||
|
||||
|
||||
General Prerequisites
|
||||
---------------------
|
||||
|
||||
* No Fink (in ``/sw``) or MacPorts (in ``/opt/local``) or other local
|
||||
libraries or utilities (in ``/usr/local``) as they could
|
||||
interfere with the build.
|
||||
|
||||
* The documentation for the release is built using Sphinx
|
||||
because it is included in the installer. For 2.7.x up to and including
|
||||
2.7.8, the ``Doc/Makefile`` used ``svn`` to download repos of
|
||||
``Sphinx`` and its dependencies. Beginning with 2.7.9, the ``Doc/Makefile``
|
||||
assumes there is an externally-provided ``sphinx-build`` and requires at
|
||||
least Python 2.6 to run. Because of this, it is no longer possible to
|
||||
build a 2.7.9 or later installer on OS X 10.5 using the Apple-supplied
|
||||
Python 2.5.
|
||||
|
||||
* It is safest to start each variant build with an empty source directory
|
||||
populated with a fresh copy of the untarred source.
|
||||
|
||||
* It is recommended that you remove any existing installed version of the
|
||||
Python being built::
|
||||
|
||||
sudo rm -rf /Library/Frameworks/Python.framework/Versions/n.n
|
||||
|
||||
|
||||
The Recipe
|
||||
----------
|
||||
|
||||
Here are the steps you need to follow to build a Python installer:
|
||||
|
||||
* Run ``build-installer.py``. Optionally you can pass a number of arguments
|
||||
to specify locations of various files. Please see the top of
|
||||
``build-installer.py`` for its usage.
|
||||
|
||||
Running this script takes some time, it will not only build Python itself
|
||||
but also some 3rd-party libraries that are needed for extensions.
|
||||
|
||||
* When done the script will tell you where the DMG image is (by default
|
||||
somewhere in ``/tmp/_py``).
|
||||
|
||||
Building other universal installers
|
||||
...................................
|
||||
|
||||
It is also possible to build a 4-way universal installer that runs on
|
||||
OS X 10.5 Leopard or later::
|
||||
|
||||
/usr/bin/python /build-installer.py \
|
||||
--dep-target=10.5
|
||||
--universal-archs=all
|
||||
--sdk-path=/Developer/SDKs/MacOSX10.5.sdk
|
||||
|
||||
This requires that the deployment target is 10.5, and hence
|
||||
also that you are building on at least OS X 10.5. 4-way includes
|
||||
``i386``, ``x86_64``, ``ppc``, and ``ppc64`` (G5). ``ppc64`` executable
|
||||
variants can only be run on G5 machines running 10.5. Note that,
|
||||
while OS X 10.6 is only supported on Intel-based machines, it is possible
|
||||
to run ``ppc`` (32-bit) executables unmodified thanks to the Rosetta ppc
|
||||
emulation in OS X 10.5 and 10.6. The 4-way installer variant must be
|
||||
built with Xcode 3. It is not regularly built or tested.
|
||||
|
||||
Other ``--universal-archs`` options are ``64-bit`` (``x86_64``, ``ppc64``),
|
||||
and ``3-way`` (``ppc``, ``i386``, ``x86_64``). None of these options
|
||||
are regularly exercised; use at your own risk.
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Ideally, the resulting binaries should be installed and the test suite run
|
||||
on all supported OS X releases and architectures. As a practical matter,
|
||||
that is generally not possible. At a minimum, variant 1 should be run on
|
||||
a PPC G4 system with OS X 10.5 and at least one Intel system running OS X
|
||||
10.8, 10.7, 10.6, or 10.5. Variant 2 should be run on 10.8, 10.7, and 10.6
|
||||
systems in both 32-bit and 64-bit modes.::
|
||||
|
||||
/usr/local/bin/pythonn.n -m test -w -u all,-largefile
|
||||
/usr/local/bin/pythonn.n-32 -m test -w -u all
|
||||
|
||||
Certain tests will be skipped and some cause the interpreter to fail
|
||||
which will likely generate ``Python quit unexpectedly`` alert messages
|
||||
to be generated at several points during a test run. These are normal
|
||||
during testing and can be ignored.
|
||||
|
||||
It is also recommend to launch IDLE and verify that it is at least
|
||||
functional. Double-click on the IDLE app icon in ``/Applications/Pythonn.n``.
|
||||
It should also be tested from the command line::
|
||||
|
||||
/usr/local/bin/idlen.n
|
||||
|
||||
1666
Mac/BuildScript/build-installer.py
Executable file
20
Mac/BuildScript/resources/Conclusion.rtf
Normal file
@@ -0,0 +1,20 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf200
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 LucidaGrande-Bold;\f2\fnil\fcharset0 LucidaGrande;
|
||||
\f3\fnil\fcharset0 Monaco;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
\margl1440\margr1440\vieww10540\viewh8400\viewkind0
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f0\fs28 \cf0 Congratulations!
|
||||
\fs24
|
||||
\f1\b\fs28 Python $FULL_VERSION for macOS $MACOSX_DEPLOYMENT_TARGET
|
||||
\f2\b0 was successfully installed.
|
||||
\fs24 \
|
||||
\
|
||||
One more thing: to verify the identity of secure network connections, this Python needs a set of SSL root certificates. You can download and install a current curated set from {\field{\*\fldinst{HYPERLINK "https://pypi.org/project/certifi/"}}{\fldrslt the Certifi project}} by double-clicking on the
|
||||
\f3 Install Certificates
|
||||
\f2 icon in {\field{\*\fldinst{HYPERLINK "file://localhost/Applications/Python%20$VERSION/"}}{\fldrslt the Finder window}}. See {\field{\*\fldinst{HYPERLINK "file://localhost/Applications/Python%20$VERSION/ReadMe.rtf"}}{\fldrslt the
|
||||
\f3 ReadMe
|
||||
\f2 file}} for more information.\
|
||||
}
|
||||
143
Mac/BuildScript/resources/License.rtf
Normal file
@@ -0,0 +1,143 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2511
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;\f2\fmodern\fcharset0 CourierNewPS-BoldMT;
|
||||
\f3\fmodern\fcharset0 CourierNewPSMT;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
\margl1440\margr1440\vieww14620\viewh13380\viewkind0
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f0\b\fs36 \cf0 \ul \ulc0 HISTORY AND LICENSE\
|
||||
|
||||
\fs24 \
|
||||
HISTORY OF THE SOFTWARE\
|
||||
|
||||
\f1\b0 \ulnone \
|
||||
Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others.\
|
||||
\
|
||||
In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software.\
|
||||
\
|
||||
In May 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. In October of the same year, the PythonLabs team moved to Digital Creations (now Zope Corporation, see http://www.zope.org). In 2001, the Python Software Foundation (PSF, see http://www.python.org/psf/) was formed, a non-profit organization created specifically to own Python-related Intellectual Property. Zope Corporation is a sponsoring member of the PSF.\
|
||||
\
|
||||
All Python releases are Open Source (see http://www.opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases.\
|
||||
\
|
||||
|
||||
\f2\b Release Derived Year Owner GPL-\
|
||||
from compatible?\
|
||||
|
||||
\f3\b0 \
|
||||
0.9.0 thru 1.2 n/a 1991-1995 CWI yes\
|
||||
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes\
|
||||
1.6 1.5.2 2000 CNRI no\
|
||||
2.0 1.6 2000 BeOpen.com no\
|
||||
1.6.1 1.6 2001 CNRI no\
|
||||
2.1 2.0+1.6.1 2001 PSF no\
|
||||
2.0.1 2.0+1.6.1 2001 PSF yes\
|
||||
2.1.1 2.1+2.0.1 2001 PSF yes\
|
||||
2.1.2 2.1.1 2002 PSF yes\
|
||||
2.1.3 2.1.2 2002 PSF yes\
|
||||
2.2 and above 2.1.1 2001-now PSF yes\
|
||||
|
||||
\f1 \
|
||||
|
||||
\f0\b Note:
|
||||
\f1\b0 GPL-compatible doesn't mean that we're distributing Python under the GPL. All Python licenses, unlike the GPL, let you distribute a modified version without making your changes open source. The GPL-compatible licenses make it possible to combine Python with other software that is released under the GPL; the others don't.\
|
||||
\
|
||||
Thanks to the many outside volunteers who have worked under Guido's direction to make these releases possible.\
|
||||
\
|
||||
\
|
||||
|
||||
\f0\b \ul TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON\
|
||||
|
||||
\f1\b0 \ulnone \
|
||||
|
||||
\f0\b PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\
|
||||
|
||||
\f1\b0 \
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation.\
|
||||
\
|
||||
2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright \'a9 2001-2020 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee.\
|
||||
\
|
||||
3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python.\
|
||||
\
|
||||
4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.\
|
||||
\
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\
|
||||
\
|
||||
6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.\
|
||||
\
|
||||
7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party.\
|
||||
\
|
||||
8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this License Agreement.\
|
||||
\
|
||||
\
|
||||
|
||||
\f0\b BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0\
|
||||
|
||||
\f1\b0 \
|
||||
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1\
|
||||
\
|
||||
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software").\
|
||||
\
|
||||
2. Subject to the terms and conditions of this BeOpen Python License Agreement, BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use the Software alone or in any derivative version, provided, however, that the BeOpen Python License is retained in the Software, alone or in any derivative version prepared by Licensee.\
|
||||
\
|
||||
3. BeOpen is making the Software available to Licensee on an "AS IS" basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.\
|
||||
\
|
||||
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\
|
||||
\
|
||||
5. This License Agreement will automatically terminate upon a material breach of its terms and conditions.\
|
||||
\
|
||||
6. This License Agreement shall be governed by and interpreted in all respects by the law of the State of California, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between BeOpen and Licensee. This License Agreement does not grant permission to use BeOpen trademarks or trade names in a trademark sense to endorse or promote products or services of Licensee, or any third party. As an exception, the "BeOpen Python" logos available at http://www.pythonlabs.com/logos.html may be used according to the permissions granted on that web page.\
|
||||
\
|
||||
7. By copying, installing or otherwise using the software, Licensee agrees to be bound by the terms and conditions of this License Agreement.\
|
||||
\
|
||||
\
|
||||
|
||||
\f0\b CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1\
|
||||
|
||||
\f1\b0 \
|
||||
1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation.\
|
||||
\
|
||||
2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013".\
|
||||
\
|
||||
3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6.1.\
|
||||
\
|
||||
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.\
|
||||
\
|
||||
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\
|
||||
\
|
||||
6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.\
|
||||
\
|
||||
7. This License Agreement shall be governed by the federal intellectual property law of the United States, including without limitation the federal copyright law, and, to the extent such U.S. federal law does not apply, by the law of the Commonwealth of Virginia, excluding Virginia's conflict of law provisions. Notwithstanding the foregoing, with regard to derivative works based on Python 1.6.1 that incorporate non-separable material that was previously distributed under the GNU General Public License (GPL), the law of the Commonwealth of Virginia shall govern this License Agreement only as to issues arising under or with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between CNRI and Licensee. This License Agreement does not grant permission to use CNRI trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party.\
|
||||
\
|
||||
8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and conditions of this License Agreement.\
|
||||
\
|
||||
ACCEPT\
|
||||
\
|
||||
\
|
||||
|
||||
\f0\b CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2\
|
||||
|
||||
\f1\b0 \
|
||||
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved.\
|
||||
\
|
||||
Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.\
|
||||
\
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\
|
||||
\
|
||||
\
|
||||
|
||||
\f0\b \ul LICENSES AND ACKNOWLEDGEMENTS FOR INCORPORATED SOFTWARE\
|
||||
|
||||
\f1\b0 \ulnone \
|
||||
This installer incorporates portions of the following third-party software:\
|
||||
\
|
||||
|
||||
\f3 $THIRD_PARTY_LIBS\
|
||||
\
|
||||
|
||||
\f1 For licenses and acknowledgements for these and other third-party software incorporated in this Python distribution, please refer to the on-line documentation {\field{\*\fldinst{HYPERLINK "https://docs.python.org/$VERSION/license.html#licenses-and-acknowledgements-for-incorporated-software"}}{\fldrslt here}}.\
|
||||
\
|
||||
\
|
||||
\
|
||||
\
|
||||
}
|
||||
81
Mac/BuildScript/resources/ReadMe.rtf
Normal file
@@ -0,0 +1,81 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2512
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fswiss\fcharset0 Helvetica-Oblique;
|
||||
\f3\fmodern\fcharset0 CourierNewPSMT;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
\margl1440\margr1440\vieww14900\viewh15540\viewkind0
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f0\fs24 \cf0 This package will install Python $FULL_VERSION for macOS $MACOSX_DEPLOYMENT_TARGET for the following architecture(s): $ARCHITECTURES.\
|
||||
\
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
|
||||
|
||||
\f1\b \cf0 NOTE: \ul Python 2.7,x has now reached end-of-life. This release, Python 2.7.18, is the FINAL RELEASE of Python 2.7.x. It will no longer be supported or updated\ulnone .
|
||||
\f0\b0 You should
|
||||
\f1\b upgrade to Python 3
|
||||
\f0\b0 as soon as you can. {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/sunset-python-2/"}}{\fldrslt Read more here}}.\
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
\cf0 \
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f1\b \cf0 \ul \ulc0 Certificate verification and OpenSSL\
|
||||
|
||||
\f0\b0 \ulnone \
|
||||
This package includes its own private copy of OpenSSL 1.0.2. The trust certificates in system and user keychains managed by the
|
||||
\f2\i Keychain Access
|
||||
\f0\i0 application and the
|
||||
\f2\i security
|
||||
\f0\i0 command line utility are not used as defaults by the Python
|
||||
\f3 ssl
|
||||
\f0 module. A sample command script is included in
|
||||
\f3 /Applications/Python 2.7
|
||||
\f0 to install a curated bundle of default root certificates from the third-party
|
||||
\f3 certifi
|
||||
\f0 package ({\field{\*\fldinst{HYPERLINK "https://pypi.org/project/certifi/"}}{\fldrslt https://pypi.org/project/certifi/}}). Double-click on
|
||||
\f3 Install Certificates
|
||||
\f0 to run it.\
|
||||
\
|
||||
The bundled
|
||||
\f3 pip
|
||||
\f0 has its own default certificate store for verifying download connections.\
|
||||
\
|
||||
|
||||
\f1\b \ul Which installer variant should I use?
|
||||
\f0\b0 \ulnone \
|
||||
\
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
|
||||
\cf0 Use the
|
||||
\f1\b macOS 64-bit installer for OS X 10.9 and later
|
||||
\f0\b0 . As of 2.7.18, the deprecated
|
||||
\f1\b macOS 64-bit/32-bit installer for Mac OS X 10.6 and later
|
||||
\f0\b0 variant is no longer provided. \
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f1\b \cf0 \ul \ulc0 \
|
||||
Using IDLE or other Tk applications
|
||||
\f0\b0 \ulnone \
|
||||
\
|
||||
This package includes its own private version of Tcl/Tk 8.6. It does not use any system-supplied or third-party supplied versions of Tcl/Tk.\
|
||||
\
|
||||
Due to new security checks on macOS 10.15 Catalina, when launching IDLE macOS may open a window with a message
|
||||
\f1\b "Python" would like to access files in your Documents folder
|
||||
\f0\b0 . This is normal as IDLE uses your
|
||||
\f1\b Documents
|
||||
\f0\b0 folder as its default when opening and saving files; you can still choose other locations in the
|
||||
\f1\b Open
|
||||
\f0\b0 and
|
||||
\f1\b Save
|
||||
\f0\b0 file dialog windows. Click on the
|
||||
\f1\b OK
|
||||
\f0\b0 button to proceed.\
|
||||
|
||||
\f1\b \ul \
|
||||
Other changes\
|
||||
\
|
||||
|
||||
\f0\b0 \ulnone For other changes in this release, see the
|
||||
\f2\i What's new
|
||||
\f0\i0 section in the {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/"}}{\fldrslt Documentation Set}} for this release and its
|
||||
\f2\i Release Notes
|
||||
\f0\i0 link at {\field{\*\fldinst{HYPERLINK "https://www.python.org/downloads/"}}{\fldrslt https://www.python.org/downloads/}}.\
|
||||
}
|
||||
33
Mac/BuildScript/resources/Welcome.rtf
Normal file
@@ -0,0 +1,33 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2512
|
||||
\cocoascreenfonts1\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fmodern\fcharset0 CourierNewPSMT;
|
||||
}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
\paperw11905\paperh16837\margl1440\margr1440\vieww13360\viewh10920\viewkind0
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
||||
|
||||
\f0\fs24 \cf0 This package will install
|
||||
\f1\b Python $FULL_VERSION
|
||||
\f0\b0 for
|
||||
\f1\b macOS $MACOSX_DEPLOYMENT_TARGET
|
||||
\f0\b0 .\
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
|
||||
\cf0 \
|
||||
|
||||
\f1\b Python for macOS
|
||||
\f0\b0 consists of the {\field{\*\fldinst{HYPERLINK "https://www.python.org"}}{\fldrslt Python}} programming language interpreter and its batteries-included standard library to allow easy access to macOS features. It also includes the Python integrated development environment,
|
||||
\f1\b IDLE
|
||||
\f0\b0 . You can also use the included
|
||||
\f1\b pip
|
||||
\f0\b0 to download and install third-party packages from the {\field{\*\fldinst{HYPERLINK "https://pypi.org"}}{\fldrslt Python Package Index}}. \
|
||||
\
|
||||
At the end of this install, click on
|
||||
\f2 Install Certificates
|
||||
\f0 to install a set of current SSL root certificates.\
|
||||
\
|
||||
|
||||
\f1\b NOTE: \ul Python 2.7,x has now reached end-of-life. This release, Python 2.7.18, is the FINAL RELEASE of Python 2.7.x. It will no longer be supported or updated\ulnone .
|
||||
\f0\b0 You should
|
||||
\f1\b upgrade to Python 3
|
||||
\f0\b0 as soon as you can. {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/sunset-python-2/"}}{\fldrslt Read more here}}.\
|
||||
}
|
||||
BIN
Mac/BuildScript/resources/background.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
48
Mac/BuildScript/resources/install_certificates.command
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
|
||||
/Library/Frameworks/Python.framework/Versions/@PYVER@/bin/python@PYVER@ << "EOF"
|
||||
|
||||
# install_certifi.py
|
||||
#
|
||||
# sample script to install or update a set of default Root Certificates
|
||||
# for the ssl module. Uses the certificates provided by the certifi package:
|
||||
# https://pypi.org/project/certifi/
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import ssl
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
STAT_0o775 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
|
||||
| stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP
|
||||
| stat.S_IROTH | stat.S_IXOTH )
|
||||
|
||||
def main():
|
||||
openssl_dir, openssl_cafile = os.path.split(
|
||||
ssl.get_default_verify_paths().openssl_cafile)
|
||||
|
||||
print(" -- pip install --upgrade certifi")
|
||||
subprocess.check_call([sys.executable,
|
||||
"-E", "-s", "-m", "pip", "install", "--upgrade", "certifi"])
|
||||
|
||||
import certifi
|
||||
|
||||
# change working directory to the default SSL directory
|
||||
os.chdir(openssl_dir)
|
||||
relpath_to_certifi_cafile = os.path.relpath(certifi.where())
|
||||
print(" -- removing any existing file or link")
|
||||
try:
|
||||
os.remove(openssl_cafile)
|
||||
except OSError:
|
||||
pass
|
||||
print(" -- creating symlink to certifi certificate bundle")
|
||||
os.symlink(relpath_to_certifi_cafile, openssl_cafile)
|
||||
print(" -- setting permissions")
|
||||
os.chmod(openssl_cafile, STAT_0o775)
|
||||
print(" -- update complete")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
EOF
|
||||
24
Mac/BuildScript/scripts/postflight.documentation
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
PYVER="@PYVER@"
|
||||
FWK="/Library/Frameworks/Python.framework/Versions/${PYVER}"
|
||||
FWK_DOCDIR_SUBPATH="Resources/English.lproj/Documentation"
|
||||
FWK_DOCDIR="${FWK}/${FWK_DOCDIR_SUBPATH}"
|
||||
APPDIR="/Applications/Python ${PYVER}"
|
||||
SHARE_DIR="${FWK}/share"
|
||||
SHARE_DOCDIR="${SHARE_DIR}/doc/python${PYVER}"
|
||||
SHARE_DOCDIR_TO_FWK="../../.."
|
||||
|
||||
# make link in /Applications/Python m.n/ for Finder users
|
||||
if [ -d "${APPDIR}" ]; then
|
||||
ln -fhs "${FWK_DOCDIR}/index.html" "${APPDIR}/Python Documentation.html"
|
||||
open "${APPDIR}" || true # open the applications folder
|
||||
fi
|
||||
|
||||
# make share/doc link in framework for command line users
|
||||
if [ -d "${SHARE_DIR}" ]; then
|
||||
mkdir -m 775 -p "${SHARE_DOCDIR}"
|
||||
# make relative link to html doc directory
|
||||
ln -fhs "${SHARE_DOCDIR_TO_FWK}/${FWK_DOCDIR_SUBPATH}" "${SHARE_DOCDIR}/html"
|
||||
fi
|
||||
|
||||
69
Mac/BuildScript/scripts/postflight.ensurepip
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Install/upgrade pip.
|
||||
#
|
||||
|
||||
PYVER="@PYVER@"
|
||||
PYMAJOR="@PYMAJOR@"
|
||||
FWK="/Library/Frameworks/Python.framework/Versions/${PYVER}"
|
||||
RELFWKBIN="../../..${FWK}/bin"
|
||||
|
||||
umask 022
|
||||
|
||||
"${FWK}/bin/python${PYVER}" -m ensurepip --upgrade
|
||||
|
||||
"${FWK}/bin/python${PYVER}" -Wi \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x badsyntax \
|
||||
"${FWK}/lib/python${PYVER}/site-packages"
|
||||
|
||||
"${FWK}/bin/python${PYVER}" -Wi -O \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x badsyntax \
|
||||
"${FWK}/lib/python${PYVER}/site-packages"
|
||||
|
||||
chgrp -R admin "${FWK}/lib/python${PYVER}/site-packages" "${FWK}/bin"
|
||||
chmod -R g+w "${FWK}/lib/python${PYVER}/site-packages" "${FWK}/bin"
|
||||
|
||||
# We do not know if the user selected the Python command-line tools
|
||||
# package that installs symlinks to /usr/local/bin. So we assume
|
||||
# that the command-line tools package has already completed or was
|
||||
# not selected and we will only install /usr/local/bin symlinks for
|
||||
# pip et al if there are /usr/local/bin/python* symlinks to our
|
||||
# framework bin directory.
|
||||
|
||||
if [ -d /usr/local/bin ] ; then
|
||||
(
|
||||
install_links_if_our_fw() {
|
||||
if [ "$(readlink -n ./$1)" = "${RELFWKBIN}/$1" ] ; then
|
||||
shift
|
||||
for fn ;
|
||||
do
|
||||
if [ -e "${RELFWKBIN}/${fn}" ] ; then
|
||||
rm -f ./${fn}
|
||||
ln -s "${RELFWKBIN}/${fn}" "./${fn}"
|
||||
chgrp -h admin "./${fn}"
|
||||
chmod -h g+w "./${fn}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
cd /usr/local/bin
|
||||
|
||||
# Create pipx.y and easy_install-x.y links if /usr/local/bin/pythonx.y
|
||||
# is linked to this framework version
|
||||
install_links_if_our_fw "python${PYVER}" \
|
||||
"pip${PYVER}" "easy_install-${PYVER}"
|
||||
|
||||
# Create pipx link if /usr/local/bin/pythonx is linked to this version
|
||||
install_links_if_our_fw "python${PYMAJOR}" \
|
||||
"pip${PYMAJOR}"
|
||||
|
||||
# Create pip and easy_install link if /usr/local/bin/python
|
||||
# is linked to this version
|
||||
install_links_if_our_fw "python" \
|
||||
"pip" "easy_install"
|
||||
)
|
||||
fi
|
||||
exit 0
|
||||
32
Mac/BuildScript/scripts/postflight.framework
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Recompile the .py files.
|
||||
#
|
||||
|
||||
PYVER="@PYVER@"
|
||||
FWK="/Library/Frameworks/Python.framework/Versions/@PYVER@"
|
||||
|
||||
"${FWK}/bin/python@PYVER@" -Wi -tt \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \
|
||||
"${FWK}/lib/python${PYVER}"
|
||||
|
||||
"${FWK}/bin/python@PYVER@" -Wi -tt -O \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \
|
||||
"${FWK}/lib/python${PYVER}"
|
||||
|
||||
"${FWK}/bin/python@PYVER@" -Wi \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x badsyntax \
|
||||
"${FWK}/lib/python${PYVER}/site-packages"
|
||||
|
||||
"${FWK}/bin/python@PYVER@" -Wi -O \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x badsyntax \
|
||||
"${FWK}/lib/python${PYVER}/site-packages"
|
||||
|
||||
chgrp -R admin "${FWK}"
|
||||
chmod -R g+w "${FWK}"
|
||||
|
||||
exit 0
|
||||
99
Mac/BuildScript/scripts/postflight.patch-profile
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "This script will update your shell profile when the 'bin' directory"
|
||||
echo "of python is not early enough of the PATH of your shell."
|
||||
echo "These changes will be effective only in shell windows that you open"
|
||||
echo "after running this script."
|
||||
|
||||
PYVER="@PYVER@"
|
||||
PYTHON_ROOT="/Library/Frameworks/Python.framework/Versions/@PYVER@"
|
||||
|
||||
if [ `id -ur` = 0 ]; then
|
||||
# Run from the installer, do some trickery to fetch the information
|
||||
# we need.
|
||||
theShell="`finger $USER | grep Shell: | head -1 | awk '{ print $NF }'`"
|
||||
|
||||
else
|
||||
theShell="${SHELL}"
|
||||
fi
|
||||
|
||||
# Make sure the directory ${PYTHON_ROOT}/bin is on the users PATH.
|
||||
BSH="`basename "${theShell}"`"
|
||||
case "${BSH}" in
|
||||
bash|ksh|sh|*csh|zsh)
|
||||
if [ `id -ur` = 0 ]; then
|
||||
P=`su - ${USER} -c 'echo A-X-4-X@@$PATH@@X-4-X-A' | grep 'A-X-4-X@@.*@@X-4-X-A' | sed -e 's/^A-X-4-X@@//g' -e 's/@@X-4-X-A$//g'`
|
||||
else
|
||||
P="`(exec -l ${theShell} -c 'echo $PATH')`"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Sorry, I don't know how to patch $BSH shells"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# Now ensure that our bin directory is on $P and before /usr/bin at that
|
||||
for elem in `echo $P | tr ':' ' '`
|
||||
do
|
||||
if [ "${elem}" = "${PYTHON_ROOT}/bin" ]; then
|
||||
echo "All right, you're a python lover already"
|
||||
exit 0
|
||||
elif [ "${elem}" = "/usr/bin" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo "${PYTHON_ROOT}/bin is not on your PATH or at least not early enough"
|
||||
case "${BSH}" in
|
||||
*csh)
|
||||
if [ -f "${HOME}/.tcshrc" ]; then
|
||||
RC="${HOME}/.tcshrc"
|
||||
else
|
||||
RC="${HOME}/.cshrc"
|
||||
fi
|
||||
# Create backup copy before patching
|
||||
if [ -f "${RC}" ]; then
|
||||
cp -fp "${RC}" "${RC}.pysave"
|
||||
fi
|
||||
echo "" >> "${RC}"
|
||||
echo "# Setting PATH for Python ${PYVER}" >> "${RC}"
|
||||
echo "# The original version is saved in .cshrc.pysave" >> "${RC}"
|
||||
echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}"
|
||||
if [ `id -ur` = 0 ]; then
|
||||
chown "${USER}" "${RC}"
|
||||
fi
|
||||
exit 0
|
||||
;;
|
||||
bash)
|
||||
if [ -e "${HOME}/.bash_profile" ]; then
|
||||
PR="${HOME}/.bash_profile"
|
||||
elif [ -e "${HOME}/.bash_login" ]; then
|
||||
PR="${HOME}/.bash_login"
|
||||
elif [ -e "${HOME}/.profile" ]; then
|
||||
PR="${HOME}/.profile"
|
||||
else
|
||||
PR="${HOME}/.bash_profile"
|
||||
fi
|
||||
;;
|
||||
zsh)
|
||||
PR="${HOME}/.zprofile"
|
||||
;;
|
||||
*sh)
|
||||
PR="${HOME}/.profile"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create backup copy before patching
|
||||
if [ -f "${PR}" ]; then
|
||||
cp -fp "${PR}" "${PR}.pysave"
|
||||
fi
|
||||
echo "" >> "${PR}"
|
||||
echo "# Setting PATH for Python ${PYVER}" >> "${PR}"
|
||||
echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}"
|
||||
echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}"
|
||||
echo 'export PATH' >> "${PR}"
|
||||
if [ `id -ur` = 0 ]; then
|
||||
chown "${USER}" "${PR}"
|
||||
fi
|
||||
exit 0
|
||||
26
Mac/BuildScript/seticon.m
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Simple tool for setting an icon on a file.
|
||||
*/
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: seticon ICON TARGET");
|
||||
return 1;
|
||||
}
|
||||
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString* iconPath = [NSString stringWithUTF8String:argv[1]];
|
||||
NSString* filePath = [NSString stringWithUTF8String:argv[2]];
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
[[NSWorkspace sharedWorkspace]
|
||||
setIcon: [[NSImage alloc] initWithContentsOfFile: iconPath]
|
||||
forFile: filePath
|
||||
options: 0];
|
||||
[pool release];
|
||||
return 0;
|
||||
}
|
||||
18
Mac/BuildScript/tk868_on_10_8_10_9.patch
Normal file
@@ -0,0 +1,18 @@
|
||||
Fix build failure with +quartz variant on OS X 10.8 and 10.9.
|
||||
Even though Gestalt was deprecated in OS X 10.8, it should work fine
|
||||
through OS X 10.9, and its replacement NSOperatingSystemVersion was
|
||||
not introduced until OS X 10.10.
|
||||
|
||||
Patch from MacPorts project and reported upstream:
|
||||
https://trac.macports.org/ticket/55649
|
||||
--- tk8.6.8/macosx/tkMacOSXXStubs.c.orig 2017-12-06 09:25:08.000000000 -0600
|
||||
+++ tk8.6.8-patched/macosx/tkMacOSXXStubs.c 2018-01-06 19:34:17.000000000 -0600
|
||||
@@ -175,7 +175,7 @@
|
||||
{
|
||||
int major, minor, patch;
|
||||
|
||||
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
|
||||
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
|
||||
Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
|
||||
Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
|
||||
Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
|
||||
161
Mac/Demo/PICTbrowse/ICONbrowse.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""browsepict - Display all "ICON" resources found"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import Win
|
||||
from Carbon import Controls
|
||||
from Carbon import List
|
||||
from Carbon import Icn
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=32
|
||||
MINHEIGHT=32
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "PICTbrowse.rsrc")
|
||||
ICONbrowse()
|
||||
|
||||
class ICONbrowse(FrameWork.Application):
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
contents = self.findICONresources()
|
||||
self.main_dialog.open(ID_MAIN, contents)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def showICON(self, resid):
|
||||
w = ICONwindow(self)
|
||||
w.open(resid)
|
||||
#EasyDialogs.Message('Show ICON %r' % (resid,))
|
||||
|
||||
def findICONresources(self):
|
||||
num = Res.CountResources('ICON')
|
||||
rv = []
|
||||
for i in range(1, num+1):
|
||||
Res.SetResLoad(0)
|
||||
try:
|
||||
r = Res.GetIndResource('ICON', i)
|
||||
finally:
|
||||
Res.SetResLoad(1)
|
||||
id, type, name = r.GetResInfo()
|
||||
rv.append((id, name))
|
||||
return rv
|
||||
|
||||
class ICONwindow(FrameWork.Window):
|
||||
def open(self, (resid, resname)):
|
||||
if not resname:
|
||||
resname = '#%r' % (resid,)
|
||||
self.resid = resid
|
||||
self.picture = Icn.GetIcon(self.resid)
|
||||
l, t, r, b = 0, 0, 32, 32
|
||||
self.pictrect = (l, t, r, b)
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < MINWIDTH: width = MINWIDTH
|
||||
elif width > MAXWIDTH: width = MAXWIDTH
|
||||
if height < MINHEIGHT: height = MINHEIGHT
|
||||
elif height > MAXHEIGHT: height = MAXHEIGHT
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
currect = self.fitrect()
|
||||
Icn.PlotIcon(currect, self.picture)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.wid.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for ICONbrowse"
|
||||
|
||||
def open(self, id, contents):
|
||||
self.id = id
|
||||
FrameWork.DialogWindow.open(self, ID_MAIN)
|
||||
self.dlg.SetDialogDefaultItem(MAIN_SHOW)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
self.setlist()
|
||||
|
||||
def setlist(self):
|
||||
self.list.LDelRow(0, 0)
|
||||
self.list.LSetDrawingMode(0)
|
||||
if self.contents:
|
||||
self.list.LAddRow(len(self.contents), 0)
|
||||
for i in range(len(self.contents)):
|
||||
v = repr(self.contents[i][0])
|
||||
if self.contents[i][1]:
|
||||
v = v + '"' + self.contents[i][1] + '"'
|
||||
self.list.LSetCell(v, (0, i))
|
||||
self.list.LSetDrawingMode(1)
|
||||
self.list.LUpdate(self.wid.GetWindowPort().visRgn)
|
||||
|
||||
def getselection(self):
|
||||
items = []
|
||||
point = (0,0)
|
||||
while 1:
|
||||
ok, point = self.list.LGetSelect(1, point)
|
||||
if not ok:
|
||||
break
|
||||
items.append(point[1])
|
||||
point = point[0], point[1]+1
|
||||
values = []
|
||||
for i in items:
|
||||
values.append(self.contents[i])
|
||||
return values
|
||||
|
||||
def do_show(self, *args):
|
||||
selection = self.getselection()
|
||||
for resid in selection:
|
||||
self.parent.showICON(resid)
|
||||
|
||||
def do_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
140
Mac/Demo/PICTbrowse/PICTbrowse.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""browsepict - Display all "PICT" resources found"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import Win
|
||||
from Carbon import Controls
|
||||
from Carbon import List
|
||||
import struct
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "PICTbrowse.rsrc")
|
||||
PICTbrowse()
|
||||
|
||||
class PICTbrowse(FrameWork.Application):
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
contents = self.findPICTresources()
|
||||
self.main_dialog.open(ID_MAIN, contents)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def showPICT(self, resid):
|
||||
w = PICTwindow(self)
|
||||
w.open(resid)
|
||||
#EasyDialogs.Message('Show PICT %r' % (resid,))
|
||||
|
||||
def findPICTresources(self):
|
||||
num = Res.CountResources('PICT')
|
||||
rv = []
|
||||
for i in range(1, num+1):
|
||||
Res.SetResLoad(0)
|
||||
try:
|
||||
r = Res.GetIndResource('PICT', i)
|
||||
finally:
|
||||
Res.SetResLoad(1)
|
||||
id, type, name = r.GetResInfo()
|
||||
rv.append((id, name))
|
||||
return rv
|
||||
|
||||
class PICTwindow(FrameWork.Window):
|
||||
def open(self, (resid, resname)):
|
||||
if not resname:
|
||||
resname = '#%r' % (resid,)
|
||||
self.resid = resid
|
||||
picture = Qd.GetPicture(self.resid)
|
||||
# Get rect for picture
|
||||
print repr(picture.data[:16])
|
||||
sz, t, l, b, r = struct.unpack('hhhhh', picture.data[:10])
|
||||
print 'pict:', t, l, b, r
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < 64: width = 64
|
||||
elif width > 480: width = 480
|
||||
if height < 64: height = 64
|
||||
elif height > 320: height = 320
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
print 'bounds:', bounds
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.wid.SetWindowPic(picture)
|
||||
self.do_postopen()
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for PICTbrowse"
|
||||
|
||||
def open(self, id, contents):
|
||||
self.id = id
|
||||
FrameWork.DialogWindow.open(self, ID_MAIN)
|
||||
self.dlg.SetDialogDefaultItem(MAIN_SHOW)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
self.setlist()
|
||||
|
||||
def setlist(self):
|
||||
self.list.LDelRow(0, 0)
|
||||
self.list.LSetDrawingMode(0)
|
||||
if self.contents:
|
||||
self.list.LAddRow(len(self.contents), 0)
|
||||
for i in range(len(self.contents)):
|
||||
v = repr(self.contents[i][0])
|
||||
if self.contents[i][1]:
|
||||
v = v + '"' + self.contents[i][1] + '"'
|
||||
self.list.LSetCell(v, (0, i))
|
||||
self.list.LSetDrawingMode(1)
|
||||
self.list.LUpdate(self.wid.GetWindowPort().visRgn)
|
||||
|
||||
def getselection(self):
|
||||
items = []
|
||||
point = (0,0)
|
||||
while 1:
|
||||
ok, point = self.list.LGetSelect(1, point)
|
||||
if not ok:
|
||||
break
|
||||
items.append(point[1])
|
||||
point = point[0], point[1]+1
|
||||
values = []
|
||||
for i in items:
|
||||
values.append(self.contents[i])
|
||||
return values
|
||||
|
||||
def do_show(self, *args):
|
||||
selection = self.getselection()
|
||||
for resid in selection:
|
||||
self.parent.showPICT(resid)
|
||||
|
||||
def do_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
BIN
Mac/Demo/PICTbrowse/PICTbrowse.rsrc
Normal file
162
Mac/Demo/PICTbrowse/PICTbrowse2.py
Normal file
@@ -0,0 +1,162 @@
|
||||
"""browsepict - Display all "PICT" resources found"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import Win
|
||||
from Carbon import Controls
|
||||
from Carbon import List
|
||||
import struct
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=64
|
||||
MINHEIGHT=64
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "PICTbrowse.rsrc")
|
||||
PICTbrowse()
|
||||
|
||||
class PICTbrowse(FrameWork.Application):
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
contents = self.findPICTresources()
|
||||
self.main_dialog.open(ID_MAIN, contents)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def showPICT(self, resid):
|
||||
w = PICTwindow(self)
|
||||
w.open(resid)
|
||||
#EasyDialogs.Message('Show PICT %r' % (resid,))
|
||||
|
||||
def findPICTresources(self):
|
||||
num = Res.CountResources('PICT')
|
||||
rv = []
|
||||
for i in range(1, num+1):
|
||||
Res.SetResLoad(0)
|
||||
try:
|
||||
r = Res.GetIndResource('PICT', i)
|
||||
finally:
|
||||
Res.SetResLoad(1)
|
||||
id, type, name = r.GetResInfo()
|
||||
rv.append((id, name))
|
||||
return rv
|
||||
|
||||
class PICTwindow(FrameWork.Window):
|
||||
def open(self, (resid, resname)):
|
||||
if not resname:
|
||||
resname = '#%r' % (resid,)
|
||||
self.resid = resid
|
||||
self.picture = Qd.GetPicture(self.resid)
|
||||
# Get rect for picture
|
||||
sz, t, l, b, r = struct.unpack('hhhhh', self.picture.data[:10])
|
||||
self.pictrect = (l, t, r, b)
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < MINWIDTH: width = MINWIDTH
|
||||
elif width > MAXWIDTH: width = MAXWIDTH
|
||||
if height < MINHEIGHT: height = MINHEIGHT
|
||||
elif height > MAXHEIGHT: height = MAXHEIGHT
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
currect = self.fitrect()
|
||||
Qd.DrawPicture(self.picture, currect)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.dlg.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for PICTbrowse"
|
||||
|
||||
def open(self, id, contents):
|
||||
self.id = id
|
||||
FrameWork.DialogWindow.open(self, ID_MAIN)
|
||||
self.dlg.SetDialogDefaultItem(MAIN_SHOW)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
self.setlist()
|
||||
|
||||
def setlist(self):
|
||||
self.list.LDelRow(0, 0)
|
||||
self.list.LSetDrawingMode(0)
|
||||
if self.contents:
|
||||
self.list.LAddRow(len(self.contents), 0)
|
||||
for i in range(len(self.contents)):
|
||||
v = repr(self.contents[i][0])
|
||||
if self.contents[i][1]:
|
||||
v = v + '"' + self.contents[i][1] + '"'
|
||||
self.list.LSetCell(v, (0, i))
|
||||
self.list.LSetDrawingMode(1)
|
||||
self.list.LUpdate(self.wid.GetWindowPort().visRgn)
|
||||
|
||||
def getselection(self):
|
||||
items = []
|
||||
point = (0,0)
|
||||
while 1:
|
||||
ok, point = self.list.LGetSelect(1, point)
|
||||
if not ok:
|
||||
break
|
||||
items.append(point[1])
|
||||
point = point[0], point[1]+1
|
||||
values = []
|
||||
for i in items:
|
||||
values.append(self.contents[i])
|
||||
return values
|
||||
|
||||
def do_show(self, *args):
|
||||
selection = self.getselection()
|
||||
for resid in selection:
|
||||
self.parent.showPICT(resid)
|
||||
|
||||
def do_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
161
Mac/Demo/PICTbrowse/cicnbrowse.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""browsepict - Display all "cicn" resources found"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import Win
|
||||
from Carbon import Controls
|
||||
from Carbon import List
|
||||
from Carbon import Icn
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=32
|
||||
MINHEIGHT=32
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "PICTbrowse.rsrc")
|
||||
CIconbrowse()
|
||||
|
||||
class CIconbrowse(FrameWork.Application):
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
contents = self.findcicnresources()
|
||||
self.main_dialog.open(ID_MAIN, contents)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def showCIcon(self, resid):
|
||||
w = CIconwindow(self)
|
||||
w.open(resid)
|
||||
#EasyDialogs.Message('Show cicn %r' % (resid,))
|
||||
|
||||
def findcicnresources(self):
|
||||
num = Res.CountResources('cicn')
|
||||
rv = []
|
||||
for i in range(1, num+1):
|
||||
Res.SetResLoad(0)
|
||||
try:
|
||||
r = Res.GetIndResource('cicn', i)
|
||||
finally:
|
||||
Res.SetResLoad(1)
|
||||
id, type, name = r.GetResInfo()
|
||||
rv.append((id, name))
|
||||
return rv
|
||||
|
||||
class CIconwindow(FrameWork.Window):
|
||||
def open(self, (resid, resname)):
|
||||
if not resname:
|
||||
resname = '#%r' % (resid,)
|
||||
self.resid = resid
|
||||
self.picture = Icn.GetCIcon(self.resid)
|
||||
l, t, r, b = 0, 0, 32, 32
|
||||
self.pictrect = (l, t, r, b)
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < MINWIDTH: width = MINWIDTH
|
||||
elif width > MAXWIDTH: width = MAXWIDTH
|
||||
if height < MINHEIGHT: height = MINHEIGHT
|
||||
elif height > MAXHEIGHT: height = MAXHEIGHT
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
currect = self.fitrect()
|
||||
Icn.PlotCIcon(currect, self.picture)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.wid.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for cicnbrowse"
|
||||
|
||||
def open(self, id, contents):
|
||||
self.id = id
|
||||
FrameWork.DialogWindow.open(self, ID_MAIN)
|
||||
self.dlg.SetDialogDefaultItem(MAIN_SHOW)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
self.setlist()
|
||||
|
||||
def setlist(self):
|
||||
self.list.LDelRow(0, 0)
|
||||
self.list.LSetDrawingMode(0)
|
||||
if self.contents:
|
||||
self.list.LAddRow(len(self.contents), 0)
|
||||
for i in range(len(self.contents)):
|
||||
v = repr(self.contents[i][0])
|
||||
if self.contents[i][1]:
|
||||
v = v + '"' + self.contents[i][1] + '"'
|
||||
self.list.LSetCell(v, (0, i))
|
||||
self.list.LSetDrawingMode(1)
|
||||
self.list.LUpdate(self.wid.GetWindowPort().visRgn)
|
||||
|
||||
def getselection(self):
|
||||
items = []
|
||||
point = (0,0)
|
||||
while 1:
|
||||
ok, point = self.list.LGetSelect(1, point)
|
||||
if not ok:
|
||||
break
|
||||
items.append(point[1])
|
||||
point = point[0], point[1]+1
|
||||
values = []
|
||||
for i in items:
|
||||
values.append(self.contents[i])
|
||||
return values
|
||||
|
||||
def do_show(self, *args):
|
||||
selection = self.getselection()
|
||||
for resid in selection:
|
||||
self.parent.showCIcon(resid)
|
||||
|
||||
def do_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
158
Mac/Demo/PICTbrowse/oldPICTbrowse.py
Normal file
@@ -0,0 +1,158 @@
|
||||
"""browsepict - Display all "PICT" resources found"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import Win
|
||||
from Carbon import List
|
||||
import struct
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "oldPICTbrowse.rsrc")
|
||||
PICTbrowse()
|
||||
|
||||
class PICTbrowse(FrameWork.Application):
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
contents = self.findPICTresources()
|
||||
self.main_dialog.open(ID_MAIN, contents)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def showPICT(self, resid):
|
||||
w = PICTwindow(self)
|
||||
w.open(resid)
|
||||
#EasyDialogs.Message('Show PICT %r' % (resid,))
|
||||
|
||||
def findPICTresources(self):
|
||||
num = Res.CountResources('PICT')
|
||||
rv = []
|
||||
for i in range(1, num+1):
|
||||
Res.SetResLoad(0)
|
||||
try:
|
||||
r = Res.GetIndResource('PICT', i)
|
||||
finally:
|
||||
Res.SetResLoad(1)
|
||||
id, type, name = r.GetResInfo()
|
||||
rv.append((id, name))
|
||||
return rv
|
||||
|
||||
class PICTwindow(FrameWork.Window):
|
||||
def open(self, (resid, resname)):
|
||||
if not resname:
|
||||
resname = '#%r' % (resid,)
|
||||
self.resid = resid
|
||||
picture = Qd.GetPicture(self.resid)
|
||||
# Get rect for picture
|
||||
print repr(picture.data[:16])
|
||||
sz, t, l, b, r = struct.unpack('hhhhh', picture.data[:10])
|
||||
print 'pict:', t, l, b, r
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < 64: width = 64
|
||||
elif width > 480: width = 480
|
||||
if height < 64: height = 64
|
||||
elif height > 320: height = 320
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
print 'bounds:', bounds
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.wid.SetWindowPic(picture)
|
||||
self.do_postopen()
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for PICTbrowse"
|
||||
|
||||
def open(self, id, contents):
|
||||
self.id = id
|
||||
FrameWork.DialogWindow.open(self, ID_MAIN)
|
||||
self.dlg.SetDialogDefaultItem(MAIN_SHOW)
|
||||
tp, h, rect = self.dlg.GetDialogItem(MAIN_LIST)
|
||||
rect2 = rect[0]+1, rect[1]+1, rect[2]-17, rect[3]-17 # Scroll bar space
|
||||
self.list = List.LNew(rect2, (0, 0, 1, len(contents)), (0,0), 0, self.wid,
|
||||
0, 1, 1, 1)
|
||||
self.contents = contents
|
||||
self.setlist()
|
||||
|
||||
def setlist(self):
|
||||
self.list.LDelRow(0, 0)
|
||||
self.list.LSetDrawingMode(0)
|
||||
if self.contents:
|
||||
self.list.LAddRow(len(self.contents), 0)
|
||||
for i in range(len(self.contents)):
|
||||
v = repr(self.contents[i][0])
|
||||
if self.contents[i][1]:
|
||||
v = v + '"' + self.contents[i][1] + '"'
|
||||
self.list.LSetCell(v, (0, i))
|
||||
self.list.LSetDrawingMode(1)
|
||||
self.list.LUpdate(self.wid.GetWindowPort().visRgn)
|
||||
|
||||
def do_listhit(self, event):
|
||||
(what, message, when, where, modifiers) = event
|
||||
Qd.SetPort(self.wid)
|
||||
where = Qd.GlobalToLocal(where)
|
||||
print 'LISTHIT', where
|
||||
if self.list.LClick(where, modifiers):
|
||||
self.do_show()
|
||||
|
||||
def getselection(self):
|
||||
items = []
|
||||
point = (0,0)
|
||||
while 1:
|
||||
ok, point = self.list.LGetSelect(1, point)
|
||||
if not ok:
|
||||
break
|
||||
items.append(point[1])
|
||||
point = point[0], point[1]+1
|
||||
values = []
|
||||
for i in items:
|
||||
values.append(self.contents[i])
|
||||
return values
|
||||
|
||||
def do_show(self, *args):
|
||||
selection = self.getselection()
|
||||
for resid in selection:
|
||||
self.parent.showPICT(resid)
|
||||
|
||||
def do_rawupdate(self, window, event):
|
||||
tp, h, rect = self.dlg.GetDialogItem(MAIN_LIST)
|
||||
Qd.SetPort(self.wid)
|
||||
Qd.FrameRect(rect)
|
||||
self.list.LUpdate(self.wid.GetWindowPort().visRgn)
|
||||
|
||||
def do_activate(self, activate, event):
|
||||
self.list.LActivate(activate)
|
||||
|
||||
def do_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_LIST:
|
||||
self.do_listhit(event)
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
BIN
Mac/Demo/PICTbrowse/oldPICTbrowse.rsrc
Normal file
362
Mac/Demo/applescript.html
Normal file
@@ -0,0 +1,362 @@
|
||||
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html><head><title>Using the Open Scripting Architecture from Python</title></head>
|
||||
<body>
|
||||
<h1>Using the Open Scripting Architecture from Python</h1>
|
||||
<hr>
|
||||
|
||||
<p><b>NOTE:</b> this document describes the OSA support that is shipped with
|
||||
the core python distribution. Most users are better of with the more
|
||||
userfriendly <a href="http://freespace.virgin.net/hamish.sanderson/appscript.html">appscript library</a>.
|
||||
|
||||
<p>OSA support in Python is still not 100% complete, but
|
||||
there is already enough in place to allow you to do some nifty things
|
||||
with other programs from your python program. </p>
|
||||
|
||||
|
||||
<p>
|
||||
In this example, we will look at a scriptable application, extract its
|
||||
“AppleScript Dictionary,” generate a Python interface package from
|
||||
the dictionary, and use that package to control the application.
|
||||
The application we are going to script is Disk Copy, Apple's standard
|
||||
utility for making copies of floppies, creating files that are mountable
|
||||
as disk images, etc.
|
||||
Because we want
|
||||
to concentrate on the OSA details, we won’t bother with a real
|
||||
user-interface for our application. </p>
|
||||
|
||||
|
||||
<p>
|
||||
<em>When we say “AppleScript” in this document we actually mean
|
||||
“the Open Scripting Architecture.” There is nothing
|
||||
AppleScript-specific in the Python implementation. Most of this document
|
||||
focuses on the classic Mac OS; <a href="#osx">Mac OS X</a> users have some
|
||||
additional tools.</em>
|
||||
</p>
|
||||
|
||||
<h2>Python OSA architecture</h2>
|
||||
|
||||
<p>Open Scripting suites and inheritance can be modelled rather nicely
|
||||
with Python packages, so we generate
|
||||
a package for each application we want to script. Each suite defined in
|
||||
the application becomes a module in the
|
||||
package, and the package main module imports everything from all the
|
||||
submodules and glues together all the classes (in Python terminology—
|
||||
events in OSA terminology or verbs in AppleScript terminology). </p>
|
||||
|
||||
<p>
|
||||
A suite in an OSA application can extend the functionality of a standard
|
||||
suite. This is implemented in Python by importing everything from the
|
||||
module that implements the standard suites and overriding anything that has
|
||||
been extended. The standard suites live in the StdSuite package. </p>
|
||||
|
||||
<p>
|
||||
This all sounds complicated, but the good news is that basic
|
||||
scripting is actually pretty simple. You can do strange and wondrous things
|
||||
with OSA scripting once you fully understand it. </p>
|
||||
|
||||
<h2>Creating the Python interface package</h2>
|
||||
|
||||
|
||||
<p>There is a tool in the standard distribution that can automatically
|
||||
generate the interface packages. This tool is called
|
||||
<code>gensuitemodule.py</code>, and lives in <code>Mac:scripts</code>.
|
||||
It looks through a file
|
||||
for an ‘AETE’ or ‘AEUT’ resource,
|
||||
the internal representation of the
|
||||
AppleScript dictionary, and parses the resource to generate the suite
|
||||
modules.
|
||||
When we start <code>gensuitemodule</code>, it asks us for an input file;
|
||||
for our example,
|
||||
we point it to the Disk Copy executable. </p>
|
||||
|
||||
<p>
|
||||
Next, <code>gensuitemodule</code> wants a folder where it will store the
|
||||
package it is going to generate.
|
||||
Note that this is the package folder, not the parent folder, so we
|
||||
navigate to <code>Python:Mac:Demo:applescript</code>, create a folder
|
||||
<code>Disk_Copy</code>, and select that. </p>
|
||||
|
||||
<p>
|
||||
We next specify the folder from which <code>gensuitemodule</code>
|
||||
should import the standard suites. Here,
|
||||
we always select <code>Python:Mac:Lib:lib-scriptpackages:StdSuites</code>. (There is
|
||||
one exception to this rule: when you are generating <code>StdSuites</code> itself
|
||||
you select <code>_builtinSuites</code>.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It starts parsing the AETE resource, and for
|
||||
each AppleEvent suite it finds, <code>gensuitemodule.py</code>
|
||||
prompts us for the filename of the
|
||||
resulting python module. Remember to change folders for the first
|
||||
module—you don't want to clutter up, say, the
|
||||
Disk Copy folder
|
||||
with your python
|
||||
interfaces. If you want to skip a suite, press <code>cancel</code> and the process
|
||||
continues with the next suite. </p>
|
||||
|
||||
<h3>Summary</h3>
|
||||
|
||||
<ol>
|
||||
|
||||
<li>Run <code>gensuitemodule</code>.</li>
|
||||
|
||||
<li>Select the application (or OSAX) for which you would like a Python interface.</li>
|
||||
|
||||
<li>Select the package folder where the interface modules should be
|
||||
stored.</li>
|
||||
|
||||
<li>Specify the folder <code>Python:Mac:Lib:lib-scriptpackages:StdSuites</code>
|
||||
to import the standard suites (or <code>_builtinSuites</code> if you are
|
||||
generating <code>StdSuites</code> itself). </li>
|
||||
|
||||
<li>Save the generated suites (use <code>cancel</code> to skip a suite).</li>
|
||||
|
||||
|
||||
</ol>
|
||||
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The interface package may occasionally need some editing by hand. For example,
|
||||
<code>gensuitemodule</code> does not handle all Python reserved words, so
|
||||
if
|
||||
one of the AppleScript verbs is a Python reserved word, a <code>SyntaxError</code>
|
||||
may be raised when the package is imported.
|
||||
Simply rename the class into something acceptable, if this happens;
|
||||
take a look at how the
|
||||
<code>print</code> verb is handled (automatically by <code>gensuitemodule</code>)
|
||||
in the standard suites. But: f you need to edit your package this should be considered a
|
||||
bug in gensuitemodule, so please report it so it can be fixed in future releases.
|
||||
</li>
|
||||
|
||||
|
||||
<li>If you want to re-create the StdSuite modules,
|
||||
you should look in one of two places. With versions of AppleScript older than 1.4.0
|
||||
(which first shipped with OS 9.0), you will find the
|
||||
AEUT resources in <code>System Folder:Extensions:Scripting
|
||||
Additions:Dialects:English Dialect</code>. For newer versions, you will
|
||||
find them in <code>System Folder:Extensions:Applescript</code>.
|
||||
</li>
|
||||
|
||||
<li>Since MacPython 2.0, this new structure, with packages
|
||||
per application and submodules per suite, is used. Older MacPythons had a
|
||||
single level of modules, with uncertain semantics. With the new structure,
|
||||
it is possible for programs to override standard suites, as programs often do.
|
||||
|
||||
</li>
|
||||
|
||||
<li><code>Gensuitemodule.py</code> may ask you questions
|
||||
like “Where is enum 'xyz ' declared?”.
|
||||
This is either due to a misunderstanding on my part or (rather too commonly)
|
||||
bugs in the AETE resources. Pressing <code>cancel</code> is usually the
|
||||
right choice: it will cause the specific enum not to be treated as an enum
|
||||
but as a “normal” type. As things like fsspecs and TEXT strings clearly are
|
||||
not enumerators, this is correct. If someone understands what is really going on
|
||||
here, please let me know.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h2>The Python interface package contents</h2>
|
||||
|
||||
<p>
|
||||
Let’s glance at the
|
||||
<a href="applescript/Disk_Copy">Disk_Copy</a> package just created. You
|
||||
may want to open Script Editor alongside to see how it
|
||||
interprets the dictionary.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
The main package module is in <code>__init__.py</code>.
|
||||
The only interesting bit is the <code>Disk_Copy</code> class, which
|
||||
includes the event handling classes from the individual suites. It also
|
||||
inherits <code>aetools.TalkTo</code>, which is a base class that handles all
|
||||
details on how to start the program and talk to it, and a class variable
|
||||
<code>_signature</code> which is the default application this class will talk
|
||||
to (you can override this in various ways when you instantiate your class, see
|
||||
<code>aetools.py</code> for details).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="applescript/Disk_Copy/Special_Events.py">Special_Events</a>
|
||||
module is a nice example of a suite module.
|
||||
The <code>Special_Events_Events</code> class is the bulk of the code
|
||||
generated. For each verb, it contains a method. Each method knows what
|
||||
arguments the verb expects, and it makes use of keyword
|
||||
arguments to present a palatable
|
||||
interface to the python programmer.
|
||||
|
||||
Notice that each method
|
||||
calls some routines from <code>aetools</code>, an auxiliary module
|
||||
living in <code>Mac:Lib</code>.
|
||||
The other thing to notice is that each method calls
|
||||
<code>self.send</code>. This comes from the <code>aetools.TalkTo</code>
|
||||
baseclass. </p>
|
||||
|
||||
|
||||
<p>
|
||||
After the big class, there are a number of little class declarations. These
|
||||
declarations are for the (AppleEvent) classes and properties in the suite.
|
||||
They allow you to create object IDs, which can then be passed to the verbs.
|
||||
For instance,
|
||||
when scripting the popular email program Eudora,
|
||||
you would use <code>mailbox("inbox").message(1).sender</code>
|
||||
to get the name of the sender of the first message in mailbox
|
||||
inbox. It is
|
||||
also possible to specify this as <code>sender(message(1, mailbox("inbox")))</code>,
|
||||
which is sometimes needed because these classes don’t always inherit correctly
|
||||
from baseclasses, so you may have to use a class or property from another
|
||||
suite. </p>
|
||||
|
||||
<p>
|
||||
Next we get the enumeration dictionaries, which allow you to pass
|
||||
english names as arguments to verbs, so you don't have to bother with the 4-letter
|
||||
type code. So, you can say
|
||||
<code>
|
||||
diskcopy.create(..., filesystem="Mac OS Standard")
|
||||
</code>
|
||||
as it is called in Script Editor, instead of the cryptic lowlevel
|
||||
<code>
|
||||
diskcopy.create(..., filesystem="Fhfs")
|
||||
</code></p>
|
||||
|
||||
<p>
|
||||
Finally, we get the “table of contents” of the module, listing all
|
||||
classes and such
|
||||
by code, which is used by <code>gensuitemodule</code> itself: if you use this
|
||||
suite as a base package in a later run this is how it knows what is defined in this
|
||||
suite, and what the Python names are.
|
||||
</p>
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The <code>aetools</code> module contains some other nifty
|
||||
AppleEvent tools as well. Have a look at it sometime, there is (of
|
||||
course) no documentation yet.
|
||||
</li>
|
||||
|
||||
<li>There are also some older object specifiers for standard objects in aetools.
|
||||
You use these in the form <code>aetools.Word(10,
|
||||
aetools.Document(1))</code>, where the corresponding AppleScript
|
||||
terminology would be <code>word 10 of the first
|
||||
document</code>. Examine
|
||||
<code>aetools</code> and <code>aetools.TalkTo</code>
|
||||
along with
|
||||
the comments at the end of your suite module if you need to create
|
||||
more than the standard object specifiers.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Using a Python suite module</h2>
|
||||
|
||||
<p>
|
||||
Now that we have created the suite module, we can use it in a Python script.
|
||||
In older MacPython distributions this used to be a rather
|
||||
complicated affair, but with the package scheme and with the application signature
|
||||
known by the package it is very simple: you import the package and instantiate
|
||||
the class, e.g.
|
||||
<code>
|
||||
talker = Disk_Copy.Disk_Copy(start=1)
|
||||
</code>
|
||||
You will usually specify the <code>start=1</code>: it will run the application if it is
|
||||
not already running.
|
||||
You may want to omit it if you want to talk to the application
|
||||
only if it is already running, or if the application is something like the Finder.
|
||||
Another way to ensure that the application is running is to call <code>talker._start()</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Looking at the sourcefile <a
|
||||
href="applescript/makedisk.py">makedisk.py</a>, we see that it starts
|
||||
with some imports. Naturally, one of these is the Python interface to Disk
|
||||
Copy.</p>
|
||||
|
||||
<p>
|
||||
The main program itself is a wonder of simplicity: we create the
|
||||
object (<code>talker</code>) that talks to Disk Copy,
|
||||
create a disk, and mount it. The bulk of
|
||||
the work is done by <code>talker</code> and the Python interface package we
|
||||
just created.</p>
|
||||
|
||||
<p>
|
||||
The exception handling does warrant a few comments, though. Since
|
||||
AppleScript is basically a connectionless RPC protocol,
|
||||
nothing happens
|
||||
when we create the <code>talker</code> object. Hence, if the destination application
|
||||
is not running, we will not notice until we send our first
|
||||
command (avoid this as described above). There is another thing to note about errors returned by
|
||||
AppleScript calls: <code>MacOS.Error</code> is raised for
|
||||
all of the errors that are known to be <code>OSErr</code>-type errors,
|
||||
while
|
||||
server generated errors raise <code>aetools.Error</code>. </p>
|
||||
|
||||
<h2>Scripting Additions</h2>
|
||||
|
||||
<p>
|
||||
If you want to use any of the scripting additions (or OSAXen, in
|
||||
everyday speech) from a Python program, you can use the same method
|
||||
as for applications, i.e. run <code>gensuitemodule</code> on the
|
||||
OSAX (commonly found in <code>System Folder:Scripting Additions</code>
|
||||
or something similar). There is one minor gotcha: the application
|
||||
signature to use is <code>MACS</code>. You will need to edit the main class
|
||||
in the <code>__init__.py</code> file of the created package and change the value
|
||||
of <code>_signature</code> to <code>MACS</code>, or use a subclass to the
|
||||
same effect.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are two minor points to watch out for when using <code>gensuitemodule</code>
|
||||
on OSAXen: they appear all to define the class <code>System_Object_Suite</code>,
|
||||
and a lot of them have the command set in multiple dialects. You have to
|
||||
watch out for name conflicts and make sure you select a reasonable dialect
|
||||
(some of the non-English dialects cause <code>gensuitemodule</code> to generate incorrect
|
||||
Python code). </p>
|
||||
|
||||
Despite these difficulties, OSAXen offer a lot of possibilities. Take a
|
||||
look at some of the OSAXen in the Scripting Additions folder, or
|
||||
<A HREF="http://www.osaxen.com/index.php">download</A> some from the net.
|
||||
|
||||
<h2>Further Reading</h2>
|
||||
|
||||
<p>
|
||||
If you want to look at more involved examples of applescripting, look at the standard
|
||||
modules <code>findertools</code> and <code>nsremote</code>, or (possibly better, as it
|
||||
is more involved) <code>fullbuild</code> from the <code>Mac:scripts</code> folder.
|
||||
</p>
|
||||
|
||||
<h2><a name="alternatives">Alternatives</a></h2>
|
||||
|
||||
<h3><a name="osx">Mac OS X</a></h3>
|
||||
|
||||
<p>
|
||||
Under Mac OS X, the above still works, but with some new difficulties.
|
||||
The application package structure can hide the ‘AETE’ or
|
||||
‘AEUT’ resource from <code>gensuitemodule</code>, so that,
|
||||
for example, it cannot generate an OSA interface to iTunes. Script
|
||||
Editor gets at the dictionary of such programs using a ‘Get
|
||||
AETE’ AppleEvent, if someone wants to donate code to use the same
|
||||
method for gensuitemodule: by all means!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One alternative is available through the Unix command line version of python.
|
||||
Apple has provided the <code>osacompile</code> and <code>osascript</code> tools,
|
||||
which can be used to compile and execute scripts written in OSA languages. See the
|
||||
man pages for more details.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
424
Mac/Demo/applescript/Disk_Copy/Special_Events.py
Normal file
@@ -0,0 +1,424 @@
|
||||
"""Suite Special Events: Commands for mounting Disk Copy images
|
||||
Level 1, version 1
|
||||
|
||||
Generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
AETE/AEUT resource version 1/0, language 0, script 0
|
||||
"""
|
||||
|
||||
import aetools
|
||||
import MacOS
|
||||
|
||||
_code = 'ddsk'
|
||||
|
||||
class Special_Events_Events:
|
||||
|
||||
_argmap_mount = {
|
||||
'access_mode' : 'Acss',
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
'RAM_caching' : 'Cach',
|
||||
}
|
||||
|
||||
def mount(self, _object, _attributes={}, **_arguments):
|
||||
"""mount: Mounts a Disk Copy image as a disk volume
|
||||
Required argument: a reference to the disk image to be mounted
|
||||
Keyword argument access_mode: the access mode for mounted volume (default is "any", i.e. best possible)
|
||||
Keyword argument checksum_verification: Verify the checksum before mounting?
|
||||
Keyword argument signature_verification: Verify the DigiSign<67> signature before mounting?
|
||||
Keyword argument RAM_caching: Cache the disk image in RAM? (if omitted, don't cache)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to mounted disk
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Moun'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_mount)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'Acss', _Enum_Acss)
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Cach', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_execute_DiskScript = {
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
}
|
||||
|
||||
def execute_DiskScript(self, _object, _attributes={}, **_arguments):
|
||||
"""execute DiskScript: Executes a Disk Copy-specific DiskScript
|
||||
Required argument: a reference to the DiskScript to execute
|
||||
Keyword argument checksum_verification: Should checksums be verified when mounting images referenced in the DiskScript?
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature of the DiskScript and the images it references be verified?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'XEQd'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_execute_DiskScript)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def unmount(self, _object, _attributes={}, **_arguments):
|
||||
"""unmount: Unmount and eject (if necessary) a volume
|
||||
Required argument: a reference to disk to be unmounted (and ejected)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Umnt'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_create = {
|
||||
'saving_as' : 'SvAs',
|
||||
'logical_blocks' : 'Blks',
|
||||
'zeroing' : 'Zero',
|
||||
'leave_image_mounted' : 'Moun',
|
||||
'filesystem' : 'Fsys',
|
||||
}
|
||||
|
||||
def create(self, _object, _attributes={}, **_arguments):
|
||||
"""create: Create a new Disk Copy document
|
||||
Required argument: the name of the volume to create
|
||||
Keyword argument saving_as: the disk image to be created
|
||||
Keyword argument logical_blocks: the number of logical blocks
|
||||
Keyword argument zeroing: Should all blocks on the disk be set to zero?
|
||||
Keyword argument leave_image_mounted: Should the image be mounted after it is created?
|
||||
Keyword argument filesystem: file system to use (Mac OS Standard/compatible, Mac OS Enhanced)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to newly created disk image (or newly mounted disk)
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Crea'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_create)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'SvAs', _Enum_fss_)
|
||||
aetools.enumsubst(_arguments, 'Blks', _Enum_long)
|
||||
aetools.enumsubst(_arguments, 'Zero', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Moun', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Fsys', _Enum_Fsys)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def verify_checksum(self, _object, _attributes={}, **_arguments):
|
||||
"""verify checksum: Verify the checksum of a Disk Copy 4.2 or a Disk Copy 6.0 read-only document
|
||||
Required argument: the disk image to be verified
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: the result of the checksum verification
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Vcrc'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def verify_signature(self, _object, _attributes={}, **_arguments):
|
||||
"""verify signature: Verify the DigiSign<67> signature for a Disk Copy document
|
||||
Required argument: the disk image to be verified
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: Is the DigiSign<67> signature valid?
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Vsig'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_sign_image = {
|
||||
'using_signer' : 'Sinr',
|
||||
}
|
||||
|
||||
def sign_image(self, _object, _attributes={}, **_arguments):
|
||||
"""sign image: Add a DigiSign<67> signature to a Disk Copy document
|
||||
Required argument: the disk image to be signed
|
||||
Keyword argument using_signer: a reference to signer file to use
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Asig'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_sign_image)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'Sinr', _Enum_alis)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_create_a_floppy_from = {
|
||||
'signature_verification' : 'VSig',
|
||||
'erase_confirmation' : 'Cfrm',
|
||||
'make_multiple_floppies' : 'Mult',
|
||||
}
|
||||
|
||||
def create_a_floppy_from(self, _object, _attributes={}, **_arguments):
|
||||
"""create a floppy from: create a floppy disk from a Disk Copy document
|
||||
Required argument: the disk image to make a floppy from
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature be verified before creating a floppy disk?
|
||||
Keyword argument erase_confirmation: Should the user be asked to confirm the erasure of the previous contents of floppy disks?
|
||||
Keyword argument make_multiple_floppies: Should the user be prompted to create multiple floppy disks?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Bfpy'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_create_a_floppy_from)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Cfrm', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Mult', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_check_image = {
|
||||
'details' : 'ChDe',
|
||||
}
|
||||
|
||||
def check_image(self, _object, _attributes={}, **_arguments):
|
||||
"""check image: Check the disk image<67>s internal data structures for any inconsistencies. Works on NDIF, Disk Copy 4.2, DART<52>, or DiskSet images.
|
||||
Required argument: the disk image to be verified
|
||||
Keyword argument details: Should the disk image details be displayed?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a record containing a boolean (true/false) value if the image passes consistency tests, and the numbers of warnings and errors
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Chek'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_check_image)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'ChDe', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_segment_image = {
|
||||
'segment_count' : 'SGCT',
|
||||
'segment_size' : 'SGSZ',
|
||||
'segment_name' : 'SGNM',
|
||||
'image_ID' : 'SGID',
|
||||
}
|
||||
|
||||
def segment_image(self, _object, _attributes={}, **_arguments):
|
||||
"""segment image: Segment a NDIF R/W or R/O image into smaller pieces
|
||||
Required argument: the disk image to be segmented
|
||||
Keyword argument segment_count: the number of image segments to create
|
||||
Keyword argument segment_size: the size of image segments (in blocks) to create
|
||||
Keyword argument segment_name: the root name for each image segment file
|
||||
Keyword argument image_ID: string used to generate a unique image ID to group the segments
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a list of references to the image segments created
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'SGMT'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_segment_image)
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_create_SMI = {
|
||||
'source_images' : 'SMI1',
|
||||
'launching_application' : 'SMI2',
|
||||
'launching_document' : 'SMI3',
|
||||
'version_string' : 'SMI4',
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
'image_signing' : 'SImg',
|
||||
}
|
||||
|
||||
def create_SMI(self, _object, _attributes={}, **_arguments):
|
||||
"""create SMI: Creates a self-mounting image (SMI) from a list of NDIF disk images
|
||||
Required argument: the self-mounting image to create
|
||||
Keyword argument source_images: a list of references to sources images
|
||||
Keyword argument launching_application: the path to an application to launch
|
||||
Keyword argument launching_document: the path to a document to open
|
||||
Keyword argument version_string: sets the 'vers' 1 resource of the self-mounting image
|
||||
Keyword argument checksum_verification: Should the checksum of the source images be verified before creating the SMI?
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature of the source images be verified before creating the SMI?
|
||||
Keyword argument image_signing: Should the SMI be given a digital signature when it is created?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to the self-mounting image created
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'MSMI'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_create_SMI)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'SImg', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
|
||||
class Verify_Checksum_reply_record(aetools.ComponentItem):
|
||||
"""Verify Checksum reply record - """
|
||||
want = 'Rcrc'
|
||||
class validity(aetools.NProperty):
|
||||
"""validity - true if checksum is valid """
|
||||
which = 'Vlid'
|
||||
want = 'bool'
|
||||
class expected_checksum(aetools.NProperty):
|
||||
"""expected checksum - checksum value stored in the image header (in hexadecimal) """
|
||||
which = 'crcE'
|
||||
want = 'TEXT'
|
||||
class calculated_checksum(aetools.NProperty):
|
||||
"""calculated checksum - checksum value actually calculated (in hexadecimal) """
|
||||
which = 'crcA'
|
||||
want = 'TEXT'
|
||||
|
||||
class Check_Image_reply_record(aetools.ComponentItem):
|
||||
"""Check Image reply record - """
|
||||
want = 'Rchk'
|
||||
class consistency(aetools.NProperty):
|
||||
"""consistency - Does the image pass consistency checks? """
|
||||
which = 'Rch1'
|
||||
want = 'bool'
|
||||
class error_count(aetools.NProperty):
|
||||
"""error count - the number of errors recorded """
|
||||
which = 'Rch2'
|
||||
want = 'long'
|
||||
class warning_count(aetools.NProperty):
|
||||
"""warning count - the number of warnings recorded """
|
||||
which = 'Rch3'
|
||||
want = 'long'
|
||||
Verify_Checksum_reply_record._propdict = {
|
||||
'validity' : validity,
|
||||
'expected_checksum' : expected_checksum,
|
||||
'calculated_checksum' : calculated_checksum,
|
||||
}
|
||||
Verify_Checksum_reply_record._elemdict = {
|
||||
}
|
||||
Check_Image_reply_record._propdict = {
|
||||
'consistency' : consistency,
|
||||
'error_count' : error_count,
|
||||
'warning_count' : warning_count,
|
||||
}
|
||||
Check_Image_reply_record._elemdict = {
|
||||
}
|
||||
_Enum_Acss = {
|
||||
'read_and_write' : 'RdWr', # read/write access
|
||||
'read_only' : 'Rdxx', # read-only access
|
||||
'any' : 'Anyx', # best possible access
|
||||
}
|
||||
|
||||
_Enum_Fsys = {
|
||||
'Mac_OS_Standard' : 'Fhfs', # classic HFS file system
|
||||
'compatible_Mac_OS_Extended' : 'Fhf+', # new HFS+ file system
|
||||
}
|
||||
|
||||
_Enum_alis = None # XXXX enum alis not found!!
|
||||
_Enum_fss_ = None # XXXX enum fss not found!!
|
||||
_Enum_long = None # XXXX enum long not found!!
|
||||
_Enum_bool = None # XXXX enum bool not found!!
|
||||
|
||||
#
|
||||
# Indices of types declared in this module
|
||||
#
|
||||
_classdeclarations = {
|
||||
'Rchk' : Check_Image_reply_record,
|
||||
'Rcrc' : Verify_Checksum_reply_record,
|
||||
}
|
||||
|
||||
_propdeclarations = {
|
||||
'crcE' : expected_checksum,
|
||||
'Rch2' : error_count,
|
||||
'crcA' : calculated_checksum,
|
||||
'Rch3' : warning_count,
|
||||
'Vlid' : validity,
|
||||
'Rch1' : consistency,
|
||||
}
|
||||
|
||||
_compdeclarations = {
|
||||
}
|
||||
|
||||
_enumdeclarations = {
|
||||
'Acss' : _Enum_Acss,
|
||||
'Fsys' : _Enum_Fsys,
|
||||
}
|
||||
477
Mac/Demo/applescript/Disk_Copy/Standard_Suite.py
Normal file
@@ -0,0 +1,477 @@
|
||||
"""Suite Standard Suite: Common terms for most applications
|
||||
Level 1, version 1
|
||||
|
||||
Generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
AETE/AEUT resource version 1/0, language 0, script 0
|
||||
"""
|
||||
|
||||
import aetools
|
||||
import MacOS
|
||||
|
||||
_code = 'Core'
|
||||
|
||||
class Standard_Suite_Events:
|
||||
|
||||
_argmap_save = {
|
||||
'_in' : 'kfil',
|
||||
'using_format' : 'SvAs',
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
'image_signing' : 'SImg',
|
||||
'leave_image_mounted' : 'Moun',
|
||||
'percent_free_space' : 'Slop',
|
||||
'logical_blocks' : 'Blks',
|
||||
'zeroing' : 'Zero',
|
||||
}
|
||||
|
||||
def save(self, _object, _attributes={}, **_arguments):
|
||||
"""save: Save an object
|
||||
Required argument: the source object
|
||||
Keyword argument _in: the target object
|
||||
Keyword argument using_format: the format for the target
|
||||
Keyword argument checksum_verification: Should the checksum be verified before saving?
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature be verified before saving?
|
||||
Keyword argument image_signing: Should the image be signed?
|
||||
Keyword argument leave_image_mounted: Should the image be mounted after saving?
|
||||
Keyword argument percent_free_space: percent free space to reserve (for image folder operation, 0-255%)
|
||||
Keyword argument logical_blocks: number of logical blocks in the image (for image folder operation)
|
||||
Keyword argument zeroing: Should all the blocks in the image be set to zeros? (for image folder operation)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: the result of the save operation
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'save'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_save)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'kfil', _Enum_obj_)
|
||||
aetools.enumsubst(_arguments, 'SvAs', _Enum_SvAs)
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'SImg', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Moun', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Slop', _Enum_long)
|
||||
aetools.enumsubst(_arguments, 'Blks', _Enum_long)
|
||||
aetools.enumsubst(_arguments, 'Zero', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def do_script(self, _object, _attributes={}, **_arguments):
|
||||
"""do script: Execute an attached script located in the folder "Scripts"
|
||||
Required argument: the script to be executed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'dosc'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
|
||||
class application(aetools.ComponentItem):
|
||||
"""application - The Disk Copy application """
|
||||
want = 'capp'
|
||||
class version(aetools.NProperty):
|
||||
"""version - the version of this application """
|
||||
which = 'vers'
|
||||
want = 'vers'
|
||||
class name(aetools.NProperty):
|
||||
"""name - the name of this application """
|
||||
which = 'pnam'
|
||||
want = 'TEXT'
|
||||
class comment(aetools.NProperty):
|
||||
"""comment - the comment associated with the application """
|
||||
which = 'comt'
|
||||
want = 'TEXT'
|
||||
class driver_version(aetools.NProperty):
|
||||
"""driver version - the version of the disk image driver """
|
||||
which = 'dVer'
|
||||
want = 'vers'
|
||||
class nonejectable_mode(aetools.NProperty):
|
||||
"""nonejectable mode - Should mounted images be non-ejectable? """
|
||||
which = 'otto'
|
||||
want = 'bool'
|
||||
class save_log_file(aetools.NProperty):
|
||||
"""save log file - Should the log file be saved on disk? """
|
||||
which = 'PSaL'
|
||||
want = 'bool'
|
||||
class use_speech(aetools.NProperty):
|
||||
"""use speech - Should Disk Copy use spoken feedback? """
|
||||
which = 'PTlk'
|
||||
want = 'bool'
|
||||
class smart_Save_As(aetools.NProperty):
|
||||
"""smart Save As - Should the Save As... dialog box automatically go to the right folder? """
|
||||
which = 'PSSP'
|
||||
want = 'bool'
|
||||
class checksum_verification(aetools.NProperty):
|
||||
"""checksum verification - Should image checksums be verified? """
|
||||
which = 'PVeC'
|
||||
want = 'bool'
|
||||
class signature_verification(aetools.NProperty):
|
||||
"""signature verification - Should digital signatures be verified? """
|
||||
which = 'PVeS'
|
||||
want = 'bool'
|
||||
class exclude_DiskScripts(aetools.NProperty):
|
||||
"""exclude DiskScripts - Should images referenced in DiskScripts/DiskSets be excluded from verification? """
|
||||
which = 'PExD'
|
||||
want = 'bool'
|
||||
class exclude_remote_images(aetools.NProperty):
|
||||
"""exclude remote images - Should images that are located on network volumes be excluded from verification? """
|
||||
which = 'PExR'
|
||||
want = 'bool'
|
||||
class image_signing(aetools.NProperty):
|
||||
"""image signing - Should images be signed with a digital signature? """
|
||||
which = 'PSiI'
|
||||
want = 'bool'
|
||||
class leave_image_mounted(aetools.NProperty):
|
||||
"""leave image mounted - Should images be mounted after they are created? """
|
||||
which = 'PMoA'
|
||||
want = 'bool'
|
||||
class erase_confirmation(aetools.NProperty):
|
||||
"""erase confirmation - Should the user be required to confirm commands that erase disks? """
|
||||
which = 'PCoE'
|
||||
want = 'bool'
|
||||
class zeroing(aetools.NProperty):
|
||||
"""zeroing - Should all blocks of a new image be set to zero? """
|
||||
which = 'PZeB'
|
||||
want = 'bool'
|
||||
class default_create_size(aetools.NProperty):
|
||||
"""default create size - the default size for a new image, in blocks (512 bytes per block) """
|
||||
which = 'PDeS'
|
||||
want = 'long'
|
||||
class default_create_name(aetools.NProperty):
|
||||
"""default create name - the default volume name for a new image """
|
||||
which = 'PDeN'
|
||||
want = 'TEXT'
|
||||
class make_multiple_floppies(aetools.NProperty):
|
||||
"""make multiple floppies - Should the user be prompted to make multiple floppy disk images at a time? """
|
||||
which = 'PBuM'
|
||||
want = 'bool'
|
||||
class auto_image_upon_insert(aetools.NProperty):
|
||||
"""auto image upon insert - Should a newly-inserted disk automatically be processed into an image? """
|
||||
which = 'Paim'
|
||||
want = 'bool'
|
||||
class eject_after_auto_image(aetools.NProperty):
|
||||
"""eject after auto image - Should auto-imaged disks be ejected afterwards? """
|
||||
which = 'Pejc'
|
||||
want = 'bool'
|
||||
class auto_copy_upon_floppy_insert(aetools.NProperty):
|
||||
"""auto copy upon floppy insert - Instead of auto-imaging, should newly-inserted floppy disks be copied? """
|
||||
which = 'Pcpf'
|
||||
want = 'bool'
|
||||
class volume_suffix(aetools.NProperty):
|
||||
"""volume suffix - the default volume name suffix """
|
||||
which = 'PDiE'
|
||||
want = 'TEXT'
|
||||
class image_suffix(aetools.NProperty):
|
||||
"""image suffix - the default image name suffix """
|
||||
which = 'PImE'
|
||||
want = 'TEXT'
|
||||
class default_file_system(aetools.NProperty):
|
||||
"""default file system - the default file system type for new blank images """
|
||||
which = 'Pfsy'
|
||||
want = 'Fsys'
|
||||
class default_image_format(aetools.NProperty):
|
||||
"""default image format - the default image file format """
|
||||
which = 'Pdfm'
|
||||
want = 'SvAs'
|
||||
|
||||
class disk(aetools.ComponentItem):
|
||||
"""disk - A mounted volume """
|
||||
want = 'Disk'
|
||||
|
||||
name = name
|
||||
|
||||
comment = comment
|
||||
class locked(aetools.NProperty):
|
||||
"""locked - Is the disk locked? """
|
||||
which = 'islk'
|
||||
want = 'bool'
|
||||
class creation_date(aetools.NProperty):
|
||||
"""creation date - the creation date of disk """
|
||||
which = 'ascd'
|
||||
want = 'ldt '
|
||||
class modification_date(aetools.NProperty):
|
||||
"""modification date - the modification date of disk """
|
||||
which = 'asmo'
|
||||
want = 'ldt '
|
||||
class crc32_checksum(aetools.NProperty):
|
||||
"""crc32 checksum - the crc-32 checksum of the disk """
|
||||
which = 'Xcrc'
|
||||
want = 'TEXT'
|
||||
class disk_copy_4_2e_2_checksum(aetools.NProperty):
|
||||
"""disk copy 4.2 checksum - the Disk Copy 4.2 checksum of the disk """
|
||||
which = 'Xc42'
|
||||
want = 'TEXT'
|
||||
class block_count(aetools.NProperty):
|
||||
"""block count - the number of blocks on disk """
|
||||
which = 'Xblk'
|
||||
want = 'long'
|
||||
class file_system(aetools.NProperty):
|
||||
"""file system - the file system used on disk """
|
||||
which = 'Xfsi'
|
||||
want = 'TEXT'
|
||||
|
||||
class folder(aetools.ComponentItem):
|
||||
"""folder - A folder or directory on a disk """
|
||||
want = 'Fold'
|
||||
|
||||
name = name
|
||||
|
||||
comment = comment
|
||||
|
||||
creation_date = creation_date
|
||||
|
||||
modification_date = modification_date
|
||||
|
||||
class disk_image(aetools.ComponentItem):
|
||||
"""disk image - A disk image file """
|
||||
want = 'DImg'
|
||||
|
||||
name = name
|
||||
|
||||
comment = comment
|
||||
|
||||
locked = locked
|
||||
|
||||
creation_date = creation_date
|
||||
|
||||
modification_date = modification_date
|
||||
class file_format(aetools.NProperty):
|
||||
"""file format - the format of the disk image file """
|
||||
which = 'Ifmt'
|
||||
want = 'TEXT'
|
||||
class signed(aetools.NProperty):
|
||||
"""signed - Does the disk image have a DigiSign<67> signature? """
|
||||
which = 'Isin'
|
||||
want = 'bool'
|
||||
class compressed(aetools.NProperty):
|
||||
"""compressed - Is the disk image compressed? """
|
||||
which = 'Icom'
|
||||
want = 'bool'
|
||||
class segmented(aetools.NProperty):
|
||||
"""segmented - Is the disk image segmented? """
|
||||
which = 'Iseg'
|
||||
want = 'bool'
|
||||
class segments(aetools.NProperty):
|
||||
"""segments - a list of references to other segments that make up a complete image """
|
||||
which = 'Isg#'
|
||||
want = 'fss '
|
||||
class disk_name(aetools.NProperty):
|
||||
"""disk name - the name of the disk this image represents """
|
||||
which = 'Idnm'
|
||||
want = 'TEXT'
|
||||
|
||||
crc32_checksum = crc32_checksum
|
||||
|
||||
disk_copy_4_2e_2_checksum = disk_copy_4_2e_2_checksum
|
||||
|
||||
block_count = block_count
|
||||
|
||||
file_system = file_system
|
||||
class data_fork_size(aetools.NProperty):
|
||||
"""data fork size - the size (in bytes) of the data fork of the disk image """
|
||||
which = 'Idfk'
|
||||
want = 'long'
|
||||
class resource_fork_size(aetools.NProperty):
|
||||
"""resource fork size - the size (in bytes) of the resource fork of the disk image """
|
||||
which = 'Irfk'
|
||||
want = 'long'
|
||||
|
||||
class Save_reply_record(aetools.ComponentItem):
|
||||
"""Save reply record - Result from the save operation """
|
||||
want = 'cpyR'
|
||||
class resulting_target_object(aetools.NProperty):
|
||||
"""resulting target object - a reference to the target object after it has been saved """
|
||||
which = 'rcpO'
|
||||
want = 'obj '
|
||||
class copy_type(aetools.NProperty):
|
||||
"""copy type - the way in which the target object was saved """
|
||||
which = 'rcpT'
|
||||
want = 'rcpT'
|
||||
application._propdict = {
|
||||
'version' : version,
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'driver_version' : driver_version,
|
||||
'nonejectable_mode' : nonejectable_mode,
|
||||
'save_log_file' : save_log_file,
|
||||
'use_speech' : use_speech,
|
||||
'smart_Save_As' : smart_Save_As,
|
||||
'checksum_verification' : checksum_verification,
|
||||
'signature_verification' : signature_verification,
|
||||
'exclude_DiskScripts' : exclude_DiskScripts,
|
||||
'exclude_remote_images' : exclude_remote_images,
|
||||
'image_signing' : image_signing,
|
||||
'leave_image_mounted' : leave_image_mounted,
|
||||
'erase_confirmation' : erase_confirmation,
|
||||
'zeroing' : zeroing,
|
||||
'default_create_size' : default_create_size,
|
||||
'default_create_name' : default_create_name,
|
||||
'make_multiple_floppies' : make_multiple_floppies,
|
||||
'auto_image_upon_insert' : auto_image_upon_insert,
|
||||
'eject_after_auto_image' : eject_after_auto_image,
|
||||
'auto_copy_upon_floppy_insert' : auto_copy_upon_floppy_insert,
|
||||
'volume_suffix' : volume_suffix,
|
||||
'image_suffix' : image_suffix,
|
||||
'default_file_system' : default_file_system,
|
||||
'default_image_format' : default_image_format,
|
||||
}
|
||||
application._elemdict = {
|
||||
}
|
||||
disk._propdict = {
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'locked' : locked,
|
||||
'creation_date' : creation_date,
|
||||
'modification_date' : modification_date,
|
||||
'crc32_checksum' : crc32_checksum,
|
||||
'disk_copy_4_2e_2_checksum' : disk_copy_4_2e_2_checksum,
|
||||
'block_count' : block_count,
|
||||
'file_system' : file_system,
|
||||
}
|
||||
disk._elemdict = {
|
||||
}
|
||||
folder._propdict = {
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'creation_date' : creation_date,
|
||||
'modification_date' : modification_date,
|
||||
}
|
||||
folder._elemdict = {
|
||||
}
|
||||
disk_image._propdict = {
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'locked' : locked,
|
||||
'creation_date' : creation_date,
|
||||
'modification_date' : modification_date,
|
||||
'file_format' : file_format,
|
||||
'signed' : signed,
|
||||
'compressed' : compressed,
|
||||
'segmented' : segmented,
|
||||
'segments' : segments,
|
||||
'disk_name' : disk_name,
|
||||
'crc32_checksum' : crc32_checksum,
|
||||
'disk_copy_4_2e_2_checksum' : disk_copy_4_2e_2_checksum,
|
||||
'block_count' : block_count,
|
||||
'file_system' : file_system,
|
||||
'data_fork_size' : data_fork_size,
|
||||
'resource_fork_size' : resource_fork_size,
|
||||
}
|
||||
disk_image._elemdict = {
|
||||
}
|
||||
Save_reply_record._propdict = {
|
||||
'resulting_target_object' : resulting_target_object,
|
||||
'copy_type' : copy_type,
|
||||
}
|
||||
Save_reply_record._elemdict = {
|
||||
}
|
||||
_Enum_UIAc = {
|
||||
'never_interact' : 'eNvr', # Don<6F>t allow any interaction at all
|
||||
'interact_with_self' : 'eInS', # Only allow interaction from internal events
|
||||
'interact_with_local' : 'eInL', # Allow interaction from any event originating on this machine
|
||||
'interact_with_all' : 'eInA', # Allow interaction from network events
|
||||
}
|
||||
|
||||
_Enum_SvAs = {
|
||||
'NDIF_RW' : 'RdWr', # read/write NDIF disk image
|
||||
'NDIF_RO' : 'Rdxx', # read-only NDIF disk image
|
||||
'NDIF_Compressed' : 'ROCo', # compressed NDIF disk image
|
||||
'Disk_Copy_4_2e_2' : 'DC42', # Disk Copy 4.2 disk image
|
||||
}
|
||||
|
||||
_Enum_rcpT = {
|
||||
'block_disk_copy' : 'cpBl', # block-by-block disk-level copy
|
||||
'files_and_file_ID_copy' : 'cpID', # all files including desktop databases and file ID<49>s
|
||||
'files_and_desktop_info' : 'cpDT', # all files and most desktop information
|
||||
'files_only' : 'cpFI', # all files but no desktop information
|
||||
'disk_image_conversion' : 'cpCV', # disk image format conversion
|
||||
'disk_image_creation' : 'cpCR', # disk image creation
|
||||
}
|
||||
|
||||
_Enum_long = None # XXXX enum long not found!!
|
||||
_Enum_bool = None # XXXX enum bool not found!!
|
||||
_Enum_obj_ = None # XXXX enum obj not found!!
|
||||
|
||||
#
|
||||
# Indices of types declared in this module
|
||||
#
|
||||
_classdeclarations = {
|
||||
'DImg' : disk_image,
|
||||
'capp' : application,
|
||||
'Disk' : disk,
|
||||
'Fold' : folder,
|
||||
'cpyR' : Save_reply_record,
|
||||
}
|
||||
|
||||
_propdeclarations = {
|
||||
'Xcrc' : crc32_checksum,
|
||||
'PDeS' : default_create_size,
|
||||
'Idnm' : disk_name,
|
||||
'PSSP' : smart_Save_As,
|
||||
'Pcpf' : auto_copy_upon_floppy_insert,
|
||||
'pnam' : name,
|
||||
'Isin' : signed,
|
||||
'otto' : nonejectable_mode,
|
||||
'PExD' : exclude_DiskScripts,
|
||||
'Iseg' : segmented,
|
||||
'islk' : locked,
|
||||
'asmo' : modification_date,
|
||||
'PTlk' : use_speech,
|
||||
'Pfsy' : default_file_system,
|
||||
'PVeC' : checksum_verification,
|
||||
'Xc42' : disk_copy_4_2e_2_checksum,
|
||||
'rcpO' : resulting_target_object,
|
||||
'Paim' : auto_image_upon_insert,
|
||||
'comt' : comment,
|
||||
'PCoE' : erase_confirmation,
|
||||
'dVer' : driver_version,
|
||||
'PDeN' : default_create_name,
|
||||
'PBuM' : make_multiple_floppies,
|
||||
'rcpT' : copy_type,
|
||||
'PDiE' : volume_suffix,
|
||||
'Ifmt' : file_format,
|
||||
'Pdfm' : default_image_format,
|
||||
'ascd' : creation_date,
|
||||
'Pejc' : eject_after_auto_image,
|
||||
'PZeB' : zeroing,
|
||||
'PExR' : exclude_remote_images,
|
||||
'PImE' : image_suffix,
|
||||
'PVeS' : signature_verification,
|
||||
'PSaL' : save_log_file,
|
||||
'Xblk' : block_count,
|
||||
'PMoA' : leave_image_mounted,
|
||||
'Isg#' : segments,
|
||||
'Irfk' : resource_fork_size,
|
||||
'Icom' : compressed,
|
||||
'Xfsi' : file_system,
|
||||
'Idfk' : data_fork_size,
|
||||
'vers' : version,
|
||||
'PSiI' : image_signing,
|
||||
}
|
||||
|
||||
_compdeclarations = {
|
||||
}
|
||||
|
||||
_enumdeclarations = {
|
||||
'SvAs' : _Enum_SvAs,
|
||||
'UIAc' : _Enum_UIAc,
|
||||
'rcpT' : _Enum_rcpT,
|
||||
}
|
||||
213
Mac/Demo/applescript/Disk_Copy/Utility_Events.py
Normal file
@@ -0,0 +1,213 @@
|
||||
"""Suite Utility Events: Commands that allow the user to select Disk Copy files
|
||||
Level 1, version 1
|
||||
|
||||
Generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
AETE/AEUT resource version 1/0, language 0, script 0
|
||||
"""
|
||||
|
||||
import aetools
|
||||
import MacOS
|
||||
|
||||
_code = 'ddsk'
|
||||
|
||||
class Utility_Events_Events:
|
||||
|
||||
_argmap_select_disk_image = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_disk_image(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select disk image: Prompt the user to select a disk image
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to a disk image
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL1'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_disk_image)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_DiskScript = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_DiskScript(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select DiskScript: Prompt the user to select a DiskScript
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to a DiskScript
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL2'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_DiskScript)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_disk_image_or_DiskScript = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_disk_image_or_DiskScript(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select disk image or DiskScript: Prompt the user to select a disk image or DiskScript
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to disk image or a DiskScript
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL3'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_disk_image_or_DiskScript)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_floppy_disk_image = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_floppy_disk_image(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select floppy disk image: Prompt the user to select a floppy disk image
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to a floppy disk image
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL4'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_floppy_disk_image)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_disk = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_disk(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select disk: Prompt the user to select a disk volume
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to the disk
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL5'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_disk)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_folder = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_folder(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select folder: Prompt the user to select a folder
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to the folder
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL6'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_folder)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_log = {
|
||||
'time_stamp' : 'TSMP',
|
||||
}
|
||||
|
||||
def log(self, _object, _attributes={}, **_arguments):
|
||||
"""log: Add a string to the log window
|
||||
Required argument: the string to add to the log window
|
||||
Keyword argument time_stamp: Should the log entry be time-stamped? (false if not supplied)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'LOG '
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_log)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'TSMP', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_Enum_TEXT = None # XXXX enum TEXT not found!!
|
||||
_Enum_bool = None # XXXX enum bool not found!!
|
||||
|
||||
#
|
||||
# Indices of types declared in this module
|
||||
#
|
||||
_classdeclarations = {
|
||||
}
|
||||
|
||||
_propdeclarations = {
|
||||
}
|
||||
|
||||
_compdeclarations = {
|
||||
}
|
||||
|
||||
_enumdeclarations = {
|
||||
}
|
||||
35
Mac/Demo/applescript/Disk_Copy/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
Package generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
Resource aete resid 0
|
||||
"""
|
||||
import aetools
|
||||
Error = aetools.Error
|
||||
import Standard_Suite
|
||||
import Special_Events
|
||||
import Utility_Events
|
||||
|
||||
|
||||
_code_to_module = {
|
||||
'Core' : Standard_Suite,
|
||||
'ddsk' : Special_Events,
|
||||
'ddsk' : Utility_Events,
|
||||
}
|
||||
|
||||
|
||||
|
||||
_code_to_fullname = {
|
||||
'Core' : ('Disk_Copy.Standard_Suite', 'Standard_Suite'),
|
||||
'ddsk' : ('Disk_Copy.Special_Events', 'Special_Events'),
|
||||
'ddsk' : ('Disk_Copy.Utility_Events', 'Utility_Events'),
|
||||
}
|
||||
|
||||
from Standard_Suite import *
|
||||
from Special_Events import *
|
||||
from Utility_Events import *
|
||||
|
||||
|
||||
class Disk_Copy(Standard_Suite_Events,
|
||||
Special_Events_Events,
|
||||
Utility_Events_Events,
|
||||
aetools.TalkTo):
|
||||
_signature = 'ddsk'
|
||||
15
Mac/Demo/applescript/makedisk.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import Disk_Copy
|
||||
import macfs
|
||||
import sys
|
||||
|
||||
talker = Disk_Copy.Disk_Copy(start=1)
|
||||
talker.activate()
|
||||
filespec = macfs.FSSpec('my disk image.img')
|
||||
try:
|
||||
objref = talker.create('my disk image', saving_as=filespec, leave_image_mounted=1)
|
||||
except Disk_Copy.Error, arg:
|
||||
print "ERROR: my disk image:", arg
|
||||
else:
|
||||
print 'objref=', objref
|
||||
print 'Type return to exit-'
|
||||
sys.stdin.readline()
|
||||
75
Mac/Demo/example0.html
Normal file
@@ -0,0 +1,75 @@
|
||||
<HTML><HEAD><TITLE>Using python to create Macintosh applications, part zero</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1>Using python to create Macintosh applications, part zero</H1>
|
||||
<HR>
|
||||
|
||||
This document will show you how to create a simple mac-style
|
||||
application using Python. We will glance at how to use file dialogs and
|
||||
messages. <p>
|
||||
|
||||
Our example program <a href="example0/checktext.py">checktext.py</a> asks
|
||||
the user for a text file and checks what style end-of-lines the file has.
|
||||
This may need a little explanation: ASCII text files are almost identical
|
||||
on different machines, with one exception:
|
||||
<ul>
|
||||
<li> Unix systems terminate lines with the "linefeed" character, <code>0x0a</code>,
|
||||
<li> Macintoshes terminate lines with the "carriage return" character,
|
||||
<code>0x0d</code> and
|
||||
<li> MSDOS and Windows terminate lines with first a carriage return and then a linefeed.
|
||||
</ul>
|
||||
|
||||
Let us have a look at the program. The first interesting statement in the main
|
||||
program is the call to <code>macfs.PromptGetFile</code>. This is one of the routines
|
||||
that allow you to ask the user to specify a file. You pass it one required
|
||||
argument, the prompt string. There are up to four optional MacOS <em>file type</em> arguments
|
||||
you can pass, as 4-byte strings. Specifying no file
|
||||
type will allow the user to select any file, specifying one or more types restricts
|
||||
the user to files of this type. File types are explained in most books on the Mac. <p>
|
||||
|
||||
<code>PromptGetFile</code> returns two values: an <em>FSSpec</em> object and a
|
||||
success indicator. The FSSpec object is the "official" MacOS way of specifying a
|
||||
file, more on it later. The success indicator tells you whether the user clicked OK
|
||||
or Cancel. In the event of Cancel we simply exit back to the finder. <p>
|
||||
|
||||
<code>PromptGetFile</code> has a number of friends that do similar things:
|
||||
<ul>
|
||||
<li> <code>StandardGetFile</code> is identical to <code>PromptGetFile</code> but
|
||||
without the prompt. It has up to four optional filetype arguments.
|
||||
<li> <code>StandardPutFile</code> asks the user for an output file. It will
|
||||
warn the user when she tries to overwrite an existing file. The routine has one
|
||||
mandatory argument: a prompt string. Pass the empty string if you do not want a prompt.
|
||||
<li> <code>GetDirectory</code> asks the user for a folder (or directory, in unix terms).
|
||||
It has one optional argument: a prompt string.
|
||||
</ul>
|
||||
All routines return an FSSpec and a success indicator. <p>
|
||||
|
||||
There are many things you can do with FSSpec objects (see the
|
||||
<a href="http://www.python.org/doc/lib/macfs.html">macfs</a> section in the
|
||||
<a href="http://www.python.org/doc/lib/Top.html">Python Library Reference</a>
|
||||
for details), but passing them to <code>open</code> is not
|
||||
one of them. For this, we first have to convert the FSSpec object to a pathname, with
|
||||
the <code>as_pathname</code> method. This returns a standard MacOS-style pathname with
|
||||
colon-separated components. This can then be passed to <code>open</code>. Note that
|
||||
we call open with mode parameter <code>'rb'</code>: we want to read the file in binary
|
||||
mode. Python, like C and C++, uses unix-style line endings internally and opening a
|
||||
file in text mode (<code>'r'</code>) would result in conversion of carriage-returns to
|
||||
linefeeds upon reading. This is something that Mac and DOS programmers are usually aware
|
||||
of but that never ceases to amaze unix buffs. <p>
|
||||
|
||||
After we open the file we attempt to read all data into memory. If this fails we use
|
||||
<code>EasyDialogs.Message</code> to display a message in a standard dialog box and exit.
|
||||
The EasyDialogs module has a few more useful simple dialog routines, more on that in
|
||||
<a href="example1.html">example 1</a>. <p>
|
||||
|
||||
The rest of the code is pretty straightforward: we check that the file actually contains
|
||||
data, count the number of linefeeds and returns and display a message with our guess of the
|
||||
end-of-line convention used in the file. <p>
|
||||
|
||||
The <a href="example0">example0</a> folder has three text files in Mac, Unix and DOS style
|
||||
for you to try the program on. After that, you can continue with <a href="example1.html">example 1</a>
|
||||
or go back to the <a href="index.html">index</a> to find another interesting topic. <p>
|
||||
|
||||
<HR>
|
||||
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
|
||||
<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 18-July-1996.
|
||||
</BODY></HTML>
|
||||
35
Mac/Demo/example0/checktext.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""checktext - Check that a text file has macintosh-style newlines"""
|
||||
|
||||
import sys
|
||||
import EasyDialogs
|
||||
import string
|
||||
|
||||
def main():
|
||||
pathname = EasyDialogs.AskFileForOpen(message='File to check end-of-lines in:')
|
||||
if not pathname:
|
||||
sys.exit(0)
|
||||
fp = open(pathname, 'rb')
|
||||
try:
|
||||
data = fp.read()
|
||||
except MemoryError:
|
||||
EasyDialogs.Message('Sorry, file is too big.')
|
||||
sys.exit(0)
|
||||
if len(data) == 0:
|
||||
EasyDialogs.Message('File is empty.')
|
||||
sys.exit(0)
|
||||
number_cr = string.count(data, '\r')
|
||||
number_lf = string.count(data, '\n')
|
||||
if number_cr == number_lf == 0:
|
||||
EasyDialogs.Message('File contains no lines.')
|
||||
if number_cr == 0:
|
||||
EasyDialogs.Message('File has unix-style line endings')
|
||||
elif number_lf == 0:
|
||||
EasyDialogs.Message('File has mac-style line endings')
|
||||
elif number_cr == number_lf:
|
||||
EasyDialogs.Message('File probably has MSDOS-style line endings')
|
||||
else:
|
||||
EasyDialogs.Message('File has no recognizable line endings (binary file?)')
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
193
Mac/Demo/example1.html
Normal file
@@ -0,0 +1,193 @@
|
||||
<HTML><HEAD><TITLE>Using python to create Macintosh applications, part one</TITLE></HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>Using python to create Macintosh applications, part one</H1>
|
||||
<HR>
|
||||
|
||||
This document will show you how to create a simple mac-style
|
||||
application using Python. We will glance at how to use dialogs and
|
||||
resources. <p>
|
||||
|
||||
The example application we look at will be a simple program with a
|
||||
dialog that allows you to perform domain name lookups on IP addresses
|
||||
and hostnames.
|
||||
The <A HREF="example1/dnslookup-1.py">source code</A> and
|
||||
<A HREF="example1/dnslookup-1.rsrc">resource file</A>
|
||||
for this application are available in the <A
|
||||
HREF="example1">example1</A> folder (which you will have to download
|
||||
if you are reading this document over the net and if you want to look
|
||||
at the resources). <p>
|
||||
|
||||
We will use the builtin module "socket" that allows a
|
||||
Python program to perform all sorts of networking functions, and we
|
||||
will create the user interface around that. You should be able to run
|
||||
the sample code with the standard Python distribution.<p>
|
||||
|
||||
<CITE>
|
||||
If you are interested in building your own extensions to python you
|
||||
should check out the companion document <A
|
||||
HREF="plugins.html">Creating Macintosh Python C extensions</A>,
|
||||
which tells you how to build your own C extension.
|
||||
<p>
|
||||
</CITE>
|
||||
|
||||
<H2><A NAME="dialog-resources">Creating dialog resources</A></H2>
|
||||
|
||||
Let us start with the creative bit: building the dialogs and creating
|
||||
an icon for our program. For this you need ResEdit, and a reasonable
|
||||
working knowledge of how to use it. "Inside Mac" or various books on
|
||||
macintosh programming will help here. <p>
|
||||
|
||||
There is one fine point that deserves to be mentioned here: <A
|
||||
NAME="resource-numbering">resource numbering</A>. Because often your
|
||||
resources will be combined with those that the Python interpreter and
|
||||
various standard modules need you should give your DLOG and DITL
|
||||
resources numbers above 512. 128 and below are reserved for Apple,
|
||||
128-228 are for extensions like Tk,
|
||||
228-255 for the Python interpreter and 256-511 for standard
|
||||
modules. If you are writing a module that you will be distributing for
|
||||
inclusion in other people's programs you may want to register a number
|
||||
in the 256-511 range, contact Guido or myself or whoever you think is
|
||||
"in charge" of Python for the Macintosh at the moment. Even though the
|
||||
application we are writing at the moment will keep its resources in a
|
||||
separate resource file it is still a good idea to make sure that no
|
||||
conflicts arise: once you have opened your resource file any attempt
|
||||
by the interpreter to open a dialog will also search your resource
|
||||
file. <p>
|
||||
|
||||
Okay, let's have a look at dnslookup-1.rsrc, our resource file.
|
||||
The DLOG and accompanying DITL resource both have number 512. Since
|
||||
ResEdit creates both with default ID=128 you should take care to
|
||||
change the number on both. The dialog itself is pretty basic: two
|
||||
buttons (Lookup and Quit), two labels and
|
||||
two text entry areas, one of which is used for output only. Here's what
|
||||
the dialog will look like at run time<p>
|
||||
<div align=center>
|
||||
<img width=324 height=189 src="example1/dnslookup-1.gif" alt="dialog image">
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<H2><A NAME="modal-dialog">An application with a modal dialog</A></H2>
|
||||
|
||||
Next, we will have to write the actual application. For this example,
|
||||
we will use a modal dialog. This means that we will put up the dialog
|
||||
and go into a loop asking the dialog manager for events (buttons
|
||||
pushed). We handle the actions requested by the user until the Quit
|
||||
button is pressed, upon which we exit our loop (and the program). This
|
||||
way of structuring your program is actually rather antisocial, since
|
||||
you force the user to do whatever you, the application writer, happen
|
||||
to want. A modal dialog leaves no way of escape whatsoever (except
|
||||
command-option-escape), and is usually not a good way to structure
|
||||
anything but the most simple questions. Even then: how often have you
|
||||
been confronted with a dialog asking a question that you could not
|
||||
answer because the data you needed was obscured by the dialog itself?
|
||||
In the next example we will look at an application that does pretty
|
||||
much the same as this one but in a more user-friendly way. <p>
|
||||
|
||||
The code itself is contained in the file <A
|
||||
HREF="example1/dnslookup-1.py"> dnslookup-1.py</A>. Have
|
||||
a copy handy before you read on. The file starts off with a
|
||||
textstring giving a short description. Not many tools do anything with
|
||||
this as yet, but at some point in the future we <EM>will</EM> have all
|
||||
sorts of nifty class browser that will display this string, so just
|
||||
include it. Just put a short description at the start of each module,
|
||||
class, method and function. After the initial description and some
|
||||
comments, we import the modules we need. <p>
|
||||
|
||||
<A NAME="easydialogs"><CODE>EasyDialogs</CODE></A> is a handy standard
|
||||
module that provides you with routines that put up common text-only
|
||||
modal dialogs:
|
||||
<UL>
|
||||
<LI> <CODE>Message(str)</CODE>
|
||||
displays the message "str" and an OK button,
|
||||
<LI> <CODE>AskString(prompt, default)</CODE>
|
||||
asks for a string, displays OK and Cancel buttons,
|
||||
<LI> <CODE>AskYesNoCancel(question, default)</CODE>
|
||||
displays a question and Yes, No and Cancel buttons.
|
||||
</UL>
|
||||
|
||||
<A NAME="res"><CODE>Res</CODE></A> is a pretty complete interface to
|
||||
the MacOS Resource Manager, described fully in Inside Mac. There is
|
||||
currently no documentation of it, but the Apple documentation (or
|
||||
Think Ref) will help you on your way if you remember two points:
|
||||
<UL>
|
||||
<LI> Resources are implemented as Python objects, and each routine
|
||||
with a resource first argument is implemented as a python method.
|
||||
<LI> When in doubt about the arguments examine the routines docstring,
|
||||
as in <CODE>print Res.OpenResFile.__doc__</CODE>
|
||||
</UL>
|
||||
|
||||
Similarly, <A NAME="dlg"><CODE>Dlg</CODE></A> is an interface to the
|
||||
Dialog manager (with Dialogs being implemented as python objects and
|
||||
routines with Dialog arguments being methods). The sys module you
|
||||
know, I hope. The string module is an often used module that enables
|
||||
you to perform many string related operations. In this case however, we
|
||||
are only using the "digits" constant from the string module. We could
|
||||
have simply defined "digits" as "0123456789". The socket module enables
|
||||
us to perform the domain name lookups. We
|
||||
use two calls from it:
|
||||
<UL>
|
||||
<LI> <CODE>gethostbyaddr()</CODE>
|
||||
returns the hostname associated with an IP address
|
||||
<LI> <CODE>gethostbyname()</CODE>
|
||||
returns the IP address associated with a hostname
|
||||
</UL>
|
||||
|
||||
Next in the source file we get definitions for our dialog resource
|
||||
number and for the item numbers in our dialog. These should match the
|
||||
situation in our resource file dnslookup-1.rsrc,
|
||||
obviously.<p>
|
||||
|
||||
On to the main program. We start off with opening our resource file,
|
||||
which should live in the same folder as the python source. If we
|
||||
cannot open it we use <CODE>EasyDialogs</CODE> to print a message and
|
||||
exit. You can try it: just move the resource file somewhere else for a
|
||||
moment. Then we call do_dialog() to do the real work. <p>
|
||||
|
||||
<CODE>Do_dialog()</CODE> uses <CODE>Dlg.GetNewDialog()</CODE> to open
|
||||
a dialog window initialized from 'DLOG' resource ID_MAIN and putting
|
||||
it on screen in the frontmost position. Next, we go into a loop,
|
||||
calling <CODE>Dlg.ModalDialog()</CODE> to wait for the next user
|
||||
action. <CODE>ModalDialog()</CODE> will return us the item number that
|
||||
the user has clicked on (or otherwise activated). It will handle a few
|
||||
slightly more complicated things also, like the user typing into
|
||||
simple textfields, but it will <EM>not</EM> do things like updating
|
||||
the physical appearance of radio buttons, etc. See Inside Mac or
|
||||
another programming guide for how to handle this
|
||||
yourself. Fortunately, our simple application doesn't have to bother with this,
|
||||
since buttons and textfields are the only active elements we have. So, we do a
|
||||
simple switch on item number and call the appropriate routine to implement the
|
||||
action requested. Upon the user pressing "Quit" we simply leave the loop and,
|
||||
hence, <CODE>do_dialog()</CODE>. This will cause the python dialog object
|
||||
<CODE>my_dlg</CODE> to be deleted and the on-screen dialog to disappear. <p>
|
||||
|
||||
<A NAME="dialog-warning">Time for a warning</A>: be very careful what
|
||||
you do as long as a dialog is on-screen. Printing something, for
|
||||
instance, may suddenly cause the standard output window to appear over
|
||||
the dialog, and since we took no measures to redraw the dialog it will
|
||||
become very difficult to get out of the dialog. Also, command-period
|
||||
may or may not work in this situation. I have also seen crashes in
|
||||
such a situation, probably due to the multiple event loops involved or
|
||||
some oversight in the interpreter. You have been warned. <p>
|
||||
|
||||
The implementation of the "Lookup" command can use a bit more
|
||||
explaining: we get the necessary information with <CODE>dnslookup()</CODE>
|
||||
but now we have to update the on-screen dialog to present this
|
||||
information to the user. The <CODE>GetDialogItem()</CODE> method of
|
||||
the dialog returns three bits of information about the given item: its
|
||||
type, its data handle and its rect (the on-screen <CODE>x,y,w,h</CODE>
|
||||
coordinates). We are only interested in the data handle here, on which
|
||||
we call <CODE>SetDialogItemText()</CODE> to set our new text. Note
|
||||
here that python programmers need not bother with the C-string versus
|
||||
pascal-string controversy: the python glue module knows what is needed
|
||||
and converts the python string to the correct type. <p>
|
||||
|
||||
And that concludes our first example of the use of resources and
|
||||
dialogs. Next, you could have a look at the source of EasyDialogs for
|
||||
some examples of using input fields and filterprocs. Or, go on with
|
||||
reading the <A HREF="example2.html">second part</A> of this document
|
||||
to see how to implement a better version of this application.<p>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
Mac/Demo/example1/dnslookup-1.gif
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
55
Mac/Demo/example1/dnslookup-1.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""Sample program performing domain name lookups and showing off EasyDialogs,
|
||||
Res and Dlg in the process"""
|
||||
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Dlg
|
||||
import socket
|
||||
import string
|
||||
import macresource
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
|
||||
ITEM_LOOKUP_ENTRY=1
|
||||
ITEM_RESULT=2
|
||||
ITEM_LOOKUP_BUTTON=3
|
||||
ITEM_QUIT_BUTTON=4
|
||||
|
||||
def main():
|
||||
"""Main routine: open resource file, call dialog handler"""
|
||||
macresource.need("DLOG", ID_MAIN, "dnslookup-1.rsrc")
|
||||
do_dialog()
|
||||
|
||||
def do_dialog():
|
||||
"""Post dialog and handle user interaction until quit"""
|
||||
my_dlg = Dlg.GetNewDialog(ID_MAIN, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == ITEM_LOOKUP_BUTTON:
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_LOOKUP_ENTRY)
|
||||
txt = Dlg.GetDialogItemText(h)
|
||||
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_RESULT)
|
||||
Dlg.SetDialogItemText(h, dnslookup(txt))
|
||||
elif n == ITEM_QUIT_BUTTON:
|
||||
break
|
||||
|
||||
def dnslookup(str):
|
||||
""" Perform DNS lookup on str. If first character of digit is numeric,
|
||||
assume that str contains an IP address. Otherwise, assume that str
|
||||
contains a hostname."""
|
||||
if str == '': str = ' '
|
||||
if str[0] in string.digits:
|
||||
try:
|
||||
value = socket.gethostbyaddr(str)[0]
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
else:
|
||||
try:
|
||||
value = socket.gethostbyname(str)
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
return value
|
||||
|
||||
main()
|
||||
BIN
Mac/Demo/example1/dnslookup-1.rsrc
Normal file
162
Mac/Demo/example2.html
Normal file
@@ -0,0 +1,162 @@
|
||||
<HTML><HEAD><TITLE>Using python to create Macintosh applications, part two</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1>Using python to create Macintosh applications, part two</H1>
|
||||
<HR>
|
||||
|
||||
In this document we rewrite the application of the <A
|
||||
HREF="example1.html">previous example</A> to use modeless dialogs. We
|
||||
will use an application framework, and we will have a look at creating
|
||||
applets, standalone applications written in Python. The <A
|
||||
HREF="example2/dnslookup-2.py">source code</A> and
|
||||
<A HREF="example2/dnslookup-2.rsrc">resource file</A> are available in the folder
|
||||
<A HREF="example2">example2</A>. <p>
|
||||
|
||||
Again, we start with ResEdit to create our dialogs. Not only do we
|
||||
want a main dialog this time but also an "About" dialog. This example is less
|
||||
than complete since we do not provide a <A NAME="bundle">BNDL resource</A>
|
||||
and related stuff that an application cannot be without. We are able to do this
|
||||
when building a python applet since BuildApplet will substitute default resources
|
||||
for BNDL, etc. when none are supplied (<A HREF="#no-bundle">See below</A>.)
|
||||
"Inside Mac" or various
|
||||
books on Macintosh programming will help here. Also, you can refer to
|
||||
the resource files provided in the Python source distribution for some
|
||||
of the python-specific points of BNDL programming: the
|
||||
"appletbundle.rsrc" file is what is used for creating applets if you
|
||||
don't provide your own resource file. <p>
|
||||
|
||||
When creating your own BNDL resouorces, keep in mind that the Finder gets
|
||||
confused if you have more than one application with the same signature. This may be due
|
||||
to some incorrectness on the side of "BuildApplet", I am not sure. There is one
|
||||
case when you definitely need a unique signature: when you create an applet that
|
||||
has its own data files and you want the user to be able to start your
|
||||
applet by double-clicking one of the datafiles. <p>
|
||||
|
||||
Let's have a look at dnslookup-2.rsrc, our resource file. Dialog 512 is the
|
||||
main window which has one button (Lookup), two labels and
|
||||
two text entry areas, one of which is used for output only. The "Quit"
|
||||
button has disappeared, because its function is handled by a menu choice. Here's
|
||||
what it will look like at run time:<p>
|
||||
<div align=center>
|
||||
<img width=324 height=205 src="example2/dnslookup-2.gif" alt="dialog image">
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<H2>A modeless dialog application using FrameWork</H2>
|
||||
|
||||
On to the source code in <A
|
||||
HREF="example2/dnslookup-2.py">dnslookup-2.py</A>. The
|
||||
start is similar to our previous example program <A
|
||||
HREF="example1/dnslookup-1.py">dnslookup-1.py</A>, with
|
||||
one extra module being imported. To make life more simple we will use
|
||||
the <CODE>FrameWork</CODE> module, a nifty piece of code that handles
|
||||
all the gory Mac details of event loop programming, menubar
|
||||
installation and all the other code that is the same for every Mac
|
||||
program in the world. Like most standard modules, FrameWork will run
|
||||
some sample test code when you invoke it as a main program, so try it
|
||||
now. It will create a menu bar with an Apple menu with the about box
|
||||
and a "File" menu with some pythonesque choices (which do nothing
|
||||
interesting, by the way) and a "Quit" command that works. <p>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If you have not used <code>FrameWork</code> before you may want to
|
||||
first take a look at the <A HREF="textedit.html">Pathetic EDitor</A>
|
||||
example, which builds a minimal text editor using FrameWork and TextEdit.
|
||||
On the other hand: we don't use many features of FrameWork, so you could
|
||||
also continue with this document.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
After the imports we get the definitions of resource-IDs in our
|
||||
resource file, slightly changed from the previous version of our
|
||||
program. The main program is also
|
||||
similar to our previous version, with one important exception: we
|
||||
first check to see whether our resource is available before opening
|
||||
the resource file. Why is this? Because later, when we will have
|
||||
converted the script to an applet, our resources will be available in
|
||||
the applet file and we don't need the separate resource file
|
||||
anymore. <p>
|
||||
|
||||
Next comes the definition of our main class,
|
||||
<CODE>DNSLookup</CODE>, which inherits
|
||||
<CODE>FrameWork.Application</CODE>. The Application class handles the
|
||||
menu bar and the main event loop and event dispatching. In the
|
||||
<CODE>__init__</CODE> routine we first let the base class initialize
|
||||
itself, then we create our modeless dialog and finally we jump into
|
||||
the main loop. The main loop continues until we call <CODE>self._quit</CODE>,
|
||||
which we will do when the user selects "Quit". When we create
|
||||
the instance of <CODE>MyDialog</CODE> (which inherits
|
||||
<CODE>DialogWindow</CODE>, which inherits <CODE>Window</CODE>) we pass
|
||||
a reference to the application object, this reference is used to tell
|
||||
Application about our new window. This enables the event loop to keep
|
||||
track of all windows and dispatch things like update events and mouse
|
||||
clicks. <p>
|
||||
|
||||
The <CODE>makeusermenus()</CODE> method (which is called sometime
|
||||
during the Application <CODE>__init__</CODE> routine) creates a File
|
||||
menu with a Quit command (shortcut command-Q), which will callback to
|
||||
our quit() method. <CODE>Quit()</CODE>, in turn, calls <CODE>_quit</CODE> which
|
||||
causes the mainloop to terminate at a convenient time. <p>
|
||||
|
||||
Application provides a standard about box, but we override this by
|
||||
providing our own <CODE>do_about()</CODE> method which shows an about
|
||||
box from a resource as a modal dialog. This piece of code should look
|
||||
familiar to you from the previous example program. That do_about is
|
||||
called when the user selects About from the Apple menu is, again,
|
||||
taken care of by the __init__ routine of Application. <p>
|
||||
|
||||
The <CODE>MyDialog</CODE> class is the container for our main
|
||||
window. Initialization is again done by first calling the base class
|
||||
<CODE>__init__</CODE> function and finally setting the local variable
|
||||
"parent." <p>
|
||||
|
||||
<CODE>Do_itemhit()</CODE> is called when an item is selected in this
|
||||
dialog by the user. We are passed the item number (and the original
|
||||
event structure, which we normally ignore). The code is similar to the
|
||||
main loop of our previous example program: a switch depending on the
|
||||
item selected. <CODE>Dnslookup()</CODE> is quite similar to our previous
|
||||
example. <p>
|
||||
|
||||
<H2><IMG SRC="html.icons/mkapplet.gif"><A NAME="applets">Creating applets</A></H2>
|
||||
|
||||
Now let us try to turn the python script into an applet, a standalone
|
||||
application. This will <em>not</em> work if you have the "classic 68k"
|
||||
Python distribution, only if you have the cfm68k or PPC distribution.
|
||||
|
||||
<blockquote>
|
||||
Actually, "standalone" is probably not the correct term here, since an
|
||||
applet does still depend on a lot of the python environment: the
|
||||
PythonCore shared library, the Python Preferences file, the python Lib
|
||||
folder and any other modules that the main module depends on. It is
|
||||
possible to get rid of all these dependencies and create true standalone
|
||||
applications in Python, but this is a bit difficult. See <a href="freezing.html">
|
||||
Standalone Applications in Python</a> for details. For this
|
||||
document, by standalone we mean here that
|
||||
the script has the look-and-feel of an application, including the
|
||||
ability to have its own document types, be droppable, etc.
|
||||
</blockquote>
|
||||
|
||||
The easiest way to create an applet is to take your source file and
|
||||
drop it onto "BuildApplet", located in the Python home
|
||||
folder. This will create an applet with the same name as your python
|
||||
source with the ".py" stripped. Also, if a resource file with the same
|
||||
name as your source but with ".rsrc" extension is available the
|
||||
resources from that file will be copied to your applet too. If there
|
||||
is no resource file for your script a set of default resources will be
|
||||
used, and the applet will have the default creator 'Pyt0'. The latter
|
||||
also happens if you do have a resource file but without the BNDL
|
||||
combo. <A NAME="no-bundle">Actually</A>, as in the present example.
|
||||
<p>
|
||||
|
||||
If you need slightly more control over the BuildApplet process you can
|
||||
double-click it, and you will get dialogs for source and
|
||||
destination of the applet. The rest of the process, including locating
|
||||
the resource file, remains the same. <p>
|
||||
|
||||
Note that though our example application completely bypasses the
|
||||
normal python user interface this is by no means necessary. Any python
|
||||
script can be turned into an applet, and all the usual features of the
|
||||
interpreter still work. <p>
|
||||
|
||||
That's all for this example, you may now return to the <A HREF="index.html">
|
||||
table of contents</A> to pick another topic. <p>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
Mac/Demo/example2/dnslookup-2.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
85
Mac/Demo/example2/dnslookup-2.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Dlg
|
||||
import socket
|
||||
import string
|
||||
import macresource
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
ID_ABOUT=513
|
||||
|
||||
ITEM_LOOKUP_ENTRY=1
|
||||
ITEM_RESULT=2
|
||||
ITEM_LOOKUP_BUTTON=3
|
||||
|
||||
def main():
|
||||
macresource.need("DLOG", ID_MAIN, "dnslookup-2.rsrc")
|
||||
DNSLookup()
|
||||
|
||||
class DNSLookup(FrameWork.Application):
|
||||
"Application class for DNS Lookup"
|
||||
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
self.main_dialog.open(ID_MAIN)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def do_about(self, *args):
|
||||
f = Dlg.GetNewDialog(ID_ABOUT, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == 1:
|
||||
return
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for DNSLookup"
|
||||
def __init__(self, parent):
|
||||
FrameWork.DialogWindow.__init__(self, parent)
|
||||
self.parent = parent
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == ITEM_LOOKUP_BUTTON:
|
||||
self.dolookup()
|
||||
|
||||
def dolookup(self):
|
||||
"""Get text entered in the lookup entry area. Place result of the
|
||||
call to dnslookup in the result entry area."""
|
||||
tp, h, rect = self.dlg.GetDialogItem(ITEM_LOOKUP_ENTRY)
|
||||
txt = Dlg.GetDialogItemText(h)
|
||||
|
||||
tp, h, rect = self.dlg.GetDialogItem(ITEM_RESULT)
|
||||
Dlg.SetDialogItemText(h, self.dnslookup(txt))
|
||||
|
||||
def dnslookup(self, str):
|
||||
""" Perform DNS lookup on str. If first character of digit is numeric,
|
||||
assume that str contains an IP address. Otherwise, assume that str
|
||||
contains a hostname."""
|
||||
if str == '': str = ' '
|
||||
if str[0] in string.digits:
|
||||
try:
|
||||
value = socket.gethostbyaddr(str)[0]
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
else:
|
||||
try:
|
||||
value = socket.gethostbyname(str)
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
return value
|
||||
|
||||
|
||||
main()
|
||||
BIN
Mac/Demo/example2/dnslookup-2.rsrc
Normal file
BIN
Mac/Demo/html.icons/createmake.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
Mac/Demo/html.icons/mkapplet.gif
Normal file
|
After Width: | Height: | Size: 1010 B |
BIN
Mac/Demo/html.icons/options.gif
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
Mac/Demo/html.icons/preferences.gif
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
Mac/Demo/html.icons/python.gif
Normal file
|
After Width: | Height: | Size: 1004 B |
115
Mac/Demo/imgbrowse/imgbrowse.py
Normal file
@@ -0,0 +1,115 @@
|
||||
"""imgbrowse - Display pictures using img"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import QuickDraw
|
||||
from Carbon import Win
|
||||
#ifrom Carbon mport List
|
||||
import struct
|
||||
import img
|
||||
import imgformat
|
||||
import mac_image
|
||||
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=64
|
||||
MINHEIGHT=64
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
|
||||
def main():
|
||||
print 'hello world'
|
||||
imgbrowse()
|
||||
|
||||
class imgbrowse(FrameWork.Application):
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
self.lastwin = None
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.openitem = FrameWork.MenuItem(m, "Open...", "O", self.opendoc)
|
||||
self.infoitem = FrameWork.MenuItem(m, "Info", "I", self.info)
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def opendoc(self, *args):
|
||||
pathname = EasyDialogs.AskFileForOpen() # Any file type
|
||||
if not pathname:
|
||||
return
|
||||
bar = EasyDialogs.ProgressBar('Reading and converting...')
|
||||
try:
|
||||
rdr = img.reader(imgformat.macrgb16, pathname)
|
||||
except img.error, arg:
|
||||
EasyDialogs.Message(repr(arg))
|
||||
return
|
||||
w, h = rdr.width, rdr.height
|
||||
bar.set(10)
|
||||
data = rdr.read()
|
||||
del bar
|
||||
pixmap = mac_image.mkpixmap(w, h, imgformat.macrgb16, data)
|
||||
self.showimg(w, h, pixmap, data)
|
||||
|
||||
def showimg(self, w, h, pixmap, data):
|
||||
win = imgwindow(self)
|
||||
win.open(w, h, pixmap, data)
|
||||
self.lastwin = win
|
||||
|
||||
def info(self, *args):
|
||||
if self.lastwin:
|
||||
self.lastwin.info()
|
||||
|
||||
class imgwindow(FrameWork.Window):
|
||||
def open(self, width, height, pixmap, data):
|
||||
self.pixmap = pixmap
|
||||
self.data = data
|
||||
self.pictrect = (0, 0, width, height)
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewCWindow(bounds, "Picture", 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
pass
|
||||
currect = self.fitrect()
|
||||
print 'PICT:', self.pictrect
|
||||
print 'WIND:', currect
|
||||
print 'ARGS:', (self.pixmap, self.wid.GetWindowPort().GetPortBitMapForCopyBits(), self.pictrect,
|
||||
currect, QuickDraw.srcCopy, None)
|
||||
self.info()
|
||||
Qd.CopyBits(self.pixmap, self.wid.GetWindowPort().GetPortBitMapForCopyBits(), self.pictrect,
|
||||
currect, QuickDraw.srcCopy, None)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.wid.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
def info(self):
|
||||
graf = self.wid.GetWindowPort()
|
||||
bits = graf.GetPortBitMapForCopyBits()
|
||||
mac_image.dumppixmap(bits.pixmap_data)
|
||||
|
||||
main()
|
||||
55
Mac/Demo/imgbrowse/mac_image.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""mac_image - Helper routines (hacks) for images"""
|
||||
import imgformat
|
||||
from Carbon import Qd
|
||||
import struct
|
||||
import MacOS
|
||||
|
||||
_fmt_to_mac = {
|
||||
imgformat.macrgb16 : (16, 16, 3, 5),
|
||||
}
|
||||
|
||||
def mkpixmap(w, h, fmt, data):
|
||||
"""kludge a pixmap together"""
|
||||
fmtinfo = _fmt_to_mac[fmt]
|
||||
|
||||
rv = struct.pack("lHhhhhhhlllhhhhlll",
|
||||
id(data)+MacOS.string_id_to_buffer, # HACK HACK!!
|
||||
w*2 + 0x8000,
|
||||
0, 0, h, w,
|
||||
0,
|
||||
0, 0, # XXXX?
|
||||
72<<16, 72<<16,
|
||||
fmtinfo[0], fmtinfo[1],
|
||||
fmtinfo[2], fmtinfo[3],
|
||||
0, 0, 0)
|
||||
## print 'Our pixmap, size %d:'%len(rv)
|
||||
## dumppixmap(rv)
|
||||
return Qd.RawBitMap(rv)
|
||||
|
||||
def dumppixmap(data):
|
||||
baseAddr, \
|
||||
rowBytes, \
|
||||
t, l, b, r, \
|
||||
pmVersion, \
|
||||
packType, packSize, \
|
||||
hRes, vRes, \
|
||||
pixelType, pixelSize, \
|
||||
cmpCount, cmpSize, \
|
||||
planeBytes, pmTable, pmReserved \
|
||||
= struct.unpack("lhhhhhhhlllhhhhlll", data)
|
||||
print 'Base: 0x%x'%baseAddr
|
||||
print 'rowBytes: %d (0x%x)'%(rowBytes&0x3fff, rowBytes)
|
||||
print 'rect: %d, %d, %d, %d'%(t, l, b, r)
|
||||
print 'pmVersion: 0x%x'%pmVersion
|
||||
print 'packing: %d %d'%(packType, packSize)
|
||||
print 'resolution: %f x %f'%(float(hRes)/0x10000, float(vRes)/0x10000)
|
||||
print 'pixeltype: %d, size %d'%(pixelType, pixelSize)
|
||||
print 'components: %d, size %d'%(cmpCount, cmpSize)
|
||||
print 'planeBytes: %d (0x%x)'%(planeBytes, planeBytes)
|
||||
print 'pmTable: 0x%x'%pmTable
|
||||
print 'pmReserved: 0x%x'%pmReserved
|
||||
for i in range(0, len(data), 16):
|
||||
for j in range(16):
|
||||
if i + j < len(data):
|
||||
print '%02.2x'%ord(data[i+j]),
|
||||
print
|
||||
156
Mac/Demo/index.html
Normal file
@@ -0,0 +1,156 @@
|
||||
<HTML><HEAD><TITLE>Macintosh Python crash course</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1><IMG SRC="html.icons/python.gif">Macintosh Python crash course</H1>
|
||||
<HR>
|
||||
|
||||
<p>This set of documents provides an introduction to various aspects of
|
||||
Python programming on the Mac. It is assumed that the reader is
|
||||
already familiar with Python and, to some extent, with MacOS Toolbox
|
||||
programming. Other readers may find something interesting here too,
|
||||
your mileage may vary. </p>
|
||||
|
||||
<p>As the previous paragraph reveals to the careful observer these examples
|
||||
are dated, most of them were writting before OSX and haven't been updated
|
||||
afterwards. They still show how to use the Carbon wrappers but aren't
|
||||
necessarily the best way to use the Carbon API's in OSX.</p>
|
||||
|
||||
Another set of Macintosh-savvy examples, more aimed at beginners, is
|
||||
maintained by Joseph Strout, at Python Tidbits in <A
|
||||
HREF="http://www.strout.net/python/">
|
||||
http://www.strout.net/python/</A>.
|
||||
<P>
|
||||
|
||||
The <a href="http://www.python.org/doc/lib/Top.html">Python Library
|
||||
Reference</a> contains a section on <a
|
||||
href="http://www.python.org/doc/lib/Macintosh-Specific-Services.html">Macintosh-specific
|
||||
modules</a> that you should also read. Documentation is also available
|
||||
in PostScript and other forms, see the <a
|
||||
href="http://www.python.org/doc/">documentation</a> section on the
|
||||
webserver. <p>
|
||||
|
||||
<p>The W widget set by Just van Rossum, does not have complete documentation as
|
||||
of this writing, but Corran Webster has documented most of it on his
|
||||
<A HREF="http://www.nevada.edu/~cwebster/Python/">Python Page</A>.</p>
|
||||
|
||||
There are also some documentation links, as well as other MacPython-related
|
||||
pages, in the
|
||||
<A HREF="http://dmoz.org/Computers/Systems/Macintosh/Development/Scripting/Python/">
|
||||
Open Directory</A>.
|
||||
|
||||
|
||||
<H2>Table of contents</H2>
|
||||
|
||||
<blockquote><B>Note:</B>
|
||||
Some of these documents were actually written a long time ago and have seen
|
||||
little maintainance, so use with care. </blockquote>
|
||||
<UL>
|
||||
<LI>
|
||||
<A HREF="example0.html">Using python to create Macintosh applications,
|
||||
part zero</A> whets your appetite by showing you how to ask the user
|
||||
for a filename, and how to display a message. It explains about end-of-line
|
||||
confusion while doing so.
|
||||
|
||||
<LI>
|
||||
<A HREF="example1.html">Using python to create Macintosh applications,
|
||||
part one</A> explains how to create a simple modal-dialog application
|
||||
in Python. It also takes a glance at using the toolbox modules Res and
|
||||
Dlg, and EasyDialogs for simple question-dialogs.
|
||||
|
||||
<LI>
|
||||
<A HREF="example2.html">Using python to create Macintosh applications,
|
||||
part two</A> turns the previous example program into a more complete
|
||||
mac application, using a modeless dialog, menus, etc. It also explains
|
||||
how to create applets, standalone applications written in Python.
|
||||
|
||||
<LI>
|
||||
<A HREF="freezing.html">Freezing Python programs</A> extends on this concept,
|
||||
and shows you how to create applications that can be used on machines without
|
||||
a full Python installed. This one is probably best skipped on first contact
|
||||
with MacPython.
|
||||
|
||||
<LI>
|
||||
<A HREF="textedit.html">Using FrameWork and TextEdit</A> shows you
|
||||
how to use <code>FrameWork</code> application framework and the
|
||||
<code>TextEdit</code> toolbox to build a text editor.
|
||||
|
||||
<LI>
|
||||
<A HREF="plugins.html">Creating a C extension module on the Macintosh</A>
|
||||
is meant for the hardcore programmer, and shows how to create an
|
||||
extension module in C. It also handles using Modulator to create the
|
||||
boilerplate for your module, and creating dynamically-loadable modules
|
||||
on PowerPC Macs. It assumes you use CodeWarrior for you development.
|
||||
|
||||
<LI>
|
||||
<A HREF="mpwextensions.html">Creating C extension modules using MPW</A>
|
||||
is a companion document, written by Corran Webster, which explains how you
|
||||
can develop Python extensions using Apple's free MPW compiler environment.
|
||||
|
||||
<LI>
|
||||
<A HREF="applescript.html">Using Open Scripting Architecture from Python</A> explains
|
||||
how to create a Python module interfacing to a scriptable application,
|
||||
and how to use that module in your python program.
|
||||
|
||||
<LI>
|
||||
<A HREF="cgi.html">Using python to create CGI scripts</A> is a preliminary
|
||||
introduction to writing CGI scripts in Python and to writing scriptable applications
|
||||
in Python.
|
||||
|
||||
<LI>
|
||||
<A HREF="building.html">Building Mac Python from source</A> explains
|
||||
how to build a PPC or 68K interpreter from a source distribution.
|
||||
|
||||
<LI>
|
||||
<A HREF="embed.html">Embedding Python on the Mac</A> is a minimal example of
|
||||
how to embed Python in other Mac applications.
|
||||
|
||||
</UL>
|
||||
|
||||
The Python distribution contains a few more examples, all unexplained:
|
||||
<UL>
|
||||
<LI>
|
||||
<I>PICTbrowse</I> is an application that locates PICT
|
||||
resources and displays them, it demonstrates some quickdraw and the
|
||||
resource and list managers. In the same folder you will find the very
|
||||
similar scripts ICONbrowse and cicnbrowse. oldPICTbrowse is the same program
|
||||
but form the pre-Appearance era, it uses a dialog with a user item and
|
||||
creates and manages its own List object.
|
||||
|
||||
<LI>
|
||||
<I>Imgbrowse</I> displays image files in
|
||||
many different formats (gif, tiff, pbm, etc). It shows how to use the
|
||||
img modules on the mac.
|
||||
|
||||
<LI>
|
||||
<I>Quicktime</I> has the standard <code>MovieInWindow</code> and
|
||||
<code>VerySimplePlayer</code> examples, re-coded in Python.
|
||||
|
||||
<LI>
|
||||
<I>Resources</I>, <I>Sound</I> and <I>Speech</I> have some examples
|
||||
on using the respective managers. In the <i>Mac:Lib</i> folder you
|
||||
will also find modules that do useful things with the Communications
|
||||
Toolbox, the Finder interface, etc.
|
||||
|
||||
<LI>
|
||||
<I>Printing</I> has an example on using the Printing module to, you guessed
|
||||
it, print from Python. The code is somewhat self-documenting. Donated
|
||||
by Just van Rossum, who also donated the Printing module itself.
|
||||
</UL>
|
||||
|
||||
At some point in the (possibly distant) future, I will add chapters on
|
||||
how to use bgen to create modules completely automatic and how to make
|
||||
your Python program scriptable, but that will have to wait. <p>
|
||||
|
||||
<HR>
|
||||
|
||||
Please let me know if you miss critical information in this
|
||||
document. I am quite sure that I will never find the time to turn it
|
||||
into a complete MacPython programmers guide (which would probably be a
|
||||
400-page book instead of 10 lousy html-files), but it should contain
|
||||
at least the information that is neither in the standard Python
|
||||
documentation nor in Inside Mac or other Mac programmers
|
||||
documentation. <p>
|
||||
|
||||
<HR>
|
||||
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
|
||||
<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 22-Apr-00.
|
||||
</BODY></HTML>
|
||||
374
Mac/Demo/mlte/mlted.py
Normal file
@@ -0,0 +1,374 @@
|
||||
# A minimal text editor using MLTE. Based on wed.py.
|
||||
#
|
||||
# To be done:
|
||||
# - Functionality: find, etc.
|
||||
|
||||
from Menu import DrawMenuBar
|
||||
from FrameWork import *
|
||||
from Carbon import Win
|
||||
from Carbon import Ctl
|
||||
from Carbon import Qd
|
||||
from Carbon import Res
|
||||
from Carbon import Scrap
|
||||
import os
|
||||
from Carbon import MacTextEditor
|
||||
from Carbon import Mlte
|
||||
|
||||
UNDOLABELS = [ # Indexed by MLTECanUndo() value
|
||||
"Typing", "Cut", "Paste", "Clear", "Font Change", "Color Change", "Size Change",
|
||||
"Style Change", "Align Left", "Align Center", "Align Right", "Drop", "Move"]
|
||||
|
||||
class MlteWindow(Window):
|
||||
def open(self, path, name, data):
|
||||
self.path = path
|
||||
self.name = name
|
||||
r = windowbounds(400, 400)
|
||||
w = Win.NewWindow(r, name, 1, 0, -1, 1, 0)
|
||||
self.wid = w
|
||||
flags = MacTextEditor.kTXNDrawGrowIconMask|MacTextEditor.kTXNWantHScrollBarMask| \
|
||||
MacTextEditor.kTXNWantVScrollBarMask
|
||||
self.ted, self.frameid = Mlte.TXNNewObject(None, w, None, flags, MacTextEditor.kTXNTextEditStyleFrameType,
|
||||
MacTextEditor.kTXNTextFile, MacTextEditor.kTXNMacOSEncoding)
|
||||
self.ted.TXNSetData(MacTextEditor.kTXNTextData, data, 0, 0x7fffffff)
|
||||
self.changed = 0
|
||||
self.do_postopen()
|
||||
self.do_activate(1, None)
|
||||
|
||||
def do_idle(self, event):
|
||||
self.ted.TXNIdle()
|
||||
self.ted.TXNAdjustCursor(None)
|
||||
|
||||
|
||||
|
||||
def do_activate(self, onoff, evt):
|
||||
if onoff:
|
||||
## self.ted.TXNActivate(self.frameid, 0)
|
||||
self.ted.TXNFocus(1)
|
||||
self.parent.active = self
|
||||
else:
|
||||
self.ted.TXNFocus(0)
|
||||
self.parent.active = None
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_update(self, wid, event):
|
||||
self.ted.TXNDraw(None)
|
||||
|
||||
def do_postresize(self, width, height, window):
|
||||
self.ted.TXNResizeFrame(width, height, self.frameid)
|
||||
|
||||
def do_contentclick(self, local, modifiers, evt):
|
||||
self.ted.TXNClick(evt)
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_char(self, ch, event):
|
||||
self.ted.TXNKeyDown(event)
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def close(self):
|
||||
if self.changed:
|
||||
save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
|
||||
if save > 0:
|
||||
self.menu_save()
|
||||
elif save < 0:
|
||||
return
|
||||
if self.parent.active == self:
|
||||
self.parent.active = None
|
||||
self.ted.TXNDeleteObject()
|
||||
del self.ted
|
||||
## del self.tedtexthandle
|
||||
self.do_postclose()
|
||||
|
||||
def menu_save(self):
|
||||
if not self.path:
|
||||
self.menu_save_as()
|
||||
return # Will call us recursively
|
||||
dhandle = self.ted.TXNGetData(0, 0x7fffffff)
|
||||
data = dhandle.data
|
||||
fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
|
||||
fp.write(data)
|
||||
if data[-1] <> '\r': fp.write('\r')
|
||||
fp.close()
|
||||
self.changed = 0
|
||||
|
||||
def menu_save_as(self):
|
||||
path = EasyDialogs.AskFileForSave(message='Save as:')
|
||||
if not path: return
|
||||
self.path = path
|
||||
self.name = os.path.split(self.path)[-1]
|
||||
self.wid.SetWTitle(self.name)
|
||||
self.menu_save()
|
||||
|
||||
def menu_cut(self):
|
||||
## self.ted.WESelView()
|
||||
self.ted.TXNCut()
|
||||
### Mlte.ConvertToPublicScrap()
|
||||
## Scrap.ZeroScrap()
|
||||
## self.ted.WECut()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_copy(self):
|
||||
## Scrap.ZeroScrap()
|
||||
self.ted.TXNCopy()
|
||||
### Mlte.ConvertToPublicScrap()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_paste(self):
|
||||
### Mlte.ConvertFromPublicScrap()
|
||||
self.ted.TXNPaste()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_clear(self):
|
||||
## self.ted.WESelView()
|
||||
self.ted.TXNClear()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_undo(self):
|
||||
self.ted.TXNUndo()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_redo(self):
|
||||
self.ted.TXNRedo()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def have_selection(self):
|
||||
start, stop = self.ted.TXNGetSelection()
|
||||
return start < stop
|
||||
|
||||
def can_paste(self):
|
||||
return Mlte.TXNIsScrapPastable()
|
||||
|
||||
def can_undo(self):
|
||||
can, which = self.ted.TXNCanUndo()
|
||||
if not can:
|
||||
return None
|
||||
if which >= len(UNDOLABELS):
|
||||
# Unspecified undo
|
||||
return "Undo"
|
||||
which = UNDOLABELS[which]
|
||||
|
||||
return "Undo "+which
|
||||
|
||||
def can_redo(self):
|
||||
can, which = self.ted.TXNCanRedo()
|
||||
if not can:
|
||||
return None
|
||||
if which >= len(UNDOLABELS):
|
||||
# Unspecified undo
|
||||
return "Redo"
|
||||
which = UNDOLABELS[which]
|
||||
|
||||
return "Redo "+which
|
||||
|
||||
class Mlted(Application):
|
||||
def __init__(self):
|
||||
Application.__init__(self)
|
||||
self.num = 0
|
||||
self.active = None
|
||||
self.updatemenubar()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = Menu(self.menubar, "File")
|
||||
self.newitem = MenuItem(m, "New window", "N", self.open)
|
||||
self.openitem = MenuItem(m, "Open...", "O", self.openfile)
|
||||
self.closeitem = MenuItem(m, "Close", "W", self.closewin)
|
||||
m.addseparator()
|
||||
self.saveitem = MenuItem(m, "Save", "S", self.save)
|
||||
self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
|
||||
m.addseparator()
|
||||
self.quititem = MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
self.editmenu = m = Menu(self.menubar, "Edit")
|
||||
self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
|
||||
self.redoitem = MenuItem(m, "Redo", None, self.redo)
|
||||
m.addseparator()
|
||||
self.cutitem = MenuItem(m, "Cut", "X", self.cut)
|
||||
self.copyitem = MenuItem(m, "Copy", "C", self.copy)
|
||||
self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
|
||||
self.clearitem = MenuItem(m, "Clear", "", self.clear)
|
||||
|
||||
# Groups of items enabled together:
|
||||
self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
|
||||
self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
|
||||
self.windowgroup_on = -1
|
||||
self.focusgroup_on = -1
|
||||
self.pastegroup_on = -1
|
||||
self.undo_label = "never"
|
||||
self.redo_label = "never"
|
||||
|
||||
def updatemenubar(self):
|
||||
changed = 0
|
||||
on = (self.active <> None)
|
||||
if on <> self.windowgroup_on:
|
||||
for m in self.windowgroup:
|
||||
m.enable(on)
|
||||
self.windowgroup_on = on
|
||||
changed = 1
|
||||
if on:
|
||||
# only if we have an edit menu
|
||||
on = self.active.have_selection()
|
||||
if on <> self.focusgroup_on:
|
||||
for m in self.focusgroup:
|
||||
m.enable(on)
|
||||
self.focusgroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_paste()
|
||||
if on <> self.pastegroup_on:
|
||||
self.pasteitem.enable(on)
|
||||
self.pastegroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_undo()
|
||||
if on <> self.undo_label:
|
||||
if on:
|
||||
self.undoitem.enable(1)
|
||||
self.undoitem.settext(on)
|
||||
self.undo_label = on
|
||||
else:
|
||||
self.undoitem.settext("Nothing to undo")
|
||||
self.undoitem.enable(0)
|
||||
changed = 1
|
||||
on = self.active.can_redo()
|
||||
if on <> self.redo_label:
|
||||
if on:
|
||||
self.redoitem.enable(1)
|
||||
self.redoitem.settext(on)
|
||||
self.redo_label = on
|
||||
else:
|
||||
self.redoitem.settext("Nothing to redo")
|
||||
self.redoitem.enable(0)
|
||||
changed = 1
|
||||
if changed:
|
||||
DrawMenuBar()
|
||||
|
||||
#
|
||||
# Apple menu
|
||||
#
|
||||
|
||||
def do_about(self, id, item, window, event):
|
||||
EasyDialogs.Message("A simple single-font text editor based on MacTextEditor")
|
||||
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
|
||||
def open(self, *args):
|
||||
self._open(0)
|
||||
|
||||
def openfile(self, *args):
|
||||
self._open(1)
|
||||
|
||||
def _open(self, askfile):
|
||||
if askfile:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
name = os.path.split(path)[-1]
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
else:
|
||||
path = None
|
||||
name = "Untitled %d"%self.num
|
||||
data = ''
|
||||
w = MlteWindow(self)
|
||||
w.open(path, name, data)
|
||||
self.num = self.num + 1
|
||||
|
||||
def closewin(self, *args):
|
||||
if self.active:
|
||||
self.active.close()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def save(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def saveas(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save_as()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
for w in self._windows.values():
|
||||
w.close()
|
||||
if self._windows:
|
||||
return
|
||||
self._quit()
|
||||
|
||||
#
|
||||
# Edit menu
|
||||
#
|
||||
|
||||
def undo(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_undo()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def redo(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_redo()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def cut(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_cut()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def copy(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_copy()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def paste(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_paste()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def clear(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_clear()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
#
|
||||
# Other stuff
|
||||
#
|
||||
|
||||
def idle(self, event):
|
||||
if self.active:
|
||||
self.active.do_idle(event)
|
||||
else:
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def main():
|
||||
Mlte.TXNInitTextension(0)
|
||||
try:
|
||||
App = Mlted()
|
||||
App.mainloop()
|
||||
finally:
|
||||
Mlte.TXNTerminateTextension()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
70
Mac/Demo/quicktime/MovieInWindow.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""MovieInWindow converted to python
|
||||
|
||||
Jack Jansen, CWI, December 1995
|
||||
"""
|
||||
|
||||
from Carbon import Qt
|
||||
from Carbon import QuickTime
|
||||
from Carbon import Qd
|
||||
from Carbon import QuickDraw
|
||||
from Carbon import Evt
|
||||
from Carbon import Events
|
||||
from Carbon import Win
|
||||
from Carbon import Windows
|
||||
from Carbon import File
|
||||
import EasyDialogs
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def main():
|
||||
# skip the toolbox initializations, already done
|
||||
# XXXX Should use gestalt here to check for quicktime version
|
||||
Qt.EnterMovies()
|
||||
|
||||
# Get the movie file
|
||||
if len(sys.argv) > 1:
|
||||
filename = sys.argv[1]
|
||||
else:
|
||||
filename = EasyDialogs.AskFileForOpen() # Was: QuickTime.MovieFileType
|
||||
if not filename:
|
||||
sys.exit(0)
|
||||
|
||||
# Open the window
|
||||
bounds = (175, 75, 175+160, 75+120)
|
||||
theWindow = Win.NewCWindow(bounds, os.path.split(filename)[1], 1, 0, -1, 0, 0)
|
||||
Qd.SetPort(theWindow)
|
||||
# XXXX Needed? SetGWorld((CGrafPtr)theWindow, nil)
|
||||
|
||||
playMovieInWindow(theWindow, filename, theWindow.GetWindowPort().GetPortBounds())
|
||||
|
||||
def playMovieInWindow(theWindow, theFile, movieBox):
|
||||
"""Play a movie in a window"""
|
||||
# XXXX Needed? SetGWorld((CGrafPtr)theWindow, nil);
|
||||
|
||||
# Get the movie
|
||||
theMovie = loadMovie(theFile)
|
||||
|
||||
# Set where we want it
|
||||
theMovie.SetMovieBox(movieBox)
|
||||
|
||||
# Start at the beginning
|
||||
theMovie.GoToBeginningOfMovie()
|
||||
|
||||
# Give a little time to preroll
|
||||
theMovie.MoviesTask(0)
|
||||
|
||||
# Start playing
|
||||
theMovie.StartMovie()
|
||||
|
||||
while not theMovie.IsMovieDone() and not Evt.Button():
|
||||
theMovie.MoviesTask(0)
|
||||
|
||||
def loadMovie(theFile):
|
||||
"""Load a movie given an fsspec. Return the movie object"""
|
||||
movieResRef = Qt.OpenMovieFile(theFile, 1)
|
||||
movie, d1, d2 = Qt.NewMovieFromFile(movieResRef, 0, QuickTime.newMovieActive)
|
||||
return movie
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
92
Mac/Demo/quicktime/VerySimplePlayer.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""VerySimplePlayer converted to python
|
||||
|
||||
Jack Jansen, CWI, December 1995
|
||||
"""
|
||||
|
||||
from Carbon import Qt
|
||||
from Carbon import QuickTime
|
||||
from Carbon import Qd
|
||||
from Carbon import QuickDraw
|
||||
from Carbon import Evt
|
||||
from Carbon import Events
|
||||
from Carbon import Win
|
||||
from Carbon import Windows
|
||||
from Carbon import File
|
||||
import EasyDialogs
|
||||
import sys
|
||||
|
||||
# XXXX maxbounds = (40, 40, 1000, 1000)
|
||||
|
||||
def main():
|
||||
print 'hello world' # XXXX
|
||||
# skip the toolbox initializations, already done
|
||||
# XXXX Should use gestalt here to check for quicktime version
|
||||
Qt.EnterMovies()
|
||||
|
||||
# Get the movie file
|
||||
fss = EasyDialogs.AskFileForOpen(wanted=File.FSSpec) # Was: QuickTime.MovieFileType
|
||||
if not fss:
|
||||
sys.exit(0)
|
||||
|
||||
# Open the window
|
||||
bounds = (175, 75, 175+160, 75+120)
|
||||
theWindow = Win.NewCWindow(bounds, fss.as_tuple()[2], 0, 0, -1, 1, 0)
|
||||
# XXXX Needed? SetGWorld((CGrafPtr)theWindow, nil)
|
||||
Qd.SetPort(theWindow)
|
||||
|
||||
# Get the movie
|
||||
theMovie = loadMovie(fss)
|
||||
|
||||
# Relocate to (0, 0)
|
||||
bounds = theMovie.GetMovieBox()
|
||||
bounds = 0, 0, bounds[2]-bounds[0], bounds[3]-bounds[1]
|
||||
theMovie.SetMovieBox(bounds)
|
||||
|
||||
# Create a controller
|
||||
theController = theMovie.NewMovieController(bounds, QuickTime.mcTopLeftMovie)
|
||||
|
||||
# Get movie size and update window parameters
|
||||
rv, bounds = theController.MCGetControllerBoundsRect()
|
||||
theWindow.SizeWindow(bounds[2], bounds[3], 0) # XXXX or [3] [2]?
|
||||
Qt.AlignWindow(theWindow, 0)
|
||||
theWindow.ShowWindow()
|
||||
|
||||
# XXXX MCDoAction(theController, mcActionSetGrowBoxBounds, &maxBounds)
|
||||
theController.MCDoAction(QuickTime.mcActionSetKeysEnabled, '1')
|
||||
|
||||
# XXXX MCSetActionFilterWithRefCon(theController, movieControllerEventFilter, (long)theWindow)
|
||||
|
||||
done = 0
|
||||
while not done:
|
||||
gotone, evt = Evt.WaitNextEvent(0xffff, 0)
|
||||
(what, message, when, where, modifiers) = evt
|
||||
## print what, message, when, where, modifiers # XXXX
|
||||
|
||||
if theController.MCIsPlayerEvent(evt):
|
||||
continue
|
||||
|
||||
if what == Events.mouseDown:
|
||||
part, whichWindow = Win.FindWindow(where)
|
||||
if part == Windows.inGoAway:
|
||||
done = whichWindow.TrackGoAway(where)
|
||||
elif part == Windows.inDrag:
|
||||
Qt.DragAlignedWindow(whichWindow, where, (0, 0, 4000, 4000))
|
||||
elif what == Events.updateEvt:
|
||||
whichWindow = Win.WhichWindow(message)
|
||||
if not whichWindow:
|
||||
# Probably the console window. Print something, hope it helps.
|
||||
print 'update'
|
||||
else:
|
||||
Qd.SetPort(whichWindow)
|
||||
whichWindow.BeginUpdate()
|
||||
Qd.EraseRect(whichWindow.GetWindowPort().GetPortBounds())
|
||||
whichWindow.EndUpdate()
|
||||
|
||||
def loadMovie(theFile):
|
||||
"""Load a movie given an fsspec. Return the movie object"""
|
||||
movieResRef = Qt.OpenMovieFile(theFile, 1)
|
||||
movie, d1, d2 = Qt.NewMovieFromFile(movieResRef, 0, QuickTime.newMovieActive)
|
||||
return movie
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
57
Mac/Demo/resources/copyres.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from Carbon.Res import *
|
||||
from Carbon.Resources import *
|
||||
import MacOS
|
||||
|
||||
READ = 1
|
||||
WRITE = 2
|
||||
smAllScripts = -3
|
||||
|
||||
def copyres(src, dst):
|
||||
"""Copy resource from src file to dst file."""
|
||||
|
||||
cur = CurResFile()
|
||||
ctor, type = MacOS.GetCreatorAndType(src)
|
||||
input = FSpOpenResFile(src, READ)
|
||||
try:
|
||||
FSpCreateResFile(dst, ctor, type, smAllScripts)
|
||||
except:
|
||||
raw_input("%s already exists... CR to write anyway! " % dst)
|
||||
output = FSpOpenResFile(dst, WRITE)
|
||||
UseResFile(input)
|
||||
ntypes = Count1Types()
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Get1IndType(itype)
|
||||
nresources = Count1Resources(type)
|
||||
for ires in range(1, 1+nresources):
|
||||
res = Get1IndResource(type, ires)
|
||||
res.LoadResource()
|
||||
id, type, name = res.GetResInfo()
|
||||
size = res.SizeResource()
|
||||
attrs = res.GetResAttrs()
|
||||
print id, type, name, size, hex(attrs)
|
||||
res.DetachResource()
|
||||
UseResFile(output)
|
||||
try:
|
||||
res2 = Get1Resource(type, id)
|
||||
except (RuntimeError, Res.Error), msg:
|
||||
res2 = None
|
||||
if res2:
|
||||
print "Duplicate type+id, not copied"
|
||||
print (res2.size, res2.data)
|
||||
print res2.GetResInfo()
|
||||
if res2.HomeResFile() == output:
|
||||
'OK'
|
||||
elif res2.HomeResFile() == input:
|
||||
'BAD!'
|
||||
else:
|
||||
print 'Home:', res2.HomeResFile()
|
||||
else:
|
||||
res.AddResource(type, id, name)
|
||||
#res.SetResAttrs(attrs)
|
||||
res.WriteResource()
|
||||
UseResFile(input)
|
||||
UseResFile(cur)
|
||||
CloseResFile(output)
|
||||
CloseResFile(input)
|
||||
|
||||
copyres('::python.<2E>.rsrc', '::foo.rsrc')
|
||||
60
Mac/Demo/resources/listres.py
Normal file
@@ -0,0 +1,60 @@
|
||||
# List all resources
|
||||
|
||||
from Carbon import Res
|
||||
from Carbon.Resources import *
|
||||
|
||||
def list1resources():
|
||||
ntypes = Res.Count1Types()
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Res.Get1IndType(itype)
|
||||
print "Type:", repr(type)
|
||||
nresources = Res.Count1Resources(type)
|
||||
for i in range(1, 1 + nresources):
|
||||
Res.SetResLoad(0)
|
||||
res = Res.Get1IndResource(type, i)
|
||||
Res.SetResLoad(1)
|
||||
info(res)
|
||||
|
||||
def listresources():
|
||||
ntypes = Res.CountTypes()
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Res.GetIndType(itype)
|
||||
print "Type:", repr(type)
|
||||
nresources = Res.CountResources(type)
|
||||
for i in range(1, 1 + nresources):
|
||||
Res.SetResLoad(0)
|
||||
res = Res.GetIndResource(type, i)
|
||||
Res.SetResLoad(1)
|
||||
info(res)
|
||||
|
||||
def info(res):
|
||||
print res.GetResInfo(), res.SizeResource(), decodeattrs(res.GetResAttrs())
|
||||
|
||||
attrnames = {
|
||||
resChanged: 'Changed',
|
||||
resPreload: 'Preload',
|
||||
resProtected: 'Protected',
|
||||
resLocked: 'Locked',
|
||||
resPurgeable: 'Purgeable',
|
||||
resSysHeap: 'SysHeap',
|
||||
}
|
||||
|
||||
def decodeattrs(attrs):
|
||||
names = []
|
||||
for bit in range(16):
|
||||
mask = 1<<bit
|
||||
if attrs & mask:
|
||||
if attrnames.has_key(mask):
|
||||
names.append(attrnames[mask])
|
||||
else:
|
||||
names.append(hex(mask))
|
||||
return names
|
||||
|
||||
def test():
|
||||
print "=== Local resourcess ==="
|
||||
list1resources()
|
||||
print "=== All resources ==="
|
||||
listresources()
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
180
Mac/Demo/sound/morse.py
Normal file
@@ -0,0 +1,180 @@
|
||||
import sys, math
|
||||
|
||||
DOT = 30
|
||||
DAH = 80
|
||||
OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
|
||||
SAMPWIDTH = 2
|
||||
FRAMERATE = 44100
|
||||
BASEFREQ = 441
|
||||
QSIZE = 20000
|
||||
|
||||
morsetab = {
|
||||
'A': '.-', 'a': '.-',
|
||||
'B': '-...', 'b': '-...',
|
||||
'C': '-.-.', 'c': '-.-.',
|
||||
'D': '-..', 'd': '-..',
|
||||
'E': '.', 'e': '.',
|
||||
'F': '..-.', 'f': '..-.',
|
||||
'G': '--.', 'g': '--.',
|
||||
'H': '....', 'h': '....',
|
||||
'I': '..', 'i': '..',
|
||||
'J': '.---', 'j': '.---',
|
||||
'K': '-.-', 'k': '-.-',
|
||||
'L': '.-..', 'l': '.-..',
|
||||
'M': '--', 'm': '--',
|
||||
'N': '-.', 'n': '-.',
|
||||
'O': '---', 'o': '---',
|
||||
'P': '.--.', 'p': '.--.',
|
||||
'Q': '--.-', 'q': '--.-',
|
||||
'R': '.-.', 'r': '.-.',
|
||||
'S': '...', 's': '...',
|
||||
'T': '-', 't': '-',
|
||||
'U': '..-', 'u': '..-',
|
||||
'V': '...-', 'v': '...-',
|
||||
'W': '.--', 'w': '.--',
|
||||
'X': '-..-', 'x': '-..-',
|
||||
'Y': '-.--', 'y': '-.--',
|
||||
'Z': '--..', 'z': '--..',
|
||||
'0': '-----',
|
||||
'1': '.----',
|
||||
'2': '..---',
|
||||
'3': '...--',
|
||||
'4': '....-',
|
||||
'5': '.....',
|
||||
'6': '-....',
|
||||
'7': '--...',
|
||||
'8': '---..',
|
||||
'9': '----.',
|
||||
',': '--..--',
|
||||
'.': '.-.-.-',
|
||||
'?': '..--..',
|
||||
';': '-.-.-.',
|
||||
':': '---...',
|
||||
"'": '.----.',
|
||||
'-': '-....-',
|
||||
'/': '-..-.',
|
||||
'(': '-.--.-',
|
||||
')': '-.--.-',
|
||||
'_': '..--.-',
|
||||
' ': ' '
|
||||
}
|
||||
|
||||
# If we play at 44.1 kHz (which we do), then if we produce one sine
|
||||
# wave in 100 samples, we get a tone of 441 Hz. If we produce two
|
||||
# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
|
||||
# appears to be a nice one for playing morse code.
|
||||
def mkwave(octave):
|
||||
global sinewave, nowave
|
||||
sinewave = ''
|
||||
n = int(FRAMERATE / BASEFREQ)
|
||||
for i in range(n):
|
||||
val = int(math.sin(2 * math.pi * i * octave / n) * 0x7fff)
|
||||
sample = chr((val >> 8) & 255) + chr(val & 255)
|
||||
sinewave = sinewave + sample[:SAMPWIDTH]
|
||||
nowave = '\0' * (n*SAMPWIDTH)
|
||||
|
||||
mkwave(OCTAVE)
|
||||
|
||||
class BufferedAudioDev:
|
||||
def __init__(self, *args):
|
||||
import audiodev
|
||||
self._base = apply(audiodev.AudioDev, args)
|
||||
self._buffer = []
|
||||
self._filled = 0
|
||||
self._addmethods(self._base, self._base.__class__)
|
||||
def _addmethods(self, inst, cls):
|
||||
for name in cls.__dict__.keys():
|
||||
if not hasattr(self, name):
|
||||
try:
|
||||
setattr(self, name, getattr(inst, name))
|
||||
except:
|
||||
pass
|
||||
for basecls in cls.__bases__:
|
||||
self._addmethods(self, inst, basecls)
|
||||
def writeframesraw(self, frames):
|
||||
self._buffer.append(frames)
|
||||
self._filled = self._filled + len(frames)
|
||||
if self._filled >= QSIZE:
|
||||
self.flush()
|
||||
def wait(self):
|
||||
self.flush()
|
||||
self._base.wait()
|
||||
def flush(self):
|
||||
print 'flush: %d blocks, %d bytes' % (len(self._buffer), self._filled)
|
||||
if self._buffer:
|
||||
import string
|
||||
self._base.writeframes(string.joinfields(self._buffer, ''))
|
||||
self._buffer = []
|
||||
self._filled = 0
|
||||
|
||||
def main(args = sys.argv[1:]):
|
||||
import getopt, string
|
||||
try:
|
||||
opts, args = getopt.getopt(args, 'o:p:')
|
||||
except getopt.error:
|
||||
sys.stderr.write('Usage ' + sys.argv[0] +
|
||||
' [ -o outfile ] [ args ] ...\n')
|
||||
sys.exit(1)
|
||||
dev = None
|
||||
for o, a in opts:
|
||||
if o == '-o':
|
||||
import aifc
|
||||
dev = aifc.open(a, 'w')
|
||||
dev.setframerate(FRAMERATE)
|
||||
dev.setsampwidth(SAMPWIDTH)
|
||||
dev.setnchannels(1)
|
||||
if o == '-p':
|
||||
mkwave(string.atoi(a))
|
||||
if not dev:
|
||||
dev = BufferedAudioDev()
|
||||
dev.setoutrate(FRAMERATE)
|
||||
dev.setsampwidth(SAMPWIDTH)
|
||||
dev.setnchannels(1)
|
||||
dev.close = dev.stop
|
||||
if args:
|
||||
line = string.join(args)
|
||||
else:
|
||||
line = sys.stdin.readline()
|
||||
while line:
|
||||
print line
|
||||
mline = morse(line)
|
||||
print mline
|
||||
play(mline, dev)
|
||||
if hasattr(dev, 'wait'):
|
||||
dev.wait()
|
||||
if not args:
|
||||
line = sys.stdin.readline()
|
||||
else:
|
||||
line = ''
|
||||
dev.close()
|
||||
|
||||
# Convert a string to morse code with \001 between the characters in
|
||||
# the string.
|
||||
def morse(line):
|
||||
res = ''
|
||||
for c in line:
|
||||
try:
|
||||
res = res + morsetab[c] + '\001'
|
||||
except KeyError:
|
||||
pass
|
||||
return res
|
||||
|
||||
# Play a line of morse code.
|
||||
def play(line, dev):
|
||||
for c in line:
|
||||
if c == '.':
|
||||
sine(dev, DOT)
|
||||
elif c == '-':
|
||||
sine(dev, DAH)
|
||||
else:
|
||||
pause(dev, DAH)
|
||||
pause(dev, DOT)
|
||||
|
||||
def sine(dev, length):
|
||||
dev.writeframesraw(sinewave*length)
|
||||
|
||||
def pause(dev, length):
|
||||
dev.writeframesraw(nowave*length)
|
||||
|
||||
if __name__ == '__main__' or sys.argv[0] == __name__:
|
||||
main()
|
||||
188
Mac/Demo/sound/morselib.py
Normal file
@@ -0,0 +1,188 @@
|
||||
"""Translate text strings to Morse code"""
|
||||
|
||||
FRAMERATE = 22050
|
||||
SAMPWIDTH = 2
|
||||
|
||||
BASEFREQ = 441
|
||||
OCTAVE = 2
|
||||
|
||||
DOT = 30
|
||||
DAH = 80
|
||||
|
||||
morsetab = {
|
||||
'a': '.-',
|
||||
'b': '-...',
|
||||
'c': '-.-.',
|
||||
'd': '-..',
|
||||
'e': '.',
|
||||
'f': '..-.',
|
||||
'g': '--.',
|
||||
'h': '....',
|
||||
'i': '..',
|
||||
'j': '.---',
|
||||
'k': '-.-',
|
||||
'l': '.-..',
|
||||
'm': '--',
|
||||
'n': '-.',
|
||||
'o': '---',
|
||||
'p': '.--.',
|
||||
'q': '--.-',
|
||||
'r': '.-.',
|
||||
's': '...',
|
||||
't': '-',
|
||||
'u': '..-',
|
||||
'v': '...-',
|
||||
'w': '.--',
|
||||
'x': '-..-',
|
||||
'y': '-.--',
|
||||
'z': '--..',
|
||||
'0': '-----',
|
||||
'1': '.----',
|
||||
'2': '..---',
|
||||
'3': '...--',
|
||||
'4': '....-',
|
||||
'5': '.....',
|
||||
'6': '-....',
|
||||
'7': '--...',
|
||||
'8': '---..',
|
||||
'9': '----.',
|
||||
',': '--..--',
|
||||
'.': '.-.-.-',
|
||||
'?': '..--..',
|
||||
';': '-.-.-.',
|
||||
':': '---...',
|
||||
"'": '.----.',
|
||||
'-': '-....-',
|
||||
'/': '-..-.',
|
||||
'(': '-.--.-',
|
||||
')': '-.--.-', # XXX same as code for '(' ???
|
||||
'_': '..--.-',
|
||||
' ': ' '
|
||||
}
|
||||
|
||||
def morsecode(s):
|
||||
from string import lower
|
||||
m = ''
|
||||
for c in s:
|
||||
c = lower(c)
|
||||
if morsetab.has_key(c):
|
||||
c = morsetab[c] + ' '
|
||||
else:
|
||||
c = '? '
|
||||
m = m + c
|
||||
return m
|
||||
|
||||
|
||||
class BaseMorse:
|
||||
"base class for morse transmissions"
|
||||
|
||||
def __init__(self):
|
||||
"constructor"
|
||||
self.dots = DOT
|
||||
self.dahs = DAH
|
||||
|
||||
def noise(self, duration):
|
||||
"beep for given duration"
|
||||
pass
|
||||
|
||||
def pause(self, duration):
|
||||
"pause for given duration"
|
||||
pass
|
||||
|
||||
def dot(self):
|
||||
"short beep"
|
||||
self.noise(self.dots)
|
||||
|
||||
def dah(self):
|
||||
"long beep"
|
||||
self.noise(self.dahs)
|
||||
|
||||
def pdot(self):
|
||||
"pause as long as a dot"
|
||||
self.pause(self.dots)
|
||||
|
||||
def pdah(self):
|
||||
"pause as long as a dah"
|
||||
self.pause(self.dahs)
|
||||
|
||||
def sendmorse(self, s):
|
||||
for c in s:
|
||||
if c == '.': self.dot()
|
||||
elif c == '-': self.dah()
|
||||
else: self.pdah()
|
||||
self.pdot()
|
||||
|
||||
def sendascii(self, s):
|
||||
self.sendmorse(morsecode(s))
|
||||
|
||||
def send(self, s):
|
||||
self.sendascii(s)
|
||||
|
||||
|
||||
import Audio_mac
|
||||
class MyAudio(Audio_mac.Play_Audio_mac):
|
||||
def _callback(self, *args):
|
||||
if hasattr(self, 'usercallback'): self.usercallback()
|
||||
apply(Audio_mac.Play_Audio_mac._callback, (self,) + args)
|
||||
|
||||
|
||||
class MacMorse(BaseMorse):
|
||||
"Mac specific class to play Morse code"
|
||||
|
||||
def __init__(self):
|
||||
BaseMorse.__init__(self)
|
||||
self.dev = MyAudio()
|
||||
self.dev.setoutrate(FRAMERATE)
|
||||
self.dev.setsampwidth(SAMPWIDTH)
|
||||
self.dev.setnchannels(1)
|
||||
self.dev.usercallback = self.usercallback
|
||||
sinewave = ''
|
||||
n = int(FRAMERATE / BASEFREQ)
|
||||
octave = OCTAVE
|
||||
from math import sin, pi
|
||||
for i in range(n):
|
||||
val = int(sin(2 * pi * i * octave / n) * 0x7fff)
|
||||
sample = chr((val >> 8) & 255) + chr(val & 255)
|
||||
sinewave = sinewave + sample[:SAMPWIDTH]
|
||||
self.sinewave = sinewave
|
||||
self.silence = '\0' * (n*SAMPWIDTH)
|
||||
self.morsequeue = ''
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
self.dev = None
|
||||
|
||||
def pause(self, duration):
|
||||
self.dev.writeframes(self.silence * duration)
|
||||
|
||||
def noise(self, duration):
|
||||
self.dev.writeframes(self.sinewave * duration)
|
||||
|
||||
def sendmorse(self, s):
|
||||
self.morsequeue = self.morsequeue + s
|
||||
self.dev.usercallback()
|
||||
self.dev.usercallback()
|
||||
self.dev.usercallback()
|
||||
|
||||
def usercallback(self):
|
||||
if self.morsequeue:
|
||||
c, self.morsequeue = self.morsequeue[0], self.morsequeue[1:]
|
||||
if c == '.': self.dot()
|
||||
elif c == '-': self.dah()
|
||||
else: self.pdah()
|
||||
self.pdot()
|
||||
|
||||
|
||||
def test():
|
||||
m = MacMorse()
|
||||
while 1:
|
||||
try:
|
||||
line = raw_input('Morse line: ')
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
break
|
||||
m.send(line)
|
||||
while m.morsequeue: pass
|
||||
|
||||
test()
|
||||
45
Mac/Demo/sound/playaiff.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from Carbon.Sound import *
|
||||
from Carbon import Snd
|
||||
|
||||
import aifc, audioop
|
||||
|
||||
fn = 'f:just samples:2ndbeat.aif'
|
||||
af = aifc.open(fn, 'r')
|
||||
print af.getparams()
|
||||
print 'nframes =', af.getnframes()
|
||||
print 'nchannels =', af.getnchannels()
|
||||
print 'framerate =', af.getframerate()
|
||||
nframes = min(af.getnframes(), 100000)
|
||||
frames = af.readframes(nframes)
|
||||
print 'len(frames) =', len(frames)
|
||||
print repr(frames[:100])
|
||||
frames = audioop.add(frames, '\x80'*len(frames), 1)
|
||||
print repr(frames[:100])
|
||||
|
||||
import struct
|
||||
|
||||
header1 = struct.pack('llhhllbbl',
|
||||
0,
|
||||
af.getnchannels(),
|
||||
af.getframerate(),0,
|
||||
0,
|
||||
0,
|
||||
0xFF,
|
||||
60,
|
||||
nframes)
|
||||
print repr(header1)
|
||||
header2 = struct.pack('llhlll', 0, 0, 0, 0, 0, 0)
|
||||
header3 = struct.pack('hhlll',
|
||||
af.getsampwidth()*8,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0)
|
||||
print repr(header3)
|
||||
header = header1 + header2 + header3
|
||||
|
||||
buffer = header + frames
|
||||
|
||||
chan = Snd.SndNewChannel(5,0x00C0)
|
||||
|
||||
Snd.SndDoCommand(chan, (bufferCmd, 0, buffer), 0)
|
||||
150
Mac/Demo/textedit.html
Normal file
@@ -0,0 +1,150 @@
|
||||
<HTML><HEAD><TITLE>Using FrameWork and TextEdit</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1>Using FrameWork and TextEdit</H1>
|
||||
<HR>
|
||||
|
||||
In this document we use the <CODE>FrameWork</CODE> and <CODE>TextEdit</CODE>
|
||||
modules to create a simple text editor. The functionality
|
||||
of the editor is very basic: you can open multiple files, type text and use
|
||||
cut/copy/paste. The main intention is to explain the use of FrameWork, really. <p>
|
||||
|
||||
<H2>FrameWork</H2>
|
||||
|
||||
The FrameWork module provides you with a skeleton application. It declares a
|
||||
number of classes suitable for subclassing in your application, thereby
|
||||
releaving you of the burden of doing all event handling, etc. yourself. For a
|
||||
real understanding you will have to browse the source. Here is a short overview
|
||||
of the classes and what functionality they provide.
|
||||
|
||||
<dl>
|
||||
<dt> <CODE>Application</CODE>
|
||||
<dd>
|
||||
This is the toplevel class you will override. It maintains the menu bar and contains
|
||||
the main event handling code. Normal use is to override the <code>__init__</code> routine
|
||||
to do your own initializations and override <code>makeusermenus</code> to create your menus
|
||||
(your menu callback routines may be here too, but this is by no means necessary).
|
||||
The event handling code can be overridden at various levels, from very low-level (the
|
||||
<code>dispatch</code> method) to intermediate level (<code>do_keyDown</code>, for instance)
|
||||
to high-level (<code>do_key</code>). The application class knows about the <code>Window</code>
|
||||
objects you create, and will forward events to the appropriate window (So, normally you
|
||||
would have a <code>do_key</code> method in your window object, not your application object).
|
||||
|
||||
<dt> <CODE>MenuBar</CODE>, <CODE>Menu</CODE> and <CODE>MenuItem</CODE>
|
||||
<dd>
|
||||
These classes (and a few friends like <CODE>SubMenu</CODE>) handle your menus. You would not
|
||||
normally override them but use them as-is. The idiom for creating menus is a bit strange,
|
||||
see the test code at the bottom of FrameWork for sample use. The apple menu is handled for you
|
||||
by <CODE>MenuBar</CODE> and <CODE>Application</CODE>.
|
||||
|
||||
<dt> <CODE>Window</CODE>
|
||||
<dd>
|
||||
The basic window. Again, a class that you normally subclass in your application, possibly
|
||||
multiple times if you have different types of windows. The init call instantiates the data
|
||||
structure but actually opening the window is delayed until you call <code>open</code>. Your
|
||||
open method should call <code>do_postopen</code> to let the base class handle linking in to
|
||||
the application object. Similarly with <code>close</code> and <code>do_postclose</code>. The
|
||||
rest of the code is mainly event-oriented: you override <code>do_postresize</code>,
|
||||
<code>do_contentclick</code>, <code>do_update</code>, <code>do_activate</code>
|
||||
and <code>do_key</code> to "do your thing". When these methods are called the relevant environment
|
||||
has been setup (like <code>BeginDrawing</code> has been called for updates, etc).
|
||||
|
||||
<dt> <CODE>windowbounds</CODE>
|
||||
<dd>
|
||||
Not a class but a function: you pass it a width and height and it will return you a rectangle
|
||||
you can use to create your window. It will take care of staggering windows and it will try
|
||||
to fit the window on the screen (but the resulting rect will <em>always</em> have the size you
|
||||
specify).
|
||||
|
||||
<dt> <CODE>ControlsWindow</CODE>
|
||||
<dd>
|
||||
A subclass of Window which automatically handles drawing and clicking for controls. You override
|
||||
the same methods as for Window (if you need to: control-related things are done automatically) and
|
||||
<code>do_controlhit</code>.
|
||||
|
||||
<dt> <CODE>ScrolledWindow</CODE>
|
||||
<dd>
|
||||
A subclass of ControlsWindow, a window with optional scrollbars. If you override <code>do_activate</code>
|
||||
or <code>do_postresize</code> you must call the ScrolledWindow methods at the end of your override.
|
||||
You call <code>scrollbars</code> to enable/disable scrollbars and <code>updatescrollbars</code> to
|
||||
update them. You provide <code>getscrollbarvalues</code> to return the current x/y values (a helper
|
||||
method <code>scalebarvalues</code> is available) and <code>scrollbarcallback</code> to update your
|
||||
display after the user has used the scrollbars.
|
||||
|
||||
<dt> <CODE>DialogWindow</CODE>
|
||||
<dd>
|
||||
A modeless dialog window initialized from a DLOG resource. See the
|
||||
<A HREF="example2.html">second Interslip example</A> for its useage.
|
||||
</dl>
|
||||
|
||||
<H2>A sample text editor</H2>
|
||||
|
||||
Let us have a look at <A HREF="textedit/ped.py">ped.py</A> (in the Demo:textedit folder), the Pathetic
|
||||
EDitor. It has multiple windows, cut/copy/paste and keyboard input, but that is about all. It looks
|
||||
as if you can resize the window but it does not work. Still, it serves as an example.
|
||||
|
||||
Ped creates two classes, <code>TEWindow</code> and <code>Ped</code>. Let us start with the latter one,
|
||||
which is a subclass of <code>FrameWork.Application</code> and our main application. The init function
|
||||
has little to do aside from the standard init: it remembers a window sequence number (for untitled windows),
|
||||
and sets things up for menu disable to work. Remember, the <code>makeusermenus</code> is called
|
||||
automatically. <p>
|
||||
|
||||
<code>Makeusermenus</code> creates the <code>File</code> and <code>Edit</code> menus. It also initializes
|
||||
a couple of lists that are used later to correctly enable and disable menu items (and complete menus) depending
|
||||
on whether a window is open, text is selected, etc. The callback functions for the menu items are
|
||||
all methods of this class. <p>
|
||||
|
||||
<code>Updatemenubar</code> handles greying out (and re-enabling) of menu items depending on whether there
|
||||
is a current window and its state. <p>
|
||||
|
||||
The rest of the methods are all callbacks and simple to understand. They check whether there is an active
|
||||
window (and complain loudly if there is none: the corresponding menu entry should have been disabled
|
||||
in that case!) and call the appropriate window method. Only the <code>_open</code> method (the common code
|
||||
for <code>Open</code> and <code>New</code>) deserves some mention. It instantiates a <code>TEWindow</code>
|
||||
object and opens it with the title, filename and contents of the file to edit. Note that FrameWork takes
|
||||
care of remembering the window object. A minor note on opening the file in binary mode: this is because
|
||||
TextEdit expects MacOS style carriage-return terminated lines, not python/unix/C style newline-terminated
|
||||
lines. <p>
|
||||
|
||||
Oh yes: the <code>quit</code> callback does a little magic too. It closes all windows, and only if this
|
||||
succeeds it actually quits. This gives the user a chance to cancel the operation if some files are unsaved.
|
||||
<p>
|
||||
|
||||
Lastly, there is the <code>idle</code> method, called by the Application base class when no event
|
||||
is available. It is forwarded to the active window, so it can blink the text caret. <p>
|
||||
|
||||
The <code>TEWindow</code> object handles a single window. Due to this structuring it is absolutely no
|
||||
problem to have multiple windows open at the same time (although a real application should exercise care when
|
||||
two windows refer to the same document). TEWindow uses the standard init code inherited from
|
||||
<code>ScrolledWindow</code>, and sets itself up at the time of the <code>open</code> call. It obtains screen
|
||||
coordinates, opens the window, creates rectangles for TextEdit to work in (the magical number <code>15</code>
|
||||
here is the size of a normal scroll bar: unfortunately there is no symbolic constant for it),
|
||||
creates the TextEdit object and initializes it with our data. Finally, the scroll bars are created (the
|
||||
initial values will be obtained automatically through <code>getscrollbarvalues</code>) and we activate
|
||||
ourselves (this is unfortunately not done automatically by the MacOS event handling code). <p>
|
||||
|
||||
<code>Do_idle</code> simply calls the TextEdit routine that blinks the cursor. <code>Getscrollbarvalues</code>
|
||||
returns the current X and Y scrollbar values, scaled to <code>0..32767</code>. For X we return <code>None</code>,
|
||||
which means "no scrollbar, please", for Y we use the scaler provided by <code>ScrolledWindow</code>. <p>
|
||||
|
||||
<code>Scrollbar_callback</code> is called when the user uses the scrollbar. It is passed a string <code>'x'</code>
|
||||
or <code>'y'</code>, one of <code>'set', '-', '--', '+', '++'</code> and (for <code>set</code>) an absolute
|
||||
value. Note that the sign of the value passed to <code>TEPinScroll</code> is counter-intuitive. <p>
|
||||
|
||||
<code>do_activate</code> (de)activates the scrollbars and calls the relevant TextEdit routine. Moreover, it
|
||||
tells the application object if we are now the active window, and updates the menubar. The next few methods
|
||||
are update and menu callbacks, and pretty straightforward. Note that <code>do_close</code> can
|
||||
return without closing the window (if the document is changed and the users cancels out of the operation).
|
||||
Also note the "magic" in <code>menu_save_as</code>
|
||||
that set the correct window title. <p>
|
||||
|
||||
Things get moderately interesting again at the cut/copy/paste handling, since the TextEdit scrap is
|
||||
separate from the desktop scrap. For that reason there are various calls to routines that move the scrap
|
||||
back and forth. <code>Have_selection</code> is called by the menubar update code to determine whether cut and
|
||||
copy should be enabled. <p>
|
||||
|
||||
Understanding the main program is left as an exercise to the reader. <p>
|
||||
|
||||
<hr>
|
||||
That's all for this example, you could now continue with the <A HREF="waste.html">next example</A>, where we use WASTE, a more-or-less
|
||||
TextEdit compatible library with more functionality, to rebuild our editor. Or you can
|
||||
return to the <A HREF="index.html">table of contents</A> to pick another topic. <p>
|
||||
359
Mac/Demo/textedit/ped.py
Normal file
@@ -0,0 +1,359 @@
|
||||
# A minimal text editor.
|
||||
#
|
||||
# To be done:
|
||||
# - Update viewrect after resize
|
||||
# - Handle horizontal scrollbar correctly
|
||||
# - Functionality: find, etc.
|
||||
|
||||
from Carbon.Menu import DrawMenuBar
|
||||
from FrameWork import *
|
||||
from Carbon import Win
|
||||
from Carbon import Qd
|
||||
from Carbon import TE
|
||||
from Carbon import Scrap
|
||||
import os
|
||||
import macfs
|
||||
|
||||
class TEWindow(ScrolledWindow):
|
||||
def open(self, path, name, data):
|
||||
self.path = path
|
||||
self.name = name
|
||||
r = windowbounds(400, 400)
|
||||
w = Win.NewWindow(r, name, 1, 0, -1, 1, 0)
|
||||
self.wid = w
|
||||
x0, y0, x1, y1 = self.wid.GetWindowPort().GetPortBounds()
|
||||
x0 = x0 + 4
|
||||
y0 = y0 + 4
|
||||
x1 = x1 - 20
|
||||
y1 = y1 - 20
|
||||
vr = dr = x0, y0, x1, y1
|
||||
##vr = 4, 0, r[2]-r[0]-15, r[3]-r[1]-15
|
||||
##dr = (0, 0, vr[2], 0)
|
||||
Qd.SetPort(w)
|
||||
Qd.TextFont(4)
|
||||
Qd.TextSize(9)
|
||||
self.ted = TE.TENew(dr, vr)
|
||||
self.ted.TEAutoView(1)
|
||||
self.ted.TESetText(data)
|
||||
w.DrawGrowIcon()
|
||||
self.scrollbars()
|
||||
self.changed = 0
|
||||
self.do_postopen()
|
||||
self.do_activate(1, None)
|
||||
|
||||
def do_idle(self):
|
||||
self.ted.TEIdle()
|
||||
|
||||
def getscrollbarvalues(self):
|
||||
dr = self.ted.destRect
|
||||
vr = self.ted.viewRect
|
||||
height = self.ted.nLines * self.ted.lineHeight
|
||||
vx = self.scalebarvalue(dr[0], dr[2]-dr[0], vr[0], vr[2])
|
||||
vy = self.scalebarvalue(dr[1], dr[1]+height, vr[1], vr[3])
|
||||
print dr, vr, height, vx, vy
|
||||
return None, vy
|
||||
|
||||
def scrollbar_callback(self, which, what, value):
|
||||
if which == 'y':
|
||||
if what == 'set':
|
||||
height = self.ted.nLines * self.ted.lineHeight
|
||||
cur = self.getscrollbarvalues()[1]
|
||||
delta = (cur-value)*height/32767
|
||||
if what == '-':
|
||||
delta = self.ted.lineHeight
|
||||
elif what == '--':
|
||||
delta = (self.ted.viewRect[3]-self.ted.lineHeight)
|
||||
if delta <= 0:
|
||||
delta = self.ted.lineHeight
|
||||
elif what == '+':
|
||||
delta = -self.ted.lineHeight
|
||||
elif what == '++':
|
||||
delta = -(self.ted.viewRect[3]-self.ted.lineHeight)
|
||||
if delta >= 0:
|
||||
delta = -self.ted.lineHeight
|
||||
self.ted.TEPinScroll(0, delta)
|
||||
print 'SCROLL Y', delta
|
||||
else:
|
||||
pass # No horizontal scrolling
|
||||
|
||||
def do_activate(self, onoff, evt):
|
||||
print "ACTIVATE", onoff
|
||||
ScrolledWindow.do_activate(self, onoff, evt)
|
||||
if onoff:
|
||||
self.ted.TEActivate()
|
||||
self.parent.active = self
|
||||
self.parent.updatemenubar()
|
||||
else:
|
||||
self.ted.TEDeactivate()
|
||||
|
||||
def do_update(self, wid, event):
|
||||
Qd.EraseRect(wid.GetWindowPort().GetPortBounds())
|
||||
self.ted.TEUpdate(wid.GetWindowPort().GetPortBounds())
|
||||
self.updatescrollbars()
|
||||
|
||||
def do_contentclick(self, local, modifiers, evt):
|
||||
shifted = (modifiers & 0x200)
|
||||
self.ted.TEClick(local, shifted)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_char(self, ch, event):
|
||||
self.ted.TESelView()
|
||||
self.ted.TEKey(ord(ch))
|
||||
self.changed = 1
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def close(self):
|
||||
if self.changed:
|
||||
save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
|
||||
if save > 0:
|
||||
self.menu_save()
|
||||
elif save < 0:
|
||||
return
|
||||
if self.parent.active == self:
|
||||
self.parent.active = None
|
||||
self.parent.updatemenubar()
|
||||
del self.ted
|
||||
self.do_postclose()
|
||||
|
||||
def menu_save(self):
|
||||
if not self.path:
|
||||
self.menu_save_as()
|
||||
return # Will call us recursively
|
||||
print 'Saving to ', self.path
|
||||
dhandle = self.ted.TEGetText()
|
||||
data = dhandle.data
|
||||
fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
|
||||
fp.write(data)
|
||||
if data[-1] <> '\r': fp.write('\r')
|
||||
fp.close()
|
||||
self.changed = 0
|
||||
|
||||
def menu_save_as(self):
|
||||
path = EasyDialogs.AskFileForSave(message='Save as:')
|
||||
if not path: return
|
||||
self.path = path
|
||||
self.name = os.path.split(self.path)[-1]
|
||||
self.wid.SetWTitle(self.name)
|
||||
self.menu_save()
|
||||
|
||||
def menu_cut(self):
|
||||
self.ted.TESelView()
|
||||
self.ted.TECut()
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
TE.TEToScrap()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_copy(self):
|
||||
self.ted.TECopy()
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
TE.TEToScrap()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_paste(self):
|
||||
TE.TEFromScrap()
|
||||
self.ted.TESelView()
|
||||
self.ted.TEPaste()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_clear(self):
|
||||
self.ted.TESelView()
|
||||
self.ted.TEDelete()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def have_selection(self):
|
||||
return (self.ted.selStart < self.ted.selEnd)
|
||||
|
||||
class Ped(Application):
|
||||
def __init__(self):
|
||||
Application.__init__(self)
|
||||
self.num = 0
|
||||
self.active = None
|
||||
self.updatemenubar()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = Menu(self.menubar, "File")
|
||||
self.newitem = MenuItem(m, "New window", "N", self.open)
|
||||
self.openitem = MenuItem(m, "Open...", "O", self.openfile)
|
||||
self.closeitem = MenuItem(m, "Close", "W", self.closewin)
|
||||
m.addseparator()
|
||||
self.saveitem = MenuItem(m, "Save", "S", self.save)
|
||||
self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
|
||||
m.addseparator()
|
||||
self.quititem = MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
self.editmenu = m = Menu(self.menubar, "Edit")
|
||||
self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
|
||||
self.cutitem = MenuItem(m, "Cut", "X", self.cut)
|
||||
self.copyitem = MenuItem(m, "Copy", "C", self.copy)
|
||||
self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
|
||||
self.clearitem = MenuItem(m, "Clear", "", self.clear)
|
||||
|
||||
# Not yet implemented:
|
||||
self.undoitem.enable(0)
|
||||
|
||||
# Groups of items enabled together:
|
||||
self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
|
||||
self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
|
||||
self.windowgroup_on = -1
|
||||
self.focusgroup_on = -1
|
||||
self.pastegroup_on = -1
|
||||
|
||||
def updatemenubar(self):
|
||||
changed = 0
|
||||
on = (self.active <> None)
|
||||
if on <> self.windowgroup_on:
|
||||
for m in self.windowgroup:
|
||||
m.enable(on)
|
||||
self.windowgroup_on = on
|
||||
changed = 1
|
||||
if on:
|
||||
# only if we have an edit menu
|
||||
on = self.active.have_selection()
|
||||
if on <> self.focusgroup_on:
|
||||
for m in self.focusgroup:
|
||||
m.enable(on)
|
||||
self.focusgroup_on = on
|
||||
changed = 1
|
||||
if hasattr(Scrap, 'InfoScrap'):
|
||||
on = (Scrap.InfoScrap()[0] <> 0)
|
||||
else:
|
||||
flavors = Scrap.GetCurrentScrap().GetScrapFlavorInfoList()
|
||||
for tp, info in flavors:
|
||||
if tp == 'TEXT':
|
||||
on = 1
|
||||
break
|
||||
else:
|
||||
on = 0
|
||||
if on <> self.pastegroup_on:
|
||||
self.pasteitem.enable(on)
|
||||
self.pastegroup_on = on
|
||||
changed = 1
|
||||
if changed:
|
||||
DrawMenuBar()
|
||||
|
||||
#
|
||||
# Apple menu
|
||||
#
|
||||
|
||||
def do_about(self, id, item, window, event):
|
||||
EasyDialogs.Message("A simple single-font text editor")
|
||||
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
|
||||
def open(self, *args):
|
||||
self._open(0)
|
||||
|
||||
def openfile(self, *args):
|
||||
self._open(1)
|
||||
|
||||
def _open(self, askfile):
|
||||
if askfile:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
name = os.path.split(path)[-1]
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
else:
|
||||
path = None
|
||||
name = "Untitled %d"%self.num
|
||||
data = ''
|
||||
w = TEWindow(self)
|
||||
w.open(path, name, data)
|
||||
self.num = self.num + 1
|
||||
|
||||
def closewin(self, *args):
|
||||
if self.active:
|
||||
self.active.close()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def save(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def saveas(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save_as()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
for w in self._windows.values():
|
||||
w.close()
|
||||
if self._windows:
|
||||
return
|
||||
self._quit()
|
||||
|
||||
#
|
||||
# Edit menu
|
||||
#
|
||||
|
||||
def undo(self, *args):
|
||||
pass
|
||||
|
||||
def cut(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_cut()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def copy(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_copy()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def paste(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_paste()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def clear(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_clear()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
#
|
||||
# Other stuff
|
||||
#
|
||||
|
||||
def idle(self, *args):
|
||||
if self.active:
|
||||
self.active.do_idle()
|
||||
else:
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def main():
|
||||
App = Ped()
|
||||
App.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
5
Mac/Extras.ReadMe.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
This folder contains examples of Python usage and useful scripts and tools.
|
||||
|
||||
You should be aware that these are not Macintosh-specific but are shared
|
||||
among Python on all platforms, so there are some that only run on Windows
|
||||
or Unix or another platform, and/or make little sense on a Macintosh.
|
||||
54
Mac/Extras.install.py
Normal file
@@ -0,0 +1,54 @@
|
||||
"""Recursively copy a directory but skip undesired files and
|
||||
directories (CVS, backup files, pyc files, etc)"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
|
||||
verbose = 1
|
||||
debug = 0
|
||||
|
||||
def isclean(name):
|
||||
if name == 'CVS': return 0
|
||||
if name == '.cvsignore': return 0
|
||||
if name == '.DS_store': return 0
|
||||
if name == '.svn': return 0
|
||||
if name.endswith('~'): return 0
|
||||
if name.endswith('.BAK'): return 0
|
||||
if name.endswith('.pyc'): return 0
|
||||
if name.endswith('.pyo'): return 0
|
||||
if name.endswith('.orig'): return 0
|
||||
return 1
|
||||
|
||||
def copycleandir(src, dst):
|
||||
for cursrc, dirs, files in os.walk(src):
|
||||
assert cursrc.startswith(src)
|
||||
curdst = dst + cursrc[len(src):]
|
||||
if verbose:
|
||||
print "mkdir", curdst
|
||||
if not debug:
|
||||
if not os.path.exists(curdst):
|
||||
os.makedirs(curdst)
|
||||
for fn in files:
|
||||
if isclean(fn):
|
||||
if verbose:
|
||||
print "copy", os.path.join(cursrc, fn), os.path.join(curdst, fn)
|
||||
if not debug:
|
||||
shutil.copy2(os.path.join(cursrc, fn), os.path.join(curdst, fn))
|
||||
else:
|
||||
if verbose:
|
||||
print "skipfile", os.path.join(cursrc, fn)
|
||||
for i in range(len(dirs)-1, -1, -1):
|
||||
if not isclean(dirs[i]):
|
||||
if verbose:
|
||||
print "skipdir", os.path.join(cursrc, dirs[i])
|
||||
del dirs[i]
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
sys.stderr.write("Usage: %s srcdir dstdir\n" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
copycleandir(sys.argv[1], sys.argv[2])
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
66
Mac/IDLE/Info.plist.in
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>py</string>
|
||||
<string>pyw</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>PythonSource.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Python Script</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>pyc</string>
|
||||
<string>pyo</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>PythonCompiled.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Python Bytecode Document</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>IDLE</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>%VERSION%, © 2001-2019 Python Software Foundation</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>IDLE.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.python.IDLE</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>IDLE</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>%VERSION%</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>%VERSION%</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<!--
|
||||
<key>LSMinimumSystemVersionByArchitecture</key>
|
||||
<dict>
|
||||
<key>x86_64</key>
|
||||
<string>10.6.0</string>
|
||||
<key>ppc64</key>
|
||||
<string>10.6.0</string>
|
||||
</dict>
|
||||
-->
|
||||
</dict>
|
||||
</plist>
|
||||
76
Mac/IDLE/Makefile.in
Normal file
@@ -0,0 +1,76 @@
|
||||
prefix=@prefix@
|
||||
CC=@CC@
|
||||
LD=@CC@
|
||||
BASECFLAGS=@BASECFLAGS@
|
||||
OPT=@OPT@
|
||||
CFLAGS=$(BASECFLAGS) $(OPT)
|
||||
LDFLAGS=@LDFLAGS@
|
||||
srcdir= @srcdir@
|
||||
VERSION= @VERSION@
|
||||
LIBDEST=$(prefix)/lib/python$(VERSION)
|
||||
UNIVERSALSDK=@UNIVERSALSDK@
|
||||
builddir= ../..
|
||||
PYTHONFRAMEWORK=@PYTHONFRAMEWORK@
|
||||
|
||||
|
||||
RUNSHARED= @RUNSHARED@
|
||||
BUILDEXE= @BUILDEXEEXT@
|
||||
BUILDPYTHON= $(builddir)/python$(BUILDEXE)
|
||||
|
||||
# Deployment target selected during configure, to be checked
|
||||
# by distutils
|
||||
MACOSX_DEPLOYMENT_TARGET=@CONFIGURE_MACOSX_DEPLOYMENT_TARGET@
|
||||
@EXPORT_MACOSX_DEPLOYMENT_TARGET@export MACOSX_DEPLOYMENT_TARGET
|
||||
|
||||
BUNDLEBULDER=$(srcdir)/../../Lib/plat-mac/bundlebuilder.py
|
||||
|
||||
PYTHONAPPSDIR=@FRAMEWORKINSTALLAPPSPREFIX@/$(PYTHONFRAMEWORK) $(VERSION)
|
||||
|
||||
all: IDLE.app
|
||||
|
||||
install: IDLE.app
|
||||
test -d "$(DESTDIR)$(PYTHONAPPSDIR)" || mkdir -p "$(DESTDIR)$(PYTHONAPPSDIR)"
|
||||
-test -d "$(DESTDIR)$(PYTHONAPPSDIR)/IDLE.app" && rm -r "$(DESTDIR)$(PYTHONAPPSDIR)/IDLE.app"
|
||||
/bin/cp -PR IDLE.app "$(DESTDIR)$(PYTHONAPPSDIR)"
|
||||
touch "$(DESTDIR)$(PYTHONAPPSDIR)/IDLE.app"
|
||||
if [ -f "$(DESTDIR)$(LIBDEST)/idlelib/config-main.def" ]; then \
|
||||
/bin/cp -p "$(DESTDIR)$(LIBDEST)/idlelib/config-main.def" \
|
||||
"$(DESTDIR)$(LIBDEST)/idlelib/config-main.def~" ; \
|
||||
sed -e 's!name= IDLE Classic Windows!name= IDLE Classic OSX!g' \
|
||||
< "$(DESTDIR)$(LIBDEST)/idlelib/config-main.def~" \
|
||||
> "$(DESTDIR)$(LIBDEST)/idlelib/config-main.def" ; \
|
||||
rm "$(DESTDIR)$(LIBDEST)/idlelib/config-main.def~" ; \
|
||||
fi
|
||||
if [ -f "$(DESTDIR)$(LIBDEST)/idlelib/config-extensions.def" ]; then \
|
||||
/bin/cp -p "$(DESTDIR)$(LIBDEST)/idlelib/config-extensions.def" \
|
||||
"$(DESTDIR)$(LIBDEST)/idlelib/config-extensions.def~" ; \
|
||||
sed -e 's!zoom-height=<Alt-Key-2>!zoom-height=<Option-Key-0>!g' \
|
||||
-e 's!<Alt-Key-!<Option-Key-!g' \
|
||||
< "$(DESTDIR)$(LIBDEST)/idlelib/config-extensions.def~" \
|
||||
> "$(DESTDIR)$(LIBDEST)/idlelib/config-extensions.def" ; \
|
||||
rm "$(DESTDIR)$(LIBDEST)/idlelib/config-extensions.def~" ; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
rm -rf IDLE.app
|
||||
|
||||
IDLE.app: \
|
||||
$(srcdir)/../Icons/IDLE.icns $(srcdir)/idlemain.py \
|
||||
$(srcdir)/../Icons/PythonSource.icns \
|
||||
$(srcdir)/../Icons/PythonCompiled.icns Info.plist
|
||||
rm -fr IDLE.app
|
||||
$(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(BUNDLEBULDER) \
|
||||
--builddir=. \
|
||||
--name=IDLE \
|
||||
--link-exec \
|
||||
--plist=Info.plist \
|
||||
--mainprogram=$(srcdir)/idlemain.py \
|
||||
--iconfile=$(srcdir)/../Icons/IDLE.icns \
|
||||
--resource=$(srcdir)/../Icons/PythonSource.icns \
|
||||
--resource=$(srcdir)/../Icons/PythonCompiled.icns \
|
||||
--python=$(prefix)/Resources/Python.app/Contents/MacOS/Python \
|
||||
build
|
||||
|
||||
Info.plist: $(srcdir)/Info.plist.in
|
||||
sed 's/%VERSION%/'"`$(RUNSHARED) $(BUILDPYTHON) -c 'import platform; print platform.python_version()'`"'/g' < $(srcdir)/Info.plist.in > Info.plist
|
||||
|
||||
73
Mac/IDLE/idlemain.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""
|
||||
Bootstrap script for IDLE as an application bundle.
|
||||
"""
|
||||
import sys, os
|
||||
|
||||
# Change the current directory the user's home directory, that way we'll get
|
||||
# a more useful default location in the open/save dialogs.
|
||||
os.chdir(os.path.expanduser('~/Documents'))
|
||||
|
||||
|
||||
# Make sure sys.executable points to the python interpreter inside the
|
||||
# framework, instead of at the helper executable inside the application
|
||||
# bundle (the latter works, but doesn't allow access to the window server)
|
||||
#
|
||||
# .../IDLE.app/
|
||||
# Contents/
|
||||
# MacOS/
|
||||
# IDLE (a python script)
|
||||
# Python{-32} (symlink)
|
||||
# Resources/
|
||||
# idlemain.py (this module)
|
||||
# ...
|
||||
#
|
||||
# ../IDLE.app/Contents/MacOS/Python{-32} is symlinked to
|
||||
# ..Library/Frameworks/Python.framework/Versions/m.n
|
||||
# /Resources/Python.app/Contents/MacOS/Python{-32}
|
||||
# which is the Python interpreter executable
|
||||
#
|
||||
# The flow of control is as follows:
|
||||
# 1. IDLE.app is launched which starts python running the IDLE script
|
||||
# 2. IDLE script exports
|
||||
# PYTHONEXECUTABLE = .../IDLE.app/Contents/MacOS/Python{-32}
|
||||
# (the symlink to the framework python)
|
||||
# 3. IDLE script alters sys.argv and uses os.execve to replace itself with
|
||||
# idlemain.py running under the symlinked python.
|
||||
# This is the magic step.
|
||||
# 4. During interpreter initialization, because PYTHONEXECUTABLE is defined,
|
||||
# sys.executable may get set to an unuseful value.
|
||||
#
|
||||
# (Note that the IDLE script and the setting of PYTHONEXECUTABLE is
|
||||
# generated automatically by bundlebuilder in the Python 2.x build.
|
||||
# Also, IDLE invoked via command line, i.e. bin/idle, bypasses all of
|
||||
# this.)
|
||||
#
|
||||
# Now fix up the execution environment before importing idlelib.
|
||||
|
||||
# Reset sys.executable to its normal value, the actual path of
|
||||
# the interpreter in the framework, by following the symlink
|
||||
# exported in PYTHONEXECUTABLE.
|
||||
pyex = os.environ['PYTHONEXECUTABLE']
|
||||
sys.executable = os.path.join(sys.prefix, 'bin', 'python%d.%d'%(sys.version_info[:2]))
|
||||
|
||||
# Remove any sys.path entries for the Resources dir in the IDLE.app bundle.
|
||||
p = pyex.partition('.app')
|
||||
if p[2].startswith('/Contents/MacOS/Python'):
|
||||
sys.path = [value for value in sys.path if
|
||||
value.partition('.app') != (p[0], p[1], '/Contents/Resources')]
|
||||
|
||||
# Unexport PYTHONEXECUTABLE so that the other Python processes started
|
||||
# by IDLE have a normal sys.executable.
|
||||
del os.environ['PYTHONEXECUTABLE']
|
||||
|
||||
# Look for the -psn argument that the launcher adds and remove it, it will
|
||||
# only confuse the IDLE startup code.
|
||||
for idx, value in enumerate(sys.argv):
|
||||
if value.startswith('-psn_'):
|
||||
del sys.argv[idx]
|
||||
break
|
||||
|
||||
# Now it is safe to import idlelib.
|
||||
from idlelib.PyShell import main
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
BIN
Mac/Icons/Disk Image.icns
Normal file
BIN
Mac/Icons/IDLE.icns
Normal file
BIN
Mac/Icons/Python Folder.icns
Normal file
BIN
Mac/Icons/PythonCompiled.icns
Normal file
BIN
Mac/Icons/PythonLauncher.icns
Normal file
BIN
Mac/Icons/PythonSource.icns
Normal file
3
Mac/Icons/ReadMe.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
The icons for use on MacOS X were created by Jacob Rus <jrus@fas.harvard.edu>
|
||||
with some feedback from the folks on pythonmac-sig@python.org.
|
||||
|
||||
331
Mac/Makefile.in
Normal file
@@ -0,0 +1,331 @@
|
||||
# This file can be invoked from the various frameworkinstall... targets in the
|
||||
# main Makefile. The next couple of variables are overridden on the
|
||||
# commandline in that case.
|
||||
|
||||
VERSION=@VERSION@
|
||||
ENSUREPIP=@ENSUREPIP@
|
||||
builddir = ..
|
||||
srcdir=@srcdir@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
LIBDEST=$(prefix)/lib/python$(VERSION)
|
||||
RUNSHARED=@RUNSHARED@
|
||||
BUILDEXE=@BUILDEXEEXT@
|
||||
BUILDPYTHON=$(builddir)/python$(BUILDEXE)
|
||||
DESTDIR=
|
||||
LDFLAGS=@LDFLAGS@
|
||||
FRAMEWORKUNIXTOOLSPREFIX=@FRAMEWORKUNIXTOOLSPREFIX@
|
||||
PYTHONFRAMEWORK=@PYTHONFRAMEWORK@
|
||||
PYTHONFRAMEWORKIDENTIFIER=@PYTHONFRAMEWORKIDENTIFIER@
|
||||
LIPO_32BIT_FLAGS=@LIPO_32BIT_FLAGS@
|
||||
CC=@CC@
|
||||
MACOSX_DEPLOYMENT_TARGET=@CONFIGURE_MACOSX_DEPLOYMENT_TARGET@
|
||||
export MACOSX_DEPLOYMENT_TARGET
|
||||
|
||||
# These are normally glimpsed from the previous set
|
||||
BINDIR= @bindir@
|
||||
PYTHONAPPSDIR=@FRAMEWORKINSTALLAPPSPREFIX@/$(PYTHONFRAMEWORK) $(VERSION)
|
||||
APPINSTALLDIR=$(prefix)/Resources/Python.app
|
||||
|
||||
# Variables for installing the "normal" unix binaries
|
||||
INSTALLED_PYTHONAPP=$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)
|
||||
|
||||
# Items more-or-less copied from the main Makefile
|
||||
DIRMODE=755
|
||||
FILEMODE=644
|
||||
INSTALL=@INSTALL@
|
||||
INSTALL_SYMLINK=ln -fsn
|
||||
INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT= @INSTALL_SCRIPT@
|
||||
INSTALL_DATA=@INSTALL_DATA@
|
||||
LN=@LN@
|
||||
STRIPFLAG=-s
|
||||
CPMAC=CpMac
|
||||
|
||||
APPTEMPLATE=$(srcdir)/Resources/app
|
||||
APPSUBDIRS=MacOS Resources
|
||||
CACHERSRC=$(srcdir)/scripts/cachersrc.py
|
||||
compileall=$(srcdir)/../Lib/compileall.py
|
||||
|
||||
installapps: install_Python install_pythonw install_BuildApplet install_PythonLauncher \
|
||||
install_IDLE checkapplepython install_versionedtools
|
||||
|
||||
|
||||
install_pythonw: pythonw
|
||||
$(INSTALL_PROGRAM) $(STRIPFLAG) pythonw "$(DESTDIR)$(prefix)/bin/pythonw$(VERSION)"
|
||||
$(INSTALL_PROGRAM) $(STRIPFLAG) pythonw "$(DESTDIR)$(prefix)/bin/python$(VERSION)"
|
||||
ln -sf python$(VERSION) "$(DESTDIR)$(prefix)/bin/python2"
|
||||
ln -sf python2 "$(DESTDIR)$(prefix)/bin/python"
|
||||
ln -sf pythonw$(VERSION) "$(DESTDIR)$(prefix)/bin/pythonw2"
|
||||
ln -sf pythonw2 "$(DESTDIR)$(prefix)/bin/pythonw"
|
||||
ifneq ($(LIPO_32BIT_FLAGS),)
|
||||
lipo $(LIPO_32BIT_FLAGS) -output $(DESTDIR)$(prefix)/bin/python$(VERSION)-32 pythonw
|
||||
lipo $(LIPO_32BIT_FLAGS) -output $(DESTDIR)$(prefix)/bin/pythonw$(VERSION)-32 pythonw
|
||||
ln -sf python$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/python2-32"
|
||||
ln -sf python2-32 "$(DESTDIR)$(prefix)/bin/python-32"
|
||||
ln -sf pythonw$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/pythonw2-32"
|
||||
ln -sf pythonw2-32 "$(DESTDIR)$(prefix)/bin/pythonw-32"
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# Install unix tools in /usr/local/bin. These are just aliases for the
|
||||
# actual installation inside the framework.
|
||||
#
|
||||
installunixtools:
|
||||
if [ ! -d "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" ]; then \
|
||||
$(INSTALL) -d -m $(DIRMODE) "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" ;\
|
||||
fi
|
||||
for fn in python pythonw idle pydoc python-config smtpd.py 2to3 \
|
||||
python2 pythonw2 idle2 \
|
||||
pydoc2 python2-config smtpd2.py \
|
||||
2to3-2 \
|
||||
python$(VERSION) pythonw$(VERSION) idle$(VERSION) \
|
||||
pydoc$(VERSION) python$(VERSION)-config smtpd$(VERSION).py \
|
||||
2to3-$(VERSION) ;\
|
||||
do \
|
||||
ln -fs "$(prefix)/bin/$${fn}" "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin/$${fn}" ;\
|
||||
done
|
||||
ifneq ($(LIPO_32BIT_FLAGS),)
|
||||
for fn in python-32 pythonw-32 \
|
||||
python2-32 pythonw2-32 \
|
||||
python$(VERSION)-32 pythonw$(VERSION)-32 ;\
|
||||
do \
|
||||
ln -fs "$(prefix)/bin/$${fn}" "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin/$${fn}" ;\
|
||||
done
|
||||
endif
|
||||
-if test "x$(ENSUREPIP)" != "xno" ; then \
|
||||
cd "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" && \
|
||||
for fn in \
|
||||
easy_install \
|
||||
pip \
|
||||
pip2 \
|
||||
; \
|
||||
do \
|
||||
rm -f $${fn} ;\
|
||||
$(LN) -s $(BINDIR)/$${fn} $${fn} ;\
|
||||
done ;\
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# Like installunixtools, but only install links to the versioned binaries.
|
||||
#
|
||||
altinstallunixtools:
|
||||
if [ ! -d "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" ]; then \
|
||||
$(INSTALL) -d -m $(DIRMODE) "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" ;\
|
||||
fi
|
||||
for fn in python$(VERSION) pythonw$(VERSION) idle$(VERSION) \
|
||||
pydoc$(VERSION) python$(VERSION)-config smtpd$(VERSION).py ;\
|
||||
do \
|
||||
ln -fs "$(prefix)/bin/$${fn}" "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin/$${fn}" ;\
|
||||
done
|
||||
ifneq ($(LIPO_32BIT_FLAGS),)
|
||||
for fn in python$(VERSION)-32 pythonw$(VERSION)-32 ;\
|
||||
do \
|
||||
ln -fs "$(prefix)/bin/$${fn}" "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin/$${fn}" ;\
|
||||
done
|
||||
endif
|
||||
ln -fs "$(prefix)/bin/2to3-$(VERSION)" "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin/2to3-$(VERSION)"
|
||||
-if test "x$(ENSUREPIP)" != "xno" ; then \
|
||||
cd "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" && \
|
||||
for fn in \
|
||||
easy_install-$(VERSION) \
|
||||
pip$(VERSION) \
|
||||
; \
|
||||
do \
|
||||
rm -f $${fn} ;\
|
||||
$(LN) -s $(BINDIR)/$${fn} $${fn} ;\
|
||||
done ;\
|
||||
fi
|
||||
|
||||
# By default most tools are installed without a version in their basename, to
|
||||
# make it easier to install (and use) several python versions side-by-side move
|
||||
# the tools to a version-specific name and add the non-versioned name as an
|
||||
# alias.
|
||||
install_versionedtools:
|
||||
for fn in idle pydoc ;\
|
||||
do \
|
||||
if [ -h "$(DESTDIR)$(prefix)/bin/$${fn}" ]; then \
|
||||
continue ;\
|
||||
fi ;\
|
||||
mv "$(DESTDIR)$(prefix)/bin/$${fn}" "$(DESTDIR)$(prefix)/bin/$${fn}$(VERSION)" ;\
|
||||
ln -sf "$${fn}$(VERSION)" "$(DESTDIR)$(prefix)/bin/$${fn}2" ;\
|
||||
ln -sf "$${fn}2" "$(DESTDIR)$(prefix)/bin/$${fn}" ;\
|
||||
done
|
||||
if [ ! -h "$(DESTDIR)$(prefix)/bin/smtpd.py" ]; then \
|
||||
mv "$(DESTDIR)$(prefix)/bin/smtpd.py" "$(DESTDIR)$(prefix)/bin/smtpd$(VERSION).py" ;\
|
||||
ln -sf "smtpd$(VERSION).py" "$(DESTDIR)$(prefix)/bin/smtpd2.py" ;\
|
||||
ln -sf "smtpd2.py" "$(DESTDIR)$(prefix)/bin/smtpd.py" ;\
|
||||
fi
|
||||
if [ ! -h "$(DESTDIR)$(prefix)/bin/2to3" ]; then \
|
||||
mv "$(DESTDIR)$(prefix)/bin/2to3" "$(DESTDIR)$(prefix)/bin/2to3-$(VERSION)" ;\
|
||||
ln -sf "2to3-$(VERSION)" "$(DESTDIR)$(prefix)/bin/2to3-2" ;\
|
||||
ln -sf "2to3-2" "$(DESTDIR)$(prefix)/bin/2to3" ;\
|
||||
fi
|
||||
|
||||
|
||||
pythonw: $(srcdir)/Tools/pythonw.c Makefile
|
||||
$(CC) $(LDFLAGS) -DPYTHONFRAMEWORK='"$(PYTHONFRAMEWORK)"' -o $@ $(srcdir)/Tools/pythonw.c -I.. -I$(srcdir)/../Include ../$(PYTHONFRAMEWORK).framework/Versions/$(VERSION)/$(PYTHONFRAMEWORK)
|
||||
|
||||
install_PythonLauncher:
|
||||
cd PythonLauncher && make install DESTDIR=$(DESTDIR)
|
||||
|
||||
install_Python:
|
||||
@for i in "$(PYTHONAPPSDIR)" "$(APPINSTALLDIR)" "$(APPINSTALLDIR)/Contents"; do \
|
||||
if test ! -d "$(DESTDIR)$$i"; then \
|
||||
echo "Creating directory $(DESTDIR)$$i"; \
|
||||
$(INSTALL) -d -m $(DIRMODE) "$(DESTDIR)$$i"; \
|
||||
fi;\
|
||||
done
|
||||
@for i in $(APPSUBDIRS); do \
|
||||
if test ! -d "$(DESTDIR)$(APPINSTALLDIR)/Contents/$$i"; then \
|
||||
echo "Creating directory $(DESTDIR)$(APPINSTALLDIR)/Contents/$$i"; \
|
||||
$(INSTALL) -d -m $(DIRMODE) "$(DESTDIR)$(APPINSTALLDIR)/Contents/$$i"; \
|
||||
else true; \
|
||||
fi; \
|
||||
done
|
||||
@for d in . $(APPSUBDIRS); \
|
||||
do \
|
||||
a=$(APPTEMPLATE)/$$d; \
|
||||
if test ! -d $$a; then continue; else true; fi; \
|
||||
b="$(DESTDIR)$(APPINSTALLDIR)/Contents/$$d"; \
|
||||
for i in $$a/*; \
|
||||
do \
|
||||
case $$i in \
|
||||
*CVS) ;; \
|
||||
*.svn) ;; \
|
||||
*.py[co]) ;; \
|
||||
*.orig) ;; \
|
||||
*~) ;; \
|
||||
*idx) \
|
||||
echo $(CPMAC) "$$i" $$b; \
|
||||
$(CPMAC) "$$i" "$$b"; \
|
||||
;; \
|
||||
*) \
|
||||
if test -d $$i; then continue; fi; \
|
||||
if test -x $$i; then \
|
||||
echo $(INSTALL_SCRIPT) "$$i" "$$b"; \
|
||||
$(INSTALL_SCRIPT) "$$i" "$$b"; \
|
||||
else \
|
||||
echo $(INSTALL_DATA) "$$i" "$$b"; \
|
||||
$(INSTALL_DATA) "$$i" "$$b"; \
|
||||
fi;; \
|
||||
esac; \
|
||||
done; \
|
||||
done
|
||||
$(INSTALL_PROGRAM) $(STRIPFLAG) $(BUILDPYTHON) "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)"
|
||||
sed -e "s!%bundleid%!$(PYTHONFRAMEWORKIDENTIFIER)!g" \
|
||||
-e "s!%version%!`$(RUNSHARED) $(BUILDPYTHON) \
|
||||
-c 'import platform; print(platform.python_version())'`!g" \
|
||||
< "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in" \
|
||||
> "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist"
|
||||
rm "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in"
|
||||
|
||||
|
||||
install_IDLE:
|
||||
cd IDLE && make install
|
||||
|
||||
install_BuildApplet:
|
||||
if ! $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) \
|
||||
-c 'import EasyDialogs' 2>/dev/null ; then \
|
||||
echo "EasyDialogs not available in this Python - skipping Build Applet.app" ; \
|
||||
else \
|
||||
$(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(srcdir)/scripts/BuildApplet.py \
|
||||
--destroot "$(DESTDIR)" \
|
||||
--python=$(prefix)/Resources/Python.app/Contents/MacOS/Python \
|
||||
--output "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app" \
|
||||
$(srcdir)/scripts/BuildApplet.py && \
|
||||
if [ -n "$(LIPO_32BIT_FLAGS)" ] ; then \
|
||||
rm "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app/Contents/MacOS/Python" && \
|
||||
lipo $(LIPO_32BIT_FLAGS) \
|
||||
-output "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app/Contents/MacOS/Python" \
|
||||
$(BUILDPYTHON) ; \
|
||||
fi \
|
||||
fi
|
||||
|
||||
MACLIBDEST=$(LIBDEST)/plat-mac
|
||||
MACTOOLSDEST=$(prefix)/Mac/Tools
|
||||
MACTOOLSSRC=$(srcdir)/Mac/Tools
|
||||
MACTOOLSSUBDIRS=IDE
|
||||
|
||||
installmacsubtree:
|
||||
@for i in $(MACTOOLSDEST); \
|
||||
do \
|
||||
if test ! -d $(DESTDIR)$$i; then \
|
||||
echo "Creating directory $(DESTDIR)$$i"; \
|
||||
$(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$i; \
|
||||
else true; \
|
||||
fi; \
|
||||
done
|
||||
@for d in $(MACTOOLSSUBDIRS); \
|
||||
do \
|
||||
a=$(MACTOOLSSRC)/$$d; \
|
||||
if test ! -d $$a; then continue; else true; fi; \
|
||||
b=$(DESTDIR)$(MACTOOLSDEST)/$$d; \
|
||||
if test ! -d $$b; then \
|
||||
echo "Creating directory $$b"; \
|
||||
$(INSTALL) -d -m $(DIRMODE) $$b; \
|
||||
else true; \
|
||||
fi; \
|
||||
done
|
||||
@for d in $(MACTOOLSSUBDIRS); \
|
||||
do \
|
||||
a=$(MACTOOLSSRC)/$$d; \
|
||||
if test ! -d $$a; then continue; else true; fi; \
|
||||
b=$(DESTDIR)$(MACTOOLSDEST)/$$d; \
|
||||
for i in $$a/*; \
|
||||
do \
|
||||
case $$i in \
|
||||
*CVS) ;; \
|
||||
*.svn) ;; \
|
||||
*.py[co]) ;; \
|
||||
*.orig) ;; \
|
||||
*~) ;; \
|
||||
*.rsrc) \
|
||||
echo $(CPMAC) $$i $$b ; \
|
||||
$(CPMAC) $$i $$b ; \
|
||||
;; \
|
||||
*) \
|
||||
if test -d $$i; then continue; fi; \
|
||||
if test -x $$i; then \
|
||||
echo $(INSTALL_SCRIPT) $$i $$b; \
|
||||
$(INSTALL_SCRIPT) $$i $$b; \
|
||||
else \
|
||||
echo $(INSTALL_DATA) $$i $$b; \
|
||||
$(INSTALL_DATA) $$i $$b; \
|
||||
fi;; \
|
||||
esac; \
|
||||
done; \
|
||||
done
|
||||
|
||||
|
||||
$(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(CACHERSRC) -v $(DESTDIR)$(MACLIBDEST) $(DESTDIR)$(MACTOOLSDEST)
|
||||
$(RUNSHARED) $(BUILDPYTHON) -Wi -tt $(compileall) -d $(MACTOOLSDEST) -x badsyntax $(DESTDIR)$(MACTOOLSDEST)
|
||||
$(RUNSHARED) $(BUILDPYTHON) -O -Wi -tt $(compileall) -d $(MACTOOLSDEST) -x badsyntax $(DESTDIR)$(MACTOOLSDEST)
|
||||
|
||||
$(INSTALLED_PYTHONAPP): install_Python
|
||||
|
||||
installextras: $(srcdir)/Extras.ReadMe.txt $(srcdir)/Extras.install.py
|
||||
$(INSTALL) -d "$(DESTDIR)$(PYTHONAPPSDIR)/Extras"
|
||||
$(INSTALL) $(srcdir)/Extras.ReadMe.txt "$(DESTDIR)$(PYTHONAPPSDIR)/Extras/ReadMe.txt"
|
||||
$(RUNSHARED) $(BUILDPYTHON) $(srcdir)/Extras.install.py $(srcdir)/../Demo \
|
||||
"$(DESTDIR)$(PYTHONAPPSDIR)/Extras/Demo"
|
||||
$(RUNSHARED) $(BUILDPYTHON) $(srcdir)/Extras.install.py $(srcdir)/Demo \
|
||||
"$(DESTDIR)$(PYTHONAPPSDIR)/Extras/Demo.Mac"
|
||||
|
||||
|
||||
checkapplepython: $(srcdir)/Tools/fixapplepython23.py
|
||||
@if ! $(RUNSHARED) $(BUILDPYTHON) $(srcdir)/Tools/fixapplepython23.py -n; then \
|
||||
echo "* WARNING: Apple-installed Python 2.3 will have trouble building extensions from now on."; \
|
||||
echo "* WARNING: Run $(srcdir)/Tools/fixapplepython23.py with \"sudo\" to fix this."; \
|
||||
fi
|
||||
|
||||
|
||||
clean:
|
||||
rm pythonw
|
||||
cd PythonLauncher && make clean
|
||||
cd IDLE && make clean
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in ../config.status
|
||||
cd .. && CONFIG_FILES=Mac/Makefile CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
89
Mac/Modules/ColorPickermodule.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/******************************************************************
|
||||
Copyright 1998 by Just van Rossum, Den Haag, The Netherlands.
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Just van Rossum not be
|
||||
used in advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
JUST VAN ROSSUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
EVENT SHALL JUST VAN ROSSUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include "Python.h"
|
||||
#include "pymactoolbox.h"
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
|
||||
#if APPLE_SUPPORTS_QUICKTIME
|
||||
|
||||
static char cp_GetColor__doc__[] =
|
||||
"GetColor(prompt, (r, g, b)) -> (r, g, b), ok"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
cp_GetColor(PyObject *self, PyObject *args)
|
||||
{
|
||||
RGBColor inColor, outColor;
|
||||
Boolean ok;
|
||||
Point where = {0, 0};
|
||||
Str255 prompt;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&O&", PyMac_GetStr255, prompt, QdRGB_Convert, &inColor))
|
||||
return NULL;
|
||||
|
||||
ok = GetColor(where, prompt, &inColor, &outColor);
|
||||
|
||||
return Py_BuildValue("O&h", QdRGB_New, &outColor, ok);
|
||||
}
|
||||
#endif /* APPLE_SUPPORTS_QUICKTIME */
|
||||
|
||||
/* List of methods defined in the module */
|
||||
|
||||
static struct PyMethodDef cp_methods[] = {
|
||||
#if APPLE_SUPPORTS_QUICKTIME
|
||||
{"GetColor", (PyCFunction)cp_GetColor, METH_VARARGS, cp_GetColor__doc__},
|
||||
#endif /* APPLE_SUPPORTS_QUICKTIME */
|
||||
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
||||
/* Initialization function for the module (*must* be called initColorPicker) */
|
||||
|
||||
static char cp_module_documentation[] =
|
||||
""
|
||||
;
|
||||
|
||||
void initColorPicker(void)
|
||||
{
|
||||
PyObject *m;
|
||||
|
||||
if (PyErr_WarnPy3k("In 3.x, the ColorPicker module is removed.", 1) < 0)
|
||||
return;
|
||||
|
||||
/* Create the module and add the functions */
|
||||
m = Py_InitModule4("ColorPicker", cp_methods,
|
||||
cp_module_documentation,
|
||||
(PyObject*)NULL,PYTHON_API_VERSION);
|
||||
|
||||
/* Add symbolic constants to the module here */
|
||||
|
||||
/* XXXX Add constants here */
|
||||
|
||||
/* Check for errors */
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("can't initialize module ColorPicker");
|
||||
}
|
||||
739
Mac/Modules/MacOS.c
Normal file
@@ -0,0 +1,739 @@
|
||||
/***********************************************************
|
||||
Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
|
||||
The Netherlands.
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the names of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
/* Macintosh OS-specific interface */
|
||||
|
||||
#include "Python.h"
|
||||
#include "pymactoolbox.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
#include <arpa/inet.h> /* for ntohl, htonl */
|
||||
|
||||
|
||||
#ifndef HAVE_OSX105_SDK
|
||||
typedef SInt16 FSIORefNum;
|
||||
#endif
|
||||
|
||||
static PyObject *MacOS_Error; /* Exception MacOS.Error */
|
||||
|
||||
#define PATHNAMELEN 1024
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
/* Declarations for objects of type Resource fork */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
FSIORefNum fRefNum;
|
||||
int isclosed;
|
||||
} rfobject;
|
||||
|
||||
static PyTypeObject Rftype;
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
do_close(rfobject *self)
|
||||
{
|
||||
if (self->isclosed ) return;
|
||||
(void)FSCloseFork(self->fRefNum);
|
||||
self->isclosed = 1;
|
||||
}
|
||||
|
||||
static char rf_read__doc__[] =
|
||||
"Read data from resource fork"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
rf_read(rfobject *self, PyObject *args)
|
||||
{
|
||||
long n;
|
||||
PyObject *v;
|
||||
OSErr err;
|
||||
ByteCount n2;
|
||||
|
||||
if (self->isclosed) {
|
||||
PyErr_SetString(PyExc_ValueError, "Operation on closed file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l", &n))
|
||||
return NULL;
|
||||
|
||||
v = PyBytes_FromStringAndSize((char *)NULL, n);
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
||||
err = FSReadFork(self->fRefNum, fsAtMark, 0, n, PyString_AsString(v), &n2);
|
||||
if (err && err != eofErr) {
|
||||
PyMac_Error(err);
|
||||
Py_DECREF(v);
|
||||
return NULL;
|
||||
}
|
||||
_PyString_Resize(&v, n2);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
static char rf_write__doc__[] =
|
||||
"Write to resource fork"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
rf_write(rfobject *self, PyObject *args)
|
||||
{
|
||||
char *buffer;
|
||||
long size;
|
||||
OSErr err;
|
||||
|
||||
if (self->isclosed) {
|
||||
PyErr_SetString(PyExc_ValueError, "Operation on closed file");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
|
||||
return NULL;
|
||||
err = FSWriteFork(self->fRefNum, fsAtMark, 0, size, buffer, NULL);
|
||||
if (err) {
|
||||
PyMac_Error(err);
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static char rf_seek__doc__[] =
|
||||
"Set file position"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
rf_seek(rfobject *self, PyObject *args)
|
||||
{
|
||||
long amount;
|
||||
int whence = SEEK_SET;
|
||||
int mode;
|
||||
OSErr err;
|
||||
|
||||
if (self->isclosed) {
|
||||
PyErr_SetString(PyExc_ValueError, "Operation on closed file");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "l|i", &amount, &whence)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_CUR:
|
||||
mode = fsFromMark;
|
||||
break;
|
||||
case SEEK_END:
|
||||
mode = fsFromLEOF;
|
||||
break;
|
||||
case SEEK_SET:
|
||||
mode = fsFromStart;
|
||||
break;
|
||||
default:
|
||||
PyErr_BadArgument();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = FSSetForkPosition(self->fRefNum, mode, amount);
|
||||
if (err != noErr) {
|
||||
PyMac_Error(err);
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static char rf_tell__doc__[] =
|
||||
"Get file position"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
rf_tell(rfobject *self, PyObject *args)
|
||||
{
|
||||
long long where;
|
||||
OSErr err;
|
||||
|
||||
if (self->isclosed) {
|
||||
PyErr_SetString(PyExc_ValueError, "Operation on closed file");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
|
||||
err = FSGetForkPosition(self->fRefNum, &where);
|
||||
if (err != noErr) {
|
||||
PyMac_Error(err);
|
||||
return NULL;
|
||||
}
|
||||
return PyLong_FromLongLong(where);
|
||||
}
|
||||
|
||||
static char rf_close__doc__[] =
|
||||
"Close resource fork"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
rf_close(rfobject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
do_close(self);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static struct PyMethodDef rf_methods[] = {
|
||||
{"read", (PyCFunction)rf_read, 1, rf_read__doc__},
|
||||
{"write", (PyCFunction)rf_write, 1, rf_write__doc__},
|
||||
{"seek", (PyCFunction)rf_seek, 1, rf_seek__doc__},
|
||||
{"tell", (PyCFunction)rf_tell, 1, rf_tell__doc__},
|
||||
{"close", (PyCFunction)rf_close, 1, rf_close__doc__},
|
||||
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
/* ---------- */
|
||||
|
||||
|
||||
static rfobject *
|
||||
newrfobject(void)
|
||||
{
|
||||
rfobject *self;
|
||||
|
||||
self = PyObject_NEW(rfobject, &Rftype);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
self->isclosed = 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rf_dealloc(rfobject *self)
|
||||
{
|
||||
do_close(self);
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
rf_getattr(rfobject *self, char *name)
|
||||
{
|
||||
return Py_FindMethod(rf_methods, (PyObject *)self, name);
|
||||
}
|
||||
|
||||
static char Rftype__doc__[] =
|
||||
"Resource fork file object"
|
||||
;
|
||||
|
||||
static PyTypeObject Rftype = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0, /*ob_size*/
|
||||
"MacOS.ResourceFork", /*tp_name*/
|
||||
sizeof(rfobject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)rf_dealloc, /*tp_dealloc*/
|
||||
(printfunc)0, /*tp_print*/
|
||||
(getattrfunc)rf_getattr, /*tp_getattr*/
|
||||
(setattrfunc)0, /*tp_setattr*/
|
||||
(cmpfunc)0, /*tp_compare*/
|
||||
(reprfunc)0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
(hashfunc)0, /*tp_hash*/
|
||||
(ternaryfunc)0, /*tp_call*/
|
||||
(reprfunc)0, /*tp_str*/
|
||||
|
||||
/* Space for future expansion */
|
||||
0L,0L,0L,0L,
|
||||
Rftype__doc__ /* Documentation string */
|
||||
};
|
||||
|
||||
|
||||
/* End of code for Resource fork objects */
|
||||
/* -------------------------------------------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Miscellaneous File System Operations */
|
||||
|
||||
static char getcrtp_doc[] = "Get MacOS 4-char creator and type for a file";
|
||||
|
||||
static PyObject *
|
||||
MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *creator, *type, *res;
|
||||
OSErr err;
|
||||
FSRef ref;
|
||||
FSCatalogInfo cataloginfo;
|
||||
FileInfo* finfo;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &ref)) {
|
||||
#if APPLE_SUPPORTS_QUICKTIME
|
||||
/* This function is documented to take an FSSpec as well,
|
||||
* which only works in 32-bit mode.
|
||||
*/
|
||||
PyErr_Clear();
|
||||
FSSpec fss;
|
||||
FInfo info;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
|
||||
return NULL;
|
||||
|
||||
if ((err = FSpGetFInfo(&fss, &info)) != noErr) {
|
||||
return PyErr_Mac(MacOS_Error, err);
|
||||
}
|
||||
|
||||
info.fdCreator = ntohl(info.fdCreator);
|
||||
info.fdType = ntohl(info.fdType);
|
||||
|
||||
creator = PyString_FromStringAndSize(
|
||||
(char *)&info.fdCreator, 4);
|
||||
type = PyString_FromStringAndSize((char *)&info.fdType, 4);
|
||||
res = Py_BuildValue("OO", creator, type);
|
||||
Py_DECREF(creator);
|
||||
Py_DECREF(type);
|
||||
return res;
|
||||
#else /* APPLE_SUPPORTS_QUICKTIME */
|
||||
return NULL;
|
||||
#endif /* APPLE_SUPPORTS_QUICKTIME */
|
||||
}
|
||||
|
||||
err = FSGetCatalogInfo(&ref,
|
||||
kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
|
||||
NULL, NULL, NULL);
|
||||
if (err != noErr) {
|
||||
PyErr_Mac(MacOS_Error, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
|
||||
/* Directory: doesn't have type/creator info.
|
||||
*
|
||||
* The specific error code is for backward compatibility with
|
||||
* earlier versions.
|
||||
*/
|
||||
PyErr_Mac(MacOS_Error, fnfErr);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
finfo = (FileInfo*)&(cataloginfo.finderInfo);
|
||||
finfo->fileCreator = ntohl(finfo->fileCreator);
|
||||
finfo->fileType = ntohl(finfo->fileType);
|
||||
creator = PyString_FromStringAndSize((char*)&(finfo->fileCreator), 4);
|
||||
type = PyString_FromStringAndSize((char*)&(finfo->fileType), 4);
|
||||
|
||||
res = Py_BuildValue("OO", creator, type);
|
||||
Py_DECREF(creator);
|
||||
Py_DECREF(type);
|
||||
return res;
|
||||
}
|
||||
|
||||
static char setcrtp_doc[] = "Set MacOS 4-char creator and type for a file";
|
||||
|
||||
static PyObject *
|
||||
MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
|
||||
{
|
||||
ResType creator, type;
|
||||
FSRef ref;
|
||||
FileInfo* finfo;
|
||||
OSErr err;
|
||||
FSCatalogInfo cataloginfo;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&O&O&",
|
||||
PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) {
|
||||
#if APPLE_SUPPORTS_QUICKTIME
|
||||
/* Try to handle FSSpec arguments, for backward compatibility */
|
||||
FSSpec fss;
|
||||
FInfo info;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&O&O&",
|
||||
PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
|
||||
return NULL;
|
||||
|
||||
if ((err = FSpGetFInfo(&fss, &info)) != noErr)
|
||||
return PyErr_Mac(MacOS_Error, err);
|
||||
|
||||
info.fdCreator = creator;
|
||||
info.fdType = type;
|
||||
|
||||
if ((err = FSpSetFInfo(&fss, &info)) != noErr)
|
||||
return PyErr_Mac(MacOS_Error, err);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
#else /* APPLE_SUPPORTS_QUICKTIME */
|
||||
return NULL;
|
||||
#endif /* APPLE_SUPPORTS_QUICKTIME */
|
||||
}
|
||||
|
||||
err = FSGetCatalogInfo(&ref,
|
||||
kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
|
||||
NULL, NULL, NULL);
|
||||
if (err != noErr) {
|
||||
PyErr_Mac(MacOS_Error, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
|
||||
/* Directory: doesn't have type/creator info.
|
||||
*
|
||||
* The specific error code is for backward compatibility with
|
||||
* earlier versions.
|
||||
*/
|
||||
PyErr_Mac(MacOS_Error, fnfErr);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
finfo = (FileInfo*)&(cataloginfo.finderInfo);
|
||||
finfo->fileCreator = creator;
|
||||
finfo->fileType = type;
|
||||
|
||||
err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &cataloginfo);
|
||||
if (err != noErr) {
|
||||
PyErr_Mac(MacOS_Error, fnfErr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static char geterr_doc[] = "Convert OSErr number to string";
|
||||
|
||||
static PyObject *
|
||||
MacOS_GetErrorString(PyObject *self, PyObject *args)
|
||||
{
|
||||
int err;
|
||||
char buf[256];
|
||||
Handle h;
|
||||
char *str;
|
||||
static int errors_loaded;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &err))
|
||||
return NULL;
|
||||
|
||||
h = GetResource('Estr', err);
|
||||
if (!h && !errors_loaded) {
|
||||
/*
|
||||
** Attempt to open the resource file containing the
|
||||
** Estr resources. We ignore all errors. We also try
|
||||
** this only once.
|
||||
*/
|
||||
PyObject *m, *rv;
|
||||
errors_loaded = 1;
|
||||
|
||||
m = PyImport_ImportModuleNoBlock("macresource");
|
||||
if (!m) {
|
||||
if (Py_VerboseFlag)
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
rv = PyObject_CallMethod(m, "open_error_resource", "");
|
||||
if (!rv) {
|
||||
if (Py_VerboseFlag)
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
else {
|
||||
Py_DECREF(rv);
|
||||
/* And try again... */
|
||||
h = GetResource('Estr', err);
|
||||
}
|
||||
Py_DECREF(m);
|
||||
}
|
||||
}
|
||||
/*
|
||||
** Whether the code above succeeded or not, we won't try
|
||||
** again.
|
||||
*/
|
||||
errors_loaded = 1;
|
||||
|
||||
if (h) {
|
||||
HLock(h);
|
||||
str = (char *)*h;
|
||||
memcpy(buf, str+1, (unsigned char)str[0]);
|
||||
buf[(unsigned char)str[0]] = '\0';
|
||||
HUnlock(h);
|
||||
ReleaseResource(h);
|
||||
}
|
||||
else {
|
||||
PyOS_snprintf(buf, sizeof(buf), "Mac OS error code %d", err);
|
||||
}
|
||||
|
||||
return Py_BuildValue("s", buf);
|
||||
}
|
||||
|
||||
|
||||
#ifndef __LP64__
|
||||
|
||||
static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
|
||||
|
||||
static PyObject *
|
||||
MacOS_splash(PyObject *self, PyObject *args)
|
||||
{
|
||||
int resid = -1;
|
||||
static DialogPtr curdialog = NULL;
|
||||
DialogPtr olddialog;
|
||||
WindowRef theWindow;
|
||||
CGrafPtr thePort;
|
||||
#if 0
|
||||
short xpos, ypos, width, height, swidth, sheight;
|
||||
#endif
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|i", &resid))
|
||||
return NULL;
|
||||
olddialog = curdialog;
|
||||
curdialog = NULL;
|
||||
|
||||
if ( resid != -1 ) {
|
||||
curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
|
||||
if ( curdialog ) {
|
||||
theWindow = GetDialogWindow(curdialog);
|
||||
thePort = GetWindowPort(theWindow);
|
||||
#if 0
|
||||
width = thePort->portRect.right - thePort->portRect.left;
|
||||
height = thePort->portRect.bottom - thePort->portRect.top;
|
||||
swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
|
||||
sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
|
||||
xpos = (swidth-width)/2;
|
||||
ypos = (sheight-height)/5 + LMGetMBarHeight();
|
||||
MoveWindow(theWindow, xpos, ypos, 0);
|
||||
ShowWindow(theWindow);
|
||||
#endif
|
||||
DrawDialog(curdialog);
|
||||
}
|
||||
}
|
||||
if (olddialog)
|
||||
DisposeDialog(olddialog);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static char DebugStr_doc[] = "Switch to low-level debugger with a message";
|
||||
|
||||
static PyObject *
|
||||
MacOS_DebugStr(PyObject *self, PyObject *args)
|
||||
{
|
||||
Str255 message;
|
||||
PyObject *object = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
|
||||
return NULL;
|
||||
|
||||
DebugStr(message);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static char SysBeep_doc[] = "BEEEEEP!!!";
|
||||
|
||||
static PyObject *
|
||||
MacOS_SysBeep(PyObject *self, PyObject *args)
|
||||
{
|
||||
int duration = 6;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|i", &duration))
|
||||
return NULL;
|
||||
SysBeep(duration);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
#endif /* __LP64__ */
|
||||
|
||||
static char WMAvailable_doc[] =
|
||||
"True if this process can interact with the display."
|
||||
"Will foreground the application on the first call as a side-effect."
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
MacOS_WMAvailable(PyObject *self, PyObject *args)
|
||||
{
|
||||
static PyObject *rv = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
if (!rv) {
|
||||
ProcessSerialNumber psn;
|
||||
|
||||
/*
|
||||
** This is a fairly innocuous call to make if we don't have a window
|
||||
** manager, or if we have no permission to talk to it. It will print
|
||||
** a message on stderr, but at least it won't abort the process.
|
||||
** It appears the function caches the result itself, and it's cheap, so
|
||||
** no need for us to cache.
|
||||
*/
|
||||
#ifdef kCGNullDirectDisplay
|
||||
/* On 10.1 CGMainDisplayID() isn't available, and
|
||||
** kCGNullDirectDisplay isn't defined.
|
||||
*/
|
||||
if (CGMainDisplayID() == 0) {
|
||||
rv = Py_False;
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
if (GetCurrentProcess(&psn) < 0 ||
|
||||
SetFrontProcess(&psn) < 0) {
|
||||
rv = Py_False;
|
||||
} else {
|
||||
rv = Py_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
Py_INCREF(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static char GetTicks_doc[] = "Return number of ticks since bootup";
|
||||
|
||||
static PyObject *
|
||||
MacOS_GetTicks(PyObject *self, PyObject *args)
|
||||
{
|
||||
return Py_BuildValue("i", (int)TickCount());
|
||||
}
|
||||
|
||||
static char openrf_doc[] = "Open resource fork of a file";
|
||||
|
||||
static PyObject *
|
||||
MacOS_openrf(PyObject *self, PyObject *args)
|
||||
{
|
||||
OSErr err;
|
||||
char *mode = "r";
|
||||
FSRef ref;
|
||||
SInt8 permission = fsRdPerm;
|
||||
rfobject *fp;
|
||||
HFSUniStr255 name;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSRef, &ref, &mode))
|
||||
return NULL;
|
||||
while (*mode) {
|
||||
switch (*mode++) {
|
||||
case '*': break;
|
||||
case 'r': permission = fsRdPerm; break;
|
||||
case 'w': permission = fsWrPerm; break;
|
||||
case 'b': break;
|
||||
default:
|
||||
PyErr_BadArgument();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
err = FSGetResourceForkName(&name);
|
||||
if (err != noErr) {
|
||||
PyMac_Error(err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( (fp = newrfobject()) == NULL )
|
||||
return NULL;
|
||||
|
||||
|
||||
err = FSOpenFork(&ref, name.length, name.unicode, permission, &fp->fRefNum);
|
||||
if (err != noErr) {
|
||||
Py_DECREF(fp);
|
||||
PyMac_Error(err);
|
||||
return NULL;
|
||||
}
|
||||
fp->isclosed = 0;
|
||||
return (PyObject *)fp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyMethodDef MacOS_Methods[] = {
|
||||
{"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
|
||||
{"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
|
||||
{"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
|
||||
{"openrf", MacOS_openrf, 1, openrf_doc},
|
||||
#ifndef __LP64__
|
||||
{"splash", MacOS_splash, 1, splash_doc},
|
||||
{"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
|
||||
{"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
|
||||
#endif /* __LP64__ */
|
||||
{"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
|
||||
{"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc},
|
||||
{NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
initMacOS(void)
|
||||
{
|
||||
PyObject *m, *d;
|
||||
|
||||
if (PyErr_WarnPy3k("In 3.x, the MacOS module is removed.", 1))
|
||||
return;
|
||||
|
||||
m = Py_InitModule("MacOS", MacOS_Methods);
|
||||
d = PyModule_GetDict(m);
|
||||
|
||||
/* Initialize MacOS.Error exception */
|
||||
MacOS_Error = PyMac_GetOSErrException();
|
||||
if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
|
||||
return;
|
||||
Rftype.ob_type = &PyType_Type;
|
||||
Py_INCREF(&Rftype);
|
||||
if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
|
||||
return;
|
||||
/*
|
||||
** This is a hack: the following constant added to the id() of a string
|
||||
** object gives you the address of the data. Unfortunately, it is needed for
|
||||
** some of the image and sound processing interfaces on the mac:-(
|
||||
*/
|
||||
{
|
||||
PyStringObject *p = 0;
|
||||
long off = (long)&(p->ob_sval[0]);
|
||||
|
||||
if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
|
||||
return;
|
||||
}
|
||||
#define PY_RUNTIMEMODEL "macho"
|
||||
if (PyDict_SetItemString(d, "runtimemodel",
|
||||
Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
|
||||
return;
|
||||
#if defined(WITH_NEXT_FRAMEWORK)
|
||||
#define PY_LINKMODEL "framework"
|
||||
#elif defined(Py_ENABLE_SHARED)
|
||||
#define PY_LINKMODEL "shared"
|
||||
#else
|
||||
#define PY_LINKMODEL "static"
|
||||
#endif
|
||||
if (PyDict_SetItemString(d, "linkmodel",
|
||||
Py_BuildValue("s", PY_LINKMODEL)) != 0)
|
||||
return;
|
||||
|
||||
}
|
||||
967
Mac/Modules/Nav.c
Normal file
@@ -0,0 +1,967 @@
|
||||
/***********************************************************
|
||||
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
|
||||
The Netherlands.
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the names of Stichting Mathematisch
|
||||
Centrum or CWI or Corporation for National Research Initiatives or
|
||||
CNRI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
While CWI is the initial source for this software, a modified version
|
||||
is made available by the Corporation for National Research Initiatives
|
||||
(CNRI) at the Internet address ftp://ftp.python.org.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
|
||||
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include "Python.h"
|
||||
#include "pymactoolbox.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#ifndef __LP64__
|
||||
|
||||
static PyObject *ErrorObject;
|
||||
|
||||
static NavEventUPP my_eventProcUPP;
|
||||
static NavPreviewUPP my_previewProcUPP;
|
||||
static NavObjectFilterUPP my_filterProcUPP;
|
||||
|
||||
/* Callback functions */
|
||||
static pascal void
|
||||
my_eventProc(NavEventCallbackMessage callBackSelector,
|
||||
NavCBRecPtr callBackParms,
|
||||
NavCallBackUserData callbackUD)
|
||||
{
|
||||
PyObject *dict = (PyObject *)callbackUD;
|
||||
PyObject *pyfunc;
|
||||
PyObject *rv;
|
||||
|
||||
if (!dict) return;
|
||||
if ( (pyfunc = PyDict_GetItemString(dict, "eventProc")) == NULL ) {
|
||||
PyErr_Print();
|
||||
return;
|
||||
}
|
||||
if ( pyfunc == Py_None ) {
|
||||
return;
|
||||
}
|
||||
rv = PyObject_CallFunction(pyfunc, "ls#", (long)callBackSelector,
|
||||
(void *)callBackParms, sizeof(NavCBRec));
|
||||
if ( rv )
|
||||
Py_DECREF(rv);
|
||||
else {
|
||||
PySys_WriteStderr("Nav: exception in eventProc callback\n");
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
|
||||
static pascal Boolean
|
||||
my_previewProc(NavCBRecPtr callBackParms,
|
||||
NavCallBackUserData callbackUD)
|
||||
{
|
||||
PyObject *dict = (PyObject *)callbackUD;
|
||||
PyObject *pyfunc;
|
||||
PyObject *rv;
|
||||
Boolean c_rv = false;
|
||||
|
||||
if (!dict) return false;
|
||||
if ( (pyfunc = PyDict_GetItemString(dict, "previewProc")) == NULL ) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
rv = PyObject_CallFunction(pyfunc, "s#", (void *)callBackParms, sizeof(NavCBRec));
|
||||
if ( rv ) {
|
||||
c_rv = PyObject_IsTrue(rv);
|
||||
Py_DECREF(rv);
|
||||
} else {
|
||||
PySys_WriteStderr("Nav: exception in previewProc callback\n");
|
||||
PyErr_Print();
|
||||
}
|
||||
return c_rv;
|
||||
}
|
||||
|
||||
static pascal Boolean
|
||||
my_filterProc(AEDesc *theItem, void *info,
|
||||
NavCallBackUserData callbackUD,
|
||||
NavFilterModes filterMode)
|
||||
{
|
||||
PyObject *dict = (PyObject *)callbackUD;
|
||||
PyObject *pyfunc;
|
||||
PyObject *rv;
|
||||
Boolean c_rv = false;
|
||||
|
||||
if (!dict) return false;
|
||||
if ( (pyfunc = PyDict_GetItemString(dict, "filterProc")) == NULL ) {
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
rv = PyObject_CallFunction(pyfunc, "O&s#h",
|
||||
AEDesc_NewBorrowed, theItem, info, sizeof(NavFileOrFolderInfo), (short)filterMode);
|
||||
if ( rv ) {
|
||||
c_rv = PyObject_IsTrue(rv);
|
||||
Py_DECREF(rv);
|
||||
} else {
|
||||
PySys_WriteStderr("Nav: exception in filterProc callback\n");
|
||||
PyErr_Print();
|
||||
}
|
||||
return c_rv;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
static int
|
||||
filldialogoptions(PyObject *d,
|
||||
AEDesc **defaultLocationP,
|
||||
NavDialogOptions *opt,
|
||||
NavEventUPP *eventProcP,
|
||||
NavPreviewUPP *previewProcP,
|
||||
NavObjectFilterUPP *filterProcP,
|
||||
NavTypeListHandle *typeListP,
|
||||
OSType *fileTypeP,
|
||||
OSType *fileCreatorP)
|
||||
{
|
||||
Py_ssize_t pos = 0;
|
||||
PyObject *key, *value;
|
||||
char *keystr;
|
||||
AEDesc *defaultLocation_storage;
|
||||
|
||||
NavGetDefaultDialogOptions(opt);
|
||||
|
||||
while ( PyDict_Next(d, &pos, &key, &value) ) {
|
||||
if ( !key || !value || !PyString_Check(key) ) {
|
||||
PyErr_SetString(ErrorObject, "DialogOption has non-string key");
|
||||
return 0;
|
||||
}
|
||||
keystr = PyString_AsString(key);
|
||||
if( strcmp(keystr, "defaultLocation") == 0 ) {
|
||||
if ( (defaultLocation_storage = PyMem_NEW(AEDesc, 1)) == NULL ) {
|
||||
PyErr_NoMemory();
|
||||
return 0;
|
||||
}
|
||||
if ( !PyArg_Parse(value, "O&", AEDesc_Convert, defaultLocation_storage) ) {
|
||||
PyMem_DEL(defaultLocation_storage);
|
||||
return 0;
|
||||
}
|
||||
*defaultLocationP = defaultLocation_storage;
|
||||
} else if( strcmp(keystr, "version") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "H", &opt->version) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "dialogOptionFlags") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "k", &opt->dialogOptionFlags) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "location") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetPoint, &opt->location) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "clientName") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetStr255, &opt->clientName) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "windowTitle") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetStr255, &opt->windowTitle) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "actionButtonLabel") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetStr255, &opt->actionButtonLabel) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "cancelButtonLabel") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetStr255, &opt->cancelButtonLabel) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "savedFileName") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetStr255, &opt->savedFileName) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "message") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetStr255, &opt->message) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "preferenceKey") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetOSType, &opt->preferenceKey) )
|
||||
return 0;
|
||||
} else if( strcmp(keystr, "popupExtension") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", ResObj_Convert, &opt->popupExtension) )
|
||||
return 0;
|
||||
} else if( eventProcP && strcmp(keystr, "eventProc") == 0 ) {
|
||||
*eventProcP = my_eventProcUPP;
|
||||
} else if( previewProcP && strcmp(keystr, "previewProc") == 0 ) {
|
||||
*previewProcP = my_previewProcUPP;
|
||||
} else if( filterProcP && strcmp(keystr, "filterProc") == 0 ) {
|
||||
*filterProcP = my_filterProcUPP;
|
||||
} else if( typeListP && strcmp(keystr, "typeList") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", ResObj_Convert, typeListP) )
|
||||
return 0;
|
||||
} else if( fileTypeP && strcmp(keystr, "fileType") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetOSType, fileTypeP) )
|
||||
return 0;
|
||||
} else if( fileCreatorP && strcmp(keystr, "fileCreator") == 0 ) {
|
||||
if ( !PyArg_Parse(value, "O&", PyMac_GetOSType, fileCreatorP) )
|
||||
return 0;
|
||||
} else {
|
||||
PyErr_Format(ErrorObject, "Unknown DialogOption key: %s", keystr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
/* Declarations for objects of type NavReplyRecord */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
NavReplyRecord itself;
|
||||
} navrrobject;
|
||||
|
||||
static PyTypeObject Navrrtype;
|
||||
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
static char nav_NavTranslateFile__doc__[] =
|
||||
"(NavTranslationOptions)->None"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavTranslateFile(navrrobject *self, PyObject *args)
|
||||
{
|
||||
NavTranslationOptions howToTranslate;
|
||||
OSErr err;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "k", &howToTranslate))
|
||||
return NULL;
|
||||
err = NavTranslateFile(&self->itself, howToTranslate);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static char nav_NavCompleteSave__doc__[] =
|
||||
"(NavTranslationOptions)->None"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavCompleteSave(navrrobject *self, PyObject *args)
|
||||
{
|
||||
NavTranslationOptions howToTranslate;
|
||||
OSErr err;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "k", &howToTranslate))
|
||||
return NULL;
|
||||
err = NavCompleteSave(&self->itself, howToTranslate);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static struct PyMethodDef navrr_methods[] = {
|
||||
{"NavTranslateFile", (PyCFunction)nav_NavTranslateFile, METH_VARARGS, nav_NavTranslateFile__doc__},
|
||||
{"NavCompleteSave", (PyCFunction)nav_NavCompleteSave, METH_VARARGS, nav_NavCompleteSave__doc__},
|
||||
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
/* ---------- */
|
||||
|
||||
|
||||
static navrrobject *
|
||||
newnavrrobject(NavReplyRecord *itself)
|
||||
{
|
||||
navrrobject *self;
|
||||
|
||||
self = PyObject_NEW(navrrobject, &Navrrtype);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
self->itself = *itself;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
navrr_dealloc(navrrobject *self)
|
||||
{
|
||||
NavDisposeReply(&self->itself);
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
navrr_getattr(navrrobject *self, char *name)
|
||||
{
|
||||
FSRef fsr;
|
||||
FSSpec fss;
|
||||
|
||||
if( strcmp(name, "__members__") == 0 )
|
||||
return Py_BuildValue(
|
||||
"ssssssssss",
|
||||
"version", "validRecord", "replacing",
|
||||
"isStationery", "translationNeeded",
|
||||
"selection",
|
||||
"selection_fsr",
|
||||
"fileTranslation", "keyScript", "saveFileName");
|
||||
|
||||
if( strcmp(name, "version") == 0 )
|
||||
return Py_BuildValue("h", self->itself.version);
|
||||
if( strcmp(name, "validRecord") == 0 )
|
||||
return Py_BuildValue("l", (long)self->itself.validRecord);
|
||||
if( strcmp(name, "replacing") == 0 )
|
||||
return Py_BuildValue("l", (long)self->itself.replacing);
|
||||
if( strcmp(name, "isStationery") == 0 )
|
||||
return Py_BuildValue("l", (long)self->itself.isStationery);
|
||||
if( strcmp(name, "translationNeeded") == 0 )
|
||||
return Py_BuildValue("l", (long)self->itself.translationNeeded);
|
||||
if( strcmp(name, "selection") == 0 ) {
|
||||
SInt32 i;
|
||||
long count;
|
||||
OSErr err;
|
||||
PyObject *rv, *rvitem;
|
||||
AEDesc desc;
|
||||
|
||||
if ((err=AECountItems(&self->itself.selection, &count))) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
if ( (rv=PyList_New(count)) == NULL )
|
||||
return NULL;
|
||||
for(i=0; i<count; i++) {
|
||||
desc.dataHandle = NULL;
|
||||
if ((err=AEGetNthDesc(&self->itself.selection, i+1, typeFSS, NULL, &desc))) {
|
||||
Py_DECREF(rv);
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
if ((err=AEGetDescData(&desc, &fss, sizeof(FSSpec)))) {
|
||||
Py_DECREF(rv);
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
rvitem = PyMac_BuildFSSpec(&fss);
|
||||
PyList_SetItem(rv, i, rvitem);
|
||||
AEDisposeDesc(&desc);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
if( strcmp(name, "selection_fsr") == 0 ) {
|
||||
SInt32 i;
|
||||
long count;
|
||||
OSErr err;
|
||||
PyObject *rv, *rvitem;
|
||||
AEDesc desc;
|
||||
|
||||
if ((err=AECountItems(&self->itself.selection, &count))) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
if ( (rv=PyList_New(count)) == NULL )
|
||||
return NULL;
|
||||
for(i=0; i<count; i++) {
|
||||
desc.dataHandle = NULL;
|
||||
if ((err=AEGetNthDesc(&self->itself.selection, i+1, typeFSRef, NULL, &desc))) {
|
||||
Py_DECREF(rv);
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
if ((err=AEGetDescData(&desc, &fsr, sizeof(FSRef)))) {
|
||||
Py_DECREF(rv);
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
rvitem = PyMac_BuildFSRef(&fsr);
|
||||
PyList_SetItem(rv, i, rvitem);
|
||||
AEDisposeDesc(&desc);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
if( strcmp(name, "fileTranslation") == 0 )
|
||||
return ResObj_New((Handle)self->itself.fileTranslation);
|
||||
if( strcmp(name, "keyScript") == 0 )
|
||||
return Py_BuildValue("h", (short)self->itself.keyScript);
|
||||
if( strcmp(name, "saveFileName") == 0 )
|
||||
return Py_BuildValue("O&", CFStringRefObj_New, self->itself.saveFileName);
|
||||
|
||||
|
||||
return Py_FindMethod(navrr_methods, (PyObject *)self, name);
|
||||
}
|
||||
|
||||
static int
|
||||
navrr_setattr(navrrobject *self, char *name, PyObject *v)
|
||||
{
|
||||
/* Set attribute 'name' to value 'v'. v==NULL means delete */
|
||||
|
||||
/* XXXX Add your own setattr code here */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char Navrrtype__doc__[] =
|
||||
"Record containing result of a Nav file selection call. Use dir() for member names."
|
||||
;
|
||||
|
||||
static PyTypeObject Navrrtype = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0, /*ob_size*/
|
||||
"Nav.NavReplyRecord", /*tp_name*/
|
||||
sizeof(navrrobject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)navrr_dealloc, /*tp_dealloc*/
|
||||
(printfunc)0, /*tp_print*/
|
||||
(getattrfunc)navrr_getattr, /*tp_getattr*/
|
||||
(setattrfunc)navrr_setattr, /*tp_setattr*/
|
||||
(cmpfunc)0, /*tp_compare*/
|
||||
(reprfunc)0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
(hashfunc)0, /*tp_hash*/
|
||||
(ternaryfunc)0, /*tp_call*/
|
||||
(reprfunc)0, /*tp_str*/
|
||||
|
||||
/* Space for future expansion */
|
||||
0L,0L,0L,0L,
|
||||
Navrrtype__doc__ /* Documentation string */
|
||||
};
|
||||
|
||||
/* End of code for NavReplyRecord objects */
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
static char nav_NavGetFile__doc__[] =
|
||||
"(DialogOptions dict or kwargs+defaultLocation,eventProc,previewProc,filterProc,typeList) -> NavReplyRecord"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavGetFile(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
AEDesc *defaultLocation = NULL;
|
||||
NavReplyRecord reply;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavEventUPP eventProc = NULL;
|
||||
NavPreviewUPP previewProc = NULL;
|
||||
NavObjectFilterUPP filterProc = NULL;
|
||||
NavTypeListHandle typeList = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, &defaultLocation, &dialogOptions, &eventProc, &previewProc, &filterProc, &typeList, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavGetFile(defaultLocation, &reply, &dialogOptions,
|
||||
eventProc, previewProc, filterProc, typeList, (void *)dict);
|
||||
PyMem_DEL(defaultLocation);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return (PyObject *)newnavrrobject(&reply);
|
||||
}
|
||||
|
||||
static char nav_NavPutFile__doc__[] =
|
||||
"(DialogOptions dict or kwargs+defaultLocation,eventProc,fileCreator,fileType) -> NavReplyRecord"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavPutFile(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
AEDesc *defaultLocation = NULL;
|
||||
NavReplyRecord reply;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavEventUPP eventProc = NULL;
|
||||
OSType fileType;
|
||||
OSType fileCreator;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, &defaultLocation, &dialogOptions, &eventProc, NULL, NULL, NULL, &fileType, &fileCreator))
|
||||
return NULL;
|
||||
err = NavPutFile(defaultLocation, &reply, &dialogOptions,
|
||||
eventProc, fileType, fileCreator, (void *)dict);
|
||||
PyMem_DEL(defaultLocation);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return (PyObject *)newnavrrobject(&reply);
|
||||
}
|
||||
|
||||
static char nav_NavAskSaveChanges__doc__[] =
|
||||
"(NavAskSaveChangesAction, DialogOptions dict or kwargs+eventProc) -> NavAskSaveChangesResult"
|
||||
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavAskSaveChanges(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavAskSaveChangesAction action;
|
||||
NavAskSaveChangesResult reply;
|
||||
NavEventUPP eventProc = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, "k", &action))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "lO!", &action, &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, NULL, &dialogOptions, &eventProc, NULL, NULL, NULL, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavAskSaveChanges(&dialogOptions, action, &reply, eventProc, (void *)dict);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)reply);
|
||||
}
|
||||
|
||||
static char nav_NavCustomAskSaveChanges__doc__[] =
|
||||
"(DialogOptions dict or kwargs+eventProc) -> NavAskSaveChangesResult"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavCustomAskSaveChanges(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavAskSaveChangesResult reply;
|
||||
NavEventUPP eventProc = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, NULL, &dialogOptions, &eventProc, NULL, NULL, NULL, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavCustomAskSaveChanges(&dialogOptions, &reply, eventProc, (void *)dict);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)reply);
|
||||
}
|
||||
|
||||
static char nav_NavAskDiscardChanges__doc__[] =
|
||||
"(DialogOptions dict or kwargs+eventProc) -> NavAskSaveChangesResult"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavAskDiscardChanges(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavAskSaveChangesResult reply;
|
||||
NavEventUPP eventProc = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, NULL, &dialogOptions, &eventProc, NULL, NULL, NULL, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavAskDiscardChanges(&dialogOptions, &reply, eventProc, (void *)dict);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)reply);
|
||||
}
|
||||
|
||||
static char nav_NavChooseFile__doc__[] =
|
||||
"(DialogOptions dict or kwargs+defaultLocation,eventProc,previewProc,filterProc,typeList) -> NavReplyRecord"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavChooseFile(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
AEDesc *defaultLocation = NULL;
|
||||
NavReplyRecord reply;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavEventUPP eventProc = NULL;
|
||||
NavPreviewUPP previewProc = NULL;
|
||||
NavObjectFilterUPP filterProc = NULL;
|
||||
NavTypeListHandle typeList = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, &defaultLocation, &dialogOptions, &eventProc, &previewProc, &filterProc, &typeList, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavChooseFile(defaultLocation, &reply, &dialogOptions,
|
||||
eventProc, previewProc, filterProc, typeList, (void *)dict);
|
||||
PyMem_DEL(defaultLocation);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return (PyObject *)newnavrrobject(&reply);
|
||||
}
|
||||
|
||||
static char nav_NavChooseFolder__doc__[] =
|
||||
"(DialogOptions dict or kwargs+defaultLocation,eventProc,filterProc) -> NavReplyRecord"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavChooseFolder(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
AEDesc *defaultLocation = NULL;
|
||||
NavReplyRecord reply;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavEventUPP eventProc = NULL;
|
||||
NavObjectFilterUPP filterProc = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, &defaultLocation, &dialogOptions, &eventProc, NULL, &filterProc, NULL, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavChooseFolder(defaultLocation, &reply, &dialogOptions,
|
||||
eventProc, filterProc, (void *)dict);
|
||||
PyMem_DEL(defaultLocation);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return (PyObject *)newnavrrobject(&reply);
|
||||
}
|
||||
|
||||
static char nav_NavChooseVolume__doc__[] =
|
||||
"(DialogOptions dict or kwargs+defaultLocation,eventProc,filterProc) -> NavReplyRecord"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavChooseVolume(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
AEDesc *defaultLocation = NULL;
|
||||
NavReplyRecord reply;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavEventUPP eventProc = NULL;
|
||||
NavObjectFilterUPP filterProc = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, &defaultLocation, &dialogOptions, &eventProc, NULL, &filterProc, NULL, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavChooseVolume(defaultLocation, &reply, &dialogOptions,
|
||||
eventProc, filterProc, (void *)dict);
|
||||
PyMem_DEL(defaultLocation);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return (PyObject *)newnavrrobject(&reply);
|
||||
}
|
||||
|
||||
static char nav_NavChooseObject__doc__[] =
|
||||
"(DialogOptions dict or kwargs+defaultLocation,eventProc,filterProc) -> NavReplyRecord"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavChooseObject(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
AEDesc *defaultLocation = NULL;
|
||||
NavReplyRecord reply;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavEventUPP eventProc = NULL;
|
||||
NavObjectFilterUPP filterProc = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, &defaultLocation, &dialogOptions, &eventProc, NULL, &filterProc, NULL, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavChooseObject(defaultLocation, &reply, &dialogOptions,
|
||||
eventProc, filterProc, (void *)dict);
|
||||
PyMem_DEL(defaultLocation);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return (PyObject *)newnavrrobject(&reply);
|
||||
}
|
||||
|
||||
static char nav_NavNewFolder__doc__[] =
|
||||
"(DialogOptions dict or kwargs+defaultLocation,eventProc) -> NavReplyRecord"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavNewFolder(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *dict;
|
||||
AEDesc *defaultLocation = NULL;
|
||||
NavReplyRecord reply;
|
||||
NavDialogOptions dialogOptions;
|
||||
NavEventUPP eventProc = NULL;
|
||||
OSErr err;
|
||||
|
||||
if ( kw && PyObject_IsTrue(kw) ) {
|
||||
if (!PyArg_ParseTuple(args, ";either keyword arguments or dictionary expected"))
|
||||
return NULL;
|
||||
dict = kw;
|
||||
} else if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
|
||||
return NULL;
|
||||
if (!filldialogoptions(dict, &defaultLocation, &dialogOptions, &eventProc, NULL, NULL, NULL, NULL, NULL))
|
||||
return NULL;
|
||||
err = NavNewFolder(defaultLocation, &reply, &dialogOptions, eventProc, (void *)dict);
|
||||
PyMem_DEL(defaultLocation);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return (PyObject *)newnavrrobject(&reply);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* XXXX I don't know what to do with the void * argument */
|
||||
static char nav_NavCustomControl__doc__[] =
|
||||
""
|
||||
;
|
||||
|
||||
|
||||
static PyObject *
|
||||
nav_NavCustomControl(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char nav_NavServicesCanRun__doc__[] =
|
||||
"()->int"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavServicesCanRun(PyObject *self, PyObject *args)
|
||||
{
|
||||
Boolean rv;
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
rv = NavServicesCanRun();
|
||||
return Py_BuildValue("l", (long)rv);
|
||||
}
|
||||
|
||||
static char nav_NavServicesAvailable__doc__[] =
|
||||
"()->int"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavServicesAvailable(PyObject *self, PyObject *args)
|
||||
{
|
||||
Boolean rv;
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
rv = NavServicesAvailable();
|
||||
return Py_BuildValue("l", (long)rv);
|
||||
}
|
||||
/* XX */
|
||||
static char nav_NavLoad__doc__[] =
|
||||
"()->None"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavLoad(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
NavLoad();
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static char nav_NavUnload__doc__[] =
|
||||
"()->None"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavUnload(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
NavUnload();
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static char nav_NavLibraryVersion__doc__[] =
|
||||
"()->int"
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavLibraryVersion(PyObject *self, PyObject *args)
|
||||
{
|
||||
UInt32 rv;
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
rv = NavLibraryVersion();
|
||||
return Py_BuildValue("l", (long)rv);
|
||||
}
|
||||
|
||||
static char nav_NavGetDefaultDialogOptions__doc__[] =
|
||||
"()->dict\nPass dict or keyword args with same names to other calls."
|
||||
;
|
||||
|
||||
static PyObject *
|
||||
nav_NavGetDefaultDialogOptions(PyObject *self, PyObject *args)
|
||||
{
|
||||
NavDialogOptions dialogOptions;
|
||||
OSErr err;
|
||||
|
||||
err = NavGetDefaultDialogOptions(&dialogOptions);
|
||||
if ( err ) {
|
||||
PyErr_Mac(ErrorObject, err);
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue(
|
||||
"{s:h,s:l,s:O&,s:O&,s:O&,s:O&,s:O&,s:O&,s:O&,s:O&,s:O&}",
|
||||
"version", dialogOptions.version,
|
||||
"dialogOptionFlags", dialogOptions.dialogOptionFlags,
|
||||
"location", PyMac_BuildPoint, dialogOptions.location,
|
||||
"clientName", PyMac_BuildStr255, &dialogOptions.clientName,
|
||||
"windowTitle", PyMac_BuildStr255, &dialogOptions.windowTitle,
|
||||
"actionButtonLabel", PyMac_BuildStr255, &dialogOptions.actionButtonLabel,
|
||||
"cancelButtonLabel", PyMac_BuildStr255, &dialogOptions.cancelButtonLabel,
|
||||
"savedFileName", PyMac_BuildStr255, &dialogOptions.savedFileName,
|
||||
"message", PyMac_BuildStr255, &dialogOptions.message,
|
||||
"preferenceKey", PyMac_BuildOSType, dialogOptions.preferenceKey
|
||||
,"popupExtension", OptResObj_New, dialogOptions.popupExtension
|
||||
);
|
||||
}
|
||||
|
||||
/* List of methods defined in the module */
|
||||
|
||||
static struct PyMethodDef nav_methods[] = {
|
||||
{"NavGetFile", (PyCFunction)nav_NavGetFile, METH_VARARGS|METH_KEYWORDS, nav_NavGetFile__doc__},
|
||||
{"NavPutFile", (PyCFunction)nav_NavPutFile, METH_VARARGS|METH_KEYWORDS, nav_NavPutFile__doc__},
|
||||
{"NavAskSaveChanges", (PyCFunction)nav_NavAskSaveChanges, METH_VARARGS|METH_KEYWORDS, nav_NavAskSaveChanges__doc__},
|
||||
{"NavCustomAskSaveChanges", (PyCFunction)nav_NavCustomAskSaveChanges, METH_VARARGS|METH_KEYWORDS, nav_NavCustomAskSaveChanges__doc__},
|
||||
{"NavAskDiscardChanges", (PyCFunction)nav_NavAskDiscardChanges, METH_VARARGS|METH_KEYWORDS, nav_NavAskDiscardChanges__doc__},
|
||||
{"NavChooseFile", (PyCFunction)nav_NavChooseFile, METH_VARARGS|METH_KEYWORDS, nav_NavChooseFile__doc__},
|
||||
{"NavChooseFolder", (PyCFunction)nav_NavChooseFolder, METH_VARARGS|METH_KEYWORDS, nav_NavChooseFolder__doc__},
|
||||
{"NavChooseVolume", (PyCFunction)nav_NavChooseVolume, METH_VARARGS|METH_KEYWORDS, nav_NavChooseVolume__doc__},
|
||||
{"NavChooseObject", (PyCFunction)nav_NavChooseObject, METH_VARARGS|METH_KEYWORDS, nav_NavChooseObject__doc__},
|
||||
{"NavNewFolder", (PyCFunction)nav_NavNewFolder, METH_VARARGS|METH_KEYWORDS, nav_NavNewFolder__doc__},
|
||||
#if 0
|
||||
{"NavCustomControl", (PyCFunction)nav_NavCustomControl, METH_VARARGS, nav_NavCustomControl__doc__},
|
||||
#endif
|
||||
{"NavServicesCanRun", (PyCFunction)nav_NavServicesCanRun, METH_VARARGS, nav_NavServicesCanRun__doc__},
|
||||
{"NavServicesAvailable", (PyCFunction)nav_NavServicesAvailable, METH_VARARGS, nav_NavServicesAvailable__doc__},
|
||||
{"NavLoad", (PyCFunction)nav_NavLoad, METH_VARARGS, nav_NavLoad__doc__},
|
||||
{"NavUnload", (PyCFunction)nav_NavUnload, METH_VARARGS, nav_NavUnload__doc__},
|
||||
{"NavLibraryVersion", (PyCFunction)nav_NavLibraryVersion, METH_VARARGS, nav_NavLibraryVersion__doc__},
|
||||
{"NavGetDefaultDialogOptions", (PyCFunction)nav_NavGetDefaultDialogOptions, METH_VARARGS, nav_NavGetDefaultDialogOptions__doc__},
|
||||
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
||||
/* Initialization function for the module (*must* be called initNav) */
|
||||
|
||||
static char Nav_module_documentation[] =
|
||||
"Interface to Navigation Services\n"
|
||||
"Most calls accept a NavDialogOptions dictionary or keywords with the same names, pass {}\n"
|
||||
"if you want the default options.\n"
|
||||
"Use NavGetDefaultDialogOptions() to find out common option names.\n"
|
||||
"See individual docstrings for additional keyword args/dictentries supported by each call.\n"
|
||||
"Pass None as eventProc to get movable-modal dialogs that process updates through the standard Python mechanism."
|
||||
;
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
|
||||
void
|
||||
initNav(void)
|
||||
{
|
||||
#ifdef __LP64__
|
||||
PyErr_SetString(PyExc_ImportError, "Navigation Services not available in 64-bit mode");
|
||||
return;
|
||||
|
||||
#else /* !__LP64__ */
|
||||
PyObject *m, *d;
|
||||
|
||||
if (PyErr_WarnPy3k("In 3.x, the Nav module is removed.", 1))
|
||||
return;
|
||||
|
||||
/* Test that we have NavServices */
|
||||
if ( !NavServicesAvailable() ) {
|
||||
PyErr_SetString(PyExc_ImportError, "Navigation Services not available");
|
||||
return;
|
||||
}
|
||||
/* Create the module and add the functions */
|
||||
m = Py_InitModule4("Nav", nav_methods,
|
||||
Nav_module_documentation,
|
||||
(PyObject*)NULL,PYTHON_API_VERSION);
|
||||
|
||||
/* Add some symbolic constants to the module */
|
||||
d = PyModule_GetDict(m);
|
||||
ErrorObject = PyString_FromString("Nav.error");
|
||||
PyDict_SetItemString(d, "error", ErrorObject);
|
||||
|
||||
/* XXXX Add constants here */
|
||||
|
||||
/* Set UPPs */
|
||||
my_eventProcUPP = NewNavEventUPP(my_eventProc);
|
||||
my_previewProcUPP = NewNavPreviewUPP(my_previewProc);
|
||||
my_filterProcUPP = NewNavObjectFilterUPP(my_filterProc);
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
}
|
||||
|
||||
102
Mac/Modules/OSATerminology.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
** An interface to the application scripting related functions of the OSA API.
|
||||
**
|
||||
** GetAppTerminology - given an FSSpec/posix path to an application,
|
||||
** returns its aevt (scripting terminology) resource(s)
|
||||
**
|
||||
** GetSysTerminology - returns the AppleScript language component's
|
||||
** aeut (scripting terminology) resource
|
||||
**
|
||||
** Written by Donovan Preston and slightly modified by Jack and HAS.
|
||||
*/
|
||||
#include "Python.h"
|
||||
#include "pymactoolbox.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#if APPLE_SUPPORTS_QUICKTIME
|
||||
static PyObject *
|
||||
PyOSA_GetAppTerminology(PyObject* self, PyObject* args)
|
||||
{
|
||||
AEDesc theDesc = {0,0};
|
||||
FSSpec fss;
|
||||
ComponentInstance defaultComponent = NULL;
|
||||
SInt16 defaultTerminology = 0;
|
||||
Boolean didLaunch = 0;
|
||||
OSAError err;
|
||||
long modeFlags = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O&|i", PyMac_GetFSSpec, &fss, &modeFlags))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
** Note that we have to use the AppleScript component here. Who knows why
|
||||
** OSAGetAppTerminology should require a scripting component in the
|
||||
** first place, but it does. Note: doesn't work with the generic scripting
|
||||
** component, which is unfortunate as the AS component is currently very
|
||||
** slow (~1 sec?) to load, but we just have to live with this.
|
||||
*/
|
||||
defaultComponent = OpenDefaultComponent (kOSAComponentType, 'ascr');
|
||||
err = GetComponentInstanceError (defaultComponent);
|
||||
if (err) return PyMac_Error(err);
|
||||
err = OSAGetAppTerminology (
|
||||
defaultComponent,
|
||||
kOSAModeNull,
|
||||
&fss,
|
||||
defaultTerminology,
|
||||
&didLaunch,
|
||||
&theDesc
|
||||
);
|
||||
if (err) return PyMac_Error(err);
|
||||
return Py_BuildValue("O&i", AEDesc_New, &theDesc, didLaunch);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyOSA_GetSysTerminology(PyObject* self, PyObject* args)
|
||||
{
|
||||
AEDesc theDesc = {0,0};
|
||||
ComponentInstance defaultComponent = NULL;
|
||||
SInt16 defaultTerminology = 0;
|
||||
OSAError err;
|
||||
|
||||
/* Accept any args for sake of backwards compatibility, then ignore them. */
|
||||
|
||||
defaultComponent = OpenDefaultComponent (kOSAComponentType, 'ascr');
|
||||
err = GetComponentInstanceError (defaultComponent);
|
||||
if (err) return PyMac_Error(err);
|
||||
err = OSAGetSysTerminology (
|
||||
defaultComponent,
|
||||
kOSAModeNull,
|
||||
defaultTerminology,
|
||||
&theDesc
|
||||
);
|
||||
if (err) return PyMac_Error(err);
|
||||
return Py_BuildValue("O&", AEDesc_New, &theDesc);
|
||||
}
|
||||
#endif /* APPLE_SUPPORTS_QUICKTIME */
|
||||
|
||||
/*
|
||||
* List of methods defined in the module
|
||||
*/
|
||||
static struct PyMethodDef OSATerminology_methods[] =
|
||||
{
|
||||
#if APPLE_SUPPORTS_QUICKTIME
|
||||
{"GetAppTerminology",
|
||||
(PyCFunction) PyOSA_GetAppTerminology,
|
||||
METH_VARARGS,
|
||||
"Get an application's terminology. GetAppTerminology(path) --> AEDesc"},
|
||||
{"GetSysTerminology",
|
||||
(PyCFunction) PyOSA_GetSysTerminology,
|
||||
METH_VARARGS,
|
||||
"Get the AppleScript language's terminology. GetSysTerminology() --> AEDesc"},
|
||||
#endif /* APPLE_SUPPORTS_QUICKTIME */
|
||||
{NULL, (PyCFunction) NULL, 0, NULL}
|
||||
};
|
||||
|
||||
void
|
||||
initOSATerminology(void)
|
||||
{
|
||||
if (PyErr_WarnPy3k("In 3.x, the OSATerminology module is removed.", 1) < 0)
|
||||
return;
|
||||
Py_InitModule("OSATerminology", OSATerminology_methods);
|
||||
}
|
||||
231
Mac/Modules/_scproxy.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Helper method for urllib to fetch the proxy configuration settings
|
||||
* using the SystemConfiguration framework.
|
||||
*/
|
||||
#include <Python.h>
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
static int32_t
|
||||
cfnum_to_int32(CFNumberRef num)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
CFNumberGetValue(num, kCFNumberSInt32Type, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
cfstring_to_pystring(CFStringRef ref)
|
||||
{
|
||||
const char* s;
|
||||
|
||||
s = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
|
||||
if (s) {
|
||||
return PyString_FromString(s);
|
||||
|
||||
} else {
|
||||
CFIndex len = CFStringGetLength(ref);
|
||||
Boolean ok;
|
||||
PyObject* result;
|
||||
result = PyString_FromStringAndSize(NULL, len*4);
|
||||
|
||||
ok = CFStringGetCString(ref,
|
||||
PyString_AS_STRING(result),
|
||||
PyString_GET_SIZE(result),
|
||||
kCFStringEncodingUTF8);
|
||||
if (!ok) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
} else {
|
||||
_PyString_Resize(&result,
|
||||
strlen(PyString_AS_STRING(result)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
get_proxy_settings(PyObject* mod __attribute__((__unused__)))
|
||||
{
|
||||
CFDictionaryRef proxyDict = NULL;
|
||||
CFNumberRef aNum = NULL;
|
||||
CFArrayRef anArray = NULL;
|
||||
PyObject* result = NULL;
|
||||
PyObject* v;
|
||||
int r;
|
||||
|
||||
proxyDict = SCDynamicStoreCopyProxies(NULL);
|
||||
if (!proxyDict) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
result = PyDict_New();
|
||||
if (result == NULL) goto error;
|
||||
|
||||
if (&kSCPropNetProxiesExcludeSimpleHostnames != NULL) {
|
||||
aNum = CFDictionaryGetValue(proxyDict,
|
||||
kSCPropNetProxiesExcludeSimpleHostnames);
|
||||
if (aNum == NULL) {
|
||||
v = PyBool_FromLong(0);
|
||||
} else {
|
||||
v = PyBool_FromLong(cfnum_to_int32(aNum));
|
||||
}
|
||||
} else {
|
||||
v = PyBool_FromLong(0);
|
||||
}
|
||||
|
||||
if (v == NULL) goto error;
|
||||
|
||||
r = PyDict_SetItemString(result, "exclude_simple", v);
|
||||
Py_DECREF(v); v = NULL;
|
||||
if (r == -1) goto error;
|
||||
|
||||
anArray = CFDictionaryGetValue(proxyDict,
|
||||
kSCPropNetProxiesExceptionsList);
|
||||
if (anArray != NULL) {
|
||||
CFIndex len = CFArrayGetCount(anArray);
|
||||
CFIndex i;
|
||||
v = PyTuple_New(len);
|
||||
if (v == NULL) goto error;
|
||||
|
||||
r = PyDict_SetItemString(result, "exceptions", v);
|
||||
Py_DECREF(v);
|
||||
if (r == -1) goto error;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
CFStringRef aString = NULL;
|
||||
|
||||
aString = CFArrayGetValueAtIndex(anArray, i);
|
||||
if (aString == NULL) {
|
||||
PyTuple_SetItem(v, i, Py_None);
|
||||
Py_INCREF(Py_None);
|
||||
} else {
|
||||
PyObject* t = cfstring_to_pystring(aString);
|
||||
if (!t) {
|
||||
PyTuple_SetItem(v, i, Py_None);
|
||||
Py_INCREF(Py_None);
|
||||
} else {
|
||||
PyTuple_SetItem(v, i, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(proxyDict);
|
||||
return result;
|
||||
|
||||
error:
|
||||
if (proxyDict) CFRelease(proxyDict);
|
||||
Py_XDECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
set_proxy(PyObject* proxies, char* proto, CFDictionaryRef proxyDict,
|
||||
CFStringRef enabledKey,
|
||||
CFStringRef hostKey, CFStringRef portKey)
|
||||
{
|
||||
CFNumberRef aNum;
|
||||
|
||||
aNum = CFDictionaryGetValue(proxyDict, enabledKey);
|
||||
if (aNum && cfnum_to_int32(aNum)) {
|
||||
CFStringRef hostString;
|
||||
|
||||
hostString = CFDictionaryGetValue(proxyDict, hostKey);
|
||||
aNum = CFDictionaryGetValue(proxyDict, portKey);
|
||||
|
||||
if (hostString) {
|
||||
int r;
|
||||
PyObject* h = cfstring_to_pystring(hostString);
|
||||
PyObject* v;
|
||||
if (h) {
|
||||
if (aNum) {
|
||||
int32_t port = cfnum_to_int32(aNum);
|
||||
v = PyString_FromFormat("http://%s:%ld",
|
||||
PyString_AS_STRING(h),
|
||||
(long)port);
|
||||
} else {
|
||||
v = PyString_FromFormat("http://%s",
|
||||
PyString_AS_STRING(h));
|
||||
}
|
||||
Py_DECREF(h);
|
||||
if (!v) return -1;
|
||||
r = PyDict_SetItemString(proxies, proto,
|
||||
v);
|
||||
Py_DECREF(v);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject*
|
||||
get_proxies(PyObject* mod __attribute__((__unused__)))
|
||||
{
|
||||
PyObject* result = NULL;
|
||||
int r;
|
||||
CFDictionaryRef proxyDict = NULL;
|
||||
|
||||
proxyDict = SCDynamicStoreCopyProxies(NULL);
|
||||
if (proxyDict == NULL) {
|
||||
return PyDict_New();
|
||||
}
|
||||
|
||||
result = PyDict_New();
|
||||
if (result == NULL) goto error;
|
||||
|
||||
r = set_proxy(result, "http", proxyDict,
|
||||
kSCPropNetProxiesHTTPEnable,
|
||||
kSCPropNetProxiesHTTPProxy,
|
||||
kSCPropNetProxiesHTTPPort);
|
||||
if (r == -1) goto error;
|
||||
r = set_proxy(result, "https", proxyDict,
|
||||
kSCPropNetProxiesHTTPSEnable,
|
||||
kSCPropNetProxiesHTTPSProxy,
|
||||
kSCPropNetProxiesHTTPSPort);
|
||||
if (r == -1) goto error;
|
||||
r = set_proxy(result, "ftp", proxyDict,
|
||||
kSCPropNetProxiesFTPEnable,
|
||||
kSCPropNetProxiesFTPProxy,
|
||||
kSCPropNetProxiesFTPPort);
|
||||
if (r == -1) goto error;
|
||||
r = set_proxy(result, "gopher", proxyDict,
|
||||
kSCPropNetProxiesGopherEnable,
|
||||
kSCPropNetProxiesGopherProxy,
|
||||
kSCPropNetProxiesGopherPort);
|
||||
if (r == -1) goto error;
|
||||
|
||||
CFRelease(proxyDict);
|
||||
return result;
|
||||
error:
|
||||
if (proxyDict) CFRelease(proxyDict);
|
||||
Py_XDECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyMethodDef mod_methods[] = {
|
||||
{
|
||||
"_get_proxy_settings",
|
||||
(PyCFunction)get_proxy_settings,
|
||||
METH_NOARGS,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
"_get_proxies",
|
||||
(PyCFunction)get_proxies,
|
||||
METH_NOARGS,
|
||||
NULL,
|
||||
},
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
void init_scproxy(void)
|
||||
{
|
||||
(void)Py_InitModule4("_scproxy", mod_methods, NULL, NULL, PYTHON_API_VERSION);
|
||||
}
|
||||
24
Mac/Modules/ae/README
Normal file
@@ -0,0 +1,24 @@
|
||||
A quick note on what all the files here are, currently (16-7-95),
|
||||
and whether they really are source or generated.
|
||||
|
||||
aegen.py Generated by aescan, temporary file
|
||||
AEModule.c Generated by aescan, from AppleEvents.h
|
||||
AEObjects.py Generated by aescan, from AEObjects.h
|
||||
aepack.py Routines to convert python objects <-> AEDesc record
|
||||
(formerly part of aetools, now imported there)
|
||||
AERegistry.py Generated by aescan, from AERegistry.h
|
||||
aescan.py Program to scan headers and generate AE modules
|
||||
aesupport.py Helper code for aescan
|
||||
aetools.py Routines/classes to create and send appleevents
|
||||
aetypes.py Classes for python objects corresponding to AEDesc types
|
||||
(formerly part of aetools, now imported there)
|
||||
AppleEvents.py Generated by aescan, from AppleEvents.h
|
||||
AppleScript_Suite.py Generated by gensuitemodule
|
||||
echo.py Old test program (may still work) to echo events back to sender
|
||||
gensuitemodule.py Program to scan aete/aeut resources and generate python
|
||||
interface modules
|
||||
Required_Suite.py Generated by gensuitemodule
|
||||
Standard_Suite.py Generated by gensuitemodule
|
||||
tae.py Old test program (may still work) to send an appleevent
|
||||
tell.py Old test program (may still work) to send an appleevent
|
||||
test_suite.py Test program to test bits of the _Suite modules and aetools/etc
|
||||
1459
Mac/Modules/ae/_AEmodule.c
Normal file
97
Mac/Modules/ae/aescan.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# Scan AppleEvents.h header file, generate aegen.py and AppleEvents.py files.
|
||||
# Then run aesupport to generate AEmodule.c.
|
||||
# (Should learn how to tell the compiler to compile it as well.)
|
||||
|
||||
import sys
|
||||
import MacOS
|
||||
|
||||
from bgenlocations import TOOLBOXDIR, BGENDIR
|
||||
sys.path.append(BGENDIR)
|
||||
|
||||
from scantools import Scanner
|
||||
|
||||
def main():
|
||||
print "=== Scanning AEDataModel.h, AppleEvents.h, AERegistry.h, AEObjects.h ==="
|
||||
input = ["AEDataModel.h", "AEInteraction.h", "AppleEvents.h", "AERegistry.h", "AEObjects.h"]
|
||||
output = "aegen.py"
|
||||
defsoutput = TOOLBOXDIR + "AppleEvents.py"
|
||||
scanner = AppleEventsScanner(input, output, defsoutput)
|
||||
scanner.scan()
|
||||
scanner.close()
|
||||
print "=== Testing definitions output code ==="
|
||||
execfile(defsoutput, {}, {})
|
||||
print "=== Done Scanning and Generating, now doing 'import aesupport' ==="
|
||||
import aesupport
|
||||
print "=== Done 'import aesupport'. It's up to you to compile AEmodule.c ==="
|
||||
|
||||
class AppleEventsScanner(Scanner):
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
classname = "AEFunction"
|
||||
listname = "functions"
|
||||
if arglist:
|
||||
t, n, m = arglist[0]
|
||||
if t[-4:] == "_ptr" and m == "InMode" and \
|
||||
t[:-4] in ("AEDesc", "AEAddressDesc", "AEDescList",
|
||||
"AERecord", "AppleEvent"):
|
||||
classname = "AEMethod"
|
||||
listname = "aedescmethods"
|
||||
return classname, listname
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return [
|
||||
"AEDisposeDesc",
|
||||
# "AEGetEventHandler",
|
||||
"AEGetDescData", # Use object.data
|
||||
"AEGetSpecialHandler",
|
||||
# Constants with funny definitions
|
||||
"kAEDontDisposeOnResume",
|
||||
"kAEUseStandardDispatch",
|
||||
]
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return [
|
||||
"ProcPtr",
|
||||
"AEArrayType",
|
||||
"AECoercionHandlerUPP",
|
||||
"UniversalProcPtr",
|
||||
"OSLCompareUPP",
|
||||
"OSLAccessorUPP",
|
||||
]
|
||||
|
||||
def makerepairinstructions(self):
|
||||
return [
|
||||
([("Boolean", "isSysHandler", "InMode")],
|
||||
[("AlwaysFalse", "*", "*")]),
|
||||
|
||||
([("void_ptr", "*", "InMode"), ("Size", "*", "InMode")],
|
||||
[("InBuffer", "*", "*")]),
|
||||
|
||||
([("EventHandlerProcPtr", "*", "InMode"), ("long", "*", "InMode")],
|
||||
[("EventHandler", "*", "*")]),
|
||||
|
||||
([("EventHandlerProcPtr", "*", "OutMode"), ("long", "*", "OutMode")],
|
||||
[("EventHandler", "*", "*")]),
|
||||
|
||||
([("AEEventHandlerUPP", "*", "InMode"), ("long", "*", "InMode")],
|
||||
[("EventHandler", "*", "*")]),
|
||||
|
||||
([("AEEventHandlerUPP", "*", "OutMode"), ("long", "*", "OutMode")],
|
||||
[("EventHandler", "*", "*")]),
|
||||
|
||||
([("void", "*", "OutMode"), ("Size", "*", "InMode"),
|
||||
("Size", "*", "OutMode")],
|
||||
[("VarVarOutBuffer", "*", "InOutMode")]),
|
||||
|
||||
([("AppleEvent", "theAppleEvent", "OutMode")],
|
||||
[("AppleEvent_ptr", "*", "InMode")]),
|
||||
|
||||
([("AEDescList", "theAEDescList", "OutMode")],
|
||||
[("AEDescList_ptr", "*", "InMode")]),
|
||||
]
|
||||
|
||||
def writeinitialdefs(self):
|
||||
self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
237
Mac/Modules/ae/aesupport.py
Normal file
@@ -0,0 +1,237 @@
|
||||
# This script will generate the AppleEvents interface for Python.
|
||||
# It uses the "bgen" package to generate C code.
|
||||
# It execs the file aegen.py which contain the function definitions
|
||||
# (aegen.py was generated by aescan.py, scanning the <AppleEvents.h> header file).
|
||||
|
||||
|
||||
from macsupport import *
|
||||
|
||||
|
||||
AEArrayType = Type("AEArrayType", "c")
|
||||
AESendMode = Type("AESendMode", "l")
|
||||
AESendPriority = Type("AESendPriority", "h")
|
||||
AEInteractAllowed = Type("AEInteractAllowed", "b")
|
||||
AEReturnID = Type("AEReturnID", "h")
|
||||
AETransactionID = Type("AETransactionID", "l")
|
||||
|
||||
|
||||
|
||||
AEEventClass = OSTypeType('AEEventClass')
|
||||
AEEventID = OSTypeType('AEEventID')
|
||||
AEKeyword = OSTypeType('AEKeyword')
|
||||
DescType = OSTypeType('DescType')
|
||||
|
||||
|
||||
AEDesc = OpaqueType('AEDesc')
|
||||
AEDesc_ptr = OpaqueType('AEDesc')
|
||||
|
||||
AEAddressDesc = OpaqueType('AEAddressDesc', 'AEDesc')
|
||||
AEAddressDesc_ptr = OpaqueType('AEAddressDesc', 'AEDesc')
|
||||
|
||||
AEDescList = OpaqueType('AEDescList', 'AEDesc')
|
||||
AEDescList_ptr = OpaqueType('AEDescList', 'AEDesc')
|
||||
|
||||
AERecord = OpaqueType('AERecord', 'AEDesc')
|
||||
AERecord_ptr = OpaqueType('AERecord', 'AEDesc')
|
||||
|
||||
AppleEvent = OpaqueType('AppleEvent', 'AEDesc')
|
||||
AppleEvent_ptr = OpaqueType('AppleEvent', 'AEDesc')
|
||||
|
||||
|
||||
class EHType(Type):
|
||||
def __init__(self, name = 'EventHandler', format = ''):
|
||||
Type.__init__(self, name, format)
|
||||
def declare(self, name):
|
||||
Output("AEEventHandlerUPP %s__proc__ = upp_GenericEventHandler;", name)
|
||||
Output("PyObject *%s;", name)
|
||||
def getargsFormat(self):
|
||||
return "O"
|
||||
def getargsArgs(self, name):
|
||||
return "&%s" % name
|
||||
def passInput(self, name):
|
||||
return "%s__proc__, (long)%s" % (name, name)
|
||||
def passOutput(self, name):
|
||||
return "&%s__proc__, (long *)&%s" % (name, name)
|
||||
def mkvalueFormat(self):
|
||||
return "O"
|
||||
def mkvalueArgs(self, name):
|
||||
return name
|
||||
def cleanup(self, name):
|
||||
Output("Py_INCREF(%s); /* XXX leak, but needed */", name)
|
||||
|
||||
class EHNoRefConType(EHType):
|
||||
def passInput(self, name):
|
||||
return "upp_GenericEventHandler"
|
||||
|
||||
EventHandler = EHType()
|
||||
EventHandlerNoRefCon = EHNoRefConType()
|
||||
|
||||
|
||||
IdleProcPtr = FakeType("upp_AEIdleProc")
|
||||
AEIdleUPP = IdleProcPtr
|
||||
EventFilterProcPtr = FakeType("(AEFilterUPP)0")
|
||||
AEFilterUPP = EventFilterProcPtr
|
||||
NMRecPtr = FakeType("(NMRecPtr)0")
|
||||
EventHandlerProcPtr = FakeType("upp_GenericEventHandler")
|
||||
AEEventHandlerUPP = EventHandlerProcPtr
|
||||
AlwaysFalse = FakeType("0")
|
||||
|
||||
|
||||
AEFunction = OSErrWeakLinkFunctionGenerator
|
||||
AEMethod = OSErrWeakLinkMethodGenerator
|
||||
|
||||
|
||||
includestuff = includestuff + """
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#ifdef USE_TOOLBOX_OBJECT_GLUE
|
||||
extern PyObject *_AEDesc_New(AEDesc *);
|
||||
extern int _AEDesc_Convert(PyObject *, AEDesc *);
|
||||
|
||||
#define AEDesc_New _AEDesc_New
|
||||
#define AEDesc_NewBorrowed _AEDesc_NewBorrowed
|
||||
#define AEDesc_Convert _AEDesc_Convert
|
||||
#endif
|
||||
|
||||
typedef long refcontype;
|
||||
|
||||
static pascal OSErr GenericEventHandler(const AppleEvent *request, AppleEvent *reply, refcontype refcon); /* Forward */
|
||||
|
||||
AEEventHandlerUPP upp_GenericEventHandler;
|
||||
|
||||
static pascal Boolean AEIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn)
|
||||
{
|
||||
if ( PyOS_InterruptOccurred() )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
AEIdleUPP upp_AEIdleProc;
|
||||
"""
|
||||
|
||||
finalstuff = finalstuff + """
|
||||
static pascal OSErr
|
||||
GenericEventHandler(const AppleEvent *request, AppleEvent *reply, refcontype refcon)
|
||||
{
|
||||
PyObject *handler = (PyObject *)refcon;
|
||||
AEDescObject *requestObject, *replyObject;
|
||||
PyObject *args, *res;
|
||||
if ((requestObject = (AEDescObject *)AEDesc_New((AppleEvent *)request)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if ((replyObject = (AEDescObject *)AEDesc_New(reply)) == NULL) {
|
||||
Py_DECREF(requestObject);
|
||||
return -1;
|
||||
}
|
||||
if ((args = Py_BuildValue("OO", requestObject, replyObject)) == NULL) {
|
||||
Py_DECREF(requestObject);
|
||||
Py_DECREF(replyObject);
|
||||
return -1;
|
||||
}
|
||||
res = PyEval_CallObject(handler, args);
|
||||
requestObject->ob_itself.descriptorType = 'null';
|
||||
requestObject->ob_itself.dataHandle = NULL;
|
||||
replyObject->ob_itself.descriptorType = 'null';
|
||||
replyObject->ob_itself.dataHandle = NULL;
|
||||
Py_DECREF(args);
|
||||
if (res == NULL) {
|
||||
PySys_WriteStderr("Exception in AE event handler function\\n");
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(res);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
PyObject *AEDesc_NewBorrowed(AEDesc *itself)
|
||||
{
|
||||
PyObject *it;
|
||||
|
||||
it = AEDesc_New(itself);
|
||||
if (it)
|
||||
((AEDescObject *)it)->ob_owned = 0;
|
||||
return (PyObject *)it;
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
initstuff = initstuff + """
|
||||
upp_AEIdleProc = NewAEIdleUPP(AEIdleProc);
|
||||
upp_GenericEventHandler = NewAEEventHandlerUPP(GenericEventHandler);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(AEDesc *, AEDesc_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(AEDesc *, AEDesc_NewBorrowed);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(AEDesc, AEDesc_Convert);
|
||||
"""
|
||||
|
||||
module = MacModule('_AE', 'AE', includestuff, finalstuff, initstuff)
|
||||
|
||||
class AEDescDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
getsetlist = [(
|
||||
'type',
|
||||
'return PyMac_BuildOSType(self->ob_itself.descriptorType);',
|
||||
None,
|
||||
'Type of this AEDesc'
|
||||
), (
|
||||
'data',
|
||||
"""
|
||||
PyObject *res;
|
||||
Size size;
|
||||
char *ptr;
|
||||
OSErr err;
|
||||
|
||||
size = AEGetDescDataSize(&self->ob_itself);
|
||||
if ( (res = PyString_FromStringAndSize(NULL, size)) == NULL )
|
||||
return NULL;
|
||||
if ( (ptr = PyString_AsString(res)) == NULL )
|
||||
return NULL;
|
||||
if ( (err=AEGetDescData(&self->ob_itself, ptr, size)) < 0 )
|
||||
return PyMac_Error(err);
|
||||
return res;
|
||||
""",
|
||||
None,
|
||||
'The raw data in this AEDesc'
|
||||
)]
|
||||
|
||||
def __init__(self, name, prefix = None, itselftype = None):
|
||||
GlobalObjectDefinition.__init__(self, name, prefix or name, itselftype or name)
|
||||
self.argref = "*"
|
||||
|
||||
def outputStructMembers(self):
|
||||
GlobalObjectDefinition.outputStructMembers(self)
|
||||
Output("int ob_owned;")
|
||||
|
||||
def outputInitStructMembers(self):
|
||||
GlobalObjectDefinition.outputInitStructMembers(self)
|
||||
Output("it->ob_owned = 1;")
|
||||
|
||||
def outputCleanupStructMembers(self):
|
||||
Output("if (self->ob_owned) AEDisposeDesc(&self->ob_itself);")
|
||||
|
||||
aedescobject = AEDescDefinition('AEDesc')
|
||||
module.addobject(aedescobject)
|
||||
|
||||
functions = []
|
||||
aedescmethods = []
|
||||
|
||||
execfile('aegen.py')
|
||||
##execfile('aedatamodelgen.py')
|
||||
|
||||
# Manual generator
|
||||
AutoDispose_body = """
|
||||
int onoff, old;
|
||||
if (!PyArg_ParseTuple(_args, "i", &onoff))
|
||||
return NULL;
|
||||
old = _self->ob_owned;
|
||||
_self->ob_owned = onoff;
|
||||
_res = Py_BuildValue("i", old);
|
||||
return _res;
|
||||
"""
|
||||
f = ManualGenerator("AutoDispose", AutoDispose_body)
|
||||
f.docstring = lambda: "(int)->int. Automatically AEDisposeDesc the object on Python object cleanup"
|
||||
aedescmethods.append(f)
|
||||
|
||||
for f in functions: module.add(f)
|
||||
for f in aedescmethods: aedescobject.add(f)
|
||||
|
||||
SetOutputFileName('_AEmodule.c')
|
||||
module.generate()
|
||||
144
Mac/Modules/ah/_AHmodule.c
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
/* =========================== Module _AH =========================== */
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
|
||||
|
||||
#include "pymactoolbox.h"
|
||||
|
||||
/* Macro to test whether a weak-loaded CFM function exists */
|
||||
#define PyMac_PRECHECK(rtn) do { if ( &rtn == NULL ) {\
|
||||
PyErr_SetString(PyExc_NotImplementedError, \
|
||||
"Not available in this shared library/OS version"); \
|
||||
return NULL; \
|
||||
}} while(0)
|
||||
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
|
||||
static PyObject *Ah_Error;
|
||||
|
||||
static PyObject *Ah_AHSearch(PyObject *_self, PyObject *_args)
|
||||
{
|
||||
PyObject *_res = NULL;
|
||||
OSStatus _err;
|
||||
CFStringRef bookname;
|
||||
CFStringRef query;
|
||||
if (!PyArg_ParseTuple(_args, "O&O&",
|
||||
CFStringRefObj_Convert, &bookname,
|
||||
CFStringRefObj_Convert, &query))
|
||||
return NULL;
|
||||
_err = AHSearch(bookname,
|
||||
query);
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;
|
||||
}
|
||||
|
||||
static PyObject *Ah_AHGotoMainTOC(PyObject *_self, PyObject *_args)
|
||||
{
|
||||
PyObject *_res = NULL;
|
||||
OSStatus _err;
|
||||
AHTOCType toctype;
|
||||
if (!PyArg_ParseTuple(_args, "h",
|
||||
&toctype))
|
||||
return NULL;
|
||||
_err = AHGotoMainTOC(toctype);
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;
|
||||
}
|
||||
|
||||
static PyObject *Ah_AHGotoPage(PyObject *_self, PyObject *_args)
|
||||
{
|
||||
PyObject *_res = NULL;
|
||||
OSStatus _err;
|
||||
CFStringRef bookname;
|
||||
CFStringRef path;
|
||||
CFStringRef anchor;
|
||||
if (!PyArg_ParseTuple(_args, "O&O&O&",
|
||||
CFStringRefObj_Convert, &bookname,
|
||||
CFStringRefObj_Convert, &path,
|
||||
CFStringRefObj_Convert, &anchor))
|
||||
return NULL;
|
||||
_err = AHGotoPage(bookname,
|
||||
path,
|
||||
anchor);
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;
|
||||
}
|
||||
|
||||
static PyObject *Ah_AHLookupAnchor(PyObject *_self, PyObject *_args)
|
||||
{
|
||||
PyObject *_res = NULL;
|
||||
OSStatus _err;
|
||||
CFStringRef bookname;
|
||||
CFStringRef anchor;
|
||||
if (!PyArg_ParseTuple(_args, "O&O&",
|
||||
CFStringRefObj_Convert, &bookname,
|
||||
CFStringRefObj_Convert, &anchor))
|
||||
return NULL;
|
||||
_err = AHLookupAnchor(bookname,
|
||||
anchor);
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;
|
||||
}
|
||||
|
||||
static PyObject *Ah_AHRegisterHelpBook(PyObject *_self, PyObject *_args)
|
||||
{
|
||||
PyObject *_res = NULL;
|
||||
OSStatus _err;
|
||||
FSRef appBundleRef;
|
||||
if (!PyArg_ParseTuple(_args, "O&",
|
||||
PyMac_GetFSRef, &appBundleRef))
|
||||
return NULL;
|
||||
_err = AHRegisterHelpBook(&appBundleRef);
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;
|
||||
}
|
||||
|
||||
static PyMethodDef Ah_methods[] = {
|
||||
{"AHSearch", (PyCFunction)Ah_AHSearch, 1,
|
||||
PyDoc_STR("(CFStringRef bookname, CFStringRef query) -> None")},
|
||||
{"AHGotoMainTOC", (PyCFunction)Ah_AHGotoMainTOC, 1,
|
||||
PyDoc_STR("(AHTOCType toctype) -> None")},
|
||||
{"AHGotoPage", (PyCFunction)Ah_AHGotoPage, 1,
|
||||
PyDoc_STR("(CFStringRef bookname, CFStringRef path, CFStringRef anchor) -> None")},
|
||||
{"AHLookupAnchor", (PyCFunction)Ah_AHLookupAnchor, 1,
|
||||
PyDoc_STR("(CFStringRef bookname, CFStringRef anchor) -> None")},
|
||||
{"AHRegisterHelpBook", (PyCFunction)Ah_AHRegisterHelpBook, 1,
|
||||
PyDoc_STR("(FSRef appBundleRef) -> None")},
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
void init_AH(void)
|
||||
{
|
||||
PyObject *m;
|
||||
PyObject *d;
|
||||
|
||||
|
||||
|
||||
|
||||
m = Py_InitModule("_AH", Ah_methods);
|
||||
d = PyModule_GetDict(m);
|
||||
Ah_Error = PyMac_GetOSErrException();
|
||||
if (Ah_Error == NULL ||
|
||||
PyDict_SetItemString(d, "Error", Ah_Error) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* ========================= End module _AH ========================= */
|
||||
|
||||
51
Mac/Modules/ah/ahscan.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# Scan an Apple header file, generating a Python file of generator calls.
|
||||
|
||||
import sys
|
||||
from bgenlocations import TOOLBOXDIR, BGENDIR
|
||||
sys.path.append(BGENDIR)
|
||||
from scantools import Scanner_OSX
|
||||
|
||||
LONG = "AppleHelp"
|
||||
SHORT = "ah"
|
||||
OBJECT = "NOTUSED"
|
||||
|
||||
def main():
|
||||
input = LONG + ".h"
|
||||
output = SHORT + "gen.py"
|
||||
defsoutput = TOOLBOXDIR + LONG + ".py"
|
||||
scanner = MyScanner(input, output, defsoutput)
|
||||
scanner.scan()
|
||||
scanner.close()
|
||||
print "=== Testing definitions output code ==="
|
||||
execfile(defsoutput, {}, {})
|
||||
print "=== Done scanning and generating, now importing the generated code... ==="
|
||||
exec "import " + SHORT + "support"
|
||||
print "=== Done. It's up to you to compile it now! ==="
|
||||
|
||||
class MyScanner(Scanner_OSX):
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
classname = "Function"
|
||||
listname = "functions"
|
||||
if arglist:
|
||||
t, n, m = arglist[0]
|
||||
# This is non-functional today
|
||||
if t == OBJECT and m == "InMode":
|
||||
classname = "Method"
|
||||
listname = "methods"
|
||||
return classname, listname
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return [
|
||||
]
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return [
|
||||
]
|
||||
|
||||
def makerepairinstructions(self):
|
||||
return [
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
45
Mac/Modules/ah/ahsupport.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# This script generates a Python interface for an Apple Macintosh Manager.
|
||||
# It uses the "bgen" package to generate C code.
|
||||
# The function specifications are generated by scanning the mamager's header file,
|
||||
# using the "scantools" package (customized for this particular manager).
|
||||
|
||||
import string
|
||||
|
||||
# Declarations that change for each manager
|
||||
MACHEADERFILE = 'AppleHelp.h' # The Apple header file
|
||||
MODNAME = '_AH' # The name of the module
|
||||
|
||||
# The following is *usually* unchanged but may still require tuning
|
||||
MODPREFIX = 'Ah' # The prefix for module-wide routines
|
||||
INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner
|
||||
OUTPUTFILE = MODNAME + "module.c" # The file generated by this program
|
||||
|
||||
from macsupport import *
|
||||
|
||||
# Create the type objects
|
||||
AHTOCType = Type("AHTOCType", "h")
|
||||
|
||||
includestuff = includestuff + """
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
"""
|
||||
|
||||
# From here on it's basically all boiler plate...
|
||||
|
||||
# Create the generator groups and link them
|
||||
module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff)
|
||||
|
||||
# Create the generator classes used to populate the lists
|
||||
Function = OSErrFunctionGenerator
|
||||
|
||||
# Create and populate the lists
|
||||
functions = []
|
||||
execfile(INPUTFILE)
|
||||
|
||||
# add the populated lists to the generator groups
|
||||
# (in a different wordl the scan program would generate this)
|
||||
for f in functions: module.add(f)
|
||||
|
||||
# generate output (open the output file as late as possible)
|
||||
SetOutputFileName(OUTPUTFILE)
|
||||
module.generate()
|
||||
1830
Mac/Modules/app/_Appmodule.c
Normal file
80
Mac/Modules/app/appscan.py
Normal file
@@ -0,0 +1,80 @@
|
||||
# Scan an Apple header file, generating a Python file of generator calls.
|
||||
|
||||
import sys
|
||||
from bgenlocations import TOOLBOXDIR, BGENDIR
|
||||
sys.path.append(BGENDIR)
|
||||
from scantools import Scanner
|
||||
|
||||
LONG = "Appearance"
|
||||
SHORT = "app"
|
||||
OBJECT = "ThemeDrawingState"
|
||||
|
||||
def main():
|
||||
input = LONG + ".h"
|
||||
output = SHORT + "gen.py"
|
||||
defsoutput = TOOLBOXDIR + LONG + ".py"
|
||||
scanner = MyScanner(input, output, defsoutput)
|
||||
scanner.scan()
|
||||
scanner.close()
|
||||
print "=== Testing definitions output code ==="
|
||||
execfile(defsoutput, {}, {})
|
||||
print "=== Done scanning and generating, now importing the generated code... ==="
|
||||
exec "import " + SHORT + "support"
|
||||
print "=== Done. It's up to you to compile it now! ==="
|
||||
|
||||
class MyScanner(Scanner):
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
classname = "Function"
|
||||
listname = "functions"
|
||||
if arglist:
|
||||
t, n, m = arglist[0]
|
||||
# This is non-functional today
|
||||
if t == OBJECT and m == "InMode":
|
||||
classname = "Method"
|
||||
listname = "methods"
|
||||
return classname, listname
|
||||
|
||||
def writeinitialdefs(self):
|
||||
self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return [
|
||||
"GetThemeFont", # Funny stringbuffer in/out parameter, I think...
|
||||
# Constants with funny definitions
|
||||
"appearanceBadBrushIndexErr",
|
||||
"appearanceProcessRegisteredErr",
|
||||
"appearanceProcessNotRegisteredErr",
|
||||
"appearanceBadTextColorIndexErr",
|
||||
"appearanceThemeHasNoAccents",
|
||||
"appearanceBadCursorIndexErr",
|
||||
]
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return [
|
||||
"MenuTitleDrawingUPP",
|
||||
"MenuItemDrawingUPP",
|
||||
"ThemeIteratorUPP",
|
||||
"ThemeTabTitleDrawUPP",
|
||||
# "ThemeEraseUPP",
|
||||
# "ThemeButtonDrawUPP",
|
||||
"WindowTitleDrawingUPP",
|
||||
"ProcessSerialNumber_ptr", # Too much work for now.
|
||||
"ThemeTrackDrawInfo_ptr", # Too much work
|
||||
# "ThemeButtonDrawInfo_ptr", # ditto
|
||||
"ThemeWindowMetrics_ptr", # ditto
|
||||
# "ThemeDrawingState", # This is an opaque pointer, so it should be simple. Later.
|
||||
"Collection", # No interface to collection mgr yet.
|
||||
"BytePtr", # Not yet.
|
||||
]
|
||||
|
||||
def makerepairinstructions(self):
|
||||
return [
|
||||
([("void", 'inContext', "OutMode")],
|
||||
[("NULL", 'inContext', "InMode")]),
|
||||
([("Point", 'ioBounds', "OutMode")],
|
||||
[("Point", 'ioBounds', "InOutMode")]),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
133
Mac/Modules/app/appsupport.py
Normal file
@@ -0,0 +1,133 @@
|
||||
# This script generates a Python interface for an Apple Macintosh Manager.
|
||||
# It uses the "bgen" package to generate C code.
|
||||
# The function specifications are generated by scanning the mamager's header file,
|
||||
# using the "scantools" package (customized for this particular manager).
|
||||
|
||||
import string
|
||||
|
||||
# Declarations that change for each manager
|
||||
MACHEADERFILE = 'Appearance.h' # The Apple header file
|
||||
MODNAME = '_App' # The name of the module
|
||||
OBJECTNAME = 'ThemeDrawingState' # The basic name of the objects used here
|
||||
KIND = '' # Usually 'Ptr' or 'Handle'
|
||||
|
||||
# The following is *usually* unchanged but may still require tuning
|
||||
MODPREFIX = 'App' # The prefix for module-wide routines
|
||||
OBJECTTYPE = OBJECTNAME + KIND # The C type used to represent them
|
||||
OBJECTPREFIX = OBJECTNAME + 'Obj' # The prefix for object methods
|
||||
INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner
|
||||
OUTPUTFILE = MODNAME + "module.c" # The file generated by this program
|
||||
|
||||
from macsupport import *
|
||||
|
||||
# Create the type objects
|
||||
#MenuRef = OpaqueByValueType("MenuRef", "MenuObj")
|
||||
|
||||
|
||||
#WindowPeek = OpaqueByValueType("WindowPeek", OBJECTPREFIX)
|
||||
|
||||
RgnHandle = FakeType("(RgnHandle)0")
|
||||
NULL = FakeType("NULL")
|
||||
|
||||
# XXXX Should be next, but this will break a lot of code...
|
||||
# RgnHandle = OpaqueByValueType("RgnHandle", "OptResObj")
|
||||
|
||||
#KeyMap = ArrayOutputBufferType("KeyMap")
|
||||
#MacOSEventKind = Type("MacOSEventKind", "h") # Old-style
|
||||
#MacOSEventMask = Type("MacOSEventMask", "h") # Old-style
|
||||
#EventMask = Type("EventMask", "h")
|
||||
#EventKind = Type("EventKind", "h")
|
||||
ThemeBrush = Type("ThemeBrush", "h")
|
||||
ThemeColor = Type("ThemeColor", "h")
|
||||
ThemeTextColor = Type("ThemeTextColor", "h")
|
||||
ThemeMenuBarState = Type("ThemeMenuBarState", "H")
|
||||
ThemeMenuState = Type("ThemeMenuState", "H")
|
||||
ThemeMenuType = Type("ThemeMenuType", "H")
|
||||
ThemeMenuItemType = Type("ThemeMenuItemType", "H")
|
||||
ThemeFontID = Type("ThemeFontID", "H")
|
||||
ThemeTabStyle = Type("ThemeTabStyle", "H")
|
||||
ThemeTabDirection = Type("ThemeTabDirection", "H")
|
||||
ThemeDrawState = Type("ThemeDrawState", "l")
|
||||
ThemeCursor = Type("ThemeCursor", "l")
|
||||
ThemeCheckBoxStyle = Type("ThemeCheckBoxStyle", "H")
|
||||
ThemeScrollBarArrowStyle = Type("ThemeScrollBarArrowStyle", "H")
|
||||
ThemeScrollBarThumbStyle = Type("ThemeScrollBarThumbStyle", "H")
|
||||
CTabHandle = OpaqueByValueType("CTabHandle", "ResObj")
|
||||
ThemeTrackEnableState = Type("ThemeTrackEnableState", "b")
|
||||
ThemeTrackPressState = Type("ThemeTrackPressState", "b")
|
||||
ThemeThumbDirection = Type("ThemeThumbDirection", "b")
|
||||
ThemeTrackAttributes = Type("ThemeTrackAttributes", "H")
|
||||
ControlPartCode = Type("ControlPartCode", "h")
|
||||
ThemeWindowAttributes = Type("ThemeWindowAttributes", "l")
|
||||
ThemeWindowType = Type("ThemeWindowType", "H")
|
||||
ThemeTitleBarWidget = Type("ThemeTitleBarWidget", "H")
|
||||
ThemeArrowOrientation = Type("ThemeArrowOrientation", "H")
|
||||
ThemePopupArrowSize = Type("ThemePopupArrowSize", "H")
|
||||
ThemeGrowDirection = Type("ThemeGrowDirection", "H")
|
||||
ThemeSoundKind = OSTypeType("ThemeSoundKind")
|
||||
ThemeDragSoundKind = OSTypeType("ThemeDragSoundKind")
|
||||
ThemeBackgroundKind = Type("ThemeBackgroundKind", "l")
|
||||
ThemeMetric = Type("ThemeMetric", "l")
|
||||
RGBColor = OpaqueType("RGBColor", "QdRGB")
|
||||
TruncCode = Type("TruncCode", "h")
|
||||
|
||||
|
||||
ThemeButtonKind = UInt16
|
||||
ThemeButtonDrawInfo_ptr = OpaqueType("ThemeButtonDrawInfo", "ThemeButtonDrawInfo")
|
||||
ThemeEraseUPP = FakeType("NULL")
|
||||
ThemeButtonDrawUPP = FakeType("NULL")
|
||||
|
||||
|
||||
includestuff = includestuff + """
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
|
||||
int ThemeButtonDrawInfo_Convert(PyObject *v, ThemeButtonDrawInfo *p_itself)
|
||||
{
|
||||
return PyArg_Parse(v, "(iHH)", &p_itself->state, &p_itself->value, &p_itself->adornment);
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
class MyObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
pass
|
||||
## def outputCheckNewArg(self):
|
||||
## Output("if (itself == NULL) return PyMac_Error(resNotFound);")
|
||||
## def outputCheckConvertArg(self):
|
||||
## OutLbrace("if (DlgObj_Check(v))")
|
||||
## Output("*p_itself = ((WindowObject *)v)->ob_itself;")
|
||||
## Output("return 1;")
|
||||
## OutRbrace()
|
||||
## Out("""
|
||||
## if (v == Py_None) { *p_itself = NULL; return 1; }
|
||||
## if (PyInt_Check(v)) { *p_itself = (WindowPtr)PyInt_AsLong(v); return 1; }
|
||||
## """)
|
||||
|
||||
# From here on it's basically all boiler plate...
|
||||
|
||||
# Create the generator groups and link them
|
||||
module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff)
|
||||
object = MyObjectDefinition(OBJECTNAME, OBJECTPREFIX, OBJECTTYPE)
|
||||
module.addobject(object)
|
||||
|
||||
ThemeDrawingState = OpaqueByValueType("ThemeDrawingState", "ThemeDrawingStateObj")
|
||||
Method = WeakLinkMethodGenerator
|
||||
|
||||
|
||||
# Create the generator classes used to populate the lists
|
||||
Function = OSErrWeakLinkFunctionGenerator
|
||||
##Method = OSErrWeakLinkMethodGenerator
|
||||
|
||||
# Create and populate the lists
|
||||
functions = []
|
||||
methods = []
|
||||
execfile(INPUTFILE)
|
||||
|
||||
# add the populated lists to the generator groups
|
||||
# (in a different wordl the scan program would generate this)
|
||||
for f in functions: module.add(f)
|
||||
for f in methods: object.add(f)
|
||||
|
||||
# generate output (open the output file as late as possible)
|
||||
SetOutputFileName(OUTPUTFILE)
|
||||
module.generate()
|
||||
152
Mac/Modules/autoGIL.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include "Python.h"
|
||||
#include <CoreFoundation/CFRunLoop.h>
|
||||
|
||||
/* These macros are defined in Python 2.3 but not 2.2 */
|
||||
#ifndef PyMODINIT_FUNC
|
||||
#define PyMODINIT_FUNC void
|
||||
#endif
|
||||
#ifndef PyDoc_STRVAR
|
||||
#define PyDoc_STRVAR(Var,Str) static char Var[] = Str
|
||||
#endif
|
||||
|
||||
|
||||
#undef AUTOGIL_DEBUG
|
||||
|
||||
static PyObject *AutoGILError;
|
||||
|
||||
|
||||
static void autoGILCallback(CFRunLoopObserverRef observer,
|
||||
CFRunLoopActivity activity,
|
||||
void *info) {
|
||||
PyThreadState **p_tstate = (PyThreadState **)info;
|
||||
|
||||
switch (activity) {
|
||||
case kCFRunLoopBeforeWaiting:
|
||||
/* going to sleep, release GIL */
|
||||
#ifdef AUTOGIL_DEBUG
|
||||
fprintf(stderr, "going to sleep, release GIL\n");
|
||||
#endif
|
||||
*p_tstate = PyEval_SaveThread();
|
||||
break;
|
||||
case kCFRunLoopAfterWaiting:
|
||||
/* waking up, acquire GIL */
|
||||
#ifdef AUTOGIL_DEBUG
|
||||
fprintf(stderr, "waking up, acquire GIL\n");
|
||||
#endif
|
||||
PyEval_RestoreThread(*p_tstate);
|
||||
*p_tstate = NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void infoRelease(const void *info) {
|
||||
/* XXX This should get called when the run loop is deallocated,
|
||||
but this doesn't seem to happen. So for now: leak. */
|
||||
PyMem_Free((void *)info);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
autoGIL_installAutoGIL(PyObject *self)
|
||||
{
|
||||
PyObject *tstate_dict = PyThreadState_GetDict();
|
||||
PyObject *v;
|
||||
CFRunLoopRef rl;
|
||||
PyThreadState **p_tstate; /* for use in the info field */
|
||||
CFRunLoopObserverContext context = {0, NULL, NULL, NULL, NULL};
|
||||
CFRunLoopObserverRef observer;
|
||||
|
||||
if (tstate_dict == NULL)
|
||||
return NULL;
|
||||
v = PyDict_GetItemString(tstate_dict, "autoGIL.InstalledAutoGIL");
|
||||
if (v != NULL) {
|
||||
/* we've already installed a callback for this thread */
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
rl = CFRunLoopGetCurrent();
|
||||
if (rl == NULL) {
|
||||
PyErr_SetString(AutoGILError,
|
||||
"can't get run loop for current thread");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p_tstate = PyMem_Malloc(sizeof(PyThreadState *));
|
||||
if (p_tstate == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"not enough memory to allocate "
|
||||
"tstate pointer");
|
||||
return NULL;
|
||||
}
|
||||
*p_tstate = NULL;
|
||||
context.info = (void *)p_tstate;
|
||||
context.release = infoRelease;
|
||||
|
||||
observer = CFRunLoopObserverCreate(
|
||||
NULL,
|
||||
kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting,
|
||||
1, 0, autoGILCallback, &context);
|
||||
if (observer == NULL) {
|
||||
PyErr_SetString(AutoGILError,
|
||||
"can't create event loop observer");
|
||||
return NULL;
|
||||
}
|
||||
CFRunLoopAddObserver(rl, observer, kCFRunLoopDefaultMode);
|
||||
/* XXX how to check for errors? */
|
||||
|
||||
/* register that we have installed a callback for this thread */
|
||||
if (PyDict_SetItemString(tstate_dict, "autoGIL.InstalledAutoGIL",
|
||||
Py_None) < 0)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(autoGIL_installAutoGIL_doc,
|
||||
"installAutoGIL() -> None\n\
|
||||
Install an observer callback in the event loop (CFRunLoop) for the\n\
|
||||
current thread, that will lock and unlock the Global Interpreter Lock\n\
|
||||
(GIL) at appropriate times, allowing other Python threads to run while\n\
|
||||
the event loop is idle."
|
||||
);
|
||||
|
||||
static PyMethodDef autoGIL_methods[] = {
|
||||
{
|
||||
"installAutoGIL",
|
||||
(PyCFunction)autoGIL_installAutoGIL,
|
||||
METH_NOARGS,
|
||||
autoGIL_installAutoGIL_doc
|
||||
},
|
||||
{ 0, 0, 0, 0 } /* sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(autoGIL_docs,
|
||||
"The autoGIL module provides a function (installAutoGIL) that\n\
|
||||
automatically locks and unlocks Python's Global Interpreter Lock\n\
|
||||
when running an event loop."
|
||||
);
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initautoGIL(void)
|
||||
{
|
||||
PyObject *mod;
|
||||
|
||||
if (PyErr_WarnPy3k("In 3.x, the autoGIL module is removed.", 1) < 0)
|
||||
return;
|
||||
|
||||
mod = Py_InitModule4("autoGIL", autoGIL_methods, autoGIL_docs,
|
||||
NULL, PYTHON_API_VERSION);
|
||||
if (mod == NULL)
|
||||
return;
|
||||
AutoGILError = PyErr_NewException("autoGIL.AutoGILError",
|
||||
PyExc_Exception, NULL);
|
||||
if (AutoGILError == NULL)
|
||||
return;
|
||||
Py_INCREF(AutoGILError);
|
||||
if (PyModule_AddObject(mod, "AutoGILError",
|
||||
AutoGILError) < 0)
|
||||
return;
|
||||
}
|
||||
115
Mac/Modules/carbonevt/CarbonEvtscan.py
Normal file
@@ -0,0 +1,115 @@
|
||||
# IBCarbonscan.py
|
||||
|
||||
import sys
|
||||
import MacOS
|
||||
import sys
|
||||
|
||||
from bgenlocations import TOOLBOXDIR, BGENDIR
|
||||
sys.path.append(BGENDIR)
|
||||
|
||||
from scantools import Scanner, Scanner_OSX
|
||||
|
||||
def main():
|
||||
print "---Scanning CarbonEvents.h---"
|
||||
input = ["CarbonEvents.h"]
|
||||
output = "CarbonEventsgen.py"
|
||||
defsoutput = TOOLBOXDIR + "CarbonEvents.py"
|
||||
scanner = CarbonEvents_Scanner(input, output, defsoutput)
|
||||
scanner.scan()
|
||||
scanner.close()
|
||||
print "=== Testing definitions output code ==="
|
||||
execfile(defsoutput, {}, {})
|
||||
print "--done scanning, importing--"
|
||||
import CarbonEvtsupport
|
||||
print "done"
|
||||
|
||||
RefObjectTypes = ["EventRef",
|
||||
"EventQueueRef",
|
||||
"EventLoopRef",
|
||||
"EventLoopTimerRef",
|
||||
"EventHandlerRef",
|
||||
"EventHandlerCallRef",
|
||||
"EventTargetRef",
|
||||
"EventHotKeyRef",
|
||||
]
|
||||
|
||||
class CarbonEvents_Scanner(Scanner_OSX):
|
||||
def destination(self, type, name, arglist):
|
||||
classname = "CarbonEventsFunction"
|
||||
listname = "functions"
|
||||
if arglist:
|
||||
t, n, m = arglist[0]
|
||||
if t in RefObjectTypes and m == "InMode":
|
||||
if t == "EventHandlerRef":
|
||||
classname = "EventHandlerRefMethod"
|
||||
else:
|
||||
classname = "CarbonEventsMethod"
|
||||
listname = t + "methods"
|
||||
#else:
|
||||
# print "not method"
|
||||
return classname, listname
|
||||
|
||||
def writeinitialdefs(self):
|
||||
self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
|
||||
self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
|
||||
self.defsfile.write("false = 0\n")
|
||||
self.defsfile.write("true = 1\n")
|
||||
self.defsfile.write("keyAEEventClass = FOUR_CHAR_CODE('evcl')\n")
|
||||
self.defsfile.write("keyAEEventID = FOUR_CHAR_CODE('evti')\n")
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return [
|
||||
"sHandler",
|
||||
"MacCreateEvent",
|
||||
# "TrackMouseLocationWithOptions",
|
||||
# "TrackMouseLocation",
|
||||
# "TrackMouseRegion",
|
||||
"RegisterToolboxObjectClass",
|
||||
"UnregisterToolboxObjectClass",
|
||||
"ProcessHICommand",
|
||||
"GetCFRunLoopFromEventLoop",
|
||||
|
||||
"InvokeEventHandlerUPP",
|
||||
"InvokeEventComparatorUPP",
|
||||
"InvokeEventLoopTimerUPP",
|
||||
"NewEventComparatorUPP",
|
||||
"NewEventLoopTimerUPP",
|
||||
"NewEventHandlerUPP",
|
||||
"DisposeEventComparatorUPP",
|
||||
"DisposeEventLoopTimerUPP",
|
||||
"DisposeEventHandlerUPP",
|
||||
|
||||
# Wrote by hand
|
||||
"InstallEventHandler",
|
||||
"RemoveEventHandler",
|
||||
|
||||
# Write by hand?
|
||||
"GetEventParameter",
|
||||
"FlushSpecificEventsFromQueue",
|
||||
"FindSpecificEventInQueue",
|
||||
"InstallEventLoopTimer",
|
||||
|
||||
# Don't do these because they require a CFRelease
|
||||
"CreateTypeStringWithOSType",
|
||||
"CopyEvent",
|
||||
]
|
||||
|
||||
# def makeblacklisttypes(self):
|
||||
# return ["EventComparatorUPP",
|
||||
# "EventLoopTimerUPP",
|
||||
# #"EventHandlerUPP",
|
||||
# "EventComparatorProcPtr",
|
||||
# "EventLoopTimerProcPtr",
|
||||
# "EventHandlerProcPtr",
|
||||
# ]
|
||||
|
||||
def makerepairinstructions(self):
|
||||
return [
|
||||
([("UInt32", 'inSize', "InMode"), ("void_ptr", 'inDataPtr', "InMode")],
|
||||
[("MyInBuffer", 'inDataPtr', "InMode")]),
|
||||
([("Boolean", 'ioWasInRgn', "OutMode")],
|
||||
[("Boolean", 'ioWasInRgn', "InOutMode")]),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
314
Mac/Modules/carbonevt/CarbonEvtsupport.py
Normal file
@@ -0,0 +1,314 @@
|
||||
# IBCarbonsupport.py
|
||||
|
||||
from macsupport import *
|
||||
|
||||
from CarbonEvtscan import RefObjectTypes
|
||||
|
||||
# where should this go? macsupport.py?
|
||||
CFStringRef = OpaqueByValueType('CFStringRef')
|
||||
|
||||
for typ in RefObjectTypes:
|
||||
execstr = "%(name)s = OpaqueByValueType('%(name)s')" % {"name": typ}
|
||||
exec execstr
|
||||
|
||||
|
||||
if 0:
|
||||
# these types will have no methods and will merely be opaque blobs
|
||||
# should write getattr and setattr for them?
|
||||
|
||||
StructObjectTypes = ["EventTypeSpec",
|
||||
"HIPoint",
|
||||
"HICommand",
|
||||
"EventHotKeyID",
|
||||
]
|
||||
|
||||
for typ in StructObjectTypes:
|
||||
execstr = "%(name)s = OpaqueType('%(name)s')" % {"name": typ}
|
||||
exec execstr
|
||||
|
||||
EventHotKeyID = OpaqueByValueType("EventHotKeyID", "EventHotKeyID")
|
||||
EventTypeSpec_ptr = OpaqueType("EventTypeSpec", "EventTypeSpec")
|
||||
|
||||
# is this the right type for the void * in GetEventParameter
|
||||
#void_ptr = FixedInputBufferType(1024)
|
||||
void_ptr = stringptr
|
||||
# here are some types that are really other types
|
||||
|
||||
class MyVarInputBufferType(VarInputBufferType):
|
||||
def passInput(self, name):
|
||||
return "%s__len__, %s__in__" % (name, name)
|
||||
|
||||
MyInBuffer = MyVarInputBufferType('char', 'long', 'l') # (buf, len)
|
||||
|
||||
EventTime = double
|
||||
EventTimeout = EventTime
|
||||
EventTimerInterval = EventTime
|
||||
EventAttributes = UInt32
|
||||
EventParamName = OSType
|
||||
EventParamType = OSType
|
||||
EventPriority = SInt16
|
||||
EventMask = UInt16
|
||||
|
||||
EventComparatorUPP = FakeType("(EventComparatorUPP)0")
|
||||
EventLoopTimerUPP = FakeType("(EventLoopTimerUPP)0")
|
||||
EventHandlerUPP = FakeType("(EventHandlerUPP)0")
|
||||
EventHandlerUPP = FakeType("(EventHandlerUPP)0")
|
||||
EventComparatorProcPtr = FakeType("(EventComparatorProcPtr)0")
|
||||
EventLoopTimerProcPtr = FakeType("(EventLoopTimerProcPtr)0")
|
||||
EventHandlerProcPtr = FakeType("(EventHandlerProcPtr)0")
|
||||
|
||||
CarbonEventsFunction = OSErrFunctionGenerator
|
||||
CarbonEventsMethod = OSErrMethodGenerator
|
||||
|
||||
class EventHandlerRefMethod(OSErrMethodGenerator):
|
||||
def precheck(self):
|
||||
OutLbrace('if (_self->ob_itself == NULL)')
|
||||
Output('PyErr_SetString(CarbonEvents_Error, "Handler has been removed");')
|
||||
Output('return NULL;')
|
||||
OutRbrace()
|
||||
|
||||
|
||||
RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
|
||||
GrafPtr = OpaqueByValueType("GrafPtr", "GrafObj")
|
||||
MouseTrackingResult = UInt16
|
||||
|
||||
|
||||
includestuff = includestuff + r"""
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
extern int CFStringRef_New(CFStringRef *);
|
||||
|
||||
extern int CFStringRef_Convert(PyObject *, CFStringRef *);
|
||||
extern int CFBundleRef_Convert(PyObject *, CFBundleRef *);
|
||||
|
||||
int EventTargetRef_Convert(PyObject *, EventTargetRef *);
|
||||
PyObject *EventHandlerCallRef_New(EventHandlerCallRef itself);
|
||||
PyObject *EventRef_New(EventRef itself);
|
||||
|
||||
/********** EventTypeSpec *******/
|
||||
static PyObject*
|
||||
EventTypeSpec_New(EventTypeSpec *in)
|
||||
{
|
||||
return Py_BuildValue("ll", in->eventClass, in->eventKind);
|
||||
}
|
||||
|
||||
static int
|
||||
EventTypeSpec_Convert(PyObject *v, EventTypeSpec *out)
|
||||
{
|
||||
if (PyArg_Parse(v, "(O&l)",
|
||||
PyMac_GetOSType, &(out->eventClass),
|
||||
&(out->eventKind)))
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********** end EventTypeSpec *******/
|
||||
|
||||
/********** HIPoint *******/
|
||||
|
||||
#if 0 /* XXX doesn't compile */
|
||||
static PyObject*
|
||||
HIPoint_New(HIPoint *in)
|
||||
{
|
||||
return Py_BuildValue("ff", in->x, in->y);
|
||||
}
|
||||
|
||||
static int
|
||||
HIPoint_Convert(PyObject *v, HIPoint *out)
|
||||
{
|
||||
if (PyArg_ParseTuple(v, "ff", &(out->x), &(out->y)))
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/********** end HIPoint *******/
|
||||
|
||||
/********** EventHotKeyID *******/
|
||||
|
||||
static PyObject*
|
||||
EventHotKeyID_New(EventHotKeyID *in)
|
||||
{
|
||||
return Py_BuildValue("ll", in->signature, in->id);
|
||||
}
|
||||
|
||||
static int
|
||||
EventHotKeyID_Convert(PyObject *v, EventHotKeyID *out)
|
||||
{
|
||||
if (PyArg_ParseTuple(v, "ll", &out->signature, &out->id))
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********** end EventHotKeyID *******/
|
||||
|
||||
/******** myEventHandler ***********/
|
||||
|
||||
static EventHandlerUPP myEventHandlerUPP;
|
||||
|
||||
static pascal OSStatus
|
||||
myEventHandler(EventHandlerCallRef handlerRef, EventRef event, void *outPyObject) {
|
||||
PyObject *retValue;
|
||||
int status;
|
||||
|
||||
retValue = PyObject_CallFunction((PyObject *)outPyObject, "O&O&",
|
||||
EventHandlerCallRef_New, handlerRef,
|
||||
EventRef_New, event);
|
||||
if (retValue == NULL) {
|
||||
PySys_WriteStderr("Error in event handler callback:\n");
|
||||
PyErr_Print(); /* this also clears the error */
|
||||
status = noErr; /* complain? how? */
|
||||
} else {
|
||||
if (retValue == Py_None)
|
||||
status = noErr;
|
||||
else if (PyInt_Check(retValue)) {
|
||||
status = PyInt_AsLong(retValue);
|
||||
} else
|
||||
status = noErr; /* wrong object type, complain? */
|
||||
Py_DECREF(retValue);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/******** end myEventHandler ***********/
|
||||
|
||||
"""
|
||||
|
||||
initstuff = initstuff + """
|
||||
myEventHandlerUPP = NewEventHandlerUPP(myEventHandler);
|
||||
"""
|
||||
module = MacModule('_CarbonEvt', 'CarbonEvents', includestuff, finalstuff, initstuff)
|
||||
|
||||
|
||||
|
||||
|
||||
class EventHandlerRefObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
def outputStructMembers(self):
|
||||
Output("%s ob_itself;", self.itselftype)
|
||||
Output("PyObject *ob_callback;")
|
||||
def outputInitStructMembers(self):
|
||||
Output("it->ob_itself = %sitself;", self.argref)
|
||||
Output("it->ob_callback = NULL;")
|
||||
def outputFreeIt(self, name):
|
||||
OutLbrace("if (self->ob_itself != NULL)")
|
||||
Output("RemoveEventHandler(self->ob_itself);")
|
||||
Output("Py_DECREF(self->ob_callback);")
|
||||
OutRbrace()
|
||||
|
||||
class MyGlobalObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
pass
|
||||
|
||||
for typ in RefObjectTypes:
|
||||
if typ == 'EventHandlerRef':
|
||||
EventHandlerRefobject = EventHandlerRefObjectDefinition('EventHandlerRef')
|
||||
else:
|
||||
execstr = typ + 'object = MyGlobalObjectDefinition(typ)'
|
||||
exec execstr
|
||||
module.addobject(eval(typ + 'object'))
|
||||
|
||||
|
||||
functions = []
|
||||
for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py
|
||||
# initialize the lists for carbongen to fill
|
||||
execstr = typ + 'methods = []'
|
||||
exec execstr
|
||||
|
||||
execfile('CarbonEventsgen.py')
|
||||
|
||||
|
||||
|
||||
for f in functions: module.add(f) # add all the functions carboneventsgen put in the list
|
||||
|
||||
for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py
|
||||
methods = eval(typ + 'methods') ## get a reference to the method list from the main namespace
|
||||
obj = eval(typ + 'object') ## get a reference to the object
|
||||
for m in methods: obj.add(m) ## add each method in the list to the object
|
||||
|
||||
|
||||
removeeventhandler = """
|
||||
OSStatus _err;
|
||||
if (_self->ob_itself == NULL) {
|
||||
PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(_args, ""))
|
||||
return NULL;
|
||||
_err = RemoveEventHandler(_self->ob_itself);
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
_self->ob_itself = NULL;
|
||||
Py_DECREF(_self->ob_callback);
|
||||
_self->ob_callback = NULL;
|
||||
Py_INCREF(Py_None);
|
||||
_res = Py_None;
|
||||
return _res;"""
|
||||
|
||||
f = ManualGenerator("RemoveEventHandler", removeeventhandler);
|
||||
f.docstring = lambda: "() -> None"
|
||||
EventHandlerRefobject.add(f)
|
||||
|
||||
|
||||
installeventhandler = """
|
||||
EventTypeSpec inSpec;
|
||||
PyObject *callback;
|
||||
EventHandlerRef outRef;
|
||||
OSStatus _err;
|
||||
|
||||
if (!PyArg_ParseTuple(_args, "O&O", EventTypeSpec_Convert, &inSpec, &callback))
|
||||
return NULL;
|
||||
|
||||
_err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
|
||||
_res = EventHandlerRef_New(outRef);
|
||||
if (_res != NULL) {
|
||||
((EventHandlerRefObject*)_res)->ob_callback = callback;
|
||||
Py_INCREF(callback);
|
||||
}
|
||||
return _res;"""
|
||||
|
||||
f = ManualGenerator("InstallEventHandler", installeventhandler);
|
||||
f.docstring = lambda: "(EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"
|
||||
EventTargetRefobject.add(f)
|
||||
|
||||
# This may not be the best, but at least it lets you get the raw data back into python as a string. You'll have to cut it up yourself and parse the result.
|
||||
|
||||
geteventparameter = """
|
||||
UInt32 bufferSize;
|
||||
EventParamName inName;
|
||||
EventParamType inType;
|
||||
OSErr _err;
|
||||
void * buffer;
|
||||
|
||||
if (!PyArg_ParseTuple(_args, "O&O&", PyMac_GetOSType, &inName, PyMac_GetOSType, &inType))
|
||||
return NULL;
|
||||
|
||||
/* Figure out the size by passing a null buffer to GetEventParameter */
|
||||
_err = GetEventParameter(_self->ob_itself, inName, inType, NULL, 0, &bufferSize, NULL);
|
||||
|
||||
if (_err != noErr)
|
||||
return PyMac_Error(_err);
|
||||
buffer = PyMem_NEW(char, bufferSize);
|
||||
if (buffer == NULL)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
_err = GetEventParameter(_self->ob_itself, inName, inType, NULL, bufferSize, NULL, buffer);
|
||||
|
||||
if (_err != noErr) {
|
||||
PyMem_DEL(buffer);
|
||||
return PyMac_Error(_err);
|
||||
}
|
||||
_res = Py_BuildValue("s#", buffer, bufferSize);
|
||||
PyMem_DEL(buffer);
|
||||
return _res;
|
||||
"""
|
||||
|
||||
f = ManualGenerator("GetEventParameter", geteventparameter);
|
||||
f.docstring = lambda: "(EventParamName eventName, EventParamType eventType) -> (String eventParamData)"
|
||||
EventRefobject.add(f)
|
||||
|
||||
SetOutputFileName('_CarbonEvtmodule.c')
|
||||
module.generate()
|
||||
|
||||
##import os
|
||||
##os.system("python setup.py build")
|
||||
2218
Mac/Modules/carbonevt/_CarbonEvtmodule.c
Normal file
4995
Mac/Modules/cf/_CFmodule.c
Normal file
141
Mac/Modules/cf/cfscan.py
Normal file
@@ -0,0 +1,141 @@
|
||||
# Scan an Apple header file, generating a Python file of generator calls.
|
||||
|
||||
import sys
|
||||
from bgenlocations import TOOLBOXDIR, BGENDIR
|
||||
sys.path.append(BGENDIR)
|
||||
from scantools import Scanner_OSX
|
||||
|
||||
LONG = "CoreFoundation"
|
||||
SHORT = "cf"
|
||||
OBJECTS = ("CFTypeRef",
|
||||
"CFArrayRef", "CFMutableArrayRef",
|
||||
"CFDataRef", "CFMutableDataRef",
|
||||
"CFDictionaryRef", "CFMutableDictionaryRef",
|
||||
"CFStringRef", "CFMutableStringRef",
|
||||
"CFURLRef",
|
||||
## "CFPropertyListRef",
|
||||
)
|
||||
# ADD object typenames here
|
||||
|
||||
def main():
|
||||
input = [
|
||||
"CFBase.h",
|
||||
"CFArray.h",
|
||||
## "CFBag.h",
|
||||
## "CFBundle.h",
|
||||
## "CFCharacterSet.h",
|
||||
"CFData.h",
|
||||
## "CFDate.h",
|
||||
"CFDictionary.h",
|
||||
## "CFNumber.h",
|
||||
## "CFPlugIn.h",
|
||||
"CFPreferences.h",
|
||||
"CFPropertyList.h",
|
||||
## "CFSet.h",
|
||||
"CFString.h",
|
||||
## "CFStringEncodingExt.h",
|
||||
## "CFTimeZone.h",
|
||||
"CFURL.h",
|
||||
]
|
||||
output = SHORT + "gen.py"
|
||||
defsoutput = TOOLBOXDIR + LONG + ".py"
|
||||
scanner = MyScanner(input, output, defsoutput)
|
||||
scanner.scan()
|
||||
scanner.gentypetest(SHORT+"typetest.py")
|
||||
scanner.close()
|
||||
print "=== Testing definitions output code ==="
|
||||
execfile(defsoutput, {}, {})
|
||||
print "=== Done scanning and generating, now importing the generated code... ==="
|
||||
exec "import " + SHORT + "support"
|
||||
print "=== Done. It's up to you to compile it now! ==="
|
||||
|
||||
class MyScanner(Scanner_OSX):
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
classname = "Function"
|
||||
listname = "functions"
|
||||
if arglist and name[:13] != 'CFPreferences':
|
||||
t, n, m = arglist[0]
|
||||
if t in OBJECTS and m == "InMode":
|
||||
classname = "Method"
|
||||
listname = t + "_methods"
|
||||
# Special case for the silly first AllocatorRef argument
|
||||
if t == 'CFAllocatorRef' and m == 'InMode' and len(arglist) > 1:
|
||||
t, n, m = arglist[1]
|
||||
if t in OBJECTS and m == "InMode":
|
||||
classname = "MethodSkipArg1"
|
||||
listname = t + "_methods"
|
||||
return classname, listname
|
||||
|
||||
def writeinitialdefs(self):
|
||||
self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return [
|
||||
# Memory allocator functions
|
||||
"CFAllocatorGetDefault",
|
||||
"CFAllocatorSetDefault",
|
||||
"CFAllocatorAllocate",
|
||||
"CFAllocatorReallocate",
|
||||
"CFAllocatorDeallocate",
|
||||
"CFGetAllocator",
|
||||
# Array functions we skip for now.
|
||||
"CFArrayGetValueAtIndex",
|
||||
# Data pointer functions. Skip for now.
|
||||
"CFDataGetBytePtr",
|
||||
"CFDataGetMutableBytePtr",
|
||||
"CFDataGetBytes", # XXXX Should support this one
|
||||
# String functions
|
||||
"CFStringGetPascalString", # Use the C-string methods.
|
||||
"CFStringGetPascalStringPtr", # TBD automatically
|
||||
"CFStringGetCStringPtr",
|
||||
"CFStringGetCharactersPtr",
|
||||
"CFStringGetCString",
|
||||
"CFStringGetCharacters",
|
||||
"CFURLCreateStringWithFileSystemPath", # Gone in later releases
|
||||
"CFStringCreateMutableWithExternalCharactersNoCopy", # Not a clue...
|
||||
"CFStringSetExternalCharactersNoCopy",
|
||||
"CFStringGetCharacterAtIndex", # No format for single unichars yet.
|
||||
"kCFStringEncodingInvalidId", # incompatible constant declaration
|
||||
"CFPropertyListCreateFromXMLData", # Manually generated
|
||||
]
|
||||
|
||||
def makegreylist(self):
|
||||
return []
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return [
|
||||
"CFComparatorFunction", # Callback function pointer
|
||||
"CFAllocatorContext", # Not interested in providing our own allocator
|
||||
"void_ptr_ptr", # Tricky. This is the initializer for arrays...
|
||||
"void_ptr", # Ditto for various array lookup methods
|
||||
"CFArrayApplierFunction", # Callback function pointer
|
||||
"CFDictionaryApplierFunction", # Callback function pointer
|
||||
"va_list", # For printf-to-a-cfstring. Use Python.
|
||||
"const_CFStringEncoding_ptr", # To be done, I guess
|
||||
]
|
||||
|
||||
def makerepairinstructions(self):
|
||||
return [
|
||||
# Buffers in CF seem to be passed as UInt8 * normally.
|
||||
([("UInt8_ptr", "*", "InMode"), ("CFIndex", "*", "InMode")],
|
||||
[("UcharInBuffer", "*", "*")]),
|
||||
|
||||
([("UniChar_ptr", "*", "InMode"), ("CFIndex", "*", "InMode")],
|
||||
[("UnicodeInBuffer", "*", "*")]),
|
||||
|
||||
# Some functions return a const char *. Don't worry, we won't modify it.
|
||||
([("const_char_ptr", "*", "ReturnMode")],
|
||||
[("return_stringptr", "*", "*")]),
|
||||
|
||||
# base URLs are optional (pass None for NULL)
|
||||
([("CFURLRef", "baseURL", "InMode")],
|
||||
[("OptionalCFURLRef", "*", "*")]),
|
||||
|
||||
# We handle CFPropertyListRef objects as plain CFTypeRef
|
||||
([("CFPropertyListRef", "*", "*")],
|
||||
[("CFTypeRef", "*", "*")]),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
666
Mac/Modules/cf/cfsupport.py
Normal file
@@ -0,0 +1,666 @@
|
||||
# This script generates a Python interface for an Apple Macintosh Manager.
|
||||
# It uses the "bgen" package to generate C code.
|
||||
# The function specifications are generated by scanning the mamager's header file,
|
||||
# using the "scantools" package (customized for this particular manager).
|
||||
|
||||
#error missing SetActionFilter
|
||||
|
||||
import string
|
||||
|
||||
# Declarations that change for each manager
|
||||
MODNAME = '_CF' # The name of the module
|
||||
|
||||
# The following is *usually* unchanged but may still require tuning
|
||||
MODPREFIX = 'CF' # The prefix for module-wide routines
|
||||
INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner
|
||||
OUTPUTFILE = MODNAME + "module.c" # The file generated by this program
|
||||
|
||||
from macsupport import *
|
||||
|
||||
# Special case generator for the functions that have an AllocatorRef first argument,
|
||||
# which we skip anyway, and the object as the second arg.
|
||||
class MethodSkipArg1(MethodGenerator):
|
||||
"""Similar to MethodGenerator, but has self as last argument"""
|
||||
|
||||
def parseArgumentList(self, args):
|
||||
if len(args) < 2:
|
||||
raise ValueError, "MethodSkipArg1 expects at least 2 args"
|
||||
a0, a1, args = args[0], args[1], args[2:]
|
||||
t0, n0, m0 = a0
|
||||
if t0 != "CFAllocatorRef" and m0 != InMode:
|
||||
raise ValueError, "MethodSkipArg1 should have dummy AllocatorRef first arg"
|
||||
t1, n1, m1 = a1
|
||||
if m1 != InMode:
|
||||
raise ValueError, "method's 'self' must be 'InMode'"
|
||||
dummy = Variable(t0, n0, m0)
|
||||
self.argumentList.append(dummy)
|
||||
self.itself = Variable(t1, "_self->ob_itself", SelfMode)
|
||||
self.argumentList.append(self.itself)
|
||||
FunctionGenerator.parseArgumentList(self, args)
|
||||
|
||||
|
||||
# Create the type objects
|
||||
|
||||
includestuff = includestuff + """
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#include "pycfbridge.h"
|
||||
|
||||
#ifdef USE_TOOLBOX_OBJECT_GLUE
|
||||
extern PyObject *_CFObj_New(CFTypeRef);
|
||||
extern int _CFObj_Convert(PyObject *, CFTypeRef *);
|
||||
#define CFObj_New _CFObj_New
|
||||
#define CFObj_Convert _CFObj_Convert
|
||||
|
||||
extern PyObject *_CFTypeRefObj_New(CFTypeRef);
|
||||
extern int _CFTypeRefObj_Convert(PyObject *, CFTypeRef *);
|
||||
#define CFTypeRefObj_New _CFTypeRefObj_New
|
||||
#define CFTypeRefObj_Convert _CFTypeRefObj_Convert
|
||||
|
||||
extern PyObject *_CFStringRefObj_New(CFStringRef);
|
||||
extern int _CFStringRefObj_Convert(PyObject *, CFStringRef *);
|
||||
#define CFStringRefObj_New _CFStringRefObj_New
|
||||
#define CFStringRefObj_Convert _CFStringRefObj_Convert
|
||||
|
||||
extern PyObject *_CFMutableStringRefObj_New(CFMutableStringRef);
|
||||
extern int _CFMutableStringRefObj_Convert(PyObject *, CFMutableStringRef *);
|
||||
#define CFMutableStringRefObj_New _CFMutableStringRefObj_New
|
||||
#define CFMutableStringRefObj_Convert _CFMutableStringRefObj_Convert
|
||||
|
||||
extern PyObject *_CFArrayRefObj_New(CFArrayRef);
|
||||
extern int _CFArrayRefObj_Convert(PyObject *, CFArrayRef *);
|
||||
#define CFArrayRefObj_New _CFArrayRefObj_New
|
||||
#define CFArrayRefObj_Convert _CFArrayRefObj_Convert
|
||||
|
||||
extern PyObject *_CFMutableArrayRefObj_New(CFMutableArrayRef);
|
||||
extern int _CFMutableArrayRefObj_Convert(PyObject *, CFMutableArrayRef *);
|
||||
#define CFMutableArrayRefObj_New _CFMutableArrayRefObj_New
|
||||
#define CFMutableArrayRefObj_Convert _CFMutableArrayRefObj_Convert
|
||||
|
||||
extern PyObject *_CFDataRefObj_New(CFDataRef);
|
||||
extern int _CFDataRefObj_Convert(PyObject *, CFDataRef *);
|
||||
#define CFDataRefObj_New _CFDataRefObj_New
|
||||
#define CFDataRefObj_Convert _CFDataRefObj_Convert
|
||||
|
||||
extern PyObject *_CFMutableDataRefObj_New(CFMutableDataRef);
|
||||
extern int _CFMutableDataRefObj_Convert(PyObject *, CFMutableDataRef *);
|
||||
#define CFMutableDataRefObj_New _CFMutableDataRefObj_New
|
||||
#define CFMutableDataRefObj_Convert _CFMutableDataRefObj_Convert
|
||||
|
||||
extern PyObject *_CFDictionaryRefObj_New(CFDictionaryRef);
|
||||
extern int _CFDictionaryRefObj_Convert(PyObject *, CFDictionaryRef *);
|
||||
#define CFDictionaryRefObj_New _CFDictionaryRefObj_New
|
||||
#define CFDictionaryRefObj_Convert _CFDictionaryRefObj_Convert
|
||||
|
||||
extern PyObject *_CFMutableDictionaryRefObj_New(CFMutableDictionaryRef);
|
||||
extern int _CFMutableDictionaryRefObj_Convert(PyObject *, CFMutableDictionaryRef *);
|
||||
#define CFMutableDictionaryRefObj_New _CFMutableDictionaryRefObj_New
|
||||
#define CFMutableDictionaryRefObj_Convert _CFMutableDictionaryRefObj_Convert
|
||||
|
||||
extern PyObject *_CFURLRefObj_New(CFURLRef);
|
||||
extern int _CFURLRefObj_Convert(PyObject *, CFURLRef *);
|
||||
extern int _OptionalCFURLRefObj_Convert(PyObject *, CFURLRef *);
|
||||
#define CFURLRefObj_New _CFURLRefObj_New
|
||||
#define CFURLRefObj_Convert _CFURLRefObj_Convert
|
||||
#define OptionalCFURLRefObj_Convert _OptionalCFURLRefObj_Convert
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Parse/generate CFRange records
|
||||
*/
|
||||
PyObject *CFRange_New(CFRange *itself)
|
||||
{
|
||||
|
||||
return Py_BuildValue("ll", (long)itself->location, (long)itself->length);
|
||||
}
|
||||
|
||||
int
|
||||
CFRange_Convert(PyObject *v, CFRange *p_itself)
|
||||
{
|
||||
long location, length;
|
||||
|
||||
if( !PyArg_ParseTuple(v, "ll", &location, &length) )
|
||||
return 0;
|
||||
p_itself->location = (CFIndex)location;
|
||||
p_itself->length = (CFIndex)length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Optional CFURL argument or None (passed as NULL) */
|
||||
int
|
||||
OptionalCFURLRefObj_Convert(PyObject *v, CFURLRef *p_itself)
|
||||
{
|
||||
if ( v == Py_None ) {
|
||||
p_itself = NULL;
|
||||
return 1;
|
||||
}
|
||||
return CFURLRefObj_Convert(v, p_itself);
|
||||
}
|
||||
"""
|
||||
|
||||
finalstuff = finalstuff + """
|
||||
|
||||
/* Routines to convert any CF type to/from the corresponding CFxxxObj */
|
||||
PyObject *CFObj_New(CFTypeRef itself)
|
||||
{
|
||||
if (itself == NULL)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "cannot wrap NULL");
|
||||
return NULL;
|
||||
}
|
||||
if (CFGetTypeID(itself) == CFArrayGetTypeID()) return CFArrayRefObj_New((CFArrayRef)itself);
|
||||
if (CFGetTypeID(itself) == CFDictionaryGetTypeID()) return CFDictionaryRefObj_New((CFDictionaryRef)itself);
|
||||
if (CFGetTypeID(itself) == CFDataGetTypeID()) return CFDataRefObj_New((CFDataRef)itself);
|
||||
if (CFGetTypeID(itself) == CFStringGetTypeID()) return CFStringRefObj_New((CFStringRef)itself);
|
||||
if (CFGetTypeID(itself) == CFURLGetTypeID()) return CFURLRefObj_New((CFURLRef)itself);
|
||||
/* XXXX Or should we use PyCF_CF2Python here?? */
|
||||
return CFTypeRefObj_New(itself);
|
||||
}
|
||||
int CFObj_Convert(PyObject *v, CFTypeRef *p_itself)
|
||||
{
|
||||
|
||||
if (v == Py_None) { *p_itself = NULL; return 1; }
|
||||
/* Check for other CF objects here */
|
||||
|
||||
if (!CFTypeRefObj_Check(v) &&
|
||||
!CFArrayRefObj_Check(v) &&
|
||||
!CFMutableArrayRefObj_Check(v) &&
|
||||
!CFDictionaryRefObj_Check(v) &&
|
||||
!CFMutableDictionaryRefObj_Check(v) &&
|
||||
!CFDataRefObj_Check(v) &&
|
||||
!CFMutableDataRefObj_Check(v) &&
|
||||
!CFStringRefObj_Check(v) &&
|
||||
!CFMutableStringRefObj_Check(v) &&
|
||||
!CFURLRefObj_Check(v) )
|
||||
{
|
||||
/* XXXX Or should we use PyCF_Python2CF here?? */
|
||||
PyErr_SetString(PyExc_TypeError, "CF object required");
|
||||
return 0;
|
||||
}
|
||||
*p_itself = ((CFTypeRefObject *)v)->ob_itself;
|
||||
return 1;
|
||||
}
|
||||
"""
|
||||
|
||||
initstuff = initstuff + """
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFTypeRef, CFObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFTypeRef, CFObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFTypeRef, CFTypeRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFTypeRef, CFTypeRefObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFStringRef, CFStringRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFStringRef, CFStringRefObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFMutableStringRef, CFMutableStringRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFArrayRef, CFArrayRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFArrayRef, CFArrayRefObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFDictionaryRef, CFDictionaryRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_NEW(CFURLRef, CFURLRefObj_New);
|
||||
PyMac_INIT_TOOLBOX_OBJECT_CONVERT(CFURLRef, CFURLRefObj_Convert);
|
||||
"""
|
||||
|
||||
variablestuff="""
|
||||
#define _STRINGCONST(name) PyModule_AddObject(m, #name, CFStringRefObj_New(name))
|
||||
_STRINGCONST(kCFPreferencesAnyApplication);
|
||||
_STRINGCONST(kCFPreferencesCurrentApplication);
|
||||
_STRINGCONST(kCFPreferencesAnyHost);
|
||||
_STRINGCONST(kCFPreferencesCurrentHost);
|
||||
_STRINGCONST(kCFPreferencesAnyUser);
|
||||
_STRINGCONST(kCFPreferencesCurrentUser);
|
||||
|
||||
"""
|
||||
|
||||
Boolean = Type("Boolean", "l")
|
||||
CFTypeID = Type("CFTypeID", "l") # XXXX a guess, seems better than OSTypeType.
|
||||
CFHashCode = Type("CFHashCode", "l")
|
||||
CFIndex = Type("CFIndex", "l")
|
||||
CFRange = OpaqueByValueType('CFRange', 'CFRange')
|
||||
CFOptionFlags = Type("CFOptionFlags", "l")
|
||||
CFStringEncoding = Type("CFStringEncoding", "l")
|
||||
CFComparisonResult = Type("CFComparisonResult", "l") # a bit dangerous, it's an enum
|
||||
CFURLPathStyle = Type("CFURLPathStyle", "l") # a bit dangerous, it's an enum
|
||||
|
||||
char_ptr = stringptr
|
||||
return_stringptr = Type("char *", "s") # ONLY FOR RETURN VALUES!!
|
||||
|
||||
CFAllocatorRef = FakeType("(CFAllocatorRef)NULL")
|
||||
CFArrayCallBacks_ptr = FakeType("&kCFTypeArrayCallBacks")
|
||||
CFDictionaryKeyCallBacks_ptr = FakeType("&kCFTypeDictionaryKeyCallBacks")
|
||||
CFDictionaryValueCallBacks_ptr = FakeType("&kCFTypeDictionaryValueCallBacks")
|
||||
# The real objects
|
||||
CFTypeRef = OpaqueByValueType("CFTypeRef", "CFTypeRefObj")
|
||||
CFArrayRef = OpaqueByValueType("CFArrayRef", "CFArrayRefObj")
|
||||
CFMutableArrayRef = OpaqueByValueType("CFMutableArrayRef", "CFMutableArrayRefObj")
|
||||
CFArrayRef = OpaqueByValueType("CFArrayRef", "CFArrayRefObj")
|
||||
CFMutableArrayRef = OpaqueByValueType("CFMutableArrayRef", "CFMutableArrayRefObj")
|
||||
CFDataRef = OpaqueByValueType("CFDataRef", "CFDataRefObj")
|
||||
CFMutableDataRef = OpaqueByValueType("CFMutableDataRef", "CFMutableDataRefObj")
|
||||
CFDictionaryRef = OpaqueByValueType("CFDictionaryRef", "CFDictionaryRefObj")
|
||||
CFMutableDictionaryRef = OpaqueByValueType("CFMutableDictionaryRef", "CFMutableDictionaryRefObj")
|
||||
CFStringRef = OpaqueByValueType("CFStringRef", "CFStringRefObj")
|
||||
CFMutableStringRef = OpaqueByValueType("CFMutableStringRef", "CFMutableStringRefObj")
|
||||
CFURLRef = OpaqueByValueType("CFURLRef", "CFURLRefObj")
|
||||
OptionalCFURLRef = OpaqueByValueType("CFURLRef", "OptionalCFURLRefObj")
|
||||
##CFPropertyListRef = OpaqueByValueType("CFPropertyListRef", "CFTypeRefObj")
|
||||
# ADD object type here
|
||||
|
||||
# Our (opaque) objects
|
||||
|
||||
class MyGlobalObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
def outputCheckNewArg(self):
|
||||
Output('if (itself == NULL)')
|
||||
OutLbrace()
|
||||
Output('PyErr_SetString(PyExc_RuntimeError, "cannot wrap NULL");')
|
||||
Output('return NULL;')
|
||||
OutRbrace()
|
||||
def outputStructMembers(self):
|
||||
GlobalObjectDefinition.outputStructMembers(self)
|
||||
Output("void (*ob_freeit)(CFTypeRef ptr);")
|
||||
def outputInitStructMembers(self):
|
||||
GlobalObjectDefinition.outputInitStructMembers(self)
|
||||
## Output("it->ob_freeit = NULL;")
|
||||
Output("it->ob_freeit = CFRelease;")
|
||||
def outputCheckConvertArg(self):
|
||||
Out("""
|
||||
if (v == Py_None) { *p_itself = NULL; return 1; }
|
||||
/* Check for other CF objects here */
|
||||
""")
|
||||
def outputCleanupStructMembers(self):
|
||||
Output("if (self->ob_freeit && self->ob_itself)")
|
||||
OutLbrace()
|
||||
Output("self->ob_freeit((CFTypeRef)self->ob_itself);")
|
||||
Output("self->ob_itself = NULL;")
|
||||
OutRbrace()
|
||||
|
||||
def outputCompare(self):
|
||||
Output()
|
||||
Output("static int %s_compare(%s *self, %s *other)", self.prefix, self.objecttype, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("/* XXXX Or should we use CFEqual?? */")
|
||||
Output("if ( self->ob_itself > other->ob_itself ) return 1;")
|
||||
Output("if ( self->ob_itself < other->ob_itself ) return -1;")
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
|
||||
def outputHash(self):
|
||||
Output()
|
||||
Output("static int %s_hash(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("/* XXXX Or should we use CFHash?? */")
|
||||
Output("return (int)self->ob_itself;")
|
||||
OutRbrace()
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFTypeRef type-%%d object at 0x%%8.8x for 0x%%8.8x>", (int)CFGetTypeID(self->ob_itself), (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
def output_tp_newBody(self):
|
||||
Output("PyObject *self;")
|
||||
Output
|
||||
Output("if ((self = type->tp_alloc(type, 0)) == NULL) return NULL;")
|
||||
Output("((%s *)self)->ob_itself = NULL;", self.objecttype)
|
||||
Output("((%s *)self)->ob_freeit = CFRelease;", self.objecttype)
|
||||
Output("return self;")
|
||||
|
||||
def output_tp_initBody(self):
|
||||
Output("%s itself;", self.itselftype)
|
||||
Output("char *kw[] = {\"itself\", 0};")
|
||||
Output()
|
||||
Output("if (PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, %s_Convert, &itself))",
|
||||
self.prefix)
|
||||
OutLbrace()
|
||||
Output("((%s *)_self)->ob_itself = itself;", self.objecttype)
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
if self.prefix != 'CFTypeRefObj':
|
||||
Output()
|
||||
Output("/* Any CFTypeRef descendent is allowed as initializer too */")
|
||||
Output("if (PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, CFTypeRefObj_Convert, &itself))")
|
||||
OutLbrace()
|
||||
Output("((%s *)_self)->ob_itself = itself;", self.objecttype)
|
||||
Output("return 0;")
|
||||
OutRbrace()
|
||||
Output("return -1;")
|
||||
|
||||
class CFTypeRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
pass
|
||||
|
||||
class CFArrayRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFTypeRef_Type"
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFArrayRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFMutableArrayRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFArrayRef_Type"
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFMutableArrayRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFDictionaryRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFTypeRef_Type"
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFDictionaryRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFMutableDictionaryRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFDictionaryRef_Type"
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFMutableDictionaryRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFDataRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFTypeRef_Type"
|
||||
|
||||
def outputCheckConvertArg(self):
|
||||
Out("""
|
||||
if (v == Py_None) { *p_itself = NULL; return 1; }
|
||||
if (PyString_Check(v)) {
|
||||
char *cStr;
|
||||
int cLen;
|
||||
if( PyString_AsStringAndSize(v, &cStr, &cLen) < 0 ) return 0;
|
||||
*p_itself = CFDataCreate((CFAllocatorRef)NULL, (unsigned char *)cStr, cLen);
|
||||
return 1;
|
||||
}
|
||||
""")
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFDataRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFMutableDataRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFDataRef_Type"
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFMutableDataRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFStringRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFTypeRef_Type"
|
||||
|
||||
def outputCheckConvertArg(self):
|
||||
Out("""
|
||||
if (v == Py_None) { *p_itself = NULL; return 1; }
|
||||
if (PyString_Check(v)) {
|
||||
char *cStr;
|
||||
if (!PyArg_Parse(v, "es", "ascii", &cStr))
|
||||
return NULL;
|
||||
*p_itself = CFStringCreateWithCString((CFAllocatorRef)NULL, cStr, kCFStringEncodingASCII);
|
||||
PyMem_Free(cStr);
|
||||
return 1;
|
||||
}
|
||||
if (PyUnicode_Check(v)) {
|
||||
/* We use the CF types here, if Python was configured differently that will give an error */
|
||||
CFIndex size = PyUnicode_GetSize(v);
|
||||
UniChar *unichars = PyUnicode_AsUnicode(v);
|
||||
if (!unichars) return 0;
|
||||
*p_itself = CFStringCreateWithCharacters((CFAllocatorRef)NULL, unichars, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
""")
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFStringRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFMutableStringRefObjectDefinition(CFStringRefObjectDefinition):
|
||||
basetype = "CFStringRef_Type"
|
||||
|
||||
def outputCheckConvertArg(self):
|
||||
# Mutable, don't allow Python strings
|
||||
return MyGlobalObjectDefinition.outputCheckConvertArg(self)
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFMutableStringRef object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
class CFURLRefObjectDefinition(MyGlobalObjectDefinition):
|
||||
basetype = "CFTypeRef_Type"
|
||||
|
||||
def outputRepr(self):
|
||||
Output()
|
||||
Output("static PyObject * %s_repr(%s *self)", self.prefix, self.objecttype)
|
||||
OutLbrace()
|
||||
Output("char buf[100];")
|
||||
Output("""sprintf(buf, "<CFURL object at 0x%%8.8x for 0x%%8.8x>", (unsigned)self, (unsigned)self->ob_itself);""")
|
||||
Output("return PyString_FromString(buf);")
|
||||
OutRbrace()
|
||||
|
||||
|
||||
# ADD object class here
|
||||
|
||||
# From here on it's basically all boiler plate...
|
||||
|
||||
# Create the generator groups and link them
|
||||
module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff, variablestuff)
|
||||
CFTypeRef_object = CFTypeRefObjectDefinition('CFTypeRef', 'CFTypeRefObj', 'CFTypeRef')
|
||||
CFArrayRef_object = CFArrayRefObjectDefinition('CFArrayRef', 'CFArrayRefObj', 'CFArrayRef')
|
||||
CFMutableArrayRef_object = CFMutableArrayRefObjectDefinition('CFMutableArrayRef', 'CFMutableArrayRefObj', 'CFMutableArrayRef')
|
||||
CFDictionaryRef_object = CFDictionaryRefObjectDefinition('CFDictionaryRef', 'CFDictionaryRefObj', 'CFDictionaryRef')
|
||||
CFMutableDictionaryRef_object = CFMutableDictionaryRefObjectDefinition('CFMutableDictionaryRef', 'CFMutableDictionaryRefObj', 'CFMutableDictionaryRef')
|
||||
CFDataRef_object = CFDataRefObjectDefinition('CFDataRef', 'CFDataRefObj', 'CFDataRef')
|
||||
CFMutableDataRef_object = CFMutableDataRefObjectDefinition('CFMutableDataRef', 'CFMutableDataRefObj', 'CFMutableDataRef')
|
||||
CFStringRef_object = CFStringRefObjectDefinition('CFStringRef', 'CFStringRefObj', 'CFStringRef')
|
||||
CFMutableStringRef_object = CFMutableStringRefObjectDefinition('CFMutableStringRef', 'CFMutableStringRefObj', 'CFMutableStringRef')
|
||||
CFURLRef_object = CFURLRefObjectDefinition('CFURLRef', 'CFURLRefObj', 'CFURLRef')
|
||||
|
||||
# ADD object here
|
||||
|
||||
module.addobject(CFTypeRef_object)
|
||||
module.addobject(CFArrayRef_object)
|
||||
module.addobject(CFMutableArrayRef_object)
|
||||
module.addobject(CFDictionaryRef_object)
|
||||
module.addobject(CFMutableDictionaryRef_object)
|
||||
module.addobject(CFDataRef_object)
|
||||
module.addobject(CFMutableDataRef_object)
|
||||
module.addobject(CFStringRef_object)
|
||||
module.addobject(CFMutableStringRef_object)
|
||||
module.addobject(CFURLRef_object)
|
||||
# ADD addobject call here
|
||||
|
||||
# Create the generator classes used to populate the lists
|
||||
Function = OSErrWeakLinkFunctionGenerator
|
||||
Method = OSErrWeakLinkMethodGenerator
|
||||
|
||||
# Create and populate the lists
|
||||
functions = []
|
||||
CFTypeRef_methods = []
|
||||
CFArrayRef_methods = []
|
||||
CFMutableArrayRef_methods = []
|
||||
CFDictionaryRef_methods = []
|
||||
CFMutableDictionaryRef_methods = []
|
||||
CFDataRef_methods = []
|
||||
CFMutableDataRef_methods = []
|
||||
CFStringRef_methods = []
|
||||
CFMutableStringRef_methods = []
|
||||
CFURLRef_methods = []
|
||||
|
||||
# ADD _methods initializer here
|
||||
execfile(INPUTFILE)
|
||||
|
||||
|
||||
# add the populated lists to the generator groups
|
||||
# (in a different wordl the scan program would generate this)
|
||||
for f in functions: module.add(f)
|
||||
for f in CFTypeRef_methods: CFTypeRef_object.add(f)
|
||||
for f in CFArrayRef_methods: CFArrayRef_object.add(f)
|
||||
for f in CFMutableArrayRef_methods: CFMutableArrayRef_object.add(f)
|
||||
for f in CFDictionaryRef_methods: CFDictionaryRef_object.add(f)
|
||||
for f in CFMutableDictionaryRef_methods: CFMutableDictionaryRef_object.add(f)
|
||||
for f in CFDataRef_methods: CFDataRef_object.add(f)
|
||||
for f in CFMutableDataRef_methods: CFMutableDataRef_object.add(f)
|
||||
for f in CFStringRef_methods: CFStringRef_object.add(f)
|
||||
for f in CFMutableStringRef_methods: CFMutableStringRef_object.add(f)
|
||||
for f in CFURLRef_methods: CFURLRef_object.add(f)
|
||||
|
||||
# Manual generators for getting data out of strings
|
||||
|
||||
getasstring_body = """
|
||||
int size = CFStringGetLength(_self->ob_itself)+1;
|
||||
char *data = malloc(size);
|
||||
|
||||
if( data == NULL ) return PyErr_NoMemory();
|
||||
if ( CFStringGetCString(_self->ob_itself, data, size, 0) ) {
|
||||
_res = (PyObject *)PyString_FromString(data);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_RuntimeError, "CFStringGetCString could not fit the string");
|
||||
_res = NULL;
|
||||
}
|
||||
free(data);
|
||||
return _res;
|
||||
"""
|
||||
|
||||
f = ManualGenerator("CFStringGetString", getasstring_body);
|
||||
f.docstring = lambda: "() -> (string _rv)"
|
||||
CFStringRef_object.add(f)
|
||||
|
||||
getasunicode_body = """
|
||||
int size = CFStringGetLength(_self->ob_itself)+1;
|
||||
Py_UNICODE *data = malloc(size*sizeof(Py_UNICODE));
|
||||
CFRange range;
|
||||
|
||||
range.location = 0;
|
||||
range.length = size;
|
||||
if( data == NULL ) return PyErr_NoMemory();
|
||||
CFStringGetCharacters(_self->ob_itself, range, data);
|
||||
_res = (PyObject *)PyUnicode_FromUnicode(data, size-1);
|
||||
free(data);
|
||||
return _res;
|
||||
"""
|
||||
|
||||
f = ManualGenerator("CFStringGetUnicode", getasunicode_body);
|
||||
f.docstring = lambda: "() -> (unicode _rv)"
|
||||
CFStringRef_object.add(f)
|
||||
|
||||
# Get data from CFDataRef
|
||||
getasdata_body = """
|
||||
int size = CFDataGetLength(_self->ob_itself);
|
||||
char *data = (char *)CFDataGetBytePtr(_self->ob_itself);
|
||||
|
||||
_res = (PyObject *)PyString_FromStringAndSize(data, size);
|
||||
return _res;
|
||||
"""
|
||||
|
||||
f = ManualGenerator("CFDataGetData", getasdata_body);
|
||||
f.docstring = lambda: "() -> (string _rv)"
|
||||
CFDataRef_object.add(f)
|
||||
|
||||
# Manual generator for CFPropertyListCreateFromXMLData because of funny error return
|
||||
fromxml_body = """
|
||||
CFTypeRef _rv;
|
||||
CFOptionFlags mutabilityOption;
|
||||
CFStringRef errorString;
|
||||
if (!PyArg_ParseTuple(_args, "l",
|
||||
&mutabilityOption))
|
||||
return NULL;
|
||||
_rv = CFPropertyListCreateFromXMLData((CFAllocatorRef)NULL,
|
||||
_self->ob_itself,
|
||||
mutabilityOption,
|
||||
&errorString);
|
||||
if (errorString)
|
||||
CFRelease(errorString);
|
||||
if (_rv == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Parse error in XML data");
|
||||
return NULL;
|
||||
}
|
||||
_res = Py_BuildValue("O&",
|
||||
CFTypeRefObj_New, _rv);
|
||||
return _res;
|
||||
"""
|
||||
f = ManualGenerator("CFPropertyListCreateFromXMLData", fromxml_body)
|
||||
f.docstring = lambda: "(CFOptionFlags mutabilityOption) -> (CFTypeRefObj)"
|
||||
CFTypeRef_object.add(f)
|
||||
|
||||
# Convert CF objects to Python objects
|
||||
toPython_body = """
|
||||
_res = PyCF_CF2Python(_self->ob_itself);
|
||||
return _res;
|
||||
"""
|
||||
|
||||
f = ManualGenerator("toPython", toPython_body);
|
||||
f.docstring = lambda: "() -> (python_object)"
|
||||
CFTypeRef_object.add(f)
|
||||
|
||||
toCF_body = """
|
||||
CFTypeRef rv;
|
||||
CFTypeID typeid;
|
||||
|
||||
if (!PyArg_ParseTuple(_args, "O&", PyCF_Python2CF, &rv))
|
||||
return NULL;
|
||||
typeid = CFGetTypeID(rv);
|
||||
|
||||
if (typeid == CFStringGetTypeID())
|
||||
return Py_BuildValue("O&", CFStringRefObj_New, rv);
|
||||
if (typeid == CFArrayGetTypeID())
|
||||
return Py_BuildValue("O&", CFArrayRefObj_New, rv);
|
||||
if (typeid == CFDictionaryGetTypeID())
|
||||
return Py_BuildValue("O&", CFDictionaryRefObj_New, rv);
|
||||
if (typeid == CFURLGetTypeID())
|
||||
return Py_BuildValue("O&", CFURLRefObj_New, rv);
|
||||
|
||||
_res = Py_BuildValue("O&", CFTypeRefObj_New, rv);
|
||||
return _res;
|
||||
"""
|
||||
f = ManualGenerator("toCF", toCF_body);
|
||||
f.docstring = lambda: "(python_object) -> (CF_object)"
|
||||
module.add(f)
|
||||
|
||||
# ADD add forloop here
|
||||
|
||||
# generate output (open the output file as late as possible)
|
||||
SetOutputFileName(OUTPUTFILE)
|
||||
module.generate()
|
||||
303
Mac/Modules/cf/pycfbridge.c
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
** Convert objects from Python to CoreFoundation and vice-versa.
|
||||
*/
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#include "Python.h"
|
||||
#include "pymactoolbox.h"
|
||||
#include "pycfbridge.h"
|
||||
|
||||
|
||||
/* ---------------------------------------- */
|
||||
/* CoreFoundation objects to Python objects */
|
||||
/* ---------------------------------------- */
|
||||
|
||||
PyObject *
|
||||
PyCF_CF2Python(CFTypeRef src) {
|
||||
CFTypeID typeid;
|
||||
|
||||
if( src == NULL ) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
typeid = CFGetTypeID(src);
|
||||
if (typeid == CFArrayGetTypeID())
|
||||
return PyCF_CF2Python_sequence((CFArrayRef)src);
|
||||
if (typeid == CFDictionaryGetTypeID())
|
||||
return PyCF_CF2Python_mapping((CFDictionaryRef)src);
|
||||
return PyCF_CF2Python_simple(src);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyCF_CF2Python_sequence(CFArrayRef src) {
|
||||
int size = CFArrayGetCount(src);
|
||||
PyObject *rv;
|
||||
CFTypeRef item_cf;
|
||||
PyObject *item_py = NULL;
|
||||
int i;
|
||||
|
||||
if ( (rv=PyList_New(size)) == NULL )
|
||||
return NULL;
|
||||
for(i=0; i<size; i++) {
|
||||
item_cf = CFArrayGetValueAtIndex(src, i);
|
||||
if (item_cf == NULL ) goto err;
|
||||
item_py = PyCF_CF2Python(item_cf);
|
||||
if (item_py == NULL ) goto err;
|
||||
if (PyList_SetItem(rv, i, item_py) < 0) goto err;
|
||||
item_py = NULL;
|
||||
}
|
||||
return rv;
|
||||
err:
|
||||
Py_XDECREF(item_py);
|
||||
Py_DECREF(rv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyCF_CF2Python_mapping(CFTypeRef src) {
|
||||
int size = CFDictionaryGetCount(src);
|
||||
PyObject *rv = NULL;
|
||||
CFTypeRef *allkeys = NULL, *allvalues = NULL;
|
||||
CFTypeRef key_cf, value_cf;
|
||||
PyObject *key_py = NULL, *value_py = NULL;
|
||||
int i;
|
||||
|
||||
allkeys = malloc(size*sizeof(CFTypeRef *));
|
||||
if (allkeys == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto err;
|
||||
}
|
||||
allvalues = malloc(size*sizeof(CFTypeRef *));
|
||||
if (allvalues == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto err;
|
||||
}
|
||||
if ( (rv=PyDict_New()) == NULL ) goto err;
|
||||
CFDictionaryGetKeysAndValues(src, allkeys, allvalues);
|
||||
for(i=0; i<size; i++) {
|
||||
key_cf = allkeys[i];
|
||||
value_cf = allvalues[i];
|
||||
key_py = PyCF_CF2Python(key_cf);
|
||||
if (key_py == NULL ) goto err;
|
||||
value_py = PyCF_CF2Python(value_cf);
|
||||
if (value_py == NULL ) goto err;
|
||||
if (PyDict_SetItem(rv, key_py, value_py) < 0) goto err;
|
||||
key_py = NULL;
|
||||
value_py = NULL;
|
||||
}
|
||||
return rv;
|
||||
err:
|
||||
Py_XDECREF(key_py);
|
||||
Py_XDECREF(value_py);
|
||||
Py_XDECREF(rv);
|
||||
free(allkeys);
|
||||
free(allvalues);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyCF_CF2Python_simple(CFTypeRef src) {
|
||||
CFTypeID typeid;
|
||||
|
||||
typeid = CFGetTypeID(src);
|
||||
if (typeid == CFStringGetTypeID())
|
||||
return PyCF_CF2Python_string((CFStringRef)src);
|
||||
if (typeid == CFBooleanGetTypeID())
|
||||
return PyBool_FromLong((long)CFBooleanGetValue(src));
|
||||
if (typeid == CFNumberGetTypeID()) {
|
||||
if (CFNumberIsFloatType(src)) {
|
||||
double d;
|
||||
CFNumberGetValue(src, kCFNumberDoubleType, &d);
|
||||
return PyFloat_FromDouble(d);
|
||||
} else {
|
||||
long l;
|
||||
if (!CFNumberGetValue(src, kCFNumberLongType, &l))
|
||||
/* XXXX Out of range! */;
|
||||
return PyInt_FromLong(l);
|
||||
}
|
||||
}
|
||||
/* XXXX Should return as CFTypeRef, really... */
|
||||
PyMac_Error(resNotFound);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Unsure - Return unicode or 8 bit strings? */
|
||||
PyObject *
|
||||
PyCF_CF2Python_string(CFStringRef src) {
|
||||
int size = CFStringGetLength(src)+1;
|
||||
Py_UNICODE *data = malloc(size*sizeof(Py_UNICODE));
|
||||
CFRange range;
|
||||
PyObject *rv;
|
||||
|
||||
range.location = 0;
|
||||
range.length = size;
|
||||
if( data == NULL ) return PyErr_NoMemory();
|
||||
CFStringGetCharacters(src, range, data);
|
||||
rv = (PyObject *)PyUnicode_FromUnicode(data, size-1);
|
||||
free(data);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* ---------------------------------------- */
|
||||
/* Python objects to CoreFoundation objects */
|
||||
/* ---------------------------------------- */
|
||||
|
||||
int
|
||||
PyCF_Python2CF(PyObject *src, CFTypeRef *dst) {
|
||||
|
||||
if (PyString_Check(src) || PyUnicode_Check(src))
|
||||
return PyCF_Python2CF_simple(src, dst);
|
||||
if (PySequence_Check(src))
|
||||
return PyCF_Python2CF_sequence(src, (CFArrayRef *)dst);
|
||||
if (PyMapping_Check(src))
|
||||
return PyCF_Python2CF_mapping(src, (CFDictionaryRef *)dst);
|
||||
return PyCF_Python2CF_simple(src, dst);
|
||||
}
|
||||
|
||||
int
|
||||
PyCF_Python2CF_sequence(PyObject *src, CFArrayRef *dst) {
|
||||
CFMutableArrayRef rv = NULL;
|
||||
CFTypeRef item_cf = NULL;
|
||||
PyObject *item_py = NULL;
|
||||
int size, i;
|
||||
|
||||
if( !PySequence_Check(src) ) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Cannot convert %.500s objects to CFArray",
|
||||
src->ob_type->tp_name);
|
||||
return 0;
|
||||
}
|
||||
size = PySequence_Size(src);
|
||||
rv = CFArrayCreateMutable((CFAllocatorRef)NULL, size, &kCFTypeArrayCallBacks);
|
||||
if (rv == NULL) {
|
||||
PyMac_Error(resNotFound);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for( i=0; i<size; i++) {
|
||||
item_py = PySequence_GetItem(src, i);
|
||||
if (item_py == NULL) goto err;
|
||||
if ( !PyCF_Python2CF(item_py, &item_cf)) goto err;
|
||||
Py_DECREF(item_py);
|
||||
CFArraySetValueAtIndex(rv, i, item_cf);
|
||||
CFRelease(item_cf);
|
||||
item_cf = NULL;
|
||||
}
|
||||
*dst = rv;
|
||||
return 1;
|
||||
err:
|
||||
Py_XDECREF(item_py);
|
||||
if (rv) CFRelease(rv);
|
||||
if (item_cf) CFRelease(item_cf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyCF_Python2CF_mapping(PyObject *src, CFDictionaryRef *dst) {
|
||||
CFMutableDictionaryRef rv = NULL;
|
||||
PyObject *aslist = NULL;
|
||||
CFTypeRef key_cf = NULL, value_cf = NULL;
|
||||
PyObject *item_py = NULL, *key_py = NULL, *value_py = NULL;
|
||||
int size, i;
|
||||
|
||||
if( !PyMapping_Check(src) ) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Cannot convert %.500s objects to CFDictionary",
|
||||
src->ob_type->tp_name);
|
||||
return 0;
|
||||
}
|
||||
size = PyMapping_Size(src);
|
||||
rv = CFDictionaryCreateMutable((CFAllocatorRef)NULL, size,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
if (rv == NULL) {
|
||||
PyMac_Error(resNotFound);
|
||||
goto err;
|
||||
}
|
||||
if ( (aslist = PyMapping_Items(src)) == NULL ) goto err;
|
||||
|
||||
for( i=0; i<size; i++) {
|
||||
item_py = PySequence_GetItem(aslist, i);
|
||||
if (item_py == NULL) goto err;
|
||||
if (!PyArg_ParseTuple(item_py, "OO", &key_py, &value_py)) goto err;
|
||||
if ( !PyCF_Python2CF(key_py, &key_cf) ) goto err;
|
||||
if ( !PyCF_Python2CF(value_py, &value_cf) ) goto err;
|
||||
CFDictionaryAddValue(rv, key_cf, value_cf);
|
||||
CFRelease(key_cf);
|
||||
key_cf = NULL;
|
||||
CFRelease(value_cf);
|
||||
value_cf = NULL;
|
||||
}
|
||||
*dst = rv;
|
||||
return 1;
|
||||
err:
|
||||
Py_XDECREF(item_py);
|
||||
Py_XDECREF(aslist);
|
||||
if (rv) CFRelease(rv);
|
||||
if (key_cf) CFRelease(key_cf);
|
||||
if (value_cf) CFRelease(value_cf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyCF_Python2CF_simple(PyObject *src, CFTypeRef *dst) {
|
||||
|
||||
#if 0
|
||||
if (PyObject_HasAttrString(src, "CFType")) {
|
||||
*dst = PyObject_CallMethod(src, "CFType", "");
|
||||
return (*dst != NULL);
|
||||
}
|
||||
#endif
|
||||
if (PyString_Check(src) || PyUnicode_Check(src))
|
||||
return PyCF_Python2CF_string(src, (CFStringRef *)dst);
|
||||
if (PyBool_Check(src)) {
|
||||
if (src == Py_True)
|
||||
*dst = kCFBooleanTrue;
|
||||
else
|
||||
*dst = kCFBooleanFalse;
|
||||
return 1;
|
||||
}
|
||||
if (PyInt_Check(src)) {
|
||||
long v = PyInt_AsLong(src);
|
||||
*dst = CFNumberCreate(NULL, kCFNumberLongType, &v);
|
||||
return 1;
|
||||
}
|
||||
if (PyFloat_Check(src)) {
|
||||
double d = PyFloat_AsDouble(src);
|
||||
*dst = CFNumberCreate(NULL, kCFNumberDoubleType, &d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Cannot convert %.500s objects to CFType",
|
||||
src->ob_type->tp_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyCF_Python2CF_string(PyObject *src, CFStringRef *dst) {
|
||||
char *chars;
|
||||
CFIndex size;
|
||||
UniChar *unichars;
|
||||
|
||||
if (PyString_Check(src)) {
|
||||
if (!PyArg_Parse(src, "es", "ascii", &chars))
|
||||
return 0; /* This error is more descriptive than the general one below */
|
||||
*dst = CFStringCreateWithCString((CFAllocatorRef)NULL, chars, kCFStringEncodingASCII);
|
||||
PyMem_Free(chars);
|
||||
return 1;
|
||||
}
|
||||
if (PyUnicode_Check(src)) {
|
||||
/* We use the CF types here, if Python was configured differently that will give an error */
|
||||
size = PyUnicode_GetSize(src);
|
||||
if ((unichars = PyUnicode_AsUnicode(src)) == NULL ) goto err;
|
||||
*dst = CFStringCreateWithCharacters((CFAllocatorRef)NULL, unichars, size);
|
||||
return 1;
|
||||
}
|
||||
err:
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Cannot convert %.500s objects to CFString",
|
||||
src->ob_type->tp_name);
|
||||
return 0;
|
||||
}
|
||||
11
Mac/Modules/cf/pycfbridge.h
Normal file
@@ -0,0 +1,11 @@
|
||||
extern PyObject *PyCF_CF2Python(CFTypeRef src);
|
||||
extern PyObject *PyCF_CF2Python_sequence(CFArrayRef src);
|
||||
extern PyObject *PyCF_CF2Python_mapping(CFTypeRef src);
|
||||
extern PyObject *PyCF_CF2Python_simple(CFTypeRef src);
|
||||
extern PyObject *PyCF_CF2Python_string(CFStringRef src);
|
||||
|
||||
extern int PyCF_Python2CF(PyObject *src, CFTypeRef *dst);
|
||||
extern int PyCF_Python2CF_sequence(PyObject *src, CFArrayRef *dst);
|
||||
extern int PyCF_Python2CF_mapping(PyObject *src, CFDictionaryRef *dst);
|
||||
extern int PyCF_Python2CF_simple(PyObject *src, CFTypeRef *dst);
|
||||
extern int PyCF_Python2CF_string(PyObject *src, CFStringRef *dst);
|
||||
1360
Mac/Modules/cg/CFMLateImport.c
Normal file
272
Mac/Modules/cg/CFMLateImport.h
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
File: CFMLateImport.h
|
||||
|
||||
Contains: Interface to CFM late import library.
|
||||
|
||||
Written by: Quinn
|
||||
|
||||
Copyright: Copyright <20> 1999 by Apple Computer, Inc., all rights reserved.
|
||||
|
||||
You may incorporate this Apple sample source code into your program(s) without
|
||||
restriction. This Apple sample source code has been provided "AS IS" and the
|
||||
responsibility for its operation is yours. You are not permitted to redistribute
|
||||
this Apple sample source code as "Apple sample source code" after having made
|
||||
changes. If you're going to re-distribute the source, we require that you make
|
||||
it clear in the source that the code was descended from Apple sample source
|
||||
code, but that you've made changes.
|
||||
|
||||
Change History (most recent first):
|
||||
|
||||
<6> 21/9/01 Quinn Changes for CWPro7 Mach-O build.
|
||||
<5> 19/9/01 Quinn Change comments to reflect the fact that an unpacked data
|
||||
section is no longer required.
|
||||
<4> 19/9/01 Quinn Simplified API and implementation after a suggestion by Eric
|
||||
Grant. You no longer have to CFM export a dummy function; you
|
||||
can just pass in the address of your fragment's init routine.
|
||||
<3> 16/11/00 Quinn Allow symbol finding via a callback and use that to implement
|
||||
CFBundle support.
|
||||
<2> 18/10/99 Quinn Renamed CFMLateImport to CFMLateImportLibrary to allow for
|
||||
possible future API expansion.
|
||||
<1> 15/6/99 Quinn First checked in.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
// MoreIsBetter Setup
|
||||
|
||||
//#include "MoreSetup.h"
|
||||
|
||||
// Mac OS Interfaces
|
||||
|
||||
#if ! MORE_FRAMEWORK_INCLUDES
|
||||
#include <MacTypes.h>
|
||||
#include <CodeFragments.h>
|
||||
#include <Devices.h>
|
||||
#include <CFBundle.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* FAQ
|
||||
---
|
||||
|
||||
Q: What does this library do?
|
||||
A: It allows you to resolve a weak linked library at runtime,
|
||||
by supply a CFM connection to the library that should substitute
|
||||
for the weak linked one.
|
||||
|
||||
Q: Does the substituted library have to have the same name as the
|
||||
weak linked library.
|
||||
A: No.
|
||||
|
||||
Q: What's this useful for?
|
||||
A: The most obvious example of where this is useful is when
|
||||
you rely on shared libraries that the user might delete
|
||||
or move. To can find the shared library (possibly even
|
||||
using CatSearch), call GetDiskFragment to open a connection
|
||||
to it, late import it using this library, and then the
|
||||
rest of your code can continue to use the shared library
|
||||
as if nothing had happened. No more defining thousands
|
||||
of stub routines which call through routine pointers.
|
||||
|
||||
There are, however, numerous less obvious uses. You can
|
||||
use this code to make a 'self repairing' application. If
|
||||
the user removes your shared library from the Extensions
|
||||
folder, the startup code for your application can offer
|
||||
tor re-install it. If the user agrees, you can then
|
||||
re-install your shared library, late import it, and then
|
||||
continue running your application if nothing happened.
|
||||
|
||||
You can even use this code to free yourself from the
|
||||
Extensions folder entirely. Say you have a suite of
|
||||
applications that currently installs a dozen shared
|
||||
libraries in the Extensions folder. You can move those
|
||||
libraries to another folder entirely and each application's
|
||||
startup code can track down the library (using an alias
|
||||
in the Preferences file) and late import it.
|
||||
|
||||
An even cooler use is to provide easy abstraction layers.
|
||||
Say you have a network code for both the MacTCP
|
||||
API and the Open Transport API. Typically, you would be
|
||||
force to do this by having an abstraction layer where every
|
||||
routine contains a switch between MacTCP and OT. Your
|
||||
OpenSocket routine might look like:
|
||||
|
||||
static int OpenSocket(void)
|
||||
{
|
||||
if (gOTAvailable) {
|
||||
return OpenSocketOT();
|
||||
} else {
|
||||
return OpenSocketMacTCP();
|
||||
}
|
||||
}
|
||||
|
||||
With this code, you can avoid that entirely. Simply
|
||||
weak link to a shared library that you know is never
|
||||
going to be implemented ("crea;MySocketsDummy") and then,
|
||||
at runtime, decide whether the system has MacTCP or OT
|
||||
and late import the relevant real implementation
|
||||
("crea;MySocketsMacTCP" or "crea;MySocketsOT").
|
||||
One benefit of this approach is that only the MacTCP or
|
||||
the OT code is resident in memory on any given system.
|
||||
*/
|
||||
|
||||
typedef pascal OSStatus (*CFMLateImportLookupProc)(ConstStr255Param symName, CFragSymbolClass symClass,
|
||||
void **symAddr, void *refCon);
|
||||
// CFMLateImportLookupProc defines a callback for CFMLateImportCore.
|
||||
// The routine is expected to look up the address of the symbol named
|
||||
// symName and return it in *symAddr. The symbol should be of class
|
||||
// symClass, although the callback decides whether a class mismatch is
|
||||
// an error. refCon is an application defined value that was originally
|
||||
// passed in to CFMLateImportCore.
|
||||
//
|
||||
// If this routine returns an error, a symbol address of 0 is assumed.
|
||||
// If the symbol is marked as a weak import, the CFMLateImportCore will
|
||||
// continue, otherwise the CFMLateImportCore routine will fail with the
|
||||
// error.
|
||||
|
||||
extern pascal OSStatus CFMLateImportCore(const CFragSystem7DiskFlatLocator *fragToFixLocator,
|
||||
CFragConnectionID fragToFixConnID,
|
||||
CFragInitFunction fragToFixInitRoutine,
|
||||
ConstStr255Param weakLinkedLibraryName,
|
||||
CFMLateImportLookupProc lookup,
|
||||
void *refCon);
|
||||
// This routine will link you, at runtime, to some library
|
||||
// that you were weak linked to and wasn't present when your
|
||||
// fragment was prepared. As well as the obvious functionality
|
||||
// of being able to resolve weak links after prepare time,
|
||||
// this functionality can be put to a number of less obvious uses,
|
||||
// some of which are discussed at the top of this header file.
|
||||
//
|
||||
// To call this routine, you need a number of pieces of information:
|
||||
//
|
||||
// 1. fragToFixLocator, fragToFixConnID: The location of your own
|
||||
// code fragment on disk and the CFM connection ID to your own
|
||||
// code fragment. Typically you get this information from your
|
||||
// fragment's CFM init routine. You must ensure that
|
||||
// fragToFixLocator->fileSpec points to an FSSpec of the
|
||||
// file which holds your code fragment.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// The fact that you pass in a CFragSystem7DiskFlatLocator as the
|
||||
// fragToFixLocator implies that the fragment to be fixed up must
|
||||
// be in the data fork of a file. The code could be modified
|
||||
// to remove this requirement, but on disk code fragments are the most
|
||||
// common case.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// The fragment to fix may have a packed data section. Packing the
|
||||
// data section will reduce the size of your fragment on disk, but it
|
||||
// will significantly increase the memory needed by this routine
|
||||
// (it increases memory usage by the sum of the sizes of the packed
|
||||
// and unpacked data section). See below for instructions on how to
|
||||
// create an unpacked data section.
|
||||
//
|
||||
// 2. fragToFixInitRoutine: A pointer to your own code fragment's
|
||||
// fragment initialiser routine. You necessarily have one of these
|
||||
// because you need it to get values for the fragToFixLocator and
|
||||
// fragToFixConnID parameters. Just pass its address in as a parameter
|
||||
// as well.
|
||||
//
|
||||
// 3. weakLinkedLibraryName: The name of the weak linked library which
|
||||
// failed to link. You must have weak linked to this library.
|
||||
// It is oxymoric for you to pass a strong linked library here,
|
||||
// because your code would not have prepared if a strong linked
|
||||
// library failed to prepare, and so you couldn't supply a valid
|
||||
/// fragToFix.
|
||||
//
|
||||
// 4. lookup, refCon: A pointer to a callback function that the
|
||||
// routine calls to look up the address of a symbol, and a refCon
|
||||
// for that callback routine.
|
||||
//
|
||||
// Note:
|
||||
// The fragToFixLocator and fragToFixInitRoutine parameters
|
||||
// are artifacts of the way in which this functionality is implemented.
|
||||
// In an ideal world, where CFM exported decent introspection APIs
|
||||
// to third party developers, these parameters would not be necessary.
|
||||
// If you're using this code inside Apple, you probably should investigate
|
||||
// using the CFM private APIs for getting at the information these
|
||||
// parameters are needed for. See the comments inside the implementation
|
||||
// for more details.
|
||||
//
|
||||
// Note:
|
||||
// The extra memory taken when you use a packed data section is also an
|
||||
// artifact of my workaround for the lack of CFM introspection APIs. In
|
||||
// my opinion it's better to use an unpacked data section and consume more
|
||||
// space on disk while saving memory. In CodeWarrior you can switch to an
|
||||
// unpacked data section by checking the "Expand Uninitialized Data"
|
||||
// checkbox in the "PPC PEF" settings panel. In MPW, specified the
|
||||
// "-packdata off" option to PPCLink.
|
||||
//
|
||||
// When the routine returns, any symbols that you imported from the
|
||||
// library named weakLinkedLibraryName will be resolved to the address
|
||||
// of the symbol provided by the "lookup" callback routine.
|
||||
//
|
||||
// It is possible for an unresolved import to remain unresolved after
|
||||
// this routine returns. If the symbol import is marked as weak (as
|
||||
// opposed to the library, which *must* be marked as weak) and the symbol
|
||||
// is not found by the "lookup" callback, the routine will simple skip
|
||||
// that symbol. If the symbol isn't marked as weak, the routine will fail
|
||||
// in that case.
|
||||
//
|
||||
// Most of the possible error results are co-opted CFM errors. These
|
||||
// include:
|
||||
//
|
||||
// cfragFragmentFormatErr -- The fragment to fix is is an unknown format.
|
||||
// cfragNoSectionErr -- Could not find the loader section in the fragment to fix.
|
||||
// cfragNoLibraryErr -- The fragment to fix is not weak linked to weakLinkedLibraryName.
|
||||
// cfragFragmentUsageErr -- The fragment to fix doesn't have a data section.
|
||||
// -- The fragment to fix is strong linked to weakLinkedLibraryName.
|
||||
// -- The fragment doesn't have an init routine.
|
||||
// cfragFragmentCorruptErr -- Encountered an undefined relocation opcode.
|
||||
// unimpErr -- Encountered an unimplement relocation opcode. The
|
||||
// relocation engine only implements a subset of the CFM
|
||||
// relocation opcodes, the subset most commonly used by
|
||||
// MPW and CodeWarrior PEF containers. If you encounter
|
||||
// this error, you'll probably have to add the weird
|
||||
// relocation opcode to the engine, which shouldn't be
|
||||
// be too hard.
|
||||
// memFullErr -- It's likely that this error is triggered by the memory
|
||||
// needed to unpack your data section. Either make your
|
||||
// data section smaller, or unpack it (see above).
|
||||
// errors returned by FindSymbol
|
||||
// errors returned by Memory Manager
|
||||
//
|
||||
// The routine needs enough memory to hold the loader section of the fragment
|
||||
// to fix in memory. It allocates that memory using NewPtr and dispsoses of
|
||||
// it before it returns. You may want to change the memory allocator, which
|
||||
// is very simple.
|
||||
|
||||
extern pascal OSStatus CFMLateImportLibrary(const CFragSystem7DiskFlatLocator *fragToFixLocator,
|
||||
CFragConnectionID fragToFixConnID,
|
||||
CFragInitFunction fragToFixInitRoutine,
|
||||
ConstStr255Param weakLinkedLibraryName,
|
||||
CFragConnectionID connIDToImport);
|
||||
// A wrapper around CFMLateImportCore that looks up symbols by calling
|
||||
// FindSymbol on a connection to a CFM library (connIDToImport).
|
||||
// You can get this connection ID through any standard CFM API, for example
|
||||
// GetSharedLibrary, GetDiskFragment, or GetMemFragment.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// The fragment name for connIDToImport *does not* have to match
|
||||
// weakLinkedLibraryName. This is part of the power of this library.
|
||||
|
||||
extern pascal OSStatus CFMLateImportBundle(const CFragSystem7DiskFlatLocator *fragToFixLocator,
|
||||
CFragConnectionID fragToFixConnID,
|
||||
CFragInitFunction fragToFixInitRoutine,
|
||||
ConstStr255Param weakLinkedLibraryName,
|
||||
CFBundleRef bundleToImport);
|
||||
// A wrapper around CFMLateImportCore that looks up symbols by calling
|
||||
// CFBundleGetFunctionPointerForName on a reference to a Core Foundation
|
||||
// bundle (bundleToImport). You can get this reference through any
|
||||
// Core Foundation bundle API, for example CFBundleCreate.
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
BIN
Mac/Modules/cg/CGStubLib
Executable file
60
Mac/Modules/cg/CGStubLib.exp
Normal file
@@ -0,0 +1,60 @@
|
||||
CGContextShowTextAtPoint
|
||||
CGContextShowText
|
||||
CGContextSelectFont
|
||||
CGContextSetTextDrawingMode
|
||||
CGContextDrawPath
|
||||
CGContextSetLineJoin
|
||||
CGContextSetLineCap
|
||||
CGContextGetTextPosition
|
||||
CGContextGetPathCurrentPoint
|
||||
CGContextSetShouldAntialias
|
||||
CGContextSynchronize
|
||||
CGContextFlush
|
||||
CGContextEndPage
|
||||
CGContextSetFontSize
|
||||
CGContextGetTextMatrix
|
||||
CGContextSetTextMatrix
|
||||
CGContextSetTextPosition
|
||||
CGContextSetCharacterSpacing
|
||||
CGContextSetCMYKStrokeColor
|
||||
CGContextSetCMYKFillColor
|
||||
CGContextSetRGBStrokeColor
|
||||
CGContextSetRGBFillColor
|
||||
CGContextSetGrayStrokeColor
|
||||
CGContextSetGrayFillColor
|
||||
CGContextClipToRect
|
||||
CGContextEOClip
|
||||
CGContextClip
|
||||
CGContextClearRect
|
||||
CGContextStrokeRectWithWidth
|
||||
CGContextStrokeRect
|
||||
CGContextFillRect
|
||||
CGContextStrokePath
|
||||
CGContextEOFillPath
|
||||
CGContextFillPath
|
||||
CGContextGetPathBoundingBox
|
||||
CGContextIsPathEmpty
|
||||
CGContextAddArcToPoint
|
||||
CGContextAddArc
|
||||
CGContextAddRect
|
||||
CGContextClosePath
|
||||
CGContextAddQuadCurveToPoint
|
||||
CGContextAddCurveToPoint
|
||||
CGContextAddLineToPoint
|
||||
CGContextMoveToPoint
|
||||
CGContextBeginPath
|
||||
CGContextSetAlpha
|
||||
CGContextSetFlatness
|
||||
CGContextSetMiterLimit
|
||||
CGContextSetLineWidth
|
||||
CGContextGetCTM
|
||||
CGContextConcatCTM
|
||||
CGContextRotateCTM
|
||||
CGContextTranslateCTM
|
||||
CGContextScaleCTM
|
||||
CGContextRestoreGState
|
||||
CGContextSaveGState
|
||||
CGContextRelease
|
||||
CreateCGContextForPort
|
||||
SyncCGContextOriginWithPort
|
||||
ClipCGContextToRegion
|
||||
3
Mac/Modules/cg/CGStubLib.readme
Normal file
@@ -0,0 +1,3 @@
|
||||
# CGStubLib was created by issuing this command in MPW:
|
||||
|
||||
MakeStub CGStubLib.exp -o CGStubLib
|
||||
1316
Mac/Modules/cg/_CGmodule.c
Normal file
83
Mac/Modules/cg/cgscan.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# Scan an Apple header file, generating a Python file of generator calls.
|
||||
|
||||
import sys
|
||||
from bgenlocations import TOOLBOXDIR, BGENDIR
|
||||
sys.path.append(BGENDIR)
|
||||
from scantools import Scanner_OSX
|
||||
|
||||
LONG = "CoreGraphics"
|
||||
SHORT = "cg"
|
||||
OBJECTS = ("CGContextRef",
|
||||
)
|
||||
# ADD object typenames here
|
||||
|
||||
def main():
|
||||
input = [
|
||||
"CGContext.h",
|
||||
]
|
||||
output = SHORT + "gen.py"
|
||||
defsoutput = TOOLBOXDIR + LONG + ".py"
|
||||
scanner = MyScanner(input, output, defsoutput)
|
||||
scanner.scan()
|
||||
scanner.gentypetest(SHORT+"typetest.py")
|
||||
scanner.close()
|
||||
print "=== Testing definitions output code ==="
|
||||
execfile(defsoutput, {}, {})
|
||||
print "=== Done scanning and generating, now importing the generated code... ==="
|
||||
exec "import " + SHORT + "support"
|
||||
print "=== Done. It's up to you to compile it now! ==="
|
||||
|
||||
class MyScanner(Scanner_OSX):
|
||||
|
||||
def destination(self, type, name, arglist):
|
||||
classname = "Function"
|
||||
listname = "functions"
|
||||
if arglist:
|
||||
t, n, m = arglist[0]
|
||||
if t in OBJECTS and m == "InMode":
|
||||
classname = "Method"
|
||||
listname = t + "_methods"
|
||||
# Special case for the silly first AllocatorRef argument
|
||||
if t == 'CFAllocatorRef' and m == 'InMode' and len(arglist) > 1:
|
||||
t, n, m = arglist[1]
|
||||
if t in OBJECTS and m == "InMode":
|
||||
classname = "MethodSkipArg1"
|
||||
listname = t + "_methods"
|
||||
return classname, listname
|
||||
|
||||
def writeinitialdefs(self):
|
||||
self.defsfile.write("def FOUR_CHAR_CODE(x): return x\n")
|
||||
|
||||
def makeblacklistnames(self):
|
||||
return [
|
||||
"CGContextRetain",
|
||||
"CGContextRelease",
|
||||
]
|
||||
|
||||
def makegreylist(self):
|
||||
return []
|
||||
|
||||
def makeblacklisttypes(self):
|
||||
return [
|
||||
"float_ptr",
|
||||
"CGRect_ptr",
|
||||
"CGPoint_ptr",
|
||||
"CGColorSpaceRef",
|
||||
"CGColorRenderingIntent",
|
||||
"CGFontRef",
|
||||
# "char_ptr",
|
||||
"CGGlyph_ptr",
|
||||
"CGImageRef",
|
||||
"CGPDFDocumentRef",
|
||||
]
|
||||
|
||||
def makerepairinstructions(self):
|
||||
return [
|
||||
([("char_ptr", "cstring", "InMode"), ("size_t", "length", "InMode")],
|
||||
[("InBuffer", "*", "*")]),
|
||||
# ([("char_ptr", "name", "InMode"),],
|
||||
# [("CCCCC", "*", "*")]),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
192
Mac/Modules/cg/cgsupport.py
Normal file
@@ -0,0 +1,192 @@
|
||||
# This script generates a Python interface for an Apple Macintosh Manager.
|
||||
# It uses the "bgen" package to generate C code.
|
||||
# The function specifications are generated by scanning the mamager's header file,
|
||||
# using the "scantools" package (customized for this particular manager).
|
||||
|
||||
#error missing SetActionFilter
|
||||
|
||||
import string
|
||||
|
||||
# Declarations that change for each manager
|
||||
MODNAME = '_CG' # The name of the module
|
||||
|
||||
# The following is *usually* unchanged but may still require tuning
|
||||
MODPREFIX = 'CG' # The prefix for module-wide routines
|
||||
INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner
|
||||
OUTPUTFILE = MODNAME + "module.c" # The file generated by this program
|
||||
|
||||
from macsupport import *
|
||||
|
||||
CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj")
|
||||
RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
|
||||
|
||||
# Create the type objects
|
||||
|
||||
includestuff = includestuff + """
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
extern int GrafObj_Convert(PyObject *, GrafPtr *);
|
||||
|
||||
/*
|
||||
** Manual converters
|
||||
*/
|
||||
|
||||
PyObject *CGPoint_New(CGPoint *itself)
|
||||
{
|
||||
|
||||
return Py_BuildValue("(ff)",
|
||||
itself->x,
|
||||
itself->y);
|
||||
}
|
||||
|
||||
int
|
||||
CGPoint_Convert(PyObject *v, CGPoint *p_itself)
|
||||
{
|
||||
if( !PyArg_Parse(v, "(ff)",
|
||||
&p_itself->x,
|
||||
&p_itself->y) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject *CGRect_New(CGRect *itself)
|
||||
{
|
||||
|
||||
return Py_BuildValue("(ffff)",
|
||||
itself->origin.x,
|
||||
itself->origin.y,
|
||||
itself->size.width,
|
||||
itself->size.height);
|
||||
}
|
||||
|
||||
int
|
||||
CGRect_Convert(PyObject *v, CGRect *p_itself)
|
||||
{
|
||||
if( !PyArg_Parse(v, "(ffff)",
|
||||
&p_itself->origin.x,
|
||||
&p_itself->origin.y,
|
||||
&p_itself->size.width,
|
||||
&p_itself->size.height) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject *CGAffineTransform_New(CGAffineTransform *itself)
|
||||
{
|
||||
|
||||
return Py_BuildValue("(ffffff)",
|
||||
itself->a,
|
||||
itself->b,
|
||||
itself->c,
|
||||
itself->d,
|
||||
itself->tx,
|
||||
itself->ty);
|
||||
}
|
||||
|
||||
int
|
||||
CGAffineTransform_Convert(PyObject *v, CGAffineTransform *p_itself)
|
||||
{
|
||||
if( !PyArg_Parse(v, "(ffffff)",
|
||||
&p_itself->a,
|
||||
&p_itself->b,
|
||||
&p_itself->c,
|
||||
&p_itself->d,
|
||||
&p_itself->tx,
|
||||
&p_itself->ty) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
"""
|
||||
|
||||
class MyOpaqueByValueType(OpaqueByValueType):
|
||||
"""Sort of a mix between OpaqueByValueType and OpaqueType."""
|
||||
def mkvalueArgs(self, name):
|
||||
return "%s, &%s" % (self.new, name)
|
||||
|
||||
CGPoint = MyOpaqueByValueType('CGPoint', 'CGPoint')
|
||||
CGRect = MyOpaqueByValueType('CGRect', 'CGRect')
|
||||
CGAffineTransform = MyOpaqueByValueType('CGAffineTransform', 'CGAffineTransform')
|
||||
|
||||
char_ptr = Type("char *", "s")
|
||||
|
||||
CGTextEncoding = int
|
||||
CGLineCap = int
|
||||
CGLineJoin = int
|
||||
CGTextDrawingMode = int
|
||||
CGPathDrawingMode = int
|
||||
CGInterpolationQuality = int
|
||||
|
||||
# The real objects
|
||||
CGContextRef = OpaqueByValueType("CGContextRef", "CGContextRefObj")
|
||||
|
||||
|
||||
class MyObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
|
||||
def outputStructMembers(self):
|
||||
ObjectDefinition.outputStructMembers(self)
|
||||
def outputCleanupStructMembers(self):
|
||||
Output("CGContextRelease(self->ob_itself);")
|
||||
|
||||
|
||||
# Create the generator groups and link them
|
||||
module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff)
|
||||
|
||||
CGContextRef_object = MyObjectDefinition('CGContextRef', 'CGContextRefObj', 'CGContextRef')
|
||||
|
||||
|
||||
# ADD object here
|
||||
|
||||
module.addobject(CGContextRef_object)
|
||||
|
||||
|
||||
|
||||
Function = FunctionGenerator
|
||||
Method = MethodGenerator
|
||||
|
||||
CGContextRef_methods = []
|
||||
|
||||
# ADD _methods initializer here
|
||||
execfile(INPUTFILE)
|
||||
|
||||
# manual method, lives in Quickdraw.h
|
||||
f = Method(void, 'SyncCGContextOriginWithPort',
|
||||
(CGContextRef, 'ctx', InMode),
|
||||
(CGrafPtr, 'port', InMode),
|
||||
)
|
||||
CGContextRef_methods.append(f)
|
||||
|
||||
# manual method, lives in Quickdraw.h
|
||||
f = Method(void, 'ClipCGContextToRegion',
|
||||
(CGContextRef, 'ctx', InMode),
|
||||
(Rect, 'portRect', InMode),
|
||||
(RgnHandle, 'region', InMode),
|
||||
)
|
||||
CGContextRef_methods.append(f)
|
||||
|
||||
|
||||
CreateCGContextForPort_body = """\
|
||||
GrafPtr port;
|
||||
CGContextRef ctx;
|
||||
OSStatus _err;
|
||||
|
||||
if (!PyArg_ParseTuple(_args, "O&", GrafObj_Convert, &port))
|
||||
return NULL;
|
||||
|
||||
_err = CreateCGContextForPort(port, &ctx);
|
||||
if (_err != noErr)
|
||||
if (_err != noErr) return PyMac_Error(_err);
|
||||
_res = Py_BuildValue("O&", CGContextRefObj_New, ctx);
|
||||
return _res;
|
||||
"""
|
||||
|
||||
f = ManualGenerator("CreateCGContextForPort", CreateCGContextForPort_body);
|
||||
f.docstring = lambda: "(CGrafPtr) -> CGContextRef"
|
||||
module.add(f)
|
||||
|
||||
|
||||
# ADD add forloop here
|
||||
for f in CGContextRef_methods:
|
||||
CGContextRef_object.add(f)
|
||||
|
||||
# generate output (open the output file as late as possible)
|
||||
SetOutputFileName(OUTPUTFILE)
|
||||
module.generate()
|
||||