/* Program Name            : FILERSTA.C                                 */
/*   Original Author       :  C. K. Hung				*/
/*   Date                  : 16-MAY-1991				*/
/*   Program Description   :                                            */
/* Revision History follows                                             */
/*  03-Jun-1999 JL usage of __FIB 					*/
 
 
#include "global.h"
#include "dx.h"
#include "filer.h"
#include "filerkpd.h"
#include "filersta.h"
#include "inquire.h"
#include <atrdef>
#include "fchdef.h"	/* Does not exist for AXP - Replace by local */
#include <fibdef.h>
#include <libclidef.h>
#include <sbkdef.h>
#include <iodef.h>
 
 
/*
**  MACRO DEFINITIONS
**/
 
/**  FILER_STATUS virtual display dimensions	**/
#define FILER_STATUS_RIGHTMOST			80
#define FILER_STATUS_PBD_ROW			1
#define FILER_STATUS_PBD_COLUMN			1
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      tbs
**
**--
**/
int	filer_status()
{
    if (DX_CURRENT_DIRECTORY.filemode == multiple)
	filer_multiple_status();
    else
	filer_single_status();
     return DX__NORMAL;
}
 
 
/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_multiple_status()
{
    char dummy[] = "";
    char errmsg[MAXFILESPEC+1];
 
    strcpy(errmsg, "Error showing file characteristics");
    filer_multiple(
	filer_status$1,
	dummy,
	errmsg);
     return DX__NORMAL;
}
 
 
int	filer_single_status()
{
    char dummy[] = "";
    char errmsg[MAXFILESPEC+1];
    char fn[MAXFILESPEC+1];
 
    if (!strcmp(DX_CURRENT_FILE->fn, "[-]"))
    {
        signal_err("Show details of 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 showing file characteristics");
	if (filer_status$1(dummy, fn, errmsg) == -1)
	    signal_err(errmsg, bell);
    }
     return DX__NORMAL;
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
int	filer_status$1(dummy, filespec, errmsg)
char *dummy;
char *filespec;
char *errmsg;
{
    static char str[BUFSIZ+1];
    $DESCRIPTOR (str_descrip, str);
 
    /**  File Characteristics Bits  **/
    unsigned long fch;
 
    /**  Record Attributes Area  **/
    struct {
	unsigned char fat$b_rtype;
	unsigned char fat$b_rattrib;
	unsigned short int fat$w_rsize;
	struct {
	    unsigned short int fat$w_hiblkh;
	    unsigned short int fat$w_hiblkl;
	} fat$l_hiblk;
	struct {
	    unsigned short int fat$w_efblkh;
	    unsigned short int fat$w_efblkl;
	} fat$l_efblk;
	short int fat$w_ffbyte;
	unsigned char fat$b_bktsize;
	unsigned char fat$b_vfcsize;
	short int fat$w_maxrec;
	short int fat$w_defext;
	short int fat$w_gbc;
	short int spares1;
	int spares2;
	short int spares3;
	short int fat$w_versions;
    } raa;
 
    /**  Statistics Block  **/
    struct sbkdef asb;
 
    /**  ASCII DATES  **/
    unsigned char adat[35];
 
    /*
    **  struct representing a 64-bit binary value expressing
    **  the date and time
    **/
 
    DATE_TIME cdt,
	      rdt,
	      edt,
	      bdt;
 
    /**  File Owner UIC  **/
    unsigned long int uic;
    char uicbuf[256];
    $DESCRIPTOR (uicbuf_descrip, uicbuf);
    unsigned short int uiclen;
    unsigned long int gic;
    char gicbuf[256];
    $DESCRIPTOR (gicbuf_descrip, gicbuf);
    unsigned short int giclen;
 
    /**  File Protection  **/
    unsigned short int fpro;
 
    /**  Access Control Block  **/
    struct {
	unsigned short w_size;
	unsigned short w_type;
	char *l_addr;
    } acb[] = {
	{  4, ATR$C_UCHAR, &fch },
	{ 32, ATR$C_RECATTR, &raa },
	{ 32, ATR$C_STATBLK, &asb },
	{ 35, ATR$C_ASCDATES, adat },
	{  8, ATR$C_CREDATE, &cdt },
	{  8, ATR$C_REVDATE, &rdt },
	{  8, ATR$C_EXPDATE, &edt },
	{  8, ATR$C_BAKDATE, &bdt },
	{  4, ATR$C_UIC, &uic },
	{  2, ATR$C_FPRO, &fpro },
	{  0, 0, NULL }
    };
 
    int iosb[2];
 
    static struct fibdef fib;
    $DESCRIPTOR(fib_descriptor, (char *)&fib);
 
    char filename[MAXFILESPEC+1];
    $DESCRIPTOR (filespec_descriptor, filename);
 
    char *cp;
    int i;
    unsigned short int rvn;
    unsigned long filer_status_display_id;
    unsigned short int word_terminator_code;
    int lineno;
    char lines[120][MAXFILESPEC+1];
    char linebuf[MAXFILESPEC+1];
    $DESCRIPTOR (linebuf_descriptor, linebuf);
    unsigned resultant_time;
    static unsigned int timlen;
    char timbuf[50];
    $DESCRIPTOR (timbuf_descriptor, timbuf);
    char forg[MAXFILESPEC+1];
    char frat[MAXFILESPEC+1];
    char frfm[MAXFILESPEC+1];
    char spro[5], opro[5], gpro[5], wpro[5];
    unsigned long old_mask;
    int prompt_row;
    struct filespec_list_tag *s;
    unsigned short int chan;
 
    LENGTH(fib_descriptor) = sizeof (struct fibdef);
 
    for (i = 0; i <= 2; i++)
	__FIB(fib,fib$r_did_overlay,fib$w_did[i]) = DX_CURRENT_FILE->did[i];
 
    if ((cp = strchr(filespec, ']')) == NULL)
	strcpy(filename, filespec);
    else
	strcpy(filename, cp+1);
    LENGTH(filespec_descriptor) = strlen(filename);
 
    /*
    **	Find the I/O channel for this file
    **/
    for (s = DX_CURRENT_DIRECTORY.cur_filter.name_filespec_list;
	    s != (struct filespec_list_tag *)NULL;  s = s->next)
    {
	struct w_dids_tag *t;
 
        for (t = s->w_dids;  t != (struct w_dids_tag *)NULL;  t = t->next)
        {
	    if (t->did[0] == DX_CURRENT_FILE->did[0] &&
		t->did[1] == DX_CURRENT_FILE->did[1] &&
		t->did[2] == DX_CURRENT_FILE->did[2])
	    {
		chan = t->chan;
		break;
	    }
        }
    }
 
    check_OK(sys$qiow (
		0,
		chan,
		IO$_ACCESS,
		iosb,
		0,
		0,
		&fib_descriptor,
		&filespec_descriptor,
		0,
		0,
		acb,
		0))
 
    if (iosb[0] != SS$_NORMAL)
    {
	/**  No READ access  **/
	strcpy(errmsg, "Insufficient privilege for read operation");
	return -1;
    } else
    {
	check_OK(smg$create_virtual_display (
		&cntrl_info_block.pasteboard_rows,
		&FILER_STATUS_RIGHTMOST,
		&filer_status_display_id,
		&SMG$M_TRUNC_ICON,
		0,
		0))
 
	check_OK(smg$paste_virtual_display (
		&filer_status_display_id,
		&cntrl_info_block.pasteboard_id,
		&FILER_STATUS_PBD_ROW,
		&FILER_STATUS_PBD_COLUMN,
		0))
 
	lineno = 0;
 
	/*
	**  Header info
	**/
	sprintf(lines[lineno++], "File name: %s", filespec);
	strcpy(lines[lineno++], "");
 
	/*
	**  # of files & total size
	**/
	sprintf(lines[lineno++],
		"%23s : %d/%d blocks",
		"Size",
		raa.fat$l_efblk.fat$w_efblkl+(raa.fat$l_efblk.fat$w_efblkh << 16),
		asb.sbk$w_filesizl+(asb.sbk$w_filesizh << 16));
 
	/*
	**  File ID
	**/
	sprintf(lines[lineno++],
		"%23s : (%d,%d,%d)",
		"File ID",
		__FIB(fib,fib$r_fid_overlay,fib$w_fid[0]),
		__FIB(fib,fib$r_fid_overlay,fib$w_fid[1]),
		__FIB(fib,fib$r_fid_overlay,fib$w_fid[2]));
 
	/*
	**  Owner UIC
	**/
 
	sprintf(lines[lineno],
		"%23s : [",
		"Owner UIC");
	gic = uic | 0xFFFF;
	if (sys$idtoasc(gic, &giclen, &gicbuf_descrip, 0, 0, 0) == SS$_NORMAL)
	{
	    gicbuf[giclen] = EOS;
	    sprintf(lines[lineno], "%s%s,", lines[lineno], gicbuf);
	}
	if (sys$idtoasc(uic, &uiclen, &uicbuf_descrip, 0, 0, 0) == SS$_NORMAL)
	{
	    uicbuf[uiclen] = EOS;
	    sprintf(lines[lineno], "%s%s", lines[lineno], uicbuf);
	}
	strcat(lines[lineno], "]");
	lineno++;
 
	/*
	**  File protection
	**/
	getpro(fpro, spro, opro, gpro, wpro);
	sprintf(lines[lineno++],
		"%23s : System:%s, Owner:%s, Group:%s, World:%s",
		"File protection",
		spro,
		opro,
		gpro,
		wpro);	
 
	/*
	**  Time, time, time, ...
	**/
	check_OK(sys$asctim (
		    &timlen,
		    &timbuf_descriptor,
		    &cdt,
		    0))
	timbuf[ timlen ] = EOS;
	sprintf(lines[lineno++], "%23s : %s", "Created", timbuf);	
 
	check_OK(sys$asctim (
		    &timlen,
		    &timbuf_descriptor,
		    &rdt,
		    0))
	timbuf[ timlen ] = EOS;
	rvn = adat[0] + (adat[1] << 8);
	sprintf(lines[lineno++],
		"%23s : %s (%d)",
		"Revised",
		timbuf,
		rvn);
 
	check_OK(sys$asctim (
		    &timlen,
		    &timbuf_descriptor,
		    &edt,
		    0))
	timbuf[ timlen ] = EOS;
	if (!strncmp(timbuf, "17-NOV-1858", 11))
	    strcpy(timbuf, "<None specified>");
	sprintf(lines[lineno++],
		"%23s : %s",
		"Expires",
		timbuf);	
 
	check_OK(sys$asctim (
		    &timlen,
		    &timbuf_descriptor,
		    &bdt,
		    0))
	timbuf[ timlen ] = EOS;
	if (!strncmp(timbuf, "17-NOV-1858", 11))
	    strcpy(timbuf, "<No backup recorded>");
	sprintf(lines[lineno++],
		"%23s : %s",
		"Backup",
		timbuf);	
 
	/*
	**  File attributes
	**/
	sprintf(lines[lineno++],
		"%23s : Allocation:%d, Extension:%d, Global buffer count:%d",
		"File attributes",
		asb.sbk$w_filesizl+(asb.sbk$w_filesizh << 16),
		raa.fat$w_defext,
		raa.fat$w_gbc);
	
	if (fch & (1 << FCH$V_DIRECTORY))
	{
	    /**  Directory file  **/
	    if (raa.fat$w_versions != 0)
		sprintf(lines[lineno],
			"%26s%s%d",
			"",
			"Default version limit: ",
			raa.fat$w_versions);
	    else
		sprintf(lines[lineno],
			"%26s%s",
			"",
			"No version limit");
	    strcat(lines[lineno], ", Directory file");
	}
	else
	{
	    /**  For non-directory file  **/
	    if (fib.fib$w_verlimit == 32767)
		sprintf(lines[lineno],
			"%26s%s",
			"",
			"No version limit");
	    else
		sprintf(lines[lineno],
			"%26s%s%d",
			"",
			"Version limit: ",
			fib.fib$w_verlimit);
	}
	if (fch & (1 << FCH$V_CONTIG))
	    strcat(lines[lineno], ", Contiguous");
	else if (fch & (1 << FCH$V_CONTIGB))
	    strcat(lines[lineno], ", Contiguous best try");
	lineno++;
 
	/*
	**  File organization
	**/
	switch (raa.fat$b_rtype & 0xF0)
	{
	    case FAB$C_SEQ: strcpy(forg, "Sequential");  break;
	    case FAB$C_REL: strcpy(forg, "Relative");  break;
	    case FAB$C_IDX: strcpy(forg, "Indexed"); break;
	    case FAB$C_HSH: strcpy(forg, "Hashed"); break;
	    default:
		;
	}
	sprintf(lines[lineno++],
		"%23s : %s",
		"File Organization",
		forg);
 
	/*
	**  Record format
	**/
	switch (raa.fat$b_rtype & 0xF)
	{
	    case FAB$C_UDF: sprintf(lines[lineno++],
				    "%23s : Undefined",
				    "Record Format");
			    break;
	    case FAB$C_FIX: sprintf(lines[lineno++],
				    "%23s : Fixed length, %d byte records",
				    "Record Format",
				    raa.fat$w_rsize);
			    break;
	    case FAB$C_VAR: sprintf(lines[lineno++],
				    "%23s : Variable length, maximum %d bytes",
				    "Record Format",
				    raa.fat$w_rsize);
			    break;
	    case FAB$C_VFC: sprintf(lines[lineno++],
				    "%23s : VFC, maximum %d bytes",
				    "Record Format",
				    max(raa.fat$w_maxrec, raa.fat$w_rsize));
			    break;
	    case FAB$C_STM: sprintf(lines[lineno++],
				    "%23s : RMS-11 stream",
				    "Record Format");
			    break;
	    case FAB$C_STMLF: sprintf(lines[lineno++],
				    "%23s : Stream_LF",
				    "Record Format");
			    break;
	    case FAB$C_STMCR: sprintf(lines[lineno++],
				    "%23s : Stream_CR",
				    "Record Format");
			    break;
	    default: sprintf(lines[lineno++],
			     "%23s : None",
			     "Record Format");
		     break;
	}
 
	/*
	**  Record attributes
	**/
	switch (raa.fat$b_rattrib)
	{
	    case FAB$M_FTN: strcpy(frat, "FORTRAN carriage control character");  break;
	    case FAB$M_CR: strcpy(frat, "Carriage return carriage control"); break;
	    case FAB$M_PRN: strcpy(frat, "Print file carriage control"); break;
	    case FAB$M_BLK: strcpy(frat, "No carriage control, Non-spanned"); break;
	    default: strcpy(frat, "None"); break;
	}
	sprintf(lines[lineno++],
		"%23s : %s",
		"Record Attributes",
		frat);	
    }
 
    for (i = 1; i <= lineno; i++)
    {
	strcpy(linebuf, lines[i-1]);
	LENGTH(linebuf_descriptor) = strlen(linebuf);
	check_OK(smg$put_chars (
			    &filer_status_display_id,
			    &linebuf_descriptor,
			    &i,
			    &1,
			    0,
			    0,
			    0,
			    0))
    }
 
    check_OK(smg$set_cursor_abs (
	      &filer_status_display_id,
	      &cntrl_info_block.pasteboard_rows,
	      &1))
 
    check_OK(lib$disable_ctrl (
	      &LIB$M_CLI_CTRLY,
	      &old_mask))
 
    smg$read_keystroke (
                 &cntrl_info_block.keyboard_id,
                 &word_terminator_code,
                 $DESCR (
	     "Press RETURN to continue -or- CTRL/Y to cancel multiple show"),
                 0,
                 &filer_status_display_id,
                 &SMG$M_REVERSE,
                 0);
 
    check_OK(lib$enable_ctrl (
	      &old_mask,
	      0))
 
    check_OK(smg$erase_display (
	      &filer_status_display_id,
	      0,
	      0,
	      0,
	      0))
 
    check_OK(smg$delete_virtual_display (
	      &filer_status_display_id))
 
    if (word_terminator_code != SMG$K_TRM_CTRLY)
    {
	return DX__NORMAL;
    }
    else
    {
	strcpy(errmsg, "ANALYZE canceled by request");
	return DX__DONTCARE;
    }
}
 
 

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      to be specified
**
**--
**/
void	    getpro(
		unsigned short pcode,
		char *spro,char *opro,char *gpro,char *wpro)
{
 
    /**  SYSTEM PROTECTION  **/
    if (!(pcode & (1 << 0)))		*spro++ = 'R';
    if (!(pcode & (1 << 1)))		*spro++ = 'W';
    if (!(pcode & (1 << 2)))		*spro++ = 'E';
    if (!(pcode & (1 << 3)))		*spro++ = 'D';
    *spro = EOS;
 
    /**  OWNER PROTECTION  **/
    if (!(pcode & (1 << 4)))		*opro++ = 'R';
    if (!(pcode & (1 << 5)))		*opro++ = 'W';
    if (!(pcode & (1 << 6)))		*opro++ = 'E';
    if (!(pcode & (1 << 7)))		*opro++ = 'D';
    *opro = EOS;
 
    /**  GROUP PROTECTION  **/
    if (!(pcode & (1 << 8)))		*gpro++ = 'R';
    if (!(pcode & (1 << 9)))		*gpro++ = 'W';
    if (!(pcode & (1 << 10)))		*gpro++ = 'E';
    if (!(pcode & (1 << 11)))		*gpro++ = 'D';
    *gpro = EOS;
 
    /**  WORLD PROTECTION  **/
    if (!(pcode & (1 << 12)))		*wpro++ = 'R';
    if (!(pcode & (1 << 13)))		*wpro++ = 'W';
    if (!(pcode & (1 << 14)))		*wpro++ = 'E';
    if (!(pcode & (1 << 15)))		*wpro++ = 'D';
    *wpro = EOS;
}
