// C++ .h file for gplot, CGM-specific I/O  -*-c++-*-
// copyright Phil Andrews, Pittsburgh Supercomputing Center, 1992
// all rights reserved
#ifndef cgmio_h
#define cgmio_h
#include <stdio.h>
#include <string.h>
#include "cgm.h"
#if __MSDOS__
#include <io.h>
#endif
#include "basicio.h"
#ifdef macintosh
#  include <UMacApp.h>
#  include <errors.h>
#endif
////
// definitions for input, output
////
enum {clearCGM, binaryCGM}; // for identification
////
// typedef for parsing array
////
typedef baseCGM *(*parseFp)(cgmContainer*, cgmInput*, baseCGM*);
////
// structure for parsing table
////
class cgmNameNew {
public:
  // default constructor, (default arguments not implemented in arrays)
  cgmNameNew() {myName=NULL; myClass=0; myElement=0; fp=NULL;}
  // real constructor
  cgmNameNew(const char **inName, int inClass, int inElement, parseFp inFp)
    {myName=inName; myClass=inClass; myElement=inElement; fp=inFp;}
  const char **myName; // clear text name
  int myClass; // cgm class
  int myElement; // cgm element
  // function to create new element
  parseFp fp;
};
////
// basic cgm input class
////
class cgmInput : public basicInput {
public:
  cgmInput(const char *inName, short refHand=0)
	 : basicInput(inName, refHand) {initialize();}
  cgmInput(FILE *inPtr, short refHand=0, int offset=0)
	 : basicInput(inPtr, refHand, offset) {initialize();}
  void initialize(); // initialize constants
  // the pure virtual functions, required of all descendants
  virtual int isa() = 0;
#if __MSDOS__
  virtual  HugePt getCmd() = 0; // get the next command
#else
  virtual unsigned char *getCmd() = 0; // get the next command
#endif
  virtual char *getString(int&) = 0; // get a string from input
  virtual int getInt(int = 0) = 0; // get an integer from input
  virtual float getReal() = 0; // get a real from input
  virtual float getFP() = 0; // get a floating point real from input
  virtual int getE() = 0; // get an enumerated int
  virtual int getType(const char**, int) = 0; // check for possible types
  virtual void getIntPrec(intPrec*) = 0; // get the integer precision
  virtual void getIntPrec(uIntPrec*) = 0; // get the unsigned integer precision
  virtual void getRealPrec(realPrec*) = 0; // get the real precision
  virtual unsigned int getCD(int = 0) = 0; // direct colour component
  virtual unsigned int getCI(int = 0) = 0; // indexed colour
  virtual int getVIP() = 0; // VDC at integer precision
  virtual float getVRP() = 0; // VDC at real precision
  virtual int getNoPts() = 0; // how many vdc points to come ?
  virtual int polygonSetSize() = 0; // how many  points in the polyset ?
  virtual int getPt(float*) = 0; // get one real vdc point
  virtual int getPt(int*) = 0; // get one integer vdc point
  virtual int getNoDColrs() = 0; // how many direct colours to get
  virtual cgmDefaults *getDefaults(cgmMetafile*) = 0; // get metafile defaults
  virtual const char *cmdSignature() = 0; // diagnostic
  // get a cell array
  virtual cellArray *getCellArray(int, const colrValueExtent*,
				  const colrTable*) = 0;
  ////
  // default functions
  ////
  virtual baseCGM *doCmd(cgmContainer*, baseCGM*); // interpret the command
  // get a direct colour
  virtual void getDColr(dColr&); 
  // get a general colour
  virtual genColr *getColr(int, const colrValueExtent*, const colrTable*); 
  // get a single VDC measure
  virtual vdc *getVdc(); 
  // get a set of VDC points
  virtual vdcPts *getVdcPts(int=0); 
  // get a colour table
  virtual colrTable *getColrTable(const colrValueExtent*);
  virtual int padCmd() {return 0;} // ignore this ?
  virtual void makeIndex(cgmMetafile*); // create an index
  ////
  // values needed for input parsing
  // default values
  intPrec defIntPrec; // default integer precision
  uIntPrec defColrPrec; // default colour precision
  uIntPrec defColrIndexPrec; // default colour index precision
  realPrec defRealPrec; // default real precision
  intPrec defVdcIntPrec; // default VDC integer precision
  realPrec defVdcRealPrec; // default VDC integer precision
  ////
  // overriding commands
  cgmVdcType *vdcTypeCmd; // vdc type, integer or real
  cgmIntegerPrec *intPrecCmd;
  cgmRealPrec *realPrecCmd;
  cgmIndexPrec *indexPrecCmd; // index precision
  cgmColrPrec *colrPrecCmd; // colour precision
  cgmColrIndexPrec *colrIndexPrecCmd; // colour index precision
  cgmVdcInteger *vdcIntPrecCmd, *defVdcIntPrecCmd;
  cgmVdcReal *vdcRealPrecCmd, *defVdcRealPrecCmd;
  ////
  // the functions to get the precisions
  virtual vdcType myVdcType() {return vdcTypeCmd ? vdcTypeCmd->myType : 0;}
  virtual intPrec& myIntPrec()
    {return intPrecCmd ? intPrecCmd->thisPrec : defIntPrec;}
  virtual realPrec& myRealPrec()
    {return realPrecCmd ? realPrecCmd->thisPrec : defRealPrec;}
  virtual intPrec& indexPrec()
    {return indexPrecCmd ? indexPrecCmd->thisPrec : defIntPrec;}
  virtual uIntPrec& colrPrec()
    {return colrPrecCmd ? colrPrecCmd->thisPrec : defColrPrec;}
  virtual uIntPrec& colrIndexPrec()
    {return colrIndexPrecCmd ? colrIndexPrecCmd->thisPrec : defColrIndexPrec;}
  virtual intPrec& vdcIntPrec() 
    {return vdcIntPrecCmd ? vdcIntPrecCmd->thisPrec :
     defVdcIntPrecCmd ? defVdcIntPrecCmd->thisPrec : defVdcIntPrec;}
  virtual realPrec& vdcRealPrec() 
    {return vdcRealPrecCmd ? vdcRealPrecCmd->thisPrec :
     defVdcRealPrecCmd ? defVdcRealPrecCmd->thisPrec : defVdcRealPrec;}
  ////
  static const int cgmNoClasses; // size of parsing array
  // get a polygon set
  virtual void polygonSet(vdcPts*&, int*&);
protected:
  static cgmNameNew* cgmNameArray; // parsing info array
  static int beginPictureIndex, endMetafileIndex;
  static void initNameArray(); // initialize the name array
  virtual int sameCmd(const cgmNameNew&) = 0; // match the command
  // local flags
  int inputError; // did we get an error ?
  static const int noErrors;
  static const int noSep;
  static const int skipParen;
};
////
// the basic clear text info, used for input parsing and output
////
class clearInfo {
protected:
  static const char termChar, termChar1, quoteChar, quoteChar1, sepChar,
  sepChar1, sepChar2, sepChar3, sepChar4, sepChar5, sepChar6, nullChar,
  nullChar1, commentChar; // the constant values, defined in cgmio.cc
  int isTerm(const char c) {return (c==termChar)||(c==termChar1);}
  int isQuote(const char c) {return (c==quoteChar)||(c==quoteChar1);}
  int isSep(const char c) {return (c==sepChar) || (c==sepChar6) ||
				    ((c>=sepChar1) && (c<=sepChar5));}
  int isNull(const char c) {return (c==nullChar)||(c==nullChar1);}
  int isComment(const char c) {return (c==commentChar);}
};
////
// input class for clear text
////
class clearInput : public cgmInput, public clearInfo {
public:
  clearInput(const char *inName, short refHand=0)
	 : cgmInput(inName, refHand) {}
  clearInput(FILE *inPtr, short refHand=0, int offset=0)
	 : cgmInput(inPtr, refHand, offset) {}
  // the required functions
  virtual int isa() {return clearCGM;}
#if __MSDOS__
  virtual HugePt getCmd();
#else
  virtual unsigned char *getCmd();
#endif
  virtual char *getString(int&);
  virtual int getInt(int = 0);
  virtual float getReal();
  virtual float getFP() {return getReal();}
  virtual int getType(const char**, int);
  virtual void getIntPrec(intPrec*);
  virtual void getIntPrec(uIntPrec*);
  virtual void getRealPrec(realPrec*);
  virtual unsigned int getCD(int flag = 0) {return getInt(flag);}
  virtual unsigned int getCI(int flag = 0) {return getInt(flag);}
  virtual int getVIP() {return getInt();}
  virtual float getVRP() {return getReal();}
  virtual int getE() {return getInt();}
  virtual int getNoDColrs() {return getNoTokens() / 3;}
  virtual cgmDefaults *getDefaults(cgmMetafile*);
  virtual const char *cmdSignature() {return (const char *) buffer;}
  // get a cell array
  virtual cellArray *getCellArray(int, const colrValueExtent*,
				  const colrTable*);
  virtual long thisSize() {return bIndex;}
private:
  virtual int sameCmd(const cgmNameNew &inName)
    {return same(*(inName.myName));}
  virtual int same(const char*);
  int getDecimal();
  long getLongDecimal();
  int getBased(int);
  int getNoTokens();
  virtual int getNoPts();
  virtual int polygonSetSize();
  virtual int getPt(float*);
  virtual int getPt(int*);
};
////
// input class for binary format
////
class binaryInput : public cgmInput {
public:
  binaryInput(const char *inName, short refHand=0)
	 : cgmInput(inName, refHand) {}
  binaryInput(FILE* inPtr, short refHand=0, int offset=0)
	 : cgmInput(inPtr, refHand, offset) {}
  ~binaryInput();
  // required functions
  virtual int isa() {return binaryCGM;}
#if __MSDOS__
  virtual HugePt getCmd();
#else
  virtual unsigned char *getCmd();
#endif
  virtual char *getString(int&);
  virtual int getInt(int = 0) {return gInt(myIntPrec().noBytes);}
  virtual int getShiftInt(int bitShift= 0)
    {return gShiftInt(myIntPrec().noBytes, bitShift);}
  virtual float getReal() {return gReal(myRealPrec());}
  virtual float getFP() {return gFP(myRealPrec());}
  virtual int getType(const char**, int) {return getE();}
  virtual void getIntPrec(intPrec *inPrec)
    {inPrec->noBytes = getInt() / 8;}
  virtual void getIntPrec(uIntPrec *inPrec)
    {inPrec->noBytes = getInt() / 8;}
  virtual void getRealPrec(realPrec*);
  virtual int getE() {return gInt(2);}
  virtual unsigned int getCD(int = 0) {return gUInt(colrPrec().noBytes);}
  virtual unsigned int getCI(int = 0) {return gUInt(colrIndexPrec().noBytes);}
  virtual int getVIP() {return gInt(vdcIntPrec().noBytes);}
  virtual float getVRP() {return gReal(vdcRealPrec());}
  virtual int getNoPts();
  virtual int polygonSetSize();
  virtual int getPt(float*);
  virtual int getPt(int*);
  virtual int getNoDColrs() // how many direct colours to come ?
    {return (bIndex<=aIndex) ? 0 : (bIndex-aIndex)/(3 * colrPrec().noBytes);}
  virtual cgmDefaults *getDefaults(cgmMetafile*);
  virtual const char *cmdSignature();
  virtual int padCmd() {return !(bufferClass() && bufferElement());}
  virtual int sameCmd(const cgmNameNew &inCmd)
    {return (bufferClass() == inCmd.myClass) &&
       (bufferElement() == inCmd.myElement);}
  // get a cell array
  virtual cellArray *getCellArray(int, const colrValueExtent*,
				  const colrTable*);
  virtual long thisSize() {return (bIndex % 2) ? bIndex + 1 : bIndex;}
  // local functions
  unsigned int bufferClass() {return buffer[0] >> 4;}
  unsigned int bufferElement()
    {return ((buffer[0] << 3) & 127) + (buffer[1] >> 5);}
protected:
  unsigned int gUInt(int); // general unsigned integer
  int gInt(int); // general signed integer
  int gShiftInt(int, int); // general shifted signed integer
  float gReal(realPrec &inPrec) // general real
    {return inPrec.format ? gFX(inPrec) : gFP(inPrec);} 
  float gFP(realPrec&); // general floating point real
  float gFX(realPrec&); // general fixed point real
};
////
// now some derivative binary variations
////
#define NCARSIZE 1440 /* NCAR comes in chunks this size */
class NCARInput : public binaryInput { // NCAR format
public:
  NCARInput(const char *inName, short refHand=0)
	 : binaryInput(inName, refHand) {initialize();}
  NCARInput(FILE *inPtr, short refHand=0, int offset=0)
	 : binaryInput(inPtr, refHand, offset) {initialize();}
  virtual int getOffBytes(unsigned int noBytes, unsigned long offset=0);
protected:
  void initialize();
  unsigned char localBuffer[NCARSIZE];
  unsigned int startIndex, endIndex;
  int fillLocalBuffer();
};
class MilInput : public binaryInput { // military format
public:
  MilInput(const char *inName, short refHand=0)
	 : binaryInput(inName, refHand) {}
  MilInput(FILE *inPtr, short refHand=0, int offset=560) // 560 = 7 * 80 lines
	 : binaryInput(inPtr, refHand, offset) {}
};
class LANLInput : public binaryInput { // LANL format
public:
  LANLInput(const char *inName, short refHand=0)
	 : binaryInput(inName, refHand) {}
  LANLInput(FILE *inPtr, short refHand=0, int offset=360)
	 : binaryInput(inPtr, refHand, offset) {}
};
////
// class to hold a complete cgm file
////
class cgmFile : public basicInput {
public:
  cgmFile(const char *inName = NULL, short file_ref_num = NULL);
  ~cgmFile();
  cgmMetafile *foundMetafile() {return metafile;}
  const char *name() {return inputName;}
private:
  char *inputName;
  int nameSize;
  cgmInput *inputHandler;
  cgmMetafile *metafile;
  cgmInput *getCgmInput();
};
////
// basic cgm output class
////
class cgmOutput { 
public:
  virtual int startCmd(baseCGM*) = 0;
  virtual int endCmd() = 0;
  virtual int outString(const char*) = 0;
  virtual int outInt(int, int = 0) = 0;
  virtual int outReal(float) = 0;
  virtual int outType(const char**, int) = 0;
  virtual int outIntPrec(intPrec*) = 0; 
  virtual int outIntPrec(uIntPrec*) = 0; 
  virtual int outRealPrec(realPrec*) = 0; 
  virtual int outDColr(dColr&) = 0; 
  virtual int outVdc(const vdc*) = 0; // output a single VDC
  virtual int outVdcPts(const vdcPts*) = 0; // output a set of VDC points
  virtual int outColr(genColr*) = 0; // output a general colour
  virtual int outCellArray(cellArray*) = 0; // output a cell array
  virtual int polygonSet(const vdcPts*, const int*); // polygon set
  virtual int outColrTable(colrTable*) = 0; // output a colour table
  virtual int outDefaults(cgmDefaults*) = 0; // output set of defaults
};
////
// output class for clear text
////
class clearOutput : public cgmOutput, public clearInfo, public basicOutput {
public:
  clearOutput(const char *inName, short ref_num=0)
	 : basicOutput(inName, ref_num) {}
  virtual int startCmd(baseCGM*);
  virtual int endCmd();
  int outString(const char*);
  virtual int outInt(int inVal, int noSep = 0)
    {return textIntOut(inVal, noSep);}
  virtual int outReal(float inVal) {return textRealOut(inVal);}
  virtual int outType(const char**, int);
  virtual int outIntPrec(intPrec*); 
  virtual int outIntPrec(uIntPrec*); 
  virtual int outRealPrec(realPrec*);
  virtual int outDColr(dColr&);
  virtual int outVdcPts(const vdcPts*);
  virtual int outVdc(const vdc*);
  virtual int outColr(genColr*);
  virtual int outCellArray(cellArray*);
  virtual int outColrTable(colrTable*);
  virtual int outDefaults(cgmDefaults*);
};
////
// output class for binary output
////
class binaryOutput { 
public:
  // the required functions
  virtual int startCmd(baseCGM*);
  virtual int endCmd();
  virtual int outString(const char*);
  virtual int outInt(int, int = 0) = 0;
  virtual int outReal(float) = 0;
  virtual int outType(const char**, int);
  virtual int outIntPrec(intPrec*) = 0; 
  virtual int outIntPrec(uIntPrec*) = 0; 
  virtual int outRealPrec(realPrec*) = 0; 
  virtual int outDColr(dColr&) = 0; 
  virtual int outVdc(const vdc*) = 0; // output a single VDC
  virtual int outVdcPts(const vdcPts*) = 0; // output a set of VDC points
  virtual int outColr(genColr*) = 0; // output a general colour
  virtual int outCellArray(cellArray*) = 0; // output a cell array
  virtual int outColrTable(colrTable*) = 0; // output a colour table
  virtual int outDefaults(cgmDefaults*) = 0; // output set of defaults
protected:
  // binary specific functions
};
#endif /* cgmio_h */
