Files correlati : agalib.lib Ricompilazione Demo : [ ] Commento : Migliorato parsing dell'elenco delle patch in installazione da internet Aggiunta possibilita' di specificare il titolo delle maschere di riga git-svn-id: svn://10.65.10.50/trunk@17902 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			719 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			719 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | |
| #include <expr.h>
 | |
| #include <files.h>
 | |
| #include <lffiles.h>
 | |
| #include <utility.h>
 | |
| #include <config.h>
 | |
| 
 | |
| #include <extcdecl.h>
 | |
| 
 | |
| #define BLOCKLEN 512
 | |
| #define INVFLD    255
 | |
| 
 | |
| TFile::TFile (int lenrec, int base)
 | |
| {
 | |
|   _file = new SecDef;
 | |
|   _file->IOR = NOERR;
 | |
|   _len = lenrec;
 | |
|   _base = base;
 | |
|   _file->LockMode = _manulock;
 | |
|   _file->lpos = -1;
 | |
|   _file->name[0] = '\0';
 | |
| }
 | |
| 
 | |
| TFile::~TFile ()
 | |
| {
 | |
|   delete _file;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Apre il file specificato
 | |
| void TFile::open (
 | |
|   const char *name,   // @parm Nome del file da aprire
 | |
|   TFilelock lockmode) // @parm Tipo di lock da attivare durante l'apertura del file
 | |
|   //       (default _manulock)
 | |
| {
 | |
|   COpen (_file, (char *) name, _len, _base, lockmode);
 | |
| }
 | |
| 
 | |
| bool TFile::verify (const char *name)
 | |
| 
 | |
| {
 | |
|   CVerify (_file, (char *) name);
 | |
|   return _file->IOR == NOERR;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Crea il file specificato
 | |
| void TFile::create (
 | |
|   const char *name,   // @parm Nome del file da creare
 | |
|   TRecnotype nrecord) // @parm Numero di recird che deve avere il file al momento
 | |
|   //              della creazione (default 0)
 | |
|   
 | |
|   // @comm Il file creato avra' dimensioni sufficienti a contenere <p nrecord> record
 | |
| 
 | |
| {
 | |
|   CCreate (_file, (char *) name, _len, _base, (nrecord * _len) / BLOCKLEN + 1);
 | |
| }
 | |
| 
 | |
| void TFile::chsize (const char *name, TRecnotype nrecord)
 | |
| 
 | |
| {
 | |
|   CChsize (_file, (char *) name, _len, _base, (nrecord * _len) / BLOCKLEN + 1);
 | |
| }
 | |
| 
 | |
| void TFile::close ()
 | |
| 
 | |
| {
 | |
|   CClose (_file);
 | |
| }
 | |
| 
 | |
| void TFile::unlink (const char *name)
 | |
| 
 | |
| {
 | |
|   CDelete (_file, (char *) name);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Legge un record dal file
 | |
| void TFile::read (
 | |
|   char *record,      // @parm Record letto
 | |
|   TRecnotype recnum, // @parm Numero del record da leggere
 | |
|   TReclock lock)     // @parm Tipo di blocco da attivare durante la letture (default _nolock)
 | |
| 
 | |
| {
 | |
|   _file->LenRec = _len;
 | |
|   _file->BaseFil = _base;
 | |
|   CRead (_file, record, recnum, lock);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Scrive un record sul file
 | |
| void TFile::write (
 | |
|   char *record,      // @parm Record da scrivere
 | |
|   TRecnotype recnum, // @parm Numero del record da scrivere
 | |
|   TReclock lock)     // @parm Tipo di blocco da attivare durante la letture (default _nolock)
 | |
| 
 | |
| {
 | |
|   _file->LenRec = _len;
 | |
|   _file->BaseFil = _base;
 | |
|   CWrite (_file, record, recnum, lock);
 | |
| }
 | |
| 
 | |
| int TFile::status () const
 | |
| {
 | |
|   return _file->IOR;
 | |
| }
 | |
| 
 | |
| TDir::TDir () : _num(-1), _com(false)
 | |
| {
 | |
|   zero ();
 | |
| }
 | |
| 
 | |
| TDir::TDir(int logicnum) : _num(logicnum), _com(false)
 | |
| {
 | |
|   zero();
 | |
|   get(logicnum, _nolock, _nordir, _sysdirop);
 | |
| }
 | |
| 
 | |
| 
 | |
| TDir::TDir(const TDir& d) 
 | |
| {             
 | |
|   _dir = d._dir;
 | |
|   _num = d._num;
 | |
|   _com = d._com;  
 | |
| }
 | |
| 
 | |
| TDir::~TDir ()
 | |
| { }
 | |
| 
 | |
| const char *TDir::name () const
 | |
| { 
 | |
|   return _dir.SysName;
 | |
| }
 | |
| 
 | |
| const char* TDir::filename() const
 | |
| { 
 | |
|   TString& tmp = get_tmp_string();
 | |
|   tmp = CAddPref(_dir.SysName); 
 | |
|   for (int i=tmp.len()-1; i>=0; i--)
 | |
|   {
 | |
|     const char c = tmp[i];
 | |
|     if (is_slash(c))
 | |
|     {
 | |
|       tmp << ".dbf";
 | |
|       break;
 | |
|     }
 | |
|     else
 | |
|       if (c == '.') 
 | |
|         break;
 | |
|   }
 | |
|   return tmp;
 | |
| }
 | |
| 
 | |
| void TDir::set_name(const char* name)
 | |
| {                       
 | |
|   CHECK(name != NULL, "NULL Filename");     
 | |
|   CHECK(strlen(name) < 42, "Name too long");
 | |
| 
 | |
|   for (int i=strlen(name); i>0; i--)
 | |
|   {
 | |
|     char c = name[i-1];
 | |
|     if (c == '\\' || c == '/')
 | |
|       break;
 | |
|     else
 | |
|       if (c == '.') 
 | |
|         c = '\0';
 | |
|         break;
 | |
|   }
 | |
| 
 | |
|   strncpy(_dir.SysName, name, 42);
 | |
|   _dir.SysName[41] = '\0';
 | |
| }
 | |
| 
 | |
| const char *TDir::des () const
 | |
| {           
 | |
|   return _dir.Des;
 | |
| }
 | |
| 
 | |
| const char* TDir::tab_des(const char* tab)
 | |
| {                                         
 | |
|   const char* t = tab; if (t[0] == '$' || t[0] == '%') t++;
 | |
| 
 | |
|   TString& tmp = get_tmp_string();          
 | |
|   tmp << DESCDIR << "/d" << t << ".des";  
 | |
| 
 | |
|   TConfig cnf(tmp, DESCTAB);
 | |
|   tmp = cnf.get("Description", NULL, -1, tab);
 | |
|   
 | |
|   return tmp;
 | |
| }
 | |
| 
 | |
| 
 | |
| const char *TDir::expr () const
 | |
| {
 | |
|   return _dir.FCalc;
 | |
| }
 | |
| 
 | |
| TRecnotype TDir::eod () const
 | |
| {
 | |
|   return _dir.EOD;
 | |
| }
 | |
| 
 | |
| TRecnotype TDir::eox () const
 | |
| {
 | |
|   return _dir.EOX;
 | |
| }
 | |
| 
 | |
| long TDir::flags () const
 | |
| {
 | |
|   return _dir.Flags;
 | |
| }
 | |
| 
 | |
| word TDir::len () const
 | |
| {
 | |
|   return _dir.LenR;
 | |
| }
 | |
| 
 | |
| int TDir::status (TDirtype dirop) const
 | |
| {
 | |
|   return fdir[dirop].IOR;
 | |
| }
 | |
| 
 | |
| void TDir::set_len (const UINT16 len)
 | |
| {
 | |
|   _dir.LenR = len;
 | |
| }
 | |
| 
 | |
| void TDir::set_flags(const RecNoType f)
 | |
| {
 | |
|   _dir.Flags = f;
 | |
| }
 | |
| 
 | |
| void TDir::set_eox(const RecNoType eox)
 | |
| {
 | |
|   _dir.EOX = eox;
 | |
|   if (eox < eod())
 | |
|     set_eod(eox);
 | |
| }
 | |
| 
 | |
| void TDir::reset_eox()
 | |
| { set_eox(0); }
 | |
| 
 | |
| void TDir::set_eod(const RecNoType eod)
 | |
| {
 | |
|   _dir.EOD = eod;
 | |
|   if (eod > eox())
 | |
|     set_eox(eod);
 | |
| }
 | |
| 
 | |
| void TDir::set (const char *name, const RecNoType eod, const RecNoType flag, const char *des, const char *calc)
 | |
| {
 | |
|   strncpy (_dir.SysName, name, sizeof (_dir.SysName));
 | |
|   set_eod(eod);
 | |
|   set_flags(flag);
 | |
|   strncpy(_dir.Des, des, sizeof (_dir.Des));
 | |
|   strncpy(_dir.FCalc, calc, sizeof (_dir.FCalc));
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiorna l'oggetto TDir con i parametri del file  
 | |
| void TDir::get (
 | |
|   int nfile,         // @parm Numero del file con cui aggiornare l'oggetto
 | |
|   TReclock lock,     // @parm Tipo di blocco (default _nolock)
 | |
|   TDirtype dirtype,  // @parm Direttorio nella quale e' contenuto il file (default _nordir)
 | |
|   TDirop op)         // @parm Tipo di operazioni effettuabili sul file (default _nordirop)
 | |
| 
 | |
| {
 | |
|   const int whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
 | |
| 
 | |
|   if (op == _nordirop)
 | |
|     COpenFile (nfile, &_dir, int(lock), whichdir);
 | |
|   else
 | |
|     CGetFile (nfile, &_dir, int(lock), whichdir);
 | |
|   _num = nfile;
 | |
|   _com = _dir.SysName[0] != '$';
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiorna il file indicato con i parametri passati
 | |
| void TDir::put (
 | |
|   int nfile,         // @parm Numero del file da aggiornare
 | |
|   TDirtype dirtype,  // @parm Direttorio nella quale e' contenuto il file (default _nordir)
 | |
|   TDirop op)         // @parm Tipo di operazioni effettuabili sul file (default _nordirop)
 | |
| {
 | |
|   CHECKD(nfile > 0, "Bad file number ", nfile);
 | |
| 
 | |
|   const int whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
 | |
| 
 | |
|   if (op == _nordirop)
 | |
|     CCloseFile (nfile, &_dir, whichdir);
 | |
|   else
 | |
|     CPutFile (nfile, &_dir, whichdir);
 | |
| }
 | |
| 
 | |
| void TDir::zero ()
 | |
| {
 | |
|   zerofdes(&_dir);
 | |
| }
 | |
| 
 | |
| void TDir::print_on (ostream & out) const
 | |
| {
 | |
|   out << _num << '\n';
 | |
|   out << (int)_com << '\n';
 | |
|   out << _dir.SysName << '|';
 | |
|   out << _dir.EOD << '|';
 | |
|   out << _dir.EOX << '|';
 | |
|   out << _dir.LenR << '|';
 | |
|   out << _dir.Flags << '|';
 | |
|   out << _dir.Des << '|';
 | |
|   out << _dir.FCalc << '|';
 | |
|   out << _dir.GenPrompt << '|' << '\n';
 | |
| }
 | |
| 
 | |
| void TDir::read_from (istream & in)
 | |
| {
 | |
|   TToken_string line(256, '|');
 | |
|   char* buf = line.get_buffer();
 | |
|   const int bufsize = line.size();
 | |
| 
 | |
|   in.getline (buf, bufsize, '\n');
 | |
|   _num = atoi(buf);
 | |
|   in.getline (buf, bufsize, '\n');
 | |
|   _com = atoi(buf) != 0;
 | |
|   in.getline (buf, bufsize, '\n');
 | |
|   
 | |
|   line.restart();
 | |
|   strncpy(_dir.SysName,   line.get(), sizeof(_dir.SysName));
 | |
|   _dir.EOD   = line.get_long();
 | |
|   _dir.EOX   = line.get_long();
 | |
|   _dir.LenR  = line.get_int();
 | |
|   _dir.Flags = line.get_long();
 | |
|   strncpy(_dir.Des,       line.get(), sizeof(_dir.Des));
 | |
|   strncpy(_dir.FCalc,     line.get(), sizeof(_dir.FCalc));
 | |
|   strncpy(_dir.GenPrompt, line.get(), sizeof(_dir.GenPrompt));
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ritorna il numero di file presenti nella directory <p dirtype>
 | |
| //
 | |
| // @rdesc Ritorna il numero di file presenti
 | |
| int TDir::items (
 | |
|     TDirtype dirtype) const  // @parm Directory della quale contare i file
 | |
| 
 | |
| {
 | |
|   const int whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
 | |
|   FileDes f;
 | |
|   CGetFile (LF_DIR, &f, _nolock, whichdir);
 | |
|   return (int) f.EOD;
 | |
| }
 | |
| 
 | |
| TTrec::TTrec (int logicnum, TDirtype dirtype) : _des(NULL), _num(-1)
 | |
| {
 | |
|   zero();
 | |
|   get(logicnum, dirtype);
 | |
| }
 | |
| 
 | |
| 
 | |
| TTrec::TTrec () : _des(NULL), _num(-1)
 | |
| {
 | |
|   zero ();
 | |
| }
 | |
| 
 | |
| TTrec::TTrec(const TTrec & r) : _des(NULL)
 | |
| {             
 | |
|   _rec = r._rec;
 | |
|   _num = r._num;
 | |
| }
 | |
| 
 | |
| TTrec::~TTrec ()
 | |
| { }
 | |
| 
 | |
| int TTrec::compare(const TSortable & a) const
 | |
| {
 | |
|   const TTrec & r = (const TTrec &) a;
 | |
|   int res = 0;
 | |
|   
 | |
|   if (_rec.NFields != r._rec.NFields || _rec.NKeys != r._rec.NKeys)  // Confronta prima il numero dei campi o il numero delle chiavi
 | |
|     res = 1;
 | |
|   else
 | |
|   {
 | |
|     const int nkeys = _rec.NKeys;
 | |
|     for (int i=0; i<nkeys && res==0; i++) // scorre la lista delle chiavi (sono meno del numero di campi)
 | |
|     {
 | |
|       const KeyDes& k1 = _rec.Ky[i];
 | |
|       const KeyDes& k2 = r._rec.Ky[i];
 | |
|       if (k1.DupKeys != k2.DupKeys || k1.NkFields != k2.NkFields)
 | |
|         res = 1;
 | |
|       else
 | |
|         for (int j=0; j<k1.NkFields && res==0; j++)
 | |
|           if (k1.FieldSeq[j] != k2.FieldSeq[j] || k1.FromCh[j] != k2.FromCh[j]
 | |
|               || (k1.FromCh[j] != INVFLD && k1.ToCh[j] != k2.ToCh[j]))
 | |
|               res = 1;
 | |
|     }
 | |
|     
 | |
|     if (res == 0) // se sono ancora uguali confronta tutti i campi
 | |
|     {
 | |
|       const int nflds = _rec.NFields;
 | |
|       for (int n=0; n<nflds && res==0; n++)
 | |
|       {
 | |
|         const RecFieldDes& r1 = _rec.Fd[n];
 | |
|         const RecFieldDes& r2 = r._rec.Fd[n];
 | |
|         if (r1.TypeF != r2.TypeF || r1.Len != r2.Len || r1.Dec != r2.Dec)
 | |
|           res = 1;
 | |
|         else
 | |
|           if (strcmp(r1.Name,r2.Name) != 0) 
 | |
|             res = 1;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return res; 
 | |
| }
 | |
| 
 | |
| void TTrec::rehash()
 | |
| {
 | |
|   int  pos, tmppos, nf, i;
 | |
|   
 | |
|   for (i = 0; i < MaxFields; i++) _rec.SortFd[i] = INVFLD; 
 | |
|   if (_rec.NFields)
 | |
|   {
 | |
|     if (_rec.NFields> MaxFields)
 | |
|       fatal_box("Troppi campi in questo tracciato") ;
 | |
|     for (i = 0; i < _rec.NFields; i++) 
 | |
|     { 
 | |
|       nf = i; 
 | |
|       pos = hashfun(_rec.Fd[nf].Name);
 | |
|       while (TRUE)
 | |
|       { 
 | |
|         if (_rec.SortFd[pos] == INVFLD) 
 | |
|         { 
 | |
|           _rec.SortFd[pos] = (byte) nf; 
 | |
|           break; 
 | |
|         } 
 | |
|         else 
 | |
|         { 
 | |
|           if (strcmp(_rec.Fd[_rec.SortFd[pos]].Name, _rec.Fd[nf].Name) <= 0) 
 | |
|           { 
 | |
|             pos++;
 | |
|             if (pos >= MaxFields)
 | |
|               pos = 0; 
 | |
|           } 
 | |
|           else 
 | |
|           { 
 | |
|             tmppos = _rec.SortFd[pos]; 
 | |
|             _rec.SortFd[pos] = (byte) nf; 
 | |
|             nf = tmppos; 
 | |
|           } 
 | |
|         } 
 | |
|       } 
 | |
|     }
 | |
|     _rec.Fd[0].RecOff = 1; 
 | |
|     for (i = 1; i < _rec.NFields; i++) 
 | |
|       _rec.Fd[i].RecOff = _rec.Fd[i - 1].RecOff + _rec.Fd[i - 1].Len; 
 | |
|   }
 | |
| }
 | |
| 
 | |
| TTrec & TTrec::operator = (const TTrec & b)
 | |
| {
 | |
|   _num = b._num;
 | |
|   _rec = b._rec;
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Assegna all'oggetto TTrec il tracciato record del file indicato
 | |
| void TTrec::get (
 | |
|   int nfile,        // @parm Numero del file da cui estrarre il tracciato record
 | |
|   TDirtype dirtype) // @parm Direttorio nella quale e' contenuto il file (default _nordir)
 | |
| 
 | |
| {
 | |
|   const int whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
 | |
|   CGetRec (nfile, &_rec, whichdir);
 | |
|   _num = nfile;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Setta il file indicato con il tracciato record dell'oggetto                                
 | |
| void TTrec::put (
 | |
|   int nfile,        // @parm Numero del file di cui settare il tracciato record
 | |
|   TDirtype dirtype) // @parm Direttorio nella quale e' contenuto il file (default _nordir)
 | |
| 
 | |
| {
 | |
|   int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
 | |
| 
 | |
|   if (nfile <= 0)
 | |
|     fatal_box ("Bad file number %d", nfile);
 | |
|   CPutRec (nfile, &_rec, _whichdir);
 | |
| }
 | |
| 
 | |
| void TTrec::zero ()
 | |
| 
 | |
| {
 | |
|   int i;
 | |
|   
 | |
|   _rec.NFields = 0; 
 | |
|   for (i = 0; i < MaxFields; i++) 
 | |
|   { 
 | |
|     strcpy(_rec.Fd[i].Name, ""); 
 | |
|     _rec.Fd[i].TypeF = _nullfld;
 | |
|     _rec.Fd[i].Len = 0; 
 | |
|     _rec.Fd[i].Dec = 0; 
 | |
|     _rec.Fd[i].RecOff = 0;
 | |
|     _rec.SortFd[i] = INVFLD; 
 | |
|   } 
 | |
|   _rec.NKeys = 0; 
 | |
|   for (i = 1; i < MaxKeys; i++) 
 | |
|   { 
 | |
|     _rec.Ky[i].DupKeys = FALSE; 
 | |
|     _rec.Ky[i].NkFields = 0; 
 | |
|     for (int j = 0; j < MKFields; j++)
 | |
|     {
 | |
|       _rec.Ky[i].FieldSeq[j] = INVFLD; 
 | |
|       _rec.Ky[i].FromCh[j] = INVFLD; 
 | |
|       _rec.Ky[i].ToCh[j] = INVFLD; 
 | |
|     }
 | |
|   } 
 | |
| }
 | |
| 
 | |
| int TTrec::status (TDirtype dirop) const
 | |
| {
 | |
|   return rdir[dirop].IOR;
 | |
| }
 | |
| 
 | |
| int TTrec::field(const char *name) const
 | |
| {
 | |
|   return findfld(&_rec, name);
 | |
| }
 | |
| 
 | |
| const char* TTrec::fielddef(int fld) const
 | |
| {
 | |
|   const RecFieldDes& fd = _rec.Fd[fld];
 | |
|   TString& tmp = get_tmp_string(50);
 | |
|   tmp.format("%s|%d|%d|%d", fd.Name, (int)fd.TypeF, (int)fd.Len, (int)fd.Dec);
 | |
|   return tmp;
 | |
| }
 | |
| 
 | |
| const char *TTrec ::keydef (int key) const
 | |
| {
 | |
|   TString& s = get_tmp_string(128);
 | |
| 
 | |
|   s = "";
 | |
|   for (int j = 0; j < _rec.Ky[key].NkFields; j++)
 | |
|   {
 | |
|     const bool upper = _rec.Ky[key].FieldSeq[j] > MaxFields;
 | |
|     const int nfld = _rec.Ky[key].FieldSeq[j] - (upper ? MaxFields : 0);
 | |
| 
 | |
|     if (j)
 | |
|       s << "+";
 | |
|     if (upper)
 | |
|       s << "UPPER(";
 | |
|     s << _rec.Fd[nfld].Name;
 | |
|     if (_rec.Ky[key].FromCh[j] < INVFLD)
 | |
|       s << format ("[%d,%d]", _rec.Ky[key].FromCh[j] + 1,
 | |
|                    _rec.Ky[key].ToCh[j] + 1);
 | |
|     if (upper)
 | |
|       s << ")";
 | |
|   }
 | |
|   s << (_rec.Ky[key].DupKeys ? "|X" : "| ");
 | |
|   return s;
 | |
| }
 | |
| 
 | |
| int TTrec::len() const
 | |
| { 
 | |
|   const int n = fields();
 | |
|   return (n > 0 && n <= MaxFields) ? _rec.Fd[n - 1].RecOff + _rec.Fd[n - 1].Len : 0; 
 | |
| }
 | |
| 
 | |
| #ifndef FOXPRO
 | |
| 
 | |
| bool TDir::is_active () const
 | |
| {
 | |
|   const int module = abs((int)flags());
 | |
|   return main_app().has_module(module, CHK_DONGLE);
 | |
| }
 | |
| 
 | |
| void TTrec::update_fielddef (int nfld, TToken_string& s)
 | |
| {
 | |
|   RecFieldDes& rfd = _rec.Fd[nfld];
 | |
|   strcpy (rfd.Name, s.get(0));
 | |
|   rfd.TypeF = s.get_int ();
 | |
|   rfd.Len = s.get_int ();
 | |
|   rfd.Dec = s.get_int ();
 | |
| }
 | |
| 
 | |
| void TTrec::update_keydef (int key, TToken_string& s)
 | |
| {
 | |
|   TExpression expr ("", _strexpr);
 | |
|   TString ke (s.get(0));
 | |
| 
 | |
|   if (expr.set(ke, _strexpr))
 | |
|   {                          
 | |
|     const char* dup = s.get();
 | |
|     _rec.Ky[key].DupKeys = (dup && *dup != ' ');
 | |
|     TCodearray & c = expr.code ();
 | |
|     c.begin ();
 | |
|     int n = 0;
 | |
|     while (!c.end ())
 | |
|     {
 | |
|       TCode & inst = c.step ();
 | |
|       TCodesym sym = inst.getsym ();
 | |
| 
 | |
|       if (sym == _variable)
 | |
|       {
 | |
|         const char *s = inst.string ();
 | |
|         int i;
 | |
| 
 | |
|         for (i = 0; i < _rec.NFields; i++)
 | |
|           if (strcmp (_rec.Fd[i].Name, s) == 0)
 | |
|             break;
 | |
| 
 | |
|         _rec.Ky[key].FieldSeq[n] = i;
 | |
|         _rec.Ky[key].FromCh[n] = INVFLD;
 | |
|         _rec.Ky[key].ToCh[n]   = INVFLD;
 | |
|         inst = c.step ();
 | |
|         sym = inst.getsym ();
 | |
|         if (sym == _upper)
 | |
|           _rec.Ky[key].FieldSeq[n] += MaxFields;
 | |
|         else if (sym == _number)
 | |
|         {
 | |
|           _rec.Ky[key].FromCh[n] = (int)inst.number().integer() - 1;
 | |
|           inst = c.step ();
 | |
|           _rec.Ky[key].ToCh[n] = _rec.Ky[key].FromCh[n] + (int)inst.number ().integer () - 1;
 | |
|           inst = c.step ();
 | |
|         }
 | |
|         else
 | |
|           c.backtrace ();
 | |
|         n++;
 | |
|       }
 | |
|     }
 | |
|     _rec.Ky[key].NkFields = n;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TTrec::print_on(ostream & out) const
 | |
| {
 | |
|   const int n = num();
 | |
|   out << n;
 | |
|   if (_des && n>=LF_TABGEN && n<=LF_TAB && _tab.not_empty()) // Solo se e' una tabella...
 | |
|     out << "|" << _tab;
 | |
|   out << '\n';
 | |
|   const int nfields = fields ();
 | |
|   TToken_string s (80);
 | |
|   int i;
 | |
| 
 | |
|   out << nfields << '\n';
 | |
|   for (i = 0; i < nfields; i++)
 | |
|   {
 | |
|     s = fielddef (i);
 | |
|     out << s ;
 | |
|     if (_des)
 | |
|       out << "|" << _des->get(_rec.Fd[i].Name);
 | |
|     out << '\n';
 | |
|   }
 | |
|   const int nkeys = keys ();
 | |
| 
 | |
|   out << nkeys << '\n';
 | |
|   for (i = 0; i < nkeys; i++)
 | |
|   {
 | |
|     s = keydef (i);
 | |
|     out << s << '\n';
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TTrec::read_from(istream & in)
 | |
| {
 | |
|   const int n = num();
 | |
| 
 | |
|   TToken_string t(256);
 | |
|   in.getline (t.get_buffer(), t.size(), '\n');
 | |
|   if (_des && n >= LF_TABGEN && n <= LF_TAB)
 | |
|   {
 | |
|     if (t.find('|') >= 0) 
 | |
|     {
 | |
|       const TString4 tabname(t.right(3));
 | |
|       t.rtrim(4); // Toglie il nome della tabella
 | |
|       if (_tab != tabname && !yesno_box("Descrizione relativa alla tabella %s.\n Continuare?",(const char*) tabname))
 | |
|         return;
 | |
|     }
 | |
|   }
 | |
|   const int ln = t.get_int(0);
 | |
|   if (n > 0 && ln != n && !yesno_box ("Descrizione relativa al file n.ro %d.\n Continuare?", ln))
 | |
|     return;
 | |
| 
 | |
|   in.getline (t.get_buffer(), t.size(), '\n');
 | |
|   const int nfields = t.get_int(0);
 | |
|   set_fields (nfields);
 | |
|   
 | |
|   for (int i = 0; i < nfields; i++)
 | |
|   {
 | |
|     in.getline (t.get_buffer(), t.size(), '\n');
 | |
|     update_fielddef (i, t);
 | |
|     const int itms = t.items();
 | |
|     if (_des && itms >= 5) // La descrizione viene caricata solo se esiste
 | |
|       _des->set(_rec.Fd[i].Name, t.get(4));
 | |
|   }
 | |
| 
 | |
|   in.getline (t.get_buffer(), t.size(), '\n');
 | |
|   const int nkeys = t.get_int(0);
 | |
|   set_keys (nkeys);
 | |
|   for (int i = 0; i < nkeys; i++)
 | |
|   {
 | |
|     in.getline (t.get_buffer(), t.size(), '\n');
 | |
|     update_keydef (i, t);
 | |
|   }
 | |
|   rehash ();
 | |
|   _des = NULL;
 | |
|   _tab = "";
 | |
| }
 | |
| 
 | |
| #endif // FOXPRO
 |