/*	XGAppCore.cpp
 *
 *		This is the application core class. This only defines the common
 *	routines which are not substantially different across operating systems.
 *	OS specific routines are contained in the various XGAppCore_XXX.cpp
 *	source files.
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  This library is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Library
 *  General Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or any
 *  later version.
 *  
 *  This library is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU Library General Public License for
 *  more details.
 *  
 *  You should have received a copy of the GNU Library General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <XError.h>
#include <XMessages.h>
#include <XAppMenu.h>
#include <XEvent.h>
#include <XApplication.h>
#include <XWindow.h>

#include <XDialog.h>
#include <XTextControls.h>
#include <XButtons.h>

#if OPT_MACOS
#include "MacFloater.h"
#endif

/************************************************************************/
/*																		*/
/*	Globals																*/
/*																		*/
/************************************************************************/

short XGAppCore::gLastMods;
XGAppCore *XGAppCore::gApplication = NULL;

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

// @G"Construction/Destruction"

/*	@F"XGAppCore::XGAppCore" @I
 *
 *		Construct the application core object. This initializes me
 */

XGAppCore::XGAppCore()
{
	Assert(gApplication == NULL);
	gApplication = this;
	fModalWindow = NULL;
	fEventOwner = NULL;
	gLastMods = 0;
	
	InitOS();							// Initialize Macintosh OS
	RegisterWindow(XGWindow);			// add predefined window to me.
	RegisterView(XGView);				// add predefined view to me.
	
	/* Required for error handling alerts */
	RegisterView(XGStaticText);
	RegisterView(XGCommandButton);
	RegisterWindow(XGDialog);
}

/*	@F"XGAppCore::~XGAppCore" @I
 *
 *		Shut me down.
 */

XGAppCore::~XGAppCore()
{
	KillOS();
	
	if (gApplication == this) gApplication = NULL;
}

/************************************************************************/
/*																		*/
/*	Application Event Processing										*/
/*																		*/
/************************************************************************/

// @G"Event Processing"

/*	@F"XGAppCore::Run" @I
 *
 *		Run the application event loop. Basically this calls 'RunOnce'
 *	until quit
 */

void XGAppCore::Run()
{
	register XGWindow *w;
	
	OpenCopyright();					// Open copyright window
	fQuitFlag = false;
	CloseCopyright();					// close copyright window
	GetAppArgs();						// and get arguments in X and Windows
	
	try {
		XGBroadcast::SendPostBroadcast();
		XGBroadcast::SendBroadcast(KXGAppPostEvent,0,NULL);
	}
	catch (XGError &e) {
		e.DisplayError();
	}
	catch (...) {
		Error(KXGRandomException);
	}
	
	for (;;) {
		while (!fQuitFlag) RunOnce(NULL);

		try {
			while (NULL != (w = XGWindow::GetFrontWindow())) {
				if (!(w->CloseWindow())) {
					fQuitFlag = false;
					break;
				}
			}
			if (w == NULL) break;		// done closing all windows
		}
		catch (XGError &e) {
			e.DisplayError();
			fQuitFlag = false;
		}
		catch (...) {
			Error(KXGRandomException);
			fQuitFlag = false;
		}
	}
}

/*	@F"XGAppCore::Exit" @I
 *
 *		Handle exit. This simply sets the 'quit' flag
 */

void XGAppCore::Exit()
{
	fQuitFlag = true;
}

/*	@F"XGAppCore::RunOnce" @I
 *
 *		Run the event loop once. Simply defer to the 'DoEvent' routine,
 *	along with the appropriate pre/post events
 */

void XGAppCore::RunOnce(XGWindow *w)
{
	/*
	 *	Set the modal window flag
	 */
	
	fModalWindow = w;
		
	try {
		/*
		 *	Send all the periodic events that need to be sent.
		 */
		
		XGBroadcast::SendBroadcast(KXGAppPreEvent,0,NULL);
		GetCurFocus()->SendDispatch(KXGAppPeriodic,0,NULL);
		
		/*
		 *	Now call the OS-specific event loop
		 */
		
		DoEvent();
		
		/*
		 *	Send the post events
		 */
		
		XGBroadcast::SendPostBroadcast();
		XGBroadcast::SendBroadcast(KXGAppPostEvent,0,NULL);
	}
	catch (XGError &e) {
		e.DisplayError();
	}
	catch (...) {
		Error(KXGRandomException);
	}
	
	/*
	 *	Clear the modal flag and return
	 */
	
	fModalWindow = NULL;
}


