controls.cpp Corretto lo scrolling e le dimensioni dei listbox window.cpp Corretti colori trasparenti git-svn-id: svn://10.65.10.50/trunk@3143 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			4367 lines
		
	
	
		
			110 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			4367 lines
		
	
	
		
			110 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <ctype.h>
 | ||
| #include <stdlib.h>     
 | ||
| 
 | ||
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
 | ||
| #define STRICT
 | ||
| #include <windows.h>
 | ||
| #endif
 | ||
| 
 | ||
| #include <applicat.h>
 | ||
| #include <form.h>
 | ||
| #include <msksheet.h>
 | ||
| #include <printer.h>
 | ||
| #include <relation.h>
 | ||
| #include <sheet.h>
 | ||
| #include <utility.h> 
 | ||
| #include <spool.h>
 | ||
| 
 | ||
| #ifndef __DEFMASK_H
 | ||
| #include <defmask.h>
 | ||
| #endif
 | ||
| 
 | ||
| #include "../ba/bafrm.h"
 | ||
|       
 | ||
| // per lo sheet di edit campi      
 | ||
| HIDDEN const int idt_id = 101;
 | ||
| HIDDEN const int dsc_id = 102;
 | ||
| HIDDEN const int prn_id = 103;    
 | ||
| HIDDEN const int yps_id = 104;
 | ||
| HIDDEN const int xps_id = 105;
 | ||
| HIDDEN const int len_id = 106;
 | ||
| HIDDEN const int col_id = 107;
 | ||
| HIDDEN const int int_id = 108;
 | ||
| HIDDEN const int spc_id = 109;
 | ||
| HIDDEN const int fnl_id = 110;
 | ||
| HIDDEN const int fnr_id = 111;
 | ||
| HIDDEN const int typ_id = 112;
 | ||
| HIDDEN const int frm_id = 113;    
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // Utility functions
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| 
 | ||
| // Current form (edit, print)                           
 | ||
| HIDDEN TForm*          _cur_form = NULL;
 | ||
| HIDDEN TPrint_section* _cur_sect = NULL;
 | ||
| HIDDEN TMask*          _special_mask = NULL;
 | ||
| 
 | ||
| HIDDEN TForm& form()
 | ||
