home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Add-Ons / WebSTAR / PPSendPartial CGI / Source / LMainCGI.cp < prev    next >
Encoding:
Text File  |  1996-10-11  |  12.6 KB  |  529 lines  |  [TEXT/CWIE]

  1. /***
  2.     File:        LMainCGI.cp
  3.  
  4.  
  5.     Contains:    Main thread for CGI
  6.  
  7.  
  8.     Written by:    Ken Wieschhoff
  9.  
  10.  
  11.     Copyright:    ©1996 Siren Enterprises, All Rights Reserved.
  12.  
  13.  
  14.     Change History (most recent first):
  15.  
  16.  
  17.  
  18.        <1>     9/5/96  kw     Original
  19.  
  20. ***/
  21.  
  22.  
  23. #include <stdio.h>
  24. #include <LWindow.h>
  25. #include <PP_Messages.h>
  26. #include <PP_Resources.h>
  27. #include <URegistrar.h>
  28. #include <PPobClasses.h>
  29. #include <LGrowZone.h>
  30. #include <UMemoryMgr.h>
  31. #include <LMenuBar.h>
  32. #include <LMenu.h>
  33. #include <LListIterator.h>
  34. #include <LPicture.h>
  35. #include <LCaption.h>
  36. #include <LDialogBox.h>
  37. #include <LEditField.h>
  38. #include <LStdControl.h>
  39. #include <LWindow.h>
  40. #include <LThread.h>
  41. #include <PP_KeyCodes.h>
  42. #include <UAppleEventsMgr.h>
  43. #include <UDesktop.h>
  44. #include <UException.h>
  45. #include <UExtractFromAEDesc.h>
  46. #include <UReanimator.h>
  47. #include <UScreenPort.h>
  48. #include <UThread.h>
  49. #include <string.h>
  50. #include <UDrawingState.h>
  51. #include <TextServices.h>
  52. #include <Profiler.h>
  53. #include "LMainCGI.h"
  54. #include "LRequest.h"
  55.  
  56.  
  57. const UInt32    kAppRunQuantum    = 0;
  58. const UInt32    ae_CGI            = 5000;
  59. const UInt32    kPostDataSize    = 8192;
  60.  
  61.  
  62. LMainCGI            *LMainCGI::sApplication        = nil;
  63. LThread                *LMainCGI::sMainThread        = nil;
  64. LCGIStatusThread    *LMainCGI::sStatusThread     = nil;
  65. AEIdleUPP             LMainCGI::sIdleUPP            = nil;
  66.  
  67. ExitToShellProcUPP        gOldExitToShell = nil;
  68. ExitToShellProcUPP        gNewExitToShell = nil;
  69. Boolean                    gCreditsRunning = false;
  70.  
  71. extern WindowPtr                LStatusWindow::sMacWindowP;
  72. extern GetNextEventFilterUPP    gOldHook;
  73.  
  74.  
  75. // ===========================================================================
  76. //        • Main Program
  77. // ===========================================================================
  78.  
  79. void main(void)
  80. {
  81.                                     // Set Debugging options
  82.                                     
  83. #ifdef Debug_Throw
  84.     gDebugThrow = debugAction_Alert;
  85. #endif
  86.  
  87. #ifdef Debug_Signal
  88.     gDebugSignal = debugAction_Alert;
  89. #endif
  90.  
  91. #if __profile__
  92.     ProfilerInit( collectDetailed, bestTimeBase, 20, 5);
  93. #endif
  94.  
  95.     InitializeHeap(4);
  96.     UQDGlobals::InitializeToolbox(&qd);
  97.     new LGrowZone(20000);
  98.     
  99.     RunApplication();
  100.  
  101. #if __profile__
  102.     ProfilerDump( "\pProfileInfo.prof");
  103.     ProfilerTerm();
  104. #endif
  105. }
  106.  
  107.  
  108. // ===========================================================================
  109. //        • RunApplication
  110. // ===========================================================================
  111.  
  112. static void    RunApplication(void)
  113. {
  114.     // create & initialize the application object
  115.     LMainCGI    *theApp;
  116.  
  117.  
  118. #if !GENERATINGCFM
  119.     // Store our current A5 (globals frame) for use by the GNE Filter
  120.     *A5Stash() = (long)LMGetCurrentA5();
  121. #endif
  122.  
  123.     // Patch ExitToShell so we can remove the GNEFilter in case of disaster
  124.     gOldExitToShell = (ExitToShellProcUPP)NGetTrapAddress( _ExitToShell, ToolTrap);
  125.     gNewExitToShell = NewExitToShellProc( ExitCGI);
  126.     NSetTrapAddress( (UniversalProcPtr)gNewExitToShell, _ExitToShell, ToolTrap);
  127.  
  128.     theApp    = new LMainCGI;
  129.  
  130.     // execute the app
  131.     theApp->Run();
  132.  
  133.     delete theApp;
  134. }
  135.  
  136. // ===========================================================================
  137. //        • ExitCGI
  138. // ===========================================================================
  139.  
  140. pascal void ExitCGI() {
  141.  
  142. #if !GENERATINGCFM
  143.     // Reset to our globals for 68K machines.
  144.     long    oldA5 = SetA5(*A5Stash());
  145. #endif
  146.  
  147.     ExitToShellProcUPP        oldExitToShell = gOldExitToShell;
  148.  
  149.  
  150.     if (LStatusWindow::sMacWindowP != nil) {
  151.         ::CloseServiceWindow(LStatusWindow::sMacWindowP);
  152.         LStatusWindow::sMacWindowP = nil;
  153.     }
  154.  
  155.     // Remove the GNE Filter from the application
  156.     RemoveGNEFilter();
  157.  
  158. #if !GENERATINGCFM
  159.     // Reset to caller's globals.
  160.     SetA5( oldA5);
  161. #endif
  162.  
  163.     // Call the old trap.
  164.     CallExitToShellProc( oldExitToShell);
  165.  
  166. }
  167.  
  168.  
  169. // ===========================================================================
  170. //        • GetApplication
  171. // ===========================================================================
  172. //    Returns a pointer to the global application object
  173.  
  174. LMainCGI    *LMainCGI::GetApplication(void)
  175. {
  176.     return (sApplication);
  177. }
  178.  
  179.  
  180. // ===========================================================================
  181. //        • LMainCGI
  182. // ===========================================================================
  183. //    Constructor
  184.  
  185. LMainCGI::LMainCGI()
  186. {    
  187.     sApplication = this;
  188.  
  189.     // Create the UPP for the threaded AppleEvent Idler Proc
  190.     sIdleUPP    = NewAEIdleProc(AEIdleProc); 
  191.  
  192.     // Create the main application thread.
  193.     sMainThread = new LMainCGIThread;
  194.  
  195.     // Create the Status Window thread.
  196.     sStatusThread = new LCGIStatusThread( this);
  197.     sStatusThread->Resume();
  198.  
  199.     // Add the Yield attachment to yield to all new threads
  200.     AddAttachment(new LYieldAttachment(kAppRunQuantum));
  201.     
  202.     UScreenPort::Initialize();    
  203. }
  204.  
  205.  
  206. // ===========================================================================
  207. //        • ~LMainCGI
  208. // ===========================================================================
  209. //    Destructor
  210. //
  211.  
  212. LMainCGI::~LMainCGI()
  213. {
  214.     if (sIdleUPP != nil)    
  215.         DisposeRoutineDescriptor(sIdleUPP);
  216.  
  217. }
  218.  
  219.  
  220.  
  221. // ===========================================================================
  222. //        • ObeyCommand
  223. // ===========================================================================
  224. //    Respond to commands
  225.  
  226. Boolean
  227. LMainCGI::ObeyCommand(
  228.     CommandT    inCommand,
  229.     void        *ioParam)
  230. {
  231.     Boolean        cmdHandled = true;
  232.     
  233.     switch (inCommand) {
  234.             
  235.         case cmd_Open:
  236.             sStatusThread->OpenStatusWindow();
  237.             break;
  238.             
  239.         case cmd_Close:
  240.             sStatusThread->CloseStatusWindow();
  241.             break;
  242.  
  243.         default:
  244.             cmdHandled = LApplication::ObeyCommand(inCommand, ioParam);
  245.             break;
  246.     }
  247.     
  248.     return cmdHandled;
  249. }
  250.  
  251. // ===========================================================================
  252. //        • FindCommandStatus
  253. // ===========================================================================
  254. //    This function enables menu commands.
  255. //
  256.  
  257. void
  258. LMainCGI::FindCommandStatus(
  259.     CommandT    inCommand,
  260.     Boolean        &outEnabled,
  261.     Boolean        &outUsesMark,
  262.     Char16        &outMark,
  263.     Str255        outName)
  264. {
  265.     
  266.     switch (inCommand) {
  267.             
  268.         case cmd_Open:
  269.             if ( sStatusThread->mWindow == nil)
  270.                 outEnabled = true;
  271.             else
  272.                 outEnabled = false;
  273.                 
  274.             break;
  275.             
  276.         case cmd_Close:
  277.             if ( sStatusThread->mWindow != nil)
  278.                 outEnabled = true;
  279.             else
  280.                 outEnabled = false;
  281.             break;
  282.  
  283.         case cmd_Quit:
  284.         case cmd_About:
  285.             outEnabled = true;
  286.             break;
  287.             
  288.         default:
  289.             LApplication::FindCommandStatus(inCommand, outEnabled,
  290.                                                 outUsesMark, outMark, outName);
  291.             break;
  292.     }
  293. }
  294.  
  295. // ===========================================================================
  296. //        • HandleAppleEvent
  297. // ===========================================================================
  298. //    Dispatch the Apple Events that we know about.
  299.  
  300. void    LMainCGI::HandleAppleEvent(
  301.     const AppleEvent    &inAppleEvent,
  302.     AppleEvent            &outAEReply,
  303.     AEDesc                &outResult,
  304.     long                inAENumber)
  305. {
  306.         
  307.     switch (inAENumber)
  308.     {
  309.     case ae_CGI:
  310.         // We just received a CGI event.  Handle it.
  311.         HandleCGIEvent(inAppleEvent, outAEReply, outResult );
  312.         break;
  313.         
  314.     default:
  315.         LApplication::HandleAppleEvent(inAppleEvent, outAEReply, outResult, inAENumber);
  316.         break;
  317.     }
  318.  
  319. }
  320.  
  321.  
  322. // ===========================================================================
  323. //        • GetSleepTime
  324. // ===========================================================================
  325. long    LMainCGI::GetSleepTime(void) const
  326. {
  327.     return (mSleepTime);
  328. }
  329.  
  330. // ===========================================================================
  331. //        • HandleCGIEvent
  332. // ===========================================================================
  333. void
  334. LMainCGI::HandleCGIEvent(
  335.     const AppleEvent    &inAppleEvent,
  336.     AppleEvent            &outAEReply,
  337.     AEDesc                & )
  338. {
  339.     LRequest            *itsRequest;
  340.     AEAddressDesc        WebSTARAddress;
  341.     DescType            typeCode;
  342.     Size                actualDataSize;
  343.     long                connectionID;
  344.     char                *itsString = "<SEND_PARTIAL>";
  345.     LStr255                itsReply;
  346.     Handle                data = nil;
  347.     StHandleLocker         *itsLocker = nil;
  348.         
  349.     Try_ {
  350.         // Fetch WebStar's return address
  351.         ThrowIfOSErr_( AEGetAttributeDesc( &inAppleEvent, 'from','****',&WebSTARAddress));
  352.  
  353.         // Fetch the connection ID.
  354.         ThrowIfOSErr_( AEGetParamPtr( &inAppleEvent, 'Kcid',typeLongInteger, 
  355.                             &typeCode, &connectionID, sizeof(connectionID) , &actualDataSize));
  356.         
  357.         // Reply immediately we'll be sending partial data.
  358.         if ( outAEReply.descriptorType != typeNull)
  359.             ThrowIfOSErr_( AEPutParamPtr( &outAEReply, keyDirectObject,typeChar,itsString,strlen(itsString)));
  360.              
  361.         // Create a pointer to hold the biggest block Webstar can send...
  362.         data = NewHandleClear ( kPostDataSize );
  363.         if ( data )
  364.         {
  365.             itsLocker = new StHandleLocker(data);
  366.             // Pull the form data off the appleevent into our buffer
  367.             Try_ {
  368.                 ThrowIfOSErr_( AEGetParamPtr ( &inAppleEvent, 'post', typeChar, &typeCode, *data, kPostDataSize, &actualDataSize ));
  369.             } Catch_ (inErr) {
  370.                 actualDataSize = 0; 
  371.             } EndCatch_;
  372.             
  373.             delete itsLocker, itsLocker = nil;
  374.             
  375.             // Resize the buffer for actual data size
  376.             SetHandleSize ( data, actualDataSize );
  377.         }
  378.  
  379.         itsRequest = new LRequest( WebSTARAddress, connectionID, data );
  380.         
  381.         // start working
  382.         itsRequest->Resume();
  383.  
  384.  
  385.     } Catch_ (inErr) {
  386.         // Ignore any errors.  
  387.     } EndCatch_;
  388.  
  389.     if ( itsLocker)
  390.         delete itsLocker;
  391.         
  392.     if ( data)
  393.         ::DisposeHandle( data);
  394. }
  395.  
  396. // ===========================================================================
  397. //        • ShowAboutBox
  398. // ===========================================================================
  399. //    Display the About Box for the Application
  400. void
  401. LMainCGI::ShowAboutBox()
  402. {
  403.  
  404.     LCreditThread            *itsCredits;
  405.  
  406.     itsCredits = new LCreditThread();
  407.     
  408.     itsCredits->Resume();
  409. }
  410.  
  411.  
  412. // ===========================================================================
  413. //        • AEIdleProc
  414. // ===========================================================================
  415. //    Thread-aware Apple Event idle proc, which does some of the same event 
  416. //    processing as LApplication::ProcessNextEvent().  In particular, it calls 
  417. //    LThread::Yield(), which gives control to other threads.
  418.  
  419. static pascal Boolean    AEIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn)
  420. {
  421.     LMainCGI    *theApp    = LMainCGI::GetApplication();
  422.     
  423.     *mouseRgn    = nil;
  424.     *sleepTime    = theApp->GetSleepTime();
  425.     
  426.     if (theEvent->what != nullEvent)
  427.         theApp->DispatchEvent(*theEvent);
  428.     else
  429.         theApp->UseIdleTime(*theEvent);
  430.     
  431.     LPeriodical::DevoteTimeToRepeaters(*theEvent);
  432.     
  433.     LThread::Yield();
  434.     
  435.     return (false);
  436. }
  437.  
  438.  
  439. // ===========================================================================
  440. //        • LMainCGIThread (Constructor)
  441. // ===========================================================================
  442. LMainCGIThread::LMainCGIThread()
  443.  
  444.     : UMainThread()
  445. {
  446.     // there's nothing else to do
  447. }
  448.  
  449.  
  450. // ===========================================================================
  451. //        • SwapContext
  452. // ===========================================================================
  453. //    Context-switching function for application's main thread.  Since there's 
  454. //    more than one thread doing any drawing, and that we draw from the main 
  455. //    thread, we have to make sure that LView doesn't make any erroneous 
  456. //    assumptions about the currently focused view.  In a nutshell, we have to 
  457. //    flush LView's cached view.
  458.  
  459. #pragma profile off
  460. void    LMainCGIThread::SwapContext(Boolean swappingIn)
  461. {
  462.     
  463.     UMainThread::SwapContext(swappingIn);
  464. }
  465.  
  466. #pragma profile reset
  467.  
  468. // ===========================================================================
  469. //        • LCreditThread (Constructor)
  470. // ===========================================================================
  471. LCreditThread::LCreditThread()
  472.     : LThread( false )
  473. {
  474.     // So we don't count this thread in the status window.
  475.     gCreditsRunning = true;
  476. }
  477.  
  478. // ===========================================================================
  479. //        • ~LCreditThread (Destructor)
  480. // ===========================================================================
  481. LCreditThread::~LCreditThread()
  482. {
  483.     gCreditsRunning = false;
  484. }
  485.  
  486.  
  487. // ===========================================================================
  488. //        • Run
  489. // ===========================================================================
  490. void*
  491. LCreditThread::Run()
  492. {
  493.     WindowPtr            itsWindow;
  494.     PicHandle            creditsPicture;
  495.     short                textOffset;
  496.  
  497.     DialogTHndl    theWIND = (DialogTHndl) ::GetResource('DLOG', 129);
  498.     
  499.     // Create yet another TSM window to do the credits.  For some reason
  500.     // "regular" windows and dialogs seem to block the AppleEvents W* sends
  501.     // which [obviously] upsets new connections.
  502.      ::NewServiceWindow( nil, &(**theWIND).boundsRect, (**theWIND).title, (**theWIND).visible, 
  503.             (**theWIND).procID, window_InFront, (**theWIND).goAwayFlag, 
  504.                 (ComponentInstance) kCurrentProcess, &itsWindow);
  505.  
  506.     if ( itsWindow) {
  507.         ShowWindow( itsWindow);
  508.  
  509.         creditsPicture = (PicHandle)GetResource( 'PICT', 128);
  510.         textOffset = -600;
  511.         
  512.         //ModalDialog( itsConfigDlgFilter, &item);
  513.         while ( !Button()) {
  514.             DrawCredits( itsWindow, creditsPicture, &textOffset); // <-Credits.c
  515.             LThread::Yield();
  516.         }
  517.         
  518.         ::CloseServiceWindow(itsWindow);
  519.         FlushEvents( mDownMask, 0);
  520.         
  521.     }
  522.  
  523.     if ( creditsPicture)
  524.         ReleaseResource( (Handle) creditsPicture);
  525.         
  526.     DeleteThread();
  527.     return nil;
  528. }
  529.