// ------------------------------- //
// -------- Start of File -------- //
// ------------------------------- //
// ----------------------------------------------------------- // 
// C++ Source Code File Name: as2ps.cpp
// Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
// Produced By: Doug Gaer 
// File Creation Date: 12/17/1997
// Date Last Modified: 03/31/1999
// ----------------------------------------------------------- // 
// ------------- Program Description and Details ------------- // 
// ----------------------------------------------------------- // 
/*
ASCII to PostScript converter program.
*/
// ----------------------------------------------------------- // 
#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include <stdlib.h> 
#include <stdio.h>
#include "as2ps.h"

// AS2PS program globals
int VerboseMode = 0;     // Echo results (off by default)
char out_file[MAX_LINE]; // PostScript file created from text file
char time_buf[255];      // Buffer used to hold time/date string
char *open_file;         // File currently open
int write_to_file = 0;   // Write the output to a file instead of stdout
unsigned num_files = 0;   // Total number of files processed

// Setup as2ps default values
PostScriptDrv::PSFonts font_code = PostScriptDrv::COURIER; 
PostScriptDrv::PSPaperSizes paper_code = PostScriptDrv::LETTER_SIZE; 
double font_size = DEFAULT_POINT_SIZE; // Font or pitch size
double lr_margin = DEFAULT_LR_MARGIN;  // Left and Right margins
double tb_margin = DEFAULT_TB_MARGIN;  // Top and Bottom margins 
int man_page = 0;   // Format UNIX man page
int cut_lines = 1;  // Truncate lines to match the number of columns
int wrap_lines = 0; // Turn line wrap on or off
int duplex = 0;     // Enable duplex printing
int manualfeed = 0; // Print from manual feed position
int use_tray = 0;   // Use a specified paper tray
int tray_number;    // Tray number for the paper tray

void HelpMessage(const char *program_name, const double version_number)
{
  char vbuffer[255];
  sprintf(vbuffer, "%.3f", version_number);
  cout << endl;
  cout << "ASCII to PostScript Converter version " << vbuffer << endl;
  cout << "Usage: " << program_name << " [switches] infile.txt " << endl;
  cout << "Switches: -?      = Display this help message." << endl;
  cout << "          -c#     = Number of copies to print. Example: -c2"
       << endl;
  cout << "          -d      = Enable duplex printing if available." << endl;
  cout << "          -D      = Print from manual feed position." << endl;
  cout << "          -fcode  = Select a font type. Example: -fC" << endl;
  cout << "          -F      = Write output to a file: infile.txt = infile.ps"
       << endl;
  cout << "          -h      = Use page headers and numbers."
       << endl;
  cout << "          -H      = Use page headers and numbers with lines."
       << endl;
  cout << "          -l      = Print in landscape mode instead of portrait."
       << endl;
  cout << "          -m#     = Set left and right margins. Example: -m1.0"
       << endl;
  cout << "          -M#     = Set top and bottom margins. Example: -M1.0"
       << endl;
  cout << "          -pcode  = Select a paper size. Example: -pLET" << endl;
  cout << "          -s#     = Specify font size. Example: -s10.0" << endl;
  cout << "          -t#     = Spaces between tab stops. Example: -t8"
       << endl;
  cout << "          -T      = Do not truncate lines that exceed margin."
       << endl;
  cout << "          -u      = Format UNIX man pages produced by nroff."
       << endl;
  cout << "          -v      = Turn verbose mode on." << endl;
  cout << "          -W      = Turn line wrap on." << endl;
  cout << "          -y#     = Use a specified paper tray. Example: -y1"
       << endl;
  cout << endl;
  cout << "Press enter to continue..." << endl;
  cin.get();

  cout << "Valid font codes for -f option: " << endl;
  cout << endl;
  cout << "\tC - Courier, CB - Courier-Bold, CO - Courier-Oblique,"  << endl;
  cout << "\tCBO - Courier-BoldObligue, T - Times-Roman, TB - Times-Bold"
       << endl;
  cout << "\tTI - Times-Italic, TBI - Times-BoldItalic, H - Helvetica" << endl;
  cout << "\tHBO - Helvetica-BoldOblique, HO - Helvetica-Oblique, " << endl;
  cout << "\tHB - Helvetica-Bold,  S - Symbol" << endl;

  cout << endl;
  cout << "Valid paper codes for -p option: " << endl;
  cout << endl;
  cout << "\tLET - Letter size  8.5 x 11 inches" << endl;
  cout << "\tLEG - Legal size   8.5 x 14 inches" << endl;
  cout << "\tTAB - Tabloid size 11 x 17 inches" << endl;
  cout << "\tA3  - A3 size 297mm x 420mm (11.70 x 16.55 inches)" << endl;
  cout << "\tA4  - A4 size 210mm x 297mm (8.27 x 11.70 inches)" << endl;
  exit(0);
}

