/*
 * @DEC_COPYRIGHT@
 */
/*
 * HISTORY
 * Revision 1.2  1995/03/09  21:51:46  bourquard
 * port to NT
 *
 *
 * Revision 1.1.4.3  1993/07/30  19:50:43  Lynda_Rice
 * 	QAR 13541:  Fixed resource problems in CreateFileSelector().
 * 	QAR 13442:  Fixed segmentation fault/core dump problem in
 * 		    QuitActivateCallback(). Sometimes this problem surfaced as:
 * 		    X Error of failed request: BadAtom (invalid Atom parameter)
 * 		    Major opcode of failed request:  18 (X_ChangeProperty)
 * 	[1993/07/28  21:46:31  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:40  Lynda_Rice
 * 	Motif 1.2 Support
 * 	[1993/06/24  20:21:17  Lynda_Rice]
 * 
 * Revision 1.1.2.4  1993/01/05  17:26:48  Don_Haney
 * 	Implement HyperHelp and mnemonics
 * 	[92/12/31  14:52:35  Don_Haney]
 * 
 * Revision 1.1.2.3  92/11/25  08:10:26  Russ_Kuhn
 * 	Added check for no files or directory specified
 * 	[92/11/25  08:08:46  Russ_Kuhn]
 * 
 * Revision 1.1.2.2  92/08/03  09:48:59  Dave_Hill
 * 	initial port to alpha
 * 	[92/08/03  09:38:45  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: mainmenucbs.c,v 1.4 1995/06/07 13:43:36 campbell 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
 *
 *	mainmenucbs.c - main menu call backs 
 *
 *	Author:	Laurence P. G. Cable
 *
 *	Created : 29th April 1988
 *
 *
 *	Description
 *	-----------
 *
 *
 *	Modification History
 *	------------ -------
 *	
 */

static char sccsid[] = "@(#)mainmenucbs.c	1.9	10:38:02 7/19/88";

#include <sys/types.h>
//#ifdef WIN32
//#define stat _stat
//#endif WIN32
#ifndef WIN32
#include <sys/stat.h>
#endif WIN32

#ifdef  DEBUG
#include <stdio.h>
#endif  /* DEBUG */
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#ifdef I18N_MULTIBYTE
#include <DXm/DECspecific.h>
#endif /* I18N_MULTIBYTE */
#include <DXm/DXmHelpB.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 "mainmenu.h"

#ifdef WIN32 
#include <excpt.h>
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#endif WIN32

#ifdef HYPERHELP
extern	Opaque	help_context;
extern	void	help_error();
extern	Widget	toplevel;
#endif


/********************** Private Routines ************************/


/*******************************
 *******************************
 **
 ** Main Menu 'Files' menu callbacks
 **
 *******************************
 *******************************/


/********************************
 *
 *      OpenFilesActivateCallback
 *
 ********************************/

#define	DXWMAGIC	24	/* dimensions of dxwm window decoration + a bit!*/

