// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

// mpaddock@cix.compulink.co.uk

// Convert .guide file (MakeGuide --amiga-39 ...) to .doc

// This program is a complete hack which will only work in specific cases!!!
// It is based on AG2TXT from which the following is quoted:

// This program (even if it is small) is Copyright (c) 1993 Jason R. Hulance.
// Apart from that the Gnu Public License holds.  You can contact me by E-mail
// at "m88jrh@ecs.oxford.ac.uk".

#include <stdio.h>
#include <proto/dos.h>
#include <string.h>
#include <stdlib.h>

enum {NONE, ATSIGN, TILLEND, BRAC, BRACSEND, TILLBRAC,
     GOT_N, GOT_O, GOT_D, GOT_E, SKIPARG, NODE, NODESEND}
	got;

enum {ERR_SHORT, ERR_MEM, ERR_IO, ERR_FILE, ERR_ARGS, ERR_NONE}
	err;

enum {ARG_FROM, ARG_TO, ARG_NODEFONT, ARG_LINKFONT}
	arg;

enum {NODEFONT, LINKFONT}
	font;

#define QUOTE 34
#define RET '\n'
#define ESC 27
#define FONT_BOLD '1'
#define FONT_ITALIC '3'
#define FONT_REVERSE '7'
#define FONT_NORMAL '0'
#define FONT_UNDERLINE '4'

void setfont(char * str,int ind);

char myfont[2] = {FONT_REVERSE,FONT_ITALIC};

const char vers[]="$VER: ag2txt 4.0 (28.6.95)";

