class tTable {
  public:
  virtual int Open(char *filename);
  virtual int Open(char *filename, char *mode);

  virtual int OpenTmp(int gmax);
  virtual int Read();
  int AsInt(int fieldno);
  virtual float AsFloat(int fieldno);
  void Print();
  void Close();
  char *fields[100];
  int  count;
  int  rhd, askoy;
  char dlm;
  char buff[2048];
  protected:
  int fldtypes[100];
  enum fieldtypes {fnothing=0,ftext,fint, ffloat};
  char *fp;
  FILE *ifs;
};

int tTable::Open(char *filename, char *mode)
{
  if ((ifs = fopen(filename,mode)) == NULL) return 1;
  dlm='\t';
  return 0;
};

int tTable::Open(char *filename)
{
  return Open(filename,"r");
};

int tTable::OpenTmp(int gmax)
{
  int i, fldsize;

  fldsize=2048/gmax;
  for (i=0;i<2048;i++) buff[i]='\0';
  for (i=0;i<100;i++) fields[i]=&buff[i*fldsize];
  return 0;
};

int tTable::Read()
{
  int i;
  char *p;
  fp=fgets(buff,2048,ifs);
  if (fp==NULL) return 1;
  fields[0]=&buff[0];
  i=1;
  for (p=&buff[0];*p!='\0' && *p!='\n';p++) {
    if (*p==dlm) {
      fields[i]=p;
      fields[i]++;
      *p='\0';
      i++;
    }
  }
  p=strchr(fields[i-1],'\n');
  if (p) *p='\0';
  count=i;
  return 0;
};

void tTable::Print()
{
  int i;

  for (i=0;i<count;i++)
     printf("%s\t",fields[i]);
  printf("\n");
}

void tTable::Close()
{

   fclose(ifs);
};

int tTable::AsInt(int fieldno)
{
    if (fieldno<count) return atoi(fields[fieldno]);
    else return 0;
};

float tTable::AsFloat(int fieldno)
{
    if (fieldno<count) return atof(fields[fieldno]);
    else return 0.0;
};


class tekTable : public tTable {
  char ftype;
  public:
  int year;
  int Open(char *filename);
  int Read();
  float AsFloat(int fieldno);
  int  rectype,Head;
  short FHEAD,FSEX,FREL,FBOSATT,FMAR,FFSTD,FAGE,FOCC,FFIRST,FSUR;
  short FLANDBRUK, FFEDRIFT, FMATR;
};

int tekTable::Open(char *filename)
{
  int i;
  if ((ifs = fopen(filename,"r")) == NULL) return 1;
  ftype=(char) fgetc(ifs);
  askoy=1;
  if (ftype=='\n') {
// Problem med f61247.tek
     fgets(buff,2000,ifs);
     ftype=(char) fgetc(ifs);
     askoy=0;
  };
  for (i=0;i<100;i++) fldtypes[i]=fnothing;
  rhd=1;
  if (ftype>='1' && ftype<='9') {
     if (ftype=='2') rhd=0;
     ftype='1';
     if ((strstr(filename,"f0")!=NULL) ||
        (strstr(filename,"b0")!=NULL))
      year = 1900;
     else year=1865;
  } else if (ftype>=1 && ftype<=9) {
     ftype=1;
     year=1900;
  } else return 2;

  dlm=(char) fgetc(ifs);
  if (dlm!='<' && dlm!=6 && dlm!='\t') return 3;
  if (rhd==0) {
    fgets(buff,2000,ifs);
    fgets(buff,2000,ifs);
    ftype=(char) fgetc(ifs);
    if (ftype>'2') rhd=1;
  }
  fclose(ifs);
  ifs=fopen(filename,"r");
      if (year==1865) {
        if ((rhd==0) || (askoy==0))   {
// Digitalarkivet, TNM
         FHEAD=2;
         FFIRST=3;
         FSUR=4;
         FSEX=9;
         FBOSATT=0;
         FREL=5;
         FOCC=6;
         FMAR=7;
         FAGE=8;
         FFSTD=10;
         FFEDRIFT=14;
         FLANDBRUK=20;
         FMATR=8;
        }
        else {
         FHEAD=4;
         FFIRST=5;
         FSUR=6;
         FSEX=11;
         FBOSATT=0;
         FREL=7;
         FOCC=8;
         FMAR=9;
         FAGE=10;
         FFSTD=12;
         FFEDRIFT=4;
         FLANDBRUK=10;
         FMATR=6;
        }
      }
      else if (year==1900) {
         FHEAD=1;
         FSEX=4;
         FBOSATT=5;
         FREL=8;
         FMAR=9;
         FOCC=10;
         FAGE=11;
         FFSTD=12;
         FSUR=3;
         FMATR=0;
      }
  if (askoy==0) {
    rhd=0;
    fgets(buff,2000,ifs);
  };

  return 0;
};

