#include <stdio.h>
#include <string.h>

void end(char *text);
void map(char *str );
void readfile( FILE *file );
void printnode(char *name, int retrace);
void printline(char *line);
int  getword( char *src, char *dst );

typedef struct line {
	struct line *next;
	struct line *son;
	char   *prev;
	char   text[1];
} LINE;

FILE *infile;
LINE *FirstNode, *CurNode;
char Keys[4000], *Key;

void
main(int argc, char *argv[])
{
	char nodename[256];
	int  retrace=0;

	if( argc!=2 )
		end("Usage: minguide <filename>");

	if( !(infile=fopen(argv[1],"r")))
		end("Can't open input");

	readfile(infile);

	strcpy( nodename, "main" );
	do {
		printnode(nodename,retrace);
		retrace=0;

		fputs("\033[37m",stdout);
		fputs(CurNode->text,   stdout);
		fputs(">\033[31m ",stdout);
		fflush(stdout);

		gets( nodename );
		if( *nodename )
			map( nodename );
		if( !strcmp(nodename,":"))
			strcpy(nodename,"main");
		if( !strcmp(nodename,"/") && CurNode->prev)
			strcpy(nodename,CurNode->prev), retrace=1;
		if( !strcmp(nodename,"."))
			strcpy(nodename,CurNode->text), retrace=1;
	} while( strlen(nodename));

	end( NULL );
}

void
map( char *str )
{
	char *k;
	int  len=strlen(str);

	for( k=Keys; k<Key; k+=strlen(k)+1 )
		if( !strnicmp(str,k,len )) {
			strcpy(str,k);
			break;
		}
}


void
readfile( FILE *file )
{
	char buf[512], *t;
	LINE *line=NULL, *prevline=NULL;
	LINE *node=NULL, *prevnode=NULL;

	fgets(buf,512,file);
	if( strnicmp(buf,"@database",9))
		end("Not an AmigaGuide file");

	while( fgets(buf,512,file) ) {
		if( node && (!strnicmp(buf,"@node",5) || !strnicmp(buf,"@endnode",8))) {
			prevnode=node;
			node=NULL;
		}
		if( !strnicmp(buf,"@node",5)) {
			node= (void*)malloc( sizeof(*node)+strlen(buf));
			node->next=NULL;

			if(!(t=strchr( buf, ' ')))
				break;
			*t=0;
			strcpy( node->text, t+1 );
			if( (t=strchr( node->text, ' ')) || (t=strchr( node->text, '\n')))
				*t=0;

			if( prevnode ) 
				prevnode->next=node;
			else
				FirstNode=node;

			line=NULL;

		} else if( node ) {
			prevline=line;
			line= (void*)malloc( sizeof(*line)+strlen(buf));
			line->next=NULL;
			strcpy( line->text,buf );
			if( prevline ) 
				prevline->next=line;
			else 
				node->son= line;
		}
	}
}

void
printnode(char *name, int retrace)
{
	LINE *node, *line;
	int  len=strlen(name);

	for( node=FirstNode; node; node=node->next )
		if( !stricmp(node->text,name ))
			goto found;
	for( node=FirstNode; node; node=node->next )
		if( !strnicmp(node->text,name,len ))
			break;

found:
	if( !node )
		puts("Page not found");
	else {
		Key=Keys;
		if( !retrace )
			node->prev= CurNode->text;
		CurNode=node;
		for( line=node->son; line; line=line->next )
			printline(line->text);
	}
	fflush(stdout);
}

void
printline( char *s )
{
	char dest[512], *d=dest, *t;

	if( (t=strchr(s,'\n')))
		*t=0;

	if( *s=='@' )
		return;

	while( *s ) {
		if( s[0]=='@' && s[1]=='{' ) {
			*d++=27; *d++='['; *d++='7'; *d++='m';
			s+=2;
			s+=getword(s,d);
			d+=strlen(d);
			*d++=27; *d++='['; *d++='m';
			s+=getword(s,d);
			s+=getword(s,Key);
			Key+=strlen(Key)+1;
			while( *s && *s!='}' )
				s++;
			if( *s=='}' )
				s++;
		} else
			*d++=*s++;
	}
	*d++=0;
	puts( dest );
	fflush( stdout );
}

int
getword( char *src, char *d )
{
	char *s=src;

	while( *s==' ' )
		s++;

	while( *s && *s!=' ' && *s!='}')
		if( *s=='\"' ) {
			s++;
			while( *s && *s!='\"' )
				*d++=*s++;
			if( *s=='\"' )
				s++;
		} else 
			*d++=*s++;
	*d++=0;

	return s-src;
}

void
end(char *text)
{
	if( infile ) fclose(infile);
	if( text )   puts(text);
	exit(0);
}
