/*
 * @DEC_COPYRIGHT@
 */
/*
 * HISTORY
 * Revision 1.2  1995/03/09  21:49:08  bourquard
 * port to NT
 *
 *
 * Revision 1.1  90/01/01  00:00:00  devrcs
 * Initial load into Alpha pool
 * 
 * Revision 1.2  91/12/30  12:48:20  devbld
 * Initial load of project
 * 
 */
/*
 * 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
 *
 *	dodiff.c - load up the display
 *
 *	Author:	Laurence P. G. Cable
 *
 *	Created : 31st May 1988
 *
 *
 *	Description
 *	-----------
 *
 *
 *	Modification History
 *	------------ -------
 *	
 *	06 Aug 1990	Colin Prosser
 *
 *	Fix storage allocation bugs and portability problems.
 *	Cures seg fault reported in UWS QAR 02624.
 *
 *
 *	02/22/94	Dhiren M. Patel
 *	Fix ootb_bug 466. Routine LoadDiffs(). The code was freeing
 *	memory space pointed to by two pointers. The contents of one
 *	were to be copied to another, but as an effect of freeing one
 *	of the pointers the data was being lost. As a remedy, made a
 *	copy of the contents and then supplied a new pointer to the 
 *	routine which frees memory.
 *
 */

static char sccsid[] = "@(#)dodiff.c	2.2";
 
#ifdef  DEBUG
#include <stdio.h>
#endif  DEBUG
#include <X11/Xlib.h>
#ifdef WIN32
#include <X11/xfuncs.h>
#endif WIN32
#include <Xm/Xm.h>

#include <sys/types.h>
#include <sys/stat.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 "displaymenu.h"

#ifndef WIN32
static char *diffcmd[] = { 
	"/usr/sh",
    "sh",
	"-c",
	"/usr/bin/diff $DxDiffLeftFile $DxDiffRightFile",
	(char *)NULL
};
#else
static char *diffcmd[] = { 
    "diff ",
	(char *)NULL
};
#endif WIN32

#ifdef I18N_MULTIBYTE

/*****************************************************************************
 *
 * LocateDiff - locate multibyte "diff" image. This is for backward 
 *		compatibility with UWS. The standard "diff" image of UWS
 *		is located in "/usr/bin/diff" and this image would not work
 *		for multibyte support. The I18N "diff" image is located in
 *		"/usr/i18n/bin/diff" instead and we would use the resource
 *		DxDiff.diffpath to store the location. This resource is
 *		not found in the standard resource file DxDiff.
 *
 * parameters : none
 *
 * return values : none
 *
 *****************************************************************************/

void LocateDiff(void)
{
	XrmDatabase database;
	char *str_type_return;
	XrmValue value_return;

	XrmInitialize();
	database = XrmGetDatabase(XtDisplay(toplevel));
	if (database != NULL) 
		/* Obtain the resource DxDiff.diffpath from DxDiff. This 
		   resource is only found in asian resource files. The current
		   value is "/usr/i18n/bin/diff".
		*/
		if (XrmGetResource(database, "DxDiff.diffpath", NULL, 
			&str_type_return, &value_return) == True) {
			
			/* Search the existence of diff (usually an I18N diff)
		       specified in DxDiff.diffpath. If it exists, 
			   use this else fallback to use /usr/bin/diff */
			if (fopen(value_return.addr, "r") != NULL){
				XtFree(diffcmd[3]);
				/* Update diffcmd[3] with the new image location
				*/
				diffcmd[3] = (char *)malloc(strlen(value_return.addr) +
					strlen(" $DxDiffLeftFile $DxDiffRightFile"));
				sprintf(diffcmd[3], "%s%s", value_return.addr,
					" $DxDiffLeftFile $DxDiffRightFile");
			}
		}
}
#endif /* I18N_MULTIBYTE */
				
/********************************
 *
 *     DoDiffs
 *
 ********************************/

Boolean
DoDiffs(display, lfile, rfile)
	DxDiffDisplayPtr display;
	char		 *lfile, 
			 *rfile;
{
	
	if (DxDiffDisplayPtrDiffList(display) != (DiffListBlkPtr)NULL) {
		FileInfoPtr filep, *filepp;
		
		filep = *(filepp = &TextDisplayPtrFile(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrLeftTextADB(display))));
		if (filep != (FileInfoPtr)NULL) {
			FreeFile(filep);
			*filepp = (FileInfoPtr)NULL;
		}

		filep = *(filepp = &TextDisplayPtrFile(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrRightTextADB(display))));
		if (filep != (FileInfoPtr)NULL) {
			FreeFile(filep);
			*filepp = (FileInfoPtr)NULL;
		}

		InitDiffListBlk(DxDiffDisplayPtrDiffList(display)); /* free it */
		XtFree((char *)DxDiffDisplayPtrDiffList(display));
	}

	if ((DxDiffDisplayPtrDiffList(display) = (DiffListBlkPtr)XtMalloc(sizeof (DiffListBlk))) ==
	    (DiffListBlkPtr)NULL) {
		return False;	/* error */
	} else {
		bzero((char *)DxDiffDisplayPtrDiffList(display), sizeof (DiffListBlk));

		if ((DxDiffDisplayPtrDiffList(display)->caches = (BackEndCachePtr)XtMalloc(sizeof (BackEndCache))) ==
		    (BackEndCachePtr)NULL) {
			XtFree((char *)DxDiffDisplayPtrDiffList(display));
			return False;
		} else {
			DxDiffDisplayPtrDiffList(display)->caches->cachesempty = True;
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->nssc), 50);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->edcsc), 400);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->dflsc), 50);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->bfnsc), 10);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->cfnsc), 10);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->ofnsc), 10);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->ifnsc), 10);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->densc), 10);
			InitializeStoreCache(&(DxDiffDisplayPtrDiffList(display)->caches->dcnsc), 10);
		}
	}

