/*	XApplication.h
 *
 *		This contains the various declarations for the different
 *	types of application that can be built with the YAAF library
 */

/*  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
 */

#ifndef PandaWave_XAPPLICATION
#define PandaWave_XAPPLICATION

#include <XConfig.h>
#include <XEvent.h>

#if OPT_XWIN
#include <X11/Xlib.h>
#define XK_MISCELLANY
#include <X11/keysymdef.h>
#endif

/************************************************************************/
/*																		*/
/*	Forwards															*/
/*																		*/
/************************************************************************/

class XGAppCore;
class XGView;
class XGWindow;
class XGMenuBar;
class XGEventOwner;

#if OPT_MACOS
extern "C" void XGRDoActivate(WindowPtr,short);
#endif

/************************************************************************/
/*																		*/
/*	Application entry point												*/
/*																		*/
/************************************************************************/

/*
 *	User defined start of YAAF application
 */

extern XGAppCore *StartApplication(void);

/************************************************************************/
/*																		*/
/*	Class Declarations													*/
/*																		*/
/************************************************************************/

/*	@C"XGAppCore"
 *	@D"XGFocus"
 *	@H"XApplication.h"
 *	@I
 *
 *		This encapsulates the core event code for the YAAF application.
 *	Your application class would be declared as a descendant of the
 *	XGAppSingleWindow or XGAppMultiWindow classes instead of this one.
 */

class XGAppCore : public XGFocus {
	public:
								XGAppCore();
		virtual					~XGAppCore();
		
		/*
		 *	Current application
		 */
		
		// @G"Status Information"
		
		/*	@F"XGAppCore::GetApplication" @I
		 *
		 *		Returns a pointer to the currently created application
		 *	object.
		 */
		
		static XGAppCore		*GetApplication()
									{
										return gApplication;
									}
		
		/*
		 *	Event processing
		 */
		
		// @G"Event Processing"
		
		virtual void			Run();
		virtual void			Exit();
		void					RunOnce(XGWindow *w);
		
		/*	@F"XGAppCore::WaitCheck" @I
		 *
		 *		Static method for running the event loop once.
		 *	Returns 'true' if the cancel key was selected.
		 */
		
		static bool				WaitCheck()
									{
										return gApplication->CancelCheck();
									}
		bool					CancelCheck();

		/*	@F"XGAppCore::IsModalWindow" @I
		 *
		 *		Returns true if the event loop is currently executing
		 *	in behalf of modal window dialog processing.
		 */
		
		bool					IsModalWindow()
									{
										return (NULL != fModalWindow);
									}

		/*	@F"XGAppCore::WaitCheck" @I
		 *
		 *		Returns the modifier flags associated with the last
		 *	keyboard or mouse event processed.
		 */
		
		static short			GetLastModifiers()
									{
										return gLastMods;
									}
		
		
		/*
		 *	Basic global menus
		 */
		
		DECLAREDISPATCH
		long					DoMenuCommand(long,void *);
		long					DoGetMenuStatus(long,void *);
		long					DoQuitApplication(long,void *);
		
		/*
		 *	copyright support
		 */
		
		virtual void			ShowCopyright();		// in reply to event
		virtual void			OpenCopyright();		// open first window
		virtual void			CloseCopyright();		// close first window

	protected:
		/*
		 *	Menu focus support routines
		 */
		
		virtual XGMenuBar		*GetCurMenu() = 0;
		virtual XGFocus			*GetCurFocus() = 0;

		XGWindow				*fEventOwner;
		XGWindow				*fModalWindow;
	private:
		static XGAppCore		*gApplication;
		static short			gLastMods;
		bool					fQuitFlag;
		
		/*
		 *	Common Internals
		 */
		
		void					InitOS();
		void					KillOS();
		void					GetAppArgs();
		void					DoEvent();
		
#if OPT_MACOS == 1
		/*
		 *	Macintosh specific stuff
		 */
		
