landsystem7.c

Go to the documentation of this file.
00001 
00002 /*  $Id: landsystem7.c 1191 2006-04-05 21:18:25Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "landinternal.h"
00032 
00033 #include "shell.h"
00034 #include "langinternal.h"
00035 #include "process.h"
00036 
00037 #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00038     #include "aeutils.h" /*PBS 03/14/02: AE OS X fix.*/
00039 #endif
00040 
00041 #ifdef flcomponent
00042     
00043     #include <SetUpA5.h>
00044     
00045     typedef pascal OSErr (*AESendCallback)(
00046                             const AppleEvent*   theAppleEvent,
00047                             AppleEvent*         reply,
00048                             AESendMode          sendMode,
00049                             AESendPriority      sendPriority,
00050                             long                timeOutInTicks,
00051                             
00052                             AEIdleUPP           idleProc, 
00053                             AEFilterUPP         filterProc);
00054     
00055     typedef pascal OSErr (*AECreateAppleEventCallback)(
00056                             AEEventClass            theAEEventClass,
00057                             AEEventID               theAEEventID,
00058                             const AEAddressDesc*    target,
00059                             short                   returnID,
00060                             long                    transactionID,
00061                             AppleEvent*             result);
00062 #endif
00063 
00064 
00065 
00066 #define ctappletypes 24
00067 
00068 #define unknownerror -1
00069 
00070 #define typeTargetID 'targ'
00071 #define typeSessionID 'ssid'
00072 
00073 typedef DescType **hdldesctype;
00074 
00075 
00076 typedef struct tysys7transportinfo { 
00077     
00078     hdlprocessthread hthread; /*must be first field*/
00079     
00080     /*note: AppleEvent records, not addresses, must be used to allow multiple thread accesss*/
00081     
00082     AppleEvent sys7message; /*in case a user ever needs access*/
00083     
00084     AppleEvent sys7reply; /*used internally to build reply*/
00085     
00086     boolean flownmessage; /*is message data owned by verb?*/
00087     
00088     boolean flownreply; /*is reply data owned by verb?*/
00089     
00090     boolean flnetwork: 1;
00091     
00092     boolean flprocessid: 1;
00093     
00094     boolean fltimedout: 1;
00095     
00096     boolean fluseraborted: 1;
00097     
00098     boolean fltoself: 1;
00099     
00100     boolean flsuspended: 1;
00101     
00102     ProcessSerialNumber receiverpsn; /*if a receiver's psn was provided by caller, here it is*/
00103     
00104     tynetworkaddress networkaddress; /*if it's a network verb, this is where it's going*/
00105     
00106     short replyid;
00107     
00108     unsigned long waketime; /*when hthread should be awakened (timeout)*/
00109     
00110     } tysys7transportinfo, *ptrsys7transportinfo, **hdlsys7transportinfo;
00111 
00112 
00113 typedef struct tylandprocessvisitinfo {
00114     tyapplicationid idrunningprocess;
00115     } tylandprocessvisitinfo;
00116 
00117 typedef struct tylandprocessvisitinfo *tylandprocessvisitinfoptr;
00118 
00119 
00120 static void suspendcurrentevent(AppleEvent *ev) {
00121 
00122     /*
00123     2002-12-04 AR: Hack to work around bug in Mac OS X 10.2.2
00124     as suggested by Steve Zellers at Apple.
00125     */
00126     
00127     static long sysversion = 0L;
00128     
00129     if (sysversion == 0)
00130         Gestalt (gestaltSystemVersion, &sysversion);
00131     
00132     if (sysversion == 0x1022L) {
00133     
00134         AEEventID eventID;
00135         DescType typeCode;
00136         Size ctbytes;
00137         
00138         if (AEGetAttributePtr(ev, keyEventIDAttr, typeType, &typeCode,
00139                 (void*) &eventID, sizeof(eventID), &ctbytes) == noErr) {
00140                 
00141             if (typeCode == typeType && ctbytes == sizeof(eventID) && eventID == kAEAnswer) {
00142             
00143                 long **h = (long**) ev->dataHandle;
00144                 long *p = *h;
00145                 
00146                 p[2]++; /*increment the reference count of reply records*/
00147                 }
00148             }
00149         }
00150     
00151     AESuspendTheCurrentEvent (ev);
00152     
00153     return;
00154     } /*suspendcurrentevent*/
00155 
00156 /*
00157   pascal OSErr EventDirectFromSelf(AppleEvent * theAppleEventPtr, Boolean * directFlagPtr)
00158   // Extract the event source attribute and check if it indicates that
00159   // the event was directly dispatched.
00160   {
00161     short theEventSource;
00162     DescType actualType;
00163     Size actualSize;
00164     OSErr retCode;
00165     
00166     retCode = AEGetAttributePtr(theAppleEventPtr, keyEventSourceAttr,
00167       typeShortInteger, &actualType, (Ptr) &theEventSource, sizeof(short),
00168       &actualSize);
00169     
00170     if (retCode == noErr && theEventSource == (short) kAEDirectCall)
00171       *directFlagPtr = true;
00172     else *directFlagPtr = false;
00173     
00174     return retCode;
00175   }
00176 */
00177 
00178 
00179 #if TARGET_API_MAC_OS8
00180 
00181 static void MakePascalStringWLen (StringPtr theDest, int theDestLen, char *theSrc, int theSrcLen) {
00182     
00183     /*
00184     10/22/91 dmb: imported this code from Leonard Rosenthal.  Reformmatted 
00185     somewhat, but left variable names as he had them.  comments are his.
00186     
00187     Given a C string, put it into a pascal storage area.    We also make
00188     sure that the length of the pascal string isn't too long (the caller
00189     specifiys the longest length possible). We are passed in the length
00190     of the C string... This makes our life simpler...
00191     */
00192     
00193     theDest [0] = theSrcLen > theDestLen ? theDestLen : theSrcLen;
00194     
00195     BlockMove (theSrc, &(theDest[1]), theDest [0]);
00196     } /*MakePascalStringWLen*/
00197 
00198 
00199 static OSErr HCProgramToPortAndLoc (char *theName, short len, LocationNameRec *theLoc, PortInfoRec *thePort) {
00200     
00201     /*
00202     10/22/91 dmb: imported this code from Leonard Rosenthal.  Reformmatted 
00203     somewhat, but left variable names as he had them.  comments are his.
00204     
00205     Convert a Hypercard program name (<zone>:<mac>:<program>) to a port.
00206     If that program has more than one port open, we take the first port 
00207     we find!
00208     */
00209     
00210     char *appleZone = 0;
00211     char *macName = 0;
00212     char *progName = 0;
00213     char *theLastChar = 0;
00214     PPCPortRec thePortSearchSpec;
00215     IPCListPortsPBRec thePBRec;
00216     int theErr;
00217     
00218     /*
00219     Assemble a location.    This is a bit of a pain, as we must
00220     carefully unpack the incomming string...
00221     */
00222     
00223     /*
00224     First job -- find the end of the incomming string so we don't
00225     run off into memory...
00226     */
00227     
00228     theLastChar = theName;
00229     
00230     appleZone = theName; /* First thing there... */
00231     
00232     while (--len >= 0) {
00233         
00234         if (*theLastChar == ':') {
00235             
00236             if (!macName) {
00237                 
00238                 macName = theLastChar + 1;
00239                 }
00240             else if (!progName) {
00241                 
00242                 progName = theLastChar + 1;
00243                 }
00244             }
00245         
00246         theLastChar++;
00247         }
00248     
00249     /*
00250     Right, make sure that we got everything...
00251     */
00252     
00253     if ((progName == 0) || (macName == 0))
00254         return (1); /* Random error... */
00255     
00256     /*
00257     Next, assemble a port record that we can use to specify what
00258     the hell we are looking for...  Use a roman script (sorry, guys),
00259     match only names that have our program, and match all types.
00260     That way we will get the first type.
00261     */
00262     
00263     thePortSearchSpec.nameScript = smRoman;
00264     
00265     thePortSearchSpec.portKindSelector = ppcByString;
00266     
00267     MakePascalStringWLen ((StringPtr) thePortSearchSpec.name, 32, progName, (Size)(theLastChar - progName));
00268     
00269     MakePascalStringWLen ((StringPtr) thePortSearchSpec.u.portTypeStr, 32, "=", 1);
00270     
00271     /*
00272     Next job is to fill in the location record that the guy passed
00273     in. The objString is the mac we wish to connect to. The zone
00274     is the apple zone.  We let the type be random...    so we set it
00275     to PPCToolBox as defined by IM VI 6 7-23.
00276     */
00277     
00278     theLoc -> locationKindSelector = ppcNBPLocation;
00279     
00280     /*bundle*/ {
00281         
00282         register EntityName *theE = &(theLoc -> u.nbpEntity);
00283     
00284         MakePascalStringWLen ((StringPtr) &(theE -> objStr), 32, macName, (int) (progName - macName - 1));
00285         
00286         MakePascalStringWLen ((StringPtr) &(theE -> typeStr), 32, "PPCToolBox", 10);
00287         
00288         MakePascalStringWLen ((StringPtr) &(theE -> zoneStr), 32, appleZone, (macName - appleZone - 1));
00289         }
00290     
00291     /*
00292     Right.  Finally, we fill in the parameter block we are to pass
00293     to IPCListPorts.
00294     */
00295     
00296     thePBRec.startIndex = 0;
00297     thePBRec.requestCount = 1;
00298     thePBRec.portName = &thePortSearchSpec;
00299     thePBRec.locationName = theLoc;
00300     thePBRec.bufferPtr = thePort;
00301     
00302     /*
00303     Call the damm routine and try to get the stupid port back!
00304     */
00305     theErr = IPCListPortsSync (&thePBRec);
00306         
00307     return (theErr);
00308     } /*HCProgramToPortAndLoc*/
00309 
00310 #endif
00311 
00312 
00313 static boolean isthisprocess (ProcessSerialNumber *targetPSN) {
00314     
00315     register OSErr err;
00316     Boolean flsame = false; 
00317     
00318     ProcessSerialNumber psn;
00319     
00320     GetCurrentProcess (&psn);
00321     
00322     err = SameProcess (targetPSN, &psn, &flsame);
00323     
00324     if (err != noErr)
00325         return (false);
00326     
00327     return (flsame);
00328     } /*isthisprocess*/
00329 
00330 
00331 static boolean landchecksameprocess (tynetworkaddress *adr) {
00332 #if TARGET_API_MAC_CARBON == 1
00333 #   pragma unused (adr)
00334 #endif
00335     /*
00336     3/9/92 dmb: if GetProcessSerialNumberFromPortName returns an error, leave 
00337     flsendingtoself false, but return true.  adr may be a valid port that 
00338     doesn't have a psn
00339     */
00340     
00341     #if TARGET_API_MAC_CARBON == 1
00342     //what the hell do I do here?
00343     return true;
00344     #else
00345         
00346     register OSErr err;
00347     ProcessSerialNumber targetPSN;
00348     
00349     if (!(*adr).target.location.locationKindSelector) { /*might be sending to ourself*/
00350         
00351         err = GetProcessSerialNumberFromPortName (&(*adr).target.name, &targetPSN);
00352         
00353         if (err == noErr)
00354             return (isthisprocess (&targetPSN));
00355         }
00356     
00357     return (false);
00358     #endif
00359         
00360     } /*landchecksameprocess*/
00361 
00362 
00363 #if TARGET_API_MAC_OS8
00364 
00365 static boolean goodstring32 (byte s32 []) {
00366     
00367     register byte *s = s32;
00368     register short len = *s;
00369     
00370     if ((len == 0) || (len > 32))
00371         return (false);
00372     
00373     while (--len >= 0) {
00374         
00375         if ((*++s) < ' ') /*non-printing character*/
00376             return (false);
00377         }
00378     
00379     return (true);
00380     } /*goodstring32*/
00381 
00382 
00383 pascal boolean landstring2networkaddress (ConstStr255Param bsadr, tynetworkaddress *adr) {
00384     
00385     /*
00386     10/27/91 dmb: even when HCProgramToPortAndLoc's IPCListPorts call returns noErr,
00387     the network address may be invalid.  so a reality check is done on the port name 
00388     to attempt to verify that something has actually been found
00389     */
00390     
00391     register hdllandglobals hg = landgetglobals ();
00392     LocationNameRec loc;
00393     PortInfoRec port;
00394     register OSErr err;
00395     
00396     if ((**hg).transport == macsystem6) /*can't call do networks on System 6*/
00397         return (false);
00398     
00399     err = HCProgramToPortAndLoc ((char *) bsadr + 1, stringlength (bsadr), &loc, &port);
00400     
00401     if (err != noErr) {
00402         
00403         landseterror (err);
00404         
00405         return (false);
00406         }
00407     
00408     if (!goodstring32 (port.name.name)) { /*make sure it actually found something*/
00409         
00410         landseterror (noResponseErr);
00411         
00412         return (false);
00413         }
00414     
00415     (*adr).target.sessionID = 0;
00416     
00417     (*adr).target.location = loc;
00418     
00419     (*adr).target.name = port.name;
00420     
00421     /*
00422     return (landchecksameprocess (adr));
00423     */
00424     
00425     return (true);
00426     } /*landstring2networkaddress*/
00427 
00428 #else
00429 
00430 pascal boolean landstring2networkaddress (ConstStr255Param bsadr, tynetworkaddress *adr) {
00431 #pragma unused (bsadr, adr)
00432     /*
00433     2004-10-21 aradke: Can't do this on Carbon, send back a bogus error.
00434     */
00435     
00436     landseterror (noResponseErr);
00437     
00438     return (false);
00439     } /*landstring2networkaddress*/
00440 
00441 #endif
00442 
00443 
00444 #if !TARGET_API_MAC_CARBON
00445     //Code change by Timothy Paustian Friday, July 21, 2000 10:40:43 PM
00446     //we don't do anything on Carbon because we can't use this anyway.
00447 
00448 static pascal Boolean landbrowserfilter (LocationNamePtr ln, PortInfoPtr port) {
00449 #pragma unused (ln)
00450     
00451     register hdllandglobals hg;
00452     register tyapplicationid id;
00453     long type;
00454     
00455     #ifdef flcomponent
00456         long curA5 = SetUpAppA5 ();
00457     #endif
00458     
00459     hg = landgetglobals ();
00460     
00461     id = (**hg).macnetglobals.idforbrowser;
00462     
00463     #ifdef flcomponent
00464         RestoreA5 (curA5);
00465     #endif
00466     
00467     if (id == 0) /*no filtering, everything qualifies*/
00468         return (true);
00469         
00470     if ((*port).name.portKindSelector != ppcByString) /*MacDTS magic*/
00471         return (false);
00472         
00473     BlockMove ((*port).name.u.portTypeStr + 1, (Ptr) &type, 4); /*MacDTS magic*/
00474     
00475     return (type == id);
00476     } /*landbrowserfilter*/
00477 
00478 
00479     #if !TARGET_RT_MAC_CFM
00480 
00481         #define landbrowserfilterUPP (&landbrowserfilter)
00482 
00483     #else
00484                 
00485         static RoutineDescriptor landbrowserfilterDesc = BUILD_ROUTINE_DESCRIPTOR (uppPPCFilterProcInfo, landbrowserfilter);
00486 
00487         #define landbrowserfilterUPP (&landbrowserfilterDesc)
00488     
00489     #endif
00490     
00491 #endif
00492 
00493 
00494 pascal boolean landbrowsenetworkapps (ConstStr255Param bsprompt, tynetworkaddress *adr, tyapplicationid id) {
00495 #if TARGET_API_MAC_CARBON
00496 #   pragma unused (bsprompt, adr, id)
00497 #endif
00498     /*
00499     7/15/91 DW: return false on system 6.
00500     
00501     2/10/92 dmb: added call to new shellactivate.  also, don't hardcode own default strings
00502     
00503     6/8/92 dmb: use landseterror to communicate error code to caller
00504     */
00505     
00506     #if !TARGET_API_MAC_CARBON
00507     register hdllandglobals hg = landgetglobals ();
00508     register OSErr err;
00509     register boolean senddirect = false;
00510     LocationNameRec loc;
00511     PortInfoRec port;
00512     PPCFilterUPP filter = landbrowserfilterUPP;
00513     long appA5;
00514     
00515     if ((**hg).transport == macsystem6) /*can't call PPCBrowser on System 6*/
00516         return (false);
00517     
00518     (**hg).macnetglobals.idforbrowser = id; /*for communication with landbrowserfilter*/
00519     
00520     shellactivate ();
00521     
00522     loc = (*adr).target.location;
00523     
00524     port.name = (*adr).target.name;
00525     
00526     #ifdef flcomponent
00527     
00528         appA5 = SetUpCurA5 (); /*for system*/
00529     
00530     #endif
00531     
00532     err = PPCBrowser (
00533             
00534             bsprompt, (ConstStr255Param) nil, true, &loc, &port, filter, nil);
00535     
00536     #ifdef flcomponent
00537     
00538         RestoreA5 (appA5);
00539     
00540     #endif
00541     
00542     if (err != noErr) { /*user cancelled the browser*/
00543         
00544         landseterror (err);
00545         
00546         return (false);
00547         }
00548     
00549     (**hg).macnetglobals.flhavebrowsed = true; /*default to the same port next time*/
00550     
00551     (*adr).target.sessionID = 0;
00552     
00553     (*adr).target.location = loc;
00554     
00555     (*adr).target.name = port.name;
00556     
00557     /*
00558     return (landchecksameprocess (adr));
00559     */
00560     
00561     return (true);
00562     #else
00563     return false;
00564     #endif
00565 
00566     } /*landbrowsenetworkapps*/
00567 
00568 
00569 pascal OSErr landgetverbattr (hdlverbrecord hverb, OSType attrkey, DescType type, AEDesc *attrdata) {
00570     
00571     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hverb).transportinfo;
00572     AppleEvent event = (**ht).sys7message;
00573     
00574     return (AEGetAttributeDesc (&event, (AEKeyword) attrkey, type, attrdata));
00575     } /*landgetverbattr*/
00576 
00577 
00578 pascal OSErr landsetverbattr (hdlverbrecord hverb, OSType attrkey, DescType attrtype, const void * attrdata, long attrsize) {
00579     
00580     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hverb).transportinfo;
00581     AppleEvent event = (**ht).sys7message;
00582     
00583     return (AEPutAttributePtr (&event, (AEKeyword) attrkey, attrtype, attrdata, attrsize));
00584     } /*landsetverbattr*/
00585 
00586 
00587 #ifdef flcomponent
00588 
00589 pascal OSErr landsystem7defaultcreate ( AEEventClass theAEEventClass, AEEventID theAEEventID,
00590                     const AEAddressDesc *target, short returnID,
00591                     long transactionID, AppleEvent *result ) {
00592     
00593     return (AECreateAppleEvent(theAEEventClass, theAEEventID, target, returnID, transactionID, result));
00594     } /*landsystem7defaultcreate*/
00595 
00596 
00597 pascal OSErr landsystem7defaultsend (const AppleEvent *theAppleEvent, AppleEvent *reply,
00598         AESendMode sendMode, AESendPriority sendPriority, long timeOutInTicks,
00599         AEIdleUPP idleProc, AEFilterUPP filterProc) {
00600     
00601     return (AESend (theAppleEvent, reply, sendMode, sendPriority, timeOutInTicks, idleProc, filterProc));
00602     } /*landsystem7defaultsend*/
00603 
00604 #endif
00605 
00606 
00607 static boolean landsystem7packverb (hdlverbrecord hverb) {
00608     
00609     /*
00610     pack up all the information in the verb record into an appleevent 
00611     message.
00612     */
00613     
00614     register hdlverbrecord hv = hverb;
00615     AppleEvent evt;
00616     register boolean flselfaddress = false;
00617     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hv).transportinfo;
00618     AEAddressDesc adr;
00619     OSErr errcode;
00620     
00621     if ((**hv).idreceiver == idnull) /*verb is being set up to hold existing event*/
00622         return (true);
00623     
00624     if ((**ht).flnetwork) { /*we have a network address*/
00625         
00626         /*
00627         flselfaddress = (**ht).networkaddress.flself;
00628         */
00629         
00630         flselfaddress = (**ht).fltoself;
00631         
00632         if (!flselfaddress) {
00633             
00634             TargetID tid;
00635             
00636             tid = (**ht).networkaddress.target;
00637             
00638             if (tid.sessionID != 0)
00639                 errcode = AECreateDesc (typeSessionID, (Ptr) &tid.sessionID, sizeof (tid.sessionID), &adr);
00640             else
00641                 errcode = AECreateDesc (typeTargetID, (Ptr) &tid, sizeof (tid), &adr);
00642             }
00643         }
00644     else if ((**ht).flprocessid) { /*we have receiver's process id*/
00645         
00646         ProcessSerialNumber psn = (**ht).receiverpsn;
00647         
00648         flselfaddress = isthisprocess (&psn);
00649         
00650         if (!flselfaddress)
00651             errcode = AECreateDesc (typeProcessSerialNumber, (Ptr) &psn, longsizeof (psn), &adr);
00652         }
00653     else {
00654         
00655         flselfaddress = ((**hv).idreceiver == (**hv).idsender);
00656         
00657         if (!flselfaddress) {
00658             
00659             OSType sig;
00660             
00661             sig = (**hv).idreceiver;
00662             
00663             errcode = AECreateDesc (typeApplSignature, (Ptr) &sig, longsizeof (sig), &adr);
00664             }
00665         }
00666     
00667     if (flselfaddress) { /*send to self*/
00668         
00669         ProcessSerialNumber psn;
00670         
00671         psn.highLongOfPSN = 0;
00672         
00673         psn.lowLongOfPSN =  kCurrentProcess;
00674         
00675         errcode = AECreateDesc (typeProcessSerialNumber, (Ptr) &psn, longsizeof (psn), &adr);
00676         
00677         (**ht).fltoself = true;
00678         }
00679     
00680     if (errcode != noErr)
00681         return (false);
00682     
00683     #ifdef flcomponent
00684         
00685         {
00686         register tyeventcreatecallback cb = (**landgetglobals ()).eventcreatecallback;
00687         
00688         errcode = (*(AECreateAppleEventCallback) cb) (
00689             
00690                 (**hv).verbclass, (**hv).verbtoken, &adr, 
00691                 
00692                 kAutoGenerateReturnID, (**hv).idtransaction, &evt);
00693         }
00694     
00695     #else
00696         
00697         errcode = AECreateAppleEvent (
00698                 
00699                 (**hv).verbclass, (**hv).verbtoken, &adr, 
00700                 
00701                 kAutoGenerateReturnID, (**hv).idtransaction, &evt);
00702     
00703     #endif
00704     
00705     AEDisposeDesc (&adr);
00706     
00707     if (errcode != noErr)
00708         return (false);
00709     
00710     (**ht).sys7message = evt;
00711     
00712     (**ht).flownmessage = true;
00713     
00714     return (true);
00715     } /*landsystem7packverb*/
00716 
00717 
00718 static boolean landsystem7getlongattr (AppleEvent *list, AEKeyword key, DescType type, void *pattr) {
00719     
00720     /*
00721     little layer to make code prettier
00722     */
00723     
00724     OSErr errcode;
00725     long size;
00726     
00727     errcode = AEGetAttributePtr (list, key, type, &type, (Ptr) pattr, longsizeof (long), &size);
00728     
00729     return (errcode == noErr);
00730     } /*landsystem7getlongattr*/
00731 
00732 
00733 static boolean landsystem7eventisdirect (AppleEvent *list) {
00734     
00735     /*
00736     2/19/93 dmb: determine if this event was sent short-curcuit, from this process
00737     */
00738     
00739     OSErr errcode;
00740     long size;
00741     ProcessSerialNumber psn;
00742     DescType type;
00743     
00744     errcode = AEGetAttributePtr (list, keyAddressAttr, typeProcessSerialNumber, &type, (Ptr) &psn, longsizeof (psn), &size);
00745     
00746     if (errcode != noErr)
00747         return (false);
00748     
00749     return ((psn.highLongOfPSN == 0) && (psn.lowLongOfPSN == kCurrentProcess));
00750     } /*landsystem7eventisdirect*/
00751 
00752 
00753 pascal boolean landsystem7unpackverb (AppleEvent *message, AppleEvent *reply, hdlverbrecord *hverb) {
00754     
00755     /*
00756     turn an appleevent into a verb record which is almost operating-system-independent.
00757     */
00758     
00759     register hdllandglobals hg = landgetglobals ();
00760     register hdlverbrecord hv;
00761     register hdlsys7transportinfo ht;
00762     tyverbclass verbclass;
00763     tyverbtoken verbtoken;
00764     long idtransaction;
00765     long ctparams;
00766     boolean fldirect;
00767     
00768     if (!landsystem7getlongattr (message, keyEventIDAttr, typeType, &verbtoken))
00769         return (false);
00770     
00771     if (!landsystem7getlongattr (message, keyEventClassAttr, typeType, &verbclass))
00772         verbclass = nulltoken;
00773     
00774     if (!landsystem7getlongattr (message, keyTransactionIDAttr, typeLongInteger, &idtransaction))
00775         idtransaction = 0;
00776     
00777     if (AECountItems (message, &ctparams) != noErr)
00778         return (false);
00779     
00780     if (!landnewverb (idnull, nil, verbclass, verbtoken, (short) ctparams, hverb))
00781         return (false);
00782     
00783     hv = *hverb; /*copy into register*/
00784     
00785     (**hv).idreceiver = (**hg).applicationid;
00786     
00787     (**hv).idtransaction = idtransaction;
00788     
00789     fldirect = landsystem7eventisdirect (message);
00790     
00791     (**hv).flverbisdirect = fldirect;
00792     
00793     ht = (hdlsys7transportinfo) (**hv).transportinfo;
00794     
00795     (**ht).sys7message = *message;
00796     
00797     if (reply != nil)
00798         (**ht).sys7reply = *reply;
00799     
00800     return (true); /*loop completed, all params popped with no errors*/
00801     } /*landsystem7unpackverb*/
00802 
00803 
00804 static pascal void *eventthreadmain (void *hverb) {
00805     
00806     /*
00807     2.1a7 dmb: geteventrecords before handling the verb (which disposes it)
00808     
00809     4.0.1b1 dmb: pass name of thread to initprocessthread; call exitprocessthread
00810     
00811     4.1b3 dmb: name for initprocessthread is more informative now
00812     */
00813     
00814     register hdlverbrecord hv = (hdlverbrecord) hverb;
00815     AppleEvent event, reply;
00816     FSSpec fs;
00817     OSType signature;
00818     ProcessSerialNumber psn;
00819     byte class [6];
00820     byte token [6];
00821     bigstring bs;
00822     
00823     landsystem7geteventrecords (hv, &event, &reply);
00824     
00825     ostypetostring ((**hv).verbclass, class);
00826     
00827     ostypetostring ((**hv).verbtoken, token);
00828     
00829     if (landsystem7getsenderinfo (&event, &psn, &fs, &signature) != noErr)
00830         ostypetostring ((**hv).idsender, fs.name);
00831     
00832     langgetstringlist (appleeventthreadstring, bs); // "\papple event ['^0', '^1'] from ^2"
00833     
00834     parsedialogstring (bs, class, token, fs.name, nil, bs);
00835     
00836     initprocessthread (bs); /*must call this*/
00837     
00838     (void) landhandleverb (hv);
00839     
00840     AEResumeTheCurrentEvent (&event, &reply, (AEEventHandlerUPP) kAENoDispatch, 0);
00841     
00842     exitprocessthread ();
00843     
00844     return (nil);
00845     } /*eventthreadmain*/
00846 
00847 
00848 static pascal OSErr landsystem7handleevent (AppleEvent *message, AppleEvent *reply, long refcon) {
00849     
00850     /*
00851     this is the dispatch routine for userland appleevents, established 
00852     at init time by landinit.
00853     
00854     we'll build a verb record (handle) that is the same as for ipc, 
00855     except that transport info will contain the original message and reply 
00856     appleevent records.
00857     
00858     10/23/91 dmb: always suspend/resume the event in case handler is 
00859     multithreaded.
00860     
00861     1/28/92 dmb: when landhandleverb fails, check landgeterror instead of always 
00862     returning memfullerr
00863     
00864     4/20/92 dmb: removed bogus disposehandle when landsystem7unpackverb fails
00865     
00866     4/29/92 dmb: if refcon is -1, we're being called from langipc's fastevent routine
00867     
00868     2/15/93 dmb: don't fork if verb is direct
00869     
00870     3.0.1b2 dmb: if newprocessthread fails, use processpsuedothread; don't 
00871     call threadmain directly, because we need to protect context globals.
00872     */
00873     
00874     register hdllandglobals hg;
00875     hdlverbrecord hverb;
00876     register hdlverbrecord hv;
00877     hdlprocessthread hthread;
00878     OSErr errcode;
00879     boolean flsystemevent;
00880     tyfastverbcontext savecontext;
00881     long curA5;
00882     
00883     assert (refcon != -1);
00884     
00885     flsystemevent = (refcon != 0) && (refcon != typeWildCard);
00886     
00887     if (flsystemevent) {
00888         
00889         #if THINK_C
00890             
00891             asm {
00892                 move.l  a5,-(a7)
00893                 move.l  refcon,a5
00894                 }
00895             
00896         #else
00897             
00898             curA5 = SetUpAppA5 ();
00899         
00900         #endif
00901         
00902         landpushfastcontext (&savecontext);
00903         }
00904     
00905     hg = landgetglobals ();
00906     
00907     errcode = noErr;
00908     
00909     if (!landsystem7unpackverb (message, reply, &hverb)) {
00910         
00911         errcode = memFullErr;
00912         
00913         goto exit;
00914         }
00915     
00916     hv = hverb; /*copy into register*/
00917     
00918     /*
00919     (**hv).flsystemverb = flsystemevent;
00920     */
00921     
00922     if (refcon == typeWildCard) {
00923         
00924         if (!(*(**hg).findhandlerroutine) (hv)) {
00925             
00926             landdisposeverb (hv);
00927             
00928             errcode = errAEEventNotHandled;
00929             
00930             goto exit;
00931             }
00932         }
00933     
00934     if ((**hv).flverbisdirect || flsystemevent || !inmainthread ()) { /*don't fork or suspend*/
00935     
00936         ++fldisableyield;
00937         
00938         if (!landhandleverb (hv))
00939             errcode = landgeterror ();
00940         
00941         --fldisableyield;
00942         
00943         goto exit;
00944         }
00945     
00946     if (newprocessthread (&eventthreadmain, (tythreadmainparams) hv, &hthread))
00947         suspendcurrentevent (message);
00948     else
00949         processpsuedothread (&eventthreadmain, (tythreadmainparams) hv);
00950     
00951     exit: { /*normal exit; not forked thread*/
00952         
00953         if (flsystemevent) {
00954             
00955             landpopfastcontext (&savecontext);
00956             
00957             #if THINK_C
00958             
00959                 asm {
00960                     move.l  (a7)+,a5
00961                     }
00962             
00963             #else
00964             
00965                 RestoreA5 (curA5);
00966             
00967             #endif
00968             }
00969         
00970         return (errcode);
00971         }
00972     } /*landsystem7handleevent*/
00973 
00974 
00975 #if !TARGET_RT_MAC_CFM
00976     #define landsystem7handleeventUPP ((AEEventHandlerUPP) landsystem7handleevent)
00977 #else
00978     #if !TARGET_API_MAC_CARBON
00979         static RoutineDescriptor landsystem7handleeventDesc = BUILD_ROUTINE_DESCRIPTOR (uppAEEventHandlerProcInfo, landsystem7handleevent);
00980         #define landsystem7handleeventUPP (&landsystem7handleeventDesc)
00981     #else
00982         AEEventHandlerUPP   landsystem7handleeventDesc = nil;
00983         #define landsystem7handleeventUPP (landsystem7handleeventDesc)
00984     #endif
00985 #endif
00986 
00987 
00988 static pascal boolean replyidvisit (Handle htinfo, long id) {
00989     
00990     hdlsys7transportinfo ht = (hdlsys7transportinfo) htinfo;
00991     
00992     return ((**ht).replyid == (short) id);
00993     } /*replyidvisit*/
00994 
00995 
00996 static pascal OSErr targettoprocessinfo (const TargetID *target, ProcessSerialNumber *psn, FSSpec *fs, OSType *signature) {
00997     
00998     #if !TARGET_API_MAC_CARBON
00999     ProcessInfoRec info;
01000     OSErr ec;
01001     
01002     if ((*target).location.locationKindSelector == ppcNoLocation) { /*local program*/
01003         
01004         ec = GetProcessSerialNumberFromPortName ((PPCPortPtr) &(*target).name, psn);
01005         
01006         if (ec != noErr)
01007             return (ec);
01008         
01009         info.processInfoLength = (long) sizeof (info);
01010         
01011         info.processName = nil;
01012         
01013         info.processAppSpec = fs;
01014         
01015         ec = GetProcessInformation (psn, &info);
01016         
01017         if (ec != noErr)
01018             return (ec);
01019         
01020         *signature = info.processSignature;
01021         }
01022         
01023     else { /*not a local program*/
01024     #endif
01025 
01026         clearbytes (psn, sizeof (ProcessSerialNumber));
01027         
01028         clearbytes (fs, sizeof (FSSpec)); /*null*/
01029         
01030         if ((*target).name.portKindSelector == ppcByCreatorAndType)
01031             *signature = (*target).name.u.port.portCreator;
01032         else
01033             BlockMove ((Ptr) (*target).name.u.portTypeStr + 1, (Ptr) signature, 4L); /*kloooge*/
01034     
01035     #if !TARGET_API_MAC_CARBON
01036     }
01037     #endif
01038 
01039     
01040     return (noErr);
01041     } /*targettoprocessinfo*/
01042 
01043 
01044 pascal OSErr landsystem7getsenderinfo (const AppleEvent *event, ProcessSerialNumber *psn, FSSpec *fs, OSType *signature) {
01045     
01046     OSErr err;
01047     DescType type;
01048     long size;
01049     TargetID target;
01050     
01051     err = AEGetAttributePtr (event, keyAddressAttr, typeTargetID, &type, &target, sizeof (target), &size);
01052     
01053     if (err == noErr)
01054         err = targettoprocessinfo (&target, psn, fs, signature);
01055     
01056     return (err);
01057     } /*landsystem7getsenderinfo*/
01058 
01059 
01060 static pascal OSErr landsystem7replyroutine (AppleEvent *message, AppleEvent *reply, long refcon) {
01061 #pragma unused (reply, refcon)
01062     /*
01063     10/24/91 dmb: created.
01064     
01065     this is the dispatch routine for events that are replies to messages sent with 
01066     the kAEQueueReply mode set.
01067     
01068     when messages are sent asynchronously, the landsystem7replyroutine send mode is used, 
01069     the transportinfo handle is put in our internal queue, and the process sleeps.  our 
01070     job is to pull the transportinfo out of the queue, stash the reply in it, and wake the 
01071     process.
01072     */
01073     
01074     long id;
01075     hdlsys7transportinfo ht;
01076     
01077     if (!landsystem7getlongattr (message, keyReturnIDAttr, typeLongInteger, &id))
01078         return (errAEEventNotHandled);
01079     
01080     if (!landpopqueueitem (&replyidvisit, id, (Handle *) &ht))
01081         return (errAEEventNotHandled);
01082     
01083     suspendcurrentevent (message); /*don't want AEM to dispose it*/
01084     
01085     (**ht).sys7reply = *message;
01086     
01087     (**ht).fltimedout = false; /*a reply was received before waking*/
01088     
01089     processwake ((**ht).hthread);
01090     
01091     return (noErr);
01092     } /*landsystem7replyroutine*/
01093 
01094 
01095 static pascal OSErr landsystem7openapproutine (AppleEvent *message, AppleEvent *reply, long refcon) {
01096 #pragma unused(reply, message, refcon)
01097 
01098     /*
01099     this is the dispatch routine for the open application (required) core event.
01100     
01101     no parameters exist for this event
01102     
01103     3/17/91 mao: Pascal callback compatability
01104     */
01105     
01106     register hdllandglobals hg = landgetglobals ();
01107     
01108     return ((*(**hg).macopenapproutine) ());
01109     } /*landsystem7openapproutine*/
01110 
01111 
01112 static pascal OSErr landsystem7visitdoclist (AppleEvent *message, landfilespeccallback docvisitroutine) {
01113 
01114     /*
01115     this is common code between the open/print documents event handlers.
01116     
01117     the direct object parameter is a list of aliases.  we'll ask for fsspecs 
01118     instead, and allow the appleevent manager do the coersion for us
01119 
01120     3/17/91 mao: Pascal callback compatability
01121     
01122     5/20/92 dmb: required event callbacks have always returned an OSErr; we were 
01123     testing boolean result, yielding inverse results
01124     
01125     2.1b3 dmb: set new maceventsender field
01126     */
01127     
01128     register OSErr err;
01129     register short n;
01130     register hdllandglobals hg = landgetglobals ();
01131     AEDescList doclist;
01132     long ctdocs;
01133     AEKeyword key;
01134     DescType type;
01135     long size;
01136     FSSpec fs;
01137     OSType signature;
01138     ProcessSerialNumber psn;
01139     
01140     err = AEGetParamDesc (message, keyDirectObject, typeAEList, &doclist);
01141     
01142     if (err != noErr)
01143         return (err);
01144     
01145     if (landsystem7getsenderinfo (message, &psn, &fs, &signature) != noErr)
01146         signature = 0;
01147     
01148     (**hg).maceventsender = signature;
01149     
01150     err = AECountItems (&doclist, &ctdocs);
01151     
01152     for (n = 1; n <= (short) ctdocs; n++) {
01153         
01154         err = AEGetNthPtr (&doclist, n, typeFSS, &key, &type, (Ptr) &fs, sizeof (fs), &size);
01155         
01156         if (err != noErr)
01157             break;
01158         
01159         err = (*docvisitroutine) (&fs);
01160         
01161         if (err != noErr)
01162             break;
01163         } /*for*/
01164     
01165     AEDisposeDesc (&doclist);
01166     
01167     return (err);
01168     } /*landsystem7visitdoclist*/
01169 
01170 
01171 static pascal OSErr landsystem7opendocsroutine (AppleEvent *message, AppleEvent *reply, long refcon) {
01172 #pragma unused (reply, refcon)
01173     /*
01174     this is the dispatch routine for the open documents (required) core event.
01175     */
01176     
01177     register hdllandglobals hg = landgetglobals ();
01178     
01179     return (landsystem7visitdoclist (message, (**hg).macopendocroutine));
01180     } /*landsystem7opendocsroutine*/
01181 
01182 
01183 static pascal OSErr landsystem7printdocsroutine (AppleEvent *message, AppleEvent *reply, long refcon) {
01184 
01185     /*
01186     this is the dispatch routine for the print documents (required) core event.
01187     */
01188     
01189     register hdllandglobals hg = landgetglobals ();
01190     
01191     if ((**hg).macprintdocroutine == nil)
01192         return (landsystem7handleevent (message, reply, refcon));
01193     
01194     return (landsystem7visitdoclist (message, (**hg).macprintdocroutine));
01195     } /*landsystem7printdocsroutine*/
01196 
01197 
01198 static pascal OSErr landsystem7quitapproutine (AppleEvent *message, AppleEvent *reply, long refcon) {
01199 #pragma unused (message, reply, refcon)
01200     /*
01201     this is the dispatch routine for the quit application (required) core event.
01202     
01203     no parameters exist for this event
01204 
01205     3/17/91 mao: Pascal callback compatability
01206     */
01207     
01208     register hdllandglobals hg = landgetglobals ();
01209     
01210     return ((*(**hg).macquitapproutine) ());
01211     } /*landsystem7quitapproutine*/
01212 
01213 
01214 static boolean landvisitprocesses (
01215         pascal boolean (* visitroutine) (tylandprocessvisitinfoptr visitinfo, ProcessInfoRec *processinfo),
01216         tylandprocessvisitinfoptr visitinfo) {
01217 
01218     ProcessInfoRec processinfo;
01219     ProcessSerialNumber psn;
01220     bigstring bsname;
01221     FSSpec fss;
01222     
01223     processinfo.processName = bsname; /*place to store process name*/
01224     
01225     processinfo.processAppSpec = &fss; /*place to store process filespec*/
01226     
01227     psn.highLongOfPSN = kNoProcess;
01228     
01229     psn.lowLongOfPSN = kNoProcess;
01230     
01231     while (GetNextProcess (&psn) == noErr) {
01232         
01233         processinfo.processInfoLength = sizeof (ProcessInfoRec);
01234         
01235         if (GetProcessInformation (&psn, &processinfo) == noErr) {
01236         
01237             if (!(*visitroutine) (visitinfo, &processinfo))
01238                 return (false);
01239             }
01240         }
01241     
01242     return (true);
01243     } /*landvisitprocesses*/
01244 
01245 
01246 static pascal boolean landprocesscreatorvisit (tylandprocessvisitinfoptr visitinfo, ProcessInfoRec *processinfo) {
01247     
01248     return (processinfo->processSignature != visitinfo->idrunningprocess);
01249     } /*landprocesscreatorvisit*/
01250 
01251 
01252 boolean landsystem7apprunning (tyapplicationid idapp) {
01253 
01254     /*
01255     2002-11-15 AR: Switched from using a global to a stack-allocated struct
01256     for passing context to the landproccesscreatorvist callback function
01257     */
01258     
01259     tylandprocessvisitinfo info;
01260     
01261     info.idrunningprocess = idapp;
01262     
01263     return (!landvisitprocesses (&landprocesscreatorvisit, &info));
01264     } /*landsystem7apprunning*/
01265 
01266 
01267 static boolean landsystem7newtransportinfo (hdlverbrecord hverb) {
01268     
01269     hdlsys7transportinfo ht;
01270     
01271     if (!landnewclearhandle (longsizeof (tysys7transportinfo), (Handle *) &ht))
01272         return (false);
01273     
01274     (**hverb).transportinfo = (Handle) ht;
01275     
01276     return (true);
01277     } /*landsystem7newtransportinfo*/
01278 
01279 
01280 boolean landsystem7newverb (hdlverbrecord hverb, ProcessSerialNumber *psn) {
01281     
01282     /*
01283     6/16/93 dmb: take psn paramter
01284     */
01285     
01286     register hdlsys7transportinfo ht;
01287     
01288     if (!landsystem7newtransportinfo (hverb))
01289         return (false);
01290     
01291     if ((psn != nil) && ((*psn).lowLongOfPSN != kNoProcess)) {
01292         
01293         ht = (hdlsys7transportinfo) (**hverb).transportinfo;
01294         
01295         (**ht).flprocessid = true;
01296         
01297         (**ht).receiverpsn = *psn;
01298         }
01299     
01300     return (landsystem7packverb (hverb));
01301     } /*landsystem7newverb*/
01302 
01303 
01304 boolean landsystem7newnetworkverb (hdlverbrecord hverb, tynetworkaddress *adr) {
01305     
01306     register hdlsys7transportinfo ht;
01307     boolean fl;
01308     
01309     if (!landsystem7newtransportinfo (hverb))
01310         return (false);
01311     
01312     ht = (hdlsys7transportinfo) (**hverb).transportinfo;
01313     
01314     (**ht).flnetwork = true;
01315     
01316     (**ht).networkaddress = *adr;
01317     
01318     fl = landchecksameprocess (adr);
01319     
01320     (**ht).fltoself = fl;
01321     
01322     return (landsystem7packverb (hverb));
01323     } /*landsystem7newnetworkverb*/
01324 
01325 
01326 void landsystem7disposeverb (hdlverbrecord hverb) {
01327     
01328     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hverb).transportinfo;
01329     
01330     if ((**ht).flownmessage)
01331         AEDisposeDesc (&(**ht).sys7message);
01332     
01333     if ((**ht).flownreply)
01334         AEDisposeDesc (&(**ht).sys7reply);
01335     } /*landsystem7disposeverb*/
01336 
01337 
01338 static pascal Boolean landsystem7idleroutine (EventRecord *ev, long *sleep, RgnHandle *mousergn) {
01339 #pragma unused (sleep, mousergn)
01340     
01341     /*
01342     10/23/91 dmb: we now pass the event through to the application so it can 
01343     respond to it
01344     */
01345     
01346     
01347     if (landbreakembrace (ev)) /*user holding down cmd, option and shift keys*/
01348         return (-1); /*stop waiting*/
01349     
01350     if (!processyield ())
01351         return (-1);
01352     
01353     return (false); /*keep waiting*/
01354     } /*landsystem7idleroutine*/
01355 
01356 
01357 #if !TARGET_RT_MAC_CFM
01358     
01359     #define landsystem7idleUPP (&landsystem7idleroutine)
01360     
01361     
01362 #elif TARGET_API_MAC_CARBON == 1
01363 
01364     AEIdleUPP landsystem7idleUPP;
01365     
01366 #else
01367 
01368     static RoutineDescriptor landsystem7idleDesc = BUILD_ROUTINE_DESCRIPTOR (uppAEIdleProcInfo, landsystem7idleroutine);
01369     
01370     #define landsystem7idleUPP (&landsystem7idleDesc)
01371     
01372 #endif
01373 
01374 
01375 pascal boolean landsystem7geteventrecords (hdlverbrecord hverb, AppleEvent *event, AppleEvent *reply) {
01376     
01377     /*
01378     3/30/93 dmb: this routine allows us to keep the sys7transportinfo structure private.
01379     */
01380     
01381     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hverb).transportinfo;
01382     
01383     *event = (**ht).sys7message;
01384     
01385     *reply = (**ht).sys7reply;
01386     
01387     return (true);
01388     } /*landsystem7geteventrecords*/
01389 
01390 
01391 boolean landsystem7send (hdlverbrecord hverb, hdlverbrecord *hvalues) {
01392     
01393     /*
01394     pack the verb into an appleevent and send it to the destination program.  then
01395     unpack the reply into a new verb handle pointed to by hvalues
01396     
01397     10/25/91 dmb: implemented queued-response verbs
01398     
01399     10/29/91 dmb: use filter routine to avoid deadlock of main thread
01400     
01401     1/2/92 dmb: don't allow interaction when sending network verbs (even when local)
01402     
01403     7/29/92 dmb: don't queue reply if fldisableyield is set; sleeping is like yielding
01404     
01405     3.0.2b1 dmb: calculate a waketime here, instead of a bedtime. this way, we look 
01406     at the timeoutticks eventinfo setting here in the right thread, instead of always 
01407     looking at the setting of the thread the happens to be checking for timeouts, 
01408     which is always the main thread.
01409     */
01410     
01411     register hdlverbrecord hv = hverb;
01412     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hv).transportinfo;
01413     register OSErr errcode;
01414     register hdllandglobals hg = landgetglobals ();
01415     AppleEvent message;
01416     AppleEvent reply;
01417     long mode;
01418     long interaction;
01419     register boolean fl;
01420     long ctparams;
01421     long id;
01422     
01423     #if TARGET_API_MAC_CARBON && TARGET_RT_MAC_CFM
01424     
01425         landsystem7idleUPP = NewAEIdleUPP (&landsystem7idleroutine);
01426 
01427     #endif
01428         
01429     /*
01430     if (!landsystem7packverb (hv, &message))
01431         return (false);
01432     */
01433     
01434     message = (**ht).sys7message;
01435     
01436     if ((**hv).flverbisdirect) {
01437         register landverbrecordcallback cb = (**hg).handleverbroutine;
01438         
01439         mode = kAEWaitReply;
01440         
01441         errcode = AECreateList (nil, 0, true, &reply);
01442         
01443         (**ht).sys7reply = reply;
01444         
01445         landseterror (noErr);
01446         
01447         (*cb) (hv);
01448         
01449         errcode = landgeterror ();
01450         }
01451     else { /*send the message & wait for reply*/
01452         
01453         if ((**hv).flverbgetsnoreply)
01454             mode = kAENoReply;
01455         
01456         else {
01457             
01458             if ((inmainthread ()) || (**ht).fltoself || fldisableyield)
01459                 mode = kAEWaitReply;
01460             else
01461                 mode = kAEQueueReply;
01462             }
01463         
01464         if ((**hg).eventsettings.interactionlevel != 0)
01465             interaction = (**hg).eventsettings.interactionlevel;
01466         
01467         else {
01468             
01469             if ((**ht).flnetwork)
01470                 interaction = kAENeverInteract;
01471             else
01472                 interaction = kAEAlwaysInteract + kAECanSwitchLayer;
01473             }
01474         
01475         #ifdef flcomponent
01476             
01477             {
01478             register tyeventsendcallback cb = (**hg).eventsendcallback;
01479             
01480             errcode = (*(AESendCallback) cb) (
01481                 
01482                 &message, &reply, mode + interaction + kAEDontRecord, kAENormalPriority, 
01483                 
01484                 kNoTimeOut, landsystem7idleUPP, nil);
01485             }
01486         
01487         #else
01488         
01489             errcode = AESend (
01490                 
01491                 &message, &reply, mode + interaction, kAENormalPriority, 
01492                 
01493                 kNoTimeOut, landsystem7idleUPP, nil);
01494         
01495         #endif
01496         
01497         #if TARGET_API_MAC_CARBON == 1
01498         
01499             DisposeAEIdleUPP (landsystem7idleUPP);
01500         
01501         #endif
01502         
01503         landsystem7getlongattr (&message, keyReturnIDAttr, typeLongInteger, &id); /*before disposal*/
01504         }
01505     
01506     AEDisposeDesc (&message);
01507     
01508     (**ht).flownmessage = false;
01509     
01510     if (errcode != noErr) {
01511         
01512         landseterror (errcode);
01513         
01514         return (false);
01515         }
01516     
01517     if (mode == kAEQueueReply) {
01518         
01519         hdlprocessthread hthread = getcurrentthread ();
01520         unsigned long waketime = (**hg).eventsettings.timeoutticks;
01521         
01522         (**ht).hthread = hthread;
01523         
01524         /*
01525         if ((long) waketime > 0)
01526             waketime += TickCount ();   //when to time out
01527         else
01528             waketime = 0xffffffff;      //never time out
01529         
01530         (**ht).waketime = waketime;
01531         */
01532         
01533         (**ht).replyid = id;
01534         
01535         (**ht).fltimedout = true; /*4.1b3 dmb: until set otherwise, assume this*/
01536         
01537         (**ht).fluseraborted = false; /*4.1b3 dmb: default state, ctn'd*/
01538         
01539         landpushqueue ((Handle) ht);
01540         
01541         if (!processsleep (hthread, waketime)) /*killed in our sleep -- bummer!*/ {
01542             
01543             landseterror (usercancellederror); /*silent error*/
01544             
01545             return (false);
01546             }
01547         
01548         /*we're back! grab reply from transport info*/
01549         
01550         if ((**ht).fltimedout) {
01551             
01552             landseterror (errAETimeout);
01553             
01554             return (false);
01555             }
01556         
01557         if ((**ht).fluseraborted) {
01558             
01559             landseterror (errAEWaitCanceled);
01560             
01561             return (false);
01562             }
01563         
01564         reply = (**ht).sys7reply;
01565         }
01566     
01567     /*we got our answer, process it and return*/
01568     
01569     errcode = AECountItems (&reply, &ctparams);
01570     
01571     if (!landnewverb (idnull, nil, nullclass, nulltoken, ctparams, hvalues)) {
01572         
01573         /*failed to create verb handle to hold returned values*/
01574         
01575         return (false); 
01576         }
01577     
01578     hv = *hvalues; /*copy into register*/
01579     
01580     fl = true; /*parameter retrieval optimism*/
01581     
01582     ht = (hdlsys7transportinfo) (**hv).transportinfo;
01583     
01584     (**ht).sys7message = reply;
01585     
01586     (**ht).flownmessage = true;
01587     
01588     return (fl);
01589     } /*landsystem7send*/
01590 
01591 
01592 static pascal void landsystem7checktimeouts (EventRecord *ev) {
01593     
01594     /*
01595     3.0.2b1 dmb: timeout time is now calculated when sending with the correct 
01596     thread active. here, eventsettings.timeoutticks tells us about the main 
01597     thread, not the threads that are sleeping (which can each have their own 
01598     setting).
01599     
01600     4.1b3 dmb: don't check timeout here; the processsleep handles that now.
01601     */
01602     
01603     hdlsys7transportinfo ht;
01604     
01605     if (landbreakembrace (ev)) {
01606         
01607         if (landpopqueue ((Handle *) &ht)) { /*abort 1st in queue*/
01608         
01609             (**ht).fluseraborted = true;
01610         
01611             processwake ((**ht).hthread);
01612             }
01613         }
01614     
01615     /*
01616     while (landpopqueueitem (&timeoutvisit, (long) TickCount (), (Handle *) &ht)) {
01617         
01618         (**ht).fltimedout = true;
01619         
01620         processwake ((**ht).hthread);
01621         }
01622     */
01623     
01624     } /*landsystem7checktimeouts*/
01625 
01626 
01627 #if !flruntime
01628 
01629 boolean landsystem7eventfilter (EventRecord *ev) {
01630     
01631     /*
01632     watch for high level events (AppleEvents)
01633     
01634     return true if we consume the event, false otherwise.
01635     */
01636     
01637     switch ((*ev).what) {
01638         
01639         case kHighLevelEvent:
01640             AEProcessAppleEvent (ev);
01641             
01642             return (true); /*consume the event*/
01643         
01644         case nullEvent:
01645             landsystem7checktimeouts (ev);
01646             
01647             return (false);
01648         } /*switch*/
01649     
01650     return (false); /*don't consume the event*/
01651     } /*landsystem7eventfilter*/
01652 
01653 #endif
01654 
01655 #if 0 // def THINK_C
01656 
01657     static boolean landsystem7installhandler (AEEventClass class, AEEventID id, tyeventhandler handler) {
01658         
01659         /*
01660         little layer to make code prettier
01661         */
01662         
01663         OSErr errcode;
01664         
01665         errcode = AEInstallEventHandler (class, id, (EventHandlerProcPtr) handler, 0, false);
01666         
01667         return (errcode == noErr);
01668         } /*landsystem7installhandler*/
01669     
01670     
01671     pascal boolean landsystem7installfasthandler (tyverbclass class, tyverbtoken token, tyeventhandler handler) {
01672         
01673         OSErr errcode;
01674         
01675         errcode = AEInstallEventHandler (class, token, (EventHandlerProcPtr) handler, (long) CurrentA5, true);
01676         
01677         return (errcode == noErr);
01678         } /*landsystem7installfasthandler*/
01679 
01680     
01681     boolean landsystem7addclass (tyverbclass class) {
01682         
01683         return (landsystem7installhandler (class, typeWildCard, (ProcPtr) &landsystem7handleevent));
01684         } /*landsystem7addclass*/
01685     
01686     
01687     boolean landsystem7addfastverb (tyverbclass class, tyverbtoken token) {
01688         
01689         return (landsystem7installfasthandler (class, token, &landsystem7handleevent));
01690         } /*landsystem7addfastverb*/
01691     
01692     
01693     boolean landsystem7acceptanyverb (void) {
01694         
01695         OSErr errcode;
01696         
01697         errcode = AEInstallEventHandler (typeWildCard, typeWildCard, (EventHandlerProcPtr) &landsystem7handleevent, typeWildCard, false);
01698         
01699         return (errcode == noErr);
01700         } /*landsystem7acceptanyverb*/
01701     
01702     
01703     pascal boolean landsystem7removefasthandler (tyverbclass class, tyverbtoken token) {
01704         
01705         EventHandlerProcPtr handler;
01706         long refcon;
01707         
01708         if (AEGetEventHandler (class, token, &handler, &refcon, true) != errAEHandlerNotFound) {
01709             
01710             if (refcon == (long) CurrentA5) /*it's our handler*/
01711                 AERemoveEventHandler (class, token, handler, true);
01712             }
01713         } /*landsystem7removefasthandler*/
01714 
01715 #else
01716 
01717     static boolean landsystem7installhandlerUPP (AEEventClass class, AEEventID id, AEEventHandlerUPP handler) {
01718         
01719         OSErr errcode;
01720         
01721         errcode = AEInstallEventHandler (class, id, handler, 0, false);
01722         
01723         return (errcode == noErr);
01724         } /*landsystem7installhandler*/
01725     
01726     
01727     static pascal boolean landsystem7installfasthandlerUPP (tyverbclass class, tyverbtoken token, AEEventHandlerUPP handler) {
01728         
01729         OSErr errcode;
01730         //Code change by Timothy Paustian Monday, June 26, 2000 3:45:05 PM
01731         //A5 worlds make no sense on PPC so why pass this as our refcon
01732         #if TARGET_API_MAC_CARBON == 1
01733         errcode = AEInstallEventHandler (class, token, handler, (long) nil, true);
01734         #else
01735         errcode = AEInstallEventHandler (class, token, handler, (long) LMGetCurrentA5 (), true);
01736         #endif
01737         
01738         return (errcode == noErr);
01739         } /*landsystem7installfasthandler*/
01740     
01741     
01742     static boolean landsystem7installhandler (AEEventClass class, AEEventID id, tyeventhandler handler) {
01743         
01744         /*
01745         little layer to make code prettier
01746         */
01747         #if TARGET_API_MAC_CARBON == 1
01748 
01749             return (landsystem7installhandlerUPP (class, id, NewAEEventHandlerUPP ((AEEventHandlerProcPtr) handler)));
01750         
01751         #else
01752 
01753             return (landsystem7installhandlerUPP (class, id, NewAEEventHandlerProc ((AEEventHandlerProcPtr) handler)));
01754         
01755         #endif
01756         } /*landsystem7installhandler*/
01757     
01758     
01759     pascal boolean landsystem7installfasthandler (tyverbclass class, tyverbtoken token, tyeventhandler handler) {
01760         
01761         #if TARGET_API_MAC_CARBON == 1
01762     
01763             return (landsystem7installfasthandlerUPP (class, token, NewAEEventHandlerUPP ((AEEventHandlerProcPtr) handler)));
01764         
01765         #else
01766 
01767             return (landsystem7installfasthandlerUPP (class, token, NewAEEventHandlerProc ((AEEventHandlerProcPtr) handler)));
01768         
01769         #endif
01770         } /*landsystem7installfasthandler*/
01771 
01772     
01773     boolean landsystem7addclass (tyverbclass class) {
01774         
01775         //Code change by Timothy Paustian Friday, July 28, 2000 1:31:13 PM
01776         //create the new handler if its still nil
01777         #if TARGET_API_MAC_CARBON && TARGET_RT_MAC_CFM
01778         if (landsystem7handleeventUPP == nil)
01779             landsystem7handleeventUPP = NewAEEventHandlerUPP(landsystem7handleevent);
01780         #endif
01781         
01782         return (landsystem7installhandlerUPP (class, typeWildCard, landsystem7handleeventUPP));
01783         } /*landsystem7addclass*/
01784     
01785     
01786     boolean landsystem7addfastverb (tyverbclass class, tyverbtoken token) {
01787         //Code change by Timothy Paustian Friday, July 28, 2000 1:31:13 PM
01788         //create the new handler is its still nil
01789         #if TARGET_API_MAC_CARBON && TARGET_RT_MAC_CFM
01790         if (landsystem7handleeventUPP == nil)
01791             landsystem7handleeventUPP = NewAEEventHandlerUPP(landsystem7handleevent);
01792         #endif
01793         return (landsystem7installfasthandlerUPP (class, token, landsystem7handleeventUPP));
01794         } /*landsystem7addfastverb*/
01795     
01796     
01797     boolean landsystem7acceptanyverb (void) {
01798         
01799         OSErr errcode;
01800         //Code change by Timothy Paustian Friday, July 28, 2000 1:31:13 PM
01801         //create the new handler is its still nil
01802         #if TARGET_API_MAC_CARBON && TARGET_RT_MAC_CFM
01803         if (landsystem7handleeventUPP == nil)
01804             landsystem7handleeventUPP = NewAEEventHandlerUPP(landsystem7handleevent);
01805         #endif
01806         errcode = AEInstallEventHandler (typeWildCard, typeWildCard, landsystem7handleeventUPP, typeWildCard, false);
01807         
01808         return (errcode == noErr);
01809         } /*landsystem7acceptanyverb*/
01810     
01811     
01812     pascal boolean landsystem7removefasthandler (tyverbclass class, tyverbtoken token) {
01813         
01814         AEEventHandlerUPP handler;
01815         long refcon;
01816         
01817         if (AEGetEventHandler (class, token, &handler, &refcon, true) != errAEHandlerNotFound) {
01818             
01819             #if TARGET_API_MAC_CARBON == 1
01820             if(refcon == (long) 'LAND'){
01821             #else
01822             if (refcon == (long) LMGetCurrentA5 ()) { /*it's our handler*/
01823             #endif
01824             
01825                 AERemoveEventHandler (class, token, handler, true);
01826                 //I need to dispose of these handlers
01827                 return (true);
01828                 }
01829             }
01830         
01831         return (false);
01832         } /*landsystem7removefasthandler*/
01833 
01834 #endif
01835 
01836 
01837 pascal boolean landsystem7pushparam (AERecord *evt, typaramtype type, Handle hval, void *pval, long len, typaramkeyword key) {
01838     
01839     /*
01840     push the given parameter record onto the verb's parameter list.  all of 
01841     the landpushxxx routines below funnel through this routine
01842     
01843     1/30/92 dmb: landseterror (memFullErr) if enlargehandle fails
01844     
01845     4/28/92 dmb: this is now a transport-specific operation
01846     
01847     4.0b7 dmb: don't dispose of hval if we fail. also check for null event
01848     */
01849     
01850     AEDesc desc;
01851     OSErr err = noErr;
01852     
01853     if (hval != nil) {
01854         
01855         desc.descriptorType = type;
01856         
01857         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
01858         
01859             newdescwithhandle (&desc, type, hval);
01860             
01861         #else
01862         
01863             desc.dataHandle = hval;
01864         
01865         #endif
01866         
01867         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
01868 
01869             if (AEGetDescDataSize (evt) > 0) /*instead of checking that's it null*/
01870         
01871         #else
01872         
01873             if ((*evt).dataHandle != NULL)  // 4.0b7 dmb: make sure it's not a null reply
01874         
01875         #endif
01876         
01877             err = AEPutParamDesc (evt, key, &desc);
01878         
01879         if (err == noErr)
01880             disposehandle (hval);
01881         }
01882     else {
01883         
01884         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
01885 
01886             if (AEGetDescDataSize (evt) > 0) /*instead of checking that's it null*/
01887             
01888         #else
01889         
01890             if ((*evt).dataHandle != NULL)  // 4.0b7 dmb: make sure it's not a null reply
01891         
01892         #endif
01893         
01894             err = AEPutParamPtr (evt, key, type, pval, len);
01895         }
01896     
01897     if (err != noErr) {
01898         
01899         landseterror (err);
01900         
01901         return (false);
01902         }
01903     
01904     return (true);
01905     } /*landsystem7pushparam*/
01906 
01907 
01908 pascal boolean landsystem7getparam (const AERecord *evt, typaramkeyword key, typaramtype type, typaramrecord *param) {
01909     
01910     /*
01911     4/28/92 dmb: created
01912     
01913     2.1b3 dmb: operate on AERecord, not hdlverbrecord
01914     */
01915     
01916 /*
01917     register hdlverbrecord hv = hverb;
01918     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hv).transportinfo;
01919     AppleEvent evt = (**ht).sys7message;
01920 */
01921     register OSErr errcode;
01922     
01923     errcode = AEGetKeyDesc (evt, key, type, &(*param).desc);
01924     
01925     if (errcode != noErr) {
01926         
01927         landseterror (errcode);
01928         
01929         return (false);
01930         }
01931     
01932     (*param).key = key;
01933     
01934     /*
01935     fl = landsystem7unpackdesc (&desc, key, param); /%may set desc's data to nil%/
01936     
01937     AEDisposeDesc (&desc);
01938     */
01939     
01940     return (true);
01941     } /*landsystem7getparam*/
01942 
01943 
01944 pascal boolean landsystem7getnthparam (const AERecord *evt, short n, typaramrecord *param) {
01945     
01946     /*
01947     4/28/92 dmb: created
01948     
01949     7/17/92 dmb: don't set error if parameter is optional
01950     
01951     2.1b3 dmb: operate on AERecord, not hdlverbrecord
01952     */
01953     
01954 /*
01955     register hdlsys7transportinfo ht = (hdlsys7transportinfo) (**hverb).transportinfo;
01956     AppleEvent evt = (**ht).sys7message;
01957 */
01958     register OSErr errcode;
01959     AEKeyword key;
01960     
01961     errcode = AEGetNthDesc (evt, (long) n, typeWildCard, &key, &(*param).desc);
01962     
01963     if (errcode != noErr) {
01964         
01965         landseterror (errcode);
01966         
01967         return (false);
01968         }
01969     
01970     (*param).key = key;
01971     
01972     return (true);
01973     
01974     /*
01975     fl = landsystem7unpackdesc (&desc, key, param); /%may set desc's data to nil%/
01976     
01977     AEDisposeDesc (&desc);
01978     
01979     return (fl);
01980     */
01981     } /*landsystem7getnthparam*/
01982 
01983 
01984 static short landcountverbs (hdlverbarray hverbs) {
01985     
01986     /*
01987     return the number of verbs stored in the array.  factors out some code
01988     that was appearing all over the place.
01989     */
01990     
01991     return ((short) (landgethandlesize ((Handle) hverbs) / longsizeof (tyverbarrayelement)));
01992     } /*landcountverbs*/
01993     
01994 
01995 static boolean removefasthandlers (hdlverbarray hverbs) {
01996     
01997     /*
01998     return true if the token is found in the indicated verb array.
01999     
02000     we split this code out so that Toolkit users can easily find out if another
02001     application supports a particular verb.
02002     
02003     9/4/91 DW: special case -- if token is 0 only match the class, it's a wildcard
02004     search for any verb in a class.
02005     */
02006     
02007     register hdlverbarray hvs = hverbs; 
02008     register short ctloops, i;
02009     
02010     if (hvs == nil) /*no verbs have been registered*/
02011         return (false);
02012     
02013     ctloops = landcountverbs (hvs);
02014     
02015     for (i = 0; i < ctloops; i++) {
02016         
02017         tyverbarrayelement item;
02018         
02019         item = (**hverbs) [i];
02020         
02021         if (item.flfasthandler)
02022             landsystem7removefasthandler (item.class, item.token);
02023         }
02024     
02025     return (true);
02026     } /*removefasthandlers*/
02027 
02028 
02029 boolean landsystem7close (void) {
02030 
02031     register hdllandglobals hg = landgetglobals ();
02032     
02033     /*
02034     landdisposehandle ((Handle) (**hg).mactypes);
02035     */
02036     
02037     removefasthandlers ((**hg).verbarray);
02038     
02039     return (true); 
02040     } /*landsystem7close*/
02041 
02042 
02043 static pascal OSErr whyinternational (DescType itxt, const void *x, Size len, DescType text, SInt32 refcon, AEDesc *result) {
02044 #pragma unused (itxt, refcon)
02045 
02046     if (*(short *) x != smRoman) /*can't treat this as plain text*/
02047         return (errAECoercionFail);
02048     
02049     return (AECreateDesc (text, ((Ptr) x) + 4, len - 4, result)); /*skip over script & language codes*/
02050     } /*whyinternational*/
02051 
02052 
02053 boolean landsystem7init (void) {
02054     
02055     /*
02056     initialize the appleevent manager and set up a dispatch routine for 
02057     the event classes that we want to handle.
02058     
02059     we set up special handlers for the four required event, then a wildcard 
02060     dispatcher to handle everything else.
02061     
02062     10/8/91 dmb: don't install handler for applicationid here; it will happen 
02063     during the verb-adding process, via landaddclass.
02064     
02065     3/2/92 dmb: our double values are SANE extended, and must use type 'exte'
02066     
02067     12/11/92 dmb: 
02068     */
02069     
02070     register hdllandglobals hg = landgetglobals ();
02071     
02072 
02073     #ifdef flcomponent
02074     
02075         #if !TARGET_API_MAC_CARBON
02076         RememberA5 ();
02077         #endif /*for event handlers, browser hook*/
02078     
02079     #endif
02080     
02081     (**hg).macnetglobals.flhavebrowsed = false;
02082     
02083     (**hg).eventsettings.timeoutticks = kNoTimeOut;
02084     
02085     /* already zero:
02086     
02087     (**hg).eventsettings.transactionid = kAnyTransactionID;
02088     
02089     */
02090     if (!landsystem7installhandler (kCoreEventClass, kAEAnswer, landsystem7replyroutine))
02091         return (false);
02092     
02093     if (!landsystem7installhandler (kCoreEventClass, kAEOpenApplication, landsystem7openapproutine))
02094         return (false);
02095     
02096     if (!landsystem7installhandler (kCoreEventClass, kAEOpenDocuments, landsystem7opendocsroutine))
02097         return (false);
02098     
02099     if (!landsystem7installhandler (kCoreEventClass, kAEPrintDocuments, landsystem7printdocsroutine))
02100         return (false);
02101     
02102     if (!landsystem7installhandler (kCoreEventClass, kAEQuitApplication, landsystem7quitapproutine))
02103         return (false);
02104     
02105     #if TARGET_API_MAC_CARBON == 1
02106     
02107         AEInstallCoercionHandler ('itxt', 'TEXT', (AECoercionHandlerUPP) NewAECoercePtrUPP (whyinternational), 0, false, false);
02108     
02109     #else
02110     
02111         AEInstallCoercionHandler ('itxt', 'TEXT', (AECoercionHandlerUPP) NewAECoercePtrProc (whyinternational), 0, false, false);
02112     
02113     #endif
02114     
02115     return (true);
02116     } /*landsystem7init*/
02117 
02118 

Generated on Wed May 31 18:19:50 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6