mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			728 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			728 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/***********************************************************
 | 
						|
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
 | 
						|
The Netherlands.
 | 
						|
 | 
						|
                        All Rights Reserved
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software and its 
 | 
						|
documentation for any purpose and without fee is hereby granted, 
 | 
						|
provided that the above copyright notice appear in all copies and that
 | 
						|
both that copyright notice and this permission notice appear in 
 | 
						|
supporting documentation, and that the names of Stichting Mathematisch
 | 
						|
Centrum or CWI 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 "pythonresources.h"
 | 
						|
 | 
						|
#include <OSUtils.h> /* for Set(Current)A5 */
 | 
						|
#include <Files.h>
 | 
						|
#include <StandardFile.h>
 | 
						|
#include <Resources.h>
 | 
						|
#include <Memory.h>
 | 
						|
#include <Events.h>
 | 
						|
#include <Windows.h>
 | 
						|
#include <Desk.h>
 | 
						|
#include <Traps.h>
 | 
						|
#include <Processes.h>
 | 
						|
#include <Fonts.h>
 | 
						|
#include <Menus.h>
 | 
						|
#include <TextUtils.h>
 | 
						|
#ifdef THINK_C
 | 
						|
#include <OSEvents.h> /* For EvQElPtr */
 | 
						|
#endif
 | 
						|
#ifdef __MWERKS__
 | 
						|
#include <SIOUX.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef HAVE_UNIVERSAL_HEADERS
 | 
						|
#define GetResourceSizeOnDisk(x) SizeResource(x)
 | 
						|
typedef DlgHookYDProcPtr DlgHookYDUPP;
 | 
						|
#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
 | 
						|
typedef FileFilterYDProcPtr FileFilterYDUPP;
 | 
						|
#endif
 | 
						|
 | 
						|
#include <signal.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
/*
 | 
						|
** We have to be careful, since we can't handle
 | 
						|
** things like updates (and they'll keep coming back if we don't
 | 
						|
** handle them). Note that we don't know who has windows open, so
 | 
						|
** even handing updates off to SIOUX under MW isn't going to work.
 | 
						|
*/
 | 
						|
#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
 | 
						|
 | 
						|
#include <signal.h>
 | 
						|
 | 
						|
/* XXX We should include Errors.h here, but it has a name conflict
 | 
						|
** with the python errors.h. */
 | 
						|
#define fnfErr -43
 | 
						|
 | 
						|
/* Declared in macfsmodule.c: */
 | 
						|
extern FSSpec *mfs_GetFSSpecFSSpec();
 | 
						|
 | 
						|
/* Interrupt code variables: */
 | 
						|
static int interrupted;			/* Set to true when cmd-. seen */
 | 
						|
static RETSIGTYPE intcatcher Py_PROTO((int));
 | 
						|
 | 
						|
/*
 | 
						|
** We attempt to be a good citizen by giving up the CPU periodically.
 | 
						|
** When in the foreground we do this less often and for shorter periods
 | 
						|
** than when in the background. At this time we also check for events and
 | 
						|
** pass them off to SIOUX, if compiling with mwerks.
 | 
						|
** The counts here are in ticks of 1/60th second.
 | 
						|
** XXXX The initial values here are not based on anything.
 | 
						|
** FG-python gives up the cpu for 1/60th 5 times per second,
 | 
						|
** BG-python for .2 second 10 times per second.
 | 
						|
*/
 | 
						|
static long interval_fg = 12;
 | 
						|
static long interval_bg = 6;
 | 
						|
static long yield_fg = 1;
 | 
						|
static long yield_bg = 12;
 | 
						|
static long lastyield;
 | 
						|
static int in_foreground;
 | 
						|
 | 
						|
/* 
 | 
						|
** When > 0, do full scanning for events (program is not event aware)
 | 
						|
** when == 0, only scan for Command-period
 | 
						|
** when < 0, don't do any event scanning 
 | 
						|
*/
 | 
						|
int PyMac_DoYieldEnabled = 1;
 | 
						|
 | 
						|
/*
 | 
						|
** Some stuff for our GetDirectory and PromptGetFile routines
 | 
						|
*/
 | 
						|
