mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	 e8e8ae0f2c
			
		
	
	
		e8e8ae0f2c
		
	
	
	
	
		
			
			cycles for background apps. MacOS has a new method to set the amount of time for bg apps.
		
			
				
	
	
		
			388 lines
		
	
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
	
		
			9.2 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 <OSUtils.h> /* for Set(Current)A5 */
 | |
| #include <Files.h>
 | |
| #include <Resources.h>
 | |
| #include <Memory.h>
 | |
| #include <Events.h>
 | |
| #include <Windows.h>
 | |
| #include <Desk.h>
 | |
| #include <Traps.h>
 | |
| 
 | |
| #ifdef __MWERKS__
 | |
| #include <SIOUX.h>
 | |
| #endif /* __MWERKS__ */
 | |
| 
 | |
| #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();
 | |
| 
 | |
| /*
 | |
| ** 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 stdwin (or 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, in_background;
 | |
| 
 | |
| /* 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;
 | |
| }
 | |
| 
 | |
| /* Replace strerror with something that might work */
 | |
| char *macstrerror(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]);
 | |
| 		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 = macstrerror(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);
 | |
| }
 | |
| 
 | |
| /*
 | |
| ** 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;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ** Yield the CPU to other tasks.
 | |
| */
 | |
| static
 | |
| PyMac_DoYield()
 | |
| {
 | |
| 	EventRecord ev;
 | |
| 	WindowPtr wp;
 | |
| 	long yield;
 | |
| 	extern int StdwinIsActive;
 | |
| 	static int no_waitnextevent = -1;
 | |
| 	int gotone;
 | |
| 	
 | |
| 	if ( no_waitnextevent < 0 ) {
 | |
| 		no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
 | |
| 							NGetTrapAddress(_Unimplemented, ToolTrap));
 | |
| 	}
 | |
| 
 | |
| 	if ( StdwinIsActive )
 | |
| 		return;
 | |
| 		
 | |
| 	if ( in_background )
 | |
| 		yield = yield_bg;
 | |
| 	else
 | |
| 		yield = yield_fg;
 | |
| 	while ( 1 ) {
 | |
| 		if ( no_waitnextevent ) {
 | |
| 			SystemTask();
 | |
| 			gotone = GetNextEvent(0xffff, &ev);
 | |
| 		} else {
 | |
| 			gotone = WaitNextEvent(everyEvent, &ev, yield, NULL);
 | |
| 		}	
 | |
| 		/* Get out quickly if nothing interesting is happening */
 | |
| 		if ( !gotone || ev.what == nullEvent )
 | |
| 			break;
 | |
| 			
 | |
| 		/* Check whether we've moved to foreground or background */
 | |
| 		if ( ev.what == osEvt &&
 | |
| 		         (ev.message & osEvtMessageMask) == (suspendResumeMessage<<24)) {
 | |
| 			if ( ev.message & resumeFlag ) {
 | |
| 				in_background = 0;
 | |
| 			} else {
 | |
| 				in_background = 1;
 | |
| 			}
 | |
| 		}
 | |
| #ifdef __MWERKS__
 | |
| 		/* If SIOUX wants it we're done too */
 | |
| 		(void)SIOUXHandleOneEvent(&ev);
 | |
| #else
 | |
| 		/* Other compilers are just unlucky: we only weed out clicks in other applications */
 | |
| 		if ( ev.what == mouseDown ) {
 | |
| 			if ( FindWindow(ev.where, &wp) == inSysWindow )
 | |
| 				SystemClick(&ev, wp);
 | |
| 		}
 | |
| #endif /* !__MWERKS__ */
 | |
| 	}
 | |
| 	lastyield = TickCount();
 | |
| }
 | |
| 
 | |
| /*
 | |
| ** Yield the CPU to other tasks if opportune
 | |
| */
 | |
| void
 | |
| PyMac_Yield() {
 | |
| 	long iv;
 | |
| 	
 | |
| 	if ( in_background )
 | |
| 		iv = interval_bg;
 | |
| 	else
 | |
| 		iv = interval_fg;
 | |
| 	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();
 | |
| }
 | |
| 
 | |
| 
 | |
| /* 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 ) {
 | |
| 		fs = fs2;
 | |
| 		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 (top, left, bottom, right) tuple.
 | |
|    (Unfortunately this is different from STDWIN's convention). */
 | |
| int
 | |
| PyMac_GetRect(PyObject *v, Rect *r)
 | |
| {
 | |
| 	return PyArg_Parse(v, "(hhhh)", &r->top, &r->left, &r->bottom, &r->right);
 | |
| }
 | |
| 
 | |
| /* Convert a Rect to a Python object */
 | |
| PyObject *
 | |
| PyMac_BuildRect(Rect *r)
 | |
| {
 | |
| 	return Py_BuildValue("(hhhh)", r->top, r->left, r->bottom, r->right);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Convert a Python object to a Point.
 | |
|    The object must be a (v, h) tuple.
 | |
|    (Unfortunately this is different from STDWIN's convention). */
 | |
| int
 | |
| PyMac_GetPoint(PyObject *v, Point *p)
 | |
| {
 | |
| 	return PyArg_Parse(v, "(hh)", &p->v, &p->h);
 | |
| }
 | |
| 
 | |
| /* Convert a Point to a Python object */
 | |
| PyObject *
 | |
| PyMac_BuildPoint(Point p)
 | |
| {
 | |
| 	return Py_BuildValue("(hh)", p.v, p.h);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* 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.v,                   
 | |
| 	                   &e->where.h,
 | |
| 	                   &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.v,
 | |
| 	                     e->where.h,
 | |
| 	                     e->modifiers);
 | |
| }
 |