static void
_OpenFileSelectorsFromCallBack(dxdiffdisplay)
	register DxDiffDisplayPtr dxdiffdisplay;
{
	if (DxDiffDisplayPtrLFileSelector(dxdiffdisplay) == (FileSelectorPtr)NULL ||
	    DxDiffDisplayPtrRFileSelector(dxdiffdisplay) == (FileSelectorPtr)NULL) {
		Arg		args[2];
		Dimension	x,y;
#ifdef I18N_MULTIBYTE
		MrmCode type;
		XmString cs_leftfileselector, cs_rightfileselector;
		XmString cs_leftfilelabel, cs_rightfilelabel;

		/* Fetch left and right fileselectors and filelabels from UID */
		MrmFetchLiteral(dxdiff_hierarchy, "k_leftfileselector",
			XtDisplay(toplevel), &cs_leftfileselector, &type);
		MrmFetchLiteral(dxdiff_hierarchy, "k_leftfilelabel",
			XtDisplay(toplevel), &cs_leftfilelabel, &type);
		MrmFetchLiteral(dxdiff_hierarchy, "k_rightfileselector",
			XtDisplay(toplevel), &cs_rightfileselector, &type);
		MrmFetchLiteral(dxdiff_hierarchy, "k_rightfilelabel",
			XtDisplay(toplevel), &cs_rightfilelabel, &type);
#endif /* I18N_MULTIBYTE */

		DxDiffDisplayPtrLFileSelector(dxdiffdisplay) = (FileSelectorPtr)
			CreateFileSelector(MainADBPtrParent(DxDiffDisplayPtrDisplayADB(dxdiffdisplay)),
#ifdef I18N_MULTIBYTE
					   /* Don't hardcode file selector and
					      label inside source program. 
					   */
					   cs_leftfileselector,
					   cs_leftfilelabel,
#else
					   "leftfileselector",
					   "Left File",
#endif  /* I18N_MULTIBYTE */
					   (CoreArgListPtr)NULL,
					   (DialogBoxArgListPtr)NULL,
					   dxdiffdisplay,
					   dxdiffdisplay
		       );

		args[0].name = XmNx; args[0].value = (XtArgVal)&x;
		args[1].name = XmNy; args[1].value = (XtArgVal)&y;

		XtGetValues(XtParent(FileSelectorPtrFileSelector(DxDiffDisplayPtrLFileSelector(dxdiffdisplay))), args, 2);
		
		DxDiffDisplayPtrRFileSelector(dxdiffdisplay) = (FileSelectorPtr)
			CreateFileSelector(MainADBPtrParent(DxDiffDisplayPtrDisplayADB(dxdiffdisplay)),
#ifdef I18N_MULTIBYTE
					   /* Don't hard-code file selector
					      and label inside source program.
					   */
					   cs_rightfileselector,
					   cs_rightfilelabel,
#else
					   "rightfileselector",
					   "Right File",
#endif /* I18N_MULTIBYTE */
					   (CoreArgListPtr)NULL,
					   (DialogBoxArgListPtr)NULL,
					   dxdiffdisplay,
					   dxdiffdisplay
		       );

		args[0].value = x + DXWMAGIC;
		args[1].value = y + DXWMAGIC;

		XtSetValues(XtParent(FileSelectorPtrFileSelector(DxDiffDisplayPtrRFileSelector(dxdiffdisplay))), args, 2); /* offset it ! */
	} else {	/* they are unmapped */
		XtManageChild(FileSelectorPtrFileSelector(DxDiffDisplayPtrLFileSelector(dxdiffdisplay)));
		XtManageChild(FileSelectorPtrFileSelector(DxDiffDisplayPtrRFileSelector(dxdiffdisplay)));
	}

}

static VoidProc
OpenFilesActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
	_OpenFileSelectorsFromCallBack((DxDiffDisplayPtr)clientd);
}

