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

#include <z_fildlg.hpp>
#include <z_dskfil.hpp>
#include <z_unistd.hpp>
#include "m_win.hpp"

#define ZAF_FILE_DIALOG_INFO
#include "lang_def.cpp"

extern "C"
{
#include _DialogS_
#include _FileSB_
}

// ----- ZafFileDialog ------------------------------------------------------

ZafFileDialog::ZafFileDialog(int left, int top, int width, int height) :
	ZafDialogWindow(left, top, width, height)
{
	// Get the error stings.
	messages = ZafLanguageManager::Allocate(className, defaultMessages);

	directory[0] = file[0] = filter[0] = 0;
	SetModal(true);
}

ZafEventType ZafFileDialog::Event(const ZafEventStruct &event)
{
	// Check for special dialog events.
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	case S_DLG_OK:
		{
		char *osText;

		// Get the filter.
		XmString osFilter;
		XtVaGetValues(screenID, XmNpattern, &osFilter, 0);
		XmStringGetLtoR(osFilter, XmFONTLIST_DEFAULT_TAG, &osText);
		zafCodeSet->ConvertToZafString(osText, filter, false);
		XmStringFree(osFilter);
		XtFree(osText);

		// Get the file and directory.
		XmString osFile;
		XtVaGetValues(screenID, XmNdirSpec, &osFile, 0);
		XmStringGetLtoR(osFile, XmFONTLIST_DEFAULT_TAG, &osText);
		ZafIChar fullPath[ZAF_MAXPATHLEN];
		zafCodeSet->ConvertToZafString(osText, fullPath, false);
		ZafDiskFileSystem::StripFullPath(fullPath, directory, file);
		XmStringFree(osFile);
		XtFree(osText);
		}
		break;

	default:
		ccode = ZafDialogWindow::Event(event);
		break;
	}

	// Return the control code.
	return (ccode);
}

void ZafFileDialog::FullPath(ZafIChar *pathBuffer, int bufferSize)
{
	// Copy directory string.
	strncpy(pathBuffer, directory, bufferSize);
	int bufferIndex = strlen(directory);

	// Append a directory separator character if neccessary.
	if (pathBuffer[bufferIndex - 1] != ZafOSDirSepStr()[0])
	{
		strncpy(&pathBuffer[bufferIndex], ZafOSDirSepStr(), bufferSize - bufferIndex);
		bufferIndex++;
	}

	// Append the file name.
	strncpy(&pathBuffer[bufferIndex], file, bufferSize - bufferIndex);
}

ZafEventType ZafFileDialog::GetFile(ZafFileDialogRequest tRequest)
{
	// Defer to the base class.
	request = tRequest;
	return (ZafDialogWindow::Control());
}

// ----- OS Specific Functions ----------------------------------------------

static void select_action(Widget , ZafFileDialog *object, XmFileSelectionBoxCallbackStruct *callback)
{
	// Queue up the proper message.
	if (callback->reason == XmCR_CANCEL)
		object->eventManager->Put(S_DLG_CANCEL);
	else if (callback->reason == XmCR_OK)
		object->eventManager->Put(S_DLG_OK);
}

OSWindowID ZafFileDialog::OSScreenID(ZafScreenIDType type) const
{
	// Return the frame widget.
	if (type == ZAF_SHELLID && screenID)
		return (XtParent(screenID));
	return (screenID);
}

void ZafFileDialog::OSSize(void)
{
	// Default to the base window object class.
	ZafWindowObject::OSSize();
}

