/*
 * @DEC_COPYRIGHT@
 */
/*
 * HISTORY
 * Revision 1.2  1995/03/09  21:50:15  bourquard
 * port to NT
 *
 *
 * Revision 1.1.4.3  1993/07/30  19:50:35  Lynda_Rice
 * 	QAR 13541:  Fixed resource problems in CreateFileSelector().
 * 	[1993/07/28  21:33:10  Lynda_Rice]
 *
 * Revision 1.2  91/12/30  12:48:20  devbld
 * 	Initial load of project
 * 
 * Revision 1.1.4.2  1993/06/25  16:58:14  Lynda_Rice
 * 	Motif 1.2 Support
 * 	[1993/06/24  20:19:14  Lynda_Rice]
 * 
 * Revision 1.1.2.4  1993/01/05  17:26:26  Don_Haney
 * 	Implement HyperHelp and mnemonics
 * 	[92/12/31  14:52:23  Don_Haney]
 * 
 * Revision 1.1.2.3  92/11/25  08:10:20  Russ_Kuhn
 * 	Add a little margin to the file sel. boxes for better appearance
 * 	[92/11/25  08:08:40  Russ_Kuhn]
 * 
 * Revision 1.1.2.2  92/08/03  09:48:34  Dave_Hill
 * 	initial port to alpha
 * 	[92/08/03  09:38:21  Dave_Hill]
 * 
 * Revision 1.1  90/01/01  00:00:00  devrcs
 * 	Initial load into Alpha pool
 * 
 */
#ifndef lint	/* BuildSystemHeader added automatically */
static char *BuildSystemHeader= "$Id: fileselect.c,v 1.3 1995/03/10 18:02:17 bourquard Exp $";
#endif		/* BuildSystemHeader */
/*
 * Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
 * 
 *                         All Rights Reserved
 * 
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

/*
 *
 *	dxdiff
 *
 *	fileselect.c - file selection stuff
 *
 *	Author:	Laurence P. G. Cable
 *
 *	Created : 23rd June 1988
 *
 *
 *	Description
 *	-----------
 *
 *
 *	Modification History
 *	------------ -------
 *	
 *	02/23/94	Dhiren M. Patel
 *	Fix ootb_bug 177. A dialog box will pop up informing the user if an
 *	attempt is made to open binary file(s). Added an include file to
 *	facilitiate prototyping.
 */

static char sccsid[] = "@(#)fileselect.c	1.1	15:20:47 7/3/88";


#include <sys/types.h>
#include <sys/stat.h>

#ifdef  DEBUG
#include <stdio.h>
#endif  /* DEBUG */
#include <X11/Xlib.h>
#ifdef WIN32
#include <X11/xfuncs.h>
#endif WIN32
#include <Xm/Xm.h>
#include <Xm/MessageB.h>
#include "dxdiff.h"
#include "arglists.h"
#include "y.tab.h"
#include "filestuff.h"
#include "parsediff.h"
#include "alloc.h"
#include "differencebox.h"
#include "menu.h"
#include "text.h"
#include "display.h"
#include "globals.h"
#include "dxdiff_proto.h"	/* Function proto's */
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif WIN32

extern int CheckForBinaryFile PROTO ((int f));
extern void Msg_messageparams ();
extern Cardinal Msg_putmessage PROTO ((	Widget parent,
					char *uil_index,
					Display *disp,
					MrmHierarchy diff_hierarchy));

/********************************
 *
 *	FileSelectorCancelCallBack
 *
 ********************************/

static void
FileSelectorCancelCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd,
		calld;
{
	register DxDiffDisplayPtr dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	register FileSelectorPtr  fsptr;

	if (FileSelectorPtrFileSelector(DxDiffDisplayPtrLFileSelector(dxdiffdisplay)) == w) {
		fsptr = DxDiffDisplayPtrLFileSelector(dxdiffdisplay);
	} else {
		fsptr = DxDiffDisplayPtrRFileSelector(dxdiffdisplay);
	}

	XtUnmanageChild(w);	/* unmanage the sucker !! */
}

static XtCallbackRec	fileselectorcancelcallbacklist[] = {
	{ (VoidProc)FileSelectorCancelCallback, NULL },
	{ (VoidProc)NULL, NULL }
};

/********************************
 *
 *	FileSelectorDestroyCallback
 *
 ********************************/