XtCallbackRec	OpenFilesCallbackList[] = {
			{ (XtCallbackProc)OpenFilesActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};


/********************************
 *
 *      ViewNextPrevActivateCallback
 *
 ********************************/

#ifdef	VIEWBTNS
static VoidProc
ViewNextPrevActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"ViewNextPrevActivateCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	ViewNextPrevCallbackList[] = {
			{ ViewNextPrevActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};
#endif



/********************************
 *
 *      QuitActivateCallback
 *
 ********************************/

static VoidProc
QuitActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
	extern	 DxDiffDisplayPtr maindxdiffdisplay;

	DxDiffDisplayPtr display = (DxDiffDisplayPtr)clientd;

#ifdef	DEBUG
	fprintf(stderr,"QuitActivateCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */

#ifdef HYPERHELP
	if(display == maindxdiffdisplay)
		DXmHelpSystemClose(help_context, help_error, "Help System Error");
#endif

	XtDestroyWidget(MainADBPtrParent(DxDiffDisplayPtrMainADB(display)));
	DxDiffDisplayDestroyed(display);
}

XtCallbackRec	QuitCallbackList[] = {
			{ (XtCallbackProc)QuitActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};



#ifdef	SEARCH
/*******************************
 *******************************
 **
 ** Main Menu 'Search' menu callbacks
 **
 *******************************
 *******************************/


/********************************
 *
 *      SetREActivateCallback
 *
 ********************************/

static VoidProc
SetREActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"SetREActivateCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	SetRECallbackList[] = {
			{ SetREActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};




/********************************
 *
 *      FindNextPrevActivateCallback
 *
 ********************************/

static VoidProc
FindNextPrevActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"FindNextPrevActivateCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	FindNextPrevCallbackList[] = {
			{ FindNextPrevActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};




/********************************
 *
 *      SearchLeftRightActivateCallback
 *
 ********************************/

static VoidProc
SearchLeftRightActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"SearchLeftRightActivateCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	SearchLeftRightCallbackList[] = {
			{ SearchLeftRightActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};
#endif	/* SEARCH */



/*******************************
 *******************************
 **
 ** Main Menu 'Options' menu callbacks
 **
 *******************************
 *******************************/


/********************************
 *
 *      SlaveVerticalScrollActivateCallback
 *
 ********************************/

static VoidProc
SlaveVerticalScrollActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
	register DxDiffDisplayPtr dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	DifferenceBoxPtr	  differencebox = DiffRegionADBPtrDifferenceBox(DxDiffDisplayPtrDiffRegionADB(dxdiffdisplay));
	AMenuBarPtr		  mainmenubar = DxDiffDisplayPtrMenuBar(dxdiffdisplay);
	PullDownEntryPtr	  pulldown =  
		(PullDownEntryPtr)MenuEntryPtrPullDown(
			AMenuBarPtrEntries(mainmenubar)[(int)OptionsButton]);
	PullDownMenuEntryPtr	  pulldownentry = PullDownEntryPtrPullDownMenuEntry(pulldown);
	PushButtonEntryPtr	  pushbutton = PullDownMenuEntryPtrPushButtons(pulldownentry)[(int)SlaveScrollVButton];

	if (differencebox->scrollmode == ScrollBoth) {
		SetDifferenceBoxScrollingMode(differencebox, ScrollOnlyOne);
		SetPushButtonToMainLabel(pushbutton);
	} else {
		if (differencebox->scrollmode == ScrollOnlyOne) {
			WhichFile	whichfile = (differencebox->lastscrolled == LeftFile) ? RightFile: LeftFile;
			TextDisplayPtr	text;
			HVScrollBarPtr	scrollbar;
			int		*top, lasttop;

			if (whichfile == LeftFile) {
				text = TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay));
				scrollbar = TextDisplayADBPtrVScroll(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay));
				lasttop = *(top = &differencebox->toplnolf);
			} else {
				text = TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrRightTextADB(dxdiffdisplay));
				scrollbar = TextDisplayADBPtrVScroll(DxDiffDisplayPtrRightTextADB(dxdiffdisplay));
				lasttop = *(top = &differencebox->toplnorf);
			}

			SetDifferenceBoxScrollingMode(differencebox, ScrollBoth);	/* will cause slave scroll */
		
			_XmTextDisableRedisplay(TextDisplayPtrWidget(text), False);
			XmTextScroll(TextDisplayPtrWidget(text), *top - lasttop);

			UpdateTextHighLights(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)),
					     TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)),
					     differencebox);

			_XmTextEnableRedisplay(TextDisplayPtrWidget(text));

			SetPushButtonToAlternativeLabel(pushbutton);
		}
	}
}

XtCallbackRec	SlaveVerticalScrollCallbackList[] = {
			{ (XtCallbackProc)SlaveVerticalScrollActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};


/********************************
 *
 *      SlaveHorizontalScrollActivateCallback
 *
 ********************************/

static VoidProc
SlaveHorizontalScrollActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
	register DxDiffDisplayPtr dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	AMenuBarPtr		  mainmenubar = DxDiffDisplayPtrMenuBar(dxdiffdisplay);
	PullDownEntryPtr	  pulldown =  (PullDownEntryPtr)MenuEntryPtrPullDown(AMenuBarPtrEntries(mainmenubar)[(int)OptionsButton]);
	PullDownMenuEntryPtr	  pulldownentry = PullDownEntryPtrPullDownMenuEntry(pulldown);
	PushButtonEntryPtr	  pushbutton = PullDownMenuEntryPtrPushButtons(pulldownentry)[(int)SlaveScrollHButton];

	if (DxDiffDisplayPtrHorizontalSlaveScroll(dxdiffdisplay)) {
		DxDiffDisplayPtrHorizontalSlaveScroll(dxdiffdisplay) = False;
		SetPushButtonToMainLabel(pushbutton);
	} else { 
		HVScrollBarPtr	scrollbar;
		XmScrollBarCallbackStruct cbs;
		Arg arg[1];
		
		DxDiffDisplayPtrHorizontalSlaveScroll(dxdiffdisplay) = True;
		SetPushButtonToAlternativeLabel(pushbutton);
		if (DxDiffDisplayPtrHorizontalScrolledLast(dxdiffdisplay) == LeftFile)
		    scrollbar = TextDisplayADBPtrHScroll(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay));
		else
		    scrollbar = TextDisplayADBPtrHScroll(DxDiffDisplayPtrRightTextADB(dxdiffdisplay));
		XtSetArg(arg[0], XmNvalue, &cbs.value);			
		XtGetValues((Widget)scrollbar, arg, 1);
		DoHorizontalScrollingFromCallBack(scrollbar, clientd, &cbs);
	}
}

