// C++ .cc file for gplot, CGM-specific classes  -*-c++-*-
// copyright Phil Andrews, Pittsburgh Supercomputing Center, 1992
// all rights reserved
#include <string.h>
#include <ctype.h>
#include "cgm.h"
#include "cgmio.h"
#if __MSDOS__
#include "cgmdisp.h"
#else
#include "cgmdisplay.h"
#endif
#ifdef macintosh
 #include <UMacApp.h>
 #pragma segment CGM1
#endif
// error handling function
extern void myError(const char *inMsg, const char *inMsg2=NULL,
		    int severity=1);


////
// direct colour class
////
// constructor
////
dColr::dColr(int inR, int inG, int inB)
{
  values[0] = inR;
  values[1] = inG;
  values[2] = inB;
}
////
// general colour class
////
// indexed colour constructor
////
genColr::genColr(int inIndex, const colrValueExtent *inExtent,
		 const colrTable *inTable) 
{
  myIndex = inIndex;
  myType = 0;
  myExtent = inExtent;
  myTable = inTable;
}
////
// direct colour constructor
////
genColr::genColr(int inRed, int inGreen, int inBlue,
		 const colrValueExtent *inExtent, const colrTable *inTable) 
{ // direct colour constructor
  myDC.setValue(0,inRed);    // myDC[0] = inRed;
  myDC.setValue(1,inGreen);  //myDC[1] = inGreen;
  myDC.setValue(2,inBlue);   //myDC[2] = inBlue;
  myIndex = 1;
  myType = 1;
  myExtent = inExtent;
  myTable = inTable;
}
////
// another direct colour constructor
////
genColr::genColr(const dColr &inDC,
		 const colrValueExtent *inExtent, const colrTable *inTable) 
{ // direct colour constructor
  myDC = inDC;
  myIndex = 1;
  myType = 1;
  myExtent = inExtent;
  myTable = inTable;
}
////
// get float values for the colours
////
float genColr::r(unsigned i) const
{
  if (i>2) i = 0; // greater than blue ?
//  int useVal = type() ? myDC[i] : myTable->val(myIndex)[i];
  int useVal = type() ? myDC.getValue(i) : myTable->val(myIndex).getValue(i);
//  if (useVal >= myExtent->white[i]) return 1; // max possible
//  if (useVal <= myExtent->black[i]) return 0; // min possible
  if (useVal >= myExtent->white.getValue(i)) return 1; // max possible
  if (useVal <= myExtent->black.getValue(i)) return 0; // min possible

// ***  return (float) (useVal - myExtent->black[i]) /
// ***   (myExtent->white[i] - myExtent->black[i]);
  return (float) (useVal - myExtent->black.getValue(i)) /
    (myExtent->white.getValue(i) - myExtent->black.getValue(i));
}
////
// colour table class
////
colrTable::colrTable(unsigned int inSize, const colrValueExtent *inExtent,
		     unsigned int inStart)
{
  mySize = inSize;
  myExtent = inExtent;
  myStart = inStart;
  myNo = 0;
  values = new dColr[size()];
  initialize(values, mySize);
}
////
// add one colour
////
void colrTable::addColr(dColr &inDColr)
{
  if (no() < size()) {
    values[no()] = inDColr; // should check that this works
    ++myNo;
  }
}
////
// extend the table
////
void colrTable::extendTable(int newSize)
{
  if (newSize < mySize) return; // nothing to do
  // need more room
  dColr *oldValues = values;
  int oldSize = mySize;
  mySize = newSize;
  values = new dColr[mySize];
  for (int i=0; i<oldSize; ++i) values[i] = oldValues[i];
  initialize(values + i, mySize - oldSize);
  delete oldValues;
}
////
// initialize values
////
void colrTable::initialize(dColr *inPtr, int size)
{
//  int rmin = myExtent->black[0]; // min red
//  int gmin = myExtent->black[1]; // min green
//  int bmin = myExtent->black[2]; // min blue
//  int rmax = myExtent->white[0]; // max red
//  int gmax = myExtent->white[1]; // max green
//  int bmax = myExtent->white[2]; // max blue

  int rmin = myExtent->black.getValue(0); // min red
  int gmin = myExtent->black.getValue(1); // min green
  int bmin = myExtent->black.getValue(2); // min blue
  int rmax = myExtent->white.getValue(0); // max red
  int gmax = myExtent->white.getValue(1); // max green
  int bmax = myExtent->white.getValue(2); // max blue

  int index = 0;
  if (index < size) {inPtr->set(rmax, gmax, bmax); ++index; ++inPtr;} // white
  if (index < size) {inPtr->set(rmin, gmin, bmin); ++index; ++inPtr;} // black
  if (index < size) {inPtr->set(rmax, gmin, bmin); ++index; ++inPtr;} // red
  if (index < size) {inPtr->set(rmin, gmax, bmin); ++index; ++inPtr;} // green
  if (index < size) {inPtr->set(rmin, gmin, bmax); ++index; ++inPtr;} // blue
  if (index < size) {inPtr->set(rmax, gmax, bmin); ++index; ++inPtr;} // yellow
  if (index < size) {inPtr->set(rmax, gmin, bmax); ++index; ++inPtr;} // magent
  if (index < size) {inPtr->set(rmin, gmax, bmax); ++index; ++inPtr;} // cyan
  if (index < size) {inPtr->set(rmax, gmax/2, bmin); ++index; ++inPtr;} // or
  if (index < size) {inPtr->set(rmax, gmin, bmax/2); ++index; ++inPtr;}
  for (int i=index; i<size; ++i) {
    inPtr->set(rmin, gmin, bmin); // black
    ++inPtr;
  }
}
////
// incorporate a new table
////
void colrTable::addTable(colrTable *inTable)
{
  if ((inTable->start() + inTable->no()) > (start() + size())) { // need room
    extendTable(inTable->start() + inTable->no() - start());
  }
  for (int i=0; i<inTable->no(); ++i) {
    values[inTable->start() - start() + i] = inTable->val(i);
  }
}
////
// get float values for the colours
////
const float *colrTable::r(unsigned index) const
{
  int i, useVal;
  static float rValues[3];
  if (index>=mySize) index = 0; // off the end
  ////
  // fill out the r, g, b values
  for (i=0; i<3; ++i) {
//    useVal = values[index][i];
    useVal = values[index].getValue(i);
//    if (useVal >= myExtent->white[i]) {
    if (useVal >= myExtent->white.getValue(i)) {
      rValues[i] = 1; // max possible
//    } else if (useVal <= myExtent->black[i]) {
    } else if (useVal <= myExtent->black.getValue(i)) {
      rValues[i] = 0; // min possible
    } else {
//      rvalues[i] = (float) (useVal - myExtent->black[i]) /
//	(myExtent->white[i] - myExtent->black[i]);
      rValues[i] = (float) (useVal - myExtent->black.getValue(i)) /
	(myExtent->white.getValue(i) - myExtent->black.getValue(i));
    }
  }
  return rValues;
}
////
// vdc pts class
////
// constructor for 2 integer points (used for rectangles)
////
vdcPts::vdcPts(int x1, int y1, int x2, int y2) 
{
  int *intPtr = new int[4];
  intPtr[0] = x1;
  intPtr[1] = y1;
  intPtr[2] = x2;
  intPtr[3] = y2;
  noPts = 2;
  myType = 0; // integer
  myPtr = intPtr;
  next=NULL;
}
////
// constructor for 2 float points (used for rectangles)
////
vdcPts::vdcPts(double x1, double y1, double x2, double y2) 
{
  float *floatPtr = new float[4];
  floatPtr[0] = x1;
  floatPtr[1] = y1;
  floatPtr[2] = x2;
  floatPtr[3] = y2;
  noPts = 2;
  myType = 1; // float
  myPtr = floatPtr;
  next=NULL;
}
////
// return the width of the points
////
float vdcPts::width() const
{
  float minX, maxX;
  int i;
  if (!noPts) return 0; // no points

  if (myType) { // real vdc's
    float *floatPtr = (float *) myPtr;
    minX = maxX = floatPtr[0];
    for (i=2; i<2 * noPts; i += 2) {
      if (minX > floatPtr[i]) minX = floatPtr[i];
      if (maxX < floatPtr[i]) maxX = floatPtr[i];
    }
  } else { // integer VDC's
    int *intPtr = (int *) myPtr;
    minX = maxX = intPtr[0];
    for (i=2; i<2 * noPts; i += 2) {
      if (minX > intPtr[i]) minX = intPtr[i];
      if (maxX < intPtr[i]) maxX = intPtr[i];
    }
  }
    return maxX - minX;
}
////
// return the height of the points
////
float vdcPts::height()  const
{
  float maxY, minY;
  int i;
  if (!noPts) return 0; // no points

  if (myType) { // real vdc's
    float *floatPtr = (float *) myPtr;
    minY = maxY = floatPtr[1];
    for (i=3; i<2 * noPts; i += 2) {
      if (minY > floatPtr[i]) minY = floatPtr[i];
      if (maxY < floatPtr[i]) maxY = floatPtr[i];
    }
  } else { // integer VDC's
    int *intPtr = (int *) myPtr;
    minY = maxY = intPtr[1];
    for (i=3; i<2 * noPts; i += 2) {
      if (minY > intPtr[i]) minY = intPtr[i];
      if (maxY < intPtr[i]) maxY = intPtr[i];
    }
  }
  return maxY - minY;
}
////
// return the max Y of the points
////
float vdcPts::maxY()  const
{
  float myMax;
  int i;
  if (!noPts) return 0; // no points

  if (myType) { // real vdc's
    float *floatPtr = (float *) myPtr;
    myMax = floatPtr[1];
    for (i=3; i<2 * noPts; i += 2) {
      if (myMax < floatPtr[i]) myMax = floatPtr[i];
    }
  } else { // integer VDC's
    int *intPtr = (int *) myPtr;
    myMax = intPtr[1];
    for (i=3; i<2 * noPts; i += 2) {
      if (myMax < intPtr[i]) myMax = intPtr[i];
    }
  }
  return myMax;
}
////
// return the min Y of the points
////
float vdcPts::minY()  const
{
  float myMin;
  int i;
  if (!noPts) return 0; // no points

  if (myType) { // real vdc's
    float *floatPtr = (float *) myPtr;
    myMin = floatPtr[1];
    for (i=3; i<2 * noPts; i += 2) {
      if (myMin > floatPtr[i]) myMin = floatPtr[i];
    }
  } else { // integer VDC's
    int *intPtr = (int *) myPtr;
    myMin = intPtr[1];
    for (i=3; i<2 * noPts; i += 2) {
      if (myMin > intPtr[i]) myMin = intPtr[i];
    }
  }
  return myMin;
}
////
// return the max X of the points
////
float vdcPts::maxX()  const
{
  float myMax;
  int i;
  if (!noPts) return 0; // no points

  if (myType) { // real vdc's
    float *floatPtr = (float *) myPtr;
    myMax = floatPtr[0];
    for (i=2; i<2 * noPts; i += 2) {
      if (myMax < floatPtr[i]) myMax = floatPtr[i];
    }
  } else { // integer VDC's
    int *intPtr = (int *) myPtr;
    myMax = intPtr[0];
    for (i=2; i<2 * noPts; i += 2) {
      if (myMax < intPtr[i]) myMax = intPtr[i];
    }
  }
  return myMax;
}
////
// return the min X of the points
////
float vdcPts::minX()  const
{
  float myMin;
  int i;
  if (!noPts) return 0; // no points

  if (myType) { // real vdc's
    float *floatPtr = (float *) myPtr;
    myMin = floatPtr[0];
    for (i=2; i<2 * noPts; i += 2) {
      if (myMin > floatPtr[i]) myMin = floatPtr[i];
    }
  } else { // integer VDC's
    int *intPtr = (int *) myPtr;
    myMin = intPtr[0];
    for (i=2; i<2 * noPts; i += 2) {
      if (myMin > intPtr[i]) myMin = intPtr[i];
    }
  }
  return myMin;
}
////
// scale the points by a constant factor
////
void vdcPts::scale(float inScale)
{
  int i;
  if (myType) {
    float *floatPtr = (float *) myPtr;
    for (i=0; i<2*noPts; ++i) floatPtr[i] *= inScale;
  } else {
    int *intPtr = (int *) myPtr;
    for (i=0; i<2*noPts; ++i) intPtr[i] = (int) (inScale * intPtr[i]);
  }
}
////
// shift the points in x and y direction
////
void vdcPts::shift(float xShift, float yShift)
{
  int i;
  if (myType) {
    float *floatPtr = (float *) myPtr;
    for (i=0; i<noPts; ++i) {
      floatPtr[2*i] += xShift;
      floatPtr[2*i+1] += yShift;
    }
  } else {
    int *intPtr = (int *) myPtr;
    for (i=0; i<noPts; ++i) {
      intPtr[2*i] += (int) xShift;
      intPtr[2*i+1] += (int) yShift;
    }
  }
}
////
// the basic text class
////
const int genText::finalFlag = 1;
const int genText::restrictedFlag = 1<<1;
const int genText::appendFlag = 1<<2;
////
// basic cgm class
////
// constructor
////
baseCGM::baseCGM(cgmContainer *inOwner, baseCGM *inPrev, baseCGM *inNext)
{
  prev = inPrev; // inititalize pointers
  next = inNext;
  owner = inOwner;
  if (prev) prev->next = this; // link pointers
  if (next) next->prev = this;
}
////
// destructor
////
baseCGM::~baseCGM() 
{
  if (prev) prev->next = next; // relink pointers
  if (next) next->prev = prev;
}
////
// output in a CGM format
////
int baseCGM::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->endCmd();
  return 1;
}
////
// default output to a display
////
int baseCGM::display(baseDisplay*)
{
  return 1;
}
////
// the Delimiter class
////
const int cgmDelimiter::myClass = 0;
////
// Begin Metafile
////
const int cgmBeginMetafile::myElement = 1;
const char *cgmBeginMetafile::myName = "BegMf";
////
// constructor
////
cgmBeginMetafile::cgmBeginMetafile(cgmContainer *inOwner, cgmInput *cgmIn,
				   baseCGM *inPrev, baseCGM *inNext)
