/*  Copyright (C) 1989 by Jingbai Wang

   This program is released to public as shareware.
   Any individual and institution can use, modify and distribute
   it freely provided the copyright note and the following box 
   are retained. One exeption is that profitable distribution (i.e., charge
   over the cost of materials and ship&handling) should have author's written
   permission.
                             */   

/* **********************************************************************
 *            This program is an auxiliary program for Scribe TEC.mak   *
 *                          desgined by myself.                         *
 *             It is used to manipulate Scribe PostScript output files  *
 *          or equally standard PostScript output from a text formatter *
 *             such that a long .ps file can be cut into shorter ones   *
 *             and double-sided documents can be separated into two     *
 *             .ps files for even-sided and odd-sided pages             *
 *                                                                      *
 *           The user can set up the programs for other purposes too    *
 *                    Copyright by Jingbai Wang August 1988             *
 ************************************************************************/

/*

   It is intended to have it adoptable to any systems. It is in my mind
   for VMS, MSDOS/PC-DOS and unix for the time being.
   
*/


#define STRSIZE 1024
#define FILEMAX 100
#define PROLENGTH 3600000

#define XM "XM"
#define MT "MT"

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

#define CLS fprintf(stderr, "\n\n\n\n");

/* Global variables */

char psfile[80]="",
     Prolog[PROLENGTH],
     outfile1[FILEMAX][80],
     outfile[80],
     evenfile[80],
     oddfile[80],
     prestring[80]="";
FILE *psfileptr, *Oddpage, *Evenpage, *Allpage;
int partnum=0,
    filestart[FILEMAX],
    fileend[FILEMAX],
    currentpage=0,
    file_flag=0;
long int prolength=0,
     pageend[1000];


int xm2mt = 1;
float current_x, current_y;

char string[1024];
get_prolog()
{
int l;

	prolength = 0;
while(1){
       fgets(&Prolog[prolength], 1024, psfileptr);
       if( memcmp(&Prolog[prolength], "%%EndProlog", 11)==0)
       {while (Prolog[++prolength] != 0) ;
       return;
       }
       else while (Prolog[++prolength] != 0) ;

        }
}

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

start_up();

  if (argc>1) {strcpy(psfile, argv[1]); file_flag=1;}

pro_info(); 
}


open_file()
{
int status, len, i, dot_check; 
dot_check=0;


if(file_flag==0)
       {CLS;        
        fprintf(stderr, "\n   PostScript file name (path and name)> ");
        scanf("%s", psfile);
       }


               len=strlen(psfile);
               for (i=0; i<len; i++)
               if (psfile[i]=='.') {dot_check=1;}

               if (dot_check==0) {strcat(psfile, ".ps");}

             
   if ( (psfileptr=fopen(psfile, "r"))==NULL)
      {fprintf(stderr, "  .ps file not found "); exit(-1);}


}


iris_ps() /* fix a Scribe PS for IRIS 4D psview */
{
int status, len, i, dot_check; 
int inhd, nothing=0;
char tmpn[80];
float tmp;
float red, green, blue;
int r, g, b;
#define BUFFSIZ 4096

if(file_flag==0)
       {CLS;        
        fprintf(stderr, "\n   PostScript file name (path and name)> ");
        scanf("%s", outfile);
       }
else strcpy(outfile, psfile);

        fprintf(stderr, "\n  Background RGB color in 255 (R G B)[255 255 255]> ");

        fgets(tmpn, 79, stdin);
        if (strlen(tmpn)==1)
	  {
	    nothing = 1;
	    red = blue = green = 1.0;
	  }
	else
	  {
        sscanf(tmpn, "%d %d %d", &r, &g, &b);
	red = r / 256.;
	green = g / 256.;
	blue = b / 256.;
      }


               len=strlen(psfile);
               for (i=0; i<len; i++)
               if (psfile[i]=='.') {dot_check=1;}

               if (dot_check==0) {strcat(psfile, ".ps");}

             sprintf(psfile, "%s~", outfile);

 /* swap the file first */

        if ((inhd = open(outfile, 0))<0)/* read only */
      {fprintf(stderr, "  .ps file not found "); exit(-1);}

        Allpage = fopen(psfile, "w"); /* write only */

   while ((len = read(inhd, Prolog, BUFFSIZ))>0)
     {
       Prolog[len] = 0;
       fputs(Prolog, Allpage);
     }

	  close(inhd);
	  fclose(Allpage);

	  open_file();
	  get_prolog();
        Allpage = fopen(outfile, "w"); /* write only */


  fputs(Prolog, Allpage);
if (!nothing)
  fprintf(Allpage, "/BS {/SV save def \n\
newpath -206 0 moveto 1034 0 rlineto 0 828 rlineto\n\
-1034 0 rlineto closepath gsave %.2f %.2f %.2f setrgbcolor fill grestore\n\
0.0 792.0 translate 0 0 0 setrgbcolor .01 -.01 scale} bind def\n", red, green, blue);

 while(1)
   {
 
     if( fgets(string, 1024, psfileptr)==NULL) 
      {
	fclose(Allpage); fclose(psfileptr);
        return;
      }

      len=strlen(string);

	if (xm2mt && len > 4) 
	{

	if (strncmp(&string[len-3], MT, 2)==0) sscanf(string, "%f %f",
	&tmp, &current_y);
	else
	  if (strncmp(&string[len-3], XM, 2)==0)
	   { sscanf(string, "%f", &current_x);
	     sprintf(string, "%.0f %.0f MT\n", current_x, current_y);
		}
      }

       fputs(string, Allpage);

   }




}

