#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dosextens.h>
#include <proto/dos.h>
#include <proto/exec.h>

#include "/lib/iomodes.h"
#include "/lib/misc.h"

char *mark="-------------------------------------------------------------";

#define MAXPAGES 100
#define LINELEN  256
#define PAGER_HELP "\
More help:\n\
  Q,q,^c - quit\n\
  r      - restart file\n\
  x      - restart in rot-13 mode\n\
  .      - no more nomore\n\
  f      - skip full page\n\
  b      - back one page\n\
  SPACE  - next page\n\
  CR,LF  - next line\n\
  others - next half page\n"

struct FileInfoBlock fib;
long pages[MAXPAGES];

void __regargs __chkabort(void);
void __regargs __chkabort(void){}
void chkabort(void) {}

void main(int argc,char *argv[])
{	char line[LINELEN],a,inte=IsInteractive(Output()),nomore=0,rot=0,clearscreen=0;
	int d,i,lines=0,skip=0,Rows,Columns,c,len,esc=0,start=1,j;
	FILE *handle;
	int  page=0,size;
	BPTR lock;

	printf("\033[0 p");	/* Hide cursor */
	pages[0]='\0';
	setmode(MODE_RAW);
	if(who(COM_GET,NULL,"rows",line))	Rows=24; /* default value */
	else								Rows=atoi(line);
	if(Rows<5)		Rows=25;
	if(Rows>100)	Rows=100;
	if(who(COM_GET,NULL,"columns",line))	Columns=80; /* default value */
	else									Columns=atoi(line);
	if(Columns<5)		Columns=80;
	if(Columns>500)		Columns=500;

	for(d=1;d<argc;d++)
	{
		if(argv[d][0]=='-')
		{
			start++;
			switch(argv[d][1])
			{
			case 's':
				clearscreen=TRUE;
				break;
			}
		}
		else
			break;
	}

	if(clearscreen)
		printf("\014");

	for(d=start;d<argc;d++)
	{
		if(lock=Lock(argv[d],ACCESS_READ))
		{
			Examine(lock, &fib);
			UnLock(lock);
			size = fib.fib_Size;
		}
		else
		{
			size = 0;
		}

		if(handle=fopen(argv[d],"rb"))
		{
			if(argc-start>1)
			{
				printf("\n%s\n%s\n%s\n",mark+strlen(mark)-strlen(argv[d]),argv[d],mark+strlen(mark)-strlen(argv[d]));
				lines+=3;
			}
			line[i=0]=0;
			while(!feof(handle))
			{
				i=strlen(line);
				if(fgets(line+i,LINELEN-2-i,handle)==NULL)
					break;

				i=len=0;
				while(c=line[i])
				{
					if(len>=Columns-1)
					{
						if(c!=0x0a)
						{
							c=0x0a;
							esc=strlen(line+i)+1;
							while(esc--)
								line[i+1+esc]=line[i+esc];
						}
						esc=0;
					}
					if(esc)
					{
						if(c!=';' && (c<'0' || c>'9'))
							esc=0;
					}
					else
					{
						switch(c)
						{
						case 0x0c:
							printf("^L\n");
							lines=Rows-1;	/* fall through */
						case 0x0a:
						case 0x0d:
							line[i]='\0';
							if(skip)
							{
								skip--;
								len=0;
								line[0]='\0';
								break;
							}
							if(line[0])
							{
								printf("%s\n",line);
							}
							else
								printf("\n");

							if((++lines>Rows-3 && !nomore && inte) || WaitForChar(Input(),1))
							{
								if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
								{
									printf("\n***Break***\n");
									setmode(MODE_CONSOLE);
									fclose(handle);
									printf("\033[ p");	/* Reveal cursor */
									exit(0);
								}
								if(page<MAXPAGES)
								{
									pages[++page]=ftell(handle);
								}
								else
								{
									for(j=0;j<MAXPAGES-1;j++)
										pages[j]=pages[j+1];
									pages[page-1]=ftell(handle);
								}
								do
								{
									if(WaitForChar(Input(),1))
									{
										Read(Input(),&a,1);
									}
									else
									{
										if(size)
											printf("\033[7mMore (%02d%%)?\033[m",100*ftell(handle)/size);
										else
											printf("\033[7mMore?\033[m");
										if(WaitForChar(Input(),120000000))
											Read(Input(),&a,1);
										else
											a=0x0a;
										if(size)
											printf("\b\b\b\b\b\b");
										printf("\b\b\b\b\b\033[K");
									}
									if(a=='h')
									{
										printf(PAGER_HELP);
									}
								}
								while(a=='h');

								switch(a)
								{
								case 'b':
									if(clearscreen)
										printf("\014");
									if(page>1)
									{
										printf("-- Back one page --\n");
										fseek(handle,pages[page-2],NULL);
										page-=2;
									}
									else
									{
										printf("-- Restart page --\n");
										fseek(handle,pages[page-1],NULL);
										page--;
									}
									lines=0;
									break;
								case 'x':
									if(clearscreen)
										printf("\014");
									fseek(handle,0,NULL);
									page=0;
									lines=0;
									rot=TRUE;
									break;
								case 'r':
									if(clearscreen)
										printf("\014");
									fseek(handle,0,NULL);
									page=0;
									lines=0;
									rot=FALSE;
									break;
								case '.':
									nomore=TRUE;
									break;
								case ' ':
									lines-=Rows-2;
									if(clearscreen)
										printf("\014");
									break;
								case 'f':
									if(clearscreen)
										printf("\014");
									printf("-skipped one page-\n");
									skip=Rows-2;
									lines-=Rows-2;
									break;
								case 0x0a:
								case 0x0d:
									lines--;
									break;
								case 'd':
									lines-=(Rows-2)/2;
									break;
								case 0x03:
								case 'q':
								case 'Q':
									printf("\n***Quit***\n");
									setmode(MODE_CONSOLE);
									fclose(handle);
									printf("\033[ p");	/* Reveal cursor */
									exit(0);
									break;
								default:
									lines-=(Rows-2)/2+1;	/* half page */
									break;
								}
							}
							if(lines<0)
								lines=0;

							if(line[i+1])
							{	strcpy(line,line+i+1);
								i=-1;
							}
							else
								line[0]='\0';
							len=0;
							/* line was cut */
							break;
						case 0x08:
						case 0x7f:
							if(len)
								--len;
							break;
						case 0x09:
							len=(len/8)*8+8;
							break;
						case 0x9b:
						case 0x1b:
							esc=-1;
							break;
						default:
							if(rot)
							{
								if(c>0x3f && c<0x5b)
									c=((c-0x40)+13)%26+0x40;
								if(c>0x5f && c<0x7b)
									c=((c-0x60)+13)%26+0x60;
								line[i]=c;
							}
							++len;
							break;
						}
					}
					i++;
				}
			}
			fclose(handle);
			if(i>1)
			{
				line[i-1]=0;
				printf("%s\n",line);
			}
			lines=Rows-4;
		}
		else
			fprintf(stderr,"Can't open file '%s'\n",argv[d]);
	}
	if(argc<2)
		fprintf(stderr,"Usage: 'more filename [file 2] .. [file n]'\n");
	printf("\033[ p");	/* Reveal cursor */
	setmode(MODE_CONSOLE);
}