: cgmDelimiter(inOwner, inPrev, inNext)
{
  mfName = cgmIn->getString(mfNameSize);
}
////
// destructor
////
cgmBeginMetafile::~cgmBeginMetafile()
{
  if (mfNameSize) delete mfName;
}
////
// output in a CGM format
////
int cgmBeginMetafile::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outString(mfNameSize ? mfName : "");
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmBeginMetafile::display(baseDisplay *inDisplay)
{
  inDisplay->newMF();
  if (inDisplay->fileDefaults() && mfOwner()->defaults()) {
    // display wants to get defaults replacement at beginning of metafile
    mfOwner()->displayDefaults(inDisplay);
  }
  return 1;
}
/////
// End Metafile
////
const int cgmEndMetafile::myElement = 2;
const int cgmEndMetafileMyElement =2;
const char *cgmEndMetafile::myName = "EndMf";
////
// constructor
////
cgmEndMetafile::cgmEndMetafile(cgmContainer *inOwner, cgmInput*,
			       baseCGM *inPrev, baseCGM *inNext)
: cgmDelimiter(inOwner, inPrev, inNext) // constructor
{
}
int cgmEndMetafile::cgmOut(cgmOutput *inOut) // output in a CGM format
{
  return inOut->startCmd(this) && inOut->endCmd();
}
////
// display output
////
int cgmEndMetafile::display(baseDisplay *inDisplay)
{
  inDisplay->endMF();
  return 1;
}
////
// Begin Picture
////
const int cgmBeginPicture::myElement = 3;
const int cgmBeginPictureMyElement = 3;
const char *cgmBeginPicture::myName = "BegPic";
////
// constructor
////
cgmBeginPicture::cgmBeginPicture(cgmContainer *inOwner, cgmInput *cgmIn,
				 baseCGM *inPrev, baseCGM *inNext)
: cgmDelimiter(inOwner, inPrev, inNext) // constructor
{
  picName = cgmIn->getString(picNameSize);
}
////
// alternate constructor
////
cgmBeginPicture::cgmBeginPicture(cgmContainer *inOwner, const char *inStr,
				 int strSize, baseCGM *inPrev, baseCGM *inNext)
: cgmDelimiter(inOwner, inPrev, inNext) // constructor
{
  picNameSize = strSize;
  if (picNameSize) {
    picName = new char [picNameSize + 1];
    for (int i=0; i<picNameSize; ++i) picName[i] = inStr[i];
    picName[i] = 0;
  } else picName = NULL;
}
////
// destructor
////
cgmBeginPicture::~cgmBeginPicture()
{
  if (picNameSize) delete picName;
}
////
// output in a CGM format
////
int cgmBeginPicture::cgmOut(cgmOutput *inOut) 
{
  inOut->startCmd(this);
  inOut->outString(picNameSize ? picName : "");
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmBeginPicture::display(baseDisplay *inDisplay)
{
  inDisplay->newPic();
  inDisplay->startPic();
  if (inDisplay->picDefaults() && mfOwner()->defaults()) {
    // display wants to get defaults replacement at each picture
    mfOwner()->displayDefaults(inDisplay);
  }
  return 1;
}
////
// Begin Picture Body
////
const int cgmBeginPictureBody::myElement = 4;
const char *cgmBeginPictureBody::myName = "BegPicBody";
////
// constructor
////
cgmBeginPictureBody::cgmBeginPictureBody(cgmContainer *inOwner, cgmInput*,
					 baseCGM *inPrev, baseCGM *inNext)
: cgmDelimiter(inOwner, inPrev, inNext)
{
}
////
// output in a CGM format
////
int cgmBeginPictureBody::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmBeginPictureBody::display(baseDisplay *inDisplay)
{
  inDisplay->newPicBody
    (owner->vdcExtent()->width(), owner->vdcExtent()->height(),
    -owner->vdcExtent()->minX(), -owner->vdcExtent()->minY());
  inDisplay->clearScreen();
  return 1;
}
////
// End Picture
////
const int cgmEndPicture::myElement = 5;
const int cgmEndPictureMyElement = 5;

const char *cgmEndPicture::myName = "EndPic";
////
// constructor
////
cgmEndPicture::cgmEndPicture(cgmContainer *inOwner, cgmInput*,
			     baseCGM *inPrev, baseCGM *inNext)
: cgmDelimiter(inOwner, inPrev, inNext)
{
}
////
// output in a CGM format
////
int cgmEndPicture::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEndPicture::display(baseDisplay *inDisplay)
{
  inDisplay->endPic();
  return 1;
}
////
// the Metafile Descriptor class
////
const int cgmMetafileDescriptor::myClass = 1;
////
// Metafile Version
////
const int cgmMetafileVersion::myElement = 1;
const char *cgmMetafileVersion::myName = "MFVersion";
////
// constructor
////
cgmMetafileVersion::cgmMetafileVersion(cgmContainer *inOwner, cgmInput *cgmIn,
				       baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  versionNumber = cgmIn->getInt();
  mfOwner()->versionCmd = this;
}
////
// output in a CGM format
////
int cgmMetafileVersion::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(versionNumber);
  inOut->endCmd();
  return 1;
}
#ifdef macintosh
 #pragma segment CGM2
#endif
////
// Metafile Description
////
const int cgmMetafileDescription::myElement = 2;
const char *cgmMetafileDescription::myName = "MFDesc";
////
// constructor
////
cgmMetafileDescription::
cgmMetafileDescription(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  mfDescription = cgmIn->getString(mfDescriptionSize);
  mfOwner()->descriptionCmd = this;
}
////
// destructor
////
cgmMetafileDescription::~cgmMetafileDescription()
{
  if (mfDescriptionSize) delete mfDescription;
}
////
// output in a CGM format
////
int cgmMetafileDescription::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outString(mfDescriptionSize ? mfDescription : "");
  inOut->endCmd();
  return 1;
}
////
// VDC Type
////
const int cgmVdcType::myElement = 3;
const int cgmVdcTypeMyElement = 3;

const char *cgmVdcType::myName = "VDCType";
//// 
// aids for parsing
//// 
const char *tmpVdcTypeList[] = {"INTEGER", "REAL"};
const char **cgmVdcType::typeList = tmpVdcTypeList;
const int cgmVdcType::typeListSize =
sizeof(tmpVdcTypeList) / sizeof(tmpVdcTypeList[0]);
//// 
// constructor
////
cgmVdcType::cgmVdcType(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  mfOwner()->vdcTypeCmd = this;
  myType = cgmIn->getType(typeList, typeListSize);
}
//// 
// output in a CGM format
//// 
int cgmVdcType::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
//// 
// Integer Precision
//// 
const int cgmIntegerPrec::myElement = 4;
const int cgmIntegerPrecMyElement = 4;
const char *cgmIntegerPrec::myName = "IntegerPrec";
//// 
// constructor
//// 
cgmIntegerPrec::cgmIntegerPrec(cgmContainer *inOwner, cgmInput *cgmIn,
			       baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  cgmIn->getIntPrec(&thisPrec);
}
//// 
// output in a CGM format
//// 
int cgmIntegerPrec::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outIntPrec(&thisPrec);
  inOut->endCmd();
  return 1;
}
//// 
// Real Precision
//// 
const int cgmRealPrec::myElement = 5;
const int cgmRealPrecMyElement = 5;
const char *cgmRealPrec::myName = "RealPrec";
//// 
// constructor
//// 
cgmRealPrec::cgmRealPrec(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  cgmIn->getRealPrec(&thisPrec);
}
//// 
// output in a CGM format
//// 
int cgmRealPrec::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outRealPrec(&thisPrec);
  inOut->endCmd();
  return 1;
}
//// 
// Index Precision
//// 
const int cgmIndexPrec::myElement = 6;
const int cgmIndexPrecMyElement = 6;
const char *cgmIndexPrec::myName = "IndexPrec";
//// 
// constructor
//// 
cgmIndexPrec::cgmIndexPrec(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  cgmIn->getIntPrec(&thisPrec);
}
//// 
// output in a CGM format
//// 
int cgmIndexPrec::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outIntPrec(&thisPrec);
  inOut->endCmd();
  return 1;
}
//// 
// Colour Precision
//// 
const int cgmColrPrec::myElement = 7;
const int cgmColrPrecMyElement = 7;
const char *cgmColrPrec::myName = "ColrPrec";
//// 
// constructor
//// 
cgmColrPrec::cgmColrPrec(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  cgmIn->getIntPrec(&thisPrec);
}
//// 
// output in a CGM format
//// 
int cgmColrPrec::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outIntPrec(&thisPrec);
  inOut->endCmd();
  return 1;
}
//// 
// Colour Index Precision
//// 
const int cgmColrIndexPrec::myElement = 8;
const int cgmColrIndexPrecMyElement = 8;
const char *cgmColrIndexPrec::myName = "ColrIndexPrec";
//// 
// constructor
//// 
cgmColrIndexPrec::cgmColrIndexPrec(cgmContainer *inOwner, cgmInput *cgmIn,
				   baseCGM *inPrev, baseCGM *inNext) 
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  cgmIn->getIntPrec(&thisPrec);
}
//// 
// output in a CGM format
//// 
int cgmColrIndexPrec::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outIntPrec(&thisPrec);
  inOut->endCmd();
  return 1;
}
//// 
// Max Colour Index
//// 
const int cgmMaxColrIndex::myElement = 9;
const char *cgmMaxColrIndex::myName = "MaxColrIndex";
//// 
// constructor
//// 
cgmMaxColrIndex::cgmMaxColrIndex(cgmContainer *inOwner, cgmInput *cgmIn,
				 baseCGM *inPrev, baseCGM *inNext) 
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  mfOwner()->maxColrIndexCmd = this;
  // maxIndexValue = cgmIn->getInt();
  maxIndexValue = cgmIn->getCI();
}
//// 
// output in a CGM format
//// 
int cgmMaxColrIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(maxIndexValue);
  inOut->endCmd();
  return 1;
}
//// 
// Colour Value Extent
//// 
const int cgmColrValueExtent::myElement = 10;
const char *cgmColrValueExtent::myName = "ColrValueExt";
//// 
// constructor
//// 
cgmColrValueExtent::cgmColrValueExtent(cgmContainer *inOwner,cgmInput *cgmIn,
				       baseCGM *inPrev, baseCGM *inNext) 
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  mfOwner()->colrValueExtentCmd = this;
  cgmIn->getDColr(myExtent.black);
  cgmIn->getDColr(myExtent.white);
}
//// 
// output in a CGM format
//// 
int cgmColrValueExtent::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outDColr(myExtent.white);
  inOut->outDColr(myExtent.black);
  inOut->endCmd();
  return 1;
}
//// 
// Metafile Element List
//// 
const int cgmMetafileElementList::myElement = 11;
const char *cgmMetafileElementList::myName = "MFElemList";
//// 
// constructor
//// 
cgmMetafileElementList::
cgmMetafileElementList(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext) 
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  // fix later
}
//// 
// output in a CGM format
//// 
int cgmMetafileElementList::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->endCmd();
  return 1;
}
//// 
// Metafile Defaults Replacement
//// 
const int cgmMetafileDefaultsReplacement::myElement = 12;
const char *cgmMetafileDefaultsReplacement::myName = "BegMFDefaults";
const char *cgmMetafileDefaultsReplacement::endName = "EndMFDefaults";
//// 
// constructor
//// 
cgmMetafileDefaultsReplacement::
cgmMetafileDefaultsReplacement(cgmContainer *inOwner, cgmInput *cgmIn,
			       baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  myDefaults = cgmIn->getDefaults(mfOwner()); // get the set of defaults
  ////
  // add them to the metafile list, 
  mfOwner()->addDefaults(myDefaults); 
}
//// 
// output in a CGM format
//// 
int cgmMetafileDefaultsReplacement::cgmOut(cgmOutput *inOut)
{ // output in a CGM format
  inOut->startCmd(this);
  inOut->outDefaults(myDefaults);
  inOut->endCmd();
  return 1;
}
////
// Font List
////
const int cgmFontList::myElement = 13;
const char *cgmFontList::myName = "FontList";
////
// constructor
////
cgmFontList::cgmFontList(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev,  baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  noFonts = 0;
}
////
// output in a CGM format
////
int cgmFontList::cgmOut(cgmOutput *inOut)
{ 
  inOut->startCmd(this);
  inOut->endCmd();
  return 1;
}
////
// Character Set List
////
const int cgmCharacterSetList::myElement = 14;
const char *cgmCharacterSetList::myName = "CharSetList";
////
// constructor
////
cgmCharacterSetList::
cgmCharacterSetList(cgmContainer *inOwner, cgmInput *cgmIn,
		    baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  noSets = 0;
}
////
// output in a CGM format
////
int cgmCharacterSetList::cgmOut(cgmOutput *inOut)
{ 
  inOut->startCmd(this);
  inOut->endCmd();
  return 1;
}
////
// Character Coding Announcer
////
const int cgmCharacterCodingAnnouncer::myElement = 15;
const char *cgmCharacterCodingAnnouncer::myName = "CharCoding";
////
// aids for parsing
//// 
const char *tmpCodingList[] = {"BASIC7BIT", "BASIC8BIT", "EXTD7BIT",
"EXTD8BIT"};
const char **cgmCharacterCodingAnnouncer::typeList = tmpCodingList;
const int cgmCharacterCodingAnnouncer::typeListSize =
sizeof(tmpCodingList) / sizeof(tmpCodingList[0]);
////
// constructor
////
cgmCharacterCodingAnnouncer::
cgmCharacterCodingAnnouncer(cgmContainer *inOwner, cgmInput *cgmIn,
			    baseCGM *inPrev, baseCGM *inNext)
