/****************************/
/*      EVENTS.C			*/
/* (c)2004 Pangea Software  */
/* By Brian Greenstone      */
/****************************/


/***************/
/* EXTERNALS   */
/***************/

extern	IBNibRef 			gNibs;
extern	Boolean				gQuitApplication;


/****************************/
/*    PROTOTYPES            */
/****************************/

static pascal OSStatus MyEventHandler(EventHandlerCallRef eventhandler, EventRef event, void *userdata);


/**********************/
/*     CONSTANTS      */
/**********************/




/**********************/
/*     VARIABLES      */
/**********************/

EventLoopTimerRef		gMainLoopTimer  = nil;

static	EventHandlerUPP			gMyEventHandlerUPP = nil;
static	EventHandlerRef			gMyEventHandlerRef = 0;

Boolean		gKeyState[255];
UInt32		gModifiers; 

int			gMouseDeltaX, gMouseDeltaY;
int			gMouseCoordX, gMouseCoordY;
long		gMouseWheelDelta;

Boolean		gMouseLeftButtonDown, gMouseRightButtonDown, gMouseMiddleButtonDown;


/******************** INIT MY EVENT HANDLER *********************/
//
// Installs and event handler to process 'xxxx' commands from Interface Builder elements
// which are not handled by other handlers.  Things such as Menu handlers, etc.
//

void InitMyEventHandler(void)
{
	OSStatus  iErr;
	EventTypeSpec	events[9] = {kEventClassCommand, kEventCommandProcess,	// command events
	
								kEventClassKeyboard, kEventRawKeyDown,		// key down events
								kEventClassKeyboard, kEventRawKeyUp,		// key up events
								kEventClassKeyboard, kEventRawKeyModifiersChanged,	// modifiers changed event

								kEventClassMouse, kEventMouseMoved,
								kEventClassMouse, kEventMouseDragged,
								kEventClassMouse, kEventMouseUp,
								kEventClassMouse, kEventMouseDown,
								kEventClassMouse, kEventMouseWheelMoved};


			/*******************************************/
			/* LOAD AND SET MENU BAR FROM OUR NIB FILE */
			/*******************************************/
			
	iErr = SetMenuBarFromNib(gNibs, CFSTR("MainMenu"));
	if (iErr != noErr)
		DoFatalAlert("\pSetMenuBarFromNib failed!");


			/************************/
			/* CREATE EVENT HANDLER */
			/************************/

	gMyEventHandlerUPP = NewEventHandlerUPP(MyEventHandler);
	
	InstallEventHandler(GetApplicationEventTarget(), gMyEventHandlerUPP, 9, events, nil, &gMyEventHandlerRef);
}


/**************** MY EVENT HANDLER *************************/
//
// 
//

