home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Add-Ons / WebSTAR / PPSendPartial CGI / Source / LCGIStatusWindow.cp < prev    next >
Encoding:
Text File  |  1997-02-26  |  12.3 KB  |  459 lines  |  [TEXT/CWIE]

  1. /***
  2.     File:        LCGIStatusWindow.cp
  3.  
  4.  
  5.     Contains:    Text Services status window
  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 "LMainCGI.h"
  24. #include "LCGIStatusWindow.h"
  25. #include <string.h>
  26. #include <UMemoryMgr.h>
  27. #include <LCaption.h>
  28. #include <LString.h>
  29. #include <TextServices.h>
  30. #include <UTextTraits.h>
  31. #include <UDrawingUtils.h>
  32.  
  33.  
  34. GetNextEventFilterUPP    gOldHook = nil;
  35. short                    gThisResource = 0;
  36. ProcessSerialNumber        gThisProcess;
  37. extern     Boolean            gCreditsRunning;
  38. WindowPtr                LStatusWindow::sMacWindowP    = nil;
  39. Boolean                    LCGIStatusThread::sNeedsRedraw    = false;
  40. Boolean                    LCGIStatusThread::sNeedsUpdate    = false;
  41. long                    LCGIStatusThread::sMaxConnected    = 0;
  42. long                    LCGIStatusThread::sTotalConnections    = 0;
  43. extern                     LCGIStatusThread *LMainCGI::sStatusThread;
  44.  
  45. #define    kStatusWindowID        128
  46. #define kRightJustified        1
  47. #define kLeftJustified        2
  48.  
  49. // ---------------------------------------------------------------------------
  50. //        • Constructor
  51. // ---------------------------------------------------------------------------
  52. LCGIStatusThread::LCGIStatusThread(LCommander *itsSuper)
  53.     : LThread( false )
  54. {
  55.     mWindow = nil;
  56.     
  57.     this->OpenStatusWindow();
  58.         
  59.     sNeedsUpdate = sNeedsRedraw = true;
  60.  
  61.     // Get our Process number.
  62.     GetCurrentProcess( &gThisProcess);
  63.     
  64.     // Stash the resource chain ID.
  65.     gThisResource = CurResFile();
  66.     
  67. }
  68.  
  69. // ---------------------------------------------------------------------------
  70. //        • Destructor
  71. // ---------------------------------------------------------------------------
  72. LCGIStatusThread::~LCGIStatusThread()
  73. {
  74.     if (mWindow)
  75.         delete mWindow;
  76.  
  77. }
  78.  
  79. // ---------------------------------------------------------------------------
  80. //        • Run
  81. // ---------------------------------------------------------------------------
  82. void*
  83. LCGIStatusThread::Run()
  84. {
  85.  
  86.     LStr255            textString;
  87.     GrafPtr            oldPort;
  88.     Int16            just;
  89.     DITLTemplateHdl    itsDITL = (DITLTemplateHdl)Get1Resource('DITL', 128);
  90.     StHandleLocker    aLocker( (Handle) itsDITL);
  91.     long            numberOfReadyThreads;
  92.         
  93.     // Give the main thread time to finish setting up.
  94.     for ( short i = 0; i < 20; i++)
  95.         LThread::Yield();
  96.  
  97.     while ( true) {
  98.         // Yield to any other thread
  99.         LThread::Yield();
  100.          
  101.         if ( mWindow) {
  102.             if ( sNeedsRedraw || sNeedsUpdate) {
  103.             
  104.                 // Stash the number of ready threads.
  105.                 numberOfReadyThreads = LThread::CountReadyThreads() - 1;
  106.                 
  107.                 // The credits are a thread
  108.                 if ( gCreditsRunning)
  109.                     numberOfReadyThreads--;
  110.                     
  111.                 if ( numberOfReadyThreads > sMaxConnected)
  112.                     sMaxConnected = numberOfReadyThreads;
  113.  
  114.                 // Draw the status screen.
  115.                 GetPort( &oldPort);
  116.                 SetPort( mWindow->sMacWindowP);
  117.                 
  118.                 
  119.                 if ( sNeedsRedraw) {
  120.  
  121.                     EraseRect( &mWindow->sMacWindowP->portRect);
  122.                     just = UTextTraits::SetPortTextTraits(kRightJustified);
  123.         
  124.                     // Number of connections
  125.                     textString = LStr255(128,1);
  126.                     UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
  127.                                 (**itsDITL).eachItem[0].bounds, just);
  128.  
  129.                     // Maximum Simultaneous Connections
  130.                     textString = LStr255(128,2);
  131.                     UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
  132.                                 (**itsDITL).eachItem[1].bounds, just);
  133.  
  134.                     // Total Requests
  135.                     textString = LStr255(128,3);
  136.                     UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
  137.                                 (**itsDITL).eachItem[2].bounds, just);
  138.                                 
  139.                     // Always update the thread counters 
  140.                     sNeedsUpdate = true;
  141.                 }
  142.  
  143.                 if ( sNeedsUpdate) {
  144.  
  145.                     just = UTextTraits::SetPortTextTraits(kLeftJustified);
  146.  
  147.                     textString = (LStr255)numberOfReadyThreads;
  148.                     UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
  149.                                 (**itsDITL).eachItem[3].bounds, just);
  150.  
  151.                     textString = (LStr255)sMaxConnected;
  152.                     UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
  153.                                 (**itsDITL).eachItem[4].bounds, just);
  154.  
  155.                     textString = (LStr255)sTotalConnections;
  156.                     UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
  157.                                 (**itsDITL).eachItem[5].bounds, just);
  158.                                 
  159.                 }
  160.  
  161.  
  162.                 sNeedsUpdate = sNeedsRedraw = false;
  163.                 SetPort( oldPort);
  164.             }
  165.         }
  166.     }
  167.         
  168.     DeleteThread();
  169.     return nil;
  170. }
  171.  
  172. // ---------------------------------------------------------------------------
  173. //        • OpenStatusWindow
  174. // ---------------------------------------------------------------------------
  175. void 
  176. LCGIStatusThread::OpenStatusWindow() {    
  177.  
  178.     if ( mWindow == nil)
  179.         mWindow = new LStatusWindow();
  180.  
  181.     sNeedsRedraw = sNeedsUpdate = true;
  182. }
  183.  
  184.  
  185. // ---------------------------------------------------------------------------
  186. //        • CloseStatusWindow
  187. // ---------------------------------------------------------------------------
  188. void 
  189. LCGIStatusThread::CloseStatusWindow() {
  190.     
  191.     if ( mWindow)
  192.         delete mWindow, mWindow = nil;
  193. }
  194.  
  195.  
  196.  
  197. // ---------------------------------------------------------------------------
  198. //        • Constructor
  199. // ---------------------------------------------------------------------------
  200. LStatusWindow::LStatusWindow()
  201. {
  202.     // Install the GetNextEvent Filter to handle mouseclicks in the window.
  203.     InstallGNEFilter();
  204.  
  205.     MakeStatusWindow();
  206.  
  207. }
  208.  
  209. // ---------------------------------------------------------------------------
  210. //        • Destructor
  211. // ---------------------------------------------------------------------------
  212. LStatusWindow::~LStatusWindow()
  213. {
  214.     if (sMacWindowP != nil) {
  215.         ::CloseServiceWindow(sMacWindowP);
  216.         sMacWindowP = nil;
  217.     }
  218.  
  219.     RemoveGNEFilter();
  220. }
  221.  
  222. // ---------------------------------------------------------------------------
  223. //        • MakeStatusWindow
  224. // ---------------------------------------------------------------------------
  225. void
  226. LStatusWindow::MakeStatusWindow( )
  227. {
  228.     DialogTHndl    theWIND = nil;
  229.     //•• I'd love to use a PPOB and all the support PowerPlant has built in for graphics
  230.     // but the Text Services Manager uses the window's refcon for it's own use. (PP uses
  231.     // the refcon also)
  232.     
  233.     Try_ {
  234.         // Get the 'DLOG' resource
  235.         theWIND = (DialogTHndl) ::GetResource('DLOG', kStatusWindowID);
  236.         ThrowIfNil_(theWIND);
  237.  
  238.         // Make a new service window in the floating layer.
  239.         ThrowIfOSErr_( ::NewServiceWindow( nil, &(**theWIND).boundsRect, (**theWIND).title, 
  240.                     (**theWIND).visible, (**theWIND).procID, window_InFront, (**theWIND).goAwayFlag, 
  241.                         (ComponentInstance) kCurrentProcess, &sMacWindowP));
  242.                         
  243.         // Make it visible
  244.         ShowWindow( sMacWindowP);
  245.  
  246.     } Catch_ (inErr) {
  247.         // Ignore any errors.  
  248.     } EndCatch_;
  249.     
  250.  
  251.     if ( theWIND)
  252.         ::ReleaseResource( (Handle) theWIND);
  253. }
  254.  
  255. // ---------------------------------------------------------------------------
  256. //        • InstallGNEFilter
  257. // ---------------------------------------------------------------------------
  258. void InstallGNEFilter () {
  259.  
  260.     // Save the old GNE hook
  261.     gOldHook = LMGetGNEFilter();
  262.     
  263.     // Two different things need to happen for either 68K machines or
  264.     // PowerPC.  
  265.     
  266.     // 68K machines need to use the glue in Call68KGNEFilter due to the way the OS
  267.     // passes values in registers.
  268.     
  269.     // The PowerMac code can be set up and called using a UPP.
  270. #if GENERATINGCFM
  271.     LMSetGNEFilter( NewGetNextEventFilterProc( CallPPCGNEFilter));
  272. #else
  273.     LMSetGNEFilter( (GNEFilterUPP) Call68KGNEFilter);
  274. #endif
  275.  
  276. }
  277.  
  278. // ---------------------------------------------------------------------------
  279. //        • RemoveGNEFilter
  280. // ---------------------------------------------------------------------------
  281. void RemoveGNEFilter () {
  282.  
  283. // Note this routine needs to happen when the application terminates or the pointer
  284. // to CGIGNEFilter will be left in low memory.  Not a Good Thing to point to a
  285. // non-existant routine.
  286.  
  287.     if ( gOldHook) {
  288.         DisposeRoutineDescriptor( LMGetGNEFilter());
  289.         LMSetGNEFilter( gOldHook);
  290.         gOldHook = nil;
  291.     }
  292. }
  293.  
  294. // ---------------------------------------------------------------------------
  295. //        • CGIGNEFilter
  296. // ---------------------------------------------------------------------------
  297. pascal short CGIGNEFilter ( short result, EventRecord *theEvent, GNEFilterUPP *oldHook) {
  298.  
  299.     short            thisResult = result;
  300.     Boolean            sameProcess = false;
  301.     short            thisResource = CurResFile();
  302.     WindowPtr        theWindow;
  303.     Point            itsPoint = theEvent->where;
  304.     RgnHandle        qdRegion;
  305.     Rect            itsRect;
  306.     short            itsPart;
  307.     LMainCGI        *theApp;
  308.     DialogTHndl        theWIND;
  309.     GrafPtr            oldPort;
  310.  
  311.     
  312. #if !GENERATINGCFM
  313.     // Reset to our globals for 68K machines.
  314.     long    oldA5 = SetA5(*A5Stash());
  315. #endif
  316.  
  317.     // Grab the old hook while the globals are set up. (A5 important)
  318.     *oldHook = gOldHook;
  319.     
  320.     // Set up the resource chain to point to us.
  321.     UseResFile(gThisResource);
  322.     
  323.  
  324.     // Filter according to event type.
  325.     switch (theEvent->what) {
  326.             
  327.         case mouseDown:
  328.         
  329.             // Got a mouseclick.  See if it's in our status window
  330.             itsPart = FindServiceWindow(theEvent->where,  &theWindow);
  331.                         
  332.             switch ( itsPart) {
  333.                 case inContent:
  334.                     // Simple click on the window.  Have the process mgr
  335.                     // bring us to the forground.
  336.                     SetFrontProcess( &gThisProcess);
  337.                     // Ignore the event
  338.                     theEvent->what = nullEvent;
  339.                     break;
  340.  
  341.                 case inDrag:
  342.                     // Get the gray region for all monitors in use.
  343.                     qdRegion = LMGetGrayRgn();
  344.                     itsRect = (**qdRegion).rgnBBox;
  345.                     // Move the window
  346.                     DragWindow( theWindow, theEvent->where, &itsRect);
  347.                     
  348.                     // Set the current port to the Text Services Window to
  349.                     // translate the window position.
  350.                     GetPort( &oldPort);
  351.                     SetPort( theWindow);
  352.                     
  353.                     // Get the last upper left and convert to global coordinates
  354.                     itsRect = theWindow->portRect;
  355.                     LocalToGlobal( (Point *)&itsRect.top);
  356.                     LocalToGlobal( (Point *)&itsRect.bottom);
  357.                     
  358.                     // Stash the new window boundaries in the resource.
  359.                     theWIND = (DialogTHndl) ::GetResource('DLOG', kStatusWindowID);
  360.                     if ( theWIND) {
  361.                         (**theWIND).boundsRect = itsRect;
  362.                         ChangedResource( (Handle) theWIND);
  363.                         UpdateResFile( gThisResource);
  364.                     }
  365.  
  366.                     SetPort( oldPort);
  367.  
  368.                     // Make the window redraw
  369.                     LCGIStatusThread::sNeedsRedraw = true;
  370.                     
  371.                     // Ignore the event
  372.                     theEvent->what = nullEvent;
  373.                     break;
  374.                 
  375.                 case inGoAway :
  376.                     // Track the movement in the close box
  377.                     if ( TrackGoAway( theWindow, theEvent->where)) {
  378.                     
  379.                         // Close the status window
  380.                         LMainCGI::sStatusThread->CloseStatusWindow();
  381.  
  382.                         // Make the application update it's menus according to the new
  383.                         // window status.
  384.                         theApp    = LMainCGI::GetApplication();
  385.                         theApp->UpdateMenus();
  386.                     }
  387.  
  388.                     // Ignore the event
  389.                     theEvent->what = nullEvent;
  390.                     break;
  391.                 
  392.             }
  393.             break;
  394.     }
  395.     
  396. #if !GENERATINGCFM
  397.     // Reset to caller's globals.
  398.     SetA5( oldA5);
  399. #endif
  400.  
  401.     UseResFile(thisResource);
  402.     return ( result);
  403.  
  404. }
  405.     
  406.  
  407. #if GENERATINGCFM
  408. // ---------------------------------------------------------------------------
  409. //        • CallPPCGNEFilter
  410. // ---------------------------------------------------------------------------
  411. void CallPPCGNEFilter( EventRecord *theEvent, short *result) {
  412.  
  413.     short             gneResult;
  414.     GNEFilterUPP    oldHook;
  415.  
  416.     gneResult = CGIGNEFilter( *result, theEvent, &oldHook);
  417.     
  418.     CallGetNextEventFilterProc( oldHook,  gneResult, theEvent);
  419.  
  420. }
  421. #else
  422. // ---------------------------------------------------------------------------
  423. //        • A5Stash
  424. // ---------------------------------------------------------------------------
  425. asm long *A5Stash() {
  426.  
  427.         // This routine provides a "hole" in the code resource in which to stash
  428.         // the A5 global frame pointer for 68k machines.
  429.         lea        ThisA5,A0
  430.         move.l    A0,4(SP)
  431.         rts
  432.  
  433. ThisA5:    dc.l    0
  434. }
  435.  
  436. // ---------------------------------------------------------------------------
  437. //        • Call68KGNEFilter
  438. // ---------------------------------------------------------------------------
  439. asm void Call68KGNEFilter() { 
  440.  
  441.         // This routine is called with A1 pointing to the Event Record and
  442.         // D0 pointing to result.
  443.         // Pascal calling conventions dictate the calling routine pushes the parameters
  444.         // from left to right onto the stack.  The called routine will NOT pop the stack.
  445.         
  446.         move.l    A1,-(SP)                // Push the EventRecord (A1) onto the stack
  447.         clr.w    -(SP)                    // Make room for the result
  448.         move.w    D0,-(SP)                // push the current value of "result" 
  449.         move.l    A1,-(SP)            
  450.         clr.l    -(SP)                    // Make room for the old filter hook
  451.         jsr        CGIGNEFilter            // Call the filter
  452.         move.w    (SP)+,D0                // Get the result and put it in D0
  453.         move.l    (SP)+,A1                // Get the EventRecord pointer and put it in A1
  454.         move.l    (SP)+,A0                  // The prior GNE filter (oldHook)
  455.         move.w    D0,4(SP)                // Move the result returned to the stack.
  456.         jmp        (A0)                    // jump directly to the next filter
  457. }
  458. #endif
  459.