: cgmMetafileDescriptor(inOwner, inPrev, inNext)
{
  announcer = cgmIn->getType(typeList, typeListSize);
}
////
// output CGM format
////
int cgmCharacterCodingAnnouncer::cgmOut(cgmOutput *inOut)
{ 
  inOut->startCmd(this);
  inOut->outType(typeList, announcer);
  inOut->endCmd();
  return 1;
}
////
// the Picture Descriptor class
////
const int cgmPictureDescriptor::myClass = 2;
////
// Scaling Mode
////
const int cgmScalingMode::myElement = 1;
const char *cgmScalingMode::myName = "ScaleMode";
////
// aids for parsing
//// 
const char *tmpScalingList[] = {"ABSTRACT", "METRIC"};
const char **cgmScalingMode::typeList = tmpScalingList;
const int cgmScalingMode::typeListSize =
sizeof(tmpScalingList) / sizeof(tmpScalingList[0]);
//// 
// constructor
////
cgmScalingMode::cgmScalingMode(cgmContainer *inOwner, cgmInput *cgmIn,
			       baseCGM *inPrev, baseCGM *inNext)
: cgmPictureDescriptor(inOwner, inPrev, inNext)
{
  owner->scalingCmd = this;
  mode = cgmIn->getType(typeList, typeListSize);
  if (mode) factor = cgmIn->getFP(); // always floating point
  else factor = 1; // for safety
}
////
// output CGM format
////
int cgmScalingMode::cgmOut(cgmOutput *inOut) 
{ 
  inOut->startCmd(this);
  inOut->outType(typeList, mode);
  if (mode) inOut->outReal(factor);
  inOut->endCmd();
  return 1;
}
////
// Colour Selection Mode
////
const int cgmColrMode::myElement = 2;
const char *cgmColrMode::myName = "ColrMode";
////
// aids for parsing
//// 
const char *tmpColrList[] = {"INDEXED", "DIRECT"};
const char **cgmColrMode::typeList = tmpColrList;
const int cgmColrMode::typeListSize =
sizeof(tmpColrList) / sizeof(tmpColrList[0]);
//// 
// constructor
//// 
cgmColrMode::cgmColrMode(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmPictureDescriptor(inOwner, inPrev, inNext)
{
  owner->colrModeCmd = this;
  mode = cgmIn->getType(typeList, typeListSize);
}
//// 
// output CGM format
//// 
int cgmColrMode::cgmOut(cgmOutput *inOut)
{ 
  inOut->startCmd(this);
  inOut->outType(typeList, mode);
  inOut->endCmd();
  return 1;
}
////
// Line Width Specification Mode
////
const int cgmLineWidthMode::myElement = 3;
const char *cgmLineWidthMode::myName = "LineWidthMode";
////
// aids for parsing
//// 
const char *tmpAbS[] = {"ABSTRACT", "SCALED"};
const char **cgmLineWidthMode::typeList = tmpAbS;
const int cgmLineWidthMode::typeListSize =
sizeof(tmpAbS) / sizeof(tmpAbS[0]);
////
// constructor
////
cgmLineWidthMode::cgmLineWidthMode(cgmContainer *inOwner, cgmInput *cgmIn,
				   baseCGM *inPrev, baseCGM *inNext)
: cgmPictureDescriptor(inOwner, inPrev, inNext)
{
  owner->lineModeCmd = this;
  mode = cgmIn->getType(typeList, typeListSize);
}
int cgmLineWidthMode::cgmOut(cgmOutput *inOut) // output CGM format
{ 
  inOut->startCmd(this);
  inOut->outType(typeList, mode);
  inOut->endCmd();
  return 1;
}
////
// Marker Size Specification Mode
////
const int cgmMarkerSizeMode::myElement = 4;
const char *cgmMarkerSizeMode::myName = "MarkerSizeMode";
////
// aids for parsing
//// 
const char **cgmMarkerSizeMode::typeList = tmpAbS;
const int cgmMarkerSizeMode::typeListSize =
sizeof(tmpAbS) / sizeof(tmpAbS[0]);
////
// constructor
////
cgmMarkerSizeMode::cgmMarkerSizeMode(cgmContainer *inOwner, cgmInput *cgmIn,
				     baseCGM *inPrev, baseCGM *inNext)
: cgmPictureDescriptor(inOwner, inPrev, inNext)
{
  mode = cgmIn->getType(typeList, typeListSize);
  owner->markerModeCmd = this;
}
////
// output CGM format
////
int cgmMarkerSizeMode::cgmOut(cgmOutput *inOut)
{ 
  inOut->startCmd(this);
  inOut->outType(typeList, mode);
  inOut->endCmd();
  return 1;
}
////
// Edge Width Specification Mode
////
const int cgmEdgeWidthMode::myElement = 5;
const char *cgmEdgeWidthMode::myName = "EdgeWidthMode";
////
// aids for parsing
//// 
const char **cgmEdgeWidthMode::typeList = tmpAbS;
const int cgmEdgeWidthMode::typeListSize =
sizeof(tmpAbS) / sizeof(tmpAbS[0]);
////
// constructor
////
cgmEdgeWidthMode::cgmEdgeWidthMode(cgmContainer *inOwner, cgmInput *cgmIn,
				   baseCGM *inPrev, baseCGM *inNext)
: cgmPictureDescriptor(inOwner, inPrev, inNext)
{
  mode = cgmIn->getType(typeList, typeListSize);
  owner->edgeModeCmd = this;
}
////
// output CGM format
////
int cgmEdgeWidthMode::cgmOut(cgmOutput *inOut) 
{ 
  inOut->startCmd(this);
  inOut->outType(typeList, mode);
  inOut->endCmd();
  return 1;
}
////
// VDC extent
////
const int cgmVdcExtent::myElement = 6;
const char *cgmVdcExtent::myName = "VDCExt";
////
// constructor
////
cgmVdcExtent::cgmVdcExtent(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmPictureDescriptor(inOwner, inPrev, inNext) 
{
  myPts = cgmIn->getVdcPts(2);
  owner->vdcExtentCmd = this;
}
////
// destructor
////
cgmVdcExtent::~cgmVdcExtent() { 
  if (myPts) delete myPts;
}
////
// output CGM format
////
int cgmVdcExtent::cgmOut(cgmOutput *inOut) 
{ 
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// Background Colour
////
const int cgmBackgroundColr::myElement = 7;
const char *cgmBackgroundColr::myName = "BackColr";
////
// constructor
////
cgmBackgroundColr::cgmBackgroundColr(cgmContainer *inOwner, cgmInput *cgmIn, baseCGM *inPrev,
				     baseCGM *inNext)
: cgmPictureDescriptor(inOwner, inPrev, inNext) 
{
  cgmIn->getDColr(background);
}
////
// output CGM format
////
int cgmBackgroundColr::cgmOut(cgmOutput *inOut) 
{ 
  inOut->startCmd(this);
  inOut->outDColr(background);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmBackgroundColr::display(baseDisplay *inDisplay)
{
  genColr genBack(background, owner->colrExtent(), owner->colrs());
  ////
  // send a general colour for convenience
  inDisplay->backColr(genBack);
  return 1;
}
#ifdef macintosh
 #pragma segment CGM3
#endif
////
// the Control class
////
const int cgmControl::myClass = 3;
////
// VDC Integer Precision
////
const int cgmVdcInteger::myElement = 1;
const int cgmVdcIntegerMyElement = 1;
const char *cgmVdcInteger::myName = "VDCIntegerPrec";
////
// constructor
////
cgmVdcInteger::cgmVdcInteger(cgmContainer *inOwner, cgmInput *cgmIn,
			     baseCGM *inPrev, baseCGM *inNext) 
: cgmControl(inOwner, inPrev, inNext)
{
  cgmIn->getIntPrec(&thisPrec);
}
////
// output CGM format
////
int cgmVdcInteger::cgmOut(cgmOutput *inOut)
{ 
  inOut->startCmd(this);
  inOut->outIntPrec(&thisPrec);
  inOut->endCmd();
  return 1;
}
////
// VDC Real Precision
////
const int cgmVdcReal::myElement = 2;
const int cgmVdcRealMyElement = 2;
const char *cgmVdcReal::myName = "VDCRealPrec";
////
// constructor
////
cgmVdcReal::cgmVdcReal(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext) 
: cgmControl(inOwner, inPrev, inNext)
{
  cgmIn->getRealPrec(&thisPrec);
}
////
// output CGM format
////
int cgmVdcReal::cgmOut(cgmOutput *inOut) 
{ 
  inOut->startCmd(this);
  inOut->outRealPrec(&thisPrec);
  inOut->endCmd();
  return 1;
}
////
// auxiliary colour
////
const int cgmAuxColr::myElement = 3;
const char *cgmAuxColr::myName = "AuxColr";
////
// constructor
////
cgmAuxColr::cgmAuxColr(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmControl(inOwner, inPrev, inNext)
{
  myColr = cgmIn->getColr(owner->colrMode(), owner->colrExtent(),
			  owner->colrs());
}
////
// output in a CGM format
////
int cgmAuxColr::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outColr(myColr);
  inOut->endCmd();
  return 1;
}
////
// transparency
////
const int cgmTransparency::myElement = 4;
const char *cgmTransparency::myName = "Transparency";
//// 
// aids for parsing
//// 
const char *tmpTransparencyList[] = {"OFF", "ON"};
const char **cgmTransparency::typeList = tmpTransparencyList;
const int cgmTransparency::typeListSize =
sizeof(tmpTransparencyList) / sizeof(tmpTransparencyList[0]);
//// 
// constructor
////
cgmTransparency::cgmTransparency(cgmContainer *inOwner, cgmInput *cgmIn,
				 baseCGM *inPrev, baseCGM *inNext)
: cgmControl(inOwner, inPrev, inNext)
{
  myType = cgmIn->getType(typeList, typeListSize);
}
//// 
// output in a CGM format
//// 
int cgmTransparency::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmTransparency::display(baseDisplay *inDisplay)
{
  inDisplay->transparency(myType);
  return 1;
}
////
// clip rectangle
////
const int cgmClipRect::myElement = 5;
const char *cgmClipRect::myName = "ClipRect";
////
// constructor
////
cgmClipRect::cgmClipRect(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmControl(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(2);
}
////
// output in a CGM format
////
int cgmClipRect::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmClipRect::display(baseDisplay *inDisplay)
{
  inDisplay->clipRect(myPts);
  return 1;
}
////
// clip indicator
////
const int cgmClip::myElement = 6;
const char *cgmClip::myName = "Clip";
//// 
// aids for parsing
//// 
const char *tmpClipList[] = {"OFF", "ON"};
const char **cgmClip::typeList = tmpClipList;
const int cgmClip::typeListSize =
sizeof(tmpClipList) / sizeof(tmpClipList[0]);
//// 
// constructor
////
cgmClip::cgmClip(cgmContainer *inOwner, cgmInput *cgmIn,
				 baseCGM *inPrev, baseCGM *inNext)
: cgmControl(inOwner, inPrev, inNext)
{
  myType = cgmIn->getType(typeList, typeListSize);
}
//// 
// output in a CGM format
//// 
int cgmClip::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmClip::display(baseDisplay *inDisplay)
{
  inDisplay->clip(myType);
  return 1;
}
////
// the Graphical Primitive class
////
const int cgmGraphicalPrimitive::myClass = 4;
////
// Polyline
////
const int cgmPolyline::myElement = 1;
const char *cgmPolyline::myName = "Line";
////
// constructor
////
cgmPolyline::cgmPolyline(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext) 
{
  myPts = cgmIn->getVdcPts();
}
////
// destructor
////
cgmPolyline::~cgmPolyline() { 
  if (myPts) delete myPts;
}
////
// output in a CGM format
////
int cgmPolyline::cgmOut(cgmOutput *inOut) 
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmPolyline::display(baseDisplay *inDisplay)
{
  inDisplay->polyline(myPts);
  return 1;
}
////
// Disjoint Polyline
////
const int cgmDisPolyline::myElement = 2;
const char *cgmDisPolyline::myName = "Disjtline";
////
// constructor
////
cgmDisPolyline::cgmDisPolyline(cgmContainer *inOwner, cgmInput *cgmIn,
			       baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext) 
{
  myPts = cgmIn->getVdcPts();
}
////
// destructor
////
cgmDisPolyline::~cgmDisPolyline() { 
  if (myPts) delete myPts;
}
////
// output in a CGM format
////
int cgmDisPolyline::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmDisPolyline::display(baseDisplay *inDisplay)
{
  inDisplay->disPolyline(myPts);
  return 1;
}
////
// Polymarker
////
const int cgmPolymarker::myElement = 3;
const char *cgmPolymarker::myName = "Marker";
////
// constructor
////
cgmPolymarker::cgmPolymarker(cgmContainer *inOwner, cgmInput *cgmIn,
			     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts();
}
////
// destructor
////
cgmPolymarker::~cgmPolymarker() {
  if (myPts) delete myPts;
}
////
// output in a CGM format
////
int cgmPolymarker::cgmOut(cgmOutput *inOut) 
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmPolymarker::display(baseDisplay *inDisplay)
{
  inDisplay->polymarker(myPts);
  return 1;
}
////
// text
////
const int cgmText::myElement = 4;
const char *cgmText::myName = "Text";
//// 
// aids for parsing
//// 
const char *tmpTextList[] = {"NOTFINAL", "FINAL"};
const char **cgmText::typeList = tmpTextList;
const int cgmText::typeListSize =
sizeof(tmpTextList) / sizeof(tmpTextList[0]);
////
// constructor
////
cgmText::cgmText(cgmContainer *inOwner, cgmInput *cgmIn,
		 baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  int textSize;
  vdcPts *myPts = cgmIn->getVdcPts(1);
  int final = cgmIn->getType(typeList, typeListSize);
  char *text = cgmIn->getString(textSize);
  myText = new genText(&(owner->tInfo), final, text, textSize, myPts);
}
////
// output in a CGM format
////
int cgmText::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myText->pos());
  inOut->outType(typeList, myText->final());
  inOut->outString(myText->size() ? myText->contents() : "");
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmText::display(baseDisplay *inDisplay)
{
  inDisplay->text(myText);
  return 1;
}
////
// restricted text
////
const int cgmRestrText::myElement = 5;
const char *cgmRestrText::myName = "RestrText";
//// 
// aids for parsing
//// 
const char **cgmRestrText::typeList = tmpTextList;
const int cgmRestrText::typeListSize =
sizeof(tmpTextList) / sizeof(tmpTextList[0]);
////
// constructor
////
cgmRestrText::cgmRestrText(cgmContainer *inOwner, cgmInput *cgmIn,
		 baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  int textSize;
  maxWidth = cgmIn->getVdc();
  maxHeight = cgmIn->getVdc();
  vdcPts *myPts = cgmIn->getVdcPts(1);
  int final = cgmIn->getType(typeList, typeListSize);
  char *text = cgmIn->getString(textSize);
  myText = new genText(&(owner->tInfo), final, text, textSize,
		       myPts, 0, maxHeight, maxWidth);
}
////
// output in a CGM format
////
int cgmRestrText::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
//  inOut->outVdc(myText->width());
//  inOut->outVdc(myText->height());
  inOut->outVdc(maxWidth);
  inOut->outVdc(maxHeight);
  inOut->outVdcPts(myText->pos());
  inOut->outType(typeList, myText->final());
  inOut->outString(myText->size() ? myText->contents() : "");
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmRestrText::display(baseDisplay *inDisplay)
{
  inDisplay->text(myText);
  return 1;
}
////
// appended text
////
const int cgmApndText::myElement = 6;
const char *cgmApndText::myName = "ApndText";
//// 
// aids for parsing
//// 
const char **cgmApndText::typeList = tmpTextList;
const int cgmApndText::typeListSize =
sizeof(tmpTextList) / sizeof(tmpTextList[0]);
////
// constructor
////
cgmApndText::cgmApndText(cgmContainer *inOwner, cgmInput *cgmIn,
		 baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  int textSize;
  int final = cgmIn->getType(typeList, typeListSize);
  char *text = cgmIn->getString(textSize);
  myText = new genText(&(owner->tInfo), final, text, textSize);
}
////
// output in a CGM format
////
int cgmApndText::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myText->final());
  inOut->outString(myText->size() ? myText->contents() : "");
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmApndText::display(baseDisplay *inDisplay)
{
  inDisplay->text(myText);
  return 1;
}
////
// Polygon
////
const int cgmPolygon::myElement = 7;
const char *cgmPolygon::myName = "Polygon";
cgmPolygon::cgmPolygon(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext) // constructor
{
  myPts = cgmIn->getVdcPts();
}
////
// destructor
////
cgmPolygon::~cgmPolygon() {
  if (myPts) delete myPts;
}
////
// output in a CGM format
////
int cgmPolygon::cgmOut(cgmOutput *inOut) 
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmPolygon::display(baseDisplay *inDisplay)
{
  inDisplay->polygon(myPts);
  return 1;
}
////
// Polygon Set
////
// aids for parsing
//// 
const char *tmpPolygonSetList[] = {"INVIS", "VIS", "CLOSEINVIS", "CLOSEVIS"};
const char **cgmPolygonSet::typeList = tmpPolygonSetList;
const int cgmPolygonSet::typeListSize =
sizeof(tmpPolygonSetList) / sizeof(tmpPolygonSetList[0]);
//// 
const int cgmPolygonSet::myElement = 8;
const char *cgmPolygonSet::myName = "PolygonSet";
cgmPolygonSet::cgmPolygonSet(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext) // constructor
{
  cgmIn->polygonSet(myPts, myFlags);
}
////
// output in a CGM format
////
int cgmPolygonSet::cgmOut(cgmOutput *inOut) 
{
  inOut->startCmd(this);
  inOut->polygonSet(myPts, myFlags);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmPolygonSet::display(baseDisplay *inDisplay)
{
  inDisplay->polygonSet(myPts, myFlags);
  return 1;
}

////
// Cell Array class
////
// constructor
////
cellArray::cellArray(int inColMode, const colrValueExtent *inExtent,
			  vdcPts *inCorners, int inNx, int inNy,
			  int inPrec, int inRepMode,
			  const colrTable *inTable)
{
  char myString[40];
  // assign the private variables
  myColMode = inColMode;
  myExtent = inExtent;
  myCorners = inCorners;
  myNx = inNx;
  myNy = inNy;
  ////
  // check the legality of the precision
  if ((inPrec != 1) && (inPrec != 2) && (inPrec != 4) && (inPrec != 8) &&
		(inPrec != 16) && (inPrec != 24) && (inPrec != 32)) {
	 sprintf(myString, "%d", inPrec);
	 myError("illegal cell array precision", myString);
	 myPrec = 8; // default
  } else myPrec = inPrec;
  myRepMode = inRepMode;
  myTable = inTable;
  ////
  // how much memory do we need (real men don't pad -- or deal with a pc!!!!)
  totalBits = (long)inNy * inNx * ((inColMode) ? 3 : 1) * inPrec;
  totalBytes = (totalBits + 7) / 8;

#if __MSDOS__
  if (totalBytes < (long)66000) totalBytes = 66000;
  hContentsBuffer = GlobalAlloc(GPTR,totalBytes);
  if (hContentsBuffer)   myContents = (HugePt)GlobalLock(hContentsBuffer);
  else myContents = NULL;
#else
  myContents = new unsigned char[totalBytes];
  for (int i=0; i<totalBytes; ++i) myContents[i] = 0;
#endif
  ////
  bitsAdded = 0; // no input values yet
}

cellArray::~cellArray()
	{
	delete myCorners;
#if __MSDOS__
  if (hContentsBuffer)
	  {
	  GlobalUnlock(hContentsBuffer);
	  GlobalFree(hContentsBuffer);
	  myContents = NULL;
	  }
#endif

  if (myContents)	delete myContents;
	}
////
// add one value
////
int cellArray::addValue(unsigned int inVal)
{
  if ((bitsAdded + myPrec) > totalBits) return 0; // too many bits
  ////
  // note that since only valid values of prec are 1,2,4,8,16,24,32
  // value either fits within one byte or spans several whole bytes
  // hence we use the most convenient storage format
  int startByte = (int) (bitsAdded / 8);
  ////
  // note use of fallthru in switch statement
  switch (myPrec) {
  case 32:
	 myContents[startByte] = 255 & ((inVal & (255 << 24)) >> 24); ++startByte;
  case 24:
	 myContents[startByte] = 255 & ((inVal & (255 << 16)) >> 16); ++startByte;
  case 16:
	 myContents[startByte] = 255 & ((inVal & (255 << 8)) >> 8); ++startByte;
  case 8:
	 myContents[startByte] = 255 & inVal; break;  // end fallthru
  case 4:
	 myContents[startByte] |= (15 & inVal) << (int) (bitsAdded % 8); break;
  case 2:
	 myContents[startByte] |= (3 & inVal) << (int) (bitsAdded % 8); break;
  case 1:
	 myContents[startByte] |= (1 & inVal) << (int) (bitsAdded % 8); break;
  }
  bitsAdded += myPrec;
  return 1;
}
////
// add multiple values
////
#if __MSDOS__
int cellArray::addValues(HugePt inPtr, int bitsAlong,  int noValues)
#else
int cellArray::addValues(unsigned char *inPtr, int bitsAlong,  int noValues)
#endif
{
  if ((bitsAdded + noValues * myPrec) > totalBits) return 0; // too many bits
  ////
  unsigned int inVal;
  unsigned long inByte, startByte, bitOffset;
  ////
  // note use of fallthru in switch statements
  for (int i=0; i<noValues; ++i) {
	 inVal = 0;
	 inByte = bitsAlong / (long)8;
	 bitOffset = 8 - (myPrec + (bitsAlong % (long)8)); // only used if myprec < 8
	 ////
	 // first get the input value
	 switch (myPrec) {
	 case 32:
		inVal |= ((unsigned int) inPtr[inByte]) << 24; ++inByte;
	 case 24:
		inVal |= ((unsigned int) inPtr[inByte]) << 16; ++inByte;
	 case 16:
		inVal |= ((unsigned int) inPtr[inByte]) << 8; ++inByte;
	 case 8:
		inVal |= inPtr[inByte]; // end fallthru
		break;
	 case 4:
		inVal |= (inPtr[inByte] & (int) (15 << bitOffset)) >> (int) bitOffset;
		break;
	 case 2:
		inVal |= (inPtr[inByte] & (int) (3 << bitOffset)) >> (int) bitOffset;
		break;
	 case 1:
		inVal |= (inPtr[inByte] & (int) (1 << bitOffset)) >> (int) bitOffset;
		break;
	 }
	 bitsAlong += myPrec;
	 // now put value into local memory
	 startByte = bitsAdded / (long)8;
	 switch (myPrec) {
	 case 32:
		myContents[startByte] = 255 & ((inVal & (255 << 24)) >> 24); ++startByte;
	 case 24:
		myContents[startByte] = 255 & ((inVal & (255 << 16)) >> 16); ++startByte;
	 case 16:
		myContents[startByte] = 255 & ((inVal & (255 << 8)) >> 8); ++startByte;
	 case 8:
		myContents[startByte] |= 255 & inVal;  // end fallthru
	 break;
	 case 4:
		myContents[startByte] |= (15 & inVal) << (int) (bitsAdded % 8);
		break;
	 case 2:
		myContents[startByte] |= (3 & inVal) << (int) (bitsAdded % 8);
		break;
	 case 1:
		myContents[startByte] |= (1 & inVal) << (int) (bitsAdded % 8);
		break;
	 }
	 bitsAdded += myPrec;
  }
  return 1;
}
////
// get a single value as set of 3 floats
////
float *cellArray::getFloats(unsigned long inIndex) const
{
  static float rValues[3];
  int i;
  if (inIndex >= (long)((long)myNx * myNy)) { // outside scope
//    for (i=0; i<3; ++i) rvalues[i] = 0;
	 for (i=0; i<3; ++i) rValues[i] = 0;
	 return rValues;
  }
  int useVal;
  if (myColMode) { // r,g,b format
	 for (i=0; i<3; ++i) {
		useVal = getValue(inIndex * 3 + i);
//      if (useVal >= myExtent->white[i]) {
		if (useVal >= myExtent->white.getValue(i)) {
	rValues[i] = 1; // max possible
//      } else if (useVal <= myExtent->black[i]) {
		} else if (useVal <= myExtent->black.getValue(i)) {
	rValues[i] = 0; // min possible
		} else {
//	rValues[i] = (float) (useVal - myExtent->black[i]) /
//	  (myExtent->white[i] - myExtent->black[i]);
	rValues[i] = (float) (useVal - myExtent->black.getValue(i)) /
	  (myExtent->white.getValue(i) - myExtent->black.getValue(i));
		}
	 }
  } else { // indexed
	 int useIndex = getValue(inIndex);
	 for (i=0; i<3; ++i) {
//      useVal = myTable->val(useIndex)[i];
		useVal = myTable->val(useIndex).getValue(i);
//      if (useVal >= myExtent->white[i]) {
		if (useVal >= myExtent->white.getValue(i)) {
	rValues[i] = 1; // max possible
//      } else if (useVal <= myExtent->black[i]) {
		} else if (useVal <= myExtent->black.getValue(i)) {
	rValues[i] = 0; // min possible
		} else {
//	rValues[i] = (float) (useVal - myExtent->black[i]) /
//	  (myExtent->white[i] - myExtent->black[i]);
	rValues[i] = (float) (useVal - myExtent->black.getValue(i)) /
	  (myExtent->white.getValue(i) - myExtent->black.getValue(i));
		}
	 }
  }
  return rValues;
}
////
// get one integer value
////
unsigned int cellArray::getValue(unsigned long inIndex) const
{
  if (inIndex * myPrec > totalBits) { // outside scope
	 return 0;
  }
  unsigned int outInt = 0;
  unsigned long bitsAlong = inIndex * myPrec;
  unsigned int bitOffset = (unsigned int) (bitsAlong & 7); // (bitsAlong % 8)
  unsigned long startByte = bitsAlong / 8;
  ////
  // note use of fallthru in switch statement
  switch (myPrec) {
  case 32:
	 outInt |= ((unsigned int) myContents[startByte]) << 24; ++startByte;
  case 24:
	 outInt |= ((unsigned int) myContents[startByte]) << 16; ++startByte;
  case 16:
	 outInt |= ((unsigned int) myContents[startByte]) << 8; ++startByte;
  case 8:
	 outInt |= myContents[startByte]; // end fallthru
	 break;
  case 4:
	 outInt |= (myContents[startByte] & (15 << bitOffset)) >> bitOffset;
	 break;
  case 2:
	 outInt |= (myContents[startByte] & (3 << bitOffset)) >> bitOffset;
	 break;
  case 1:
	 outInt |= (myContents[startByte] & (1 << bitOffset)) >> bitOffset;
	 break;
  }
  return outInt;
}

// decompress
////
void cellArray::decompress()
{
}
////
// dump out as a set of grey values
////
void cellArray::fillGrey(unsigned char* &inPtr) const
{
  float *myColrs;
  unsigned char *myPtr = inPtr = new unsigned char [nx() * ny()];
  for (int i=0; i<ny(); ++i) {
    for (int j=0; j<nx(); ++j) {
      myColrs = getFloats(j, i);
      *(myPtr++) = (unsigned char)
	(255.99 * (0.3 * myColrs[0] + 0.59 * myColrs[1] + 0.11 * myColrs[2]));
    }
  }
}
////
// dump out as a set of colours
////
void cellArray::fillColr(unsigned char* &inPtr) const
{
  float *myColrs;
  unsigned char *myPtr = inPtr = new unsigned char [nx() * ny() * 3];
  for (int i=0; i<ny(); ++i) {
	 for (int j=0; j<nx(); ++j) {
      myColrs = getFloats(j, i);
      for (int k=0; k<3; ++k) {
	*(myPtr++) = (unsigned char) (255.99 * myColrs[k]);
      }
    }
  }
}

////
// Cell Array element
////
const int cgmCellArray::myElement = 9;
const char *cgmCellArray::myName = "CellArray";
cgmCellArray::cgmCellArray(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext) // constructor
{
  myCell = cgmIn->getCellArray(owner->colrMode(), owner->colrExtent(),
			       owner->colrs());
}
////
// destructor
////
cgmCellArray::~cgmCellArray() {
  if (myCell) delete myCell;
}
////
// output in a CGM format
////
int cgmCellArray::cgmOut(cgmOutput *inOut) 
{
  inOut->startCmd(this);
  inOut->outCellArray(myCell);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmCellArray::display(baseDisplay *inDisplay)
{
  inDisplay->cells(myCell);
  return 1;
}


////
// Generalized Drawing Primitive
////
const int cgmGDP::myElement = 10;
const char *cgmGDP::myName = "GDP";
cgmGDP::cgmGDP(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext) // constructor
{
}
////
// output in a CGM format
////
int cgmGDP::cgmOut(cgmOutput *inOut) 
{
  inOut->startCmd(this);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmGDP::display(baseDisplay *inDisplay)
{
//   inDisplay->GDP(myPts); // fix later
  return 1;
}
////
// Rectangle
////
const int cgmRectangle::myElement = 11;
const char *cgmRectangle::myName = "Rect";
////
// constructor
////
cgmRectangle::cgmRectangle(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(2);
  if (myPts->no() != 2) myError("not enough points for rectangle");
}
////
// destructor
////
cgmRectangle::~cgmRectangle() {
  if (myPts) delete myPts;
}
////
// output in a CGM format
////
int cgmRectangle::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmRectangle::display(baseDisplay *inDisplay)
{
  inDisplay->rectangle(myPts);
  return 1;
}
////
// Circle
////
const int cgmCircle::myElement = 12;
const char *cgmCircle::myName = "Circle";
////
// constructor
////
cgmCircle::cgmCircle(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  centre = cgmIn->getVdcPts(1);
  radius = cgmIn->getVdc();
}
////
// destructor
////
cgmCircle::~cgmCircle() {
  if (centre) delete centre;
  if (radius) delete radius;
}
////
// output in a CGM format
////
int cgmCircle::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(centre);
  inOut->outVdc(radius);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmCircle::display(baseDisplay *inDisplay)
{
  inDisplay->circle(centre, radius);
  return 1;
}
////
// Circular arc, 3 pts
////
const int cgmArc3Pt::myElement = 13;
const char *cgmArc3Pt::myName = "Arc3Pt";
////
// constructor
////
cgmArc3Pt::cgmArc3Pt(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(3);
}
////
// output in a CGM format
////
int cgmArc3Pt::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmArc3Pt::display(baseDisplay *inDisplay)
{
  inDisplay->arc3Pt(myPts, -1); // -1 -> not closed
  return 1;
}
////
// Circular arc, 3 pts, closed
////
const int cgmArc3PtClose::myElement = 14;
const char *cgmArc3PtClose::myName = "Arc3PtClose";
//// 
// aids for parsing
//// 
const char *tmpCloseList[] = {"PIE", "CHORD"};
const char **cgmArc3PtClose::typeList = tmpCloseList;
const int cgmArc3PtClose::typeListSize =
sizeof(tmpCloseList) / sizeof(tmpCloseList[0]);
////
// constructor
////
cgmArc3PtClose::cgmArc3PtClose(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(3);
  myType = cgmIn->getType(typeList, typeListSize);
}
////
// output in a CGM format
////
int cgmArc3PtClose::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmArc3PtClose::display(baseDisplay *inDisplay)
{
  inDisplay->arc3Pt(myPts, myType);
  return 1;
}
////
// Circular arc, centre, 2 vectors and a radius
////
const int cgmArcCtr::myElement = 15;
const char *cgmArcCtr::myName = "ArcCtr";
////
// constructor
////
cgmArcCtr::cgmArcCtr(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(3);
  radius =  cgmIn->getVdc();
}
////
// output in a CGM format
////
int cgmArcCtr::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->outVdc(radius);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmArcCtr::display(baseDisplay *inDisplay)
{
  inDisplay->arcCtr(myPts, radius, -1); // -1 -> not closed
  return 1;
}
////
// Circular arc, centre, 2 vectors and a radius, closed
////
const int cgmArcCtrClose::myElement = 16;
const char *cgmArcCtrClose::myName = "ArcCtrClose";
//// 
// aids for parsing
//// 
const char **cgmArcCtrClose::typeList = tmpCloseList;
const int cgmArcCtrClose::typeListSize =
sizeof(tmpCloseList) / sizeof(tmpCloseList[0]);
////
// constructor
////
cgmArcCtrClose::cgmArcCtrClose(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(3);
  radius =  cgmIn->getVdc();
  myType = cgmIn->getType(typeList, typeListSize);
}
////
// output in a CGM format
////
int cgmArcCtrClose::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->outVdc(radius);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmArcCtrClose::display(baseDisplay *inDisplay)
{
  inDisplay->arcCtr(myPts, radius, myType); 
  return 1;
}
////
// Ellipse, specified by 3 pts
////
const int cgmEllipse::myElement = 17;
const char *cgmEllipse::myName = "Ellipse";
////
// constructor
////
cgmEllipse::cgmEllipse(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(3);
}
////
// output in a CGM format
////
int cgmEllipse::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEllipse::display(baseDisplay *inDisplay)
{
  inDisplay->ellipse(myPts);
  return 1;
}
////
// Elliptical arc, specified by 5 pts
////
const int cgmEllipArc::myElement = 18;
const char *cgmEllipArc::myName = "EllipArc";
////
// constructor
////
cgmEllipArc::cgmEllipArc(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(5);
}
////
// output in a CGM format
////
int cgmEllipArc::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEllipArc::display(baseDisplay *inDisplay)
{
  inDisplay->ellipArc(myPts, -1);
  return 1;
}
////
// Elliptical arc, specified by 5 pts, closed
////
const int cgmEllipArcClose::myElement = 19;
const char *cgmEllipArcClose::myName = "EllipArcClose";
//// 
// aids for parsing
//// 
const char **cgmEllipArcClose::typeList = tmpCloseList;
const int cgmEllipArcClose::typeListSize =
sizeof(tmpCloseList) / sizeof(tmpCloseList[0]);
////
// constructor
////
cgmEllipArcClose::cgmEllipArcClose(cgmContainer *inOwner, cgmInput *cgmIn,
		     baseCGM *inPrev, baseCGM *inNext)
: cgmGraphicalPrimitive(inOwner, inPrev, inNext)
{
  myPts = cgmIn->getVdcPts(5);
  myType = cgmIn->getType(typeList, typeListSize);
}
////
// output in a CGM format
////
int cgmEllipArcClose::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEllipArcClose::display(baseDisplay *inDisplay)
{
  inDisplay->ellipArc(myPts, myType);
  return 1;
}
////
// the Attribute class
////
const int cgmAttribute::myClass = 5;
////
// line bundle index
////
const int cgmLineIndex::myElement = 1;
const char *cgmLineIndex::myName = "LineIndex";
////
// constructor
////
cgmLineIndex::cgmLineIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmLineIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmLineIndex::display(baseDisplay *inDisplay)
{
  inDisplay->lineIndex(myIndex);
  return 1;
}
#ifdef macintosh
 #pragma segment CGM4
#endif
////
// line type
////
const int cgmLineType::myElement = 2;
const char *cgmLineType::myName = "LineType";
////
// constructor
////
cgmLineType::cgmLineType(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myType = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmLineType::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmLineType::display(baseDisplay *inDisplay)
{
  inDisplay->lineType(myType);
  return 1;
}
////
// line width
////
const int cgmLineWidth::myElement = 3;
const char *cgmLineWidth::myName = "LineWidth";
////
// constructor
////
cgmLineWidth::cgmLineWidth(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myVdcR = (owner->lineMode()) ? new vdcR(cgmIn->getReal()) // scaled
    : new vdcR(cgmIn->getVdc()); // absolute
}
////
// destructor
////
cgmLineWidth::~cgmLineWidth()
{
  if (myVdcR) delete myVdcR;
}
////
// output in a CGM format
////
int cgmLineWidth::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  if (myVdcR->type()) inOut->outReal(myVdcR->f()); // scaled
  else inOut->outVdc(myVdcR->v()); // absolute
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmLineWidth::display(baseDisplay *inDisplay)
{
  inDisplay->lineWidth(myVdcR);
  return 1;
}
////
// line colour
////
const int cgmLineColr::myElement = 4;
const char *cgmLineColr::myName = "LineColr";
////
// constructor
////
cgmLineColr::cgmLineColr(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myColr = cgmIn->getColr(owner->colrMode(), owner->colrExtent(),
			  owner->colrs());
}
////
// output in a CGM format
////
int cgmLineColr::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outColr(myColr);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmLineColr::display(baseDisplay *inDisplay)
{
  if (myColr) inDisplay->lineColr(*myColr);
  return 1;
}
////
// Marker bundle index
////
const int cgmMarkerIndex::myElement = 5;
const char *cgmMarkerIndex::myName = "MarkerIndex";
////
// constructor
////
cgmMarkerIndex::cgmMarkerIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmMarkerIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmMarkerIndex::display(baseDisplay *inDisplay)
{
  inDisplay->markerIndex(myIndex);
  return 1;
}
////
// marker type
////
const int cgmMarkerType::myElement = 6;
const char *cgmMarkerType::myName = "MarkerType";
////
// constructor
////
cgmMarkerType::cgmMarkerType(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myType = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmMarkerType::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmMarkerType::display(baseDisplay *inDisplay)
{
  inDisplay->markerType(myType);
  return 1;
}
////
// marker size
////
const int cgmMarkerSize::myElement = 7;
const char *cgmMarkerSize::myName = "MarkerSize";
////
// constructor
////
cgmMarkerSize::cgmMarkerSize(cgmContainer *inOwner, cgmInput *cgmIn,
			     baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myVdcR = (owner->markerMode()) ? new vdcR(cgmIn->getReal()) // scaled
    : new vdcR(cgmIn->getVdc()); // absolute
}
////
// destructor
////
cgmMarkerSize::~cgmMarkerSize()
{
  if (myVdcR) delete myVdcR;
}
////
// output in a CGM format
////
int cgmMarkerSize::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  if (myVdcR->type()) inOut->outReal(myVdcR->f()); // scaled
  else inOut->outVdc(myVdcR->v()); // absolute
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmMarkerSize::display(baseDisplay *inDisplay)
{
  inDisplay->markerSize(myVdcR);
  return 1;
}
////
// marker colour
////
const int cgmMarkerColr::myElement = 8;
const char *cgmMarkerColr::myName = "MarkerColr";
////
// constructor
////
cgmMarkerColr::cgmMarkerColr(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myColr = cgmIn->getColr(owner->colrMode(), owner->colrExtent(),
			  owner->colrs());
}
////
// output in a CGM format
////
int cgmMarkerColr::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outColr(myColr);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmMarkerColr::display(baseDisplay *inDisplay)
{
  if (myColr) inDisplay->markerColr(*myColr);
  return 1;
}
////
// text bundle index
////
const int cgmTextIndex::myElement = 9;
const char *cgmTextIndex::myName = "TextIndex";
////
// constructor
////
cgmTextIndex::cgmTextIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmTextIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmTextIndex::display(baseDisplay *inDisplay)
{
  inDisplay->textIndex(myIndex);
  return 1;
}
////
// text font index
////
const int cgmFontIndex::myElement = 10;
const char *cgmFontIndex::myName = "TextFontIndex";
////
// constructor
////
cgmFontIndex::cgmFontIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmFontIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmFontIndex::display(baseDisplay *inDisplay)
{
  inDisplay->fontIndex(myIndex);
  owner->tInfo.setFont(myIndex);
  return 1;
}
////
// Text Precision
////
const int cgmTextPrec::myElement = 11;
const char *cgmTextPrec::myName = "TextPrec";
//// 
// aids for parsing
//// 
const char *tmpTextPrecList[] = {"STRING", "CHAR", "STROKE"};
const char **cgmTextPrec::typeList = tmpTextPrecList;
const int cgmTextPrec::typeListSize =
sizeof(tmpTextPrecList) / sizeof(tmpTextPrecList[0]);
//// 
// constructor
////
cgmTextPrec::cgmTextPrec(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myType = cgmIn->getType(typeList, typeListSize);
}
//// 
// output in a CGM format
//// 
int cgmTextPrec::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmTextPrec::display(baseDisplay *inDisplay)
{
  inDisplay->textPrec(myType);
  owner->tInfo.setPrec(myType);
  return 1;
}
////
// character expansion factor
////
const int cgmCharExpan::myElement = 12;
const char *cgmCharExpan::myName = "CharExpan";
//// 
// constructor
////
cgmCharExpan::cgmCharExpan(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  factor = cgmIn->getReal();
  owner->tInfo.setExpan(factor);
}
//// 
// output in a CGM format
//// 
int cgmCharExpan::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outReal(factor);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmCharExpan::display(baseDisplay *inDisplay)
{
  inDisplay->charExpan(factor);
  owner->tInfo.setExpan(factor);
  return 1;
}
////
// character spacing
////
const int cgmCharSpace::myElement = 13;
const char *cgmCharSpace::myName = "CharSpace";
//// 
// constructor
////
cgmCharSpace::cgmCharSpace(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  spacing = cgmIn->getReal();
}
//// 
// output in a CGM format
//// 
int cgmCharSpace::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outReal(spacing);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmCharSpace::display(baseDisplay *inDisplay)
{
  inDisplay->charSpace(spacing);
  owner->tInfo.setSpace(spacing);
  return 1;
}
////
// text colour
////
const int cgmTextColr::myElement = 14;
const char *cgmTextColr::myName = "TextColr";
////
// constructor
////
cgmTextColr::cgmTextColr(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myColr = cgmIn->getColr(owner->colrMode(), owner->colrExtent(),
			  owner->colrs());
}
////
// output in a CGM format
////
int cgmTextColr::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outColr(myColr);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmTextColr::display(baseDisplay *inDisplay)
{
  if (myColr) {
    inDisplay->textColr(*myColr);
    owner->tInfo.setColr(myColr);
  }
  return 1;
}
////
// character height
////
const int cgmCharHeight::myElement = 15;
const char *cgmCharHeight::myName = "CharHeight";
//// 
// constructor
////
cgmCharHeight::cgmCharHeight(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  height = cgmIn->getVdc();
}
//// 
// output in a CGM format
//// 
int cgmCharHeight::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdc(height);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmCharHeight::display(baseDisplay *inDisplay)
{
  owner->tInfo.setHeight(height->f());
  inDisplay->charHeight(height);
  return 1;
}
////
// character orientation
////
const int cgmCharOri::myElement = 16;
const char *cgmCharOri::myName = "CharOri";
//// 
// constructor
////
cgmCharOri::cgmCharOri(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
 orientation = cgmIn->getVdcPts(2);
}
//// 
// output in a CGM format
//// 
int cgmCharOri::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(orientation);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmCharOri::display(baseDisplay *inDisplay)
{
  owner->tInfo.setOrientation(orientation);
  inDisplay->charOri(orientation);
  return 1;
}
////
// Text Path
////
const int cgmTextPath::myElement = 17;
const char *cgmTextPath::myName = "TextPath";
//// 
// aids for parsing
//// 
const char *tmpTextPathList[] = {"RIGHT", "LEFT", "UP", "DOWN"};
const char **cgmTextPath::typeList = tmpTextPathList;
const int cgmTextPath::typeListSize =
sizeof(tmpTextPathList) / sizeof(tmpTextPathList[0]);
//// 
// constructor
////
cgmTextPath::cgmTextPath(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myType = cgmIn->getType(typeList, typeListSize);
}
//// 
// output in a CGM format
//// 
int cgmTextPath::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmTextPath::display(baseDisplay *inDisplay)
{
  inDisplay->textPath(myType);
  owner->tInfo.setPath(myType);
  return 1;
}
////
// Text alignment
////
const int cgmTextAlign::myElement = 18;
const char *cgmTextAlign::myName = "TextAlign";
//// 
// aids for parsing
//// 
const char *tmpTextAlignList1[] = {"NORMHORIZ", "LEFT", "CTR", "RIGHT",
				 "CONTHORIZ"};
const char **cgmTextAlign::typeList1 = tmpTextAlignList1;
const int cgmTextAlign::typeListSize1 =
sizeof(tmpTextAlignList1) / sizeof(tmpTextAlignList1[0]);
const char *tmpTextAlignList2[] = {"NORMVERT", "TOP", "CAP", "HALF",
				 "BASE", "BOTTOM", "CONTVERT"};
const char **cgmTextAlign::typeList2 = tmpTextAlignList2;
const int cgmTextAlign::typeListSize2 =
sizeof(tmpTextAlignList2) / sizeof(tmpTextAlignList2[0]);
//// 
// constructor
////
cgmTextAlign::cgmTextAlign(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  int inH = cgmIn->getType(typeList1, typeListSize1);
  int inV = cgmIn->getType(typeList2, typeListSize2);
  float inCH = cgmIn->getReal();
  float inCV = cgmIn->getReal();
  myAlign = new alignment(inH, inV, inCH, inCV);
}
//// 
// output in a CGM format
//// 
int cgmTextAlign::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList1, myAlign->h());
  inOut->outType(typeList2, myAlign->v());
  inOut->outReal(myAlign->cH());
  inOut->outReal(myAlign->cV());
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmTextAlign::display(baseDisplay *inDisplay)
{
  owner->tInfo.setAlign(myAlign);
  inDisplay->textAlign(myAlign);
  return 1;
}
////
// character set index
////
const int cgmCharSetIndex::myElement = 19;
const char *cgmCharSetIndex::myName = "CharSetIndex";
////
// constructor
////
cgmCharSetIndex::cgmCharSetIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmCharSetIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmCharSetIndex::display(baseDisplay *inDisplay)
{
  inDisplay->charSetIndex(myIndex);
  return 1;
}
////
// alternate character set index
////
const int cgmAltCharSetIndex::myElement = 20;
const char *cgmAltCharSetIndex::myName = "AltCharSetIndex";
////
// constructor
////
cgmAltCharSetIndex::cgmAltCharSetIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmAltCharSetIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmAltCharSetIndex::display(baseDisplay *inDisplay)
{
  inDisplay->altCharSetIndex(myIndex);
  return 1;
}
////
// fill bundle index
////
const int cgmFillIndex::myElement = 21;
const char *cgmFillIndex::myName = "FillIndex";
////
// constructor
////
cgmFillIndex::cgmFillIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmFillIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmFillIndex::display(baseDisplay *inDisplay)
{
  inDisplay->fillIndex(myIndex);
  return 1;
}
////
// interior style
////
const int cgmIntStyle::myElement = 22;
const char *cgmIntStyle::myName = "IntStyle";
//// 
// aids for parsing
//// 
const char *tmpIntStyleList[] = {"HOLLOW", "SOLID", "PAT",
			       "HATCH", "EMPTY"};
const char **cgmIntStyle::typeList = tmpIntStyleList;
const int cgmIntStyle::typeListSize =
sizeof(tmpIntStyleList) / sizeof(tmpIntStyleList[0]);
//// 
// constructor
////
cgmIntStyle::cgmIntStyle(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myType = cgmIn->getType(typeList, typeListSize);
}
//// 
// output in a CGM format
//// 
int cgmIntStyle::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmIntStyle::display(baseDisplay *inDisplay)
{
  inDisplay->intStyle(myType);
  return 1;
}
////
// fill colour
////
const int cgmFillColr::myElement = 23;
const char *cgmFillColr::myName = "FillColr";
////
// constructor
////
cgmFillColr::cgmFillColr(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myColr = cgmIn->getColr(owner->colrMode(), owner->colrExtent(),
			  owner->colrs());
}
////
// output in a CGM format
////
int cgmFillColr::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outColr(myColr);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmFillColr::display(baseDisplay *inDisplay)
{
  if (myColr) inDisplay->fillColr(*myColr);
  return 1;
}
////
// hatch index
////
const int cgmHatchIndex::myElement = 24;
const char *cgmHatchIndex::myName = "HatchIndex";
////
// constructor
////
cgmHatchIndex::cgmHatchIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmHatchIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmHatchIndex::display(baseDisplay *inDisplay)
{
  inDisplay->hatchIndex(myIndex);
  return 1;
}
////
// pattern index
////
const int cgmPatIndex::myElement = 24;
const char *cgmPatIndex::myName = "PatIndex";
////
// constructor
////
cgmPatIndex::cgmPatIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmPatIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmPatIndex::display(baseDisplay *inDisplay)
{
  inDisplay->patIndex(myIndex);
  return 1;
}
////
// Edge bundle index
////
const int cgmEdgeIndex::myElement = 26;
const char *cgmEdgeIndex::myName = "EdgeIndex";
////
// constructor
////
cgmEdgeIndex::cgmEdgeIndex(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myIndex = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmEdgeIndex::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myIndex);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEdgeIndex::display(baseDisplay *inDisplay)
{
  inDisplay->edgeIndex(myIndex);
  return 1;
}
////
// edge type
////
const int cgmEdgeType::myElement = 27;
const char *cgmEdgeType::myName = "EdgeType";
////
// constructor
////
cgmEdgeType::cgmEdgeType(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myType = cgmIn->getInt();
}
////
// output in a CGM format
////
int cgmEdgeType::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outInt(myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEdgeType::display(baseDisplay *inDisplay)
{
  inDisplay->edgeType(myType);
  return 1;
}
#ifdef macintosh
 #pragma segment CGM5
#endif
////
// edge width
////
const int cgmEdgeWidth::myElement = 28;
const char *cgmEdgeWidth::myName = "EdgeWidth";
////
// constructor
////
cgmEdgeWidth::cgmEdgeWidth(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myVdcR = (owner->edgeMode()) ? new vdcR(cgmIn->getReal()) // scaled
    : new vdcR(cgmIn->getVdc()); // absolute
}
////
// destructor
////
cgmEdgeWidth::~cgmEdgeWidth()
{
  if (myVdcR) delete myVdcR;
}
////
// output in a CGM format
////
int cgmEdgeWidth::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  if (myVdcR->type()) inOut->outReal(myVdcR->f()); // scaled
  else inOut->outVdc(myVdcR->v()); // absolute
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEdgeWidth::display(baseDisplay *inDisplay)
{
  inDisplay->edgeWidth(myVdcR);
  return 1;
}
////
// edge colour
////
const int cgmEdgeColr::myElement = 29;
const char *cgmEdgeColr::myName = "EdgeColr";
////
// constructor
////
cgmEdgeColr::cgmEdgeColr(cgmContainer *inOwner, cgmInput *cgmIn,
			   baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myColr = cgmIn->getColr(owner->colrMode(), owner->colrExtent(),
			  owner->colrs());
}
////
// output in a CGM format
////
int cgmEdgeColr::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outColr(myColr);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEdgeColr::display(baseDisplay *inDisplay)
{
  if (myColr) inDisplay->edgeColr(*myColr);
  return 1;
}
////
// edge visibility
////
const int cgmEdgeVis::myElement = 30;
const char *cgmEdgeVis::myName = "EdgeVis";
//// 
// aids for parsing
//// 
const char *tmpEdgeVisList[] = {"OFF", "ON"};
const char **cgmEdgeVis::typeList = tmpEdgeVisList;
const int cgmEdgeVis::typeListSize =
sizeof(tmpEdgeVisList) / sizeof(tmpEdgeVisList[0]);
//// 
// constructor
////
cgmEdgeVis::cgmEdgeVis(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  myType = cgmIn->getType(typeList, typeListSize);
}
//// 
// output in a CGM format
//// 
int cgmEdgeVis::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outType(typeList, myType);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmEdgeVis::display(baseDisplay *inDisplay)
{
  inDisplay->edgeVis(myType);
  return 1;
}
////
// fill reference point
////
const int cgmFillRefPt::myElement = 31;
const char *cgmFillRefPt::myName = "FillRefPt";
//// 
// constructor
////
cgmFillRefPt::cgmFillRefPt(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
 myPts = cgmIn->getVdcPts(1);
}
//// 
// output in a CGM format
//// 
int cgmFillRefPt::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmFillRefPt::display(baseDisplay *inDisplay)
{
  inDisplay->fillRefPt(myPts);
  return 1;
}
////
// pattern size
////
const int cgmPatSize::myElement = 33;
const char *cgmPatSize::myName = "PatSize";
//// 
// constructor
////
cgmPatSize::cgmPatSize(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
 myPts = cgmIn->getVdcPts(2);
}
//// 
// output in a CGM format
//// 
int cgmPatSize::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outVdcPts(myPts);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmPatSize::display(baseDisplay *inDisplay)
{
  // nothing for now
  return 1;
}
////
// pattern table
////
const int cgmPatTable::myElement = 32;
const char *cgmPatTable::myName = "PatTable";
//// 
// constructor
////
cgmPatTable::cgmPatTable(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  // fixlater
}
//// 
// output in a CGM format
//// 
int cgmPatTable::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  // fix later
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmPatTable::display(baseDisplay *inDisplay)
{
  // fix later
  return 1;
}
////
// colour table
////
const int cgmColrTable::myElement = 34;
const char *cgmColrTable::myName = "ColrTable";
//// 
// constructor
////
cgmColrTable::cgmColrTable(cgmContainer *inOwner, cgmInput *cgmIn,
		       baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
 myTable = cgmIn->getColrTable(owner->colrExtent());
 owner->colrs()->addTable(myTable);
}
//// 
// output in a CGM format
//// 
int cgmColrTable::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  inOut->outColrTable(myTable);
  inOut->endCmd();
  return 1;
}
////
// display output
////
int cgmColrTable::display(baseDisplay *inDisplay)
{
  inDisplay->colrs(myTable);
  return 1;
}
#ifdef macintosh
 #pragma segment CGM6
#endif
////
// aspect source flags
////
const int cgmASF::myElement = 35;
const char *cgmASF::myName = "ASF";
//// 
// constructor
////
cgmASF::cgmASF(cgmContainer *inOwner, cgmInput *cgmIn,
	    baseCGM *inPrev, baseCGM *inNext)
: cgmAttribute(inOwner, inPrev, inNext)
{
  // fill out later
}
//// 
// output in a CGM format
//// 
int cgmASF::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  // fill out later
  inOut->endCmd();
  return 1;
}
////
// the Escape class
////
const int cgmEscape::myClass = 6;
////
// escape element
////
const int cgmEscapeElement::myElement = 1;
const char *cgmEscapeElement::myName = "Escape";
const int cgmEscapeElement::indexFlag = -64;
//// 
// constructor
////
cgmEscapeElement::cgmEscapeElement(cgmContainer *inOwner, cgmInput *cgmIn,
	    baseCGM *inPrev, baseCGM *inNext)
: cgmEscape(inOwner, inPrev, inNext)
{
  myId = cgmIn->getInt();
  myData = cgmIn->getString(dataSize);
  if ((myId = indexFlag) && !mfOwner()->indexed() &&
      (cgmIn->isa() != clearCGM)) { // don't trust on clear text
    mfOwner()->setIndexed(); // so as not recurse indefinitely
    filePos startPos = cgmIn->pos(); // mark our spot
    makeIndex(mfOwner(), cgmIn);
    if (cgmIn->pos() != startPos) cgmIn->goTo(startPos); // safety
  }
}
////
// construct an index using our index blocks
////
void cgmEscapeElement::makeIndex(cgmMetafile *inMF, cgmInput *cgmIn)
{
  // have to assume filepos is a long here in order to use sscanf
  long myAddress, nextPos, nextPtr;
  baseCGM *myCGM;
  cgmBeginPicture *myBeginPic;
  cgmPicture *myPic, *lastPic;
  cgmEscapeElement *myEscape;
  int noPages, done = 0, i, strLen;
  char *strPtr;
  // get ready for the loop
  myEscape = this;
  // get the last picture that we already know
  for (lastPic = inMF->firstPic; lastPic && lastPic->next;
       lastPic = lastPic->next);
  do {
    strPtr = myEscape->data();
    while (*strPtr == ' ') ++strPtr; // skip spaces
    if (sscanf(strPtr, "%d", &noPages) != 1) { // how many pages ?
      myError("couldn't read noPages");
      return;
    }
    while (haveNumber(*strPtr)) ++strPtr; // skip number
    ////
    for (i=0; i<noPages; ++i) { // entry for each page
      while (*strPtr == ' ') ++strPtr; // skip spaces
      if (sscanf(strPtr, "%ld", &myAddress) != 1) { // get the address
	myError("couldn't get byte address");
	return;
      }
      while (haveNumber(*strPtr)) ++strPtr; // skip number
      while (*strPtr == ' ') ++strPtr; // skip spaces
      if (sscanf(strPtr, "%ld", &strLen) != 1) { // get the string length
	myError("couldn't get string length");
	return;
      }
      while (haveNumber(*strPtr)) ++strPtr; // skip number
      // now have the picture name
      ++strPtr;	// one-char gap
      // get new begin picture and cgm picture
      myBeginPic = new cgmBeginPicture(inMF, strPtr, strLen);
      myPic = new cgmPicture(inMF, cgmIn, myBeginPic, lastPic,
			       cgmIn->lastPos() + myAddress);
      if (!lastPic) inMF->firstPic = myPic;
      lastPic = myPic;

      strPtr += strLen; // skip over the string
    }
    // now need pointer to next index block
    if (sscanf(strPtr, " %d", &nextPtr) != 1) {
      myError("couldn't read pointer to next index block");
      return;
    }
    if (nextPtr) {
      nextPos = cgmIn->lastPos() + nextPtr;
      cgmIn->goTo(nextPos);
      if (!cgmIn->getCmd()) {
	myError("couldn't get next index block");
	return;
      }
      if (!(myCGM = cgmIn->doCmd(inMF, NULL))) {
	myError("couldn't parse next index block");
	return;
      }
      if ((myCGM->cgmClass() != myClass)||(myCGM->cgmElement() != myElement)) {
	myError("next index block not in an escape element",
		myCGM->cgmName());
	return;
      }
      // now know we have an escape element
      myEscape = (cgmEscapeElement *) myCGM;
      if (myEscape->myId != indexFlag) {
	myError("index block escape element has wrong id");
	return;
      }
    }
    else done = 1;
  } while (!done);
}
//// 
// output in a CGM format
//// 
int cgmEscapeElement::cgmOut(cgmOutput *inOut)
{
  // strip out escapes for now, may do more harm than good
  // inOut->startCmd(this);
  // fill out later
  // inOut->endCmd();
  return 1;
}
////
// the External class
////
const int cgmExternal::myClass = 7;
////
// message element
////
const int cgmMessage::myElement = 1;
const char *cgmMessage::myName = "Message";
//// 
// constructor
////
cgmMessage::cgmMessage(cgmContainer *inOwner, cgmInput *cgmIn,
	    baseCGM *inPrev, baseCGM *inNext)
: cgmExternal(inOwner, inPrev, inNext)
{
  // fill out later
}
//// 
// output in a CGM format
//// 
int cgmMessage::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  // fill out later
  inOut->endCmd();
  return 1;
}
////
// application data
////
const int cgmApplData::myElement = 2;
const char *cgmApplData::myName = "ApplData";
//// 
// constructor
////
cgmApplData::cgmApplData(cgmContainer *inOwner, cgmInput *cgmIn,
			 baseCGM *inPrev, baseCGM *inNext)
: cgmExternal(inOwner, inPrev, inNext)
{
  // fill out later
}
//// 
// output in a CGM format
//// 
int cgmApplData::cgmOut(cgmOutput *inOut)
{
  inOut->startCmd(this);
  // fill out later
  inOut->endCmd();
  return 1;
}
////
// the containing classes
////
////
// container for one metafile
////
// constructor
////
cgmMetafile::cgmMetafile(cgmBeginMetafile *inStart, cgmInput *inInput)
{
  contents = inStart;
  myInput = inInput;
  myStart = myInput->pos();
  if (inStart) inStart->setOwner(this); // get off on the right foot
  myDefaults = NULL;
  firstPic = NULL;
  versionCmd = NULL;
  descriptionCmd = NULL;
  vdcTypeCmd = NULL;
  maxColrIndexCmd = NULL;
  colrValueExtentCmd = NULL;
  vdcExtentCmd = NULL;
  intDefVdcExtent = new vdcPts(0, 0, 32767, 32767);
  // double for macintosh
  floatDefVdcExtent = new vdcPts((double)0.0, (double)0.0,
				 (double)1.0, (double) 1.0);
  myColrTable = new colrTable(64, colrExtent());
  myIndexed = 0; // not indexed yet
}
////
// destructor
////
cgmMetafile::~cgmMetafile() 
{
  delete intDefVdcExtent;
  delete floatDefVdcExtent;
  for (cgmPicture *myPic = firstPic; myPic; myPic = firstPic) {
    firstPic = myPic->next;
    delete myPic;
  }
}
////
// add one set of defaults to the metafile
////
void cgmMetafile::addDefaults(cgmDefaults *inDefaults) 
{
  if (!myDefaults) myDefaults = inDefaults; // first set
  else {
    cgmDefaults *myPtr = myDefaults;
    while (myPtr->next()) myPtr = myPtr->next(); // find last one
    myPtr->addNext(inDefaults);
  }
}
////
// output the whole metafile to a cgm format
////
cgmMetafile::cgmOut(cgmOutput *inOut) 
{
  for (baseCGM *myCGM = contents; myCGM; myCGM = myCGM->next) {
    myCGM->cgmOut(inOut); // metafile specifics
  }
  // now do the pages
  for (cgmPicture *myPic = firstPic; myPic; myPic = myPic->next) {
    if (myPic->want()) { // want this one
      myPic->readIn();
      myPic->cgmOut(inOut);
      myPic->setAside();
    } else if (!indexed()) { // don't already have all of their positions
      myPic->readIn(); // just to get next picture position
      myPic->setAside();
    }
  }
  return 1;
}
////
// display the whole file
////
void cgmMetafile::display(baseDisplay *inDisplay)
{
  for (baseCGM *myCGM = contents; myCGM; myCGM = myCGM->next) {
    myCGM->display(inDisplay); // metafile specifics
  }
}
////
// index the file (if we can)
////
int cgmMetafile::makeIndex()
{
  if (!indexed() && myInput) myInput->makeIndex(this);
  myIndexed = 1; // mark as done
  return 1;
}
////
// return the version
////
int cgmMetafile::version() 
{
  return versionCmd ? versionCmd->versionNumber : 1;
}
////
// return the description
////
const char *cgmMetafile::description() 
{
  return descriptionCmd ? descriptionCmd->mfDescription : NULL;
}
////
// return the colour value extent
////
const colrValueExtent *cgmMetafile::colrExtent() 
{
  return colrValueExtentCmd ? &(colrValueExtentCmd->myExtent) : &defExtent;
}
////
// now access to the picture state defaults
////
// return the scaling mode
////
int cgmMetafile::scalingMode() 
{
  return scalingCmd ? scalingCmd->mode : 0;
}
////
// return the scaling factor
////
float cgmMetafile::scalingFactor() 
{
  return scalingCmd ? scalingCmd->factor : 1.0;
}
////
// return the colour selection mode
////
int cgmMetafile::colrMode() 
{
  return colrModeCmd ? colrModeCmd->mode : 0;
}
////
// return the line width specification mode
////
int cgmMetafile::lineMode() 
{
  return lineModeCmd ? lineModeCmd->mode : 1;
}
////
// return the marker size specification mode
////
int cgmMetafile::markerMode() 
{
  return markerModeCmd ? markerModeCmd->mode : 1;
}
////
// return the edge width specification mode
////
int cgmMetafile::edgeMode() 
{
  return edgeModeCmd ? edgeModeCmd->mode : 1;
}


////
// return the vdc extent
////

const vdcPts *cgmMetafile::vdcExtent() const
{
  return vdcExtentCmd ? vdcExtentCmd->myPts : myVdcType() ?
    floatDefVdcExtent : intDefVdcExtent;
}
////
// container for a single picture
////
cgmPicture::cgmPicture(cgmMetafile *inMetafile, cgmInput *inInput,
		       cgmBeginPicture *inPicture, cgmPicture *inPrev,
		       filePos inPos)
{ 
  myColrTable = NULL; // get when we read in data
  contents = NULL;
  prev = next = NULL;
  metafile = inMetafile;
  if (!metafile) myError("no metafile for cgmPicture", "exiting", 0);
  prev = inPrev;
  if (prev) prev->next = this; // link pointers
  myInput = inInput;
  // do we already have the position ?
  myPos = (inPos) ? inPos : myInput->pos(); 
  myBeginPicture = inPicture;
  if (!myBeginPicture) myError("no beginPicture for cgmPicture", "exiting", 0);
  setWant(1); // default is to want it
}
////
// destructor
////
cgmPicture::~cgmPicture()
{
  delete myBeginPicture;
  for (baseCGM *myCGM = contents; myCGM; myCGM = contents) {
    contents = myCGM->next;
    delete myCGM;
  }
}
////
// output to cgm format
////
cgmPicture::cgmOut(cgmOutput *inOut) 
{
  myBeginPicture->cgmOut(inOut); // the begin picture element
  for (baseCGM *myCGM = contents; myCGM && myCGM->cgmOut(inOut);
       myCGM = myCGM->next);
  return !myCGM;
}
////
// display one picture
////
void cgmPicture::display(baseDisplay *inDisplay) 
{
  if (!inDisplay) myError("no inDisplay for cgmPicture", "exiting", 0); 
  if (!myBeginPicture) myError("no myBeginPicture for cgmPicture display",
			       "exiting", 0);
  myBeginPicture->display(inDisplay); // the begin picture body

  if (!contents) { 
    myError("no contents in this picture");
    return;
  }
  baseCGM *myCGM = contents;
  // go to begin picture body
  while (myCGM &&
	 !((myCGM->cgmClass() == cgmDelimiter::myClass) &&
	   (myCGM->cgmElement() == cgmBeginPictureBody::myElement))) {
    myCGM->display(inDisplay); // for control elements, etc.
    myCGM = myCGM->next;
  }
  ////
  // have a chance to adjust things before picture body
  ////
  if (tInfo.height() == 0) { // never set text height
    tInfo.setHeight(vdcExtent()->height() * 0.01); // default
  }
  ////
  // display everything up to the end picture
  while (myCGM &&
	 !((myCGM->cgmClass() == cgmDelimiter::myClass) &&
		(myCGM->cgmElement() == cgmEndPicture::myElement))
	 ) {
    myCGM->display(inDisplay); // for graphical primitives attributes, etc.
    myCGM = myCGM->next; 
  }
  if (myCGM) myCGM->display(inDisplay); // the end picture
  // done
}
////
// read in one picture
////
int cgmPicture::readIn()
{
  if (contents) return 1; // already read in
  baseCGM *gotCmd, *lastPtr = NULL;
  // set up defaults
  tInfo = metafile->tInfo; // bit wise copy
  myColrTable = new colrTable(64, colrExtent());
  if (myInput->goTo(myPos)) { // go to the correct position
    myError("couldn't goTo beginning of picture");
    return 0;
  }
  // loop thru commands
  while(myInput->getCmd()) { // have input
    // is this an unknown command ?
    if (!(gotCmd = myInput->doCmd(this, lastPtr))) continue;
    // is this a delimiter ?
    if (gotCmd->cgmClass() == cgmDelimiter::myClass) {
		switch(gotCmd->cgmElement()) {
		case cgmBeginPictureMyElement: // begin picture
//		case cgmBeginPicture::myElement: // begin picture

	if (!contents) continue; // first element, OK
	else if (!next) { // new next picture
	  next = new cgmPicture(metafile, myInput,
				(cgmBeginPicture *) gotCmd, this);
	  if (lastPtr) lastPtr->next = NULL;
	  return 1; // done
	} else {
	  myError("unexpected begin picture"); // should never happen
	  return 0;
	}
		case cgmEndPictureMyElement: // end picture
	if (next) return 1; // don't need to go any farther
	else break;
		case cgmEndMetafileMyElement:
	if (lastPtr) lastPtr->next = NULL;
	return 1; // done
      } 
    }
    if (!contents) contents = gotCmd;
    lastPtr = gotCmd;
  } 
  if (lastPtr) lastPtr->next = NULL;
  return 0; // ran out of commands
}
////
// set it aside as we go on to another picture
////
void cgmPicture::setAside()
{
  baseCGM *myPtr, *nextPtr; // delete the main contents (save the BP)
  for (myPtr = contents; myPtr; myPtr = nextPtr) {
    nextPtr = myPtr->next;
    delete myPtr;
  }
  contents = NULL; // nothing there
}
////
// now access to the state variables
////
// the colour value extent
////
const colrValueExtent *cgmPicture::colrExtent()
{
  return metafile->colrExtent();
}
////
// return the scaling mode
////
int cgmPicture::scalingMode() 
{
  return scalingCmd ? scalingCmd->mode : metafile->scalingMode();
}
////
// return the scaling factor
////
float cgmPicture::scalingFactor() 
{
  return scalingCmd ? scalingCmd->factor : metafile->scalingFactor();
}
////
// return the colour selection mode
////
int cgmPicture::colrMode() 
{
  return colrModeCmd ? colrModeCmd->mode : metafile->colrMode();
}
////
// return the line width specification mode
////
int cgmPicture::lineMode() 
{
  return lineModeCmd ? lineModeCmd->mode : metafile->lineMode();
}
////
// return the marker size specification mode
////
int cgmPicture::markerMode() 
{
  return markerModeCmd ? markerModeCmd->mode : metafile->markerMode();
}
////
// return the edge width specification mode
////
int cgmPicture::edgeMode() 
{
  return edgeModeCmd ? edgeModeCmd->mode : metafile->edgeMode();
}
////
// return the vdc extent
////
const vdcPts *cgmPicture::vdcExtent() const
{
  return vdcExtentCmd ? vdcExtentCmd->myPts : metafile->vdcExtent();
}
////
// particular classes for the cgm state
////
// the cgm file object, refHand usd as file ref#/handle by the mac/pc
// must be in this file since it needs case label constants at compile time
////
cgmFile::cgmFile(const char *inName, short refHand) : basicInput(inName, refHand)
{
  metafile = NULL;
  inputHandler = NULL;
  if (inName) { // got a name, store
    nameSize = strlen(inName);
    inputName = new char[nameSize + 1];
    strcpy(inputName, inName);
  } else { // no name
    inputName = NULL;
    nameSize = 0;
  }
  if (!openedFile()) return; 
  ////
  // get the input handler
  if (!(inputHandler = getCgmInput())) return;
#if __MSDOS__
  if (hGlobalBuffer)
	  {
	  GlobalUnlock(hGlobalBuffer);
	  GlobalFree(hGlobalBuffer);
	  buffer = NULL;
	  hGlobalBuffer = NULL;
	  }
#endif
  ////
  // get the first command and parse it
  if (!inputHandler->getCmd()) { // no commands at all
    myError("no commands in file", inputName);
    return;
  }
  baseCGM *gotCmd = inputHandler->doCmd(NULL, NULL); // parse it
  if (!gotCmd) { // couldn't parse it
    myError("couldn't parse first command in", inputName);
    return;
  }
  ////
  // make sure it's a begin metafile
  if (!((gotCmd->cgmClass() == cgmDelimiter::myClass) &&
	(gotCmd->cgmElement() == cgmBeginMetafile::myElement))) { 
    myError("illegal first command", gotCmd->cgmName());
    return;
  }
  ////
  // create the metafile
  metafile = new cgmMetafile((cgmBeginMetafile *) gotCmd, inputHandler);
  ////
  // parse to the first begin picture
  baseCGM *lastPtr = gotCmd; // for initialization
  while(inputHandler->getCmd()) { // while we have commands
    gotCmd = inputHandler->doCmd(metafile, lastPtr); // parse it
    if (gotCmd) { // successfully parsed
      if ((gotCmd->cgmClass() == cgmDelimiter::myClass) &&
	  (gotCmd->cgmElement() == cgmBeginPicture::myElement)) {
	if (lastPtr) lastPtr->next = NULL;
	gotCmd->prev = NULL; // terminate chain
	break; // done
      } else {
	if ((gotCmd->cgmClass() != cgmMetafileDescriptor::myClass) &&
	    (gotCmd->cgmClass() != cgmEscape::myClass) &&
	    (gotCmd->cgmClass() != cgmExternal::myClass))  {
	  myError("illegal command in metafile descriptor area",
		  gotCmd->cgmName());
	} 
      }
      lastPtr = gotCmd;
    } // successfully parsed
  } // successfully got
  // might have got first picture from index block
  if (!metafile->firstPic) {
    ////
    // get the first picture
    if (gotCmd && (gotCmd->cgmClass() == cgmDelimiter::myClass) &&
	(gotCmd->cgmElement() == cgmBeginPicture::myElement)) { // picture
      metafile->firstPic = new cgmPicture(metafile, inputHandler,
					  (cgmBeginPicture *)gotCmd);
    } else {
      myError("no first picture", inName);
      return;
    }
  }
  metafile->firstPic->readIn(); // read in first picture
}
////
// destructor
////
cgmFile::~cgmFile()
{
  if (inputName) delete inputName;
  if (inputHandler) delete inputHandler;
}
////
// function to return the correct input handler
////
cgmInput *cgmFile::getCgmInput()
{
  // try to figure out what type of file we have
  if (!getOffBytes(4)) { // need 4 bytes to identify NCAR files
    myError("couldn't get file header");
    return NULL;
  }
  // now see if we recognize them, try binary types first
  if ((((binaryInput *)this)->bufferClass()==cgmDelimiter::myClass) &&
      (((binaryInput *)this)->bufferElement()==cgmBeginMetafile::myElement)) {
	 return new binaryInput(filePtr, frefHand); // regular binary
  } else if (buffer[0] == 1) {
	 return new LANLInput(filePtr, frefHand); // LANL-style
  } else if ((buffer[0] == 's') && (buffer[1] == 'r')) {
	 return new MilInput(filePtr, frefHand); // military-style
  } else if ((buffer[0] < 128) && (isprint(buffer[0])||isspace(buffer[0])) &&
	     (buffer[1] < 128) && (isprint(buffer[1])||isspace(buffer[1]))) {
	 return new clearInput(filePtr, frefHand); // clear text
  } else if ((buffer[2] == 52) && (buffer[3] == 0)) { // 52 = 3 << 4 + 4
	 return new NCARInput(filePtr, frefHand); // NCAR file
  }
  else { // unknown
    char myString[60]; // should be enough
    sprintf(myString,  "header = [%d, %d, %d, %d]\n", (int) buffer[0],
	    (int) buffer[1], (int) buffer[2], (int) buffer[3]);
    myError("unknown format CGM file", myString);
    return NULL;
  }
}
////
// interpret the command in memory and return appropriate  CGM object
// this function needs to know some cgm constants
////
baseCGM *cgmInput::doCmd(cgmContainer *inOwner, baseCGM *inPrev)
{
  baseCGM *gotCmd;
  for (int i=0; (i<cgmNoClasses) && !sameCmd(cgmNameArray[i]);  ++i);
  if (i>=cgmNoClasses) {
    if (!padCmd()) myError("unknown command", cmdSignature());
    return NULL;
  } 
  // only the begin metafile command can have no owner
  if (!inOwner &&
      !((cgmNameArray[i].myClass == cgmDelimiter::myClass) &&
	(cgmNameArray[i].myElement  == cgmBeginMetafile::myElement))) {
    myError("illegal first command", *cgmNameArray[i].myName);
    return NULL;
  } else gotCmd = cgmNameArray[i].fp(inOwner, this, inPrev);
  //
  // may need to mark this command for use in interpretation
  if (gotCmd->cgmClass() == cgmMetafileDescriptor::myClass) {
    switch (gotCmd->cgmElement()) {
	 case cgmVdcTypeMyElement:
      vdcTypeCmd = (cgmVdcType *) gotCmd;
      break;
	 case cgmIntegerPrecMyElement:
      intPrecCmd = (cgmIntegerPrec *) gotCmd;
      break;
	 case cgmRealPrecMyElement:
      realPrecCmd = (cgmRealPrec *) gotCmd;
      break;
	 case cgmIndexPrecMyElement:
      indexPrecCmd = (cgmIndexPrec *) gotCmd;
      break;
	 case cgmColrPrecMyElement:
      colrPrecCmd = (cgmColrPrec *) gotCmd;
      break;
	 case cgmColrIndexPrecMyElement:
      colrIndexPrecCmd = (cgmColrIndexPrec *) gotCmd;
      break;
    }
  } else if (gotCmd->cgmClass() == cgmControl::myClass) {
    switch (gotCmd->cgmElement()) {
	 case cgmVdcIntegerMyElement:
		if (inOwner->mf()) { // metafile owner, set defaults
	defVdcIntPrecCmd = (cgmVdcInteger *) gotCmd;
		} else vdcIntPrecCmd = (cgmVdcInteger *) gotCmd;
	 case cgmVdcRealMyElement:
      if (inOwner->mf()) { // metafile owner, set defaults
	defVdcRealPrecCmd = (cgmVdcReal *) gotCmd;
      } else vdcRealPrecCmd = (cgmVdcReal *) gotCmd;
    }
  } else if ((gotCmd->cgmClass() == cgmDelimiter::myClass) &&
		  (gotCmd->cgmElement() == cgmBeginPicture::myElement)) {
    vdcIntPrecCmd = NULL;
    vdcRealPrecCmd = NULL;
  }
  return gotCmd;
}
////
// binary input
////
// get a set of defaults (the whole set is in the buffer aleady)
////
cgmDefaults *binaryInput::getDefaults(cgmMetafile *inOwner)
{
  // make some room and copy over the contained commands
  if (tempBufferIndex || tempBufferSize) {
    myError("tempBuffer already in use");
    return NULL;
  }
  tempBufferSize = bIndex - aIndex;
  tempBufferIndex = 0;
  if (tempBufferSize <= 0) { // screwed up somewhere
    myError("no contents to binary Metafile Defaults");
    tempBufferSize = 0;
    return NULL; 
  }
  // move over the data
  tempBuffer = new unsigned char[tempBufferSize];
  for (int i=0; i<tempBufferSize; ++i) tempBuffer[i] = buffer[i + aIndex];
  baseCGM *lastPtr = NULL, *firstPtr = NULL, *gotCmd;
  ////
  // loop thru commands until end of defaults
  while((tempBufferIndex < tempBufferSize) && getCmd()) {
    gotCmd = doCmd(inOwner, lastPtr); // parse it
    ////
    if (!gotCmd) continue; // go on to next command
    ////
    // legal command for defaults replacement ?
    if ((gotCmd->cgmClass() != cgmPictureDescriptor::myClass) &&
	(gotCmd->cgmClass() != cgmControl::myClass) &&
	(gotCmd->cgmClass() != cgmAttribute::myClass)) {
      myError("illegal defaults replacement", gotCmd->cgmName());
      break; // maybe lost end of command
    } else {
      // take care of first, last ptr
      if (!firstPtr) firstPtr = gotCmd;
      lastPtr = gotCmd;
    }
  }
  delete tempBuffer;
  tempBuffer = NULL;
  tempBufferIndex = 0;
  tempBufferSize = 0;
  return new cgmDefaults(firstPtr);
}
////
// clear text input
////
// get a set of defaults
////
cgmDefaults *clearInput::getDefaults(cgmMetafile *inOwner)
{
  baseCGM *lastPtr = NULL, *firstPtr = NULL, *gotCmd;
  ////
  // loop thru commands until end of defaults
  while(*getCmd() && !same(cgmMetafileDefaultsReplacement::endName)) { 
    gotCmd = doCmd(inOwner, lastPtr); // parse it
    ////
    if (!gotCmd) continue; // go on to next command
    ////
    // legal command for defaults replacement ?
    if ((gotCmd->cgmClass() != cgmPictureDescriptor::myClass) &&
	(gotCmd->cgmClass() != cgmControl::myClass) &&
	(gotCmd->cgmClass() != cgmAttribute::myClass)) {
      myError("illegal defaults replacement", gotCmd->cgmName());
      break; // maybe lost end of command
    } else {
      // take care of first, last ptr
      if (!firstPtr) firstPtr = gotCmd;
      lastPtr = gotCmd;
    }
  }
  return new cgmDefaults(firstPtr);
}
////
// parsing info
////
// set the size of the parsing table, has to be here for the MAC
////
const int cgmInput::cgmNoClasses = 
cgmEndPicture::myElement + cgmCharacterCodingAnnouncer::myElement +
cgmBackgroundColr::myElement + cgmClip::myElement +
cgmEllipArcClose::myElement + cgmASF::myElement +
cgmEscapeElement::myElement + cgmApplData::myElement;

void cgmDefaults::display(baseDisplay *inDisplay) // display the elements
	 {for (baseCGM *myPtr=contents(); myPtr; myPtr=myPtr->next)
		 myPtr->display(inDisplay);}

void cgmMetafile::displayDefaults(baseDisplay *inDisplay) const // display the defaults
	 {for (cgmDefaults *myPtr=myDefaults; myPtr; myPtr=myPtr->next())
		 myPtr->display(inDisplay);}
