//	Zinc Application Framework - M_ERROR1.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <z_stdlib.hpp>
#include <z_cset.hpp>
#include <z_error.hpp>
#include "m_utils.hpp"
#include "m_win.hpp"

extern "C"
{
#include _MessageB_
}

// ----- ZafErrorSystem -----------------------------------------------------

static ZafDialogEvent ccode = 0;

static void callback(Widget , ZafWindowObject *, XmAnyCallbackStruct *callback)
{
	// Determine the appropriate error message.
	if (callback->reason == XmCR_CANCEL)
		ccode = S_DLG_CANCEL;
	else if (callback->reason == XmCR_OK)
		ccode = S_DLG_OK;
	else if (callback->reason == XmCR_HELP)
		ccode = S_HELP;
}

static void error_win_on_top(Widget widget, Widget errorDlg, XEvent *event,
 Boolean)
{
	if ((event->type == FocusOut && widget == errorDlg) ||
	 (event->type == FocusIn && widget != errorDlg))
	{
		Widget shell = XtParent(errorDlg);
		XRaiseWindow(XtDisplay(shell), XtWindow(shell));
	}
}

ZafDialogEvent ZafErrorSystem::ErrorMessage(ZafWindowObject *object,
	const ZafIChar *title, ZafDialogFlags msgFlags, const ZafIChar *message)
{
	// Beep the system.
	Beep();
	if (!message)
		return (0);
	ZafWindowManager *windowManager = zafWindowManager;

	// Create the motif error window.
	Arg args[5];
	int nargs = 0;

#if defined(ZAF_UNICODE)
	char *osText = zafCodeSet->ConvertToOSString(message);
	XmString osMessage = XmStringCreateLocalized(osText);
	XtSetArg(args[nargs], XmNmessageString, osMessage); nargs++;
	delete []osText;
#else
	char *osText = zafCodeSet->ConvertToOSString(message);
	XmString osMessage = XmStringCreateLtoR(osText, XmFONTLIST_DEFAULT_TAG);
	XtSetArg(args[nargs], XmNmessageString, osMessage); nargs++;
	delete []osText;
#endif

	osText = zafCodeSet->ConvertToOSString((title && *title) ? title :
	 messages->GetMessage(ZAF_MSG_TITLE));
	XtSetArg(args[nargs], XmNtitle, osText); nargs++;
	XtSetArg(args[nargs], XmNiconName, osText); nargs++;
	XtSetArg(args[nargs], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); nargs++;

	char *name = zafCodeSet->ConvertToOSString(className, 0, false);
	Widget widget = XmCreateErrorDialog(((ZafScreenDisplay *)windowManager->display)->topLevelShell, name, args, nargs);

	XmStringFree(osMessage);
	delete []osText;
	XtManageChild(widget);

	// Center the error window.
	Dimension errorWidth, errorHeight;
	XtVaGetValues(widget, XmNwidth, &errorWidth, XmNheight, &errorHeight, NULL);

	Position errorXPos = (windowManager->Display()->columns - errorWidth) / 2;
	Position errorYPos = (windowManager->Display()->lines - errorHeight) / 2;
	XtVaSetValues(XtParent(widget), XmNx, errorXPos, XmNy, errorYPos, NULL);

	// Add special callbacks.
	if (msgFlags & ZAF_DIALOG_CANCEL)
		XtAddCallback(widget, XmNcancelCallback, (XtCallbackProc)callback, (XtPointer)object);
	else
		XtUnmanageChild(XmMessageBoxGetChild(widget, XmDIALOG_CANCEL_BUTTON));
	if (msgFlags & ZAF_DIALOG_OK)
		XtAddCallback(widget, XmNokCallback, (XtCallbackProc)callback, (XtPointer)object);
	else
		XtUnmanageChild(XmMessageBoxGetChild(widget, XmDIALOG_OK_BUTTON));
	if (msgFlags & ZAF_DIALOG_HELP)
		XtAddCallback(widget, XmNhelpCallback, (XtCallbackProc)callback, (XtPointer)object);
	else
		XtUnmanageChild(XmMessageBoxGetChild(widget, XmDIALOG_HELP_BUTTON));

	// Keep the error dialog on top.
	XtAddEventHandler(widget, FocusChangeMask, true,
	 (XtEventHandler)error_win_on_top, widget);
	if (object && object->screenID)
		XtAddEventHandler(object->screenID, FocusChangeMask, true,
		 (XtEventHandler)error_win_on_top, widget);

	// Change the cursor of parent to indicate error window is modal.
	Cursor modalCursor;
	Display *display;
	ZafWindowObject *rootObject;
	if (object && object->screenID)
	{
		display = ((ZafScreenDisplay *)object->Display())->xDisplay;
		rootObject = object->RootObject();
		modalCursor = XCreateFontCursor(display, XC_dot);
	 	XDefineCursor(display, XtWindow(rootObject->OSScreenID(ZAF_SHELLID)), modalCursor);
	}

	ccode = 0;

	// Block until the status is updated or while the window is open.
	XtVaSetValues(widget, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, 0);

	while (ccode == 0 && XtIsManaged(widget))
		XtAppProcessEvent(((ZafScreenDisplay *)zafDisplay)->xAppContext, XtIMAll);
	
	// Clean up
	if (object && object->screenID)
	{
		// Unregister event handler
		XtRemoveEventHandler(object->screenID, FocusChangeMask, true,
		 (XtEventHandler)error_win_on_top, widget);

		// Restore cursor
		XUndefineCursor(display, XtWindow(rootObject->OSScreenID(ZAF_SHELLID)));
		XFreeCursor(display, modalCursor);
	}
	XtDestroyWidget(widget);
		
	// Return the error response.
	return (ccode);
}

