Files correlati : ba0 ba8 Ricompilazione Demo : [ ] Commento : Aggiunto supporto per campi booleani nei report Supporto per assenza di chiavetta=DEMO git-svn-id: svn://10.65.10.50/trunk@19531 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1563 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1563 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <codeb.h>
 | 
						|
#include <diction.h>
 | 
						|
#include <dongle.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
 | 
						|
  {
 | 
						|
    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 <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)) 
 | 
						|
    {
 | 
						|
      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 <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;
 | 
						|
  }    
 | 
						|
 | 
						|
  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); }
 |