cg3?00.cpp Promossi alcuni bool a int e tolti linkrecinst git-svn-id: svn://10.65.10.50/trunk@6462 c028cbd2-c16b-5b4b-a496-9718f37d4682
2942 lines
75 KiB
C++
Executable File
2942 lines
75 KiB
C++
Executable File
#include <xinclude.h>
|
|
|
|
#include <applicat.h>
|
|
#include <colors.h>
|
|
#include <controls.h>
|
|
#include <execp.h>
|
|
#include <mailbox.h>
|
|
#include <progind.h>
|
|
#include <recarray.h>
|
|
#include <relation.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
#include <varmask.h>
|
|
|
|
#include "cg3.h"
|
|
#include "cglib01.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;
|
|
|
|
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 change_step(long step); // Forza il passo per gli elementi
|
|
long 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
long TList::choose_step(long expected_size)
|
|
{
|
|
long step = expected_size / MAX_SKIP + 1;
|
|
if (step < 8)
|
|
step = 8;
|
|
change_step(step);
|
|
return 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;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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, bool ignora_movap = FALSE);
|
|
void read(const TBill& b, int esercizio, bool ignora_movap = FALSE);
|
|
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, bool ignora_movap = FALSE);
|
|
TBalance(const TBill& b, int esercizio, bool ignora_movap = FALSE);
|
|
virtual ~TBalance() { }
|
|
};
|
|
|
|
TBalance::TBalance()
|
|
{
|
|
}
|
|
|
|
TBalance::TBalance(int g, int c, long s, int esercizio, bool ignora_movap)
|
|
{
|
|
read(g, c, s, esercizio, ignora_movap);
|
|
}
|
|
|
|
TBalance::TBalance(const TBill& b, int esercizio, bool ignora_movap)
|
|
{
|
|
read(b, esercizio, ignora_movap);
|
|
}
|
|
|
|
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, bool ignora_movap)
|
|
{
|
|
const TBill zio(gruppo, conto, sottoconto);
|
|
read(zio, esercizio, ignora_movap);
|
|
}
|
|
|
|
void TBalance::read(const TBill& b, int esercizio, bool ignora_movap)
|
|
{
|
|
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 (precedente > 0 && find(b, precedente, si, pd, pa, sf))
|
|
{
|
|
_saldo_ini = si;
|
|
_saldo_ini += pd;
|
|
_saldo_ini += pa;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ignora_movap)
|
|
_saldo_ini.set('D', ZERO);
|
|
}
|
|
}
|
|
|
|
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; // Tipo della riga
|
|
TRecnotype _mov, _rmov; // Numero fisico di record movivento e riga movimento
|
|
real _dare, _avere; // Progressivi dare ed avere
|
|
TDate _data; // Data di registrazione (Ottimizzazione)
|
|
|
|
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; // Dare-Avere normalizzato
|
|
|
|
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 TCursor* _cur;
|
|
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:
|
|
TCursor& cur() { return *_cur; }
|
|
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(); }
|
|
|
|
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;
|
|
|
|
int esercizio() const { return _esercizio; }
|
|
const TDate& inizio_periodo() const { return _da_data; }
|
|
const TDate& fine_periodo() const { return _a_data; }
|
|
void periodo(TDate& dd, TDate& ad) const { dd = _da_data; ad = _a_data; }
|
|
|
|
bool expandable(long rec) const;
|
|
bool expand(long rec);
|
|
bool collapse(long rec);
|
|
|
|
TMastrino();
|
|
virtual ~TMastrino();
|
|
};
|
|
|
|
long TMastrino::_instances = 0L;
|
|
TCursor* TMastrino::_cur = NULL;
|
|
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");
|
|
_cur = new TCursor(_rel);
|
|
_rmov = &_rel->lfile();
|
|
_mov = &_rel->lfile(LF_MOV);
|
|
}
|
|
_instances++;
|
|
}
|
|
|
|
TMastrino::~TMastrino()
|
|
{
|
|
_instances--;
|
|
if (_instances == 0L)
|
|
{
|
|
delete _cur; _cur = NULL;
|
|
delete _rel; _rel = NULL;
|
|
_rmov = _mov = NULL;
|
|
}
|
|
}
|
|
|
|
long TMastrino::succ(long rec, tipo_riga_mastrino tipo) const
|
|
{
|
|
if (rec < 0) rec = -1;
|
|
|
|
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
|
|
{
|
|
if (rec > items()) rec = items();
|
|
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();
|
|
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();
|
|
|
|
const bool test_caus = !(dc.blank() && ac.blank());
|
|
_da_caus = dc;
|
|
_a_caus = ac.blank() ? "zzz" : ac; // Se vuota sceglie la massima causale
|
|
|
|
TDate max_data_reg = _a_data;
|
|
long num_giorni = _a_data - inizio_esercizio + 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();
|
|
}
|
|
|
|
TString caption(80);
|
|
caption.format("Caricamento mastrino %03d.%03d.%06ld",
|
|
_conto.gruppo(), _conto.conto(), _conto.sottoconto());
|
|
TProgind pi(num_giorni, caption, FALSE, TRUE, 48);
|
|
|
|
// Stima dimensione mastrino
|
|
_riga.choose_step(num_giorni);
|
|
|
|
// 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
|
|
|
|
TBalance saldo(_conto, ae, TRUE);
|
|
_pdare_ini = saldo.progressivo_dare_iniziale();
|
|
_pavere_ini = saldo.progressivo_avere_iniziale();
|
|
|
|
// Valori dei saldi finali:
|
|
// Comprendono i movimenti di apertura, chiusura ed i progressivi attuali
|
|
saldo.read(_conto, ae, FALSE);
|
|
_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;
|
|
|
|
rmov_rec.zero();
|
|
conto.put(rmov_rec);
|
|
rmov_rec.put(RMV_DATAREG, inizio_esercizio);
|
|
|
|
const TRecfield rmov_datareg (rmov_rec, RMV_DATAREG);
|
|
const TRecfield rmov_numreg (rmov_rec, RMV_NUMREG);
|
|
const TRecfield rmov_gruppo (rmov_rec, RMV_GRUPPO);
|
|
const TRecfield rmov_conto (rmov_rec, RMV_CONTO);
|
|
const TRecfield rmov_sottoconto(rmov_rec, RMV_SOTTOCONTO);
|
|
const TRecfield rmov_sezione (rmov_rec, RMV_SEZIONE);
|
|
const TRecfield rmov_importo (rmov_rec, RMV_IMPORTO);
|
|
|
|
const TRecfield mov_datacomp (mov_rec, MOV_DATACOMP);
|
|
const TRecfield mov_provvis (mov_rec, MOV_PROVVIS);
|
|
const TRecfield mov_codcaus (mov_rec, MOV_CODCAUS);
|
|
|
|
#ifdef DBG
|
|
long num_rec = 0;
|
|
const clock_t clock_start = clock();
|
|
#endif
|
|
|
|
TDate ultimo_giorno; // memorizza ultima data registrazione utilizzata
|
|
|
|
for (int err = rel().read(_isgteq); err == NOERR; err = rel().next())
|
|
{
|
|
// Controlla di non aver superato la data limite
|
|
const TDate data_reg((const char*)rmov_datareg);
|
|
if (data_reg > max_data_reg)
|
|
break;
|
|
|
|
// Controlla che il conto sia ancora quello selezionato
|
|
if (_conto.sottoconto() != long(rmov_sottoconto) ||
|
|
_conto.conto() != int(rmov_conto) ||
|
|
_conto.gruppo() != int(rmov_gruppo))
|
|
break;
|
|
|
|
#ifdef DBG
|
|
num_rec++;
|
|
if ((num_rec & 0x7F) == 0)
|
|
{
|
|
const double sec = (clock() - clock_start) / CLOCKS_PER_SEC;
|
|
if (sec > 0.0)
|
|
{
|
|
TString80 msg;
|
|
msg.format("%ld records at %ld rec/sec", num_rec, long(num_rec/sec));
|
|
pi.set_text(msg);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Ignora i movimenti provvisori
|
|
const char provvis = *(const char*)mov_provvis;
|
|
if (provvis > ' ')
|
|
continue;
|
|
|
|
const TDate data_corrente = _esercizio <= 0 ? data_reg : TDate((const char*)mov_datacomp);
|
|
if (data_corrente > _a_data)
|
|
continue;
|
|
|
|
// Aggiorna la barra solo una volta al giorno
|
|
if (data_reg > ultimo_giorno)
|
|
{
|
|
const long giorno = data_reg - inizio_esercizio + 1;
|
|
pi.setstatus(giorno);
|
|
ultimo_giorno = data_reg;
|
|
}
|
|
|
|
const char sezione = *((const char*)rmov_sezione);
|
|
const real importo((const char*)rmov_importo);
|
|
|
|
if (data_corrente < _da_data)
|
|
{
|
|
if (data_corrente >= inizio_esercizio)
|
|
{
|
|
if (sezione == 'D')
|
|
_pdare_ini += importo;
|
|
else
|
|
_pavere_ini += importo;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sezione == 'D')
|
|
_pdare_per += importo;
|
|
else
|
|
_pavere_per += importo;
|
|
|
|
// Controlla che la causale sia nei limiti
|
|
if (test_caus)
|
|
{
|
|
const bool ok = _da_caus <= mov_codcaus && _a_caus >= mov_codcaus;
|
|
if (!ok)
|
|
continue;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// Genera le righe di contropartita di una riga del mastrino
|
|
bool TMastrino::expand(long rec)
|
|
{
|
|
bool ok = expandable(rec);
|
|
if (ok)
|
|
{
|
|
const TRectype& head = testata(rec); // Testata movimento
|
|
const long numreg = head.get_long(RMV_NUMREG); // Numero di registrazione
|
|
const int numrig = riga(rec).get_int(RMV_NUMRIG); // Numero riga contabile
|
|
const TDate datareg = head.get(MOV_DATAREG); // Data di registrazione
|
|
|
|
rmov().setkey(1); // Usa chiave NUMREG+NUMRIG
|
|
TRectype& curr = rmov().curr(); // Record corrente
|
|
|
|
const TRecfield rnumreg (curr, RMV_NUMREG); // Numero di registrazione corrente
|
|
const TRecfield rnumrig (curr, RMV_NUMRIG); // Numero di riga corrente
|
|
const TRecfield rsezione(curr, RMV_SEZIONE); // Sezione Dare/Avere
|
|
const TRecfield rimporto(curr, RMV_IMPORTO); // Importo della riga
|
|
|
|
int err = NOERR;
|
|
if (numrig != 1) // Se non e' gia' posizionato grazie a riga(rec)
|
|
{
|
|
curr.zero(); // Azzera record corrente
|
|
curr.put(RMV_NUMREG, numreg); // Inizializza la chiave parziale
|
|
err = rmov().read(_isgteq); // Cerca la prima riga del movimento
|
|
}
|
|
for (; err == NOERR; err = rmov().next()) // Scandisce righe movimento
|
|
{
|
|
if (numreg != (long)rnumreg) // Controlla validita' numero
|
|
break;
|
|
|
|
if (numrig != (int)rnumrig) // Ignora la riga gia' presente
|
|
{
|
|
real dare, avere; // Costruisce importo della riga
|
|
if (*(const char*)rsezione == 'D')
|
|
dare = rimporto;
|
|
else
|
|
avere = rimporto;
|
|
// Aggiunge una riga di contropartita al mastrino
|
|
TRiga_mastrino* r = new TRiga_mastrino(riga_contropartita,
|
|
rmov().recno(), mov().recno(),
|
|
dare, avere, datareg);
|
|
_riga.append(r, rec++);
|
|
}
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
// Elimina le righe di contropartita di una riga del mastrino
|
|
bool TMastrino::collapse(long rec)
|
|
{
|
|
bool ok = TRUE; // Posso eliminare?
|
|
if (row(rec).tipo() != riga_mastrino) // Se non sono su una riga mastrino ...
|
|
rec = pred(rec, riga_mastrino); // ... mi sposto sulla precedente riga mastrino
|
|
else
|
|
ok = !expandable(rec); // Controlla che sia possibile
|
|
|
|
if (ok) // Posso effetivamente procedere
|
|
{
|
|
rec++; // Elimino ogni riga contropartita successiva
|
|
while (rec < items() && row(rec).tipo() != riga_mastrino)
|
|
_riga.remove(rec);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_control
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TGrid_control;
|
|
|
|
|
|
class TGrid_cell : public TFixed_string
|
|
{
|
|
XI_EVENT* _xiev;
|
|
|
|
public:
|
|
TString& set(const char* txt);
|
|
TString& 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 { return _xiev->v.cell_request.col_nbr; }
|
|
|
|
TString& operator = (const char* str) { return set(str); }
|
|
TString& operator = (const TString& str) { return set(str); }
|
|
|
|
TGrid_cell(XI_EVENT* 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);
|
|
virtual word class_id() const;
|
|
|
|
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);
|
|
|
|
void reset_columns_order();
|
|
void save_columns_order() const;
|
|
|
|
TGrid_field(TMask* 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;
|
|
|
|
int _default_width[MAX_COL];
|
|
int _columns_order;
|
|
|
|
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);
|
|
|
|
void set_columns_order(TToken_string* order);
|
|
|
|
XI_OBJ* find_column(short cid) const;
|
|
XI_OBJ* find_column(const char* head) const;
|
|
|
|
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;
|
|
|
|
void load_columns_order();
|
|
void save_columns_order() const;
|
|
void reset_columns_order() { set_columns_order(NULL); }
|
|
|
|
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), _columns_order(0)
|
|
{
|
|
_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 'A':
|
|
auto_num = TRUE;
|
|
break;
|
|
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
|
|
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;
|
|
#ifdef XI_R4
|
|
l->min_heading_height = xi_button_calc_height_font(xi_get_system_font()) * lines_in_header;
|
|
#else
|
|
l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font()) * lines_in_header;
|
|
#endif
|
|
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, (XinRect*)&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();
|
|
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
RCT rct; xi_get_rect(column[i], (XinRect*)&rct);
|
|
_default_width[i] = rct.right - rct.left;
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
else
|
|
_columns_order = 1;
|
|
break;
|
|
case XIE_COL_SIZE:
|
|
{
|
|
const short cid = col2cid(xiev->v.column.col_nbr);
|
|
if (_grid->on_resize_column(cid, xiev->v.column.new_col_width))
|
|
_columns_order = 1;
|
|
else
|
|
refused = TRUE;
|
|
}
|
|
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)
|
|
{
|
|
#ifndef XI_R4
|
|
_cur_rec = rec; // Assegno subito il record corrente
|
|
_grid->on_record_button(rec);
|
|
#endif
|
|
}
|
|
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.size() > 2)
|
|
{
|
|
cell.set(rec+1);
|
|
// Setto il colore del testo altrimenti verrebbe grigio:
|
|
// non uso la set_color perche' ignora NORMAL_COLOR
|
|
xiev->v.cell_request.color = NORMAL_COLOR;
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
XI_OBJ* TGrid_control::find_column(short cid) const
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
for (int i = num-1; i >= 0; i--)
|
|
{
|
|
if (column[i]->cid == cid)
|
|
break;
|
|
}
|
|
return i >= 0 ? column[i] : NULL;
|
|
}
|
|
|
|
XI_OBJ* TGrid_control::find_column(const char* head) const
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
|
|
TString80 text;
|
|
for (int i = num-1; i >= 0; i--)
|
|
{
|
|
xi_get_text(column[i], text.get_buffer(), text.size());
|
|
if (text == head)
|
|
break;
|
|
}
|
|
return i >= 0 ? column[i] : NULL;
|
|
}
|
|
|
|
void TGrid_control::set_columns_order(TToken_string* order)
|
|
{
|
|
XI_OBJ* itf = get_interface();
|
|
XI_OBJ* focus = xi_get_focus(itf);
|
|
xi_set_focus(itf);
|
|
|
|
int num_cols;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num_cols);
|
|
|
|
// Costante da sottrarre nella xi_column_set_pixel_width altrimenti la somma due volte!
|
|
const int offset = 2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
|
|
const int fixed = xi_get_fixed_columns(_obj);
|
|
if (fixed > 1)
|
|
xi_set_fixed_columns(_obj, 1);
|
|
|
|
if (order == NULL)
|
|
{
|
|
for (int index = 1; index < num_cols; index++)
|
|
{
|
|
const short cid = FIRST_FIELD + 1000 + index - 1;
|
|
XI_OBJ* col = find_column(cid);
|
|
if (col)
|
|
{
|
|
xi_move_column(col, index);
|
|
RCT rct; xi_get_rect(col, (XinRect*)&rct);
|
|
if (_default_width[index] != rct.right - rct.left)
|
|
xi_column_set_pixel_width(col, _default_width[index]-offset);
|
|
}
|
|
}
|
|
_columns_order = 0x3;
|
|
}
|
|
else
|
|
{
|
|
TToken_string col(8, ',');
|
|
int pos = 0;
|
|
for (col = order->get(0); !col.blank(); col = order->get(), pos++)
|
|
{
|
|
const char* head = esc(col.get(0));
|
|
const int width = col.get_int();
|
|
XI_OBJ* column = find_column(head);
|
|
if (column) // Controlla che esista ancora
|
|
{
|
|
if (pos > 0 && pos < num_cols)
|
|
xi_move_column(column, pos); // Sposta la colonna se possibile
|
|
if (width > XI_FU_MULTIPLE) // Se ha una larghezza valida
|
|
xi_column_set_pixel_width(column, width - offset);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fixed > 1)
|
|
xi_set_fixed_columns(_obj, fixed);
|
|
|
|
if (focus)
|
|
xi_set_focus(focus);
|
|
}
|
|
|
|
HIDDEN TFilename& field2parag(const TMask_field& f, TFilename& name)
|
|
{
|
|
const TMask& m = f.mask();
|
|
name = m.source_file();
|
|
name.ext(""); // Nome della maschera senza estensione
|
|
const int index = m.number();
|
|
CHECKD(index >= 0 && index <= 8, "Bad mask index:", index);
|
|
if (index > 0) // Aggiunge l'eventuale numero di sotto-maschera
|
|
name << '(' << index << ')';
|
|
return name;
|
|
}
|
|
|
|
void TGrid_control::load_columns_order()
|
|
{
|
|
TFilename parag; field2parag(*_grid, parag);
|
|
TConfig config(CONFIG_USER, parag);
|
|
TToken_string order = config.get("Browse", NULL, id());
|
|
if (order.empty_items())
|
|
config.remove("Browse", id());
|
|
else
|
|
set_columns_order(&order);
|
|
_columns_order = 0;
|
|
}
|
|
|
|
void TGrid_control::save_columns_order() const
|
|
{
|
|
if (_columns_order)
|
|
{
|
|
TFilename parag; field2parag(*_grid, parag);
|
|
TConfig config(CONFIG_USER, parag); // Apre il file di configurazione
|
|
|
|
TToken_string order(127); // Nuovo ordine delle colonne
|
|
if (_columns_order == 1) // Se vale 3 devo solo resettare
|
|
{
|
|
int num;
|
|
XI_OBJ** column = xi_get_member_list(_obj, &num);
|
|
TString80 head;
|
|
for (int i = 0; i < num; i++) // Scorre tutte le colonne
|
|
{
|
|
xi_get_text(column[i], head.get_buffer(), head.size());
|
|
const int acapo = head.find('\n');
|
|
if (acapo > 0)
|
|
{
|
|
head[acapo] = '\\';
|
|
head.insert("n", acapo+1);
|
|
}
|
|
order.add(head);
|
|
RCT rct; xi_get_rect(column[i], (XinRect*)&rct);
|
|
order << ',' << rct.right - rct.left;
|
|
}
|
|
config.set("Browse", order, NULL, TRUE, id());
|
|
}
|
|
else
|
|
config.remove("Browse", id());
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_cell
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TGrid_cell::TGrid_cell(XI_EVENT* xiev)
|
|
: TFixed_string(xiev->v.cell_request.s, xiev->v.cell_request.len),
|
|
_xiev(xiev)
|
|
{ }
|
|
|
|
|
|
// Setta il testo di una cella (Mai piu' testo troppo lungo!)
|
|
// Se c'e' gia' un'icona la elimina
|
|
TString& TGrid_cell::set(const char* txt)
|
|
{
|
|
strncpy(txt, size());
|
|
if (not_empty())
|
|
{
|
|
int& icon = _xiev->v.cell_request.icon_rid;
|
|
if (icon)
|
|
icon = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
TString& TGrid_cell::set(long num)
|
|
{
|
|
char buff[16];
|
|
sprintf(buff, "%ld", num);
|
|
return 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;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TGrid_field
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TGrid_field::TGrid_field(TMask* m)
|
|
: TOperable_field(m)
|
|
{ }
|
|
|
|
word TGrid_field::class_id() const
|
|
{
|
|
return CLASS_GRID_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);
|
|
grid().load_columns_order();
|
|
}
|
|
|
|
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); }
|
|
|
|
void TGrid_field::reset_columns_order()
|
|
{
|
|
grid().reset_columns_order();
|
|
}
|
|
|
|
void TGrid_field::save_columns_order() const
|
|
{
|
|
grid().save_columns_order();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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);
|
|
static bool reset_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);
|
|
|
|
_pixmap = TRUE;
|
|
set_pen(COLOR_BLACK);
|
|
|
|
RCT rct; field(100).get_rect(rct);
|
|
set_brush(back);
|
|
frame(rct.left, 2*rct.top - rct.bottom - CHARY/2, rct.right, rct.top - CHARY/2, 0);
|
|
|
|
field(99).get_rect(rct);
|
|
set_brush(fore);
|
|
frame(rct.left, 2*rct.top - rct.bottom - CHARY/2, rct.right, rct.top - CHARY/2, 0);
|
|
|
|
_pixmap = FALSE;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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();
|
|
m.set_focus();
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TColor_mask::reset_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE && f.yesno_box("Si desidera azzerare tutti i colori?"))
|
|
{
|
|
TColor_mask& m = (TColor_mask&) f.mask();
|
|
|
|
m._mas_back = NORMAL_BACK_COLOR;
|
|
m._mas_fore = NORMAL_COLOR;
|
|
m._con_back = NORMAL_BACK_COLOR;
|
|
m._con_fore = NORMAL_COLOR;
|
|
TSheet_field& s = (TSheet_field&)f.mask().field(101);
|
|
s.set_back_and_fore_color(NORMAL_BACK_COLOR, NORMAL_COLOR, -1);
|
|
s.force_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)
|
|
{
|
|
set_handler(102, reset_handler);
|
|
set_caption("Colori delle righe mastrini");
|
|
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);
|
|
|
|
void update_mask() const;
|
|
|
|
public:
|
|
virtual void on_dbl_cell(long rec, short id);
|
|
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_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.format("%s %c", imp.valore().string("."), imp.sezione());
|
|
f.set(str);
|
|
}
|
|
else
|
|
f.reset();
|
|
}
|
|
|
|
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);
|
|
cell = riga.data().string();
|
|
cell << ' ' << mov.get(MOV_DATADOC);
|
|
}
|
|
break;
|
|
case 102:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
const int anno = _esercizi.date2esc(riga.data());
|
|
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(_causali.decode(mov.get(MOV_CODCAUS)));
|
|
}
|
|
else
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell.format("%03d.%03d.%06ld",
|
|
rmov.get_int(RMV_GRUPPO),
|
|
rmov.get_int(RMV_CONTO),
|
|
rmov.get_long(RMV_SOTTOCONTO));
|
|
}
|
|
break;
|
|
case 104:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell.set(mov.get(MOV_DESCR));
|
|
if (cell.empty())
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell.set(rmov.get(RMV_DESCR));
|
|
if (cell.empty())
|
|
{
|
|
TBill uncle(rmov,TRUE);
|
|
cell.set(uncle.descrizione());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell.set(rmov.get(RMV_DESCR));
|
|
if (cell.empty())
|
|
{
|
|
const TBill conto(rmov);
|
|
cell.set(conto.descrizione());
|
|
}
|
|
}
|
|
break;
|
|
case 105:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
if (rmov.get_char(RMV_SEZIONE) == 'D')
|
|
cell = rmov.get_real(RMV_IMPORTO).string(".");
|
|
}
|
|
break;
|
|
case 106:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
if (rmov.get_char(RMV_SEZIONE) == 'A')
|
|
cell = rmov.get_real(RMV_IMPORTO).string(".");
|
|
}
|
|
break;
|
|
case 107:
|
|
if (riga.tipo() == riga_mastrino)
|
|
{
|
|
const TRectype& mov = _mastrino.testata(rec);
|
|
cell = mov.get(MOV_NUMDOC); cell.left_just(7);
|
|
cell << ' ' << mov.get(MOV_PROTIVA);
|
|
}
|
|
break;
|
|
case 108:
|
|
{
|
|
const TRectype& rmov = _mastrino.riga(rec);
|
|
cell = rmov.get_real(RMV_IMPORTO).string(".");
|
|
cell << ' ' << rmov.get(RMV_SEZIONE);
|
|
}
|
|
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();
|
|
cell = imp.valore().string(".");
|
|
cell << ' ' << imp.sezione();
|
|
}
|
|
}
|
|
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()
|
|
{
|
|
const long total = _mastrino.items();
|
|
if (total > 0)
|
|
{
|
|
TProgind* pi = NULL;
|
|
|
|
if (total > 50)
|
|
pi = new TProgind(total, "Aggiornamento contropartite ...", FALSE, TRUE, 48);
|
|
else
|
|
begin_wait();
|
|
|
|
// Cerca l'ultima contropartita
|
|
const long last_con = _mastrino.last(riga_contropartita);
|
|
// Se non esistono contropartite devo espandere le righe
|
|
const bool expand = last_con < 0;
|
|
|
|
#ifdef DBG
|
|
const clock_t clock_start = clock();
|
|
#endif
|
|
|
|
if (expand)
|
|
{
|
|
long step = 0;
|
|
for (long n = _mastrino.first(riga_mastrino);
|
|
n < _mastrino.items(); n = _mastrino.succ(n, riga_mastrino))
|
|
{
|
|
if (_mastrino.expandable(n))
|
|
_mastrino.expand(n);
|
|
if (pi)
|
|
{
|
|
pi->setstatus(++step);
|
|
#ifdef DBG
|
|
if ((step & 0x7F) == 0)
|
|
{
|
|
const double sec = (clock() - clock_start) / CLOCKS_PER_SEC;
|
|
if (sec > 0.0)
|
|
{
|
|
TString80 msg;
|
|
msg.format("%ld records at %ld rec/sec", step, long(step/sec));
|
|
pi->set_text(msg);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (long n = last_con; n > 0; n = _mastrino.pred(n, riga_contropartita))
|
|
{
|
|
_mastrino.collapse(n);
|
|
if (pi)
|
|
pi->setstatus(total - n + 1);
|
|
}
|
|
}
|
|
|
|
if (pi)
|
|
delete pi;
|
|
else
|
|
end_wait();
|
|
|
|
update();
|
|
}
|
|
}
|
|
|
|
void TMastrini_grid::on_record_button(long rec)
|
|
{
|
|
TWait_cursor hourglass;
|
|
|
|
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();
|
|
mask().set_focus();
|
|
|
|
TMailbox mail;
|
|
if (mail.next_s(MSG_LN) != NULL)
|
|
{
|
|
if (yesno_box("Si desidera aggiornare il mastrino?"))
|
|
reread();
|
|
}
|
|
}
|
|
|
|
// Posso ridimensionare solo le descrizioni, le altre devono rimanere fisse per
|
|
// non perdere la formattazione su due righe
|
|
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();
|
|
|
|
gm.set(F_ESERCIZIO, _mastrino.esercizio());
|
|
gm.set(F_DADATA, _mastrino.inizio_periodo());
|
|
gm.set(F_ADATA, _mastrino.fine_periodo());
|
|
|
|
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);
|
|
virtual void handler(WINDOW win, EVENT* ep);
|
|
|
|
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;
|
|
case K_ENTER:
|
|
case K_CTRL+'+':
|
|
case K_CTRL+'-':
|
|
if (focus_field().dlg() == _grid->dlg())
|
|
_grid->on_dbl_cell(rec, DLG_USER);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (rec != grid().selected())
|
|
{
|
|
grid().select(rec);
|
|
return TRUE;
|
|
}
|
|
|
|
return TMask::on_key(k);
|
|
}
|
|
|
|
void TGrid_mask::handler(WINDOW win, EVENT* ep)
|
|
{
|
|
static TGrid_field* _last_grid = NULL;
|
|
|
|
if (ep->type == E_MOUSE_DOWN && ep->v.mouse.button == 1)
|
|
{
|
|
_last_grid = NULL;
|
|
|
|
RCT rct; _grid->get_rect(rct);
|
|
if (xvt_rect_has_point(&rct, ep->v.mouse.where))
|
|
_last_grid = _grid;
|
|
|
|
if (_last_grid)
|
|
{
|
|
TGrid_field& sht = (TGrid_field&)*_last_grid;
|
|
#if (XVT_PTK_VERSION_MAJOR > 4) || (XVT_PTK_VERSION_MAJOR == 4 && XVT_PTK_VERSION_MINOR >= 50)
|
|
MENU_ITEM* menu = xvt_res_get_menu(BROWSE_BAR);
|
|
if (menu)
|
|
{
|
|
const PNT& p = ep->v.mouse.where;
|
|
RCT cr; xvt_vobj_get_client_rect(win, &cr);
|
|
XVT_POPUP_ALIGNMENT pa = XVT_POPUP_CENTER;
|
|
if (p.h < cr.right / 3)
|
|
pa = XVT_POPUP_LEFT_ALIGN;
|
|
else
|
|
if (p.h > 2 * cr.right / 3)
|
|
pa = XVT_POPUP_RIGHT_ALIGN;
|
|
|
|
xvt_menu_popup(menu->child, win, p, pa, NULL);
|
|
xvt_res_free_menu_tree(menu);
|
|
}
|
|
#else
|
|
ASK_RESPONSE r = xvt_dm_post_ask("Annulla", "Ripristina", "Salva",
|
|
"Ordinamento delle colonne");
|
|
if (r == RESP_2)
|
|
sht.reset_columns_order();
|
|
if (r == RESP_2 || r == RESP_3)
|
|
sht.save_columns_order();
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
if (ep->type == E_COMMAND)
|
|
{
|
|
if (_last_grid)
|
|
{
|
|
switch (ep->v.cmd.tag)
|
|
{
|
|
case M_EDIT_UNDO:
|
|
_last_grid->reset_columns_order();
|
|
case M_EDIT_COPY:
|
|
_last_grid->save_columns_order();
|
|
break;
|
|
case M_EDIT_SEARCH:
|
|
_last_grid->on_key(K_F11);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
TMask::handler(win, ep);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TQuery_mask
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TQuery_mask : public TMask
|
|
{
|
|
protected:
|
|
static bool esercizio_handler(TMask_field& f, KEY k);
|
|
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_ESERCIZIO, esercizio_handler);
|
|
set_handler(F_DADATA, data_handler);
|
|
set_handler(F_ADATA, data_handler);
|
|
set_handler(DLG_FINDREC, find_handler);
|
|
}
|
|
|
|
bool TQuery_mask::esercizio_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_TAB && f.focusdirty())
|
|
{
|
|
TEsercizi_contabili esc;
|
|
const int anno = atoi(f.get());
|
|
if (esc.exist(anno))
|
|
{
|
|
TMask& m = f.mask();
|
|
TDate dd = m.get(F_DADATA);
|
|
if (esc.date2esc(dd) != anno)
|
|
m.set(F_DADATA, esc[anno].inizio());
|
|
dd = m.get(F_ADATA);
|
|
if (esc.date2esc(dd) != anno)
|
|
m.set(F_ADATA, esc[anno].fine());
|
|
}
|
|
else
|
|
{
|
|
if (anno > 0)
|
|
return error_box("Esercizio inesistente: %d", anno);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TQuery_mask::data_handler(TMask_field& f, KEY k)
|
|
{
|
|
bool ok = TRUE;
|
|
if (k == K_ENTER)
|
|
{
|
|
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);
|
|
const TDate da_data(get(F_DADATA));
|
|
const TDate a_data(get(F_ADATA));
|
|
|
|
const TString& da_caus = get(F_DACAUSALE);
|
|
const TString& a_caus = get(F_ACAUSALE);
|
|
|
|
conto.set(gm, F_GRUPPO, F_CONTO, F_SOTTOCONTO, 0, F_DESSOTTOC);
|
|
|
|
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);
|
|
}
|
|
va_end(marker);
|
|
}
|
|
|
|
bool TMastrini_video::create()
|
|
{
|
|
xvt_statbar_set("", TRUE);
|
|
|
|
open_files(LF_RMOV, LF_MOV, LF_CAUSALI, 0);
|
|
open_files(LF_SALDI, LF_PCON, 0);
|
|
|
|
_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(-5); // Azzera causali
|
|
|
|
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;
|
|
}
|
|
|
|
|