pro_info()
{
int i, yes, junk;
char tmpstr[40];

start:


CLS; 

fprintf(stderr, "\n            1. Get page mapping information\n");
fprintf(stderr, "            2. Extract some pages from the document\n");
fprintf(stderr, "            3. Divide document into parts\n");
fprintf(stderr, "            4. Split document into even and odd pages\n");
fprintf(stderr, "            5. Reverse the page numbers \n");
fprintf(stderr, "            6. Merge a few .ps files together\n");
fprintf(stderr, "            7. Fix converted zeta.lps file\n");
fprintf(stderr, "            8. Filter for IRIS psview\n");
fprintf(stderr, "            9. quit\n\n\n");

select:
yes = 0;
tmpstr[0] = 0;
fprintf(stderr, "                       Select a number from above ==> ");

 select1:
gets(tmpstr, 30, stdin);
if (tmpstr[0]==10 || tmpstr[0] == 13) {
tmpstr[0] = 0;
tmpstr[0] = 0;
fflush(stdin);
tmpstr[0] = 0;
fflush(stdout);
goto select1;
}

sscanf(tmpstr, "%d", &yes);
if (yes <=0 || yes > 9) goto select;

 switch(yes)
  {
    case 1: open_file(); page_map(); break;
    case 2: partnum=1; open_file(); get_prolog(); extract(); break;
    case 3: open_file(); get_prolog();
            fprintf(stderr, "\n\n   How many parts to divide>");
            scanf("%d", &partnum);
            fflush(stdin); divide(); break;
    case 4: open_file(); get_prolog(); even_odd(); break;
    case 5: open_file(); get_prolog(); reverse_page(); break;
    case 6: merge(); break;
    case 7: open_file(); fix_zeta();break;
    case 8: xm2mt = 1; iris_ps(); break;
    case 9: exit(-1);
  default: fprintf(stderr, "%c", 7); goto select;
  }


/*
hit_continue();              
 clear_up();
*/
goto start;

}


even_odd()
{
long int i;
int len;

  fprintf(stderr, "       Output file name odd pages > ");
        scanf("%s", oddfile);

  fprintf(stderr, "       Output file name even pages > ");
        scanf("%s", evenfile);

Evenpage=fopen(evenfile, "w");
Oddpage=fopen(oddfile, "w");

for (i=0; i<prolength; i++)
 { fprintf(Evenpage, "%c", Prolog[i]);
   fprintf(Oddpage, "%c", Prolog[i]);
 }

 while(1)
   {
     if( fgets(string, 1024, psfileptr)==NULL)
{
fclose(psfileptr);
fclose(Evenpage);
fclose(Oddpage);
return;
}

       fprintf(Oddpage, "%s", string);
     if (memcmp(string, "%%Page:", 7)==0) {
       len=strlen(string);  string[len-2]=0;     
      fprintf(stderr, "[%s]", &string[8]);
      }


     if( fgets(string, 1024, psfileptr)==NULL) 
{
fclose(psfileptr);
fclose(Evenpage);
fclose(Oddpage);
return;
}
     
       fprintf(Evenpage, "%s", string);
    if (memcmp(string, "%%Page:", 7)==0)
      {
       len=strlen(string);  string[len-2]=0;     
      fprintf(stderr, "[%s]", &string[8]);
      }
   }




}


extract() /* extract a page */
{
char tmpstr[80];

  fprintf(stderr, "\n      Filename for output > ");
        scanf("%s", outfile);
  Allpage=fopen(outfile, "w");

    fprintf(stderr, "       Starting page >");
	scanf("%s", tmpstr);
    sscanf(tmpstr, "%d", &filestart[0]);
	tmpstr[0] = 0;

  fprintf(stderr, "       End page >");
	scanf("%s", tmpstr);
  sscanf(tmpstr, "%d", &fileend[0]);


     while(currentpage<filestart[0])
        {
         if(  (fgets(string, 1024, psfileptr))==NULL) 
            {fclose(Allpage); fclose(psfileptr);return;}
         if (memcmp(string, "%%Page:", 7)==0) currentpage++;
        }
          strcpy(prestring,string);


go(0); fclose(Allpage); fclose(psfileptr);

}