// Process Program argument list
PostScriptDrv ProcessArgs(int argc, char *argv[])
{
  // Establish default values
  PostScriptDrv psdrv;
  int ibuf;
  char *sbuf;
  
  // process the program's argument list
  int i;
  for(i = 1; i < argc; i++ ) {
    if(*argv[i] == '-') {
      char sw = *(argv[i] +1);
      switch(sw) {
	case '?' :
	  HelpMessage(ProgramName, ASPSVersionNumber);
	  break;

	case 'c' :
	  ibuf = atoi(&argv[i][2]);
	  if(ibuf <= 0) ibuf = 1;
	  psdrv.Copies(ibuf);
	  break;

	case 'F':
	  write_to_file = 1;
	  break;
	  
	case 'l' :
	  psdrv.LandScapeMode();
	  break;

	case 'm' :
	  lr_margin = atof(&argv[i][2]);
	  if(lr_margin <= 0)
	    lr_margin = DEFAULT_LR_MARGIN;
	  psdrv.UseLRMargin();
	  break;

	case 'M' :
	  tb_margin = atof(&argv[i][2]);
	  if(tb_margin <= 0)
	    tb_margin = DEFAULT_TB_MARGIN;
	  psdrv.UseTBMargin();
	  break;

	case 's' : 
	  font_size = atof(&argv[i][2]);
	  if(font_size <= 0)
	    font_size = DEFAULT_POINT_SIZE;
	  break;
	
	case 't' :
	  ibuf = atoi(&argv[i][2]);
	  if(ibuf < 1) ibuf = DEFAULT_TAB_SIZE;
	  psdrv.SetTabStop(ibuf);
	  break;

	case 'v' :
	  VerboseMode = 1;
	  break;

	case 'f' :
	  sbuf = &argv[i][2]; 
	  if(strcmp(sbuf, "C") == 0) font_code = PostScriptDrv::COURIER;
	  if(strcmp(sbuf, "CB") == 0) font_code = PostScriptDrv::COURIER_BOLD;
	  if(strcmp(sbuf, "CO") == 0)
	    font_code = PostScriptDrv::COURIER_OBLIQUE;
	  if(strcmp(sbuf, "CBO") == 0)
	    font_code = PostScriptDrv::COURIER_BOLD_OBLIQUE;

	  if(strcmp(sbuf, "T") == 0) font_code = PostScriptDrv::TIMES;
	  if(strcmp(sbuf, "TB") == 0) font_code = PostScriptDrv::TIMES_BOLD;
	  if(strcmp(sbuf, "TI") == 0) font_code = PostScriptDrv::TIMES_ITALIC;
	  if(strcmp(sbuf, "TBI") == 0)
	    font_code = PostScriptDrv::TIMES_BOLD_ITALIC;

	  if(strcmp(sbuf, "H") == 0) font_code = PostScriptDrv::HELV;
	  if(strcmp(sbuf, "HB") == 0) font_code = PostScriptDrv::HELV_BOLD;
	  if(strcmp(sbuf, "HO") == 0) font_code = PostScriptDrv::HELV_OBLIQUE;
	  if(strcmp(sbuf, "HBO") == 0)
	    font_code = PostScriptDrv::HELV_BOLD_OBLIQUE;

	  if(strcmp(sbuf, "S") == 0) font_code = PostScriptDrv::SYMBOL;
	  break;
	  
	case 'p' :
	  sbuf = &argv[i][2]; 
	  if(strcmp(sbuf, "LET") == 0)
	    paper_code = PostScriptDrv::LETTER_SIZE;
	  if(strcmp(sbuf, "LEG") == 0)
	    paper_code = PostScriptDrv::LEGAL_SIZE;
	  if(strcmp(sbuf, "TAB") == 0)
	    paper_code = PostScriptDrv::TABLOID_SIZE;
	  if(strcmp(sbuf, "A3") == 0)
	    paper_code = PostScriptDrv::A3_SIZE;
	  if(strcmp(sbuf, "A4") == 0)
	    paper_code = PostScriptDrv::A4_SIZE;
	  break;
	  
	case 'u' :
	  man_page = 1;
	  cut_lines = 0;
	  wrap_lines = 0;
	  break;

	case 'T' :
	  cut_lines = 0;
	  break;

	case 'W' :
	  wrap_lines = 1;
	  cut_lines = 0;
	  break;
	  
	case 'd' :
	  duplex = 1;
	  break;

	case 'D' :
	  manualfeed = 1;
	  break;

	case 'y' :
	  use_tray = 1;
	  tray_number = atoi(&argv[i][2]);
	  break;

	case 'h' :
	  psdrv.UseHeader();
	  break;
	  
	case 'H' :
	  psdrv.UseHeader();
	  psdrv.DrawHeaderLine();
	  break;
	  
	default:
	  cerr << endl;
	  cerr << "Unknown switch " << argv[i] << endl;
	  cerr << "Exiting..." << endl;
	  cerr << endl;
	  exit(0);
	  break;
      }
    }
  }

  return psdrv;
}