		Point					fLastClick;
		long					fLastTime;
		
		bool					fAppleEvents;
		
		/*
		 *	Macintosh routines
		 */
		
		bool					IsSystemMenu(short);
		bool					DoSystemMenu(short);
		
		/*
		 *	Event management
		 */
		 		
		void					GetWindowMinMax(WindowPtr,Rect *);
		void					SetWindowZoom(WindowPtr);
		void					DrawGrowIcon(WindowPtr);
		short					GetEventFlags(EventRecord &);
		short					GetKeyCode(EventRecord &);
		bool					DoMenuKey(char);
		void					DoMenuClick(Point);
		void					DoWindowKey(EventRecord &);
		void					DoActivate(WindowPtr,bool);
		void					DoUpdate(WindowPtr);
		void					DoSizeContents(WindowPtr);
		void					DoWindowClick(WindowPtr,EventRecord &);
		void					DoCloseWindow(WindowPtr);
		void					DoMouseClick(EventRecord &);
		void					DoMouseMove(EventRecord &);
		
		void					RunUpdateOnce();
		
		void					RunEventLoop(void);
		
		void					InitOS6Events(void);
		void					InitAppleEvents(void);
		static OSErr 			GotRequiredParams(AppleEvent *);
		static pascal OSErr		AEHandleProc(AppleEvent *event, 
											 AppleEvent *retval, 
											 long refNum);
		
	friend void XGRDoActivate(WindowPtr,short);
#endif

#if OPT_XWIN
		/*
		 *	Event management for X
		 */
		
		void					ArrangeOrder();
		short					GetSpecialKey(KeySym);
		short					DeriveFlags(long);
		static Window			GetParentWindow(Window);
#endif

	/*
	 *	WINPROC access
	 */
	 
#if OPT_WINOS
		void					VerifyFocus(void);
		
		static short 			GetExtendedKeyCode(WPARAM wp, LPARAM lp);
		static short 			GetStateFlags();
		static long				ProcKeyboardCommon(UINT,WPARAM,LPARAM);
		static long				ProcXGWindowCommon(XGWindow *,UINT,WPARAM,LPARAM);

	friend LRESULT CALLBACK _GMainMDIWindowProc(HWND, UINT, WPARAM, LPARAM);
	friend LRESULT CALLBACK _GChildWindowProc(HWND, UINT, WPARAM, LPARAM);
	friend LRESULT CALLBACK _GSingleWindowProc(HWND, UINT, WPARAM, LPARAM);
#endif
	
	friend class XGEventOwner;
	friend class XGWindow;
};

#if OPT_WINOS || OPT_XWIN

/*	XGEventOwner
 *
 *		A small stack-based class which assists in noting the owner
 *	of an event (for Windows and XWindows applications). This is
 *	created during the processing of an event owned by a window,
 *	which lets my application core know where the event should be
 *	routed to.
 */

class XGEventOwner {
	public:
		XGEventOwner(XGWindow *w)
			{
				XGAppCore::GetApplication()->fEventOwner = w;
			}
		~XGEventOwner()
			{
				XGAppCore::GetApplication()->fEventOwner = NULL;
			}
};

#endif

/************************************************************************/
/*																		*/
/*	Single Window Application Type										*/
/*																		*/
/************************************************************************/

/*	@C"XGAppSingleWindow"
 *	@D"XGAppCore"
 *	@H"XApplication.h"
 *	@I
 *
 *		This implements a single-window application. On Windows, this
 *	creates an SDI window application; on the Macintosh this creates
 *	an application which quits as soon as the window is closed.
 *
 *		The way this works is to create a single menu bar object
 *	(in Windows, in the opened window), and update the menu bar
 *	according to the messages received by 'ReceiveDispatch' (on the
 *	periodic events).
 *
 *		When the main window close event is received, we terminate
 *	the event loop and quit this program.
 */