divide()
{
int i;

  for (i=0; i<partnum; i++)
 {
   fprintf(stderr, "\n      Filename for output part %d> ", i+1);
        scanf("%s", outfile1[i]);

  if (i==0)
    { fprintf(stderr, "       Part %d starts at page # >", i+1);
      scanf("%d", &filestart[i]);
      fflush(stdin);

    } 
    else filestart[i]=fileend[i-1]+1;

    fprintf(stderr, "       Part %d ends at page # >", i+1);
    scanf("%d", &fileend[i]);
    fflush(stdin);

 }


if (filestart[0]>1){
     while(currentpage<filestart[0]) /* get rid of the overhead */
        {
         if(  (fgets(string, 1024, psfileptr))==NULL) return;
         if (memcmp(string, "%%Page:", 7)==0) currentpage++;
        }
          strcpy(prestring,string);

     }



  for (i=0; i<partnum; i++)
 {
  fprintf(stderr, "\n%s:\n", outfile1[i]);
  Allpage=fopen(outfile1[i], "w");
  go(i); fclose(Allpage);
 }

fclose(psfileptr);
}

go(number)
int number;
{
int i;
int len;
float tmp;

  fputs(Prolog, Allpage);

  len=strlen(prestring);
    if (len>0) { fprintf(Allpage, "%s", prestring); 
      prestring[len-1]=0;/* get rid of <CR> */
      fprintf(stderr, "[%s]", &prestring[8]);           }     


 while(1)
   {
 
     if( fgets(string, 1024, psfileptr)==NULL) 
      {
        return;
      }

      len=strlen(string);

	if (xm2mt && len > 4) 
	{

	if (strncmp(&string[len-3], MT, 2)==0) sscanf(string, "%f %f",
	&tmp, &current_y);
	else
	if (strncmp(&string[len-3], XM, 2)==0)
	   { sscanf(string, "%f", &current_x);
	     sprintf(string, "%.0f %.0f MT\n", current_x, current_y);
		}
	else
	     if (memcmp(string, "%%Page:", 7)==0) {currentpage++;
        	if (currentpage>fileend[number]) {strcpy(prestring, string);
	         return;} 

		  string[len-1]=0;     /* get rid of <CR> */
	      fprintf(stderr, "[%s]", &string[8]);
		  string[len-1]=10;
	      }

	}
	else
	     if (memcmp(string, "%%Page:", 7)==0) {currentpage++;
        	if (currentpage>fileend[number]) {strcpy(prestring, string);
	         return;} 

		  string[len-1]=0;     /* get rid of <CR> */
	      fprintf(stderr, "[%s]", &string[8]);
		  string[len-1]=10;
	      }


       fprintf(Allpage, "%s", string);

   }

}


page_map()
{
int count, len;

fprintf(stderr, "     Map file filename for output (2 <Return> for screen)-> ");
fflush(stdin);
scanf("%s", outfile);
if (outfile[0]=='2') Allpage=stderr;
else Allpage=fopen(outfile, "w");

fprintf(stderr , "\n\n");

while(1)
   {
     if( fgets(string, 1024, psfileptr)==NULL) 
      {
       fclose(psfileptr); 
       if (Allpage!=stderr) fclose(Allpage);
       return;
       }


     if (memcmp(string, "%%Page:", 7)==0) {currentpage++;
       len=strlen(string);  string[len-1]=0; count++;     
     if (count>10) {count=0; fprintf(Allpage, "\n");}      
      fprintf(Allpage, "[%s]", &string[8]);
      }


    }

}


reverse_page()
{
int i;
long int j;
 

fprintf(stderr, "     Filename for output file -> ");
fflush(stdin);
scanf("%s", outfile);
Allpage=fopen(outfile, "w");

for (i=0; i<prolength; i++)
  {fprintf(Allpage, "%c", Prolog[i]); Prolog[i]=0;}

prolength=0; currentpage=0;
       pageend[0]=0;

 while(1)
   {
     if( fgets(string, 1024, psfileptr)==NULL) 
      {
        fclose(psfileptr);
        goto out;
      }
       strcat(Prolog, string);
       
     if (memcmp(string, "%%Page:", 7)==0) {currentpage++;
         pageend[currentpage]=prolength;        
      }
       
       prolength += strlen(string);

   }

out:

         for (j=pageend[currentpage]; j<prolength; j++)
            fprintf(Allpage, "%c", Prolog[j]);


    for (i=currentpage; i>0; i--)
       {
         for (j=pageend[i-1]; j<pageend[i]; j++)
            fprintf(Allpage, "%c", Prolog[j]);
       }     

        fclose(Allpage);

}