#ifdef I18N_MULTIBYTE
	/* Locate the I18N image location for "diff" and update "diffcmd" with
	   the new location.
	*/
	LocateDiff();
#endif /* I18N_MULTIBYTE */

	return InvokeDiff(diffcmd, lfile, rfile, DxDiffDisplayPtrDiffList(display));
}
	
/********************************
 *
 *     LoadDiffs
 *
 ********************************/

LoadDiffs(dxdiffdisplay, lfile, rfile, edcph, edcpt)
		DxDiffDisplayPtr dxdiffdisplay;
		char		 *lfile, 
				 *rfile;
		EdcPtr		 edcph,
				 edcpt;
{
	Arg		args[4];
	unsigned short	numlines, txtnumlines;
	AMenuBarPtr	menubar;
	CoreArgListPtr	core;
	unsigned int	inc;

/* dp:	fix ootb_bug 466 
 *	SetFileName () frees both (one on each call)
 *	TextDisplayADBPtrFilename(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)),
 *	TextDisplayADBPtrFilename(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)).
 *	If the user does a "Do Differences" just after loading the files
 *	from command line; e.g. "dxdiff foo blah", rfile and lfile have the 
 *	same addresses as 
 *	TextDisplayADBPtrFilename(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)) &
 *	TextDisplayADBPtrFilename(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay))
 *	respectively. Hence it is necessary to supply copies of the pointers.
 */
	char *l_file, *r_file;

	l_file = (char *) XtMalloc(strlen(lfile) + 1);
	strcpy(l_file, lfile);
	r_file = (char *) XtMalloc(strlen(rfile) + 1);
	strcpy(r_file, rfile);

	SetFileName(TextDisplayADBPtrFilename(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)), r_file);
	SetFileName(TextDisplayADBPtrFilename(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)), l_file);
	SetFileNameHighLight(TextDisplayADBPtrFilename(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)), True);
	SetFileNameHighLight(TextDisplayADBPtrFilename(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)), True);

	SetFileNameSensitivity(TextDisplayADBPtrFilename(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)), True);
	SetFileNameSensitivity(TextDisplayADBPtrFilename(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)), True);

	LoadTextDisplay(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)), r_file);

	LoadTextDisplay(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)), l_file);

	InitializeHighLightInfo(TextDisplayPtrFile(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrRightTextADB(dxdiffdisplay))),
				edcph, 
				edcpt,
				0, RightFile);

	InitializeHighLightInfo(TextDisplayPtrFile(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay))),
				edcph, 
				edcpt,
				0, LeftFile);


	ReLoadDifferenceBox(DiffRegionADBPtrDifferenceBox(DxDiffDisplayPtrDiffRegionADB(dxdiffdisplay)),
			     edcph, 
			     edcpt,
			     TextDisplayPtrFile(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)))->numlines,
			     TextDisplayPtrFile(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)))->numlines

	);

	menubar = TextDisplayADBPtrMenuBar(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay));
	SetPushButtonSensitivity(MenuEntryPtrPushButton(AMenuBarPtrEntries(menubar)[(int)NextDiffButton]), True);
	SetPushButtonSensitivity(MenuEntryPtrPushButton(AMenuBarPtrEntries(menubar)[(int)PrevDiffButton]), True);
	
	menubar = TextDisplayADBPtrMenuBar(DxDiffDisplayPtrRightTextADB(dxdiffdisplay));
	SetPushButtonSensitivity(MenuEntryPtrPushButton(AMenuBarPtrEntries(menubar)[(int)NextDiffButton]), True);
	SetPushButtonSensitivity(MenuEntryPtrPushButton(AMenuBarPtrEntries(menubar)[(int)PrevDiffButton]), True);

	if (DiffRegionADBPtrDifferenceBox(DxDiffDisplayPtrDiffRegionADB(dxdiffdisplay))->vdtop != (EdcPtr)NULL) {
		UpdateTextHighLights(TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrLeftTextADB(dxdiffdisplay)),
				     TextDisplayADBPtrTextDisplay(DxDiffDisplayPtrRightTextADB(dxdiffdisplay)),
				     DiffRegionADBPtrDifferenceBox(DxDiffDisplayPtrDiffRegionADB(dxdiffdisplay)));
	}
}
