home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / M / MacPerl 4.13 source.sit / Perl Source ƒ / MacPerl / MPDrop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  7.5 KB  |  357 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPDrop.c            -    Droplets
  4. Author    :    Matthias Neeracher
  5. Language    :    MPW C
  6.  
  7. $Log: MPDrop.c,v $
  8. Revision 1.2  1994/05/04  02:50:15  neeri
  9. Debugger support.
  10.  
  11. Revision 1.1  1994/02/27  23:00:19  neeri
  12. Initial revision
  13.  
  14. Revision 0.1  1993/10/02  00:00:00  neeri
  15. Compiles correctly
  16.  
  17. *********************************************************************/
  18.  
  19. #include <Dialogs.h>
  20. #include <QuickDraw.h>
  21. #include <Windows.h>
  22. #include <Menus.h>
  23. #include <Fonts.h>
  24. #include <AppleEvents.h>
  25. #include <AERegistry.h>
  26. #include <Processes.h>
  27. #include <files.h>
  28. #include <StandardFile.h>
  29. #include <Aliases.h>
  30. #include <GestaltEqu.h>
  31. #include <Folders.h>
  32. #include <Errors.h>
  33. #include <Resources.h>
  34.  
  35. #pragma segment Main
  36.  
  37. #define FAILOSERR(call) if (err = call) return err; else 0
  38.  
  39. Boolean        gQuitting;
  40. FSSpec        gMySelf;
  41. EventRecord    gLastEvent;
  42.  
  43. pascal Boolean CheckEnvironment()
  44. {
  45.     long    result;
  46.     
  47.     if (Gestalt(gestaltAppleEventsAttr, &result))
  48.         return false;
  49.         
  50.     return (result & (1 << gestaltAppleEventsPresent)) != 0;
  51. }  /* CheckEnvironment */
  52.  
  53. /* The following stuff is adapted from Jens Peter Alfke's SignatureToApp code */
  54.  
  55. OSErr MacPerlRunning(ProcessSerialNumber *psn)
  56. {
  57.     OSErr err;
  58.     ProcessInfoRec info;
  59.     
  60.     psn->highLongOfPSN = 0;
  61.     psn->lowLongOfPSN  = kNoProcess;
  62.     do    {
  63.         FAILOSERR(GetNextProcess(psn));
  64.             
  65.         info.processInfoLength     = sizeof(info);
  66.         info.processName             = nil;
  67.         info.processAppSpec         = nil;
  68.         
  69.         FAILOSERR(GetProcessInformation(psn, &info));
  70.     } while(info.processSignature != 'McPL');
  71.  
  72.     *psn = info.processNumber;
  73.     
  74.     return noErr;
  75. }
  76.  
  77. OSErr GetSysVolume(short *vRefNum)
  78. {
  79.     long dir;
  80.     
  81.     return FindFolder(kOnSystemDisk, kSystemFolderType, false, vRefNum, &dir);
  82. }
  83.  
  84. OSErr GetIndVolume(short index, short *vRefNum)
  85. {
  86.     OSErr             err;
  87.     ParamBlockRec     pb;
  88.     
  89.     pb.volumeParam.ioNamePtr     = nil;
  90.     pb.volumeParam.ioVolIndex     = index;
  91.     
  92.     FAILOSERR(PBGetVInfoSync(&pb));
  93.     
  94.     *vRefNum = pb.volumeParam.ioVRefNum;
  95.     
  96.     return noErr;
  97. }
  98.  
  99. OSErr VolHasDesktopDB(short vRefNum, Boolean * hasDesktop)
  100. {
  101.     OSErr                         err;
  102.     HParamBlockRec             pb;
  103.     GetVolParmsInfoBuffer     info;
  104.     
  105.     pb.ioParam.ioNamePtr     = nil;
  106.     pb.ioParam.ioVRefNum     = vRefNum;
  107.     pb.ioParam.ioBuffer         = (Ptr)&info;
  108.     pb.ioParam.ioReqCount     = sizeof(GetVolParmsInfoBuffer);
  109.     
  110.     FAILOSERR(PBHGetVolParmsSync(&pb));
  111.  
  112.     *hasDesktop = (info.vMAttrib & (1 << bHasDesktopMgr))!=0;
  113.     
  114.     return noErr;
  115. }
  116.  
  117. OSErr FindAppOnVolume(short vRefNum, FSSpec *file)
  118. {
  119.     OSErr     err;
  120.     DTPBRec     pb;
  121.     
  122.     /* Get Acess path to Desktop database on this volume */
  123.     
  124.     pb.ioVRefNum         = vRefNum;
  125.     pb.ioNamePtr         = nil;
  126.     FAILOSERR(PBDTGetPath(&pb));
  127.     
  128.     pb.ioIndex             = 0;
  129.     pb.ioFileCreator     = 'McPL';
  130.     pb.ioNamePtr         = file->name;
  131.     switch (err = PBDTGetAPPLSync(&pb))    {
  132.     case noErr:
  133.         file->vRefNum     = vRefNum;
  134.         file->parID     = pb.ioAPPLParID;
  135.     
  136.         return noErr;
  137.     case fnfErr:
  138.         return afpItemNotFound;                        /* Bug in PBDTGetAPPL            */
  139.     default:
  140.         return err;
  141.     }
  142. }
  143.  
  144. OSErr LaunchIt(FSSpecPtr fileSpec, ProcessSerialNumber * psn )
  145. {
  146.     OSErr                     err;
  147.     LaunchParamBlockRec     pb;
  148.     
  149.     pb.launchBlockID             = extendedBlock;
  150.     pb.launchEPBLength         = extendedBlockLen;
  151.     pb.launchFileFlags         = launchNoFileFlags;
  152.     pb.launchControlFlags    = launchContinue + launchNoFileFlags;
  153.     pb.launchAppSpec             = fileSpec;
  154.     pb.launchAppParameters    = nil;
  155.     
  156.     FAILOSERR(LaunchApplication(&pb));
  157.  
  158.     *psn = pb.launchProcessSN;
  159.     
  160.     return noErr;
  161. }
  162.  
  163. /* Get the psn ofa copy of MacPerl. Launch one if necessary. Buy one. Steal one. */
  164. static OSErr LaunchMacPerl(ProcessSerialNumber *psn)
  165. {
  166.     OSErr     err;
  167.     short     vRefNum, sysVRefNum, index;
  168.     FSSpec     file;
  169.     Boolean     hasDesktopDB;
  170.     
  171.     /* See if ToolServer is already running:                    */
  172.     err    = MacPerlRunning(psn);
  173.     
  174.     if    (err != procNotFound)
  175.         return err;
  176.     
  177.     /* Not running, try to launch it */
  178.     
  179.     FAILOSERR(GetSysVolume(&sysVRefNum));
  180.     
  181.     vRefNum = sysVRefNum;
  182.     
  183.     for (index = 0; !err; err = GetIndVolume(++index,&vRefNum)) {
  184.         if (!index || vRefNum != sysVRefNum) {
  185.             if (err = VolHasDesktopDB(vRefNum,&hasDesktopDB))
  186.                 return err;
  187.                 
  188.             if (hasDesktopDB)    
  189.                 switch (err = FindAppOnVolume(vRefNum, &file))    {
  190.                 case noErr:
  191.                     return LaunchIt(&file, psn);
  192.                 case afpItemNotFound:
  193.                     break;
  194.                 default:
  195.                     return err;
  196.                 }
  197.         }
  198.     }
  199.     
  200.     switch (err) {
  201.     case nsvErr:
  202.     case afpItemNotFound:
  203.         return fnfErr;
  204.     default:
  205.         return err;
  206.     }
  207. }
  208.  
  209. void WhoAmI(FSSpec * me)
  210. {
  211.     FCBPBRec        fcb;
  212.     
  213.     fcb.ioNamePtr    =    &me->name;
  214.     fcb.ioRefNum    =    CurResFile();
  215.     fcb.ioFCBIndx    =    0;
  216.     
  217.     PBGetFCBInfoSync(&fcb);
  218.     
  219.     me->vRefNum    =    fcb.ioFCBVRefNum;
  220.     me->parID    =    fcb.ioFCBParID;
  221. }
  222.  
  223. pascal OSErr Yo(const AppleEvent *message, AppleEvent *reply, long refcon)
  224. {
  225.     OSErr                        err;
  226.     AppleEvent                doscript;
  227.     ProcessSerialNumber    perl;
  228.     AEAddressDesc            perladdr;
  229.     AEDescList                args;
  230.     AEDescList                incoming;
  231.     AliasHandle                alias;
  232.     AEDesc                    arg;
  233.     AEKeyword                kw;
  234.     Boolean                    doDebug = true;
  235.     
  236.     gQuitting = true;
  237.  
  238.     WaitNextEvent(0, &gLastEvent, 0, nil);
  239.     
  240.     switch (err = LaunchMacPerl(&perl)) {
  241.     case noErr:
  242.         break;
  243.     case fnfErr:
  244.         ParamText(
  245.             "\pFailed to launch MacPerl. Either you don't have MacPerl "
  246.             "or your desktop needs to be rebuilt.", "\p", "\p", "\p");
  247.         Alert(4096, nil);
  248.         
  249.         return err;
  250.     default:
  251.         ParamText(
  252.             "\pFailed to launch MacPerl (possibly because of "
  253.             "a memory problem).", "\p", "\p", "\p");
  254.         Alert(4096, nil);
  255.         
  256.         return err;
  257.     }
  258.     
  259.     FAILOSERR(SetFrontProcess(&perl));
  260.     
  261.     FAILOSERR(
  262.         AECreateDesc(
  263.             typeProcessSerialNumber,
  264.             (Ptr)&perl,
  265.             sizeof(ProcessSerialNumber),
  266.             &perladdr));
  267.     
  268.     if (refcon && (gLastEvent.modifiers & optionKey))
  269.         FAILOSERR(
  270.             AECreateAppleEvent(
  271.                 'McPL', kAEOpenDocuments, &perladdr, 
  272.                 kAutoGenerateReturnID, kAnyTransactionID, 
  273.                 &doscript));
  274.     else {
  275.         FAILOSERR(
  276.             AECreateAppleEvent(
  277.                 kAEMiscStandards, kAEDoScript, &perladdr, 
  278.                 kAutoGenerateReturnID, kAnyTransactionID, 
  279.                 &doscript));
  280.         if (gLastEvent.modifiers & controlKey)
  281.             FAILOSERR(AEPutParamPtr(&doscript, 'DEBG', typeBoolean, (Ptr) &doDebug, 1));
  282.     }
  283.     
  284.     FAILOSERR(AECreateList(nil,0,false,&args));
  285.     FAILOSERR(NewAlias(nil,&gMySelf,&alias));
  286.     
  287.     HLock((Handle) alias);
  288.     FAILOSERR(AEPutPtr(&args, 0, typeAlias, (Ptr) *alias, GetHandleSize((Handle) alias)));
  289.     DisposHandle((Handle) alias);
  290.     
  291.     if (!AEGetParamDesc(message, keyDirectObject, typeAEList, &incoming)) {
  292.         short    i = 1;
  293.         
  294.         while (!AEGetNthDesc(&incoming, i++, typeWildCard, &kw, &arg)) {
  295.             FAILOSERR(AEPutDesc(&args, 0, &arg));
  296.             AEDisposeDesc(&arg);
  297.         }
  298.         
  299.         AEDisposeDesc(&incoming);
  300.     }
  301.     
  302.     FAILOSERR(AEPutParamDesc(&doscript, keyDirectObject, &args));
  303.     FAILOSERR(
  304.         AESend(
  305.             &doscript, reply,
  306.             kAENoReply+kAEAlwaysInteract,
  307.             kAENormalPriority, kAEDefaultTimeout,
  308.             nil, nil));
  309.     
  310.     return noErr;
  311. }
  312.  
  313. pascal void MainEvent(void)
  314. {
  315.     if (WaitNextEvent(everyEvent, &gLastEvent, 60, nil))
  316.         switch (gLastEvent.what) {
  317.         case kHighLevelEvent:
  318.             AEProcessAppleEvent(&gLastEvent);
  319.             break;
  320.         }
  321. }
  322.  
  323. void main()
  324. {
  325.     InitGraf(&qd.thePort);
  326.     InitFonts();
  327.     FlushEvents(everyEvent, 0);
  328.     InitWindows();
  329.     InitMenus();
  330.     TEInit();
  331.     InitDialogs(nil);
  332.     InitCursor();
  333.  
  334.     gQuitting          = false;
  335.  
  336.     /*check environment checks to see if we are running 7.0*/
  337.     if (!CheckEnvironment()) {
  338.         SetCursor(&qd.arrow);
  339.         /*pose the only 7.0 alert*/
  340.         ParamText(
  341.             "\pMacPerl droplets need at least System 7.0 to run "
  342.             "(you may run me from the \"MacPerl Runtime\" "
  343.             "application, however).", "\p", "\p", "\p");
  344.         Alert(4096, nil);
  345.         
  346.         ExitToShell();
  347.     }
  348.  
  349.     AEInstallEventHandler( kCoreEventClass, kAEOpenApplication, (EventHandlerProcPtr)Yo, 1, false) ;
  350.     AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments,   (EventHandlerProcPtr)Yo, 0, false) ;
  351.  
  352.     WhoAmI(&gMySelf);
  353.     
  354.     while (!gQuitting)
  355.         MainEvent();
  356. }
  357.