/*	mark saeger,	msaeger@cse.unl.edu				*/
/*	file.c								*/
/*	Copyright 1995 Mark Saeger.					*/
/*									*/
/*	Permission is granted to any individual or instituition to use,	*/
/*	copy, or redistribute this executable so long as it is not	*/
/*	modified and that it is not sold for profit.			*/
/*									*/
/*	LIKE ANYTHING THAT IS FREE, MORE IS PROVIDED AS IS AND COMES	*/
/*	WITH NO	WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED.	*/
/*	IN NO EVENT WILL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DAMAGES	*/
/*	RESULTING FROM THE USE OF THIS SOFTWARE.			*/
#include "more.h"

/* NOTE:  tried to use the magic values to determine what a file is, but
could not get the ELF format figured out on IRIX, so just do a simple check
of the first 5 bytes or so...*/

#define CHECKHIT 5	/* 5 seems to be a good number*/

/*used to check the first CHECKHIT bytes to see if a binary file*/
int check_bin(FILE *ip)
{
	unsigned char dumbuf[CHECKHIT];	/*the buffer to store in*/
	int dum;			/*just a dummy*/
	int retvalue=0;			/*0=all ascii, >0 possible binary*/

	dum=read(ip->_file,dumbuf,CHECKHIT);

	for(dum=0;dum<CHECKHIT;dum++)
		if((dumbuf[dum]<' ') || (dumbuf[dum]>127))
		{
			switch(dumbuf[dum])
			{
				case '\n':	/*all legal chars*/
				case '\t':
				case '\v':
				case '\b':
				case '\r':
				case '\f':
				case '\a':
					break;
				default:	/*not a legal, so ++ */
					retvalue++;
					break;
			}
		}
	return(retvalue);
}

/*
	return TRUE if need to read another chunk, so do goto
	FALSE means we were able to take care of skipping in current chunk
*/
int read_forward(int max_to_read, unsigned char bigbuf[], int *x, int *xcount,
		int *poffset, long *countlines)
{
	extern int optpl;	/*the positive offset into file*/
	int xx=0;		/*dummy*/
	int xdoing=TRUE;	/*for loop control*/
	int cc;			/*to hold the character from bigbuf*/

	if (*xcount == 1)	/*if initial time, show 'skipping...'*/
	{
		printf("skipping...%d lines\n",optpl);	
		fflush(stdout);	/*print it right away*/
	}
	if(optpl==1)	/*skip only one line, so disregard*/
	{
		xdoing=FALSE;
		*poffset=FALSE;
	}
	xx = *x;

	while(xdoing)
	{
		while(xx < max_to_read)	/*go through buffer*/
		{
			cc=bigbuf[xx++];	/*get character*/
			if(cc=='\n')	/*look for newlines*/
			{
				++*xcount;	/*the number of lines to skip*/
				++*countlines;	/*where we are*/
				/*only this one, not mlcounter*/
				/*used by do_prompt*/
			}
			if(*xcount == optpl)	/*the correct amount?*/
			{
				*x=xx;	/*where to start*/
				xx=max_to_read;/*break loop*/
				xdoing=FALSE;
				*poffset = FALSE;/*turn it off*/
			}
		}
		if(xdoing && *poffset)	/*means not in current chunk of data*/
		{
				*x=xx;	/*max it out*/
				return TRUE;
		}
	}
	return FALSE;
}

