Files correlati : ba1.exe Ricompilazione Demo : [ ] Commento : 0001036: installazione cd patch 180 Installando ex novo ed indicando una società esistente di dati su una cartella diversa viene segnalato l'errore ba1.exe in fase di conversione archivi, richiamando da manutenzione archivi la conversione vengono generati gli errori allegati. Nell'area ftp di Aga, cartella Ilaria allego l'area dati SIDA per il test. git-svn-id: svn://10.65.10.50/trunk@17971 c028cbd2-c16b-5b4b-a496-9718f37d4682
1513 lines
33 KiB
C++
Executable File
1513 lines
33 KiB
C++
Executable File
#include <codeb.h>
|
|
#include <diction.h>
|
|
#include <extcdecl.h>
|
|
#include <currency.h>
|
|
#include <prefix.h>
|
|
#include <progind.h>
|
|
#include <recarray.h>
|
|
#include <scanner.h>
|
|
#include <tabutil.h>
|
|
#include <utility.h>
|
|
|
|
#include <nditte.h>
|
|
|
|
// 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 <c TPrefix> 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 <c TPrefix> letto
|
|
TPrefix& prefix()
|
|
{
|
|
CHECK(_prefhndl, "Can't access null prefix");
|
|
return *_prefhndl;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Distrugge l'oggett <c TPrefix> 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<items; i++) // scorre i campi dell'espressione
|
|
{
|
|
ws = k.get(i); // Primo campo
|
|
const bool is_upper = ws.find("UPPER") >= 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
|
|
{
|
|
#ifdef DBG
|
|
error_box("You shouldn't reclose file %s", (const char*)_name);
|
|
#endif
|
|
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)
|
|
error_box("You shouldn't reopen file %d exclusively", num());
|
|
#endif
|
|
close_low();
|
|
}
|
|
_exclusive = _locked = 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)
|
|
{
|
|
if (is_open())
|
|
{
|
|
// Chiudi fisicamente solo se necessario
|
|
if (_locked || _exclusive || dir_type() == _extdir)
|
|
err = close_low();
|
|
}
|
|
_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] > ' ')
|
|
{
|
|
if (_filedes.SysName[0] != '$')
|
|
_dir = _comdir;
|
|
else
|
|
_dir = _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 > 0 && 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.not_empty())
|
|
{
|
|
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);
|
|
if (i.ref_count() == 0)
|
|
NFCHECK("Can't use closed file %d", i.num());
|
|
|
|
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();
|
|
_rec.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);
|
|
_rec.add(name, ditta.get(name));
|
|
}
|
|
}
|
|
else
|
|
NFCHECK("Can't read firm %ld: error %d", cod, err);
|
|
|
|
return _rec.items() > 0;
|
|
}
|
|
|
|
const TString& TFirm::get(const char* attr) const
|
|
{
|
|
const TString* str = (const TString*)_rec.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);
|
|
|
|
const TFilename dir(prfx);
|
|
const long primaditta = atol(dir.name());
|
|
if (primaditta > 0L && !exist(primaditta))
|
|
set_codditta(0L, 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 <p name> 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);
|
|
xvt_sys_set_profile_string(NULL, "Main", "Company", _firm->get(NDT_RAGSOC));
|
|
}
|
|
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 <p cod> puo' indicare anche il nome di una tabella. In questo caso ne
|
|
// ritorna la descrizione.
|
|
// <nl>Passando il nome di una tabella in <p cod> si ottiene la stessa cosa della
|
|
// funzione <mf TDir::Tab_des>, 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;
|
|
}
|
|
|
|
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;
|
|
|
|
TLocalisamfile ditte(LF_NDITTE);
|
|
ditte.zero();
|
|
ditte.put(NDT_CODDITTA,codditta);
|
|
if (ditte.read(_isequal,_testandlock) == _islocked)
|
|
{
|
|
message_box("Archivi della ditta %ld in fase di creazione da parte di un altro utente.",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(30);
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
ditte.reread(_unlock);
|
|
|
|
set_codditta(codditta);
|
|
set_autoload_new_files(TRUE);
|
|
|
|
return true;
|
|
}
|
|
|
|
int TPrefix::firms(TString_array& codes) const
|
|
{
|
|
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();
|
|
if (exist(atol(code)))
|
|
codes.add(code);
|
|
}
|
|
xvt_slist_destroy(dirs);
|
|
return codes.items();
|
|
}
|
|
|
|
int TPrefix::firms(TPointer_array& codes) const
|
|
{
|
|
TString_array strcodes; firms(strcodes);
|
|
FOR_EACH_ARRAY_ROW(strcodes, t, row)
|
|
codes.add_long(atol(*row));
|
|
return codes.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); }
|