home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-02-26 | 12.3 KB | 459 lines | [TEXT/CWIE] |
- /***
- File: LCGIStatusWindow.cp
-
-
- Contains: Text Services status window
-
-
- Written by: Ken Wieschhoff
-
-
- Copyright: ©1996 Siren Enterprises, All Rights Reserved.
-
-
- Change History (most recent first):
-
-
-
- <1> 9/5/96 kw Original
-
- ***/
-
-
- #include "LMainCGI.h"
- #include "LCGIStatusWindow.h"
- #include <string.h>
- #include <UMemoryMgr.h>
- #include <LCaption.h>
- #include <LString.h>
- #include <TextServices.h>
- #include <UTextTraits.h>
- #include <UDrawingUtils.h>
-
-
- GetNextEventFilterUPP gOldHook = nil;
- short gThisResource = 0;
- ProcessSerialNumber gThisProcess;
- extern Boolean gCreditsRunning;
- WindowPtr LStatusWindow::sMacWindowP = nil;
- Boolean LCGIStatusThread::sNeedsRedraw = false;
- Boolean LCGIStatusThread::sNeedsUpdate = false;
- long LCGIStatusThread::sMaxConnected = 0;
- long LCGIStatusThread::sTotalConnections = 0;
- extern LCGIStatusThread *LMainCGI::sStatusThread;
-
- #define kStatusWindowID 128
- #define kRightJustified 1
- #define kLeftJustified 2
-
- // ---------------------------------------------------------------------------
- // • Constructor
- // ---------------------------------------------------------------------------
- LCGIStatusThread::LCGIStatusThread(LCommander *itsSuper)
- : LThread( false )
- {
- mWindow = nil;
-
- this->OpenStatusWindow();
-
- sNeedsUpdate = sNeedsRedraw = true;
-
- // Get our Process number.
- GetCurrentProcess( &gThisProcess);
-
- // Stash the resource chain ID.
- gThisResource = CurResFile();
-
- }
-
- // ---------------------------------------------------------------------------
- // • Destructor
- // ---------------------------------------------------------------------------
- LCGIStatusThread::~LCGIStatusThread()
- {
- if (mWindow)
- delete mWindow;
-
- }
-
- // ---------------------------------------------------------------------------
- // • Run
- // ---------------------------------------------------------------------------
- void*
- LCGIStatusThread::Run()
- {
-
- LStr255 textString;
- GrafPtr oldPort;
- Int16 just;
- DITLTemplateHdl itsDITL = (DITLTemplateHdl)Get1Resource('DITL', 128);
- StHandleLocker aLocker( (Handle) itsDITL);
- long numberOfReadyThreads;
-
- // Give the main thread time to finish setting up.
- for ( short i = 0; i < 20; i++)
- LThread::Yield();
-
- while ( true) {
- // Yield to any other thread
- LThread::Yield();
-
- if ( mWindow) {
- if ( sNeedsRedraw || sNeedsUpdate) {
-
- // Stash the number of ready threads.
- numberOfReadyThreads = LThread::CountReadyThreads() - 1;
-
- // The credits are a thread
- if ( gCreditsRunning)
- numberOfReadyThreads--;
-
- if ( numberOfReadyThreads > sMaxConnected)
- sMaxConnected = numberOfReadyThreads;
-
- // Draw the status screen.
- GetPort( &oldPort);
- SetPort( mWindow->sMacWindowP);
-
-
- if ( sNeedsRedraw) {
-
- EraseRect( &mWindow->sMacWindowP->portRect);
- just = UTextTraits::SetPortTextTraits(kRightJustified);
-
- // Number of connections
- textString = LStr255(128,1);
- UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
- (**itsDITL).eachItem[0].bounds, just);
-
- // Maximum Simultaneous Connections
- textString = LStr255(128,2);
- UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
- (**itsDITL).eachItem[1].bounds, just);
-
- // Total Requests
- textString = LStr255(128,3);
- UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
- (**itsDITL).eachItem[2].bounds, just);
-
- // Always update the thread counters
- sNeedsUpdate = true;
- }
-
- if ( sNeedsUpdate) {
-
- just = UTextTraits::SetPortTextTraits(kLeftJustified);
-
- textString = (LStr255)numberOfReadyThreads;
- UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
- (**itsDITL).eachItem[3].bounds, just);
-
- textString = (LStr255)sMaxConnected;
- UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
- (**itsDITL).eachItem[4].bounds, just);
-
- textString = (LStr255)sTotalConnections;
- UTextDrawing::DrawWithJustification( (Ptr)&textString[1], textString[0],
- (**itsDITL).eachItem[5].bounds, just);
-
- }
-
-
- sNeedsUpdate = sNeedsRedraw = false;
- SetPort( oldPort);
- }
- }
- }
-
- DeleteThread();
- return nil;
- }
-
- // ---------------------------------------------------------------------------
- // • OpenStatusWindow
- // ---------------------------------------------------------------------------
- void
- LCGIStatusThread::OpenStatusWindow() {
-
- if ( mWindow == nil)
- mWindow = new LStatusWindow();
-
- sNeedsRedraw = sNeedsUpdate = true;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CloseStatusWindow
- // ---------------------------------------------------------------------------
- void
- LCGIStatusThread::CloseStatusWindow() {
-
- if ( mWindow)
- delete mWindow, mWindow = nil;
- }
-
-
-
- // ---------------------------------------------------------------------------
- // • Constructor
- // ---------------------------------------------------------------------------
- LStatusWindow::LStatusWindow()
- {
- // Install the GetNextEvent Filter to handle mouseclicks in the window.
- InstallGNEFilter();
-
- MakeStatusWindow();
-
- }
-
- // ---------------------------------------------------------------------------
- // • Destructor
- // ---------------------------------------------------------------------------
- LStatusWindow::~LStatusWindow()
- {
- if (sMacWindowP != nil) {
- ::CloseServiceWindow(sMacWindowP);
- sMacWindowP = nil;
- }
-
- RemoveGNEFilter();
- }
-
- // ---------------------------------------------------------------------------
- // • MakeStatusWindow
- // ---------------------------------------------------------------------------
- void
- LStatusWindow::MakeStatusWindow( )
- {
- DialogTHndl theWIND = nil;
- //•• I'd love to use a PPOB and all the support PowerPlant has built in for graphics
- // but the Text Services Manager uses the window's refcon for it's own use. (PP uses
- // the refcon also)
-
- Try_ {
- // Get the 'DLOG' resource
- theWIND = (DialogTHndl) ::GetResource('DLOG', kStatusWindowID);
- ThrowIfNil_(theWIND);
-
- // Make a new service window in the floating layer.
- ThrowIfOSErr_( ::NewServiceWindow( nil, &(**theWIND).boundsRect, (**theWIND).title,
- (**theWIND).visible, (**theWIND).procID, window_InFront, (**theWIND).goAwayFlag,
- (ComponentInstance) kCurrentProcess, &sMacWindowP));
-
- // Make it visible
- ShowWindow( sMacWindowP);
-
- } Catch_ (inErr) {
- // Ignore any errors.
- } EndCatch_;
-
-
- if ( theWIND)
- ::ReleaseResource( (Handle) theWIND);
- }
-
- // ---------------------------------------------------------------------------
- // • InstallGNEFilter
- // ---------------------------------------------------------------------------
- void InstallGNEFilter () {
-
- // Save the old GNE hook
- gOldHook = LMGetGNEFilter();
-
- // Two different things need to happen for either 68K machines or
- // PowerPC.
-
- // 68K machines need to use the glue in Call68KGNEFilter due to the way the OS
- // passes values in registers.
-
- // The PowerMac code can be set up and called using a UPP.
- #if GENERATINGCFM
- LMSetGNEFilter( NewGetNextEventFilterProc( CallPPCGNEFilter));
- #else
- LMSetGNEFilter( (GNEFilterUPP) Call68KGNEFilter);
- #endif
-
- }
-
- // ---------------------------------------------------------------------------
- // • RemoveGNEFilter
- // ---------------------------------------------------------------------------
- void RemoveGNEFilter () {
-
- // Note this routine needs to happen when the application terminates or the pointer
- // to CGIGNEFilter will be left in low memory. Not a Good Thing to point to a
- // non-existant routine.
-
- if ( gOldHook) {
- DisposeRoutineDescriptor( LMGetGNEFilter());
- LMSetGNEFilter( gOldHook);
- gOldHook = nil;
- }
- }
-
- // ---------------------------------------------------------------------------
- // • CGIGNEFilter
- // ---------------------------------------------------------------------------
- pascal short CGIGNEFilter ( short result, EventRecord *theEvent, GNEFilterUPP *oldHook) {
-
- short thisResult = result;
- Boolean sameProcess = false;
- short thisResource = CurResFile();
- WindowPtr theWindow;
- Point itsPoint = theEvent->where;
- RgnHandle qdRegion;
- Rect itsRect;
- short itsPart;
- LMainCGI *theApp;
- DialogTHndl theWIND;
- GrafPtr oldPort;
-
-
- #if !GENERATINGCFM
- // Reset to our globals for 68K machines.
- long oldA5 = SetA5(*A5Stash());
- #endif
-
- // Grab the old hook while the globals are set up. (A5 important)
- *oldHook = gOldHook;
-
- // Set up the resource chain to point to us.
- UseResFile(gThisResource);
-
-
- // Filter according to event type.
- switch (theEvent->what) {
-
- case mouseDown:
-
- // Got a mouseclick. See if it's in our status window
- itsPart = FindServiceWindow(theEvent->where, &theWindow);
-
- switch ( itsPart) {
- case inContent:
- // Simple click on the window. Have the process mgr
- // bring us to the forground.
- SetFrontProcess( &gThisProcess);
- // Ignore the event
- theEvent->what = nullEvent;
- break;
-
- case inDrag:
- // Get the gray region for all monitors in use.
- qdRegion = LMGetGrayRgn();
- itsRect = (**qdRegion).rgnBBox;
- // Move the window
- DragWindow( theWindow, theEvent->where, &itsRect);
-
- // Set the current port to the Text Services Window to
- // translate the window position.
- GetPort( &oldPort);
- SetPort( theWindow);
-
- // Get the last upper left and convert to global coordinates
- itsRect = theWindow->portRect;
- LocalToGlobal( (Point *)&itsRect.top);
- LocalToGlobal( (Point *)&itsRect.bottom);
-
- // Stash the new window boundaries in the resource.
- theWIND = (DialogTHndl) ::GetResource('DLOG', kStatusWindowID);
- if ( theWIND) {
- (**theWIND).boundsRect = itsRect;
- ChangedResource( (Handle) theWIND);
- UpdateResFile( gThisResource);
- }
-
- SetPort( oldPort);
-
- // Make the window redraw
- LCGIStatusThread::sNeedsRedraw = true;
-
- // Ignore the event
- theEvent->what = nullEvent;
- break;
-
- case inGoAway :
- // Track the movement in the close box
- if ( TrackGoAway( theWindow, theEvent->where)) {
-
- // Close the status window
- LMainCGI::sStatusThread->CloseStatusWindow();
-
- // Make the application update it's menus according to the new
- // window status.
- theApp = LMainCGI::GetApplication();
- theApp->UpdateMenus();
- }
-
- // Ignore the event
- theEvent->what = nullEvent;
- break;
-
- }
- break;
- }
-
- #if !GENERATINGCFM
- // Reset to caller's globals.
- SetA5( oldA5);
- #endif
-
- UseResFile(thisResource);
- return ( result);
-
- }
-
-
- #if GENERATINGCFM
- // ---------------------------------------------------------------------------
- // • CallPPCGNEFilter
- // ---------------------------------------------------------------------------
- void CallPPCGNEFilter( EventRecord *theEvent, short *result) {
-
- short gneResult;
- GNEFilterUPP oldHook;
-
- gneResult = CGIGNEFilter( *result, theEvent, &oldHook);
-
- CallGetNextEventFilterProc( oldHook, gneResult, theEvent);
-
- }
- #else
- // ---------------------------------------------------------------------------
- // • A5Stash
- // ---------------------------------------------------------------------------
- asm long *A5Stash() {
-
- // This routine provides a "hole" in the code resource in which to stash
- // the A5 global frame pointer for 68k machines.
- lea ThisA5,A0
- move.l A0,4(SP)
- rts
-
- ThisA5: dc.l 0
- }
-
- // ---------------------------------------------------------------------------
- // • Call68KGNEFilter
- // ---------------------------------------------------------------------------
- asm void Call68KGNEFilter() {
-
- // This routine is called with A1 pointing to the Event Record and
- // D0 pointing to result.
- // Pascal calling conventions dictate the calling routine pushes the parameters
- // from left to right onto the stack. The called routine will NOT pop the stack.
-
- move.l A1,-(SP) // Push the EventRecord (A1) onto the stack
- clr.w -(SP) // Make room for the result
- move.w D0,-(SP) // push the current value of "result"
- move.l A1,-(SP)
- clr.l -(SP) // Make room for the old filter hook
- jsr CGIGNEFilter // Call the filter
- move.w (SP)+,D0 // Get the result and put it in D0
- move.l (SP)+,A1 // Get the EventRecord pointer and put it in A1
- move.l (SP)+,A0 // The prior GNE filter (oldHook)
- move.w D0,4(SP) // Move the result returned to the stack.
- jmp (A0) // jump directly to the next filter
- }
- #endif
-