XtCallbackRec	SlaveHorizontalScrollCallBackList[] = {
			{(XtCallbackProc) SlaveHorizontalScrollActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};


/********************************
 *
 *      DiffRenderModeActivateCallback
 *
 ********************************/

static VoidProc
DiffRenderModeActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
	register DxDiffDisplayPtr dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	DifferenceBoxPtr	  differencebox = DiffRegionADBPtrDifferenceBox(DxDiffDisplayPtrDiffRegionADB(dxdiffdisplay));
	AMenuBarPtr		  mainmenubar = DxDiffDisplayPtrMenuBar(dxdiffdisplay);
	PullDownEntryPtr	  pulldown = (PullDownEntryPtr) MenuEntryPtrPullDown(AMenuBarPtrEntries(mainmenubar)[(int)OptionsButton]);
	PullDownMenuEntryPtr	  pulldownentry = PullDownEntryPtrPullDownMenuEntry(pulldown);
	PushButtonEntryPtr	  pushbutton = PullDownMenuEntryPtrPushButtons(pulldownentry)[(int)RenderDiffsButton];

	if (differencebox->drawdiffsas == DrawDiffsAsLines) {
		SetDifferenceBoxPaintingStyle(differencebox, DrawDiffsAsFilledPolygons);
		SetPushButtonToMainLabel(pushbutton);
	} else {
		if (differencebox->drawdiffsas == DrawDiffsAsFilledPolygons) {
			SetDifferenceBoxPaintingStyle(differencebox, DrawDiffsAsLines);
			SetPushButtonToAlternativeLabel(pushbutton);
		}
	}
}

XtCallbackRec	DiffRenderModeCallbackList[] = {
			{(XtCallbackProc) DiffRenderModeActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};




/********************************
 *
 *      RenderLinesNumberingActivateCallback
 *
 ********************************/

static VoidProc
RenderLineNumberingActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
	register DxDiffDisplayPtr dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	DifferenceBoxPtr	  differencebox = DiffRegionADBPtrDifferenceBox(DxDiffDisplayPtrDiffRegionADB(dxdiffdisplay));
	AMenuBarPtr		  mainmenubar = DxDiffDisplayPtrMenuBar(dxdiffdisplay);
	PullDownEntryPtr	  pulldown =  (PullDownEntryPtr)MenuEntryPtrPullDown(AMenuBarPtrEntries(mainmenubar)[(int)OptionsButton]);
	PullDownMenuEntryPtr	  pulldownentry = PullDownEntryPtrPullDownMenuEntry(pulldown);
	PushButtonEntryPtr	  pushbutton = PullDownMenuEntryPtrPushButtons(pulldownentry)[(int)RenderLineNumbersButton];

	if (differencebox->linenumbers) {
		SetDifferenceBoxDisplayLineNumbers(differencebox, False);
		SetPushButtonToMainLabel(pushbutton);
	} else {
		SetDifferenceBoxDisplayLineNumbers(differencebox, True);
		SetPushButtonToAlternativeLabel(pushbutton);
	}
}


XtCallbackRec	RenderLineNumberingCallbackList[] = {
			{(XtCallbackProc) RenderLineNumberingActivateCallback, 0 },
			{ (VoidProc)NULL, 0}
		};




/*******************************
 *******************************
 **
 ** Main Menu 'Differences' menu callbacks
 **
 *******************************
 *******************************/



/********************************
 *
 *      DoDifferencesActivateCallback
 *
 ********************************/