/************************************************************************/
/*																		*/
/*	Application Event Processing										*/
/*																		*/
/************************************************************************/

/*
 *	Dispatch table
 */

BEGINDISPATCH(XGAppCore,XGDispatch)
	DISPATCHTABLE(KXGGetMenuStatus,XGAppCore::DoGetMenuStatus)
	DISPATCHTABLE(KXGDoMenuCommand,XGAppCore::DoMenuCommand)
	DISPATCHTABLE(KXGQuitApplication,XGAppCore::DoQuitApplication)
ENDDISPATCH

/*	XGAppCore::DoGetMenuStatus
 *
 *		Get the menu status for this menu item
 */

long XGAppCore::DoGetMenuStatus(long arg, void *parg)
{
	XGSMenuStatus *m = (XGSMenuStatus *)parg;
	
	if (IsModalWindow()) return -1;
	switch (arg) {
		case KXGAppAboutMe:
		case KXGFileQuit:
			m->enable = true;
			return 0;
		case KXGFileClose:
			m->enable = (XGWindow::GetFrontWindow() != NULL) ? true : false;
			return 0;

#if OPT_MACOS == 1
		case KXGEditUndo:
		case KXGEditCut:
		case KXGEditCopy:
		case KXGEditPaste:
		case KXGEditClear:
			m->enable = IsSystemMenu(arg);
			return 0;
#endif

		default:
			return -1;
	}
}

/*	XGAppCore::DoMenuCommand
 *
 *		Do the menu command
 */

long XGAppCore::DoMenuCommand(long arg, void *)
{
	XGWindow *w;
	
	if (IsModalWindow()) return -1;
	switch (arg) {
		case KXGAppAboutMe:
			ShowCopyright();
			return 0;
			
		case KXGFileQuit:
			GetCurFocus()->SendDispatch(KXGQuitApplication,0,NULL);
			return 0;

		case KXGFileClose:
			w = XGWindow::GetFrontWindow();
			if (w) w->CloseWindow();
			return 0;

#if OPT_MACOS == 1
		case KXGEditUndo:
		case KXGEditCut:
		case KXGEditCopy:
		case KXGEditPaste:
		case KXGEditClear:
			if (DoSystemMenu(arg)) return 0;
			return -1;
#endif

		default:
			return -1;
	}
}

/*	XGAppCore::DoQuitApplication
 *
 *		Handle quit application message
 */

long XGAppCore::DoQuitApplication(long,void *)
{
	XGWindow *w;
	
	while (NULL != (w = XGWindow::gList)) {
		if (!w->CloseWindow()) return -1;
	}
	Exit();
	return 0;
}

/************************************************************************/
/*																		*/
/*	Macintosh Desktop Routines											*/
/*																		*/
/************************************************************************/

#if OPT_MACOS == 1

/*	XGAppCore::IsSystemMenu
 *
 *		Does this belong to the system menu?
 */

bool XGAppCore::IsSystemMenu(short id)
{
	WindowPtr w;
	
	w = MFrontWindow();
	if (((WindowPeek)w)->windowKind > 0) return false;
	switch (id) {
		case KXGEditUndo:
		case KXGEditCut:
		case KXGEditCopy:
		case KXGEditPaste:
		case KXGEditClear:
			return true;
	}
	return false;
}

/*	XGAppCore::DoSystemMenu
 *
 *		Does this belong to the system menu?
 */

bool XGAppCore::DoSystemMenu(short id)
{
	switch (id) {
		case KXGEditUndo:
			return SystemEdit(0);
		case KXGEditCut:
			return SystemEdit(2);
		case KXGEditCopy:
			return SystemEdit(3);
		case KXGEditPaste:
			return SystemEdit(4);
		case KXGEditClear:
			return SystemEdit(5);
	}
	return false;
}

#endif
