]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
This commit was manufactured by cvs2svn to create branch
authorcvs2svn <tools@python.org>
Wed, 11 Jul 2001 12:15:15 +0000 (12:15 +0000)
committercvs2svn <tools@python.org>
Wed, 11 Jul 2001 12:15:15 +0000 (12:15 +0000)
'release21-maint'.

16 files changed:
Lib/test/test_socketserver.py [new file with mode: 0644]
Mac/Demo/quicktime/VerySimplePlayer.py [new file with mode: 0644]
Mac/Distributions/readme.txt [new file with mode: 0644]
Mac/Include/config.h [new file with mode: 0644]
Mac/Include/macglue.h [new file with mode: 0644]
Mac/Lib/EasyDialogs.py [new file with mode: 0644]
Mac/Modules/macfsmodule.c [new file with mode: 0644]
Mac/Python/macimport.c [new file with mode: 0644]
Mac/Python/macmain.c [new file with mode: 0644]
Mac/Resources/dialogs.rsrc [new file with mode: 0644]
Mac/Tools/IDE/MacPrefs.py [new file with mode: 0644]
Mac/Tools/IDE/PyBrowser.py [new file with mode: 0644]
Mac/Tools/IDE/PyEdit.py [new file with mode: 0644]
Mac/Tools/IDE/PyFontify.py [new file with mode: 0644]
Mac/Tools/IDE/Wcontrols.py [new file with mode: 0644]
Mac/Tools/IDE/Wtraceback.py [new file with mode: 0644]

diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py
new file mode 100644 (file)
index 0000000..b2d9661
--- /dev/null
@@ -0,0 +1,162 @@
+# Test suite for SocketServer.py
+
+# XXX This must be run manually -- somehow the I/O redirection of the
+# regression test breaks the test.
+
+from test_support import verbose, verify, TESTFN
+if not verbose:
+    raise ImportError, "test_socketserver can only be run manually"
+
+from SocketServer import *
+import socket
+import select
+import time
+import threading
+import os
+
+NREQ = 3
+DELAY = 0.5
+
+class MyMixinHandler:
+    def handle(self):
+        time.sleep(DELAY)
+        line = self.rfile.readline()
+        time.sleep(DELAY)
+        self.wfile.write(line)
+
+class MyStreamHandler(MyMixinHandler, StreamRequestHandler):
+    pass
+
+class MyDatagramHandler(MyMixinHandler, DatagramRequestHandler):
+    pass
+
+class MyMixinServer:
+    def serve_a_few(self):
+        for i in range(NREQ):
+            self.handle_request()
+    def handle_error(self, request, client_address):
+        self.close_request(request)
+        self.server_close()
+        raise
+
+teststring = "hello world\n"
+
+def receive(sock, n, timeout=20):
+    r, w, x = select.select([sock], [], [], timeout)
+    if sock in r:
+        return sock.recv(n)
+    else:
+        raise RuntimeError, "timed out on %s" % `sock`
+
+def testdgram(proto, addr):
+    s = socket.socket(proto, socket.SOCK_DGRAM)
+    s.sendto(teststring, addr)
+    buf = data = receive(s, 100)
+    while data and '\n' not in buf:
+        data = receive(s, 100)
+        buf += data
+    verify(buf == teststring)
+    s.close()
+
+def teststream(proto, addr):
+    s = socket.socket(proto, socket.SOCK_STREAM)
+    s.connect(addr)
+    s.send(teststring)
+    buf = data = receive(s, 100)
+    while data and '\n' not in buf:
+        data = receive(s, 100)
+        buf += data
+    verify(buf == teststring)
+    s.close()
+
+class ServerThread(threading.Thread):
+    def __init__(self, addr, svrcls, hdlrcls):
+        threading.Thread.__init__(self)
+        self.__addr = addr
+        self.__svrcls = svrcls
+        self.__hdlrcls = hdlrcls
+    def run(self):
+        class svrcls(MyMixinServer, self.__svrcls):
+            pass
+        if verbose: print "thread: creating server"
+        svr = svrcls(self.__addr, self.__hdlrcls)
+        if verbose: print "thread: serving three times"
+        svr.serve_a_few()
+        if verbose: print "thread: done"
+
+seed = 0
+def pickport():
+    global seed
+    seed += 1
+    return 10000 + (os.getpid() % 1000)*10 + seed
+
+host = "localhost"
+testfiles = []
+def pickaddr(proto):
+    if proto == socket.AF_INET:
+        return (host, pickport())
+    else:
+        fn = TESTFN + str(pickport())
+        testfiles.append(fn)
+        return fn
+
+def cleanup():
+    for fn in testfiles:
+        try:
+            os.remove(fn)
+        except os.error:
+            pass
+    testfiles[:] = []
+
+def testloop(proto, servers, hdlrcls, testfunc):
+    for svrcls in servers:
+        addr = pickaddr(proto)
+        if verbose:
+            print "ADDR =", addr
+            print "CLASS =", svrcls
+        t = ServerThread(addr, svrcls, hdlrcls)
+        if verbose: print "server created"
+        t.start()
+        if verbose: print "server running"
+        for i in range(NREQ):
+            time.sleep(DELAY)
+            if verbose: print "test client", i
+            testfunc(proto, addr)
+        if verbose: print "waiting for server"
+        t.join()
+        if verbose: print "done"
+
+tcpservers = [TCPServer, ThreadingTCPServer]
+if hasattr(os, 'fork'):
+    tcpservers.append(ForkingTCPServer)
+udpservers = [UDPServer, ThreadingUDPServer]
+if hasattr(os, 'fork'):
+    udpservers.append(ForkingUDPServer)
+
+if not hasattr(socket, 'AF_UNIX'):
+    streamservers = []
+    dgramservers = []
+else:
+    class ForkingUnixStreamServer(ForkingMixIn, UnixStreamServer): pass
+    streamservers = [UnixStreamServer, ThreadingUnixStreamServer,
+                     ForkingUnixStreamServer]
+    class ForkingUnixDatagramServer(ForkingMixIn, UnixDatagramServer): pass
+    dgramservers = [UnixDatagramServer, ThreadingUnixDatagramServer,
+                    ForkingUnixDatagramServer]
+
+def testall():
+    testloop(socket.AF_INET, tcpservers, MyStreamHandler, teststream)
+    testloop(socket.AF_INET, udpservers, MyDatagramHandler, testdgram)
+    if hasattr(socket, 'AF_UNIX'):
+        testloop(socket.AF_UNIX, streamservers, MyStreamHandler, teststream)
+        # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
+        # client address so this cannot work:
+        ##testloop(socket.AF_UNIX, dgramservers, MyDatagramHandler, testdgram)
+
+def main():
+    try:
+        testall()
+    finally:
+        cleanup()
+
+main()
diff --git a/Mac/Demo/quicktime/VerySimplePlayer.py b/Mac/Demo/quicktime/VerySimplePlayer.py
new file mode 100644 (file)
index 0000000..3053d33
--- /dev/null
@@ -0,0 +1,92 @@
+"""VerySimplePlayer converted to python
+
+Jack Jansen, CWI, December 1995
+"""
+
+import Qt
+import QuickTime
+import Qd
+import QuickDraw
+import Evt
+import Events
+import Win
+import Windows
+import macfs
+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, ok = macfs.StandardGetFile(QuickTime.MovieFileType)
+       if not ok:
+               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().portRect)
+                               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()
+       
diff --git a/Mac/Distributions/readme.txt b/Mac/Distributions/readme.txt
new file mode 100644 (file)
index 0000000..9aa6a65
--- /dev/null
@@ -0,0 +1,43 @@
+How to make a Python-distribution.
+----------------------------------
+
+These notes are mainly for myself, or for whoever tries to make a MacPython
+distribution when I'm fed up with it. They were last updated for 2.1b2.
+
+- Increase fragment version number in PythonCore and PythonCoreCarbon.
+  the fragment number is Python's sys.hexversion, it should be set in the
+  "PEF" preferences.
+- Increase version number in _versioncheck.py
+- Build PythonStandSmall, run once in root folder
+- Update Relnotes, readme's, Demo:build.html
+- Make sure tkresources.rsrc is up-to-date
+- fullbuild everything with increase-buildno
+- Update Numeric and build/install it both with Classic and with Carbon python
+- Run configurepython
+- Recompile OSAm and possibly other Contrib stuff
+- mkdistr binary.include
+- mkdistr dev.include
+- make distribution archive with Installer Vise
+  Things to make sure of:
+  - Finder icon positions
+  - Version numbers in "Packages..." window
+  - Version number in "Installer Settings" -> "Easy Install Text"
+  - Version number in "Project" -> Attributes
+  - Version number in "Project" -> PostProcess
+  - Version number in "Internet" -> "Download Sites"
+  - Version number in "Internet" -> "File Groups".
+- test on virgin systems (OSX, OS9, OS8 without Carbon). Make sure to test
+  tkinter too.
+- Upload
+- Update README file in ftp directory
+- Change version number in public_html/macpythonversion.txt .
+- Update macpython.html
+- Send an announcement to:
+   pythonmac-sig@python.org
+   python-dev@python.org
+   python-announce@python.org
+   archivist@info-mac.org
+   adcnews@apple.com
+   http://www.macupdate.com
+   http://guide.apple.com/usindex.html
+   http://www.versiontracker.com/ Jack.Jansen@oratrix.com
\ No newline at end of file
diff --git a/Mac/Include/config.h b/Mac/Include/config.h
new file mode 100644 (file)
index 0000000..4158873
--- /dev/null
@@ -0,0 +1,740 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+/* config.h for Macintosh.
+   Valid only for CodeWarrior.
+   There's no point in giving exact version numbers of the compilers
+   since we don't update this file as each compiler comes out;
+   with CodeWarrior, we generally use the most recent version.
+*/
+
+#define USE_STACKCHECK
+
+/* Define if on Macintosh (MPW or __MWERKS__ should also be defined) */
+#ifndef macintosh
+#define macintosh
+#endif
+
+#if defined(USE_GUSI1) || defined(USE_GUSI2)
+#define USE_GUSI
+#endif
+
+#ifndef USE_GUSI
+#define DONT_HAVE_SYS_TYPES_H
+#define DONT_HAVE_SYS_STAT_H
+#define HAVE_STAT_H
+#endif
+
+/* Define if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if type char is unsigned and you are not using gcc.  */
+#ifndef __CHAR_UNSIGNED__
+#undef __CHAR_UNSIGNED__
+#endif
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef gid_t
+
+/* Define if your struct tm has tm_zone.  */
+#undef HAVE_TM_ZONE
+
+/* Define if you don't have tm_zone but do have the external array
+   tzname.  */
+#undef HAVE_TZNAME
+
+/* Define if on MINIX.  */
+#undef _MINIX
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef pid_t
+
+/* Define if the system does not provide POSIX.1 features except
+   with this defined.  */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define if your <sys/time.h> declares struct tm.  */
+#undef TM_IN_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef uid_t
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+#define WORDS_BIGENDIAN 1
+
+/* Define for AIX if your compiler is a genuine IBM xlC/xlC_r
+   and you want support for AIX C++ shared extension modules. */
+#undef AIX_GENUINE_CPLUSPLUS
+
+/* Define if your <unistd.h> contains bad prototypes for exec*()
+   (as it does on SGI IRIX 4.x) */
+#undef BAD_EXEC_PROTOTYPES
+
+/* Define if your compiler botches static forward declarations */
+#define BAD_STATIC_FORWARD
+
+/* Define this if you have BeOS threads */
+#undef BEOS_THREADS
+
+/* Define if you have the Mach cthreads package */
+#undef C_THREADS
+
+/* Defined when case of imported modules are checked against case of file. */
+#define CHECK_IMPORT_CASE
+
+/* Define to `long' if <time.h> doesn't define.  */
+#undef clock_t
+
+/* Defined on Solaris to see additional function prototypes. */
+#undef __EXTENSIONS__
+
+/* Define if getpgrp() must be called as getpgrp(0). */
+#undef GETPGRP_HAVE_ARG
+
+/* Define if gettimeofday() does not have second (timezone) argument
+   This is the case on Motorola V4 (R40V4.2) */
+#undef GETTIMEOFDAY_NO_TZ
+
+/* Define this if your time.h defines altzone */
+#undef HAVE_ALTZONE
+
+/* Defined when any dynamic module loading is enabled */
+/* #undef HAVE_DYNAMIC_LOADING */
+
+/* Define this if you have flockfile(), getc_unlocked(), and funlockfile() */
+#undef HAVE_GETC_UNLOCKED
+
+/* Define this if you have some version of gethostbyname_r() */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define this if you have the 3-arg version of gethostbyname_r() */
+#undef HAVE_GETHOSTBYNAME_R_3_ARG
+
+/* Define this if you have the 5-arg version of gethostbyname_r() */
+#undef HAVE_GETHOSTBYNAME_R_5_ARG
+
+/* Define this if you have the 6-arg version of gethostbyname_r() */
+#undef HAVE_GETHOSTBYNAME_R_6_ARG
+
+/* Defined to enable large file support when an off_t is bigger than a long
+   and long long is available and at least as big as an off_t. You may need
+   to add some flags for configuration and compilation to enable this mode.
+   E.g, for Solaris 2.7:
+   CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" OPT="-O2 $CFLAGS" \
+ configure
+*/
+#undef HAVE_LARGEFILE_SUPPORT
+
+/* Define this if you have the type long long */
+#undef HAVE_LONG_LONG
+
+/* Define if your compiler supports function prototypes */
+#define HAVE_PROTOTYPES 1
+
+/* Define if you have GNU PTH threads */
+#undef HAVE_PTH
+
+/* Define if your compiler supports variable length function prototypes
+   (e.g. void fprintf(FILE *, char *, ...);) *and* <stdarg.h> */
+#define HAVE_STDARG_PROTOTYPES
+
+/* Define this if you have the type uintptr_t */
+#undef HAVE_UINTPTR_T
+
+/* Define if you have a useable wchar_t type defined in wchar.h; useable
+   means wchar_t must be 16-bit unsigned type. (see
+   Include/unicodeobject.h). */
+#define HAVE_USABLE_WCHAR_T 1
+
+/* Define if the compiler provides a wchar.h header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define if you want to have a Unicode type. */
+#define Py_USING_UNICODE 1
+
+/* Define as the integral type used for Unicode representation. */
+#define PY_UNICODE_TYPE wchar_t
+
+/* Define as the size of the unicode type. */
+#define Py_UNICODE_SIZE 2
+
+/* Define if malloc(0) returns a NULL pointer */
+#ifdef USE_MSL_MALLOC
+#define MALLOC_ZERO_RETURNS_NULL
+#else
+#undef MALLOC_ZERO_RETURNS_NULL
+#endif
+
+/* Define if you have POSIX threads */
+#ifdef USE_GUSI2
+#define _POSIX_THREADS
+#endif
+
+/* Define if you want to build an interpreter with many run-time checks  */
+#undef Py_DEBUG
+
+/* Define to force use of thread-safe errno, h_errno, and other functions */
+#undef _REENTRANT
+
+/* Define if setpgrp() must be called as setpgrp(0, 0). */
+#undef SETPGRP_HAVE_ARG
+
+/* Define to empty if the keyword does not work.  */
+#undef signed
+
+/* Define if i>>j for signed int i does not extend the sign bit
+   when i < 0
+*/
+#define SIGNED_RIGHT_SHIFT_ZERO_FILLS
+
+/* The number of bytes in an off_t. */
+#define SIZEOF_OFF_T 4
+
+/* The number of bytes in a time_t. */
+#define SIZEOF_TIME_T 4
+
+/* The number of bytes in a pthread_t. */
+#ifdef USE_GUSI2
+#define SIZEOF_PTHREAD_T 4
+#endif
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef socklen_t
+
+/* Define if  you can safely include both <sys/select.h> and <sys/time.h>
+   (which you can't on SCO ODT 3.0). */
+#undef SYS_SELECT_WITH_SYS_TIME
+
+/* Define if a va_list is an array of some kind */
+#undef VA_LIST_IS_ARRAY
+
+/* Define to empty if the keyword does not work.  */
+#undef volatile
+
+/* Define if you want SIGFPE handled (see Include/pyfpe.h). */
+#undef WANT_SIGFPE_HANDLER
+
+/* Define if you want wctype.h functions to be used instead of the
+   one supplied by Python itself. (see Include/unicodectype.h). */
+#undef WANT_WCTYPE_FUNCTIONS
+
+/* Define if you want to compile in cycle garbage collection */
+#undef WITH_CYCLE_GC
+
+/* Define if you want to emulate SGI (IRIX 4) dynamic linking.
+   This is rumoured to work on VAX (Ultrix), Sun3 (SunOS 3.4),
+   Sequent Symmetry (Dynix), and Atari ST.
+   This requires the "dl-dld" library,
+   ftp://ftp.cwi.nl/pub/dynload/dl-dld-1.1.tar.Z,
+   as well as the "GNU dld" library,
+   ftp://ftp.cwi.nl/pub/dynload/dld-3.2.3.tar.Z.
+   Don't bother on SunOS 4 or 5, they already have dynamic linking using
+   shared libraries */ 
+#undef WITH_DL_DLD
+
+/* Define if you want to use the new-style (Openstep, Rhapsody, MacOS)
+   dynamic linker (dyld) instead of the old-style (NextStep) dynamic
+   linker (rld). Dyld is necessary to support frameworks. */
+#undef WITH_DYLD
+
+/* Define if you want to compile in Python-specific mallocs */
+#undef WITH_PYMALLOC
+
+/* Define if you want to produce an OpenStep/Rhapsody framework
+   (shared library plus accessory files). */
+#undef WITH_NEXT_FRAMEWORK
+
+/* Define if you want to use SGI (IRIX 4) dynamic linking.
+   This requires the "dl" library by Jack Jansen,
+   ftp://ftp.cwi.nl/pub/dynload/dl-1.6.tar.Z.
+   Don't bother on IRIX 5, it already has dynamic linking using SunOS
+   style shared libraries */ 
+#undef WITH_SGI_DL
+
+/* Define if you want to compile in rudimentary thread support */
+/* #undef WITH_THREAD */
+
+/* The number of bytes in a char.  */
+#define SIZEOF_CHAR 1
+
+/* The number of bytes in a double.  */
+#define SIZEOF_DOUBLE 8
+
+/* The number of bytes in a float.  */
+#define SIZEOF_FLOAT 4
+
+/* The number of bytes in a fpos_t.  */
+#define SIZEOF_FPOS_T 4
+
+/* The number of bytes in a int.  */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long.  */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a long long.  */
+#undef SIZEOF_LONG_LONG
+
+/* The number of bytes in a short.  */
+#define SIZEOF_SHORT 2
+
+/* The number of bytes in a uintptr_t.  */
+#define SIZEOF_UINTPTR_T 4
+
+/* The number of bytes in a void *.  */
+#define SIZEOF_VOID_P 4
+
+/* Define if you have the _getpty function.  */
+#undef HAVE__GETPTY
+
+/* Define if you have the alarm function.  */
+#undef HAVE_ALARM
+
+/* Define if you have the chown function.  */
+#undef HAVE_CHOWN
+
+/* Define if you have clock.  */
+#define HAVE_CLOCK
+
+/* Define if you have the confstr function.  */
+#undef HAVE_CONFSTR
+
+/* Define if you have the ctermid function.  */
+#undef HAVE_CTERMID
+
+/* Define if you have the ctermid_r function.  */
+#undef HAVE_CTERMID_R
+
+/* Define if you have the dlopen function.  */
+#undef HAVE_DLOPEN
+
+/* Define if you have the dup2 function.  */
+#undef HAVE_DUP2
+
+/* Define if you have the execv function.  */
+#undef HAVE_EXECV
+
+/* Define if you have the fdatasync function.  */
+#undef HAVE_FDATASYNC
+
+/* Define if you have the flock function.  */
+#undef HAVE_FLOCK
+
+/* Define if you have the fork function.  */
+#undef HAVE_FORK
+
+/* Define if you have the forkpty function.  */
+#undef HAVE_FORKPTY
+
+/* Define if you have the fpathconf function.  */
+#undef HAVE_FPATHCONF
+
+/* Define if you have the fseek64 function.  */
+#undef HAVE_FSEEK64
+
+/* Define if you have the fseeko function.  */
+#undef HAVE_FSEEKO
+
+/* Define if you have the fstatvfs function.  */
+#undef HAVE_FSTATVFS
+
+/* Define if you have the fsync function.  */
+#define HAVE_FSYNC
+
+/* Define if you have the ftell64 function.  */
+#undef HAVE_FTELL64
+
+/* Define if you have the ftello function.  */
+#undef HAVE_FTELLO
+
+/* Define if you have the ftime function.  */
+#undef HAVE_FTIME
+
+/* Define if you have the ftruncate function.  */
+#ifdef USE_GUSI
+#define HAVE_FTRUNCATE
+#endif
+
+/* Define if you have the getcwd function.  */
+#define HAVE_GETCWD
+
+/* Define if you have the getgroups function.  */
+#undef HAVE_GETGROUPS
+
+/* Define if you have the gethostbyname function.  */
+#ifdef USE_GUSI
+#define HAVE_GETHOSTBYNAME 1
+#endif
+
+/* Define if you have the getlogin function.  */
+#undef HAVE_GETLOGIN
+
+/* Define if you have the getpeername function.  */
+#ifdef USE_GUSI
+#define HAVE_GETPEERNAME
+#endif
+
+/* Define if you have the getpgrp function.  */
+#undef HAVE_GETPGRP
+
+/* Define if you have the getpid function.  */
+#undef HAVE_GETPID
+
+/* Define if you have the getpwent function.  */
+#undef HAVE_GETPWENT
+
+/* Define if you have the gettimeofday function.  */
+#ifdef USE_GUSI
+#define HAVE_GETTIMEOFDAY
+#endif
+
+/* Define if you have the getwd function.  */
+#undef HAVE_GETWD
+
+/* Define if you have the hypot function.  */
+#ifndef __MC68K__
+/* 68K hypot definition (and implementation) are unuseable
+** because they use 10-byte floats.
+*/
+#define HAVE_HYPOT
+#endif
+
+/* Define if you have the kill function.  */
+#undef HAVE_KILL
+
+/* Define if you have the link function.  */
+#undef HAVE_LINK
+
+/* Define if you have the lstat function.  */
+#undef HAVE_LSTAT
+
+/* Define if you have the memmove function.  */
+#define HAVE_MEMMOVE
+
+/* Define if you have the mkfifo function.  */
+#undef HAVE_MKFIFO
+
+/* Define if you have the mktime function.  */
+#define HAVE_MKTIME
+
+/* Define if you have the mremap function.  */
+#undef HAVE_MREMAP
+
+/* Define if you have the nice function.  */
+#undef HAVE_NICE
+
+/* Define if you have the openpty function.  */
+#undef HAVE_OPENPTY
+
+/* Define if you have the pathconf function.  */
+#undef HAVE_PATHCONF
+
+/* Define if you have the pause function.  */
+#undef HAVE_PAUSE
+
+/* Define if you have the plock function.  */
+#undef HAVE_PLOCK
+
+/* Define if you have the poll function.  */
+#undef HAVE_POLL
+
+/* Define if you have the pthread_init function.  */
+#undef HAVE_PTHREAD_INIT
+
+/* Define if you have the putenv function.  */
+#undef HAVE_PUTENV
+
+/* Define if you have the readlink function.  */
+#undef HAVE_READLINK
+
+/* Define if you have the select function.  */
+#ifdef USE_GUSI
+#define HAVE_SELECT
+#endif
+
+/* Define if you have the setegid function.  */
+#undef HAVE_SETEGID
+
+/* Define if you have the seteuid function.  */
+#undef HAVE_SETEUID
+
+/* Define if you have the setgid function.  */
+#undef HAVE_SETGID
+
+/* Define if you have the setlocale function.  */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the setpgid function.  */
+#undef HAVE_SETPGID
+
+/* Define if you have the setpgrp function.  */
+#undef HAVE_SETPGRP
+
+/* Define if you have the setregid function.  */
+#undef HAVE_SETREGID
+
+/* Define if you have the setreuid function.  */
+#undef HAVE_SETREUID
+
+/* Define if you have the setsid function.  */
+#undef HAVE_SETSID
+
+/* Define if you have the setuid function.  */
+#undef HAVE_SETUID
+
+/* Define if you have the setvbuf function.  */
+#define HAVE_SETVBUF
+
+/* Define if you have the sigaction function.  */
+#undef HAVE_SIGACTION
+
+/* Define if you have the siginterrupt function.  */
+#undef HAVE_SIGINTERRUPT
+
+/* Define if you have the sigrelse function.  */
+#undef HAVE_SIGRELSE
+
+/* Define if you have the statvfs function.  */
+#undef HAVE_STATVFS
+
+/* Define if you have the strdup function.  */
+#undef HAVE_STRDUP
+
+/* Define if you have the strerror function.  */
+#define HAVE_STRERROR
+
+/* Define if you have the strftime function.  */
+#define HAVE_STRFTIME
+
+/* Define if you have the strptime function.  */
+#undef HAVE_STRPTIME
+
+/* Define if you have the symlink function.  */
+#undef HAVE_SYMLINK
+
+/* Define if you have the sysconf function.  */
+#undef HAVE_SYSCONF
+
+/* Define if you have the tcgetpgrp function.  */
+#undef HAVE_TCGETPGRP
+
+/* Define if you have the tcsetpgrp function.  */
+#undef HAVE_TCSETPGRP
+
+/* Define if you have the tempnam function.  */
+#undef HAVE_TEMPNAM
+
+/* Define if you have the timegm function.  */
+#undef HAVE_TIMEGM
+
+/* Define if you have the times function.  */
+#undef HAVE_TIMES
+
+/* Define if you have the tmpfile function.  */
+#define HAVE_TMPFILE
+
+/* Define if you have the tmpnam function.  */
+#define HAVE_TMPNAM
+
+/* Define if you have the tmpnam_r function.  */
+#undef HAVE_TMPNAM_R
+
+/* Define if you have the truncate function.  */
+#define HAVE_TRUNCATE
+
+/* Define if you have the uname function.  */
+#undef HAVE_UNAME
+
+/* Define if you have the waitpid function.  */
+#undef HAVE_WAITPID
+
+/* Define if you have the <db.h> header file.  */
+#undef HAVE_DB_H
+
+/* Define if you have the <db1/ndbm.h> header file.  */
+#undef HAVE_DB1_NDBM_H
+
+/* Define if you have the <db_185.h> header file.  */
+#undef HAVE_DB_185_H
+
+/* Define if you have the <dirent.h> header file.  */
+#ifdef USE_GUSI
+#define HAVE_DIRENT_H
+#endif
+
+/* Define if you have the <dlfcn.h> header file.  */
+#undef HAVE_DLFCN_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#define HAVE_FCNTL_H
+
+/* Define if you have the <gdbm/ndbm.h> header file.  */
+#undef HAVE_GDBM_NDBM_H
+
+/* Define if you have the <libutil.h> header file.  */
+#undef HAVE_LIBUTIL_H
+
+/* Define if you have the <limits.h> header file.  */
+#define HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file.  */
+#define HAVE_LOCALE_H
+
+/* Define if you have the <ncurses.h> header file.  */
+#undef HAVE_NCURSES_H
+
+/* Define if you have the <ndbm.h> header file.  */
+#undef HAVE_NDBM_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <poll.h> header file.  */
+#undef HAVE_POLL_H
+
+/* Define if you have the <pthread.h> header file.  */
+#ifdef USE_GUSI2
+#define HAVE_PTHREAD_H
+#endif
+
+/* Define if you have the <pty.h> header file.  */
+#undef HAVE_PTY_H
+
+/* Define if you have the <signal.h> header file.  */
+#define HAVE_SIGNAL_H
+
+/* Define if you have the <stdarg.h> header file.  */
+#define HAVE_STDARG_H
+
+/* Define if you have the <stddef.h> header file.  */
+#define HAVE_STDDEF_H
+
+/* Define if you have the <stdlib.h> header file.  */
+#define HAVE_STDLIB_H
+
+/* Define if you have the <sys/audioio.h> header file.  */
+#undef HAVE_SYS_AUDIOIO_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/file.h> header file.  */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <sys/lock.h> header file.  */
+#undef HAVE_SYS_LOCK_H
+
+/* Define if you have the <sys/modem.h> header file.  */
+#undef HAVE_SYS_MODEM_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/param.h> header file.  */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/select.h> header file.  */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/socket.h> header file.  */
+#ifdef USE_GUSI
+#define HAVE_SYS_SOCKET_H
+#endif
+
+/* Define if you have the <sys/time.h> header file.  */
+#ifdef USE_GUSI
+#define HAVE_SYS_TIME_H
+#endif
+
+/* Define if you have the <sys/times.h> header file.  */
+#undef HAVE_SYS_TIMES_H
+
+/* Define if you have the <sys/un.h> header file.  */
+#undef HAVE_SYS_UN_H
+
+/* Define if you have the <sys/utsname.h> header file.  */
+#undef HAVE_SYS_UTSNAME_H
+
+/* Define if you have the <sys/wait.h> header file.  */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if you have the <termios.h> header file.  */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <thread.h> header file.  */
+#undef HAVE_THREAD_H
+
+/* Define if you have the <unistd.h> header file.  */
+#define HAVE_UNISTD_H
+
+/* Define if you have the <utime.h> header file.  */
+#define HAVE_UTIME_H
+
+/* Define if you have the dl library (-ldl).  */
+#undef HAVE_LIBDL
+
+/* Define if you have the dld library (-ldld).  */
+#undef HAVE_LIBDLD
+
+/* Define if you have the ieee library (-lieee).  */
+#undef HAVE_LIBIEEE
+
+#ifdef __CYGWIN__
+#ifdef USE_DL_IMPORT
+#define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE
+#define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
+#else
+#define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE
+#define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
+#endif
+#endif
diff --git a/Mac/Include/macglue.h b/Mac/Include/macglue.h
new file mode 100644 (file)
index 0000000..e0c0ff5
--- /dev/null
@@ -0,0 +1,160 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+#ifdef WITHOUT_FRAMEWORKS
+#include <Types.h>
+#include <Files.h>
+#include <Events.h>
+#include <StandardFile.h>
+#else
+#include <Carbon/Carbon.h>
+#endif
+
+#ifdef __cplusplus
+       extern "C" {
+#endif
+
+/* Scheduler parameters */
+typedef struct {
+       int             check_interrupt;        /* if true check for command-dot */
+       int             process_events;         /* if nonzero enable evt processing, this mask */
+       int             besocial;               /* Be social, give up CPU now and again */
+       double          check_interval;         /* how often to check */
+       double          bg_yield;               /* yield at most so long when in background */
+} PyMacSchedParams;
+
+char *PyMac_getscript(void);   /* Get the default encoding for our 8bit character set */
+#ifdef USE_GUSI1
+void PyMac_FixGUSIcd(void);            /* Workaround for GUSI chdir() call */
+extern void PyMac_SetGUSISpin(void);           /* Install our private GUSI spin routine */
+#endif
+
+char *PyMac_StrError(int);                     /* strerror with mac errors */
+PyObject *PyErr_Mac(PyObject *, int);          /* Exception with a mac error */
+PyObject *PyMac_Error(OSErr);                  /* Uses PyMac_GetOSErrException */
+unsigned char *Pstring(char *str);             /* Convert c-string to pascal-string in static buffer */
+
+#ifdef USE_GUSI
+extern int PyMac_ConsoleIsDead;                        /* True when exiting */
+extern void PyMac_StopGUSISpin(void);          /* Stop eventprocessing during exit() */
+#endif
+
+extern short PyMac_AppRefNum;                  /* RefNum of application rsrcfork (from macmain.c) */
+extern FSSpec PyMac_ApplicationFSSpec;         /* Application location (from macargv.c) */
+extern char PyMac_ApplicationPath[];           /* Application location (from macargv.c) */
+extern OSErr PyMac_init_application_location(void);    /* Init the above */
+extern OSErr PyMac_GetFullPath(FSSpec *, char *); /* convert fsspec->path (macargv.c) */
+extern int PyMac_GetArgv(char ***, int);       /* Get argc, argv (from macargv.c) */
+extern int PyMac_AppearanceCompliant;  /* True if in appearance support mode */
+
+extern PyObject *PyMac_OSErrException;         /* Exception for OSErr */
+PyObject *PyMac_GetOSErrException(void);       /* Initialize & return it */
+
+#if !TARGET_API_MAC_OSX
+void PyMac_GetSchedParams(PyMacSchedParams *); /* Get schedulers params */
+void PyMac_SetSchedParams(PyMacSchedParams *); /* Set schedulers params */
+int PyMac_DoYield(int, int);   /* Yield cpu. First arg is maxtime, second ok to call python */
+#endif
+int PyMac_HandleEvent(EventRecord *);  /* Handle one event, possibly in Python */
+void PyMac_HandleEventIntern(EventRecord *); /* Handle one event internal only */
+int PyMac_SetEventHandler(PyObject *); /* set python-coded event handler */
+
+#if !TARGET_API_MAC_OSX
+void PyMac_InitMenuBar(void);                  /* Setup menu bar as we want it */
+void PyMac_RestoreMenuBar(void);               /* Restore menu bar for ease of exiting */
+void PyMac_RaiseConsoleWindow();               /* Bring console window to front, if it exists */
+#endif
+int PyMac_FindResourceModule(PyStringObject *, char *, char *); /* Test for 'PYC ' resource in a file */
+PyObject * PyMac_LoadResourceModule(char *, char *); /* Load 'PYC ' resource from file */
+int PyMac_FindCodeResourceModule(PyStringObject *, char *, char *); /* Test for 'PYD ' resource in a file */
+PyObject * PyMac_LoadCodeResourceModule(char *, char *); /* Load 'PYD ' resource from file */
+struct filedescr *PyMac_FindModuleExtension(char *, size_t *, char *); /* Look for module in single folder */
+
+#if TARGET_API_MAC_OS8
+int PyMac_GetDirectory(FSSpec *dirfss, char *prompt);          /* Ask user for a directory */
+void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList, 
+       StandardFileReply *reply, char *prompt);        /* Ask user for file, with prompt */
+#endif /* TARGET_API_MAC_OS8 */
+
+int PyMac_GetOSType(PyObject *, OSType *);     /* argument parser for OSType */
+PyObject *PyMac_BuildOSType(OSType);           /* Convert OSType to PyObject */
+
+PyObject *PyMac_BuildNumVersion(NumVersion);   /* Convert NumVersion to PyObject */
+
+int PyMac_GetStr255(PyObject *, Str255);       /* argument parser for Str255 */
+PyObject *PyMac_BuildStr255(Str255);           /* Convert Str255 to PyObject */
+PyObject *PyMac_BuildOptStr255(Str255);                /* Convert Str255 to PyObject, NULL to None */
+
+int PyMac_GetRect(PyObject *, Rect *);         /* argument parser for Rect */
+PyObject *PyMac_BuildRect(Rect *);             /* Convert Rect to PyObject */
+
+int PyMac_GetPoint(PyObject *, Point *);       /* argument parser for Point */
+PyObject *PyMac_BuildPoint(Point);             /* Convert Point to PyObject */
+
+int PyMac_GetEventRecord(PyObject *, EventRecord *); /* argument parser for EventRecord */
+PyObject *PyMac_BuildEventRecord(EventRecord *); /* Convert EventRecord to PyObject */
+
+int PyMac_GetFixed(PyObject *, Fixed *);       /* argument parser for Fixed */
+PyObject *PyMac_BuildFixed(Fixed);                     /* Convert Fixed to PyObject */
+int PyMac_Getwide(PyObject *, wide *); /* argument parser for wide */
+PyObject *PyMac_Buildwide(wide *);                     /* Convert wide to PyObject */
+void PyMac_InitApplet(void);                   /* Initialize and run an Applet */
+void PyMac_Initialize(void);                   /* Initialize function for embedding Python */
+
+#ifdef USE_GUSI2
+short PyMac_OpenPrefFile(void);                        /* From macgetpath.c, open and return preference file */
+#endif
+
+/* from macfsmodule.c: */
+int PyMac_GetFSSpec(PyObject *, FSSpec *);     /* argument parser for FSSpec */
+PyObject *PyMac_BuildFSSpec(FSSpec *);         /* Convert FSSpec to PyObject */
+
+int PyMac_GetFSRef(PyObject *, FSRef *);       /* argument parser for FSRef */
+PyObject *PyMac_BuildFSRef(FSRef *);           /* Convert FSRef to PyObject */
+
+
+/* From macfiletype.c: */
+
+long PyMac_getfiletype(char *);                        /* Get file type */
+int PyMac_setfiletype(char *, long, long);             /* Set file creator and type */
+
+/* from macmain.c: */
+void PyMac_Exit(int);
+void PyMac_InitApplication(void);
+void PyMac_OutputSeen(void);
+void PyMac_OutputNotSeen(void);
+int PyMac_GetDelayConsoleFlag(void);
+#ifdef USE_MAC_APPLET_SUPPORT
+void PyMac_InitApplet(void);
+#endif
+
+/* from macgetargv: */
+OSErr PyMac_init_process_location(void);
+#ifndef HAVE_STRDUP
+char * strdup(const char *str);
+#endif
+
+#ifdef __cplusplus
+       }
+#endif
diff --git a/Mac/Lib/EasyDialogs.py b/Mac/Lib/EasyDialogs.py
new file mode 100644 (file)
index 0000000..a9d3e16
--- /dev/null
@@ -0,0 +1,564 @@
+"""Easy to use dialogs.
+
+Message(msg) -- display a message and an OK button.
+AskString(prompt, default) -- ask for a string, display OK and Cancel buttons.
+AskPassword(prompt, default) -- like AskString(), but shows text as bullets.
+AskYesNoCancel(question, default) -- display a question and Yes, No and Cancel buttons.
+bar = Progress(label, maxvalue) -- Display a progress bar
+bar.set(value) -- Set value
+bar.inc( *amount ) -- increment value by amount (default=1)
+bar.label( *newlabel ) -- get or set text label. 
+
+More documentation in each function.
+This module uses DLOG resources 260 and on.
+Based upon STDWIN dialogs with the same names and functions.
+"""
+
+from Dlg import GetNewDialog, SetDialogItemText, GetDialogItemText, ModalDialog
+import Qd
+import QuickDraw
+import Dialogs
+import Windows
+import Dlg,Win,Evt,Events # sdm7g
+import Ctl
+import Controls
+import Menu
+import MacOS
+import string
+from ControlAccessor import *  # Also import Controls constants
+import macfs
+
+def cr2lf(text):
+       if '\r' in text:
+               text = string.join(string.split(text, '\r'), '\n')
+       return text
+
+def lf2cr(text):
+       if '\n' in text:
+               text = string.join(string.split(text, '\n'), '\r')
+       if len(text) > 253:
+               text = text[:253] + '\311'
+       return text
+
+def Message(msg, id=260, ok=None):
+       """Display a MESSAGE string.
+       
+       Return when the user clicks the OK button or presses Return.
+       
+       The MESSAGE string can be at most 255 characters long.
+       """
+       
+       d = GetNewDialog(id, -1)
+       if not d:
+               print "Can't get DLOG resource with id =", id
+               return
+       h = d.GetDialogItemAsControl(2)
+       SetDialogItemText(h, lf2cr(msg))
+       if ok != None:
+               h = d.GetDialogItemAsControl(1)
+               h.SetControlTitle(ok)
+       d.SetDialogDefaultItem(1)
+       d.AutoSizeDialog()
+       d.GetDialogWindow().ShowWindow()
+       while 1:
+               n = ModalDialog(None)
+               if n == 1:
+                       return
+
+
+def AskString(prompt, default = "", id=261, ok=None, cancel=None):
+       """Display a PROMPT string and a text entry field with a DEFAULT string.
+       
+       Return the contents of the text entry field when the user clicks the
+       OK button or presses Return.
+       Return None when the user clicks the Cancel button.
+       
+       If omitted, DEFAULT is empty.
+       
+       The PROMPT and DEFAULT strings, as well as the return value,
+       can be at most 255 characters long.
+       """
+       
+       d = GetNewDialog(id, -1)
+       if not d:
+               print "Can't get DLOG resource with id =", id
+               return
+       h = d.GetDialogItemAsControl(3)
+       SetDialogItemText(h, lf2cr(prompt))
+       h = d.GetDialogItemAsControl(4)
+       SetDialogItemText(h, lf2cr(default))
+       d.SelectDialogItemText(4, 0, 999)
+#      d.SetDialogItem(4, 0, 255)
+       if ok != None:
+               h = d.GetDialogItemAsControl(1)
+               h.SetControlTitle(ok)
+       if cancel != None:
+               h = d.GetDialogItemAsControl(2)
+               h.SetControlTitle(cancel)
+       d.SetDialogDefaultItem(1)
+       d.SetDialogCancelItem(2)
+       d.AutoSizeDialog()
+       d.GetDialogWindow().ShowWindow()
+       while 1:
+               n = ModalDialog(None)
+               if n == 1:
+                       h = d.GetDialogItemAsControl(4)
+                       return cr2lf(GetDialogItemText(h))
+               if n == 2: return None
+
+def AskPassword(prompt,         default='', id=264, ok=None, cancel=None):     
+       """Display a PROMPT string and a text entry field with a DEFAULT string.
+       The string is displayed as bullets only.
+       
+       Return the contents of the text entry field when the user clicks the
+       OK button or presses Return.
+       Return None when the user clicks the Cancel button.
+       
+       If omitted, DEFAULT is empty.
+       
+       The PROMPT and DEFAULT strings, as well as the return value,
+       can be at most 255 characters long.
+       """
+       d = GetNewDialog(id, -1)
+       if not d:
+               print "Can't get DLOG resource with id =", id
+               return
+       h = d.GetDialogItemAsControl(3)
+       SetDialogItemText(h, lf2cr(prompt))     
+       pwd = d.GetDialogItemAsControl(4)
+       bullets = '\245'*len(default)
+##     SetControlData(pwd, kControlEditTextPart, kControlEditTextTextTag, bullets)
+       SetControlData(pwd, kControlEditTextPart, kControlEditTextPasswordTag, default)
+       d.SelectDialogItemText(4, 0, 999)
+       Ctl.SetKeyboardFocus(d.GetDialogWindow(), pwd, kControlEditTextPart)
+       if ok != None:
+               h = d.GetDialogItemAsControl(1)
+               h.SetControlTitle(ok)
+       if cancel != None:
+               h = d.GetDialogItemAsControl(2)
+               h.SetControlTitle(cancel)
+       d.SetDialogDefaultItem(Dialogs.ok)
+       d.SetDialogCancelItem(Dialogs.cancel)
+       d.AutoSizeDialog()
+       d.GetDialogWindow().ShowWindow()
+       while 1:
+               n = ModalDialog(None)
+               if n == 1:
+                       h = d.GetDialogItemAsControl(4)
+                       return cr2lf(GetControlData(pwd, kControlEditTextPart, kControlEditTextPasswordTag))
+               if n == 2: return None
+
+def AskYesNoCancel(question, default = 0, yes=None, no=None, cancel=None, id=262):
+       """Display a QUESTION string which can be answered with Yes or No.
+       
+       Return 1 when the user clicks the Yes button.
+       Return 0 when the user clicks the No button.
+       Return -1 when the user clicks the Cancel button.
+       
+       When the user presses Return, the DEFAULT value is returned.
+       If omitted, this is 0 (No).
+       
+       The QUESTION string can be at most 255 characters.
+       """
+       
+       d = GetNewDialog(id, -1)
+       if not d:
+               print "Can't get DLOG resource with id =", id
+               return
+       # Button assignments:
+       # 1 = default (invisible)
+       # 2 = Yes
+       # 3 = No
+       # 4 = Cancel
+       # The question string is item 5
+       h = d.GetDialogItemAsControl(5)
+       SetDialogItemText(h, lf2cr(question))
+       if yes != None:
+               if yes == '':
+                       d.HideDialogItem(2)
+               else:
+                       h = d.GetDialogItemAsControl(2)
+                       h.SetControlTitle(yes)
+       if no != None:
+               if no == '':
+                       d.HideDialogItem(3)
+               else:
+                       h = d.GetDialogItemAsControl(3)
+                       h.SetControlTitle(no)
+       if cancel != None:
+               if cancel == '':
+                       d.HideDialogItem(4)
+               else:
+                       h = d.GetDialogItemAsControl(4)
+                       h.SetControlTitle(cancel)
+       d.SetDialogCancelItem(4)
+       if default == 1:
+               d.SetDialogDefaultItem(2)
+       elif default == 0:
+               d.SetDialogDefaultItem(3)
+       elif default == -1:
+               d.SetDialogDefaultItem(4)
+       d.AutoSizeDialog()
+       d.GetDialogWindow().ShowWindow()
+       while 1:
+               n = ModalDialog(None)
+               if n == 1: return default
+               if n == 2: return 1
+               if n == 3: return 0
+               if n == 4: return -1
+
+
+               
+
+screenbounds = Qd.qd.screenBits.bounds
+screenbounds = screenbounds[0]+4, screenbounds[1]+4, \
+       screenbounds[2]-4, screenbounds[3]-4
+
+                               
+class ProgressBar:
+       def __init__(self, title="Working...", maxval=100, label="", id=263):
+               self.w = None
+               self.d = None
+               self.maxval = maxval
+               self.curval = -1
+               self.d = GetNewDialog(id, -1)
+               self.w = self.d.GetDialogWindow()
+               self.label(label)
+               self._update(0)
+               self.d.AutoSizeDialog()
+               self.title(title)
+               self.w.ShowWindow()
+               self.d.DrawDialog()
+
+       def __del__( self ):
+               if self.w:
+                       self.w.BringToFront()
+                       self.w.HideWindow()
+               del self.w
+               del self.d
+               
+       def title(self, newstr=""):
+               """title(text) - Set title of progress window"""
+               self.w.BringToFront()
+               self.w.SetWTitle(newstr)
+               
+       def label( self, *newstr ):
+               """label(text) - Set text in progress box"""
+               self.w.BringToFront()
+               if newstr:
+                       self._label = lf2cr(newstr[0])
+               text_h = self.d.GetDialogItemAsControl(2)
+               SetDialogItemText(text_h, self._label)          
+                               
+       def _update(self, value):
+               maxval = self.maxval
+               if maxval == 0:
+                       # XXXX Quick fix. Should probably display an unknown duration
+                       value = 0
+                       maxval = 1
+               if maxval > 32767:
+                       value = int(value/(maxval/32767.0))
+                       maxval = 32767
+               progbar = self.d.GetDialogItemAsControl(3)
+               progbar.SetControlMaximum(maxval)
+               progbar.SetControlValue(value)  
+               # Test for cancel button
+               
+               ready, ev = Evt.WaitNextEvent( Events.mDownMask, 1  )
+               if ready : 
+                       what,msg,when,where,mod = ev
+                       part = Win.FindWindow(where)[0]
+                       if Dlg.IsDialogEvent(ev):
+                               ds = Dlg.DialogSelect(ev)
+                               if ds[0] and ds[1] == self.d and ds[-1] == 1:
+                                       self.w.HideWindow()
+                                       self.w = None
+                                       self.d = None
+                                       raise KeyboardInterrupt, ev
+                       else:
+                               if part == 4:   # inDrag 
+                                       self.d.DragWindow(where, screenbounds)
+                               else:
+                                       MacOS.HandleEvent(ev) 
+                       
+                       
+       def set(self, value, max=None):
+               """set(value) - Set progress bar position"""
+               if max != None:
+                       self.maxval = max
+               if value < 0: value = 0
+               if value > self.maxval: value = self.maxval
+               self.curval = value
+               self._update(value)
+
+       def inc(self, n=1):
+               """inc(amt) - Increment progress bar position"""
+               self.set(self.curval + n)
+
+ARGV_ID=265
+ARGV_ITEM_OK=1
+ARGV_ITEM_CANCEL=2
+ARGV_OPTION_GROUP=3
+ARGV_OPTION_EXPLAIN=4
+ARGV_OPTION_VALUE=5
+ARGV_OPTION_ADD=6
+ARGV_COMMAND_GROUP=7
+ARGV_COMMAND_EXPLAIN=8
+ARGV_COMMAND_ADD=9
+ARGV_ADD_OLDFILE=10
+ARGV_ADD_NEWFILE=11
+ARGV_ADD_FOLDER=12
+ARGV_CMDLINE_GROUP=13
+ARGV_CMDLINE_DATA=14
+
+##def _myModalDialog(d):
+##     while 1:
+##             ready, ev = Evt.WaitNextEvent(0xffff, -1)
+##             print 'DBG: WNE', ready, ev
+##             if ready : 
+##                     what,msg,when,where,mod = ev
+##                     part, window = Win.FindWindow(where)
+##                     if Dlg.IsDialogEvent(ev):
+##                             didit, dlgdone, itemdone = Dlg.DialogSelect(ev)
+##                             print 'DBG: DialogSelect', didit, dlgdone, itemdone, d
+##                             if didit and dlgdone == d:
+##                                     return itemdone
+##                     elif window == d.GetDialogWindow():
+##                             d.GetDialogWindow().SelectWindow()
+##                             if part == 4:   # inDrag 
+##                                             d.DragWindow(where, screenbounds)
+##                             else:
+##                                     MacOS.HandleEvent(ev) 
+##                     else:
+##                             MacOS.HandleEvent(ev) 
+##
+def _setmenu(control, items):
+               mhandle = control.GetControlData_Handle(Controls.kControlMenuPart,
+                               Controls.kControlPopupButtonMenuHandleTag)
+               menu = Menu.as_Menu(mhandle)
+               for item in items:
+                       if type(item) == type(()):
+                               label = item[0]
+                       else:
+                               label = item
+                       if label[-1] == '=' or label[-1] == ':':
+                               label = label[:-1]
+                       menu.AppendMenu(label)
+##             mhandle, mid = menu.getpopupinfo()
+##             control.SetControlData_Handle(Controls.kControlMenuPart,
+##                             Controls.kControlPopupButtonMenuHandleTag, mhandle)
+               control.SetControlMinimum(1)
+               control.SetControlMaximum(len(items)+1)
+               
+def _selectoption(d, optionlist, idx):
+       if idx < 0 or idx >= len(optionlist):
+               MacOS.SysBeep()
+               return
+       option = optionlist[idx]
+       if type(option) == type(()) and \
+                       len(option) > 1:
+               help = option[-1]
+       else:
+               help = ''
+       h = d.GetDialogItemAsControl(ARGV_OPTION_EXPLAIN)
+       Dlg.SetDialogItemText(h, help)
+       hasvalue = 0
+       if type(option) == type(()):
+               label = option[0]
+       else:
+               label = option
+       if label[-1] == '=' or label[-1] == ':':
+               hasvalue = 1
+       h = d.GetDialogItemAsControl(ARGV_OPTION_VALUE)
+       Dlg.SetDialogItemText(h, '')
+       if hasvalue:
+               d.ShowDialogItem(ARGV_OPTION_VALUE)
+               d.SelectDialogItemText(ARGV_OPTION_VALUE, 0, 0)
+       else:
+               d.HideDialogItem(ARGV_OPTION_VALUE)
+
+
+def GetArgv(optionlist=None, commandlist=None, addoldfile=1, addnewfile=1, addfolder=1, id=ARGV_ID):
+       d = GetNewDialog(id, -1)
+       if not d:
+               print "Can't get DLOG resource with id =", id
+               return
+#      h = d.GetDialogItemAsControl(3)
+#      SetDialogItemText(h, lf2cr(prompt))
+#      h = d.GetDialogItemAsControl(4)
+#      SetDialogItemText(h, lf2cr(default))
+#      d.SelectDialogItemText(4, 0, 999)
+#      d.SetDialogItem(4, 0, 255)
+       if optionlist:
+               _setmenu(d.GetDialogItemAsControl(ARGV_OPTION_GROUP), optionlist)
+               _selectoption(d, optionlist, 0)
+       else:
+               d.GetDialogItemAsControl(ARGV_OPTION_GROUP).DeactivateControl()
+       if commandlist:
+               _setmenu(d.GetDialogItemAsControl(ARGV_COMMAND_GROUP), commandlist)
+               if type(commandlist[0]) == type(()) and len(commandlist[0]) > 1:
+                       help = commandlist[0][-1]
+                       h = d.GetDialogItemAsControl(ARGV_COMMAND_EXPLAIN)
+                       Dlg.SetDialogItemText(h, help)
+       else:
+               d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).DeactivateControl()
+       if not addoldfile:
+               d.GetDialogItemAsControl(ARGV_ADD_OLDFILE).DeactivateControl()
+       if not addnewfile:
+               d.GetDialogItemAsControl(ARGV_ADD_NEWFILE).DeactivateControl()
+       if not addfolder:
+               d.GetDialogItemAsControl(ARGV_ADD_FOLDER).DeactivateControl()
+       d.SetDialogDefaultItem(ARGV_ITEM_OK)
+       d.SetDialogCancelItem(ARGV_ITEM_CANCEL)
+       d.GetDialogWindow().ShowWindow()
+       d.DrawDialog()
+       appsw = MacOS.SchedParams(1, 0)
+       try:
+               while 1:
+                       stringstoadd = []
+                       n = ModalDialog(None)
+                       if n == ARGV_ITEM_OK:
+                               break
+                       elif n == ARGV_ITEM_CANCEL:
+                               raise SystemExit
+                       elif n == ARGV_OPTION_GROUP:
+                               idx = d.GetDialogItemAsControl(ARGV_OPTION_GROUP).GetControlValue()-1
+                               _selectoption(d, optionlist, idx)
+                       elif n == ARGV_OPTION_VALUE:
+                               pass
+                       elif n == ARGV_OPTION_ADD:
+                               idx = d.GetDialogItemAsControl(ARGV_OPTION_GROUP).GetControlValue()-1
+                               if 0 <= idx < len(optionlist):
+                                       option = optionlist[idx]
+                                       if type(option) == type(()):
+                                               option = option[0]
+                                       if option[-1] == '=' or option[-1] == ':':
+                                               option = option[:-1]
+                                               h = d.GetDialogItemAsControl(ARGV_OPTION_VALUE)
+                                               value = Dlg.GetDialogItemText(h)
+                                       else:
+                                               value = ''
+                                       if len(option) == 1:
+                                               stringtoadd = '-' + option
+                                       else:
+                                               stringtoadd = '--' + option
+                                       stringstoadd = [stringtoadd]
+                                       if value:
+                                               stringstoadd.append(value)
+                               else:
+                                       MacOS.SysBeep()
+                       elif n == ARGV_COMMAND_GROUP:
+                               idx = d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).GetControlValue()-1
+                               if 0 <= idx < len(commandlist) and type(commandlist[idx]) == type(()) and \
+                                               len(commandlist[idx]) > 1:
+                                       help = commandlist[idx][-1]
+                                       h = d.GetDialogItemAsControl(ARGV_COMMAND_EXPLAIN)
+                                       Dlg.SetDialogItemText(h, help)
+                       elif n == ARGV_COMMAND_ADD:
+                               idx = d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).GetControlValue()-1
+                               if 0 <= idx < len(commandlist):
+                                       command = commandlist[idx]
+                                       if type(command) == type(()):
+                                               command = command[0]
+                                       stringstoadd = [command]
+                               else:
+                                       MacOS.SysBeep()
+                       elif n == ARGV_ADD_OLDFILE:
+                               fss, ok = macfs.StandardGetFile()
+                               if ok:
+                                       stringstoadd = [fss.as_pathname()]
+                       elif n == ARGV_ADD_NEWFILE:
+                               fss, ok = macfs.StandardPutFile('')
+                               if ok:
+                                       stringstoadd = [fss.as_pathname()]
+                       elif n == ARGV_ADD_FOLDER:
+                               fss, ok = macfs.GetDirectory()
+                               if ok:
+                                       stringstoadd = [fss.as_pathname()]
+                       elif n == ARGV_CMDLINE_DATA:
+                               pass # Nothing to do
+                       else:
+                               raise RuntimeError, "Unknown dialog item %d"%n
+                       
+                       for stringtoadd in stringstoadd:
+                               if '"' in stringtoadd or "'" in stringtoadd or " " in stringtoadd:
+                                       stringtoadd = `stringtoadd`
+                               h = d.GetDialogItemAsControl(ARGV_CMDLINE_DATA)
+                               oldstr = GetDialogItemText(h)
+                               if oldstr and oldstr[-1] != ' ':
+                                       oldstr = oldstr + ' '
+                               oldstr = oldstr + stringtoadd
+                               if oldstr[-1] != ' ':
+                                       oldstr = oldstr + ' '
+                               SetDialogItemText(h, oldstr)
+                               d.SelectDialogItemText(ARGV_CMDLINE_DATA, 0x7fff, 0x7fff)
+               h = d.GetDialogItemAsControl(ARGV_CMDLINE_DATA)
+               oldstr = GetDialogItemText(h)
+               tmplist = string.split(oldstr)
+               newlist = []
+               while tmplist:
+                       item = tmplist[0]
+                       del tmplist[0]
+                       if item[0] == '"':
+                               while item[-1] != '"':
+                                       if not tmplist:
+                                               raise RuntimeError, "Unterminated quoted argument"
+                                       item = item + ' ' + tmplist[0]
+                                       del tmplist[0]
+                               item = item[1:-1]
+                       if item[0] == "'":
+                               while item[-1] != "'":
+                                       if not tmplist:
+                                               raise RuntimeError, "Unterminated quoted argument"
+                                       item = item + ' ' + tmplist[0]
+                                       del tmplist[0]
+                               item = item[1:-1]
+                       newlist.append(item)
+               return newlist
+       finally:
+               apply(MacOS.SchedParams, appsw)
+               del d
+       
+def test():
+       import time, sys
+
+       Message("Testing EasyDialogs.")
+       optionlist = (('v', 'Verbose'), ('verbose', 'Verbose as long option'), 
+                               ('flags=', 'Valued option'), ('f:', 'Short valued option'))
+       commandlist = (('start', 'Start something'), ('stop', 'Stop something'))
+       argv = GetArgv(optionlist=optionlist, commandlist=commandlist, addoldfile=0)
+       for i in range(len(argv)):
+               print 'arg[%d] = %s'%(i, `argv[i]`)
+       print 'Type return to continue - ',
+       sys.stdin.readline()
+       ok = AskYesNoCancel("Do you want to proceed?")
+       ok = AskYesNoCancel("Do you want to identify?", yes="Identify", no="No")
+       if ok > 0:
+               s = AskString("Enter your first name", "Joe")
+               s2 = AskPassword("Okay %s, tell us your nickname"%s, s, cancel="None")
+               if not s2:
+                       Message("%s has no secret nickname"%s)
+               else:
+                       Message("Hello everybody!!\nThe secret nickname of %s is %s!!!"%(s, s2))
+       text = ( "Working Hard...", "Hardly Working..." , 
+                       "So far, so good!", "Keep on truckin'" )
+       bar = ProgressBar("Progress, progress...", 100)
+       try:
+               appsw = MacOS.SchedParams(1, 0)
+               for i in range(100):
+                       bar.set(i)
+                       time.sleep(0.1)
+                       if i % 10 == 0:
+                               bar.label(text[(i/10) % 4])
+               bar.label("Done.")
+               time.sleep(0.3)         # give'em a chance to see the done.
+       finally:
+               del bar
+               apply(MacOS.SchedParams, appsw)
+
+if __name__ == '__main__':
+       try:
+               test()
+       except KeyboardInterrupt:
+               Message("Operation Canceled.")
+
diff --git a/Mac/Modules/macfsmodule.c b/Mac/Modules/macfsmodule.c
new file mode 100644 (file)
index 0000000..5e34a64
--- /dev/null
@@ -0,0 +1,1266 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+#include "Python.h"
+#include "macglue.h"
+
+#ifdef WITHOUT_FRAMEWORKS
+#include <Memory.h>
+#include <Files.h>
+#include <Folders.h>
+#include <StandardFile.h>
+#include <Aliases.h>
+#include <LowMem.h>
+#else
+#include <Carbon/Carbon.h>
+#endif
+
+#include "getapplbycreator.h"
+
+
+static PyObject *ErrorObject;
+
+/* ----------------------------------------------------- */
+/* Declarations for objects of type Alias */
+
+typedef struct {
+       PyObject_HEAD
+       AliasHandle alias;
+} mfsaobject;
+
+staticforward PyTypeObject Mfsatype;
+
+#define is_mfsaobject(v)               ((v)->ob_type == &Mfsatype)
+
+/* ---------------------------------------------------------------- */
+/* Declarations for objects of type FSSpec */
+
+typedef struct {
+       PyObject_HEAD
+       FSSpec fsspec;
+} mfssobject;
+
+staticforward PyTypeObject Mfsstype;
+
+#define is_mfssobject(v)               ((v)->ob_type == &Mfsstype)
+
+/* ---------------------------------------------------------------- */
+/* Declarations for objects of type FSRef */
+
+typedef struct {
+       PyObject_HEAD
+       FSRef fsref;
+} mfsrobject;
+
+staticforward PyTypeObject Mfsrtype;
+
+#define is_mfsrobject(v)               ((v)->ob_type == &Mfsrtype)
+
+
+/* ---------------------------------------------------------------- */
+/* Declarations for objects of type FInfo */
+
+typedef struct {
+       PyObject_HEAD
+       FInfo finfo;
+} mfsiobject;
+
+staticforward PyTypeObject Mfsitype;
+
+#define is_mfsiobject(v)               ((v)->ob_type == &Mfsitype)
+
+
+staticforward mfssobject *newmfssobject(FSSpec *fss); /* Forward */
+staticforward mfsrobject *newmfsrobject(FSRef *fsr); /* Forward */
+
+/* ---------------------------------------------------------------- */
+
+static PyObject *
+mfsa_Resolve(self, args)
+       mfsaobject *self;
+       PyObject *args;
+{
+       FSSpec from, *fromp, result;
+       Boolean changed;
+       OSErr err;
+       
+       from.name[0] = 0;
+       if (!PyArg_ParseTuple(args, "|O&", PyMac_GetFSSpec, &from))
+               return NULL;
+       if (from.name[0] )
+               fromp = &from;
+       else
+               fromp = NULL;
+       err = ResolveAlias(fromp, self->alias, &result, &changed);
+       if ( err && err != fnfErr ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return Py_BuildValue("(Oi)", newmfssobject(&result), (int)changed);
+}
+
+static PyObject *
+mfsa_GetInfo(self, args)
+       mfsaobject *self;
+       PyObject *args;
+{
+       Str63 value;
+       int i;
+       OSErr err;
+       
+       if (!PyArg_ParseTuple(args, "i", &i))
+               return NULL;
+       err = GetAliasInfo(self->alias, (AliasInfoType)i, value);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return 0;
+       }
+       return PyString_FromStringAndSize((char *)&value[1], value[0]);
+}
+
+static PyObject *
+mfsa_Update(self, args)
+       mfsaobject *self;
+       PyObject *args;
+{
+       FSSpec target, fromfile, *fromfilep;
+       OSErr err;
+       Boolean changed;
+       
+       fromfile.name[0] = 0;
+       if (!PyArg_ParseTuple(args, "O&|O&",  PyMac_GetFSSpec, &target,
+                                        PyMac_GetFSSpec, &fromfile))
+               return NULL;
+       if ( fromfile.name[0] )
+               fromfilep = &fromfile;
+       else
+               fromfilep = NULL;
+       err = UpdateAlias(fromfilep, &target, self->alias, &changed);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return 0;
+       }
+       return Py_BuildValue("i", (int)changed);
+}
+
+static struct PyMethodDef mfsa_methods[] = {
+       {"Resolve",     (PyCFunction)mfsa_Resolve,      1},
+       {"GetInfo",     (PyCFunction)mfsa_GetInfo,      1},
+       {"Update",      (PyCFunction)mfsa_Update,       1},
+       {NULL,          NULL}           /* sentinel */
+};
+
+/* ---------- */
+
+static PyObject *
+mfsa_getattr(self, name)
+       mfsaobject *self;
+       char *name;
+{
+       if ( strcmp(name, "data") == 0 ) {
+               int size;
+               PyObject *rv;
+               
+               size = GetHandleSize((Handle)self->alias);
+               HLock((Handle)self->alias);
+               rv = PyString_FromStringAndSize(*(Handle)self->alias, size);
+               HUnlock((Handle)self->alias);
+               return rv;
+       }
+       return Py_FindMethod(mfsa_methods, (PyObject *)self, name);
+}
+
+static mfsaobject *
+newmfsaobject(AliasHandle alias)
+{
+       mfsaobject *self;
+
+       self = PyObject_NEW(mfsaobject, &Mfsatype);
+       if (self == NULL)
+               return NULL;
+       self->alias = alias;
+       return self;
+}
+
+
+static void
+mfsa_dealloc(self)
+       mfsaobject *self;
+{
+#if 0
+       if ( self->alias ) {
+               should we do something here?
+       }
+#endif
+               
+       PyMem_DEL(self);
+}
+
+statichere PyTypeObject Mfsatype = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /*ob_size*/
+       "Alias",                        /*tp_name*/
+       sizeof(mfsaobject),             /*tp_basicsize*/
+       0,                              /*tp_itemsize*/
+       /* methods */
+       (destructor)mfsa_dealloc,       /*tp_dealloc*/
+       (printfunc)0,                   /*tp_print*/
+       (getattrfunc)mfsa_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*/
+};
+
+/* End of code for Alias objects */
+/* -------------------------------------------------------- */
+
+/* ---------------------------------------------------------------- */
+
+static struct PyMethodDef mfsi_methods[] = {
+       
+       {NULL,          NULL}           /* sentinel */
+};
+
+/* ---------- */
+
+static mfsiobject *
+newmfsiobject()
+{
+       mfsiobject *self;
+       
+       self = PyObject_NEW(mfsiobject, &Mfsitype);
+       if (self == NULL)
+               return NULL;
+       memset((char *)&self->finfo, '\0', sizeof(self->finfo));
+       return self;
+}
+
+static void
+mfsi_dealloc(self)
+       mfsiobject *self;
+{
+       PyMem_DEL(self);
+}
+
+static PyObject *
+mfsi_getattr(self, name)
+       mfsiobject *self;
+       char *name;
+{
+       if ( strcmp(name, "Type") == 0 )
+               return PyMac_BuildOSType(self->finfo.fdType);
+       else if ( strcmp(name, "Creator") == 0 )
+               return PyMac_BuildOSType(self->finfo.fdCreator);
+       else if ( strcmp(name, "Flags") == 0 )
+               return Py_BuildValue("i", (int)self->finfo.fdFlags);
+       else if ( strcmp(name, "Location") == 0 )
+               return PyMac_BuildPoint(self->finfo.fdLocation);
+       else if ( strcmp(name, "Fldr") == 0 )
+               return Py_BuildValue("i", (int)self->finfo.fdFldr);
+       else
+               return Py_FindMethod(mfsi_methods, (PyObject *)self, name);
+}
+
+
+static int
+mfsi_setattr(self, name, v)
+       mfsiobject *self;
+       char *name;
+       PyObject *v;
+{
+       int rv;
+       int i;
+       
+       if ( v == NULL ) {
+               PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
+               return -1;
+       }
+       if ( strcmp(name, "Type") == 0 )
+               rv = PyMac_GetOSType(v, &self->finfo.fdType);
+       else if ( strcmp(name, "Creator") == 0 )
+               rv = PyMac_GetOSType(v, &self->finfo.fdCreator);
+       else if ( strcmp(name, "Flags") == 0 ) {
+               rv = PyArg_Parse(v, "i", &i);
+               self->finfo.fdFlags = (short)i;
+       } else if ( strcmp(name, "Location") == 0 )
+               rv = PyMac_GetPoint(v, &self->finfo.fdLocation);
+       else if ( strcmp(name, "Fldr") == 0 ) {
+               rv = PyArg_Parse(v, "i", &i);
+               self->finfo.fdFldr = (short)i;
+       } else {
+               PyErr_SetString(PyExc_AttributeError, "No such attribute");
+               return -1;
+       }
+       if (rv)
+               return 0;
+       return -1;
+}
+
+
+static PyTypeObject Mfsitype = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /*ob_size*/
+       "FInfo",                        /*tp_name*/
+       sizeof(mfsiobject),             /*tp_basicsize*/
+       0,                              /*tp_itemsize*/
+       /* methods */
+       (destructor)mfsi_dealloc,       /*tp_dealloc*/
+       (printfunc)0,           /*tp_print*/
+       (getattrfunc)mfsi_getattr,      /*tp_getattr*/
+       (setattrfunc)mfsi_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*/
+};
+
+/* End of code for FInfo object objects */
+/* -------------------------------------------------------- */
+
+
+/*
+** Helper routines for the FSRef and FSSpec creators in macglue.c
+** They return an FSSpec/FSRef if the Python object encapsulating
+** either is passed. They return a boolean success indicator.
+** Note that they do not set an exception on failure, they're only
+** helper routines.
+*/
+static int
+_mfs_GetFSSpecFromFSSpec(PyObject *self, FSSpec *fssp)
+{
+       if ( is_mfssobject(self) ) {
+               *fssp = ((mfssobject *)self)->fsspec;
+               return 1;
+       }
+       return 0;
+}
+
+/* Return an FSSpec if this is an FSref */
+static int
+_mfs_GetFSSpecFromFSRef(PyObject *self, FSSpec *fssp)
+{
+       static FSRef *fsrp;
+       
+       if ( is_mfsrobject(self) ) {
+               fsrp = &((mfsrobject *)self)->fsref;
+               if ( FSGetCatalogInfo(&((mfsrobject *)self)->fsref, kFSCatInfoNone, NULL, NULL, fssp, NULL) == noErr )
+                       return 1;
+       }
+       return 0;
+}
+
+/* Return an FSRef if this is an FSRef */
+static int
+_mfs_GetFSRefFromFSRef(PyObject *self, FSRef *fsrp)
+{
+       if ( is_mfsrobject(self) ) {
+               *fsrp = ((mfsrobject *)self)->fsref;
+               return 1;
+       }
+       return 0;
+}
+
+/* Return an FSRef if this is an FSSpec */
+static int
+_mfs_GetFSRefFromFSSpec(PyObject *self, FSRef *fsrp)
+{
+       if ( is_mfssobject(self) ) {
+               if ( FSpMakeFSRef(&((mfssobject *)self)->fsspec, fsrp) == noErr )
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+** Two generally useful routines
+*/
+static OSErr
+PyMac_GetFileDates(fss, crdat, mddat, bkdat)
+       FSSpec *fss;
+       unsigned long *crdat, *mddat, *bkdat;
+{
+       CInfoPBRec pb;
+       OSErr error;
+       
+       pb.dirInfo.ioNamePtr = fss->name;
+       pb.dirInfo.ioFDirIndex = 0;
+       pb.dirInfo.ioVRefNum = fss->vRefNum;
+       pb.dirInfo.ioDrDirID = fss->parID;
+       error = PBGetCatInfoSync(&pb);
+       if ( error ) return error;
+       *crdat = pb.hFileInfo.ioFlCrDat;
+       *mddat = pb.hFileInfo.ioFlMdDat;
+       *bkdat = pb.hFileInfo.ioFlBkDat;
+       return 0;
+}      
+
+static OSErr
+PyMac_SetFileDates(fss, crdat, mddat, bkdat)
+       FSSpec *fss;
+       unsigned long crdat, mddat, bkdat;
+{
+       CInfoPBRec pb;
+       OSErr error;
+       
+       pb.dirInfo.ioNamePtr = fss->name;
+       pb.dirInfo.ioFDirIndex = 0;
+       pb.dirInfo.ioVRefNum = fss->vRefNum;
+       pb.dirInfo.ioDrDirID = fss->parID;
+       error = PBGetCatInfoSync(&pb);
+       if ( error ) return error;
+       pb.dirInfo.ioNamePtr = fss->name;
+       pb.dirInfo.ioFDirIndex = 0;
+       pb.dirInfo.ioVRefNum = fss->vRefNum;
+       pb.dirInfo.ioDrDirID = fss->parID;
+       pb.hFileInfo.ioFlCrDat = crdat;
+       pb.hFileInfo.ioFlMdDat = mddat;
+       pb.hFileInfo.ioFlBkDat = bkdat;
+       error = PBSetCatInfoSync(&pb);
+       return error;
+}
+
+static PyObject *
+mfss_as_pathname(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       char strbuf[257];
+       OSErr err;
+
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       err = PyMac_GetFullPath(&self->fsspec, strbuf);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return PyString_FromString(strbuf);
+}
+
+static PyObject *
+mfss_as_tuple(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       return Py_BuildValue("(iis#)", self->fsspec.vRefNum, self->fsspec.parID, 
+                                               &self->fsspec.name[1], self->fsspec.name[0]);
+}
+
+static PyObject *
+mfss_NewAlias(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       FSSpec src, *srcp;
+       OSErr err;
+       AliasHandle alias;
+       
+       src.name[0] = 0;
+       if (!PyArg_ParseTuple(args, "|O&", PyMac_GetFSSpec, &src))
+               return NULL;
+       if ( src.name[0] )
+               srcp = &src;
+       else
+               srcp = NULL;
+       err = NewAlias(srcp, &self->fsspec, &alias);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       
+       return (PyObject *)newmfsaobject(alias);
+}
+
+static PyObject *
+mfss_NewAliasMinimal(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       AliasHandle alias;
+       
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       err = NewAliasMinimal(&self->fsspec, &alias);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (PyObject *)newmfsaobject(alias);
+}
+
+static PyObject *
+mfss_FSpMakeFSRef(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       FSRef fsref;
+       
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       err = FSpMakeFSRef(&self->fsspec, &fsref);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (PyObject *)newmfsrobject(&fsref);
+}
+
+/* XXXX These routines should be replaced by a wrapper to the *FInfo routines */
+static PyObject *
+mfss_GetCreatorType(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       FInfo info;
+       
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       err = FSpGetFInfo(&self->fsspec, &info);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return Py_BuildValue("(O&O&)",
+                  PyMac_BuildOSType, info.fdCreator, PyMac_BuildOSType, info.fdType);
+}
+
+static PyObject *
+mfss_SetCreatorType(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       OSType creator, type;
+       FInfo info;
+       
+       if (!PyArg_ParseTuple(args, "O&O&", PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
+               return NULL;
+       err = FSpGetFInfo(&self->fsspec, &info);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       info.fdType = type;
+       info.fdCreator = creator;
+       err = FSpSetFInfo(&self->fsspec, &info);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject *
+mfss_GetFInfo(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       mfsiobject *fip;
+       
+       
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       if ( (fip=newmfsiobject()) == NULL )
+               return NULL;
+       err = FSpGetFInfo(&self->fsspec, &fip->finfo);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               Py_DECREF(fip);
+               return NULL;
+       }
+       return (PyObject *)fip;
+}
+
+static PyObject *
+mfss_SetFInfo(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       mfsiobject *fip;
+       
+       if (!PyArg_ParseTuple(args, "O!", &Mfsitype, &fip))
+               return NULL;
+       err = FSpSetFInfo(&self->fsspec, &fip->finfo);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject *
+mfss_GetDates(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       unsigned long crdat, mddat, bkdat;
+       
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       err = PyMac_GetFileDates(&self->fsspec, &crdat, &mddat, &bkdat);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return Py_BuildValue("ddd", (double)crdat, (double)mddat, (double)bkdat);
+}
+
+static PyObject *
+mfss_SetDates(self, args)
+       mfssobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       double crdat, mddat, bkdat;
+       
+       if (!PyArg_ParseTuple(args, "ddd", &crdat, &mddat, &bkdat))
+               return NULL;
+       err = PyMac_SetFileDates(&self->fsspec, (unsigned long)crdat, 
+                               (unsigned long)mddat, (unsigned long)bkdat);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static struct PyMethodDef mfss_methods[] = {
+       {"as_pathname",         (PyCFunction)mfss_as_pathname,                  1},
+       {"as_tuple",            (PyCFunction)mfss_as_tuple,                             1},
+       {"as_fsref",    (PyCFunction)mfss_FSpMakeFSRef,                 1},
+       {"FSpMakeFSRef",        (PyCFunction)mfss_FSpMakeFSRef,                 1},
+       {"NewAlias",            (PyCFunction)mfss_NewAlias,                             1},
+       {"NewAliasMinimal",     (PyCFunction)mfss_NewAliasMinimal,              1},
+       {"GetCreatorType",      (PyCFunction)mfss_GetCreatorType,               1},
+       {"SetCreatorType",      (PyCFunction)mfss_SetCreatorType,               1},
+       {"GetFInfo",            (PyCFunction)mfss_GetFInfo,                             1},
+       {"SetFInfo",            (PyCFunction)mfss_SetFInfo,                             1},
+       {"GetDates",            (PyCFunction)mfss_GetDates,                             1},
+       {"SetDates",            (PyCFunction)mfss_SetDates,                             1},
+       {NULL,                  NULL}           /* sentinel */
+};
+
+/* ---------- */
+
+static PyObject *
+mfss_getattr(self, name)
+       mfssobject *self;
+       char *name;
+{
+       if ( strcmp(name, "data") == 0)
+               return PyString_FromStringAndSize((char *)&self->fsspec, sizeof(FSSpec));       
+       return Py_FindMethod(mfss_methods, (PyObject *)self, name);
+}
+
+mfssobject *
+newmfssobject(fss)
+       FSSpec *fss;
+{
+       mfssobject *self;
+       
+       self = PyObject_NEW(mfssobject, &Mfsstype);
+       if (self == NULL)
+               return NULL;
+       self->fsspec = *fss;
+       return self;
+}
+
+static void
+mfss_dealloc(self)
+       mfssobject *self;
+{
+       PyMem_DEL(self);
+}
+
+static PyObject *
+mfss_repr(self)
+       mfssobject *self;
+{
+       char buf[512];
+
+       sprintf(buf, "FSSpec((%d, %d, '%.*s'))",
+               self->fsspec.vRefNum, 
+               self->fsspec.parID,
+               self->fsspec.name[0], self->fsspec.name+1);
+       return PyString_FromString(buf);
+}
+
+static int
+mfss_compare(v, w)
+       mfssobject *v, *w;
+{
+       int minlen;
+       int res;
+       
+       if ( v->fsspec.vRefNum < w->fsspec.vRefNum ) return -1;
+       if ( v->fsspec.vRefNum > w->fsspec.vRefNum ) return 1;
+       if ( v->fsspec.parID < w->fsspec.parID ) return -1;
+       if ( v->fsspec.parID > w->fsspec.parID ) return 1;
+       minlen = v->fsspec.name[0];
+       if ( w->fsspec.name[0] < minlen ) minlen = w->fsspec.name[0];
+       res = strncmp((char *)v->fsspec.name+1, (char *)w->fsspec.name+1, minlen);
+       if ( res ) return res;
+       if ( v->fsspec.name[0] < w->fsspec.name[0] ) return -1;
+       if ( v->fsspec.name[0] > w->fsspec.name[0] ) return 1;
+       return res;
+}
+
+statichere PyTypeObject Mfsstype = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /*ob_size*/
+       "FSSpec",                       /*tp_name*/
+       sizeof(mfssobject),             /*tp_basicsize*/
+       0,                              /*tp_itemsize*/
+       /* methods */
+       (destructor)mfss_dealloc,       /*tp_dealloc*/
+       (printfunc)0,           /*tp_print*/
+       (getattrfunc)mfss_getattr,      /*tp_getattr*/
+       (setattrfunc)0, /*tp_setattr*/
+       (cmpfunc)mfss_compare,          /*tp_compare*/
+       (reprfunc)mfss_repr,            /*tp_repr*/
+       0,                      /*tp_as_number*/
+       0,              /*tp_as_sequence*/
+       0,              /*tp_as_mapping*/
+       (hashfunc)0,            /*tp_hash*/
+};
+
+/* End of code for FSSpec objects */
+/* -------------------------------------------------------- */
+
+static PyObject *
+mfsr_as_fsspec(self, args)
+       mfsrobject *self;
+       PyObject *args;
+{
+       OSErr err;
+       FSSpec fss;
+       
+       if (!PyArg_ParseTuple(args, ""))
+               return NULL;
+       err = FSGetCatalogInfo(&self->fsref, kFSCatInfoNone, NULL, NULL, &fss, NULL);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       Py_INCREF(Py_None);
+       return (PyObject *)newmfssobject(&fss);
+}
+
+static struct PyMethodDef mfsr_methods[] = {
+       {"as_fsspec",           (PyCFunction)mfsr_as_fsspec,    1},
+#if 0
+       {"as_pathname",         (PyCFunction)mfss_as_pathname,                  1},
+       {"as_tuple",            (PyCFunction)mfss_as_tuple,                             1},
+       {"NewAlias",            (PyCFunction)mfss_NewAlias,                             1},
+       {"NewAliasMinimal",     (PyCFunction)mfss_NewAliasMinimal,              1},
+       {"GetCreatorType",      (PyCFunction)mfss_GetCreatorType,               1},
+       {"SetCreatorType",      (PyCFunction)mfss_SetCreatorType,               1},
+       {"GetFInfo",            (PyCFunction)mfss_GetFInfo,                             1},
+       {"SetFInfo",            (PyCFunction)mfss_SetFInfo,                             1},
+       {"GetDates",            (PyCFunction)mfss_GetDates,                             1},
+       {"SetDates",            (PyCFunction)mfss_SetDates,                             1},
+#endif
+       {NULL,                  NULL}           /* sentinel */
+};
+
+/* ---------- */
+
+static PyObject *
+mfsr_getattr(self, name)
+       mfsrobject *self;
+       char *name;
+{
+       if ( strcmp(name, "data") == 0)
+               return PyString_FromStringAndSize((char *)&self->fsref, sizeof(FSRef)); 
+       return Py_FindMethod(mfsr_methods, (PyObject *)self, name);
+}
+
+mfsrobject *
+newmfsrobject(fsr)
+       FSRef *fsr;
+{
+       mfsrobject *self;
+       
+       self = PyObject_NEW(mfsrobject, &Mfsrtype);
+       if (self == NULL)
+               return NULL;
+       self->fsref = *fsr;
+       return self;
+}
+
+static int
+mfsr_compare(v, w)
+       mfsrobject *v, *w;
+{
+       OSErr err;
+       
+       if ( v == w ) return 0;
+       err = FSCompareFSRefs(&v->fsref, &w->fsref);
+       if ( err == 0 )
+               return 0;
+       if (v < w )
+               return -1;
+       return 1;
+}
+
+static void
+mfsr_dealloc(self)
+       mfsrobject *self;
+{
+       PyMem_DEL(self);
+}
+
+statichere PyTypeObject Mfsrtype = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /*ob_size*/
+       "FSRef",                        /*tp_name*/
+       sizeof(mfsrobject),             /*tp_basicsize*/
+       0,                              /*tp_itemsize*/
+       /* methods */
+       (destructor)mfsr_dealloc,       /*tp_dealloc*/
+       (printfunc)0,           /*tp_print*/
+       (getattrfunc)mfsr_getattr,      /*tp_getattr*/
+       (setattrfunc)0, /*tp_setattr*/
+       (cmpfunc)mfsr_compare,          /*tp_compare*/
+       (reprfunc)0,            /*tp_repr*/
+       0,                      /*tp_as_number*/
+       0,              /*tp_as_sequence*/
+       0,              /*tp_as_mapping*/
+       (hashfunc)0,            /*tp_hash*/
+};
+
+/* End of code for FSRef objects */
+/* -------------------------------------------------------- */
+
+static PyObject *
+mfs_ResolveAliasFile(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       FSSpec fss;
+       Boolean chain = 1, isfolder, wasaliased;
+       OSErr err;
+
+       if (!PyArg_ParseTuple(args, "O&|i", PyMac_GetFSSpec, &fss, &chain))
+               return NULL;
+       err = ResolveAliasFile(&fss, chain, &isfolder, &wasaliased);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return Py_BuildValue("Oii", newmfssobject(&fss), (int)isfolder, (int)wasaliased);
+}
+
+#if !TARGET_API_MAC_CARBON
+static PyObject *
+mfs_StandardGetFile(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       SFTypeList list;
+       short numtypes;
+       StandardFileReply reply;
+       
+       list[0] = list[1] = list[2] = list[3] = 0;
+       numtypes = 0;
+       if (!PyArg_ParseTuple(args, "|O&O&O&O&", PyMac_GetOSType, &list[0],
+                        PyMac_GetOSType, &list[1], PyMac_GetOSType, &list[2],
+                         PyMac_GetOSType, &list[3]) )
+               return NULL;
+       while ( numtypes < 4 && list[numtypes] ) {
+               numtypes++;
+       }
+       if ( numtypes == 0 )
+               numtypes = -1;
+       StandardGetFile((FileFilterUPP)0, numtypes, list, &reply);
+       return Py_BuildValue("(Oi)", newmfssobject(&reply.sfFile), reply.sfGood);
+}
+
+static PyObject *
+mfs_PromptGetFile(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       SFTypeList list;
+       short numtypes;
+       StandardFileReply reply;
+       char *prompt = NULL;
+       
+       list[0] = list[1] = list[2] = list[3] = 0;
+       numtypes = 0;
+       if (!PyArg_ParseTuple(args, "s|O&O&O&O&", &prompt, PyMac_GetOSType, &list[0],
+                        PyMac_GetOSType, &list[1], PyMac_GetOSType, &list[2],
+                         PyMac_GetOSType, &list[3]) )
+               return NULL;
+       while ( numtypes < 4 && list[numtypes] ) {
+               numtypes++;
+       }
+       if ( numtypes == 0 )
+               numtypes = -1;
+       PyMac_PromptGetFile(numtypes, list, &reply, prompt);
+       return Py_BuildValue("(Oi)", newmfssobject(&reply.sfFile), reply.sfGood);
+}
+
+static PyObject *
+mfs_StandardPutFile(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       Str255 prompt, dft;
+       StandardFileReply reply;
+       
+       dft[0] = 0;
+       if (!PyArg_ParseTuple(args, "O&|O&", PyMac_GetStr255, &prompt, PyMac_GetStr255, &dft) )
+               return NULL;
+       StandardPutFile(prompt, dft, &reply);
+       return Py_BuildValue("(Oi)",newmfssobject(&reply.sfFile), reply.sfGood);
+}
+
+/*
+** Set initial directory for file dialogs */
+static PyObject *
+mfs_SetFolder(self, args)
+       PyObject *self;
+       PyObject *args;
+{
+       FSSpec spec;
+       FSSpec ospec;
+       short orefnum;
+       long oparid;
+       
+       /* Get old values */
+       orefnum = -LMGetSFSaveDisk();
+       oparid = LMGetCurDirStore();
+       (void)FSMakeFSSpec(orefnum, oparid, "\pplaceholder", &ospec);
+       
+       /* Go to working directory by default */
+       (void)FSMakeFSSpec(0, 0, "\p:placeholder", &spec);
+       if (!PyArg_ParseTuple(args, "|O&", PyMac_GetFSSpec, &spec))
+               return NULL;
+       /* Set standard-file working directory */
+       LMSetSFSaveDisk(-spec.vRefNum);
+       LMSetCurDirStore(spec.parID);
+       return (PyObject *)newmfssobject(&ospec);
+}
+#endif
+
+static PyObject *
+mfs_FSSpec(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       FSSpec fss;
+
+       if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
+               return NULL;
+       return (PyObject *)newmfssobject(&fss);
+}
+
+static PyObject *
+mfs_FSRef(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       FSRef fsr;
+
+       if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &fsr))
+               return NULL;
+       return (PyObject *)newmfsrobject(&fsr);
+}
+
+static PyObject *
+mfs_RawFSSpec(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       FSSpec *fssp;
+       int size;
+
+       if (!PyArg_ParseTuple(args, "s#", &fssp, &size))
+               return NULL;
+       if ( size != sizeof(FSSpec) ) {
+               PyErr_SetString(PyExc_TypeError, "Incorrect size for FSSpec record");
+               return NULL;
+       }
+       return (PyObject *)newmfssobject(fssp);
+}
+
+static PyObject *
+mfs_RawAlias(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       char *dataptr;
+       Handle h;
+       int size;
+
+       if (!PyArg_ParseTuple(args, "s#", &dataptr, &size))
+               return NULL;
+       h = NewHandle(size);
+       if ( h == NULL ) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+       HLock(h);
+       memcpy((char *)*h, dataptr, size);
+       HUnlock(h);
+       return (PyObject *)newmfsaobject((AliasHandle)h);
+}
+
+#if !TARGET_API_MAC_CARBON
+static PyObject *
+mfs_GetDirectory(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       FSSpec fsdir;
+       int ok;
+       char *prompt = NULL;
+               
+       if (!PyArg_ParseTuple(args, "|s", &prompt) )
+               return NULL;
+               
+       ok = PyMac_GetDirectory(&fsdir, prompt);
+       return Py_BuildValue("(Oi)", newmfssobject(&fsdir), ok);
+}
+#endif
+
+static PyObject *
+mfs_FindFolder(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       OSErr err;
+       short where;
+       OSType which;
+       int create;
+       short refnum;
+       long dirid;
+               
+       if (!PyArg_ParseTuple(args, "hO&i", &where, PyMac_GetOSType, &which, &create) )
+               return NULL;
+       err = FindFolder(where, which, (Boolean)create, &refnum, &dirid);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return Py_BuildValue("(ii)", refnum, dirid);
+}
+
+static PyObject *
+mfs_FindApplication(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       OSErr err;
+       OSType which;
+       FSSpec  fss;
+               
+       if (!PyArg_ParseTuple(args, "O&", PyMac_GetOSType, &which) )
+               return NULL;
+       err = FindApplicationFromCreator(which, &fss);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (PyObject *)newmfssobject(&fss);
+}
+
+static PyObject *
+mfs_FInfo(self, args)
+       PyObject *self;
+       PyObject *args;
+{      
+       return (PyObject *)newmfsiobject();
+}
+
+static PyObject *
+mfs_NewAliasMinimalFromFullPath(self, args)
+       PyObject *self; /* Not used */
+       PyObject *args;
+{
+       OSErr err;
+       char *fullpath;
+       int fullpathlen;
+       AliasHandle alias;
+       Str32 zonename;
+       Str31 servername;
+                       
+       if (!PyArg_ParseTuple(args, "s#", &fullpath, &fullpathlen) )
+               return NULL;
+       zonename[0] = 0;
+       servername[0] = 0;
+       err = NewAliasMinimalFromFullPath(fullpathlen, (Ptr)fullpath, zonename, 
+                       servername, &alias);
+       if ( err ) {
+               PyErr_Mac(ErrorObject, err);
+               return NULL;
+       }
+       return (PyObject *)newmfsaobject(alias);
+}
+
+
+/* List of methods defined in the module */
+
+static struct PyMethodDef mfs_methods[] = {
+       {"ResolveAliasFile",    mfs_ResolveAliasFile,   1},
+#if !TARGET_API_MAC_CARBON
+       {"StandardGetFile",             mfs_StandardGetFile,    1},
+       {"PromptGetFile",               mfs_PromptGetFile,              1},
+       {"StandardPutFile",             mfs_StandardPutFile,    1},
+       {"GetDirectory",                mfs_GetDirectory,               1},
+       {"SetFolder",                   mfs_SetFolder,                  1},
+#endif
+       {"FSSpec",                              mfs_FSSpec,                             1},
+       {"FSRef",                               mfs_FSRef,                              1},
+       {"RawFSSpec",                   mfs_RawFSSpec,                  1},
+       {"RawAlias",                    mfs_RawAlias,                   1},
+       {"FindFolder",                  mfs_FindFolder,                 1},
+       {"FindApplication",             mfs_FindApplication,    1},
+       {"FInfo",                               mfs_FInfo,                              1},
+       {"NewAliasMinimalFromFullPath", mfs_NewAliasMinimalFromFullPath,        1},
+       {NULL,          NULL}           /* sentinel */
+};
+
+/*
+** Convert a Python object to an FSSpec.
+** The object may either be a full pathname, an FSSpec, an FSRef or a triple
+** (vrefnum, dirid, path).
+*/
+int
+PyMac_GetFSRef(PyObject *v, FSRef *fsr)
+{
+       OSErr err;
+
+       /* If it's an FSRef we're also okay. */
+       if (_mfs_GetFSRefFromFSRef(v, fsr))
+               return 1;
+       /* first check whether it already is an FSSpec */
+       if ( _mfs_GetFSRefFromFSSpec(v, fsr) )
+               return 1;
+       if ( PyString_Check(v) ) {
+               PyErr_SetString(PyExc_NotImplementedError, "Cannot create an FSRef from a pathname on this platform");
+               return 0;
+       }
+       PyErr_SetString(PyExc_TypeError, "FSRef argument should be existing FSRef, FSSpec or (OSX only) pathname");
+       return 0;
+}
+
+/* Convert FSSpec to PyObject */
+PyObject *PyMac_BuildFSRef(FSRef *v)
+{
+       return (PyObject *)newmfsrobject(v);
+}
+
+/*
+** Convert a Python object to an FSRef.
+** The object may either be a full pathname (OSX only), an FSSpec or an FSRef.
+*/
+int
+PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
+{
+       Str255 path;
+       short refnum;
+       long parid;
+       OSErr err;
+
+       /* first check whether it already is an FSSpec */
+       if ( _mfs_GetFSSpecFromFSSpec(v, fs) )
+               return 1;
+       /* If it's an FSRef we're also okay. */
+       if (_mfs_GetFSSpecFromFSRef(v, fs))
+               return 1;
+       if ( PyString_Check(v) ) {
+               /* It's a pathname */
+               if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
+                       return 0;
+               refnum = 0; /* XXXX Should get CurWD here?? */
+               parid = 0;
+       } else {
+               if( !PyArg_Parse(v, "(hlO&); FSSpec should be FSSpec, FSRef, fullpath or (vrefnum,dirid,path)",
+                                                       &refnum, &parid, PyMac_GetStr255, &path)) {
+                       return 0;
+               }
+       }
+       err = FSMakeFSSpec(refnum, parid, path, fs);
+       if ( err && err != fnfErr ) {
+               PyMac_Error(err);
+               return 0;
+       }
+       return 1;
+}
+
+/* Convert FSSpec to PyObject */
+PyObject *PyMac_BuildFSSpec(FSSpec *v)
+{
+       return (PyObject *)newmfssobject(v);
+}
+
+/* Initialization function for the module (*must* be called initmacfs) */
+
+void
+initmacfs()
+{
+       PyObject *m, *d;
+
+       /* Create the module and add the functions */
+       m = Py_InitModule("macfs", mfs_methods);
+
+       /* Add some symbolic constants to the module */
+       d = PyModule_GetDict(m);
+       ErrorObject = PyMac_GetOSErrException();
+       PyDict_SetItemString(d, "error", ErrorObject);
+
+       Mfsatype.ob_type = &PyType_Type;
+       Py_INCREF(&Mfsatype);
+       PyDict_SetItemString(d, "AliasType", (PyObject *)&Mfsatype);
+       Mfsstype.ob_type = &PyType_Type;
+       Py_INCREF(&Mfsstype);
+       PyDict_SetItemString(d, "FSSpecType", (PyObject *)&Mfsstype);
+       Mfsitype.ob_type = &PyType_Type;
+       Py_INCREF(&Mfsitype);
+       PyDict_SetItemString(d, "FInfoType", (PyObject *)&Mfsitype);
+       /* XXXX Add constants here */
+}
diff --git a/Mac/Python/macimport.c b/Mac/Python/macimport.c
new file mode 100644 (file)
index 0000000..b47a694
--- /dev/null
@@ -0,0 +1,492 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+
+#include "Python.h"
+
+#include "macglue.h"
+#include "marshal.h"
+#include "import.h"
+#include "importdl.h"
+
+#include "pythonresources.h"
+
+#include <Types.h>
+#include <Files.h>
+#include <Resources.h>
+#if 0
+#include <OSUtils.h> /* for Set(Current)A5 */
+#include <StandardFile.h>
+#include <Memory.h>
+#include <Windows.h>
+#include <Traps.h>
+#include <Processes.h>
+#include <Fonts.h>
+#include <Menus.h>
+#include <TextUtils.h>
+#endif
+#include <CodeFragments.h>
+#include <StringCompare.h>
+
+#ifdef USE_GUSI1
+#include "TFileSpec.h" /* for Path2FSSpec() */
+#endif
+
+typedef void (*dl_funcptr)();
+#define FUNCNAME_PATTERN "init%.200s"
+
+static int
+fssequal(FSSpec *fs1, FSSpec *fs2)
+{
+       if ( fs1->vRefNum != fs2->vRefNum || fs1->parID != fs2->parID )
+               return 0;
+       return EqualString(fs1->name, fs2->name, false, true);
+}
+/*
+** findnamedresource - Common code for the various *ResourceModule functions.
+** Check whether a file contains a resource of the correct name and type, and
+** optionally return the value in it.
+*/
+static int
+findnamedresource(
+       PyStringObject *obj, 
+       char *module, 
+       char *filename, 
+       OSType restype, 
+       StringPtr dataptr)
+{
+       FSSpec fss;
+       FInfo finfo;
+       short oldrh, filerh;
+       int ok;
+       Handle h;
+
+#ifdef INTERN_STRINGS
+       /*
+       ** If we have interning find_module takes care of interning all
+       ** sys.path components. We then keep a record of all sys.path
+       ** components for which GetFInfo has failed (usually because the
+       ** component in question is a folder), and we don't try opening these
+       ** as resource files again.
+       */
+#define MAXPATHCOMPONENTS 32
+       static PyStringObject *not_a_file[MAXPATHCOMPONENTS];
+       static int max_not_a_file = 0;
+       int i;
+               
+       if (obj && obj->ob_sinterned ) {
+               for( i=0; i< max_not_a_file; i++ )
+                       if ( obj == not_a_file[i] )
+                               return 0;
+       }
+#endif /* INTERN_STRINGS */
+#ifdef USE_GUSI1
+       if ( Path2FSSpec(filename, &fss) != noErr ) {
+#else
+       if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr ) {
+#endif
+#ifdef INTERN_STRINGS
+               if ( obj && max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned )
+                       not_a_file[max_not_a_file++] = obj;
+#endif /* INTERN_STRINGS */
+               /* doesn't exist or is folder */
+               return 0;
+       }                       
+       if ( fssequal(&fss, &PyMac_ApplicationFSSpec) ) {
+               /*
+               ** Special case: the application itself. Use a shortcut to
+               ** forestall opening and closing the application numerous times
+               ** (which is dead slow when running from CDROM)
+               */
+               oldrh = CurResFile();
+               UseResFile(PyMac_AppRefNum);
+               filerh = -1;
+       } else {
+#ifdef INTERN_STRINGS
+               if ( FSpGetFInfo(&fss, &finfo) != noErr ) {
+                       if ( obj && max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned )
+                               not_a_file[max_not_a_file++] = obj;
+                       /* doesn't exist or is folder */
+                       return 0;
+               }                       
+#endif /* INTERN_STRINGS */
+               oldrh = CurResFile();
+               filerh = FSpOpenResFile(&fss, fsRdPerm);
+               if ( filerh == -1 )
+                       return 0;
+               UseResFile(filerh);
+       }
+       if ( dataptr == NULL )
+               SetResLoad(0);
+       h = Get1NamedResource(restype, Pstring(module));
+       SetResLoad(1);
+       ok = (h != NULL);
+       if ( ok && dataptr != NULL ) {
+               HLock(h);
+               /* XXXX Unsafe if resource not correctly formatted! */
+#ifdef __CFM68K__
+               /* for cfm68k we take the second pstring */
+               *dataptr = *((*h)+(**h)+1);
+               memcpy(dataptr+1, (*h)+(**h)+2, (int)*dataptr);
+#else
+               /* for ppc we take the first pstring */
+               *dataptr = **h;
+               memcpy(dataptr+1, (*h)+1, (int)*dataptr);
+#endif
+               HUnlock(h);
+       }
+       if ( filerh != -1 )
+               CloseResFile(filerh);
+       UseResFile(oldrh);
+       return ok;
+}
+
+/*
+** Returns true if the argument has a resource fork, and it contains
+** a 'PYC ' resource of the correct name
+*/
+int
+PyMac_FindResourceModule(obj, module, filename)
+PyStringObject *obj;
+char *module;
+char *filename;
+{
+       int ok;
+       
+       ok = findnamedresource(obj, module, filename, 'PYC ', (StringPtr)0);
+       return ok;
+}
+
+/*
+** Returns true if the argument has a resource fork, and it contains
+** a 'PYD ' resource of the correct name
+*/
+int
+PyMac_FindCodeResourceModule(obj, module, filename)
+PyStringObject *obj;
+char *module;
+char *filename;
+{
+       int ok;
+       
+       ok = findnamedresource(obj, module, filename, 'PYD ', (StringPtr)0);
+       return ok;
+}
+
+
+/*
+** Load the specified module from a code resource
+*/
+PyObject *
+PyMac_LoadCodeResourceModule(name, pathname)
+       char *name;
+       char *pathname;
+{
+       PyObject *m, *d, *s;
+       char funcname[258];
+       char *lastdot, *shortname, *packagecontext;
+       dl_funcptr p = NULL;
+       Str255 fragmentname;
+       CFragConnectionID connID;
+       Ptr mainAddr;
+       Str255 errMessage;
+       OSErr err;
+       char buf[512];
+       Ptr symAddr;
+       CFragSymbolClass class;
+
+       if ((m = _PyImport_FindExtension(name, name)) != NULL) {
+               Py_INCREF(m);
+               return m;
+       }
+       lastdot = strrchr(name, '.');
+       if (lastdot == NULL) {
+               packagecontext = NULL;
+               shortname = name;
+       }
+       else {
+               packagecontext = name;
+               shortname = lastdot+1;
+       }
+       sprintf(funcname, FUNCNAME_PATTERN, shortname);
+       if( !findnamedresource((PyStringObject *)0, name, pathname, 'PYD ', fragmentname)) {
+               PyErr_SetString(PyExc_ImportError, "PYD resource not found");
+               return NULL;
+       }
+       
+       /* Load the fragment
+          (or return the connID if it is already loaded */
+       err = GetSharedLibrary(fragmentname, kCompiledCFragArch,
+                             kLoadCFrag, &connID, &mainAddr,
+                             errMessage);
+       if ( err ) {
+               sprintf(buf, "%.*s: %.200s",
+                       errMessage[0], errMessage+1,
+                       PyMac_StrError(err));
+               PyErr_SetString(PyExc_ImportError, buf);
+               return NULL;
+       }
+       /* Locate the address of the correct init function */
+       err = FindSymbol(connID, Pstring(funcname), &symAddr, &class);
+       if ( err ) {
+               sprintf(buf, "%s: %.200s",
+                       funcname, PyMac_StrError(err));
+               PyErr_SetString(PyExc_ImportError, buf);
+               return NULL;
+       }
+       p = (dl_funcptr)symAddr;
+       if (p == NULL) {
+               PyErr_Format(PyExc_ImportError,
+                  "dynamic module does not define init function (%.200s)",
+                            funcname);
+               return NULL;
+       }
+       _Py_PackageContext = packagecontext;
+       (*p)();
+       _Py_PackageContext = NULL;
+       if (PyErr_Occurred())
+               return NULL;
+       if (_PyImport_FixupExtension(name, name) == NULL)
+               return NULL;
+
+       m = PyDict_GetItemString(PyImport_GetModuleDict(), name);
+       if (m == NULL) {
+               PyErr_SetString(PyExc_SystemError,
+                               "dynamic module not initialized properly");
+               return NULL;
+       }
+#if 1
+       /* Remember the filename as the __file__ attribute */
+       d = PyModule_GetDict(m);
+       s = PyString_FromString(pathname);
+       if (s == NULL || PyDict_SetItemString(d, "__file__", s) != 0)
+               PyErr_Clear(); /* Not important enough to report */
+       Py_XDECREF(s);
+#endif
+       if (Py_VerboseFlag)
+               PySys_WriteStderr("import %s # pyd fragment %#s loaded from %s\n",
+                       name, fragmentname, pathname);
+       Py_INCREF(m);
+       return m;
+}
+
+/*
+** Load the specified module from a resource
+*/
+PyObject *
+PyMac_LoadResourceModule(module, filename)
+char *module;
+char *filename;
+{
+       FSSpec fss;
+       FInfo finfo;
+       short oldrh, filerh;
+       Handle h;
+       OSErr err;
+       PyObject *m, *co;
+       long num, size;
+       
+#ifdef USE_GUSI1
+       if ( (err=Path2FSSpec(filename, &fss)) != noErr ||
+            FSpGetFInfo(&fss, &finfo) != noErr )
+#else
+       if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
+#endif
+               goto error;
+       if ( fssequal(&fss, &PyMac_ApplicationFSSpec) ) {
+               /*
+               ** Special case: the application itself. Use a shortcut to
+               ** forestall opening and closing the application numerous times
+               ** (which is dead slow when running from CDROM)
+               */
+               oldrh = CurResFile();
+               UseResFile(PyMac_AppRefNum);
+               filerh = -1;
+       } else {
+               if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
+                       goto error;
+               oldrh = CurResFile();
+               filerh = FSpOpenResFile(&fss, fsRdPerm);
+               if ( filerh == -1 ) {
+                       err = ResError();
+                       goto error;
+               }
+               UseResFile(filerh);
+       }
+       h = Get1NamedResource('PYC ', Pstring(module));
+       if ( h == NULL ) {
+               err = ResError();
+               goto error;
+       }
+       HLock(h);
+       /*
+       ** XXXX The next few lines are intimately tied to the format of pyc
+       ** files. I'm not sure whether this code should be here or in import.c -- Jack
+       */
+       size = GetHandleSize(h);
+       if ( size < 8 ) {
+               PyErr_SetString(PyExc_ImportError, "Resource too small");
+               co = NULL;
+       } else {
+               num = (*h)[0] & 0xff;
+               num = num | (((*h)[1] & 0xff) << 8);
+               num = num | (((*h)[2] & 0xff) << 16);
+               num = num | (((*h)[3] & 0xff) << 24);
+               if ( num != PyImport_GetMagicNumber() ) {
+                       PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
+                       co = NULL;
+               } else {
+                       co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
+                       /*
+                       ** Normally, byte 4-7 are the time stamp, but that is not used
+                       ** for 'PYC ' resources. We abuse byte 4 as a flag to indicate
+                       ** that it is a package rather than an ordinary module. 
+                       ** See also py_resource.py. (jvr)
+                       */
+                       if ((*h)[4] & 0xff) {
+                               /* it's a package */
+                               /* Set __path__ to the package name */
+                               PyObject *d, *s;
+                               int err;
+                               
+                               m = PyImport_AddModule(module);
+                               if (m == NULL) {
+                                       co = NULL;
+                                       goto packageerror;
+                               }
+                               d = PyModule_GetDict(m);
+                               s = PyString_InternFromString(module);
+                               if (s == NULL) {
+                                       co = NULL;
+                                       goto packageerror;
+                               }
+                               err = PyDict_SetItemString(d, "__path__", s);
+                               Py_DECREF(s);
+                               if (err != 0) {
+                                       co = NULL;
+                                       goto packageerror;
+                               }
+                       }
+               }
+       }
+packageerror:
+       HUnlock(h);
+       if ( filerh != -1 )
+               CloseResFile(filerh);
+       else
+               ReleaseResource(h);
+       UseResFile(oldrh);
+       if ( co ) {
+               m = PyImport_ExecCodeModuleEx(module, co, "<pyc resource>");
+               Py_DECREF(co);
+       } else {
+               m = NULL;
+       }
+       if (Py_VerboseFlag)
+               PySys_WriteStderr("import %s # pyc resource from %s\n",
+                       module, filename);
+       return m;
+error:
+       {
+               char buf[512];
+               
+               sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
+               PyErr_SetString(PyExc_ImportError, buf);
+               return NULL;
+       }
+}
+
+/*
+** Look for a module in a single folder. Upon entry buf and len
+** point to the folder to search, upon exit they refer to the full
+** pathname of the module found (if any).
+*/
+struct filedescr *
+PyMac_FindModuleExtension(char *buf, size_t *lenp, char *module)
+{
+       struct filedescr *fdp;
+       unsigned char fnbuf[64];
+       int modnamelen = strlen(module);
+       FSSpec fss;
+#ifdef USE_GUSI1
+       FInfo finfo;
+#endif
+       short refnum;
+       long dirid;
+       
+       /*
+       ** Copy the module name to the buffer (already :-terminated)
+       ** We also copy the first suffix, if this matches immedeately we're
+       ** lucky and return immedeately.
+       */
+       if ( !_PyImport_Filetab[0].suffix )
+               return 0;
+               
+#if 0
+       /* Pre 1.5a4 */
+       strcpy(buf+*lenp, module);
+       strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix);
+#else
+       strcpy(buf+*lenp, _PyImport_Filetab[0].suffix);
+#endif
+#ifdef USE_GUSI1
+       if ( Path2FSSpec(buf, &fss) == noErr && 
+                       FSpGetFInfo(&fss, &finfo) == noErr)
+               return _PyImport_Filetab;
+#else
+       if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr )
+               return _PyImport_Filetab;
+#endif
+       /*
+       ** We cannot check for fnfErr (unfortunately), it can mean either that
+       ** the file doesn't exist (fine, we try others) or the path leading to it.
+       */
+       refnum = fss.vRefNum;
+       dirid = fss.parID;
+       if ( refnum == 0 || dirid == 0 )        /* Fail on nonexistent dir */
+               return 0;
+       /*
+       ** We now have the folder parameters. Setup the field for the filename
+       */
+       if ( modnamelen > 54 ) return 0;        /* Leave room for extension */
+       strcpy((char *)fnbuf+1, module);
+       
+       for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) {
+               strcpy((char *)fnbuf+1+modnamelen, fdp->suffix);
+               fnbuf[0] = strlen((char *)fnbuf+1);
+               if (Py_VerboseFlag > 1)
+                       PySys_WriteStderr("# trying %s%s\n", buf, fdp->suffix);
+               if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) {
+                       /* Found it. */
+#if 0
+                       strcpy(buf+*lenp+modnamelen, fdp->suffix);
+#else
+                       strcpy(buf+*lenp, fdp->suffix);
+#endif
+                       *lenp = strlen(buf);
+                       return fdp;
+               }
+       }
+       return 0;
+}
diff --git a/Mac/Python/macmain.c b/Mac/Python/macmain.c
new file mode 100644 (file)
index 0000000..10c5a5f
--- /dev/null
@@ -0,0 +1,672 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+/* Python interpreter main program */
+
+#include "Python.h"
+#include "pythonresources.h"
+#include "import.h"
+#include "marshal.h"
+#include "macglue.h"
+
+#include <Memory.h>
+#include <Resources.h>
+#include <stdio.h>
+#include <Events.h>
+#include <Windows.h>
+#include <Fonts.h>
+#include <Balloons.h>
+#ifdef USE_APPEARANCE
+#include <Gestalt.h>
+#include <Appearance.h>
+#endif /* USE_APPEARANCE */
+#ifdef __MWERKS__
+#include <SIOUX.h>
+#define USE_SIOUX
+extern int ccommand(char ***);
+#if __profile__ == 1
+#include <profiler.h>
+#endif
+#endif
+#include <unistd.h>
+#ifdef USE_MAC_SHARED_LIBRARY
+extern PyMac_AddLibResources(void);
+#endif
+//#ifdef USE_GUSI
+//#include "GUSISIOUX.h"
+//#endif
+
+#define STARTUP "PythonStartup"
+
+#define COPYRIGHT \
+    "Type \"copyright\", \"credits\" or \"license\" for more information."
+
+
+extern int Py_DebugFlag; /* For parser.c, declared in pythonrun.c */
+extern int Py_VerboseFlag; /* For import.c, declared in pythonrun.c */
+short PyMac_AppRefNum; /* RefNum of application resource fork */
+
+/* For Py_GetArgcArgv(); set by main() */
+static char **orig_argv;
+static int  orig_argc;
+
+/* A flag which remembers whether the user has acknowledged all the console
+** output (by typing something)
+*/
+#define STATE_UNKNOWN 0
+#define STATE_LASTREAD 1
+#define STATE_LASTWRITE 2
+int console_output_state = STATE_UNKNOWN;
+
+PyMac_PrefRecord PyMac_options;
+
+static void Py_Main(int, char **); /* Forward */
+void PyMac_Exit(int); /* Forward */
+
+static void init_appearance()
+{
+#ifdef USE_APPEARANCE
+       OSErr err;
+       SInt32 response;
+
+       err = Gestalt(gestaltAppearanceAttr,&response);
+       if ( err ) goto no_appearance;
+       if ( !(response&(1<<gestaltAppearanceExists)) ) goto no_appearance;
+       /* XXXX Should we check the version? Compat-mode? */
+       PyMac_AppearanceCompliant = 1;
+no_appearance:
+       return;
+#endif /* USE_APPEARANCE */
+}
+/* Initialize the Mac toolbox world */
+
+static void
+init_mac_world()
+{
+#if !TARGET_API_MAC_CARBON
+       /* These aren't needed for carbon */
+       MaxApplZone();
+       InitGraf(&qd.thePort);
+       InitFonts();
+       InitWindows();
+       TEInit();
+       InitDialogs((long)0);
+       InitMenus();
+#endif
+       InitCursor();
+       init_appearance();
+}
+
+/*
+** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
+*/
+static void
+PyMac_InteractiveOptions(PyMac_PrefRecord *p, int *argcp, char ***argvp)
+{
+       KeyMap rmap;
+       unsigned char *map;
+       short item, type;
+       ControlHandle handle;
+       DialogPtr dialog;
+       Rect rect;
+       int old_argc = *argcp;
+       int i;
+
+       /*
+       ** If the preferences disallows interactive options we return,
+       ** similarly of <option> isn't pressed.
+       */
+       if (p->nointopt) return;
+       
+       GetKeys(rmap);
+       map = (unsigned char *)rmap;
+       if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 )    /* option key is 3a */
+               return;
+
+       dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
+       if ( dialog == NULL ) {
+               printf("Option dialog not found - cannot set options\n");
+               return;
+       }
+       SetDialogDefaultItem(dialog, OPT_OK);
+       SetDialogCancelItem(dialog, OPT_CANCEL);
+       
+       /* Set default values */
+#define SET_OPT_ITEM(num, var) \
+               GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
+               SetControlValue(handle, (short)p->var);
+
+       SET_OPT_ITEM(OPT_INSPECT, inspect);
+       SET_OPT_ITEM(OPT_VERBOSE, verbose);
+       SET_OPT_ITEM(OPT_OPTIMIZE, optimize);
+       SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
+       SET_OPT_ITEM(OPT_DEBUGGING, debugging);
+       GetDialogItem(dialog, OPT_KEEPALWAYS, &type, (Handle *)&handle, &rect);
+       SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_ALWAYS));
+       GetDialogItem(dialog, OPT_KEEPOUTPUT, &type, (Handle *)&handle, &rect);
+       SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_OUTPUT));
+       GetDialogItem(dialog, OPT_KEEPERROR, &type, (Handle *)&handle, &rect);
+       SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_ERROR));
+       GetDialogItem(dialog, OPT_KEEPNEVER, &type, (Handle *)&handle, &rect);
+       SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_NEVER));
+/*     SET_OPT_ITEM(OPT_KEEPCONSOLE, keep_console); */
+       SET_OPT_ITEM(OPT_TABWARN, tabwarn);
+       SET_OPT_ITEM(OPT_NOSITE, nosite);
+       SET_OPT_ITEM(OPT_NONAVSERV, nonavservice);
+       /* The rest are not settable interactively */
+
+#undef SET_OPT_ITEM
+       
+       while (1) {
+               handle = NULL;
+               ModalDialog(NULL, &item);
+               if ( item == OPT_OK )
+                       break;
+               if ( item == OPT_CANCEL ) {
+                       DisposeDialog(dialog);
+                       exit(0);
+               }
+#if !TARGET_API_MAC_CARBON
+               if ( item == OPT_HELP ) {
+                       HMSetBalloons(!HMGetBalloons());
+               }
+#endif
+               if ( item == OPT_CMDLINE ) {
+                       int new_argc, newer_argc;
+                       char **new_argv, **newer_argv;
+                       
+                       new_argc = ccommand(&new_argv);
+                       newer_argc = (new_argc-1) + old_argc;
+                       newer_argv = malloc((newer_argc+1)*sizeof(char *));
+                       if( !newer_argv )
+                               Py_FatalError("Cannot malloc argv\n");
+                       for(i=0; i<old_argc; i++)
+                               newer_argv[i] = (*argvp)[i];
+                       for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
+                               newer_argv[i] = new_argv[i-old_argc+1];
+                       *argvp = newer_argv;
+                       *argcp = newer_argc;
+                       
+                       /* XXXX Is it not safe to use free() here, apparently */
+               }
+#define OPT_ITEM(num, var) \
+               if ( item == (num) ) { \
+                       p->var = !p->var; \
+                       GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
+                       SetControlValue(handle, (short)p->var); \
+               }
+               
+               OPT_ITEM(OPT_INSPECT, inspect);
+               OPT_ITEM(OPT_VERBOSE, verbose);
+               OPT_ITEM(OPT_OPTIMIZE, optimize);
+               OPT_ITEM(OPT_UNBUFFERED, unbuffered);
+               OPT_ITEM(OPT_DEBUGGING, debugging);
+               if ( item == OPT_KEEPALWAYS ) p->keep_console = POPT_KEEPCONSOLE_ALWAYS;
+               if ( item == OPT_KEEPOUTPUT ) p->keep_console = POPT_KEEPCONSOLE_OUTPUT;
+               if ( item == OPT_KEEPERROR ) p->keep_console = POPT_KEEPCONSOLE_ERROR;
+               if ( item == OPT_KEEPNEVER ) p->keep_console = POPT_KEEPCONSOLE_NEVER;
+               GetDialogItem(dialog, OPT_KEEPALWAYS, &type, (Handle *)&handle, &rect);
+               SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_ALWAYS));
+               GetDialogItem(dialog, OPT_KEEPOUTPUT, &type, (Handle *)&handle, &rect);
+               SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_OUTPUT));
+               GetDialogItem(dialog, OPT_KEEPERROR, &type, (Handle *)&handle, &rect);
+               SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_ERROR));
+               GetDialogItem(dialog, OPT_KEEPNEVER, &type, (Handle *)&handle, &rect);
+               SetControlValue(handle, (short)(p->keep_console == POPT_KEEPCONSOLE_NEVER));
+               OPT_ITEM(OPT_TABWARN, tabwarn);
+               OPT_ITEM(OPT_NOSITE, nosite);
+               OPT_ITEM(OPT_NONAVSERV, nonavservice);
+               
+#undef OPT_ITEM
+       }
+       DisposeDialog(dialog);
+}
+
+/*
+** Initialization code, shared by interpreter and applets
+*/
+static void
+init_common(int *argcp, char ***argvp, int embedded)
+{
+       /* Remember resource fork refnum, for later */
+       PyMac_AppRefNum = CurResFile();
+       
+       /* Initialize toolboxes */
+       init_mac_world();
+       
+#ifdef USE_MAC_SHARED_LIBRARY
+       /* Add the shared library to the stack of resource files */
+       (void)PyMac_init_process_location();
+       PyMac_AddLibResources();
+#endif
+
+#if defined(USE_GUSI1)
+       /* Setup GUSI */
+       GUSIDefaultSetup();
+       PyMac_SetGUSISpin();
+       PyMac_SetGUSIOptions();
+#endif
+#if defined(USE_GUSI)
+       atexit(PyMac_StopGUSISpin);
+#endif 
+
+#ifdef USE_SIOUX
+       /* Set various SIOUX flags. Some are changed later based on options */
+/*     SIOUXSettings.standalone = 0;   /* XXXX Attempting to keep sioux from eating events */
+       SIOUXSettings.asktosaveonclose = 0;
+       SIOUXSettings.showstatusline = 0;
+       SIOUXSettings.tabspaces = 4;
+#endif
+
+       /* Get options from preference file (or from applet resource fork) */
+       PyMac_options.keep_console = POPT_KEEPCONSOLE_OUTPUT;           /* default-default */
+       PyMac_PreferenceOptions(&PyMac_options);
+       
+       if ( embedded ) {
+               static char *emb_argv[] = {"embedded-python", 0};
+               
+               *argcp = 1;
+               *argvp = emb_argv;
+       } else {
+               /* Create argc/argv. Do it before we go into the options event loop. */
+               *argcp = PyMac_GetArgv(argvp, PyMac_options.noargs);
+#ifndef NO_ARGV0_CHDIR
+               if (*argcp >= 1 && (*argvp)[0] && (*argvp)[0][0]) {
+                       /* Workaround for MacOS X, which currently (DP4) doesn't set
+                       ** the working folder correctly
+                       */
+                       char app_wd[256], *p;
+                       
+                       strncpy(app_wd, (*argvp)[0], 256);
+                       p = strrchr(app_wd, ':');
+                       if ( p ) *p = 0;
+                       chdir(app_wd);
+               }
+#endif
+               /* Do interactive option setting, if allowed and <option> depressed */
+               PyMac_InteractiveOptions(&PyMac_options, argcp, argvp);
+       }
+       
+       /* Copy selected options to where the machine-independent stuff wants it */
+       Py_VerboseFlag = PyMac_options.verbose;
+/*     Py_SuppressPrintingFlag = PyMac_options.suppress_print; */
+       Py_OptimizeFlag = PyMac_options.optimize;
+       Py_DebugFlag = PyMac_options.debugging;
+       Py_NoSiteFlag = PyMac_options.nosite;
+       Py_TabcheckFlag = PyMac_options.tabwarn;
+       if ( PyMac_options.noargs ) {
+               /* don't process events at all without the scripts permission */
+               PyMacSchedParams scp;
+               
+               PyMac_GetSchedParams(&scp);
+               scp.process_events = 0;
+               /* Should we disable command-dot as well? */
+               PyMac_SetSchedParams(&scp);
+       }
+       /* XXXX dispatch oldexc and nosite */
+
+       /* Set buffering */
+       if (PyMac_options.unbuffered) {
+#ifndef MPW
+               setbuf(stdout, (char *)NULL);
+               setbuf(stderr, (char *)NULL);
+#else
+               /* On MPW (3.2) unbuffered seems to hang */
+               setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
+               setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
+#endif
+       }
+#if __profile__ == 1
+       /* collectSummary or collectDetailed, timebase, #routines, max stack depth */
+       ProfilerInit(collectSummary, bestTimeBase, 8000, 250);
+#endif
+
+       /* Tell the rest of python about our argc/argv */
+       orig_argc = *argcp;     /* For Py_GetArgcArgv() */
+       orig_argv = *argvp;
+       Py_SetProgramName((*argvp)[0]);
+}
+
+/*
+** Inspection mode after script/applet termination
+*/
+static int
+run_inspect()
+{
+       int sts = 0;
+       
+       if (PyMac_options.inspect && isatty((int)fileno(stdin)))
+               sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
+       return sts;
+}
+
+/*
+** Import the macfsn module, which will override the Standard File
+** calls in the macfs builtin module by Navigation Services versions,
+** if available on this machine.
+*/
+static void
+PyMac_InstallNavServicesForSF()
+{
+       if ( !PyMac_options.nonavservice ) {
+               PyObject *m = PyImport_ImportModule("macfsn");
+               
+               if ( m == NULL ) {
+                       PySys_WriteStderr("'import macfsn' failed; ");
+                       if (Py_VerboseFlag) {
+                               PySys_WriteStderr("traceback:\n");
+                               PyErr_Print();
+                       }
+                       else {
+                               PySys_WriteStderr("use -v for traceback\n");
+                       }
+               }
+       }
+}
+
+#ifdef USE_MAC_APPLET_SUPPORT
+/* Applet support */
+
+/* Run a compiled Python Python script from 'PYC ' resource __main__ */
+static int
+run_main_resource()
+{
+       Handle h;
+       long size;
+       PyObject *code;
+       PyObject *result;
+       
+       h = GetNamedResource('PYC ', "\p__main__");
+       if (h == NULL) {
+               Alert(NOPYC_ALERT, NULL);
+               return 1;
+       }
+       size = GetResourceSizeOnDisk(h);
+       HLock(h);
+       code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
+       HUnlock(h);
+       ReleaseResource(h);
+       if (code == NULL) {
+               PyErr_Print();
+               return 1;
+       }
+       result = PyImport_ExecCodeModule("__main__", code);
+       Py_DECREF(code);
+       if (result == NULL) {
+               PyErr_Print();
+               return 1;
+       }
+       Py_DECREF(result);
+       return 0;
+}
+
+/* Initialization sequence for applets */
+void
+PyMac_InitApplet()
+{
+       int argc;
+       char **argv;
+       int err;
+
+       init_common(&argc, &argv, 0);
+       
+       Py_Initialize();
+       PyMac_InstallNavServicesForSF();
+       PySys_SetArgv(argc, argv);
+       
+       err = run_main_resource();
+       
+       err = (run_inspect() || err);
+       
+       fflush(stderr);
+       fflush(stdout);
+       PyMac_Exit(err);
+       /* XXX Should we bother to Py_Exit(sts)? */
+}
+
+/*
+** Hook for embedding python.
+*/
+void
+PyMac_Initialize()
+{
+       int argc;
+       char **argv;
+       
+       init_common(&argc, &argv, 1);
+       Py_Initialize();
+       PyMac_InstallNavServicesForSF();
+       PySys_SetArgv(argc, argv);
+}
+
+#endif /* USE_MAC_APPLET_SUPPORT */
+
+/* For normal application */
+void
+PyMac_InitApplication()
+{
+       int argc;
+       char **argv;
+       
+       init_common(&argc, &argv, 0);
+       
+       if ( argc > 1 ) {
+               /* We're running a script. Attempt to change current directory */
+               char curwd[256], *endp;
+               
+               strcpy(curwd, argv[1]);
+               endp = strrchr(curwd, ':');
+               if ( endp && endp > curwd ) {
+                       *endp = '\0';
+
+                       chdir(curwd);
+#ifdef USE_GUSI1
+                       /* Change MacOS's idea of wd too */
+                       PyMac_FixGUSIcd();
+#endif
+               }
+       }
+       Py_Main(argc, argv);
+}
+
+/* Main program */
+
+static void
+Py_Main(argc, argv)
+       int argc;
+       char **argv;
+{
+       int sts;
+       char *command = NULL;
+       char *filename = NULL;
+       FILE *fp = stdin;
+
+       filename = argv[1];
+
+       if (Py_VerboseFlag ||
+           command == NULL && filename == NULL && isatty((int)fileno(fp)))
+               fprintf(stderr, "Python %s on %s\n%s\n",
+                       Py_GetVersion(), Py_GetPlatform(), COPYRIGHT);
+       
+       if (filename != NULL) {
+               if ((fp = fopen(filename, "r")) == NULL) {
+                       fprintf(stderr, "%s: can't open file '%s'\n",
+                               argv[0], filename);
+                       PyMac_Exit(2);
+               }
+       }
+       
+       /* We initialize the menubar here, hoping SIOUX is initialized by now */
+       PyMac_InitMenuBar();
+       
+       Py_Initialize();
+       
+       PyUnicode_SetDefaultEncoding(PyMac_getscript());
+       
+       PyMac_InstallNavServicesForSF();
+
+       PySys_SetArgv(argc-1, argv+1);
+
+       if (filename == NULL && isatty((int)fileno(fp))) {
+               FILE *fp = fopen(STARTUP, "r");
+               if (fp != NULL) {
+                       (void) PyRun_SimpleFile(fp, STARTUP);
+                       PyErr_Clear();
+                       fclose(fp);
+               }
+       }
+       sts = PyRun_AnyFile(
+                       fp, filename == NULL ? "<stdin>" : filename) != 0;
+       if (filename != NULL)
+               fclose(fp);
+               
+       if ( filename != NULL || command != NULL )
+               sts = (run_inspect() || sts);
+
+       Py_Exit(sts);
+       /*NOTREACHED*/
+}
+
+/*
+** Reset the "unseen output" flag
+*/
+void
+PyMac_OutputSeen()
+{
+       if ( console_output_state == STATE_UNKNOWN )
+               PyMac_InitMenuBar();
+       console_output_state = STATE_LASTREAD;
+}
+
+/*
+** Set the "unseen output" flag
+*/
+void
+PyMac_OutputNotSeen()
+{
+       if ( console_output_state == STATE_UNKNOWN )
+               PyMac_InitMenuBar();
+       console_output_state = STATE_LASTWRITE;
+}
+
+/*
+** Override abort() - The default one is not what we want.
+*/
+void
+abort()
+{
+       console_output_state = STATE_LASTWRITE;
+       PyMac_Exit(1);
+}
+
+/*
+** Terminate application
+*/
+void
+PyMac_Exit(status)
+       int status;
+{
+       int keep = 0;
+
+#if __profile__ == 1
+       ProfilerDump("\pPython Profiler Results");
+       ProfilerTerm();
+#endif 
+               
+#ifdef USE_SIOUX
+       switch (PyMac_options.keep_console) {
+       case POPT_KEEPCONSOLE_NEVER:
+               keep = 0;
+               break;
+       case POPT_KEEPCONSOLE_OUTPUT:
+               if (console_output_state == STATE_LASTWRITE ||
+                               console_output_state == STATE_UNKNOWN )
+                       keep = 1;
+               else
+                       keep = 0;
+               break;
+       case POPT_KEEPCONSOLE_ERROR:
+               keep = (status != 0);
+               break;
+       default:
+               keep = 1;
+       }
+       if (keep) {
+               SIOUXSettings.standalone = 1;
+               SIOUXSettings.autocloseonquit = 0;
+               SIOUXSetTitle("\p\307terminated\310");
+               PyMac_RaiseConsoleWindow();
+               PyMac_RestoreMenuBar();
+#ifdef USE_MSL
+               /*
+               ** Temporary workaround: autocloseonquit clearing does not
+               ** currently work for the MSL/GUSI combo.
+               */
+               while(getchar() > 0);
+#endif
+       }
+       else
+               SIOUXSettings.autocloseonquit = 1;
+#endif /* USE_SIOUX */
+
+       exit(status);
+}
+
+/* Return the program name -- some code out there needs this. */
+char *
+Py_GetProgramFullPath()
+{
+       return orig_argv[0];
+}
+
+
+/* Make the *original* argc/argv available to other modules.
+   This is rare, but it is needed by the secureware extension. */
+
+void
+Py_GetArgcArgv(int *argc,char ***argv)
+{
+       *argc = orig_argc;
+       *argv = orig_argv;
+}
+
+/* More cruft that shouldn't really be here, used in sysmodule.c */
+
+char *
+Py_GetPrefix()
+{
+       return PyMac_GetPythonDir();
+}
+
+char *
+Py_GetExecPrefix()
+{
+       return PyMac_GetPythonDir();
+}
+
+int
+PyMac_GetDelayConsoleFlag()
+{
+       return (int)PyMac_options.delayconsole;
+}
\ No newline at end of file
diff --git a/Mac/Resources/dialogs.rsrc b/Mac/Resources/dialogs.rsrc
new file mode 100644 (file)
index 0000000..52efd23
Binary files /dev/null and b/Mac/Resources/dialogs.rsrc differ
diff --git a/Mac/Tools/IDE/MacPrefs.py b/Mac/Tools/IDE/MacPrefs.py
new file mode 100644 (file)
index 0000000..b1fa7ca
--- /dev/null
@@ -0,0 +1,108 @@
+import macfs
+import marshal
+import types
+
+from MACFS import kOnSystemDisk
+
+class PrefObject:
+       
+       def __init__(self, dict = None):
+               if dict == None:
+                       self._prefsdict = {}
+               else:
+                       self._prefsdict = dict
+       
+       def __len__(self):
+               return len(self._prefsdict)
+       
+       def __delattr__(self, attr):
+               if self._prefsdict.has_key(attr):
+                       del self._prefsdict[attr]
+               else:
+                       raise AttributeError, 'delete non-existing instance attribute'
+       
+       def __getattr__(self, attr):
+               if attr == '__members__':
+                       keys = self._prefsdict.keys()
+                       keys.sort()
+                       return keys
+               try:
+                       return self._prefsdict[attr]
+               except KeyError:
+                       raise AttributeError, attr
+       
+       def __setattr__(self, attr, value):
+               if attr[0] <> '_':
+                       self._prefsdict[attr] = value
+               else:
+                       self.__dict__[attr] = value
+       
+       def getprefsdict(self):
+               return self._prefsdict
+
+
+class PrefFile(PrefObject):
+       
+       def __init__(self, path, creator = 'Pyth'):
+               # Find the preferences folder and our prefs file, create if needed.
+               self.__path = path
+               self.__creator = creator
+               self._prefsdict = {}
+               try:
+                       prefdict = marshal.load(open(self.__path, 'rb'))
+               except (IOError, ValueError):
+                       # file not found, or currupt marshal data
+                       pass
+               else:
+                       for key, value in prefdict.items():
+                               if type(value) == types.DictType:
+                                       self._prefsdict[key] = PrefObject(value)
+                               else:
+                                       self._prefsdict[key] = value
+       
+       def save(self):
+               prefdict = {}
+               for key, value in self._prefsdict.items():
+                       if type(value) == types.InstanceType:
+                               prefdict[key] = value.getprefsdict()
+                               if not prefdict[key]:
+                                       del prefdict[key]
+                       else:
+                               prefdict[key] = value
+               marshal.dump(prefdict, open(self.__path, 'wb'))
+               fss = macfs.FSSpec(self.__path)
+               fss.SetCreatorType(self.__creator, 'pref')
+       
+       def __getattr__(self, attr):
+               if attr == '__members__':
+                       keys = self._prefsdict.keys()
+                       keys.sort()
+                       return keys
+               try:
+                       return self._prefsdict[attr]
+               except KeyError:
+                       if attr[0] <> '_':
+                               self._prefsdict[attr] = PrefObject()
+                               return self._prefsdict[attr]
+                       else:
+                               raise AttributeError, attr
+
+
+_prefscache = {}
+
+def GetPrefs(prefname, creator = 'Pyth'):
+       import macostools, os
+       if _prefscache.has_key(prefname):
+               return _prefscache[prefname]
+       # Find the preferences folder and our prefs file, create if needed.
+       vrefnum, dirid = macfs.FindFolder(kOnSystemDisk, 'pref', 0)
+       prefsfolder_fss = macfs.FSSpec((vrefnum, dirid, ''))
+       prefsfolder = prefsfolder_fss.as_pathname()
+       path = os.path.join(prefsfolder, prefname)
+       head, tail = os.path.split(path)
+       # make sure the folder(s) exist
+       macostools.mkdirs(head)
+       
+       preffile = PrefFile(path, creator)
+       _prefscache[prefname] = preffile
+       return preffile
diff --git a/Mac/Tools/IDE/PyBrowser.py b/Mac/Tools/IDE/PyBrowser.py
new file mode 100644 (file)
index 0000000..c8e5066
--- /dev/null
@@ -0,0 +1,442 @@
+import W
+import Wkeys
+import struct
+import string
+import types
+import re
+
+nullid = '\0\0'
+closedid = struct.pack('h', 468)
+openid = struct.pack('h', 469)
+closedsolidid = struct.pack('h', 470)
+opensolidid = struct.pack('h', 471)
+
+arrows = (nullid, closedid, openid, closedsolidid, opensolidid)
+
+has_ctlcharsRE = re.compile(r'[\000-\037\177-\377]')
+def ctlcharsREsearch(str):
+       if has_ctlcharsRE.search(str) is None:
+               return -1
+       return 1
+       
+def double_repr(key, value, truncvalue = 0, 
+                       type = type, StringType = types.StringType,
+                       has_ctlchars = ctlcharsREsearch, _repr = repr, str = str):
+       if type(key) == StringType and has_ctlchars(key) < 0:
+               key = str(key)
+       else:
+               key = _repr(key)
+       if key == '__builtins__':
+               value = "<" + type(value).__name__ + " '__builtin__'>"
+       elif key == '__return__':
+               # bleh, when returning from a class codeblock we get infinite recursion in repr. 
+               # Use safe repr instead.
+               import repr
+               value = repr.repr(value)
+       else:
+               try:
+                       value = _repr(value)
+                       '' + value      # test to see if it is a string, in case a __repr__ method is buggy
+               except:
+                       value = '\xa5\xa5\xa5 exception in repr()'
+       if truncvalue:
+               return key + '\t' + value[:255]
+       return key + '\t' + value
+
+
+class BrowserWidget(W.List):
+       
+       LDEF_ID = 471
+       
+       def __init__(self, possize, object = None, col = 100, closechildren = 0):
+               W.List.__init__(self, possize, callback = self.listhit)
+               self.object = (None,)
+               self.indent = 16
+               self.lastmaxindent = 0
+               self.closechildren = closechildren
+               self.children = []
+               self.mincol = 64
+               self.setcolumn(col)
+               self.bind('return', self.openselection)
+               self.bind('enter', self.openselection)
+               if object is not None:
+                       self.set(object)
+       
+       def set(self, object):
+               if self.object[0] is not object:
+                       self.object = object,
+                       self[:] = self.unpack(object, 0)
+               elif self._parentwindow is not None and self._parentwindow.wid:
+                       self.update()
+       
+       def unpack(self, object, indent):
+               return unpack_object(object, indent)
+       
+       def update(self):
+               # for now...
+               W.SetCursor('watch')
+               self.setdrawingmode(0)
+               sel = self.getselectedobjects()
+               fold = self.getunfoldedobjects()
+               topcell = self.gettopcell()
+               self[:] = self.unpack(self.object[0], 0)
+               self.unfoldobjects(fold)
+               self.setselectedobjects(sel)
+               self.settopcell(topcell)
+               self.setdrawingmode(1)
+       
+       def setcolumn(self, col):
+               self.col = col
+               self.colstr = struct.pack('h', col)
+               if self._list:
+                       sel = self.getselection()
+                       self.setitems(self.items)
+                       self.setselection(sel)
+       
+       def key(self, char, event):
+               if char in (Wkeys.leftarrowkey, Wkeys.rightarrowkey):
+                       sel = self.getselection()
+                       sel.reverse()
+                       self.setdrawingmode(0)
+                       for index in sel:
+                               self.fold(index, char == Wkeys.rightarrowkey)
+                       self.setdrawingmode(1)
+               else:
+                       W.List.key(self, char, event)
+       
+       def rollover(self, (x, y), onoff):
+               if onoff:
+                       if self.incolumn((x, y)):
+                               W.SetCursor('hmover')
+                       else:
+                               W.SetCursor('arrow')
+       
+       def inarrow(self, (x, y)):
+               cl, ct, cr, cb = self._list.LRect((0, 0))
+               l, t, r, b = self._bounds
+               if (x - cl) < 16:
+                       cellheight = cb - ct
+                       index = (y - ct) / cellheight
+                       if index < len(self.items):
+                               return 1, index
+               return None, None
+       
+       def incolumn(self, (x, y)):
+               l, t, r, b = self._list.LRect((0, 0))
+               abscol = l + self.col
+               return abs(abscol - x) < 3
+       
+       def trackcolumn(self, (x, y)):
+               import Qd, QuickDraw, Evt
+               self.SetPort()
+               l, t, r, b = self._bounds
+               bounds = l, t, r, b = l + 1, t + 1, r - 16, b - 1
+               abscol = l + self.col
+               mincol = l + self.mincol
+               maxcol = r - 10
+               diff = abscol - x
+               Qd.PenPat('\000\377\000\377\000\377\000\377')
+               Qd.PenMode(QuickDraw.srcXor)
+               rect = abscol - 1, t, abscol, b
+               Qd.PaintRect(rect)
+               lastpoint = (x, y)
+               newcol = -1
+               #W.SetCursor('fist')
+               while Evt.Button():
+                       (x, y) = Evt.GetMouse()
+                       if (x, y) <> lastpoint:
+                               newcol = x + diff
+                               newcol = max(newcol, mincol)
+                               newcol = min(newcol, maxcol)
+                               Qd.PaintRect(rect)
+                               rect = newcol - 1, t, newcol, b
+                               Qd.PaintRect(rect)
+                               lastpoint = (x, y)
+               Qd.PaintRect(rect)
+               Qd.PenPat(Qd.qd.black)
+               Qd.PenNormal()
+               if newcol > 0 and newcol <> abscol:
+                       self.setcolumn(newcol - l)
+       
+       def click(self, point, modifiers):
+               if point == (-1, -1):   # gross.
+                       W.List.click(self, point ,modifiers)
+                       return
+               hit, index = self.inarrow(point)
+               if hit:
+                       (key, value, arrow, indent) = self.items[index]
+                       self.fold(index, arrow == 1)
+               elif self.incolumn(point):
+                       self.trackcolumn(point)
+               else:
+                       W.List.click(self, point, modifiers)
+       
+       # for W.List.key
+       def findmatch(self, tag):
+               lower = string.lower
+               items = self.items
+               taglen = len(tag)
+               match = '\377' * 100
+               match_i = -1
+               for i in range(len(items)):
+                       item = lower(str(items[i][0]))
+                       if tag <= item < match:
+                               match = item
+                               match_i = i
+               if match_i >= 0:
+                       return match_i
+               else:
+                       return len(items) - 1
+       
+       def close(self):
+               if self.closechildren:
+                       for window in self.children:
+                               window.close()
+               self.children = []
+               W.List.close(self)
+       
+       def fold(self, index, onoff):
+               (key, value, arrow, indent) = self.items[index]
+               if arrow == 0 or (onoff and arrow == 2) or (not onoff and arrow == 1):
+                       return
+               W.SetCursor('watch')
+               topcell = self.gettopcell()
+               if onoff:
+                       self[index] = (key, value, 4, indent)
+                       self.setdrawingmode(0)
+                       self[index+1:index+1] = self.unpack(value, indent + 1)
+                       self[index] = (key, value, 2, indent)
+               else:
+                       self[index] = (key, value, 3, indent)
+                       self.setdrawingmode(0)
+                       count = 0
+                       for i in range(index + 1, len(self.items)):
+                               (dummy, dummy, dummy, subindent) = self.items[i]
+                               if subindent <= indent:
+                                       break
+                               count = count + 1
+                       self[index+1:index+1+count] = []
+                       self[index] = (key, value, 1, indent)
+               maxindent = self.getmaxindent()
+               if maxindent <> self.lastmaxindent:
+                       newabsindent = self.col + (maxindent - self.lastmaxindent) * self.indent
+                       if newabsindent >= self.mincol:
+                               self.setcolumn(newabsindent)
+                       self.lastmaxindent = maxindent
+               self.settopcell(topcell)
+               self.setdrawingmode(1)
+       
+       def unfoldobjects(self, objects):
+               for obj in objects:
+                       try:
+                               index = self.items.index(obj)
+                       except ValueError:
+                               pass
+                       else:
+                               self.fold(index, 1)
+       
+       def getunfoldedobjects(self):
+               curindent = 0
+               objects = []
+               for index in range(len(self.items)):
+                       (key, value, arrow, indent) = self.items[index]
+                       if indent > curindent:
+                               (k, v, a, i) = self.items[index - 1]
+                               objects.append((k, v, 1, i))
+                               curindent = indent
+                       elif indent < curindent:
+                               curindent = indent
+               return objects
+       
+       def listhit(self, isdbl):
+               if isdbl:
+                       self.openselection()
+       
+       def openselection(self):
+               import os
+               sel = self.getselection()
+               for index in sel:
+                       (key, value, arrow, indent) = self[index]
+                       if arrow:
+                               self.children.append(Browser(value))
+                       elif type(value) == types.StringType and '\0' not in value:
+                               editor = self._parentwindow.parent.getscript(value)
+                               if editor:
+                                       editor.select()
+                                       return
+                               elif os.path.exists(value) and os.path.isfile(value):
+                                       import macfs
+                                       fss = macfs.FSSpec(value)
+                                       if fss.GetCreatorType()[1] == 'TEXT':
+                                               W.getapplication().openscript(value)
+       
+       def itemrepr(self, (key, value, arrow, indent), str = str, double_repr = double_repr, 
+                       arrows = arrows, pack = struct.pack):
+               arrow = arrows[arrow]
+               return arrow + pack('h', self.indent * indent) + self.colstr + \
+                               double_repr(key, value, 1)
+       
+       def getmaxindent(self, max = max):
+               maxindent = 0
+               for item in self.items:
+                       maxindent = max(maxindent, item[3])
+               return maxindent
+       
+       def domenu_copy(self, *args):
+               sel = self.getselectedobjects()
+               selitems = []
+               for key, value, dummy, dummy in sel:
+                       selitems.append(double_repr(key, value))
+               text = string.join(selitems, '\r')
+               if text:
+                       import Scrap
+                       Scrap.ZeroScrap()
+                       Scrap.PutScrap('TEXT', text)
+
+
+class Browser:
+       
+       def __init__(self, object = None, title = None, closechildren = 0):
+               if hasattr(object, '__name__'):
+                       name = object.__name__
+               else:
+                       name = ''
+               if title is None:
+                       title = 'Object browser'
+                       if name:
+                               title = title + ': ' + name
+               self.w = w = W.Window((300, 400), title, minsize = (100, 100))
+               w.info = W.TextBox((18, 8, -70, 15))
+               w.updatebutton = W.Button((-64, 4, 50, 16), 'Update', self.update)
+               w.browser = BrowserWidget((-1, 24, 1, -14), None)
+               w.bind('cmdu', w.updatebutton.push)
+               w.open()
+               self.set(object, name)
+       
+       def close(self):
+               if self.w.wid:
+                       self.w.close()
+       
+       def set(self, object, name = ''):
+               W.SetCursor('watch')
+               tp = type(object).__name__
+               try:
+                       length = len(object)
+               except:
+                       length = -1
+               if not name and hasattr(object, '__name__'):
+                       name = object.__name__
+               if name:
+                       info = name + ': ' + tp
+               else:
+                       info = tp
+               if length >= 0:
+                       if length == 1:
+                               info = info + ' (%d element)' % length
+                       else:
+                               info = info + ' (%d elements)' % length
+               self.w.info.set(info)
+               self.w.browser.set(object)
+       
+       def update(self):
+               self.w.browser.update()
+
+
+SIMPLE_TYPES = (
+       types.NoneType,
+       types.IntType,
+       types.LongType,
+       types.FloatType,
+       types.ComplexType,
+       types.StringType
+)
+
+INDEXING_TYPES = (
+       types.TupleType,
+       types.ListType,
+       types.DictionaryType
+)
+
+def unpack_object(object, indent = 0):
+       tp = type(object)
+       if tp in SIMPLE_TYPES and tp is not types.NoneType:
+               raise TypeError, "can't browse simple type: %s" % tp.__name__
+       elif tp == types.DictionaryType:
+               return unpack_dict(object, indent)
+       elif tp in (types.TupleType, types.ListType):
+               return unpack_sequence(object, indent)
+       elif tp == types.InstanceType:
+               return unpack_instance(object, indent)
+       elif tp == types.ClassType:
+               return unpack_class(object, indent)
+       elif tp == types.ModuleType:
+               return unpack_dict(object.__dict__, indent)
+       else:
+               return unpack_other(object, indent)
+
+def unpack_sequence(seq, indent = 0):
+       items = map(None, range(len(seq)), seq)
+       items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent: 
+                               (k, v, not type(v) in simp, indent), items)
+       return items
+
+def unpack_dict(dict, indent = 0):
+       items = dict.items()
+       return pack_items(items, indent)
+
+def unpack_instance(inst, indent = 0):
+       if hasattr(inst, '__pybrowse_unpack__'):
+               return unpack_object(inst.__pybrowse_unpack__(), indent)
+       else:
+               items = [('__class__', inst.__class__)] + inst.__dict__.items()
+               return pack_items(items, indent)
+
+def unpack_class(clss, indent = 0):
+       items = [('__bases__', clss.__bases__), ('__name__', clss.__name__)] + clss.__dict__.items()
+       return pack_items(items, indent)
+
+def unpack_other(object, indent = 0):
+       attrs = []
+       if hasattr(object, '__members__'):
+               attrs = attrs + object.__members__
+       if hasattr(object, '__methods__'):
+               attrs = attrs + object.__methods__
+       items = []
+       for attr in attrs:
+               items.append((attr, getattr(object, attr)))
+       return pack_items(items, indent)
+
+def pack_items(items, indent = 0):
+       items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent: 
+                               (k, v, not type(v) in simp, indent), 
+                       items)
+       return tuple_caselesssort(items)
+
+def caselesssort(alist):
+       """Return a sorted copy of a list. If there are only strings in the list, 
+       it will not consider case"""
+       
+       try:
+               # turn ['FOO',  'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible
+               tupledlist = map(lambda item, lower = string.lower: (lower(item), item), alist)
+       except TypeError:
+               # at least one element in alist is not a string, proceed the normal way...
+               alist = alist[:]
+               alist.sort()
+               return alist
+       else:
+               tupledlist.sort()
+               # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO']
+               return map(lambda x: x[1], tupledlist)
+
+def tuple_caselesssort(items):
+       try:
+               tupledlist = map(lambda tuple, lower = string.lower: (lower(tuple[0]), tuple), items)
+       except (AttributeError, TypeError):
+               items = items[:]
+               items.sort()
+               return items
+       else:
+               tupledlist.sort()
+               return map(lambda (low, tuple): tuple, tupledlist)
+
diff --git a/Mac/Tools/IDE/PyEdit.py b/Mac/Tools/IDE/PyEdit.py
new file mode 100644 (file)
index 0000000..10f583f
--- /dev/null
@@ -0,0 +1,1305 @@
+"""A (less & less) simple Python editor"""
+
+import W
+import Wtraceback
+from Wkeys import *
+
+import macfs
+import MACFS
+import MacOS
+import Win
+import Res
+import Evt
+import os
+import imp
+import sys
+import string
+import marshal
+import re
+
+try:
+       import Wthreading
+except ImportError:
+       haveThreading = 0
+else:
+       haveThreading = Wthreading.haveThreading
+
+_scriptuntitledcounter = 1
+# _wordchars = string.letters + string.digits + "_"
+_wordchars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
+
+
+runButtonLabels = ["Run all", "Stop!"]
+runSelButtonLabels = ["Run selection", "Pause!", "Resume"]
+
+
+class Editor(W.Window):
+       
+       def __init__(self, path = "", title = ""):
+               defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
+               global _scriptuntitledcounter
+               if not path:
+                       if title:
+                               self.title = title
+                       else:
+                               self.title = "Untitled Script " + `_scriptuntitledcounter`
+                               _scriptuntitledcounter = _scriptuntitledcounter + 1
+                       text = ""
+                       self._creator = W._signature
+               elif os.path.exists(path):
+                       path = resolvealiases(path)
+                       dir, name = os.path.split(path)
+                       self.title = name
+                       f = open(path, "rb")
+                       text = f.read()
+                       f.close()
+                       fss = macfs.FSSpec(path)
+                       self._creator, filetype = fss.GetCreatorType()
+               else:
+                       raise IOError, "file '%s' does not exist" % path
+               self.path = path
+               
+               if '\n' in text:
+                       import EasyDialogs
+                       if string.find(text, '\r\n') >= 0:
+                               sourceOS = 'DOS'
+                               searchString = '\r\n'
+                       else:
+                               sourceOS = 'UNIX'
+                               searchString = '\n'
+                       change = EasyDialogs.AskYesNoCancel('"%s" contains %s-style line feeds. '
+                                       'Change them to MacOS carriage returns?' % (self.title, sourceOS), 1)
+                       # bug: Cancel is treated as No
+                       if change > 0:
+                               text = string.replace(text, searchString, '\r')
+               else:
+                       change = 0
+               
+               self.settings = {}
+               if self.path:
+                       self.readwindowsettings()
+               if self.settings.has_key("windowbounds"):
+                       bounds = self.settings["windowbounds"]
+               else:
+                       bounds = defaultwindowsize
+               if self.settings.has_key("fontsettings"):
+                       self.fontsettings = self.settings["fontsettings"]
+               else:
+                       self.fontsettings = defaultfontsettings
+               if self.settings.has_key("tabsize"):
+                       try:
+                               self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
+                       except:
+                               self.tabsettings = defaulttabsettings
+               else:
+                       self.tabsettings = defaulttabsettings
+               
+               W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
+               self.setupwidgets(text)
+               if change > 0:
+                       self.editgroup.editor.changed = 1
+               
+               if self.settings.has_key("selection"):
+                       selstart, selend = self.settings["selection"]
+                       self.setselection(selstart, selend)
+               self.open()
+               self.setinfotext()
+               self.globals = {}
+               self._buf = ""  # for write method
+               self.debugging = 0
+               self.profiling = 0
+               if self.settings.has_key("run_as_main"):
+                       self.run_as_main = self.settings["run_as_main"]
+               else:
+                       self.run_as_main = 0
+               if self.settings.has_key("run_with_interpreter"):
+                       self.run_with_interpreter = self.settings["run_with_interpreter"]
+               else:
+                       self.run_with_interpreter = 0
+               self._threadstate = (0, 0)
+               self._thread = None
+       
+       def readwindowsettings(self):
+               try:
+                       resref = Res.FSpOpenResFile(self.path, 1)
+               except Res.Error:
+                       return
+               try:
+                       Res.UseResFile(resref)
+                       data = Res.Get1Resource('PyWS', 128)
+                       self.settings = marshal.loads(data.data)
+               except:
+                       pass
+               Res.CloseResFile(resref)
+               
+       def writewindowsettings(self):
+               try:
+                       resref = Res.FSpOpenResFile(self.path, 3)
+               except Res.Error:
+                       Res.FSpCreateResFile(self.path, self._creator, 'TEXT', MACFS.smAllScripts)
+                       resref = Res.FSpOpenResFile(self.path, 3)
+               try:
+                       data = Res.Resource(marshal.dumps(self.settings))
+                       Res.UseResFile(resref)
+                       try:
+                               temp = Res.Get1Resource('PyWS', 128)
+                               temp.RemoveResource()
+                       except Res.Error:
+                               pass
+                       data.AddResource('PyWS', 128, "window settings")
+               finally:
+                       Res.UpdateResFile(resref)
+                       Res.CloseResFile(resref)
+       
+       def getsettings(self):
+               self.settings = {}
+               self.settings["windowbounds"] = self.getbounds()
+               self.settings["selection"] = self.getselection()
+               self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
+               self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
+               self.settings["run_as_main"] = self.run_as_main
+               self.settings["run_with_interpreter"] = self.run_with_interpreter
+       
+       def get(self):
+               return self.editgroup.editor.get()
+       
+       def getselection(self):
+               return self.editgroup.editor.ted.WEGetSelection()
+       
+       def setselection(self, selstart, selend):
+               self.editgroup.editor.setselection(selstart, selend)
+       
+       def getfilename(self):
+               if self.path:
+                       return self.path
+               return '<%s>' % self.title
+       
+       def setupwidgets(self, text):
+               topbarheight = 24
+               popfieldwidth = 80
+               self.lastlineno = None
+               
+               # make an editor
+               self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
+               editor = W.PyEditor((0, 0, -15,-15), text, 
+                               fontsettings = self.fontsettings, 
+                               tabsettings = self.tabsettings,
+                               file = self.getfilename())
+               
+               # make the widgets
+               self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
+               self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
+               self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
+               self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
+               self.editgroup.editor = editor  # add editor *after* scrollbars
+               
+               self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
+               self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
+               
+               self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
+               self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
+               self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
+               self.runbutton = W.Button((5, 4, 80, 16), runButtonLabels[0], self.run)
+               self.runselbutton = W.Button((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
+               
+               # bind some keys
+               editor.bind("cmdr", self.runbutton.push)
+               editor.bind("enter", self.runselbutton.push)
+               editor.bind("cmdj", self.domenu_gotoline)
+               editor.bind("cmdd", self.domenu_toggledebugger)
+               editor.bind("<idle>", self.updateselection)
+               
+               editor.bind("cmde", searchengine.setfindstring)
+               editor.bind("cmdf", searchengine.show)
+               editor.bind("cmdg", searchengine.findnext)
+               editor.bind("cmdshiftr", searchengine.replace)
+               editor.bind("cmdt", searchengine.replacefind)
+               
+               self.linefield.bind("return", self.dolinefield)
+               self.linefield.bind("enter", self.dolinefield)
+               self.linefield.bind("tab", self.dolinefield)
+               
+               # intercept clicks
+               editor.bind("<click>", self.clickeditor)
+               self.linefield.bind("<click>", self.clicklinefield)
+       
+       def makeoptionsmenu(self):
+               menuitems = [('Font settings\xc9', self.domenu_fontsettings), 
+                               ("Save options\xc9", self.domenu_options),
+                               '-',
+                               ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main), 
+                               #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_toggle_run_with_interpreter), 
+                               #'-',
+                               ('Modularize', self.domenu_modularize),
+                               ('Browse namespace\xc9', self.domenu_browsenamespace), 
+                               '-']
+               if self.profiling:
+                       menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
+               else:
+                       menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
+               if self.editgroup.editor._debugger:
+                       menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
+                               ('Clear breakpoints', self.domenu_clearbreakpoints),
+                               ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
+               else:
+                       menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
+               self.editgroup.optionsmenu.set(menuitems)
+       
+       def domenu_toggle_run_as_main(self):
+               self.run_as_main = not self.run_as_main
+               self.run_with_interpreter = 0
+               self.editgroup.editor.selchanged = 1
+       
+       def domenu_toggle_run_with_interpreter(self):
+               self.run_with_interpreter = not self.run_with_interpreter
+               self.run_as_main = 0
+               self.editgroup.editor.selchanged = 1
+       
+       def showbreakpoints(self, onoff):
+               self.editgroup.editor.showbreakpoints(onoff)
+               self.debugging = onoff
+       
+       def domenu_clearbreakpoints(self, *args):
+               self.editgroup.editor.clearbreakpoints()
+       
+       def domenu_editbreakpoints(self, *args):
+               self.editgroup.editor.editbreakpoints()
+       
+       def domenu_toggledebugger(self, *args):
+               if not self.debugging:
+                       W.SetCursor('watch')
+               self.debugging = not self.debugging
+               self.editgroup.editor.togglebreakpoints()
+               
+       def domenu_toggleprofiler(self, *args):
+               self.profiling = not self.profiling
+       
+       def domenu_browsenamespace(self, *args):
+               import PyBrowser, W
+               W.SetCursor('watch')
+               globals, file, modname = self.getenvironment()
+               if not modname:
+                       modname = self.title
+               PyBrowser.Browser(globals, "Object browser: " + modname)
+       
+       def domenu_modularize(self, *args):
+               modname = _filename_as_modname(self.title)
+               if not modname:
+                       raise W.AlertError, "Can't modularize \"%s\"" % self.title
+               run_as_main = self.run_as_main
+               self.run_as_main = 0
+               self.run()
+               self.run_as_main = run_as_main
+               if self.path:
+                       file = self.path
+               else:
+                       file = self.title
+               
+               if self.globals and not sys.modules.has_key(modname):
+                       module = imp.new_module(modname)
+                       for attr in self.globals.keys():
+                               setattr(module,attr,self.globals[attr])
+                       sys.modules[modname] = module
+                       self.globals = {}
+       
+       def domenu_fontsettings(self, *args):
+               import FontSettings
+               fontsettings = self.editgroup.editor.getfontsettings()
+               tabsettings = self.editgroup.editor.gettabsettings()
+               settings = FontSettings.FontDialog(fontsettings, tabsettings)
+               if settings:
+                       fontsettings, tabsettings = settings
+                       self.editgroup.editor.setfontsettings(fontsettings)
+                       self.editgroup.editor.settabsettings(tabsettings)
+       
+       def domenu_options(self, *args):
+               rv = SaveOptions(self._creator)
+               if rv:
+                       self.editgroup.editor.selchanged = 1 # ouch...
+                       self._creator = rv
+       
+       def clicklinefield(self):
+               if self._currentwidget <> self.linefield:
+                       self.linefield.select(1)
+                       self.linefield.selectall()
+                       return 1
+       
+       def clickeditor(self):
+               if self._currentwidget <> self.editgroup.editor:
+                       self.dolinefield()
+                       return 1
+       
+       def updateselection(self, force = 0):
+               sel = min(self.editgroup.editor.getselection())
+               lineno = self.editgroup.editor.offsettoline(sel)
+               if lineno <> self.lastlineno or force:
+                       self.lastlineno = lineno
+                       self.linefield.set(str(lineno + 1))
+                       self.linefield.selview()
+       
+       def dolinefield(self):
+               try:
+                       lineno = string.atoi(self.linefield.get()) - 1
+                       if lineno <> self.lastlineno:
+                               self.editgroup.editor.selectline(lineno)
+                               self.updateselection(1)
+               except:
+                       self.updateselection(1)
+               self.editgroup.editor.select(1)
+       
+       def setinfotext(self):
+               if not hasattr(self, 'infotext'):
+                       return
+               if self.path:
+                       self.infotext.set(self.path)
+               else:
+                       self.infotext.set("")
+       
+       def close(self):
+               if self.editgroup.editor.changed:
+                       import EasyDialogs
+                       import Qd
+                       Qd.InitCursor()
+                       save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
+                                       default=1, no="Don\xd5t save")
+                       if save > 0:
+                               if self.domenu_save():
+                                       return 1
+                       elif save < 0:
+                               return 1
+               self.globals = None
+               W.Window.close(self)
+       
+       def domenu_close(self, *args):
+               return self.close()
+       
+       def domenu_save(self, *args):
+               if not self.path:
+                       # Will call us recursively
+                       return self.domenu_save_as()
+               data = self.editgroup.editor.get()
+               fp = open(self.path, 'wb')  # open file in binary mode, data has '\r' line-endings
+               fp.write(data)
+               fp.close()
+               fss = macfs.FSSpec(self.path)
+               fss.SetCreatorType(self._creator, 'TEXT')
+               self.getsettings()
+               self.writewindowsettings()
+               self.editgroup.editor.changed = 0
+               self.editgroup.editor.selchanged = 0
+               import linecache
+               if linecache.cache.has_key(self.path):
+                       del linecache.cache[self.path]
+               import macostools
+               macostools.touched(self.path)
+       
+       def can_save(self, menuitem):
+               return self.editgroup.editor.changed or self.editgroup.editor.selchanged
+       
+       def domenu_save_as(self, *args):
+               fss, ok = macfs.StandardPutFile('Save as:', self.title)
+               if not ok: 
+                       return 1
+               self.showbreakpoints(0)
+               self.path = fss.as_pathname()
+               self.setinfotext()
+               self.title = os.path.split(self.path)[-1]
+               self.wid.SetWTitle(self.title)
+               self.domenu_save()
+               self.editgroup.editor.setfile(self.getfilename())
+               app = W.getapplication()
+               app.makeopenwindowsmenu()
+               if hasattr(app, 'makescriptsmenu'):
+                       app = W.getapplication()
+                       fss, fss_changed = app.scriptsfolder.Resolve()
+                       path = fss.as_pathname()
+                       if path == self.path[:len(path)]:
+                               W.getapplication().makescriptsmenu()
+       
+       def domenu_save_as_applet(self, *args):
+               import buildtools
+               
+               buildtools.DEBUG = 0    # ouch.
+               
+               if self.title[-3:] == ".py":
+                       destname = self.title[:-3]
+               else:
+                       destname = self.title + ".applet"
+               fss, ok = macfs.StandardPutFile('Save as Applet:', destname)
+               if not ok: 
+                       return 1
+               W.SetCursor("watch")
+               destname = fss.as_pathname()
+               if self.path:
+                       filename = self.path
+                       if filename[-3:] == ".py":
+                               rsrcname = filename[:-3] + '.rsrc'
+                       else:
+                               rsrcname = filename + '.rsrc'
+               else:
+                       filename = self.title
+                       rsrcname = ""
+               
+               pytext = self.editgroup.editor.get()
+               pytext = string.split(pytext, '\r')
+               pytext = string.join(pytext, '\n') + '\n'
+               try:
+                       code = compile(pytext, filename, "exec")
+               except (SyntaxError, EOFError):
+                       raise buildtools.BuildError, "Syntax error in script %s" % `filename`
+               
+               # Try removing the output file
+               try:
+                       os.remove(destname)
+               except os.error:
+                       pass
+               template = buildtools.findtemplate()
+               buildtools.process_common(template, None, code, rsrcname, destname, 0, 1)
+       
+       def domenu_gotoline(self, *args):
+               self.linefield.selectall()
+               self.linefield.select(1)
+               self.linefield.selectall()
+       
+       def domenu_selectline(self, *args):
+               self.editgroup.editor.expandselection()
+       
+       def domenu_find(self, *args):
+               searchengine.show()
+       
+       def domenu_entersearchstring(self, *args):
+               searchengine.setfindstring()
+       
+       def domenu_replace(self, *args):
+               searchengine.replace()
+       
+       def domenu_findnext(self, *args):
+               searchengine.findnext()
+       
+       def domenu_replacefind(self, *args):
+               searchengine.replacefind()
+       
+       def domenu_run(self, *args):
+               self.runbutton.push()
+       
+       def domenu_runselection(self, *args):
+               self.runselbutton.push()
+       
+       def run(self):
+               if self._threadstate == (0, 0):
+                       self._run()
+               else:
+                       lock = Wthreading.Lock()
+                       lock.acquire()
+                       self._thread.postException(KeyboardInterrupt)
+                       if self._thread.isBlocked():
+                               self._thread.start()
+                       lock.release()
+       
+       def _run(self):
+               if self.run_with_interpreter:
+                       if self.editgroup.editor.changed:
+                               import EasyDialogs
+                               import Qd; Qd.InitCursor()
+                               save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
+                               if save > 0:
+                                       if self.domenu_save():
+                                               return
+                               elif save < 0:
+                                       return
+                       if not self.path:
+                               raise W.AlertError, "Can't run unsaved file"
+                       self._run_with_interpreter()
+               else:
+                       pytext = self.editgroup.editor.get()
+                       globals, file, modname = self.getenvironment()
+                       self.execstring(pytext, globals, globals, file, modname)
+       
+       def _run_with_interpreter(self):
+               interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
+               if not os.path.exists(interp_path):
+                       raise W.AlertError, "Can't find interpreter"
+               import findertools
+               XXX
+       
+       def runselection(self):
+               if self._threadstate == (0, 0):
+                       self._runselection()
+               elif self._threadstate == (1, 1):
+                       self._thread.block()
+                       self.setthreadstate((1, 2))
+               elif self._threadstate == (1, 2):
+                       self._thread.start()
+                       self.setthreadstate((1, 1))
+       
+       def _runselection(self):
+               if self.run_with_interpreter:
+                       raise W.AlertError, "Can't run selection with Interpreter"
+               globals, file, modname = self.getenvironment()
+               locals = globals
+               # select whole lines
+               self.editgroup.editor.expandselection()
+               
+               # get lineno of first selected line
+               selstart, selend = self.editgroup.editor.getselection()
+               selstart, selend = min(selstart, selend), max(selstart, selend)
+               selfirstline = self.editgroup.editor.offsettoline(selstart)
+               alltext = self.editgroup.editor.get()
+               pytext = alltext[selstart:selend]
+               lines = string.split(pytext, '\r')
+               indent = getminindent(lines)
+               if indent == 1:
+                       classname = ''
+                       alllines = string.split(alltext, '\r')
+                       for i in range(selfirstline - 1, -1, -1):
+                               line = alllines[i]
+                               if line[:6] == 'class ':
+                                       classname = string.split(string.strip(line[6:]))[0]
+                                       classend = identifieRE_match(classname)
+                                       if classend < 1:
+                                               raise W.AlertError, "Can't find a class."
+                                       classname = classname[:classend]
+                                       break
+                               elif line and line[0] not in '\t#':
+                                       raise W.AlertError, "Can't find a class."
+                       else:
+                               raise W.AlertError, "Can't find a class."
+                       if globals.has_key(classname):
+                               klass = globals[classname]
+                       else:
+                               raise W.AlertError, "Can't find class \"%s\"." % classname
+                       # add class def
+                       pytext = ("class %s:\n" % classname) + pytext
+                       selfirstline = selfirstline - 1
+               elif indent > 0:
+                       raise W.AlertError, "Can't run indented code."
+               
+               # add "newlines" to fool compile/exec: 
+               # now a traceback will give the right line number
+               pytext = selfirstline * '\r' + pytext
+               self.execstring(pytext, globals, locals, file, modname)
+               if indent == 1 and globals[classname] is not klass:
+                       # update the class in place
+                       klass.__dict__.update(globals[classname].__dict__)
+                       globals[classname] = klass
+       
+       def setthreadstate(self, state):
+               oldstate = self._threadstate
+               if oldstate[0] <> state[0]:
+                       self.runbutton.settitle(runButtonLabels[state[0]])
+               if oldstate[1] <> state[1]:
+                       self.runselbutton.settitle(runSelButtonLabels[state[1]])
+               self._threadstate = state
+       
+       def _exec_threadwrapper(self, *args, **kwargs):
+               apply(execstring, args, kwargs)
+               self.setthreadstate((0, 0))
+               self._thread = None
+       
+       def execstring(self, pytext, globals, locals, file, modname):
+               tracebackwindow.hide()
+               # update windows
+               W.getapplication().refreshwindows()
+               if self.run_as_main:
+                       modname = "__main__"
+               if self.path:
+                       dir = os.path.dirname(self.path)
+                       savedir = os.getcwd()
+                       os.chdir(dir)
+                       sys.path.insert(0, dir)
+               else:
+                       cwdindex = None
+               try:
+                       if haveThreading:
+                               self._thread = Wthreading.Thread(os.path.basename(file), 
+                                                       self._exec_threadwrapper, pytext, globals, locals, file, self.debugging, 
+                                                       modname, self.profiling)
+                               self.setthreadstate((1, 1))
+                               self._thread.start()
+                       else:
+                               execstring(pytext, globals, locals, file, self.debugging, 
+                                                       modname, self.profiling)
+               finally:
+                       if self.path:
+                               os.chdir(savedir)
+                               del sys.path[0]
+       
+       def getenvironment(self):
+               if self.path:
+                       file = self.path
+                       dir = os.path.dirname(file)
+                       # check if we're part of a package
+                       modname = ""
+                       while os.path.exists(os.path.join(dir, "__init__.py")):
+                               dir, dirname = os.path.split(dir)
+                               modname = dirname + '.' + modname
+                       subname = _filename_as_modname(self.title)
+                       if modname:
+                               if subname == "__init__":
+                                       # strip trailing period
+                                       modname = modname[:-1]
+                               else:
+                                       modname = modname + subname
+                       else:
+                               modname = subname
+                       if sys.modules.has_key(modname):
+                               globals = sys.modules[modname].__dict__
+                               self.globals = {}
+                       else:
+                               globals = self.globals
+                               modname = subname
+               else:
+                       file = '<%s>' % self.title
+                       globals = self.globals
+                       modname = file
+               return globals, file, modname
+       
+       def write(self, stuff):
+               """for use as stdout"""
+               self._buf = self._buf + stuff
+               if '\n' in self._buf:
+                       self.flush()
+       
+       def flush(self):
+               stuff = string.split(self._buf, '\n')
+               stuff = string.join(stuff, '\r')
+               end = self.editgroup.editor.ted.WEGetTextLength()
+               self.editgroup.editor.ted.WESetSelection(end, end)
+               self.editgroup.editor.ted.WEInsert(stuff, None, None)
+               self.editgroup.editor.updatescrollbars()
+               self._buf = ""
+               # ? optional:
+               #self.wid.SelectWindow()
+       
+       def getclasslist(self):
+               from string import find, strip
+               methodRE = re.compile(r"\r[ \t]+def ")
+               findMethod = methodRE.search
+               editor = self.editgroup.editor
+               text = editor.get()
+               list = []
+               append = list.append
+               functag = "func"
+               classtag = "class"
+               methodtag = "method"
+               pos = -1
+               if text[:4] == 'def ':
+                       append((pos + 4, functag))
+                       pos = 4
+               while 1:
+                       pos = find(text, '\rdef ', pos + 1)
+                       if pos < 0:
+                               break
+                       append((pos + 5, functag))
+               pos = -1
+               if text[:6] == 'class ':
+                       append((pos + 6, classtag))
+                       pos = 6
+               while 1:
+                       pos = find(text, '\rclass ', pos + 1)
+                       if pos < 0:
+                               break
+                       append((pos + 7, classtag))
+               pos = 0
+               while 1:
+                       m = findMethod(text, pos + 1)
+                       if m is None:
+                               break
+                       pos = m.regs[0][0]
+                       #pos = find(text, '\r\tdef ', pos + 1)
+                       append((m.regs[0][1], methodtag))
+               list.sort()
+               classlist = []
+               methodlistappend = None
+               offsetToLine = editor.ted.WEOffsetToLine
+               getLineRange = editor.ted.WEGetLineRange
+               append = classlist.append
+               for pos, tag in list:
+                       lineno = offsetToLine(pos)
+                       lineStart, lineEnd = getLineRange(lineno)
+                       line = strip(text[pos:lineEnd])
+                       line = line[:identifieRE_match(line)]
+                       if tag is functag:
+                               append(("def " + line, lineno + 1))
+                               methodlistappend = None
+                       elif tag is classtag:
+                               append(["class " + line])
+                               methodlistappend = classlist[-1].append
+                       elif methodlistappend and tag is methodtag:
+                               methodlistappend(("def " + line, lineno + 1))
+               return classlist
+       
+       def popselectline(self, lineno):
+               self.editgroup.editor.selectline(lineno - 1)
+       
+       def selectline(self, lineno, charoffset = 0):
+               self.editgroup.editor.selectline(lineno - 1, charoffset)
+
+class _saveoptions:
+       
+       def __init__(self, creator):
+               self.rv = None
+               self.w = w = W.ModalDialog((240, 140), 'Save options')
+               radiobuttons = []
+               w.label = W.TextBox((8, 8, 80, 18), "File creator:")
+               w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
+               w.interp_radio = W.RadioButton((8, 42, 160, 18), "Python Interpreter", radiobuttons, self.interp_hit)
+               w.other_radio = W.RadioButton((8, 62, 50, 18), "Other:", radiobuttons)
+               w.other_creator = W.EditText((62, 62, 40, 20), creator, self.otherselect)
+               w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
+               w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
+               w.setdefaultbutton(w.okbutton)
+               if creator == 'Pyth':
+                       w.interp_radio.set(1)
+               elif creator == W._signature:
+                       w.ide_radio.set(1)
+               else:
+                       w.other_radio.set(1)
+               w.bind("cmd.", w.cancelbutton.push)
+               w.open()
+       
+       def ide_hit(self):
+               self.w.other_creator.set(W._signature)
+       
+       def interp_hit(self):
+               self.w.other_creator.set("Pyth")
+       
+       def otherselect(self, *args):
+               sel_from, sel_to = self.w.other_creator.getselection()
+               creator = self.w.other_creator.get()[:4]
+               creator = creator + " " * (4 - len(creator))
+               self.w.other_creator.set(creator)
+               self.w.other_creator.setselection(sel_from, sel_to)
+               self.w.other_radio.set(1)
+       
+       def cancelbuttonhit(self):
+               self.w.close()
+       
+       def okbuttonhit(self):
+               self.rv = self.w.other_creator.get()[:4]
+               self.w.close()
+
+
+def SaveOptions(creator):
+       s = _saveoptions(creator)
+       return s.rv
+
+
+def _escape(where, what) : 
+       return string.join(string.split(where, what), '\\' + what)
+
+def _makewholewordpattern(word):
+       # first, escape special regex chars
+       for esc in "\\[]()|.*^+$?":
+               word = _escape(word, esc)
+       notwordcharspat = '[^' + _wordchars + ']'
+       pattern = '(' + word + ')'
+       if word[0] in _wordchars:
+               pattern = notwordcharspat + pattern
+       if word[-1] in _wordchars:
+               pattern = pattern + notwordcharspat
+       return re.compile(pattern)
+
+class SearchEngine:
+       
+       def __init__(self):
+               self.visible = 0
+               self.w = None
+               self.parms = {  "find": "",
+                                       "replace": "",
+                                       "wrap": 1,
+                                       "casesens": 1,
+                                       "wholeword": 1
+                               }
+               import MacPrefs
+               prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+               if prefs.searchengine:
+                       self.parms["casesens"] = prefs.searchengine.casesens
+                       self.parms["wrap"] = prefs.searchengine.wrap
+                       self.parms["wholeword"] = prefs.searchengine.wholeword
+       
+       def show(self):
+               self.visible = 1
+               if self.w:
+                       self.w.wid.ShowWindow()
+                       self.w.wid.SelectWindow()
+                       self.w.find.edit.select(1)
+                       self.w.find.edit.selectall()
+                       return
+               self.w = W.Dialog((420, 150), "Find")
+               
+               self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
+               self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
+               
+               self.w.boxes = W.Group((10, 50, 300, 40))
+               self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
+               self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
+               self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
+               
+               self.buttons = [        ("Find",                "cmdf",  self.find), 
+                                       ("Replace",          "cmdr",     self.replace), 
+                                       ("Replace all",  None,   self.replaceall), 
+                                       ("Don't find",  "cmdd",  self.dont), 
+                                       ("Cancel",            "cmd.",    self.cancel)
+                               ]
+               for i in range(len(self.buttons)):
+                       bounds = -90, 22 + i * 24, 80, 16
+                       title, shortcut, callback = self.buttons[i]
+                       self.w[title] = W.Button(bounds, title, callback)
+                       if shortcut:
+                               self.w.bind(shortcut, self.w[title].push)
+               self.w.setdefaultbutton(self.w["Don't find"])
+               self.w.find.edit.bind("<key>", self.key)
+               self.w.bind("<activate>", self.activate)
+               self.w.bind("<close>", self.close)
+               self.w.open()
+               self.setparms()
+               self.w.find.edit.select(1)
+               self.w.find.edit.selectall()
+               self.checkbuttons()
+       
+       def close(self):
+               self.hide()
+               return -1
+       
+       def key(self, char, modifiers):
+               self.w.find.edit.key(char, modifiers)
+               self.checkbuttons()
+               return 1
+       
+       def activate(self, onoff):
+               if onoff:
+                       self.checkbuttons()
+       
+       def checkbuttons(self):
+               editor = findeditor(self)
+               if editor:
+                       if self.w.find.get():
+                               for title, cmd, call in self.buttons[:-2]:
+                                       self.w[title].enable(1)
+                               self.w.setdefaultbutton(self.w["Find"])
+                       else:
+                               for title, cmd, call in self.buttons[:-2]:
+                                       self.w[title].enable(0)
+                               self.w.setdefaultbutton(self.w["Don't find"])
+               else:
+                       for title, cmd, call in self.buttons[:-2]:
+                               self.w[title].enable(0)
+                       self.w.setdefaultbutton(self.w["Don't find"])
+       
+       def find(self):
+               self.getparmsfromwindow()
+               if self.findnext():
+                       self.hide()
+       
+       def replace(self):
+               editor = findeditor(self)
+               if not editor:
+                       return
+               if self.visible:
+                       self.getparmsfromwindow()
+               text = editor.getselectedtext()
+               find = self.parms["find"]
+               if not self.parms["casesens"]:
+                       find = string.lower(find)
+                       text = string.lower(text)
+               if text == find:
+                       self.hide()
+                       editor.insert(self.parms["replace"])
+       
+       def replaceall(self):
+               editor = findeditor(self)
+               if not editor:
+                       return
+               if self.visible:
+                       self.getparmsfromwindow()
+               W.SetCursor("watch")
+               find = self.parms["find"]
+               if not find:
+                       return
+               findlen = len(find)
+               replace = self.parms["replace"]
+               replacelen = len(replace)
+               Text = editor.get()
+               if not self.parms["casesens"]:
+                       find = string.lower(find)
+                       text = string.lower(Text)
+               else:
+                       text = Text
+               newtext = ""
+               pos = 0
+               counter = 0
+               while 1:
+                       if self.parms["wholeword"]:
+                               wholewordRE = _makewholewordpattern(find)
+                               match = wholewordRE.search(text, pos)
+                               if match:
+                                       pos = match.start(1)
+                               else:
+                                       pos = -1
+                       else:
+                               pos = string.find(text, find, pos)
+                       if pos < 0:
+                               break
+                       counter = counter + 1
+                       text = text[:pos] + replace + text[pos + findlen:]
+                       Text = Text[:pos] + replace + Text[pos + findlen:]
+                       pos = pos + replacelen
+               W.SetCursor("arrow")
+               if counter:
+                       self.hide()
+                       import EasyDialogs
+                       import Res
+                       editor.changed = 1
+                       editor.selchanged = 1
+                       editor.ted.WEUseText(Res.Resource(Text))
+                       editor.ted.WECalText()
+                       editor.SetPort()
+                       editor.GetWindow().InvalWindowRect(editor._bounds)
+                       #editor.ted.WEUpdate(self.w.wid.GetWindowPort().visRgn)
+                       EasyDialogs.Message("Replaced %d occurrences" % counter)
+       
+       def dont(self):
+               self.getparmsfromwindow()
+               self.hide()
+       
+       def replacefind(self):
+               self.replace()
+               self.findnext()
+       
+       def setfindstring(self):
+               editor = findeditor(self)
+               if not editor:
+                       return
+               find = editor.getselectedtext()
+               if not find:
+                       return
+               self.parms["find"] = find
+               if self.w:
+                       self.w.find.edit.set(self.parms["find"])
+                       self.w.find.edit.selectall()
+       
+       def findnext(self):
+               editor = findeditor(self)
+               if not editor:
+                       return
+               find = self.parms["find"]
+               if not find:
+                       return
+               text = editor.get()
+               if not self.parms["casesens"]:
+                       find = string.lower(find)
+                       text = string.lower(text)
+               selstart, selend = editor.getselection()
+               selstart, selend = min(selstart, selend), max(selstart, selend)
+               if self.parms["wholeword"]:
+                       wholewordRE = _makewholewordpattern(find)
+                       match = wholewordRE.search(text, selend)
+                       if match:
+                               pos = match.start(1)
+                       else:
+                               pos = -1
+               else:
+                       pos = string.find(text, find, selend)
+               if pos >= 0:
+                       editor.setselection(pos, pos + len(find))
+                       return 1
+               elif self.parms["wrap"]:
+                       if self.parms["wholeword"]:
+                               match = wholewordRE.search(text, 0)
+                               if match:
+                                       pos = match.start(1)
+                               else:
+                                       pos = -1
+                       else:
+                               pos = string.find(text, find)
+                       if selstart > pos >= 0:
+                               editor.setselection(pos, pos + len(find))
+                               return 1
+       
+       def setparms(self):
+               for key, value in self.parms.items():
+                       try:
+                               self.w[key].set(value)
+                       except KeyError:
+                               self.w.boxes[key].set(value)
+       
+       def getparmsfromwindow(self):
+               if not self.w:
+                       return
+               for key, value in self.parms.items():
+                       try:
+                               value = self.w[key].get()
+                       except KeyError:
+                               value = self.w.boxes[key].get()
+                       self.parms[key] = value
+       
+       def cancel(self):
+               self.hide()
+               self.setparms()
+       
+       def hide(self):
+               if self.w:
+                       self.w.wid.HideWindow()
+                       self.visible = 0
+       
+       def writeprefs(self):
+               import MacPrefs
+               self.getparmsfromwindow()
+               prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+               prefs.searchengine.casesens = self.parms["casesens"]
+               prefs.searchengine.wrap = self.parms["wrap"]
+               prefs.searchengine.wholeword = self.parms["wholeword"]
+               prefs.save()
+       
+
+class TitledEditText(W.Group):
+       
+       def __init__(self, possize, title, text = ""):
+               W.Group.__init__(self, possize)
+               self.title = W.TextBox((0, 0, 0, 16), title)
+               self.edit = W.EditText((0, 16, 0, 0), text)
+       
+       def set(self, value):
+               self.edit.set(value)
+       
+       def get(self):
+               return self.edit.get()
+
+
+class ClassFinder(W.PopupWidget):
+       
+       def click(self, point, modifiers):
+               W.SetCursor("watch")
+               self.set(self._parentwindow.getclasslist())
+               W.PopupWidget.click(self, point, modifiers)
+
+
+def getminindent(lines):
+       indent = -1
+       for line in lines:
+               stripped = string.strip(line)
+               if not stripped or stripped[0] == '#':
+                       continue
+               if indent < 0 or line[:indent] <> indent * '\t':
+                       indent = 0
+                       for c in line:
+                               if c <> '\t':
+                                       break
+                               indent = indent + 1
+       return indent
+
+
+def getoptionkey():
+       return not not ord(Evt.GetKeys()[7]) & 0x04
+
+
+def execstring(pytext, globals, locals, filename="<string>", debugging=0, 
+                       modname="__main__", profiling=0):
+       if debugging:
+               import PyDebugger, bdb
+               BdbQuit = bdb.BdbQuit
+       else:
+               BdbQuit = 'BdbQuitDummyException'
+       pytext = string.split(pytext, '\r')
+       pytext = string.join(pytext, '\n') + '\n'
+       W.SetCursor("watch")
+       globals['__name__'] = modname
+       globals['__file__'] = filename
+       sys.argv = [filename]
+       try:
+               code = compile(pytext, filename, "exec")
+       except:
+               # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError 
+               # special. That's wrong because THIS case is special (could be literal 
+               # overflow!) and SyntaxError could mean we need a traceback (syntax error 
+               # in imported module!!!
+               tracebackwindow.traceback(1, filename)
+               return
+       try:
+               if debugging:
+                       if haveThreading:
+                               lock = Wthreading.Lock()
+                               lock.acquire()
+                               PyDebugger.startfromhere()
+                               lock.release()
+                       else:
+                               PyDebugger.startfromhere()
+               elif not haveThreading:
+                       MacOS.EnableAppswitch(0)
+               try:
+                       if profiling:
+                               import profile, ProfileBrowser
+                               p = profile.Profile()
+                               p.set_cmd(filename)
+                               try:
+                                       p.runctx(code, globals, locals)
+                               finally:
+                                       import pstats
+                                       
+                                       stats = pstats.Stats(p)
+                                       ProfileBrowser.ProfileBrowser(stats)
+                       else:
+                               exec code in globals, locals
+               finally:
+                       if not haveThreading:
+                               MacOS.EnableAppswitch(-1)
+       except W.AlertError, detail:
+               raise W.AlertError, detail
+       except (KeyboardInterrupt, BdbQuit):
+               pass
+       except:
+               if haveThreading:
+                       import continuation
+                       lock = Wthreading.Lock()
+                       lock.acquire()
+               if debugging:
+                       sys.settrace(None)
+                       PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
+                       return
+               else:
+                       tracebackwindow.traceback(1, filename)
+               if haveThreading:
+                       lock.release()
+       if debugging:
+               sys.settrace(None)
+               PyDebugger.stop()
+
+
+_identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
+
+def identifieRE_match(str):
+       match = _identifieRE.match(str)
+       if not match:
+               return -1
+       return match.end()
+
+def _filename_as_modname(fname):
+       if fname[-3:] == '.py':
+               modname = fname[:-3]
+               match = _identifieRE.match(modname)
+               if match and match.start() == 0 and match.end() == len(modname):
+                       return string.join(string.split(modname, '.'), '_')
+
+def findeditor(topwindow, fromtop = 0):
+       wid = Win.FrontWindow()
+       if not fromtop:
+               if topwindow.w and wid == topwindow.w.wid:
+                       wid = topwindow.w.wid.GetNextWindow()
+       if not wid:
+               return
+       app = W.getapplication()
+       if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
+               window = W.getapplication()._windows[wid]
+       else:
+               return
+       if not isinstance(window, Editor):
+               return
+       return window.editgroup.editor
+
+
+class _EditorDefaultSettings:
+       
+       def __init__(self):
+               self.template = "%s, %d point"
+               self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
+               self.w = W.Dialog((328, 120), "Editor default settings")
+               self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
+               self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
+               
+               self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
+               self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
+               self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
+               self.w.xsize = W.EditText((98, 48, 40, 20), `self.windowsize[0]`)
+               self.w.ysize = W.EditText((148, 48, 40, 20), `self.windowsize[1]`)
+               
+               self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
+               self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
+               self.w.setdefaultbutton(self.w.okbutton)
+               self.w.bind('cmd.', self.w.cancelbutton.push)
+               self.w.open()
+       
+       def picksize(self):
+               app = W.getapplication()
+               editor = findeditor(self)
+               if editor is not None:
+                       width, height = editor._parentwindow._bounds[2:]
+                       self.w.xsize.set(`width`)
+                       self.w.ysize.set(`height`)
+               else:
+                       raise W.AlertError, "No edit window found"
+       
+       def dofont(self):
+               import FontSettings
+               settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
+               if settings:
+                       self.fontsettings, self.tabsettings = settings
+                       sys.exc_traceback = None
+                       self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
+       
+       def close(self):
+               self.w.close()
+               del self.w
+       
+       def cancel(self):
+               self.close()
+       
+       def ok(self):
+               try:
+                       width = string.atoi(self.w.xsize.get())
+               except:
+                       self.w.xsize.select(1)
+                       self.w.xsize.selectall()
+                       raise W.AlertError, "Bad number for window width"
+               try:
+                       height = string.atoi(self.w.ysize.get())
+               except:
+                       self.w.ysize.select(1)
+                       self.w.ysize.selectall()
+                       raise W.AlertError, "Bad number for window height"
+               self.windowsize = width, height
+               seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
+               self.close()
+
+def geteditorprefs():
+       import MacPrefs
+       prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+       try:
+               fontsettings = prefs.pyedit.fontsettings
+               tabsettings = prefs.pyedit.tabsettings
+               windowsize = prefs.pyedit.windowsize
+       except:
+               fontsettings = prefs.pyedit.fontsettings = ("Python-Sans", 0, 9, (0, 0, 0))
+               tabsettings = prefs.pyedit.tabsettings = (8, 1)
+               windowsize = prefs.pyedit.windowsize = (500, 250)
+               sys.exc_traceback = None
+       return fontsettings, tabsettings, windowsize
+
+def seteditorprefs(fontsettings, tabsettings, windowsize):
+       import MacPrefs
+       prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
+       prefs.pyedit.fontsettings = fontsettings
+       prefs.pyedit.tabsettings = tabsettings
+       prefs.pyedit.windowsize = windowsize
+       prefs.save()
+
+_defaultSettingsEditor = None
+
+def EditorDefaultSettings():
+       global _defaultSettingsEditor
+       if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
+               _defaultSettingsEditor = _EditorDefaultSettings()
+       else:
+               _defaultSettingsEditor.w.select()
+
+def resolvealiases(path):
+       try:
+               return macfs.ResolveAliasFile(path)[0].as_pathname()
+       except (macfs.error, ValueError), (error, str):
+               if error <> -120:
+                       raise
+               dir, file = os.path.split(path)
+               return os.path.join(resolvealiases(dir), file)
+
+searchengine = SearchEngine()
+tracebackwindow = Wtraceback.TraceBack()
diff --git a/Mac/Tools/IDE/PyFontify.py b/Mac/Tools/IDE/PyFontify.py
new file mode 100644 (file)
index 0000000..5680aa8
--- /dev/null
@@ -0,0 +1,155 @@
+"""Module to analyze Python source code; for syntax coloring tools.
+
+Interface:
+       tags = fontify(pytext, searchfrom, searchto)
+
+The 'pytext' argument is a string containing Python source code.
+The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext. 
+The returned value is a list of tuples, formatted like this:
+       [('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ]
+The tuple contents are always like this:
+       (tag, startindex, endindex, sublist)
+tag is one of 'keyword', 'string', 'comment' or 'identifier'
+sublist is not used, hence always None. 
+"""
+
+# Based on FontText.py by Mitchell S. Chapman,
+# which was modified by Zachary Roadhouse,
+# then un-Tk'd by Just van Rossum.
+# Many thanks for regular expression debugging & authoring are due to:
+#      Tim (the-incredib-ly y'rs) Peters and Cristian Tismer
+# So, who owns the copyright? ;-) How about this:
+# Copyright 1996-2001: 
+#      Mitchell S. Chapman,
+#      Zachary Roadhouse,
+#      Tim Peters,
+#      Just van Rossum
+
+__version__ = "0.4"
+
+import string
+import re
+
+# First a little helper, since I don't like to repeat things. (Tismer speaking)
+import string
+def replace(where, what, with):
+       return string.join(string.split(where, what), with)
+
+# This list of keywords is taken from ref/node13.html of the
+# Python 1.3 HTML documentation. ("access" is intentionally omitted.)
+keywordsList = [
+       "assert", "exec",
+       "del", "from", "lambda", "return",
+       "and", "elif", "global", "not", "try",
+       "break", "else", "if", "or", "while",
+       "class", "except", "import", "pass",
+       "continue", "finally", "in", "print",
+       "def", "for", "is", "raise", "yield"]
+
+# Build up a regular expression which will match anything
+# interesting, including multi-line triple-quoted strings.
+commentPat = r"#[^\n]*"
+
+pat = r"q[^\\q\n]*(\\[\000-\377][^\\q\n]*)*q"
+quotePat = replace(pat, "q", "'") + "|" + replace(pat, 'q', '"')
+
+# Way to go, Tim!
+pat = r"""
+       qqq
+       [^\\q]*
+       (
+               (       \\[\000-\377]
+               |       q
+                       (       \\[\000-\377]
+                       |       [^\q]
+                       |       q
+                               (       \\[\000-\377]
+                               |       [^\\q]
+                               )
+                       )
+               )
+               [^\\q]*
+       )*
+       qqq
+"""
+pat = string.join(string.split(pat), '')       # get rid of whitespace
+tripleQuotePat = replace(pat, "q", "'") + "|" + replace(pat, 'q', '"')
+
+# Build up a regular expression which matches all and only
+# Python keywords. This will let us skip the uninteresting
+# identifier references.
+# nonKeyPat identifies characters which may legally precede
+# a keyword pattern.
+nonKeyPat = r"(^|[^a-zA-Z0-9_.\"'])"
+
+keyPat = nonKeyPat + "(" + "|".join(keywordsList) + ")" + nonKeyPat
+
+matchPat = commentPat + "|" + keyPat + "|" + tripleQuotePat + "|" + quotePat
+matchRE = re.compile(matchPat)
+
+idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*"     # Ident w. leading whitespace.
+idRE = re.compile(idKeyPat)
+
+
+def fontify(pytext, searchfrom = 0, searchto = None):
+       if searchto is None:
+               searchto = len(pytext)
+       # Cache a few attributes for quicker reference.
+       search = matchRE.search
+       idSearch = idRE.search
+       
+       tags = []
+       tags_append = tags.append
+       commentTag = 'comment'
+       stringTag = 'string'
+       keywordTag = 'keyword'
+       identifierTag = 'identifier'
+       
+       start = 0
+       end = searchfrom
+       while 1:
+               m = search(pytext, end)
+               if m is None:
+                       break   # EXIT LOOP
+               start = m.start()
+               if start >= searchto:
+                       break   # EXIT LOOP
+               match = m.group(0)
+               end = start + len(match)
+               c = match[0]
+               if c not in "#'\"":
+                       # Must have matched a keyword.
+                       if start <> searchfrom:
+                               # there's still a redundant char before and after it, strip!
+                               match = match[1:-1]
+                               start = start + 1
+                       else:
+                               # this is the first keyword in the text.
+                               # Only a space at the end.
+                               match = match[:-1]
+                       end = end - 1
+                       tags_append((keywordTag, start, end, None))
+                       # If this was a defining keyword, look ahead to the
+                       # following identifier.
+                       if match in ["def", "class"]:
+                               m = idSearch(pytext, end)
+                               if m is not None:
+                                       start = m.start()
+                                       if start == end:
+                                               match = m.group(0)
+                                               end = start + len(match)
+                                               tags_append((identifierTag, start, end, None))
+               elif c == "#":
+                       tags_append((commentTag, start, end, None))
+               else:
+                       tags_append((stringTag, start, end, None))
+       return tags
+
+
+def test(path):
+       f = open(path)
+       text = f.read()
+       f.close()
+       tags = fontify(text)
+       for tag, start, end, sublist in tags:
+               print tag, `text[start:end]`
diff --git a/Mac/Tools/IDE/Wcontrols.py b/Mac/Tools/IDE/Wcontrols.py
new file mode 100644 (file)
index 0000000..7394084
--- /dev/null
@@ -0,0 +1,393 @@
+import Ctl
+import Controls
+import Win
+import Wbase
+import Qd
+import Evt
+
+class ControlWidget(Wbase.ClickableWidget):
+       
+       """Baseclass for all native controls."""
+       
+       def __init__(self, possize, title = "Control", procID = 0, callback = None, value = 0, min = 0, max = 1):
+               Wbase.ClickableWidget.__init__(self, possize)
+               self._control = None
+               self._title = title
+               self._callback = callback
+               self._procID = procID
+               self._value = value
+               self._min = min
+               self._max = max
+               self._enabled = 1
+       
+       def open(self):
+               self._calcbounds()
+               self._control = Ctl.NewControl(self._parentwindow.wid, 
+                                               self._bounds, 
+                                               self._title, 
+                                               1, 
+                                               self._value, 
+                                               self._min, 
+                                               self._max, 
+                                               self._procID, 
+                                               0)
+               self.SetPort()
+               #self.GetWindow().ValidWindowRect(self._bounds)
+               self.enable(self._enabled)
+       
+       def adjust(self, oldbounds):
+               self.SetPort()
+               self._control.HideControl()
+               self._control.MoveControl(self._bounds[0], self._bounds[1])
+               self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
+               if self._visible:
+                       Qd.EraseRect(self._bounds)
+                       self._control.ShowControl()
+                       self.GetWindow().ValidWindowRect(self._bounds)
+       
+       def close(self):
+               self._control.HideControl()
+               self._control = None
+               Wbase.ClickableWidget.close(self)
+       
+       def enable(self, onoff):
+               if self._control and self._enabled <> onoff:
+                       self._control.HiliteControl((not onoff) and 255)
+                       self._enabled = onoff
+       
+       def show(self, onoff):
+               self._visible = onoff
+               for w in self._widgets:
+                       w.show(onoff)
+               if onoff:
+                       self._control.ShowControl()
+               else:
+                       self._control.HideControl()
+       
+       def activate(self, onoff):
+               self._activated = onoff
+               if self._enabled:
+                       self._control.HiliteControl((not onoff) and 255)
+       
+       def draw(self, visRgn = None):
+               if self._visible:
+                       self._control.Draw1Control()
+       
+       def test(self, point):
+               ctltype, control = Ctl.FindControl(point, self._parentwindow.wid)
+               if self._enabled and control == self._control:
+                       return 1
+       
+       def click(self, point, modifiers):
+               if not self._enabled:
+                       return
+               part = self._control.TrackControl(point)
+               if part:
+                       if self._callback:
+                               Wbase.CallbackCall(self._callback, 0)
+       
+       def settitle(self, title):
+               if self._control:
+                       self._control.SetControlTitle(title)
+               self._title = title
+       
+       def gettitle(self):
+               return self._title
+
+class Button(ControlWidget):
+       
+       """Standard push button."""
+       
+       def __init__(self, possize, title = "Button", callback = None):
+               procID = Controls.pushButProc | Controls.useWFont
+               ControlWidget.__init__(self, possize, title, procID, callback, 0, 0, 1)
+               self._isdefault = 0
+       
+       def push(self):
+               if not self._enabled:
+                       return
+               import time
+               self._control.HiliteControl(1)
+               time.sleep(0.1)
+               self._control.HiliteControl(0)
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 0)
+       
+       def enable(self, onoff):
+               if self._control and self._enabled <> onoff:
+                       self._control.HiliteControl((not onoff) and 255)
+                       self._enabled = onoff
+                       if self._isdefault and self._visible:
+                               self.SetPort()
+                               self.drawfatframe(onoff)
+       
+       def activate(self, onoff):
+               self._activated = onoff
+               if self._enabled:
+                       self._control.HiliteControl((not onoff) and 255)
+                       if self._isdefault and self._visible:
+                               self.SetPort()
+                               self.drawfatframe(onoff)
+       
+       def show(self, onoff):
+               ControlWidget.show(self, onoff)
+               if self._isdefault:
+                       self.drawfatframe(onoff and self._enabled)
+       
+       def draw(self, visRgn = None):
+               if self._visible:
+                       self._control.Draw1Control()
+                       if self._isdefault and self._activated:
+                               self.drawfatframe(self._enabled)
+       
+       def drawfatframe(self, onoff):
+               state = Qd.GetPenState()
+               if onoff:
+                       Qd.PenPat(Qd.qd.black)
+               else:
+                       Qd.PenPat(Qd.qd.white)
+               fatrect = Qd.InsetRect(self._bounds, -4, -4)
+               Qd.PenSize(3, 3)
+               Qd.FrameRoundRect(fatrect, 16, 16)
+               Qd.SetPenState(state)
+       
+       def _setdefault(self, onoff):
+               self._isdefault = onoff
+               if self._control and self._enabled:
+                       self.SetPort()
+                       self.drawfatframe(onoff)
+       
+       def adjust(self, oldbounds):
+               if self._isdefault:
+                       old = Qd.InsetRect(oldbounds, -4, -4)
+                       new = Qd.InsetRect(self._bounds, -4, -4)
+                       Qd.EraseRect(old)
+                       self.GetWindow().InvalWindowRect(old)
+                       self.GetWindow().InvalWindowRect(new)
+               ControlWidget.adjust(self, oldbounds)
+
+
+class CheckBox(ControlWidget):
+       
+       """Standard checkbox."""
+       
+       def __init__(self, possize, title = "Checkbox", callback = None, value = 0):
+               procID = Controls.checkBoxProc | Controls.useWFont
+               ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
+       
+       def click(self, point, modifiers):
+               if not self._enabled:
+                       return
+               part = self._control.TrackControl(point)
+               if part:
+                       self.toggle()
+                       if self._callback:
+                               Wbase.CallbackCall(self._callback, 0, self.get())
+       
+       def push(self):
+               if not self._enabled:
+                       return
+               self.toggle()
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 0, self.get())
+       
+       def toggle(self):
+               self.set(not self.get())
+       
+       def set(self, value):
+               if self._control:
+                       self._control.SetControlValue(value)
+               else:
+                       self._value = value
+       
+       def get(self):
+               if self._control:
+                       return self._control.GetControlValue()
+               else:
+                       return self._value
+       
+
+class RadioButton(ControlWidget):
+       
+       """Standard radiobutton."""
+       
+       # XXX We need a radiogroup widget; this is too kludgy.
+       
+       def __init__(self, possize, title, thebuttons, callback = None, value = 0):
+               procID = Controls.radioButProc | Controls.useWFont
+               ControlWidget.__init__(self, possize, title, procID, callback, value, 0, 1)
+               self.thebuttons = thebuttons
+               thebuttons.append(self)
+       
+       def close(self):
+               self.thebuttons = None
+               ControlWidget.close(self)
+       
+       def click(self, point, modifiers):
+               if not self._enabled:
+                       return
+               part = self._control.TrackControl(point)
+               if part:
+                       self.set(1)
+                       if self._callback:
+                               Wbase.CallbackCall(self._callback, 0, 1)
+       
+       def push(self):
+               if not self._enabled:
+                       return
+               self.set(1)
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 0, 1)
+       
+       def set(self, value):
+               for button in self.thebuttons:
+                       if button._control:
+                               button._control.SetControlValue(button == self)
+                       else:
+                               button._value = (button == self)
+       
+       def get(self):
+               if self._control:
+                       return self._control.GetControlValue()
+               else:
+                       return self._value
+       
+
+class Scrollbar(ControlWidget):
+       
+       """Standard scrollbar."""
+       
+       def __init__(self, possize, callback = None, value = 0, min = 0, max = 0):
+               procID = Controls.scrollBarProc
+               ControlWidget.__init__(self, possize, "", procID, callback, value, min, max)
+       
+       # interface
+       def set(self, value):
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 1, value)
+       
+       def up(self):
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 1, '+')
+       
+       def down(self):
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 1, '-')
+       
+       def pageup(self):
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 1, '++')
+       
+       def pagedown(self):
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 1, '--')
+       
+       def setmin(self, min):
+               self._control.SetControlMinimum(min)
+       
+       def setmax(self, min):
+               self._control.SetControlMinimum(max)
+       
+       def getmin(self):
+               return self._control.GetControlMinimum()
+       
+       def getmax(self):
+               return self._control.GetControlMinimum()
+       
+       # internals
+       def click(self, point, modifiers):
+               if not self._enabled:
+                       return
+               # custom TrackControl. A mousedown in a scrollbar arrow or page area should
+               # generate _control hits as long as the mouse is a) down, b) still in the same part
+               part = self._control.TestControl(point)
+               if Controls.inUpButton <= part <= Controls.inPageDown:  
+                       self._control.HiliteControl(part)
+                       self._hit(part)
+                       oldpart = part
+                       # slight delay before scrolling at top speed...
+                       now = Evt.TickCount()
+                       while Evt.StillDown():
+                               if (Evt.TickCount() - now) > 18: # 0.3 seconds
+                                       break
+                       while Evt.StillDown():
+                               part = self._control.TestControl(point)
+                               if part == oldpart:
+                                       self._control.HiliteControl(part)
+                                       self._hit(part)
+                               else:
+                                       self._control.HiliteControl(0)
+                               self.SetPort()
+                               point = Evt.GetMouse()
+                       self._control.HiliteControl(0)
+               elif part == Controls.inThumb:
+                       part = self._control.TrackControl(point)
+                       if part:
+                               self._hit(part)
+       
+       def _hit(self, part):
+               if part == Controls.inThumb:
+                       value = self._control.GetControlValue()
+               elif part == Controls.inUpButton:
+                       value = "+"
+               elif part == Controls.inDownButton:
+                       value = "-"
+               elif part == Controls.inPageUp:
+                       value = "++"
+               elif part == Controls.inPageDown:
+                       value = "--"
+               if self._callback:
+                       Wbase.CallbackCall(self._callback, 1, value)
+       
+       def draw(self, visRgn = None):
+               if self._visible:
+                       self._control.Draw1Control()
+                       Qd.FrameRect(self._bounds)
+       
+       def adjust(self, oldbounds):
+               self.SetPort()
+               self.GetWindow().InvalWindowRect(oldbounds)
+               self._control.HideControl()
+               self._control.MoveControl(self._bounds[0], self._bounds[1])
+               self._control.SizeControl(self._bounds[2] - self._bounds[0], self._bounds[3] - self._bounds[1])
+               if self._visible:
+                       Qd.EraseRect(self._bounds)
+                       if self._activated:
+                               self._control.ShowControl()
+                       else:
+                               Qd.FrameRect(self._bounds)
+                       self.GetWindow().ValidWindowRect(self._bounds)
+       
+       def activate(self, onoff):
+               self._activated = onoff
+               if self._visible:
+                       if onoff:
+                               self._control.ShowControl()
+                       else:
+                               self._control.HideControl()
+                               self.draw(None)
+                               self.GetWindow().ValidWindowRect(self._bounds)
+               
+       def set(self, value):
+               if self._control:
+                       self._control.SetControlValue(value)
+               else:
+                       self._value = value
+       
+       def get(self):
+               if self._control:
+                       return self._control.GetControlValue()
+               else:
+                       return self._value
+       
+
+def _scalebarvalue(absmin, absmax, curmin, curmax):
+       if curmin <= absmin and curmax >= absmax:
+               return None
+       if curmin <= absmin:
+               return 0
+       if curmax >= absmax:
+               return 32767
+       perc = float(curmin-absmin) / float((absmax - absmin) - (curmax - curmin))
+       return int(perc*32767)
+
diff --git a/Mac/Tools/IDE/Wtraceback.py b/Mac/Tools/IDE/Wtraceback.py
new file mode 100644 (file)
index 0000000..4960ad0
--- /dev/null
@@ -0,0 +1,190 @@
+import traceback
+import sys
+import W
+import os
+import types
+import List
+
+
+class TraceBack:
+       
+       def __init__(self, title = "Traceback"):
+               app = W.getapplication()  # checks if W is properly initialized
+               self.title = title
+               self.w = None
+               self.closed = 1
+               self.start = 0
+               self.lastwindowtitle = ""
+               self.bounds = (360, 298)
+       
+       def traceback(self, start = 0, lastwindowtitle = ""):
+               try:
+                       self.lastwindowtitle = lastwindowtitle
+                       self.start = start
+                       self.type, self.value, self.tb = sys.exc_info()
+                       if self.type is not SyntaxError:
+                               self.show()
+                               if type(self.type) == types.ClassType:
+                                       errortext = self.type.__name__
+                               else:
+                                       errortext = str(self.type)
+                               value = str(self.value)
+                               if self.value and value:
+                                       errortext = errortext + ": " + value
+                               self.w.text.set(errortext)
+                               self.buildtblist()
+                               self.w.list.set(self.textlist)
+                               self.w.list.setselection([len(self.textlist) - 1])
+                               self.w.wid.SelectWindow()
+                               self.closed = 0
+                       else:
+                               self.syntaxerror()
+               except:
+                       traceback.print_exc()
+       
+       def syntaxerror(self):
+               try:
+                       value, (filename, lineno, charno, line) = self.value
+               except:
+                       filename = ""
+                       lineno = None
+                       value = self.value
+               if not filename and self.lastwindowtitle:
+                       filename = self.lastwindowtitle
+               elif not filename:
+                       filename = "<unknown>"
+               if filename and os.path.exists(filename):
+                       filename = os.path.split(filename)[1]
+               if lineno and charno is not None:
+                       charno = charno - 1
+                       text = str(value) + '\rFile: "' + str(filename) + '", line ' + str(lineno) + '\r\r' + line[:charno] + "\xa5" + line[charno:-1]
+               else:
+                       text = str(value) + '\rFile: "' + str(filename) + '"'
+               self.syntaxdialog = W.ModalDialog((360, 120), "Syntax Error")
+               self.syntaxdialog.text = W.TextBox((10, 10, -10, -40), text)
+               self.syntaxdialog.cancel = W.Button((-190, -32, 80, 16), "Cancel", self.syntaxclose)
+               self.syntaxdialog.edit = W.Button((-100, -32, 80, 16), "Edit", self.syntaxedit)
+               self.syntaxdialog.setdefaultbutton(self.syntaxdialog.edit)
+               self.syntaxdialog.bind("cmd.", self.syntaxdialog.cancel.push)
+               self.syntaxdialog.open()
+       
+       def syntaxclose(self):
+               self.syntaxdialog.close()
+               del self.syntaxdialog
+       
+       def syntaxedit(self):
+               try:
+                       value, (filename, lineno, charno, line) = self.value
+               except:
+                       filename = ""
+                       lineno = None
+               if not filename and self.lastwindowtitle:
+                       filename = self.lastwindowtitle
+               elif not filename:
+                       filename = "<unknown>"
+               self.syntaxclose()
+               if lineno:
+                       if charno is None:
+                               charno = 1
+                       W.getapplication().openscript(filename, lineno, charno - 1)
+               else:
+                       W.getapplication().openscript(filename)
+       
+       def show(self):
+               if self.closed:
+                       self.setupwidgets()
+                       self.w.open()
+               else:
+                       self.w.wid.ShowWindow()
+                       self.w.wid.SelectWindow()
+       
+       def hide(self):
+               if self.closed:
+                       return
+               self.w.close()
+       
+       def close(self):
+               self.bounds = self.w.getbounds()
+               self.closed = 1
+               self.type, self.value, self.tb = None, None, None
+               self.tblist = None
+       
+       def activate(self, onoff):
+               if onoff:
+                       if self.closed:
+                               self.traceback()
+                       self.closed = 0
+                       self.checkbuttons()
+       
+       def setupwidgets(self):
+               self.w = W.Window(self.bounds, self.title, minsize = (316, 168))
+               self.w.text = W.TextBox((10, 10, -10, 30))
+               self.w.tbtitle = W.TextBox((10, 40, -10, 10), "Traceback (innermost last):")
+               self.w.list = W.TwoLineList((10, 60, -10, -40), callback = self.listhit)
+               
+               self.w.editbutton = W.Button((10, -30, 60, 16), "Edit", self.edit)
+               self.w.editbutton.enable(0)
+               
+               self.w.browselocalsbutton = W.Button((80, -30, 100, 16), "Browse locals\xc9", self.browselocals)
+               self.w.browselocalsbutton.enable(0)
+               
+               self.w.postmortembutton = W.Button((190, -30, 100, 16), "Post mortem\xc9", self.postmortem)
+               
+               self.w.setdefaultbutton(self.w.editbutton)
+               self.w.bind("cmdb", self.w.browselocalsbutton.push)
+               self.w.bind("<close>", self.close)
+               self.w.bind("<activate>", self.activate)
+       
+       def buildtblist(self):
+               tb = self.tb
+               for i in range(self.start):
+                       if tb.tb_next is None:
+                               break
+                       tb = tb.tb_next
+               self.tblist = traceback.extract_tb(tb)
+               self.textlist = []
+               for filename, lineno, func, line in self.tblist:
+                       tbline = ""
+                       if os.path.exists(filename):
+                               filename = os.path.split(filename)[1]
+                               tbline = 'File "' + filename + '", line ' + `lineno` + ', in ' + func
+                       else:
+                               tbline = 'File "' + filename + '", line ' + `lineno` + ', in ' + func
+                       if line:
+                               tbline = tbline + '\r      ' + line
+                       self.textlist.append(tbline[:255])
+       
+       def edit(self):
+               sel = self.w.list.getselection()
+               for i in sel:
+                       filename, lineno, func, line = self.tblist[i]
+                       W.getapplication().openscript(filename, lineno)
+       
+       def browselocals(self):
+               sel = self.w.list.getselection()
+               for i in sel:
+                       tb = self.tb
+                       for j in range(i + self.start):
+                               tb = tb.tb_next
+                       self.browse(tb.tb_frame.f_locals)
+       
+       def browse(self, object):
+               import PyBrowser
+               PyBrowser.Browser(object)
+       
+       def postmortem(self):
+               import PyDebugger
+               PyDebugger.postmortem(self.type, self.value, self.tb)
+       
+       def listhit(self, isdbl):
+               if isdbl:
+                       self.w.editbutton.push()
+               else:
+                       self.checkbuttons()
+       
+       def checkbuttons(self):
+               havefile = len(self.w.list.getselection()) > 0
+               self.w.editbutton.enable(havefile)
+               self.w.browselocalsbutton.enable(havefile)
+               self.w.setdefaultbutton(havefile and self.w.editbutton or self.w.postmortembutton)
+