static void
_DoDifferencesFromCallBack(dxdiffdisplay, lfile, rfile)
  register DxDiffDisplayPtr dxdiffdisplay;
  char 	*lfile, *rfile;
{
#ifndef WIN32
    struct stat statBuf;
    int ok;
#else 
    HANDLE hFile;
#endif WIN32

    Boolean fspresent = (DxDiffDisplayPtrLFileSelector(dxdiffdisplay) != 
			 (FileSelectorPtr)NULL);

#ifdef I18N_MULTIBYTE
	long byte_count;
	long status;
	XmString null_cs;
	Display *dpy = XtDisplay(toplevel);
	MrmCode type;
	XmString error;

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

    if (lfile == (char *)NULL) {
#ifdef I18N_MULTIBYTE
	/* fileselector pointer "file" has changed type to XmString and hence
	   must use converter to change it back to file code first.
	*/
	if (fspresent && FileSelectorPtrFile(
		DxDiffDisplayPtrLFileSelector(dxdiffdisplay)) != null_cs) {
			lfile = DXmCvtCStoFC(FileSelectorPtrFile(
			  	DxDiffDisplayPtrLFileSelector(dxdiffdisplay)),
				&byte_count, &status);
#else
	if (fspresent && 
	        FileSelectorPtrFile(DxDiffDisplayPtrLFileSelector(
					      dxdiffdisplay)) != (char *)NULL) {
	    lfile = FileSelectorPtrFile(DxDiffDisplayPtrLFileSelector(
								dxdiffdisplay));
#endif  /* I18N_MULTIBYTE */
	} else {	/* none selected - use the current file */
	    lfile = FileNamePtrFile(TextDisplayADBPtrFilename(
                              DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)));
	}
    }

    if (rfile == (char *)NULL) {
#ifdef I18N_MULTIBYTE
	/* fileselector pointer "file" has changed type to XmString and hence
	   must use converter to change it back to file code first.
	*/
	if (fspresent && FileSelectorPtrFile(
		DxDiffDisplayPtrRFileSelector(dxdiffdisplay)) != null_cs) {
			rfile = DXmCvtCStoFC(FileSelectorPtrFile(
				DxDiffDisplayPtrRFileSelector(dxdiffdisplay)),
				&byte_count, &status);
#else
	if (fspresent && FileSelectorPtrFile(DxDiffDisplayPtrRFileSelector(
                dxdiffdisplay)) != (char *)NULL) {
	    rfile = FileSelectorPtrFile(DxDiffDisplayPtrRFileSelector(
                                        dxdiffdisplay));
#endif  /* I18N_MULTIBYTE */
	} else {	/* none selected - use the current file */
	    rfile = FileNamePtrFile(TextDisplayADBPtrFilename(
                       DxDiffDisplayPtrRightTextADB(dxdiffdisplay)));
	}
    }


    if (lfile == NULL) {
#ifdef I18N_MULTIBYTE
	/* Don't hard-code error message inside source program */
	MrmFetchLiteral(dxdiff_hierarchy, "k_no_left_file",
			dpy, &error, &type);
#endif  /* I18N_MULTIBYTE */
	CreateMessageBox(MainADBPtrWidget(DxDiffDisplayPtrMainADB(
                                                            dxdiffdisplay)),
			 "dxdiffdisplayerror", (CoreArgListPtr)NULL,
			 (DialogBoxArgListPtr)NULL, (LabelArgListPtr)NULL,
#ifdef I18N_MULTIBYTE
			 error, NULL);
#else
			 "Please specify a left file", NULL );
#endif  /* I18N_MULTIBYTE */
	return;
    }

    if (rfile == NULL) {
#ifdef I18N_MULTIBYTE
	/* Don't hard-code error message inside source program */
	MrmFetchLiteral(dxdiff_hierarchy, "k_no_right_file",
			 dpy, &error, &type);
#endif  /* I18N_MULTIBYTE */
	CreateMessageBox(MainADBPtrWidget(DxDiffDisplayPtrMainADB(
                                                            dxdiffdisplay)),
			 "dxdiffdisplayerror", (CoreArgListPtr)NULL,
			 (DialogBoxArgListPtr)NULL, (LabelArgListPtr)NULL,
#ifdef I18N_MULTIBYTE
			 error, NULL);
#else
			 "Please specify a right file", NULL );
#endif /* I18N_MULTIBYTE */
	return;
    }

    /* Check for directories */
	 
