home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / nshellmegasource1.50 / mega src / commands / odoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-24  |  11.7 KB  |  485 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     odoc.c
  4.         
  5.     Copyright (c) 1993,1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #ifdef __MWERKS__            // CodeWarrior requires an A4 setup
  16. #include <A4Stuff.h>
  17. #endif
  18.  
  19. #include <appleevents.h>
  20. #include <processes.h>
  21. #include <Aliases.h>
  22. #include <GestaltEqu.h>
  23.  
  24. #include "nshc.h"
  25.  
  26. #include "arg_utl.proto.h"
  27. #include "str_utl.proto.h"
  28. #include "fss_utl.proto.h"
  29. #include "nshc_utl.proto.h"
  30.  
  31. /* ======================================== */
  32.  
  33. // prototypes
  34.  
  35. int        Pre7( void );
  36. int        is_it_running( OSType targetSignature );
  37. OSErr    odoc( int gotFSSpec, FSSpec *doc_fss, OSType app_sig, t_nshc_calls *nshc_calls );
  38. int        SearchOne( short vol, OSType creator, FSSpec *app_fss );
  39. int        SearchAllButOne( Boolean remote_search, OSType creator, FSSpec *doc_fss, FSSpec *app_fss );
  40. int        find_app( OSType creator, FSSpec *doc_fss, FSSpec *app_fss );
  41. OSErr    launch( int gotFSSpec, FSSpec *launchApp, FSSpec *launchDoc, t_nshc_calls *nshc_calls );
  42.  
  43. /* ======================================== */
  44.  
  45. // return true if 'sysv' is previous to 7.0
  46.  
  47. int    Pre7( void )
  48. {
  49.     OSErr    error;
  50.     long    response;
  51.     
  52.     if ( error = Gestalt( 'sysv', &response ) )
  53.         return(true);
  54.         
  55.     if ( response < 0x700 )
  56.         return(true);
  57.     else
  58.         return(false);
  59. }
  60.  
  61. /* ======================================== */
  62.  
  63. int    is_it_running( OSType targetSignature )
  64. {
  65.     Str255                    name;
  66.     ProcessSerialNumber        psn_p;
  67.     ProcessInfoRec          pi;
  68.             
  69.     pi.processName       = name;
  70.     pi.processInfoLength = sizeof(pi);
  71.     pi.processAppSpec    = NULL;
  72.     
  73.     psn_p.highLongOfPSN = 0;
  74.     psn_p.lowLongOfPSN  = kNoProcess;
  75.         
  76.     while(!GetNextProcess(&psn_p))
  77.         if(!GetProcessInformation(&psn_p,&pi))
  78.             if ( pi.processSignature == targetSignature )
  79.                 return( 1 );
  80.  
  81.     return( 0 );
  82. }
  83.  
  84. /* ======================================== */
  85.  
  86. OSErr odoc( int gotFSSpec, FSSpec *doc_fss, OSType app_sig, t_nshc_calls *nshc_calls )
  87. {
  88.     OSErr            myErr;
  89.     FInfo            finfo;
  90.     int                appRunning;
  91.     AEDesc            appDesc;
  92.     AliasHandle        docAlias;
  93.     AppleEvent        openAE;
  94.     AppleEvent        replyAE;
  95.     AEDescList        docList;
  96.     
  97.     // initialize
  98.     
  99.     openAE.dataHandle = nil;
  100.     replyAE.dataHandle = nil;
  101.     appDesc.dataHandle = nil;
  102.     docList.dataHandle = nil;
  103.     
  104.     docAlias = nil;
  105.             
  106.     // see if the app is running
  107.     
  108.     appRunning = is_it_running( app_sig );
  109.     
  110.     if (!appRunning) {
  111.         nshc_calls->NSH_putStr_err("\podoc: Target process is not running\r");
  112.         return(1);
  113.         }
  114.  
  115.     myErr = AECreateDesc(typeApplSignature,
  116.                          (Ptr)&app_sig,
  117.                          sizeof(app_sig),
  118.                          &appDesc);
  119.     if (myErr) goto Cleanup;    
  120.                          
  121.     myErr = NewAlias(nil,doc_fss,&docAlias);
  122.     if (myErr) goto Cleanup;    
  123.  
  124.     myErr = AECreateAppleEvent(kCoreEventClass,
  125.                                kAEOpenDocuments,
  126.                                &appDesc,
  127.                                kAutoGenerateReturnID,
  128.                                kAnyTransactionID,
  129.                                &openAE);
  130.     if (myErr) goto Cleanup;    
  131.  
  132.     myErr = AECreateList(nil,0,false,&docList);
  133.     if (myErr) goto Cleanup;    
  134.  
  135.     HLock((Handle)docAlias);
  136.     myErr = AEPutPtr(&docList,
  137.                      0,
  138.                      typeAlias,
  139.                      (Ptr)*docAlias,
  140.                      sizeof(AliasHandle)+(**docAlias).aliasSize);
  141.     HUnlock((Handle)docAlias);
  142.     if (myErr) goto Cleanup;    
  143.  
  144.     myErr = AEPutParamDesc(&openAE,keyDirectObject,&docList);
  145.     if (myErr) goto Cleanup;
  146.     
  147.     myErr = AESend(&openAE,&replyAE,kAENoReply,kAENormalPriority,kAEDefaultTimeout,nil,nil);
  148.         
  149. Cleanup:
  150.  
  151.     if (myErr) nshc_calls->NSH_putStr_err("\podoc: Message could not be sent.\r");
  152.     
  153.     if (docList.dataHandle) AEDisposeDesc(&docList);
  154.     if (openAE.dataHandle) AEDisposeDesc(&openAE);
  155.     if (replyAE.dataHandle) AEDisposeDesc(&replyAE);
  156.     if (appDesc.dataHandle) AEDisposeDesc(&appDesc);
  157.     
  158.     if (docAlias) DisposHandle((Handle)docAlias);
  159.     
  160.     return(myErr);
  161. }
  162.  
  163. /* ======================================== */
  164.  
  165. OSErr launch( int gotFSSpec, FSSpec *launchApp, FSSpec *launchDoc, t_nshc_calls *nshc_calls )
  166. {    
  167.     AEDesc                docDesc;
  168.     AEDesc                parmDesc;
  169.     AEDesc                adrDesc;
  170.     AEDescList            docList;
  171.     AliasHandle            docAlias;
  172.     AppleEvent            fakeEvent;
  173.     AppParametersPtr    docParm;
  174.     LaunchParamBlockRec    launchThis;
  175.     OSErr                myErr;
  176.     ProcessSerialNumber myPSN;
  177.     
  178.     // initialize
  179.     
  180.     docDesc.dataHandle = nil;
  181.     parmDesc.dataHandle = nil;
  182.     adrDesc.dataHandle = nil;
  183.     docList.dataHandle = nil;
  184.     docAlias = nil;
  185.     fakeEvent.dataHandle = nil;
  186.  
  187.     GetCurrentProcess(&myPSN);        // used to initialize new AE things
  188.     
  189.     // create the address desc for the event
  190.     
  191.     myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&myPSN, sizeof(ProcessSerialNumber), &adrDesc);
  192.     if (myErr) goto Cleanup;
  193.  
  194.     // stuff it in my launch parameter block
  195.     
  196.     launchThis.launchAppSpec = launchApp;
  197.     
  198.     if (launchDoc) {
  199.         
  200.         // create an apple event for "open doc"
  201.         myErr = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &adrDesc, kAutoGenerateReturnID, kAnyTransactionID, &fakeEvent);
  202.         if (myErr) goto Cleanup;
  203.  
  204.         // create a list to hold the doc alias
  205.         myErr = AECreateList(nil, 0, false, &docList);
  206.         if (myErr) goto Cleanup;
  207.     
  208.         // ae needs an alias to the doc
  209.         myErr = NewAlias(nil, launchDoc, &docAlias);
  210.         if (myErr) goto Cleanup;
  211.  
  212.         // and a descriptor for the alias
  213.         HLock((Handle)docAlias);
  214.         myErr = AECreateDesc(typeAlias, (Ptr)*docAlias, GetHandleSize((Handle)docAlias), &docDesc);
  215.         HUnlock((Handle)docAlias);
  216.         if (myErr) goto Cleanup;
  217.     
  218.         // the descriptor goes in the list
  219.         myErr = AEPutDesc(&docList, 0, &docDesc);
  220.         if (myErr) goto Cleanup;
  221.         
  222.         // and the list goes into the event
  223.         myErr = AEPutParamDesc(&fakeEvent, keyDirectObject, &docList);
  224.         if (myErr) goto Cleanup;
  225.     
  226.         // but the fake event is REALLY a parameter!
  227.         myErr = AECoerceDesc(&fakeEvent, typeAppParameters, &parmDesc);
  228.         if (myErr) goto Cleanup;
  229.         
  230.         docParm = (AppParametersPtr)*(parmDesc.dataHandle);
  231.         }
  232.     else
  233.         docParm = nil;
  234.     
  235.     // stuff the LaunchParamBlockRec and send it
  236.     
  237.     HLock((Handle)fakeEvent.dataHandle);
  238.     
  239.     launchThis.launchAppParameters = docParm;
  240.     launchThis.launchBlockID = extendedBlock;
  241.     launchThis.launchEPBLength = extendedBlockLen;
  242.     launchThis.launchFileFlags = 0;
  243.     launchThis.launchControlFlags = launchContinue + launchNoFileFlags;
  244.     
  245.     myErr = LaunchApplication(&launchThis);
  246.     
  247.     HUnlock((Handle)fakeEvent.dataHandle);
  248.     
  249. Cleanup:
  250.  
  251.     if (myErr) nshc_calls->NSH_putStr_err("\plaunch: Message could not be sent.\r");
  252.     
  253.     if ( docDesc.dataHandle ) AEDisposeDesc(&docDesc);
  254.     if ( parmDesc.dataHandle ) AEDisposeDesc(&parmDesc);
  255.     if ( adrDesc.dataHandle ) AEDisposeDesc(&adrDesc);
  256.     if ( docList.dataHandle ) AEDisposeDesc(&docDesc);
  257.     if ( fakeEvent.dataHandle )AEDisposeDesc(&fakeEvent);
  258.  
  259.     if ( docAlias ) DisposeHandle((Handle)docAlias);
  260.  
  261.     return(myErr);
  262. }
  263.  
  264. /* ======================================== */
  265.  
  266. int SearchOne( short vol, OSType creator, FSSpec *app_fss )
  267. {
  268.     DTPBRec        desktopParams;
  269.     OSErr        myErr;
  270.     int            found;
  271.     
  272.     found = 0;
  273.  
  274.     desktopParams.ioVRefNum = vol;
  275.     desktopParams.ioNamePtr = nil;
  276.     
  277.     myErr = PBDTGetPath(&desktopParams);
  278.     
  279.     if (!myErr && (desktopParams.ioDTRefNum != 0)) {
  280.     
  281.         desktopParams.ioIndex = 0;
  282.         desktopParams.ioFileCreator = creator;
  283.         desktopParams.ioNamePtr = app_fss->name;
  284.         
  285.         myErr = PBDTGetAPPLSync(&desktopParams);
  286.         
  287.         if (!myErr) {
  288.         
  289.             // okay, found it; fill in the application file spec
  290.             // and set the flag indicating we're done
  291.             
  292.             app_fss->parID = desktopParams.ioAPPLParID;
  293.             app_fss->vRefNum = desktopParams.ioVRefNum;
  294.             found = 1;
  295.             
  296.         }
  297.     }
  298.     
  299.     return( found );    
  300. }
  301.  
  302. int SearchAllButOne( Boolean remote_search, OSType creator, FSSpec *doc_fss, FSSpec *app_fss )
  303. {
  304.     HParamBlockRec            hfsParams;
  305.     FInfo                    documentFInfo;
  306.     short                    volumeIndex;
  307.     int                        found;
  308.     GetVolParmsInfoBuffer    volumeInfoBuffer;
  309.     OSErr                    myErr;
  310.     
  311.     found = 0;
  312.     volumeIndex = 0;
  313.     
  314.     while (!found) {
  315.         
  316.         volumeIndex++;
  317.             
  318.         // convert the volumeIndex into a vRefNum
  319.         
  320.         hfsParams.volumeParam.ioNamePtr = nil;
  321.         hfsParams.volumeParam.ioVRefNum = 0;
  322.         hfsParams.volumeParam.ioVolIndex = volumeIndex;
  323.         myErr = PBHGetVInfoSync(&hfsParams);
  324.         
  325.         // a nsvErr indicates that the current pass is over
  326.         if (myErr) return( 0 );
  327.         
  328.         // since we handled the document volume during the documentPass,
  329.         // skip it if we have hit that volume again
  330.         
  331.         if (hfsParams.volumeParam.ioVRefNum != doc_fss->vRefNum) {
  332.         
  333.             // call GetVolParms to determine if this volume is a server
  334.             // (a remote volume)
  335.             
  336.             hfsParams.ioParam.ioBuffer = (Ptr) &volumeInfoBuffer;
  337.             hfsParams.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer);
  338.             myErr = PBHGetVolParmsSync(&hfsParams);
  339.             
  340.             if (myErr) return( 0 );
  341.             
  342.             // if the vMServerAdr field of the volume information buffer
  343.             // is zero, this is a local volume; skip this volume
  344.             // if it's local on a remote pass or remote on a local pass
  345.             
  346.             if ( ( volumeInfoBuffer.vMServerAdr == 0 ) != remote_search )
  347.                 found = SearchOne( hfsParams.volumeParam.ioVRefNum, creator, app_fss );
  348.                 
  349.             }
  350.                 
  351.     }
  352.     
  353.     return( found );
  354. }
  355.  
  356. /* ======================================== */
  357.  
  358. int find_app( OSType creator, FSSpec *doc_fss, FSSpec *app_fss )
  359. {
  360.     OSErr    found;
  361.     
  362.     found = SearchOne( doc_fss->vRefNum, creator, app_fss );
  363.     
  364.     if (!found)
  365.         found = SearchAllButOne( 0, creator, doc_fss, app_fss );
  366.  
  367.     if (!found)
  368.         found = SearchAllButOne( 1, creator, doc_fss, app_fss );
  369.         
  370.     return(found);
  371. }
  372.  
  373. /* ======================================== */
  374.  
  375. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  376. {
  377.     FInfo    finfo;
  378.     FSSpec    app_fss;
  379.     FSSpec    doc_fss;
  380.     int        gotFSSpec;
  381.     int        result;
  382.     OSType    creator;
  383.     
  384. #ifdef __MWERKS__
  385.     long oldA4  = SetCurrentA4();
  386. #endif
  387.     
  388.     nshc_parms->action = nsh_idle;        // always one pass to this command
  389.     gotFSSpec = fss_test();                // find out if fss is there
  390.     
  391.     // *** reason not to run 1 - bad included version
  392.     
  393.     if (nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION )) {
  394.         result = NSHC_ERR_VERSION;
  395.         goto Cleanup;
  396.         }
  397.     
  398.     // *** reason not to run 2 - bad os version
  399.     
  400.     if ( Pre7() ) {
  401.         nshc_calls->NSH_putStr_err("\podoc: This command requires System 7.\r");
  402.         result = NSHC_ERR_GENERAL;
  403.         goto Cleanup;
  404.         }
  405.         
  406.     // *** reason not to run 3 - bad parameters
  407.     
  408.     if (( nshc_parms->argc < 2 ) || ( nshc_parms->argc > 3 )) {
  409.         nshc_calls->NSH_putStr_err("\pUsage: odoc doc_path [app_path]\r");
  410.         result = NSHC_ERR_PARMS;
  411.         goto Cleanup;
  412.         }
  413.         
  414.     // *** reason not to run 4 - can't find doc
  415.     
  416.     result = arg_to_fss( nshc_parms, nshc_calls, 1, &doc_fss );
  417.  
  418.     if (!result)
  419.         result = fss_GetFInfo( gotFSSpec, &doc_fss, &finfo );
  420.  
  421.     if (result) {
  422.         nshc_calls->NSH_putStr_err("\podoc: Document not found.\r");
  423.         result = NSHC_ERR_PARMS;
  424.         goto Cleanup;
  425.         }
  426.         
  427.     creator = finfo.fdCreator;        // if nothing else, use doc's creator
  428.                     
  429.     // *** reason not to run 5 - can't find app
  430.     
  431.     if ( nshc_parms->argc > 2 ) {
  432.     
  433.         result = arg_to_fss( nshc_parms, nshc_calls, 2, &app_fss );
  434.         
  435.         if (!result)
  436.             result = fss_GetFInfo( gotFSSpec, &app_fss, &finfo );
  437.     
  438.         if (result || ( finfo.fdType != 'APPL' ) ) {
  439.             nshc_calls->NSH_putStr_err("\podoc: Application not found.\r");
  440.             result = NSHC_ERR_PARMS;
  441.             goto Cleanup;
  442.             }
  443.             
  444.         creator = finfo.fdCreator;        // if available, use apps's creator
  445.                     
  446.         }
  447.         
  448.     // see if we should open or launch
  449.     
  450.     if (is_it_running( creator )) {
  451.         
  452.         // *** finally try to open the thing
  453.             
  454.         result = odoc( gotFSSpec, &doc_fss, creator, nshc_calls );
  455.  
  456.         }
  457.     
  458.     else {
  459.     
  460.         // *** or else try to launch it
  461.             
  462.         if ( nshc_parms->argc < 3 )
  463.             if ( !find_app( creator, &doc_fss, &app_fss ) ) {
  464.                 nshc_calls->NSH_putStr_err("\podoc: Document creator not found.\r");
  465.                 result = NSHC_ERR_PARMS;
  466.                 goto Cleanup;
  467.                 }
  468.         
  469.         result = launch( gotFSSpec, &app_fss, &doc_fss, nshc_calls );
  470.  
  471.         }
  472.  
  473.     // *** log the result and return
  474.     
  475. Cleanup:
  476.             
  477.     nshc_parms->result = result;
  478.  
  479. #ifdef __MWERKS__
  480.     SetA4(oldA4);        // CodeWarrior needs to restore A4
  481. #else
  482.     ;                    // Think needs a ; to go with the Cleanup label
  483. #endif
  484. }
  485.