mirror of
				https://github.com/python/cpython.git
				synced 2025-10-29 20:51:26 +00:00 
			
		
		
		
	 7d5f9e847a
			
		
	
	
		7d5f9e847a
		
	
	
	
	
		
			
			- Unified initialization code for interpreter and applet - Implemented new options to skip AE-processing for argc/argv and for disabling interactive option setting
		
			
				
	
	
		
			316 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			316 lines
		
	
	
	
		
			7.8 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.
 | |
| 
 | |
| ******************************************************************/
 | |
| 
 | |
| /* Construct argc and argv for main() by using Apple Events */
 | |
| /* From Jack's implementation for STDWIN */
 | |
| 
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #ifndef SystemSevenOrLater
 | |
| #define SystemSevenOrLater 1
 | |
| #endif
 | |
| 
 | |
| #include <Types.h>
 | |
| #include <Files.h>
 | |
| #include <Events.h>
 | |
| #include <Memory.h>
 | |
| #include <Processes.h>
 | |
| #include <Errors.h>
 | |
| #include <AppleEvents.h>
 | |
| #include <AEObjects.h>
 | |
| #include <Desk.h>
 | |
| #include <Fonts.h>
 | |
| #include <TextEdit.h>
 | |
| #include <Menus.h>
 | |
| #include <Dialogs.h>
 | |
| #include <Windows.h>
 | |
| 
 | |
| #ifdef GENERATINGCFM	/* Defined to 0 or 1 in Universal headers */
 | |
| #define HAVE_UNIVERSAL_HEADERS
 | |
| #endif
 | |
| 
 | |
| #ifdef SYMANTEC__CFM68K__
 | |
| #pragma lib_export on
 | |
| #endif
 | |
| 
 | |
| #ifndef HAVE_UNIVERSAL_HEADERS
 | |
| #define NewAEEventHandlerProc(x) (x)
 | |
| #define AEEventHandlerUPP EventHandlerProcPtr
 | |
| #endif
 | |
| 
 | |
| static int arg_count;
 | |
| static char *arg_vector[256];
 | |
| 
 | |
| /* Duplicate a string to the heap. We also export this since it isn't standard
 | |
| ** and others use it
 | |
| */
 | |
| 
 | |
| char *
 | |
| strdup(char *src)
 | |
| {
 | |
| 	char *dst = malloc(strlen(src) + 1);
 | |
| 	if (dst)
 | |
| 		strcpy(dst, src);
 | |
| 	return dst;
 | |
| }
 | |
| 
 | |
| /* Return FSSpec of current application */
 | |
| 
 | |
| OSErr
 | |
| PyMac_process_location(FSSpec *applicationSpec)
 | |
| {
 | |
| 	ProcessSerialNumber currentPSN;
 | |
| 	ProcessInfoRec info;
 | |
| 	
 | |
| 	currentPSN.highLongOfPSN = 0;
 | |
| 	currentPSN.lowLongOfPSN = kCurrentProcess;
 | |
| 	info.processInfoLength = sizeof(ProcessInfoRec);
 | |
| 	info.processName = NULL;
 | |
| 	info.processAppSpec = applicationSpec;
 | |
| 	return GetProcessInformation(¤tPSN, &info);
 | |
| }
 | |
| 
 | |
| /* Given an FSSpec, return the FSSpec of the parent folder */
 | |
| 
 | |
| static OSErr
 | |
| get_folder_parent (FSSpec * fss, FSSpec * parent)
 | |
| {
 | |
| 	CInfoPBRec rec;
 | |
| 	short err;
 | |
| 
 | |
|         * parent = * fss;
 | |
|         rec.hFileInfo.ioNamePtr = parent->name;
 | |
|         rec.hFileInfo.ioVRefNum = parent->vRefNum;
 | |
|         rec.hFileInfo.ioDirID = parent->parID;
 | |
| 		rec.hFileInfo.ioFDirIndex = -1;
 | |
|         rec.hFileInfo.ioFVersNum = 0;
 | |
|         if (err = PBGetCatInfoSync (& rec))
 | |
|         	return err;
 | |
|         parent->parID = rec.dirInfo.ioDrParID;
 | |
| /*	parent->name[0] = 0; */
 | |
|         return 0;
 | |
| }
 | |
