/*
 *				T 2
 *
 * Processing for each file (and each page output).
 *
 */

#include	<stdio.h>
#ifdef	vms
#include	<ctype.h>
#endif
#include	"t.h"
#define	FALSE		0
#define	TRUE		1
#ifdef	rsx
extern	int		$$rsts;			/* TRUE if on RSTS/E	*/
#endif
int
process(fname, row)
char		*fname;		/* File argument (with wildcards)	*/
int		row;		/* row for file error message if needed	*/
/*
 * Display this file.  Return number of files found.
 */
{
	register int	nfiles;	/* Number of wildcard files found	*/
	register int	ratt;	/* FDB @ F.RATT				*/
	register int	temp;	/* FDB @ F.RTYP plus junk		*/
	RFA		*mp;	/* Memory pointer			*/
	extern FILETYPE	*FWILD();
	extern FILE	*FNEXT();

	fixfilename(fname);
	/*
	 * Open the file "unformatted" and deblock records locally.
	 * This is because (on RSX) ftell() returns a record pointer
	 * while T needs a line pointer.  Unfortunately, several
	 * record formats on RSX pack multiple lines in one record
	 * and/or multiple records per line.  We don't really have
	 * to do this in RT11, but we do it anyways.
	 */
	nfiles = 0;
	if ((infd = FWILD(pfilename, FWILDMODE)) == NULL) {
		cant("open", pfilename, row, TRUE);
		return (nfiles);
	}
	/*
	 * For each file (matched by the wildcard argument)
	 */
	for (nfiles = 0; FNEXT(infd) != NULL && !finis; nfiles++) {
#ifdef	rsx
		/*
		 * fdb_seqn -> the sequence number word in the file fdb.
		 * This is needed for vms printfile processing.
		 */
		fdb_seqn = (int *) &infd->io_fdb[(int) &F_SEQN];
#endif
		eofseen = FALSE;
		FGETNAME(infd, file_name);
#ifdef	rsx
		/*
		 * Determine how records are to be deblocked.
		 * The FDB is organized such that
		 *	F.RTYP is at offset 0 and
		 *	F.RATT is at offset 1.
		 * implied_cr is TRUE if FD.CR is set in the fdb
		 *	or we are running under RSTS/E and the file
		 *	is native RSTS stream (zero attributes) or
		 *	RSX stream (RTYP == 4 and RATT == 0).
		 * fortran_cr is TRUE if FD.FTN is set.
		 * vms_printfile is TRUE if FDB@F.RTYP == R.SEQ and
 		 *		FDB@F.RATT == FD.VFC.  This is the
		 *	way RSX (compatibility mode) handles vms
		 * 	print file format.  (Files transferred to
		 *	native RSX or RSX/RSTS via DECnet may also
		 *	get this attribute.
		 */
		temp = infd->io_fdb[(int) &F_RTYP] & 0377;
		ratt = infd->io_fdb[(int) &F_RATT] & 0377;
		implied_cr =
			 (((ratt & ((int) &FD_CR)) != 0)
			|| (ratt == ((int) &R_STM))
			|| ($$rsts != 0 && ratt == 0 && temp == 0));
		fortran_cr = ((ratt & ((int) &FD_FTN)) != 0);
		vms_printfile =
			  ((temp == ((int) &R_SEQ))
		     /*	|| (ratt == ((int) &FD_VFC))); */
			|| (ratt == FD_VFC));
		/*
		 * Use information in the IOV to allocate a
		 * record buffer (freeing any current one).
		 * Note that the allocated buffer is two bytes
		 * longer than the longest logical record.
		 * One of these is needed for the trailing EOS
		 * (null) byte, and the other is prepended for
		 * carriage-control formatting.  If the file is
		 * in vms_printfile, the record size is increased so
		 * that the maximum number of leading/trailing line
		 * separators may be appended.
		 *
		 * buff -> where the read will start at.
		 */
		if (allobuff != NULL)
			free(allobuff);
		max_size = temp = infd->io_rbsz;
		if (vms_printfile)
			temp += 256;		/* Add in guard space	*/
		if ((allobuff = calloc(temp + 2, sizeof (char))) == NULL)
			error("Can't get %d byte buffer\n", temp);
		buff = &allobuff[ (vms_printfile) ? 128 : 1 ];
#endif
#ifdef	DEBUG
		if (debug) {
		    _tracef("file %s", file_name);
		}
#endif
		scerpg(1, 1);
		/*
		 * Put a message on the first page.
		 */
		concat(temptext, "File \"", file_name, "\"", NULL);
		midmsg();
		scout(0, 0, textline);
		row = 3;
		/*
		 * Initialize the top of page memory buffer, set
		 * current record to "beginning of the file", and
		 * clear eof and breakout flags.
		 */
		for (mp = memory; mp <= LASTMEM; mp++) {
			mp->record_rfa = magic_cookie;
			mp->buff_offset = 0;
			mp->line_offset = 0;
		}
		memptr = &memory[-1];
		rec_rfa = magic_cookie;
		rec_bor = rec_eor = buff;
		rec_txt = textline;
		rec_savec = EOS;
		iseof = 0;
		breakout = FALSE;
		while (!finis && !breakout) {
			/*
			 * New page -- moving forward in the file,
			 * save the position of the top of the page.
			 */
			saveplace();
			do {
				/*
				 * Print the page, and loop while
				 * inquire() has us moving backward
				 * in the file.
				 */
				dopage(row);
				row = 1;
			} while (inquire());
		}
	}
	/*
	 * All wildcard matches done
	 */
	if (nfiles == 0) {
		cant("locate", pfilename, row, TRUE);
	}
	else {
		/*
		 * Successful ending
		 */
		scerpg(1, 1);
	}
	return (nfiles);
}