int GenOutputFileName(char *extension)
// Generate a name for the output file using the open_file
// name with the specified dot extension.
{
  unsigned i = 0;
  for(i = 0; i < MAX_LINE; i++) out_file[i] = '\0';
  char *p = open_file;
  unsigned len = strlen(p);
  for(i = 0; i < len && i != MAX_LINE; i++, p++) {
    if(*p == '.') break;
    out_file[i] = *p;
  }
  if((strlen(out_file) + strlen(extension)) > (MAX_LINE - 1)) return 0;
  strcat(out_file, extension); // Add the file extension (.xxx)
  return 1;
}

void DocumentSetup(PostScriptDrv &psdrv)
{
  psdrv.SetPaperSize(paper_code);
  psdrv.SetFont(font_code, font_size);
  if(psdrv.UsingHeader()) {
    psdrv.SetDocumentName(open_file);
    GetSystemTime(time_buf);
    psdrv.SetDateString(time_buf);
  }
  
  psdrv.DocumentSetup(lr_margin, tb_margin, man_page);
  
  if(VerboseMode) {
    cout << "Font            = " << psdrv.TextFont() << endl;
    cout << "Font Size       = " << psdrv.FontSize() << endl;
    cout << "Character width = " << psdrv.CharWidth() << endl;
    cout << "Chars Per inch  = " << psdrv.CharsPerInch() << endl;
    cout << "Columns         = " << psdrv.Columns() << endl;
    
    cout << "Paper size      = ";
    if(paper_code == PostScriptDrv::LETTER_SIZE) cout << "LETTER" << endl;
    if(paper_code == PostScriptDrv::LEGAL_SIZE) cout << "LEGAL" << endl;
    if(paper_code == PostScriptDrv::TABLOID_SIZE) cout << "TABLOID" << endl;
    if(paper_code == PostScriptDrv::A3_SIZE) cout << "A3" << endl;
    if(paper_code == PostScriptDrv::A4_SIZE) cout << "A4" << endl;
    
    cout << "Page width      = " << psdrv.PageWidth() << endl;
    cout << "Page height     = " << psdrv.PageHeight() << endl;
    cout << "Starting X pos  = " << psdrv.StartX() << endl;
    cout << "Starting Y pos  = " << psdrv.StartY() << endl;
    cout << "Lines per page  = " << psdrv.LinesPerPage() << endl;
    
    cout << "Copies          = " << psdrv.NCopies() << endl;    
    cout << "Tab Stop Spaces = " << psdrv.TabStop() << endl;
   
    cout << "Input text file = " << open_file << endl;
    if(write_to_file == 0 ) { 
      cout << "Output PS file  = stdout" << endl;
    }
    else {
      GenOutputFileName(".ps");
      cout << "Output PS file  = " << out_file << endl;
    }
    if(psdrv.GetMode()) cout << "Printing in landscape mode" << endl;
    if(psdrv.UsingLRMargin()) cout << "Using left and right margins" << endl;
    if(psdrv.UsingTBMargin()) cout << "Using top and bottom margins" << endl;
    cout << endl;
    cout << "Press enter to continue..." << endl;
    cin.get();
  }
}

