// ------------------------------- //
// -------- 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: 10/16/1998 
// ----------------------------------------------------------- // 
// ------------- 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.hpp"

// AS2PS program globals
int VerboseMode = 0;     // Echo results (off by default)
char in_file[MAX_LINE];  // Input file to convert to PostScript
char out_file[MAX_LINE]; // Optional output file name
char time_buf[255];      // Buffer used to hold time/date string

// 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 "
       << "outfile.ps (optional)" << 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 << "           -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 '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;
      }
    }
    else { 
      strcpy(in_file, argv[i]);      // Input file name
      if(argv[i+1]) {
	strcpy(out_file, argv[i+1]); // Output file name
	break;
      }
      else
	break;
    }
  }

  return psdrv;
}

int main(int argc, char *argv[])
{
  // If no argument is given print usage message to the screen 1
  if(argc < 2) {
    HelpMessage(ProgramName, ASPSVersionNumber);
    return(0);
  }

  PostScriptDrv psdrv = ProcessArgs(argc, argv);
   
  if(in_file[0] == 0 ) {
    cout << endl;
    cout << "You must specify a valid input file name." << endl;
    cout << endl;
    exit(0);
  }

  psdrv.SetPaperSize(paper_code);
  psdrv.SetFont(font_code, font_size);
  if(psdrv.UsingHeader()) {
    psdrv.SetDocumentName(in_file);
    GetSystemTime(time_buf);
    psdrv.SetDateString(time_buf);
  }

  psdrv.DocumentSetup(lr_margin, tb_margin, man_page);
  
  if(VerboseMode) {
    cerr << "Font            = " << psdrv.TextFont() << endl;
    cerr << "Font Size       = " << psdrv.FontSize() << endl;
    cerr << "Character width = " << psdrv.CharWidth() << endl;
    cerr << "Chars Per inch  = " << psdrv.CharsPerInch() << endl;
    cerr << "Columns         = " << psdrv.Columns() << endl;

    cerr << "Paper size      = ";
    if(paper_code == PostScriptDrv::LETTER_SIZE) cerr << "LETTER" << endl;
    if(paper_code == PostScriptDrv::LEGAL_SIZE) cerr << "LEGAL" << endl;
    if(paper_code == PostScriptDrv::TABLOID_SIZE) cerr << "TABLOID" << endl;
    if(paper_code == PostScriptDrv::A3_SIZE) cerr << "A3" << endl;
    if(paper_code == PostScriptDrv::A4_SIZE) cerr << "A4" << endl;

    cerr << "Page width      = " << psdrv.PageWidth() << endl;
    cerr << "Page height     = " << psdrv.PageHeight() << endl;
    cerr << "Starting X pos  = " << psdrv.StartX() << endl;
    cerr << "Starting Y pos  = " << psdrv.StartY() << endl;
    cerr << "Lines per page  = " << psdrv.LinesPerPage() << endl;

    cerr << "Copies          = " << psdrv.NCopies() << endl;    
    cerr << "Tab Stop Spaces = " << psdrv.TabStop() << endl;

    cerr << "Input text file = " << in_file << endl;
    if(out_file[0] == 0 ) 
      cerr << "Output PS file  = stdout" << endl;
    else
      cerr << "Output PS file  = " << out_file << endl;
    if(psdrv.GetMode()) cerr << "Printing in landscape mode" << endl;
    if(psdrv.UsingLRMargin()) cerr << "Using left and right margins" << endl;
    if(psdrv.UsingTBMargin()) cerr << "Using top and bottom margins" << endl;
    cerr << endl;
    cerr << "Press enter to continue..." << endl;
    cin.get();
  }
  
  ifstream infile(in_file, ios::in|ios::nocreate);
  if(!infile) {
      cerr << endl;
      cerr << "Cannot open file: " << in_file << endl;
      cerr << "Exiting..." << endl;
      cerr << endl;
    return 1;
  }

  if(out_file[0] == 0 ) { 
    // No Output file name specified, defaulting to stdout
    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 {
    ofstream stream(out_file, ios::out); // Open file and truncate it
    if(!stream) {
      cerr << endl;
      cerr << "Cannot open " << 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();
  return 0;
}
// ----------------------------------------------------------- //
// ------------------------------- //
// --------- End of File --------- //
// ------------------------------- //