static void
FileSelectorDestroyCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd,
		calld;
{
	register DxDiffDisplayPtr dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	register FileSelectorPtr  fsptr = NULL;

#ifdef I18N_MULTIBYTE
	long byte_count;
	long status;
	XmString null_cs;

	/* create an empty XmString for comparison purpose */
	null_cs = (XmString) DXmCvtFCtoCS("", &byte_count, &status);
#endif /* I18N_MULTIBYTE */

	if (DxDiffDisplayPtrLFileSelector(dxdiffdisplay) &&
	    FileSelectorPtrFileSelector(DxDiffDisplayPtrLFileSelector(dxdiffdisplay)) == w) {
		fsptr = DxDiffDisplayPtrLFileSelector(dxdiffdisplay);
			DxDiffDisplayPtrLFileSelector(dxdiffdisplay) = (FileSelectorPtr)NULL;
	} else {
		fsptr = DxDiffDisplayPtrRFileSelector(dxdiffdisplay);
		DxDiffDisplayPtrRFileSelector(dxdiffdisplay) = (FileSelectorPtr)NULL;
	}

	if (fsptr == (FileSelectorPtr)NULL)
		return;

#ifdef I18N_MULTIBYTE
	/* The fileselector pointer "file" and "dir" have changed types to 
	   XmString 
	*/
	if (FileSelectorPtrFile(fsptr) != null_cs)
		XmStringFree(FileSelectorPtrFile(fsptr));
	if (FileSelectorPtrDir(fsptr) != null_cs)
		XmStringFree(FileSelectorPtrDir(fsptr));
#else
	if (FileSelectorPtrFile(fsptr) != (char *)NULL)
		XtFree(FileSelectorPtrFile(fsptr));
	if (FileSelectorPtrDir(fsptr) != (char *)NULL)
		XtFree(FileSelectorPtrDir(fsptr));
#endif /* I18N_MULTIBYTE */

	XtFree((char *)fsptr);

}


static XtCallbackRec	fileselectordestroycallbacklist[] = {
	{ (VoidProc)FileSelectorDestroyCallback, NULL },
	{ (VoidProc)NULL, NULL }
};

/********************************
 *
 *	FileSelectorActivateCallback
 *
 ********************************/

