#include <stdio.h>
#include <stdlib.h>

#define __ISAM_CPP
#include <isam.h>

#include <execp.h>
#include <extcdecl.h>
#include <utility.h>

#ifndef FOXPRO
#include <progind.h>
#endif

#define NOT_LINKED(i,f) CHECKS(i != NULL, "Record senza tracciato: impossibile eseguire ", f)
#define NOT_OPEN(f) CHECKS(_isamfile != NULL, "File chiuso, impossibile eseguire ", f)

HIDDEN void UNKNOWN_FIELD(int num, const char* name) 
{ yesnofatal_box("Il campo '%s' non appartiene al file %d", name, num); }

#define NOALLOC (char **) -1

class TExtrectype : public TRectype
{
public:
  // FPUB 

  TExtrectype(const TTrec& r);  // Costruisce il record a partire da r
  virtual ~TExtrectype();
};

TExtrectype::TExtrectype(const TTrec& r) : TRectype(6)
  
{
  delete _rec;
  _length = r.len();
  _rec = new char [ _length ];
  _i = new isdef;
  _i->r = r.rec();
  zero();
}

TExtrectype::~TExtrectype()
  
{
  delete _rec;
  delete _i;
}

TBaseisamfile::TBaseisamfile(int logicnum, bool linkrecinst)

{
  TTrec   r;

  _isamfile = NULL;
  _logicnum = logicnum;
  _lasterr = NOERR;
  _delopenrec = FALSE;
  if ((openrec[_logicnum - 1] == NULL) || (!linkrecinst))
  {
    _current = new TRectype(this);
    if (openrec[_logicnum - 1] == NULL)
    {
      openrec[_logicnum - 1] = _current;
      _delopenrec = TRUE;
    }
    _delrec = TRUE;
  }
  else 
  {
    _current = openrec[_logicnum - 1];
    _delrec = FALSE;
  }

  r.get(logicnum);
  _historicfile = ((r.field(RFLD_SYS_DATE) != FIELDERR) &&
                   (r.field(RFLD_SYS_FIRST) != FIELDERR) &&
                   (r.field(RFLD_SYS_LAST) != FIELDERR));
}


TBaseisamfile::~TBaseisamfile()
  
{
  if (_delrec)
  {
    if (_delopenrec)
      openrec[_logicnum - 1] = NULL;
    delete _current;
  }
  if (_isamfile != NULL)
    delete _isamfile;
}


int TBaseisamfile::gethr(TRectype& rec, TDate& atdate)
  
{
  TRecfield               fd0(rec, RFLD_SYS_DATE);
  TDate                   d0((const TDate&) fd0);
  
  if (d0 < atdate)
  {
    atdate = eotime;
    return NOERR;
  }
  TRectype                wr(rec);
  TRecfield               flf(wr, RFLD_SYS_FIRST),
  fll(wr, RFLD_SYS_LAST),
  fd1(wr, RFLD_SYS_DATE);
  TDate                           d1;
  TRecnotype      wr0 = -1L, wr1 = -1L;
  
  if ((wr0 == flf.ptr()) == -1L) return _iskeynotfound;
  _hf.read(wr.string(), wr0);
  if ((d1 = (const TDate&) fd1) > atdate)
  {
    rec = wr;
    atdate = d0 - 1L;
    return _iskeynotfound;
  }
  while ((d1 < atdate) && (wr0 > 0))
  {
    rec = wr;
    wr1 = wr0;
    if ((wr0 = fll.ptr()) > 0)
    {
      _hf.read(wr.string(), wr0);
      d1 = (const TDate&) fd1;
    }
  }
  if (wr0 <= 0)
    atdate = d0 - 1L;
  else
    atdate = d1 - 1L;
  return NOERR;
}


int TBaseisamfile::addhr(const TRectype& rec, TDate& atdate)
  
{
  return NOERR;
}


int TBaseisamfile::rewhr(const TRectype& rec, TDate& atdate)

{
  return NOERR;
}


int TBaseisamfile::delhr(const TRectype& rec, TDate& atdate)

{
  return NOERR;
}

long TBaseisamfile::items() const
{
  return filehnd()->i.Base[filehnd()->i.PN].PEOD;
}

const char* TBaseisamfile::name() const
{
  sprintf(__tmp_string, "%d", num());
  return __tmp_string;
}

const char* TBaseisamfile::filename() const

{
  NOT_OPEN(name());
  return _isamfile->d->SysName;
}

void TBaseisamfile::setkey(int nkey)

{
  CHECKD(nkey > 0 && nkey - 1 <= _isamfile->r->NKeys, "Chiave non valida n.ro ", nkey);
  NOT_OPEN(name());

  _isamfile->i.PN = nkey - 1;
}


int TBaseisamfile::getkey() const
{
  NOT_OPEN(name());
  return _isamfile->i.PN + 1;
}

int TBaseisamfile::first(word lockop)
  
