8f381b6ff9
git-svn-id: svn://10.65.10.50/trunk@3935 c028cbd2-c16b-5b4b-a496-9718f37d4682
2569 lines
62 KiB
C++
Executable File
2569 lines
62 KiB
C++
Executable File
#include <stdlib.h>
|
|
|
|
#include <applicat.h>
|
|
#include <colors.h>
|
|
#include <controls.h>
|
|
#include <execp.h>
|
|
#include <mailbox.h>
|
|
#include <progind.h>
|
|
#include <relation.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
#include <varmask.h>
|
|
|
|
#include "cg3.h"
|
|
#include "cglib.h"
|
|
|
|
#include "cg3600.h"
|
|
|
|
#include "causali.h"
|
|
#include "mov.h"
|
|
#include "pconti.h"
|
|
#include "rmov.h"
|
|
#include "saldi.h"
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TList
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TList : public TContainer
|
|
{
|
|
enum { MAX_SKIP = 8192 };
|
|
|
|
struct TList_object : public TObject
|
|
{
|
|
TObject* _obj;
|
|
TList_object* _next;
|
|
TList_object* _prev;
|
|
};
|
|
|
|
TList_object** _skip;
|
|
long _items, _current;
|
|
long _step, _last_skip;
|
|
|
|
protected:
|
|
// @cmember Ritorna un puntatore al primo oggetto del contenitore
|
|
virtual TObject* first_item( );
|
|
// @cmember Ritorna un puntatore all'ultimo oggetto del contenitore
|
|
virtual TObject* last_item( );
|
|
// @cmember Ritorna un puntatore all'oggetto successivo all'oggetto corrente
|
|
virtual TObject* succ_item( );
|
|
// @cmember Ritorna un puntatore all'oggetto che precede l'oggetto corrente
|
|
virtual TObject* pred_item( );
|
|
// @cmember Ritorna il numero di oggetti nel contenitore
|
|
virtual long objects( );
|
|
|
|
protected:
|
|
TList_object* detach_lstobj(long index);
|
|
TList_object* lstobjptr(long index) const;
|
|
void change_step(long step);
|
|
|
|
public:
|
|
long items() const { return _items; }
|
|
|
|
TObject* objptr(long index) const;
|
|
|
|
TObject& obj(long index)
|
|
{ TObject* o = objptr(index); CHECK(o, "Null list item"); return *o; }
|
|
|
|
const TObject& obj(long index) const
|
|
{ const TObject* o = objptr(index); CHECK(o, "Null list item"); return *o; }
|
|
|
|
void destroy();
|
|
long insert(TObject* obj, long pos);
|
|
long append(TObject* obj, long pos = -1);
|
|
|
|
TObject* detach(long pos);
|
|
bool remove(long pos);
|
|
|
|
void choose_step(long expected_size); // Sceglie il passo per gli elemnti
|
|
|
|
TList(long expected_size = 128L);
|
|
virtual ~TList();
|
|
};
|
|
|
|
TList::TList(long expected_size)
|
|
: _items(0), _current(0)
|
|
{
|
|
_skip = new TList_object*[MAX_SKIP+1];
|
|
_skip[0] = NULL;
|
|
choose_step(expected_size);
|
|
}
|
|
|
|
TList::~TList()
|
|
{
|
|
destroy();
|
|
delete [] _skip;
|
|
}
|
|
|
|
long TList::objects( )
|
|
{
|
|
return _items;
|
|
}
|
|
|
|
TObject* TList::first_item()
|
|
{
|
|
return objptr(_current = 0);
|
|
}
|
|
|
|
TObject* TList::succ_item()
|
|
{
|
|
return objptr(++_current);
|
|
}
|
|
|
|
TObject* TList::pred_item()
|
|
{
|
|
return objptr(_current++);
|
|
}
|
|
|
|
TObject* TList::last_item()
|
|
{
|
|
return objptr(_current = _items-1);
|
|
}
|
|
|
|
void TList::destroy()
|
|
{
|
|
TList_object* head = _skip[0];
|
|
while (head)
|
|
{
|
|
TList_object* next = head->_next;
|
|
if (head->_obj)
|
|
delete head->_obj;
|
|
delete head;
|
|
head = next;
|
|
}
|
|
_items = _current = _last_skip = 0;
|
|
_skip[0] = NULL;
|
|
}
|
|
|
|
TList::TList_object* TList::lstobjptr(long index) const
|
|
{
|
|
TList_object* lstobj = NULL;
|
|
const ldiv_t p = ldiv(index, _step);
|
|
if (p.quot >= 0 && p.quot < _last_skip)
|
|
{
|
|
TList_object* lo = _skip[p.quot];
|
|
for (long s = p.rem; lo && s > 0; s--)
|
|
lo = lo->_next;
|
|
|
|
lstobj = lo;
|
|
}
|
|
return lstobj;
|
|
}
|
|
|
|
TObject* TList::objptr(long index) const
|
|
{
|
|
const TList_object* lo = lstobjptr(index);
|
|
return lo ? lo->_obj : NULL;
|
|
}
|
|
|
|
void TList::change_step(long step)
|
|
{
|
|
CHECKD(step > 0 && step <= 16384, "Bad list step ", step);
|
|
_step = step;
|
|
_last_skip = 0;
|
|
|
|
step = 0;
|
|
for (TList_object* lo = _skip[0]; lo; lo = lo->_next, step--)
|
|
{
|
|
if (step == 0)
|
|
{
|
|
CHECK(_last_skip < MAX_SKIP, "Too many items");
|
|
_skip[_last_skip++] = lo;
|
|
step = _step;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TList::choose_step(long expected_size)
|
|
{
|
|
long step = expected_size / MAX_SKIP + 1;
|
|
change_step(step);
|
|
}
|
|
|
|
long TList::insert(TObject* obj, long index)
|
|
{
|
|
if (index < 0)
|
|
index = 0;
|
|
else
|
|
{
|
|
if (index > _items)
|
|
index = _items;
|
|
}
|
|
const long pred = index-1;
|
|
|
|
TList_object* newobj = new TList_object;
|
|
newobj->_obj = obj;
|
|
|
|
if (pred < 0)
|
|
{
|
|
newobj->_prev = NULL;
|
|
newobj->_next = _skip[0];
|
|
if (_skip[0])
|
|
_skip[0]->_prev = newobj;
|
|
}
|
|
else
|
|
{
|
|
TList_object* lo = lstobjptr(pred);
|
|
CHECK(lo, "NULL insertion point");
|
|
newobj->_next = lo->_next;
|
|
newobj->_prev = lo;
|
|
if (lo->_next)
|
|
lo->_next->_prev = newobj;
|
|
lo->_next = newobj;
|
|
}
|
|
_items++;
|
|
|
|
ldiv_t p = ldiv(index, _step);
|
|
if (p.rem == 0 && p.quot < MAX_SKIP) // Cambia il capolista
|
|
_skip[p.quot] = newobj;
|
|
|
|
for (long i = p.quot + 1; i < _last_skip; i++)
|
|
_skip[i] = _skip[i]->_prev; // Aggiorna capilista successivi
|
|
|
|
// Siamo andati oltre l'ultimo skip
|
|
const long s = (_items - 1) / _step + 1;
|
|
if (s > _last_skip)
|
|
{
|
|
if (s > MAX_SKIP)
|
|
change_step(_step+1);
|
|
else
|
|
{
|
|
if (_last_skip > 0)
|
|
{
|
|
TList_object* lo = _skip[_last_skip-1];
|
|
while (lo->_next != NULL)
|
|
lo = lo->_next;
|
|
_skip[_last_skip++] = lo;
|
|
_skip[_last_skip] = NULL;
|
|
}
|
|
else
|
|
_last_skip = 1;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
long TList::append(TObject* obj, long index)
|
|
{
|
|
if (index < 0 || index >= _items)
|
|
index = _items;
|
|
else
|
|
index++;
|
|
return insert(obj, index);
|
|
}
|
|
|
|
TList::TList_object* TList::detach_lstobj(long index)
|
|
{
|
|
TList_object* lo = lstobjptr(index);
|
|
if (lo)
|
|
{
|
|
if (lo->_prev)
|
|
lo->_prev->_next = lo->_next;
|
|
if (lo->_next)
|
|
lo->_next->_prev = lo->_prev;
|
|
ldiv_t res = ldiv(index, _step);
|
|
if (res.rem == 0)
|
|
_skip[res.quot] = lo->_next;
|
|
long p;
|
|
for (p = res.quot + 1; p < _last_skip; p++)
|
|
_skip[p] = _skip[p]->_next;
|
|
|
|
_items--;
|
|
|
|
p = (_items - 1) / _step + 1;
|
|
if (p < _last_skip)
|
|
{
|
|
_last_skip--;
|
|
_skip[_last_skip] = NULL;
|
|
}
|
|
}
|
|
|
|
return lo;
|
|
}
|
|
|
|
TObject* TList::detach(long index)
|
|
{
|
|
TList_object* lo = detach_lstobj(index);
|
|
TObject* obj;
|
|
if (lo)
|
|
{
|
|
obj = lo->_obj;
|
|
delete lo;
|
|
}
|
|
else
|
|
obj = NULL;
|
|
return obj;
|
|
}
|
|
|
|
bool TList::remove(long index)
|
|
{
|
|
TObject* o = detach(index);
|
|
if (o)
|
|
delete o;
|
|
return o != NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TDecoder
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TDecoder : private TAssoc_array
|
|
{
|
|
TLocalisamfile* _file;
|
|
TString _if, _of;
|
|
|
|
public:
|
|
const TString& decode(const char* code);
|
|
const TString& decode(long code);
|
|
|
|
TDecoder(int num, const char* inf, const char* outf);
|
|
TDecoder(const char* table, const char* outf = "S0");
|
|
virtual ~TDecoder();
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TDecoder
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TDecoder::TDecoder(int num, const char* inf, const char* outf)
|
|
: _file(new TLocalisamfile(num)), _if(inf), _of(outf)
|
|
{ }
|
|
|
|
TDecoder::TDecoder(const char* tab, const char* outf)
|
|
: _file(new TTable(tab)), _if("CODTAB"), _of(outf)
|
|
{ }
|
|
|
|
TDecoder::~TDecoder()
|
|
{
|
|
delete _file;
|
|
}
|
|
|
|
const TString& TDecoder::decode(const char* code)
|
|
{
|
|
if (code == NULL)
|
|
code = "";
|
|
|
|
TObject* obj = objptr(code);
|
|
if (obj == NULL)
|
|
{
|
|
int err = ~NOERR;
|
|
if (*code)
|
|
{
|
|
_file->setkey(1);
|
|
_file->put(_if, code);
|
|
err = _file->read();
|
|
}
|
|
if (err == NOERR)
|
|
obj = new TString(_file->get(_of)); // Found
|
|
else
|
|
obj = new TString(1); // Not found
|
|
add(code, obj);
|
|
}
|
|
const TString& s = (const TString&)*obj;
|
|
return s;
|
|
}
|
|
|
|
const TString& TDecoder::decode(long code)
|
|
{
|
|
TString16 c;
|
|
if (code > 0)
|
|
c << code;
|
|
return decode(c);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TBalance
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TBalance : public TObject
|
|
{
|
|
TImporto _saldo_ini, _progr_dare, _progr_avere, _saldo_fin;
|
|
|
|
protected:
|
|
bool find(const TBill& b, int esercizio,
|
|
TImporto& si, TImporto& da, TImporto& av, TImporto& sf) const;
|
|
|
|
public:
|
|
void read(int g, int c, long s, int esercizio);
|
|
void read(const TBill& b, int esercizio);
|
|
void reread();
|
|
|
|
const TImporto& saldo_iniziale() const;
|
|
const real& progressivo_dare_iniziale() const;
|
|
const real& progressivo_avere_iniziale() const;
|
|
real progressivo_dare_finale() const;
|
|
real progressivo_avere_finale() const;
|
|
TImporto saldo_finale(bool chiusura = FALSE) const;
|
|
TImporto saldo_finale_chiusura() const;
|
|
|
|
TBalance();
|
|
TBalance(int g, int c, long s, int esercizio);
|
|
TBalance(const TBill& b, int esercizio);
|
|
virtual ~TBalance() { }
|
|
};
|
|
|
|
TBalance::TBalance()
|
|
{
|
|
}
|
|
|
|
TBalance::TBalance(int g, int c, long s, int esercizio)
|
|
{
|
|
read(g, c, s, esercizio);
|
|
}
|
|
|
|
TBalance::TBalance(const TBill& b, int esercizio)
|
|
{
|
|
read(b, esercizio);
|
|
}
|
|
|
|
bool TBalance::find(const TBill& b, int esercizio,
|
|
TImporto& si, TImporto& da, TImporto& av, TImporto& sf) const
|
|
{
|
|
CHECK(b.sottoconto() > 0L, "Sottoconto mancante");
|
|
|
|
TLocalisamfile saldi(LF_SALDI);
|
|
TRectype& curr = saldi.curr();
|
|
curr.put(SLD_GRUPPO, b.gruppo());
|
|
curr.put(SLD_CONTO, b.conto());
|
|
curr.put(SLD_SOTTOCONTO, b.sottoconto());
|
|
curr.put(SLD_ANNOES, esercizio);
|
|
curr.put(SLD_FLSCA, FALSE);
|
|
const bool ok = saldi.read() == NOERR;
|
|
if (ok)
|
|
{
|
|
si.set(curr.get_char(SLD_FLAGSALINI), curr.get_real(SLD_SALDO));
|
|
da.set('D', curr.get_real(SLD_PDARE));
|
|
av.set('A', curr.get_real(SLD_PAVERE));
|
|
sf.set(curr.get_char(SLD_FLAGSALFIN), curr.get_real(SLD_SALDOFIN));
|
|
}
|
|
else
|
|
{
|
|
si.set('D', ZERO);
|
|
da = av = sf = si;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
|
|
void TBalance::read(int gruppo, int conto, long sottoconto, int esercizio)
|
|
{
|
|
const TBill zio(gruppo, conto, sottoconto);
|
|
read(zio, esercizio);
|
|
}
|
|
|
|
void TBalance::read(const TBill& b, int esercizio)
|
|
{
|
|
TImporto si, sf, pd, pa;
|
|
|
|
find(b, esercizio, si, pd, pa, sf);
|
|
_saldo_ini = si;
|
|
_progr_dare = pd;
|
|
_progr_avere = pa;
|
|
_saldo_fin = sf;
|
|
|
|
if (_saldo_ini.is_zero())
|
|
{
|
|
TLocalisamfile pcon(LF_PCON);
|
|
TRectype& curr = pcon.curr();
|
|
curr.put(PCN_GRUPPO, b.gruppo());
|
|
curr.put(PCN_CONTO, b.conto());
|
|
const int err = pcon.read();
|
|
CHECK(err == NOERR, "Impossibile stabilire indicatore di bilancio");
|
|
const int indbil = curr.get_int(PCN_INDBIL);
|
|
if (indbil == 1 || indbil == 2 || indbil == 5)
|
|
{
|
|
TEsercizi_contabili esercizi;
|
|
const int precedente = esercizi.pred(esercizio);
|
|
if (find(b, precedente, si, pd, pa, sf))
|
|
{
|
|
_saldo_ini = si;
|
|
_saldo_ini += pd;
|
|
_saldo_ini += pa;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const TImporto& TBalance::saldo_iniziale() const
|
|
{ return _saldo_ini; }
|
|
|
|
const real& TBalance::progressivo_dare_iniziale() const
|
|
{
|
|
return _saldo_ini.sezione() == 'D' ? _saldo_ini.valore() : ZERO;
|
|
}
|
|
|
|
const real& TBalance::progressivo_avere_iniziale() const
|
|
{
|
|
return _saldo_ini.sezione() == 'A' ? _saldo_ini.valore() : ZERO;
|
|
}
|
|
|
|
real TBalance::progressivo_dare_finale() const
|
|
{
|
|
real pd = progressivo_dare_iniziale();
|
|
pd += _progr_dare.valore();
|
|
if (_saldo_fin.sezione() == 'D')
|
|
pd += _saldo_fin.valore();
|
|
return pd;
|
|
}
|
|
|
|
real TBalance::progressivo_avere_finale() const
|
|
{
|
|
real pa = progressivo_avere_iniziale();
|
|
pa += _progr_avere.valore();
|
|
if (_saldo_fin.sezione() == 'A')
|
|
pa += _saldo_fin.valore();
|
|
return pa;
|
|
}
|
|
|
|
TImporto TBalance::saldo_finale(bool chiusura) const
|
|
{
|
|
TImporto sf(_saldo_ini);
|
|
sf += _progr_dare;
|
|
sf += _progr_avere;
|
|
if (chiusura)
|
|
sf += _saldo_fin;
|
|
return sf;
|
|
}
|
|
|
|
TImporto TBalance::saldo_finale_chiusura() const
|
|
{
|
|
return saldo_finale(TRUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TMastrino
|
|
///////////////////////////////////////////////////////////
|
|
|
|
enum tipo_riga_mastrino { riga_mastrino, riga_contropartita };
|
|
|
|
class TRiga_mastrino : public TObject
|
|
{
|
|
tipo_riga_mastrino _type;
|
|
TRecnotype _mov, _rmov;
|
|
TDate _data;
|
|
real _dare, _avere;
|
|
|
|
public:
|
|
tipo_riga_mastrino tipo() const { return _type; }
|
|
TRecnotype rmov() const { return _rmov; }
|
|
TRecnotype mov() const { return _mov; }
|
|
|
|
const TDate& data() const { return _data; }
|
|
const real& dare() const { return _dare; }
|
|
const real& avere() const { return _avere; }
|
|
TImporto saldo() const;
|
|
|
|
TRiga_mastrino(tipo_riga_mastrino trig,
|
|
TRecnotype rmov, TRecnotype mov,
|
|
const real& d, const real& a,
|
|
const TDate& datareg);
|
|
virtual ~TRiga_mastrino() { }
|
|
};
|
|
|
|
TRiga_mastrino::TRiga_mastrino(tipo_riga_mastrino trig,
|
|
TRecnotype rmov, TRecnotype mov,
|
|
const real& d, const real& a,
|
|
const TDate& datareg)
|
|
: _type(trig), _rmov(rmov), _mov(mov),
|
|
_dare(d), _avere(a), _data(datareg)
|
|
{ }
|
|
|
|
TImporto TRiga_mastrino::saldo() const
|
|
{
|
|
TImporto imp('D', _dare - _avere);
|
|
imp.normalize();
|
|
return imp;
|
|
}
|
|
|
|
class TMastrino : public TObject
|
|
{
|
|
static long _instances;
|
|
static TRelation* _rel;
|
|
static TLocalisamfile *_rmov; // File principale della relazione
|
|
static TLocalisamfile *_mov; // File secondario della relazione
|
|
|
|
TBill _conto; // Conto del mastrino
|
|
int _esercizio; // Esercizio di riferimento (eventualmente 0)
|
|
TDate _da_data, _a_data;
|
|
TString _da_caus, _a_caus;
|
|
|
|
real _pdare_ini, _pavere_ini;
|
|
real _pdare_per, _pavere_per;
|
|
real _pdare_fin, _pavere_fin;
|
|
|
|
TList _riga; // Righe del mastrino
|
|
|
|
protected:
|
|
TRelation& rel() { return *_rel; }
|
|
TLocalisamfile& rmov() { return *_rmov; }
|
|
TLocalisamfile& mov() { return *_mov; }
|
|
|
|
void position_rel(long n);
|
|
TRiga_mastrino& row(long n) const { return (TRiga_mastrino&)_riga.obj(n); }
|
|
|
|
public:
|
|
long items() const { return _riga.items(); }
|
|
|
|
void read(const TBill& conto,
|
|
int annoes, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac);
|
|
void reread();
|
|
|
|
TRiga_mastrino& operator[](long n) const { return row(n); }
|
|
const TRectype& riga(long n);
|
|
const TRectype& testata(long n);
|
|
|
|
long first(tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
long pred(long rec, tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
long succ(long rec, tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
long last(tipo_riga_mastrino tipo = riga_mastrino) const;
|
|
|
|
void destroy() { _riga.destroy(); }
|
|
int esercizio() const { return _esercizio; }
|
|
|
|
const real& progressivo_dare_iniziale() const { return _pdare_ini; }
|
|
const real& progressivo_avere_iniziale() const { return _pavere_ini; }
|
|
TImporto saldo_iniziale() const;
|
|
|
|
const real& progressivo_dare_finale() const { return _pdare_fin; }
|
|
const real& progressivo_avere_finale() const { return _pavere_fin; }
|
|
TImporto saldo_finale() const;
|
|
|
|
real progressivo_dare_periodo() const { return _pdare_ini + _pdare_per; }
|
|
real progressivo_avere_periodo() const { return _pavere_ini + _pavere_per; }
|
|
TImporto saldo_periodo() const;
|
|
|
|
bool expandable(long rec) const;
|
|
bool expand(long rec);
|
|
bool collapse(long rec);
|
|
|
|
TMastrino();
|
|
virtual ~TMastrino();
|
|
};
|
|
|
|
long TMastrino::_instances = 0L;
|
|
TRelation* TMastrino::_rel = NULL;
|
|
TLocalisamfile* TMastrino::_rmov = NULL; // File principale della relazione
|
|
TLocalisamfile* TMastrino::_mov = NULL; // File secondario della relazione
|
|
|
|
|
|
TMastrino::TMastrino()
|
|
: _esercizio(0)
|
|
{
|
|
if (_instances == 0L)
|
|
{
|
|
_rel = new TRelation(LF_RMOV);
|
|
_rel->add(LF_MOV, "NUMREG=NUMREG");
|
|
_rmov = &_rel->lfile();
|
|
_mov = &_rel->lfile(LF_MOV);
|
|
}
|
|
_instances++;
|
|
}
|
|
|
|
TMastrino::~TMastrino()
|
|
{
|
|
_instances--;
|
|
if (_instances == 0L)
|
|
{
|
|
delete _rel;
|
|
_rel = NULL;
|
|
_rmov = _mov = NULL;
|
|
}
|
|
}
|
|
|
|
long TMastrino::succ(long rec, tipo_riga_mastrino tipo) const
|
|
{
|
|
const long ul = items();
|
|
for (long i = rec+1; i < ul; i++)
|
|
{
|
|
if (row(i).tipo() == tipo)
|
|
break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
long TMastrino::pred(long rec, tipo_riga_mastrino tipo) const
|
|
{
|
|
for (long i = rec-1; i >= 0; i--)
|
|
{
|
|
if (row(i).tipo() == tipo)
|
|
break;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
long TMastrino::first(tipo_riga_mastrino tipo) const
|
|
{
|
|
return succ(-1, tipo);
|
|
}
|
|
|
|
long TMastrino::last(tipo_riga_mastrino tipo) const
|
|
{
|
|
return pred(items(), tipo);
|
|
}
|
|
|
|
void TMastrino::read(const TBill& conto,
|
|
int ae, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac)
|
|
{
|
|
TEsercizi_contabili esercizi;
|
|
|
|
_conto = conto;
|
|
_esercizio = ae;
|
|
|
|
_riga.destroy();
|
|
|
|
rmov().setkey(2);
|
|
TRectype& rmov_rec = rmov().curr();
|
|
const TRectype& mov_rec = mov().curr();
|
|
|
|
if (ae <= 0)
|
|
{
|
|
if (dd.ok())
|
|
ae = esercizi.date2esc(dd);
|
|
else
|
|
ae = esercizi.date2esc(ad);
|
|
}
|
|
CHECKD(esercizi.exist(ae), "Anno di esercizio fantasioso: ", ae);
|
|
|
|
const TDate& inizio_esercizio = esercizi[ae].inizio();
|
|
_da_data = dd.ok() ? dd : inizio_esercizio;
|
|
_a_data = ad.ok() ? ad : esercizi[ae].fine();
|
|
|
|
_da_caus = dc;
|
|
_a_caus = ac.blank() ? "zzz" : ac;
|
|
|
|
const TDate& min_data_reg = _da_data;
|
|
TDate max_data_reg;
|
|
|
|
long num_giorni = _a_data - _da_data + 1;
|
|
if (_esercizio > 0)
|
|
{
|
|
const int succ = esercizi.next(ae);
|
|
if (succ > 0)
|
|
{
|
|
max_data_reg = esercizi[succ].fine();
|
|
num_giorni += 30;
|
|
}
|
|
else
|
|
max_data_reg = esercizi[ae].fine();
|
|
}
|
|
else
|
|
max_data_reg = _a_data;
|
|
|
|
TString caption(80);
|
|
caption.format("Caricamento mastrino %03d.%03d.%06ld",
|
|
_conto.gruppo(), _conto.conto(), _conto.sottoconto());
|
|
TProgind pi(num_giorni, caption, FALSE, TRUE, 48);
|
|
|
|
// Valori dei saldi fino alla data di inizio stampa:
|
|
// Vengono inizializzati con i saldi iniziali dell'esercizio,
|
|
// poi verranno sommati gli importi dei movimenti che
|
|
// vanno dall'inizio dell'esercizio al giorno precedente
|
|
// la data di inizio stampa
|
|
|
|
const TBalance saldo(_conto, ae);
|
|
_pdare_ini = saldo.progressivo_dare_iniziale();
|
|
_pavere_ini = saldo.progressivo_avere_iniziale();
|
|
_pdare_fin = saldo.progressivo_dare_finale();
|
|
_pavere_fin = saldo.progressivo_avere_finale();
|
|
|
|
// Valori dei saldi del perido in esame:
|
|
// Vengono inizializzati a zero e poi si incrementa man mano
|
|
// coi valori degli importi dei movimenti compresi nei
|
|
// limiti della stampa
|
|
_pdare_per = _pavere_per = ZERO;
|
|
|
|
conto.put(rmov_rec);
|
|
rmov_rec.put(RMV_DATAREG, min_data_reg);
|
|
|
|
for (int err = rel().read(_isgteq); err == NOERR; err = rel().next())
|
|
{
|
|
// Controlla di non aver superato la data limite
|
|
const TDate data_reg = mov_rec.get(MOV_DATAREG);
|
|
if (data_reg > max_data_reg)
|
|
break;
|
|
|
|
// Controlla che il conto sia ancora quello selezionato
|
|
const TBill conto_corrente(rmov_rec);
|
|
if (conto_corrente != conto)
|
|
break;
|
|
|
|
const long giorno = data_reg - min_data_reg + 1;
|
|
pi.setstatus(giorno);
|
|
|
|
// Ignora i movimenti provvisori
|
|
if (mov_rec.get_char(MOV_PROVVIS) > ' ')
|
|
continue;
|
|
|
|
const TDate data_corrente(_esercizio <= 0 ? data_reg : mov_rec.get_date(MOV_DATADOC));
|
|
if (data_corrente > _a_data)
|
|
continue;
|
|
|
|
const char sezione = rmov_rec.get_char(RMV_SEZIONE);
|
|
const real importo = rmov_rec.get(RMV_IMPORTO);
|
|
|
|
if (data_corrente < _da_data)
|
|
{
|
|
if (data_corrente >= inizio_esercizio)
|
|
{
|
|
if (sezione == 'D')
|
|
_pdare_ini += importo;
|
|
else
|
|
_pavere_ini += importo;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (sezione == 'D')
|
|
_pdare_per += importo;
|
|
else
|
|
_pavere_per += importo;
|
|
|
|
// Controlla che la causale sia nei limiti
|
|
const TString& causale = mov_rec.get(MOV_CODCAUS);
|
|
if (causale >= _da_caus && causale <= _a_caus)
|
|
{
|
|
TRiga_mastrino* r = new TRiga_mastrino(riga_mastrino,
|
|
rmov().recno(), mov().recno(),
|
|
_pdare_per, _pavere_per, data_reg);
|
|
_riga.append(r);
|
|
}
|
|
}
|
|
}
|
|
|
|
pi.setstatus(num_giorni); // Raramente arriva in fondo!
|
|
}
|
|
|
|
void TMastrino::reread()
|
|
{
|
|
read(_conto, _esercizio, _da_data, _a_data, _da_caus, _a_caus);
|
|
}
|
|
|
|
|
|
void TMastrino::position_rel(long n)
|
|
{
|
|
const TRiga_mastrino& r = row(n);
|
|
if (rmov().recno() != r.rmov())
|
|
rmov().readat(r.rmov());
|
|
if (mov().recno() != r.mov())
|
|
mov().readat(r.mov());
|
|
}
|
|
|
|
const TRectype& TMastrino::riga(long n)
|
|
{
|
|
position_rel(n);
|
|
return rmov().curr();
|
|
}
|
|
|
|
const TRectype& TMastrino::testata(long n)
|
|
{
|
|
position_rel(n);
|
|
return mov().curr();
|
|
}
|
|
|
|
TImporto TMastrino::saldo_iniziale() const
|
|
{
|
|
TImporto s('D', _pdare_ini - _pavere_ini);
|
|
return s.normalize();
|
|
}
|
|
|
|
TImporto TMastrino::saldo_finale() const
|
|
{
|
|
TImporto s('D', _pdare_fin - _pavere_fin);
|
|
return s.normalize();
|
|
}
|
|
|
|
TImporto TMastrino::saldo_periodo() const
|
|
{
|
|
TImporto s('D', progressivo_dare_periodo() - progressivo_avere_periodo());
|
|
return s.normalize();
|
|
}
|
|
|
|
bool TMastrino::expandable(long rec) const
|
|
{
|
|
bool e = FALSE;
|
|
if (row(rec).tipo() == riga_mastrino)
|
|
{
|
|
if (rec < items()-1)
|
|
e = row(rec+1).tipo() != riga_contropartita;
|
|
else
|
|
e = TRUE;
|
|
}
|
|
return e;
|
|
}
|
|
|
|
bool TMastrino::expand(long rec)
|
|
{
|
|
bool ok = expandable(rec);
|
|
if (ok)
|
|
{
|
|
const TRectype& head = testata(rec);
|
|
const long numreg = head.get_long(MOV_NUMREG);
|
|
|
|
rmov().setkey(1);
|
|
TRectype& curr = rmov().curr();
|
|
curr.zero();
|
|
curr.put(RMV_NUMREG, numreg);
|
|
for (int err = rmov().read(_isgteq); err == NOERR; err = rmov().next())
|
|
{
|
|
if (curr.get_long(RMV_NUMREG) != numreg)
|
|
break;
|
|
|
|
const TBill bill(curr, TRUE); // Legge il conto di contropartita
|
|
if (bill == _conto)
|
|
{
|
|
real dare, avere;
|
|
if (curr.get_char(RMV_SEZIONE) == 'D')
|
|
dare = curr.get_real(RMV_IMPORTO);
|
|
else
|
|
avere = curr.get_real(RMV_IMPORTO);
|
|
|
|
const TDate data(head.get(MOV_DATAREG));
|
|
|
|
TRiga_mastrino* r = new TRiga_mastrino(riga_contropartita,
|
|
rmov().recno(), mov().recno(),
|
|
dare, avere, data);
|
|
_riga.append(r, rec);
|
|
}
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TMastrino::collapse(long rec)
|
|
{
|
|
if (row(rec).tipo() != riga_mastrino)
|
|
rec = pred(rec, riga_mastrino);
|
|
bool ok = !expandable(rec);
|
|
if (ok)
|
|
{
|
|
rec++;
|
|
while (rec < items() && row(rec).tipo() != riga_mastrino)
|
|
_riga.remove(rec);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_control
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TGrid_control;
|
|
|
|
class TGrid_cell : public TObject
|
|
{
|
|
XI_EVENT* _xiev;
|
|
|
|
public:
|
|
void set(const char* txt);
|
|
void set(long num);
|
|
void set_icon(int id);
|
|
void show_button(bool on = TRUE);
|
|
void hide_button() { show_button(FALSE); }
|
|
void set_back_color(COLOR col);
|
|
void set_fore_color(COLOR col);
|
|
void set_colors(COLOR back, COLOR fore);
|
|
|
|
short get_column() const;
|
|
short get_size() const;
|
|
|
|
TGrid_cell(XI_EVENT* xiev) : _xiev(xiev) { }
|
|
virtual ~TGrid_cell() { }
|
|
};
|
|
|
|
class TGrid_field : public TOperable_field
|
|
{
|
|
protected: // TMask_field
|
|
virtual void create(WINDOW parent);
|
|
virtual void parse_head(TScanner& scanner);
|
|
virtual bool parse_item(TScanner& scanner);
|
|
|
|
TGrid_control& grid() const { return (TGrid_control&)*_ctl; }
|
|
|
|
public:
|
|
virtual bool handler(XI_EVENT* xiev);
|
|
virtual long items() const;
|
|
virtual void cell_request(long rec, short id, TGrid_cell& cell);
|
|
|
|
virtual bool on_record(long rec) { return TRUE; }
|
|
virtual bool off_record(long rec) { return TRUE; }
|
|
virtual bool on_resize_column(short cid, int new_size) { return TRUE; }
|
|
virtual void on_dbl_cell(long rec, short id) { }
|
|
virtual void on_grid_button() { }
|
|
virtual void on_record_button(long rec) { }
|
|
virtual void on_cell_button(long rec, short cid) { }
|
|
|
|
long selected() const;
|
|
void update(long n = -1);
|
|
int visible_rows() const;
|
|
bool select(long rec);
|
|
|
|
TGrid_field(TMask* m) : TOperable_field(m) { }
|
|
virtual ~TGrid_field() { }
|
|
};
|
|
|
|
class TGrid_control : public TControl
|
|
{
|
|
enum grid_control_constants { MAX_COL = 128 };
|
|
|
|
long _cur_rec;
|
|
bool _read_only;
|
|
|
|
// @cmember:(INTERNAL) Tipo di ogni colonna
|
|
byte _type[MAX_COL];
|
|
|
|
TGrid_field* _grid;
|
|
|
|
protected: // TControl
|
|
//@cmember Gestisce gli eventi delle celle
|
|
virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);
|
|
|
|
//@cmember Chiama gli handlers opportuni per verificare il cambio record
|
|
bool try_to_select(long rec) const;
|
|
|
|
protected:
|
|
//@cmember Ritorna il numero totale di righe
|
|
long items() const { return _grid->items(); }
|
|
|
|
//@cmember Converte un record nella eventuale riga corrispondente a video
|
|
int rec2row(long rec) const;
|
|
|
|
//@cmember Converte una riga a video nell'eventuale record corrispondente
|
|
long row2rec(int row) const;
|
|
|
|
//@cmember Converte un indice di colonna nel corrispondente id
|
|
short int col2cid(int pos) const;
|
|
|
|
void update_selection(XI_EVENT* xiev);
|
|
|
|
public:
|
|
long selected() const { return _cur_rec; }
|
|
bool select(long n);
|
|
|
|
int visible_rows() const;
|
|
|
|
byte& column_type(int c) { CHECKD(c >= 0 && c < MAX_COL, "Bad column ", c); return _type[c]; }
|
|
|
|
void update(long n = -1);
|
|
bool is_visible(long rec) const;
|
|
|
|
TGrid_control(WINDOW parent, short cid,
|
|
short x, short y, short dx, short dy,
|
|
const char* flags, const char* head,
|
|
TGrid_field* owner);
|
|
virtual ~TGrid_control() {}
|
|
};
|
|
|
|
|
|
TGrid_control::TGrid_control(
|
|
WINDOW parent, // @parm Finestra alla quale appartiene lo spreadsheet
|
|
short cid, // @parm Identificatore
|
|
short x, // @parm Coordinata x (in caratteri) nel quale posizionare lo spreadsheet
|
|
short y, // @parm Coordinata y (in caratteri) nel quale posizionare lo spreadsheet
|
|
short dx, // @parm Larghezza (in caratteri) dello spreasheet
|
|
short dy, // @parm Lunghezza (in caratteri) dello spreasheet
|
|
const char* flags, // @parm Flags di abilitazione
|
|
const char* head, // @parm Titolo delle colonne
|
|
TGrid_field* owner)
|
|
: _grid(owner), _cur_rec(-1)
|
|
{
|
|
_read_only = FALSE;
|
|
bool auto_num = FALSE;
|
|
bool multi_line = FALSE;
|
|
int lines_in_cell = 1;
|
|
|
|
for (const char* f = flags; *f; f++)
|
|
{
|
|
switch(*f)
|
|
{
|
|
case 'D':
|
|
_read_only = TRUE;
|
|
break;
|
|
case 'M':
|
|
multi_line = TRUE;
|
|
lines_in_cell = (int)xi_get_pref(XI_PREF_DEFAULT_MAX_LINES_IN_CELL);
|
|
break;
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
if (multi_line)
|
|
lines_in_cell = *f - '0';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
const int NUMBER_WIDTH = auto_num ? 7 : 1;
|
|
short v_width[MAX_COL];
|
|
short m_width[MAX_COL];
|
|
int fixed_columns = 1; // Number of fixed columns
|
|
int lines_in_header = 1; // Number of header lines
|
|
|
|
// Calcolo larghezza massima tabella
|
|
TToken_string header(head);
|
|
TToken_string new_header(256);
|
|
int i = 0;
|
|
int f_width = NUMBER_WIDTH; // Stima larghezza colonne fisse
|
|
int max_width = f_width; // Stima larghezza della colonna piu' grande
|
|
|
|
for (const char* h = header.get(); h; h = header.get(), i++)
|
|
{
|
|
CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i);
|
|
_type[i] = ' ';
|
|
|
|
TFixed_string testa(esc(h));
|
|
const bool multiple = testa.find('\n') > 0;
|
|
if (multiple)
|
|
lines_in_header = 2;
|
|
|
|
const int at = testa.find('@');
|
|
int v = testa.len(); // Video width
|
|
if (at >= 0)
|
|
{
|
|
const TString& wi = testa.mid(at+1);
|
|
const int video = atoi(wi);
|
|
if (video > 0) v = video;
|
|
if (wi.find('F') >= 0)
|
|
{
|
|
fixed_columns = i+2;
|
|
f_width += v+1;
|
|
}
|
|
if (wi.find('R') >= 0)
|
|
_type[i] = 'R';
|
|
|
|
testa.cut(at);
|
|
}
|
|
|
|
v++;
|
|
// memory width of column
|
|
m_width[i] = v * lines_in_cell;
|
|
if (v > 64) v = 64;
|
|
v_width[i] = v;
|
|
if (v_width[i] > max_width)
|
|
max_width = v_width[i];
|
|
new_header.add(testa);
|
|
}
|
|
|
|
// Calcola rettangolo massimo per lo sheet
|
|
XI_RCT rct; coord2rct(parent, x, y, dx, dy, rct);
|
|
rct.right -= 2*XI_FU_MULTIPLE; // toglie scroll-bar
|
|
|
|
// Controlla se ci sono troppe colonne fisse
|
|
if ((f_width+max_width)*XI_FU_MULTIPLE > rct.right)
|
|
fixed_columns = 1;
|
|
|
|
XI_OBJ* itf = get_interface(parent);
|
|
|
|
XI_OBJ_DEF* listdef = xi_add_list_def(NULL, cid,
|
|
rct.top, rct.left, rct.bottom-rct.top,
|
|
XI_ATR_ENABLED | XI_ATR_VISIBLE,
|
|
NORMAL_COLOR, NORMAL_BACK_COLOR, // normal
|
|
DISABLED_COLOR, DISABLED_BACK_COLOR, // disabled
|
|
FOCUS_COLOR, // active
|
|
0);
|
|
|
|
listdef->app_data = (long)this;
|
|
|
|
XI_LIST_DEF* l = listdef->v.list;
|
|
l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font()) * lines_in_header;
|
|
l->sizable_columns = TRUE;
|
|
l->movable_columns = TRUE;
|
|
l->fixed_columns = fixed_columns;
|
|
l->max_lines_in_cell = lines_in_cell;
|
|
l->scroll_bar = TRUE;
|
|
l->scroll_bar_button = TRUE;
|
|
l->white_space_color = MASK_DARK_COLOR;
|
|
l->rule_color = MASK_DARK_COLOR;
|
|
|
|
if (_read_only)
|
|
l->single_select = TRUE;
|
|
else
|
|
l->active_back_color = FOCUS_BACK_COLOR;
|
|
|
|
// Definizione della prima colonna (numero di riga)
|
|
const long attr = XI_ATR_VISIBLE | XI_ATR_RJUST | XI_ATR_SELECTABLE;
|
|
XI_OBJ_DEF* coldef = xi_add_column_def(listdef, FIRST_FIELD+1000-1, attr, 0,
|
|
NUMBER_WIDTH * XI_FU_MULTIPLE, NUMBER_WIDTH , "");
|
|
|
|
coldef->app_data = (long)this;
|
|
XI_COLUMN_DEF* cd = coldef->v.column;
|
|
cd->heading_platform = TRUE;
|
|
cd->column_platform = TRUE;
|
|
|
|
for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++)
|
|
{
|
|
long attr = XI_ATR_VISIBLE | XI_ATR_ENABLED | XI_ATR_AUTOSCROLL;
|
|
if (_read_only)
|
|
attr |= XI_ATR_READONLY | XI_ATR_SELECTABLE;
|
|
if (_type[i] == 'R')
|
|
attr |= XI_ATR_RJUST;
|
|
coldef = xi_add_column_def(listdef, FIRST_FIELD+i+1000, attr, i+1,
|
|
v_width[i] * XI_FU_MULTIPLE, m_width[i], (char*)h);
|
|
|
|
coldef->app_data = (long)this;
|
|
cd = coldef->v.column;
|
|
cd->heading_platform = TRUE;
|
|
cd->center_heading = TRUE;
|
|
if (multi_line)
|
|
cd->wrap_text = _type[i] != 'R';
|
|
}
|
|
|
|
RCT rd; xi_get_def_rect(listdef, &rd);
|
|
if ((rd.right - rd.left) > (rct.right - rct.left))
|
|
l->width = rct.right - rct.left;
|
|
|
|
_obj = xi_create(itf, listdef); // Create the whole thing!
|
|
xi_dequeue(); // Flush events in XOL
|
|
xi_tree_free(listdef); // Free definitions
|
|
|
|
CHECKD(_obj, "Can't create list control ", cid);
|
|
update_tab_cid();
|
|
}
|
|
|
|
// Converts a record number in the correspondig row number
|
|
int TGrid_control::rec2row(long record) const
|
|
{
|
|
int rows;
|
|
const long* rec = xi_get_list_info(_obj, &rows);
|
|
int r = rows > 0 ? int(record - rec[0]) : -1;
|
|
if (r < 0 || r >= rows)
|
|
r = -1;
|
|
return r;
|
|
}
|
|
|
|
// Converts a row number in the correspondig record number
|
|
long TGrid_control::row2rec(int row) const
|
|
{
|
|
CHECK(row >= 0, "Negative grid row?");
|
|
|
|
int rows;
|
|
const long* handle = xi_get_list_info(_obj, &rows);
|
|
|
|
long rec;
|
|
if (rows > 0)
|
|
{
|
|
if (row >= rows)
|
|
rec = handle[rows-1] + row - rows + 1;
|
|
else
|
|
rec = handle[row];
|
|
}
|
|
else
|
|
rec = -1;
|
|
|
|
if (rec < 0 || rec >= items())
|
|
rec = -1;
|
|
|
|
return rec;
|
|
}
|
|
|
|
int TGrid_control::visible_rows() const
|
|
{
|
|
return xi_get_visible_rows(_obj, NULL, NULL);
|
|
}
|
|
|
|
bool TGrid_control::is_visible(long rec) const
|
|
{
|
|
int first, last;
|
|
xi_get_visible_rows(_obj, &first, &last);
|
|
|
|
int rows;
|
|
const long* handle = xi_get_list_info(_obj, &rows);
|
|
|
|
bool yes = rec >= handle[first] && rec <= handle[last];
|
|
return yes;
|
|
}
|
|
|
|
|
|
void TGrid_control::update(long n)
|
|
{
|
|
if (n >= 0)
|
|
{
|
|
const int riga = rec2row(n);
|
|
if (riga >= 0)
|
|
{
|
|
XI_OBJ row;
|
|
XI_MAKE_ROW(&row, _obj, riga);
|
|
xi_cell_request(&row);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int num = 0;
|
|
const long* handle = xi_get_list_info(_obj, &num);
|
|
|
|
bool scroll_first = items() == 0;
|
|
if (!scroll_first)
|
|
{
|
|
int first = 0, last = 0;
|
|
xi_get_visible_rows(_obj, &first, &last);
|
|
n = handle[first];
|
|
scroll_first = n > items();
|
|
}
|
|
|
|
if (scroll_first)
|
|
xi_scroll(_obj, XI_SCROLL_FIRST);
|
|
else
|
|
xi_scroll_rec(_obj, n, NORMAL_COLOR, XI_ATR_ENABLED, 0);
|
|
}
|
|
}
|
|
|
|
bool TGrid_control::select(long rec)
|
|
{
|
|
bool ok, sel;
|
|
if (rec >= 0)
|
|
{
|
|
ok = try_to_select(rec);
|
|
sel = ok;
|
|
}
|
|
else
|
|
{
|
|
ok = _cur_rec >= 0 && _cur_rec < items() && _grid->off_record(_cur_rec);
|
|
sel = FALSE;
|
|
}
|
|
|
|
if (ok)
|
|
{
|
|
if (sel)
|
|
{
|
|
int first, last;
|
|
xi_get_visible_rows(_obj, &first, &last);
|
|
// Controllo che la nuova riga sia completamente visibile
|
|
const int next_row = rec2row(rec);
|
|
if (next_row >= first && next_row <= last)
|
|
{
|
|
if (_read_only)
|
|
{
|
|
XI_OBJ riga; XI_MAKE_ROW(&riga, _obj, next_row);
|
|
long attr = xi_get_attrib(&riga);
|
|
attr |= XI_ATR_SELECTED;
|
|
xi_set_attrib(&riga, attr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long attr = XI_ATR_ENABLED;
|
|
if (_read_only)
|
|
attr |= XI_ATR_SELECTED;
|
|
xi_scroll_rec(_obj, rec, NORMAL_COLOR, attr, 0);
|
|
}
|
|
|
|
if (!_read_only)
|
|
{
|
|
const int next_row = rec2row(rec);
|
|
XI_OBJ cella; XI_MAKE_CELL(&cella, _obj, next_row, 1);
|
|
xi_set_focus(&cella);
|
|
}
|
|
} // end if (sel)
|
|
|
|
// Deseleziona record precedente se ancora visibile
|
|
if (_read_only)
|
|
{
|
|
const int cur_row = rec2row(_cur_rec);
|
|
if (cur_row >= 0)
|
|
{
|
|
XI_OBJ riga; XI_MAKE_ROW(&riga, _obj, cur_row);
|
|
long attr = xi_get_attrib(&riga);
|
|
attr &= ~XI_ATR_SELECTED;
|
|
xi_set_attrib(&riga, attr);
|
|
}
|
|
xi_dequeue();
|
|
}
|
|
|
|
if (rec < 0 || rec >= items())
|
|
rec = -1;
|
|
_cur_rec = rec;
|
|
} // end if (ok)
|
|
|
|
return ok;
|
|
}
|
|
|
|
short TGrid_control::col2cid(int pos) const
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
CHECKD(pos >= 0 && pos < num, "Bad column ", pos);
|
|
const short cid = column[pos]->cid - 1000;
|
|
return cid;
|
|
}
|
|
|
|
bool TGrid_control::try_to_select(long rec) const
|
|
{
|
|
bool ok = rec >= 0 && rec < items();
|
|
if (ok && rec != _cur_rec)
|
|
{
|
|
if (_cur_rec >= 0 && _cur_rec < items())
|
|
ok = _grid->off_record(_cur_rec);
|
|
if (ok)
|
|
ok = _grid->on_record(rec);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
void TGrid_control::update_selection(XI_EVENT* xiev)
|
|
{
|
|
const bool is_curr = xiev->v.rec_request.data_rec == _cur_rec;
|
|
if (_read_only)
|
|
{
|
|
if (is_curr)
|
|
xiev->v.rec_request.attrib |= XI_ATR_SELECTED;
|
|
else
|
|
xiev->v.rec_request.attrib &= ~XI_ATR_SELECTED;
|
|
}
|
|
else
|
|
xiev->v.rec_request.has_focus = is_curr;
|
|
}
|
|
|
|
// Certified 75%
|
|
bool TGrid_control::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
|
|
{
|
|
BOOLEAN& refused = xiev->refused;
|
|
|
|
const bool handled = _grid->handler(xiev);
|
|
if (handled)
|
|
return !refused;
|
|
|
|
switch (xiev->type)
|
|
{
|
|
case XIE_GET_FIRST:
|
|
if (items() > 0L)
|
|
{
|
|
long n = items() * (long)xiev->v.rec_request.percent / 100L;
|
|
if (n < 0L) n = 0L;
|
|
xiev->v.rec_request.data_rec = n;
|
|
update_selection(xiev);
|
|
}
|
|
else
|
|
refused = TRUE;
|
|
break;
|
|
case XIE_GET_LAST:
|
|
xiev->v.rec_request.data_rec = items()-1;
|
|
update_selection(xiev);
|
|
break;
|
|
case XIE_GET_PREV:
|
|
case XIE_GET_NEXT:
|
|
{
|
|
const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ;
|
|
if (n >= 0 && n < items())
|
|
{
|
|
xiev->v.rec_request.data_rec = n;
|
|
update_selection(xiev);
|
|
}
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
break;
|
|
case XIE_GET_PERCENT:
|
|
{
|
|
const long rec = xiev->v.get_percent.record;
|
|
long n = items(); if (n <= 0) n = 1;
|
|
xiev->v.get_percent.percent = short(rec * 100L / n);
|
|
}
|
|
break;
|
|
case XIE_COL_MOVE:
|
|
// Rifiuta di spostare una colonna nelle o dalle colonne fisse
|
|
if (xiev->v.column.in_fixed ||
|
|
xiev->v.column.col_nbr < xi_get_fixed_columns(xiev->v.column.list))
|
|
refused = TRUE;
|
|
break;
|
|
case XIE_COL_SIZE:
|
|
{
|
|
const short cid = col2cid(xiev->v.column.col_nbr);
|
|
refused = !_grid->on_resize_column(cid, xiev->v.column.new_col_width);
|
|
}
|
|
break;
|
|
case XIE_SELECT:
|
|
if (xiev->v.select.xi_obj->type == XIT_ROW) // Considero solo le righe
|
|
{
|
|
if (xiev->v.select.selected) // Sto selezionando
|
|
{
|
|
const long rec = row2rec(xiev->v.select.xi_obj->v.row_data.row);
|
|
if (try_to_select(rec))
|
|
{
|
|
if (xiev->v.select.column == 0)
|
|
{
|
|
_cur_rec = rec; // Assegno subito il record corrente
|
|
_grid->on_record_button(rec);
|
|
}
|
|
else
|
|
{
|
|
if (_read_only && rec == _cur_rec)
|
|
{
|
|
const short cid = col2cid(xiev->v.select.column);
|
|
_grid->on_dbl_cell(rec, cid);
|
|
}
|
|
_cur_rec = rec; // Assegno solo ora il record corrente
|
|
}
|
|
}
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case XIE_CELL_REQUEST:
|
|
{
|
|
const long& rec = xiev->v.cell_request.rec;
|
|
if (rec >= 0 && rec < items())
|
|
{
|
|
TGrid_cell cell(xiev);
|
|
const short cid = col2cid(cell.get_column());
|
|
if (cid >= FIRST_FIELD)
|
|
{
|
|
_grid->cell_request(rec, cid, cell);
|
|
}
|
|
else
|
|
{
|
|
if (cell.get_size() > 2)
|
|
cell.set(rec);
|
|
}
|
|
}
|
|
else
|
|
refused = TRUE; // Ogni tanto succede
|
|
}
|
|
break;
|
|
case XIE_ON_ROW:
|
|
{ // Qui ci passa solo se non e' _read_only
|
|
const long rec = row2rec(xiev->v.xi_obj->v.row);
|
|
if (rec >= 0)
|
|
{
|
|
if (_grid->on_record(rec))
|
|
_cur_rec = rec;
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
else
|
|
{
|
|
NFCHECK("You are entering an invalid row: %d", xiev->v.xi_obj->v.row);
|
|
refused = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case XIE_OFF_ROW:
|
|
// Qui ci passa solo se non e' _read_only
|
|
if (_cur_rec >= 0 && _cur_rec < items())
|
|
refused = !_grid->off_record(_cur_rec);
|
|
break;
|
|
case XIE_ON_CELL:
|
|
break;
|
|
case XIE_DBL_CELL:
|
|
{
|
|
const long rec = row2rec(xiev->v.xi_obj->v.cell.row);
|
|
if (try_to_select(rec))
|
|
{
|
|
const short cid = col2cid(xiev->v.xi_obj->v.cell.column);
|
|
_grid->on_dbl_cell(rec, cid);
|
|
}
|
|
}
|
|
break;
|
|
case XIE_BUTTON:
|
|
if (xiev->v.xi_obj->type == XIT_LIST)
|
|
{
|
|
_grid->on_grid_button();
|
|
}
|
|
else
|
|
{
|
|
const XI_CELL_DATA& cell = xiev->v.xi_obj->v.cell;
|
|
const long rec = row2rec(cell.row);
|
|
if (try_to_select(rec))
|
|
{
|
|
const short cid = col2cid(cell.column);
|
|
_grid->on_cell_button(rec, cid);
|
|
}
|
|
else
|
|
NFCHECK("You are clicking an invalid cell: %d", cell.row);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return !refused;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_cell
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Setta il testo di una cella (Mai piu' testo troppo lungo!)
|
|
// Se c'e' gia' un'icona la elimina
|
|
void TGrid_cell::set(const char* txt)
|
|
{
|
|
char* str = _xiev->v.cell_request.s;
|
|
if (txt)
|
|
{
|
|
const short& max = _xiev->v.cell_request.len;
|
|
strncpy(str, txt, max);
|
|
str[max-1] = '\0';
|
|
}
|
|
else
|
|
str[0] = '\0';
|
|
|
|
if (str[0])
|
|
{
|
|
int& icon = _xiev->v.cell_request.icon_rid;
|
|
if (icon)
|
|
icon = 0;
|
|
}
|
|
}
|
|
|
|
void TGrid_cell::set(long num)
|
|
{
|
|
char buff[16];
|
|
sprintf(buff, "%ld", num);
|
|
set(buff);
|
|
}
|
|
|
|
// Setta l'icona di una cella
|
|
// Se c'e' gia' un testo lo elimina
|
|
void TGrid_cell::set_icon(int id)
|
|
{
|
|
_xiev->v.cell_request.icon_rid = id;
|
|
if (id)
|
|
_xiev->v.cell_request.s[0] = '\0';
|
|
}
|
|
|
|
void TGrid_cell::show_button(bool on)
|
|
{
|
|
_xiev->v.cell_request.button = on;
|
|
_xiev->v.cell_request.button_on_focus = on;
|
|
}
|
|
|
|
void TGrid_cell::set_back_color(COLOR col)
|
|
{
|
|
if (col != NORMAL_BACK_COLOR)
|
|
_xiev->v.cell_request.back_color = col;
|
|
}
|
|
|
|
void TGrid_cell::set_fore_color(COLOR col)
|
|
{
|
|
if (col != NORMAL_COLOR)
|
|
_xiev->v.cell_request.color = col;
|
|
}
|
|
|
|
void TGrid_cell::set_colors(COLOR back, COLOR fore)
|
|
{
|
|
if (back != NORMAL_BACK_COLOR)
|
|
_xiev->v.cell_request.back_color = back;
|
|
if (fore != NORMAL_COLOR)
|
|
_xiev->v.cell_request.color = fore;
|
|
}
|
|
|
|
short TGrid_cell::get_column() const
|
|
{
|
|
return _xiev->v.cell_request.col_nbr;
|
|
}
|
|
|
|
short TGrid_cell::get_size() const
|
|
{
|
|
return _xiev->v.cell_request.len;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
void TGrid_field::update(long n)
|
|
{ grid().update(n); }
|
|
|
|
void TGrid_field::parse_head(TScanner& scanner)
|
|
{
|
|
_ctl_data._width = scanner.integer();
|
|
_ctl_data._height = scanner.integer();
|
|
if (_ctl_data._height == 0)
|
|
_ctl_data._height = -1;
|
|
}
|
|
|
|
void TGrid_field::create(WINDOW parent)
|
|
{
|
|
_ctl = new TGrid_control(parent, dlg(),
|
|
_ctl_data._x, _ctl_data._y,
|
|
_ctl_data._width, _ctl_data._height,
|
|
_ctl_data._flags, _ctl_data._park,
|
|
this);
|
|
}
|
|
|
|
bool TGrid_field::parse_item(TScanner& scanner)
|
|
{
|
|
if (scanner.key() == "IT")
|
|
{
|
|
_ctl_data._park.add(scanner.string());
|
|
return TRUE;
|
|
}
|
|
return TMask_field::parse_item(scanner);
|
|
}
|
|
|
|
|
|
bool TGrid_field::handler(XI_EVENT* xiev)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
long TGrid_field::items() const
|
|
{
|
|
return 100000L;
|
|
}
|
|
|
|
int TGrid_field::visible_rows() const
|
|
{
|
|
return grid().visible_rows();
|
|
}
|
|
|
|
void TGrid_field::cell_request(long rec, short id, TGrid_cell& cell)
|
|
{
|
|
cell.set("Cell");
|
|
}
|
|
|
|
long TGrid_field::selected() const
|
|
{ return grid().selected(); }
|
|
|
|
bool TGrid_field::select(long rec)
|
|
{ return grid().select(rec); }
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Da qui in poi e' tutta roba specializzata del programma
|
|
///////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Maschere per colori
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TRow_mask : public TMask
|
|
{
|
|
public:
|
|
virtual void update();
|
|
|
|
TRow_mask();
|
|
virtual ~TRow_mask() { }
|
|
};
|
|
|
|
class TColor_mask : public TVariable_mask
|
|
{
|
|
static TRow_mask* _sheet_mask;
|
|
static TMask* get_mask(int, TMask&) { return _sheet_mask; }
|
|
|
|
COLOR _mas_back, _mas_fore;
|
|
COLOR _con_back, _con_fore;
|
|
|
|
protected:
|
|
static bool color_handler(TMask_field& f, KEY k);
|
|
|
|
void type2colors(char tipo, COLOR& back, COLOR& fore) const;
|
|
|
|
public:
|
|
void get_cur_colors(COLOR& back, COLOR& fore) const;
|
|
void set_cur_colors(COLOR back, COLOR fore);
|
|
|
|
void get_colors(COLOR& mb, COLOR& mf, COLOR& cb, COLOR& cf) const;
|
|
|
|
TColor_mask(COLOR mb, COLOR mf, COLOR cb, COLOR cf);
|
|
virtual ~TColor_mask();
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TRow_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TRow_mask* TColor_mask::_sheet_mask = NULL;
|
|
|
|
TRow_mask::TRow_mask()
|
|
: TMask("cg2100k", 1)
|
|
{
|
|
}
|
|
|
|
void TRow_mask::update()
|
|
{
|
|
TSheet_field* s = get_sheet();
|
|
TColor_mask& m = (TColor_mask&)s->mask();
|
|
COLOR back, fore;
|
|
m.get_cur_colors(back, fore);
|
|
|
|
set_pen(COLOR_BLACK);
|
|
set_brush(back);
|
|
frame(2, 4, 16, 6, 0);
|
|
set_brush(fore);
|
|
frame(20, 4, 34, 6, 0);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TColor_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
void TColor_mask::type2colors(char tipo, COLOR& back, COLOR& fore) const
|
|
{
|
|
if (toupper(tipo) == 'M')
|
|
{
|
|
back = _mas_back;
|
|
fore = _mas_fore;
|
|
}
|
|
else
|
|
{
|
|
back = _con_back;
|
|
fore = _con_fore;
|
|
}
|
|
}
|
|
|
|
void TColor_mask::get_cur_colors(COLOR& back, COLOR& fore) const
|
|
{
|
|
TSheet_field& s = (TSheet_field&)fld(0);
|
|
TToken_string& row = s.row(s.selected());
|
|
const char tipo = row[5];
|
|
type2colors(tipo, back, fore);
|
|
}
|
|
|
|
void TColor_mask::set_cur_colors(COLOR back, COLOR fore)
|
|
{
|
|
TSheet_field& s = (TSheet_field&)fld(0);
|
|
const int cur = s.selected();
|
|
TToken_string& row = s.row(cur);
|
|
const char tipo = toupper(row[5]);
|
|
if (tipo == 'M')
|
|
{
|
|
_mas_back = back;
|
|
_mas_fore = fore;
|
|
}
|
|
else
|
|
{
|
|
_con_back = back;
|
|
_con_fore = fore;
|
|
}
|
|
s.set_back_and_fore_color(back, fore, cur);
|
|
s.force_update(cur);
|
|
}
|
|
|
|
bool TColor_mask::color_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TMask& m = f.mask();
|
|
TColor_mask& cm = (TColor_mask&)m.get_sheet()->mask();
|
|
|
|
COLOR back, fore;
|
|
cm.get_cur_colors(back, fore);
|
|
const bool use_back = f.dlg() == 100;
|
|
|
|
const COLOR col = choose_color(use_back ? back : fore, m.win());
|
|
if (col != COLOR_INVALID)
|
|
{
|
|
if (use_back)
|
|
back = col;
|
|
else
|
|
fore = col;
|
|
cm.set_cur_colors(back, fore);
|
|
cm._sheet_mask->update();
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void TColor_mask::get_colors(COLOR& mb, COLOR& mf, COLOR& cb, COLOR& cf) const
|
|
{
|
|
mb = _mas_back;
|
|
mf = _mas_fore;
|
|
cb = _con_back;
|
|
cf = _con_fore;
|
|
}
|
|
|
|
TColor_mask::TColor_mask(COLOR mb, COLOR mf, COLOR cb, COLOR cf)
|
|
: TVariable_mask("cg2100k"),
|
|
_mas_back(mb), _mas_fore(mf), _con_back(cb), _con_fore(cf)
|
|
{
|
|
CHECK(_sheet_mask == NULL, "One color at time, please");
|
|
_sheet_mask = new TRow_mask;
|
|
_sheet_mask->set_handler(99, color_handler);
|
|
_sheet_mask->set_handler(100, color_handler);
|
|
|
|
TVariable_sheet_field& s = (TVariable_sheet_field&)fld(0);
|
|
s.set_getmask(get_mask);
|
|
|
|
const char* const tipi = "MC";
|
|
int row = 0;
|
|
for (const char* c = tipi; *c; c++)
|
|
{
|
|
COLOR back, fore;
|
|
type2colors(*c, back, fore);
|
|
TToken_string& riga = s.row(-1);
|
|
riga << "Riga " << (*c == 'M' ? "mastrino" : "contropartita");
|
|
s.set_back_and_fore_color(back, fore, row++);
|
|
}
|
|
}
|
|
|
|
TColor_mask::~TColor_mask()
|
|
{
|
|
delete _sheet_mask;
|
|
_sheet_mask = NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TMastrini_grid
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TMastrini_grid : public TGrid_field
|
|
{
|
|
TMastrino _mastrino;
|
|
|
|
TDecoder _causali;
|
|
TEsercizi_contabili _esercizi;
|
|
|
|
COLOR _mas_back, _mas_fore;
|
|
COLOR _con_back, _con_fore;
|
|
|
|
protected: // TGrid_field
|
|
virtual bool on_record(long rec);
|
|
virtual void cell_request(long rec, short id, TGrid_cell& cell);
|
|
virtual void on_grid_button();
|
|
virtual bool on_resize_column(short id, int new_size);
|
|
virtual void on_dbl_cell(long rec, short id);
|
|
|
|
void update_mask() const;
|
|
|
|
public:
|
|
virtual void on_record_button(long rec);
|
|
virtual long items() const { return _mastrino.items(); }
|
|
|
|
void destroy();
|
|
void read(const TBill& conto,
|
|
int annoes, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac);
|
|
void reread();
|
|
|
|
TMastrino& mastrino() { return _mastrino; }
|
|
|
|
void save_colors();
|
|
void load_colors();
|
|
void set_colors();
|
|
|
|
TMastrini_grid(TMask* m);
|
|
virtual ~TMastrini_grid() { }
|
|
};
|
|
|
|
TMastrini_grid::TMastrini_grid(TMask* m)
|
|
: TGrid_field(m), _causali(LF_CAUSALI, CAU_CODCAUS, CAU_DESCR)
|
|
{
|
|
load_colors();
|
|
}
|
|
|
|
void TMastrini_grid::destroy()
|
|
{
|
|
_mastrino.destroy();
|
|
grid().select(-1);
|
|
}
|
|
|
|
HIDDEN void set_imp(TMask_field& f, const TImporto& imp)
|
|
{
|
|
if (!imp.is_zero())
|
|
{
|
|
TString80 str;
|
|
str = imp.valore().string(".");
|
|
str << ' ' << imp.sezione();
|
|
f.set(str);
|
|
}
|
|
}
|
|
|
|
void TMastrini_grid::cell_request(long rec, short id, TGrid_cell& cell)
|
|
{
|
|
const TRiga_mastrino& riga = _mastrino[rec];
|
|
|
|
switch (id)
|
|
{
|
|
case 101:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
TString80 text;
|
|
text = mov.get(MOV_DATAREG);
|
|
text << ' ' << mov.get(MOV_DATADOC);
|
|
cell.set(text);
|
|
}
|
|
break;
|
|
case 102:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
const int anno = _esercizi.date2esc(mov.get_date(MOV_DATAREG));
|
|
const int eser = mov.get_int(MOV_ANNOES);
|
|
const comp = anno == eser;
|
|
cell.set_icon(comp ? ICO_CHECK_ON : ICO_CHECK_OFF);
|
|
}
|
|
break;
|
|
case 103:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell.set(mov.get(MOV_DESCR));
|
|
}
|
|
else
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
const char* text = rmov.get(RMV_DESCR);
|
|
if (*text == '\0')
|
|
{
|
|
const TBill conto(rmov);
|
|
text = conto.descrizione();
|
|
}
|
|
cell.set(text);
|
|
}
|
|
break;
|
|
case 104:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell.set(_causali.decode(mov.get(MOV_CODCAUS)));
|
|
}
|
|
else
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
TString16 text;
|
|
text.format("%03d.%03d.%06ld",
|
|
rmov.get_int(RMV_GRUPPO),
|
|
rmov.get_int(RMV_CONTO),
|
|
rmov.get_long(RMV_SOTTOCONTO));
|
|
cell.set(text);
|
|
}
|
|
break;
|
|
case 105:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
if (rmov.get_char(RMV_SEZIONE) == 'D')
|
|
cell.set(rmov.get_real(RMV_IMPORTO).string("."));
|
|
}
|
|
break;
|
|
case 106:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
if (rmov.get_char(RMV_SEZIONE) == 'A')
|
|
cell.set(rmov.get_real(RMV_IMPORTO).string("."));
|
|
}
|
|
break;
|
|
case 107:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
TString80 text;
|
|
text = mov.get(MOV_NUMDOC); text.left_just(7);
|
|
text << ' ' << mov.get(MOV_PROTIVA);
|
|
cell.set(text);
|
|
}
|
|
break;
|
|
case 108:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
TString80 text;
|
|
text = rmov.get_real(RMV_IMPORTO).string(".");
|
|
text << ' ' << rmov.get(RMV_SEZIONE);
|
|
cell.set(text);
|
|
}
|
|
break;
|
|
case 109:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const long next_row = _mastrino.succ(rec, riga_mastrino);
|
|
bool stampa = next_row >= _mastrino.items();
|
|
if (!stampa)
|
|
{
|
|
const TDate& data = _mastrino[next_row].data();
|
|
stampa = riga.data() < data;
|
|
}
|
|
if (stampa)
|
|
{
|
|
TImporto imp = riga.saldo();
|
|
imp += _mastrino.saldo_iniziale();
|
|
imp.normalize();
|
|
TString80 text;
|
|
text = imp.valore().string(".");
|
|
text << ' ' << imp.sezione();
|
|
cell.set(text);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (riga.tipo() == riga_mastrino)
|
|
cell.set_colors(_mas_back, _mas_fore);
|
|
else
|
|
cell.set_colors(_con_back, _con_fore);
|
|
}
|
|
|
|
bool TMastrini_grid::on_record(long rec)
|
|
{
|
|
if (_mastrino[rec].tipo() != riga_mastrino)
|
|
rec = _mastrino.pred(rec, riga_mastrino);
|
|
|
|
TRiga_mastrino& riga = _mastrino[rec];
|
|
TMask& gm = mask();
|
|
set_imp(gm.field(F_TOTRIG_SAL), riga.saldo());
|
|
gm.set(F_TOTRIG_DAR, riga.dare());
|
|
gm.set(F_TOTRIG_AVE, riga.avere());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void TMastrini_grid::on_dbl_cell(long rec, short id)
|
|
{
|
|
if (_mastrino.expandable(rec))
|
|
_mastrino.expand(rec);
|
|
else
|
|
_mastrino.collapse(rec);
|
|
update();
|
|
}
|
|
|
|
void TMastrini_grid::on_grid_button()
|
|
{
|
|
begin_wait();
|
|
|
|
if (items() > 0)
|
|
{
|
|
long sample_rec = selected();
|
|
if (sample_rec < 0 || sample_rec >= items())
|
|
sample_rec = 0;
|
|
|
|
if (_mastrino.expandable(sample_rec))
|
|
{
|
|
for (long n = items()-1; n >= 0; n--)
|
|
if (_mastrino.expandable(n))
|
|
_mastrino.expand(n);
|
|
}
|
|
else
|
|
{
|
|
for (long n = 0; n < _mastrino.items(); n++)
|
|
if (_mastrino[n].tipo() != riga_mastrino)
|
|
_mastrino.collapse(--n);
|
|
}
|
|
update();
|
|
}
|
|
end_wait();
|
|
}
|
|
|
|
void TMastrini_grid::on_record_button(long rec)
|
|
{
|
|
begin_wait();
|
|
|
|
const TRectype& testata = _mastrino.testata(rec);
|
|
TString text;
|
|
text << "1|" << testata.get(MOV_NUMREG);
|
|
|
|
const char* const appname = "cg2 -0";
|
|
TMessage pn(appname, MSG_LN, text);
|
|
pn.send();
|
|
|
|
TExternal_app a(appname);
|
|
a.run();
|
|
|
|
TMailbox mail;
|
|
if (mail.next_s(MSG_LN) != NULL)
|
|
{
|
|
if (yesno_box("Si desidera aggiornare il mastrino?"))
|
|
reread();
|
|
}
|
|
|
|
end_wait();
|
|
}
|
|
|
|
bool TMastrini_grid::on_resize_column(short cid, int new_size)
|
|
{
|
|
return cid == 103 || cid == 104;
|
|
}
|
|
|
|
|
|
void TMastrini_grid::read(const TBill& conto,
|
|
int annoes, const TDate& dd, const TDate& ad,
|
|
const TString& dc, const TString& ac)
|
|
{
|
|
destroy();
|
|
_mastrino.read(conto, annoes, dd, ad, dc, ac);
|
|
update();
|
|
update_mask();
|
|
}
|
|
|
|
void TMastrini_grid::reread()
|
|
{
|
|
destroy();
|
|
_mastrino.reread();
|
|
update();
|
|
update_mask();
|
|
}
|
|
|
|
void TMastrini_grid::update_mask() const
|
|
{
|
|
TMask& gm = mask();
|
|
|
|
set_imp(gm.field(F_TOTPRO_SAL), _mastrino.saldo_iniziale());
|
|
gm.set(F_TOTPRO_DAR, _mastrino.progressivo_dare_iniziale());
|
|
gm.set(F_TOTPRO_AVE, _mastrino.progressivo_avere_iniziale());
|
|
|
|
gm.reset(F_TOTRIG_SAL);
|
|
gm.reset(F_TOTRIG_DAR);
|
|
gm.reset(F_TOTRIG_AVE);
|
|
|
|
set_imp(gm.field(F_TOTPER_SAL), _mastrino.saldo_periodo());
|
|
gm.set(F_TOTPER_DAR, _mastrino.progressivo_dare_periodo());
|
|
gm.set(F_TOTPER_AVE, _mastrino.progressivo_avere_periodo());
|
|
|
|
set_imp(gm.field(F_TOTATT_SAL), _mastrino.saldo_finale());
|
|
gm.set(F_TOTATT_DAR, _mastrino.progressivo_dare_finale());
|
|
gm.set(F_TOTATT_AVE, _mastrino.progressivo_avere_finale());
|
|
|
|
gm.enable(DLG_LINK, _mastrino.items() > 0);
|
|
}
|
|
|
|
void TMastrini_grid::load_colors()
|
|
{
|
|
TConfig conf(CONFIG_USER, "cg3600b");
|
|
_mas_back = conf.get_color("ColorMB", NULL, -1, FOCUS_BACK_COLOR);
|
|
_mas_fore = conf.get_color("ColorMF", NULL, -1, FOCUS_COLOR);
|
|
_con_back = conf.get_color("ColorCB", NULL, -1, NORMAL_BACK_COLOR);
|
|
_con_fore = conf.get_color("ColorCF", NULL, -1, NORMAL_COLOR);
|
|
}
|
|
|
|
void TMastrini_grid::save_colors()
|
|
{
|
|
TConfig conf(CONFIG_USER, "cg3600b");
|
|
conf.set_color("ColorMB", _mas_back);
|
|
conf.set_color("ColorMF", _mas_fore);
|
|
conf.set_color("ColorCB", _con_back);
|
|
conf.set_color("ColorCF", _con_fore);
|
|
}
|
|
|
|
void TMastrini_grid::set_colors()
|
|
{
|
|
TColor_mask m(_mas_back, _mas_fore, _con_back, _con_fore);
|
|
if (m.run() == K_ENTER)
|
|
{
|
|
m.get_colors(_mas_back, _mas_fore, _con_back, _con_fore);
|
|
save_colors();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TGrid_mask : public TMask
|
|
{
|
|
TMastrini_grid* _grid;
|
|
|
|
protected: // TMask
|
|
virtual TMask_field* parse_field(TScanner& sc);
|
|
virtual bool on_key(KEY k);
|
|
|
|
static bool link_handler(TMask_field& f, KEY k);
|
|
|
|
public:
|
|
TMastrini_grid& grid() { CHECK(_grid, "What's grid?"); return *_grid; }
|
|
|
|
TGrid_mask();
|
|
virtual ~TGrid_mask() { }
|
|
};
|
|
|
|
TGrid_mask::TGrid_mask()
|
|
: _grid(NULL)
|
|
{
|
|
read_mask("cg3600b", 0, 0);
|
|
set_handler(DLG_LINK, link_handler);
|
|
}
|
|
|
|
TMask_field* TGrid_mask::parse_field(TScanner& sc)
|
|
{
|
|
TMask_field* f;
|
|
if (sc.key() == "SP")
|
|
f = _grid = new TMastrini_grid(this);
|
|
else
|
|
f = TMask::parse_field(sc);
|
|
return f;
|
|
}
|
|
|
|
bool TGrid_mask::link_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TGrid_mask& gm = (TGrid_mask&)f.mask();
|
|
TMastrini_grid& grid = gm.grid();
|
|
const long rec = grid.selected();
|
|
if (rec >= 0 && rec < grid.items())
|
|
grid.on_record_button(rec);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TGrid_mask::on_key(KEY k)
|
|
{
|
|
long rec = grid().selected();
|
|
switch (k)
|
|
{
|
|
case K_LHOME:
|
|
rec = 0;
|
|
break;
|
|
case K_PREV:
|
|
rec -= _grid->visible_rows();
|
|
if (rec < 0) rec = 0;
|
|
break;
|
|
case K_UP:
|
|
if (rec > 0)
|
|
rec--;
|
|
break;
|
|
case K_DOWN:
|
|
if (rec < _grid->items()-1)
|
|
rec++;
|
|
break;
|
|
case K_NEXT:
|
|
rec += _grid->visible_rows();
|
|
if (rec >= _grid->items())
|
|
rec = _grid->items()-1;
|
|
break;
|
|
case K_LEND:
|
|
rec = _grid->items()-1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (rec != grid().selected())
|
|
{
|
|
grid().select(rec);
|
|
return TRUE;
|
|
}
|
|
|
|
return TMask::on_key(k);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TQuery_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TQuery_mask : public TMask
|
|
{
|
|
protected:
|
|
static bool data_handler(TMask_field& f, KEY k);
|
|
static bool find_handler(TMask_field& f, KEY k);
|
|
|
|
public:
|
|
void do_query(TGrid_mask& gm);
|
|
|
|
TQuery_mask();
|
|
virtual ~TQuery_mask() { }
|
|
};
|
|
|
|
TQuery_mask::TQuery_mask()
|
|
: TMask("cg3600a")
|
|
{
|
|
set_handler(F_DADATA, data_handler);
|
|
set_handler(F_ADATA, data_handler);
|
|
set_handler(DLG_FINDREC, find_handler);
|
|
}
|
|
|
|
bool TQuery_mask::data_handler(TMask_field& f, KEY k)
|
|
{
|
|
bool ok = TRUE;
|
|
if (f.to_check(k))
|
|
{
|
|
const TQuery_mask& qm = (const TQuery_mask&)f.mask();
|
|
const TEsercizi_contabili esercizi;
|
|
int codice_esercizio = qm.get_int(F_ESERCIZIO);
|
|
|
|
if (codice_esercizio == 0)
|
|
{
|
|
const short id_altra_data = f.dlg() == F_DADATA ? F_ADATA : F_DADATA;
|
|
const TDate d = qm.get(id_altra_data);
|
|
if (d.ok())
|
|
codice_esercizio = esercizi.date2esc(d);
|
|
}
|
|
|
|
if (f.empty())
|
|
{
|
|
if (codice_esercizio == 0)
|
|
return error_box("E' necessario specificare almeno una data.");
|
|
return TRUE;
|
|
}
|
|
|
|
const TDate d = f.get();
|
|
const int esercizio = esercizi.date2esc(d);
|
|
if (codice_esercizio != 0)
|
|
{
|
|
if (esercizio != codice_esercizio)
|
|
ok = error_box("La data deve appartenere all'esercizio %d", codice_esercizio);
|
|
}
|
|
else
|
|
{
|
|
if (esercizio == 0)
|
|
ok = error_box("La data deve appartenere ad un esercizio contabile");
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool TQuery_mask::find_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
const TQuery_mask& qm = (const TQuery_mask&)f.mask();
|
|
short id;
|
|
switch (qm.get(F_TIPO)[0])
|
|
{
|
|
case 'C': id = F_CLIENTE; break;
|
|
case 'F': id = F_FORNITORE; break;
|
|
default : id = F_SOTTOCONTO; break;
|
|
}
|
|
qm.field(id).on_key(K_F9);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void TQuery_mask::do_query(TGrid_mask& gm)
|
|
{
|
|
const char t = get(F_TIPO)[0];
|
|
const int g = get_int(F_GRUPPO);
|
|
const int c = get_int(F_CONTO);
|
|
const long s = get_long((t <= ' ') ? F_SOTTOCONTO : ((t == 'C') ? F_CLIENTE : F_FORNITORE));
|
|
|
|
const TBill conto(g, c, s, t);
|
|
|
|
const int annoes = get_int(F_ESERCIZIO);
|
|
|
|
TDate da_data(get(F_DADATA));
|
|
|
|
TDate a_data(get(F_ADATA));
|
|
|
|
TString da_caus(get(F_DACAUSALE));
|
|
|
|
TString a_caus(get(F_ACAUSALE));
|
|
|
|
conto.set(gm, F_GRUPPO, F_CONTO, F_SOTTOCONTO, 0, F_DESSOTTOC);
|
|
gm.set(F_ESERCIZIO, annoes);
|
|
gm.set(F_DADATA, da_data);
|
|
gm.set(F_ADATA, a_data);
|
|
gm.grid().read(conto, annoes, da_data, a_data, da_caus, a_caus);
|
|
|
|
gm.run();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TMastrini_video
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TMastrini_video : public TApplication
|
|
{
|
|
TQuery_mask* _qm;
|
|
TGrid_mask* _gm;
|
|
|
|
TArray _file;
|
|
|
|
protected:
|
|
virtual bool create();
|
|
virtual bool destroy();
|
|
virtual bool menu(MENU_TAG);
|
|
virtual void on_firm_change();
|
|
|
|
public:
|
|
void open_files(int logicnum, ...);
|
|
};
|
|
|
|
void TMastrini_video::open_files(int logicnum, ...)
|
|
{
|
|
va_list marker;
|
|
va_start(marker, logicnum);
|
|
while (logicnum > 0)
|
|
{
|
|
if (_file.objptr(logicnum))
|
|
NFCHECK("File gia' aperto: %d", logicnum);
|
|
else
|
|
_file.add(new TLocalisamfile(logicnum), logicnum);
|
|
logicnum = va_arg(marker, int);
|
|
}
|
|
}
|
|
|
|
bool TMastrini_video::create()
|
|
{
|
|
open_files(LF_RMOV, LF_MOV);
|
|
open_files(LF_SALDI, LF_PCON);
|
|
|
|
_qm = new TQuery_mask;
|
|
_gm = new TGrid_mask;
|
|
|
|
dispatch_e_menu(BAR_ITEM(1));
|
|
return TRUE;
|
|
}
|
|
|
|
bool TMastrini_video::destroy()
|
|
{
|
|
delete _gm;
|
|
delete _qm;
|
|
|
|
_file.destroy();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void TMastrini_video::on_firm_change()
|
|
{
|
|
TEsercizi_contabili::update();
|
|
}
|
|
|
|
bool TMastrini_video::menu(MENU_TAG mt)
|
|
{
|
|
if (mt == BAR_ITEM(1))
|
|
{
|
|
TQuery_mask& qm = *_qm;
|
|
|
|
const TEsercizi_contabili esercizi;
|
|
const int codice_ultimo_esercizio = esercizi.last();
|
|
if (codice_ultimo_esercizio > 0)
|
|
{
|
|
const TEsercizio& esercizio = esercizi.esercizio(codice_ultimo_esercizio);
|
|
qm.set(F_ESERCIZIO, codice_ultimo_esercizio);
|
|
qm.set(F_DADATA, esercizio.inizio());
|
|
qm.set(F_ADATA, esercizio.fine());
|
|
}
|
|
|
|
KEY key = 0;
|
|
while (key != K_QUIT)
|
|
{
|
|
qm.reset(F_SOTTOCONTO); // Azzera sottoconto
|
|
qm.reset(F_CLIENTE); // Azzera cliente
|
|
qm.reset(F_FORNITORE); // Azzera fornitore
|
|
qm.reset(F_DACAUSALE); // Azzera causali
|
|
qm.reset(F_ACAUSALE);
|
|
|
|
key = qm.run();
|
|
switch (key)
|
|
{
|
|
case K_ENTER:
|
|
disable_menu_item(M_FONT);
|
|
qm.do_query(*_gm);
|
|
enable_menu_item(M_FONT);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
_gm->grid().set_colors();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Main
|
|
///////////////////////////////////////////////////////////
|
|
|
|
int cg3600(int argc, char* argv[])
|
|
{
|
|
TMastrini_video mv;
|
|
mv.run(argc, argv, "Mastrini");
|
|
return 0;
|
|
}
|
|
|
|
|