fixfilename(fname)
char		*fname;
/*
 * Copy the argument to global pfilename[], appending ".*" if no
 * '.' was seen.
 */
{
	register char	*ep;
	extern char	*cpystr();

	for (ep = cpystr(pfilename, fname);
			ep >= pfilename
			&& *ep != ']' && *ep != '.' && *ep != ';';
			ep--)
		;
	if (pfilename[0] != EOS && *ep != ';' && *ep != '.') {
		concat(pfilename, pfilename, ".*", NULL);
	}
}

dopage(startrow)
int		startrow;
/*
 * Do one page of the file, return TRUE if at end of file.
 */
{
	register char	*tp;
	register int	row;
	extern char	*getline();

#ifdef	DEBUG
#ifdef	vms
	if (debug) {
	    _tracef("dopage: page %d, rec_rfa = %d %d %d, bor %d, txt %d",
		(memptr - memory),
		rec_rfa.word[0], rec_rfa.word[1], rec_rfa.word[2],
		rec_bor - buff, rec_txt - textline);
	    if (memptr >= memory) {
		_tracef(" prev. rfa %d %d %d, buff_offset %d, line_offset %d",
		    memptr[-1].record_rfa.word[0],
		    memptr[-1].record_rfa.word[1],
		    memptr[-1].record_rfa.word[2],
		    memptr[-1].buff_offset, memptr[-1].line_offset);
	    }
	}
#endif
#endif
	for (row = startrow; row <= linesperscreen; row++) {
		if ((tp = getline(row)) == NULL) {
			/*
			 * End of file
			 */
			if (row == startrow) {
				/*
				 * EOF at top of page -- finis
				 */
				return (TRUE);
			}
			else {
				/*
				 * Wait till prompt and then
				 * it's finis for the file.
				 */
				scerpg(row, 1);
				break;
			}
		}
		/*
		 * Note that getline() has normalized formfeeds
		 * so that they always are by themselves.
		 */
		if (row == startrow) {
			/*
			 * Skip blank lines at the top of a screen.
			 */
			switch (*tp) {
			case '\f':
			case EOS:	row--;
					continue;
			}
			scerpg(row, 1);
		}
		else if (*tp == '\f') {
			/*
			 * Page break
			 */
			break;
		}
		else {
			/*
			 * Not at the top of the page,
			 * go to the next line.
			 */
			scout(0, 0, "\r\n");		/* Quick move	*/
		}
		/*
		 * Output the current line
		 */
		scout(0, 0, tp);
	}
	/*
	 * This page is complete.
	 */
	scout(cursrow, curscol, "");	/* Home cursor			*/
	cursrow = curscol = 1;		/* Reset to standard home	*/
	scout(0, 0, NULL);		/* Flush buffers		*/
}	

cant(why, filename, row, flag)
char		*why;
char		*filename;
int		row;			/* Error msg on row and row+1	*/
int		flag;			/* True to print perror msg.	*/
/*
 * Can't open file message
 */
{
	sprintf(textline, "Can't %s \"%s\"", why, filename);
	scerpg(row, 1);
	if (flag) {
		scout(0, 0, NULL);
		perror(textline);
	}
	else {
		scout(0, 0, textline);
	}
	scout(0, 0, NULL);
	return (TRUE);
}