int main(void) {
	int state=NONE;
	int quote;
	char *in;
	char *out;
	char *max;
	LONG args[4] = {0,0,0,0};
	BOOL ok = FALSE;
	FILE *from,*to;
	char *bin,*bout=NULL;
	int len;
	struct RDArgs *rdargs;
	if (rdargs = ReadArgs("FROM/A,TO/A,NODEFONT=NODE/K,LINKFONT=LINK/K",
									args,NULL)) {
		if (from = fopen((char *)args[ARG_FROM],"r")) {
			fseek(from,0,2);
			if (len = ftell(from)) {
				rewind(from);
				if (to = fopen((char *)args[ARG_TO],"w")) {
					if (args[ARG_NODEFONT]) {
						setfont((char *)args[ARG_NODEFONT],NODEFONT);
					}
					if (args[ARG_LINKFONT]) {
						setfont((char *)args[ARG_LINKFONT],LINKFONT);
					}
					if ((bin = (char *)malloc(len)) && (bout = (char *)malloc(len))) {
						fread(bin,len,1,from);
						in = bin;
						out = bout;
						max = bin+len;
						// Skip till main Node
						while ((in<max) && (state == NONE)) {
							if ((*in == '@') && (in[1] == 'N')) {
								state = ATSIGN;
							}
							in++;
						}
						if (in < max) {
							in--;
						}
						state = NONE;
						while (in<max) {
							switch (state) {
							case NONE:
								if (*in == '@') {
									if (in[1] == '{') {
										state = BRAC;
										in++;
									}
									else {
										if ((in == bin) || (in[-1] == RET)) {
											state = ATSIGN;
										}
										else {
											*out++ = *in;
										}
									}
								}
								else {
									*out++ = *in;
								}
								break;
							case ATSIGN:
								if ((*in == 'N') || (*in == 'n')) {
									state = GOT_N;
								}
								else {
									state = TILLEND;
								}
								break;
							case TILLEND:
								if (*in == RET) {
									state = NONE;
								}
								break;
							case BRAC:
								if (*in == 'b') {
									*out++ = ESC;
									*out++ = '[';
									*out++ = FONT_BOLD;
									*out++ = 'm';
									in++;
									state = NONE;
								}
								else {
									if ((*in == 'u') && (in[1] != '}')) {
										*out++ = ESC;
										*out++ = '[';
										*out++ = FONT_NORMAL;
										*out++ = 'm';
										in++;
										in++;
										state = NONE;
									}
									else {
										if (*in == 'u') {
											*out++ = ESC;
											*out++ = '[';
											*out++ = FONT_UNDERLINE;
											*out++ = 'm';
											in++;
											state = NONE;
										}
										else {
											if (*in == 'i') {
												*out++ = ESC;
												*out++ = '[';
												*out++ = FONT_ITALIC;
												*out++ = 'm';
												in++;
												state = NONE;
											}
											else {
												if (*in != ' ') {
													quote = (*in == QUOTE);
													*out++ = ESC;
													*out++ = '[';
													*out++ = myfont[LINKFONT];
													*out++ = 'm';
													state = BRACSEND;
												}
											}
										}
									}
								}
								break;
							case BRACSEND:
								if ((quote && (*in == QUOTE)) || (!quote && (*in == ' '))) {
									*out++ = ESC;
									*out++ = '[';
									*out++ = FONT_NORMAL;
									*out++ = 'm';
									state = TILLBRAC;
								}
								else {
									*out++ = *in;
								}
								break;
							case TILLBRAC:
								if (*in == '}') {
									// pad extra space (for V39)
									if (in[1] != '.') {
										*out++ = ' ';
									}
									state = NONE;
								}
								break;
							case GOT_N:
								if ((*in == 'O') || (*in == 'o')) {
									state = GOT_O;
								}
								else {
									state = TILLEND;
								}
								break;
							case GOT_O:
								if ((*in == 'D') || (*in == 'd')) {
									state = GOT_D;
								}
								else {
									state = TILLEND;
								}
								break;
							case GOT_D:
								if ((*in == 'E') || (*in == 'e')) {
									state = GOT_E;
								}
								else {
									state = TILLEND;
								}
								break;
							case GOT_E:
								if (*in != ' ') {
									quote = (*in == QUOTE);
									state = SKIPARG;
								}
								break;
							case SKIPARG:
								if ((quote && (*in == QUOTE)) || (!quote && (*in == ' '))) {
									state = NODE;
								}
								break;
							case NODE:
								if (*in != ' ') {
									quote = (*in == QUOTE);
									*out++ = ESC;
									*out++ = '[';
									*out++ = myfont[NODEFONT];
									*out++ = 'm';
									state = NODESEND;
								}
								break;
							case NODESEND:
								if ((quote && (*in == QUOTE)) || (!quote && (*in == ' ')) || (*in == RET)) {
									*out++ = ESC;
									*out++ = '[';
									*out++ = FONT_NORMAL;
									*out++ = 'm';
									*out++ = RET;
									*out++ = RET;
									if (*in == RET) {
										state = NONE;
									}
									else {
										state = TILLEND;
									}
								}
								else {
									*out++ = *in;
								}
								break;
							default:
								*out++ = *in;
								break;
							}
							in++;
						}
						fwrite(bout,out - bout,1,to);
						ok = TRUE;
					}
					else {
						printf("Error allocating memory\n");
					}
					if (bin) {
						free(bin);
					}
					if (bout) {
						free(bout);
					}
					fclose(to);
				}
				else {
					printf("Error opening TO\n");
				}
			}
			else {
				printf("FROM empty\n");
			}
			fclose(from);
		}
		else {
			printf("Error opening FROM\n");
		}
		FreeArgs(rdargs);
	}
	else {
		printf("Error in ReadArgs\n");
	}
	if (ok) {
		return 0;
	}
	else {
		return 10;
	}
}

void setfont(char * str,int ind) {
  if (!(stricmp(str, "PLAIN"))) {
		myfont[ind]=FONT_NORMAL;
		return;
	}
  if (!(stricmp(str, "ITALIC"))) {
		myfont[ind]=FONT_ITALIC;
		return;
	}
  if (!(stricmp(str, "REVERSE"))) {
		myfont[ind]=FONT_REVERSE;
		return;
	}
  if (!(stricmp(str, "BOLD"))) {
		myfont[ind]=FONT_BOLD;
		return;
	}
  if (!(stricmp(str, "UNDERLINE"))) {
		myfont[ind]=FONT_UNDERLINE;
		return;
	}
}
