/*****************************************************************
 *
 *  WrapGuide.c
 *  Copyright © 1994,1995 Udo Schuermann
 *  All rights reserved
 *
 *  -----------------------------------------------------------
 *
 *  With AmigaGuide V39 and later, .guide documents support
 *  proportonal fonts and wordwrapped text (as well as quite a
 *  few other goodes.)  Unfortunately, AmigaGuide V34, which is
 *  the version supported by Kickstart 2.x, not only fails to
 *  support these new features, but actually crashes the system
 *  when it encounters the long lines which AmigaGuide V39+
 *  would wrap into nice paragraphs.
 *
 *  WrapGuide, therefore, performs an (unconditional) wordwrap
 *  operation on any .guide file, converting blank spaces into
 *  newline characters so that AmigaGuide V34 is kept happy.
 *
 *  To the best of my knowledge, WrapGuide understands all the
 *  various '@' constructs that AmigaGuide understands.  Style
 *  symbols (such as "@{B}") and information not part of the
 *  visible text of links do not occupy "screen space" and
 *  WrapGuide knows this.
 *
 *  The program requires as parameters only the name of a
 *  .guide file.  If not given a 2nd parameter for the text
 *  width, it will use a default of 65 characters.
 *
 *  Limitations:  Lines (paragraphs) may not exceed 8K bytes
 *                in size; WrapGuide uses a static 8K buffer
 *                for its input lines.
 *                   You have the source code, however, so you
 *                should have no trouble altering this if you
 *                have the need.
 *
 *  WrapGuide is freely distributable.  Please do not separate
 *  the executable from the source code if you pass it on to
 *  others.  Naturally, if you merely include the binary with a
 *  project, you need not include the source code, but it would
 *  be nice if you did.
 *
 *  WrapGuide should be pretty much portable to any system.
 *
 *  If you find bugs in this software, have suggestions, or you
 *  make improvments to it, please let me know!  I can be reached
 *  by email as:  walrus@wam.umd.edu
 *
 *  Cheers & Support your Amiga!
 *
 *  ._.  Udo Schuermann
 *  ( )  walrus@wam.umd.edu
 *
 *****************************************************************
 */

#include <stdio.h>
#include <stdlib.h>


#define DEFAULTMARGIN 65
char VERSION[] = "$VER: WrapGuide 1.1 "__AMIGADATE__;
char buf[8192];      /* size of this buffer determines max line length */
short Margin;

void Usage(void) {

  printf("%s\n"
	 "Copyright © 1994,1995 Udo Schuermann\n"
	 "All rights reserved\n\n"
         "Usage: WrapGuide filename.guide [ textwidth ]\n"
	 "  Inserts newlines so that guide is readable without wordwrap.\n"
	 "  NOTE:\tThe default textwidth is %d and must be in range 50..999\n"
	 "\tThe given .guide file is modified directly!\n",
	 &VERSION[6],DEFAULTMARGIN);
  exit(10);
}

int main( int argc, char *argv[] ) {

  if( argc >= 2 ) {
    FILE *f;

    if( *argv[1] == '?' )
      Usage();

    if( argc > 2 ) {
      int i = atol(argv[2]);
      if( (i < 50) || (i > 999) ) {
	printf("WrapGuide: a textwidth of %ld is not allowed (50..999 is legal); using %d\n",i,DEFAULTMARGIN);
	Margin = DEFAULTMARGIN;
      } else
	Margin = i;
    } else
      Margin = DEFAULTMARGIN;

    if( f = fopen(argv[1],"r+") ) {
      unsigned long offset=0,i,pos;
//      unsigned long line=0;
      unsigned short dirty = 0;
      unsigned short best,col;

      while( fgets(buf,sizeof(buf),f) ) {
//	line++;
	pos = ftell( f );       /* find out where we are at the end of the line */

	best = 0;
	col = 1;

	/* our buffer now contains bytes 'offset' through 'pos'-1 */
	i = 0;
	while( buf[i] ) {
	  if( buf[i] == ' ' ) {                 /* a spot where line breaks are possible */
	    if( col < Margin )
	      best = i;
	    else {
	      if( buf[best] == ' ' )
		best = i;
	      else
		i = best;
	      buf[best] = '\n';
	      best = i+1;
	      col = 0;
	      dirty = 1;
	    }
	    col++;
	  } else
	    if( buf[i] == '\\' ) {              /* special escaped character, i.e. \@ */
	      if( buf[i+1] )
		i++;
	      col++;
	    } else
	      if( buf[i] == '@' ) {             /* possible link or style code */
		if( buf[i+1] == '{' ) {         /* ...only if followed by '{' */
		  i += 2;
		  while( buf[i] ) {
		    if( buf[i] == '"' )
		      break;
		    if( buf[i] == '}' )
		      break;
		    i++;
		  } /* while */
		  if( buf[i] == '"' ) {
		    i++;
		    while( buf[i] ) {
		      if( buf[i] == '\\' )
			i++;
		      else
			if( buf[i] == '"' )
			  break;
		      col++;
		      i++;
		    } /* while */
		    if( buf[i] == '"' ) {
		      i++;
		      while( buf[i] ) {
			if( buf[i] == '}' )
			  break;
			i++;
		      } /* while */
		    }
		  }
		} else {
		  if( i == 0 )  /* '@' WITHOUT following '{' in column 1 is a macro command */
		    break;
		}
	      } else
		col++;
	  i++;
	} /* while */
	
	if( (col >= Margin) && (buf[best] == ' ') ) {
	  buf[best] = '\n';
	  dirty = 1;
	} /* if */

	if( dirty ) {
	  fseek( f, offset, SEEK_SET );
	  fwrite( buf, 1, i-1, f );
	  fseek( f, pos, SEEK_SET );
	  dirty = 0;
	} /* if */

	offset = pos;           /* preparation for next loop */
      } /* while */

      fclose(f);
    } else {
      printf("WrapGuide: cannot open file (%s)\n",argv[1]);
      exit(20);
    }
  } else
    Usage();
} /* main() */