void ZafFileDialog::OSRegisterObject(void)
{
	// Level 1 - Create the dialog shell.
	char *name = zafCodeSet->ConvertToOSString(stringID, 0, false);
	OSDisplayContext xDisplay = XtDisplay(((ZafScreenDisplay *)display)->topLevelShell);
	screenID = XtVaAppCreateShell(0, name,
		(WidgetClass)&MtfWindowShell::classRecord, xDisplay, 0);

	// Update the shell attributes.
	if (Sizeable())
		SetDecoration(MWM_DECOR_RESIZEH);
	else
		ClearDecoration(MWM_DECOR_RESIZEH);
	XtVaSetValues(screenID,
		// region
		XmNx, zafRegion.left,
		XmNy, zafRegion.top,
		XmNwidth, 10,
		XmNheight, 10,
		// miscellaneous
		XmNdeleteResponse, XmDO_NOTHING, // wait for ExitShell.
		XmNsensitive, Disabled(false) ? false : true,
		XtNallowShellResize, false,
		XmNmwmDecorations, Decorations() | MWM_DECOR_BORDER | MWM_DECOR_MENU | MWM_DECOR_MAXIMIZE | MWM_DECOR_MINIMIZE | MWM_DECOR_TITLE,
		0);
	if (Minimized())
		XtVaSetValues(screenID, XmNinitialState, IconicState, 0);
	else if (Maximized())
		maximized = false; // not allowed by default in Motif.

	// Tell Motif to call ExitShell when user tries to close the window.
	Atom deleteWindowAtom = XmInternAtom(((ZafScreenDisplay *)display)->xDisplay, "WM_DELETE_WINDOW", false);
	XmAddWMProtocolCallback(screenID, deleteWindowAtom,
		(XtCallbackProc)MtfWindowShell::delete_window, (XtPointer)this);

	// Add callbacks for shell size and position changes.
	XtAddEventHandler(screenID, StructureNotifyMask | FocusChangeMask,
		false, (XtEventHandler)MtfWindowShell::callback,
		(XtPointer)this);

	// Set the shell title.
	ZafIChar *title = ZAF_NULLP(ZafIChar);
	if (request == ZAF_FILE_DIALOG_NEW)
		title = messages->GetMessage(ZAF_MSG_NEW);
	else if (request == ZAF_FILE_DIALOG_OPEN)
		title = messages->GetMessage(ZAF_MSG_OPEN);
	else if (request == ZAF_FILE_DIALOG_SAVEAS)
		title = messages->GetMessage(ZAF_MSG_SAVEAS);
	char *osText = zafCodeSet->ConvertToOSString(title);
	XtVaSetValues(screenID,
		XtNtitle, osText,
		XtNtitleEncoding, XA_STRING,
		0);
	delete []osText;

	// The default no match string is "[ ]". This is to small and file list 
	// is to narrow.  Make this larger by creating an XmString and passing it
	// to the XmFileSelectoinDialog on creation.
	XmString noMatch = XmStringCreateLocalized("[                    ]");

	// Level 2 - Create the file selection box.
	screenID = XtVaCreateManagedWidget(name,
		xmFileSelectionBoxWidgetClass, screenID,
		// user information
		XmNuserData, this,
		// miscellaneous
		XmNfileTypeMask, XmFILE_REGULAR,
		XmNnoMatchString, noMatch,
		0);

	// Make sure the file list has scroll bars. (For Solaris bug)
	Widget fileList = XmFileSelectionBoxGetChild(screenID, XmDIALOG_LIST);
	if (fileList)
		XtVaSetValues(fileList, XmNscrollBarDisplayPolicy, XmSTATIC, NULL);

	// Check for a specified directory.
	if (directory[0])
	{
		char *osText = zafCodeSet->ConvertToOSString(directory);
		XmString osDirectory = XmStringCreate(osText, XmFONTLIST_DEFAULT_TAG);
		XtVaSetValues(screenID, XmNdirectory, osDirectory, 0);
		XmStringFree(osDirectory);
		delete []osText;
	}

	// Check for a specified filter.
	if (filter[0])
	{
		char *osText = zafCodeSet->ConvertToOSString(filter);
		XmString osPattern = XmStringCreate(osText, XmFONTLIST_DEFAULT_TAG);
		XtVaSetValues(screenID, XmNpattern, osPattern, 0);
		XmStringFree(osPattern);
		delete []osText;
	}

	// Check for a specified file.
	if (file[0])
	{
		ZafIChar fullPath[ZAF_MAXPATHLEN];
		ZafDiskFileSystem::MakeFullPath(fullPath, directory, file);
		char *osText = zafCodeSet->ConvertToOSString(fullPath);
		XmString osFile = XmStringCreate(osText, XmFONTLIST_DEFAULT_TAG);
		XtVaSetValues(screenID, XmNtextString, osFile, 0);
		XmStringFree(osFile);
		delete []osText;
	}

	// Unmanage the help button.
	Widget helpButton = XmFileSelectionBoxGetChild(screenID, XmDIALOG_HELP_BUTTON);
	XtUnmanageChild(helpButton);

	// Register special callbacks.
	XtAddCallback(screenID, XmNcancelCallback,
		(XtCallbackProc)select_action, (XtPointer)this);
	XtAddCallback(screenID, XmNokCallback,
		(XtCallbackProc)select_action, (XtPointer)this);
}

