//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Tue Dec 28 00:44:28 PST 2010
// Last Modified: Tue Dec 28 00:44:31 PST 2010
// Filename:      ...sig/examples/all/mdfont2ppm.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/musedata/mdfont2ppm.cpp
// Syntax:        C++; museinfo
//
// Description:   Convert MuseData fonts into PPM image.
//

#include "museinfo.h"
#include "Options.h"
#include "PerlRegularExpression.h"

#ifndef OLDCPP
   #include <fstream>
   using namespace std;
#else
   #include <fstream.h>
#endif

// function declarations
void      checkOptions(Options& opts, int argc, char* argv[]);
void      example(void);
void      usage(const char* command);
void      printData(ostream& out, Array<Array<char>*>& data);
void      getTextFile(Array<Array<char>*>& textfile, 
                              const char* filename);
void      getTextFile(Array<Array<char>*>& textfile, istream& input);
void      appendString(Array<Array<char>*>& listing, 
                              Array<char>& lastone);
void      deleteData(Array<Array<char>*>& data);


// global variables
Options   options;             // database for command-line arguments


///////////////////////////////////////////////////////////////////////////

int main(int argc, char* argv[]) {
   checkOptions(options, argc, argv);
   int numinputs = options.getArgCount();

   Array<Array<char>*> fontfile;
   if (numinputs > 0) {
      getTextFile(fontfile, options.getArg(1));
   } else {
      getTextFile(fontfile, cin);
   }
   printData(cout, fontfile);



   deleteData(fontfile);

   return 0;
}



///////////////////////////////////////////////////////////////////////////


//////////////////////////////
//
// deleteData -- 
//

void deleteData(Array*>& data) {
   int i;
   for (i=0; i<data.getSize(); i++) {
      delete data[i];
      data[i] = NULL;
   }
   data.setSize(0);
}


//////////////////////////////
//
// getTextFile -- return the contents of a text-based font file.
//

void getTextFile(Array*>& fontfile, const char* filename) {
   #ifndef OLDCPP
      ifstream input(filename, ios::in);
   #else
      ifstream input(filename, ios::in | ios::nocreate);
   #endif
	  
   getTextFile(fontfile, input);
}


void getTextFile(Array*>& fontfile, istream& input) {
   fontfile.setSize(1000000);
   fontfile.setGrowth(5000000);
   fontfile.setSize(0);

   Array<char> dataline;
   dataline.setSize(1000);
   dataline.setGrowth(500000);
   dataline.setSize(0);
   int character;
   char value;
   int  isnewline;
   char lastvalue = 0;

   while (!input.eof()) {
      character = input.get();
      if (input.eof()) {
         // end of file found without a newline termination on last line.
         if (dataline.getSize() > 0) {
            appendString(fontfile, dataline);
            dataline.setSize(0);
            break;
         }
      }
      value = (char)character;
      if ((value == 0x0d) || (value == 0x0a)) {
         isnewline = 1;
      } else {
         isnewline = 0;
      }

      if (isnewline && (value == 0x0a) && (lastvalue == 0x0d)) {
         // ignore the second newline character in a dos-style newline.
         lastvalue = value;
         continue;
      } else {
         lastvalue = value;
      }

      if (isnewline) {
         appendString(fontfile, dataline);
         dataline.setSize(0);
      } else {
         dataline.append(value);
      }
   }

}



//////////////////////////////
//
// appendString -- 
//

void appendString(Array*>& listing, Array& lastone) {
   int index = listing.getSize();
   listing.setSize(index+1);

   Array<char>* temp = new Array<char>;
   int size = lastone.getSize();
   temp->setSize(size+1);

   char* ptr1 = temp->getBase();
   char* ptr2 = lastone.getBase();
   int i;

   for (i=0; i<lastone.getSize(); i++) {
      ptr1[i] = ptr2[i];
   }

   (*temp)[size] = '\0';
   temp->setSize(size);
   listing[index] = temp;
}



//////////////////////////////
//
// printData --
//

void printData(ostream& out, Array*>& data) {
   int i;
   for (i=0; i<data.getSize(); i++) {
      out <<data[i]->getBase() << '\n';
   }
   out << flush;
}



//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//

void checkOptions(Options& opts, int argc, char* argv[]) {

   opts.define("debug=b");              // determine bad input line num
   opts.define("author=b");             // author of program
   opts.define("version=b");            // compilation info
   opts.define("example=b");            // example usages
   opts.define("h|help=b");             // short description
   opts.process(argc, argv);
   
   // handle basic options:
   if (opts.getBoolean("author")) {
      cout << "Written by Craig Stuart Sapp, "
           << "craig@ccrma.stanford.edu, Dec 2010" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 28 Dec 2010" << endl;
      cout << "compiled: " << __DATE__ << endl;
      cout << MUSEINFO_VERSION << endl;
      exit(0);
   } else if (opts.getBoolean("help")) {
      usage(opts.getCommand());
      exit(0);
   } else if (opts.getBoolean("example")) {
      example();
      exit(0);
   }


}



//////////////////////////////
//
// example -- example usage of the program
//

void example(void) {
   cout <<
   "                                                                         \n"
   << endl;
}



//////////////////////////////
//
// usage -- gives the usage statement for the program
//

void usage(const char* command) {
   cout <<
   "                                                                         \n"
   << endl;
}


// md5sum: 8cdf09863001234c510f418cda4fa89f mdfont2ppm.cpp [20110107]