campo-sirio/include/prefix.cpp
guy 2a3e35827d Patch level : 10.0 200
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
2008-12-23 09:05:22 +00:00

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); }