home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / DClap / DChildApp.cpp < prev    next >
Encoding:
Text File  |  1995-12-17  |  8.0 KB  |  347 lines  |  [TEXT/R*ch]

  1. // DChildApp.cpp
  2.  
  3.  
  4. #include "DClap.h"
  5. #include "DChildApp.h"
  6.  
  7.  
  8. #ifdef WIN_MAC
  9.     // undef some conflicts b/n Types.h && NlmTypes
  10. #undef Handle
  11. #undef true
  12. #undef false
  13. //#undef Boolean
  14. #include <AppleEvents.h>
  15. #include <Processes.h>
  16. //#define Boolean  Nlm_Boolean
  17. #endif
  18.  
  19. //class DChildFile : public DFile
  20.  
  21.  
  22. DChildFile::DChildFile( const char* filename, short kind, Boolean deleteWhenDone,
  23.     short doneAction, const char* openmode, const char* ftype, const char* fcreator) :
  24.     DFile( filename, openmode, ftype, fcreator),
  25.     fAction(doneAction), fKind(kind), fDelete( deleteWhenDone)
  26. {
  27.     if (!openmode) switch (fKind) {
  28.         case kInput: 
  29.         case kStdin:  fMode= StrDup("r"); break;    //?? we really open "w" not "r" ??
  30.         case kOutput: fMode= StrDup("r"); break;  //?? we really open "r" not "w" !? 
  31.         case kStdout: fMode= StrDup("r"); break;  // was "a", ??? "w" or "a"
  32.         case kStderr: fMode= StrDup("r"); break;  // was "a", ??? "w" or "a"
  33.         }
  34. }
  35.  
  36. DChildFile::~DChildFile()
  37. {
  38.     if (fDelete) this->Delete();
  39. }
  40.  
  41. void DChildFile::ClearStorage()
  42. {
  43.     this->Close();
  44.     if (fDelete) this->Delete();
  45. }
  46.  
  47.  
  48.  
  49.  
  50.  
  51. //class DChildApp : public DTaskMaster
  52.     
  53. DChildApp::DChildApp() :     
  54.     DTaskMaster(0),
  55.     fName(NULL), fCmdline(NULL), 
  56.     fStdin(NULL), fStdout(NULL), fStderr(NULL),
  57.     fLaunched(0), fResult(0), fReusable(false),
  58.     fProcessNum(0), fFiles(NULL)
  59. {
  60.   if (!DChildAppManager::gChildList) DChildAppManager::gChildList= new DList();
  61.     DChildAppManager::gChildList->InsertLast( this); // do this here so caller doesn't forget
  62. }
  63.  
  64.  
  65. DChildApp::DChildApp( char* appname, char* cmdline, 
  66.     Boolean showStdout, char* Stdinfile, Boolean showStderr)  :  
  67.     DTaskMaster(0),
  68.     fName(NULL), fCmdline(NULL), 
  69.     fStdin(NULL), fStdout(NULL), fStderr(NULL),
  70.     fLaunched(0), fResult(0), fReusable(false),
  71.     fProcessNum(0), fFiles(NULL)
  72. {
  73.     fName= StrDup( appname);
  74.     fCmdline= StrDup( cmdline);
  75.     fFiles= new DList();
  76.  
  77.     // this is called for launching docs as well as apps,
  78.     // don't do the stdout/stderr stuff if this is doc
  79.     if (showStdout) AddFile( DChildFile::kStdout, NULL);
  80.     if (showStderr) AddFile( DChildFile::kStderr, NULL);
  81.     if (Stdinfile) AddFile( DChildFile::kStdin, Stdinfile);
  82.     
  83.   if (!DChildAppManager::gChildList) DChildAppManager::gChildList= new DList();
  84.     DChildAppManager::gChildList->InsertLast( this); // do this here so caller doesn't forget
  85. }
  86.  
  87.  
  88. #if 0
  89. DChildApp* DChildAppManager::newChildApp( char* appname, char* cmdline, 
  90.     Boolean Stdout, char* Stdinfile, Boolean Stderr)
  91. {  
  92.     DChildApp* aChild= new DChildApp( char* appname, char* cmdline, 
  93.         Boolean Stdout, char* Stdinfile, Boolean Stderr);
  94.     gChildList->InsertLast( aChild); // !! must do this here or ?? in DChildapp constructors?
  95.     return aChild;
  96. }
  97. #endif
  98.  
  99.  
  100. DChildApp::~DChildApp()
  101. {
  102.     MemFree( fName);
  103.     MemFree( fCmdline);
  104.     if (fFiles) {
  105.         short i, n= fFiles->GetSize();
  106.         for (i=0; i<n; i++) {
  107.             DChildFile* afile= (DChildFile*) fFiles->At(i);
  108.             delete afile;
  109.             }
  110.         delete fFiles;
  111.         }
  112.     DChildAppManager::gChildList->Delete( this); //need here to balance constructor Insert()
  113. }
  114.  
  115.  
  116.  
  117. void DChildApp::AddInputBuffer( short filekind, char* buffer, ulong buflen)
  118. {
  119.     char    namestore[512], *name;
  120.     DChildFile* aFile;
  121.     name= gFileManager->TempFilename(namestore);
  122.     switch (filekind) {
  123.         case DChildFile::kInput: 
  124.         case DChildFile::kStdin:  
  125.             aFile= new DChildFile( name, filekind, true, DChildFile::kNoAction);
  126.             break;
  127.         default:
  128.             return;
  129.         }
  130.     if (aFile) {
  131.         aFile->Open("w");
  132.         aFile->WriteData( buffer, buflen);
  133.         aFile->Close();
  134.         aFile->SetMode("r");
  135.         this->AddFile( aFile);
  136.         }
  137. }
  138.  
  139. void DChildApp::AddFile( DChildFile* aFile)
  140. {
  141.         // ?? need to check if fFiles already has one of stdio types ??
  142.     fFiles->InsertLast( aFile);
  143.     switch (aFile->fKind) {
  144.         case DChildFile::kStdin:  
  145.             fStdin= aFile->GetName();
  146.             break;
  147.         case DChildFile::kStdout:  
  148.             fStdout= aFile->GetName();
  149.             break;
  150.         case DChildFile::kStderr:  
  151.             fStderr= aFile->GetName();
  152.             break;
  153.         }
  154. }
  155.  
  156. void DChildApp::AddFile( short filekind, char* name)
  157. {
  158.     char    namestore[512];
  159.     DChildFile* aFile;
  160.     if (!name) {
  161.         if (filekind == DChildFile::kStdin || filekind == DChildFile::kInput) return;
  162.         name= gFileManager->TempFilename(namestore);
  163.       }
  164.       
  165.     switch (filekind) {
  166.         case DChildFile::kInput: 
  167.         case DChildFile::kStdin:  
  168.             aFile= new DChildFile( name, filekind, false, DChildFile::kNoAction);
  169.             break;
  170.         
  171.         case DChildFile::kOutput:   
  172.         case DChildFile::kStdout:  
  173.             aFile= new DChildFile( name, filekind, false);
  174.             break;
  175.         case DChildFile::kStderr:  
  176.             aFile= new DChildFile( name, filekind, true);
  177.             break;
  178.         }
  179.     this->AddFile( aFile);
  180.  
  181.  
  182.  
  183. #ifdef WIN_MAC
  184. extern "C" ProcessSerialNumber  gChildProcessSN;
  185. #else
  186. extern "C" long gChildProcessSN;
  187. #endif
  188.  
  189. class DBurialTask : public DTask {
  190. public:
  191.     DBurialTask( long processnum, DTaskMaster* itsSource) :
  192.         DTask( processnum, DTask::kOtherTask, itsSource) {}
  193.     virtual void DoIt() { DChildAppManager::BuryDeadChildApp(fNumber); }
  194. };
  195.  
  196.  
  197. Boolean DChildApp::Launch()
  198. {
  199.         // ?? want special handling for stdin/stdout/stderr files !!
  200.         // !! must assume OtherFiles are already handled, either in cmdline or by child app !!
  201.     fResult= 0;
  202.     if (fName || fCmdline) {
  203.         fLaunched++;
  204.         fResult= Dgg_LaunchApp( fName, fCmdline, (char*)fStdin, (char*)fStdout, (char*)fStderr);
  205.  
  206.         if (fResult) {
  207. #ifdef WIN_MAC
  208.             fProcessNum= (long) MemNew(sizeof(ProcessSerialNumber));
  209.             *((ProcessSerialNumberPtr) fProcessNum)= gChildProcessSN;
  210. #else
  211.             fProcessNum= gChildProcessSN;
  212. #endif
  213.  
  214. #ifdef WIN_MSWIN
  215.         // can we assume no multiprocessing?? that child app is terminated by here??
  216.             DBurialTask* buryMe = new DBurialTask( gChildProcessSN, this);
  217.             PostTask( buryMe);
  218. #endif
  219.  
  220.             //gChildList->InsertLast( this); // done in constructor;
  221.             // can we assume only one copy of this in list ??
  222.             } 
  223.         }
  224.     return fResult;
  225. }
  226.  
  227.  
  228. void DChildApp::FileAction(DChildFile* aFile)
  229. {
  230.     switch (aFile->fAction) {
  231.       case DChildFile::kOpenPict:
  232.         case DChildFile::kOpenText:
  233.             gApplication->OpenDocument( aFile);
  234.             break;
  235.         default:
  236.             break;
  237.         }
  238. }
  239.  
  240. void DChildApp::Finished()
  241. {
  242.     fLaunched--; // ?? or use this as counter?
  243.     if (fFiles) {
  244.         short i, n= fFiles->GetSize();
  245.         for (i=0; i<n; i++) {
  246.             DChildFile* aFile= (DChildFile*) fFiles->At(i);
  247.             if (aFile->Exists() && aFile->LengthF()>0) 
  248.                 FileAction( aFile);
  249.             aFile->ClearStorage();
  250.             }
  251.         }
  252. }
  253.  
  254.  
  255.  
  256. // class DExternalHandler : public DChildApp
  257.  
  258. DExternalHandler::DExternalHandler( char* cmdlineOrDocname) :
  259.     DChildApp( cmdlineOrDocname, NULL, false, NULL, false)
  260. {
  261. }
  262.  
  263. Boolean DExternalHandler::Launch()
  264. {
  265.     return DChildApp::Launch();
  266. }
  267.  
  268. void DExternalHandler::Finished()
  269. {
  270.     DChildApp::Finished();
  271. }
  272.             
  273.  
  274.  
  275.  
  276.  
  277. // class DChildAppManager : public DObject
  278.  
  279.  
  280. //static
  281. DList* DChildAppManager::gChildList = NULL; // new DList(); << bad on SGI // of DChildApp
  282.  
  283. DChildAppManager::DChildAppManager()
  284. {
  285. }
  286.  
  287.  
  288. //static
  289. short DChildAppManager::BuryDeadChildApp( long theEvent)
  290. {
  291. #ifdef WIN_MAC
  292.     short         err;
  293.     long             appErr;
  294.     Size            actualSize;
  295.     ProcessSerialNumber appSN;
  296.     DescType     returnedType;
  297.      AppleEvent* theAppleEvent;
  298.      
  299.      if (theEvent) {
  300.      theAppleEvent = (AppleEvent*) theEvent;
  301.  
  302.     err= ::AEGetParamPtr( theAppleEvent, keyErrorNumber, typeLongInteger, 
  303.                                                 &returnedType, &appErr, sizeof(appErr), &actualSize);
  304.     if (appErr == 0) { 
  305.         err = AEGetParamPtr( theAppleEvent, keyProcessSerialNumber, typeProcessSerialNumber, 
  306.                                                     &returnedType, &appSN, sizeof(appSN), &actualSize);
  307.         Boolean match;
  308.         DChildApp* child= NULL;
  309.         short i, n= gChildList->GetSize();
  310.         for (i=0, match= false; !match && i<n; i++) {
  311.             child= (DChildApp*) gChildList->At(i);
  312.             err= ::SameProcess( (ProcessSerialNumberPtr)child->fProcessNum, &appSN, &match);
  313.             }
  314.             
  315.         if (match) {
  316.             child->Finished();
  317.             //gChildList->Delete(child); // done by child destructor
  318.             if (!child->fReusable) delete child; 
  319.             }
  320.      }
  321.      }
  322. #endif
  323.  
  324. #if defined(WIN_MOTIF) || defined(WIN_MSWIN)
  325.     // use unix(?) signals
  326.     Boolean match;
  327.     DChildApp* child= NULL;
  328.     short i, n= gChildList->GetSize();
  329.     for (i=0, match= false; !match && i<n; i++) {
  330.         child= (DChildApp*) gChildList->At(i);
  331.         match= (child->fProcessNum == theEvent);
  332.         }
  333.     if (match) {
  334.         child->Finished();
  335.         //gChildList->Delete(child); // done by child destructor
  336.         if (!child->fReusable) delete child; 
  337.         }
  338. #endif
  339.     return 0;
  340. }
  341.  
  342.  
  343.  
  344.  
  345.  
  346.