int main(int argc, char *argv[])
// NOTE: None of the MSVC compilers will expand wildcard characters
// used in command-line arguments unless linked with the setargv.obj
// library. All the UNIX compliers will expand wildcard characters
// by default.
{
  // If no argument is given print usage message to the screen 1
  if(argc < 2) {
    HelpMessage(ProgramName, ASPSVersionNumber);
    return(0);
  }

  // Process command ling arguments and files 
  int narg;
  PostScriptDrv psdrv;
  char *arg = argv[narg = 1];
  while (narg < argc) {
    if (arg[0] != '\0') {
      if (arg[0] == '-') { // Look for command line arguments
	psdrv = ProcessArgs(argc, argv);
      }
      else { 
	open_file = arg; // Update the open file name pointer
	ifstream infile(open_file, ios::in|ios::nocreate);
	if(!infile) {
	  cerr << endl;
	  cerr << "Cannot open file: " << open_file << endl;
	  cerr << "Exiting..." << endl;
	  cerr << endl;
	  return 0;
	}
	num_files++;

	// Process the test file
	DocumentSetup(psdrv);
	if(write_to_file == 0 ) { 
	  psdrv.Prologue(cout);
	  psdrv.MediaSetup(cout, duplex, manualfeed, use_tray, tray_number);
	  
	  if(psdrv.ConvertTextFile(infile, cout, wrap_lines, cut_lines) == 0) {
	    cerr << endl;
	    cerr << "Encountered fatal error during conversion" << endl;
	    cerr << "Exiting..." << endl;
	    cerr << endl;
	    return 1;
	  }
	  psdrv.Epilogue(cout, psdrv.page_count);
	}
	else {
	  GenOutputFileName(".ps");
	  ofstream stream(out_file, ios::out); // Open file and truncate it
	  if(!stream) {
	    cerr << endl;
	    cerr << "Cannot write to " << out_file << endl;
	    cerr << endl;
	    return 1;
	  }
	  
	  psdrv.Prologue(stream);
	  psdrv.MediaSetup(stream, duplex, manualfeed, use_tray, tray_number);
	  
	  if(psdrv.ConvertTextFile(infile, stream, wrap_lines, cut_lines) == 0)
	    {
	      cerr << endl;
	      cerr << "Encountered fatal error during conversion" << endl;
	      cerr << "Exiting..." << endl;
	      cerr << endl;
	      return 1;
	    }
	  psdrv.Epilogue(stream, psdrv.page_count);
	  stream.close();
	  infile.close();
	}
      }
      arg = argv[++narg];
    }
  }
  
  if(num_files == 0) {
    cerr << endl;
    cerr << "You must enter a file name." << endl;
    cerr << "Exiting..." << endl;
    cerr << endl;
    return 0;
  }

  return 0;
}
// ----------------------------------------------------------- //
// ------------------------------- //
// --------- End of File --------- //
// ------------------------------- //
