/*
Newsgroups: alt.sources
From: cloister@milton.u.washington.edu (cloister bell)
Subject: re-vamped PostScript to ascii-text converter.
Summary: modified to work real slick on .ps files from dvitps
Keywords: postscript converter
Organization: University of Washington
Date: Wed, 19 Feb 1992 03:13:58 GMT

I took the program posted here a couple of days ago, and found that it
produced less than satisfactory results on postscript files generated from
dvitps.  This version has been written to convert files from dvitps, which use
a lot of odd defined commands in order to save space in the file.  As near as
I can tell, it generates lines of ascii text that correspond to what lines of
text were in the PostScript file.  It should compile stock on any unix system
with cc.  So if you find yourself without a dvitotty program, but you do have
dvitps, this program will be useful should you find yourself stuck on a z19 or
something.

By: jason black, feb 18 1992

ps2txt.c extracts strings from a PostScript file.  This version has been 
modified to correctly deal with the oddities of PostScript files generated by 
dvi-to-PostScript converters, so if you keep this and the original program 
around, you might want to rename one of them.

Input can come from stdin, from '-' or from a file named on the command line:
		    	ps2txt file.ps
		 	cat file.ps | ps2txt 
			ps2txt - < file.ps
			etc.

VERSION:  1.1	Fixed bug dealing with comments.
	  1.2	By popular demand:  put spaces between strings.
	  2.0   fixed most problems of extraneous spaces and newlines
		between strings.
		added support for the ligatures ff, fi, fl, ffi, & ffl.
		re-designed the control structures, and otherwise cleaned
		up the code.

Originally by Iqbal Qazi.  This version has been about 98% re-written, so I'm
going to claim it as mine.

Comments/suggestions to cloister@u.washington.edu
*/

#include <stdio.h>
#define Putc(x) putchar(x);

void main(argc, argv)
int argc; 
char **argv;
{
  int ch,             /* current character */
      prev_ch = '\n', /* previously read character */
      in_paren = 0,   /* inside or outside of parentheses? */
      b_flag = 0,     /* true if previous character was ')' */
      b_space = 1;    /* true if a 'b' should produce a space */
  char junk[80];
  FILE *file, *source;

  if ((argc == 1) || ((argv[1][0] == '-') && (argv[1][1] == 0)))
    source = stdin;
  else
    if ((file=fopen(argv[1],"r"))!=NULL)
      source=file;
    else 
      {
	fprintf(stderr,"ps2txt: error opening file %s\n",argv[1]);
	exit(1);
      }
    
  while ((ch = fgetc(source)) != EOF)
    {
      if (ch == '\n') ch = fgetc(source);
      if (in_paren)              /* strings to print come inside parentheses */
	switch(ch)
	  {
	  case ')'  : in_paren--; b_flag=1; break; /* not in paren's anymore */
	  case '\n' : Putc(' '); break;              /* <cr> = ' ' in parens */
	  case '\\' : 
	    switch(ch=fgetc(source))
	      {
	      case '(' :
	      case ')' : Putc(ch); break;                         /* from \? */
	      case 't' : Putc('\t'); break;                   /* write a tab */
	      case 'n' : Putc('\n'); break;                  /* write a <cr> */
	      case '\\': Putc('"'); break;                    /* open quotes */
	      case '0' : switch(ch=fgetc(source))
		{
		case '1': switch(ch=fgetc(source))
		  {
		  case '3' : fputs("ff",stdout); break;         /* from \01? */
		  case '4' : fputs("fi",stdout); break;
		  case '5' : fputs("fl",stdout); break;
		  case '6' : fputs("ffi",stdout); break;
		  case '7' : fputs("ffl",stdout); break;
		  default: fputs("\\01",stdout); Putc(ch);   /* unknown code */
		  } break;                                       /* from \0? */
		default: fputs("\\0",stdout); Putc(ch);      /* unknown code */
		} break;
	      case '1' : case '2' : case '3' : case '4' :
	      case '5' : case '6' : case '7' : Putc('\\');   /* unknown code */
	      default: Putc(ch);
	      } break;                               /* from original switch */
	  default: Putc(ch);
	  }
      else                                                 /* not in paren's */
	switch(ch)
	  {
	  case '%'  : fgets(junk, 80, source); break;   /* toss out comments */
	  case '\n' : break;                /* skip <cr>'s outside of parens */
	  case '-'  : if (b_flag) 
	    {
	      b_flag = 0;                   /* because now prev. char != ')' */
	      b_space = 0;    /* but the number after ')' is negative, so no */
         /* space in case the letter code is 'b'.  the default is b_space = 1*/
	    } break;
	  case '('  : in_paren++;                    /* back in parens again */
	    switch(prev_ch)     /* check prev char to see if we need a space */
	      {
	      case 'l' : case 'm' : case 'n' : case 'o' : /* not for these 8 */
	      case 'q' : case 'r' : case 's' : case 't' : 
		break;
	      case 'y' : Putc('\n'); break;                /* need a newline */
	      case 'b' : if (b_space) Putc(' '); break; /* 'b' w/ a + number */
	      case 'a' : case 'c' : case 'd' : case 'e' : 
	      case 'f' : case 'g' : case 'h' : case 'i' : 
	      case 'j' : case 'k' : case 'x' : Putc(' '); break;
	      default: break;
	      } 
	    b_space = 1;              /* reset flag to default for next time */
	    break;
	  default: b_flag = 0; break;            /* junk stuff not in parens */
	  }
      prev_ch=ch;  /* remember this char in case !in_paren and next ch = '(' */
    }
}
