campo-sirio/include/printapp.cpp
guy 81534d006f Patch level : 10.0
Files correlati     : tutti
Ricompilazione Demo : [ ]
Commento            :
0001213: mappa di login, fuoco
Lla mappa di login si apre ma per poter digitare la password bisogna cliccare sul campo col mouse. Stesso problema richiamando le ricerche, per esempio quella clienti.


git-svn-id: svn://10.65.10.50/trunk@18591 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-03-23 15:16:49 +00:00

1641 lines
45 KiB
C++
Executable File
Raw Blame History

//#include <ctype.h>
//#include <stdarg.h>
//#include <currency.h>
#include <tabutil.h>
#include <printapp.h>
#include <progind.h>
#include <urldefid.h>
#include <utility.h>
const char* const printf_types = "dDiIuUoOxXfeEgGcCnNsSpPrRtTaAvV";
// _FieldTok flags
const word LONG_FLAG = 0x0001;
const word PICTURE_FLAG = 0x0002;
const word PAD_FLAG = 0x0004;
const word ALIGN_FLAG = 0x0008;
const word TRANS_FLAG = 0x0010;
const word DATE_FLAG = 0x0020;
const word STRING_FLAG = 0x0040;
const word NUMBER_FLAG = 0x0080;
const word DEC_FLAG = 0x0100;
const word FONT_FLAG = 0x0200;
const word JUMP_FLAG = 0x0400;
const word RECNO_FLAG = 0x0800;
const word BOOLEAN_FLAG = 0x1000;
const word IGNORE_FILL = 0x2000;
const word VALUTA_FLAG = 0x4000;
///////////////////////////////////////////////////////////
// print token containers
///////////////////////////////////////////////////////////
class _Transfield : public TObject
{
friend class TPrint_application;
int _lognum; // logical number
TString16 _fn;
TString _from, _to;
public:
_Transfield (int l, const char *fn, const char *from, const char *to) :
_lognum(l), _fn(fn), _from (from), _to (to)
{ }
virtual ~_Transfield() { }
};
class _Token : public TObject
{
friend class TPrint_application;
int _tag;
int _row;
public:
int tag() const { return _tag; }
int row() const { return _row; }
void tag(int t) { _tag = t; }
void row (int r) { _row = r; }
virtual ~ _Token () {}
};
class _PrintfTok : public _Token
// something to be printed (actually already printed on _val)
{
friend class TPrint_application;
TString _val;
public:
_PrintfTok (int rw, const char *val) : _val(val)
{ tag(0); row(rw); }
virtual ~_PrintfTok () {}
};
class _FieldTok : public _Token
// something more complex to be printed
{
friend class TPrint_application;
int _size, _dec;
char _align;
TString80 _fld; // field description
word _flags; // all you need to know
public:
_FieldTok (int rw, const char *fld, word flags, char align = 'l',
int size = -1, int dec = -1)
{
tag(1);
row(rw);
_fld = fld;
_flags = flags;
_size = size;
_align = align;
_dec = dec;
}
virtual ~_FieldTok () { }
};
class _PrintfRef : public _Token
// to be printed by reference via format
// must pass valid pointer to object
{
friend class TPrint_application;
void *_what;
char _type;
TString _fmt;
public:
_PrintfRef (int rw, const char *fmt, char type, void *what):_fmt (1)
{
tag (2);
row (rw);
_type = type;
_what = what;
_fmt = fmt;
_fmt[0] = '%';
}
virtual ~ _PrintfRef () {}
};
class _PrintRowToken : public _Token
// printrow direct
// must pass valid printrow (duplicated)
{
friend class TPrint_application;
TPrintrow _pr;
public:
TPrintrow& printrow() { return _pr; }
_PrintRowToken (int rw, TPrintrow& pr) : _pr((const TPrintrow&)pr)
{ tag(3); row(rw); }
virtual ~ _PrintRowToken () {}
};
void TPrint_application::_reset_tree(link_item * head)
{
if (head)
{
if (head->_brother)
_reset_tree (head->_brother);
if (head->_son)
_reset_tree (head->_son);
delete head;
}
}
// @doc INTERNAL
// @mfunc Cerca per il nodo <p head> dove agganciarsi per rispettare la relazione
//
// @rdesc Ritorna il nodo a cui agganciarsi
link_item *TPrint_application::_look_print_node (
link_item * head, // @parm Nodo per cui effettuare la ricerca
int logicnum) // @parm Numero logico del file
// @comm E' necessario che non esistano piu' nodi per lo stesso file/alias, altrimenti la
// la ricerca termina alla proma occorrenza incontrata
{
link_item *s;
while (head)
{
if (head->_logicnum == logicnum)
return head;
else if (head->_son)
if ((s = _look_print_node (head->_son, logicnum)) != NULL)
return s;
head = head->_brother;
}
return NULL;
}
// @doc EXTERNAL
// @mfunc Setta un segnalibro nell'anteprima di stampa
//
// @rdesc Ritorna il numero identificatore il segnalibro creato
int TPrint_application::set_bookmark(
const char* txt, // @parm Testo del segnalibro
int father) // @parm Identificatore del segnalibro padre (default -1)
// @comm L'aggiunta dei segnalibri causa la comparsa del menu 'Indice' nella viswin,
// con la lista dei segnalibri inseriti; questi possono essere legati ad albero n-ario
// specificando il bookmark padre, in tal caso il menu sara' gerarchico a sua volta.
// <nl>Nella prossima release di XVT il menu indice sara' pop-up nella finestra
{
return printer().set_bookmark(txt, father);
}
void TPrint_application::add_file (const char *tab, int from)
{
add_file(TTable::name2log(tab), from);
}
// @doc EXTERNAL
// @mfunc Aggiunge un file del cursore nell'albero di stampa
void TPrint_application::add_file (
int file, // @parm Numero logico del file da aggiungere
int from) // @parm Posizione nell'albero di stampa nel quale aggiungere il file
// @parm const char* | tab | Nome del del file da aggiungere
// @syntax add_file(int file, int from = 0);
// @syntax add_file(const char* tab, int from = 0);
{
link_item *nw = new link_item (file);
if (_pr_tree == NULL)
{
_pr_tree = nw;
return;
}
if (from == 0)
from = _pr_tree->_logicnum;
link_item *fr = _look_print_node (_pr_tree, from);
CHECKD (fr, "add_file: nonexistent node: logicnum = ", from);
if (fr->_son)
{
fr = fr->_son;
while (fr->_brother)
fr = fr->_brother;
fr->_brother = nw;
}
else
fr->_son = nw;
}
// ---------------------------------------------------------------
// ------------ user function ------------------------------------
// @doc EXTERNAL
// @mfunc Permette di trovare un link ipertestuale
//
// @rdesc Ritorna l'ID del link ipertestuale trovato (-1 se non viene trovato)
int TPrint_application::find_link(
const char* descr) const // @parm Testo del link da trovare
// @xref <mf TPrint_application::enable_link>
{
const TArray& arr = printer().links();
for (int i = 0; i < arr.items(); i++)
{
TToken_string& tt = (TToken_string&)arr[i];
const TFixed_string d(tt.get(0));
if (d == descr)
return i;
}
return -1;
}
// @doc EXTERNAL
// @mfunc Permette di abilitare determinati colori come indicatori di legame ipertestuale
//
// @rdesc Ritorna l'ID del link ipertestuale di cui sono stati abilitati i colori
int TPrint_application::enable_link(
const char *descr, // @parm Testo del link da abilitare
char fg, // @parm Colore del carattere
char bg) // @parm Colore dello sfondo (default 'w')
// @comm Quando si vogliono abilitare determinati colori come indicatori di legame ipertestuale,
// si faccia enable_link nella create. L' ID ritornato viene passato a process_link
// assieme al testo selezionato.
{
int lnk = find_link(descr);
if (lnk < 0)
{
TToken_string *tt = new TToken_string(30);
char b[2] = { '\0', '\0' };
tt->add(descr);
b[0] = fg;
tt->add(b);
b[0] = bg;
tt->add(b);
lnk = printer().links().add(tt);
}
return lnk;
}
void TPrint_application::disable_link (char fg, char bg)
{
for (int i = 0; i < printer().links().items (); i++)
{
TToken_string & t = (TToken_string&)printer().links()[i];
const char f = *(t.get(1));
const char b = *(t.get());
if (f == fg && b == bg)
{
printer().links().remove(i, TRUE);
break;
}
}
}
// @doc EXTERNAL
// @mfunc Abilita/disabilita pi<70> link per la <mf TPrint_application::enable_link>
void TPrint_application::set_multiple_link (
bool on) // @parm Indica se effettuare il link con tutti gli elementi selezioanti della riga
// @comm Se si setta <p on> a TRUE anziche' la descrizione del testo selezionato
// viene passata a <mf TPrint_application::enable_link> una tokenstring con tutti i
// 'bottoni' dello stesso colore presenti sulla riga.
{
printer().setmultiplelink (on);
}
bool TPrint_application::_pp_link (int id, const char *text)
{
TPrint_application& prapp = (TPrint_application&)main_app();
return prapp.process_link(id, text);
}
void TPrint_application::_pp_header (TPrinter& p)
{
TPrint_application& prapp = (TPrint_application&)main_app();
prapp.preprocess_header();
p.resetheader();
const int ii = prapp._header.last();
// reset and add header/footer lines
for (int i = 0; i <= ii; i++)
{
TPrintrow* pr = (TPrintrow*)prapp._header.objptr(i);
if (pr) p.setheaderline (i, new TPrintrow(*pr));
}
}
void TPrint_application::_pp_footer (TPrinter& p)
{
TPrint_application& prapp = (TPrint_application&)main_app();
prapp.preprocess_footer ();
p.resetfooter ();
int ii = prapp._footer.last();
for (int i = 0; i <= ii; i++)
{
TPrintrow* pr = (TPrintrow*)prapp._footer.objptr(i);
if (pr) p.setfooterline (i, new TPrintrow(*pr));
}
}
// @doc EXTERNAL
// @mfunc Permette di stampare sullo sfondo e per variarne gli attributi
void TPrint_application::set_background (
const char *bgdesc) // @parm Stringa contente i codici per la stampa (vedi descrizione)
// @comm Occorre passare una stringa che contiene codici per stampare box, linee, bitmap
// sullo sfondo, e per variarne gli attributi: se NULL lo azzera.
// <nl>Il background e' stampato sia su <c TViswin> che su stampante, e riguarda
// una PAGINA fisica e non le righe o le "pages" relative al cursore;
// viene replicato ad ogni nuova pagina fisica a meno che non venga cancellato
// o ridefinito in una <lt>qualcosa<gt>process<lt>qualcos'altro<gt>().
// <nl><nl>CODICI BACKGROUND
// <nl>Una stringa con n codici, opzionalmente separati da spazi o tab
// <nl>SETTINGS
// @flag P<lt>n<gt> | Setta pen style (n = codice XVT)
// @flag B<lt>n<gt> | Setta brush style (idem)
// @flag W<lt>n<gt> | Altezza della linea in pixel
// @flag C<lt>n<gt> | Colore della penna (codice colore solito)
// @comm <nl><nl> DRAWING COMMANDS
// @flag i{string,x1,y1,x2,y2} | Disegna la bitmap <p string> (nome file) alle coordinate indicate
// @flag l{x1,y1,x2,y2} | Linea da/a (la resa delle oblique dipende dalla stampante)
// @flag b{x1,y1,x2,y2} | Box
// @flag r{x1,y1,x2,y2} | Rounded box
// @flag t{text,x,y} | Testo <lt>text<gt> a <p x>, <p y>
{
printer().setbackground (bgdesc);
}
const char* FLD (int lognum, const char *f, int from, int to)
{
TString80 tb; tb.format("%c|%d|%s|%d|%d", 'n', lognum, f, from, to);
return _strdup(tb);
}
const char* FLD (int lognum, const char *f, const char *picture)
{
TString80 tb; tb.format("%c|%d|%s|%s", 'p', lognum, f, picture);
return _strdup(tb);
}
const char* FLD (const char *tabname, const char *f, int from, int to)
{
CHECKS (strlen (tabname) < 5, "Invalid table name", tabname);
const int lognum = TTable::name2log (tabname);
TString80 tb; tb.format("%c|%d|%s|%d|%d", 'n', lognum, f, from, to);
return _strdup(tb);
}
const char* FLD (const char *tabname, const char *f, const char *picture)
{
CHECKS (strlen(tabname) <= 4, "Invalid table name", tabname);
const int lognum = TTable::name2log(tabname);
TString80 tb; tb.format("%c|%d|%s|%s", 'p', lognum, f, picture);
return _strdup(tb);
}
TString& fill_str (TString & t, char f)
{
const int len = t.len();
int kk;
for (kk = len - 1; kk >= 0; kk--)
if (t[kk] == ' ') t[kk] = f;
else break;
for (kk = 0; kk < len; kk++)
if (t[kk] == ' ') t[kk] = f;
else break;
return t;
}
///////////////////////////////////////////////////////////
// Printapp code at last
///////////////////////////////////////////////////////////
void TPrint_application::select_cursor (int c)
{
if (c < 0) _cur = NULL;
else _cur = (TCursor *) & _cursors[c];
}
TCursor* TPrint_application::get_cursor (int c)
{
if (c < 0) return NULL;
else return (TCursor *) & _cursors[c];
}
// @doc EXTERNAL
// @mfunc Aggiunge un cursore alla classe
//
// @rdesc Ritorna l'identificatore del cursore aggiunto
int TPrint_application::add_cursor (
TCursor * c) // @parm Cursore da aggiungere all'albero
// @comm Nel caso sia passato NULL a <p c> non viene utilizzato nessun file, ma la
// <mf TPirnt_application::print_one> viene chaiamta e le iterazione sono valoutate da
// pre_ e post_ process.
{
if (c == NULL)
return -1;
_cursors.add (c);
_cur = c;
return _cursors.items() - 1;
}
void TPrint_application::reset_row (int r)
{
r--;
int tmp = _rows.items ();
for (int j = 0; j < tmp; j++)
{
_Token *t = (_Token *) (_rows.objptr (j));
if (t)
{
if (t->row () == r)
_rows.add (NULL, j);
}
}
_rows.pack ();
if (_maxrow == r && _maxrow > 0)
_maxrow--;
}
void TPrint_application::reset_print ()
{
_rows.destroy ();
_maxrow = 0;
_print_defined = FALSE;
}
// @doc EXTERNAL
// @mfunc Permette di definire l'header della stampa
void TPrint_application::set_header (
int r, // @parm Numero della riga nella quale stampare l'header
const char *fmt, // @parm Testo dell'header da stampare
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
{
TString256 tmp;
CHECK (r >= 1, "Header rows start at 1");
va_list vl;
va_start (vl, fmt);
vsprintf (tmp.get_buffer(), fmt, vl);
va_end (vl);
TPrintrow *pp = (TPrintrow *)_header.objptr(r - 1);
if (!pp)
{
pp = new TPrintrow;
_header.add (pp, r - 1);
}
pp->put (tmp);
}
// @doc EXTERNAL
// @mfunc Permette di definire il footer della stampa
void TPrint_application::set_footer (
int r, // @parm Numero della riga nella quale stampare il footer
const char *fmt, // @parm Testo del footer da stampare
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
{
CHECK (r >= 1, "Footer rows start at 1");
TString256 tmp;
va_list vl;
va_start (vl, fmt);
vsprintf (tmp.get_buffer(), fmt, vl);
va_end (vl);
TPrintrow *pp = (TPrintrow *) _footer.objptr (r - 1);
if (pp == NULL)
{
pp = new TPrintrow;
_footer.add (pp, r - 1);
}
pp->put (tmp);
}
void TPrint_application::reset_header ()
{
_header.destroy ();
printer().resetheader ();
}
void TPrint_application::reset_footer ()
{
_footer.destroy ();
printer().resetfooter ();
}
void TPrint_application::fill_page (int from)
{
from--;
for (int i = (from == -1 ? _maxrow : from); i <= printer().formlen (); i++)
{
reset_row (i);
set_row (i, "");
}
}
void TPrint_application::merge_export_file(const char* file, bool header, bool direct)
{
if (direct) printer().merge_export_file(file, header);
else
{
set_row(_currow+1,"");
TTextfile txt(file);
for (long i = 0l; i < txt.lines(); i++)
set_row(_currow+(int)i+1 + (i == 0l ? 1 : 0), txt.line_formatted(i));
}
}
void TPrint_application::set_row(int r, TPrintrow& pr)
{
CHECK (r >= 1, "Print rows start at 1");
_print_defined = TRUE;
_currow = --r;
if (_currow > _maxrow)
_maxrow = _currow;
_rows.add(new _PrintRowToken(_currow, pr));
}
// @doc EXTERNAL
// @mfunc Permette di settare una riga di stampa
void TPrint_application::set_row (
int r, // @parm Numero della riga da settare
const char *frmt, // @parm Contenuto della riga da stampare
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p frmt>
// @comm COME SETTARE LE RIGHE DI STAMPA
// <nl><nl>Questa funzione si usa come una printf per settare le righe di stampa
// che vengono stampate da <mf TPrint_application::print>.
// <nl>I codici per gli argomenti variabili sono di 3 tipi:
// @flag @ | Si usa per stampare campi di database o informazioni di controllo
// posizione carrello e font
// ATTENZIONE: i codici di formato sono diversi da quelli di printf e
// sono elencati sotto. Per i campi di database occorre che il codice
// sia accoppiato ad una delle funzioni <f FLD> passata come argomento;
// questa provoca la stampa di campi della relazione corrente,
// posizionata come e' stato deciso nell'inizializzazione
// @flag % | Si usa esattamente come in una printf con un plus: se il codice di
// formato e' maiuscolo (es. S per stringa, D per intero) viene
// ignorato il carattere di riempimento eventualmente specificato
// con <mf TPrint_application::set_fillchar>. Cio' vale anche per i codici @ (vedi)
// <nl>E' possibile usare due codici aggiuntivi: r(R) e t(T). A questi
// va fatto seguire un PUNTATORE a <c real> o a <c TString>. Il formato
// viene interpretato con le stesse regole di %t in dsprintf per real
// (come %d o %f) e di %s per TString. Il puntatore NON
// viene memorizzato; per questo occorre il codice # (sotto).
// @flag # | Si usa come % (stessi codici di printf) ma memorizza gli argomenti
// per riferimento: ovvero, ogni volta che la riga viene stampata
// viene stampato il contenuto in quel momento (che si puo' cambiare
// in una delle pre- o post- process). Cio' implica che:
// 1) gli argomenti vanno passati per RIFERIMENTO (set_row(1,"#5d",&i))
// 2) i puntatori devono rimanere validi e costanti tra la set_row e
// la fine della stampa
// Quindi, attenzione a %s con <c TString> ridimensionate; si possono
// usare solo se predimensionate alla dimensione massima, ma e' meglio
// usare char* o il codice apposito. I codici #r, #a e #t prendono puntatori a
// real, <c TParagraph_string> e a <c TString>, memorizzandoli. Non ci sono problemi con la resize.
// Comunque, il modo corretto di adoperare il codice # e'
// usarlo solo per stampare MEMBRI della classe derivata da TPrint_application
//
// @comm <nl><nl>CODICI DI CAMPO (da utilizzare con una delle funzione <f FLD>):
// @flag @@ | Carattere @
// @flag @[n[,{l<pipe>c<pipe>r}]s | STRING: n = pad, lcr = alignment
// @flag @{[n[.d=0]]<pipe>[n[,{l<pipe>c<pipe>r}]]p}n | NUMBER: n = digits, d = decimals
// p = picture string (first matching arg)
// @flag @[l]d | DATE: l = full year
// @flag @f | BOOL: prints si/no
// @flag @[n,{l<pipe>c<pipe>r}]t | Translated field (must set translation)
//
// @comm Tutti questi codici possono essere usati anche maiuscoli, il che inibisce
// l'uso del carattere di riempimento (set_fillchar) per uno specifico campo.
//
// <nl><nl>Per tutti i codici che riguardano la stampa di <c real> (@n, %r, #r)
// se non vengono date ulteriori specifiche di formato viene usata
// una picture che e' "" per default, ma puo' essere modificata con
// <mf TPint_application::set_real_picture>.
// <nl>Normalmente un real uguale a zero viene stampato come stringa vuota
// a meno che non si specifichi TRUE nella <mf TPrint_application::set_print_zero>.
//
// <nl><nl>CODICI POSIZIONAMENTO E MOVIMENTO CARRELLO
// @flag @<lt>n<gt>g | Vai a posizione n
// @flag @<lt>n<gt>j | Salta di n posizioni (in orizzontale)
// @comm <nl><nl>CODICI STILE
// @flag @b | Grassetto
// @flag @i | Corsivo
// @flag @u | Sottolineato
// @flag @r | Ritorna allo stile normale
//
// @comm <nl><nl>CODICI COLORE PER VISUALIZZAZIONE E COLLEGAMENTO
//
// <nl><nl>Se si vuole che in visualizzazione il testo sia colorato
// si usa il codice $[]; tra le quadre si scrive il colore
// di foreground, opzionalmente seguito da una virgola e dal
// colore di background (bianco per default). I colori si
// specificano con un singolo carattere come segue:
// @flag n | Nero
// @flag g | Verde
// @flag b | Blu
// @flag c | Cyan
// @flag y | Giallo
// @flag v | Magenta
// @flag m | Colore background maschere (azzurrotto)
// @flag d | Grigio scuro
// @flag l | Grigio chiaro
// @flag k | Grigio normale
//
// @comm <nl><nl>Se si fa <mf TPrint_application::enable_link> con un certo colore, tutto
// cio che e' scritto in quel colore diventa selezionabile
// e alla sua selezione (premendo 'Collega') si puo' associare
// un'azione in <mf TPrint_application::process_link>. A quest'ultima viene passata
// l'ID ritornata da enable_link() e il testo selezionato alla
// pressione di Collega. Vedere ba6 e stampare l'elenco (con
// Includi ditte abilitato) per un esempio.
{
CHECK (r >= 1, "Print rows start at 1");
r--;
char digbuf[10];
TString bigbuf(256);
char* strbuf = bigbuf.get_buffer();
// let the poor programmer use format() at will
const TString fftt(frmt);
char fill = _fillchar;
word flags = 0;
int size = 0, dec = 0, strind = 0;
char ch, align = 'l';
_print_defined = TRUE;
_currow = r;
if (_currow > _maxrow)
_maxrow = _currow;
va_list params;
va_start(params, frmt);
// parse format string
const char* fmt = fftt;
while ((ch = *fmt++) != '\0')
{
if (ch == '@')
{
// check for pending string
if (strind)
{
strbuf[strind] = '\0';
_rows.add (new _PrintfTok (_currow, strbuf));
strind = 0;
}
ch = *fmt++;
if (isdigit (ch))
{
int i = 0;
digbuf[i++] = ch;
while (isdigit (ch = *fmt++))
digbuf[i++] = ch;
digbuf[i] = '\0';
size = atoi (digbuf);
flags |= PAD_FLAG;
if (ch == '.')
{
// decimal size follows
i = 0;
digbuf[i++] = ch;
while (isdigit (ch = *fmt++))
digbuf[i] = ch;
digbuf[i] = '\0';
dec = atoi (digbuf);
flags |= DEC_FLAG;
}
else if (ch == ',')
{
// aligment spec follows
align = (ch = *fmt++);
CHECK (ch == 'l' || ch == 'r' || ch == 'c',
"TPrint_application::set_row: invalid alignment spec");
flags |= ALIGN_FLAG;
ch = *fmt++;
}
}
switch (ch)
{
// modifiers
case 'l':
case 'L':
flags |= LONG_FLAG;
ch = *fmt++;
break;
case 'p':
case 'P':
flags |= PICTURE_FLAG;
ch = *fmt++;
break;
}
switch (ch)
{
// codes
case '@':
_rows.add (new _PrintfTok (_currow, "@"));
break;
case 'b':
case 'i':
case 'u':
case 'r':
{
char x[2] = { ch, '\0' };
_rows.add (new _FieldTok (_currow, x, FONT_FLAG));
}
break;
case 'g':
case 'j':
{
const char* x = format ("%c %d", ch, size);
_rows.add (new _FieldTok (_currow, x, JUMP_FLAG));
}
break;
case 'T':
flags |= IGNORE_FILL;
// fall down
case 't':
flags |= TRANS_FLAG;
break;
case 'D':
flags |= IGNORE_FILL;
// fall down
case 'd':
flags |= DATE_FLAG;
break;
case 'F':
flags |= IGNORE_FILL;
// fall down
case 'f':
flags |= BOOLEAN_FLAG;
break;
case 'S':
flags |= IGNORE_FILL;
// fall down
case 's':
flags |= STRING_FLAG;
break;
case 'C':
flags |= IGNORE_FILL;
// fall down
case 'c':
flags |= RECNO_FLAG;
break;
case 'N':
flags |= IGNORE_FILL;
// fall down
case 'n':
if (_magic_currency)
{
if (size >= 9 && dec == 0 && _picture.find(',') < 0)
{
flags |= VALUTA_FLAG;
flags &= ~PAD_FLAG;
}
else
flags |= NUMBER_FLAG;
}
else
flags |= NUMBER_FLAG;
break;
case 'V':
flags |= IGNORE_FILL;
// fall down
case 'v':
flags |= VALUTA_FLAG;
flags &= ~PAD_FLAG;
break;
default:
CHECK (0, "TPrint_application::set_row: invalid @ code");
break;
}
if (flags & NUMBER_FLAG ||
flags & DATE_FLAG ||
flags & TRANS_FLAG ||
flags & BOOLEAN_FLAG ||
flags & STRING_FLAG ||
flags & VALUTA_FLAG)
{
char* x = va_arg (params, char *);
_rows.add (new _FieldTok (_currow, x, flags, align, size, dec));
delete x; // FLD macro has mallocated it!
}
flags = 0x0000;
align = 'l';
}
else
{
switch (ch)
{
case '#':
case '%':
{
const char ccc = ch;
// check for pending string
if (strind)
{
strbuf[strind] = '\0';
_rows.add (new _PrintfTok (_currow, strbuf));
strind = 0;
}
if ((ch = *fmt++) == ccc)
_rows.add (new _PrintfTok (_currow, ccc == '%' ? "%" : "#"));
else
{
// read format
TString80 formato;
formato << ccc;
bool islong = FALSE;
while (strchr (printf_types, ch) == NULL)
{
formato << ch;
if (ch == 'l')
islong = TRUE;
ch = *fmt++;
if (ch == '\0')
NFCHECK("sorry, zer's samzing vruong uitz ioar format.");
}
if (isupper (ch))
{
ch = tolower (ch);
fill = ' ';
}
if (ch == 't' || ch == 'a')
formato << 's';
else if (ch == 'r')
#ifdef __LONGDOUBLE__
formato << "Lf";
#else
formato << 't';
#endif
else
formato << ch;
if (ccc == '%')
{
TString256 q;
switch (ch)
{
case 'd':
case 'i':
case 'u':
case 'o':
case 'x':
case 'X':
q.format (formato, islong ? va_arg (params, long) : va_arg (params, int));
break;
case 'f':
case 'e':
case 'E':
case 'G':
#ifdef WIN32
q.format (formato, islong ? va_arg (params, double) : va_arg (params, float));
#else
q.format (formato, va_arg (params, double));
#endif
break;
case 'c':
#ifdef WIN32
q.format (formato, va_arg (params, char));
#else
q.format (formato, va_arg (params, int));
#endif
break;
case 's':
q.format (formato, va_arg (params, char *));
break;
case 't': // TString
q.format(formato,(const char*)(TString)*((va_arg (params, TString*))));
break;
case 'a': // TParagraph_string
q.format(formato,(const char*)(TParagraph_string)*((va_arg (params, TParagraph_string*))));
break;
case 'r': // Real
{
const real& rrr = * va_arg (params, real *);
if (_picture.not_empty() && (formato.len() == 2 || formato == "%Lf"))
{
// no format specifications
// use default picture
q.cut(0);
if (_magic_currency)
{
if (_picture == "." || (_picture.len() >= 9 && _picture.find(',') < 0))
real2currency(q, rrr);
}
if (q.empty())
q = rrr.string(_picture);
}
else
{
#ifdef __LONGDOUBLE__
q.format(formato, (long double)rrr);
#else
q = rrr.format(formato);
#endif
}
if (rrr.is_zero () && !_print_zero)
q.fill (' ', q.len());
}
break;
case 'v': // Currency
{
const TCurrency& cur = *va_arg(params, TCurrency*);
if (cur.get_num().is_zero() && !_print_zero)
q.cut(0);
else
q = cur.string(_picture.find('.') >= 0);
const int width = atoi(formato.mid(1,-1));
if (width > 0)
q.right_just(width);
}
break;
default:
break;
}
if (fill != ' ')
q = fill_str (q, fill);
fill = _fillchar;
_rows.add (new _PrintfTok (_currow, q));
}
else
_rows.add (new _PrintfRef (_currow, formato, ch, va_arg (params, void *)));
}
}
break;
case '\n': // ignore
break;
default:
// add to string
strbuf[strind++] = ch;
if (!ch)
fmt--;
break;
}
}
}
if (strind)
{
strbuf[strind] = '\0';
_rows.add(new _PrintfTok(_currow, strbuf));
strind = 0;
}
va_end (params);
}
// @doc EXTERNAL
// @mfunc Setta i valori di traduzione dei campi
void TPrint_application::set_translation (
int lognum, // @parm Numero logido del file condenete il campo da tradurre
const char *field, // @parm Campo di cui effettuare la straduzione
const char *from, // @parm Valore da tradurre
const char *to) // @parm Valore che assume il campo
// @comm Questa funzione occorre che sia chiamata per ogni traduzione da effettuare.
// <nl>Esempio: set_translation(12,"STATOCIV","1","Celibe") provoca la stampa
// automatica di stringhe al posto di determinati valori dei campi se e' dato
// il codice @t.
// <nl>Il posto giusto per chiamarla e' nella <mf TPrint_application::user_create>.
{
_transtab.add (new _Transfield (lognum, field, from, to));
}
void TPrint_application::print()
{
_cancelled = FALSE;
_print_defined = FALSE;
// open printer if needed
if (!(printer().isopen ()))
if (!printer().open ())
return;
// only external apps can change it
_repeat_print = FALSE;
// NULL cursor passed only prints once
// pre and post process do everything
if (_cur == NULL)
{
//************************************************
int cnt = 0;
bool ok = TRUE;
do {
if (preprocess_print (0, cnt))
{
int cnt2 = 0;
do {
if (preprocess_page (0, cnt2))
{
set_page (0, cnt2);
ok = print_one (0);
}
}
while (ok && postprocess_page (0, cnt2++) == REPEAT_PAGE);
}
}
while (ok && postprocess_print (0, cnt++) == REPEAT_PAGE);
// *****************************************************
}
else
{
// cursor exists *********************************************
(*_cur) = 0l;
_cur->freeze (TRUE);
if (_cur->items () >= _wthr &&
(_force_progind || printer ().printtype () != screenvis))
_prind = new TProgind (_cur->items (), TR("Stampa in corso..."), _wcancel, _wbar);
print_tree (_pr_tree);
_cur->freeze (FALSE);
if (_prind)
{
delete _prind;
_prind = NULL;
}
// ****************************************************************
}
if (!_repeat_print)
{
if (printer().isopen ())
{
printer().close();
printer().resetheader();
printer().resetfooter();
}
postclose_print ();
}
else
printer().formfeed();
}
bool TPrint_application::print_tree (link_item * head)
{
bool go = TRUE;
while (head)
{
head->_cnt = 0;
if (_cur->is_first_match (head->_logicnum))
{
do
{
if (!preprocess_print (head->_logicnum, head->_cnt))
break;
do
{
// set print rows according to current file
if (_force_setpage || _cur_file != head->_logicnum
|| !_print_defined)
{
reset_print ();
set_page(head->_logicnum, head->_cnt);
_cur_file = head->_logicnum;
}
int cnt2 = 0;
do
{
if (!preprocess_page (head->_logicnum, cnt2))
break;
go = print_one (head->_logicnum);
if (go && head->_son)
go = print_tree (head->_son);
}
while (go && postprocess_page (head->_logicnum, cnt2++) ==
REPEAT_PAGE);
}
while (go && _cur->next_match (head->_logicnum));
}
while (go && postprocess_print (head->_logicnum, head->_cnt++) == REPEAT_PAGE);
}
if (!go)
break;
go = TRUE;
head = head->_brother;
}
return go;
}
void TPrint_application::real2currency(TString& s, const real& r, const char* p) const
{
const TFixed_string pic = (p && *p) ? p : (const char *) _picture;
if (!r.is_zero() || _print_zero)
{
TCurrency c(r);
if (_curr_codval.not_empty())
c.change_value(_curr_codval);
const bool dotted = pic.empty() || pic.find('.') >= 0;
s = c.string(dotted);
}
else
s.cut(0);
const int len = pic.len();
if (len >= 9)
s.right_just(len);
}
HIDDEN void raddoppia_chiocciole(TString& toprint)
{
for (int i = toprint.len()-1; i >= 0; i--)
{
if (toprint[i] == '@')
toprint.insert("@", i);
}
}
// @doc INTERNAL
// @mfunc Stampa un singolo record
//
// @rdesc Ritorna il risultato dell'operazione:
//
// @flag TRUE | Se e' riuscito a stampare il record
// @flag FALSE | Se la stampa non ha avuto successo
bool TPrint_application::print_one (
int file) // @parm Numero logico del file di cui stampare il record
// @comm Dopo la stampa del record non viene spostato in avanti il cursore
{
int i = 0;
TPrinter& prn = printer();
if ((_prind && _prind->iscancelled()) || prn.frozen())
if (_cancelled = cancel_hook()) return FALSE;
if (!_print_defined)
return TRUE;
if (_prind && file == _pr_tree->_logicnum)
_prind->addstatus (1);
TArray rw(_maxrow + 1);
int *pos = new int[_maxrow + 1];
for (i = 0; i <= _maxrow; i++)
{
rw.add(new TPrintrow());
pos[i] = -1;
}
// printing workhorse
for (i = 0; i <= _maxrow; i++)
for (int j = 0; j < _rows.items (); j++)
{
_Token* t = (_Token*)&(_rows[j]);
if (!t) continue; // should not happen
if (t->row() == i)
{
TString80 pic; // was char pic[36]
TString16 fn; // was char fn[17]
int ch, ln, from, to;
if (t->tag() == 3)
{
_PrintRowToken* r = (_PrintRowToken*)t;
rw.add(r->printrow(), r->row());
}
else if (t->tag () == 1)
{
// it's a _FieldTok
_FieldTok *ft = (_FieldTok *) t;
TString256 toprint;
from = to = -1;
if (ft->_flags & FONT_FLAG)
{
TPrintstyle st = normalstyle;
switch (ft->_fld[0])
{
case 'u':
st = underlinedstyle;
break;
case 'b':
st = boldstyle;
break;
case 'i':
st = italicstyle;
break;
case 'r':
st = normalstyle;
break;
default:
st = normalstyle;
break;
}
((TPrintrow *)(&rw[ft->row()]))->set_style (st);
}
else if (ft->_flags & JUMP_FLAG)
{
char ch;
int p;
ch = ft->_fld[0];
p = atoi (((const char *) ft->_fld) + 2);
if (ch == 'g')
// go to
pos[ft->row ()] = p;
else
// jump ahead
pos[ft->row ()] =
((TPrintrow *) (&rw[ft->row ()]))->lastpos () + p;
}
else
{
if (ft->_fld[0] == 'p')
{
// picture
TToken_string ttt (ft->_fld, '|');
ch = (ttt.get ())[0];
ln = atoi ((const char *) ttt.get ());
fn = ttt.get();
pic = ttt.get();
}
else
{
TToken_string ttt (ft->_fld, '|');
ch = (ttt.get ())[0];
ln = ttt.get_int();
fn = ttt.get();
from = ttt.get_int();
to = ttt.get_int();
}
// get field val
TLocalisamfile &f = _cur->file(ln);
if (ft->_flags & TRANS_FLAG)
{
_Transfield *tr = NULL;
// look up field value in translation table
int i;
for (i = 0; i < _transtab.items (); i++)
{
tr = (_Transfield *) & _transtab[i];
if (tr->_fn == fn && tr->_lognum == ln)
{
// check value
if (tr->_from == f.get(fn).sub(from<0 ? 0 : from,to))
break;
}
}
if (i == _transtab.items())
toprint = "";
else
toprint = tr->_to;
}
else if (ft->_flags & DATE_FLAG)
{
const TDate d(f.get(fn));
toprint = d.string (ft->_flags & LONG_FLAG ? full : brief);
if (toprint.empty ())
{
toprint = (ft->_flags & LONG_FLAG ? " - - " : " - - ");
}
}
else if (ft->_flags & BOOLEAN_FLAG)
{
toprint = f.get(fn) == "X" ? TR("Si") : TR("No");
}
else if (ft->_flags & NUMBER_FLAG)
{
TString80 pict;
real r(f.get(fn));
bool isreal = f.curr ().type (fn) == _realfld;
if (ft->_flags & PICTURE_FLAG)
pict = pic;
else if (!(ft->_flags & DEC_FLAG) && *_picture && isreal)
pict = _picture;
if (pict.len () > 0)
toprint = r.string (pict);
else if (ft->_flags & DEC_FLAG)
toprint = r.string (ft->_size, ft->_dec);
else
toprint = r.string ();
if (r.is_zero () && !_print_zero)
toprint.fill (' ', toprint.len());
}
else if (ft->_flags & STRING_FLAG)
{
toprint = f.curr().get (fn);
// perform string extraction
if (from != -1)
toprint = toprint.sub (from, to);
else if (to != -1)
toprint = toprint.left (to);
if (toprint.find('@') >= 0)
raddoppia_chiocciole(toprint);
}
else if (ft->_flags & VALUTA_FLAG)
{
const real n(f.get(fn));
real2currency(toprint, n);
}
}
// adjust size and set fill char
if (ft->_flags & PAD_FLAG)
{
if (!(ft->_flags & NUMBER_FLAG))
{
if (ft->_size < toprint.len ())
toprint.cut (ft->_size);
else
toprint.left_just (ft->_size);
}
if (ft->_flags & ALIGN_FLAG)
{
if (ft->_align == 'r')
toprint.right_just (ft->_size);
else if (ft->_align == 'c')
toprint.center_just (ft->_size);
else if (ft->_align == 'l')
toprint.left_just (ft->_size);
}
}
if (_fillchar != ' ' && !(ft->_flags & IGNORE_FILL))
toprint = fill_str (toprint, _fillchar);
// add to print row
((TPrintrow *)(&rw[ft->row()]))->put (toprint, pos[ft->row ()]);
if (pos[ft->row()] != -1)
pos[ft->row ()] += toprint.len ();
}
else if (t->tag () == 0)
{
// it's a _PrintfTok
_PrintfTok *pt = (_PrintfTok *) t;
TString v = pt->_val;
((TPrintrow *) (&rw[pt->row ()]))->put (v, pos[pt->row ()]);
if (pos[pt->row ()] != -1)
{
pos[pt->row ()] += v.len ();
const char* s = v;
while (*s && strncmp(s, "$[", 2) == 0)
{
while (*s && *s != ']')
{
pos[pt->row()]--;
s++;
}
if (*s)
pos[pt->row()]--;
while (*s && *s != '$') s++;
}
}
}
else
if (t->tag () == 2)
{
// printf by reference
_PrintfRef *pr = (_PrintfRef *) t;
TString ps;
TParagraph_string * para_str = NULL;
bool islong = (pr->_fmt).find ('l') != -1;
switch (pr->_type)
{
case 'd':
case 'i':
case 'u':
case 'o':
case 'x':
case 'X':
ps.format (pr->_fmt, islong ? *((long *) (pr->_what)) :
*((int *) (pr->_what)));
break;
case 'f':
case 'e':
ps.format (pr->_fmt, islong ? *((double *) (pr->_what)) :
*((float *) (pr->_what)));
break;
case 'c':
ps.format (pr->_fmt, *((char *) (pr->_what)));
break;
case 's':
ps.format (pr->_fmt, (char *) (pr->_what));
break;
case 't':
ps.format (pr->_fmt, (const char *)
(*((TString *) (pr->_what))));
break;
case 'a':
{
para_str = ((TParagraph_string *) (pr->_what));
const char * s = para_str->get();
if (s != NULL)
ps.format (pr->_fmt, s);
break;
}
case 'r':
{
const real& rrr = *(real*)pr->_what;
const char* fff = pr->_fmt;
if (*_picture && (strlen(fff) == 2 || strcmp(fff, "%Lf") == 0))
{
if (_magic_currency && _picture == "." ||
(_picture.len() >= 9 && _picture.find(',') < 0))
real2currency(ps, rrr);
else
ps = rrr.string(_picture);
}
else
{
#ifdef __LONGDOUBLE__
ps.format(fff, (long double)rrr);
#else
ps = rrr.format(fff);
#endif
}
if (rrr.is_zero () && !_print_zero)
ps.fill (' ', ps.len());
}
break;
default:
break;
}
ps = fill_str (ps, _fillchar);
((TPrintrow *) (&rw[pr->row ()]))->put (ps, pos[pr->row ()]);
if (para_str != NULL)
{
const char * s = para_str->get();
int row = pr->row();
TPrintstyle xstyle = ((TPrintrow *)(&rw[row]))->get_style();
while (s != NULL)
{
ps.format (pr->_fmt, s);
ps = fill_str (ps, _fillchar);
row++;
if (rw.objptr(row) == NULL)
rw.add(new TPrintrow ());
((TPrintrow *) (&rw[row]))->set_style(xstyle);
((TPrintrow *) (&rw[row]))->put(ps, pos[pr->row()]);
s = para_str->get();
}
((TPrintrow *) (&rw[row]))->set_style(normalstyle);
}
if (pos[pr->row ()] != -1)
pos[pr->row ()] += ps.len ();
}
}
}
// print!
const int last = rw.last();
for (i = 0; i <= /*_maxrow*/ last; i++)
{
TPrintrow *pr = (TPrintrow *) & rw[i];
if (!(prn.print(*pr)))
break;
}
//callback che segnala la fine della stampa fisica di una riga (da lui chiamata "page")
on_page_printed(file);
if (_auto_ff && prn.rows_left() > 0)
printer().formfeed ();
delete pos;
// TRUE if all rows have been printed
// if stopped by preprocess_page returns ok
return i == last /*_maxrow */ + 1;
}
bool TPrint_application::menu(MENU_TAG m)
{
// funziona da se' fino a 20 voci della menubar
if (m >= BAR_ITEM_ID(1) && m <= BAR_ITEM_ID(20))
{
_last_choice = m;
do_print((m - BAR_ITEM_ID(0)) / 100);
}
// Se non esistono altre voci di menu termina l'applicazione
return xvtil_test_menu_tag (BAR_ITEM_ID(2));
}
bool TPrint_application::create()
{
TApplication::create();
printer().setfooterhandler (_pp_footer);
printer().setheaderhandler (_pp_header);
printer().setlinkhandler (_pp_link);
if (user_create())
{
dispatch_e_menu (_last_choice);
return TRUE;
}
return FALSE;
}
bool TPrint_application::destroy ()
{
user_destroy();
reset_files();
_cursors.destroy();
return TApplication::destroy ();
}
void TPrint_application::do_print(int n)
{
while (set_print(n))
{
do { print(); } while(_repeat_print);
enable_print_menu();
}
}
void TPrint_application::enable_print_menu()
{
enable_menu_item(M_FILE_PREVIEW, TRUE);
enable_menu_item(M_FILE_PRINT, TRUE);
}
void TPrint_application::disable_print_menu()
{
enable_menu_item(M_FILE_PREVIEW, FALSE);
enable_menu_item(M_FILE_PRINT, FALSE);
}
void TPrint_application::enable_setprint_menu()
{
enable_menu_item(BAR_ITEM_ID(1), TRUE);
}
void TPrint_application::disable_setprint_menu()
{
enable_menu_item (BAR_ITEM_ID(1), FALSE);
}
TPrint_application::TPrint_application ():TApplication (), _rows (100),
_cursors (10), _transtab (10), _header (10),
_footer (10)
{
_cur = NULL;
_repeat_print = FALSE;
_currow = _maxrow = 0;
_auto_ff = FALSE;
_wbar = _wcancel = TRUE;
_wthr = 5;
_fillchar = ' ';
_pr_tree = NULL;
_print_defined = FALSE;
_force_progind = FALSE;
_force_setpage = FALSE;
_magic_currency = FALSE;
_prind = NULL;
_cur_file = 0;
_magic_currency = FALSE;
_print_zero = FALSE;
_last_choice = BAR_ITEM_ID(1);
}
void TPrint_application::reset_files()
{
if (_pr_tree != NULL)
{
_reset_tree(_pr_tree);
_pr_tree = NULL;
}
}
TPrint_application::~TPrint_application ()
{}