| {
 | ||
|   CHECK(_cur_form, "Can't print NULL form");
 | ||
|   return *_cur_form;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN TPrint_section& section()
 | ||
| {
 | ||
|   CHECK(_cur_sect, "Can't print NULL section");
 | ||
|   return *_cur_sect;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN TMask& special_mask()
 | ||
| {
 | ||
|   CHECK(_special_mask, "Can't access NULL mask");
 | ||
|   return *_special_mask;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // @doc INTERNAL
 | ||
| 
 | ||
| // @func Funzione che converte dalla notazione carattere al corrispondente
 | ||
| //       enum <t pagetype>
 | ||
| //
 | ||
| // @rdesc Ritorna il <t pagetype> corrispondente
 | ||
| pagetype char2page(
 | ||
|          char c)  // @parm Notazione carattere del tipo di pagina
 | ||
|          
 | ||
| {  
 | ||
|   pagetype pt;
 | ||
|   switch(c)
 | ||
|   {
 | ||
|   case '1':
 | ||
|   case 'E':
 | ||
|     pt = even_page; break;
 | ||
|   case '2':
 | ||
|   case 'F':
 | ||
|     pt = first_page; break;
 | ||
|   case '3':
 | ||
|   case 'L':
 | ||
|     pt = last_page; break;
 | ||
|   default:
 | ||
|     pt = odd_page; break;   
 | ||
|   }
 | ||
|   return pt;
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // Gestione TFieldref su maschera
 | ||
| // ID   CAMPO                                       ATTIVO  
 | ||
| // xx0  Stringa completa del TFieldref                 
 | ||
| // xx1  Descrizione file 
 | ||
| // xx2  Bottone selezione file                         X
 | ||
| // xx3  Descrizione campo
 | ||
| // xx4  Bottone selezione campo                        X
 | ||
| // xx5  Primo carattere campo                          X
 | ||
| // xx6  Ultimo carattere campo                         X
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| HIDDEN void put_fieldref(const TFieldref& fr, TMask_field& f)
 | ||
| {             
 | ||
|   TRelation_description& rd = form().rel_desc();
 | ||
|   rd.set_cur_file(fr.file());
 | ||
| 
 | ||
|   TString80 desc; desc << fr;
 | ||
|   f.set(desc);
 | ||
|   
 | ||
|   TMask& m = f.mask();
 | ||
|   const short id = f.dlg(); // Campo contenente il TFieldref
 | ||
| 
 | ||
|   m.set(id+1, rd.file_desc());
 | ||
|   m.set(id+3, rd.get_field_description(fr.name()));
 | ||
|   m.set(id+5, (fr.from() > 0 || fr.to() > 0) ? fr.from()+1 : 0);
 | ||
|   m.set(id+6, fr.to() > fr.from() ? fr.to() : 0);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // Handler of F_BUT_FILE field on mask
 | ||
| HIDDEN bool but_file_handler(TMask_field& f, KEY k)                      
 | ||
| {
 | ||
|   if (k == K_F9)
 | ||
|   {                          
 | ||
|     TRelation_description& r = form().rel_desc();                                   
 | ||
|     
 | ||
|     TEdit_field& e = f.mask().efield(f.dlg()-1);
 | ||
|     TFieldref ref; ref = e.get();
 | ||
|     if (r.choose_file(ref.file()))
 | ||
|     {
 | ||
|       ref.set_file(r.file_num());
 | ||
|       put_fieldref(ref, e);
 | ||
|     }  
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }                      
 | ||
| 
 | ||
| HIDDEN bool but_file_handler_sub(TMask_field& f, KEY k)                      
 | ||
| {
 | ||
|   if (k == K_SPACE)
 | ||
|   {                          
 | ||
|     TRelation_description& r = form().rel_desc();                                   
 | ||
|     
 | ||
|     TEdit_field& e = f.mask().efield(f.dlg()-2);
 | ||
|     TFieldref ref; ref = e.get();
 | ||
|     if (r.choose_file(ref.file()))
 | ||
|     {
 | ||
|       ref.set_file(r.file_num());
 | ||
|       f.mask().set(F_FILE1,r.file_desc());  
 | ||
|     }
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }                      
 | ||
| 
 | ||
| 
 | ||
| // Handler of F_BUT_FIELD field on mask
 | ||
| HIDDEN bool but_field_handler(TMask_field& f, KEY k)                      
 | ||
| {
 | ||
|   if (k == K_F9)
 | ||
|   {                          
 | ||
|     TRelation_description& r = form().rel_desc();                                   
 | ||
|     TEdit_field& e = f.mask().efield(f.dlg()-3); // TBC
 | ||
|     TFieldref ref; ref = e.get();
 | ||
|     if (r.choose_field(ref.name()))
 | ||
|     {
 | ||
|       ref.set_name(r.field_name());
 | ||
|       put_fieldref(ref, e);
 | ||
|     }  
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }                      
 | ||
| 
 | ||
| // Handler of F_FROM field on mask
 | ||
| HIDDEN bool from_handler(TMask_field& f, KEY k)                      
 | ||
| {
 | ||
|   if (f.to_check(k))
 | ||
|   {
 | ||
|     TEdit_field& e = f.mask().efield(f.dlg()-5);
 | ||
|     TFieldref ref; ref = e.get();
 | ||
|     ref.set_from(atoi(f.get()));
 | ||
|     put_fieldref(ref, e);
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| // Handler of F_TO field on mask
 | ||
| HIDDEN bool to_handler(TMask_field& f, KEY k)                      
 | ||
| {
 | ||
|   if (f.to_check(k))
 | ||
|   {
 | ||
|     TEdit_field& e = f.mask().efield(f.dlg()-6);
 | ||
|     TFieldref ref; ref = e.get();
 | ||
|     ref.set_to(atoi(f.get()));
 | ||
|     put_fieldref(ref, e);
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN bool dateformat_handler(TMask_field& f, KEY k)
 | ||
| {
 | ||
|   if (k == K_SPACE) 
 | ||
|   {
 | ||
|     TMask& m = f.mask();
 | ||
|     
 | ||
|     char fmt[8]; 
 | ||
|     fmt[0] = m.get(F_DFORMAT)[0];
 | ||
|     fmt[1] = m.get(F_DDAY)[0];
 | ||
|     fmt[2] = m.get(F_DMONTH)[0];
 | ||
|     fmt[3] = m.get(F_DYEAR)[0];
 | ||
|     fmt[4] = m.get(F_DSEP)[0];
 | ||
|     fmt[5] = '\0';
 | ||
|     
 | ||
|     const TDate d(TODAY);
 | ||
|     const TFormatted_date ex(d,fmt);
 | ||
|     m.set(F_DEXAMPLE, ex.string());
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| HIDDEN bool fmt_handler(TMask_field& f, KEY k)
 | ||
| {              
 | ||
|   if (k==K_ENTER || k==K_TAB)
 | ||
|   {                           
 | ||
|     TMask& m = f.mask();
 | ||
|     TPrint_section& s = ::section();
 | ||
|     if (s.columnwise())
 | ||
|     {
 | ||
|       const int fmt_len = m.get(F_PICTURE).len();       // length of picture
 | ||
|       m.set(F_LENFMT,fmt_len);
 | ||
|       m.set(F_NUMCOL,s.fields());
 | ||
|     }
 | ||
|     else
 | ||
|       m.set(F_NUMCOL,999);
 | ||
|   }
 | ||
|   return TRUE;    
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_flags
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| TForm_flags::TForm_flags()
 | ||
| {
 | ||
|   automagic = dirty = finkr = finkl = memo = FALSE;
 | ||
|   shown = enabled  = TRUE;
 | ||
| }
 | ||
| 
 | ||
| // Read from string
 | ||
| // Certified 100%
 | ||
| bool TForm_flags::update(const char* s)
 | ||
| {
 | ||
|   CHECK(s, "NULL flags string");
 | ||
|   for (; *s; s++) switch(toupper(*s))
 | ||
|   {
 | ||
|   case 'A': 
 | ||
|     automagic = TRUE; break;
 | ||
|   case 'D': 
 | ||
|     enabled = FALSE; break;
 | ||
|   case 'H': 
 | ||
|     shown = FALSE; break;
 | ||
|   case 'F': 
 | ||
|     finkl = TRUE; break;
 | ||
|   case 'K': 
 | ||
|     finkr = TRUE; break;
 | ||
|   case 'M':
 | ||
|     memo = TRUE; break;
 | ||
|   default : 
 | ||
|     error_box("Unknown form item flag '%c'", *s); break;
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // Print on stream
 | ||
| // Certified 100%
 | ||
| void TForm_flags::print_on(ostream& out) const
 | ||
| {
 | ||
|   TString16 s;
 | ||
| 
 | ||
|   if (automagic) s << "A";
 | ||
|   if (!enabled) s << "D";
 | ||
|   if (!shown) s << "H";
 | ||
|   if (memo) s << "M";
 | ||
|   if (finkl) s << "F";
 | ||
|   if (finkr) s << "K";
 | ||
| 
 | ||
|   if (s.not_empty()) 
 | ||
|     out << " FLAGS \"" << s << '"' << endl;
 | ||
| }
 | ||
| 
 | ||
| // Set mask fields
 | ||
| // Certified 100%
 | ||
| void TForm_flags::print_on(TMask& m)
 | ||
| {
 | ||
|   m.set(F_DISABLED,  enabled   ? " " : "X");
 | ||
|   m.set(F_HIDDEN,    shown     ? " " : "X");
 | ||
|   m.set(F_AUTOMAGIC, automagic ? "X" : " ");
 | ||
|   m.set(F_FINKL,     finkl     ? " " : "X");
 | ||
|   m.set(F_FINKR,     finkr     ? " " : "X");
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // Get mask fields
 | ||
| // Certified 100%
 | ||
| void TForm_flags::read_from(const TMask& m)
 | ||
| {
 | ||
|   shown     = !m.get_bool(F_HIDDEN);
 | ||
|   enabled   = !m.get_bool(F_DISABLED);
 | ||
|   automagic = m.get_bool(F_AUTOMAGIC);
 | ||
|   finkl     = !m.get_bool(F_FINKL);
 | ||
|   finkr     = !m.get_bool(F_FINKR);
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_item
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| 
 | ||
| TForm_item::TForm_item(TPrint_section* section)
 | ||
| : _section(section), _x(-1), _y(-1), _width(0), _height(0), _id(0), _ofs(0),
 | ||
|   _temp(FALSE)
 | ||
| {}
 | ||
| 
 | ||
| void TForm_item::copy_to_form_item(TForm_item* fi) const
 | ||
| {
 | ||
|   fi->_flag = _flag; fi->_group = _group;
 | ||
|   // come copiarlo facendo una cosa orrenda...
 | ||
|   fi->_special.destroy();
 | ||
|   specials().restart();
 | ||
|   int items = special_items();
 | ||
|   for (int k = 0; k < items; k++)
 | ||
|   {                                           
 | ||
|     THash_object*  ho = specials().get_hashobj(); 
 | ||
|     fi->_special.add(ho->key(),ho->obj());
 | ||
|   }
 | ||
|   // fi->_special = _special;     sarebbe utile avere un "operator =" per i TAssoc_array
 | ||
| 
 | ||
|   fi->_temp = _temp; fi->_id = _id;
 | ||
|   fi->_x = _x; fi->_y = _y; 
 | ||
|   fi->_width = _width; fi->_height = _height;
 | ||
|   fi->_effective_height = _effective_height;
 | ||
|   fi->_ofs = _ofs;  fi->_prompt = _prompt;
 | ||
|   fi->_desc = _desc; fi->_col_head = _col_head;
 | ||
|   // Anche qui... copia uno alla volta
 | ||
|   items = _message.items();
 | ||
|   for (k = 0; k < items; k++)
 | ||
|     fi->_message.add(_message.row(k),k);
 | ||
|   // fi->_message = _message;     sarebbe utile avere un "operator =" per i TString_array
 | ||
| }
 | ||
| 
 | ||
| TObject* TForm_item::dup() const
 | ||
| {
 | ||
|   TForm_item * fi = new TForm_item(_section);
 | ||
|   copy_to_form_item(fi);
 | ||
|   return fi;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_item::parse_head(TScanner& scanner)
 | ||
| {                                  
 | ||
|   _id = scanner.integer();
 | ||
|   
 | ||
|   if (_id == 0)                             // Temporary
 | ||
|     _id = _section->fields()+1;
 | ||
|   
 | ||
|   _width  = scanner.integer();
 | ||
|   if (_width > 0) 
 | ||
|     _height = scanner.integer();
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TForm_item::print_on(ostream& out) const
 | ||
| {
 | ||
|   out << class_name() << ' ' << id();
 | ||
|   if (_width > 0)
 | ||
|   {
 | ||
|     out << ' ' << _width;
 | ||
|     if (_height > 0)
 | ||
|       out << ' ' << _height;
 | ||
|   }
 | ||
|   out << "\nBEGIN\n";
 | ||
| 
 | ||
|   print_body(out);
 | ||
| 
 | ||
|   out << "END\n" << endl;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TForm_item::print_body(ostream& out) const
 | ||
| {
 | ||
|   out << " KEY \"" << _desc << "\"\n";
 | ||
| 
 | ||
|   if (_y >= 0)
 | ||
|     out << " PROMPT " << _x << ' ' << _y << " \"" << _prompt << "\"\n";
 | ||
| 
 | ||
|   if (_group.ones())
 | ||
|     out << " GROUP " << _group << "\n";
 | ||
| 
 | ||
|   out << _flag;
 | ||
|   
 | ||
|   if (_message.items() == 1)
 | ||
|   {
 | ||
|     const TToken_string& m = _message.row(0);
 | ||
|     if (!m.empty_items())
 | ||
|       out << " MESSAGE " << m << endl;
 | ||
|   }
 | ||
|   
 | ||
|   if (_special.items() > 0)
 | ||
|   {
 | ||
|     TAssoc_array& aa = specials();
 | ||
|     aa.restart();                 
 | ||
|     
 | ||
|     THash_object* op;
 | ||
|     
 | ||
|     while ((op = aa.get_hashobj()) != NULL)
 | ||
|     {                          
 | ||
|       TToken_string& t = (TToken_string&)op->obj();
 | ||
|       TString typ(t.get(0));
 | ||
|       TString val(t.get(1));
 | ||
|       TString des(t.get(2));
 | ||
|       out << " SPECIAL " << typ << " " << op->key() 
 | ||
|           << " \"" << val << "\" \"" << des << "\"\n";
 | ||
|     }
 | ||
|   } 
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TForm_item::parse_item(TScanner& scanner)
 | ||
| {
 | ||
|   if (scanner.key() == "PR")
 | ||
|   {
 | ||
|     _x = scanner.integer();
 | ||
|     _y = scanner.integer();
 | ||
|     _prompt = scanner.string();
 | ||
|     return TRUE;
 | ||
|   }                      
 | ||
|   
 | ||
|   if (scanner.key() == "FL")
 | ||
|     return _flag.update(scanner.string());
 | ||
| 
 | ||
|   if (scanner.key() == "ME")
 | ||
|   {
 | ||
|     TFixed_string m(scanner.line());
 | ||
|     m.strip_spaces();   
 | ||
|     int n = 0; 
 | ||
|     if (m.left(5) == "EMPTY")
 | ||
|     {
 | ||
|       n = 1;
 | ||
|       m.ltrim(5);
 | ||
|     }
 | ||
|     if (!m.blank())
 | ||
|       message(n).add(m);
 | ||
|     return TRUE;
 | ||
|   }
 | ||
|   
 | ||
|   if (scanner.key() == "KE")
 | ||
|   {                    
 | ||
|     _desc = scanner.string();
 | ||
|     return TRUE;
 | ||
|   }
 | ||
| 
 | ||
|   if (scanner.key() == "GR")
 | ||
|   {
 | ||
|     _group.set(scanner.line());
 | ||
|     return TRUE;
 | ||
|   }
 | ||
|                                                  
 | ||
|   if (scanner.key() == "SP")
 | ||
|   {
 | ||
|     TToken_string val(scanner.pop());
 | ||
|     TString16 var = scanner.pop();
 | ||
|     val.add(scanner.string());
 | ||
|     val.add(scanner.string());
 | ||
| 
 | ||
|     _special.add(var,val); 
 | ||
|     return TRUE;
 | ||
|   }  
 | ||
|                                                
 | ||
|   yesnofatal_box("Unknown symbol in item '%s': '%s'",
 | ||
|                  (const char*)key(), (const char*)scanner.token());
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_item::parse(TScanner& scanner)
 | ||
| {
 | ||
|   bool ok = parse_head(scanner);
 | ||
| 
 | ||
|   if (ok && scanner.popkey() != "BE")
 | ||
|     ok = yesnofatal_box("Missing BEGIN in form item %s", (const char*)key());
 | ||
| 
 | ||
|   while (ok && scanner.popkey() != "EN")
 | ||
|     ok = parse_item(scanner); 
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_item::read_from(const TRectype& prof)
 | ||
| {
 | ||
|   CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
 | ||
|   bool changed = FALSE;
 | ||
|   
 | ||
|   int i = prof.get_int("X");
 | ||
|   if (_x != i) 
 | ||
|   {
 | ||
|     _x = i;
 | ||
|     changed = TRUE;
 | ||
|   }
 | ||
|   i = prof.get_int("Y");
 | ||
|   if (_y != i) 
 | ||
|   {
 | ||
|     _y = i;
 | ||
|     changed = TRUE;
 | ||
|   }
 | ||
|   i = prof.get_int("LEN");
 | ||
|   if (_width != i) 
 | ||
|   {
 | ||
|     _width = i;
 | ||
|     changed = TRUE;
 | ||
|   }
 | ||
|   i = prof.get_int("HGT");
 | ||
|   if (_height != i) 
 | ||
|   {
 | ||
|     _height = i;
 | ||
|     changed = TRUE;
 | ||
|   }
 | ||
|   TString p(prof.get("PROMPT"));
 | ||
|   if (p.not_empty())
 | ||
|   {
 | ||
|     if (p[0] == '\xFE') p.cut(0);
 | ||
|     const int l = p.len();
 | ||
|     if (l > 0 && p[l-1] == '\xFF')
 | ||
|     {
 | ||
|       p[l-1] = ' ';
 | ||
|       p << '\0';      
 | ||
|     }
 | ||
|     _prompt = p;
 | ||
|     changed = TRUE;
 | ||
|   }
 | ||
| 
 | ||
|   const bool s = prof.get_bool("ATTIVO");
 | ||
|   if (_flag.shown != s)
 | ||
|   {
 | ||
|     _flag.shown = s;
 | ||
|     changed = TRUE;
 | ||
|   }                       
 | ||
|                               
 | ||
|   TToken_string special(prof.get("SPECIAL"),'\n'); 
 | ||
|   special.rtrim();
 | ||
|   const int sp_items = special.items();
 | ||
|   for (i = 0; i < sp_items; i++)
 | ||
|   {                                  
 | ||
|     TToken_string sp(special.get(i), '$');  
 | ||
|     TString key(sp.get(0));
 | ||
|     TString val(sp.get(1));
 | ||
|       
 | ||
|     if (!_special.is_key(key))
 | ||
|     {
 | ||
|       error_box("Variabile speciale non presente nel profilo: %s", 
 | ||
|                  (const char*)key); 
 | ||
|       continue;
 | ||
|     }
 | ||
|     TToken_string& tt = (TToken_string&)_special[key];
 | ||
|     tt.add(val,1);                   
 | ||
|     // forza riscrittura su memo
 | ||
|     if (tt.items() == 3) tt.add("X");
 | ||
|   }
 | ||
| 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| void TForm_item::print_on(TRectype& prof)
 | ||
| {
 | ||
|   CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
 | ||
|   prof.put("ID", id());
 | ||
|   prof.put("X", _x);
 | ||
|   prof.put("Y", _y);
 | ||
|   prof.put("LEN", width());
 | ||
|   prof.put("HGT", height());
 | ||
|   if (_prompt.empty()) _prompt << '\xFE' << '\0';
 | ||
|   const int l = _prompt.len();
 | ||
|   const char c = _prompt[l-1];
 | ||
|   if (c==' ') _prompt[l-1]='\xFF';
 | ||
|   prof.put("PROMPT", _prompt);
 | ||
|   prof.put("ATTIVO", shown() ? "X" : " ");  
 | ||
|   
 | ||
|   // specials: se e' stato cambiato, la tokenstring del valore contiene 
 | ||
|   // una X alla fine (campo 3)
 | ||
|   {                             
 | ||
|     TToken_string special(128,'\n');
 | ||
|     _special.restart();            
 | ||
|     
 | ||
|     for (int i = 0; i < _special.items(); i++)
 | ||
|     {   
 | ||
|       THash_object* o = _special.get_hashobj();
 | ||
|       
 | ||
|       TString key(o->key());
 | ||
|       TToken_string& tt = (TToken_string&)o->obj();
 | ||
|           
 | ||
|       if (tt.items() == 4)
 | ||
|       {              
 | ||
|         TToken_string sp(key,'$'); 
 | ||
|         TString val(tt.get(1));
 | ||
|         sp.add(val);
 | ||
|         special.add(sp);
 | ||
|       }    
 | ||
|     }
 | ||
|     special.rtrim();
 | ||
|     prof.put("SPECIAL", special);
 | ||
|   }  
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Abilita/Disabilita il campo
 | ||
| void TForm_item::enable(
 | ||
|      bool on) // @parm Operazione da svolgere sul campo:
 | ||
|     // @flag TRUE | Il campo viene abiliato
 | ||
|     // @flag FALSE | Il campo viene disabiliato
 | ||
| 
 | ||
| // @comm Viene automaticamente setta se il campo diventi visibile o nascosto (chaiam <mf TForm_item::show>)
 | ||
| {
 | ||
|   _flag.enabled = on;
 | ||
|   show(on);
 | ||
| }
 | ||
| 
 | ||
| void TForm_item::set_special_value(const char* s, const char* val)
 | ||
| {
 | ||
|   TToken_string& tt = (TToken_string&) _special[s];
 | ||
|   tt.add(val,1);
 | ||
|   if (tt.items()==3) tt.add("X");
 | ||
| }
 | ||
| 
 | ||
| const char* TForm_item::get_special_item(const char* s, int n) const
 | ||
| {
 | ||
|   TAssoc_array& sp = (TAssoc_array&)_special;
 | ||
|   if (sp.is_key(s))
 | ||
|   {
 | ||
|     TToken_string& tt = (TToken_string&) sp[s];
 | ||
|     return tt.get(n);
 | ||
|   } else return "";
 | ||
| }
 | ||
| 
 | ||
| void TForm_item::string_at(int x, int y, const char* s)
 | ||
| {
 | ||
|   if (shown())
 | ||
|   {
 | ||
|     if (section().columnwise()) x += _ofs;
 | ||
|     TPrintrow& row = section().row(y-1);         // Seleziona riga di stampa
 | ||
| 
 | ||
|     if (_width > 0 && strlen(s) > (word)_width)  // Tronca testo se necessario
 | ||
|     {
 | ||
|       strncpy(__tmp_string, s, width());
 | ||
|       __tmp_string[_width] = '\0';
 | ||
|       s = __tmp_string;
 | ||
|     }
 | ||
|     row.put(s, x-1);                             // Stampa testo
 | ||
|   }  
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TToken_string& TForm_item::message(int m)
 | ||
| {
 | ||
|   TToken_string* t = (TToken_string*)_message.objptr(m);
 | ||
|   if (t == NULL)
 | ||
|   {
 | ||
|     t = new TToken_string(16);
 | ||
|     _message.add(t, m);
 | ||
|   }
 | ||
|   return *t;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
|   
 | ||
| // @mfunc Manda il messaggio al campo <p dest>
 | ||
| void TForm_item::send_message(
 | ||
|      const TString& cmd,  // @parm Messaggio di comando
 | ||
|      TForm_item& des) const // @parm Campo a cui destinare il messaggio
 | ||
| {
 | ||
|   if (cmd == "ADD" || cmd == "INC")
 | ||
|   {
 | ||
|     const real n((cmd[0] == 'I') ? "1.0" : get());
 | ||
|     real r(des.get());
 | ||
|     r += n;
 | ||
|     des.set(r.string());
 | ||
|   } else
 | ||
|     if (cmd == "COPY")
 | ||
|     {
 | ||
|       des.set(get());
 | ||
|     } else
 | ||
|       if (cmd == "APPEND")
 | ||
|       {
 | ||
|         TString256 val = des.get();
 | ||
|         if (val.not_empty()) val << ' ';
 | ||
|         val << get();
 | ||
|         des.set(val);
 | ||
|       } else
 | ||
|         if (cmd == "DISABLE")
 | ||
|         {
 | ||
|           des.disable();
 | ||
|         } else
 | ||
|           if (cmd == "ENABLE")
 | ||
|           {
 | ||
|             des.enable();
 | ||
|           } else
 | ||
|             if (cmd == "HIDE")
 | ||
|             {
 | ||
|               des.hide();
 | ||
|             } else
 | ||
|               if (cmd == "RESET")
 | ||
|               {
 | ||
|                 des.set("");
 | ||
|               } else        
 | ||
|                 if (cmd == "SHOW")
 | ||
|                 {
 | ||
|                   des.show();
 | ||
|                 } else
 | ||
|                   if (cmd[0] == '"')
 | ||
|                   {
 | ||
|                     TString256 val(cmd);
 | ||
|                     val.strip("\"");
 | ||
|                     des.set(val);
 | ||
|                   } else
 | ||
|                     error_box("Unknown message in item '%s': '%s'",
 | ||
|                               (const char*)key(), (const char*)cmd);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TForm_item& TForm_item::find_field(const TString& id) const
 | ||
| {
 | ||
|   if (isdigit(id[0]))              // Field in the same section
 | ||
|   {
 | ||
|     TForm_item& des = section().find_field(atoi(id));
 | ||
|     return des;
 | ||
|   }  
 | ||
| 
 | ||
|   const pagetype pt = (id[1] == '-') ? section().page_type() : char2page(id[1]);
 | ||
|   const int freccia = id.find("->");
 | ||
|   CHECKS(freccia > 0, "Non trovo la freccia nel campo ", (const char*)id);
 | ||
|   TForm_item& des = form().find_field(id[0], pt, atoi(id.mid(freccia+2)));
 | ||
|   return des;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_item::do_message(int num)
 | ||
| {
 | ||
|   TToken_string& messaggio = message(num);
 | ||
|   if (messaggio.empty_items()) return FALSE;
 | ||
| 
 | ||
|   TToken_string msg(16, ',');
 | ||
|   for (const char* m = messaggio.get(0); m; m = messaggio.get())
 | ||
|   {
 | ||
|     msg = m;
 | ||
|     if (*m == '_')
 | ||
|     {
 | ||
|       form().validate(*this, msg);
 | ||
|       put_paragraph(get());
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       const TString16 cmd(msg.get());      // Get command
 | ||
|       const TString16 id = msg.get();      // Get destination
 | ||
| 
 | ||
|       if (id.right(1) == "@")
 | ||
|       {
 | ||
|         const word group = atoi(id);
 | ||
|         // Send the message to all fields with the given group
 | ||
|         for (word i = 0; i < section().fields(); i++)
 | ||
|         {
 | ||
|           TForm_item& des = section().field(i);
 | ||
|           if (des.in_group(group))
 | ||
|             send_message(cmd, des);
 | ||
|         }
 | ||
|       }  
 | ||
|       else
 | ||
|       {                  
 | ||
|         TForm_item& des = find_field(id);
 | ||
|         send_message(cmd, des);
 | ||
|       }
 | ||
|     }  
 | ||
|   }
 | ||
| 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TForm_item::update()
 | ||
| { 
 | ||
|   if (_prompt.right(1) == "#")
 | ||
|   {   
 | ||
|     TString prompt(_prompt);
 | ||
|     for (int i = prompt.len()-2; i >= 0; i--)
 | ||
|       if (prompt[i] != '#') break;
 | ||
|     prompt.cut(i+1);  
 | ||
|     string_at(x(), _y, prompt);
 | ||
|   }
 | ||
|   else string_at(x(), _y, _prompt);
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| void TForm_item::print_on(TToken_string& row)  const
 | ||
| { 
 | ||
|   row.cut(0);     
 | ||
|   row.add(id());
 | ||
|   row.add(key());  
 | ||
|   row.add(_y);
 | ||
|   row.add(_x);
 | ||
|   row.add(shown() ? " " : "X");
 | ||
|   
 | ||
|   if (form().edit_level() > 1)
 | ||
|   {
 | ||
|     const long fu = _group.first_one();
 | ||
|     if (fu > 0) row.add(fu); 
 | ||
|     else row.add(" ");
 | ||
|   }  
 | ||
| }                        
 | ||
| 
 | ||
| void TForm_item::print_on_sheet_row(TToken_string& tt) const
 | ||
| { 
 | ||
|   TString tmp(80);
 | ||
|   tt.add(_id, idt_id - 101);
 | ||
|   tt.add(_desc, dsc_id - 101);
 | ||
|   tt.add(_x, _section->columnwise() ? col_id - 101 : xps_id - 101);
 | ||
|   tt.add(_width, len_id - 101);
 | ||
|   if (!_section->columnwise())
 | ||
|     tt.add(_y, yps_id - 101);
 | ||
|   tt.add(class_name(), typ_id - 101);
 | ||
|   tt.add(shown() ? " " : "X", prn_id - 101);
 | ||
|   tmp = example(); tt.add(tmp, frm_id - 101);
 | ||
|       
 | ||
|   if (_section->columnwise())
 | ||
|   { 
 | ||
|     tt.add(_ofs, spc_id -101); 
 | ||
|     tt.add(finkl() ? " " : "X", fnl_id -101); 
 | ||
|     tt.add(finkr() ? " " : "X", fnr_id -101); 
 | ||
|     tt.add(_col_head, int_id - 101);
 | ||
|   }
 | ||
| }                            
 | ||
| 
 | ||
| void TForm_item::print_on(TMask& m)
 | ||
| {
 | ||
|   m.set(F_CLASS, class_name());
 | ||
|   m.set(F_ID, id());
 | ||
|   m.set(F_KEY, key());
 | ||
|   m.set(F_X, _x);
 | ||
|   m.set(F_Y, _y);
 | ||
|   m.set(F_PROMPT, _prompt);
 | ||
|   m.set(F_WIDTH, _width);
 | ||
|   if (_section->columnwise())
 | ||
|     m.set(F_INTEST, _col_head);
 | ||
|   m.set(F_HEIGHT, _height);
 | ||
|   m.set(F_SPACES, _ofs);
 | ||
|   
 | ||
|   _flag.print_on(m);
 | ||
|   
 | ||
|   for (int g = 1; g <= 24; g++)      
 | ||
|     m.set(F_GROUP+g, _group[g] ? "X" : " ");
 | ||
| }
 | ||
| 
 | ||
| void TForm_item::read_from(const TMask& m)
 | ||
| {
 | ||
|   _desc = m.get(F_KEY);
 | ||
|   _x = atoi(m.get(F_X));
 | ||
|   _y = atoi(m.get(F_Y));
 | ||
|   _prompt = m.get(F_PROMPT);
 | ||
|   _width = atoi(m.get(F_WIDTH));
 | ||
|   if (_section->columnwise())
 | ||
|     _col_head = m.get(F_INTEST);
 | ||
|   _height = atoi(m.get(F_HEIGHT));
 | ||
|   _id     = atoi(m.get(F_ID)); 
 | ||
|   _ofs    = atoi(m.get(F_SPACES));
 | ||
| 
 | ||
|   _flag.read_from(m);
 | ||
|   
 | ||
|   _group.reset();
 | ||
|   for (int g = 1; g <= 24; g++)      
 | ||
|     _group.set(g, m.get_bool(F_GROUP+g));
 | ||
| }
 | ||
| 
 | ||
| void TForm_item::read_from(TToken_string& s)
 | ||
| {  
 | ||
|   _id     = s.get_int(idt_id - 101);
 | ||
|   _desc   = s.get(dsc_id - 101);
 | ||
|   _x      = _section->columnwise() ? s.get_int(col_id - 101) : s.get_int(xps_id - 101);
 | ||
|   _width = s.get_int(len_id - 101);
 | ||
|   if (!_section->columnwise())
 | ||
|     _y      = s.get_int(yps_id - 101); 
 | ||
|   _flag.set_shown(s.get(prn_id - 101)[0] != 'X'); 
 | ||
| 
 | ||
|   if (_section->columnwise())
 | ||
|   {  
 | ||
|     _ofs    = s.get_int(spc_id - 101);
 | ||
|     _flag.set_finkl(s.get(fnl_id - 101)[0] != 'X'); 
 | ||
|     _flag.set_finkr(s.get(fnr_id - 101)[0] != 'X');
 | ||
|     _col_head = s.get(int_id - 101);
 | ||
|   }
 | ||
|   set_dirty();
 | ||
| }
 | ||
| 
 | ||
| bool TForm_item::edit(TMask& m)
 | ||
| {
 | ||
|   m.enable(F_CLASS, m.insert_mode());
 | ||
|   m.reset();  
 | ||
| 
 | ||
|   if (m.insert_mode())
 | ||
|   {   
 | ||
|     short id = 0;
 | ||
|     for (word i = 0; i < section().fields(); i++)
 | ||
|     {            
 | ||
|       const TForm_item& f = section().field(i);
 | ||
|       if (f.id() > id) id = f.id();
 | ||
|     }                              
 | ||
|     _id = id+1;
 | ||
|   }
 | ||
|   
 | ||
|   print_on(m);
 | ||
|   
 | ||
|   const bool godmode = form().edit_level() > 1;
 | ||
|   m.enable_page(1, godmode);
 | ||
|   m.enable(-7, godmode);
 | ||
|   m.enable(F_ID, godmode);
 | ||
|   m.enable(F_KEY,godmode);
 | ||
|   m.enable(F_Y,!_section->columnwise());
 | ||
|   m.enable(F_INTEST,_section->columnwise());
 | ||
|   if (_flag.memo)
 | ||
|   {
 | ||
|     m.disable(F_PROMPT);
 | ||
|     m.hide(F_PROMPT);
 | ||
|     m.enable(F_MEMO);
 | ||
|     m.show(F_MEMO);
 | ||
|     m.enable(F_HEIGHT);
 | ||
|     m.show(F_HEIGHT);
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     m.hide(F_MEMO);
 | ||
|     m.disable(F_MEMO);
 | ||
|   }
 | ||
|   const bool dirty = m.run() == K_ENTER; 
 | ||
|   if (dirty) 
 | ||
|   {
 | ||
|     read_from(m);
 | ||
|     set_dirty();
 | ||
|   }
 | ||
|   return dirty;
 | ||
| }
 | ||
| 
 | ||
| const TString& TForm_item::picture() const 
 | ||
| {               
 | ||
|   CHECK(0, "Can't get the picture of a generic form item!");
 | ||
|   return _prompt; 
 | ||
| }
 | ||
| 
 | ||
| void TForm_item::set_picture(const char*)
 | ||
| {               
 | ||
|   CHECK(0, "Can't set the picture of a generic form item!");
 | ||
| }
 | ||
| 
 | ||
| TToken_string& TForm_item::memo_info()
 | ||
| {
 | ||
|   CHECK(0, "Can't get a memo of a generic form item!");
 | ||
|   return TToken_string();
 | ||
| }
 | ||
| 
 | ||
| short TForm_item::x()
 | ||
| {
 | ||
|   if (_section == NULL || !_section->columnwise()) 
 | ||
|     return _x;
 | ||
|   return _section->tab(_x-1) + _section->ofspc();
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_subsection
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TForm_subsection : public TForm_item
 | ||
| {  
 | ||
|   TPrint_section _ssec;
 | ||
|   TString _name;
 | ||
| 
 | ||
|   int _file_id;      // ID del file su cui iterare in stampa se previsto
 | ||
| 
 | ||
| protected:
 | ||
|   virtual void print_on(ostream& out) const; 
 | ||
| public:
 | ||
|   virtual TObject* dup() const;
 | ||
|   virtual bool parse(TScanner& s);
 | ||
|   virtual bool update();  
 | ||
|   virtual bool edit(TMask& m);
 | ||
|   
 | ||
|   virtual const char* class_name() const { return "SEZIONE"; }
 | ||
|   
 | ||
|   TPrint_section& subsection()  { return _ssec; }
 | ||
| 
 | ||
|   virtual void show(bool on = TRUE);
 | ||
|   virtual void enable(bool on = TRUE);
 | ||
|   void hide()    { show(FALSE);   }
 | ||
|   void disable() { enable(FALSE); }
 | ||
| 
 | ||
|   void name(const char* s) { _name = s; _desc << "Sottosezione " << s; }
 | ||
|   const char* name() const { return _name; }
 | ||
| 
 | ||
|   TForm_subsection(TPrint_section* section, const char* name = "");
 | ||
|   virtual ~TForm_subsection() {}
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| TForm_subsection::TForm_subsection(TPrint_section* s, const char* nm) :
 | ||
| TForm_item(s), _ssec(&(s->form()), s->section_type(), s->page_type(), TRUE), _file_id(-1), _name(nm)
 | ||
| {}
 | ||
| 
 | ||
| TObject* TForm_subsection::dup() const
 | ||
| {
 | ||
|   TForm_subsection* fs = new TForm_subsection(_section);
 | ||
|   copy_to_form_item(fs);
 | ||
|   fs->_ssec = _ssec;
 | ||
|   fs->_name = _name;
 | ||
|   fs->_file_id = _file_id;
 | ||
|   return fs;  
 | ||
| }
 | ||
| 
 | ||
| bool TForm_subsection::parse(TScanner& s)
 | ||
| { 
 | ||
|   name(s.pop()); 
 | ||
|   _width  = s.integer();
 | ||
|   _height = s.integer();
 | ||
|   _x      = s.integer();    
 | ||
|   _y      = s.integer();    
 | ||
|   
 | ||
|   if (s.popkey() == "FI")     // FILE su cui iterare con next_match
 | ||
|     _file_id = s.integer();   // TBI controllo alias
 | ||
|   else s.push();
 | ||
|   
 | ||
|   return _ssec.parse(s); 
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TForm_subsection::update()
 | ||
| {    
 | ||
|   bool ok = FALSE;
 | ||
|   TRelation* rel = form().relation();
 | ||
|   
 | ||
|   if (rel == NULL || _file_id == -1)
 | ||
|     ok = _ssec.update();
 | ||
|   else
 | ||
|   { 
 | ||
|     int i = 0; 
 | ||
|     if (rel->is_first_match(_file_id)) 
 | ||
|       do {
 | ||
|         if (!(ok = _ssec.update()))
 | ||
|           break;   
 | ||
|         _ssec.set_repeat_count(++i);
 | ||
|       } 
 | ||
|     while (rel->next_match(_file_id));
 | ||
|     _ssec.set_repeat_count(0);
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TForm_subsection::edit(TMask& m)
 | ||
| {             
 | ||
|   // mask con nome e bottone edit contents / annulla
 | ||
|   TMask mu("ba2100u");     
 | ||
|   mu.set(F_CAPTION, _name);
 | ||
|   mu.set(F_WIDTH,   _width);
 | ||
|   mu.set(F_HEIGHT,  _height); 
 | ||
|   mu.set(F_X,       _x);
 | ||
|   mu.set(F_Y,       _y);
 | ||
|   
 | ||
|   mu.set_handler(F_BUT_FILE1, but_file_handler_sub);
 | ||
|   
 | ||
|   if (_file_id != -1)
 | ||
|   {
 | ||
|     // set file description  
 | ||
|     form().rel_desc().set_cur_file(_file_id);
 | ||
|     TString80 desc; desc << form().rel_desc().file_desc();
 | ||
|     mu.set(F_FILE1, desc);
 | ||
|   }
 | ||
|   
 | ||
|   KEY k; 
 | ||
|   
 | ||
|   // vedere se e' nuova etc. 
 | ||
|   // gestire aggiunta / modifica menu    
 | ||
|   
 | ||
|   while ((k = mu.run()) != K_ESC)
 | ||
|   {  
 | ||
|     if (mu.field(F_CAPTION).dirty())
 | ||
|       _name = mu.get(F_CAPTION);
 | ||
|     
 | ||
|     if (mu.field(F_WIDTH).dirty())
 | ||
|       _width = mu.get_int(F_WIDTH);
 | ||
|     
 | ||
|     if (mu.field(F_HEIGHT).dirty())
 | ||
|       _height = mu.get_int(F_HEIGHT);
 | ||
|     
 | ||
|     if (mu.field(F_X).dirty())
 | ||
|       _x = mu.get_int(F_X);
 | ||
|     
 | ||
|     if (mu.field(F_Y).dirty())
 | ||
|       _y = mu.get_int(F_Y);
 | ||
|     
 | ||
|     if (mu.field(F_FILE1).dirty())
 | ||
|     {
 | ||
|       if (mu.get(F_FILE1).empty())
 | ||
|         _file_id = -1;
 | ||
|       else
 | ||
|         _file_id = form().rel_desc().file_num();
 | ||
|     }
 | ||
|     
 | ||
|     if (k == K_INS)
 | ||
|       _ssec.edit(_name); 
 | ||
|     else if (k == K_DEL)
 | ||
|     { 
 | ||
|       // remove myself
 | ||
|       
 | ||
|     }
 | ||
|     else if (k == K_ENTER)
 | ||
|       break;    
 | ||
|   }
 | ||
| 
 | ||
|   return k != K_ESC;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TForm_subsection::print_on(ostream& out) const
 | ||
| { 
 | ||
|   out << "SEZIONE " << _name << ' ' << _width << ' ' << _height 
 | ||
|     << ' ' << _x << ' ' << _y;
 | ||
|   
 | ||
|   if (_file_id != -1)
 | ||
|     out << " FILE " << _file_id;
 | ||
|   out << "\n";
 | ||
| 
 | ||
|   for (word i = 0; i < _ssec.fields(); i++)
 | ||
|     out << _ssec.field(i);
 | ||
|   out << "\nEND" << "\n";
 | ||
| }
 | ||
| 
 | ||
| // ???
 | ||
| void TForm_subsection::show(bool on)
 | ||
| {
 | ||
|   for (unsigned int i = 0; i < _ssec.fields(); i++)
 | ||
|     _ssec.field(i).show(on);
 | ||
| }
 | ||
| 
 | ||
| // ???
 | ||
| void TForm_subsection::enable(bool on)
 | ||
| {
 | ||
|   for (unsigned int i = 0; i < _ssec.fields(); i++)
 | ||
|     _ssec.field(i).enable(on);
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_string
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TForm_string : public TForm_item
 | ||
| {
 | ||
|   TString _str, _picture;
 | ||
|   TArray _field;
 | ||
|   TToken_string _memo;
 | ||
| 
 | ||
| protected:
 | ||
|   virtual const char* class_name() const { return "STRINGA"; }
 | ||
|   virtual void print_body(ostream& out) const;
 | ||
| 
 | ||
|   virtual void print_on(TMask& m);
 | ||
|   virtual void read_from(const TMask& m);
 | ||
|   
 | ||
|   virtual bool read_from(const TRectype& rform);
 | ||
|   virtual void print_on(TRectype& rform);
 | ||
| 
 | ||
|   virtual void print_on(TToken_string& row);
 | ||
| 
 | ||
|   virtual bool parse_item(TScanner&);
 | ||
|   virtual bool read();
 | ||
|   virtual bool update();
 | ||
|   virtual const char* example() const;
 | ||
|   virtual void apply_format(TString& s, const TString& p) const;
 | ||
|   
 | ||
|   virtual TToken_string& memo_info() { return _memo; }
 | ||
|   
 | ||
|   virtual const char* get() const;
 | ||
|   bool set(const char*);
 | ||
| 
 | ||
|   TFieldref& field(int i) const { return (TFieldref&)_field[i]; }
 | ||
| 
 | ||
| public:
 | ||
|   virtual TObject* dup() const;
 | ||
|   virtual const int fields() { return _field.items();}
 | ||
|   virtual const TString& picture() const { return _picture; }
 | ||
|   virtual void  set_picture(const char* p) { _picture = p; }
 | ||
|   virtual void put_paragraph(const char* s);
 | ||
| 
 | ||
|   virtual bool edit(TMask& m); 
 | ||
|   TForm_string(TPrint_section* section);
 | ||
|   virtual ~TForm_string() {}
 | ||
| };
 | ||
| 
 | ||
| TForm_string::TForm_string(TPrint_section* section) 
 | ||
|             : TForm_item(section), _memo("",'\n')
 | ||
| {}
 | ||
| 
 | ||
| TObject* TForm_string::dup() const
 | ||
| {
 | ||
|   TForm_string* fs = new TForm_string(_section);
 | ||
|   copy_to_form_item(fs);
 | ||
|   fs->_str = _str;
 | ||
|   fs->_picture = _picture;
 | ||
|   fs->_field = _field;
 | ||
|   fs->_memo = _memo;
 | ||
|   return fs;  
 | ||
| }
 | ||
| 
 | ||
| bool TForm_string::edit(TMask& m)
 | ||
| { 
 | ||
|   const bool godmode = form().edit_level() > 1;
 | ||
|   m.enable(F_PROMPT, godmode ? TRUE : (_field.items()==0));
 | ||
|   return TForm_item::edit(m);
 | ||
| }                                 
 | ||
| 
 | ||
| bool TForm_string::parse_item(TScanner& scanner)
 | ||
| {
 | ||
|   if (scanner.key() == "FI")
 | ||
|   {
 | ||
|     TFieldref* fr = new TFieldref(scanner.line(), 0);
 | ||
|     _field.add(fr);        
 | ||
|     return TRUE;
 | ||
|   }
 | ||
| 
 | ||
|   if (scanner.key() == "PI")
 | ||
|   {
 | ||
|     set_picture(scanner.string());
 | ||
|     return TRUE;
 | ||
|   }
 | ||
| 
 | ||
|   return TForm_item::parse_item(scanner);
 | ||
| }
 | ||
| 
 | ||
| void TForm_string::print_body(ostream& out) const
 | ||
| {
 | ||
|   TForm_item::print_body(out);
 | ||
|   if (_picture.not_empty())
 | ||
|     out << " PICTURE \"" << _picture << "\"" << endl;
 | ||
|   for (int i = 0; i < _field.items(); i++)
 | ||
|     out << " FIELD " << field(i) << endl;
 | ||
| }  
 | ||
| 
 | ||
| bool TForm_string::read_from(const TRectype& prof)
 | ||
| { 
 | ||
|   bool changed = TForm_item::read_from(prof);
 | ||
| 
 | ||
|   const TString& pict = prof.get("PICT");
 | ||
|   if (_picture != pict)
 | ||
|   {
 | ||
|     _picture = pict;
 | ||
|     changed = TRUE;
 | ||
|   }  
 | ||
|   
 | ||
|   if (has_memo())
 | ||
|   {           
 | ||
|     const TString& m = prof.get("TESTO");
 | ||
|     if (_memo != m)
 | ||
|     {
 | ||
|       _memo = m;
 | ||
|       changed = TRUE;
 | ||
|     }  
 | ||
|   }
 | ||
|   
 | ||
|   return changed;
 | ||
| }
 | ||
| 
 | ||
| void TForm_string::print_on(TToken_string& row)
 | ||
| {
 | ||
|   TForm_item::print_on(row);  
 | ||
|   if (_field.items() && form().edit_level() > 1)
 | ||
|     row << '|' << field(0);
 | ||
| }
 | ||
| 
 | ||
| void TForm_string::print_on(TRectype& prof)
 | ||
| {
 | ||
|   TForm_item::print_on(prof);
 | ||
|   prof.put("PICT", _picture);
 | ||
|   if (has_memo())
 | ||
|   {
 | ||
|     prof.put("TESTO", _memo);
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TForm_string::print_on(TMask& m)
 | ||
| {
 | ||
|   TForm_item::print_on(m);
 | ||
|   for (int i = 0; i < _field.items(); i++)
 | ||
|     put_fieldref(field(i), m.field(i == 0 ? F_FIELDREF1 : F_FIELDREF2));
 | ||
|   
 | ||
|   m.set(F_PICTURE, _picture);
 | ||
|   m.set(F_MEMO, _memo);
 | ||
|   
 | ||
|   TSheet_field& s = (TSheet_field&)m.field(F_ITEMS);
 | ||
|   s.reset();
 | ||
|   if (_message.items() > 0)
 | ||
|   {
 | ||
|     TToken_string& row = s.row(0);
 | ||
|     row = " | ";
 | ||
|     row.add(message(0));
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TForm_string::read_from(const TMask& m)
 | ||
| {
 | ||
|   TForm_item::read_from(m);
 | ||
|   _picture = m.get(F_PICTURE);
 | ||
|   _memo    = m.get(F_MEMO);
 | ||
|   
 | ||
|   for (int i = 0; i < 2; i++)
 | ||
|   {
 | ||
|     const TString& f = m.get(i == 0 ? F_FIELDREF1 : F_FIELDREF2);
 | ||
|     if (f.not_empty())
 | ||
|     {
 | ||
|       TFieldref* fr = (TFieldref*)_field.objptr(i);
 | ||
|       if (fr == NULL) 
 | ||
|       {
 | ||
|         fr = new TFieldref(f, 0);
 | ||
|         _field.add(fr, i);
 | ||
|       }
 | ||
|       *fr = f;
 | ||
|     }  
 | ||
|     else
 | ||
|       _field.destroy(i);                  
 | ||
|   }  
 | ||
|   
 | ||
|   TSheet_field& f = (TSheet_field&)m.field(F_ITEMS);
 | ||
|   TToken_string& msg = f.row(0);
 | ||
|   if (msg.empty_items())
 | ||
|     _message.destroy(0);
 | ||
|   else
 | ||
|     _message.add(msg.get(2), 0);
 | ||
| }
 | ||
| 
 | ||
| bool TForm_string::set(const char* s)
 | ||
| {
 | ||
|   _str = s;
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| const char* TForm_string::get() const
 | ||
| { return _str; }
 | ||
| 
 | ||
| 
 | ||
| // Se un campo e' abilitato ed ha almeno un riferimento su file leggilo 
 | ||
| bool TForm_string::read()
 | ||
| {
 | ||
|   const bool ok = enabled();
 | ||
|   if (ok)
 | ||
|   {                    
 | ||
|     if (_field.items() != 0)
 | ||
|     {
 | ||
|       const char* s = "";
 | ||
|       const TRelation* r = form().relation();
 | ||
|       CHECK(r, "Can't read from null relation");
 | ||
|       for (int i = 0; i < _field.items() && *s == '\0'; i++)
 | ||
|         s = field(i).read(*r);
 | ||
|       set(s);
 | ||
|     }  
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| void TForm_string::put_paragraph(const char* s)
 | ||
| {
 | ||
|   if (hidden()) return;
 | ||
|   
 | ||
|   if (height() > 1)
 | ||
|   {
 | ||
|     TParagraph_string p(s, width());
 | ||
|     int i = _prompt.not_empty() ? 1 : 0;
 | ||
|     for (; (s = p.get()) != NULL && i < height(); i++)
 | ||
|       string_at(x(), _y+i, s);
 | ||
|   }
 | ||
|   else
 | ||
|     string_at(-1, _y, s);
 | ||
| }
 | ||
| 
 | ||
|                          
 | ||
| void TForm_string::apply_format(TString& s, const TString& p) const
 | ||
| {                     
 | ||
|   TString tmp(s);
 | ||
|   if (!p.blank())
 | ||
|   {           
 | ||
|     TToken_string delim(4, ',');         // Stringa con i due delimitatori
 | ||
|     const char* pic = p;                 // Picture senza delimitatori
 | ||
|       
 | ||
|     if (pic[0] == '(')                   // Se ci sono i delimitatori ...
 | ||
|     {
 | ||
|       const int bra = p.find(')'); 
 | ||
|       if (bra > 0)                       // ... cerca la parentesi chiusa
 | ||
|       {
 | ||
|         delim = p.sub(1, bra);   // memorizza delimitatori
 | ||
|         pic += bra+1;                    // toglili dalla picture
 | ||
|       }  
 | ||
|     }
 | ||
|       
 | ||
|     if (class_name() == "DATA" && s.empty()) 
 | ||
|       tmp ="";
 | ||
|     else
 | ||
|       tmp.picture(pic, s);               // riempi la stringa col valore pitturato
 | ||
| 
 | ||
|     if (!delim.empty_items())            // Aggiungi delimitatori
 | ||
|     {
 | ||
|       TString16 d(delim.get(0)); 
 | ||
|       const int ld = d.len();
 | ||
|         
 | ||
|       if (ld > 0)                  // Se il primo delimitatore e' valido ...
 | ||
|       {
 | ||
|         for (int spc = 0;s[spc]==' ' ; spc++) ;
 | ||
|         if (spc < ld)
 | ||
|         {         
 | ||
|           TString16 spazi;
 | ||
|           spazi.spaces(ld - spc);
 | ||
|           tmp.insert(spazi,0);
 | ||
|           spc = ld; 
 | ||
|         }
 | ||
|         tmp.overwrite(d,spc - ld);
 | ||
|       }
 | ||
|       d = delim.get(); 
 | ||
|       if (d.not_empty())                 // Se il secondo delimitatore e' valido ...
 | ||
|         tmp << d;                          // ... aggiungilo alla fine
 | ||
|     }  
 | ||
|     s = tmp;
 | ||
|   }
 | ||
| }                         
 | ||
|                          
 | ||
| bool TForm_string::update()
 | ||
| {
 | ||
|   if (read())
 | ||
|   {
 | ||
|     TString s;
 | ||
|     TForm_item::update();
 | ||
|     if (!picture().blank())
 | ||
|     {    
 | ||
|       s = get();
 | ||
|       apply_format(s, picture());         
 | ||
|       put_paragraph(s);  
 | ||
|     } 
 | ||
|     else 
 | ||
|       put_paragraph(s=get());                // Stampa immediata senza picture
 | ||
|     const int n = (_message.objptr(1) != NULL  && s.empty() ? 1 : 0);
 | ||
|     do_message(n);
 | ||
|   }        
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| const char* TForm_string::example() const
 | ||
| { 
 | ||
|   TString prova("XXXXXXXXXXXXXXXXXXXXXXXXXX");
 | ||
|   apply_format(prova, picture());
 | ||
|   const int w = width();
 | ||
|   if (prova.size() > w && w > 0) prova.cut(w);
 | ||
|   return strcpy(__tmp_string, prova);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_number
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TForm_number : public TForm_string
 | ||
| {                  
 | ||
|   void apply_format(real& r, TString& s) const;
 | ||
|   
 | ||
| protected: // TForm_string             
 | ||
|   virtual const char* class_name() const { return "NUMERO"; }
 | ||
|   virtual bool parse_head(TScanner& scanner);
 | ||
|   virtual bool update();
 | ||
|   //virtual int height() const { return 0; }
 | ||
| 
 | ||
| protected:  
 | ||
|   int decimals() const { return _height; }
 | ||
| 
 | ||
| public:
 | ||
| 
 | ||
|   virtual TObject* dup() const;
 | ||
|   void set_decimals(int d) { _height = d; }
 | ||
|   virtual const char* example() const;
 | ||
|   virtual void set_picture(const char* p);
 | ||
|   virtual void put_paragraph(const char * s);
 | ||
| 
 | ||
|   TForm_number(TPrint_section* section) : TForm_string(section) {}
 | ||
|   virtual ~TForm_number() {}
 | ||
| };
 | ||
| 
 | ||
| bool TForm_number::parse_head(TScanner& scanner)
 | ||
| {                         
 | ||
|   return TForm_item::parse_head(scanner);
 | ||
| }
 | ||
| 
 | ||
| TObject* TForm_number::dup() const
 | ||
| {
 | ||
|   TForm_number *fn = new TForm_number(_section);
 | ||
|   copy_to_form_item(fn);
 | ||
|   return fn;
 | ||
| }
 | ||
| 
 | ||
| void TForm_number::put_paragraph(const char* s)
 | ||
| {
 | ||
|   if (hidden()) return;
 | ||
|   
 | ||
|   int gap = 0;
 | ||
|   if (section().columnwise())
 | ||
|   {
 | ||
|     const int w = width();
 | ||
|     const int l = strlen(s);
 | ||
|     if (w>l) gap = w-l;
 | ||
|   }
 | ||
|   if (_prompt.empty())
 | ||
|     string_at(x()+gap, _y, s);
 | ||
|   else
 | ||
|     string_at(-1, _y, s); // se ha il prompt stampa all'ultima posizione raggiunta
 | ||
| }
 | ||
| 
 | ||
| bool TForm_number::update()
 | ||
| {
 | ||
|   if (read())
 | ||
|   {
 | ||
|     TForm_item::update();
 | ||
|     real n(get());
 | ||
|     n.round(decimals());
 | ||
|     
 | ||
|     if (!n.is_zero())
 | ||
|     {
 | ||
|       TString s;
 | ||
|       apply_format(n,s);
 | ||
|       put_paragraph(s);
 | ||
|       do_message(); 
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       const int n = (_message.objptr(1) != NULL ? 1 : 0);
 | ||
|       do_message(n);
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   return TRUE;  
 | ||
| }
 | ||
| 
 | ||
| void TForm_number::apply_format(real& n , TString& s) const
 | ||
| {
 | ||
|   if (!picture().blank())
 | ||
|   {           
 | ||
|     TToken_string delim(4, ',');         // Stringa con i due delimitatori
 | ||
|     TString pic(picture());              // Picture senza delimitatori
 | ||
|     int maxlen = -1;
 | ||
|     int comma = pic.find(',');
 | ||
|     int at = pic.find('@');
 | ||
|     if (at >= 0 && comma <0)       
 | ||
|     {
 | ||
|       maxlen = atoi(&pic[at+1]);
 | ||
|       pic.cut(at);
 | ||
|     }
 | ||
|     if (pic[0] == '(')                   // Se ci sono i delimitatori ...
 | ||
|     {
 | ||
|       const int bra = pic.find(')'); 
 | ||
|       if (bra > 0)                       // ... cerca la parentesi chiusa
 | ||
|       {
 | ||
|         delim = pic.sub(1, bra);         // memorizza delimitatori
 | ||
|         pic.ltrim(bra + 1);              // toglili dalla picture
 | ||
|       }  
 | ||
|     }
 | ||
|         
 | ||
|     s=n.string(pic);          // riempi la stringa col valore pitturato
 | ||
|         
 | ||
|     if (maxlen >= 0 && maxlen < s.size())
 | ||
|       s.cut(maxlen);
 | ||
|     if (!delim.empty_items())            // Aggiungi delimitatori
 | ||
|     {
 | ||
|       TString16 d(delim.get(0)); 
 | ||
|       const int ld = d.len();
 | ||
|       
 | ||
|       if (ld > 0)                  // Se il primo delimitatore e' valido ...
 | ||
|       {
 | ||
|         for (int spc = 0;s[spc]==' ' ; spc++) ;
 | ||
|         if (spc < ld)
 | ||
|         {
 | ||
|           TString16 spazi;
 | ||
|            spazi.spaces(ld - spc);
 | ||
|            s.insert(spazi,0);
 | ||
|            spc = ld; 
 | ||
|          }
 | ||
|          s.overwrite(d,spc - ld);
 | ||
|        }
 | ||
|        d = delim.get(); 
 | ||
|        if (d.not_empty())                 // Se il secondo delimitatore e' valido ...
 | ||
|          s << d;                          // ... aggiungilo alla fine
 | ||
|     }  
 | ||
|   } 
 | ||
|   else s = n.string();
 | ||
| }
 | ||
| 
 | ||
| void TForm_number::set_picture(const char *p)
 | ||
| {
 | ||
|   TForm_string::set_picture(p);
 | ||
|   const int comma = picture().find(',');
 | ||
|   if (comma > 0) set_decimals(picture().len() - comma -1);
 | ||
| }   
 | ||
| 
 | ||
| const char* TForm_number::example() const
 | ||
| {
 | ||
|   real n("123456789120.00"); n.round(2);
 | ||
|   TString s;
 | ||
|   apply_format(n,s);
 | ||
|   return strcpy(__tmp_string, s);
 | ||
| }
 | ||
|                         
 | ||
|                         
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_date
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TForm_date : public TForm_string
 | ||
| {
 | ||
|   TString16 _format;
 | ||
| 
 | ||
| protected:
 | ||
|   virtual const char* class_name() const { return "DATA"; }
 | ||
|   virtual bool read();
 | ||
|   virtual bool set(const char*);
 | ||
|   bool set(const TDate& d);
 | ||
|   virtual bool parse_item(TScanner& scanner);
 | ||
|   virtual void print_body(ostream& out) const;
 | ||
|   
 | ||
|   virtual void print_on(TMask& m);
 | ||
|   virtual void read_from(const TMask& m);
 | ||
|   
 | ||
|   virtual bool read_from(const TRectype& rform);
 | ||
|   virtual void print_on(TRectype& rform);
 | ||
|   
 | ||
| public:
 | ||
|   
 | ||
|   virtual TObject* dup() const;
 | ||
|   void set_format(const char* f) { _format = f; }
 | ||
|   virtual bool edit(TMask& m);
 | ||
|   virtual const char* example() const;
 | ||
|   TForm_date(TPrint_section* section);
 | ||
|   virtual ~TForm_date() {}
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| TForm_date::TForm_date(TPrint_section* section) 
 | ||
| : TForm_string(section), _format("1444-")
 | ||
| {}
 | ||
| 
 | ||
| TObject* TForm_date::dup() const
 | ||
| {
 | ||
|   TForm_date* fd = new TForm_date(_section);
 | ||
|   copy_to_form_item(fd);
 | ||
|   fd->_format = _format;
 | ||
|   return fd;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_date::read()
 | ||
| {                        
 | ||
|   bool ok = TForm_string::read();
 | ||
|   if (ok && !get()[0] && automagic()) 
 | ||
|     set(printer().getdate());
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| void TForm_date::print_body(ostream& out) const
 | ||
| {
 | ||
|   TForm_string::print_body(out);
 | ||
|   out << " FORMAT \"" << _format << "\"\n";
 | ||
| }
 | ||
| 
 | ||
| bool TForm_date::parse_item(TScanner& scanner)
 | ||
| {
 | ||
|   if (scanner.key() == "FO")
 | ||
|   {
 | ||
|     _format = scanner.string();
 | ||
|     return TRUE;
 | ||
|   }
 | ||
|   return TForm_string::parse_item(scanner);
 | ||
| }
 | ||
| 
 | ||
| bool TForm_date::read_from(const TRectype& prof)
 | ||
| { 
 | ||
|   bool changed = TForm_string::read_from(prof);
 | ||
|   
 | ||
|   const TString& df = prof.get("DATEFORM");
 | ||
|   if (df.not_empty() && df != _format)
 | ||
|   {
 | ||
|     _format = df;
 | ||
|     changed = TRUE;
 | ||
|   }  
 | ||
|   
 | ||
|   return changed;
 | ||
| }
 | ||
| 
 | ||
| void TForm_date::print_on(TRectype& prof)
 | ||
| { 
 | ||
|   TForm_string::print_on(prof);
 | ||
|   prof.put("DATEFORM", _format);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TForm_date::set(const char* s)
 | ||
| {
 | ||
|   const TDate da(s);
 | ||
|   return set(da);
 | ||
| }
 | ||
| 
 | ||
| bool TForm_date::set(const TDate& da)
 | ||
| {
 | ||
|   TFormatted_date d(da); d.set_format(_format);
 | ||
|   TForm_string::set(d.string());
 | ||
|   return TRUE;
 | ||
| }                             
 | ||
| 
 | ||
| void TForm_date::print_on(TMask& m)
 | ||
| {                        
 | ||
|   const TDate dd(TODAY);
 | ||
|   TFormatted_date d(dd); d.set_format(_format);           
 | ||
|   m.set(F_DEXAMPLE, d.string());
 | ||
|   
 | ||
|   m.set(F_DFORMAT, _format.mid(0,1));
 | ||
|   m.set(F_DDAY,    _format.mid(1,1));
 | ||
|   m.set(F_DMONTH,  _format.mid(2,1));
 | ||
|   m.set(F_DYEAR,   _format.mid(3,1));
 | ||
|   m.set(F_DSEP,    _format.mid(4,1));
 | ||
| 
 | ||
|   TForm_string::print_on(m);
 | ||
| }
 | ||
| 
 | ||
| void TForm_date::read_from(const TMask& m)
 | ||
| {
 | ||
|   TForm_string::read_from(m);
 | ||
| 
 | ||
|   // adjust format string
 | ||
|   _format[0] = m.get(F_DFORMAT)[0];
 | ||
|   _format[1] = m.get(F_DDAY   )[0];
 | ||
|   _format[2] = m.get(F_DMONTH )[0];
 | ||
|   _format[3] = m.get(F_DYEAR  )[0];
 | ||
|   _format[4] = m.get(F_DSEP   )[0];   
 | ||
|   _format[5] = '\0';
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| bool TForm_date::edit(TMask& m)
 | ||
| {         
 | ||
|   return TForm_string::edit(m);
 | ||
| }
 | ||
| 
 | ||
| const char* TForm_date::example() const
 | ||
| { 
 | ||
|   const TDate dd(TODAY);
 | ||
|   TFormatted_date d(dd); d.set_format(_format);           
 | ||
|   TString s(d.string());
 | ||
|   return strcpy(__tmp_string, s);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_list
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TForm_list : public TForm_string
 | ||
| {
 | ||
|   TToken_string _codes;
 | ||
|   TToken_string _values;
 | ||
| 
 | ||
| protected:
 | ||
|   virtual const char* class_name() const { return "LISTA"; }
 | ||
|   virtual bool parse_item(TScanner& scanner); 
 | ||
|   virtual void print_on(TMask& m);
 | ||
|   virtual void read_from(const TMask& m);
 | ||
|   virtual void print_body(ostream& out) const;
 | ||
|   virtual bool update();
 | ||
| 
 | ||
| public:
 | ||
|   virtual TObject* dup() const;
 | ||
|   TForm_list(TPrint_section* section);
 | ||
|   virtual ~TForm_list() {}
 | ||
| };
 | ||
| 
 | ||
| TForm_list::TForm_list(TPrint_section* section)
 | ||
| : TForm_string(section)
 | ||
| {}
 | ||
| 
 | ||
| TObject* TForm_list::dup() const
 | ||
| {
 | ||
|   TForm_list* fl = new TForm_list(_section);
 | ||
|   copy_to_form_item(fl);
 | ||
|   fl->_codes = _codes;
 | ||
|   fl->_values = _values;
 | ||
|   return fl;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_list::parse_item(TScanner& scanner)
 | ||
| {
 | ||
|   if (scanner.key() == "IT")
 | ||
|   {
 | ||
|     TToken_string s(scanner.string());
 | ||
|     _codes.add(s.get());
 | ||
|     _values.add(s.get());
 | ||
|     
 | ||
|     while (scanner.popkey() == "ME")
 | ||
|     {
 | ||
|       TFixed_string m(scanner.line());
 | ||
|       m.strip_spaces();
 | ||
|       message(_values.items()-1).add(m);
 | ||
|     }
 | ||
|     scanner.push();
 | ||
|     return TRUE;
 | ||
|   }
 | ||
| 
 | ||
|   return TForm_string::parse_item(scanner);
 | ||
| }
 | ||
| 
 | ||
| void TForm_list::print_on(TMask& m)
 | ||
| {       
 | ||
|   TForm_string::print_on(m);
 | ||
|   TSheet_field& s = (TSheet_field&)m.field(F_ITEMS);
 | ||
|   s.reset();
 | ||
|   _codes.restart(); _values.restart(); 
 | ||
|   for (int i = 0; i < _codes.items(); i++)
 | ||
|   {
 | ||
|     TToken_string& row = s.row(i);
 | ||
|     row = _codes.get();
 | ||
|     row.add(_values.get());
 | ||
|     row.add(message(i));
 | ||
|   }
 | ||
|   //  s.force_update();
 | ||
| }
 | ||
| 
 | ||
| void TForm_list::read_from(const TMask& m)
 | ||
| {
 | ||
|   TForm_string::read_from(m);
 | ||
| 
 | ||
|   TSheet_field& s = (TSheet_field&)m.field(F_ITEMS);
 | ||
|   
 | ||
|   _codes = _values = ""; 
 | ||
|   for (int i = 0; i < s.items(); i++)
 | ||
|   {
 | ||
|     TToken_string& row = s.row(i);
 | ||
|     _codes.add(row.get(0));
 | ||
|     _values.add(row.get());
 | ||
|     message(i) = row.get();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TForm_list::print_body(ostream& out) const
 | ||
| {
 | ||
|   TForm_string::print_body(out);
 | ||
| 
 | ||
|   TToken_string& cod = (TToken_string&)_codes; // Trick to skip const
 | ||
|   TToken_string& val = (TToken_string&)_values;
 | ||
| 
 | ||
|   int i = 0;
 | ||
|   TString c(cod.get(0));
 | ||
|   TString v(val.get(0));
 | ||
| 
 | ||
|   for (; c[0]; c = cod.get(), v = val.get(), i++)
 | ||
|   {
 | ||
|     out << " ITEM \"" << c;
 | ||
|     if (v.not_empty()) out << '|' << v;
 | ||
|     out << '"';
 | ||
| 
 | ||
|     const char* m = ((TForm_list*)this)->message(i);
 | ||
|     if (*m) out << " MESSAGE " << m;
 | ||
| 
 | ||
|     out << endl;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TForm_list::update()
 | ||
| {
 | ||
|   bool ok = TRUE;
 | ||
| 
 | ||
|   if (!read()) return ok;
 | ||
| 
 | ||
|   const TString& val =get();
 | ||
|   int pos = _codes.get_pos(val);
 | ||
|   if (pos < 0)
 | ||
|   {
 | ||
|     TString def= _codes.get(0);
 | ||
|     def.trim();
 | ||
|     if (val == def) pos = 0; // Test default (first & empty) value
 | ||
|     else
 | ||
|     {
 | ||
|       ok = yesno_box("Il campo '%s' non puo' valere '%s': continuare ugualmente",
 | ||
|                      (const char*)key(), (const char*)val);
 | ||
|       set(_codes.get(pos = 0));               
 | ||
|     }
 | ||
|   }
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     do_message(pos);
 | ||
| 
 | ||
|     if (!hidden())
 | ||
|     {
 | ||
|       const char* c = _values.get(pos);
 | ||
|       if (c == NULL) c = val;
 | ||
|       if (c) string_at(x(), _y, c);
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm_group
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TForm_group : public TForm_item
 | ||
| {
 | ||
| protected:
 | ||
|   virtual const char* class_name() const { return "GRUPPO"; }
 | ||
|   virtual bool update() { return TRUE; }
 | ||
| 
 | ||
| public:
 | ||
|   TForm_group(TPrint_section* section) : TForm_item(section) {};
 | ||
|   virtual ~TForm_group() {}
 | ||
| };
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TGraphic_section
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TGraphic_section : public TPrint_section
 | ||
| {
 | ||
|   TString _back;                                        
 | ||
| 
 | ||
| protected:  
 | ||
|   TForm_item* parse_item(const TString& s);
 | ||
|   bool update();
 | ||
|   
 | ||
| public:
 | ||
|   void append(const char* s) { _back << s; }
 | ||
| 
 | ||
|   TGraphic_section(TForm* f, pagetype pt) : TPrint_section(f, 'G', pt) {}  
 | ||
|   virtual ~TGraphic_section() {}
 | ||
| };
 | ||
| 
 | ||
| class TForm_picture : public TForm_item
 | ||
| {
 | ||
| protected:
 | ||
|   virtual const char* class_name() const { return "FIGURA"; }
 | ||
|   virtual bool update();
 | ||
| 
 | ||
| public:
 | ||
|   TForm_picture(TGraphic_section* section) : TForm_item(section) {}
 | ||
|   virtual ~TForm_picture() {}
 | ||
| };
 | ||
| 
 | ||
| class TForm_line : public TForm_item
 | ||
| {
 | ||
| protected:
 | ||
|   virtual const char* class_name() const { return "LINEA"; }
 | ||
|   virtual bool update();
 | ||
| 
 | ||
| public:
 | ||
|   TForm_line(TGraphic_section* section) : TForm_item(section) {}
 | ||
|   virtual ~TForm_line() {}
 | ||
| };
 | ||
| 
 | ||
| class TForm_box : public TForm_item
 | ||
| {
 | ||
| protected:
 | ||
|   virtual const char* class_name() const { return "BOX"; }
 | ||
|   virtual bool update();
 | ||
| 
 | ||
| public:
 | ||
|   TForm_box(TGraphic_section* section) : TForm_item(section) {}
 | ||
|   virtual ~TForm_box() {}
 | ||
| };
 | ||
| 
 | ||
| bool TForm_picture::update()
 | ||
| {                        
 | ||
|   const bool ok = _prompt.not_empty();
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     TString80 i;
 | ||
|     i << "i{" << _prompt << ',' << _x << ',' << _y << ',' 
 | ||
|       << (_x+width()-1) << ',' << (_y+height()-1) << '}';
 | ||
|     ((TGraphic_section&)section()).append(i);
 | ||
|   }  
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_line::update()
 | ||
| {                                        
 | ||
|   int spessore = 1;
 | ||
|   char codice = 'l';
 | ||
|   for (int j = _prompt.len()-1; j >= 0; j--)
 | ||
|   {
 | ||
|     switch (_prompt[j])
 | ||
|     {        
 | ||
|     case 'B':
 | ||
|     case 'b':
 | ||
|       spessore = 3; break;
 | ||
|     case 'R':
 | ||
|     case 'r':
 | ||
|       codice = 'r'; break;
 | ||
|     default:
 | ||
|       break;    
 | ||
|     }
 | ||
|   }  
 | ||
| 
 | ||
|   TString80 i;      
 | ||
|   i << 'W' << spessore << codice
 | ||
|     << '{' << _x << ',' << _y << ','
 | ||
|     << (_x+width()-1) << ',' << (_y+height()-1) << '}';
 | ||
|   
 | ||
|   ((TGraphic_section&)section()).append(i);
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| bool TForm_box::update()
 | ||
| {                                        
 | ||
|   TString80 i;
 | ||
|   const int w = _prompt[0] == '@' ? 3 : 1; 
 | ||
|   i << 'W' << w << "b{" << _x << ',' << _y << ','
 | ||
|     << (_x+width()-1) << ',' << (_y+height()-1) << '}';
 | ||
|   
 | ||
|   ((TGraphic_section&)section()).append(i);
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TForm_item* TGraphic_section::parse_item(const TString& s)
 | ||
| {
 | ||
|   if (s == "FI")
 | ||
|     return new TForm_picture(this);
 | ||
|   else if (s == "LI")
 | ||
|     return new TForm_line(this);
 | ||
|   else if (s == "BO")
 | ||
|     return new TForm_box(this);
 | ||
| 
 | ||
|   error_box("Campo di stampa non ammesso per lo sfondo: %s", (const char*)s);
 | ||
|   return NULL;  
 | ||
| }
 | ||
| 
 | ||
| bool TGraphic_section::update()
 | ||
| {                       
 | ||
|   _back = "";
 | ||
|   const bool ok = TPrint_section::update();
 | ||
|   printer().setbackground(_back);
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TPrint_section
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| HIDDEN bool font_handler(TMask_field& f, KEY key)
 | ||
| {
 | ||
|   if (key == K_SPACE)
 | ||
|   {                
 | ||
|     main_app().begin_wait();           
 | ||
| 
 | ||
|     const char* family = f.get();
 | ||
|     const int MAXSIZES = 16;
 | ||
|     long sizes[MAXSIZES]; 
 | ||
|     BOOLEAN scalable;
 | ||
|     const int num_sizes = (int)xvt_fmap_get_family_sizes(printer().get_printrcd(), 
 | ||
|                                                          (char*)family, sizes, &scalable, MAXSIZES);
 | ||
|     
 | ||
|     TToken_string pn1(80), pn2(80);                                                    
 | ||
|     if (scalable)
 | ||
|     {
 | ||
|       for (int i = 4; i <= 32; i++)
 | ||
|       {
 | ||
|         pn1.add(i);
 | ||
|         pn2.add(i);
 | ||
|       }               
 | ||
|     }  
 | ||
|     else                           
 | ||
|     {
 | ||
|       if (num_sizes > 0)
 | ||
|       {
 | ||
|         for (int i = 0; i < num_sizes; i++)
 | ||
|           pn1.add(sizes[i]);
 | ||
|       }
 | ||
|       else pn1.add(printer().get_char_size());
 | ||
|       pn2 = pn1;
 | ||
|     }
 | ||
|     TList_field& lst = (TList_field&)f.mask().field(F_SIZE);
 | ||
|     lst.replace_items(pn1, pn2);
 | ||
|     lst.set(format("%d",printer().get_char_size()));
 | ||
|     
 | ||
|     main_app().end_wait();           
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| TMask* TPrint_section::_msk = NULL;
 | ||
| 
 | ||
| 
 | ||
| TPrint_section::TPrint_section(TForm* f, char st, pagetype pt, bool sub) 
 | ||
| : _height(0), _form(f), _sec_type(st), _page_type(pt), _dirty(FALSE),
 | ||
|   _subsection(sub), _repeat_count(0), _ofspc(0), _ofsvr(0), _nfld(0), _temp(0),
 | ||
|   _columnwise(FALSE)
 | ||
| { 
 | ||
|   reset_tabs(); 
 | ||
| }
 | ||
| 
 | ||
| TPrint_section::~TPrint_section()
 | ||
| {
 | ||
|   if (_msk) 
 | ||
|   {
 | ||
|     delete _msk;
 | ||
|     _msk = NULL;
 | ||
|   }  
 | ||
| }
 | ||
| 
 | ||
| void  TPrint_section::change_field(int n, TForm_item* f)
 | ||
| {  
 | ||
|   _item.add(f,n);
 | ||
| }
 | ||
| 
 | ||
| void  TPrint_section::insert_field(int n, TForm_item* f)
 | ||
| {  
 | ||
|   _item.insert(f,n);
 | ||
| }
 | ||
| 
 | ||
| void  TPrint_section::add_field(TForm_item* f)
 | ||
| {  
 | ||
|   _item.add(f);
 | ||
| }
 | ||
| 
 | ||
| const TPrint_section& TPrint_section::copy(const TPrint_section& ps)
 | ||
| {
 | ||
|   _msk = ps._msk;  _height = ps._height;  _ofspc = ps._ofspc;
 | ||
|   _ofsvr = ps._ofsvr;  _nfld  = ps._nfld;  _dirty = ps._dirty;
 | ||
|   _columnwise = ps._columnwise;  _temp = ps._temp; _form = ps._form;
 | ||
|   _sec_type = ps._sec_type; _page_type = ps._page_type; _subsection = ps._subsection;
 | ||
|   _item = ps._item; _repeat_count = ps._repeat_count;
 | ||
|   for (int i = 0; i < MAXCOLUMNS; i++) _tab[i] = ps._tab[i];
 | ||
|   return ps;
 | ||
| }
 | ||
| 
 | ||
| TPrintrow& TPrint_section::row(int num)
 | ||
| {
 | ||
|   TPrintrow* pr = (TPrintrow*)objptr(num);
 | ||
|   if (pr == NULL)
 | ||
|   {
 | ||
|     pr = new TPrintrow;
 | ||
|     add(pr, num);
 | ||
|   }
 | ||
|   return *pr;
 | ||
| }
 | ||
| 
 | ||
| void TPrint_section::reset_tabs()
 | ||
| {
 | ||
|   for (int i = 0; i < MAXCOLUMNS; i++)
 | ||
|     _tab[i] = -1;
 | ||
| }
 | ||
|           
 | ||
| int TPrint_section::tab(int col)
 | ||
| {  
 | ||
|   int ret = -1;
 | ||
|   if (_columnwise)
 | ||
|   {   
 | ||
|     if (_tab[0] == -1)  
 | ||
|     {
 | ||
|       // compute column offset 
 | ||
|       _nfld = 0;   
 | ||
|       _tab[0] = 2;
 | ||
|       short maxcolreached = 0;
 | ||
|       for (word i = 0; i < fields(); i++) 
 | ||
|       {                                                                    
 | ||
|         if (field(i).shown())
 | ||
|         {                 
 | ||
|           CHECKD (field(i)._x < MAXCOLUMNS, "Colonna ammessa e non concessa: ", field(i)._x);
 | ||
|           _tab[field(i)._x] = field(i)._width + 1; // one is for separation 
 | ||
|           if (field(i)._x > maxcolreached) maxcolreached = field(i)._x;
 | ||
|           _nfld++;
 | ||
|         }
 | ||
|       }                   
 | ||
|       // cumulate offsets
 | ||
|       int last = 0;
 | ||
|       for (i = 1; i <= (word)maxcolreached; i++)
 | ||
|       { 
 | ||
|         if (_tab[i - 1] != -1)
 | ||
|           last = i - 1;
 | ||
|         if (_tab[i] != -1)
 | ||
|           _tab[i] += _tab[last];  
 | ||
|       }  
 | ||
|     } 
 | ||
|     // se manca la colonna, vai a prendere quella immediatamente prima              
 | ||
|     while (_tab[col] == -1 && col > 0)  
 | ||
|       col--;
 | ||
|     ret = _tab[col];
 | ||
|   }    
 | ||
|   return ret;                     
 | ||
| }          
 | ||
|           
 | ||
| void TPrint_section::offset(int& x, int& y)
 | ||
| { 
 | ||
|   if (x >= 0)
 | ||
|   {
 | ||
|     if (_columnwise) x = tab(x-1) + _ofspc;
 | ||
|     x += form().offset_x();
 | ||
|   }
 | ||
|   if (y >= 0) y += form().offset_y() + (_height * _repeat_count);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TForm_item* TPrint_section::parse_item(const TString& s)
 | ||
| {
 | ||
|   if (s == "ST")
 | ||
|     return new TForm_string(this);
 | ||
|   if (s == "NU")
 | ||
|     return new TForm_number(this);
 | ||
|   if (s == "DA")
 | ||
|     return new TForm_date(this);
 | ||
|   if (s == "LI")
 | ||
|     return new TForm_list(this);
 | ||
|   if (s == "GR")
 | ||
|     return new TForm_group(this);
 | ||
|   if (s == "SE")
 | ||
|     return new TForm_subsection(this); 
 | ||
|   
 | ||
|   yesnofatal_box("Campo di stampa non ammesso per la sezione di stampa: %s", (const char*)s);
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TForm_item* TPrint_section::parse_item(TScanner& scanner)
 | ||
| {
 | ||
|   return parse_item(scanner.key());
 | ||
| }
 | ||
| 
 | ||
| bool TPrint_section::parse(TScanner& scanner)
 | ||
| {
 | ||
|   _height = scanner.integer();  
 | ||
|   scanner.integer();scanner.integer(); // Eat offset X and Y of Print_section if present
 | ||
| 
 | ||
|   if (scanner.popkey() == "CO")        // COLUMNWISE attribute
 | ||
|     _columnwise = TRUE;
 | ||
|   else
 | ||
|   {
 | ||
|     _columnwise = FALSE;
 | ||
|     scanner.push();
 | ||
|   }                                                           
 | ||
|   
 | ||
|   while (scanner.popkey() != "EN")
 | ||
|   {
 | ||
|     TForm_item *fi = parse_item(scanner);
 | ||
|     if (fi == NULL) return FALSE;
 | ||
| 
 | ||
|     if (fi->parse(scanner))
 | ||
|       _item.add(fi);
 | ||
|     else
 | ||
|       return FALSE;
 | ||
|   }        
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| // Azzera tutte le righe della sezione di stampa
 | ||
| void TPrint_section::reset()
 | ||
| {
 | ||
|   for (word i = 0; i < height(); i++)
 | ||
|     row(i).reset();
 | ||
| }
 | ||
| 
 | ||
| // Aggiorna tutti i campi e li stampa
 | ||
| bool TPrint_section::update()
 | ||
| {
 | ||
|   bool ok = TRUE;
 | ||
|   
 | ||
|   reset();
 | ||
|   for (word i = 0; i < fields(); i++)
 | ||
|   {
 | ||
|     const bool esito = field(i).update();
 | ||
|     if (!esito) ok = FALSE;
 | ||
|   }
 | ||
| 
 | ||
|   return ok;
 | ||
| } 
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Legge dal record <p rec> altezza e offset prima colonna della sezione
 | ||
| //
 | ||
| // @rdesc Ritorna se i valori letti hanno modificato quelli attuali
 | ||
| bool TPrint_section::read_from(
 | ||
|      const TRectype& prof)  // @parm Record dal quela leggere i valori
 | ||
| 
 | ||
| // @comm Nel caso il record non sia LF_RFORM viene dato un messaggio di <f CHECK>.
 | ||
| {
 | ||
|   CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
 | ||
|   
 | ||
|   bool changed = FALSE;
 | ||
|   const word h = (word)prof.get_int("HGT");
 | ||
|   const word l = (word)prof.get_int("LEN");
 | ||
|   const word y = (word)prof.get_int("Y");
 | ||
|   if (_height != h) 
 | ||
|   {
 | ||
|     _height = h;
 | ||
|     changed = TRUE;
 | ||
|   }         
 | ||
|   if (_ofspc != l)
 | ||
|   {
 | ||
|     _ofspc = l;
 | ||
|     changed = TRUE;
 | ||
|   }
 | ||
|   if (_ofsvr != y)
 | ||
|   {
 | ||
|     _ofsvr = y;
 | ||
|     changed = TRUE;
 | ||
|   }
 | ||
|   return changed;
 | ||
| }
 | ||
| 
 | ||
| void TPrint_section::print_on(TRectype& prof)
 | ||
| {
 | ||
|   CHECK(prof.num() == LF_RFORM, "Il record deve essere del file LF_RFORM");
 | ||
|   prof.put("ID", 0);
 | ||
|   prof.put("X", 0);
 | ||
|   prof.put("Y", _ofsvr);
 | ||
|   prof.put("LEN", _ofspc);
 | ||
|   prof.put("HGT", _height);
 | ||
| }
 | ||
| 
 | ||
| typedef struct {
 | ||
|   char name_1[80];  // Fontname old
 | ||
|   char name_2[80];  // Fontname new
 | ||
|   int  size_1;      // size (height) of old font
 | ||
|   int  size_2;      // size (height) of new font
 | ||
|   double ratio;     // ratio (width_old_font/width_new_font)
 | ||
| } s_data;                
 | ||
| 
 | ||
| BOOLEAN XVT_CALLCONV1 wpr (long data)
 | ||
| {                        
 | ||
|   s_data* st =(s_data*)data;
 | ||
|   WINDOW prwin = xvt_print_create_win(printer().get_printrcd(),"");
 | ||
|   long width_old,width_new;
 | ||
|   TString spc(100);
 | ||
|   spc.fill('m');
 | ||
|   xvt_set_font(prwin,st->name_1, XVT_FS_NONE, st->size_1);  
 | ||
|   width_old = xvt_dwin_get_text_width(prwin,(char*)(const char*)spc, 100);
 | ||
|   xvt_set_font(prwin,st->name_2, XVT_FS_NONE, st->size_2);  
 | ||
|   width_new = xvt_dwin_get_text_width(prwin,(char*)(const char*)spc, 100);
 | ||
|   st->ratio = (double)width_old / (double)width_new;
 | ||
|   xvt_vobj_destroy(prwin);
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
|                                          
 | ||
| bool TPrint_section::special_field_handler(TMask_field& f, KEY k)
 | ||
| {
 | ||
|   if (k == K_SPACE && _special_mask != NULL)
 | ||
|      _special_mask->run();
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| void TPrint_section::repos_fields(const char* name, int size)
 | ||
| {
 | ||
|   TPrint_section& ps = ::section();
 | ||
|   if (ps.form().fontname() != name || 
 | ||
|     ps.form().fontsize() != size)
 | ||
|   {
 | ||
|     if (!ps.form().dirty()) ps.form().set_dirty();
 | ||
|     ps.set_dirty();
 | ||
|     if (yesno_box("E' stato cambiato il font o la dimensione del carattere.\nSi desidera aggiornare le coordinate dei campi?"))
 | ||
|     {
 | ||
|       s_data  prm;
 | ||
|       prm.size_1=ps.form().fontsize();
 | ||
|       strcpy(prm.name_1,ps.form().fontname());
 | ||
|       prm.size_2=size;
 | ||
|       strcpy(prm.name_2,name);
 | ||
|       prm.ratio = 1.0;
 | ||
|       // Next 3 lines may be changed
 | ||
|       xvt_print_open();
 | ||
|       xvt_print_start_thread (wpr, (long)&prm); 
 | ||
|       xvt_print_close();
 | ||
|       
 | ||
|       const char sechar[4] = { 'B', 'F', 'G',  'H' };
 | ||
|       for (int sn = 0; sn < 4 ; sn++) 
 | ||
|       {
 | ||
|         const char sc = sechar[sn];
 | ||
|         for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
 | ||
|         {            
 | ||
|           TPrint_section* sec = ps.form().exist(sc, pt);
 | ||
|           if (sec != NULL && !sec->columnwise())
 | ||
|           { 
 | ||
|             sec->set_dirty();                       
 | ||
|             for (word i = 0; i < sec->fields() ; i++)
 | ||
|             {
 | ||
|               TForm_item& fi = sec->field(i);
 | ||
|               short value =  fi.x();
 | ||
|               if (value > 0 && (prm.ratio != 1.0))
 | ||
|               {
 | ||
|                 real x_pos;
 | ||
|                 x_pos = value * prm.ratio;
 | ||
|                 x_pos.round();
 | ||
|                 fi.set_x((short)x_pos.integer()); 
 | ||
|                 fi.set_dirty();
 | ||
|               }
 | ||
|             }
 | ||
|           }
 | ||
|         }    
 | ||
|       }
 | ||
|     }
 | ||
|     ps.form().fontname() = name;
 | ||
|     ps.form().fontsize() = size;
 | ||
|     // Aggiorna lo spreadsheet
 | ||
|     TSheet_field& ms = (TSheet_field&)ps._msk->field(F_FIELDS);
 | ||
|     TToken_string tt(128);
 | ||
|     const word flds = ps.fields();
 | ||
|     for (word i = 0; i < flds; i++)
 | ||
|     {
 | ||
|       TForm_item& f = ps.field(i); 
 | ||
|       ps.field(i).print_on_sheet_row(tt);    
 | ||
|       ms.row(i) = tt;
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
|                                           
 | ||
| // handlers for section editing
 | ||
| bool TPrint_section::detail_field_handler(TMask_field& f, KEY k)
 | ||
| {              
 | ||
|   if (k == K_SPACE)
 | ||
|   { 
 | ||
|     
 | ||
|     if (_cur_form && TString(_cur_form->section_mask()).left(2) == "ba")
 | ||
|     {
 | ||
|       TString80 name(_msk->get(F_FONT));
 | ||
|       int       size = _msk->get_int(F_SIZE);
 | ||
|       repos_fields(name, size);
 | ||
|     }
 | ||
|     
 | ||
|     bool consider_sheet_mask = FALSE;
 | ||
|     if (f.mask().is_running())  // Se la maschera di editing dello sheet e' running
 | ||
|       consider_sheet_mask = TRUE;     // allora deve tener conto anche di essa per l'I/O
 | ||
|                              
 | ||
|     // to avoid kasinations with recursion                                  
 | ||
|     TPrint_section& section = ::section();    
 | ||
|     TSheet_field& ms = *f.mask().get_sheet();
 | ||
|     int field = ms.selected();
 | ||
|     TToken_string& tt = ms.row(field);
 | ||
|     TToken_string  tt_mask(tt);
 | ||
|     if (consider_sheet_mask)
 | ||
|     {
 | ||
|       TMask& msheet = f.mask();
 | ||
|       tt_mask.add(msheet.get(idt_id), idt_id - 101);
 | ||
|       tt_mask.add(msheet.get(dsc_id), dsc_id - 101);
 | ||
|       tt_mask.add(msheet.get(len_id), len_id - 101);
 | ||
|       tt_mask.add(msheet.get(prn_id), prn_id - 101);
 | ||
|             
 | ||
|       if (section.columnwise())
 | ||
|       { 
 | ||
|         tt_mask.add(msheet.get(col_id), col_id - 101);
 | ||
|         tt_mask.add(msheet.get(spc_id), spc_id -101); 
 | ||
|         tt_mask.add(msheet.get(int_id), int_id - 101);
 | ||
|         tt_mask.add(msheet.get(fnl_id), fnl_id -101); 
 | ||
|         tt_mask.add(msheet.get(fnr_id), fnr_id -101); 
 | ||
|       }
 | ||
|       else
 | ||
|       {
 | ||
|         tt_mask.add(msheet.get(xps_id), xps_id - 101);
 | ||
|         tt_mask.add(msheet.get(yps_id), yps_id - 101);
 | ||
|       }
 | ||
|     }
 | ||
|     
 | ||
|     TMask msk("ba2100f");
 | ||
|       
 | ||
|     msk.set_handler(F_DFORMAT,    dateformat_handler);
 | ||
|     msk.set_handler(F_DYEAR,      dateformat_handler);
 | ||
|     msk.set_handler(F_DMONTH,     dateformat_handler);
 | ||
|     msk.set_handler(F_DDAY,       dateformat_handler);
 | ||
|     msk.set_handler(F_DSEP,       dateformat_handler); 
 | ||
|       
 | ||
|     msk.set_handler(F_FILE1,  but_file_handler);
 | ||
|     msk.set_handler(F_FIELD1, but_field_handler);
 | ||
|     msk.set_handler(F_FROM1,      from_handler);
 | ||
|     msk.set_handler(F_TO1,        to_handler);
 | ||
|     msk.set_handler(F_FILE2,  but_file_handler);
 | ||
|     msk.set_handler(F_FIELD2, but_field_handler);
 | ||
|     msk.set_handler(F_FROM2,      from_handler);
 | ||
|     msk.set_handler(F_TO2,        to_handler);
 | ||
|     msk.set_handler(F_PICTURE,fmt_handler); 
 | ||
|     // TBI set_mode etc, vedi sotto
 | ||
|                                          
 | ||
|     // gna'                 
 | ||
|     TForm_item& fi = section.field(field);
 | ||
|     
 | ||
|     msk.enable(F_OPTIONS, fi.special_items() > 3);
 | ||
|     msk.enable(F_SPACES, section.columnwise());
 | ||
|     msk.enable(F_FINKL, section.columnwise());
 | ||
|     msk.enable(F_FINKR, section.columnwise());
 | ||
|     
 | ||
|     // build option mask                                     
 | ||
|     if (fi.special_items() > 3)
 | ||
|     {
 | ||
|       msk.set_handler(F_OPTIONS, special_field_handler);
 | ||
|                                                                                             
 | ||
|       CHECK(fi.special_items() < 18, "Quanti special! Non ho nessuna voglia di "
 | ||
|             " farti una maschera a piu' pagine. Ripensaci e riprova");
 | ||
|                                                                                                   
 | ||
|       _special_mask = new TMask("Variabili personalizzate", 1, 78, fi.special_items() + 3);   
 | ||
|       _special_mask->add_button(DLG_OK, 0, "", -12, -1, 10, 2);
 | ||
|       _special_mask->add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2);  
 | ||
|       fi.specials().restart();
 | ||
|       
 | ||
|       for (int k = 0; k < fi.special_items(); k++)
 | ||
|       {                                           
 | ||
|          THash_object*  ho = fi.specials().get_hashobj(); 
 | ||
|          TToken_string& tt = (TToken_string&)(ho->obj()); 
 | ||
|          TString type = tt.get(0);
 | ||
|          TString val  = tt.get(1);
 | ||
|          TToken_string des(tt.get(2),'/');
 | ||
|          TString prompt(des.get(0));
 | ||
|          
 | ||
|          if (type == "STRINGA")
 | ||
|          {
 | ||
|            _special_mask->add_string(101+k, 0, prompt, 1, k+1, des.get_int(1),"");
 | ||
|            _special_mask->set(101+k, val); 
 | ||
|          }
 | ||
|          else if (type == "NUMERO")
 | ||
|          {
 | ||
|            _special_mask->add_number(101+k, 0, prompt, 1, k+1, des.get_int(1),"",des.get_int(2));
 | ||
|            _special_mask->set(101+k, val); 
 | ||
|          }
 | ||
|          else if (type == "LISTA")
 | ||
|          {
 | ||
|            TToken_string codes(128);
 | ||
|            TToken_string value(128);
 | ||
|            
 | ||
|            for (int jj = 2; jj < des.items(); jj++)
 | ||
|            {
 | ||
|              CHECK (jj < (des.items() - 1), "AAARGH! 'Sta LISTA special e' fatta male");
 | ||
|              TString t1(des.get(jj++)); 
 | ||
|              TString t2(des.get(jj));  
 | ||
|              codes.add(t1);
 | ||
|              value.add(t2);
 | ||
|            }                                                                  
 | ||
|                                                                              
 | ||
|            _special_mask->add_list(101+k, 0, prompt, 1, k+1, des.get_int(1), "", codes, value);
 | ||
|            _special_mask->set(101+k, val); 
 | ||
|          }
 | ||
|          else if (type == "BOOLEAN")
 | ||
|          {
 | ||
|            _special_mask->add_boolean(101+k, 0, prompt, 1, k+1);
 | ||
|            _special_mask->set(101+k, val); 
 | ||
|          }
 | ||
|          else if (type == "DATA")
 | ||
|          {
 | ||
|            _special_mask->add_date(101+k, 0, prompt, 1, k+1);
 | ||
|            _special_mask->set(101+k, val); 
 | ||
|          }         
 | ||
|       }
 | ||
|     }
 | ||
|     if (consider_sheet_mask)
 | ||
|       fi.read_from(tt_mask);
 | ||
|     else                                     
 | ||
|       fi.read_from(tt);
 | ||
|     fi.edit(msk);   
 | ||
| 
 | ||
|     // check specials 
 | ||
|     if (_special_mask != NULL)
 | ||
|     {                        
 | ||
|       if (_special_mask->last_key() == K_ENTER)
 | ||
|       {
 | ||
|         fi.specials().restart();
 | ||
|       
 | ||
|         for (int k = 0; k < fi.special_items(); k++)
 | ||
|         {                                           
 | ||
|            THash_object*  ho = fi.specials().get_hashobj(); 
 | ||
|            TToken_string& tt = (TToken_string&)(ho->obj()); 
 | ||
|            TString val  = tt.get(1);
 | ||
|            TString nvl  = _special_mask->get(k + 101);
 | ||
|            if (nvl != val)
 | ||
|            {
 | ||
|              tt.add(nvl, 1);
 | ||
|              if (tt.items() == 3) tt.add("X");
 | ||
|              fi.set_dirty();
 | ||
|            }
 | ||
|          }
 | ||
|        }                   
 | ||
|        
 | ||
|        if (_special_mask != NULL) 
 | ||
|        {
 | ||
|          delete _special_mask;
 | ||
|          _special_mask = NULL;
 | ||
|        }
 | ||
|     }
 | ||
|     
 | ||
|     if (!consider_sheet_mask)
 | ||
|       fi.print_on_sheet_row(tt);    
 | ||
|     else
 | ||
|       {
 | ||
|         TMask& msheet = f.mask();
 | ||
|         fi.print_on_sheet_row(tt_mask);
 | ||
|         msheet.set(idt_id, tt_mask.get_int(idt_id - 101));
 | ||
|         msheet.set(dsc_id, tt_mask.get(dsc_id - 101));
 | ||
|         msheet.set(len_id, tt_mask.get_int(len_id - 101));
 | ||
|         msheet.set(prn_id, tt_mask.get(prn_id - 101)); 
 | ||
|         msheet.set(frm_id, fi.example());
 | ||
|       
 | ||
|         if (section.columnwise())
 | ||
|         {  
 | ||
|           msheet.set(spc_id, tt_mask.get_int(spc_id - 101));
 | ||
|           msheet.set(col_id, tt_mask.get_int(col_id - 101));
 | ||
|           msheet.set(int_id, tt_mask.get(int_id - 101));
 | ||
|           msheet.set(fnl_id, tt_mask.get(fnl_id - 101)); 
 | ||
|           msheet.set(fnr_id, tt_mask.get(fnr_id - 101)); 
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           msheet.set(xps_id, tt_mask.get_int(xps_id - 101));
 | ||
|           msheet.set(yps_id, tt_mask.get_int(yps_id - 101)); 
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|     ms.force_update();
 | ||
| 
 | ||
|     _cur_sect = §ion;
 | ||
|   }
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| bool TPrint_section::detail_field_notify (TSheet_field& s, int r, KEY k)
 | ||
| {   
 | ||
|   TPrint_section& sec = ::section();
 | ||
|   if (k == K_DEL || k == K_INS)
 | ||
|   {
 | ||
|     if (::form().edit_level() <= 1) 
 | ||
|       return FALSE;
 | ||
|     if (k == K_DEL)         
 | ||
|     {
 | ||
|       // elimina campo
 | ||
|       sec.destroy_field(r);  
 | ||
|       sec.set_dirty();
 | ||
|     }
 | ||
|   }
 | ||
|   else if (k == (K_INS + K_CTRL))
 | ||
|   {  
 | ||
|     // new field: set defaults and create field
 | ||
|     TForm_string* f = new TForm_string(&sec);   
 | ||
|     sec.insert_field(r, f);
 | ||
|     TToken_string& tt = s.row(r);
 | ||
|     f->print_on_sheet_row(tt);   
 | ||
|     tt.add("Nuovo campo", sec.columnwise() ? int_id : dsc_id);
 | ||
|     if (sec.columnwise()) tt.add(r+1, col_id - 101);
 | ||
|     s.force_update();
 | ||
|     sec.set_dirty();
 | ||
|   }
 | ||
|   else if (k == K_ENTER)
 | ||
|   {
 | ||
|     // modify field    
 | ||
|     TForm_item*   fld = &sec.field(r);
 | ||
|     TToken_string& tt = s.row(r);
 | ||
|   
 | ||
|     if (sec.columnwise() && ((word)tt.get_int(col_id - 101) <= 0 || 
 | ||
|                              (word)tt.get_int(col_id - 101) > sec.fields()))
 | ||
|     {
 | ||
|       warning_box("Numero di colonna non accettabile (deve essere da 1 a %u)", sec.fields());
 | ||
|       return FALSE;
 | ||
|     }
 | ||
|     // ??? type changed ???
 | ||
|     if (strcmp(tt.get(typ_id - 101), fld->class_name()) != 0)
 | ||
|     { 
 | ||
|       // so'ccazzi: crea nuovo campo del tipo dato e
 | ||
|       // copia gli special (e il resto) 
 | ||
|       TString typ(tt.get(typ_id - 101));  
 | ||
|       TForm_item* fff = NULL;
 | ||
|       if (typ == "NUMERO")
 | ||
|         fff = new TForm_number(&sec);
 | ||
|       else if (typ == "STRINGA")
 | ||
|         fff = new TForm_string(&sec);
 | ||
|       else if (typ == "DATA")
 | ||
|         fff = new TForm_date(&sec);
 | ||
|       else if (typ == "LISTA")
 | ||
|         fff = new TForm_list(&sec);
 | ||
|       else if (typ == "GRUPPO")
 | ||
|         fff = new TForm_group(&sec);
 | ||
|       else if (typ == "LINEA")
 | ||
|         fff = new TForm_line((TGraphic_section*)&sec);
 | ||
|       else if (typ == "BOX")
 | ||
|         fff = new TForm_box((TGraphic_section*)&sec);
 | ||
|       else if (typ == "FIGURA")
 | ||
|         fff = new TForm_picture((TGraphic_section*)&sec);
 | ||
|        
 | ||
|       // copia SPECIALS 
 | ||
|       TAssoc_array& aa = fld->specials();  
 | ||
|       TAssoc_array& bb = fff->specials();  
 | ||
|       THash_object* oo = NULL;
 | ||
|       aa.restart();
 | ||
|       
 | ||
|       for (int i = 0; i < aa.items(); i++)
 | ||
|       {
 | ||
|          oo = aa.get_hashobj();
 | ||
|          bb.add(oo->key(), oo->obj());
 | ||
|       }
 | ||
|       sec.change_field(r, fld = fff);
 | ||
|       fld->set_dirty();
 | ||
|     }
 | ||
|     // modifica valori
 | ||
|     fld->read_from(tt);  
 | ||
|   } 
 | ||
|   else
 | ||
|   if (k == K_SPACE)
 | ||
|   {
 | ||
|     if (_cur_form && TString(_cur_form->section_mask()).left(2) == "ba")
 | ||
|     {
 | ||
|       TString80 name(s.mask().get(F_FONT));
 | ||
|       int       size = s.mask().get_int(F_SIZE);
 | ||
|       repos_fields(name,size);  
 | ||
|       s.force_update();
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Esegue l'edit della sezione di stampa 
 | ||
| //
 | ||
| // @rdesc Ritorna TRUE se e' stata modificata effettivamente
 | ||
| bool TPrint_section::edit(
 | ||
|      const char* title)  // @parm Titolo della maschera di edit
 | ||
| {
 | ||
|   const bool is_ba_editor = TString(_form->section_mask()).left(2) == "ba";
 | ||
|   bool nstd_dirty = FALSE;
 | ||
|   bool  font_found = FALSE;
 | ||
|   
 | ||
|   _cur_form = _form;
 | ||
|   _cur_sect = this;
 | ||
|   
 | ||
|   if (!_subsection)
 | ||
|   {
 | ||
|     TMask m(_form->section_mask());  
 | ||
|     _msk = &m;
 | ||
|     m.set_caption(title);
 | ||
|     m.set(F_HEIGHT, _height);
 | ||
|     m.set(F_OFSPC, _ofspc);
 | ||
|     m.set(F_OFSVR, _ofsvr);
 | ||
|     if (is_ba_editor)
 | ||
|     {
 | ||
|       m.set(F_X, form().offset_x());
 | ||
|       m.set(F_Y, form().offset_y());
 | ||
|       m.set(F_CTP, format("%c",form().char_to_pos()));
 | ||
|       m.set(F_IPX, form().ipx());
 | ||
|       m.set(F_IPY, form().ipy());
 | ||
|       m.set(F_FPX, form().fpx());
 | ||
|       m.set(F_FLEN, printer().formlen());
 | ||
|     } 
 | ||
|     else
 | ||
|        _form->pre_edit_checks(m,_cur_sect);
 | ||
|     TSheet_field& ms = (TSheet_field&)m.field(F_FIELDS);
 | ||
|     
 | ||
|     m.hide(F_OFSVR);//Offset verticale, per _columnwise. Non ancora usato.
 | ||
|     if (_columnwise)
 | ||
|     {
 | ||
|       m.disable(F_HEIGHT);
 | ||
|       ms.delete_column(xps_id); ms.sheet_mask().hide(xps_id);
 | ||
|       ms.delete_column(yps_id); ms.sheet_mask().hide(yps_id);
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       m.hide(F_OFSPC);
 | ||
|       ms.delete_column(int_id); ms.sheet_mask().hide(int_id);
 | ||
|       ms.delete_column(col_id); ms.sheet_mask().hide(col_id);
 | ||
|       ms.delete_column(spc_id); ms.sheet_mask().hide(spc_id);
 | ||
|       ms.delete_column(fnl_id); ms.sheet_mask().hide(fnl_id);
 | ||
|       ms.delete_column(fnr_id); ms.sheet_mask().hide(fnr_id);
 | ||
|     }
 | ||
|     
 | ||
|     ms.enable_column(frm_id - 101, FALSE);    
 | ||
|     
 | ||
|     if (form().edit_level() <= 1)
 | ||
|     {
 | ||
|       ms.enable_column(idt_id - 101, FALSE);
 | ||
|       ms.enable_column(typ_id - 101, FALSE);
 | ||
|     }                                     
 | ||
|     
 | ||
|     // handlers
 | ||
|     ms.set_notify(detail_field_notify);
 | ||
|     ms.sheet_mask().set_handler(100, detail_field_handler);
 | ||
|     if (_form->edit_level()<=1) ms.sheet_mask().disable(DLG_DELREC);
 | ||
|     
 | ||
|     TToken_string tt(128);
 | ||
|     const word flds = fields();
 | ||
|     
 | ||
|     // fill sheet
 | ||
|     for (word i = 0; i < flds; i++)
 | ||
|     {
 | ||
|       TForm_item& f = field(i); 
 | ||
|       field(i).print_on_sheet_row(tt);    
 | ||
|       // TBI colorare se specials (e vedi se colorare solo se non standard)
 | ||
|       ms.row(-1) = tt;
 | ||
|     }
 | ||
|     
 | ||
|     if (is_ba_editor)
 | ||
|     {
 | ||
|       const int MAX_FAMILIES = 128;
 | ||
|       char* family[MAX_FAMILIES];
 | ||
|       const int num_families = (int)xvt_fmap_get_families(printer().get_printrcd(), family, MAX_FAMILIES);
 | ||
|       TToken_string pn1(256), pn2(256);                                                    
 | ||
| 
 | ||
|       for (int i = 0; i < num_families; i++)
 | ||
|       {
 | ||
|         pn1.add(family[i]);
 | ||
|         pn2.add(family[i]);
 | ||
|         if (!font_found) 
 | ||
|           if (form().fontname() == family[i]) font_found = TRUE;
 | ||
|         xvt_mem_free(family[i]);
 | ||
|       }  
 | ||
|       TList_field& lst = (TList_field&)m.field(F_FONT);
 | ||
|       if (!font_found)
 | ||
|       {
 | ||
|         warning_box("Il font %s non esiste per la stampante di default.",(const char*) form().fontname());  
 | ||
|         pn1.add(form().fontname());
 | ||
|         pn2.add(form().fontname());
 | ||
|       }
 | ||
|       lst.replace_items(pn1, pn2);
 | ||
|       lst.set(form().fontname());
 | ||
|       printer().set_char_size(form().fontsize());
 | ||
|       m.set_handler(F_FONT,font_handler);
 | ||
|     }
 | ||
|     
 | ||
|     if(_columnwise)
 | ||
|     {
 | ||
|       bool ok = FALSE;
 | ||
|       while (m.run() != K_ESC)
 | ||
|       {
 | ||
|         TSheet_field& ms = (TSheet_field&)m.field(F_FIELDS);
 | ||
|         const int items = ms.items();
 | ||
|         for (int i=0; i<items && !ok; i++)
 | ||
|         {
 | ||
|           TToken_string& tt = ms.row(i);
 | ||
|           ok = tt.get_char(prn_id - 101)==' ';
 | ||
|         }
 | ||
|         if (i==items && !ok) error_box("Selezionare almeno una colonna stampabile.");
 | ||
|         if (ok) break;
 | ||
|       }
 | ||
|       _msk = NULL;
 | ||
|       if (!ok) return FALSE;
 | ||
|     }
 | ||
|     else
 | ||
|       if (m.run() == K_ESC)
 | ||
|       {
 | ||
|         // Se premo Annulla ed il form e' nuovo lo devo cancellare.
 | ||
|         if (form()._isnew)
 | ||
|         {
 | ||
|           TLocalisamfile frm(LF_FORM);
 | ||
|           frm.zero();
 | ||
|           frm.put("TIPOPROF",form().name());
 | ||
|           frm.put("CODPROF",form().code());
 | ||
|           frm.remove();
 | ||
|         }
 | ||
|         _msk = NULL;
 | ||
|         return FALSE;
 | ||
|       }
 | ||
| 
 | ||
|     bool dirty = m.dirty() != 0; 
 | ||
|     
 | ||
|     if (dirty)
 | ||
|     {
 | ||
|       // Controlli da fare sempre a prescindere dal form editor
 | ||
|       if (_height != (word)m.get_int(F_HEIGHT) )
 | ||
|       {
 | ||
|         _height = m.get_int(F_HEIGHT);
 | ||
|         _dirty=TRUE;
 | ||
|       }
 | ||
|       if (_ofspc != (word)m.get_int(F_OFSPC) )
 | ||
|       {
 | ||
|         _ofspc = m.get_int(F_OFSPC);
 | ||
|         _dirty=TRUE;
 | ||
|       }
 | ||
|       if (_ofsvr != (word)m.get_int(F_OFSVR) )
 | ||
|       {
 | ||
|         _ofsvr = m.get_int(F_OFSVR);
 | ||
|         _dirty=TRUE;
 | ||
|       }
 | ||
|       if (is_ba_editor)
 | ||
|       { // Controlli solo se il form editor e' quello base
 | ||
|         if (m.get_int(F_X) != form().offset_x() || m.get_int(F_Y) != form().offset_y())
 | ||
|         {
 | ||
|           form().offset_x() = m.get_int(F_X);
 | ||
|           form().offset_y() = m.get_int(F_Y);
 | ||
|           form().set_dirty();
 | ||
|           _dirty = TRUE;
 | ||
|         }                                         
 | ||
|         if (m.get(F_CTP)[0] != form().char_to_pos() ||
 | ||
|             m.get_int(F_IPX) != form().ipx() ||
 | ||
|             m.get_int(F_IPY) != form().ipy() ||
 | ||
|             m.get_int(F_IPX) != form().fpx())
 | ||
|         {               
 | ||
|           form().char_to_pos() = m.get(F_CTP)[0];
 | ||
|           form().ipx() = m.get_int(F_IPX);
 | ||
|           form().ipy() = m.get_int(F_IPY);
 | ||
|           form().fpx() = m.get_int(F_FPX);
 | ||
|           _dirty = TRUE;
 | ||
|         }
 | ||
|         
 | ||
|         TString80 name(m.get(F_FONT));
 | ||
|         int       size = m.get_int(F_SIZE);
 | ||
|         repos_fields(name,size);
 | ||
|       } else  // controlli se l'editor non e' quello base
 | ||
|           nstd_dirty = _form->post_edit_checks(m,_cur_sect);
 | ||
|     }
 | ||
|     _msk = NULL;
 | ||
|   }
 | ||
| 
 | ||
|   if (is_ba_editor)
 | ||
|     if (form()._isnew || (_dirty && yesno_box("Dati generali modificati. Salvare?")))
 | ||
|     {
 | ||
|       TLocalisamfile frm(LF_FORM);
 | ||
|       frm.zero();
 | ||
|       frm.put("TIPOPROF",form().name());
 | ||
|       frm.put("CODPROF",form().code());
 | ||
|       if (frm.read(_isequal,_lock) == NOERR)
 | ||
|       {
 | ||
|           frm.put("OFFY",form().offset_y());
 | ||
|           frm.put("OFFX",form().offset_x());
 | ||
|           frm.put("FONTNAME",form().fontname());
 | ||
|           frm.put("FONTSIZE",form().fontsize());
 | ||
|           frm.put("CTP",form().char_to_pos());
 | ||
|           frm.put("IPX", form().ipx());
 | ||
|           frm.put("IPY", form().ipy());
 | ||
|           frm.put("FPX", form().fpx());
 | ||
|           frm.rewrite();
 | ||
|           _dirty = FALSE;    
 | ||
|       }
 | ||
|     }
 | ||
|     
 | ||
|   if (!_dirty) 
 | ||
|     for (word j = 0; j < fields(); j++)
 | ||
|       _dirty |= field(j).dirty();  
 | ||
|       
 | ||
|   set_dirty(_dirty);
 | ||
|   return (_dirty || nstd_dirty);
 | ||
| }
 | ||
| 
 | ||
| void TPrint_section::print_on(ostream& out) const
 | ||
| {        
 | ||
|   out << ' ';
 | ||
|   switch (page_type())
 | ||
|   {
 | ||
|   case even_page:
 | ||
|     out << "EVEN"; break;
 | ||
|   case first_page:
 | ||
|     out << "FIRST"; break;
 | ||
|   case last_page:
 | ||
|     out << "LAST"; break;
 | ||
|   default:
 | ||
|     out << "ODD"; break;
 | ||
|   }
 | ||
|   out << ' ' << _height;
 | ||
|   if (_columnwise) out << " COLUMNWISE";
 | ||
|   out << endl << endl;
 | ||
|   for(word i = 0; i < fields(); i++)
 | ||
|     if (!field(i).temp()) out << field(i);
 | ||
| }
 | ||
| 
 | ||
| TForm_item& TPrint_section::find_field(short id) const
 | ||
| {
 | ||
|   for(word i = 0; i < fields(); i++)
 | ||
|   {
 | ||
|     TForm_item& f = field(i);
 | ||
|     if (f.id() == id) return f;
 | ||
|   }              
 | ||
|   yesnofatal_box("Can't find item with id %d", id);
 | ||
|   return field(0);  
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| TForm_editor& TForm::editor() const
 | ||
| { return (TForm_editor&)main_app(); }
 | ||
| 
 | ||
| bool TForm::parse_use(TScanner& scanner)
 | ||
| {
 | ||
|   const int logicnum = scanner.integer();
 | ||
|   const char* tab = NULL;
 | ||
| 
 | ||
|   if (logicnum > 0)
 | ||
|     _relation = new TRelation(logicnum);
 | ||
|   else
 | ||
|   {
 | ||
|     tab = scanner.pop();
 | ||
|     _relation = new TRelation(tab);
 | ||
|   }
 | ||
|   
 | ||
|   int key = 1;
 | ||
|   if (scanner.popkey() == "KE")
 | ||
|     key = scanner.integer();
 | ||
|   else 
 | ||
|     scanner.push();
 | ||
| 
 | ||
|   _cursor = new TCursor(_relation, "", key);   
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| bool TForm::parse_join(TScanner& scanner)
 | ||
| {
 | ||
|   TString16 j(scanner.pop());           // File or table
 | ||
| 
 | ||
|   int to = 0;
 | ||
|   if (scanner.popkey() == "TO")         // TO keyword
 | ||
|   {
 | ||
|     const char* n = scanner.pop();
 | ||
|     to = name2log(n);
 | ||
|   }
 | ||
|   else scanner.push();
 | ||
| 
 | ||
|   int key = 1;
 | ||
|   if (scanner.popkey() == "KE")
 | ||
|     key = scanner.integer();
 | ||
|   else scanner.push();
 | ||
| 
 | ||
|   int alias = 0;
 | ||
|   if (scanner.popkey() == "AL")
 | ||
|     alias = scanner.integer();
 | ||
|   else scanner.push();
 | ||
| 
 | ||
|   TToken_string exp(80);
 | ||
|   if (scanner.pop() == "INTO")
 | ||
|   {
 | ||
|     const char* r = scanner.pop();
 | ||
|     while (strchr(r, '=') != NULL)
 | ||
|     {
 | ||
|       exp.add(r);
 | ||
|       r = scanner.pop();
 | ||
|     }
 | ||
|   }
 | ||
|   if (exp.empty())
 | ||
|     yesnofatal_box("JOIN senza espressioni INTO");
 | ||
|   scanner.push();
 | ||
|   
 | ||
|   if (isdigit(j[0]))
 | ||
|     _relation->add(atoi(j), exp, key, to, alias);   // join file
 | ||
|   else
 | ||
|     _relation->add(j, exp, key, to, alias);         // join table
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| TRelation_description& TForm::rel_desc() const 
 | ||
| {         
 | ||
|   CHECK(_rel_desc, "No relation description");
 | ||
|   return *_rel_desc; 
 | ||
| }
 | ||
| 
 | ||
| bool TForm::parse_description(TScanner& scanner)
 | ||
| {
 | ||
|   if (edit_level() > 0)
 | ||
|   {
 | ||
|     CHECK(_rel_desc == NULL, "Can't parse descriptions two times");
 | ||
|     _rel_desc = new TRelation_description(*_relation);
 | ||
|   }
 | ||
| 
 | ||
|   bool ok = scanner.popkey() == "DE";
 | ||
|   if (ok)
 | ||
|   {     
 | ||
|     if (edit_level() > 0)
 | ||
|     {
 | ||
|       scanner.popkey(); // eat BEGIN              
 | ||
|       TFieldref fld;
 | ||
|       while (scanner.pop() != "END")
 | ||
|       {       
 | ||
|         fld = scanner.token();
 | ||
|         _rel_desc->set_cur_file(fld.file());
 | ||
|         if (fld.name() == "*")
 | ||
|           _rel_desc->file_desc(scanner.string());
 | ||
|         else  
 | ||
|           _rel_desc->set_field_description(fld.name(), scanner.string());
 | ||
|       }
 | ||
|     }  
 | ||
|     else
 | ||
|     {
 | ||
|       while (scanner.line() != "END");
 | ||
|       ok = FALSE;
 | ||
|     }  
 | ||
|   }    
 | ||
|   else scanner.push();
 | ||
| 
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| void TForm::print_description(ostream& out) const
 | ||
| {
 | ||
|   out << "DESCRIPTION\nBEGIN\n";
 | ||
|   out << rel_desc();
 | ||
|   out << "END\n" << endl;
 | ||
| }
 | ||
| 
 | ||
| bool TForm::parse_general(TScanner &scanner)
 | ||
| {
 | ||
|   bool ok = scanner.popkey() == "GE";
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     while (scanner.pop() != "END")
 | ||
|     {  
 | ||
|       if (scanner.popkey() == "OF")   // Offsets
 | ||
|       {
 | ||
|         _x = scanner.integer();
 | ||
|         _y = scanner.integer();
 | ||
|       }
 | ||
|       else scanner.push();    
 | ||
|       if (scanner.popkey() == "FO")   // Font name
 | ||
|         _fontname = scanner.string();
 | ||
|       else scanner.push();    
 | ||
|       if (scanner.popkey() == "SI")   // Font size
 | ||
|         _fontsize = scanner.integer();
 | ||
|       else scanner.push();
 | ||
|       if (scanner.popkey() == "CA")   // Carattere di posizionamento
 | ||
|         _char_to_pos = scanner.string()[0];
 | ||
|       else scanner.push();
 | ||
|       if (scanner.popkey() == "IN")   // Riga e colonna del posizionamento iniziale
 | ||
|       {
 | ||
|         _ipx = scanner.integer();
 | ||
|         _ipy = scanner.integer();
 | ||
|       }
 | ||
|       else scanner.push();
 | ||
|       if (scanner.popkey() == "FI")   // Riga e colonna del posizionamento finale
 | ||
|       {                              
 | ||
|         _fpx = scanner.integer();
 | ||
|       }
 | ||
|       else scanner.push();
 | ||
| 
 | ||
|       if (scanner.popkey() == "GR")   // Carattere di posizionamento
 | ||
|         set_fincatura(scanner.string());
 | ||
|       else scanner.push();
 | ||
|       
 | ||
|       extended_parse_general(scanner); // Parse non-standard parameters
 | ||
|     }
 | ||
|   } else scanner.push();
 | ||
|   
 | ||
|   return (ok);
 | ||
| }
 | ||
| 
 | ||
| void TForm::print_general(ostream& out) const
 | ||
| {
 | ||
|   out << "GENERAL\nBEGIN\n";
 | ||
|   out << "  OFFSET " << _x << " " << _y << "\n";
 | ||
|   out << "  FONT " << "\"" << _fontname << "\"\n";
 | ||
|   out << "  SIZE " << _fontsize << "\n" ; 
 | ||
|   if (_char_to_pos != '\0')                
 | ||
|   {
 | ||
|     out << "  CARATTERE \"" << _char_to_pos << "\"\n" ; 
 | ||
|     out << "  INIZIO_POS " << _ipx << " " << _ipy << "\n";
 | ||
|     out << "  FINE_POS " << _fpx << "\n";
 | ||
|   }                                         
 | ||
|   out << "  GRID \"" << _fink << "\"\n";
 | ||
|   out << "END\n" << endl;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Controlla se esiste una sezione di stampa
 | ||
| //
 | ||
| // @rdesc Ritorna la <c TPrint_section> trovata o creata
 | ||
| TPrint_section* TForm::exist(
 | ||
|       char s,   // @parm Indica in quale parte deve cercare:
 | ||
|         //
 | ||
|         // @flag F | Tra i footers
 | ||
|         // @flag G | Tra gli sfondi
 | ||
|         // @flag H | Tra gli headers
 | ||
|         // @flag B | Tra i bodies (default)
 | ||
|     pagetype t,   // @parm Tipo di pagina (vedi <t pagetype>)
 | ||
|     bool create)  // @parm Indica se creare la sezione nel caso non esista
 | ||
| {
 | ||
|   TArray* a;
 | ||
|   switch (toupper(s))
 | ||
|   {
 | ||
|   case 'F':
 | ||
|     a = &_foot; break;
 | ||
|   case 'G':
 | ||
|     a = &_back; break;
 | ||
|   case 'H':
 | ||
|     a = &_head; break;
 | ||
|   default:
 | ||
|     a = &_body; break;
 | ||
|   }
 | ||
|   
 | ||
|   TPrint_section* sec = (TPrint_section*)a->objptr(t);
 | ||
|   if (sec == NULL && create) 
 | ||
|   {
 | ||
|     sec = (s == 'G') ? new TGraphic_section(this, t) : new TPrint_section(this, s, t);
 | ||
|     a->add(sec, t);
 | ||
|   }  
 | ||
|   
 | ||
|   return sec;
 | ||
| }
 | ||
| 
 | ||
| TForm_item& TForm::find_field(char s, pagetype t, short id) const
 | ||
| {                 
 | ||
|   const TPrint_section* ps = ((TForm*)this)->exist(s, t);
 | ||
|   CHECKD(ps, "Can't find section for field ", id);
 | ||
|   return ps->find_field(id);
 | ||
| }
 | ||
| 
 | ||
| TPrint_section& TForm::section(char s, pagetype pos)
 | ||
| {              
 | ||
|   TPrint_section* sec = exist(s, pos, TRUE);
 | ||
|   return *sec;
 | ||
| }
 | ||
| 
 | ||
| TPrint_section& TForm::section(char s, word pagenum)
 | ||
| {              
 | ||
|   pagetype pt = odd_page;  
 | ||
|   if (pagenum == 0 && exist(s, last_page)) 
 | ||
|     pt = last_page;
 | ||
|   if (pagenum == 1 && exist(s, first_page)) 
 | ||
|     pt = first_page;
 | ||
|   if (pt == odd_page && (pagenum & 0x1) == 0 && exist(s, even_page)) 
 | ||
|     pt = even_page;
 | ||
|   
 | ||
|   return section(s, pt);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Rilegge la sezione specificata
 | ||
| //
 | ||
| // @rdesc Ritorna se ce l'ha fatta
 | ||
| bool TForm::reread(
 | ||
|      char sec,    // @parm Sezione da rileggere
 | ||
|      pagetype p,  // @parm Posizione della pagina
 | ||
|      bool force)  // @parm Forza rilettura anche se nessun campo e' cambiato
 | ||
| {
 | ||
|   TPrint_section* s = exist(sec,p);
 | ||
|   bool ok = force;
 | ||
|   if (s != NULL)
 | ||
|       for (word j = 0; j < s->fields(); j++)
 | ||
|         ok |= s->field(j).dirty();
 | ||
|   if (s != NULL && ok)
 | ||
|   {
 | ||
|     s->destroy_fields();  // Distrugge tutti gli items...
 | ||
|     // ...si posiziona nel file sorgente alla sezione opportuna...
 | ||
|     TFilename n(_name); n.ext("frm");
 | ||
|     TScanner scanner(n);
 | ||
|     bool ok = FALSE;
 | ||
|     while (!ok)
 | ||
|     {
 | ||
|       while (TRUE)     // ...scans searching for a section...
 | ||
|       {
 | ||
|         const TString& key = scanner.popkey();
 | ||
|         if (key == "SE" || key == "") // ..if section or end of file...
 | ||
|           break;
 | ||
|       }
 | ||
|       const char   secr = scanner.popkey()[0];             // Section name (GRAPH, HEAD, BODY, FOOT)
 | ||
|       if (secr=='\0') break;
 | ||
|       const pagetype pr = char2page(scanner.popkey()[0]);  // Section type (odd, even, first, last)
 | ||
|       if (secr==sec && pr==p) ok = TRUE;  // L'ha trovata...
 | ||
|     }
 | ||
|     // ...riesegue la parse della sezione leggendo dal file sorgente
 | ||
|     if(ok && s->parse(scanner))
 | ||
|     {                          
 | ||
|      // Legge le modifiche su archivio e poi e' finita.
 | ||
|       s->set_dirty(FALSE);
 | ||
|       TLocalisamfile rprof(LF_RFORM); 
 | ||
|       const char sez[3] = {sec,p+'0','\0'};
 | ||
|       rprof.zero();
 | ||
|       rprof.put("TIPOPROF", _name);
 | ||
|       rprof.put("CODPROF", _code);
 | ||
|       rprof.put("SEZ", sez);
 | ||
|       const TRectype filter(rprof.curr());
 | ||
|                     
 | ||
|       for (int err = rprof.read(_isgteq); err == NOERR && rprof.curr() == filter; err = rprof.next())
 | ||
|       {              
 | ||
|         const short id = rprof.get_int("ID");
 | ||
|                       
 | ||
|         if (id == 0)
 | ||
|         {
 | ||
|           TPrint_section& se = section(sec, p);
 | ||
|           se.read_from(rprof.curr());
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           TForm_item& item = find_field(sec, p, id);
 | ||
|           item.read_from(rprof.curr());
 | ||
|         }
 | ||
|       }
 | ||
|       set_compulsory_specials();  
 | ||
|     }
 | ||
|   }             
 | ||
|   return ok;
 | ||
| }
 | ||
|                             
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TForm                                      
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Cambia il formato di tutte le date nel form
 | ||
| //
 | ||
| // @rdesc Ritorna sempre TRUE
 | ||
| bool TForm::ps_change_date_format(
 | ||
|      TPrint_section& s,   // @parm Sezione nella quale modificare le date
 | ||
|      const char* f)   // @parm Nuovo formato delle date
 | ||
| 
 | ||
| // @comm Ha le stesse funzioni di <mf TForm::change_date_format>, ma per <c TPrint_section>,
 | ||
| //   all'uopo di chiamarla con ricorsiva insistenza
 | ||
|   
 | ||
| {
 | ||
|   for (word i = 0; i < s.fields(); i++)
 | ||
|   {
 | ||
|     TForm_item& fi = s.field(i);
 | ||
|     if (strcmp(fi.class_name(), "SEZIONE") == 0)
 | ||
|     {
 | ||
|       TPrint_section& ps = ((TForm_subsection&)fi).subsection();
 | ||
|       ps_change_date_format(ps, f);
 | ||
|     } 
 | ||
|     else if (strcmp(fi.class_name(), "DATA") == 0) 
 | ||
|     {
 | ||
|       ((TForm_date&)fi).set_format(f);
 | ||
|       if (!s.dirty()) s.set_dirty();
 | ||
|       if (!fi.dirty()) fi.set_dirty();
 | ||
|     }
 | ||
|   } 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Cambia il formato di tutti i numeri nel form
 | ||
| //
 | ||
| // @rdesc Ritorna sempre TRUE
 | ||
| bool TForm::ps_change_number_format(
 | ||
|      TPrint_section& s,   // @parm Sezione nella quale modificare i numeri
 | ||
|      int w,       // @parm Dimensione massima del fomato numerico
 | ||
|      int dec,       // @parm Numero di decimali
 | ||
|      const char* p)   // @parm Picture del nuovo formato
 | ||
| 
 | ||
| // @comm Ha le stesse funzioni di <mf TForm::change_number_format>, ma per <c TPrint_section>,
 | ||
| //   all'uopo di chiamarla con ricorsiva insistenza
 | ||
| {                       
 | ||
|   for (word i = 0; i < s.fields(); i++)
 | ||
|   {
 | ||
|     TForm_item& fi = s.field(i);
 | ||
|     if (strcmp(fi.class_name(), "SEZIONE") == 0)
 | ||
|     {
 | ||
|       TPrint_section& ps = ((TForm_subsection&)fi).subsection();
 | ||
|       ps_change_number_format(ps, w, dec, p);
 | ||
|     } 
 | ||
|     else if (strcmp(fi.class_name(), "NUMERO") == 0) 
 | ||
|     {
 | ||
|       TForm_number& fn = (TForm_number&)fi; 
 | ||
|       fn.width() = w;
 | ||
|       fn.set_decimals(dec);
 | ||
|       fn.set_picture(p);
 | ||
|       if (!s.dirty()) s.set_dirty();
 | ||
|       if (!fn.dirty()) fn.set_dirty();
 | ||
|     }
 | ||
|   } 
 | ||
|   return TRUE;
 | ||
| } 
 | ||
| 
 | ||
| 
 | ||
| void TForm::change_date_format(const char* f)                              
 | ||
| {                    
 | ||
|   char secs[] = { "FHGB" };
 | ||
|   char ptyp[] = { "LOEF" };
 | ||
|   TPrint_section* ps;
 | ||
|   
 | ||
|   for (int sc = 0; sc < 4; sc++)
 | ||
|     for (int pt = 0; pt < 4; pt++)
 | ||
|        if ((ps = exist(secs[sc], char2page(ptyp[pt]), FALSE)) != NULL)
 | ||
|          ps_change_date_format(*ps, f);
 | ||
| }
 | ||
| 
 | ||
| void TForm::change_number_format(int w, int dec, const char* p)
 | ||
| {
 | ||
|   char secs[] = { "FHGB" };
 | ||
|   char ptyp[] = { "LOEF" };
 | ||
|   TPrint_section* ps;
 | ||
|   
 | ||
|   for (int sc = 0; sc < 4; sc++)
 | ||
|     for (int pt = 0; pt < 4; pt++)
 | ||
|        if ((ps = exist(secs[sc], char2page(ptyp[pt]), FALSE)) != NULL)
 | ||
|          ps_change_number_format(*ps, w, dec, p);
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
|            
 | ||
| // @mfunc Effettua l'update della sezione grafica background
 | ||
| //
 | ||
| // @rdesc Ritorna la lunghezza della pagina da stampare
 | ||
| word TForm::set_background(
 | ||
|      word p,  // @parm Numero pagina 
 | ||
|      bool u)  // @parm Indica se aggiornare lo sfondo nella stampante corrente
 | ||
| 
 | ||
| // @xref <mf TForm::set_header> <mf TForm::set_body> <mf TForm::set_footer>
 | ||
| {
 | ||
|   word len = 0;
 | ||
|   
 | ||
|   if (u && _back.items()) 
 | ||
|   {
 | ||
|     TPrint_section& graph = section('G', p);
 | ||
|     graph.update();
 | ||
|     len = printer().formlen();
 | ||
|   }    
 | ||
|   
 | ||
|   return len;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Effettua l'update della sezione header
 | ||
| //
 | ||
| // @rdesc Ritorna l'altezza dell'header settato
 | ||
| word TForm::set_header(
 | ||
|      word p,  // @parm Numero pagina
 | ||
|      bool u)  // @parm Indica se cambiare l'eventuale header corrente!!!
 | ||
| 
 | ||
| // @xref <mf TForm::set_background> <mf TForm::set_body> <mf TForm::set_footer>
 | ||
| {           
 | ||
|   TPrinter& pr = printer();
 | ||
|   pr.resetheader();
 | ||
| 
 | ||
|   TPrint_section& head = section('H', p);
 | ||
|   
 | ||
|   if (u) head.update(); 
 | ||
|   else 
 | ||
|   {
 | ||
|     head.reset();
 | ||
|     pr.headerlen(head.height());
 | ||
|   }
 | ||
|   
 | ||
|   for (word j = 0; j < head.height(); j++)
 | ||
|     pr.setheaderline(j, head.row(j));
 | ||
|   
 | ||
|   return head.height();
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Effettua l'update della sezione body
 | ||
| //
 | ||
| // @rdesc Ritorna l'altezza del body settato
 | ||
| word TForm::set_body(
 | ||
|      word p,  // @parm Numero pagina
 | ||
|      bool u)  // @parm Indica se cambiare l'eventuale body corrente!!!
 | ||
| 
 | ||
| // @xref <mf TForm::set_background> <mf TForm::set_header> <mf TForm::set_footer>
 | ||
| 
 | ||
| {
 | ||
|   TPrint_section& body = section('B', p);
 | ||
| 
 | ||
|   if (u) body.update(); 
 | ||
|   else body.reset();
 | ||
|   
 | ||
|   if (u) 
 | ||
|   {
 | ||
|     TPrinter& pr = printer();
 | ||
|     for (word j = 0; j < body.height(); j++)
 | ||
|       pr.print(body.row(j));
 | ||
|   }
 | ||
|   
 | ||
|   return body.height();
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Effettua l'update della sezione footer
 | ||
| //
 | ||
| // @rdesc Ritorna l'altezza del footer settato
 | ||
| word TForm::set_footer(
 | ||
|      word p,  // @parm Numero pagina
 | ||
|      bool u)  // @parm Indica se cambiare l'eventuale footer corrente!!!
 | ||
| 
 | ||
| // @xref <mf TForm::set_background> <mf TForm::set_header> <mf TForm::set_body>
 | ||
| 
 | ||
| {
 | ||
|   TPrinter& pr = printer();
 | ||
|   pr.resetfooter();
 | ||
| 
 | ||
|   TPrint_section& foot = section('F', p);
 | ||
|   
 | ||
|   if (u) foot.update();
 | ||
|   else 
 | ||
|   {
 | ||
|     foot.reset();
 | ||
|     pr.footerlen(foot.height());
 | ||
|   }
 | ||
|   
 | ||
|   for (word j = 0; j < foot.height(); j++)
 | ||
|     pr.setfooterline(j, foot.row(j));
 | ||
| 
 | ||
|   return foot.height();
 | ||
| }
 | ||
| 
 | ||
| void TForm::header_handler(TPrinter& p)
 | ||
| {
 | ||
|   const word page = form().page(p);
 | ||
|   form().set_background(page, TRUE);
 | ||
|   form().set_header(page, TRUE);
 | ||
|   form().set_footer(page, FALSE);
 | ||
| }
 | ||
| 
 | ||
| void TForm::footer_handler(TPrinter& p)
 | ||
| {
 | ||
|   const word page = form().page(p);
 | ||
|   form().set_footer(page, TRUE); 
 | ||
|   if (page)
 | ||
|     form().set_header(page+1, FALSE);
 | ||
| }   
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Ritorna il numero di pagina correntemente in stampa
 | ||
| //
 | ||
| // @rdesc Se <md _TForm::lastpage> e' TRUE (sta stampando l'ultima pagina)
 | ||
| //    ritorna 0, altrimenti ritorna il numero della pagian corrente da stampare
 | ||
| //    (chiam <mf TPrinter::getcurrentepage>).
 | ||
| word TForm::page(
 | ||
|      const TPrinter& p) const // @parm Operazione corrente di stampa
 | ||
| {
 | ||
|   return _lastpage ? 0 : p.getcurrentpage();
 | ||
| }                                   
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Effettua il posizionamento manuale del modulo
 | ||
| void TForm::arrange_form()
 | ||
| 
 | ||
| // @comm Nota: siccome si scrive direttamente sulla porta, sarebbe necessario 
 | ||
| //   mandare una stringa di reset alla stampante, o per lo meno far si' che 
 | ||
| //   ogni volta che si fa il posizionamento il font col quale scrive sia sempre
 | ||
| //   lo stesso. Tutto cio' non e' possibile con la generica solo testo, o meglio
 | ||
| //   ad ogni stampa col posizionamento e' necessario che la stampante sia resettata.
 | ||
| //   <nl>Riassumendo, come regola generale, i posizionamenti devono essere fatti con il 
 | ||
| //   font di default della stampante (tipicamente 10 cpi). Accade pero' (con la generica 
 | ||
| //   solo testo) che rimanga settato l'ultimo font, di conseguenza quando si effettua una
 | ||
| //   seconda stampa con posizionamento, stampera' tali caratteri in 17"! Per questo 
 | ||
| //   motivo e' necessario settare a 17 cpi, almeno la prima volta, la stampante!.
 | ||
| //   <nl>Quindi, per ovviare a tutto cio, visto che <mf TForm::arange_form> ha senso solo su 
 | ||
| //   stampanti ad aghi, che le stampanti ad aghi possono andare in emulazione EPSON o IBM, 
 | ||
| //   che il codice per settare il font draft 17cpi e' lo stesso sia per EPSON che IBM
 | ||
| //   CHR(15), allora prima del posizionamento scrivo il chr(15) sulla stampante!
 | ||
| 
 | ||
| {                     
 | ||
|   int i, x;
 | ||
|   TString str_pos;  
 | ||
|   TMask m("ba2100c");
 | ||
|   
 | ||
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
 | ||
| /*
 | ||
|   char defPrinter[80];
 | ||
|   char szDevice[50];
 | ||
| 
 | ||
|   // get default printer driver
 | ||
|   GetProfileString ("windows", "device", ",,,", defPrinter, sizeof(defPrinter));
 | ||
|   TToken_string pdev (defPrinter, ',');
 | ||
|   GetProfileString ("devices", pdev, "", szDevice, sizeof(szDevice));
 | ||
|   pdev.add(szDevice);             
 | ||
|   device = pdev.get(2);
 | ||
|   device = device.left(4); //Legge solo LPTx... 
 | ||
|   */
 | ||
| #else
 | ||
|   TString device(printer.printername());
 | ||
|   FILE* lpt = fopen(device,"w"); 
 | ||
| 
 | ||
|   if (lpt == NULL)
 | ||
|     fatal_box("Non rieso ad aprire il device %s.",device);
 | ||
| #endif
 | ||
|   
 | ||
|   // _ipy viene assunto uguale per entrambi i posizionamneti
 | ||
|   str_pos = "\017";  // Questo e' 15 in ottale...
 | ||
|   for (i=1; i < _ipy; i++) str_pos << "\n";
 | ||
| #if XVT_OS == XVT_OS_WIN ||  XVT_OS == XVT_OS_NT 
 | ||
|   SpoolRow((char *) (const char *) str_pos, str_pos.len());
 | ||
| #else                                           
 | ||
| 
 | ||
|   fprintf(lpt,"%s",(const char*) str_pos);  
 | ||
|   fflush(lpt);              // Salta le righe...                           
 | ||
|   fclose(lpt);
 | ||
| #endif  
 | ||
|   str_pos = "";  //Azzera la stringa di posizionamento
 | ||
|   for (i=1; i < _ipx; i++) str_pos << " "; //Aggiunge gli spazi necessari...
 | ||
|   if (_ipx > 0 && _ipy > 0)
 | ||
|     str_pos << _char_to_pos;   // aggiunge il primo carattere di posizionamento...
 | ||
|   x = _fpx - _ipx ;                 // calcola quanti spazi aggiungere...
 | ||
|   for (i=1; i < x; i++) str_pos << " ";
 | ||
|   if (_fpx > 0)
 | ||
|     str_pos << _char_to_pos;  // aggiunge il secondo carattere di posizionamento
 | ||
|   str_pos << '\r';
 | ||
| //  TString bspc; bspc.fill('\b',str_pos.len()); // Questi servono per tornare indietro...
 | ||
|   do
 | ||
|   { 
 | ||
| #if XVT_OS == XVT_OS_WIN ||  XVT_OS == XVT_OS_NT 
 | ||
|     SpoolRow((char *)(const char *) str_pos, str_pos.len());
 | ||
| #else                                           
 | ||
|     lpt = fopen(device,"w");             
 | ||
|     if (lpt == NULL) fatal_box("Non riesco ad aprire il device %s.",device);
 | ||
| //    fprintf(lpt,"%s",(const char*) bspc);  
 | ||
|     fprintf(lpt,"%s\r",(const char*) str_pos);  
 | ||
|     fflush(lpt);          
 | ||
|     fclose(lpt);                                
 | ||
| #endif
 | ||
|   } while (m.run() == K_ESC);     // cicla sulla stampa posizionamento...
 | ||
| /*  const int h = height(odd_page);                   
 | ||
|   str_pos.cut(0);
 | ||
|   for (i=0; i < h; i++) str_pos << "\n";
 | ||
|   lpt = fopen(device,"w");
 | ||
|   if (lpt == NULL) fatal_box("Non rieso ad aprire il device %s.",device);
 | ||
|   fprintf(lpt, "%s", (const char*) str_pos); // Salta tante righe quanto e' lungo il form standard
 | ||
|   fclose (lpt);       */
 | ||
|   printer().set_offset(_ipy - 1, printer().get_column_offset());
 | ||
| }
 | ||
| 
 | ||
| long TForm::records() const
 | ||
| {             
 | ||
|   const long r = cursor() ? cursor()->items() : 0;
 | ||
|   return r;
 | ||
| }                                                                        
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Genera automaticamente la sezione grafica con colonne fincate
 | ||
| //
 | ||
| // @rdesc Ritorna FALSE se non c'e' il body per quella pagina
 | ||
| bool TForm::genera_fincatura(
 | ||
|      pagetype p,  // @parm Posizione della pagina (vedi <t pagetype>)
 | ||
|      int y1,    // @parm Prima y per le righe verticali
 | ||
|      int y2,    // @parm Ultima y per le righe verticali
 | ||
|      const int* rows) // @parm Array di posizioni riga con 0 per finire
 | ||
| 
 | ||
| 
 | ||
| {
 | ||
|   TPrint_section* body = exist('B', p);
 | ||
|   if (body == NULL) return FALSE;      
 | ||
| 
 | ||
|   body->reset_tabs();
 | ||
|   
 | ||
|   bool istemp = exist('G', p) == NULL;
 | ||
|   
 | ||
|   TGraphic_section* grs = (TGraphic_section*)exist('G', p, TRUE); 
 | ||
|   grs->temp() = istemp;
 | ||
|   
 | ||
|   int j = 0, start = 999, end = 0, wlast = 0;
 | ||
|   int cols[MAXCOLUMNS];
 | ||
|  
 | ||
|   for (word k = grs->fields(); k > 0; k--)   
 | ||
|     if (grs->field(k-1).temp())  
 | ||
|       grs->destroy_field(k-1);    
 | ||
|   
 | ||
|   for (int i = 0; i < (int)body->fields(); i++)
 | ||
|   {
 | ||
|     TForm_item& f = body->field(i);
 | ||
|     if (!f.shown()) continue;
 | ||
|     
 | ||
|     int x = f.x(); 
 | ||
|     
 | ||
|     if (x < start) start = x;
 | ||
|     if (x > end)   { end = x; wlast = f.width(); }
 | ||
|     cols[j++] = f.finkl() ? -x : x;
 | ||
|   }
 | ||
|   
 | ||
|   // inner lines
 | ||
|   for (i = 0; i < j; i++)
 | ||
|   {
 | ||
|     if (cols[i] != start && cols[i] > 0)
 | ||
|     {
 | ||
|       TForm_line* l = new TForm_line(grs);
 | ||
|       l->set_x(cols[i]-1);
 | ||
|       l->y()      = (word)y1;  
 | ||
|       l->id()     = -1;
 | ||
|       l->width()  = 1;
 | ||
|       l->height() = (int)(y2 - y1 + 1);
 | ||
|       l->set("@R");   
 | ||
|       l->temp() = TRUE;
 | ||
|       grs->add_field(l);
 | ||
|     }
 | ||
|   }  
 | ||
|   
 | ||
|   // box around
 | ||
|   if (start != 999 && end != 0)
 | ||
|   {
 | ||
|     TForm_box* l = new TForm_box(grs);
 | ||
|     l->set_x(start-1);
 | ||
|     l->y()      = (word)y1;  
 | ||
|     l->id()     = -1;
 | ||
|     l->width()  = (int)(end + wlast - start + 2);
 | ||
|     l->height() = (int)(y2 - y1 + 1);
 | ||
|     l->set("@B@R");   
 | ||
|     l->temp() = TRUE;
 | ||
|     grs->add_field(l);
 | ||
|   }                   
 | ||
|   
 | ||
|   // horizontal lines 
 | ||
|   if (start != 999 && end != 0)
 | ||
|     for (i = 0; rows[i]; i++)
 | ||
|     { 
 | ||
|       TForm_line* l = new TForm_line(grs);
 | ||
|       l->set_x(start-1);
 | ||
|       l->y()      = (word)rows[i];  
 | ||
|       l->id()     = -1;
 | ||
|       l->width()  = (int)(end + wlast - start + 2);
 | ||
|       l->height() = 1;
 | ||
|       l->set("@R");
 | ||
|       l->temp() = TRUE;
 | ||
|       grs->add_field(l);
 | ||
|     }
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Genera le righe di intestazione colonna alla riga indicata, vale per COLUMNWISE
 | ||
| //
 | ||
| // @rdesc Ritorna FALSE se non esiste body (o non e' COLUMNWISE) o se non esiste l'header
 | ||
| bool TForm::genera_intestazioni(
 | ||
|      pagetype p,  // @parm Posizione della pgaina (vedi <t pagetype>)
 | ||
|      short y)     // @parm Riga dell'header in cui vanno inserite
 | ||
| 
 | ||
| // @comm I form_items di intestazione vengono aggiunti alla sezione header di tipo <p p> con ID -1
 | ||
| 
 | ||
| {
 | ||
|   TPrint_section* body = exist('B', p);
 | ||
|   if (body == NULL || !body->columnwise()) return FALSE;      
 | ||
| 
 | ||
|   TPrint_section* header = exist('H', p);
 | ||
|   if (header == NULL) return FALSE;
 | ||
|   body->reset_tabs();
 | ||
|   const word items = body->fields();
 | ||
|   for (word j=0;j<items;j++)
 | ||
|   {// Scans all body items to print, and append header items...
 | ||
|     TForm_item& fi = body->field(j);
 | ||
|     if (!fi.shown())
 | ||
|       continue;
 | ||
|     TForm_string* s = new TForm_string(header);
 | ||
|     s->id() = -1;
 | ||
|     s->set_x(fi.x());
 | ||
|     s->y() = y;
 | ||
|     s->set_prompt(fi.col_head());
 | ||
|     s->temp() = TRUE;
 | ||
|     header->add_field(s);
 | ||
|   }           
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| /*
 | ||
| void TForm::remove_temp_items(char sec, pagetype p)
 | ||
| {                    
 | ||
|   TPrint_section* s = exist(sec,p);
 | ||
|   if (s!=NULL)
 | ||
|   {
 | ||
|     const word items = s->fields();
 | ||
|     for (word j=0;j<items; j++)
 | ||
|     {
 | ||
|       if  (s->field(j).temp())
 | ||
|         s->destroy_field(j,FALSE);
 | ||
|     }
 | ||
|     s->field_array().pack(); 
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void TForm::put_examples(char sez, pagetype p)
 | ||
| {
 | ||
|   TPrint_section* s = exist(sez,p);
 | ||
|   if (s!=NULL)
 | ||
|   {
 | ||
|     const word items = s->fields();
 | ||
|     for (word i=0;i<items;i++)
 | ||
|     {
 | ||
|       TForm_item& fi = s->field(i);
 | ||
|       if (fi.fields()!=0) continue;
 | ||
|       if (fi.memo()) 
 | ||
|         fi.set(fi.memo_info());
 | ||
|       else
 | ||
|       if (fi.prompt().empty())
 | ||
|       { 
 | ||
|         if (fi.class_name() == "DATA")
 | ||
|         {
 | ||
|           const TDate d(TODAY);
 | ||
|           fi.set(d);
 | ||
|         }
 | ||
|         else
 | ||
|           if (fi.class_name() == "NUMERO")
 | ||
|           {
 | ||
|             fi.set_prompt(fi.example());
 | ||
|             fi.temp() = TRUE;
 | ||
|           }
 | ||
|           else
 | ||
|             fi.set(fi.key());
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TForm::remove_examples(char sez, pagetype p)
 | ||
| {
 | ||
|   TPrint_section* s = exist(sez,p);
 | ||
|   if (s!=NULL)
 | ||
|   {
 | ||
|     const word items = s->fields();
 | ||
|     for (word i=0;i<items;i++)
 | ||
|     {
 | ||
|       TForm_item& fi = s->field(i);
 | ||
|       if (fi.fields()!=0) continue;
 | ||
|       if (fi.memo()) 
 | ||
|         fi.set("");
 | ||
|       else
 | ||
|         if (fi.class_name() == "NUMERO" && fi.temp())
 | ||
|         {
 | ||
|           fi.set_prompt("");
 | ||
|           fi.temp() = FALSE;
 | ||
|         }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| */
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Stampa gli items da <p form> a <p to>
 | ||
| //
 | ||
| // @rdesc Ritorna se ha effettuato correttamente la stampa
 | ||
| bool TForm::print(
 | ||
|      long from,   // @parm Primo item da stampare (default 0l)
 | ||
|      long to)   // @parm Ultimo da stampare (se <lt>0 stampa fino alla fine del file, default -1l)
 | ||
| 
 | ||
| // @comm Se i parametri di posizionamento sono settati e cosi' pure gli offset genera un <f error_box>.
 | ||
| { 
 | ||
|   _cur_form = this;
 | ||
|   
 | ||
|   if ((_char_to_pos != '\0' || ((_ipx +_ipy+_fpx) != 0)) &&  // Se i parametri di posizionamento sono settati e
 | ||
|       (_x != 0 || _y != 0))                                      // cosi' pure gli offset genera un errore.
 | ||
|   {
 | ||
|     error_box("Non e' possibile settare contemporaneamente gli offset"
 | ||
|               " e i parametri di posizionamento del modulo.");
 | ||
|     return FALSE;
 | ||
|   }
 | ||
|   TPrinter& pr = printer();
 | ||
|   if (_char_to_pos != '\0' || (_ipx +_ipy+_fpx) != 0)   // Effettua il posizionamento del form...
 | ||
|   {
 | ||
|     if (pr.printtype() == screenvis)
 | ||
|       error_box("Stampa a video selezionata. Non e' possibile effettuare il posizionamento.");
 | ||
|     else
 | ||
|       if (_arrange)
 | ||
|         arrange_form();
 | ||
|   }                        
 | ||
|   
 | ||
|   pr.setheaderhandler(header_handler); // Setta handlers
 | ||
|   pr.setfooterhandler(footer_handler);
 | ||
|   if (!pr.is_generic())
 | ||
|   {
 | ||
|     for (pagetype t = odd_page; t <= last_page; t = pagetype(t+1)) 
 | ||
|     {
 | ||
|       if (height(t)> (word)pr.formlen()) 
 | ||
|       { 
 | ||
|         TString s("La lunghezza totale della sezione ");
 | ||
|         switch ( t )   
 | ||
|         {
 | ||
|         case odd_page:   
 | ||
|           s << "standard"; break;
 | ||
|         case even_page:  
 | ||
|           s << "pagine pari"; break;
 | ||
|         case first_page: 
 | ||
|           s << "prima pagina"; break;
 | ||
|         case last_page:  
 | ||
|           s << "ultima pagina"; break;
 | ||
|         default: 
 | ||
|           break;
 | ||
|         } 
 | ||
|         s << " eccede la lunghezza reale del foglio.";
 | ||
|         message_box(s);
 | ||
|       }  
 | ||
|     }
 | ||
|   }
 | ||
|   else
 | ||
|   {
 | ||
|     pr.formlen(height(odd_page));
 | ||
|   }
 | ||
|   pr.set_offset(_y,_x);
 | ||
|   pr.set_char_size(_fontsize);                     // Set font name and size
 | ||
|   pr.set_fontname(_fontname);                      // according to current form
 | ||
|   const bool was_open = pr.isopen();
 | ||
| 
 | ||
|   set_last_page(FALSE);                            // non e' l'ultima pagina
 | ||
|   
 | ||
|   set_background(1, TRUE);
 | ||
| 
 | ||
|   if (!was_open && !pr.open())
 | ||
|     return FALSE;
 | ||
|   do_events();
 | ||
|   
 | ||
|   long lastrec= records()-1;
 | ||
|   
 | ||
|   if (to < 0) to = lastrec;
 | ||
|   if (to == lastrec) to--; // l'ultima pagina <20> gestita come caso particolare
 | ||
|   
 | ||
|   bool ok = TRUE;
 | ||
| 
 | ||
|   for (long i = from; i <= to && ok; i++)
 | ||
|   {
 | ||
|     if (from < 0) to = from;
 | ||
|     else if (cursor()) *cursor() = i;
 | ||
|         
 | ||
|     if (pr.current_row() > pr.headersize()+1)
 | ||
|     {
 | ||
|       const word h = set_body(page(pr), FALSE);
 | ||
|       if (h > pr.rows_left())
 | ||
|         pr.formfeed();
 | ||
|     }
 | ||
| 
 | ||
|     set_body(page(pr), TRUE);
 | ||
|   }
 | ||
|   
 | ||
|   if (i == lastrec && from >= 0)
 | ||
|   {                
 | ||
|     if (cursor()) *cursor() = i;
 | ||
|     set_last_page(TRUE);
 | ||
|     set_background(0, TRUE);
 | ||
|     set_header(0, TRUE);
 | ||
|     set_body(0, TRUE);
 | ||
|     pr.formfeed();
 | ||
|   }
 | ||
|   
 | ||
|   if (!was_open)
 | ||
|     pr.close();
 | ||
| 
 | ||
|   pr.setheaderhandler(NULL);
 | ||
|   pr.setfooterhandler(NULL);
 | ||
|   
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| void TForm::print_section(ostream& out, char s) const
 | ||
| {
 | ||
|   for (pagetype t = odd_page; t <= last_page; t = pagetype(t+1)) 
 | ||
|   {
 | ||
|     const TPrint_section* sec = ((TForm*)this)->exist(s, t);
 | ||
|     if (sec && sec->ok() && !sec->temp())
 | ||
|     {
 | ||
|       const char* name;
 | ||
|       switch (s)
 | ||
|       {
 | ||
|       case 'F': 
 | ||
|         name = "FOOTER"; break;
 | ||
|       case 'G': 
 | ||
|         name = "GRAPHICS"; break;
 | ||
|       case 'H': 
 | ||
|         name = "HEADER"; break;
 | ||
|         default : 
 | ||
|         name = "BODY"; break;
 | ||
|       }
 | ||
|       out << "SECTION " << name;
 | ||
|       out << *sec;
 | ||
|       out << "END\n" << endl;
 | ||
|     }  
 | ||
|   }
 | ||
| } 
 | ||
| 
 | ||
| bool TForm::validate(TForm_item& f, TToken_string&)
 | ||
| { return FALSE; }                                        
 | ||
| 
 | ||
| void TForm::print_on(ostream& out) const
 | ||
| {                   
 | ||
|   main_app().begin_wait();
 | ||
|   
 | ||
|   if (relation())
 | ||
|   {
 | ||
|     out << *relation() << "\nEND" << endl;
 | ||
|     print_description(out);
 | ||
|   }
 | ||
|   
 | ||
|   print_general(out);  
 | ||
|   
 | ||
|   print_section(out, 'G');
 | ||
|   print_section(out, 'H');
 | ||
|   print_section(out, 'B');
 | ||
|   print_section(out, 'F');
 | ||
|   
 | ||
|   out << "END" << endl;
 | ||
|   
 | ||
|   main_app().end_wait();
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| word TForm::height(word page)
 | ||
| {               
 | ||
|   word h = 0;
 | ||
|   
 | ||
|   if (_back.items() == 0)
 | ||
|   {
 | ||
|     if (_head.items() && exist('H', pagetype(page)) != NULL)
 | ||
|       h += section('H', page).height();
 | ||
|     if (_body.items() && exist('B', pagetype(page)) != NULL)
 | ||
|       h += section('B', page).height();
 | ||
|     if (_foot.items() && exist('F', pagetype(page)) != NULL)
 | ||
|       h += section('F', page).height();
 | ||
|   } 
 | ||
|   else 
 | ||
|     h = printer().formlen();    
 | ||
|   
 | ||
|   return h;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Legge un profilo
 | ||
| //
 | ||
| // @rdesc Ritorna se e' riuscito nell'operazione:
 | ||
| // @flag TRUE | E' riuscito a leggere il prfilo
 | ||
| // @flag FALSE | Non ha letto il profilo
 | ||
| bool TForm::read_profile()
 | ||
| // @comm Per la lettura del profilo procede leggendo prima la definizione del
 | ||
| //   profilo base e successivamente le modifiche relative.
 | ||
| {      
 | ||
|   TLocalisamfile prof(LF_FORM);  
 | ||
|   TLocalisamfile rprof(LF_RFORM); 
 | ||
|   
 | ||
|   prof.zero();
 | ||
|   prof.put("TIPOPROF",_name);
 | ||
|   prof.put("CODPROF",_code);
 | ||
|   if (prof.read(_isequal) == NOERR)
 | ||
|   {
 | ||
|     rprof.zero();
 | ||
|     rprof.put("TIPOPROF", _name);
 | ||
|     rprof.put("CODPROF", _code);
 | ||
|     const TRectype filter(rprof.curr());
 | ||
|     
 | ||
|     for (int err = rprof.read(_isgteq); err == NOERR && rprof.curr() == filter; err = rprof.next())
 | ||
|     {   
 | ||
|       // controllo lingua per codici profilo
 | ||
|       char cl = rprof.curr().get("CODPROF").right(1)[0];
 | ||
|       char cp = _code.right(1)[0];
 | ||
|       
 | ||
|       // stop se il codice letto e' di un profilo EC in lingua e 
 | ||
|       // il corrente e' ec non in lingua
 | ||
|       if (!isdigit(cl) && cl != cp) break;
 | ||
| 
 | ||
|       const TString& s = rprof.get("SEZ"); 
 | ||
|       const char sec = s[0];
 | ||
|       const pagetype pt = char2page(s[1]);
 | ||
|       const short id = rprof.get_int("ID");
 | ||
|       
 | ||
|       if (id == 0)
 | ||
|       {
 | ||
|         TPrint_section& se = section(sec, pt);
 | ||
|         se.read_from(rprof.curr());
 | ||
|       }
 | ||
|       else
 | ||
|       {
 | ||
|         TForm_item& item = find_field(sec, pt, id);
 | ||
|         item.read_from(rprof.curr());
 | ||
|       }
 | ||
|     }              
 | ||
|     if (_code.not_empty()&& !_isnew)
 | ||
|     {
 | ||
|       _x = prof.get_int("OFFX");
 | ||
|       _y = prof.get_int("OFFY");
 | ||
|       _fontname = prof.get("FONTNAME");
 | ||
|       _fontsize = prof.get_int("FONTSIZE");
 | ||
|       _char_to_pos = prof.get("CTP")[0];
 | ||
|       _ipx = prof.get_int("IPX");
 | ||
|       _ipy = prof.get_int("IPY");
 | ||
|       _fpx = prof.get_int("FPX");
 | ||
|       set_fincatura(prof.get("GRID"));
 | ||
|     }
 | ||
|   }             
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| bool TForm::write_profile()
 | ||
| {
 | ||
|   const char sechar[4] = { 'B', 'F', 'G',  'H' };
 | ||
|   
 | ||
|   get_compulsory_specials();
 | ||
|   TLocalisamfile form(LF_FORM);
 | ||
|   form.zero();
 | ||
|   form.put("TIPOPROF",_name);
 | ||
|   form.put("CODPROF",_code);
 | ||
|   if (form.read(_isequal,_lock) == NOERR)
 | ||
|   {
 | ||
|     if (_dirty)
 | ||
|     {
 | ||
|       form.put("OFFY",_y);
 | ||
|       form.put("OFFX",_x);
 | ||
|       form.put("FONTNAME",_fontname);
 | ||
|       form.put("FONTSIZE",_fontsize);
 | ||
|       form.put("CTP",_char_to_pos);
 | ||
|       form.put("IPX", _ipx);
 | ||
|       form.put("IPY", _ipy);
 | ||
|       form.put("FPX", _fpx);
 | ||
|       form.put("GRID", _fink);
 | ||
|       form.rewrite();    
 | ||
|       _dirty=FALSE;
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   TLocalisamfile rform(LF_RFORM);
 | ||
|   TRectype& cur = rform.curr(); 
 | ||
|   
 | ||
|   int err = NOERR;
 | ||
|   for (int sn = 0; sn < 4 && err == NOERR; sn++)                        // For each section
 | ||
|   {
 | ||
|     const char sc = sechar[sn];
 | ||
|     for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))  // For each section type
 | ||
|     {            
 | ||
|       TPrint_section* sec = exist(sc, pt);
 | ||
|       if (sec != NULL && sec->dirty())
 | ||
|       {                        
 | ||
|         const char codsez[3] = { sc, pt+'0', '\0' };
 | ||
|         cur.zero();
 | ||
|         cur.put("TIPOPROF", name());
 | ||
|         cur.put("CODPROF", code());
 | ||
|         cur.put("SEZ", codsez);
 | ||
|         sec->print_on(cur);
 | ||
|         sec->set_dirty(FALSE);
 | ||
|         
 | ||
|         err = _isnew ? rform.write() : rform.rewrite();
 | ||
|         if (err != NOERR)
 | ||
|           err = _isnew ? rform.rewrite() : rform.write();
 | ||
|         
 | ||
|         for (word i = 0; i < sec->fields() && err == NOERR; i++)
 | ||
|         {
 | ||
|           TForm_item& fi = sec->field(i);
 | ||
|           if (fi.dirty())
 | ||
|           {
 | ||
|             fi.print_on(cur);
 | ||
|             err = _isnew ? rform.write() : rform.rewrite();
 | ||
|             if (err != NOERR)
 | ||
|               err = _isnew ? rform.rewrite() : rform.write();
 | ||
|             fi.set_dirty(FALSE);  
 | ||
|           }
 | ||
|         }  
 | ||
|       }  
 | ||
|     }
 | ||
|   }
 | ||
|   form.reread(_unlock);
 | ||
|   if (err != NOERR)
 | ||
|     return error_box("Errore di salvataggio profilo: %d", err);
 | ||
|   
 | ||
|   return TRUE;
 | ||
| }    
 | ||
| 
 | ||
| void TForm::init()
 | ||
| {
 | ||
|   _relation= NULL;
 | ||
|   _cursor= NULL;
 | ||
|   _rel_desc= NULL;
 | ||
|   _isnew= FALSE;
 | ||
|   _fontname= "Roman 17cpi";
 | ||
|   _fontsize= 12;
 | ||
|   _x= 0;
 | ||
|   _y= 0;
 | ||
|   _char_to_pos= '\0';
 | ||
|   _ipx= 0;
 | ||
|   _ipy= 0;
 | ||
|   _fpx= 0;
 | ||
|   _arrange= TRUE;
 | ||
|   set_fincatura("+++++++++-|");
 | ||
|   _dirty= FALSE;                         
 | ||
|   _background_mode = printer().isgraphics() ? graphics : testo;
 | ||
| }
 | ||
| 
 | ||
| // @doc EXTERNAL
 | ||
| 
 | ||
| // @mfunc Carica il form dal file specificato
 | ||
| void TForm::read(
 | ||
|      const char* name,  // @parm Nome del profilo di stampa da leggere
 | ||
|      const char* code,  // @parm Codice del profilo di stampa da leggere
 | ||
|      int lev,     // @parm Permessi di stampa
 | ||
|      const char* desc)  // @parm Descrizione del formato da leggere
 | ||
| {
 | ||
|   _name= name;
 | ||
|   _code= code;
 | ||
|   _editlevel= lev;
 | ||
|   _desc= desc;
 | ||
| 
 | ||
|   main_app().begin_wait();
 | ||
| 
 | ||
|   if (_code.not_empty())
 | ||
|   {
 | ||
|     // extract base form name    
 | ||
|     TLocalisamfile forms(LF_FORM);
 | ||
|     forms.zero();
 | ||
|     
 | ||
|     forms.put("TIPOPROF", _name);
 | ||
|     forms.put("CODPROF", _code);
 | ||
|     _isnew = forms.read() != NOERR;
 | ||
|     if (_isnew)
 | ||
|     {
 | ||
|       // create new form
 | ||
|       forms.put("TIPOPROF", _name);
 | ||
|       forms.put("CODPROF", _code);   
 | ||
|       forms.put("DESC",    _desc);
 | ||
|       forms.put("OFFY",_y);
 | ||
|       forms.put("OFFX",_x);
 | ||
|       forms.put("FONTNAME",_fontname);
 | ||
|       forms.put("FONTSIZE",_fontsize);
 | ||
|       forms.put("CTP", _char_to_pos);
 | ||
|       forms.put("IPX", _ipx);
 | ||
|       forms.put("IPY", _ipy);
 | ||
|       forms.put("FPX", _fpx);
 | ||
|       forms.put("GRID", _fink);
 | ||
|       forms.write();
 | ||
|     }                
 | ||
|     else
 | ||
|       if (forms.status() == NOERR)
 | ||
|       { 
 | ||
|         _desc = forms.get("DESC");
 | ||
|         if (_desc != desc && desc != "") // Controlla se la descrizione e' diversa, in questo caso l'aggiorna
 | ||
|         {
 | ||
|           forms.reread(_lock);
 | ||
|           forms.put("DESC",desc);
 | ||
|           forms.rewrite();
 | ||
|         }
 | ||
|       }
 | ||
|   }
 | ||
| 
 | ||
|   // read base form  
 | ||
|   TFilename n(_name); n.ext("frm");
 | ||
|   TScanner scanner(n);
 | ||
| 
 | ||
|   bool ok = TRUE;
 | ||
|   if (scanner.popkey() == "US")                         // Parse relation
 | ||
|   {
 | ||
|     ok = parse_use(scanner);
 | ||
|     while (ok && scanner.popkey() == "JO")
 | ||
|       ok = parse_join(scanner);  
 | ||
|     
 | ||
|     parse_description(scanner);                         // Parse description
 | ||
|   } 
 | ||
|   else scanner.push();   
 | ||
|   
 | ||
|   if (ok) parse_general(scanner);                       // Parse general
 | ||
| 
 | ||
|   while (ok)
 | ||
|   {                         
 | ||
|     if (scanner.popkey() != "SE")                       // SECTION or END
 | ||
|       break;
 | ||
|     const char sec = scanner.popkey()[0];               // Section name (GRAPH, HEAD, BODY, FOOT)
 | ||
|     const pagetype p = char2page(scanner.popkey()[0]);  // Section type (odd, even, first, last)   
 | ||
|     TPrint_section* ps = exist(sec, p, TRUE);           // Create section
 | ||
|     ok = ps->parse(scanner);                            // Parse section
 | ||
|   }         
 | ||
|   
 | ||
|   if (_code.not_empty())
 | ||
|     read_profile();    // read from LF_RFORM file
 | ||
| 
 | ||
|   set_compulsory_specials();
 | ||
|   TPrinter& pr = printer();
 | ||
|   pr.set_offset(_y,_x);
 | ||
|   pr.set_char_size(_fontsize);
 | ||
|   pr.set_fontname(_fontname);
 | ||
|   set_mode(_background_mode);
 | ||
|   
 | ||
|   main_app().end_wait();
 | ||
| }
 | ||
| 
 | ||
| void TForm::set_compulsory_specials()
 | ||
| {
 | ||
|   const char sechar[3] = { 'B', 'F', 'H' };
 | ||
|   
 | ||
|   for (int sn = 0; sn < 3; sn++)
 | ||
|   {
 | ||
|     const char sc = sechar[sn];
 | ||
|     for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
 | ||
|     {            
 | ||
|       TPrint_section* sec = exist(sc, pt);
 | ||
|       if (sec != NULL)
 | ||
|       {
 | ||
|         const word fields = sec->fields();
 | ||
|         const bool col_wise = sec->columnwise();
 | ||
|         for (word i = 0; col_wise && i < fields; i++)
 | ||
|         {
 | ||
|           TForm_item& fi = sec->field(i);
 | ||
|           if (fi.special_items()>0)
 | ||
|           {
 | ||
|             fi.set_col_head(fi.get_special_value("INTESTAZIONE"));
 | ||
|             fi.ofs() = (short)atoi(fi.get_special_value("OFFSET"));
 | ||
|             TString fnk(fi.get_special_value("FINCATURA"));
 | ||
|             fi.set_finkl(fnk[0]!='X'); // !finkl significa fincatura abilitata
 | ||
|             fi.set_finkr(fnk[1]!='X'); // !finkr significa fincatura abilitata
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TForm::get_compulsory_specials()
 | ||
| {
 | ||
|   const char sechar[3] = { 'B', 'F', 'H' };
 | ||
|   
 | ||
|   for (int sn = 0; sn < 3; sn++)
 | ||
|   {
 | ||
|     const char sc = sechar[sn];
 | ||
|     for (pagetype pt = odd_page; pt <= last_page; pt = pagetype(pt+1))
 | ||
|     {            
 | ||
|       TPrint_section* sec = exist(sc, pt);
 | ||
|       if (sec != NULL)
 | ||
|       {
 | ||
|         const word fields = sec->fields();
 | ||
|         const bool col_wise = sec->columnwise();
 | ||
|         for (word i = 0; col_wise && i < fields; i++)
 | ||
|         {
 | ||
|           TForm_item& fi = sec->field(i);
 | ||
|           if (fi.special_items()>0)
 | ||
|           {
 | ||
|             fi.set_special_value("INTESTAZIONE", fi.col_head());
 | ||
|             fi.set_special_value("OFFSET", format("%d",fi.ofs()));
 | ||
|             TString fnk(fi.finkl()? " " : "X");
 | ||
|             fnk << (fi.finkr() ? " " : "X");
 | ||
|             fi.set_special_value("FINCATURA",fnk);
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TForm::set_fincatura(const char* s)
 | ||
| { 
 | ||
|   _fink = s; _fink.cut(11);
 | ||
|   printer().set_fincatura(_fink);
 | ||
| }
 | ||
| 
 | ||
| void TForm::set_mode(bkg_mode b)
 | ||
| { 
 | ||
|   _background_mode = b; 
 | ||
|   if (_background_mode == graphics && printer().is_generic()) _background_mode = testo;
 | ||
|   printer().set_graphics(_background_mode == graphics ? TRUE : FALSE);
 | ||
| }
 | ||
| 
 | ||
| TForm::TForm()
 | ||
| {
 | ||
|   init();
 | ||
| }
 | ||
| 
 | ||
| TForm::TForm(const char* name, const char* code, int lev, const char* desc) 
 | ||
| {
 | ||
|   init();
 | ||
|   read(name, code, lev, desc);
 | ||
| }
 | ||
| 
 | ||
| TForm::~TForm()
 | ||
| {
 | ||
|   if (_cursor)
 | ||
|   {
 | ||
|     delete _cursor;
 | ||
|     delete _relation;   
 | ||
|     if (_rel_desc)
 | ||
|       delete _rel_desc;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 |