class XGAppSingleWindow : public XGAppCore {
	public:
								XGAppSingleWindow();
		virtual					~XGAppSingleWindow();
		
		/*
		 *	Application initialization procedures
		 */
		
		void					Run(void);
		
		DECLAREDISPATCH
		long					DoWindowCreate(long, void *);
		long					DoWindowDestroy(long, void *);
		long					DoPostPeriodic(long, void *);

	protected:
		/*
		 *	Overrides--this determines how we handle the focus
		 */
		 
		virtual XGMenuBar		*GetCurMenu();
		virtual XGFocus			*GetCurFocus();

	private:
		XGWindow				*fMyWindow;
		XGMenuBar				*fMyMenuBar;
		
		/*
		 *	Initialization
		 */

#if OPT_WINOS == 1
		void					InitInstance();
		void					InitApplication();
#endif
};

/************************************************************************/
/*																		*/
/*	Multiple Window Application Type									*/
/*																		*/
/************************************************************************/

/*	XGLstRecord
 *
 *		This is an internal record used to record the list of windows that
 *	are in my application
 */

struct XGLstRecord {
	short						menuAccel;
	short						menuID;
	XGWindow					*fWindow;
	
#if OPT_WINOS || OPT_XWIN
	XGMenuBar					*fMenuBar;
#endif
};

/*	@C"XGAppMultiWindow"
 *	@D"XGAppCore"
 *	@H"XApplication.h"
 *	@I
 *
 *		This implements a multi-window application. On Windows, this
 *	creates an MDI window application; on the Macintosh this creates
 *	the standard multi-window application
 *
 *		This works by creating a global menu bar, and maintaining both
 *	that menu bar and a global table of all the open windows. (This
 *	is used to maintain the window menu.)
 *
 *		This terminates when the quit command is issued. This may also
 *	quit when all the windows are closed, depending on the mode and
 *	the platform this is running under.
 *
 *		Macintosh:		App quits only on quit command
 *
 *		X:				App quits when all windows are closed
 *
 *		MS Windows:		If 'appName' is NULL, SDI application will
 *						quit when all windows are closed; otherwise,
 *						MDI app quits on quit command only.
 */

class XGAppMultiWindow : public XGAppCore {
	public:
								XGAppMultiWindow(char *appName = NULL);
		virtual					~XGAppMultiWindow();
		
		/*
		 *	Application initialization procedures
		 */
		
		DECLAREDISPATCH
		long					DoWindowCreate(long, void *);
		long					DoWindowDestroy(long, void *);
		long					DoWindowName(long, void *);
		long					DoGetMenuStatus(long, void *);
		long					DoMenuCommand(long, void *);
		long					DoPostPeriodic(long, void *);

	protected:
		/*
		 *	Overrides--this determines how we handle the focus
		 */
		 
		virtual XGMenuBar		*GetCurMenu();
		virtual XGFocus			*GetCurFocus();

	private:
		/*
		 *	Initialization
		 */

#if OPT_WINOS == 1
		void					InitMDIInstance(char *);
		void					InitMDIApplication();
		void					InitSDIInstance();
		void					InitSDIApplication();
#endif

		/*
		 *	Support routines
		 */
		
		void					DoCreateWindow(XGWindow *);
		void					DoDestroyWindow(XGWindow *);
		void					DoRenameWindow(XGWindow *);
		
		void					SortWindowList();
		void					UpdateWindowMenu();
		void					UpdateWindowMenu(XGMenuBar *);

		
#if (OPT_MACOS == 1) || (OPT_WINOS == 1)
		void					TileWindows();
		void					CascadeWindows();
#endif

#if OPT_WINOS
		void					ArrangeIcons();
#endif

		/*
		 *	Internal structures
		 */
		
		XGSDynArray<XGLstRecord> fWindowList;
	
#if (OPT_MACOS == 1) || (OPT_WINOS == 1)
		XGMenuBar				*fMyMenuBar;
#endif
};

#endif // PandaWave_XAPPLICATION