| 
 | |
| /* Given an FSSpec return a full, colon-separated pathname */
 | |
| 
 | |
| static OSErr
 | |
| get_full_path (FSSpec *fss, char *buf)
 | |
| {
 | |
| 	short err;
 | |
| 	FSSpec fss_parent, fss_current;
 | |
| 	char tmpbuf[256];
 | |
| 	int plen;
 | |
| 
 | |
| 	fss_current = *fss;
 | |
| 	plen = fss_current.name[0];
 | |
| 	memcpy(buf, &fss_current.name[1], plen);
 | |
| 	buf[plen] = 0;
 | |
| 	while (fss_current.parID > 1) {
 | |
|     		/* Get parent folder name */
 | |
|                 if (err = get_folder_parent(&fss_current, &fss_parent))
 | |
|              		return err;
 | |
|                 fss_current = fss_parent;
 | |
|                 /* Prepend path component just found to buf */
 | |
|     			plen = fss_current.name[0];
 | |
|     			if (strlen(buf) + plen + 1 > 256) {
 | |
|     				/* Oops... Not enough space (shouldn't happen) */
 | |
|     				*buf = 0;
 | |
|     				return -1;
 | |
|     			}
 | |
|     			memcpy(tmpbuf, &fss_current.name[1], plen);
 | |
|     			tmpbuf[plen] = ':';
 | |
|     			strcpy(&tmpbuf[plen+1], buf);
 | |
|     			strcpy(buf, tmpbuf);
 | |
|         }
 | |
|         return 0;
 | |
| }
 | |
| 
 | |
| /* Return the full program name */
 | |
| 
 | |
| static char *
 | |
| get_application_name()
 | |
| {
 | |
| 	static char appname[256];
 | |
| 	FSSpec appspec;
 | |
| 	
 | |
| 	if (PyMac_process_location(&appspec))
 | |
| 		return NULL;
 | |
| 	if (get_full_path(&appspec, appname))
 | |
| 		return NULL;
 | |
| 	return appname;
 | |
| }
 | |
| 
 | |
| /* Check that there aren't any args remaining in the event */
 | |
| 
 | |
| static OSErr 
 | |
| get_missing_params(AppleEvent *theAppleEvent)
 | |
| {
 | |
| 	DescType theType;
 | |
| 	Size actualSize;
 | |
| 	OSErr err;
 | |
| 	
 | |
| 	err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
 | |
| 				&theType, nil, 0, &actualSize);
 | |
| 	if (err == errAEDescNotFound)
 | |
| 		return noErr;
 | |
| 	else
 | |
| 		return errAEEventNotHandled;
 | |
| }
 | |
| 
 | |
| static int got_one; /* Flag that we can stop getting events */
 | |
| 
 | |
| /* Handle the Print or Quit events (by failing) */
 | |
| 
 | |
| static pascal OSErr
 | |
