#include #include #include #include #include #include #include #include #include #include #include #include // Definita in isam.cpp extern int get_error(int); /////////////////////////////////////////////////////////// // extern variables are NO-NO! /////////////////////////////////////////////////////////// HIDDEN TPrefix* _prefhndl = NULL; // @doc EXTERNAL // @func Inizializza (crea) un nuovo file "prefix.txt" // // @rdesc Ritorna l'oggetto creato TPrefix& prefix_init() { CHECK(_prefhndl == NULL, "Can't create two prefix objects"); _prefhndl = new TPrefix; return *_prefhndl; } // @doc EXTERNAL // @func Determina se il prefix e' stato inizializzato // // @rdesc Ritorna true o false bool prefix_valid() { return _prefhndl != NULL; } // @doc EXTERNAL // @func Legge il file "prefix.txt" // // @rdesc Ritorna l'oggetto letto TPrefix& prefix() { CHECK(_prefhndl, "Can't access null prefix"); return *_prefhndl; } // @doc EXTERNAL // @func Distrugge l'oggett in memoria void prefix_destroy() { if (_prefhndl != NULL) { delete _prefhndl; _prefhndl = NULL; } } /////////////////////////////////////////////////////////// // TFile_manager /////////////////////////////////////////////////////////// class TRecord_info : public TObject { RecDes _recdes; TDirtype _dirtype; int _len; TString_array _relations; int _logicnum; protected: void translate_key(TToken_string& t) const; void compute_len(); bool create(TTrec& rec, TToken_string& keys); public: // TObject virtual bool ok() const; public: operator const RecDes&() const { return _recdes; } int len() const { return _len; } TDirtype dir_type() const { return _dirtype; } bool mutable_dir() const { return _dirtype <= _studir; } bool fixed_dir() const { return _dirtype > _studir; } TToken_string & relation(int logicnum); TRecord_info(int logicnum); TRecord_info(const char* name); TRecord_info(TTrec& rec, TToken_string& keys); virtual ~TRecord_info() { } }; void TRecord_info::translate_key(TToken_string& t) const// Traduce l'espressione chiave di CodeBase { // Trasforma l'espressione TToken_string k(t.get(0),'+'); TToken_string range("",','); TString ws; const bool is_dup = t.get(1)[0] == 'X'; const int items = k.items(); t = ""; for (int i = 0; i= 0; const bool is_sub = ws.find("SUBSTR") >= 0; int paren1 = ws.find('('); // Trova la prima parentesi aperta int paren2,last,from = 0,to = 0; if (paren1 >= 0 && is_sub && is_upper) paren1 = ws.find('('); // Trova la seconda parentesi (in questo caso c'e' per forza) if (paren1 >= 0) // Trova la prima virgola o parentesi chiusa (per qualsiasi espressione) { paren2 = ws.find(','); if (paren2 == -1) // se non ci sono virgole trova la parentesi chiusa paren2 = ws.find(')'); CHECK(paren2 > paren1,"Something wrong happened translating CodeBase expressions."); if (is_sub) // Se e' una sottostringa estrae i campi DA e A { range = ws; last = ws.find(')'); range.sub(paren2,last); // dalla virgola alla parentesi from = range.get_int(0); to = range.get_int(1); } ws = ws.sub(paren1+1,paren2); // Nome del campo pulito pulito ws.upper(); } if (is_upper) t << "UPPER("; t << ws; // aggiunge il nome del campo if (is_sub) { t << "["; t << from << ","; t << to << "]"; } if (is_upper) t << ")"; t << '+'; } t.rtrim(1); // Toglie il + in piu' t.add(is_dup ? "X" : " "); } bool TRecord_info::ok() const { return _recdes.NFields > 0 && _recdes.NKeys > 0 && _recdes.NKeys < MaxKeys; } void TRecord_info::compute_len() { _len = 0; for (int f = _recdes.NFields-1; f >= 0; f--) _len += _recdes.Fd[f].Len; if (_len > 0) _len++; } TToken_string & TRecord_info::relation(int logicnum) { if (_relations.empty()) { const TFilename rels("recdesc/relations.ini"); if (rels.exist()) { TString key; key.format("%d", _logicnum); TConfig c(rels, key); TString_array vars; c.list_variables(vars, true); FOR_EACH_ARRAY_ROW(vars, r, row) { const int num = row->get_int(); _relations.add(row->get(), num); } } } TToken_string * rel = _relations.rowptr(logicnum); if (rel == NULL) { const RecDes & fd = prefix().get_recdes(_logicnum); const RecDes & rd = prefix().get_recdes(logicnum); const KeyDes& kd = rd.Ky[0]; // Tracciato della chiave primaria rel = new TToken_string(EMPTY_STRING); for (int i = 0; i < kd.NkFields; i++) // Riempio tutta la chiave primaria { const int nPos = kd.FieldSeq[i] % MaxFields; // Posizione del campo i della chiave const RecFieldDes& dfield = rd.Fd[nPos]; // Nome del campo i della chiave int nBest = -1; double dBest = 0.0; for (int j = 0; i < fd.NFields; j++) { const RecFieldDes& field = fd.Fd[j]; if (field.TypeF == dfield.TypeF && field.Len == dfield.Len) { const double fuzzy = xvt_str_fuzzy_compare(field.Name, dfield.Name); if (fuzzy > dBest) { nBest = j; dBest = fuzzy; if (dBest == 1.0) break; } } } rel->add(nBest >= 0 ? fd.Fd[nBest].Name : ""); } _relations.add(rel, logicnum); } return *((TToken_string *) rel); } TRecord_info::TRecord_info(int logicnum) { _logicnum = logicnum; memset(&_recdes, 0, sizeof(_recdes)); FileDes fd; memset(&fd, 0, sizeof(fd)); CGetFile(logicnum, &fd, _nolock, _nordir); if (fd.SysName[0]) { _dirtype = fd.SysName[0] != '$' ? _comdir : _nordir; CGetRec(logicnum, &_recdes, _dirtype); } if (ok()) compute_len(); } bool TRecord_info::create(TTrec& rec, TToken_string& keys) { _logicnum = rec.num(); rec.rehash(); const int num_keys = rec.keys(); TToken_string trans; for (int i = 0; i < num_keys; i++) { trans = keys.get(i); translate_key(trans); // Traduce l'espressione chiave di CodeBase rec.update_keydef(i, trans); } _recdes = rec.rec(); compute_len(); return _len > 0; } TRecord_info::TRecord_info(TTrec& rec, TToken_string& keys) : _dirtype(_extdir) { create(rec, keys); } TRecord_info::TRecord_info(const char* name) : _dirtype(_extdir) { TFilename fname(name); fname.ext("dbf"); if (fname.exist()) { TToken_string keys(256*MaxKeys, '$'); fname.ext(""); FileDes fd; TTrec rec; int err = DB_recinfo(fname, &fd, (RecDes*)&rec.rec(), keys.get_buffer()); if (err != NOERR) create(rec, keys); else memset(&_recdes, 0, sizeof(_recdes)); } else memset(&_recdes, 0, sizeof(_recdes)); } class TFile_info : public TObject { TFilename _name; int _ref_count; int _num; int _handle; clock_t _last_access, _last_change; bool _locked, _exclusive; TDirtype _dir; FileDes _filedes; int _last_key; protected: int open_low(bool exclusive, bool index); int close_low(); public: // TObject virtual bool ok() const { return _name.not_empty(); } public: const TFilename& pathname() const { return _name; } int num() const { return _num; } int handle() const { return _handle; } bool is_open() const { return _handle >= 0; } clock_t last_access() const { return _last_access; } clock_t last_change() const { return _last_change; } bool is_exclusive() const { return _exclusive; } bool is_locked() const { return _locked; } int ref_count() const { return _ref_count; } int last_key() const { return _last_key; } void touch() { _last_access = clock(); } void set_dirty() { _last_change = clock(); } TDirtype dir_type() const { return _dir; } bool mutable_dir() const { return _dir <= _studir; } bool fixed_dir() const { return _dir > _studir; } int open(bool exclusive, bool index); int close(); const TFilename& load_filedes(); void lock_record(TRecnotype rec); void unlock_record(TRecnotype rec); int auto_open(int key); void auto_close(); operator const FileDes&() const { return _filedes; } TFile_info(int logicnum, TFilename& name); virtual ~TFile_info(); }; int TFile_info::open_low(bool exclusive, bool index) { if (_handle < 0) _handle = DB_open(_name, exclusive, index); #ifdef DBG else error_box("You shouldn't reopen file %s", (const char*)_name); #endif int err = NOERR; if (_handle >= 0) { if (num() < LF_EXTERNAL && (_dir == _nordir || _dir == _comdir)) { const TRecnotype n = DB_reccount(_handle); _filedes.EOD = n; _filedes.EOX = n; TDir d; d.get(num(), _nolock, _dir, _sysdirop); d.set_eod(n); d.set_eox(n); d.put(num(), _dir, _sysdirop); } if (index) err = DB_tagselect(_handle, _last_key = 1); else _last_key = 0; } else { err = get_error(_handle); } return err; } int TFile_info::close_low() { int err = NOERR; if (_handle >= 0) { DB_close(_handle); _handle = -1; _last_key = -1; _exclusive = _locked = false; } else { err = _isnotopen; } return err; } int TFile_info::open(bool exclusive, bool index) { int err = NOERR; if (exclusive || !index) { if (_ref_count > 0 || is_open()) { #ifdef DBG if (_ref_count > 0 && (_exclusive || _locked)) error_box("You shouldn't reopen file %d exclusively", num()); #endif close_low(); } _exclusive = _locked = true; // shouldn't be exclusive instead of true? err = open_low(exclusive, index); } touch(); // Memorizza ora apertura del file _ref_count++; return err; } int TFile_info::close() { int err = NOERR; if (_ref_count > 0) { _ref_count--; if (_ref_count == 0 || _exclusive) { if (is_open()) { // Chiudi fisicamente solo se necessario if (_locked || _exclusive || dir_type() == _extdir) err = close_low(); // Chiudo fisicamente il file per eliminare i lock } _locked = _exclusive = false; } } else err = _isnotopen; return err; } void TFile_info::auto_close() { const bool yes = is_open() && !(is_locked() || is_exclusive()); if (yes) close_low(); } int TFile_info::auto_open(int key) { if (_handle < 0) open_low(false, true); if (_handle >= 0) { if (key > 0 && key != _last_key) { const int err = DB_tagselect(_handle, _last_key = key); if (err != NOERR) { #ifdef DBG NFCHECK("Can't set key %d on file %d", key, num()); #endif return err; } } } return _handle; } void TFile_info::lock_record(TRecnotype) { _locked = true; } void TFile_info::unlock_record(TRecnotype) { _locked = false; } const TFilename& TFile_info::load_filedes() { memset(&_filedes, 0, sizeof(_filedes)); CGetFile(num(), &_filedes, _nolock, _nordir); if (_filedes.SysName[0] > ' ') { _dir = _filedes.SysName[0] != '$' ? _comdir : _nordir; _name = CAddPref(_filedes.SysName); strncpy(_filedes.Des, dictionary_translate(_filedes.Des), sizeof(_filedes.Des)-1); } else _name.cut(0); return _name; } TFile_info::TFile_info(int logicnum, TFilename& name) : _ref_count(0), _num(logicnum), _handle(-1), _last_access(0), _last_change(0), _locked(false), _exclusive(false), _last_key(-1) { if (logicnum < LF_EXTERNAL) { load_filedes(); if (name.full()) { // File dati temporaneo _dir = _extdir; _name = name; _name.ext(""); } else name = _name; } else { // File dati esterno _dir = _extdir; _name = name; _name.ext("dbf"); if (_name.exist()) { TToken_string keys(256*MaxKeys, '$'); _name.ext(""); TTrec rec; int err = DB_recinfo(_name, &_filedes, (RecDes*)&rec.rec(), keys.get_buffer()); if (err == NOERR && prefix().add_recdes(logicnum, rec, keys)) { strncpy(_filedes.SysName, _name, sizeof(_filedes.SysName)); _filedes.SysName[41] = '\0'; } else _name.cut(0); } else _name.cut(0); } } TFile_info::~TFile_info() { if (is_open()) close_low(); } TFile_info& TFile_manager::fileinfo(TIsam_handle num) const { TFile_info* i = (TFile_info*)_fileinfo.objptr(num); if (i == NULL && num >= LF_USER && num < LF_EXTERNAL) { TFilename name; i = new TFile_info(num, name); //if (i->ok()) ((TFile_manager*)this)->_fileinfo.add(i, num); /* else { delete i; i = NULL; }*/ } CHECKD(i, "Unknown file ", num); return *i; } TRecord_info& TFile_manager::recinfo(int logicnum) const { TRecord_info* i = (TRecord_info*)_recinfo.objptr(logicnum); if (i == NULL) { i = new TRecord_info(logicnum); ((TFile_manager*)this)->_recinfo.add(i, logicnum); } return *i; } bool TFile_manager::add_recdes(int logicnum, TTrec& rec, TToken_string& keys) { TRecord_info* i = (TRecord_info*)_recinfo.objptr(logicnum); if (i == NULL) { if (logicnum < LF_EXTERNAL) i = new TRecord_info(logicnum); else i = new TRecord_info(rec, keys); if (i->ok()) _recinfo.add(i, logicnum); else { delete i; i = NULL; } } return i != NULL; } bool TFile_manager::close_oldest() { int oldest = 0; clock_t age = 0; _open_files = 0; // Intanto ricalcolo il numero di file veramente aperti for (int n = _fileinfo.last(); n > 0; n = _fileinfo.pred(n)) { TFile_info& i = (TFile_info&)_fileinfo[n]; if (i.is_open()) { _open_files++; if (!i.is_locked() && !i.is_exclusive()) { if (oldest == 0 || i.last_access() < age) { oldest = n; age = i.last_access(); } } } } if (oldest) { TFile_info& i = (TFile_info&)_fileinfo[oldest]; i.auto_close(); _open_files--; } return oldest != 0; //verificare } // name : nome del file TIsam_handle TFile_manager::get_handle(TFilename& name) { TFile_info* i = NULL; TFilename fname(name); fname.ext(""); int num; for (num = LF_EXTERNAL; (i = (TFile_info*)_fileinfo.objptr(num)) != NULL; num++) { if (i->pathname() == fname) break; } if (i == NULL) { i = new TFile_info(num, name); if (!i->ok()) { delete i; return -60; } _fileinfo.add(i, num); } return num; } // name : nome del file (vuoto per i file normali viene riempito automaticamente) // logicnum: numero logico del file (LF_EXTERNAL per gli esterni viene generato automaticamente) TIsam_handle TFile_manager::open(int& logicnum, TFilename& name, bool exclusive, bool index) { TIsam_handle num = logicnum; if (name.full()) { num = get_handle(name); if (logicnum >= LF_EXTERNAL) logicnum = num; } TFile_info* i = (TFile_info*)_fileinfo.objptr(num); if (i == NULL) { i = new TFile_info(logicnum, name); if (!i->ok()) { delete i; return -60; } _fileinfo.add(i, num); } i->open(exclusive, index); name = i->pathname(); return num; } int TFile_manager::close(TIsam_handle& name) { int err = _isnotopen; TFile_info* i = (TFile_info*)_fileinfo.objptr(name); if (i != NULL) { const bool was_open = i->is_open(); err = i->close(); // Se chiuso veramente ... (Per efficienza non chiude sempre) if (err == NOERR && !i->is_open()) { if (was_open) _open_files--; if (name >= LF_EXTERNAL && i->ref_count() <= 0) { _fileinfo.remove(name); _recinfo.remove(name); } } } name = 0; return err; } void TFile_manager::destroy_info(int logicnum) { _fileinfo.destroy(logicnum); _recinfo.destroy(logicnum); } TCodeb_handle TFile_manager::get_handle(TIsam_handle name, int key) { TFile_info& i = fileinfo(name); #ifdef DBG if (i.ref_count() == 0) { NFCHECK("Sarebbe bene aggiungere una bella open_files(%d, ...) in TYour_app::create()", i.num()); i.open(false, true); } #endif TCodeb_handle handle = i.handle(); if (handle < 0) { if (_open_files >= _max_open_files) close_oldest(); // Se ho passato key = -1 mi va bene la chiave principale if (key < 0) key = 1; handle = i.auto_open(key); if (handle >= 0) _open_files++; } else { // Se ho passato key = -1 mi va bene la chiave corrente if (key >= 0 && i.last_key() != key) handle = i.auto_open(key); } // i.touch(); // Memorizza troppo spesso l'accesso return handle; } void TFile_manager::lock_record(TIsam_handle num, TRecnotype rec) { TFile_info& i = fileinfo(num); i.lock_record(rec); } void TFile_manager::unlock_record(TIsam_handle num, TRecnotype rec) { TFile_info& i = fileinfo(num); i.unlock_record(rec); } const RecDes& TFile_manager::get_recdes(int logicnum) const { const TRecord_info& i = recinfo(logicnum); return i; } TToken_string& TFile_manager::get_relation(int fromlogic, int tologic) const { TRecord_info& i = recinfo(fromlogic); return i.relation(tologic); } const RecDes& TFile_manager::update_recdes(int logicnum) { _recinfo.destroy(logicnum); return get_recdes(logicnum); } int TFile_manager::get_reclen(int logicnum) { const TRecord_info& i = recinfo(logicnum); return i.ok() ? i.len() : 0; } TDirtype TFile_manager::get_dirtype(int logicnum) { const TRecord_info& i = recinfo(logicnum); return i.dir_type(); } void TFile_manager::notify_change(TIsam_handle name) { TFile_info& i = fileinfo(name); i.set_dirty(); } long TFile_manager::last_change(TIsam_handle name) const { TFile_info& i = fileinfo(name); return i.last_change(); } int TFile_manager::close_closeable() { _open_files = 0; for (TIsam_handle n = _fileinfo.last(); n > 0; n = _fileinfo.pred(n)) { TFile_info& i = fileinfo(n); if (i.is_open()) { if (!i.is_locked() && !i.is_exclusive()) { cache().discard(i.num()); i.auto_close(); } else _open_files++; } if (i.ref_count() <= 0) _fileinfo.destroy(n); } return _open_files; } void TFile_manager::close_all() { const int zoccolo_duro = close_closeable(); #ifdef DBG if (zoccolo_duro > 0) NFCHECK("%d files refuse to be closed!", zoccolo_duro); #endif for (int n = _recinfo.last(); n > 0; n = _recinfo.pred(n)) { const TRecord_info& r = recinfo(n); if (r.mutable_dir()) _recinfo.destroy(n); } } void TFile_manager::open_all() { for (TIsam_handle n = _fileinfo.last(); n > 0; n = _fileinfo.pred(n)) { TFile_info& i = fileinfo(n); if (!i.is_exclusive()) { if (i.mutable_dir()) i.load_filedes(); } } } const FileDes& TFile_manager::get_filedes(TIsam_handle id) const { TFile_info& i = fileinfo(id); return i; } const TFilename& TFile_manager::get_filename(TIsam_handle id) const { TFile_info& i = fileinfo(id); return i.pathname(); } TFile_manager::TFile_manager() : _open_files(0) { _max_open_files = xvt_sys_get_profile_int(NULL, "Main", "MaxHandles", 32); if (_max_open_files < 16) _max_open_files = 16; else if (_max_open_files > 64) _max_open_files = 64; } /////////////////////////////////////////////////////////// // TFirm /////////////////////////////////////////////////////////// bool TFirm::read(long cod) { int err = NOERR; if (cod < 0L) cod = prefix().get_codditta(); destroy(); TLocalisamfile ditte(LF_NDITTE); if (cod > 0L) { ditte.put(NDT_CODDITTA, cod); err = ditte.read(); } else err = ditte.first(); if (err == NOERR) { const TRectype& ditta = ditte.curr(); for (int f = ditta.items()-1; f >= 0; f--) { const char* name = ditta.fieldname(f); add(name, ditta.get(name)); } } else NFCHECK("Can't read firm %ld: error %d", cod, err); return items() > 0; } const TString& TFirm::get(const char* attr) const { const TString* str = (const TString*)objptr(attr); if (str == NULL) str = &EMPTY_STRING; return *str; } long TFirm::get_long(const char* attr) const { return atol(get(attr)); } long TFirm::codice() const { return get_long(NDT_CODDITTA); } const TString& TFirm::codice_valuta() const { const TString& codval = get(NDT_VALUTA); if (codval.empty()) return TCurrency::get_euro_val(); return codval; } const TString& TFirm::ragione_sociale() const { return get(NDT_RAGSOC); } TFirm::TFirm(long code) { read(code); } /////////////////////////////////////////////////////////// // TPrefix /////////////////////////////////////////////////////////// TPrefix::TPrefix() : _filelevel(0), _stdlevel(0), _items(0), _firm(NULL) { _prefix = "."; const char* prfx = CGetPref(); if (!fexist(__ptprf) || strchr(__ptprf, ' ') != NULL) fatal_box(FR("Percorso dati non valido: '%s'"), __ptprf); if (dongle().demo()) { const bool dati_demo = ini_get_bool(CONFIG_STUDIO, "Main", "Demo"); if (!dati_demo) fatal_box(FR("Area dati '%s' non utilizzabile in DEMO!"), __ptprf); } const TFilename dir(prfx); long primaditta = atol(dir.name()); if (primaditta > 0L && !exist(primaditta)) { TPointer_array ditte; firms(ditte); primaditta = ditte.empty() ? 0L : ditte.get_long(0); set_codditta(primaditta, true); } DB_init(); set(""); // Dati standard _stdlevel = filelevel(); set("DEF"); // Ditta corrente } TPrefix::~TPrefix() { set(); if (_firm) delete _firm; _manager.close_all(); DB_exit(); } // @doc EXTERNAL // @mfunc Riapre tutti gli archivi della ditta attiva void TPrefix::reopen() const { if (_prefix != ".") { TFile_manager& mgr = ((TPrefix*)this)->_manager; // Safe non const cast mgr.close_all(); mgr.open_all(); } } // @doc EXTERNAL // @mfunc Setta la ditta corrente void TPrefix::set( const char* name, // @parm Nome del direttorio dati da attivare (default NULL) bool force, // @parm Permette di settarla anche se non esiste (default false) TFilelock mode) // @parm Permette di aprire la ditta in modo esclusivo (default _manulock) // @comm Il parametro