{
  NOT_OPEN(name());
  curr().setdirty();
  cisread(_isamfile, curr().string(), _isfirst + lockop, &_lasterr);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::last(word lockop)
  
{
  NOT_OPEN(name());
  curr().setdirty();
  cisread(_isamfile, curr().string(), _islast + lockop, &_lasterr);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::next(word lockop)
  
{
  NOT_OPEN(name());
  curr().setdirty();
  cisread(_isamfile, curr().string(), _isnext + lockop, &_lasterr);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::next(TDate& atdate)
  
{
  TRectype                wr(curr());
  TRecfield               fll(curr(), RFLD_SYS_LAST),
  fd(wr, RFLD_SYS_DATE);
  TRecnotype      wrn;
  
  NOT_OPEN(name());
  if (!_historicfile)
    error_box("%s not historic file", filename());
  if (_lasthf == -1L) return _iseof;
  curr().setdirty();
  _hf.read(curr().string(), _lasthf);
  wrn = fll.ptr();
  if (wrn < 0L)
  {
    readat(-wrn);
    atdate = eotime;
    _lasthf = -1L;
  }
  else
  {
    _hf.read(curr().string(), wrn);
    _lasthf = wrn;
    wrn = fll.ptr();
    if (wrn < 0) readat(wr, -wrn);
    else _hf.read(wr.string(), wrn);
    atdate = (const TDate&)fd - 1L;
  }
  return  NOERR;
}


int TBaseisamfile::prev(word lockop)
  
{
  NOT_OPEN(name());
  curr().setdirty();
  cisread(_isamfile, curr().string(), _isprev + lockop, &_lasterr);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::prev(TDate& atdate)
  
{
  TRecfield               flf(curr(), RFLD_SYS_LAST),
  fd(curr(), RFLD_SYS_DATE);
  TRecnotype      wrn;
  
  NOT_OPEN(name());
  if (!_historicfile)
    error_box("%s not historic file", filename());
  if (_lasthf == -1L) return _isbof;
  curr().setdirty();
  _hf.read(curr().string(), _lasthf);
  wrn = flf.ptr();
  atdate = (const TDate&) fd - 1L;
  if (wrn < 0L) _lasthf = -1L;
  else
  {
    _hf.read(curr().string(), wrn);
    _lasthf = wrn;
  }
  return NOERR;
}

int TBaseisamfile::reread(word lockop, TDate& atdate)
  
{
  NOT_OPEN(name());
  
  curr().setdirty();
  if ((!_historicfile) || (atdate == botime))
    return cisread(_isamfile, curr().string(), _iscurr + lockop, &_lasterr);
  else
  {
    if (cisread(_isamfile, curr().string(), _iscurr + lockop, &_lasterr) == NOERR)
      _lasterr =  gethr(curr(), atdate);
  }
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::reread(TRectype& rec, word lockop, TDate& atdate)
  
{
  NOT_OPEN(name());
  rec.setdirty();
  if ((!_historicfile) || (atdate == botime))
    cisread(_isamfile, rec.string(), _iscurr + lockop, &_lasterr);
  else
  {
    if (cisread(_isamfile, rec.string(), _iscurr + lockop, &_lasterr) == NOERR)
      _lasterr = gethr(rec, atdate);
  }
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::skip(TRecnotype nrec, word lockop)
  
{
  NOT_OPEN(name());
  if (!nrec) return NOERR;
  curr().setdirty();
  if (nrec >0)
    cisread(_isamfile, curr().string(), _isnextn + lockop + (UINT16) nrec, &_lasterr);
  else
    cisread(_isamfile, curr().string(), _isprevn + lockop - (UINT16) nrec, &_lasterr);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::read(word op, word lockop, TDate& atdate)
  
{
  CHECKD(op >= _iscurr && op <= _isgteq, "Invalid read operation : ", op);
  NOT_OPEN(name());
  curr().setdirty();
  if ((!_historicfile) || (atdate == botime))
    cisread(_isamfile, curr().string(), op + lockop, &_lasterr);
  else
  {
    if (cisread(_isamfile, curr().string(), op + lockop, &_lasterr) == NOERR)
      _lasterr = gethr(curr(), atdate);
  }
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::read(TRectype& rec, word op, word lockop, TDate& atdate)
  
{
  CHECKD(op >= _iscurr && op <= _isgteq, "Invalid read operation : ", op);
  NOT_OPEN(name());
  rec.setdirty();
  if ((!_historicfile) || (atdate == botime))
    cisread(_isamfile, rec.string(), op + lockop, &_lasterr);
  else
  {
    if (cisread(_isamfile, rec.string(), op + lockop, &_lasterr) == NOERR)
      _lasterr = gethr(rec, atdate);
  }
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::readat(TRecnotype nrec, word lockop)
  
{
  NOT_OPEN(name());
  curr().setdirty();
  cisreadrec(_isamfile, nrec, curr().string(), lockop, &_lasterr);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::readat(TRectype& rec, TRecnotype nrec, word lockop)
  
{
  NOT_OPEN(name());
  rec.setdirty();
  cisreadrec(_isamfile, nrec, rec.string(), lockop, &_lasterr);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::write(TDate& atdate)
  
{
  NOT_OPEN(name());
  if ((!_historicfile) || (atdate == botime))
    ciswrite(_isamfile, curr().string(), &_lasterr);
  else
    _lasterr = addhr(curr(), atdate);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::write(const TRectype& rec, TDate& atdate)
  
{
  NOT_OPEN(_isamfile->d->SysName);
  if ((!_historicfile) || (atdate == botime))
    ciswrite(_isamfile, rec.string(), &_lasterr);
  else
    _lasterr = addhr(rec, atdate);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::rewrite(TDate& atdate)
  
{
  NOT_OPEN(name());
  if ((!_historicfile) || (atdate == botime))
    cisrewrite(_isamfile, curr().string(), &_lasterr);
  else
    _lasterr = rewhr(curr(), atdate);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::rewrite(const TRectype& rec, TDate& atdate)
  
{
  NOT_OPEN(name());
  if ((!_historicfile) || (atdate == botime))
    cisrewrite(_isamfile, rec.string(), &_lasterr);
  else
    _lasterr = rewhr(rec, atdate);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::rewriteat(TRecnotype nrec)
  
{
  NOT_OPEN(name());
  return cisrewrec(_isamfile, nrec, curr().string(), &_lasterr);
}


int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec)
  
{
  NOT_OPEN(name());
  return cisrewrec(_isamfile, nrec, curr().string(), &_lasterr);
}


int TBaseisamfile::remove(TDate& atdate)
  
{
  NOT_OPEN(name());
  if ((!_historicfile) || (atdate == botime))
    cisdelete(_isamfile, curr().string(), &_lasterr);
  else
    _lasterr = delhr(curr(), atdate);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::remove(const TRectype& rec, TDate& atdate)
  
{
  NOT_OPEN(name());
  if ((!_historicfile) || (atdate == botime))
    cisdelete(_isamfile, rec.string(), &_lasterr);
  else
    _lasterr = delhr(rec, atdate);
  _recno = _isamfile->RecNo;
  return _lasterr;
}


int TBaseisamfile::lock()
  
{
  NOT_OPEN(name());
  return cislock(_isamfile, &_lasterr);
}


int TBaseisamfile::unlock()
  
{
  NOT_OPEN(name());
  return cisunlock(_isamfile, &_lasterr);
}


void TBaseisamfile::indexon()
  
{
  IndexOn();
}


bool TBaseisamfile::empty()
  
{ 
  return _isamfile->i.Base[_isamfile->i.PN].PEOD == 0;
}

void TBaseisamfile::indexoff()
  
{
  IndexOff();
}



int TBaseisamfile::_open(unsigned int mode)
  
{
  int err;
  
  if (filehnd() != NULL)
    fatal_box("Il file %d e' gia' aperto", _logicnum);
  
  //             if ((cisopen(ptrfilehnd(), _logicnum, NOALLOC, mode, &err) == NOERR) &&
  //                             (_historicfile))
  if ((cisopen(&_isamfile, _logicnum, NOALLOC, mode, &err) == NOERR) &&
      (_historicfile))
  {
    TFilename  s(filename());
    
    s.ext("hst");
    _hf.len() = filehnd()->d->LenR;
    _hf.base() = 1;
    _hf.open(s);
    if (_hf.status() == 2)
    {
      _hf.create(s);
      _hf.open(s);
    }
    if (_hf.error()) return err = _hf.status();
    _lasthf = -1L;
    _hfhd = _hf;
    _hfhd.len() = sizeof(TRecnotype);
    _hfhd.base() = 0;
  }
  _recno = -1L;
  _current->_i = filehnd();
  setstatus(err);
  return err;
}


int TBaseisamfile::_close()
  
{
  int err = NOERR;
  
  if (filehnd() != NULL)
  {
    cisclose(ptrfilehnd(), NULL, &err);
    clearfilehnd();
  }
  _current->_i = NULL;
  setstatus(err);
  return err;
}


TLocalisamfile::TLocalisamfile(int logicnum, bool linkrecinst)
:       TBaseisamfile(logicnum, linkrecinst)
  
{
  open();
}


TLocalisamfile::~TLocalisamfile()
  
{
  close();
}


int TLocalisamfile::close()
  
{
  int err = NOERR;

  if (!_was_open)
  {
    clearfilehnd();
  }
  else
  {
    if (_isamfile)
    {
      cisclose(&_isamfile, NULL, &err);
      _isamfile = NULL;
    }
  }
  setstatus(err);
  return err;
}

int TLocalisamfile::open(unsigned int mode)
  
{
  int err = NOERR;
  const int logicnum = num();

  if (openf[logicnum - 1] != NULL)
  {
    _was_open = FALSE;
    _isamfile = openf[logicnum - 1];
    _current->_i = filehnd();
  }
  else
  {
    err = _open();
    _was_open = TRUE;
  }
  _isatab = FALSE;
  setstatus(err);
  return err;
}

int TLocalisamfile::operator +=(const TRecnotype npos)
  
{ 
  skip(npos);
  return status();
}


int TLocalisamfile::operator -=(const TRecnotype npos)
  
{
  skip(-npos);
  return status();
}


int TLocalisamfile::operator ++()
  
{
  next();
  return status();
}


int TLocalisamfile::operator --()
  
{
  prev();
  return status();
}


TIsamfile::TIsamfile(int logicnum, bool linkrecinst) : TBaseisamfile(logicnum, linkrecinst) {}


TIsamfile::~TIsamfile()
  
{
  close();
}


int TIsamfile::flags(bool updateeod)
  
{
  int err;
  
  NOT_OPEN(name());
  setstatus(err);
  return cisupdflags(filehnd(), &err, updateeod);
}


TIsamtempfile::TIsamtempfile(int logicnum, bool linkrecinst) : TBaseisamfile(logicnum, linkrecinst) {}


TIsamtempfile::~TIsamtempfile()
  
{
  close();
}


int TIsamtempfile::open(char* radix, bool create, TRecnotype eod, TRecnotype eox)
  
{
  int err;
  
  if (filehnd() != NULL)
    fatal_box("File %s already open", filename());
  if ((cisopentemp(ptrfilehnd(), _logicnum, radix, NOALLOC, create, eod, eox, &err) == NOERR) &&
      (_historicfile))
  {
    TFilename               s(filename());
    
    s.ext("hst");
    _hf.len() = filehnd()->d->LenR;
    _hf.base() = 1;
    _hf.open(s);
    if (_hf.status() == 2)
    {
      _hf.create(s);
      _hf.open(s);
    }
    if (_hf.error()) return err = _hf.status();
    _lasthf = -1L;
    _hfhd = _hf;
    _hfhd.len() = sizeof(TRecnotype);
    _hfhd.base() = 0;
  }
  _current->_i = filehnd();
  _recno = -1L;
  setstatus(err);
  return err;
}


int TIsamtempfile::close(bool flagdel)
  
{
  int err;
  
  if (filehnd() != NULL)
  {
    cisclosetemp(ptrfilehnd(), NULL, flagdel, &err);
    clearfilehnd();
  }
  _current->_i = NULL;
  setstatus(err);
  return err;
}


TSystemisamfile::TSystemisamfile(int logicnum, bool linkrecinst) : TIsamfile(logicnum, linkrecinst) {}

TSystemisamfile::~TSystemisamfile() {}

int TSystemisamfile::build(TRecnotype eox)
  
{
  int err;
  
  if(filehnd() != NULL)
    fatal_box("Can't recreate open file %s", filename());
  cisbuild(filehnd(), num(), eox, &err);
  setstatus(err);
  clearfilehnd();
  return err;
}


int TSystemisamfile::extend(TRecnotype eox)
  
{
  int     err;
  
  if (filehnd() != NULL)
    fatal_box("Can't extend open file %s", filename());
  cisextend(filehnd(), num(), eox, &err);
  setstatus(err);
  clearfilehnd();
  return err;
}


long TSystemisamfile::size(TRecnotype eox)
  
{
  int err;
  const long size = cisextension(num(), eox, &err);
  if (err != NOERR) setstatus(err);
  return size;
}

#ifndef FOXPRO

int TSystemisamfile::update(TTrec& newrec, bool vis)
  
{
  if (filehnd() != NULL)
    fatal_box("Can't update description for open file %s", filename());
  int err = NOERR;
  TDir           dir;
  TTrec  oldrec;

  oldrec.get(num());
  if (newrec == oldrec) return NOERR;
  dir.get(num(), _lock, _nordir, _sysdirop);
  const TRecnotype nitems = dir.eod();
  const unsigned int lenr = newrec.len();
  if (dir.eox() > 0L)
  {
    TRecnotype ni = 0L;
    TFilename tmpfname;

    tmpfname.temp(NULL);
    FILE* f = fopen(tmpfname, "w");
    err = ferror(f);

    if (f == NULL) 
    {
      clearerr(f);
      setstatus(err);
      return err;
    }
    open(_excllock);
    TFilename fname(filename());
    TString s(80);
    s.format("Aggiornamento archivio %s", (const char*) fname);
    TProgind p(nitems ? nitems : 1, s, TRUE, TRUE, 50);
    int nflds = curr().items();
    TArray  fld(nflds);
    TExtrectype nrec(newrec);
    TRecnotype i;
    for (int j = 0; j < nflds; j++)
      fld.add(TString(curr().fieldname(j)), j);

    for (i = 1; i <= nitems && !p.iscancelled(); i++)
    {
      if ((i % 50) == 0) p.setstatus(i + 1);
      readat(i);
      if (curr().valid())
      {
        nrec.zero();
        ni++;
        for (j = 0; j < nflds; j++)
          if (nrec.exist((const TString&) fld[j]))
            nrec.put((const TString&) fld[j], get((const TString&) fld[j]));
        fwrite(nrec.string(), lenr, 1, f);
      }
    }
    close();
    fclose(f);
    fcopy(tmpfname, fname);
    ::remove(tmpfname);
    dir.eod() = ni;
  }
  // aggiornare il log file
  dir.set_len(lenr);
  dir.put(num(), _nordir, _sysdirop);
  newrec.put(num());
  if (dir.eox() > 0L) packindex();
  // setstatus(cupdatefile(num(), lenr, newrec.rec(), vis, &err));
  return err;
}


int TSystemisamfile::packfile(bool vis)
  
{
  int err;
  
  if (filehnd() != NULL)
    fatal_box("Can't pack open file %s", filename());
  setstatus(creorgfile(num(), vis, &err));
  return err;
  
}


int TSystemisamfile::packindex(bool vis)
  
{
  int err;
  
  if (filehnd() != NULL)
    fatal_box("Can't pack open file %s", filename());
  setstatus(creorgindex(num(), vis, &err));
  return err;
}


int TSystemisamfile::load(const char* from, char fs, char fd, char rs, bool vis)
  
{
  FILE* f = fopen(from, "r+");
  int err = ferror(f);
  TRecnotype r = 0, e = 0, nitems = 1, nread = 0;
  if (f != NULL)
  {
    fseek(f, 0L, SEEK_END);
    nitems = ftell(f);
    fclose(f);
    f = fopen(from, "r");
    err = ferror(f);
  }  
  
  if (f == NULL) 
  {
    clearerr(f);
    setstatus(err);
    return err;
  }
  open();
  TToken_string s(1024, fs);
  bool fixedlen = (fs == '\0');
  int nflds = curr().items();
  TArray  fld(nflds);
  int*            len = NULL;
  TString sfd(3);
  TString s1(64);

  if (fixedlen) len = new int[nflds];
  for (int j = 0; j < nflds; j++)
  {
    fld.add(TString(curr().fieldname(j)), j);
    if (fixedlen)
      len[j] = curr().length((const TString&)fld[j]);
  }

  if (fd) sfd << fd;
  int last = NOERR;    
  
  s1.format("Imp. archivio %s\n%6ld records %6ld errori - %3d", filename(), r, e, last);
  TProgind p(nitems, s, TRUE, TRUE, 70);
  int c = fgetc(f);
  while (c != EOF && !p.iscancelled())
  {
    if ((r + e) % 50 == 0)
    {
      s1.format("Imp. archivio %s\n%6ld rec. %6ld errori - %3d", filename(), r, e, last);
      p.set_text(s1);
    }
    p.setstatus(nread + 1);
    s = "";
    while (c != EOF && c != rs)
    {
      s << (char) c;
      c = getc(f);
    }
    nread += s.len() + 1;
    zero();
    if (fixedlen)
    {
      int pos = 0;
      for (j = 0; j < nflds; j++)
      {
        put((const TString&) fld[j], s.mid(pos, len[j]));
        pos += len[j];
      }
    }
    else
    {
      s.restart();
      for (j = 0; j < nflds; j++)
      {
        char* s2 = (char*) s.get();
        if (fd) 
        {
          s2++;
          s2[strlen(s2) - 1] = '\0';
        }
        put((const TString&) fld[j], s2);
      }
    }            
    if (write() == NOERR) r++;
    else 
    {
      e++;
      last = status();
    }
    if (c != EOF) c = fgetc(f);
  }
  s1.format("Imp. archivio %s : %6ld rec. %6ld errori - %3d", filename(), r, e, last);
  p.set_text(s1);
  close();
  fclose(f);
  if (fixedlen) delete len;
  // setstatus(cloadfile((char*)from, num(), fs, fd, rs, vis, &err));
  return err;
}

int TSystemisamfile::dump(const char* to, int nkey, char fs, char fd, char rs, bool vis, bool withdeleted)

{
  FILE* f = fopen(to, "w");
  int err = ferror(f);

  if (withdeleted) nkey = 0;
  if (f == NULL) 
  {
    clearerr(f);
    setstatus(err);
    return err;
  }
  open();
  TString s(512);
  bool fixedlen = (fs == '\0');
  int nflds = curr().items();
  TArray  fld(nflds);
  TBit_array rjust(nflds);
  int*            len = NULL;

  if (fixedlen) len = new int[nflds];
  for (int j = 0; j < nflds; j++)
  {
    fld.add(TString(curr().fieldname(j)), j);
    if (fixedlen)
    {
      const TFieldtypes t = curr().type((const TString&)fld[j]);
      rjust.set(j, t == _intfld || t == _longfld || t == _realfld ||
                t == _wordfld || t == _intzerofld || t == _longzerofld);
      len[j] = curr().length((const TString&)fld[j]);
    }
  }
  TRecnotype i = 0;
  const TRecnotype nitems = nkey ? items() : filehnd()->d->EOD;
  s.format("Esportazione archivio %s", filename());
  TProgind p(nitems, s, TRUE, TRUE, 50);
  TString s1;
  if (nkey)
  {
    setkey(nkey);
    for ( first(); status() == NOERR && !p.iscancelled(); next(), i++)
    {
      p.setstatus(i + 1);
      s = "";
      for (j = 0; j < nflds; j++)
      {
        if (fixedlen)
        {
          s1 = get((const TString&)fld[j]);
          if (rjust[j]) s1.right_just(len[j]);
          else s1.left_just(len[j]);
        }
        else
        {
          s1 = "";
          if (j && fs) s1 << fs;
          if (fd) s1 << fd;
          s1 << get((const TString&)fld[j]);
          if (fd) s1 << fd;
        }
        s << s1;
      }
      fprintf(f, "%s%c", (const char*) s, rs);
    }
  }
  else
  {
    for (i = 0; i < nitems && !p.iscancelled(); i++)
    {
      p.setstatus(i + 1);
      readat(i + 1);
      s="";
      if (withdeleted || curr().valid())
      {
        for (j = 0; j < nflds; j++)
        {
          if (fixedlen)
          {
            s1 = get((const TString&)fld[j]);
            if (rjust[j]) s1.right_just(len[j]);
            else s1.left_just(len[j]);
          }
          else
          {
            s1 = "";
            if (j && fs) s1 << fs;
            if (fd) s1 << fd;
            s1 << get((const TString&)fld[j]);
            if (fd) s1 << fd;
          }
          s << s1;
        }
        fprintf(f, "%s%c", (const char*) s, rs);
      }
    }
  }
  close();
  fclose(f);
  if (fixedlen) delete len;
  // setstatus(cdumpfile((char*)to, num(), nkey, fs, fd, rs, vis, &err));
  return err;
}

#endif // FOXPRO

////////////////////////////////////////////////////////////
//      TRectype
////////////////////////////////////////////////////////////

TRectype::TRectype(int logicnum)
  
{
  TDir wdir;
  
  _logicnum = logicnum;
  wdir.get(_logicnum, _nolock, _nordir, _sysdirop);
  if (wdir.name()[0] == '%')
    wdir.get(_logicnum, _nolock, _comdir, _sysdirop);
  _length = wdir.len();
  _rec = new char [ _length ];
  _i = openf[_logicnum - 1];
  setempty(TRUE);
}


TRectype::TRectype(const TBaseisamfile* i)

{
  _logicnum = i->num();
  if (i->filehnd() != NULL)
    _length = i->filehnd()->d->LenR;
  else
  {
    TDir wdir;

    wdir.get(_logicnum, _nolock, _nordir, _sysdirop);
    if (wdir.name()[0] == '%')
      wdir.get(_logicnum, _nolock, _comdir, _sysdirop);
    _length = wdir.len();
  }
  _rec = new char [ _length ];
  _i = i->filehnd();
  setempty(TRUE);
}


TRectype::TRectype(const TRectype& r)
  
{
  _logicnum = r._logicnum;
  _length = r.len();
  _rec = new char [ _length ];
  _rec[0] = r._rec[0];
  // strncpy(_rec + 1, r._rec + 1, _length - 1);
  memcpy(_rec + 1, r._rec + 1, _length - 1);
  _i = r._i;
  setempty(r.empty());
}

TRectype::~TRectype()
  
{
  delete _rec;
}

TObject* TRectype::dup() const

{
  TRectype* o = new TRectype(*this);
  
  return o;
}


HIDDEN bool fld_empty(const char* s, int len, bool number)

{
  /*if (number)
    {
    for (; len; s++, len--)
    if (strchr(" 0.", *s) == NULL) return FALSE;
    }
    else */
  if (*s)
  {
    for (; len; s++, len--)
      if (*s != ' ') return FALSE;
  }
  return TRUE;
}


HIDDEN int fld_cmp(const char* a, const char* b, int len, bool number)
{
  for (int i = 0; i < len && *a == *b; b++, a++, i++);
  if (i == len) return 0;
  int res = *a - *b;      
  if (number)
  {
    b -= i;
    i  = 0;
  }
  return fld_empty(b, len - i, number) ? 0 : res;
}


///////////////////////////////////////////////////////////
// TRectype (record di un file)
///////////////////////////////////////////////////////////

int TRectype::items() const

{
  return _i->r->NFields;
}


const char* TRectype::start(int nf) const

{
  return string() + _i->r->Fd[nf].RecOff;
}


int TRectype::compare(const TSortable& s) const

{
  const TRectype& br = (const TRectype&) s;
  int res = 0;

  if (br.empty()) return UNDEFINED;
  for (int i = 0; i < items() ; i++)
  {
    const char* b = br.start(i);
    const char* a = start(i);
    const byte typ = _i->r->Fd[i].TypeF;
    /* if (typ == _boolfld) res = *a - *b;
       else
       { */
    const int  sz  = _i->r->Fd[i].Len;
    const bool number = (typ == _intfld) || (typ == _realfld) ||
      (typ == _longfld) || (typ == _wordfld) ||
        (typ == _intzerofld) || (typ == _longzerofld)

          || (typ == _datefld) ;

    if (fld_empty(b, sz, number)) continue;
    res = ::fld_cmp(a, b, sz, number);
    /* } */
    if (res) return res;
  }
  return 0;
}

TFieldtypes TRectype::type(const char* fieldname) const

{
  NOT_LINKED(_i, "type");
  return (TFieldtypes) CFieldType((char*) fieldname, _i->r);
}


int TRectype::length(const char* fieldname) const

{
  NOT_LINKED(_i, "length");
  return CFieldSize((char*) fieldname, _i->r);
}


int TRectype::ndec(const char* fieldname) const

{
  NOT_LINKED(_i, "dec");
  return CFieldDec((char*) fieldname, _i->r);
}


bool TRectype::exist(const char* fieldname) const

{
  NOT_LINKED(_i, "exist");
  return findfld(_i->r, (char*)fieldname) != -1;
}


const char* TRectype::fieldname(int i) const

{
  NOT_LINKED(_i, "fieldname");
  return i >= 0 && i < _i->r->NFields ? _i->r->Fd[i].Name : NULL;
}


#ifndef FOXPRO

int TRectype::get_int(const char* fieldname) const

{
  NOT_LINKED(_i, "get_int");
  if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  return atoi(__tmp_string);
}


long TRectype::get_long(const char* fieldname) const

{
  NOT_LINKED(_i, "get_long");
  if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  return atol(__tmp_string);
}


word TRectype::get_word(const char* fieldname) const

{
  NOT_LINKED(_i, "get_word");
  if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  return (word)atoi(__tmp_string);
}

real TRectype::get_real(const char* fieldname) const

{
  NOT_LINKED(_i, "get_real");
  if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  real r(__tmp_string);
  return r;
}


char TRectype::get_char(const char* fieldname) const

{
  NOT_LINKED(_i, "get_char");
  
  if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  return *__tmp_string;
}


bool TRectype::get_bool(const char* fieldname) const

{
  NOT_LINKED(_i, "get_bool");
  if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  return *__tmp_string == 'X';
}

#endif // FOXPRO


TDate TRectype::get_date(const char* fieldname) const

{
  NOT_LINKED(_i, "get_date");
  
  const TRecfield f((TRectype&)*this, fieldname);
  return (TDate) f;
}


const TString& TRectype::get(const char* fieldname) const

{
  static TFixed_string s(__tmp_string, 256);

  NOT_LINKED(_i, "get");
  if (CFieldType((char*) fieldname, _i->r) == _datefld)
  {
    const TRecfield f((TRectype&)*this, fieldname);

    s = (const char*) f;
  }
  else
    if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1)
      UNKNOWN_FIELD(num(), fieldname);
  return s;
}


#ifndef FOXPRO

void TRectype::put(const char* fieldname, int val)

{
  NOT_LINKED(_i, "put");
  if (CPutField((char*) fieldname, _i->r, &val, _rec) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  setempty(FALSE);
}


void TRectype::put(const char* fieldname, long val)

{
  NOT_LINKED(_i, "put");
  if (CPutField((char*) fieldname, _i->r, &val, _rec) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  setempty(FALSE);
}


void TRectype::put(const char* fieldname, word val)

{
  NOT_LINKED(_i, "put");
  if (CPutField((char*) fieldname, _i->r, &val, _rec) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  setempty(FALSE);
}

void TRectype::put(const char* fieldname, const real& val)

{
  NOT_LINKED(_i, "put");
  if (CPutField((char*) fieldname, _i->r, val.ptr(), _rec) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  setempty(FALSE);
}

void TRectype::put(const char* fieldname, const TDate& val)

{
  NOT_LINKED(_i, "put");
  TRecfield f(*this, fieldname);
  f = val.string(4);
  //      long v = long(val);
  //      CPutField((char*) fieldname, _i->r, &v, _rec);
  setempty(FALSE);
}

void TRectype::put(const char* fieldname, char val)

{
  NOT_LINKED(_i, "put");
  char  w[2] = {val, '\0'};
  
  if (CPutFieldBuff((char*) fieldname, _i->r, w, _rec) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  setempty(FALSE);
}


void TRectype::put(const char* fieldname, bool val)

{
  NOT_LINKED(_i, "put");
  char* s = val ? "X" : " ";
  if (CPutFieldBuff((char*) fieldname, _i->r, s, _rec) == -1)
    UNKNOWN_FIELD(num(), fieldname);
  setempty(FALSE);
}

#endif // FOXPRO


void TRectype::put(const char* fieldname, const char* val)

{
  NOT_LINKED(_i, "put");

  if (val == NULL || *val == '\0')  // Da provare
  {
    TRecfield f(*this, fieldname);
    if (*f.pos() == '\0') return;
  }

  if (CFieldType((char*) fieldname, _i->r) == _datefld)
  {
    TRecfield f(*this, fieldname);
    f = val;
  }
  else
    if (CPutFieldBuff((char*) fieldname, _i->r, (char*) val, _rec) == -1)
      UNKNOWN_FIELD(num(), fieldname);
  setempty(FALSE);
}


void TRectype::zero(const char* fieldname)
  
{
  NOT_LINKED(_i, "zero");
  if (CZeroField((char*) fieldname, _i->r, _rec) == -1)
    UNKNOWN_FIELD(num(), fieldname);
}


void TRectype::zero()
  
{
  zero('\0');
}


void TRectype::zero(char c)
  
{
  NOT_LINKED(_i, "zero");
  recall();
  memset(_rec + 1, c, len() - 1);
  if (exist(RFLD_SYS_FIRST))
  {
    put(RFLD_SYS_FIRST, "-1");
    put(RFLD_SYS_LAST, "-1");
  }
  setempty(TRUE);
}


// Certified 99%
TRectype& TRectype::operator =(const TRectype& rec)
  
{
  CHECK(num() == rec.num(), "Can't assign records of different files");
  
  _i = rec._i;                             // Copy filehndl
  memcpy(_rec, rec._rec, _length);         // Copy contents
  setempty(rec.empty());                   // Copy emptiness status
  return *this;
}


// Certified 100%
TRectype& TRectype::operator =(const TBaseisamfile& f)
{
  return *this = f.curr();
}


// Certified 99%
TRectype& TRectype::operator =(const char* rec)
{
  memcpy(_rec, rec, _length);
  setempty(FALSE);
  return *this;
}


const char* TRectype::key(int numkey) const
{
  NOT_LINKED(_i, "key");
  CBuildKey(_i->r, numkey, _rec, __tmp_string);
  return __tmp_string;
}


TRec_array::TRec_array(int dimension, TBaseisamfile& i)
: TArray(dimension)

{
  TRectype r(&i);
  for (int j = 0 ; j < size(); j++) add(r, j);
}


///////////////////////////////////////////////////////////
// TRecfield (campo/sottocampo di un record)
///////////////////////////////////////////////////////////

void TRecfield::set(int from, int to)

{
  int nf;
  const isdef*  bf = _rec->filehnd();

  if ((nf = findfld(bf->r, _name)) == -1)
  {
    _p = NULL;
    _len = 0;
    _dec = 0;
    _type = _nullfld;
    yesnofatal_box("File n. %d unknown field %s", _rec->num(), _name);
  }
  else
  {
    CHECK(from >= 0, "Invalid Start");
    _p = _rec->string() + bf->r->Fd[nf].RecOff + from;
    _dec = bf->r->Fd[nf].Dec;
    _type = bf->r->Fd[nf].TypeF;
    if  (to >= 0)
    {
      CHECK(from <= to && to <= bf->r->Fd[nf].Len,
            "Invalid Range");
      _len = to - from + 1;
    }
    else _len = bf->r->Fd[nf].Len - from;
  }
}

TRecfield::TRecfield(TRectype& rec, const char* name, int from, int to)

{
  strcpy(_name, name);
  NOT_LINKED(rec.filehnd(), "TRecfield");
  _rec = &rec;
  set(from, to);
}


HIDDEN void __getfieldbuff(byte l, byte t, const char* recin, char *s)

{
  if (recin == NULL)
  {
    *s = '\0';
    return;
  }
  if ((t != _alfafld) && (t != _datefld))
  {
    while ((*recin == ' ') && (l))
    {
      recin++;
      l--;
    }
    if ((t != _realfld) && (t != _charfld) &&
        (t != _intzerofld) && (t != _longzerofld))
    {
      while ((*recin == '0') && (l))
      {
        recin++;
        l--;
      }
    }
  }
  if (l)
  {
    strncpy(s, recin, l);
    while (s[--l] == ' ');
    l++;
  }
  s[l] = '\0';
  if (t == _datefld && *s)
  {
    TDate   dt(atol(s));
    strcpy(s, dt.string(4));
  }
  // else
  //       if (t == _realfld)
  //               if ((char* s1 = strchr(s, ',')) != NULL) *s1 = '.';
}


HIDDEN void  __putfieldbuff(byte l, byte d, byte t, const char* s, char* recout)

{
  int                     len, i;

  if (recout == NULL) return;

  // char* s2 = new char [256];
  char s2[256];

  strcpy(s2, s);

  if (t == _datefld)
  {
    if (*s2)
    {
      TDate dt(s2);
      sprintf(s2,"%06ld", (long) dt);
    }
  } else
    if (t == _realfld) setdec(s2, d);

  len = strlen(s2);
  if (len > l) return ;
  if ((t == _intfld) ||
      (t == _longfld) ||
      (t == _wordfld) ||
      (t == _realfld))
  {
    if (len == 0)
    {
      strcpy(s2, "0");
      len = 1;
    }
    i = 0;
    while (i < l - len - 1) recout[i++] = ' ';
    strncpy(&recout[l - len - 1], s2, len) ;
  }
  else
  {
    strncpy(recout, s2, len) ;
    while (len < l) recout[len++] = ' ';
  }
  // delete s2;
}



int TRecfield::operator =(int i)

{
  if (_type == _intzerofld)
    sprintf(__tmp_string, "%0*d", _len, i);
  else
    sprintf(__tmp_string, "%d", i);
  __putfieldbuff( _len, _dec, _type, __tmp_string, _p);
  _rec->setempty(FALSE);
  return i;
}


long TRecfield::operator =(long l)

{
  if (_type == _longzerofld)
    sprintf(__tmp_string, "%0*ld", _len, l);
  else
    sprintf(__tmp_string, "%ld", l);
  __putfieldbuff( _len, _dec, _type, __tmp_string, _p);
  _rec->setempty(FALSE);
  return l;
}


#ifndef FOXPRO
const real& TRecfield::operator =(const real& r)
  
{
  strcpy(__tmp_string, r.string());
  __putfieldbuff( _len, _dec, _type, __tmp_string, _p);
  _rec->setempty(FALSE);
  return r;
}
#endif // FOXPRO


const TDate& TRecfield::operator =(const TDate& d)
  
{
  strcpy(__tmp_string, (const char*) d);
  __putfieldbuff( _len, _dec, _type, __tmp_string, _p);
  _rec->setempty(FALSE);
  return d;
}



const char* TRecfield::operator =(const char* s)

{
  __putfieldbuff( _len, _dec, _type, s, _p);
  _rec->setempty(FALSE);
  return s;
}


void TRecfield::setptr(TRecnotype r)

{
  if (_p == NULL) return;
  
  bool n = r < 0;
  unsigned char*  wp = (unsigned char*) _p;

  if (n) r = -r;
  while(wp - (unsigned char*) _p <= 3)
  {
    *wp = r && 0x000000FF;
    r >>= 8;
    wp++;
  }
  if (n) *wp += 128;
}


TRecfield::operator int() const

{
  __getfieldbuff( _len, _type, _p, __tmp_string);
  return atoi(__tmp_string);
}


TRecfield::operator long() const

{
  __getfieldbuff( _len, _type, _p, __tmp_string);
  return atol(__tmp_string);
}



#ifndef FOXPRO
TRecfield::operator const real() const

{
  __getfieldbuff( _len, _type, _p, __tmp_string);
  real r(__tmp_string);
  return r;
}
#endif // FOXPRO


TRecfield::operator TDate() const

{
  static TDate d;
  __getfieldbuff( _len, _type, _p, __tmp_string);
  d = __tmp_string;
  return d;
}


TRecfield::operator const char*() const

{
  __getfieldbuff( _len, _type, _p, __tmp_string);
  return __tmp_string;
}


TRecnotype TRecfield::ptr() const


{
  if (_p == NULL) return(-1L);
  unsigned char*  wp = (unsigned char*) _p + 3;
  TRecnotype   r  = *wp;
  bool         n = r > 127;

  if (n) r -= 128;
  while(wp-- > (unsigned char*) _p) r = r << 8 + *wp;
  return n ? -r : r;
}


void TTransaction::begin()

{
  StTrans();
}


void TTransaction::end(bool success)

{
  if (success) EndTrans();
  else AbTrans();
}