| handle_not(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
 | |
| {
 | |
| 	#pragma unused (reply, refCon)
 | |
| 	got_one = 1;
 | |
| 	return errAEEventNotHandled;
 | |
| }
 | |
| 
 | |
| /* Handle the Open Application event (by ignoring it) */
 | |
| 
 | |
| static pascal OSErr
 | |
| handle_open_app(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
 | |
| {
 | |
| 	#pragma unused (reply, refCon)
 | |
| #if 0
 | |
| 	/* Test by Jack: would removing this facilitate debugging? */
 | |
| 	got_one = 1;
 | |
| #endif
 | |
| 	return get_missing_params(theAppleEvent);
 | |
| }
 | |
| 
 | |
| /* Handle the Open Document event, by adding an argument */
 | |
| 
 | |
| static pascal OSErr
 | |
| handle_open_doc(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
 | |
| {
 | |
| 	#pragma unused (reply, refCon)
 | |
| 	OSErr err;
 | |
| 	AEDescList doclist;
 | |
| 	AEKeyword keywd;
 | |
| 	DescType rttype;
 | |
| 	long i, ndocs, size;
 | |
| 	FSSpec fss;
 | |
| 	char path[256];
 | |
| 	
 | |
| 	got_one = 1;
 | |
| 	if (err = AEGetParamDesc(theAppleEvent,
 | |
| 				 keyDirectObject, typeAEList, &doclist))
 | |
| 		return err;
 | |
| 	if (err = get_missing_params(theAppleEvent))
 | |
| 		return err;
 | |
| 	if (err = AECountItems(&doclist, &ndocs))
 | |
| 		return err;
 | |
| 	for(i = 1; i <= ndocs; i++) {
 | |
| 		err = AEGetNthPtr(&doclist, i, typeFSS,
 | |
| 				  &keywd, &rttype, &fss, sizeof(fss), &size);
 | |
| 		if (err)
 | |
| 			break;
 | |
| 		get_full_path(&fss, path);
 | |
| 		arg_vector[arg_count++] = strdup(path);
 | |
| 	}
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| /* Install standard core event handlers */
 | |
| AEEventHandlerUPP open_doc_upp;
 | |
| AEEventHandlerUPP open_app_upp;
 | |
| AEEventHandlerUPP not_upp;
 | |
| 
 | |
| static void
 | |
| set_ae_handlers()
 | |
| {
 | |
| 	open_doc_upp = NewAEEventHandlerProc(handle_open_doc);
 | |
| 	open_app_upp = NewAEEventHandlerProc(handle_open_app);
 | |
| 	not_upp = NewAEEventHandlerProc(handle_not);
 | |
| 	
 | |
| 	AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
 | |
| 			      open_app_upp, 0L, false);
 | |
| 	AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
 | |
| 			      open_doc_upp, 0L, false);
 | |
| 	AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
 | |
| 			      not_upp, 0L, false);
 | |
| 	AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
 | |
| 			      not_upp, 0L, false);
 | |
| }
 | |
| 
 | |
| /* Uninstall standard core event handlers */
 | |
| 
 | |
| static void
 | |
| reset_ae_handlers()
 | |
| {
 | |
| 	AERemoveEventHandler(kCoreEventClass, kAEOpenApplication,
 | |
| 			     open_app_upp, false);
 | |
| 	AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments,
 | |
| 			     open_doc_upp, false);
 | |
| 	AERemoveEventHandler(kCoreEventClass, kAEPrintDocuments,
 | |
| 			     not_upp, false);
 | |
| 	AERemoveEventHandler(kCoreEventClass, kAEQuitApplication,
 | |
| 			     not_upp, false);
 | |
| }
 | |
| 
 | |
| /* Wait for events until a core event has been handled */
 | |
| 
 | |
| static void 
 | |
| event_loop()
 | |
| {
 | |
| 	EventRecord event;
 | |
| 	int n;
 | |
| 	int ok;
 | |
| 	
 | |
| 	got_one = 0;
 | |
| 	for (n = 0; n < 100 && !got_one; n++) {
 | |
| 		SystemTask();
 | |
| 		ok = GetNextEvent(everyEvent, &event);
 | |
| 		if (ok && event.what == kHighLevelEvent) {
 | |
| 			AEProcessAppleEvent(&event);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Get the argv vector, return argc */
 | |
| 
 | |
| int
 | |
| PyMac_GetArgv(pargv, noevents)
 | |
| 	char ***pargv;
 | |
| 	int noevents;
 | |
| {
 | |
| 	
 | |
| 	arg_count = 0;
 | |
| 	arg_vector[arg_count++] = strdup(get_application_name());
 | |
| 	
 | |
| 	if( !noevents ) {
 | |
| 		set_ae_handlers();
 | |
| 		event_loop();
 | |
| 		reset_ae_handlers();
 | |
| 	}
 | |
| 	
 | |
| 	arg_vector[arg_count] = NULL;
 | |
| 	
 | |
| 	*pargv = arg_vector;
 | |
| 	return arg_count;
 | |
| }
 |