/* Program Name            : FILERTYP.C                                 */
/*   Original Author       : C. K. Hung					*/
/*   Date                  : 16-MAY-1991				*/
/*   Program Description   :                                            */
/*                         :                                            */
/* Revision History follows                                             */
 
#include "global.h"
#include "dx.h"
#include "filer.h"
#include "filerkpd.h"
#include "filertyp.h"
#include "inquire.h"
#include <libclidef.h>
#include <rmsdef.h>
 
 
/*
**
**  MACROS
**
**/
 
#define MAXLINES 65535
#define MAXBUFSIZ 65535
 
 
/*
**
**  FUNCTIONAL PROTOTYPING
**
**/
 
static int      type_no_page(struct FAB, unsigned long, unsigned long,
			     unsigned short int *, char *, char *);
static int      type_by_page(struct FAB, unsigned long, unsigned long,
			     unsigned short int *, char *, char *);
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      tbs
**
**--
**/
int	filer_type()
{
    if (DX_CURRENT_DIRECTORY.filemode == multiple)
	filer_multiple_type();
    else
	filer_single_type();
    return DX__NORMAL;
}
 
 
/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_multiple_type()
{
    char dummy[] = "";
    char errmsg[MAXFILESPEC+1];
 
    strcpy(errmsg, "Error typing file");
    filer_multiple(
	filer_type$1,
	dummy,
	errmsg);
    return DX__NORMAL;
}
 
 
/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_single_type()
{
    char dummy[] = "";
    char errmsg[MAXFILESPEC+1];
    char fn[MAXFILESPEC+1];
 
    if (!strcmp(DX_CURRENT_FILE->fn, "[-]"))
    {
        signal_err("Type 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 typing file");
	if (filer_type$1(dummy, fn, errmsg) == -1)
	    signal_err(errmsg, bell);
    }
    return DX__NORMAL;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_type$1(dummy, filespec, errmsg)
char *dummy;
char *filespec;
char *errmsg;
{
    return filer_type$2 (
		filespec,
		errmsg,
		dummy,
		(cntrl_info_block.user_pref.type_by_page?
		    type_by_page : type_no_page));
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_type$2(filespec, errmsg, option, func)
char *filespec;
char *errmsg;
char *option;
int (*func)();
{
    unsigned long filer_type1_display_id;
    unsigned long filer_type2_display_id;
 
    struct FAB from_fab;
 
    int status;
    unsigned short len;
    unsigned long retcode;
    unsigned short int word_terminator_code = 0;
    char errmsg1[MAXFILESPEC+1];
    $DESCRIPTOR (errmsg1_descrip, errmsg1);
    unsigned long old_mask;
    int filer_type1_bottom = cntrl_info_block.pasteboard_rows-2;
 
    /*
    **	Initialize Source File FAB
    **/
    from_fab = cc$rms_fab;
    from_fab.fab$l_fna = filespec;
    from_fab.fab$b_fns = strlen(filespec);
 
    /*
    **	Start outputing ...
    **/
    if ((retcode = sys$open (
			&from_fab,
			0,
			0)) != RMS$_NORMAL)
    {
	lib$sys_getmsg (
	    &retcode,
	    &len,
	    &errmsg1_descrip,
	    0,
	    0);
	errmsg1[len] = EOS;
	strcpy(errmsg, errmsg1);
	return DX__ERROR;
    }
 
    check_OK(smg$create_virtual_display (
	      &filer_type1_bottom,
	      &FILER_TYPE1_RIGHTMOST,
	      &filer_type1_display_id,
	      &SMG$M_TRUNC_ICON,
	      0,
	      0))
 
    check_OK(smg$create_virtual_display (
	      &FILER_TYPE2_BOTTOM,
	      &FILER_TYPE2_RIGHTMOST,
	      &filer_type2_display_id,
	      0,
	      0,
	      0))
 
    check_OK(lib$disable_ctrl (
	      &LIB$M_CLI_CTRLY,
	      &old_mask))
 
    status = (*func)(from_fab,
		     filer_type1_display_id,
		     filer_type2_display_id,
		     &word_terminator_code,
		     errmsg,
		     option);
 
    check_OK(lib$enable_ctrl (
	      &old_mask,
	      0))
 
    check_OK(smg$erase_display (
	      &filer_type1_display_id,
	      0,
	      0,
	      0,
	      0))
 
    check_OK(smg$delete_virtual_display (
	      &filer_type1_display_id))
 
    check_OK(smg$erase_display (
	      &filer_type2_display_id,
	      0,
	      0,
	      0,
	      0))
 
    check_OK(smg$delete_virtual_display (
	      &filer_type2_display_id))
 
    if ((retcode = sys$close (
			&from_fab,
			0,
			0)) != RMS$_NORMAL)
    {
	lib$sys_getmsg (
	    &retcode,
	    &len,
	    &errmsg1_descrip,
	    0,
	    0);
	errmsg1[len] = EOS;
	strcpy(errmsg, errmsg1);
	return DX__ERROR;
    }
 
    if (status == DX__ERROR)
    {
	return DX__ERROR;
    }
    else if (word_terminator_code == SMG$K_TRM_CTRLY)
    {
	strcpy(errmsg, "TYPE canceled by request");
	return DX__DONTCARE;
    }
 
    return DX__NORMAL;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
static int	type_no_page(from_fab,
			     filer_type1_display_id,
			     filer_type2_display_id,
			     word_terminator_code,
			     errmsg,
			     dummy)
struct FAB from_fab;
unsigned long filer_type1_display_id,
	      filer_type2_display_id;
unsigned short int *word_terminator_code;
char *errmsg;
char *dummy;
{
    char linebuf[MAXBUFSIZ+1];
    $DESCRIPTOR (linebuf_descrip, linebuf);
 
    struct RAB from_rab;
 
    char errmsg1[MAXFILESPEC+1];
    $DESCRIPTOR (errmsg1_descrip, errmsg1);
    unsigned short int len;
    unsigned long retcode;
    int filer_type2_pasteboard_row = cntrl_info_block.pasteboard_rows-1;
 
    /*
    **	Initialize Source File RAB
    **/
 
    from_rab = cc$rms_rab;
    from_rab.rab$l_fab = &from_fab;
    from_rab.rab$b_rac = RAB$C_SEQ;
    from_rab.rab$l_ubf = linebuf;
    from_rab.rab$w_usz = MAXBUFSIZ;
 
    if ((retcode = sys$connect (
			&from_rab,
			0,
			0)) != RMS$_NORMAL)
    {
	lib$sys_getmsg (
	    &retcode,
	    &len,
	    &errmsg1_descrip,
	    0,
	    0);
	errmsg1[len] = EOS;
	strcpy(errmsg, errmsg1);
	return DX__ERROR;
    }
 
    check_OK(smg$paste_virtual_display (
	      &filer_type1_display_id,
	      &cntrl_info_block.pasteboard_id,
	      &FILER_TYPE1_PBD_ROW,
	      &FILER_TYPE1_PBD_COLUMN,
	      0))
 
    check_OK(smg$paste_virtual_display (
	      &filer_type2_display_id,
	      &cntrl_info_block.pasteboard_id,
	      &filer_type2_pasteboard_row,
	      &FILER_TYPE2_PBD_COLUMN,
	      0))
 
    while (retcode != RMS$_EOF)
    {
	retcode = sys$get (
		      &from_rab,
		      0,
		      0);
	if (retcode == RMS$_EOF)
	{
	    strcpy(linebuf, "[EOF] ");
	    from_rab.rab$w_rsz = strlen("[EOF] ");
	}
	else if (retcode != RMS$_NORMAL)
	{
	    lib$sys_getmsg (
		&retcode,
		&len,
		&errmsg1_descrip,
		0,
		0);
	    errmsg1[len] = EOS;
	    strcpy(errmsg, errmsg1);
	    return DX__ERROR;
	}
	LENGTH(linebuf_descrip) = from_rab.rab$w_rsz;
	smg$put_line (
		&filer_type1_display_id,
		&linebuf_descrip,
		0,
		0,
		0,
		0,
		0,
		0);
    }
    smg$put_chars (
	&filer_type2_display_id,
	$DESCR ("Press RETURN to continue -or- keypad 0 and CTRL/Y to cancel"),
	&FILER_TYPE2_BOTTOM,
	&1,
	0,
	&SMG$M_REVERSE,
	0,
	0);
    smg$read_keystroke (
	&cntrl_info_block.keyboard_id,
	word_terminator_code,
	0,
	0,
	&filer_type2_display_id,
	0,
	0);
    check_OK(smg$erase_line (
		  &filer_type2_display_id,
		  &FILER_TYPE2_BOTTOM,
		  &1))
    return DX__NORMAL;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
static int	type_by_page(from_fab,
			     filer_type1_display_id,
			     filer_type2_display_id,
			     word_terminator_code,
			     errmsg,
			     dummy)
struct FAB from_fab;
unsigned long filer_type1_display_id,
	      filer_type2_display_id;
unsigned short int *word_terminator_code;
char *errmsg;
char *dummy;
{
    char linebuf[MAXBUFSIZ+1];
    $DESCRIPTOR (linebuf_descrip, linebuf);
 
    struct RAB from_rab;
 
    int filer_type1_bottom = cntrl_info_block.pasteboard_rows-2;
    int filer_type2_pasteboard_row = cntrl_info_block.pasteboard_rows-1;
    unsigned long old_mask;
    int lastline, linepos;
    char errmsg1[MAXFILESPEC+1];
    $DESCRIPTOR (errmsg1_descrip, errmsg1);
    unsigned short int len;
    unsigned long retcode;
    char *base_address;
    char *lines[MAXLINES];
    int i;
    int allocate_size;
 
    /*
    **	Initialize Source File RAB
    **/
 
    from_rab = cc$rms_rab;
    from_rab.rab$l_fab = &from_fab;
    from_rab.rab$b_rac = RAB$C_SEQ;
    from_rab.rab$l_ubf = linebuf;
    from_rab.rab$w_usz = MAXBUFSIZ;
 
    if ((retcode = sys$connect (
			&from_rab,
			0,
			0)) != RMS$_NORMAL)
    {
	lib$sys_getmsg (
	    &retcode,
	    &len,
	    &errmsg1_descrip,
	    0,
	    0);
	errmsg1[len] = EOS;
	strcpy(errmsg, errmsg1);
	return DX__ERROR;
    }
 
    check_OK(smg$paste_virtual_display (
	      &filer_type1_display_id,
	      &cntrl_info_block.pasteboard_id,
	      &FILER_TYPE1_PBD_ROW,
	      &FILER_TYPE1_PBD_COLUMN,
	      0))
 
    check_OK(smg$paste_virtual_display (
	      &filer_type2_display_id,
	      &cntrl_info_block.pasteboard_id,
	      &filer_type2_pasteboard_row,
	      &FILER_TYPE2_PBD_COLUMN,
	      0))
 
    lastline = 0;
 
    /*
    **	Display the first page and wait for user response
    **/
 
    for (i = 1;  retcode != RMS$_EOF && i <= filer_type1_bottom;  i++)
    {
	retcode = sys$get (
		      &from_rab,
		      0,
		      0);
	if (retcode == RMS$_EOF)
	{
	    strcpy(linebuf, "[EOF] ");
	    from_rab.rab$w_rsz = strlen("[EOF] ");
	}
	else if (retcode != RMS$_NORMAL)
	{
	    lib$sys_getmsg (
		&retcode,
		&len,
		&errmsg1_descrip,
		0,
		0);
	    errmsg1[len] = EOS;
	    strcpy(errmsg, errmsg1);
	    goto free_vm;
	}
	LENGTH(linebuf_descrip) = from_rab.rab$w_rsz;
	smg$put_line (
		&filer_type1_display_id,
		&linebuf_descrip,
		0,
		0,
		0,
		0,
		0,
		0);
	allocate_size = (int) from_rab.rab$w_rsz+1;
	check_OK(lib$get_vm (
		  	&allocate_size,
		  	&base_address,
		  	0))
	strncpy(base_address, linebuf, from_rab.rab$w_rsz);
	base_address[allocate_size-1] = EOS;
	lines[lastline++] = base_address;
    }
 
    smg$put_chars (
	&filer_type2_display_id,
	$DESCR (
    "Press ARROW KEYS for prev or next -or-  keypad 0 and CTRL/Y to cancel"),
	&FILER_TYPE2_BOTTOM,
	&1,
	0,
	&SMG$M_REVERSE,
	0,
	0);
    smg$read_keystroke (
	&cntrl_info_block.keyboard_id,
	word_terminator_code,
	0,
	0,
	&filer_type2_display_id,
	0,
	0);
    check_OK(smg$erase_line (
		  &filer_type2_display_id,
		  &FILER_TYPE2_BOTTOM,
		  &1))
    linepos = 1;
 
    /*
    **	Keep typing until exit by the user
    **/
 
    while (*word_terminator_code != SMG$K_TRM_CTRLY &&
	   *word_terminator_code != SMG$K_TRM_CTRLC &&
	   *word_terminator_code != SMG$K_TRM_KP0 &&
	   *word_terminator_code != SMG$K_TRM_CTRLZ)
    {
	switch (*word_terminator_code)
	{
	    case SMG$K_TRM_UP :
		 if (linepos == 1)
		 {
		     check_OK(smg$ring_bell (
			          &filer_type1_display_id,
			          0))
		 }
		 else
		 {
		     for (i = filer_type1_bottom;  i > 1 && linepos > 1;  i--)
		     {
			linepos--;
			strcpy(linebuf, lines[linepos-1]);
			LENGTH(linebuf_descrip) = strlen(linebuf);
			smg$insert_line (
				 &filer_type1_display_id,
				 &1,
				 &linebuf_descrip,
				 &SMG$M_DOWN,
				 0,
				 0,
				 0,
				 0);
		     }
		 }
		 break;
	    case SMG$K_TRM_DOWN:
	    case SMG$K_TRM_CR :	
		if (linepos+filer_type1_bottom-1 >= lastline &&
		     retcode == RMS$_EOF)
		{
		    check_OK(smg$ring_bell (
				    &filer_type1_display_id,
				    0))
		}
		else
		{
		    for (i = filer_type1_bottom;  i > 1;  i--)
		    {
			if (linepos+filer_type1_bottom-1 < lastline)
			{
			    linepos++;
			    strcpy(
				linebuf,
				lines[linepos+filer_type1_bottom-2]);
			    LENGTH(linebuf_descrip) = strlen(linebuf);
			    smg$insert_line (
				     &filer_type1_display_id,
				     &filer_type1_bottom,
				     &linebuf_descrip,
				     &SMG$M_UP,
				     0,
				     0,
				     0,
				     0);
			}
			else if (retcode != RMS$_EOF)
			{
			    retcode = sys$get (
					&from_rab,
					0,
					0);
			    if (retcode == RMS$_EOF)
			    {
			       strcpy(linebuf, "[EOF] ");
			       from_rab.rab$w_rsz = strlen("[EOF] ");
			    }
			    else if (retcode != RMS$_NORMAL)
			    {
				 lib$sys_getmsg (
				       &retcode,
				       &len,
				       &errmsg1_descrip,
				       0,
				       0);
				 errmsg1[len] = EOS;
				 strcpy(errmsg, errmsg1);
				 goto free_vm;
			    }
			    LENGTH(linebuf_descrip) = from_rab.rab$w_rsz;
			    linepos++;
			    smg$insert_line (
				      &filer_type1_display_id,
				      &filer_type1_bottom,
				      &linebuf_descrip,
				      &SMG$M_UP,
				      0,
				      0,
				      0,
				      0);
			    allocate_size = (int) from_rab.rab$w_rsz+1;
			    check_OK(lib$get_vm (
					    &allocate_size,
					    &base_address,
					    0))
			    memcpy(base_address, linebuf, from_rab.rab$w_rsz);
			    base_address[allocate_size-1] = EOS;
			    lines[lastline++] = base_address;
			}
		    }
		}
		break;
	    case SMG$K_TRM_CTRLW:
		check_OK(smg$repaint_screen (
			      &cntrl_info_block.pasteboard_id))
		break;
	    default:
		if (*word_terminator_code != SMG$K_TRM_CANCELLED)
		{	/**  Returned from broadcast message trapping  **/
		    check_OK(smg$ring_bell (
				  &filer_type1_display_id,
				  0))
		}
		break;
    }
    check_OK(smg$put_chars (
		   &filer_type2_display_id,
		   $DESCR (
    "Press ARROW KEYS for prev or next -or- keypad 0 and CTRL/Y to cancel"),
		   &FILER_TYPE2_BOTTOM,
		   &1,
		   0,
		   &SMG$M_REVERSE,
		   0,
		   0))
    smg$read_keystroke (
	 &cntrl_info_block.keyboard_id,
	 word_terminator_code,
	 0,
	 0,
	 &filer_type2_display_id,
	 0,
	 0);
    check_OK(smg$erase_line (
		   &filer_type2_display_id,
		   &FILER_TYPE2_BOTTOM,
		   &1))
    }
 
free_vm:
    for (i = 0;  i < lastline;  i++)
    {
	allocate_size = strlen(lines[i])+1;
    	check_OK(lib$free_vm (
		     &allocate_size,
		     &lines[i],
		     0))
    }
 
    return (retcode == RMS$_NORMAL || retcode == RMS$_EOF?
		DX__NORMAL : DX__ERROR);
}
