assoc.cpp Stessa roba object.h Aggiunti distruttori virtuali printapp.cpp Sostituito == -1 con < 0 nei metodi set/get_cursor relation.cpp Riportate modifiche suggerite da Angelo string.* Aggiunti distruttori virtuali git-svn-id: svn://10.65.10.50/trunk@3740 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1567 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1567 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <ctype.h>
 | ||
| #include <stdarg.h>
 | ||
| 
 | ||
| #ifndef __LONGDOUBLE__
 | ||
| #include <gm.h>
 | ||
| #endif
 | ||
| 
 | ||
| #include <progind.h>
 | ||
| #include <utility.h>
 | ||
| #include <tabutil.h>
 | ||
| #include <printapp.h>
 | ||
| #include <urldefid.h>
 | ||
| 
 | ||
| TLocalisamfile *fff;
 | ||
| 
 | ||
| const char* const printf_types = "dDiIuUoOxXfeEgGcCnNsSpPrRtTaA";
 | ||
| 
 | ||
| // _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;
 | ||
| 
 | ||
| // =============================================================
 | ||
| // print token containers
 | ||
| // =============================================================
 | ||
| 
 | ||
| class _Transfield:public TObject
 | ||
| {
 | ||
|   friend class TPrint_application;
 | ||
|   TString _from,    // "from" value 
 | ||
|     _to,      // "to" value
 | ||
|     _fn;      // field name
 | ||
| 
 | ||
|   int _lognum;      // logical number
 | ||
| 
 | ||
|     public:
 | ||
|     _Transfield (int l, const char *fn, const char *from, const char *to):
 | ||
|     _from (3), _to (20), _fn (10)
 | ||
|   {
 | ||
|     _lognum = l;
 | ||
|     _from = from;
 | ||
|     _to = to;
 | ||
|     _fn = fn;
 | ||
|   }
 | ||
| };
 | ||
| 
 | ||
| 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;
 | ||
|   TString _fld;     // field description
 | ||
| 
 | ||
|   word _flags;      // all you need to know 
 | ||
| 
 | ||
|     public:
 | ||
|     _FieldTok (int rw, char *fld, word flags, char align = 'l',
 | ||
|          int size = -1, int dec = -1):
 | ||
|     _fld (20)
 | ||
|   {
 | ||
|     tag(1);
 | ||
|     row(rw);
 | ||
|     _fld = (const char *) fld;
 | ||
|     _flags = flags;
 | ||
|     _size = size, _align = align;
 | ||
|     _dec = dec;
 | ||
|     delete fld;
 | ||
|   }
 | ||
|   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 ------------------------------------
 | ||
| 
 | ||
| static char tb[120];
 | ||
| 
 | ||
| // @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);
 | ||
| }
 | ||
| 
 | ||
| void TPrint_application::_pp_link (int id, const char *text)
 | ||
| {
 | ||
|   TPrint_application& prapp = (TPrint_application&)main_app();
 | ||
|   prapp.process_link(id, text); 
 | ||
| }
 | ||
| 
 | ||
| void TPrint_application::_pp_header (TPrinter &)
 | ||
| {
 | ||
|   TPrint_application& prapp = (TPrint_application&)main_app();
 | ||
|   prapp.preprocess_header();
 | ||
|   printer().resetheader();
 | ||
|   const int ii = prapp._header.last();
 | ||
|   // reset and add header/footer lines
 | ||
|   for (int i = 0; i <= ii; i++)
 | ||
|     if (prapp._header.objptr(i) != NULL)
 | ||
|       printer().setheaderline (i, new TPrintrow((TPrintrow &)prapp._header[i]));
 | ||
| }
 | ||
| 
 | ||
| void TPrint_application::_pp_footer (TPrinter &)
 | ||
| {
 | ||
|   TPrint_application& prapp = (TPrint_application&)main_app();
 | ||
| 
 | ||
|   prapp.preprocess_footer ();
 | ||
|   printer().resetfooter ();
 | ||
|   int ii = prapp._footer.last();
 | ||
|   for (int i = 0; i <= ii; i++)
 | ||
|     if (prapp._footer.objptr(i) != NULL)
 | ||
|       printer().setfooterline (i,
 | ||
|        new TPrintrow ((TPrintrow &) (prapp._footer)[i]));
 | ||
| }
 | ||