int read_backward(unsigned char bigbuf[], int *x, int *mlcounter,
		int *boffset, long *countlines, int *countchar)
{
	extern int optl;
	extern int mcolumns;
/*	extern FILE *tty;*/	/*TESTING PURPOSES ONLY*/
	int xx;		/*dummy*/
	int xdoing=TRUE;	/*loop control*/
	int cc;			/*to hold the character from bigbuf*/
	int xbreak=TRUE;	/*more loop control*/
	int lcount=0;
	extern int newone;
	extern test_top_of_form;
	extern test_mlcounter;	/*trying to fix /43/247' glitch*/
/*	unsigned char tb[256];*/	/*temp line buffer*/
/*	int tb_count=0;*/		/*the offset into the array tb*/
/*	unsigned char tempflipit;*/	/*to store value when inverting line*/
/*	int flipit;*/		/*the other counter when flipping a line*/
/*	int lmcounter=1;*/	/* local mccounter for sim_hand...*/

	xx=*x;			/*where we are in the file*/
/*the above(xx=*x) sets xx to the start of the line following the last \n
now if that is a blank line(e.g. a \n) then the count will get off when we
go back because there is an extra \n we didnt count on.  To fix, just do
xx--, which will not hurt if there is test, but will move before the \n*/
	xx--;

	while(xdoing)
	{
		while(xx >= 0 && xbreak)
		{		    /*1*/
/*
** will only do this branch iff we were going backwards on the first line
** trying to find the first character for displaying and we needed to read
** another chunk of data since there was a break
** e.g.
**     100 this is just a samp				{prev. chunk
**                            !
**                             le of what i mean	{current chunk
*/
			if(*mlcounter==0)
				goto moveon;
/*go right to processing; basically we are continuing were we left off when
 we were processing the line*/

			cc=bigbuf[xx--];
/*			if(cc=='\b')*/	/*handle nroff stuff*/
	/*			tb_count--;*/	/*overwrite*/
	/*		else
				tb[tb_count++]=cc;*/
			++*countchar;
			if(cc=='\n')	/*looking for nl's*/
			{
	/*			int local_tb;*/

/*				tb[--tb_count]='\0';*//*erase nl with NULL*/
	/*			tb_count--;*/	/*around NULL*/
/*				local_tb=tb_count;
				for(flipit=0;flipit<tb_count;flipit++,tb_count--)
				{
					tempflipit=tb[flipit];
					tb[flipit]=tb[tb_count];
					tb[tb_count]=tempflipit;
				}*/

				++*mlcounter;	/*passed in a negative*/
				--*countlines;	/*where we are*/
/*
				lmcounter=1;
				for(flipit=0;flipit<=local_tb;flipit++)
					if(tb[flipit]=='\t')
						sim_handle_tab(&lmcounter);
					else
						lmcounter++;
				if((*countlines<=test_top_of_form) && (lmcounter+1 > mcolumns))
				{
				}
*/
/*this was needed to get around when a longline is the very LAST line on the
current page, and the user presses b or ', then it would be off a line.
Not a very elegant fix(someday remove the global variable) but it works.
To simulate the problem.  /43/150'/200'/250'/247' end on line 42(vs 43)*/

				if(test_mlcounter)
				{
					test_mlcounter=FALSE;
					++*mlcounter;
				}

/*				tb_count=0;*/
/*
				printf("mlcount:%d countl:%d lmcounter:%d\n",*mlcounter,*countlines,lmcounter+1);
				fgetc(tty);*/

/*what happend was countchar>80 which ++mlcounter but that made mlcounter
go -1,0,..,2,3 and so on*/
/*don't use constant 79*/			/*80*/
/**took out 26aug95 fix ' bug	if(*countchar>mcolumns)
					++*mlcounter; ** */ /*may bump mlcounter >0*/

				*countchar=0;
			}
/*	will redraw the same page right, but wont go backwards..
			if(optl && lcount > 1)
			{
				xx+=2;
				++*countlines;
				*mlcounter=0;
			}
*/
/*here we test for going back the correct # of lines first, and if that isnt
 true, then we may be at the absolute beginning of the file*/
				/*may be >0*/
			if(*mlcounter >= 0)
			{
moveon:
				while((bigbuf[xx] != '\n') && (xx > -1))
					xx--;
				if(xx<=0)
/*will get here iff we are reading through the 1st line to find the beginning
 and we encounter a break in the file e.g. need a new chunk*/
					goto fin;

				xx+=1;	/*offset around ?\nhere*/
					/*		^  ^*/
					/*		x  |where we want*/
				*x=xx;	/*and set it to the point*/
				*mlcounter = 0;
				xbreak = FALSE;
				xdoing = FALSE;
				*boffset = FALSE;/*turn it off*/
			}
		}
		if(xdoing && *boffset)
		{
fin:
			*x=-1;	/*set to negative so we read next chunk*/
			return TRUE;
		}
	}
	return FALSE;
}
