#include #include #include #include #include #include #include #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

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

// // @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 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 nel file %d.\n Continuare?",(const char*) tabname), n) 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