| 
 | ||
| // @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)
 | ||
| {
 | ||
|   sprintf (tb, "%c|%d|%s|%d|%d", 'n', lognum, f, from, to);
 | ||
|   char *p = new char[strlen (tb) + 1];
 | ||
|   strcpy (p, tb);
 | ||
|   return p;
 | ||
| }
 | ||
| 
 | ||
| const char* FLD (int lognum, const char *f, const char *picture)
 | ||
| {
 | ||
|   sprintf (tb, "%c|%d|%s|%s", 'p', lognum, f, picture);
 | ||
|   char *p = new char[strlen (tb) + 1];
 | ||
|   strcpy (p, tb);
 | ||
|   return p;
 | ||
| }
 | ||
| 
 | ||
| const char* FLD (const char *tabname, const char *f, int from, int to)
 | ||
| {
 | ||
|   CHECKS (strlen (tabname) < 5, "Invalid table name", tabname);
 | ||
|   int lognum = TTable ::name2log (tabname);
 | ||
|   sprintf (tb, "%c|%d|%s|%d|%d", 'n', lognum, f, from, to);
 | ||
|   char *p = new char[strlen (tb) + 1];
 | ||
|   strcpy (p, tb);
 | ||
|   return p;
 | ||
| }
 | ||
| 
 | ||
| const char* FLD (const char *tabname, const char *f, const char *picture)
 | ||
| {
 | ||
|   CHECKS (strlen (tabname) < 5, "Invalid table name", tabname);
 | ||
|   int lognum = TTable ::name2log (tabname);
 | ||
|   sprintf (tb, "%c|%d|%s|%s", 'p', lognum, f, picture);
 | ||
|   char *p = new char[strlen (tb) + 1];
 | ||
|   strcpy (p, tb);
 | ||
|   return p;
 | ||
| }
 | ||
| 
 | ||
| TString& fill_str (TString & t, char f)
 | ||
| {
 | ||
|   for (int kk = t.len () - 1; kk >= 0; kk--)
 | ||
|     if (t[kk] == ' ')  t[kk] = f;
 | ||
|     else break;
 | ||
|   for (kk = 0; kk < t.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>
 | ||
| 
 | ||
| {
 | ||
|   CHECK (r >= 1, "Header rows start at 1");
 | ||
|   va_list vl;
 | ||
|   va_start (vl, fmt);
 | ||
|   vsprintf (__tmp_string, 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_string);
 | ||
| }
 | ||
| 
 | ||
| // @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");
 | ||
|   va_list vl;
 | ||
|   va_start (vl, fmt);
 | ||
|   vsprintf (__tmp_string, 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_string);
 | ||
| }
 | ||
| 
 | ||
| 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];
 | ||
|   char strbuf[120];
 | ||
|   char fftt[120];
 | ||
|   char *fmt = fftt;
 | ||
|   char fill = _fillchar;
 | ||
| 
 | ||
|   word flags = 0;
 | ||
|   int size = 0, dec = 0, strind = 0;
 | ||
|   char ch, align = 'l';
 | ||
| 
 | ||
|   // let the poor programmer use format() at will
 | ||
|   strcpy (fmt, frmt);
 | ||
|   _print_defined = TRUE;
 | ||
| 
 | ||
|   _currow = r;
 | ||
|   if (_currow > _maxrow)
 | ||
|     _maxrow = _currow;
 | ||
| 
 | ||
|   va_list params;
 | ||
|   va_start(params, frmt);
 | ||
| 
 | ||
|   // parse format string
 | ||
|   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 *xxxx = new char[2];
 | ||
|          xxxx[0] = ch;
 | ||
|          xxxx[1] = '\0';
 | ||
|          _rows.add (new _FieldTok (_currow, xxxx, FONT_FLAG));
 | ||