struct hook_args {
 | 
						|
	int selectcur_hit;		/* Set to true when "select current" selected */
 | 
						|
	char *prompt;			/* The prompt */
 | 
						|
};
 | 
						|
static DlgHookYDUPP myhook_upp;
 | 
						|
static int upp_inited = 0;
 | 
						|
 | 
						|
 | 
						|
/* Convert C to Pascal string. Returns pointer to static buffer. */
 | 
						|
unsigned char *
 | 
						|
Pstring(char *str)
 | 
						|
{
 | 
						|
	static Str255 buf;
 | 
						|
	int len;
 | 
						|
 | 
						|
	len = strlen(str);
 | 
						|
	if (len > 255)
 | 
						|
		len = 255;
 | 
						|
	buf[0] = (unsigned char)len;
 | 
						|
	strncpy((char *)buf+1, str, len);
 | 
						|
	return buf;
 | 
						|
}
 | 
						|
 | 
						|
/* Like strerror() but for Mac OS error numbers */
 | 
						|
char *PyMac_StrError(int err)
 | 
						|
{
 | 
						|
	static char buf[256];
 | 
						|
	Handle h;
 | 
						|
	char *str;
 | 
						|
	
 | 
						|
	h = GetResource('Estr', err);
 | 
						|
	if ( h ) {
 | 
						|
		HLock(h);
 | 
						|
		str = (char *)*h;
 | 
						|
		memcpy(buf, str+1, (unsigned char)str[0]);
 | 
						|
		buf[(unsigned char)str[0]] = '\0';
 | 
						|
		HUnlock(h);
 | 
						|
		ReleaseResource(h);
 | 
						|
	} else {
 | 
						|
		sprintf(buf, "Mac OS error code %d", err);
 | 
						|
	}
 | 
						|
	return buf;
 | 
						|
}
 | 
						|
 | 
						|
/* Exception object shared by all Mac specific modules for Mac OS errors */
 | 
						|
PyObject *PyMac_OSErrException;
 | 
						|
 | 
						|
/* Initialize and return PyMac_OSErrException */
 | 
						|
PyObject *
 | 
						|
PyMac_GetOSErrException()
 | 
						|
{
 | 
						|
	if (PyMac_OSErrException == NULL)
 | 
						|
		PyMac_OSErrException = PyString_FromString("Mac OS Error");
 | 
						|
	return PyMac_OSErrException;
 | 
						|
}
 | 
						|
 | 
						|
/* Set a MAC-specific error from errno, and return NULL; return None if no error */
 | 
						|
PyObject * 
 | 
						|