int tekTable::Read()
{
  int i;
  char *p;
  fp=fgets(buff,2048,ifs);
  if (fp==NULL) return 0;
  fields[0]=&buff[0];
  i=1;
  for (p=&buff[0];*p!='\0';p++) {
    if (*p==dlm) {
      fields[i]=p;
      fields[i]++;
      *p='\0';
      i++;
    }
  }
  count=i-1;
  if (fields[0][0]<10) rectype=(int) fields[0][0];
  else rectype= (int) fields[0][0] - 48;
  if (rectype==5) {
     for (i=0;i<16;i++) fldtypes[i]=ftext;
     if (fields[FHEAD][0]=='1')
        Head=1;
     else
        Head=0;
  }
  else if (rectype==7) {
     for (i=count;i<17;i++) {
         p++;
         fields[i]=p;
         *p='\0';
     };
     for (i=0;i<4;i++) fldtypes[i]=ftext;
     for (i=4;i<9;i++) fldtypes[i]=fint;
     for (i=9;i<16;i++) fldtypes[i]=ffloat;
  };
  if (count<1) count=1;
  if (askoy==0) {
     if ((fields[FFIRST][0]=='\0')
        || ((fields[FFIRST][0]>='0') && (fields[FFIRST][0]<='9'))
        || (fields[0][0]=='2'))
         fields[0][0]='9';
  }
  return count;
};


float tekTable::AsFloat(int fieldno)
{
  char *p, *p2;
  float tal,nemnar;

  if (fieldno<count) {
     tal=atof(fields[fieldno]);
     p=strchr(fields[fieldno],' ');
     p2=strchr(fields[fieldno],'/');
     if (p!=NULL && p2!=NULL) {
        p++;p2++;
        nemnar=atof(p2);
        if (nemnar!=0)
          tal=tal+(atof(p)/nemnar);
     }
     else if (p2!=NULL)  {
        p2++;
        nemnar=atof(p2);
        if (nemnar!=0)
          tal=tal/nemnar;
     }
     return tal;
  }
    else return 0.0;
};


class Setning
{
    public:
    Setning();
    void SetData(const char *s);
/*    string GetWord();
      AnsiString GetLast();
    string GetLast();
*/
    char  *GetLast();
    char  *GetFirst();
    short fields;
    private:
    char dlm;
    char *data;
    char *words[20];
    short count,fix;

};

Setning::Setning()
{
  dlm= ' ';
};

void Setning::SetData(const char *s)
{
    char *p;
    short i;

    count=(short) (strlen(s)+1);
    data= new char[count];
    strcpy(data,s);
    words[0]=&data[0];
    i=1;
    for (p=&data[0];*p!='\0';p++) {
      if (*p==dlm) {
        words[i]=p;
        words[i]++;
        *p='\0';
        i++;
      }
   }
   fields=i;
}

/*
AnsiString Setning::GetLast()
{
    return AnsiString(words[fields-1]);
}

string Setning::GetLast()
{
    return string(words[fields-1]);
}
*/