|          }
 | ||
|          break;
 | ||
|        case 'g':
 | ||
|        case 'j':
 | ||
|          {
 | ||
|          const char *xxx = format ("%c %d", ch, size);
 | ||
|          char *xxxx = new char[strlen (xxx) + 1];
 | ||
|          strcpy (xxxx, xxx);
 | ||
|          _rows.add (new _FieldTok (_currow, xxxx, 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':
 | ||
|          flags |= NUMBER_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)
 | ||
|       {
 | ||
|         char *xxx = va_arg (params, char *);
 | ||
|         _rows.add (new _FieldTok (_currow, xxx, flags, align, size, dec));
 | ||
|       }
 | ||
|       flags = 0x0000;
 | ||
|       align = 'l';
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       TString t;
 | ||
|       switch (ch)
 | ||
|       {
 | ||
|       case '#':
 | ||
|       case '%':
 | ||
|         {
 | ||
|         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 
 | ||
|          t << ccc;
 | ||
|          bool islong = FALSE;
 | ||
|          while (strchr (printf_types, ch) == NULL)
 | ||
|          {
 | ||
|            t << ch;
 | ||
|            if (ch == 'l')
 | ||
|              islong = TRUE;
 | ||
|            ch = *fmt++;
 | ||
|            if (ch == '\0')
 | ||
|            fatal_box ("sorry, zer's samzing vruong uitz ioar format.");
 | ||
|          }
 | ||
|          if (isupper (ch))
 | ||
|          {
 | ||
|            ch = tolower (ch);
 | ||
|            fill = ' ';
 | ||
|         }
 | ||
|         if (ch == 't' || ch == 'a')
 | ||
|           t << 's';
 | ||
|         else if (ch == 'r')
 | ||
| #ifdef __LONGDOUBLE__
 | ||
|           t << "Lf";
 | ||
| #else        
 | ||
|           t << 't';
 | ||
| #endif          
 | ||
|         else
 | ||
|           t << ch;
 | ||
|         if (ccc == '%')
 | ||
|         {
 | ||
|           TString q (60);
 | ||
|           switch (ch)
 | ||
|           {
 | ||
|             case 'd':
 | ||
|             case 'i':
 | ||
|             case 'u':
 | ||
|             case 'o':
 | ||
|             case 'x':
 | ||
|             case 'X':
 | ||
|               q.format (t, islong ? va_arg (params, long) : va_arg (params, int));
 | ||
|               break;
 | ||
|             case 'f':
 | ||
|             case 'e':
 | ||
|             case 'E':
 | ||
|             case 'G':
 | ||
|               q.format (t, islong ? va_arg (params, double) : va_arg (params, float));
 | ||
|               break;
 | ||
|             case 'c':
 | ||
|               q.format (t, va_arg (params, char));
 | ||
|               break;
 | ||
|             case 's':
 | ||
|               q.format (t, va_arg (params, char *));
 | ||
|               break;
 | ||
|             case 't': // TString
 | ||
|               q.format(t,(const char*)(TString)*((va_arg (params, TString*))));
 | ||
|               break;
 | ||
|             case 'a': // TParagraph_string
 | ||
|               q.format(t,(const char*)(TParagraph_string)*((va_arg (params, TParagraph_string*))));
 | ||
|               break;
 | ||
|             case 'r': // Real
 | ||
|               {
 | ||
|               const real& rrr = * va_arg (params, real *);
 | ||
|               if (t.len () == 2 && *_picture)
 | ||
|               {
 | ||
|                 // no format specifications
 | ||
|                 // use default picture
 | ||
|                 q = rrr.string(_picture);
 | ||
|               }
 | ||
|               else
 | ||
|               {   
 | ||
| #ifdef __LONGDOUBLE__ 
 | ||
|                 sprintf (__tmp_string, t, (long double)rrr);
 | ||
| #else        
 | ||
|                 char *fff = (char*)(const char *)t;
 | ||
|                 dsprintf (__tmp_string, fff, rrr.ptr());
 | ||
| #endif          
 | ||
|                 q = __tmp_string;
 | ||
|               }
 | ||
|               if (rrr.is_zero () && !_print_zero)
 | ||
|                 q.fill (' ');
 | ||
|               }
 | ||
|               break;
 | ||
|             default:
 | ||
|               break;
 | ||
|           }
 | ||
|           if (fill != ' ')
 | ||
|              q = fill_str (q, fill);
 | ||
|           fill = _fillchar;
 | ||
|           _rows.add (new _PrintfTok (_currow, q));
 | ||
|         }
 | ||
|         else
 | ||
|           _rows.add (new _PrintfRef (_currow, t, 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;
 | ||
| 
 | ||
|   // open printer if needed
 | ||
|   if (!(printer().isopen ()))
 | ||
|     if (!printer().open ())
 | ||
|       return;  
 | ||
|   
 | ||
|   // only external apps can change it
 | ||
|   _repeat_print = FALSE;
 | ||
|   int ncopies = printer().n_copies();
 | ||
|                                                        
 | ||
|    // never print multiple copies if printer is viswin
 | ||
|    // only application may repeat printing by setting _repeat_print
 | ||
|    int nc = printer().printtype() == screenvis ? 1 : ncopies;
 | ||
|    
 | ||
|   // NULL cursor passed only prints once
 | ||
|   // pre and post process do everything                                    
 | ||
|   
 | ||
|   if (_cur == NULL)
 | ||
|   { 
 | ||
|     //************************************************
 | ||
|     while (nc--)
 | ||
|     {
 | ||
|      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  *********************************************          
 | ||
|       while (nc--)
 | ||
|   {
 | ||
|     (*_cur) = 0l;
 | ||
|     _cur->freeze (TRUE);
 | ||
|     
 | ||
|     if (_cur->items () >= _wthr &&
 | ||
|         (_force_progind || printer ().printtype () != screenvis))
 | ||
|       _prind = new TProgind (_cur->items (), _wmess, _wcancel, _wbar, 35);
 | ||
|     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;
 | ||
| }
 | ||
| 
 | ||
| // @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;
 | ||
| 
 | ||
|   if ((_prind && _prind->iscancelled()) || printer().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)
 | ||
|       {
 | ||
|         char pic[36], 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;
 | ||
|           TString toprint;
 | ||
|           from = to = -1;
 | ||
| 
 | ||
|           if (ft->_flags & FONT_FLAG)
 | ||
|           {
 | ||
|              TPrintstyle st = normalstyle;
 | ||
|              switch (((const char *) (ft->_fld))[0])
 | ||
|              {
 | ||
|                case 'u':
 | ||
|                  st = underlinedstyle;
 | ||
|                  break;
 | ||
|                case 'b':
 | ||
|                  st = boldstyle;
 | ||
|                  break;
 | ||
|                case 'i':
 | ||
|                  st = italicstyle;
 | ||
|                  break;
 | ||
|                case 'r':
 | ||
|                  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 ((*(const char *) (ft->_fld)) == 'p')
 | ||
|             {
 | ||
|               // picture
 | ||
|               TToken_string ttt (ft->_fld, '|');
 | ||
|               ch = (ttt.get ())[0];
 | ||
|               ln = atoi ((const char *) ttt.get ());
 | ||
|               strcpy (fn, (const char *) ttt.get ());
 | ||
|               strcpy (pic, (const char *) ttt.get ());
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|               TToken_string ttt (ft->_fld, '|');
 | ||
|               ch = (ttt.get ())[0];
 | ||
|               ln = atoi ((const char *) ttt.get ());
 | ||
|               strcpy (fn, (const char *) ttt.get ());
 | ||
|               from = atoi ((const char *) ttt.get ());
 | ||
|               to = atoi ((const char *) ttt.get ());
 | ||
|             }
 | ||
|             // get field val
 | ||
|             TLocalisamfile &f = _cur->file(ln);
 | ||
|             if (ft->_flags & TRANS_FLAG)
 | ||
|             {
 | ||
|               _Transfield *tr = NULL;
 | ||
|               // look up field value in translation table
 | ||
|               for (int 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))
 | ||
|                   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" ? "Si" : "No";
 | ||
|             }
 | ||
|             else if (ft->_flags & NUMBER_FLAG)
 | ||
|             {
 | ||
|               TString pict (0);
 | ||
|               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 (' ');
 | ||
|             }
 | ||
|             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);
 | ||
|             }
 | ||
|          }
 | ||
|          // 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;
 | ||
|       if (pr->_fmt.len () == 2 && *_picture)
 | ||
|       {
 | ||
|         strcpy (__tmp_string, rrr.string (_picture));
 | ||
|       }
 | ||
|       else
 | ||
|       {       
 | ||
|         const char* fff = pr->_fmt;
 | ||
| #ifdef __LONGDOUBLE__      
 | ||
|         sprintf(__tmp_string, fff, (long double)rrr);
 | ||
| #else            
 | ||
|         dsprintf(__tmp_string, (char*)fff, rrr.ptr());
 | ||
| #endif
 | ||
|       }
 | ||
|       ps = __tmp_string;
 | ||
|       if (rrr.is_zero () && !_print_zero)
 | ||
|         ps.fill (' ');
 | ||
|       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 (!(printer().print(*pr)))
 | ||
|       break;
 | ||
|   }
 | ||
|   if (_auto_ff && last /* _maxrox */ < printer().formlen ())
 | ||
|     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 (1) && m <= BAR_ITEM (20))
 | ||
|     {
 | ||
|       _last_choice = m;
 | ||
|       do_print((m - BAR_ITEM (0)) / 100);
 | ||
|     }
 | ||
| 
 | ||
|   // Se non esistono altre voci di menu termina l'applicazione
 | ||
|   return xvt_test_menu_tag (BAR_ITEM (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;
 | ||
|   }
 | ||
|   else 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_PRINT, TRUE);
 | ||
| }
 | ||
| 
 | ||
| void TPrint_application::disable_print_menu()
 | ||
| {
 | ||
|   enable_menu_item(M_FILE_PRINT, FALSE);
 | ||
| }
 | ||
| 
 | ||
| void TPrint_application::enable_setprint_menu()
 | ||
| {
 | ||
|   enable_menu_item(BAR_ITEM (1), TRUE);
 | ||
| }
 | ||
| 
 | ||
| void TPrint_application::disable_setprint_menu()
 | ||
| {
 | ||
|   enable_menu_item (BAR_ITEM (1), FALSE);
 | ||
| }
 | ||
| 
 | ||
| TPrint_application::TPrint_application ():TApplication (), _transtab (10),
 | ||
|                     _cursors (10), _header (10),
 | ||
|                     _footer (10), _rows (100)
 | ||
| {
 | ||
|   _cur = NULL;  
 | ||
|   _repeat_print = FALSE;
 | ||
|   _currow = _maxrow = 0;
 | ||
|   _auto_ff = FALSE;
 | ||
|   _wbar = _wcancel = TRUE;
 | ||
|   _wmess = "Stampa in corso\nPrego attendere";
 | ||
|   _wthr = 5;
 | ||
|   _fillchar = ' ';
 | ||
|   _pr_tree = NULL;
 | ||
|   _print_defined = FALSE;
 | ||
|   _force_progind = FALSE;
 | ||
|   _force_setpage = FALSE;
 | ||
|   _prind = NULL;
 | ||
|   _cur_file = 0;
 | ||
|   _picture = "";
 | ||
|   _print_zero = FALSE;
 | ||
|   _last_choice = BAR_ITEM (1);
 | ||
| }
 | ||
| 
 | ||
| void TPrint_application::reset_files() 
 | ||
| { 
 | ||
|   if (_pr_tree != NULL)
 | ||
|   {
 | ||
|     _reset_tree(_pr_tree); 
 | ||
|     _pr_tree = NULL; 
 | ||
|   }  
 | ||
| } 
 | ||
| 
 | ||
| 
 | ||
| TPrint_application::~TPrint_application ()
 | ||
| {}
 |