home *** CD-ROM | disk | FTP | other *** search
- /*
- HASEventDispatch.c from Hsoi's App Shell © 1995-1997 John C. Daub. All rights reserved.
-
- This file contains one function to deal with events (except AppleEvents, that's
- another file). This is just the "dispatch" file; the functions to actually
- deal with each event are located elsewhere. But this is the "chain of command"
- where all things go from.
- */
-
- #pragma mark ••• #includes •••
-
- #ifndef _WASTE_
- #include "WASTE.h"
- #endif
- #include "HASGlobals.h"
- #ifndef __HSOIS_APP_SHELL__
- #include "HASMain.h"
- #endif
- #include "HASMenus.h"
- #include "HASHelp.h"
- #include "HASMenuWindows.h"
- #include "HASEventDispatch.h"
- #include "HASMiscEvents.h"
- #include "HASCoolAboutBox.h"
- #include "HASWindows.h"
- #include "HASUtilities.h"
- #include "HASUtilCursors.h"
- #include "HASSoundSpeech.h"
- #include "HASDialogs.h"
-
- #ifndef _WASTEOBJECTS_
- #include "WASTE_Objects.h"
- #endif
-
- #pragma mark -
-
- /*
- * HsoiDoEvent() is all there is here: as soon as an event is snagged via WaitNextEvent()
- * in the main event loop, it's passed here for dispatching
- */
-
-
- void HsoiDoEvent( const EventRecord *event )
- {
- short myError;
- short windowPart;
- WindowRef window;
- char key;
- Point mountPoint;
- Boolean isCmdKey;
-
-
- // switch on what the event was...
-
- switch( event->what )
- {
-
- // no need to handle null events here, due to how the main event loop is written.
-
- // networkEvt, app1Evt, app2Evt are all obsolete events, so we don't need to
- // handle them. app4Evt has been renamed to osEvt. There is the app3Evt
- // which is something that we aren't handling...it's an event type that the
- // application can set for itself (like if your application needs to insert events
- // into the event queue and needs to handle its own type of event, you can use
- // the app3Evt event type as your switch case for this). It really still is
- // an obsolete event, but you probably could get away in using it, if you wanted to,
- // by just #define-ing a few things, like #define app3Evt 14, and #define app3EvtMask
- // 0x4000 or something. but, i doubt you'll need this (it's not in my Universal Headers).
-
-
- // take care of AppleEvents
-
- case kHighLevelEvent:
- AEProcessAppleEvent( event );
- break;
-
- // end case kHighLevelEvent
-
-
- // take care of mouseDown events.
-
- case mouseDown:
-
- // find where the mouseDown occured.
-
- windowPart = FindWindow( event->where, &window );
-
- // handle if we're in a modal/movable modal dialog
-
- if ( gInModalState && (window != FrontWindow() ) && ( windowPart != inMenuBar) )
- {
- SysBeep( 5 );
- return;
- }
-
- switch( windowPart )
- {
- // if they click in the menu bar...
-
- case inMenuBar:
- {
- long menuResult;
- Str255 originalMenuString, HASMenuString;
- Boolean textChanged;
- MenuRef appleMenuH = GetMenuHandle( mApple );
-
- // prepare menu items first
-
- HsoiAdjustMenus();
-
- // to prep for the "easter egg", if the user has the option
- // key held down (opt-click on the About will do the easter egg)
- // we want to text of the About item to change. Normally it
- // should say "About xxx..." where xxx is the name of the
- // app you've written. But, this easter egg is something for
- // Hsoi's App Shell (as per the rules/regs/usage/etc things).
- // So, let's change the text of the About menu item to reflect
- // that change.
-
- // first, let's see if the opt key is held down, else forget it
-
- if ( event->modifiers & optionKey )
- {
- // ok. it's a go, so let's save the original menu text
-
- GetMenuItemText( appleMenuH, iAbout, originalMenuString );
-
- // get the "About HAS" string from the resource fork
-
- GetIndString( HASMenuString, rCoolAboutBoxMenuItemStrings, strAboutHAS );
-
- // change the menu item text
-
- SetMenuItemText( appleMenuH, iAbout, HASMenuString );
-
- // note that the text was changed (so we can change it back )
-
- textChanged = true;
- }
- else
- {
- // text wasnt' changed...no need to change it back
-
- textChanged = false;
- }
-
- // find out the menu and the item clicked on
-
- menuResult = MenuSelect( event->where );
-
- // for the cool about box, they can see that if they click on
- // About with the option key down, so let's check for that.
-
- // it's kinda like an Easter Egg :-)
-
- if ( (HiWrd( menuResult ) == mApple) &&
- (LoWrd( menuResult ) == iAbout) &&
- (event->modifiers & optionKey ) )
- {
- HsoiDoCoolAboutBox();
-
- HiliteMenu( 0 );
- }
- else
- HsoiDoMenuCommand( menuResult );
-
- // see if we have to change the about menu item text back, if so, change it back
-
- if ( textChanged )
- SetMenuItemText( appleMenuH, iAbout, originalMenuString );
-
- }
- break;
-
- // if they click in a system window (like a DA or something)
-
- case inSysWindow:
- // ?? SystemClick() should be defined as
- // SystemClick( const EventRecord *, WindowRef ) (Marco discovered this
- // inconsistancy in Apple's Universal Headers 2.1)
- SystemClick( event, (WindowPtr)window );
- break;
-
- // if they click in the content region of a window...
-
- case inContent:
- {
- if ( HsoiDoContentClick( event->where, event, window ) )
- {
- SelectWindow( window );
-
- // force the clipboard window to redraw/update
- if ( HsoiIsClipboardWindow( window ) )
- {
- WEReference we = HsoiGetWindowWE( window );
- Str255 tempStr = NIL_STRING;
-
- HideWindow( window );
-
- WEFeatureFlag( weFReadOnly, weBitClear, we );
-
- if ( WECanPaste( we ) )
- {
- // since WEPaste (and it's call to WEInsert) and WEDElete could take a long time
- // (like if the scrap is HUGE) can take a long time to perform, let's spin
- // our cursor. Again (as with just about all my uses of the VBL spinning cursor)
- // this is good to do cause otherwise it sorta looks like the computer froze up
- // and this could worry the user...if the cursor is spinning, at least the
- // user is getting some feedback that the computer is running...and heck, if
- // we know the cursor is supposed to spin and it freezes up, then we probably
- // do have some sort of bad error and the computer is probably fubar
-
- // start the VBL spinning cursor
-
- HsoiStartVBLSpinning();
-
- // let's take whatever's currently in the window and delete it
-
- WESetSelection( 0, MAXLONG, we );
- WEDelete( we );
-
- // now paste whatever's on the scrap into the window
-
- //WEPaste( we );
- WEObjectsPaste( we );
-
- // and stop the spinning cursor
-
- HsoiStopVBLSpinning();
- }
- else
- {
- // we shouldn't use the prefs error alert box for this, but it's the "cleanest"
- // error box for use to use for this. this will change when i get the error handlers
- // all re-written
-
- GetIndString( tempStr, rClipboardWindowStrings, strClipboardEmpty );
- ParamText( tempStr, NIL_STRING, NIL_STRING, NIL_STRING );
- NoteAlert( rPrefsErrorAlert, HsoiGetMyStandardDialogFilter() );
-
- // and through testing some other stuff, i found this as a bug...if !canPaste,
- // and there was something already in the window (like from a previous "sucessful"
- // ShowClipboard), the "old" window contents showed up! not good...we should
- // make sure the window contains nothing. so, simple fix:
-
- // and going with the above ( if canPaste ) thing about a long time, since
- // WEDelete could take a bit to do, let's sping the cursor
-
- HsoiStartVBLSpinning();
-
- WESetSelection( 0, MAXLONG, we );
- WEDelete( we );
-
- HsoiStopVBLSpinning();
- }
-
- // set the read-only bit. users should not be able to cut/copy/paste to/from this
- // window for obvious reasons
-
- WEFeatureFlag( weFReadOnly, weBitSet, we );
-
- // now we can show it and all that good stuff
-
- ShowWindow( window );
- SelectWindow( window );
- SetPortWindowPort( window );
-
-
- }
- }
- }
- break;
-
- // if they click in the drag region of the window...
-
- case inDrag:
- HsoiDoDrag( event->where, window );
- break;
-
- // if they click in the grow box...
-
- case inGrow:
- HsoiDoGrow( event->where, window );
- break;
-
- // if they click in the go away box...
-
- case inGoAway:
- if ( TrackGoAway( window, event->where ) && !gHiliting )
- HsoiDoClose( closingWindow, savingAsk, window );
- break;
-
- // if they click in the zoom box...
-
- case inZoomIn:
- case inZoomOut:
- if ( TrackBox( window, event->where, windowPart ) )
- HsoiDoZoom( windowPart, window );
-
- break;
-
- } // end switch( windowPart )
- break;
-
- // end case mouseDown
-
- // and now, the next favorite event of the day, the keyDown. now, I don't need
- // to specially handle autoKey's, so I can nicely handle these 2 events with
- // one set of code. However, if you have some differences in your code that
- // calls for special handling of keyDowns and autoKey's, you can always
- // double this code, or you could even write your switch statement without
- // a "break" in there to let things fall through...what programming skills!!! :-)
-
- case keyDown:
- case autoKey:
-
- // extract what key was pressed from the EventRecord.
-
- key = event->message & charCodeMask;
-
- // is this a command+key combo?
-
- isCmdKey = (BAND(event->modifiers, cmdKey) != 0);
-
- // map function keys to the equivalent command+key combos
- // note that all function keys generate the same character code, i.e. 0x10
- // so we have to do a little ferretting around to find out exactly which
- // function key was pressed...
-
- if ( key == 0x10 ) // if it's a function key, find out which on
- {
- isCmdKey = true;
-
- // now, with a little funky bit shifting, we can figure out exactly
- // what function key was pressed. then, we can map that key to do
- // whatever action we want. in this case, we'll do stuff like the
- // little template that comes with Apple keyboards has: F1 - Undo,
- // F2 - cut, F3 - copy, and F4, paste. but of course, you can have
- // your function keys do whatever.
-
- switch( BSR( BAND( event->message, keyCodeMask ), 8 ) )
- {
- case keyF1:
- key = 'z';
- break;
-
- case keyF2:
- key = 'x';
- break;
-
- case keyF3:
- key = 'c';
- break;
-
- case keyF4:
- key = 'v';
- break;
-
- default:
- key = 0;
-
- }// end switch BSR( BAND( event->message, keyCodeMask), 8 )
-
- } // end if ( key == 0x10 )
-
- // now, either it wasn't a function key that was pressed, or it was a function
- // key and we've figured out what key it was, and then set things up as such
- // to properly dispatch.
-
-
- if ( isCmdKey && ( (key >= 0x30) && (key <= 0x39)))
- // translate ASCII Hex of this above line to decimal: 48 - 57, and char: 0 - 9
- // hence why only key > 0x30...we can't have a cmd-0 item (just nine windows get
- // cmd keys!)
- {
- // they want to select a window from the windows menu. since this
- // window can constantly change in the menu (sometimes cmd-1 gives you
- // window 1 and other times (like after window 1 is closed) cmd-1 might
- // give you window 2) we do this to facilitate it all.
-
- if ( key == 0x30 ) // so the cmd-0 doesn't fall through and print
- break;
-
- HsoiDoSelectFromWindowsMenu( (short)((short)key - 48 + iFirstWindow - 1));
- }
- else if ( isCmdKey && (key >= 0x20) ) // is the command key down? (cmd+printable character
- // combos are routed to MenuKey())
- { // if so, do a menu command...
- HsoiAdjustMenus();
- HsoiDoMenuCommand( MenuKey( key ) );
- }
-
- else if ( key == kHelpKey ) // or let's handle one special other case, the help key
- // on the extended keyboard
- {
- HsoiDoHelpStuff();
- }
- else
- { // and all other keys, we'll just handle them "normally"
- HsoiDoKey( key, event );
- }
-
- break;
-
- // end case keyDown/autoKey
-
- // activate events are simple enough...
-
- case activateEvt:
- // remember, if it is a window related event, a reference to the window is stored
- // in the event->message part of the EventRecord
- HsoiDoActivate( (event->modifiers & activeFlag != 0 ), (WindowRef)event->message );
- break;
-
- // end case activatEvt
-
-
- // update events are pretty easy to handle also...
-
- case updateEvt:
- // as with the activateEvt, a reference to the window is stored in the
- // EventRecord's message field
- HsoiDoUpdate( (WindowRef)event->message );
- break;
-
- // end case updateEvt
-
- // if the user sticks a disk in that is unreadable (like an unformatted disk, or one
- // formatted for another platform), let's put up stuff to deal with the disk.
-
- case diskEvt:
- if ( HiWrd(event->message) != noErr )
- {
- mountPoint.h = kDILeft;
- mountPoint.v = kDITop;
- myError = DIBadMount( mountPoint, event->message );
- }
- break;
-
- // end case diskEvt
-
- // this used to be called an app4Evt, but is now an osEvt (with the advent of MultiFinder/System 7)
- // handles the backgrounding stuff (multitasking)
-
- case osEvt:
- switch( (event->message >> 24) & 0x0FF )
- {
- case suspendResumeMessage:
-
- window = FrontWindow();
-
- if ( ( event->message & resumeFlag ) == 0 ) // suspend
- {
- // if we have text speaking, stop it
-
- HsoiDoStop();
-
- // if we have a sound playing, stop it before we proceed. it's
- // kinda "strange" to have your sound continuing playing while your
- // app is in the background...tho some people might want this *shrug*
-
- if ( SoundIsPlaying() )
- StopCurrentSound();
-
- gInBackground = true;
- }
- else // resuming
- {
- gInBackground = false;
-
- // remove any notification requests
-
- if ( gHasNotification )
- HsoiRemoveNMMessage();
-
- }
-
- // if there is a window, let's make sure to activate or deactivate it
- // so that all things look right on the screen.
-
- if ( window != nil )
- HsoiDoActivate( (event->message & resumeFlag ) != 0, window );
-
- break;
-
-
- case mouseMovedMessage:
- // do nothing
- break;
-
- } // end switch( event->message >> 24 ) & 0x0FF )
- break;
-
- // end case osEvt
- }
-
- return;
- }
-
-