PyErr_Mac(PyObject *eobj, int err)
 | 
						|
{
 | 
						|
	char *msg;
 | 
						|
	PyObject *v;
 | 
						|
	
 | 
						|
	if (err == 0 && !PyErr_Occurred()) {
 | 
						|
		Py_INCREF(Py_None);
 | 
						|
		return Py_None;
 | 
						|
	}
 | 
						|
	if (err == -1 && PyErr_Occurred())
 | 
						|
		return NULL;
 | 
						|
	msg = PyMac_StrError(err);
 | 
						|
	v = Py_BuildValue("(is)", err, msg);
 | 
						|
	PyErr_SetObject(eobj, v);
 | 
						|
	Py_DECREF(v);
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/* Call PyErr_Mac with PyMac_OSErrException */
 | 
						|
PyObject *
 | 
						|
PyMac_Error(OSErr err)
 | 
						|
{
 | 
						|
	return PyErr_Mac(PyMac_GetOSErrException(), err);
 | 
						|
}
 | 
						|
 | 
						|
/* The catcher routine (which may not be used for all compilers) */
 | 
						|
static RETSIGTYPE
 | 
						|
intcatcher(sig)
 | 
						|
	int sig;
 | 
						|
{
 | 
						|
	interrupted = 1;
 | 
						|
	signal(SIGINT, intcatcher);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PyOS_InitInterrupts()
 | 
						|
{
 | 
						|
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 | 
						|
		signal(SIGINT, intcatcher);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** This routine scans the event queue looking for cmd-.
 | 
						|
** This is the only way to get an interrupt under THINK (since it
 | 
						|
** doesn't do SIGINT handling), but is also used under MW, when
 | 
						|
** the full-fledged event loop is disabled. This way, we can at least
 | 
						|
** interrupt a runaway python program.
 | 
						|
*/
 | 
						|
static void
 | 
						|
scan_event_queue(flush)
 | 
						|
	int flush;
 | 
						|
{
 | 
						|
#if defined(__MWERKS__) && defined(__CFM68K__)
 | 
						|
	return; /* No GetEvQHdr yet */
 | 
						|
#else
 | 
						|
	register EvQElPtr q;
 | 
						|
	
 | 
						|
	q = (EvQElPtr) GetEvQHdr()->qHead;
 | 
						|
	
 | 
						|
	for (; q; q = (EvQElPtr)q->qLink) {
 | 
						|
		if (q->evtQWhat == keyDown &&
 | 
						|
				(char)q->evtQMessage == '.' &&
 | 
						|
				(q->evtQModifiers & cmdKey) != 0) {
 | 
						|
			if ( flush )
 | 
						|
				FlushEvents(keyDownMask, 0);
 | 
						|
			interrupted = 1;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
PyOS_InterruptOccurred()
 | 
						|
{
 | 
						|
	if (PyMac_DoYieldEnabled < 0)
 | 
						|
		return 0;
 | 
						|
#ifdef THINK_C
 | 
						|
	scan_event_queue(1);
 | 
						|
#endif
 | 
						|
	PyMac_Yield();
 | 
						|
	if (interrupted) {
 | 
						|
		interrupted = 0;
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
 | 
						|
** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
 | 
						|
** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
 | 
						|
** thereafter.
 | 
						|
*/
 | 
						|
static int
 | 
						|
intrpeek()
 | 
						|
{
 | 
						|
#ifdef THINK_C
 | 
						|
	scan_event_queue(0);
 | 
						|
#endif
 | 
						|
	return interrupted;
 | 
						|
}
 | 
						|
 | 
						|
/* Check whether we are in the foreground */
 | 
						|
int
 | 
						|
PyMac_InForeground()
 | 
						|
{
 | 
						|
	static ProcessSerialNumber ours;
 | 
						|
	static inited;
 | 
						|
	ProcessSerialNumber curfg;
 | 
						|
	Boolean eq;
 | 
						|
	
 | 
						|
	if ( inited == 0 )
 | 
						|
		(void)GetCurrentProcess(&ours);
 | 
						|
	inited = 1;
 | 
						|
	if ( GetFrontProcess(&curfg) < 0 )
 | 
						|
		eq = 1;
 | 
						|
	else if ( SameProcess(&ours, &curfg, &eq) < 0 )
 | 
						|
		eq = 1;
 | 
						|
	return (int)eq;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Set yield timeouts
 | 
						|
*/
 | 
						|
void
 | 
						|
PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
 | 
						|
{
 | 
						|
	interval_fg = fgi;
 | 
						|
	yield_fg = fgy;
 | 
						|
	interval_bg = bgi;
 | 
						|
	yield_bg = bgy;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Handle an event, either one found in the mainloop eventhandler or
 | 
						|
** one passed back from the python program.
 | 
						|
*/
 | 
						|
void
 | 
						|
PyMac_HandleEvent(evp)
 | 
						|
	EventRecord *evp;
 | 
						|
{
 | 
						|
			
 | 
						|
#ifdef __MWERKS__
 | 
						|
	/* If SIOUX wants it we're done */
 | 
						|
	(void)SIOUXHandleOneEvent(evp);
 | 
						|
#else
 | 
						|
	/* Other compilers are just unlucky: we only weed out clicks in other applications */
 | 
						|
	if ( evp->what == mouseDown ) {
 | 
						|
		WindowPtr wp;
 | 
						|
		
 | 
						|
		if ( FindWindow(evp->where, &wp) == inSysWindow )
 | 
						|
			SystemClick(evp, wp);
 | 
						|
	}
 | 
						|
#endif /* !__MWERKS__ */
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Yield the CPU to other tasks.
 | 
						|
*/
 | 
						|
static
 | 
						|
PyMac_DoYield()
 | 
						|
{
 | 
						|
	EventRecord ev;
 | 
						|
	long yield;
 | 
						|
	static int no_waitnextevent = -1;
 | 
						|
	int gotone;
 | 
						|
	
 | 
						|
	if ( no_waitnextevent < 0 ) {
 | 
						|
		no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
 | 
						|
							NGetTrapAddress(_Unimplemented, ToolTrap));
 | 
						|
	}
 | 
						|
 | 
						|
	if ( !PyMac_DoYieldEnabled ) {
 | 
						|
#ifndef THINK_C
 | 
						|
		/* Under think this has been done before in intrcheck() or intrpeek() */
 | 
						|
		scan_event_queue(0);
 | 
						|
#endif
 | 
						|
		return;
 | 
						|
	}
 | 
						|
		
 | 
						|
	in_foreground = PyMac_InForeground();
 | 
						|
	if ( in_foreground )
 | 
						|
		yield = yield_fg;
 | 
						|
	else
 | 
						|
		yield = yield_bg;
 | 
						|
	while ( 1 ) {
 | 
						|
		if ( no_waitnextevent ) {
 | 
						|
			SystemTask();
 | 
						|
			gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
 | 
						|
		} else {
 | 
						|
			gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
 | 
						|
		}	
 | 
						|
		/* Get out quickly if nothing interesting is happening */
 | 
						|
		if ( !gotone || ev.what == nullEvent )
 | 
						|
			break;
 | 
						|
		PyMac_HandleEvent(&ev);
 | 
						|
	}
 | 
						|
	lastyield = TickCount();
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Yield the CPU to other tasks if opportune
 | 
						|
*/
 | 
						|
void
 | 
						|
PyMac_Yield() {
 | 
						|
	long iv;
 | 
						|
	
 | 
						|
	if ( in_foreground )
 | 
						|
		iv = interval_fg;
 | 
						|
	else
 | 
						|
		iv = interval_bg;
 | 
						|
	if ( TickCount() > lastyield + iv )
 | 
						|
		PyMac_DoYield();
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Idle routine for busy-wait loops.
 | 
						|
** Gives up CPU, handles events and returns true if an interrupt is pending
 | 
						|
** (but not actually handled yet).
 | 
						|
*/
 | 
						|
int
 | 
						|
PyMac_Idle()
 | 
						|
{
 | 
						|
	PyMac_DoYield();
 | 
						|
	return intrpeek();
 | 
						|
}
 | 
						|
/*
 | 
						|
** Returns true if the argument has a resource fork, and it contains
 | 
						|
** a 'PYC ' resource of the correct name
 | 
						|
*/
 | 
						|
int
 | 
						|
PyMac_FindResourceModule(module, filename)
 | 
						|
char *module;
 | 
						|
char *filename;
 | 
						|
{
 | 
						|
	FSSpec fss;
 | 
						|
	FInfo finfo;
 | 
						|
	short oldrh, filerh;
 | 
						|
	int ok;
 | 
						|
	Handle h;
 | 
						|
	
 | 
						|
	if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
 | 
						|
		return 0;			/* It doesn't exist */
 | 
						|
	if ( FSpGetFInfo(&fss, &finfo) != noErr )
 | 
						|
		return 0;			/* shouldn't happen, I guess */
 | 
						|
	oldrh = CurResFile();
 | 
						|
	filerh = FSpOpenResFile(&fss, fsRdPerm);
 | 
						|
	if ( filerh == -1 )
 | 
						|
		return 0;
 | 
						|
	UseResFile(filerh);
 | 
						|
	SetResLoad(0);
 | 
						|
	h = Get1NamedResource('PYC ', Pstring(module));
 | 
						|
	SetResLoad(1);
 | 
						|
	ok = (h != NULL);
 | 
						|
	CloseResFile(filerh);
 | 
						|
	UseResFile(oldrh);
 | 
						|
	return ok;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** 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;
 | 
						|
	
 | 
						|
	if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
 | 
						|
		goto error;
 | 
						|
	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);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	HUnlock(h);
 | 
						|
	CloseResFile(filerh);
 | 
						|
	UseResFile(oldrh);
 | 
						|
	if ( co ) {
 | 
						|
		m = PyImport_ExecCodeModule(module, co);
 | 
						|
		Py_DECREF(co);
 | 
						|
	} else {
 | 
						|
		m = NULL;
 | 
						|
	}
 | 
						|
	return m;
 | 
						|
error:
 | 
						|
	{
 | 
						|
		char buf[512];
 | 
						|
		
 | 
						|
		sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
 | 
						|
		PyErr_SetString(PyExc_ImportError, buf);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Helper routine for GetDirectory
 | 
						|
*/
 | 
						|
static pascal short
 | 
						|
myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
 | 
						|
{
 | 
						|
	if ( item == sfHookFirstCall && dataptr->prompt) {
 | 
						|
		Handle prompth;
 | 
						|
		short type;
 | 
						|
		Rect rect;
 | 
						|
		
 | 
						|
		GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
 | 
						|
		if ( prompth )
 | 
						|
			SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
 | 
						|
	} else
 | 
						|
	if ( item == SELECTCUR_ITEM ) {
 | 
						|
		item = sfItemCancelButton;
 | 
						|
		dataptr->selectcur_hit = 1;
 | 
						|
	}
 | 
						|
	return item;
 | 
						|
}	
 | 
						|
 | 
						|
/*
 | 
						|
** Ask the user for a directory. I still can't understand
 | 
						|
** why Apple doesn't provide a standard solution for this...
 | 
						|
*/
 | 
						|
int
 | 
						|
PyMac_GetDirectory(dirfss, prompt)
 | 
						|
	FSSpec *dirfss;
 | 
						|
	char *prompt;
 | 
						|
{
 | 
						|
	static SFTypeList list = {'fldr', 0, 0, 0};
 | 
						|
	static Point where = {-1, -1};
 | 
						|
	StandardFileReply reply;
 | 
						|
	struct hook_args hook_args;
 | 
						|
	
 | 
						|
	if ( !upp_inited ) {
 | 
						|
		myhook_upp = NewDlgHookYDProc(myhook_proc);
 | 
						|
		upp_inited = 1;
 | 
						|
	}
 | 
						|
	if ( prompt && *prompt )
 | 
						|
		hook_args.prompt = (char *)Pstring(prompt);
 | 
						|
	else
 | 
						|
		hook_args.prompt = NULL;
 | 
						|
	hook_args.selectcur_hit = 0;
 | 
						|
	CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
 | 
						|
				NULL, NULL, NULL, (void *)&hook_args);
 | 
						|
				
 | 
						|
	reply.sfFile.name[0] = 0;
 | 
						|
	if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
 | 
						|
		return 0;
 | 
						|
	return hook_args.selectcur_hit;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
** Slightly extended StandardGetFile: accepts a prompt */
 | 
						|
void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList, 
 | 
						|
		StandardFileReply *reply, char *prompt)
 | 
						|
{
 | 
						|
	static Point where = {-1, -1};
 | 
						|
	struct hook_args hook_args;
 | 
						|
	
 | 
						|
	if ( !upp_inited ) {
 | 
						|
		myhook_upp = NewDlgHookYDProc(myhook_proc);
 | 
						|
		upp_inited = 1;
 | 
						|
	}
 | 
						|
	if ( prompt && *prompt )
 | 
						|
		hook_args.prompt = (char *)Pstring(prompt);
 | 
						|
	else
 | 
						|
		hook_args.prompt = NULL;
 | 
						|
	hook_args.selectcur_hit = 0;
 | 
						|
	CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
 | 
						|
				myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
 | 
						|
}
 | 
						|
 | 
						|
/* Convert a 4-char string object argument to an OSType value */
 | 
						|
int
 | 
						|
PyMac_GetOSType(PyObject *v, OSType *pr)
 | 
						|
{
 | 
						|
	if (!PyString_Check(v) || PyString_Size(v) != 4) {
 | 
						|
		PyErr_SetString(PyExc_TypeError,
 | 
						|
			"OSType arg must be string of 4 chars");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	memcpy((char *)pr, PyString_AsString(v), 4);
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
/* Convert an OSType value to a 4-char string object */
 | 
						|
PyObject *
 | 
						|
PyMac_BuildOSType(OSType t)
 | 
						|
{
 | 
						|
	return PyString_FromStringAndSize((char *)&t, 4);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Convert a Python string object to a Str255 */
 | 
						|
int
 | 
						|
PyMac_GetStr255(PyObject *v, Str255 pbuf)
 | 
						|
{
 | 
						|
	int len;
 | 
						|
	if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
 | 
						|
		PyErr_SetString(PyExc_TypeError,
 | 
						|
			"Str255 arg must be string of at most 255 chars");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	pbuf[0] = len;
 | 
						|
	memcpy((char *)(pbuf+1), PyString_AsString(v), len);
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
/* Convert a Str255 to a Python string object */
 | 
						|
PyObject *
 | 
						|
PyMac_BuildStr255(Str255 s)
 | 
						|
{
 | 
						|
	return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
** Convert a Python object to an FSSpec.
 | 
						|
** The object may either be a full pathname or a triple
 | 
						|
** (vrefnum, dirid, path).
 | 
						|
** NOTE: This routine will fail on pre-sys7 machines. 
 | 
						|
** The caller is responsible for not calling this routine
 | 
						|
** in those cases (which is fine, since everyone calling
 | 
						|
** this is probably sys7 dependent anyway).
 | 
						|
*/
 | 
						|
int
 | 
						|
PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
 | 
						|
{
 | 
						|
	Str255 path;
 | 
						|
	short refnum;
 | 
						|
	long parid;
 | 
						|
	OSErr err;
 | 
						|
	FSSpec *fs2;
 | 
						|
 | 
						|
	/* first check whether it already is an FSSpec */
 | 
						|
	fs2 = mfs_GetFSSpecFSSpec(v);
 | 
						|
	if ( fs2 ) {
 | 
						|
		(void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, 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 fullpath or (vrefnum,dirid,path)",
 | 
						|
							&refnum, &parid, PyMac_GetStr255, &path)) {
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	err = FSMakeFSSpec(refnum, parid, path, fs);
 | 
						|
	if ( err && err != fnfErr ) {
 | 
						|
		PyErr_Mac(PyExc_ValueError, err);
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Convert a Python object to a Rect.
 | 
						|
   The object must be a (left, top, right, bottom) tuple.
 | 
						|
   (This differs from the order in the struct but is consistent with
 | 
						|
   the arguments to SetRect(), and also with STDWIN). */
 | 
						|
int
 | 
						|
PyMac_GetRect(PyObject *v, Rect *r)
 | 
						|
{
 | 
						|
	return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
 | 
						|
}
 | 
						|
 | 
						|
/* Convert a Rect to a Python object */
 | 
						|
PyObject *
 | 
						|
PyMac_BuildRect(Rect *r)
 | 
						|
{
 | 
						|
	return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Convert a Python object to a Point.
 | 
						|
   The object must be a (h, v) tuple.
 | 
						|
   (This differs from the order in the struct but is consistent with
 | 
						|
   the arguments to SetPoint(), and also with STDWIN). */
 | 
						|
int
 | 
						|
PyMac_GetPoint(PyObject *v, Point *p)
 | 
						|
{
 | 
						|
	return PyArg_Parse(v, "(hh)", &p->h, &p->v);
 | 
						|
}
 | 
						|
 | 
						|
/* Convert a Point to a Python object */
 | 
						|
PyObject *
 | 
						|
PyMac_BuildPoint(Point p)
 | 
						|
{
 | 
						|
	return Py_BuildValue("(hh)", p.h, p.v);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Convert a Python object to an EventRecord.
 | 
						|
   The object must be a (what, message, when, (v, h), modifiers) tuple. */
 | 
						|
int
 | 
						|
PyMac_GetEventRecord(PyObject *v, EventRecord *e)
 | 
						|
{
 | 
						|
	return PyArg_Parse(v, "(hll(hh)h)",
 | 
						|
	                   &e->what,
 | 
						|
	                   &e->message,
 | 
						|
	                   &e->when,
 | 
						|
	                   &e->where.h,
 | 
						|
	                   &e->where.v,                   
 | 
						|
	                   &e->modifiers);
 | 
						|
}
 | 
						|
 | 
						|
/* Convert a Rect to an EventRecord object */
 | 
						|
PyObject *
 | 
						|
PyMac_BuildEventRecord(EventRecord *e)
 | 
						|
{
 | 
						|
	return Py_BuildValue("(hll(hh)h)",
 | 
						|
	                     e->what,
 | 
						|
	                     e->message,
 | 
						|
	                     e->when,
 | 
						|
	                     e->where.h,
 | 
						|
	                     e->where.v,
 | 
						|
	                     e->modifiers);
 | 
						|
}
 |