puo' assumere i seguenti valori: // // @flag NULL | Chiude tutti i files // @flag COM | Apre il direttorio con i dati comuni // @flag DEF | Riapre la ditta indicata nel file prefix.txt // @flag codice ditta | Apre la ditta indicata { if (name == NULL) { close_closeable_isamfiles(); CCloseDir(NORDIR); CCloseDir(COMDIR); CCloseRecDir(NORDIR); CCloseRecDir(COMDIR); _prefix = "."; return; } if (_prefix == name) return; if (!force && !test(name)) return; if (_prefix != ".") { _manager.close_all(); CCloseDir(NORDIR); CCloseDir(COMDIR); CCloseRecDir(NORDIR); CCloseRecDir(COMDIR); } if (strcmp(name, "DEF") == 0) { const char* prfx = CGetPref(); xvt_fsys_parse_pathname(prfx, NULL, NULL, _prefix.get_buffer(), NULL, NULL); } else { _prefix = name; if (_prefix.full()) { const TString saved_prf = __ptprf; // Salvo __ptprf che viene cambiato da CGetPref char* prfx = (char*)CGetPref(); // Safe non const cast for StPath cprefix strcpy(__ptprf, saved_prf); xvt_fsys_build_pathname(prfx, NULL, __ptprf, _prefix, NULL, NULL); } else { char* prfx = (char*)CGetPref(); // Safe non const cast for StPath cprefix *prfx = '\0'; } } if (!test(_prefix)) fatal_box("Impossibile utilizzare la ditta %s", name); COpenDir((int) mode, NORDIR); COpenDir((int) mode, COMDIR); COpenRecDir((int) mode, NORDIR); COpenRecDir((int) mode, COMDIR); if (_prefix != ".") { FileDes d; CGetFile(LF_DIR, &d, _nolock, NORDIR); _filelevel = d.Flags; _items = (int)d.EOD; _manager.open_all(); } } bool TPrefix::exist(long codditta) const { if (codditta > 0L && codditta < 100000L) { TFilename s = firm2dir(codditta); s.add("dir.gen"); if (s.exist()) { s = s.path(); s.add("trc.gen"); return s.exist(); } } return false; } bool TPrefix::test(const char* s) const { if (s && *s && strcmp(s, "DEF") != 0) { TFilename s1(__ptprf); s1.add(s); s1.add("dir.gen"); if (s1.exist()) { if (xvt_fsys_access(s1, 0x2) != 0) return error_box(FR("Impossibile accedere in lettura/scrittura al file '%s'"), (const char*)s1); } else return error_box(FR("Impossibile trovare il file '%s'"), (const char*)s1); } return true; } void TPrefix::lock_record(TIsam_handle num, TRecnotype rec) { _manager.lock_record(num, rec); } void TPrefix::unlock_record(TIsam_handle num, TRecnotype rec) { _manager.unlock_record(num, rec); } bool TPrefix::test(long codditta) const { TString8 s("com"); if (codditta > 0L) s.format("%05lda", codditta); return test(s); } long TPrefix::get_codditta() const { const long codditta = atol(_prefix); return codditta; } bool TPrefix::set_codditta(long codditta, bool force) { if (force || test(codditta)) { TString8 s("com"); if (codditta > 0L) s.format("%05lda", codditta); set(s, force); CPutPref(_prefix); if (_firm && _firm->read(codditta)) { TConfig ini(CONFIG_DITTA, "Main"); FOR_EACH_ASSOC_STRING((*_firm), h, key, str) { if (*str > ' ') ini.set(key, str); } } return true; } return false; } const char* TPrefix::get_studio() const { return __ptprf; } bool TPrefix::set_studio(const char* study, long ditta) { TFilename dirtest(study); if (!dirtest.exist() || dirtest.find(' ') >= 0) return false; dirtest.add("com/dir.gen"); if (!dirtest.exist()) return false; // Chiudi tutti i files! _manager.close_all(); const TString old_study(__ptprf); const TString old_firm(_prefix); strcpy(__ptprf, study); const word len = strlen(__ptprf); if (len > 0 && __ptprf[len-1] != '\\' && __ptprf[len-1] != '/') { __ptprf[len] = SLASH; __ptprf[len+1] = '\0'; } if (!test(ditta)) ditta = 0L; bool ok = set_codditta(ditta, TRUE); if (!ok) { strcpy(__ptprf, old_study); set(old_firm, true); } return ok; } // @doc EXTERNAL // @mfunc Ritorna la descrizione del file passato const char* TPrefix::description( const char* cod) const // @parm Nome del file di cui si vuole conoscere la descrizione // @syntax const char* description(const char* cod); // @syntax const char* description(int cod); // // @comm Il parametro