#ifdef WIN32
	if (FILE_ATTRIBUTE_DIRECTORY == GetFileAttributes(lfile)) {
#else
    ok = stat( lfile, &statBuf );	/* Get file status */
    if (! (statBuf.st_mode & S_IFREG)) {
#endif WIN32
#ifdef I18N_MULTIBYTE
	/* Don't hard-code error message inside source program */
	MrmFetchLiteral(dxdiff_hierarchy, "k_left_file_not_regular",
			dpy, &error, &type);
#endif /* I18N_MULTIBYTE */
	CreateMessageBox(MainADBPtrWidget(DxDiffDisplayPtrMainADB(
                                                            dxdiffdisplay)),
			 "dxdiffdisplayerror", (CoreArgListPtr)NULL,
			 (DialogBoxArgListPtr)NULL, (LabelArgListPtr)NULL,
#ifdef I18N_MULTIBYTE
 			 error, NULL);
#else
			 "Left file is not a regular file", NULL );
#endif  /* I18N_MULTIBYTE */
	return;
    }
	
#ifdef WIN32
	if (FILE_ATTRIBUTE_DIRECTORY == GetFileAttributes(rfile)) {
#else
    ok = stat( rfile, &statBuf );	/* Get file status */
    if (! (statBuf.st_mode & S_IFREG)) {
#endif WIN32
#ifdef I18N_MULTIBYTE
	/* Don't hard-code error message inside source program */
	MrmFetchLiteral(dxdiff_hierarchy, "k_right_file_not_regular",
			 dpy, &error, &type);
#endif /* I18N_MULTIBYTE */
	CreateMessageBox(MainADBPtrWidget(DxDiffDisplayPtrMainADB(
                                                            dxdiffdisplay)),
			 "dxdiffdisplayerror", (CoreArgListPtr)NULL,
			 (DialogBoxArgListPtr)NULL, (LabelArgListPtr)NULL,
#ifdef I18N_MULTIBYTE
			 error, NULL);
#else
			 "Right file is not a regular file", NULL );
#endif  /* I18N_MULTIBYTE */
	return;
    }

    if (DoDiffs(dxdiffdisplay, lfile, rfile)) {
	LoadDiffs(dxdiffdisplay, lfile, rfile, 
		  DxDiffDisplayPtrDiffList(dxdiffdisplay)->edchead,
		  DxDiffDisplayPtrDiffList(dxdiffdisplay)->edctail);
    } else {	/* oops - error */
	ReportDiffErrors(dxdiffdisplay);
    }
}

static VoidProc
DoDifferencesActivateCallback(w, clientd, calld)
	Widget	w;	
	caddr_t	clientd;
	caddr_t	calld;
{
	_DoDifferencesFromCallBack((DxDiffDisplayPtr)clientd, (char *)NULL, (char *)NULL);
}


