/* Program Name            : FILERDIF.C                                 */
/*   Original Author       : C. K. Hung					*/
/*   Date                  : 18-MAY-1991				*/
/*   Program Description   :                                            */
/*                         :                                            */
/* Revision History follows                                             */
 
#include "global.h"
#include "diff.h"
#include "dx.h"
#include "filer.h"
#include "filerdif.h"
#include "inquire.h"
#include <libclidef.h>
#include <signal.h>
 
/* ****  INTERNAL FUNCTION PROTOTYPING *** */
 
static int		    filer_diff$2(char *, char *, char *);
static int		    diff_read(TXTINF f[], int *n, char *m, char *dna, char *errmsg);
 
 
 
/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      tbs
**
**--
**/
int	filer_diff()
{
    if (DX_CURRENT_DIRECTORY.filemode == multiple)
	filer_multiple_diff();
    else
	filer_single_diff();
    return DX__NORMAL;
}
 
 
/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_multiple_diff()
{
    char errmsg[MAXFILESPEC+1];
 
    strcpy(errmsg, "Error comparing file");
    multi_get_userinput_and_exec(
	filer_diff$1,
	"Multiple diff",
	"Compare with: ",
	"",
	errmsg);
    return DX__NORMAL;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_single_diff()
{
    char errmsg[MAXFILESPEC+1];
    char fn[MAXFILESPEC+1];
 
    if (!strcmp(DX_CURRENT_FILE->fn, "[-]"))
    {
        signal_err("Compare a parent directory file not allowed", bell);
    }
    else
    {
	find_full_path_name(DX_CURRENT_FILE->fn, fn, cntrl_info_block.cur_win);
	strcpy(errmsg, "Error comparing file");
	get_userinput_and_execute(
	    filer_diff$1,
	    "Compare File",
	    "Compare with: ",
	    "",
	    errmsg,
	    fn);
    }
    return DX__NORMAL;
}
 
 
/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_diff$1(to, from, errmsg)
char *to;
char *from;
char *errmsg;
{
    return filer_diff$2(from, to, errmsg);
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
static int	filer_diff$2(from, old_to, errmsg)
char *from;
char *old_to;
char *errmsg;
{
    TXTINF file1[MAXLINES];
    int n1;
    TXTINF file2[MAXLINES];
    int n2;
    unsigned long int display_id;
    unsigned short word_terminator_code;
    char result_string[255];
    $DESCRIPTOR (result_string_descrip, result_string);
    int i;
    int vm_len;
    unsigned long old_mask;
    char to[MAXFILESPEC+1];
 
    /*
    **	Do not update the user-specified diff TO filespec
    **/
 
    strcpy(to, old_to);
 
    /*
    **	Read two files to be compared
    **/
 
    if (diff_read (file1, &n1, from, from, errmsg) == -1  ||
	diff_read (file2, &n2, to, from, errmsg) == -1)
    {
	return DX__ERROR;
    }
 
    /*
    **	Since compare() does not use SMG$ output routines to
    **	show the differences, need to save the current display
    **	and restore back after the comparison.
    **/
 
    check_OK(smg$save_physical_screen (
		&cntrl_info_block.pasteboard_id,
		&display_id,
		0,
		0))
 
    check_OK(smg$set_physical_cursor (
	      &cntrl_info_block.pasteboard_id,
	      &cntrl_info_block.pasteboard_rows,
	      &1))
 
    /*
    **	Set the signal back to system default so that it won't
    **	interfere with smg$read_keystroke() routine.
    **/
 
    alarm(0);
    signal(SIGALRM, SIG_DFL);
 
    fprintf (stdout, "DX File Comparison Utility\n");
    fprintf (stdout, "    %s-\n", from);
    fprintf (stdout, "    %s\n\n\n\n", to);
 
    /*
    **	Start the comparison of the two files.
    **	No paging mechanism is provided at present.
    **/
 
    compare (from, file1, n1, to, file2, n2, LNGVAL);
 
    /*
    **	Free up the dynamic memory used by DIFF
    **/
 
    for (i = 1;  i <= n1;  i++)
    {
	vm_len = file1[i].len+1;
        check_OK(lib$free_vm (
		   &vm_len,
		   &(file1[i].content),
		   0))
    }
    for (i = 1;  i <= n2;  i++)
    {
	vm_len = file2[i].len+1;
        check_OK(lib$free_vm (
		   &vm_len,
		   &(file2[i].content),
		   0))
    }
 
    /*
    **	Prompt for user input.
    **	CTRL/Y cancel multiple DIFF operations.  All other key
    **	puts the user back to DX.
    **/
 
    sleep(2);
    fprintf (
	stdout,
	"\n\n\nPress RETURN to continue -or- CTRL/Y to cancel multiple DIFF ");
    check_OK(lib$disable_ctrl (
	      &LIB$M_CLI_CTRLY,
	      &old_mask))
    smg$read_keystroke (
                 &cntrl_info_block.keyboard_id,
                 &word_terminator_code,
                 0,
                 0,
                 0,
                 0,
                 0);
    check_OK(lib$enable_ctrl (
	      &old_mask,
	      0))
 
    /*
    **	Cleanup and exit
    **/
 
    check_OK(smg$restore_physical_screen (
	      &cntrl_info_block.pasteboard_id,
	      &display_id))
 
    if (word_terminator_code == SMG$K_TRM_CTRLY)
    {
	strcpy(errmsg, "DIFF canceled by request");
	return DX__DONTCARE;
    }
 
    return DX__NORMAL;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
static int	diff_read(TXTINF f[], int *n, char *m, char *dna, char *errmsg)
{
    struct FAB fab;
    struct RAB rab;
    struct NAM nam;
 
    unsigned long retcode;
    long vm_len;
    char s[MAXCHARS+1];
    char *t;
    char resultant_name[NAM$C_MAXRSS];
 
    /**  Initialize File FAB  **/
    fab = cc$rms_fab;
    nam = cc$rms_nam;
    fab.fab$l_fna = m;
    fab.fab$b_fns = strlen(m);
    fab.fab$l_dna = dna;
    fab.fab$b_dns = strcspn(dna, ";")+1;    /**  Default to highest version  **/
    fab.fab$l_nam = &nam;
 
    nam.nam$l_rsa = &resultant_name;
    nam.nam$b_rss = NAM$C_MAXRSS;
 
    /**  Initialize Source File RAB  **/
    rab = cc$rms_rab;
    rab.rab$l_fab = &fab;
 
    rab.rab$b_rac = RAB$C_SEQ;
    rab.rab$l_ubf = s;
    rab.rab$w_usz = MAXCHARS;
 
    /**  Open and file  **/
    if ((retcode = sys$open (&fab, 0, 0)) != RMS$_NORMAL ||
	(retcode = sys$connect (&rab, 0, 0)) != RMS$_NORMAL)
    {
	sys$close(&fab, 0, 0);
	sprintf(errmsg, "Error opening %s as input file", m);
	return DX__ERROR;
    }
 
    resultant_name[nam.nam$b_rsl] = EOS;
    strcpy(m, resultant_name);
 
    *n = 0;
 
    while ((retcode = sys$get(&rab, 0, 0)) != RMS$_EOF)
    {
	if (*n >= MAXLINES)
	{
            sprintf (errmsg, "File %s too big", m);
	    sys$close (&fab, 0, 0);
	    return DX__ERROR;
	}
 
	vm_len = rab.rab$w_rsz + 1;
	if ((retcode = lib$get_vm (
			     &vm_len,
			     &t,
			     0)) != SS$_NORMAL)
	 {
	    strcpy(errmsg, "Error allocating virtual memory - exceeded quota");
	    sys$close (&fab, 0, 0);
	    return DX__ERROR;
	}
 
	memcpy (t, s, rab.rab$w_rsz);
	t[rab.rab$w_rsz] = EOS;
	f[++(*n)].content = t;
	f[*n].len = rab.rab$w_rsz;
    }
 
    sys$close (&fab, 0, 0);
 
    return DX__NORMAL;
}