puo' indicare anche il nome di una tabella. In questo caso ne // ritorna la descrizione. // Passando il nome di una tabella in

si ottiene la stessa cosa della // funzione , ma viene cercato la descrizione nel titolo della maschera. { TString& n = get_tmp_string(); n = cod; if (n[0] == '%') n.ltrim(1); const int logicnum = atoi(n); if (logicnum == 0) { TTable t(cod); n = t.description(); } else { if (logicnum > 0 && logicnum < items()) { TBaseisamfile f(logicnum); n = f.description(); } else n.cut(0); } return n; } const char* TPrefix::description(int cod) const { TString8 n; n << cod; return description(n); } const TFirm& TPrefix::firm() { if (_firm == NULL) _firm = new TFirm; return *_firm; } // Certified 90% // @doc EXTERNAL // @func Converte il numero di una ditta nella sua directory dati // // @rdesc Restituisce il nome di una directory dati // @parm Codice ditta da convertire const char* firm2dir(long codditta) { TString8 firm; switch (codditta) { case -2: // Dati generali campione case -1: // Dati di studio firm.cut(0); break; case 0: // Dati comuni firm = "com"; break; default: // Dati ditta firm.format("%05lda", codditta); break; } if (__ptprf[0] == '\0') { CGetPref(); CHECK(__ptprf[0], "Invalid prefix"); } TString& path = get_tmp_string(_MAX_PATH); xvt_fsys_build_pathname(path.get_buffer(), "", __ptprf, firm, NULL, NULL); return path; } int safely_close_closeable_isamfiles() { int f = 0; if (_prefhndl) f = _prefhndl->close_closeable_isamfiles(); return f; } bool TPrefix::build_firm_data(long codditta, bool flagcom) { const char* const ndir = "dir.gen"; const char* const ntrc = "trc.gen"; TFilename s(firm2dir(codditta)); s.add(ndir); bool exist = s.exist(); if (!exist) { s = s.path(); s.add(ntrc); exist = s.exist(); } if (exist) return message_box("Direttorio dati danneggiato, impossibile attivare la ditta %ld", codditta); if (!yesno_box("Gli archivi della ditta %ld non esistono: si desidera generarli?", codditta)) return false; set_autoload_new_files(yesno_box("Si desidera precaricare gli archivi standard")); s = s.path(); s.rtrim(1); if (!s.exist() && !make_dir(s)) return error_box("Impossibile creare il direttorio della ditta %ld (%s)", codditta, (const char*)s); s.add(ndir); if (!fcopy(ndir, s)) return error_box("Impossibile copiare il file %s della ditta %ld", ndir, codditta); s = s.path(); s.add(ntrc); if (!fcopy(ntrc, s)) return error_box("Impossibile copiare il file %s della ditta %ld", ntrc, codditta); TDir dir, dir1; TTrec rec; set(""); dir1.get(LF_DIR, _nolock, _nordir, _sysdirop); const long maxeod0 = dir1.eod(); set_codditta(codditta); dir.get(LF_DIR, _nolock, _nordir, _sysdirop); if (dir.eod() == 0) { dir1.set_eod(1); dir1.put(LF_DIR, _nordir, _sysdirop); dir.get(LF_DIR, _nolock, _nordir, _sysdirop); } const long maxeod1 = dir.eod(); if (maxeod0 > maxeod1) { dir.get(LF_DIR, _nolock, _nordir, _sysdirop); dir.set_eod(maxeod0); dir.put(LF_DIR, _nordir, _sysdirop); rec.zero(); } TString mess(TR("Generazione archivi della ditta ")); mess << codditta; TProgind p(maxeod0 ? maxeod0 : 1, mess, false, TRUE); for (int i = LF_USER; i <= maxeod0; i++) { p.addstatus(1); set(""); dir.get(i, _nolock, _nordir, _sysdirop); rec.get(i); bool create_now = dir.is_active(); prefix().set_codditta(codditta); dir.put(i, _nordir, _sysdirop); rec.put(i); dir.set_flags(0); create_now = create_now && (flagcom ? dir.is_com() : dir.is_firm()); if (dir.is_valid() && create_now) { TSystemisamfile f(i); f.build(); } else { dir.put(i, _nordir, _sysdirop); rec.put(i); } } TConfig c(CONFIG_STUDIO, "cg"); if (c.get_bool("StiReg")) { TTable reg("REG"); for (reg.first(_lock); reg.good(); reg.next(_lock)) { reg.put("B9", "X"); reg.rewrite(); } } set_codditta(codditta); set_autoload_new_files(TRUE); return true; } int TPrefix::firms(TString_array& codes) { codes.destroy(); TFilename n = __ptprf; n.add("?????A"); SLIST dirs = xvt_fsys_list_files(DIR_TYPE, n, true); for (SLIST_ELT e = xvt_slist_get_first(dirs); e; e = xvt_slist_get_next(dirs, e)) { n = xvt_slist_get(dirs, e, NULL); const TString& code = n.name_only(); TFilename s = firm2dir(atol(code)); s.add("dir.gen"); if (s.exist()) codes.add(code); } xvt_slist_destroy(dirs); return codes.items(); } int TPrefix::firms(TPointer_array& codes) { TString_array strcodes; firms(strcodes); FOR_EACH_ARRAY_ROW(strcodes, t, row) codes.add_long(atol(*row)); return codes.items(); } int TPrefix::firms(TArray& ditte) { ditte.destroy(); TPointer_array codes; firms(codes); for (int i = 0; i < codes.items(); i++) { const long codditta = codes.get_long(i); TFilename ininame = firm2dir(codditta); ininame.add("ditta.ini"); TConfig ini(ininame, "Main"); TAssoc_array& fields = ini.list_variables(); if (fields.empty() && prefix_valid()) { TLocalisamfile nditte(LF_NDITTE); TRectype& ditta = nditte.curr(); ditta.put(NDT_CODDITTA, codditta); if (nditte.read() == NOERR) { for (int f = 0; f < ditta.items(); f++) { const char* fname = ditta.fieldname(f); const TString& value = ditta.get(fname); if (!value.blank()) ini.set(fname, value); } } } if (fields.empty()) { ini.set(NDT_CODDITTA, codditta); CHECK(!fields.empty(), "Can't genenerate firm data"); } ditte.add(fields); } return ditte.items(); } /////////////////////////////////////////////////////////// // TTable name converter /////////////////////////////////////////////////////////// class TTable_names : public TObject { TAssoc_array _names; TArray _ids; long _filled; protected: void fill(); void add_file(int logic, const TString& table); public: const TString& name(int logic_num); int logic_num(const TString& name); TTable_names() : _filled(-1) { } } _table_names; void TTable_names::add_file(int logic, const TString& table) { TString8 id; id << logic; _names.add(table, id); _ids.add(table, logic); } void TTable_names::fill() { if (_filled != prefix().get_codditta()) { FileDes dir; CGetFile(LF_DIR, &dir, _nolock, NORDIR); const int nfiles = (int)dir.EOD; TFilename n; for (int logic = LF_USER; logic <= nfiles; logic++) { n = prefix().get_filename(logic); n = n.name_only(); n.upper(); if (_names.objptr(n) == NULL) add_file(logic, n); } _filled = prefix().get_codditta(); } } int TTable_names::logic_num(const TString& n) { // Non cambiare: n puo' essere temporaneo e pieno di spazi! TString80 name = n; name.trim(); const int namelen = name.len(); if (isdigit(name[0]) || name[0] == '-') { int num = atoi(name); if (name[namelen-1] == '@') num = -num; return num; } name.upper(); // ATTENZIONE: NON includere qui MAG! if (namelen == 3 && name != "DOC" && name != "MOV" && name != "RIP" && name != "CDC") return LF_TAB; switch (name[0]) { case '^': return LF_TABGEN; case '%': return LF_TABCOM; case '$': return LF_TAB; case '&': return LF_TABMOD; default : break; } TString* str = (TString*)_names.objptr(name); if (str == NULL) { fill(); str = (TString*)_names.objptr(name); } return str == NULL ? 0 : atoi(*str); } const TString& TTable_names::name(int logic_num) { TString* str = (TString*)_ids.objptr(logic_num); if (str == NULL) { fill(); str = (TString*)_ids.objptr(logic_num); } return str == NULL ? (const TString&)EMPTY_STRING : *str; } const TString& logic2table(int logic_num) { return _table_names.name(logic_num); } int table2logic(const TString& name) { return _table_names.logic_num(name); }