home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Add-Ons / MacPerl / Droplet / MPDrop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  8.8 KB  |  405 lines  |  [TEXT/CWIE]

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