static pascal OSStatus MyEventHandler(EventHandlerCallRef eventhandler, EventRef event, void *userdata)
{
OSStatus	result = eventNotHandledErr;
HICommand   command;
UInt32		eventClass, eventKind;
char		charCode;
Point		mouseDelta, mouseCoord;
short		whichButton;
	
	      
#pragma unused (eventhandler, userdata)

			/* GET EVENT CLASS & KIND */
			
	eventClass = GetEventClass(event);
	eventKind  = GetEventKind(event);
  
	switch (eventClass)
	{
				/*************************/
				/* HANDLE COMMAND EVENTS */
				/*************************/
	
		case	kEventClassCommand:

						/* EXTRACT COMMAND INFO FROM EVENT */
						
				GetEventParameter(event, kEventParamDirectObject, typeHICommand, nil,
								sizeof(HICommand), nil, &command);

						/* HANDLE THE COMMAND */
							
				switch (command.commandID)
				{	 
					case	'quit':							// Quit menu item
							gQuitApplication = true;
							result = noErr;
							break;
							
					case	'pref':							// Preferences... menu item
							break;
							
					case	'helo':							// Say Hello menu item
							DoAlert("\pHello");
							break;
							
					case	'snd1':							// Play Sound #1
							OAL_PlaySound3D(0, nil, nil, 1.0, 1.0, AL_FALSE);
							break;
							
					case	'snd2':							// Play Sound #2
							OAL_PlaySound3D(1, nil, nil, 1.0, 1.0, AL_FALSE);
							break;
				}	 
				break;
				
		
				/**************************/
				/* HANDLE KEYBOARD EVENTS */
				/**************************/
				
		case	kEventClassKeyboard:
					
				switch(eventKind)
				{
					case	kEventRawKeyDown:
							GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, nil,
											sizeof(charCode), nil, &charCode);
							gKeyState[charCode] = true;		// this key is down
							break;
				
					case	kEventRawKeyUp:
							GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, nil,
											sizeof(charCode), nil, &charCode);
							gKeyState[charCode] = false;	// this key is up
							break;
							
					case	kEventRawKeyModifiersChanged:	// get modifier key bits
							GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, nil,
											sizeof(gModifiers), nil, &gModifiers);		
							break;
				}
				break;

				/***********************/
				/* HANDLE MOUSE EVENTS */
				/***********************/
				
		case	kEventClassMouse:
					
				switch(eventKind)
				{
							/* MOUSE MOVED */
							//
							// Note:  the gMouseDelta values always contain
							//		whatever the most recent deltas were.  If the
							//		user stops moving the mouse the deltas do not
							//		go to 0.
							//
							
					case	kEventMouseMoved:
					case	kEventMouseDragged:										
															// get mouse delta
							GetEventParameter(event, kEventParamMouseDelta, typeQDPoint,
											nil, sizeof(mouseDelta), nil, &mouseDelta);

							gMouseDeltaX = mouseDelta.h;
							gMouseDeltaY = mouseDelta.v;
							
															// get mouse coord
															
							GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
											nil, sizeof(mouseCoord), nil, &mouseCoord);
							
							gMouseCoordX = mouseCoord.h;
							gMouseCoordY = mouseCoord.v;							
							break;
							
				
							/* MOUSE WHEEL MOVED */
							//
							// Note: the gMousWheelDelta variable always contains
							//		whatever the most recent delta was.  So, if the
							//		user stops spinning the wheel, it isn't going to
							//		go to 0. 
							//
							
					case	kEventMouseWheelMoved:										
							GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32,
											nil, sizeof(gMouseWheelDelta), nil, &gMouseWheelDelta);
							break;
							
							
							/* MOUSE BUTTON DOWN */
							
					case	kEventMouseDown:
															// which button was pressed?
							GetEventParameter(event, kEventParamMouseButton, typeMouseButton,
											nil ,sizeof(whichButton), nil, &whichButton); 	
											
							switch(whichButton)
							{
								case	kEventMouseButtonPrimary:		// left button?
										gMouseLeftButtonDown = true;
										break;
										
								case	kEventMouseButtonSecondary:		// right button?
										gMouseRightButtonDown = true;
										break;
										
								case	kEventMouseButtonTertiary:		// middle button?
										gMouseMiddleButtonDown = true;
										break;
							}
							break;

							/* MOUSE BUTTON UP */
							
					case	kEventMouseUp:
															// which button was released?
							GetEventParameter(event, kEventParamMouseButton, typeMouseButton,
											nil ,sizeof(whichButton), nil, &whichButton); 	
											
							switch(whichButton)
							{
								case	kEventMouseButtonPrimary:		// left button?
										gMouseLeftButtonDown = false;
										break;
										
								case	kEventMouseButtonSecondary:		// right button?
										gMouseRightButtonDown = false;
										break;
										
								case	kEventMouseButtonTertiary:		// middle button?
										gMouseMiddleButtonDown = false;
										break;
							}
							break;
				}
				break;
		}
				
				
	return(result);
}


/******************* REMOVE MY COMMAND EVENT HANDLER *************************/
//
// Call this if you ever need to remove the event handler callback.
//

void RemoveMyCommandEventHandlers(void)
{

	//	if the handler has been installed, remove it

	if (gMyEventHandlerRef != 0)
	{
		RemoveEventHandler(gMyEventHandlerRef);
		gMyEventHandlerRef = 0;
		
		DisposeEventHandlerUPP(gMyEventHandlerUPP);
		gMyEventHandlerUPP = nil;
	}
	
}





#pragma mark -


/***************** SET MY MAIN LOOP EVENT TIMER ***********************/

void SetMyMainLoopEventTimer(EventLoopTimerProcPtr myMainLoopFunc)
{
EventLoopTimerUPP		eventLoopTimerUPP;
EventLoopRef			mainLoop;

		/* MAKE SURE WE DONÕT ALREADY HAVE AN EVENT TIMER GOING */

	if (gMainLoopTimer != nil)
		DoFatalAlert("\ptimer already set!");


		/* GET A REFERENCE TO OUR APPÕS MAIN EVENT LOOP */

	mainLoop = GetMainEventLoop();

			/* CREATE A NEW EVENT LOOP TIMER */
			//
			// This inserts our main loop callback into a
			// new event timer
			//

	eventLoopTimerUPP  =  NewEventLoopTimerUPP(myMainLoopFunc);

	InstallEventLoopTimer(mainLoop,					
				kEventDurationNoWait,		// delay before first shot
				kEventDurationMillisecond,	// delay until next shot
				eventLoopTimerUPP,			// which event loop timer to install
				nil,						// no user data
				 &gMainLoopTimer);			// timer reference that gets returned
						
		/* CLEANUP */
 
	DisposeEventLoopTimerUPP(eventLoopTimerUPP);
}


/*********************** REMOVE MY MAIN LOOP EVENT TIMER *********************/

void RemoveMyMainLoopEventTimer(void)
{
	if (gMainLoopTimer != nil)
	{
		RemoveEventLoopTimer(gMainLoopTimer);
		gMainLoopTimer = nil;
	}
}