XtCallbackRec	DoDifferencesCallbackList[] = {
			{(XtCallbackProc) DoDifferencesActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};






/********************************
 *
 *      DoDifferencesInNewActivateCallback
 *
 ********************************/

static VoidProc
DoDifferencesInNewActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
	extern	 CoreArgList	  initcore;
	extern	 DxDiffDisplayPtr maindxdiffdisplay;

	register DxDiffDisplayPtr newdxdiffdisplay, dxdiffdisplay = (DxDiffDisplayPtr)clientd;
	char 	 *lfile, *rfile;
	Boolean	 fspresent = (DxDiffDisplayPtrLFileSelector(dxdiffdisplay) != (FileSelectorPtr)NULL);
#ifdef I18N_MULTIBYTE
	long byte_count;
	long status;
	XmString null_cs;

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

	if ((newdxdiffdisplay = (DxDiffDisplayPtr)CreateNewDxDiffDisplay(
	    (Widget)NULL, "dxdiffdisplay", &initcore)) == (DxDiffDisplayPtr)NULL) {
		return;	/* error */
	}

#ifdef I18N_MULTIBYTE
	/* fileselector pointer "file" has changed type to XmString and hence
	   must use converter to change it back to file code first.
	*/
	if (fspresent && FileSelectorPtrFile(
		DxDiffDisplayPtrLFileSelector(dxdiffdisplay)) != null_cs) {
			lfile = DXmCvtCStoFC(FileSelectorPtrFile(
				DxDiffDisplayPtrLFileSelector(dxdiffdisplay)),
				&byte_count, &status);
#else
	if (fspresent && FileSelectorPtrFile(DxDiffDisplayPtrLFileSelector(dxdiffdisplay)) != (char *)NULL) {
			lfile = FileSelectorPtrFile(DxDiffDisplayPtrLFileSelector(dxdiffdisplay));
#endif  /* I18N_MULTIBYTE */
	} else {	/* none selected - use the current file */
		lfile = FileNamePtrFile(TextDisplayADBPtrFilename(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)));
	}

#ifdef I18N_MULTIBYTE
	/* fileselector pointer "file" has changed type to XmString and hence
	   must use converter to change it back to file code first.
	*/
	if (fspresent && FileSelectorPtrFile(
		DxDiffDisplayPtrRFileSelector(dxdiffdisplay)) != null_cs) {
			rfile = DXmCvtCStoFC(FileSelectorPtrFile(
				DxDiffDisplayPtrRFileSelector(dxdiffdisplay)),
				&byte_count, &status);
#else
	if (fspresent && FileSelectorPtrFile(DxDiffDisplayPtrRFileSelector(dxdiffdisplay)) != (char *)NULL) {
			rfile = FileSelectorPtrFile(DxDiffDisplayPtrRFileSelector(dxdiffdisplay));
#endif  /* I18N_MULTIBYTE */
	} else {	/* none selected - use the current file */
		rfile = FileNamePtrFile(TextDisplayADBPtrFilename(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)));
	}
				
	_DoDifferencesFromCallBack(newdxdiffdisplay, lfile, rfile);
}