start_up()

{
char junk;
CLS; 


fprintf(stderr, "               Welcome to Textformatter .ps File Manager\n");
fprintf(stderr, "                          by JB Wang, 1989\n\n");

fprintf(stderr, "     This utility program can be used to 1) extract certain pages to be\n\
     printed; 2) divide the .ps file into a few smaller files;  3) split \n\
     the document into two files for odd and even pages; 4) reverse the\n\
     page numbering; 5) Merge .ps files in intelligent way; 6) Fix a converted\n\
     zeta.plt PostScript file at Pitt\n\n");

fprintf(stderr, "\
     Text formatter .ps output file is composed of a prologue, a main body\n\
     of pages, and a trailer. Each page carries two page numbers,\n\
     that is, the physical page number (printed) and a counter number\n\
     that accumulates from 1 to the end. The program can provide the\n\
     mapping information between these two numbers in the following format\n\
     [page_number counter_number].\n\n");

fprintf(stderr, "     This program uses the counter number instead of the physical number.\n\
     Therefore, you are advised to get the mapping information before\n\
     you output files.\n\n\n");

fprintf(stderr, "                                Hit <Return> to continue -->");

scanf("%c", &junk);
fflush(stdin);

}


merge()
{
int i;

fprintf(stderr, "\n\n  How many files to merge? ");
scanf("%d", &partnum);
fflush(stdin);

if (file_flag==1) 
  {strcpy(outfile, psfile);
  fprintf(stderr, "\n      Filename for output > %s", outfile);
  }
else {
  fprintf(stderr, "\n      Filename for output > ");
        scanf("%s", outfile);
     }
  Allpage=fopen(outfile, "w");

  for (i=0; i<partnum; i++)
 {
again:
   fprintf(stderr, "       File %d  to merge >", i+1);
        scanf("%s", outfile1[i]);
   if ( (psfileptr=fopen(outfile1[i], "r"))==NULL)
      {fprintf(stderr, "  .ps file not found "); goto again;}
       fclose(psfileptr);
 }

  for (i=0; i<partnum; i++)
 {
   psfileptr=fopen(outfile1[i], "r");
   if (i>0)  get_prolog();
    while(fgets(string, 1024, psfileptr)!=NULL) 
    fprintf(Allpage, "%s", string);    
   fclose(psfileptr);
  }

}


fix_zeta()
{
int i;
char ch;

  fprintf(stderr, "\n      Filename for output > ");
        scanf("%s", outfile);

for (i=0; i<685; i++)
  fgetc(psfileptr);

if (fgetc(psfileptr)!='d') 
{ fclose(psfileptr); 
fprintf(stderr, "\n     Wrong version of converted .lps file");
return;
}

  fgetc(psfileptr);  fgetc(psfileptr); 
  Allpage=fopen(outfile, "w");

fprintf(Allpage, "%%!\n\
/s { 72 mul 300 div } def /steps { 72 mul 2032 div } def /d { count 0 gt  { s exch s exch moveto { count 0 gt \n\
{ s exch s exch lineto } { exit } ifelse } loop 0.3 setlinewidth stroke clear } if } def /g { count 0 gt  { s exch s exch moveto\n\
{ count 0 gt { s exch s exch lineto } { exit } ifelse } loop [3 5] 0 setdash 0.5 setlinewidth stroke clear [] 0 setdash } if } def\n\
/h { /Courier findfont 6 scalefont setfont  -6 -26  moveto } def /f { -6 -16 moveto } def\n\
 /n { d newpath } def /a0 { arc stroke } def  /a1 { arcn stroke } def /mr { moveto rotate } def\n\
 /cf { /Courier findfont } def /ss { scalefont setfont } def  /ur { rotate } def  /dd { [] 0 setdash } def d\n");


while ((ch=fgetc(psfileptr))!=EOF)
    fprintf(Allpage, "%c", ch);

fclose(psfileptr);
fclose(Allpage);
}


hit_continue()
{
char junk;

fprintf(stderr, "\n\n                           Hit <Return> to continue -->");

fflush(stdin);
fflush(stdin);
fflush(stdin);
scanf("%c", &junk);
fflush(stdin);              

}

clear_up()
{
long int i;

   partnum=0;
  for (i=0; i<prolength; i++)
    Prolog[i]=0;
  prolength=0;
  strcpy(prestring, "");
  currentpage=0;
  file_flag=0;
}
