/*	XGAppCore_win.cpp
 *
 *		Windows specific implementation of various XGAppCore methods
 */

/*  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 <XApplication.h>
#include <XWindow.h>
#include <XMessages.h>
#include <XMenu.h>
#include <XError.h>
#include <XModifiers.h>
#include <XDataUtil.h>

#include <string.h>
#include <ctype.h>

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

UINT GTimerID;

/************************************************************************/
/*																		*/
/*	OS Init/Shutdown													*/
/*																		*/
/************************************************************************/

/*	XGAppCore::InitOS
 *
 *		Initialize the OS. I don't need to do very much here, just kick
 *  off a periodic event. I don't need to process this with any special
 *	code because my code automagically fires the periodic event handling
 *	code anyways.
 */

void XGAppCore::InitOS()
{
	GTimerID = ::SetTimer(NULL,0,250,NULL);
}

/*	XGAppCore::KillOS
 *
 *		Kill the OS. I don't need to do much here, either...
 */

void XGAppCore::KillOS()
{
	::KillTimer(NULL,GTimerID);
}

/*	XGAppCore::GetAppArgs
 *
 *		Called right before the event pump is run, this parses
 *	the arguments on the command line and passes them to my app
 */

void XGAppCore::GetAppArgs()
{
	char *ptr;
	char *arg[32];
	int i;
	int j;
	char buffer[256];
	
	/*
	 *	Convert into argv pairs
	 */
	
	strcpy(buffer,_GArgString);
	ptr = buffer;
	i = 0;
	for (;;) {
		while (isspace(*ptr)) ptr++;
		if (*ptr == '\0') break;
		if (*ptr == '\"') {
			/*
			 *	Escaped with quotes
			 */
			
			ptr++;
			arg[i++] = ptr;
			while ((*ptr != '\"') && (*ptr != '\0')) ptr++;
			if (*ptr == '\0') break;
			*ptr++ = 0;
		} else {
			/*
			 *	Not escaped
			 */
			
			arg[i++] = ptr;
			while (!isspace(*ptr) && (*ptr != '\0')) ptr++;
			if (*ptr == '\0') break;
			*ptr++ = 0;
		}
		if (i >= 32) break;
	}
	
	/*
	 *	Now start passing open document messages
	 */
	
	if (i > 0) {
		for (j = 0; j < i; j++) {
			GetCurFocus()->SendDispatch(KXGOpenDocument,0,(void *)arg[j]);
		}
	} else {
		GetCurFocus()->SendDispatch(KXGOpenApplication,0,NULL);
	}
}

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

/*	XGAppCore::VerifyFocus
 *
 *		This gets the current focus. If the window is not the main
 *	window, this sets the focus pointers correctly
 *
 *		If the focus is set to a
 */

void XGAppCore::VerifyFocus(void)
{
	HWND focus;
	XGView *v;
	XGWindow *w;
	
	focus = ::GetFocus();
	if (focus == NULL) return;
	
	if (NULL != (v = (XGView *)::GetProp(focus,_GControlClass))) {
		/* Yank the library focus here */
		if (!(v->HasFocus())) {
			if (!(v->SetFocus())) {
				/* Change not allowed. Put the focus <<back>> */
				focus = v->GetRootWindow();
				::SetFocus(focus);
			}
		}
	} else if (NULL != (w = (XGWindow *)::GetProp(focus,_GWindowClass))) {
		/* Yank Window's focus to the one who has focus */
		v = dynamic_cast<XGView *>(w->GetFocus());
		if (v) {
			if (v->GetRootWindow() != focus) {
				::SetFocus(v->GetRootWindow());
			}
		}
	}
}

/*	XGAppCore::DoEvent
 *
 *		Do one pass through my event loop.
 */

void XGAppCore::DoEvent()
{
	MSG msg;
	
	// Get the message
	if (!GetMessage(&msg,NULL,0,0)) {
		fQuitFlag = true;
		return;
	}
	
	// Process and dispatch
	if (!_GMDIWindow || !TranslateMDISysAccel(_GMDIWindow,&msg)) {
		if (!GetCurMenu()->TranslateAccelerator(_GMainWindow,&msg)) {
			XGWindow *w;
			
			w = XGWindow::GetXGWindow(msg.hwnd);
			if (w) fEventOwner = w;
			
			// Dispatch to allow me to intercept it
			if (1 == GetCurFocus()->SendDispatch(KXGAppEvent,0,(void *)&msg)) {
				VerifyFocus();
				return;
			}
			
			// Trap WM_CHAR, WM_KEYDOWN messages. This allows me
			// to process these messages and skim out the 'tab'
			// keys and the like.
			
			if (-1 != ProcKeyboardCommon(msg.message,msg.wParam,msg.lParam)) {
				VerifyFocus();
				return;
			}
			
			// Note: TranslateMessage is called after ProcKeyboardCommon
			// in order to prevent me from resending WM_CHAR commands
			// for keyboard events that I already handled.
	
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			
			fEventOwner = NULL;
		}
	}
	
	VerifyFocus();
}

/*	XGAppCore::CancelCheck
 *
 *		This checks for a cancel key on Windows; this checks to make
 *	sure the 'escape' key is not pressed to stop this operation.
 */

bool XGAppCore::CancelCheck(void)
{
	short keystate = GetAsyncKeyState(VK_ESCAPE);
	if (keystate & 0x8000) return true;
	return false;
}