XtCallbackRec	DoDifferencesInNewCallbackList[] = {
			{ (XtCallbackProc)DoDifferencesInNewActivateCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};

XtCallbackRec	NullCallbackList[] = {
			{ (VoidProc)NULL, 0 }
		};


/*******************************
 *******************************
 **
 ** Main Menu 'Help' menu callbacks
 **
 *******************************
 *******************************/

static Widget helpDialog = NULL;
static Widget main_window = NULL;
static Widget app_shell = NULL;

static Widget
GetAppShell (client)
Widget client;
{
    Widget lastWidget = client;
    for (app_shell = client;
             app_shell &&
               (XtClass(app_shell) != (WidgetClass)topLevelShellWidgetClass); ) {
	    lastWidget = app_shell;
            app_shell = XtParent(app_shell);
    }
    if (!app_shell)
	app_shell = lastWidget;
    return app_shell;
}


/********************************
 *
 *      HelpActivateCallback
 *
 ********************************/

VoidProc
HelpActivateCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;

#ifdef HYPERHELP
{
	DXmHelpSystemDisplay(help_context, dxdiff_help, "topic", 
			     (char *) clientd, help_error, "Help System Error");
}



/*
 * Switch into context-sensitive mode and call the selected widget's
 * context-sensitive help callback.
 */

VoidProc
HelpOnContextCallback(w, clientd, calld)
	Widget  w;
	caddr_t clientd;
	caddr_t calld;

{
	DXmHelpOnContext(toplevel, FALSE);
}


/*
 * The mapping of help callbacks (both explicit and context-sensitive) to
 * the dxdiff.decw_book symbol which is appropriate for each.  This would
 * typically be in the uil files but since dxdiff has none ....
 */

XtCallbackRec	HelpMenuOnContextSymbol[] = {
			{(XtCallbackProc) HelpOnContextCallback, "help_menu_oncontext" },
			{ (VoidProc)NULL, 0 }
		};

/* Define a macro to make these mappings easier and more readable */

#define MapHelpSymbol(rec, sym)						 \
	XtCallbackRec rec[] = {						 \
			  {(XtCallbackProc) HelpActivateCallback, sym }, \
			  {(VoidProc) NULL, 0}				 \
		      };

MapHelpSymbol(VisualDiffsSymbol, "visual_diffs");
MapHelpSymbol(HelpMenuSymbol, "help_menu");
MapHelpSymbol(HelpOnContextSymbol, "help_menu_oncontext");
MapHelpSymbol(AboutSymbol, "about");
MapHelpSymbol(SelectFilesSymbol, "select_files");
MapHelpSymbol(ChangeCharsSymbol, "change_chars");
MapHelpSymbol(DisplayDiffsSymbol, "display_diffs");
MapHelpSymbol(DiffExitSymbol, "diff_exit");
MapHelpSymbol(CompareNewSymbol, "compare_new");
MapHelpSymbol(MovingBetweenSymbol, "moving_between");

#else

{
	static XmString help_librarySpec = (XmString) NULL;
	static XmString help_applicationName;
	static XmString topic;
	Arg help_args[5];
	int ac = 0;

#ifdef	DEBUG
	fprintf(stderr,"HelpActivateCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
	if (!help_librarySpec) {
#ifdef WIN32
            {
                char * InstalledDirPnt ;
                char * HelpLibPnt ;
                
                HelpLibPnt = malloc(MAX_PATH) ;
                InstalledDirPnt = _XGetInstalledLocation();
                strcpy (HelpLibPnt, InstalledDirPnt);
                XFree(InstalledDirPnt);
                strcat(HelpLibPnt, "\\lib\\x11\\help\\dxdiff");
	        help_librarySpec = XmStringCreateSimple(HelpLibPnt);
	        free(HelpLibPnt);
	    }
#else	    
	    help_librarySpec = XmStringCreateSimple("/usr/lib/X11/help/dxdiff");
#endif
	    help_applicationName = XmStringCreateSimple("dxdiff");
	}
	if (clientd == NULL) {
	    topic = XmStringCreateSimple("About");
	} else {
	    topic = XmStringCreateSimple(clientd);
	}

	XtSetArg(help_args[ac], DXmNfirstTopic, topic);ac++;
	XtSetArg(help_args[ac], DXmNlibrarySpec, help_librarySpec);ac++;
	XtSetArg(help_args[ac], DXmNlibraryType, DXmTextLibrary);ac++;
	XtSetArg(help_args[ac], DXmNapplicationName, help_applicationName);ac++;
	if (!helpDialog) {
	    (void) GetAppShell(w);
	    DXmInitialize();
	    helpDialog = DXmCreateHelpDialog(app_shell, "helpDialog",
						help_args, ac);
	}

	if (helpDialog) {
	    XtSetValues(helpDialog, help_args, ac);
	    XtManageChild(helpDialog);
	}
	XmStringFree(topic);
}

XtCallbackRec	HelpCallbackList[] = {
			{(XtCallbackProc) HelpActivateCallback, "About" },
			{ (VoidProc)NULL, 0 }
		};

#endif  /* HYPERHELP */



/*******************************
 *******************************
 **
 ** Main Menu Pull Down menu callbacks
 **
 *******************************
 *******************************/


/********************************
 *
 *      FilesPullDownCallback
 *
 ********************************/

static VoidProc
FilesPullDownCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"FilesPullDownCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	FilesPullDownCallbackList[] = {
			{(XtCallbackProc) FilesPullDownCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};


/********************************
 *
 *      SearchPullDownCallback
 *
 ********************************/

#ifdef	SEARCH
static VoidProc
SearchPullDownCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"SearchPullDownCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	SearchPullDownCallbackList[] = {
			{ SearchPullDownCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};
#endif


/********************************
 *
 *      OptionsPullDownCallback
 *
 ********************************/

static VoidProc
OptionsPullDownCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"OptionsPullDownCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	OptionsPullDownCallbackList[] = {
			{(XtCallbackProc) OptionsPullDownCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};


/********************************
 *
 *      DifferencesPullDownCallback
 *
 ********************************/

static VoidProc
DifferencesPullDownCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"DifferencesPullDownCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	DifferencesPullDownCallbackList[] = {
			{(XtCallbackProc) DifferencesPullDownCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};

#ifdef HYPERHELP

/********************************
 *
 *      HelpPullDownCallback
 *
 ********************************/

static VoidProc
HelpPullDownCallback(w, clientd, calld)
	Widget	w;
	caddr_t	clientd;
	caddr_t	calld;
{
#ifdef	DEBUG
	fprintf(stderr,"HelpPullDownCallback(0x%x, 0x%x, 0x%x)\n",
	        w, clientd, calld);
#endif	/* DEBUG */
}

XtCallbackRec	HelpPullDownCallbackList[] = {
			{(XtCallbackProc) HelpPullDownCallback, 0 },
			{ (VoidProc)NULL, 0 }
		};

#endif