static void
FileSelectorActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd,
		calld;
{
	register DxDiffDisplayPtr	dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	XmFileSelectionBoxCallbackStruct	*cbsp = (XmFileSelectionBoxCallbackStruct *)calld;
	register FileSelectorPtr 	fsptr;

#if (((XmVERSION == 1) && (XmREVISION >=2)) || XmVERSION >= 2)
#define charset XmFONTLIST_DEFAULT_TAG
#else
	char				*charset = "ISO8859-1";
#endif


	int fd;
	int file_ascii;
	char *filename;

#ifdef WIN32
	char *msgstr;
#endif WIN32

#ifdef I18N_MULTIBYTE
	long byte_count;
	long status;
	XmString null_cs;


	/* Create an empty XmString for comparison purpose */
	null_cs  = (XmString) DXmCvtFCtoCS("", &byte_count, &status);
#endif /* I18N_MULTIBYTE */

	if (FileSelectorPtrFileSelector(DxDiffDisplayPtrLFileSelector(dxdiffdisplay)) == w) {
		fsptr = DxDiffDisplayPtrLFileSelector(dxdiffdisplay);
	} else {
		fsptr = DxDiffDisplayPtrRFileSelector(dxdiffdisplay);
	}

	if (cbsp->reason == XmCR_OK) {
		int len;

#ifdef I18N_MULTIBYTE
		/* This seems to be a more precise comparison */
		if (cbsp->value != null_cs)
#else
		if (cbsp->value != (XmString)NULL)
#endif /* I18N_MULTIBYTE */
		{
			FileSelectorPtrValue(fsptr) = (XmString)(cbsp->value);

#ifdef I18N_MULTIBYTE
			/* fileselector pointer "file" has changed type to 
			   XmString. Also, it should be updated with the whole
			   of cbsp->value and not just a single text segment.
			*/
			if (FileSelectorPtrFile(fsptr) != null_cs)
				XmStringFree(FileSelectorPtrFile(fsptr));
			FileSelectorPtrFile(fsptr) = (XmString) XmStringCopy(cbsp->value);
#else
			if (FileSelectorPtrFile(fsptr) != (char *)NULL)
				XtFree(FileSelectorPtrFile(fsptr));

			
			XmStringGetLtoR(cbsp->value, charset, 
					&FileSelectorPtrFile(fsptr));
#endif /* I18N_MULTIBYTE */


#ifdef I18N_MULTIBYTE
			filename = (char *)DXmCvtCStoFC(FileSelectorPtrFile
						(fsptr), &byte_count, &status);
#else
			filename = FileSelectorPtrFile(fsptr);
#endif /* I18N_MULTIBYTE */

			/* dp: 
			 * check to make sure that the selected file is a
			 * legitimate file. If it is not, issue an error
			 * message & leave the File Selection dialog on screen.
			 */
			fd = open(filename, 0);
			if (!(file_ascii = CheckForBinaryFile(fd)))
			{
#ifndef WIN32
			    Msg_messageparams (1,filename);
			    Msg_putmessage(toplevel,"k_file_binary",
					XtDisplay(toplevel), dxdiff_hierarchy);
#else
				msgstr = XtMalloc( strlen ("File  is a binary file.") + strlen(filename) + 1);
				strcat (msgstr, "File ");
				strcat (msgstr, filename);
				strcat (msgstr, " is a binary file.");
				MessageBoxEx( NULL,				/* owner window handle */
							   msgstr,
							   "Dxdiff: message",
					    	   MB_ICONEXCLAMATION || MB_SETFOREGROUND || MB_OK,
					    	   MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
				XtFree(msgstr);
#endif		
#ifdef I18N_MULTIBYTE
			    XtFree((char *) filename);
#endif /* I18N_MULTIBYTE */
			    return;
			}
		}

#ifdef I18N_MULTIBYTE
		/* This seems to be a more precise comparison */
		if (cbsp->mask != null_cs) 
#else
		if (cbsp->mask != (XmString)NULL)
#endif /* I18N_MULTIBYTE */
		{
			FileSelectorPtrValue(fsptr) = (XmString)(cbsp->mask);

#ifdef I18N_MULTIBYTE
			/* fileselector pointer "dir" has changed type to 
			   XmString. Also, it should be updated with the whole
			   of cbsp->mask and not just a single text segment.
			*/
			if (FileSelectorPtrDir(fsptr) != null_cs)
				XmStringFree(FileSelectorPtrDir(fsptr));
			FileSelectorPtrDir(fsptr) = XmStringCopy(cbsp->mask);
#else
			if (FileSelectorPtrDir(fsptr) != (char *)NULL)
				XtFree(FileSelectorPtrDir(fsptr));

			
			XmStringGetLtoR(cbsp->mask, charset,
					&FileSelectorPtrDir(fsptr));
#endif /* I18N_MULTIBYTE */
		}
	    XtUnmanageChild(w);	/* bring the window down */
	}
}

static XtCallbackRec	fileselectoractivatecallbacklist[] = {
	{ (VoidProc)FileSelectorActivateCallback, NULL },
	{ (VoidProc)NULL, NULL }
};

extern void HelpActivateCallback();

#ifdef HYPERHELP
static XtCallbackRec	fileselectorhelpcallbacklist[] = {
	{ (VoidProc)HelpActivateCallback, "select_files"},
	{ (VoidProc)NULL, NULL }
#else
static XtCallbackRec	fileselectorhelpcallbacklist[] = {
	{ (VoidProc)HelpActivateCallback, "Overview file_menu open_files"},
	{ (VoidProc)NULL, NULL }
#endif
};
/********************************
 *
 *	NewFileSelector
 *
 ********************************/

static FileSelectorPtr
NewFileSelector(copy)
	register FileSelectorPtr copy;
{
	register FileSelectorPtr new;

	if ((new = (FileSelectorPtr)XtMalloc(sizeof (FileSelector))) == (FileSelectorPtr)NULL) {
		return (FileSelectorPtr)NULL;	/* error */
	}

	if (copy != (FileSelectorPtr)NULL)
		bcopy((char*)copy, (char *)new, sizeof (FileSelector));

	return new;
}

/********************************
 *
 *	CreateFileSelector
 *
 ********************************/

static FileSelector fileselector = {
	StaticInitCoreArgList(0, 0, 0, 0, 0, (XtArgVal)fileselectordestroycallbacklist),
	StaticInitDialogBoxArgList(XmPIXELS, XmSTRING, NULL, XmDIALOG_MODELESS,
				   XmRESIZE_ANY, True, 10, 10),
	{ XmNautoUnmanage, False},
	{ XmNdefaultPosition, True },
	{ XmNdirMask, NULL },
	{ XmNokCallback, (XtArgVal)fileselectoractivatecallbacklist },
	{ XmNcancelCallback, (XtArgVal)fileselectorcancelcallbacklist },
	{ XmNhelpCallback, (XtArgVal)fileselectorhelpcallbacklist},
	NULL,
	NULL,			 	/* leave the context alone! */
	NULL,
	NULL,
	NULL,
	NULL
};

FileSelectorPtr
CreateFileSelector(parent, name, label, core, dialog, dxdiffdisplay, closure)
	Widget			parent;
#ifdef I18N_MULTIBYTE
	XmString		name;
	XmString		label;
#else
	char			*name;
	char			*label;
#endif /* I18N_MULTIBYTE */
	CoreArgListPtr		core;
	DialogBoxArgListPtr	dialog;
	DxDiffDisplayPtr	dxdiffdisplay;
	caddr_t			closure;
{
	register FileSelectorPtr new;

#ifdef I18N_MULTIBYTE
	long byte_count;
	long status;
#endif /* I18N_MULTIBYTE */

	if ((new = NewFileSelector(&fileselector)) == (FileSelectorPtr)NULL) {
		return (FileSelectorPtr)NULL;	/* error */
	}


	if (core != (CoreArgListPtr)NULL) {
		bcopy((char *)core, (char *)&FileSelectorPtrCoreArgList(new), sizeof (CoreArgList) - 
		      sizeof (Arg));
	}

	if (dialog != (DialogBoxArgListPtr)NULL) {
		bcopy((char *)dialog, (char *)&FileSelectorPtrDialogBoxArgList(new), sizeof (DialogBoxArgList));
	}

	DialogBoxStyle(FileSelectorPtrDialogBoxArgList(new)) = XmDIALOG_MODELESS;
#ifdef I18N_MULTIBYTE
	/* "label" has changed type to XmString. Must use convertor
	   DXmCvtCStoFC() to change it back to file code here.
	*/
	DialogBoxTitle(FileSelectorPtrDialogBoxArgList(new)) = 
				DXmCvtCStoFC(label, &byte_count, &status);
#else
	DialogBoxTitle(FileSelectorPtrDialogBoxArgList(new)) = (XtArgVal)label;
#endif /* I18N_MULTIBYTE */
	FileSelectorPtrDirMaskArg(new) = (XtArgVal)
#ifdef I18N_MULTIBYTE
		/* Use DXmCvtFCtoCS() to be more consistent */
		DXmCvtFCtoCS("*", &byte_count, &status);
#else
	/* dp: there was an apparent memory corruption issue in 
	 * XmStringLtoRCreate in Motif 1.2 for Sterling 
	 */
		XmStringCreate("*" , XmFONTLIST_DEFAULT_TAG);
#endif /* I18N_MULTIBYTE */

	fileselectordestroycallbacklist[0].closure = fileselectoractivatecallbacklist[0].closure = 
	fileselectorcancelcallbacklist[0].closure = closure;


	FileSelectorPtrFileSelector(new) = (Widget)XmCreateFileSelectionDialog(parent,
#ifdef I18N_MULTIBYTE 
				/* "name" has changed type to XmString. Use
				    DXmCvtCStoFC() to change it back to file
				    code here.
				*/
				DXmCvtCStoFC(name, &byte_count, &status),
#else
								  name,
#endif
								  &FileSelectorPtrCoreArgList(new),
								  NumberOfArgsBetween(&FileSelectorPtrCoreArgList(new),
								  &FileSelectorPtrHelpCallBack(new)));

	if (FileSelectorPtrFileSelector(new) == (Widget)NULL) {
             return (FileSelectorPtr)NULL;   /* error */
        }

	{
#ifdef I18N_MULTIBYTE
		char buf[3];
		char *new_title, *title;
		long byte_count, status;

		/* "label" has changed type to XmString and hence must convert
		   it back to file code before concat with "buf". Then we use
		   XmbSetWMProperties() to set the new title. This function
		   can handle multibyte title.
		*/
		sprintf(buf, ":%1d",
			DxDiffDisplayPtrDisplayIdx(dxdiffdisplay));
		title = (char *) DXmCvtCStoFC(label, &byte_count, &status);
		new_title = XtMalloc(strlen(title)+strlen(buf)+1);
		strcpy(new_title, title);
		strcat(new_title, buf);
		XmbSetWMProperties(
		XtDisplay(XtParent(FileSelectorPtrFileSelector(new))), 
		XtWindow(XtParent(FileSelectorPtrFileSelector(new))), 
		new_title, NULL, NULL, 0, NULL, NULL, NULL); 
		XtFree(title);
		XtFree(new_title);
#else
		char	newname[80];
		Arg	arg;

		/* Only print :x if this is not the main window. */
		if ( DxDiffDisplayPtrDisplayIdx(dxdiffdisplay) == 0 )
		    sprintf(newname,"%s", label );
		else sprintf(newname,"%s: %1d", label, DxDiffDisplayPtrDisplayIdx(dxdiffdisplay));
		
		arg.name = XtNtitle;
		arg.value = (XtArgVal)newname;

		XtSetValues(XtParent(FileSelectorPtrFileSelector(new)), &arg, 1);
#endif /* I18N_MULTIBYTE */
	}
	
	XtManageChild(FileSelectorPtrFileSelector(new));

	return new;
}