char *Setning::GetLast()
{
    return words[fields-1];
}

char *Setning::GetFirst()
{
    return words[0];
}

class tvars
    {
    public:
        char   vtype;
        string sname;
        string lname;
        string koder;
        int minv;
        int maxv;
        int dec;
        int miss;
    };

class NSDvardok
{
    public:
    NSDvardok(char *fn, int aar);
    ~NSDvardok();
    void AddVar(string vsname, string vlname, int vminv, int vmaxv, int vdec);
    void AddKodaVar(string vsname, string vlname, string vkoder);
    void SkrivVar();
    void SkrivDok();
    private:
    ofstream vf;
    char filename[100];
    tvars *vars[200];
    int count;
    int ftaar;
};

NSDvardok::NSDvardok(char *fn,int aar)
{
 count=0;
 sprintf(filename,"data/%s%d.var",fn,aar);
 vf.open(filename);
 ftaar=aar;
};


NSDvardok::~NSDvardok()
{
 int i;
 for (i=0;i<count;i++) delete vars[i];
 vf.close();
};

void NSDvardok::AddVar(string vsname, string vlname, int vminv, int vmaxv, int vdec)
{
   vars[count]=new tvars;
   vars[count]->minv=vminv;
   vars[count]->maxv=vmaxv;
   vars[count]->dec=vdec;
   if (vmaxv<9) vars[count]->miss=9;
   else if (vmaxv<99) vars[count]->miss=99;
   else if (vmaxv<999) vars[count]->miss=999;
   else if (vmaxv<9999) vars[count]->miss=9999;
   else if (vmaxv<99999) vars[count]->miss=99999;
   else if (vmaxv<999999) vars[count]->miss=999999;
   else vars[count]->miss=9999999;
   vars[count]->sname.assign(vsname);
   vars[count]->lname.assign(vlname);
   vars[count]->vtype='K';
   count++;
}

void NSDvardok::AddKodaVar(string vsname, string vlname,string vkoder)
{
   vars[count]=new tvars;
   vars[count]->sname.assign(vsname);
   vars[count]->lname=vlname;
   vars[count]->koder=string(vkoder);
   vars[count]->vtype='D';
   count++;
};

void NSDvardok::SkrivVar()
{
   int i;
   for (i=0;i<count;i++) {
     vf << "+" << "\n" << vars[i]->vtype;
     vf << vars[i]->sname << ":" << vars[i]->lname << "(" << ftaar << ")" << endl;
     if (vars[i]->vtype=='D') {
        vf << vars[i]->koder;
     } else {
       vf << vars[i]->minv << endl;
       vf << vars[i]->maxv << endl;
       vf << vars[i]->dec << endl;
       vf << vars[i]->miss << " # mangler" << endl;
     }
   }
}

void NSDvardok::SkrivDok()
{
 int i;
 vf.close();
 i=strlen(filename);
 if (i>4) {
    filename[i-3]='d';
    filename[i-2]='o';
    filename[i-1]='k';
 }
 vf.open(filename);
 for (i=0;i<count;i++)
   vf << "+" << endl;
}


class cForceEof {
   public:
    cForceEof(char *s);
    int kfound,skoletil,ltil,npostar,skip,lesfra, lestil;
   private:
    tTable params;
    int skolefra, lfra;
} ;

cForceEof::cForceEof(char *s)
{
   params.Open("param/pgjles.txt");
   params.dlm=';';
   kfound=1;
   skip=1;
   while ((params.Read()==0) && (kfound!=0)) {
     if (strcmp(params.fields[0],s)==0) {
       kfound=0;
       skolefra=params.AsInt(1);
       skoletil=params.AsInt(2);
       lfra=params.AsInt(3);
       ltil=params.AsInt(4);
       lesfra=params.AsInt(5);
       npostar=params.AsInt(6);
       lestil=params.AsInt(7);
       if (lesfra>0) {
          skip=0;
          kfound=1;
       }
       else
          skip=1;
     }
   }
   params.Close();
}